/** * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. */ package net.juniper.contrail.vcenter; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import com.vmware.vim25.ArrayOfEvent; import com.vmware.vim25.ArrayOfGuestNicInfo; import com.vmware.vim25.Event; import com.vmware.vim25.EventFilterSpec; import com.vmware.vim25.EventFilterSpecByEntity; import com.vmware.vim25.EventFilterSpecByTime; import com.vmware.vim25.EventFilterSpecRecursionOption; import com.vmware.vim25.ObjectSpec; import com.vmware.vim25.ObjectUpdate; import com.vmware.vim25.PropertyChange; import com.vmware.vim25.PropertyChangeOp; import com.vmware.vim25.PropertyFilterSpec; import com.vmware.vim25.PropertyFilterUpdate; import com.vmware.vim25.PropertySpec; import com.vmware.vim25.RequestCanceled; import com.vmware.vim25.SelectionSpec; import com.vmware.vim25.UpdateSet; import com.vmware.vim25.VirtualMachineToolsRunningStatus; import com.vmware.vim25.WaitOptions; import com.vmware.vim25.mo.Datacenter; import com.vmware.vim25.mo.EventHistoryCollector; import com.vmware.vim25.mo.EventManager; import com.vmware.vim25.mo.ManagedObject; import com.vmware.vim25.mo.PropertyCollector; import com.vmware.vim25.mo.PropertyFilter; import net.juniper.contrail.watchdog.TaskWatchDog; import com.vmware.vim25.EnteredMaintenanceModeEvent; import com.vmware.vim25.ExitMaintenanceModeEvent; import com.vmware.vim25.GuestNicInfo; import com.vmware.vim25.HostConnectedEvent; import com.vmware.vim25.HostConnectionLostEvent; import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.RuntimeFault; import com.vmware.vim25.mo.VmwareDistributedVirtualSwitch; import com.google.common.base.Throwables; import com.vmware.vim25.InvalidState; import org.apache.log4j.Logger; /** * @author Sachchidanand Vaidya * */ public class VCenterNotify implements Runnable { private static final Logger s_logger = Logger.getLogger(VCenterNotify.class); static volatile VCenterDB vcenterDB = null; static volatile VncDB vncDB; private VCenterEventHandler eventHandler; private static boolean vCenterConnected = false; private Calendar vcenterConnectedTime; private final static String[] guestProps = { "guest.toolsRunningStatus", "guest.net" }; private final static String[] ipPoolProps = { "summary.ipPoolId" }; private static Map<String, String> watchedVMs = new HashMap<String, String>(); private static Map<String, String> watchedVNs = new HashMap<String, String>(); private static Map<ManagedObject, PropertyFilter> watchedFilters = new HashMap<ManagedObject, PropertyFilter>(); private static List<EventHistoryCollector> collectors = new ArrayList<EventHistoryCollector>(); private static final int MAX_CACHED_EVENTS = 100; @SuppressWarnings("serial") private static Map<Integer, Event> eventsLRUCache = new LinkedHashMap<Integer, Event>() { @Override protected boolean removeEldestEntry(Map.Entry<Integer, Event> eldest) { return size() > MAX_CACHED_EVENTS; } }; private static Boolean shouldRun; private static Thread watchUpdates = null; private static final int VCENTER_READ_TIMEOUT = 30000; //30 sec private static final int VCENTER_CONNECT_TIMEOUT = 30000; //30 sec private static final int VCENTER_WAIT_FOR_UPDATES_READ_TIMEOUT = 180000; // 3 minutes private static final int VCENTER_WAIT_FOR_UPDATES_SERVER_TIMEOUT = 120; // 2 minutes private static final int VCENTER_TIMEOUT_DELTA = 10000; // 10 seconds private static PropertyCollector propColl; private static EventManager eventManager; public VCenterNotify( String vcenterUrl, String vcenterUsername, String vcenterPassword, String dcName, String dvsName, String ipFabricPgName, String _apiServerAddress, int _apiServerPort, String _username, String _password, String _tenant, String _authtype, String _authurl, Mode mode) { vcenterDB = new VCenterDB(vcenterUrl, vcenterUsername, vcenterPassword, dcName, dvsName, ipFabricPgName, mode); switch (mode) { case VCENTER_ONLY: vncDB = new VncDB(_apiServerAddress, _apiServerPort, mode); break; case VCENTER_AS_COMPUTE: vncDB = new VncDB(_apiServerAddress, _apiServerPort, _username, _password, _tenant, _authtype, _authurl, mode); break; default: vncDB = new VncDB(_apiServerAddress, _apiServerPort, mode); } eventHandler = new VCenterEventHandler(vcenterDB, vncDB); } public static VCenterDB getVcenterDB() { return vcenterDB; } public static boolean getVCenterConnected() { return vCenterConnected; } private void cleanupEventFilters() { for (Map.Entry<ManagedObject, PropertyFilter> entry: watchedFilters.entrySet()) { try { PropertyFilter pf = entry.getValue(); pf.destroyPropertyFilter(); } catch (RemoteException e) { // it is ok, we can receive exception if vcenter was restarted } } watchedFilters.clear(); watchedVMs.clear(); watchedVNs.clear(); for(EventHistoryCollector collector: collectors) { try { collector.destroyCollector(); } catch (RemoteException e) { // it is ok, we can receive exception if vcenter was restarted } } } public static void watchVm(VirtualMachineInfo vmInfo) { if (VCenterMonitor.mode == Mode.VCENTER_AS_COMPUTE) { return; } if (vmInfo.vm == null) { return; } String key = vmInfo.vm.getMOR().getVal(); if (watchedVMs.containsKey(key)) { String val = watchedVMs.get(key); if (!val.equals(vmInfo.getUuid())) { s_logger.error("Found different UUID in watched VMs, expected " + vmInfo.getUuid() + ", actual " + val + ", for mor " + vmInfo.vm.getMOR().getType() + ", value " + key); watchedVMs.put(key, vmInfo.getUuid()); } return; } s_logger.info("Now watching VM with MOR " + key + ", " + vmInfo); watchedVMs.put(key, vmInfo.getUuid()); watchManagedObject(vmInfo.vm, guestProps); } public static void unwatchVm(VirtualMachineInfo vmInfo) { if (VCenterMonitor.mode == Mode.VCENTER_AS_COMPUTE) { return; } if (vmInfo.vm == null) { return; } String key = vmInfo.vm.getMOR().getVal(); if (!watchedVMs.containsKey(key)) { return; } s_logger.info("Unwatching VM with MOR " + key + ", " + vmInfo); watchedVMs.remove(key); unwatchManagedObject(vmInfo.vm); } public static void watchVn(VirtualNetworkInfo vnInfo) { if (VCenterMonitor.mode == Mode.VCENTER_AS_COMPUTE) { return; } if (vnInfo.dpg == null) { return; } String key = vnInfo.dpg.getMOR().getVal(); if (watchedVNs.containsKey(key)) { String val = watchedVNs.get(key); if (!val.equals(vnInfo.getUuid())) { s_logger.error("Found different UUID in watched VNs, expected " + vnInfo.getUuid() + ", actual " + val + ", for mor " + vnInfo.dpg.getMOR().getType() + " value " + key ); watchedVNs.put(key, vnInfo.getUuid()); } return; } s_logger.info("Now watching VN with MOR " + key + ", " + vnInfo); watchedVNs.put(key, vnInfo.getUuid()); watchManagedObject(vnInfo.dpg, ipPoolProps); } public static void unwatchVn(VirtualNetworkInfo vnInfo) { if (VCenterMonitor.mode == Mode.VCENTER_AS_COMPUTE) { return; } if (vnInfo.dpg == null) { return; } String key = vnInfo.dpg.getMOR().getVal(); if (!watchedVNs.containsKey(key)) { return; } s_logger.info("Unwatching VN with MOR " + key + ", " + vnInfo); watchedVNs.remove(key); unwatchManagedObject(vnInfo.dpg); } private static void watchManagedObject(ManagedObject mos, String[] propNames) { PropertyFilterSpec pfs = new PropertyFilterSpec(); ObjectSpec[] oss = new ObjectSpec[1]; oss[0] = new ObjectSpec(); oss[0].setObj(mos.getMOR()); pfs.setObjectSet(oss); PropertySpec ps = new PropertySpec(); ps.setType(mos.getMOR().getType()); ps.setPathSet(propNames); pfs.setPropSet(new PropertySpec[] { ps }); try { PropertyFilter pf = propColl.createFilter(pfs, true); //report only nesting properties, not enclosing ones. if (pf != null) { watchedFilters.put(mos, pf); } } catch(RemoteException re) { throw new RuntimeException(re); } } private static void unwatchManagedObject(ManagedObject mos) { if (watchedFilters.containsKey(mos)) { try { PropertyFilter pf = watchedFilters.remove(mos); pf.destroyPropertyFilter(); } catch (RemoteException e) { s_logger.error("Cannot unwatchManagedObject " + mos + " due to exception " + e); s_logger.error(Throwables.getStackTraceAsString(e)); } } } private EventHistoryCollector createEventHistoryCollector(ManagedObject mo, String[] events) throws InvalidState, RuntimeFault, RemoteException { if (eventManager == null) { s_logger.error("Cannot create EventHistoryCollector, eventManager is null"); return null; } EventFilterSpec eventFilterSpec = new EventFilterSpec(); eventFilterSpec.setType(events); // Create an Entity Event Filter Spec to // specify the MoRef of the MO to be get events filtered for EventFilterSpecByEntity entitySpec = new EventFilterSpecByEntity(); entitySpec.setEntity(mo.getMOR()); entitySpec.setRecursion(EventFilterSpecRecursionOption.children); // set the entity spec in the EventFilter eventFilterSpec.setEntity(entitySpec); if (vcenterConnectedTime != null) { EventFilterSpecByTime timeSpec = new EventFilterSpecByTime(); timeSpec.setBeginTime(vcenterConnectedTime); // set the time spec in the EventFilter eventFilterSpec.setTime(timeSpec); } // create the EventHistoryCollector to monitor events for a VM // and get the ManagedObjectReference of the EventHistoryCollector // returned EventHistoryCollector collector = eventManager.createCollectorForEvents(eventFilterSpec); collector.setCollectorPageSize(1000); collectors.add(collector); return collector; } private PropertyFilterSpec createEventFilterSpec(EventHistoryCollector collector) throws Exception { // Set up a PropertySpec to use the latestPage attribute // of the EventHistoryCollector PropertySpec propSpec = new PropertySpec(); propSpec.setAll(new Boolean(false)); propSpec.setPathSet(new String[] { "latestPage" }); propSpec.setType(collector.getMOR().getType()); // PropertySpecs are wrapped in a PropertySpec array PropertySpec[] propSpecAry = new PropertySpec[] { propSpec }; // Set up an ObjectSpec with the above PropertySpec for the // EventHistoryCollector we just created // as the Root or Starting Object to get Attributes for. ObjectSpec objSpec = new ObjectSpec(); objSpec.setObj(collector.getMOR()); objSpec.setSkip(new Boolean(false)); // Get Event objects in "latestPage" from "EventHistoryCollector" // and no "traversal" further, so, no SelectionSpec is specified objSpec.setSelectSet(new SelectionSpec[] {}); // ObjectSpecs are wrapped in an ObjectSpec array ObjectSpec[] objSpecAry = new ObjectSpec[] { objSpec }; PropertyFilterSpec spec = new PropertyFilterSpec(); spec.setPropSet(propSpecAry); spec.setObjectSet(objSpecAry); return spec; } private void handleUpdate(UpdateSet update) throws Exception { ObjectUpdate[] vmUpdates; PropertyFilterUpdate[] pfus = update.getFilterSet(); if (pfus == null) { return; } for (int pfui = 0; pfui < pfus.length; pfui++) { vmUpdates = pfus[pfui].getObjectSet(); if (vmUpdates == null) { continue; } for (ObjectUpdate vmi : vmUpdates) { handleChanges(vmi); } } } void handleChanges(ObjectUpdate oUpdate) throws Exception { PropertyChange[] changes = oUpdate.getChangeSet(); if (changes == null) { return; } String toolsRunningStatus = null; GuestNicInfo[] nics = null; for (int pci = 0; pci < changes.length; ++pci) { if (changes[pci] == null) { continue; } Object value = changes[pci].getVal(); String propName = changes[pci].getName(); PropertyChangeOp op = changes[pci].getOp(); if (op!= PropertyChangeOp.remove) { if (propName.equals("summary.ipPoolId")) { Integer newPoolId = (Integer)value; ManagedObjectReference mor = oUpdate.getObj(); if (watchedVNs.containsKey(mor.getVal())) { String vnUuid = watchedVNs.get(mor.getVal()); VirtualNetworkInfo vnInfo = MainDB.getVnById(vnUuid); Integer oldPoolId = vnInfo.getIpPoolId(); s_logger.info("Received Event ID summary.ipPoolId change to " + newPoolId + " from " + oldPoolId + " for " + vnInfo); if ((oldPoolId == null && newPoolId == null) || (oldPoolId != null && newPoolId != null && oldPoolId.equals(newPoolId))) { s_logger.info("Done processing property update, nothing changed"); continue; } VirtualNetworkInfo newVnInfo = new VirtualNetworkInfo(vnInfo); newVnInfo.setIpPoolId(newPoolId, vcenterDB); if ((newVnInfo.getIpPoolId() != null) && !newVnInfo.getIpPoolId().equals(oldPoolId)) { s_logger.info("IP Pool ID for " + newVnInfo + " set to " + newVnInfo.getIpPoolId()); vnInfo.update(newVnInfo, vncDB); } } else { s_logger.info("Received Event ID summary.ipPoolId property change to " + newPoolId + " for unwatched VN"); } } else if (propName.equals("guest.toolsRunningStatus")) { toolsRunningStatus = (String)value; s_logger.info("Received Event ID guest.toolsRunningStatus property change to " + toolsRunningStatus); } else if (value instanceof ArrayOfEvent) { s_logger.info("Received ArrayOfEvent"); ArrayOfEvent aoe = (ArrayOfEvent) value; Event[] evts = aoe.getEvent(); if (evts == null) { s_logger.info("Done processing array of events, null event received"); continue; } Arrays.sort(evts, new Comparator<Event>() { public int compare(Event e1, Event e2) { if (e1.getKey() == e2.getKey()) { return 0; } if (e1.getKey() < e2.getKey()) { return -1; } return 1; } }); for (int evtID = 0; evtID < evts.length; ++evtID) { Event anEvent = evts[evtID]; if (anEvent == null) { continue; } if (eventsLRUCache.containsKey(anEvent.getKey())) { s_logger.info("Skipping already handled Event ID " + anEvent.getKey()); continue; } eventsLRUCache.put(anEvent.getKey(), anEvent); printEvent(anEvent); eventHandler.handle(anEvent); } s_logger.info("Done processing array of events"); } else if ((value instanceof EnteredMaintenanceModeEvent) || (value instanceof HostConnectionLostEvent)) { Event anEvent = (Event) value; if (eventsLRUCache.containsKey(anEvent.getKey())) { s_logger.info("Skipping already handled Event ID " + anEvent.getKey()); } else { eventsLRUCache.put(anEvent.getKey(), anEvent); printEvent(anEvent); String hostName = anEvent.getHost().getName(); String vRouterIpAddress = vcenterDB.esxiToVRouterIpMap.get(hostName); if (vRouterIpAddress != null) { s_logger.info("Entering maintenance mode. Marking the host " + hostName + " inactive. VRouter ip address is " + anEvent.getHost().getName()); VRouterNotifier.setVrouterActive(vRouterIpAddress, false); } else { s_logger.info("Skipping event for unmanaged host " + hostName); } s_logger.info("Done processing event " + anEvent.getFullFormattedMessage()); } } else if ((value instanceof ExitMaintenanceModeEvent) || (value instanceof HostConnectedEvent)) { Event anEvent = (Event) value; if (eventsLRUCache.containsKey(anEvent.getKey())) { s_logger.info("Skipping already handled Event ID " + anEvent.getKey()); } else { eventsLRUCache.put(anEvent.getKey(), anEvent); printEvent(anEvent); String hostName = anEvent.getHost().getName(); String vRouterIpAddress = vcenterDB.esxiToVRouterIpMap.get(hostName); if (vRouterIpAddress != null) { s_logger.info("\nExit maintenance mode. Marking the host " + hostName + " active. VRouter IP address is " + vRouterIpAddress); VRouterNotifier.setVrouterActive(vRouterIpAddress, true); } else { s_logger.info("Skipping event for unmanaged host " + hostName); } s_logger.info("Done processing event " + anEvent.getFullFormattedMessage()); } } else if (value instanceof ArrayOfGuestNicInfo) { s_logger.info("Received event ID array of GuestNics"); ArrayOfGuestNicInfo aog = (ArrayOfGuestNicInfo) value; nics = aog.getGuestNicInfo(); } else if (value instanceof Event) { Event anEvent = (Event)value; if (eventsLRUCache.containsKey(anEvent.getKey())) { s_logger.info("Skipping already handled Event ID " + anEvent.getKey()); } else { eventsLRUCache.put(anEvent.getKey(), anEvent); printEvent(anEvent); eventHandler.handle(anEvent); } } else { if (value != null) { s_logger.info("\n Received unhandled property"); } else { s_logger.info("\n Received unhandled null value"); } } } else if (op == PropertyChangeOp.remove) { } } if (toolsRunningStatus != null || nics != null) { ManagedObjectReference mor = oUpdate.getObj(); if (watchedVMs.containsKey(mor.getVal())) { String vmUuid = watchedVMs.get(mor.getVal()); VirtualMachineInfo vmInfo = MainDB.getVmById(vmUuid); if (toolsRunningStatus != null) { s_logger.info("Set toolsRunning status to " + toolsRunningStatus + " for " + vmInfo); vmInfo.setToolsRunningStatus(toolsRunningStatus); } if (vmInfo.getToolsRunningStatus().equals( VirtualMachineToolsRunningStatus.guestToolsRunning.toString())) { vmInfo.updatedGuestNics(nics, vncDB); } else { s_logger.warn("Received guestNic info, but guestToolsRunningStatus is " + toolsRunningStatus + ", for " + vmInfo); } } s_logger.info("Done processing property update for MOR type " + mor.getType() + " , value " + mor.getVal()); } } public void start() { try { watchUpdates = new Thread(this); shouldRun = true; watchUpdates.start(); } catch (Exception e) { s_logger.error("Caught Exception : " + " Name : " + e.getClass().getName() + " Message : " + e.getMessage() + " Trace : "); s_logger.error(Throwables.getStackTraceAsString(e)); } } @SuppressWarnings("deprecation") public void terminate() throws Exception { shouldRun = false; propColl.cancelWaitForUpdates(); cleanupEventFilters(); vcenterDB.getServiceInstance().getServerConnection().logout(); watchUpdates.stop(); } private boolean connect2vnc() { TaskWatchDog.startMonitoring(this, "Init Vnc", 300000, TimeUnit.MILLISECONDS); try { s_logger.info("Connecting to the API server ..."); while (vncDB.Initialize() != true) { s_logger.info("Waiting for API server ..."); Thread.sleep(5000); } s_logger.info("Connected to the API server ..."); } catch (Exception e) { s_logger.error("Error while initializing connection with the API server: " + e); s_logger.error(Throwables.getStackTraceAsString(e)); TaskWatchDog.stopMonitoring(this); return false; } TaskWatchDog.stopMonitoring(this); return true; } private void connect2vcenter() { TaskWatchDog.startMonitoring(this, "Init VCenter", 300000, TimeUnit.MILLISECONDS); try { if (vcenterDB.connect(VCENTER_CONNECT_TIMEOUT) == true) { vCenterConnected = true; vcenterConnectedTime = vcenterDB.getLastTimeSeenAlive(); // cache PropertyCollector and EventManager for faster processing propColl = vcenterDB.getServiceInstance().getPropertyCollector(); eventManager = vcenterDB.getServiceInstance().getEventManager(); eventsLRUCache.clear(); createEventFilters(); } } catch (Exception e) { s_logger.error("Error while initializing VCenter connection: "); s_logger.error(Throwables.getStackTraceAsString(e)); } TaskWatchDog.stopMonitoring(this); } @Override public void run() { try { if (connect2vnc() == false) { return; } boolean syncNeeded = true; for (String version = "" ; shouldRun; ) { //check if you are the master from time to time //sometimes things don't go as planned if (VCenterMonitor.isZookeeperLeader() == false) { s_logger.warn("Lost zookeeper leadership. Restarting myself\n"); System.exit(0); } if (vCenterConnected == false) { connect2vcenter(); version = ""; syncNeeded = true; } while (vncDB.isVncApiServerAlive() == false) { s_logger.info("Waiting for API server... "); Thread.sleep(5000); } // Perform sync between VNC and VCenter DBs. if (syncNeeded) { s_logger.info("+++++++++++++ Start syncing +++++++++++++++++++++"); TaskWatchDog.startMonitoring(this, "Sync", 300000, TimeUnit.MILLISECONDS); // When sync is run, it also does // addPort to vrouter agent for existing VMIs. try { vcenterDB.setReadTimeout(VCENTER_READ_TIMEOUT); MainDB.sync(vcenterDB, vncDB, VCenterMonitor.mode); syncNeeded = false; } catch (Exception e) { vCenterConnected = false; s_logger.error("Error in sync: " + e); s_logger.error(Throwables.getStackTraceAsString(e)); TaskWatchDog.stopMonitoring(this); continue; } TaskWatchDog.stopMonitoring(this); s_logger.info("+++++++++++++ Done syncing +++++++++++++++++++++"); } s_logger.info("+++++++++++++ Waiting for events +++++++++++++++++++++"); try { WaitOptions wOpt = new WaitOptions(); wOpt.setMaxWaitSeconds(VCENTER_WAIT_FOR_UPDATES_SERVER_TIMEOUT); for ( ; ; ) { vcenterDB.setReadTimeout(VCENTER_WAIT_FOR_UPDATES_READ_TIMEOUT); TaskWatchDog.startMonitoring(this, "WaitForUpdatesEx", VCENTER_WAIT_FOR_UPDATES_READ_TIMEOUT + VCENTER_TIMEOUT_DELTA, TimeUnit.MILLISECONDS); UpdateSet update = propColl.waitForUpdatesEx(version, wOpt); TaskWatchDog.stopMonitoring(this); if (update != null && update.getFilterSet() != null) { this.handleUpdate(update); version = update.getVersion(); } else { vcenterDB.setReadTimeout(VCENTER_READ_TIMEOUT); TaskWatchDog.startMonitoring(this, "AlivenessCheck", VCENTER_READ_TIMEOUT + VCENTER_TIMEOUT_DELTA, TimeUnit.MILLISECONDS); if (vcenterDB.isAlive() == false) { s_logger.error("Vcenter connection lost, reconnect and resync needed"); vCenterConnected = false; TaskWatchDog.stopMonitoring(this); break; } TaskWatchDog.stopMonitoring(this); } } } catch (RemoteException e) { vCenterConnected = false; s_logger.info("Vcenter disconnected, reconnect and resync needed: " + e); s_logger.info(Throwables.getStackTraceAsString(e)); } catch (Exception e) { vCenterConnected = false; s_logger.error("Error in event handling, reconnect and resync needed"); s_logger.error(Throwables.getStackTraceAsString(e)); } } } catch (Exception e) { if (e instanceof RequestCanceled) { System.out.println("OK"); } else { s_logger.error("Caught Exception : " + " Name : " + e.getClass().getName() + " Message : " + e.getMessage() + " Trace : "); s_logger.error(Throwables.getStackTraceAsString(e)); } } } public static void printEvent(Event event) { s_logger.info("\n----------" + "\n Event ID: " + event.getKey() + "\n Event: " + event.getClass().getName() + ", happened on: " + event.getCreatedTime().getTime() + "\n FullFormattedMessage: " + event.getFullFormattedMessage() + "\n----------\n"); } public static VncDB getVncDB() { return vncDB; } private void createEventFilters() throws RemoteException { cleanupEventFilters(); createDvsEventFilter(vcenterDB.getContrailDvs()); createDatacenterEventFilter(vcenterDB.getDatacenter()); } private void createDvsEventFilter(VmwareDistributedVirtualSwitch dvs) throws RemoteException { String[] dvsEventNames = { // DV Port group events // DV port create "DVPortgroupCreatedEvent", // DV port modify "DVPortgroupReconfiguredEvent", "DVPortgroupRenamedEvent", // DV port delete "DVPortgroupDestroyedEvent" }; watchManagedObjectEvents(dvs, dvsEventNames); } private void createDatacenterEventFilter(Datacenter dc) throws RemoteException { if (dc == null) { s_logger.error("Cannot register for events on null datacenter "); return; } s_logger.info("Register for events on datacenter "); String[] eventNames = { // Host events "HostConnectionLostEvent", "HostConnectedEvent", "EnteredMaintenanceModeEvent", "ExitMaintenanceModeEvent", // VM events // VM create events "VmCreatedEvent", "VmClonedEvent", "VmDeployedEvent", // VM modify events "VmPoweredOnEvent", "DrsVmPoweredOnEvent", "VmPoweredOffEvent", "VmSuspendedEvent", "VmRenamedEvent", "VmMacChangedEvent", "VmMacAssignedEvent", "VmReconfiguredEvent", // VM Migration events "DrsVmMigratedEvent", "VmMigratedEvent", // VM delete events "VmRemovedEvent" }; watchManagedObjectEvents(dc, eventNames); } private void watchManagedObjectEvents(ManagedObject mos, String[] events) { if (mos == null || events == null) { s_logger.error("Null arguments in watchManagedObjectEvents"); return; } try { EventHistoryCollector collector = createEventHistoryCollector(mos, events); if (collector == null) { s_logger.error("Cannot create EventHistoryCollector for events" + events); return; } PropertyFilterSpec eventFilterSpec = createEventFilterSpec(collector); if (eventFilterSpec == null) { s_logger.error("Cannot create PropertyFilterSpec for EventHistoryCollector for events" + events); return; } PropertyFilter propFilter = propColl.createFilter(eventFilterSpec, true); if (propFilter != null) { watchedFilters.put(mos, propFilter); } else { s_logger.error("Cannot create event filter for managed object "); } } catch(Exception e) { s_logger.error("Cannot watchManagedObjectEvents for " + mos + ", exception " + e); s_logger.error(Throwables.getStackTraceAsString(e)); throw new RuntimeException(e); } } @SuppressWarnings("unused") private void unwatchManagedObjectEvents(ManagedObject mos) { if (mos == null) { s_logger.error("Null arguments in unwatchManagedObjectEvents"); return; } if (watchedFilters.containsKey(mos)) { try { PropertyFilter pf = watchedFilters.remove(mos); if (pf != null) { pf.destroyPropertyFilter(); } } catch (RemoteException e) { s_logger.error("Cannot unwatchManagedObjectEvents for " + mos + ", exception " + e); s_logger.error(Throwables.getStackTraceAsString(e)); } } } }