/************************************************************************* * Copyright 2009-2015 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. ************************************************************************/ package com.eucalyptus.vm; import static com.eucalyptus.reporting.event.ResourceAvailabilityEvent.ResourceType.Core; import static com.eucalyptus.reporting.event.ResourceAvailabilityEvent.ResourceType.Disk; import static com.eucalyptus.reporting.event.ResourceAvailabilityEvent.ResourceType.Instance; import static com.eucalyptus.reporting.event.ResourceAvailabilityEvent.ResourceType.Memory; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import com.eucalyptus.bootstrap.Bootstrap; import com.eucalyptus.bootstrap.Hosts; import com.eucalyptus.cluster.common.internal.Cluster; import com.eucalyptus.cluster.Clusters; import com.eucalyptus.cluster.common.internal.ResourceState; import com.eucalyptus.event.ClockTick; import com.eucalyptus.event.EventListener; import com.eucalyptus.event.ListenerRegistry; import com.eucalyptus.event.Listeners; import com.eucalyptus.reporting.event.ResourceAvailabilityEvent; import com.eucalyptus.compute.common.internal.vmtypes.VmType; import com.eucalyptus.reporting.event.ResourceAvailabilityEvent.Availability; import com.eucalyptus.reporting.event.ResourceAvailabilityEvent.ResourceType; import com.eucalyptus.reporting.event.ResourceAvailabilityEvent.Type; import com.eucalyptus.vmtypes.VmTypes; import com.google.common.base.Function; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; /** * */ public class VmInstanceAvailabilityEventListener implements EventListener<ClockTick> { private static final Logger logger = Logger.getLogger( VmInstanceAvailabilityEventListener.class ); private static final class AvailabilityAccumulator { private long total; private long available; private final Function<VmType,Integer> valueExtractor; private final List<Availability> availabilities = Lists.newArrayList(); private AvailabilityAccumulator( final Function<VmType,Integer> valueExtractor ) { this.valueExtractor = valueExtractor; } private void rollUp( final Iterable<ResourceAvailabilityEvent.Tag> tags ) { availabilities.add( new Availability( total, available, tags ) ); total = 0; available = 0; } } public static void register( ) { Listeners.register( ClockTick.class, new VmInstanceAvailabilityEventListener() ); } @Override public void fireEvent( final ClockTick event ) { if ( Bootstrap.isOperational() && Hosts.isCoordinator() ) { final ArrayListMultimap<ResourceType,Availability> availabilityByType = ArrayListMultimap.create( ); final Map<ResourceType,AvailabilityAccumulator> availabilities = Maps.newEnumMap( ResourceType.class ); final Iterable<VmType> vmTypes = Lists.newArrayList( VmTypes.list( ) ); for ( final Cluster cluster : Clusters.list( ) ) { 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 ); availabilityByType.put( Instance, new Availability( va.getMax(), va.getAvailable(), Lists.<ResourceAvailabilityEvent.Tag>newArrayList( new ResourceAvailabilityEvent.Dimension( "AvailabilityZone", cluster.getPartition() ), new 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() ) ) ); } } for ( final Map.Entry<ResourceType,AvailabilityAccumulator> entry : availabilities.entrySet() ) { for ( final Availability availability : entry.getValue().availabilities ) { availabilityByType.put( entry.getKey( ), availability ); } } for ( final Map.Entry<ResourceType,Collection<Availability>> resourceEntry : availabilityByType.asMap( ).entrySet( ) ) try { ListenerRegistry.getInstance().fireEvent( new ResourceAvailabilityEvent( resourceEntry.getKey( ), resourceEntry.getValue( ) ) ); } catch ( Exception ex ) { logger.error( ex, ex ); } } } }