/** * Copyright (c) 2016 Inria * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * - Philippe Merle <philippe.merle@inria.fr> * - Christophe Gourdin <christophe.gourdin@inria.fr> * * Generated at Tue May 10 13:08:38 CEST 2016 from platform:/plugin/org.occiware.clouddesigner.occi.infrastructure/model/Infrastructure.occie by org.occiware.clouddesigner.occi.gen.connector */ package org.occiware.clouddesigner.occi.infrastructure.connector.vmware; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vmware.vim25.Description; import com.vmware.vim25.GuestNicInfo; import com.vmware.vim25.HostPortGroup; import com.vmware.vim25.HostPortGroupPort; import com.vmware.vim25.HostVirtualSwitch; import com.vmware.vim25.MethodFault; import com.vmware.vim25.TaskInfo; import com.vmware.vim25.TaskInfoState; import com.vmware.vim25.VirtualDeviceConfigSpec; import com.vmware.vim25.VirtualDeviceConfigSpecOperation; import com.vmware.vim25.VirtualDeviceConnectInfo; import com.vmware.vim25.VirtualEthernetCard; import com.vmware.vim25.VirtualMachineConfigSpec; import com.vmware.vim25.mo.Folder; import com.vmware.vim25.mo.HostSystem; import com.vmware.vim25.mo.Network; import com.vmware.vim25.mo.ServiceInstance; import com.vmware.vim25.mo.Task; import com.vmware.vim25.mo.VirtualMachine; import com.vmware.vim25.mox.VirtualMachineDeviceManager; import java.lang.reflect.InvocationTargetException; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.net.util.SubnetUtils; import org.apache.log4j.Level; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.common.util.EList; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.xtext.xtext.ecoreInference.EClassifierInfo.EClassInfo.FindResult; import org.occiware.clouddesigner.occi.Attribute; import org.occiware.clouddesigner.occi.AttributeState; import org.occiware.clouddesigner.occi.Configuration; import org.occiware.clouddesigner.occi.Link; import org.occiware.clouddesigner.occi.Mixin; import org.occiware.clouddesigner.occi.OCCIFactory; import org.occiware.clouddesigner.occi.Resource; import org.occiware.clouddesigner.occi.infrastructure.Architecture; import org.occiware.clouddesigner.occi.infrastructure.NetworkInterfaceStatus; import org.occiware.clouddesigner.occi.infrastructure.NetworkStatus; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.DatacenterNotFoundException; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.DatastoreNotFoundException; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.VirtualSwitchNotFoundException; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.allocator.Allocator; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.allocator.AllocatorImpl; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils.DatacenterHelper; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils.DatastoreHelper; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils.HostHelper; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils.NetworkHelper; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils.VCenterClient; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils.VMHelper; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils.thread.EntityUtils; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils.thread.EntityUtilsHeadless; import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils.thread.UIDialog; import org.occiware.clouddesigner.occi.util.OcciHelper; /** * Connector implementation for the OCCI kind: - scheme: * http://schemas.ogf.org/occi/infrastructure# - term: network - title: Network * Resource */ public class NetworkConnector extends org.occiware.clouddesigner.occi.infrastructure.impl.NetworkImpl { /** * Initialize the logger. */ private static Logger LOGGER = LoggerFactory.getLogger(NetworkConnector.class); private static final String ATTR_HOSTSYSTEM_NAME = "hostsystemname"; private static final String ATTR_DATACENTER_NAME = "datacentername"; private static final String ATTR_DATASTORE_NAME = "datastorename"; private static final String ATTR_CLUSTER_NAME = "clustername"; private static final String ATTR_VSWITCH_NBPORT = "nbport"; private static final String VMWARE_MIXIN_FOLDERS_TERM = "vmwarefolders"; private static final String VMWARE_MIXIN_VSWITCH_INFOS_TERM = "vswitchinfos"; // Message to end users management. private String titleMessage = ""; private String globalMessage = ""; private Level levelMessage = null; private String nbPortStr = null; private String vSwitchName = null; private String portGroupName = null; private int vlanId = 0; /** * Managed object reference id. Unique reference for virtual machine. */ private String morId; /** * Represent the physical compute which be used for this standard switch. */ private String hostSystemName = null; /** * Constructs a network connector. */ NetworkConnector() { LOGGER.debug("Constructor called on " + this); } // // OCCI CRUD callback operations. // /** * Called when this Network instance is completely created. */ @Override public void occiCreate() { titleMessage = "Reference a vswitch and retrieve it : " + getTitle(); // IRunnableWithProgress runnableWithProgress = new IRunnableWithProgress() { // // @Override // public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { // LOGGER.debug("occiCreate() called on " + this); // if (!VCenterClient.checkConnection()) { // // Must return true if connection is established. // return; // } // ServiceInstance si = VCenterClient.getServiceInstance(); // Folder rootFolder = si.getRootFolder(); // // String vSwitchName = getTitle(); // String networkName = getLabel(); // // if (vSwitchName == null) { // // No name ==> no vswitch. // globalMessage = "The vswitch name is not setted, please check your configuration (attribute title)."; // levelMessage = Level.INFO; // LOGGER.warn(globalMessage); // VCenterClient.disconnect(); // return; // } // Allocator allocator = new AllocatorImpl(rootFolder); // // // Create a new vSwitch and add his network name. // // // 1 : Check if this vSwitch exist. // // // Get the attribute value for occi.network.vmware.hostsystemname. // hostSystemName = getAttributeValueByOcciKey(ATTR_HOSTSYSTEM_NAME); // if (hostSystemName == null) { // // Get the host system if set on computes link via network adapters // // and set it. // findAndSetHostSystemNameFromLinkedVMs(); // } // if (hostSystemName == null) { // // Auto allocation. // LOGGER.info("Auto allocating a host system"); // allocator.allocateDatacenter(); // allocator.allocateCluster(); // allocator.allocateHostSystem(); // } // // if (hostSystemName == null) { // LOGGER.error( // "Cant create the vswitch and port group, no host system defined, please set the attribute occi.network.vmware.hostsystemname"); // VCenterClient.disconnect(); // return; // } // // Load the hostsystem object. // // HostSystem host = HostHelper.findHostSystemForName(rootFolder, getHostSystemName()); // if (host == null) { // LOGGER.error("The host system : " + hostSystemName + " doesnt exist on vCenter with your ids."); // VCenterClient.disconnect(); // return; // } // HostVirtualSwitch hostVswitch = null; // try { // hostVswitch = NetworkHelper.findVSwitch(host, vSwitchName); // } catch (VirtualSwitchNotFoundException ex) { // // no op. // } // if (hostVswitch == null) { // nbPortStr = getAttributeValueByOcciKey(ATTR_VSWITCH_NBPORT); // if (nbPortStr == null || nbPortStr.isEmpty()) { // nbPortStr = "8"; // } // int nbPort = 8; // try { // nbPort = Integer.valueOf(nbPortStr); // } catch (NumberFormatException ex) { // LOGGER.error("bad value for " + ATTR_VSWITCH_NBPORT); // LOGGER.error("Cant create the vswitch."); // VCenterClient.disconnect(); // return; // } // // // Get the ip Addresses in cidr notation. // SubnetUtils subnetUtil = new SubnetUtils(getAttributeValueByOcciKey("occi.network.address")); // String netmask = subnetUtil.getInfo().getNetmask(); // String ipAddress = subnetUtil.getInfo().getAddress(); // // String networkAddress = subnetUtil.getInfo().getNetworkAddress(); // String vmKernelIpAddress; // boolean dhcpMode = (getAttributeValueByOcciKey("occi.network.allocation") != null && getAttributeValueByOcciKey("occi.network.allocation").equals("dynamic")); // // // Create the vswitch (without set macAddress, null value).. // try { // NetworkHelper.createVSwitch(vSwitchName, networkName, nbPort, getVlan(), host, null, ipAddress, netmask, dhcpMode); // } catch (RemoteException ex) { // // TODO : Message global. // } // } else { // LOGGER.warn("Cant create the vswitch : " + vSwitchName + " for the host : " + hostSystemName + " , cause it already exist."); // VCenterClient.disconnect(); // return; // } // // // 2 : check if created. // try { // hostVswitch = NetworkHelper.findVSwitch(host, vSwitchName); // } catch (VirtualSwitchNotFoundException ex) { // LOGGER.warn("The vswitch is not created, please check your configuration."); // } // // VCenterClient.disconnect(); // // } // }; // // UIDialog.executeActionThread(runnableWithProgress, titleMessage); // // if (globalMessage != null && !globalMessage.isEmpty()) { // UIDialog.showUserMessage(titleMessage, globalMessage, levelMessage); // } // // retrieve resource informations when no errors has been launched. // if (levelMessage != null && !Level.ERROR.equals(levelMessage)) { // occiRetrieve(); // } // globalMessage = ""; // levelMessage = null; // occiRetrieve(); } /** * Search on the linked virtual machine if any the host system name. * * @return */ private void findAndSetHostSystemNameFromLinkedVMs() { Configuration conf = OcciHelper.getConfiguration(this); List<Resource> resources = conf.getResources(); ComputeConnector compute = null; Resource target; boolean found; for (Resource res : resources) { found = false; if (res instanceof ComputeConnector) { // Check if this compute is linked to this vswitch by his // adapters. EList<Link> links = res.getLinks(); for (Link link : links) { if (link instanceof NetworkinterfaceConnector) { // Check if this network interface is linked to this // vswitch. target = link.getTarget(); if (target != null && this.equals(target)) { // We found a compute linked to this network // vswitch. compute = (ComputeConnector) res; found = true; break; } } } if (found) { break; } } } if (compute != null) { // Get the host system name. // to be sure to get the host system name, we refresh this object // before. compute.occiRetrieve(); if (compute.getHostSystemName() != null) { this.setHostSystemName(compute.getHostSystemName()); } } } /** * Called when this Network instance must be retrieved. */ @Override public void occiRetrieve() { titleMessage = "Retrieve a vswitch : " + getTitle(); LOGGER.debug("occiRetrieve() called on " + this); if (UIDialog.isStandAlone()) { // Launching thread with business code. LOGGER.debug("Console mode."); // Retrieve a compute without monitoring. retrieveNetwork(null); } else { // Launching IRunnableWithProgress UI thread with business code. LOGGER.debug("UI mode."); IRunnableWithProgress runnableWithProgress = new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { retrieveNetwork(monitor); } }; UIDialog.executeActionThread(runnableWithProgress, titleMessage); if (globalMessage != null && !globalMessage.isEmpty()) { UIDialog.showUserMessage(titleMessage, globalMessage, levelMessage); } updateAttributesOnNetwork(); } globalMessage = ""; levelMessage = null; if (VCenterClient.isConnected()) { VCenterClient.disconnect(); } } /** * Called when this Network instance is completely updated. */ @Override public void occiUpdate() { titleMessage = "Update a vswitch : " + getTitle(); LOGGER.debug("occiUpdate() called on " + this); // if (!VCenterClient.checkConnection()) { // // Must return true if connection is established. // return; // } // // // // VCenterClient.disconnect(); } /** * Called when this Network instance will be deleted. */ @Override public void occiDelete() { titleMessage = "Delete a vswitch: " + getTitle(); LOGGER.debug("occiDelete() called on " + this); // if (!VCenterClient.checkConnection()) { // // Must return true if connection is established. // return; // } // // // TODO : Remove vSwitch network and detach his linked adapters device // // from network. // // VCenterClient.disconnect(); } // // Network actions. // /** * Implement OCCI action: - scheme: * http://schemas.ogf.org/occi/infrastructure/network/action# - term: up - * title: */ @Override public void up() { titleMessage = "Enable a vswitch : " + getTitle(); LOGGER.debug("Action up() called on " + this); // if (!VCenterClient.checkConnection()) { // // Must return true if connection is established. // return; // } // // // Activate vswitch. // // VCenterClient.disconnect(); } /** * Implement OCCI action: - scheme: * http://schemas.ogf.org/occi/infrastructure/network/action# - term: down - * title: */ @Override public void down() { titleMessage = "Disable a vwitch : " + getTitle(); LOGGER.debug("Action down() called on " + this); // if (!VCenterClient.checkConnection()) { // // Must return true if connection is established. // return; // } // // // TODO : Disconnect all network interfaces. // // VCenterClient.disconnect(); } /** * get attribute value with his occi key, deserve when no property value * set, with Mixin attribute as it is defined by Cloud designer. * * @param key * @return an attribute value, null if no one is found. */ public String getAttributeValueByOcciKey(String key) { String value = null; if (key == null) { return value; } List<AttributeState> attrs = this.getAttributes(); for (AttributeState attr : attrs) { if (attr.getName().equals(key)) { value = attr.getValue(); break; } } return value; } /** * Create an attribute without add this to the current connector object. * * @param name * @param value * @return AttributeState object. */ public AttributeState createAttribute(final String name, final String value) { AttributeState attr = OCCIFactory.eINSTANCE.createAttributeState(); attr.setName(name); attr.setValue(value); return attr; } /** * Get an attribute state object for key parameter. * * @param key * ex: occi.core.title. * @return an AttributeState object, if attribute doesnt exist, null value * is returned. */ private AttributeState getAttributeStateObject(final String key) { AttributeState attr = null; if (key == null) { return attr; } // Load the corresponding attribute state. for (AttributeState attrState : this.getAttributes()) { if (attrState.getName().equals(key)) { attr = attrState; break; } } return attr; } public String getHostSystemName() { return hostSystemName; } public void setHostSystemName(String hostSystemName) { this.hostSystemName = hostSystemName; } /** * Check if this compute has mixin vmware folder addon. * * @return */ public boolean hasMixinVMwareFolders() { boolean result = false; String mixinTerm = null; List<Mixin> mixins = this.getMixins(); for (Mixin mixin : mixins) { mixinTerm = mixin.getTerm(); // This mixin contains attributes for datacenter, datastore, cluster // and others goodies on folders. if (mixinTerm.equals(VMWARE_MIXIN_FOLDERS_TERM)) { result = true; break; } } return result; } /** * Has vswitch infos folders. * @return */ public boolean hasMixinVSwitchInfos() { boolean result = false; String mixinTerm = null; List<Mixin> mixins = this.getMixins(); for (Mixin mixin : mixins) { mixinTerm = mixin.getTerm(); // This mixin contains attributes for datacenter, datastore, cluster // and others goodies on folders. if (mixinTerm.equals(VMWARE_MIXIN_VSWITCH_INFOS_TERM)) { result = true; break; } } return result; } /** * Update this object attributes. */ public void updateAttributesOnNetwork() { Map<String, String> attrsToCreate = new HashMap<>(); Map<String, String> attrsToUpdate = new HashMap<>(); List<String> attrsToDelete = new ArrayList<>(); // // ATTR_DATACENTER_NAME // if (datacenterName != null) { // if (this.getAttributeValueByOcciKey(ATTR_DATACENTER_NAME) == null) { // attrsToCreate.put(ATTR_DATACENTER_NAME, datacenterName); // } else { // // update // attrsToUpdate.put(ATTR_DATACENTER_NAME, datacenterName); // } // } // if (datastoreName != null) { // // ATTR_DATASTORE_NAME // if (this.getAttributeValueByOcciKey(ATTR_DATASTORE_NAME) == null) { // attrsToCreate.put(ATTR_DATASTORE_NAME, datastoreName); // } else { // attrsToUpdate.put(ATTR_DATASTORE_NAME, datastoreName); // } // } // // // ATTR_CLUSTER_NAME // if (clusterName != null) { // if (this.getAttributeValueByOcciKey(ATTR_CLUSTER_NAME) == null) { // attrsToCreate.put(ATTR_CLUSTER_NAME, clusterName); // } else { // attrsToUpdate.put(ATTR_CLUSTER_NAME, clusterName); // } // } boolean hasMixinVMwareFolders = hasMixinVMwareFolders(); boolean hasMixinVswitchInfos = hasMixinVSwitchInfos(); // ATTR_HOSTSYSTEM_NAME if (hostSystemName != null && hasMixinVMwareFolders) { if (this.getAttributeStateObject(ATTR_HOSTSYSTEM_NAME) == null) { attrsToCreate.put(ATTR_HOSTSYSTEM_NAME, hostSystemName); } else { attrsToUpdate.put(ATTR_HOSTSYSTEM_NAME, hostSystemName); } } // ATTR_VSWITCH_NBPORT. if (nbPortStr != null && hasMixinVswitchInfos) { if (this.getAttributeStateObject(ATTR_VSWITCH_NBPORT) == null) { attrsToCreate.put(ATTR_VSWITCH_NBPORT, nbPortStr); } else { attrsToUpdate.put(ATTR_VSWITCH_NBPORT, nbPortStr); } } if (UIDialog.isStandAlone()) { // Headless environment. EntityUtilsHeadless.updateAttributes(this, attrsToCreate, attrsToUpdate, attrsToDelete); } else { // Gui environment EntityUtils.updateAttributes(this, attrsToCreate, attrsToUpdate, attrsToDelete); } if (vSwitchName != null && !vSwitchName.isEmpty()) { this.setTitle(vSwitchName); this.setState(NetworkStatus.ACTIVE); } this.setVlan(vlanId); if (portGroupName != null && !portGroupName.isEmpty()) { this.setLabel(portGroupName); } } /** * Retrieve a vswitch from network label (port group) and others infos. * @param monitor must be null if we are in console mode */ public void retrieveNetwork(IProgressMonitor monitor) { if (!VCenterClient.checkConnection()) { // Must return true if connection is established. globalMessage = "No connection to Vcenter has been established."; levelMessage = Level.WARN; LOGGER.warn(globalMessage); return; } ServiceInstance si = VCenterClient.getServiceInstance(); Folder rootFolder = si.getRootFolder(); // Search a host that contain this portgroup. String networkLabelName = getLabel(); if (networkLabelName == null || networkLabelName.isEmpty()) { globalMessage = "No label for this network, please set the attribute label."; levelMessage = Level.ERROR; LOGGER.error(globalMessage); return; } HostSystem host = HostHelper.findHostForPortGroup(rootFolder, networkLabelName); if (host == null) { globalMessage = "No host found for this port group : " + networkLabelName; levelMessage = Level.ERROR; LOGGER.error(globalMessage); return; } HostPortGroup portGroup = NetworkHelper.findPortGroup(host, networkLabelName); if (portGroup == null) { globalMessage = "No portGroup found cant retrieve vswitch informations."; levelMessage = Level.ERROR; LOGGER.error(globalMessage); return; } // Find now the network. vSwitchName = portGroup.getSpec().getVswitchName(); vlanId = portGroup.getSpec().getVlanId(); portGroupName = networkLabelName; hostSystemName = host.getName(); try { HostVirtualSwitch hostVswitch = NetworkHelper.findVSwitch(host, vSwitchName); nbPortStr = "" + hostVswitch.getNumPorts(); } catch (VirtualSwitchNotFoundException ex) { globalMessage = "The vswitch : " + vSwitchName + " is not found, please check your configuration."; levelMessage = Level.WARN; LOGGER.warn(globalMessage); return; } // TODO : How to check that vswitch / port group is active ? // Set the network state. if (UIDialog.isStandAlone()) { updateAttributesOnNetwork(); } } }