Java tutorial
/* werecloud provides a simple API to the VMWare vCenter data. Copyright (C) 2015 NigelB 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; either version 2 of the License, or (at your option) any later version. 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package werecloud.api.bean; import com.vmware.vim25.*; import com.vmware.vim25.mo.*; import com.vmware.vim25.mo.util.MorUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import werecloud.api.controller.v1_0_0.VirtualMachineController; import werecloud.api.model.ConnectionModel; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * <code>VMWareMacCache</code> * Date: 28/12/2014 * Time: 1:05 PM */ public class VMWareMacCache implements ApplicationListener, Runnable { private PropertyFilter propFilter; private EventManager _eventManager; private Thread updaeThread; private Logger logger = LoggerFactory.getLogger(VirtualMachineController.class); private Folder rootFolder; // public static Logger private ServiceInstance si = null; private ConnectionModel conn; private EventHistoryCollector collector; private int loadThreads; private Hashtable<String, String> macAddresses = new Hashtable<String, String>(); private Hashtable<String, String> vmIDMap = new Hashtable<String, String>(); private PropertyCollector propColl; private EventHistoryCollector _eventHistoryCollector; private volatile boolean running = true; public VMWareMacCache(ConnectionModel connection, int loadThreads) throws MalformedURLException, RemoteException { System.out.println(connection); System.out.println(loadThreads); this.conn = connection; this.loadThreads = loadThreads; try { si = conn.getServiceInstance(); rootFolder = si.getRootFolder(); initializeMACCache(); } catch (RemoteException e) { si = null; e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } try { _eventManager = si.getEventManager(); createEventHistoryCollector(); PropertyFilterSpec eventFilterSpec = createEventFilterSpec(); propColl = si.getPropertyCollector(); propFilter = propColl.createFilter(eventFilterSpec, true); updaeThread = new Thread(this); updaeThread.start(); } catch (Exception e) { e.printStackTrace(); } } private void createEventHistoryCollector() throws Exception { // Create an Entity Event Filter Spec to // specify the MoRef of the VM to be get events filtered for EventFilterSpecByEntity entitySpec = new EventFilterSpecByEntity(); entitySpec.setEntity(rootFolder.getMOR()); entitySpec.setRecursion(EventFilterSpecRecursionOption.children); // set the entity spec in the EventFilter EventFilterSpec eventFilter = new EventFilterSpec(); eventFilter.setEntity(entitySpec); // we are only interested in getting events for the VM. // Add as many events you want to track relating to vm. // Refer to API Data Object vmEvent and see the extends class list for // elaborate list of vmEvents eventFilter.setType( new String[] { "VmReconfiguredEvent", "VmRenamedEvent", "VmCreatedEvent", "VmRemovedEvent" }); // eventFilter.setType(new String[] { "VmPoweredOffEvent", // "VmPoweredOnEvent", "VmSuspendedEvent", "VmRenamedEvent" }); // create the EventHistoryCollector to monitor events for a VM // and get the ManagedObjectReference of the EventHistoryCollector // returned _eventHistoryCollector = _eventManager.createCollectorForEvents(eventFilter); } private PropertyFilterSpec createEventFilterSpec() { // 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(_eventHistoryCollector.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(_eventHistoryCollector.getMOR()); objSpec.setSkip(new Boolean(false)); // Get Event objects in "latestPage" from "EventHistoryCollector" // and no "traversl" 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; } public String getVM(String mac) { logger.info("Requesting name of vm with MAC address: {}, found: {} ", mac.toUpperCase(), macAddresses.get(mac.toUpperCase())); return macAddresses.get(mac.toUpperCase()); } private void initializeMACCache() throws RemoteException, InterruptedException { long start = System.currentTimeMillis(); ManagedEntity[] mes = new InventoryNavigator(rootFolder).searchManagedEntities("VirtualMachine"); ExecutorService exec = Executors.newFixedThreadPool(loadThreads); try { for (final ManagedEntity me : mes) { exec.submit(new Runnable() { @Override public void run() { VirtualMachine vm = (VirtualMachine) me; addVirtualMachine(vm); } }); } } finally { exec.shutdown(); } exec.awaitTermination(1, TimeUnit.HOURS); logger.info("{} MAC addresses added and took {} milliseconds.", macAddresses.size(), System.currentTimeMillis() - start); } private void addVirtualMachine(VirtualMachine vm) { vmIDMap.put(vm.getMOR().get_value(), vm.getName()); VirtualMachineConfigInfo config = vm.getConfig(); for (VirtualDevice virtualDevice : config.getHardware().getDevice()) { if (virtualDevice instanceof VirtualEthernetCard) { macAddresses.put(((VirtualEthernetCard) virtualDevice).getMacAddress().toUpperCase(), vm.getName()); logger.debug("Adding MAC {} for vm {}", ((VirtualEthernetCard) virtualDevice).getMacAddress().toUpperCase(), vm.getName()); } } } private void removeVMByName(String name) { ArrayList<String> toRemove = new ArrayList<String>(); for (Map.Entry<String, String> macEntry : macAddresses.entrySet()) { if (macEntry.getValue().equals(name)) { toRemove.add(macEntry.getKey()); } } for (String invalidMACAddress : toRemove) { macAddresses.remove(invalidMACAddress); logger.trace(String.format("Removing MAC address: %s for %s", invalidMACAddress, name)); } for (Map.Entry<String, String> stringStringEntry : vmIDMap.entrySet()) { if (stringStringEntry.getValue().equals(name)) { vmIDMap.remove(stringStringEntry.getValue()); logger.trace("Removed " + stringStringEntry.getKey() + " -> " + stringStringEntry.getValue() + " from vmIDMap"); } } } @Override public void onApplicationEvent(ApplicationEvent event) { try { Method m = this.getClass().getMethod("handle", event.getClass()); m.invoke(this, event); return; } catch (NoSuchMethodException nme) { logger.trace(String.format("Unhandled event: %s", event)); } catch (Exception e) { logger.error("Error: ", e); } // logger.trace(event.toString()); } public void handle(ContextRefreshedEvent event) { System.out.println(event); } public void handle() { } private void handleUpdate(UpdateSet update) { ObjectUpdate[] vmUpdates; PropertyFilterUpdate[] pfus = update.getFilterSet(); for (int pfui = 0; pfui < pfus.length; pfui++) { // System.out.println("Virtual Machine updates:"); vmUpdates = pfus[pfui].getObjectSet(); for (ObjectUpdate vmi : vmUpdates) { // System.out.println("Handling object update"); handleObjectUpdate(vmi); } } } void handleObjectUpdate(ObjectUpdate oUpdate) { PropertyChange[] pc = oUpdate.getChangeSet(); // System.out.println("Update kind = " + oUpdate.getKind()); if (oUpdate.getKind() == ObjectUpdateKind.enter) { // System.out.println(" New Data:"); handleChanges(pc); } else if (oUpdate.getKind() == ObjectUpdateKind.leave) { // System.out.println(" Removed Data:"); handleChanges(pc); } else if (oUpdate.getKind() == ObjectUpdateKind.modify) { // System.out.println(" Changed Data:"); handleChanges(pc); } } synchronized void handleChanges(PropertyChange[] changes) { for (int pci = 0; pci < changes.length; ++pci) { String name = changes[pci].getName(); Object value = changes[pci].getVal(); PropertyChangeOp op = changes[pci].getOp(); if (value != null && op != PropertyChangeOp.remove) { // logger.debug(String.format("Unhandled: %s", value)); /* System.out.println("==============="); System.out.println("\nEvent Details follows:"); if (value instanceof ArrayOfEvent) { ArrayOfEvent aoe = (ArrayOfEvent) value; Event[] evts = aoe.getEvent(); for (int evtID = 0; evtID < evts.length; ++evtID) { Event anEvent = evts[evtID]; System.out.println("\n----------" + "\n Event ID: " + anEvent.getKey() + "\n Event: " + anEvent.getClass().getName() + "\n FullFormattedMessage: " + anEvent.getFullFormattedMessage() + "\n VM Reference: " + anEvent.getVm().getVm().get_value() + "\n----------\n"); } } else*/ if (value instanceof VmEvent) { VmEvent anEvent = (VmEvent) value; // System.out.println("\n----------" + "\n Event ID: " // + anEvent.getKey() + "\n Event: " // + anEvent.getClass().getName() // + "\n FullFormattedMessage: " // + anEvent.getFullFormattedMessage() // + "\n VM Reference: " // + anEvent.getVm().getVm().get_value() // + "\n----------\n"); try { logger.trace(anEvent.getClass().toString()); Method m = VMWareMacCache.class.getDeclaredMethod("handleEvent", anEvent.getClass()); logger.trace(String.format("Event Handler: %s", m)); m.invoke(this, anEvent); } catch (NoSuchMethodException e) { logger.debug(String.format("1. Unhandled: %s", anEvent)); } catch (InvocationTargetException e) { logger.debug(String.format("2. Unhandled: %s", anEvent)); } catch (IllegalAccessException e) { logger.debug(String.format("3. Unhandled: %s", anEvent)); } } // System.out.println("==============="); } } } private void handleEvent(VmRenamedEvent renamedEvent) { VirtualMachine vm = (VirtualMachine) MorUtil.createExactManagedObject(si.getServerConnection(), renamedEvent.getVm().getVm()); ArrayList<String> toRename = new ArrayList<String>(); vmIDMap.put(vm.getMOR().get_value(), renamedEvent.getNewName()); for (Map.Entry<String, String> macEntry : macAddresses.entrySet()) { if (macEntry.getValue().equals(renamedEvent.getOldName())) { toRename.add(macEntry.getKey()); } } for (String mac : toRename) { macAddresses.put(mac, renamedEvent.getNewName()); logger.debug("Renamed " + mac + " to " + renamedEvent.getNewName()); } } private void handleEvent(VmReconfiguredEvent vmEvent) { VirtualMachine vm = (VirtualMachine) MorUtil.createExactManagedObject(si.getServerConnection(), vmEvent.getVm().getVm()); logger.trace(String.format("%s reconfigured.", vm.getName())); String name = vm.getName(); // if (vmIDMap.containsKey(vm.getMOR().get_value())) { // name = vmIDMap.get(vm.getMOR().get_value()); // } removeVMByName(name); addVirtualMachine(vm); } private void handleEvent(VmCreatedEvent vmEvent) { VirtualMachine vm = (VirtualMachine) MorUtil.createExactManagedObject(si.getServerConnection(), vmEvent.getVm().getVm()); logger.trace(String.format("Adding Virtual Machine: %s", vm.getName())); addVirtualMachine(vm); } private void handleEvent(VmRemovedEvent vmEvent) { logger.trace(String.format("Removing VM %s", vmEvent.getVm().getName())); removeVMByName(vmEvent.getVm().getName()); } @Override public void run() { String version = ""; while (running) { try { UpdateSet update = propColl.waitForUpdates(version); if (update != null && update.getFilterSet() != null) { version = update.getVersion(); logger.info(" Current Version: " + version); handleUpdate(update); } else { logger.warn("No update is present!"); } } catch (Throwable e) { logger.error(e.getMessage(), e); } } } }