@Override
  public void fireEvent(final ClockTick event) {
    if (Bootstrap.isFinished() && Hosts.isCoordinator()) {

      final List<ResourceAvailabilityEvent> resourceAvailabilityEvents = Lists.newArrayList();
      final Map<ResourceAvailabilityEvent.ResourceType, AvailabilityAccumulator> availabilities =
          Maps.newEnumMap(ResourceAvailabilityEvent.ResourceType.class);
      final Iterable<VmType> vmTypes = Lists.newArrayList(VmTypes.list());
      for (final Cluster cluster : Clusters.getInstance().listValues()) {
        availabilities.put(Core, new AvailabilityAccumulator(VmType.SizeProperties.Cpu));
        availabilities.put(Disk, new AvailabilityAccumulator(VmType.SizeProperties.Disk));
        availabilities.put(Memory, new AvailabilityAccumulator(VmType.SizeProperties.Memory));

        for (final VmType vmType : vmTypes) {
          final ResourceState.VmTypeAvailability va =
              cluster.getNodeState().getAvailability(vmType.getName());

          resourceAvailabilityEvents.add(
              new ResourceAvailabilityEvent(
                  Instance,
                  new ResourceAvailabilityEvent.Availability(
                      va.getMax(),
                      va.getAvailable(),
                      Lists.<ResourceAvailabilityEvent.Tag>newArrayList(
                          new ResourceAvailabilityEvent.Dimension(
                              "availabilityZone", cluster.getPartition()),
                          new ResourceAvailabilityEvent.Dimension("cluster", cluster.getName()),
                          new ResourceAvailabilityEvent.Type("vm-type", vmType.getName())))));

          for (final AvailabilityAccumulator availability : availabilities.values()) {
            availability.total =
                Math.max(
                    availability.total, va.getMax() * availability.valueExtractor.apply(vmType));
            availability.available =
                Math.max(
                    availability.available,
                    va.getAvailable() * availability.valueExtractor.apply(vmType));
          }
        }

        for (final AvailabilityAccumulator availability : availabilities.values()) {
          availability.rollUp(
              Lists.<ResourceAvailabilityEvent.Tag>newArrayList(
                  new ResourceAvailabilityEvent.Dimension(
                      "availabilityZone", cluster.getPartition()),
                  new ResourceAvailabilityEvent.Dimension("cluster", cluster.getName())));
        }
      }

      for (final Map.Entry<ResourceAvailabilityEvent.ResourceType, AvailabilityAccumulator> entry :
          availabilities.entrySet()) {
        resourceAvailabilityEvents.add(
            new ResourceAvailabilityEvent(entry.getKey(), entry.getValue().availabilities));
      }

      for (final ResourceAvailabilityEvent resourceAvailabilityEvent : resourceAvailabilityEvents)
        try {
          ListenerRegistry.getInstance().fireEvent(resourceAvailabilityEvent);
        } catch (Exception ex) {
          logger.error(ex, ex);
        }
    }
  }