You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by al...@apache.org on 2012/06/29 02:45:07 UTC
[37/50] [abbrv] moving out VMWAre and Nexus VSM support code into
plugins/hypervisors/vmware
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8197f1f0/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
new file mode 100755
index 0000000..a8c61f6
--- /dev/null
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -0,0 +1,4202 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License. Citrix Systems, Inc.
+// reserves all rights not expressly granted by the License.
+// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.hypervisor.vmware.resource;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.nio.channels.SocketChannel;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.TimeZone;
+import java.util.UUID;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.NDC;
+
+import com.cloud.agent.IAgentControl;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.AttachIsoCommand;
+import com.cloud.agent.api.AttachVolumeAnswer;
+import com.cloud.agent.api.AttachVolumeCommand;
+import com.cloud.agent.api.BackupSnapshotAnswer;
+import com.cloud.agent.api.BackupSnapshotCommand;
+import com.cloud.agent.api.BumpUpPriorityCommand;
+import com.cloud.agent.api.CheckHealthAnswer;
+import com.cloud.agent.api.CheckHealthCommand;
+import com.cloud.agent.api.CheckNetworkAnswer;
+import com.cloud.agent.api.CheckNetworkCommand;
+import com.cloud.agent.api.CheckOnHostAnswer;
+import com.cloud.agent.api.CheckOnHostCommand;
+import com.cloud.agent.api.CheckRouterAnswer;
+import com.cloud.agent.api.CheckRouterCommand;
+import com.cloud.agent.api.CheckVirtualMachineAnswer;
+import com.cloud.agent.api.CheckVirtualMachineCommand;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
+import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
+import com.cloud.agent.api.CreateStoragePoolCommand;
+import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer;
+import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
+import com.cloud.agent.api.DeleteStoragePoolCommand;
+import com.cloud.agent.api.GetDomRVersionAnswer;
+import com.cloud.agent.api.GetDomRVersionCmd;
+import com.cloud.agent.api.GetHostStatsAnswer;
+import com.cloud.agent.api.GetHostStatsCommand;
+import com.cloud.agent.api.GetStorageStatsAnswer;
+import com.cloud.agent.api.GetStorageStatsCommand;
+import com.cloud.agent.api.GetVmStatsAnswer;
+import com.cloud.agent.api.GetVmStatsCommand;
+import com.cloud.agent.api.GetVncPortAnswer;
+import com.cloud.agent.api.GetVncPortCommand;
+import com.cloud.agent.api.HostStatsEntry;
+import com.cloud.agent.api.MaintainAnswer;
+import com.cloud.agent.api.MaintainCommand;
+import com.cloud.agent.api.ManageSnapshotAnswer;
+import com.cloud.agent.api.ManageSnapshotCommand;
+import com.cloud.agent.api.MigrateAnswer;
+import com.cloud.agent.api.MigrateCommand;
+import com.cloud.agent.api.ModifySshKeysCommand;
+import com.cloud.agent.api.ModifyStoragePoolAnswer;
+import com.cloud.agent.api.ModifyStoragePoolCommand;
+import com.cloud.agent.api.NetworkUsageAnswer;
+import com.cloud.agent.api.NetworkUsageCommand;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.PingRoutingCommand;
+import com.cloud.agent.api.PingTestCommand;
+import com.cloud.agent.api.PoolEjectCommand;
+import com.cloud.agent.api.PrepareForMigrationAnswer;
+import com.cloud.agent.api.PrepareForMigrationCommand;
+import com.cloud.agent.api.ReadyAnswer;
+import com.cloud.agent.api.ReadyCommand;
+import com.cloud.agent.api.RebootAnswer;
+import com.cloud.agent.api.RebootCommand;
+import com.cloud.agent.api.RebootRouterCommand;
+import com.cloud.agent.api.SetupAnswer;
+import com.cloud.agent.api.SetupCommand;
+import com.cloud.agent.api.StartAnswer;
+import com.cloud.agent.api.StartCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.agent.api.StartupStorageCommand;
+import com.cloud.agent.api.StopAnswer;
+import com.cloud.agent.api.StopCommand;
+import com.cloud.agent.api.StoragePoolInfo;
+import com.cloud.agent.api.UpgradeSnapshotCommand;
+import com.cloud.agent.api.ValidateSnapshotAnswer;
+import com.cloud.agent.api.ValidateSnapshotCommand;
+import com.cloud.agent.api.VmStatsEntry;
+import com.cloud.agent.api.check.CheckSshAnswer;
+import com.cloud.agent.api.check.CheckSshCommand;
+import com.cloud.agent.api.routing.DhcpEntryCommand;
+import com.cloud.agent.api.routing.IpAssocAnswer;
+import com.cloud.agent.api.routing.IpAssocCommand;
+import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
+import com.cloud.agent.api.routing.NetworkElementCommand;
+import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
+import com.cloud.agent.api.routing.SavePasswordCommand;
+import com.cloud.agent.api.routing.SetFirewallRulesAnswer;
+import com.cloud.agent.api.routing.SetFirewallRulesCommand;
+import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer;
+import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
+import com.cloud.agent.api.routing.SetStaticNatRulesAnswer;
+import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
+import com.cloud.agent.api.routing.VmDataCommand;
+import com.cloud.agent.api.routing.VpnUsersCfgCommand;
+import com.cloud.agent.api.storage.CopyVolumeAnswer;
+import com.cloud.agent.api.storage.CopyVolumeCommand;
+import com.cloud.agent.api.storage.CreateAnswer;
+import com.cloud.agent.api.storage.CreateCommand;
+import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
+import com.cloud.agent.api.storage.DestroyCommand;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
+import com.cloud.agent.api.to.IpAddressTO;
+import com.cloud.agent.api.to.NicTO;
+import com.cloud.agent.api.to.PortForwardingRuleTO;
+import com.cloud.agent.api.to.StaticNatRuleTO;
+import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.agent.api.to.VirtualMachineTO;
+import com.cloud.agent.api.to.VolumeTO;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.Vlan;
+import com.cloud.exception.InternalErrorException;
+import com.cloud.host.Host.Type;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.hypervisor.vmware.manager.VmwareHostService;
+import com.cloud.hypervisor.vmware.manager.VmwareManager;
+import com.cloud.hypervisor.vmware.mo.ClusterMO;
+import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
+import com.cloud.hypervisor.vmware.mo.CustomFieldsManagerMO;
+import com.cloud.hypervisor.vmware.mo.DatacenterMO;
+import com.cloud.hypervisor.vmware.mo.DatastoreMO;
+import com.cloud.hypervisor.vmware.mo.DiskControllerType;
+import com.cloud.hypervisor.vmware.mo.HostFirewallSystemMO;
+import com.cloud.hypervisor.vmware.mo.HostMO;
+import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
+import com.cloud.hypervisor.vmware.mo.NetworkDetails;
+import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
+import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
+import com.cloud.hypervisor.vmware.mo.VirtualSwitchType;
+import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
+import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostNetworkSummary;
+import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostResourceSummary;
+import com.cloud.hypervisor.vmware.util.VmwareContext;
+import com.cloud.hypervisor.vmware.util.VmwareGuestOsMapper;
+import com.cloud.hypervisor.vmware.util.VmwareHelper;
+import com.cloud.network.HAProxyConfigurator;
+import com.cloud.network.LoadBalancerConfigurator;
+import com.cloud.network.Networks;
+import com.cloud.network.Networks.BroadcastDomainType;
+import com.cloud.resource.ServerResource;
+import com.cloud.serializer.GsonHelper;
+import com.cloud.storage.Storage;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.storage.Volume;
+import com.cloud.storage.resource.StoragePoolResource;
+import com.cloud.storage.template.TemplateInfo;
+import com.cloud.utils.DateUtil;
+import com.cloud.utils.Pair;
+import com.cloud.utils.StringUtils;
+import com.cloud.utils.component.ComponentLocator;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.exception.ExceptionUtil;
+import com.cloud.utils.mgmt.JmxUtil;
+import com.cloud.utils.mgmt.PropertyMapDynamicBean;
+import com.cloud.utils.net.NetUtils;
+import com.cloud.utils.ssh.SshHelper;
+import com.cloud.vm.DiskProfile;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachine.State;
+import com.cloud.vm.VirtualMachineName;
+import com.cloud.vm.VmDetailConstants;
+import com.google.gson.Gson;
+import com.vmware.vim25.AboutInfo;
+import com.vmware.vim25.ClusterDasConfigInfo;
+import com.vmware.vim25.ComputeResourceSummary;
+import com.vmware.vim25.DatastoreSummary;
+import com.vmware.vim25.DynamicProperty;
+import com.vmware.vim25.HostFirewallInfo;
+import com.vmware.vim25.HostFirewallRuleset;
+import com.vmware.vim25.HostNetworkTrafficShapingPolicy;
+import com.vmware.vim25.HostPortGroupSpec;
+import com.vmware.vim25.ManagedObjectReference;
+import com.vmware.vim25.ObjectContent;
+import com.vmware.vim25.OptionValue;
+import com.vmware.vim25.PerfCounterInfo;
+import com.vmware.vim25.PerfEntityMetric;
+import com.vmware.vim25.PerfEntityMetricBase;
+import com.vmware.vim25.PerfMetricId;
+import com.vmware.vim25.PerfMetricIntSeries;
+import com.vmware.vim25.PerfMetricSeries;
+import com.vmware.vim25.PerfQuerySpec;
+import com.vmware.vim25.PerfSampleInfo;
+import com.vmware.vim25.RuntimeFault;
+import com.vmware.vim25.ToolsUnavailable;
+import com.vmware.vim25.VimPortType;
+import com.vmware.vim25.VirtualDevice;
+import com.vmware.vim25.VirtualDeviceConfigSpec;
+import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
+import com.vmware.vim25.VirtualDisk;
+import com.vmware.vim25.VirtualEthernetCard;
+import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
+import com.vmware.vim25.VirtualLsiLogicController;
+import com.vmware.vim25.VirtualMachineConfigSpec;
+import com.vmware.vim25.VirtualMachineFileInfo;
+import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
+import com.vmware.vim25.VirtualMachinePowerState;
+import com.vmware.vim25.VirtualMachineRuntimeInfo;
+import com.vmware.vim25.VirtualSCSISharing;
+
+public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService {
+ private static final Logger s_logger = Logger.getLogger(VmwareResource.class);
+
+ protected String _name;
+
+ protected final long _ops_timeout = 900000; // 15 minutes time out to time
+ protected final int _shutdown_waitMs = 300000; // wait up to 5 minutes for shutdown
+
+ // out an operation
+ protected final int _retry = 24;
+ protected final int _sleep = 10000;
+ protected final int DEFAULT_DOMR_SSHPORT = 3922;
+ protected final int MAX_CMD_MBEAN = 100;
+
+ protected String _url;
+ protected String _dcId;
+ protected String _pod;
+ protected String _cluster;
+ protected String _username;
+ protected String _password;
+ protected String _guid;
+ protected String _vCenterAddress;
+
+ protected String _privateNetworkVSwitchName;
+ protected String _publicNetworkVSwitchName;
+ protected String _guestNetworkVSwitchName;
+ protected VirtualSwitchType _vSwitchType = VirtualSwitchType.StandardVirtualSwitch;
+ protected boolean _nexusVSwitch = false;
+
+ protected float _cpuOverprovisioningFactor = 1;
+ protected boolean _reserveCpu = false;
+
+ protected float _memOverprovisioningFactor = 1;
+ protected boolean _reserveMem = false;
+ protected boolean _recycleHungWorker = false;
+ protected DiskControllerType _rootDiskController = DiskControllerType.ide;
+
+ protected ManagedObjectReference _morHyperHost;
+ protected VmwareContext _serviceContext;
+ protected String _hostName;
+
+ protected HashMap<String, State> _vms = new HashMap<String, State>(71);
+ protected List<PropertyMapDynamicBean> _cmdMBeans = new ArrayList<PropertyMapDynamicBean>();
+
+ protected Gson _gson;
+
+ protected volatile long _cmdSequence = 1;
+
+ protected static HashMap<VirtualMachinePowerState, State> s_statesTable;
+ static {
+ s_statesTable = new HashMap<VirtualMachinePowerState, State>();
+ s_statesTable.put(VirtualMachinePowerState.poweredOn, State.Running);
+ s_statesTable.put(VirtualMachinePowerState.poweredOff, State.Stopped);
+ s_statesTable.put(VirtualMachinePowerState.suspended, State.Stopped);
+ }
+
+ public VmwareResource() {
+ _gson = GsonHelper.getGsonLogger();
+ }
+
+ @Override
+ public Answer executeRequest(Command cmd) {
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("Begin executeRequest(), cmd: " + cmd.getClass().getSimpleName());
+
+ Answer answer = null;
+ NDC.push(_hostName != null ? _hostName : _guid + "(" + ComponentLocator.class.getPackage().getImplementationVersion() + ")");
+ try {
+ long cmdSequence = _cmdSequence++;
+ Date startTime = DateUtil.currentGMTTime();
+ PropertyMapDynamicBean mbean = new PropertyMapDynamicBean();
+ mbean.addProp("StartTime", DateUtil.getDateDisplayString(TimeZone.getDefault(), startTime));
+ mbean.addProp("Command", _gson.toJson(cmd));
+ mbean.addProp("Sequence", String.valueOf(cmdSequence));
+ mbean.addProp("Name", cmd.getClass().getSimpleName());
+
+ if (cmd instanceof CreateCommand) {
+ answer = execute((CreateCommand) cmd);
+ } else if (cmd instanceof SetPortForwardingRulesCommand) {
+ answer = execute((SetPortForwardingRulesCommand) cmd);
+ } else if (cmd instanceof SetStaticNatRulesCommand) {
+ answer = execute((SetStaticNatRulesCommand) cmd);
+ } else if (cmd instanceof LoadBalancerConfigCommand) {
+ answer = execute((LoadBalancerConfigCommand) cmd);
+ } else if (cmd instanceof IpAssocCommand) {
+ answer = execute((IpAssocCommand) cmd);
+ } else if (cmd instanceof SavePasswordCommand) {
+ answer = execute((SavePasswordCommand) cmd);
+ } else if (cmd instanceof DhcpEntryCommand) {
+ answer = execute((DhcpEntryCommand) cmd);
+ } else if (cmd instanceof VmDataCommand) {
+ answer = execute((VmDataCommand) cmd);
+ } else if (cmd instanceof ReadyCommand) {
+ answer = execute((ReadyCommand) cmd);
+ } else if (cmd instanceof GetHostStatsCommand) {
+ answer = execute((GetHostStatsCommand) cmd);
+ } else if (cmd instanceof GetVmStatsCommand) {
+ answer = execute((GetVmStatsCommand) cmd);
+ } else if (cmd instanceof CheckHealthCommand) {
+ answer = execute((CheckHealthCommand) cmd);
+ } else if (cmd instanceof StopCommand) {
+ answer = execute((StopCommand) cmd);
+ } else if (cmd instanceof RebootRouterCommand) {
+ answer = execute((RebootRouterCommand) cmd);
+ } else if (cmd instanceof RebootCommand) {
+ answer = execute((RebootCommand) cmd);
+ } else if (cmd instanceof CheckVirtualMachineCommand) {
+ answer = execute((CheckVirtualMachineCommand) cmd);
+ } else if (cmd instanceof PrepareForMigrationCommand) {
+ answer = execute((PrepareForMigrationCommand) cmd);
+ } else if (cmd instanceof MigrateCommand) {
+ answer = execute((MigrateCommand) cmd);
+ } else if (cmd instanceof DestroyCommand) {
+ answer = execute((DestroyCommand) cmd);
+ } else if (cmd instanceof CreateStoragePoolCommand) {
+ return execute((CreateStoragePoolCommand) cmd);
+ } else if (cmd instanceof ModifyStoragePoolCommand) {
+ answer = execute((ModifyStoragePoolCommand) cmd);
+ } else if (cmd instanceof DeleteStoragePoolCommand) {
+ answer = execute((DeleteStoragePoolCommand) cmd);
+ } else if (cmd instanceof CopyVolumeCommand) {
+ answer = execute((CopyVolumeCommand) cmd);
+ } else if (cmd instanceof AttachVolumeCommand) {
+ answer = execute((AttachVolumeCommand) cmd);
+ } else if (cmd instanceof AttachIsoCommand) {
+ answer = execute((AttachIsoCommand) cmd);
+ } else if (cmd instanceof ValidateSnapshotCommand) {
+ answer = execute((ValidateSnapshotCommand) cmd);
+ } else if (cmd instanceof ManageSnapshotCommand) {
+ answer = execute((ManageSnapshotCommand) cmd);
+ } else if (cmd instanceof BackupSnapshotCommand) {
+ answer = execute((BackupSnapshotCommand) cmd);
+ } else if (cmd instanceof CreateVolumeFromSnapshotCommand) {
+ answer = execute((CreateVolumeFromSnapshotCommand) cmd);
+ } else if (cmd instanceof CreatePrivateTemplateFromVolumeCommand) {
+ answer = execute((CreatePrivateTemplateFromVolumeCommand) cmd);
+ } else if (cmd instanceof CreatePrivateTemplateFromSnapshotCommand) {
+ answer = execute((CreatePrivateTemplateFromSnapshotCommand) cmd);
+ } else if (cmd instanceof UpgradeSnapshotCommand) {
+ answer = execute((UpgradeSnapshotCommand) cmd);
+ } else if (cmd instanceof GetStorageStatsCommand) {
+ answer = execute((GetStorageStatsCommand) cmd);
+ } else if (cmd instanceof PrimaryStorageDownloadCommand) {
+ answer = execute((PrimaryStorageDownloadCommand) cmd);
+ } else if (cmd instanceof GetVncPortCommand) {
+ answer = execute((GetVncPortCommand) cmd);
+ } else if (cmd instanceof SetupCommand) {
+ answer = execute((SetupCommand) cmd);
+ } else if (cmd instanceof MaintainCommand) {
+ answer = execute((MaintainCommand) cmd);
+ } else if (cmd instanceof PingTestCommand) {
+ answer = execute((PingTestCommand) cmd);
+ } else if (cmd instanceof CheckOnHostCommand) {
+ answer = execute((CheckOnHostCommand) cmd);
+ } else if (cmd instanceof ModifySshKeysCommand) {
+ answer = execute((ModifySshKeysCommand) cmd);
+ } else if (cmd instanceof PoolEjectCommand) {
+ answer = execute((PoolEjectCommand) cmd);
+ } else if (cmd instanceof NetworkUsageCommand) {
+ answer = execute((NetworkUsageCommand) cmd);
+ } else if (cmd instanceof StartCommand) {
+ answer = execute((StartCommand) cmd);
+ } else if (cmd instanceof RemoteAccessVpnCfgCommand) {
+ answer = execute((RemoteAccessVpnCfgCommand) cmd);
+ } else if (cmd instanceof VpnUsersCfgCommand) {
+ answer = execute((VpnUsersCfgCommand) cmd);
+ } else if (cmd instanceof CheckSshCommand) {
+ answer = execute((CheckSshCommand) cmd);
+ } else if (cmd instanceof CheckRouterCommand) {
+ answer = execute((CheckRouterCommand) cmd);
+ } else if (cmd instanceof SetFirewallRulesCommand) {
+ answer = execute((SetFirewallRulesCommand)cmd);
+ } else if (cmd instanceof BumpUpPriorityCommand) {
+ answer = execute((BumpUpPriorityCommand)cmd);
+ } else if (cmd instanceof GetDomRVersionCmd) {
+ answer = execute((GetDomRVersionCmd)cmd);
+ } else if (cmd instanceof CheckNetworkCommand) {
+ answer = execute((CheckNetworkCommand) cmd);
+ } else {
+ answer = Answer.createUnsupportedCommandAnswer(cmd);
+ }
+
+ if(cmd.getContextParam("checkpoint") != null) {
+ answer.setContextParam("checkpoint", cmd.getContextParam("checkpoint"));
+ }
+
+ Date doneTime = DateUtil.currentGMTTime();
+ mbean.addProp("DoneTime", DateUtil.getDateDisplayString(TimeZone.getDefault(), doneTime));
+ mbean.addProp("Answer", _gson.toJson(answer));
+
+ synchronized (this) {
+ try {
+ JmxUtil.registerMBean("VMware " + _morHyperHost.get_value(), "Command " + cmdSequence + "-" + cmd.getClass().getSimpleName(), mbean);
+ _cmdMBeans.add(mbean);
+
+ if (_cmdMBeans.size() >= MAX_CMD_MBEAN) {
+ PropertyMapDynamicBean mbeanToRemove = _cmdMBeans.get(0);
+ _cmdMBeans.remove(0);
+
+ JmxUtil.unregisterMBean("VMware " + _morHyperHost.get_value(), "Command " + mbeanToRemove.getProp("Sequence") + "-" + mbeanToRemove.getProp("Name"));
+ }
+ } catch (Exception e) {
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("Unable to register JMX monitoring due to exception " + ExceptionUtil.toString(e));
+ }
+ }
+
+ } finally {
+ NDC.pop();
+ }
+
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("End executeRequest(), cmd: " + cmd.getClass().getSimpleName());
+
+ return answer;
+ }
+
+ protected Answer execute(CheckNetworkCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource CheckNetworkCommand " + _gson.toJson(cmd));
+ }
+
+ // TODO setup portgroup for private network needs to be done here now
+ return new CheckNetworkAnswer(cmd, true , "Network Setup check by names is done");
+ }
+
+ protected Answer execute(NetworkUsageCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource NetworkUsageCommand " + _gson.toJson(cmd));
+ }
+ if(cmd.getOption()!=null && cmd.getOption().equals("create") ){
+ String result = networkUsage(cmd.getPrivateIP(), "create", null);
+ NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, result, 0L, 0L);
+ return answer;
+ }
+ long[] stats = getNetworkStats(cmd.getPrivateIP());
+
+ NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, "", stats[0], stats[1]);
+ return answer;
+ }
+
+ protected Answer execute(SetPortForwardingRulesCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource SetPortForwardingRulesCommand: " + _gson.toJson(cmd));
+ }
+
+ String controlIp = getRouterSshControlIp(cmd);
+ String args = "";
+ String[] results = new String[cmd.getRules().length];
+ int i = 0;
+
+ boolean endResult = true;
+ for (PortForwardingRuleTO rule : cmd.getRules()) {
+ args += rule.revoked() ? " -D " : " -A ";
+ args += " -P " + rule.getProtocol().toLowerCase();
+ args += " -l " + rule.getSrcIp();
+ args += " -p " + rule.getStringSrcPortRange();
+ args += " -r " + rule.getDstIp();
+ args += " -d " + rule.getStringDstPortRange();
+
+ try {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "/root/firewall.sh " + args);
+
+ if (s_logger.isDebugEnabled())
+ s_logger.debug("Executing script on domain router " + controlIp + ": /root/firewall.sh " + args);
+
+ if (!result.first()) {
+ s_logger.error("SetPortForwardingRulesCommand failure on setting one rule. args: " + args);
+ results[i++] = "Failed";
+ endResult = false;
+ } else {
+ results[i++] = null;
+ }
+ } catch (Throwable e) {
+ s_logger.error("SetPortForwardingRulesCommand(args: " + args + ") failed on setting one rule due to " + VmwareHelper.getExceptionMessage(e), e);
+ results[i++] = "Failed";
+ endResult = false;
+ }
+ }
+
+ return new SetPortForwardingRulesAnswer(cmd, results, endResult);
+ }
+
+ protected SetFirewallRulesAnswer execute(SetFirewallRulesCommand cmd) {
+ String controlIp = getRouterSshControlIp(cmd);
+ String[] results = new String[cmd.getRules().length];
+
+ String[][] rules = cmd.generateFwRules();
+ String args = "";
+ args += " -F ";
+ StringBuilder sb = new StringBuilder();
+ String[] fwRules = rules[0];
+ if (fwRules.length > 0) {
+ for (int i = 0; i < fwRules.length; i++) {
+ sb.append(fwRules[i]).append(',');
+ }
+ args += " -a " + sb.toString();
+ }
+
+ try {
+ VmwareManager mgr = getServiceContext().getStockObject(
+ VmwareManager.CONTEXT_STOCK_NAME);
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp,
+ DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(),
+ null, "/root/firewall_rule.sh " + args);
+
+ if (s_logger.isDebugEnabled())
+ s_logger.debug("Executing script on domain router " + controlIp
+ + ": /root/firewall_rule.sh " + args);
+
+ if (!result.first()) {
+ s_logger.error("SetFirewallRulesCommand failure on setting one rule. args: "
+ + args);
+ //FIXME - in the future we have to process each rule separately; now we temporarily set every rule to be false if single rule fails
+ for (int i=0; i < results.length; i++) {
+ results[i] = "Failed";
+ }
+
+ return new SetFirewallRulesAnswer(cmd, false, results);
+ }
+ } catch (Throwable e) {
+ s_logger.error("SetFirewallRulesCommand(args: " + args
+ + ") failed on setting one rule due to "
+ + VmwareHelper.getExceptionMessage(e), e);
+ //FIXME - in the future we have to process each rule separately; now we temporarily set every rule to be false if single rule fails
+ for (int i=0; i < results.length; i++) {
+ results[i] = "Failed";
+ }
+ return new SetFirewallRulesAnswer(cmd, false, results);
+ }
+
+ return new SetFirewallRulesAnswer(cmd, true, results);
+ }
+
+ protected Answer execute(SetStaticNatRulesCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource SetFirewallRuleCommand: " + _gson.toJson(cmd));
+ }
+
+ String args = null;
+ String[] results = new String[cmd.getRules().length];
+ int i = 0;
+ boolean endResult = true;
+ for (StaticNatRuleTO rule : cmd.getRules()) {
+ // 1:1 NAT needs instanceip;publicip;domrip;op
+ args = rule.revoked() ? " -D " : " -A ";
+
+ args += " -l " + rule.getSrcIp();
+ args += " -r " + rule.getDstIp();
+
+ if (rule.getProtocol() != null) {
+ args += " -P " + rule.getProtocol().toLowerCase();
+ }
+
+ args += " -d " + rule.getStringSrcPortRange();
+ args += " -G ";
+
+ try {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ String controlIp = getRouterSshControlIp(cmd);
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "/root/firewall.sh " + args);
+
+ if (s_logger.isDebugEnabled())
+ s_logger.debug("Executing script on domain router " + controlIp + ": /root/firewall.sh " + args);
+
+ if (!result.first()) {
+ s_logger.error("SetStaticNatRulesCommand failure on setting one rule. args: " + args);
+ results[i++] = "Failed";
+ endResult = false;
+ } else {
+ results[i++] = null;
+ }
+ } catch (Throwable e) {
+ s_logger.error("SetStaticNatRulesCommand (args: " + args + ") failed on setting one rule due to " + VmwareHelper.getExceptionMessage(e), e);
+ results[i++] = "Failed";
+ endResult = false;
+ }
+ }
+ return new SetStaticNatRulesAnswer(cmd, results, endResult);
+ }
+
+ protected Answer execute(final LoadBalancerConfigCommand cmd) {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ File keyFile = mgr.getSystemVMKeyFile();
+
+ String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+ String controlIp = getRouterSshControlIp(cmd);
+
+ assert(controlIp != null);
+
+ LoadBalancerConfigurator cfgtr = new HAProxyConfigurator();
+ String[] config = cfgtr.generateConfiguration(cmd);
+
+ String[][] rules = cfgtr.generateFwRules(cmd);
+ String tmpCfgFilePath = "/tmp/" + routerIp.replace('.', '_') + ".cfg";
+ String tmpCfgFileContents = "";
+ for (int i = 0; i < config.length; i++) {
+ tmpCfgFileContents += config[i];
+ tmpCfgFileContents += "\n";
+ }
+
+ try {
+ SshHelper.scpTo(controlIp, DEFAULT_DOMR_SSHPORT, "root", keyFile, null, "/tmp/", tmpCfgFileContents.getBytes(), routerIp.replace('.', '_') + ".cfg", null);
+
+ try {
+ String[] addRules = rules[LoadBalancerConfigurator.ADD];
+ String[] removeRules = rules[LoadBalancerConfigurator.REMOVE];
+ String[] statRules = rules[LoadBalancerConfigurator.STATS];
+
+ String args = "";
+ args += "-i " + routerIp;
+ args += " -f " + tmpCfgFilePath;
+
+ StringBuilder sb = new StringBuilder();
+ if (addRules.length > 0) {
+ for (int i = 0; i < addRules.length; i++) {
+ sb.append(addRules[i]).append(',');
+ }
+
+ args += " -a " + sb.toString();
+ }
+
+ sb = new StringBuilder();
+ if (removeRules.length > 0) {
+ for (int i = 0; i < removeRules.length; i++) {
+ sb.append(removeRules[i]).append(',');
+ }
+
+ args += " -d " + sb.toString();
+ }
+
+ sb = new StringBuilder();
+ if (statRules.length > 0) {
+ for (int i = 0; i < statRules.length; i++) {
+ sb.append(statRules[i]).append(',');
+ }
+
+ args += " -s " + sb.toString();
+ }
+
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "scp " + tmpCfgFilePath + " /etc/haproxy/haproxy.cfg.new");
+
+ if (!result.first()) {
+ s_logger.error("Unable to copy haproxy configuration file");
+ return new Answer(cmd, false, "LoadBalancerConfigCommand failed due to uanble to copy haproxy configuration file");
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run command on domain router " + routerIp + ", /root/loadbalancer.sh " + args);
+ }
+
+ result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "/root/loadbalancer.sh " + args);
+
+ if (!result.first()) {
+ String msg = "LoadBalancerConfigCommand on domain router " + routerIp + " failed. message: " + result.second();
+ s_logger.error(msg);
+
+ return new Answer(cmd, false, msg);
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("LoadBalancerConfigCommand on domain router " + routerIp + " completed");
+ }
+ } finally {
+ SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "rm " + tmpCfgFilePath);
+ }
+
+ return new Answer(cmd);
+ } catch (Throwable e) {
+ s_logger.error("Unexpected exception: " + e.toString(), e);
+ return new Answer(cmd, false, "LoadBalancerConfigCommand failed due to " + VmwareHelper.getExceptionMessage(e));
+ }
+ }
+
+ protected void assignPublicIpAddress(VirtualMachineMO vmMo, final String vmName, final String privateIpAddress, final String publicIpAddress, final boolean add, final boolean firstIP,
+ final boolean sourceNat, final String vlanId, final String vlanGateway, final String vlanNetmask, final String vifMacAddress, String guestIp) throws Exception {
+
+ String publicNeworkName = HypervisorHostHelper.getPublicNetworkNamePrefix(vlanId);
+ Pair<Integer, VirtualDevice> publicNicInfo = vmMo.getNicDeviceIndex(publicNeworkName);
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Find public NIC index, public network name: " + publicNeworkName + ", index: " + publicNicInfo.first());
+ }
+
+ boolean addVif = false;
+ boolean removeVif = false;
+ if (add && publicNicInfo.first().intValue() == -1) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Plug new NIC to associate" + privateIpAddress + " to " + publicIpAddress);
+ }
+
+ addVif = true;
+ } else if (!add && firstIP) {
+ removeVif = true;
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Unplug NIC " + publicNicInfo.first());
+ }
+ }
+
+ if (addVif) {
+ plugPublicNic(vmMo, vlanId, vifMacAddress);
+ publicNicInfo = vmMo.getNicDeviceIndex(publicNeworkName);
+ if (publicNicInfo.first().intValue() >= 0) {
+ networkUsage(privateIpAddress, "addVif", "eth" + publicNicInfo.first());
+ }
+ }
+
+ if (publicNicInfo.first().intValue() < 0) {
+ String msg = "Failed to find DomR VIF to associate/disassociate IP with.";
+ s_logger.error(msg);
+ throw new InternalErrorException(msg);
+ }
+
+ String args = null;
+
+ if (add) {
+ args = " -A ";
+ } else {
+ args = " -D ";
+ }
+
+ if (sourceNat) {
+ args += " -s ";
+ }
+ if (firstIP) {
+ args += " -f ";
+ }
+ String cidrSize = Long.toString(NetUtils.getCidrSize(vlanNetmask));
+ args += " -l ";
+ args += publicIpAddress + "/" + cidrSize;
+
+ args += " -c ";
+ args += "eth" + publicNicInfo.first();
+
+ args += " -g ";
+ args += vlanGateway;
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run command on domain router " + privateIpAddress + ", /root/ipassoc.sh " + args);
+ }
+
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ Pair<Boolean, String> result = SshHelper.sshExecute(privateIpAddress, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "/root/ipassoc.sh " + args);
+
+ if (!result.first()) {
+ s_logger.error("ipassoc command on domain router " + privateIpAddress + " failed. message: " + result.second());
+ throw new Exception("ipassoc failed due to " + result.second());
+ }
+
+ if (removeVif) {
+
+ String nicMasksStr = vmMo.getCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK);
+ int nicMasks = Integer.parseInt(nicMasksStr);
+ nicMasks &= ~(1 << publicNicInfo.first().intValue());
+ vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMasks));
+
+ HostMO hostMo = vmMo.getRunningHost();
+ List<NetworkDetails> networks = vmMo.getNetworksWithDetails();
+ for (NetworkDetails netDetails : networks) {
+ if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) {
+ if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) {
+ cleanupNetwork(hostMo, netDetails);
+ }
+ }
+ }
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("ipassoc command on domain router " + privateIpAddress + " completed");
+ }
+ }
+
+ private void plugPublicNic(VirtualMachineMO vmMo, final String vlanId, final String vifMacAddress) throws Exception {
+ // TODO : probably need to set traffic shaping
+ Pair<ManagedObjectReference, String> networkInfo = null;
+
+ if (!_nexusVSwitch) {
+ networkInfo = HypervisorHostHelper.prepareNetwork(this._publicNetworkVSwitchName, "cloud.public",
+ vmMo.getRunningHost(), vlanId, null, null, this._ops_timeout, true);
+ } else {
+ networkInfo = HypervisorHostHelper.prepareNetwork(this._publicNetworkVSwitchName, "cloud.public",
+ vmMo.getRunningHost(), vlanId, null, null, this._ops_timeout);
+ }
+
+ int nicIndex = allocPublicNicIndex(vmMo);
+
+ try {
+ VirtualDevice[] nicDevices = vmMo.getNicDevices();
+
+ VirtualEthernetCard device = (VirtualEthernetCard) nicDevices[nicIndex];
+
+ if (!_nexusVSwitch) {
+ VirtualEthernetCardNetworkBackingInfo nicBacking = new VirtualEthernetCardNetworkBackingInfo();
+ nicBacking.setDeviceName(networkInfo.second());
+ nicBacking.setNetwork(networkInfo.first());
+ device.setBacking(nicBacking);
+ } else {
+ HostMO hostMo = vmMo.getRunningHost();
+ DatacenterMO dataCenterMo = new DatacenterMO(hostMo.getContext(), hostMo.getHyperHostDatacenter());
+ device.setBacking(dataCenterMo.getDvPortBackingInfo(networkInfo));
+ }
+
+ VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
+ VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
+ deviceConfigSpecArray[0] = new VirtualDeviceConfigSpec();
+ deviceConfigSpecArray[0].setDevice(device);
+ deviceConfigSpecArray[0].setOperation(VirtualDeviceConfigSpecOperation.edit);
+
+ vmConfigSpec.setDeviceChange(deviceConfigSpecArray);
+ if(!vmMo.configureVm(vmConfigSpec)) {
+ throw new Exception("Failed to configure devices when plugPublicNic");
+ }
+ } catch(Exception e) {
+
+ // restore allocation mask in case of exceptions
+ String nicMasksStr = vmMo.getCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK);
+ int nicMasks = Integer.parseInt(nicMasksStr);
+ nicMasks &= ~(1 << nicIndex);
+ vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMasks));
+
+ throw e;
+ }
+ }
+
+ private int allocPublicNicIndex(VirtualMachineMO vmMo) throws Exception {
+ String nicMasksStr = vmMo.getCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK);
+ if(nicMasksStr == null || nicMasksStr.isEmpty()) {
+ throw new Exception("Could not find NIC allocation info");
+ }
+
+ int nicMasks = Integer.parseInt(nicMasksStr);
+ VirtualDevice[] nicDevices = vmMo.getNicDevices();
+ for(int i = 3; i < nicDevices.length; i++) {
+ if((nicMasks & (1 << i)) == 0) {
+ nicMasks |= (1 << i);
+ vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMasks));
+ return i;
+ }
+ }
+
+ throw new Exception("Could not allocate a free public NIC");
+ }
+
+ protected Answer execute(IpAssocCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource IPAssocCommand: " + _gson.toJson(cmd));
+ }
+
+ int i = 0;
+ String[] results = new String[cmd.getIpAddresses().length];
+
+ VmwareContext context = getServiceContext();
+ try {
+ VmwareHypervisorHost hyperHost = getHyperHost(context);
+
+ IpAddressTO[] ips = cmd.getIpAddresses();
+ String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
+ String controlIp = VmwareResource.getRouterSshControlIp(cmd);
+
+ VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(routerName);
+
+ // command may sometimes be redirect to a wrong host, we relax
+ // the check and will try to find it within cluster
+ if(vmMo == null) {
+ if(hyperHost instanceof HostMO) {
+ ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(),
+ ((HostMO)hyperHost).getParentMor());
+ vmMo = clusterMo.findVmOnHyperHost(routerName);
+ }
+ }
+
+ if (vmMo == null) {
+ String msg = "Router " + routerName + " no longer exists to execute IPAssoc command";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ for (IpAddressTO ip : ips) {
+ assignPublicIpAddress(vmMo, routerName, controlIp, ip.getPublicIp(), ip.isAdd(), ip.isFirstIP(), ip.isSourceNat(), ip.getVlanId(), ip.getVlanGateway(), ip.getVlanNetmask(),
+ ip.getVifMacAddress(), ip.getGuestIp());
+ results[i++] = ip.getPublicIp() + " - success";
+ }
+ } catch (Throwable e) {
+ s_logger.error("Unexpected exception: " + e.toString() + " will shortcut rest of IPAssoc commands", e);
+
+ for (; i < cmd.getIpAddresses().length; i++) {
+ results[i++] = IpAssocAnswer.errorResult;
+ }
+ }
+
+ return new IpAssocAnswer(cmd, results);
+ }
+
+ protected Answer execute(SavePasswordCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource SavePasswordCommand. vmName: " + cmd.getVmName() + ", vmIp: " + cmd.getVmIpAddress() + ", password: "
+ + StringUtils.getMaskedPasswordForDisplay(cmd.getPassword()));
+ }
+
+ String controlIp = getRouterSshControlIp(cmd);
+ final String password = cmd.getPassword();
+ final String vmIpAddress = cmd.getVmIpAddress();
+
+ // Run save_password_to_domr.sh
+ String args = " -v " + vmIpAddress;
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run command on domain router " + controlIp + ", /root/savepassword.sh " + args + " -p " + StringUtils.getMaskedPasswordForDisplay(cmd.getPassword()));
+ }
+
+ args += " -p " + password;
+
+
+ try {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "/root/savepassword.sh " + args);
+
+ if (!result.first()) {
+ s_logger.error("savepassword command on domain router " + controlIp + " failed, message: " + result.second());
+
+ return new Answer(cmd, false, "SavePassword failed due to " + result.second());
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("savepassword command on domain router " + controlIp + " completed");
+ }
+
+ } catch (Throwable e) {
+ String msg = "SavePasswordCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+ return new Answer(cmd);
+ }
+
+ protected Answer execute(DhcpEntryCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource DhcpEntryCommand: " + _gson.toJson(cmd));
+ }
+
+ // ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$domr "/root/edithosts.sh $mac $ip $vm $dfltrt $ns $staticrt" >/dev/null
+ String args = " " + cmd.getVmMac();
+ args += " " + cmd.getVmIpAddress();
+ args += " " + cmd.getVmName();
+
+ if (cmd.getDefaultRouter() != null) {
+ args += " " + cmd.getDefaultRouter();
+ }
+
+ if (cmd.getDefaultDns() != null) {
+ args += " " + cmd.getDefaultDns();
+ }
+
+ if (cmd.getStaticRoutes() != null) {
+ args += " " + cmd.getStaticRoutes();
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /root/edithosts.sh " + args);
+ }
+
+ try {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ String controlIp = getRouterSshControlIp(cmd);
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
+ "/root/edithosts.sh " + args);
+
+ if (!result.first()) {
+ s_logger.error("dhcp_entry command on domR " + controlIp + " failed, message: " + result.second());
+
+ return new Answer(cmd, false, "DhcpEntry failed due to " + result.second());
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("dhcp_entry command on domain router " + controlIp + " completed");
+ }
+
+ } catch (Throwable e) {
+ String msg = "DhcpEntryCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+
+ return new Answer(cmd);
+ }
+
+ protected Answer execute(CheckRouterCommand cmd) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Executing resource CheckRouterCommand: " + _gson.toJson(cmd));
+ s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /root/checkrouter.sh ");
+ }
+
+ Pair<Boolean, String> result;
+ try {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ String controlIp = getRouterSshControlIp(cmd);
+ result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
+ "/root/checkrouter.sh ");
+
+ if (!result.first()) {
+ s_logger.error("check router command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + " failed, message: " + result.second());
+
+ return new CheckRouterAnswer(cmd, "CheckRouter failed due to " + result.second());
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("check router command on domain router " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + " completed");
+ }
+ } catch (Throwable e) {
+ String msg = "CheckRouterCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new CheckRouterAnswer(cmd, msg);
+ }
+ return new CheckRouterAnswer(cmd, result.second(), true);
+ }
+
+ protected Answer execute(GetDomRVersionCmd cmd) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Executing resource GetDomRVersionCmd: " + _gson.toJson(cmd));
+ s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /opt/cloud/bin/get_template_version.sh ");
+ }
+
+ Pair<Boolean, String> result;
+ try {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ String controlIp = getRouterSshControlIp(cmd);
+ result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
+ "/opt/cloud/bin/get_template_version.sh ");
+
+ if (!result.first()) {
+ s_logger.error("GetDomRVersionCmd on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + " failed, message: " + result.second());
+
+ return new GetDomRVersionAnswer(cmd, "GetDomRVersionCmd failed due to " + result.second());
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("GetDomRVersionCmd on domain router " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + " completed");
+ }
+ } catch (Throwable e) {
+ String msg = "GetDomRVersionCmd failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new GetDomRVersionAnswer(cmd, msg);
+ }
+ String[] lines = result.second().split("&");
+ if (lines.length != 2) {
+ return new GetDomRVersionAnswer(cmd, result.second());
+ }
+ return new GetDomRVersionAnswer(cmd, result.second(), lines[0], lines[1]);
+ }
+
+ protected Answer execute(BumpUpPriorityCommand cmd) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Executing resource BumpUpPriorityCommand: " + _gson.toJson(cmd));
+ s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /root/bumpup_priority.sh ");
+ }
+
+ Pair<Boolean, String> result;
+ try {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ String controlIp = getRouterSshControlIp(cmd);
+ result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
+ "/root/bumpup_priority.sh ");
+
+ if (!result.first()) {
+ s_logger.error("BumpUpPriority command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + " failed, message: " + result.second());
+
+ return new Answer(cmd, false, "BumpUpPriorityCommand failed due to " + result.second());
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("BumpUpPriorityCommand on domain router " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + " completed");
+ }
+ } catch (Throwable e) {
+ String msg = "BumpUpPriorityCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+ if (result.second() == null || result.second().isEmpty()) {
+ return new Answer(cmd, true, result.second());
+ }
+ return new Answer(cmd, false, result.second());
+ }
+
+ protected Answer execute(VmDataCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource VmDataCommand: " + _gson.toJson(cmd));
+ }
+
+ String routerPrivateIpAddress = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+ String controlIp = getRouterSshControlIp(cmd);
+
+ String vmIpAddress = cmd.getVmIpAddress();
+ List<String[]> vmData = cmd.getVmData();
+ String[] vmDataArgs = new String[vmData.size() * 2 + 4];
+ vmDataArgs[0] = "routerIP";
+ vmDataArgs[1] = routerPrivateIpAddress;
+ vmDataArgs[2] = "vmIP";
+ vmDataArgs[3] = vmIpAddress;
+ int i = 4;
+ for (String[] vmDataEntry : vmData) {
+ String folder = vmDataEntry[0];
+ String file = vmDataEntry[1];
+ String contents = (vmDataEntry[2] != null) ? vmDataEntry[2] : "none";
+
+ vmDataArgs[i] = folder + "," + file;
+ vmDataArgs[i + 1] = contents;
+ i += 2;
+ }
+
+ String content = encodeDataArgs(vmDataArgs);
+ String tmpFileName = UUID.randomUUID().toString();
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run vm_data command on domain router " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", data: " + content);
+ }
+
+ try {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ SshHelper.scpTo(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "/tmp", content.getBytes(), tmpFileName, null);
+
+ try {
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
+ "/root/userdata.py " + tmpFileName);
+
+ if (!result.first()) {
+ s_logger.error("vm_data command on domain router " + controlIp + " failed. messge: " + result.second());
+ return new Answer(cmd, false, "VmDataCommand failed due to " + result.second());
+ }
+ } finally {
+
+ SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "rm /tmp/" + tmpFileName);
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("vm_data command on domain router " + controlIp + " completed");
+ }
+
+ } catch (Throwable e) {
+ String msg = "VmDataCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+ return new Answer(cmd);
+ }
+
+ private String encodeDataArgs(String[] dataArgs) {
+ StringBuilder sb = new StringBuilder();
+
+ for (String arg : dataArgs) {
+ sb.append(arg);
+ sb.append("\n");
+ }
+
+ return sb.toString();
+ }
+
+ protected CheckSshAnswer execute(CheckSshCommand cmd) {
+ String vmName = cmd.getName();
+ String privateIp = cmd.getIp();
+ int cmdPort = cmd.getPort();
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Ping command port, " + privateIp + ":" + cmdPort);
+ }
+
+ try {
+ String result = connect(cmd.getName(), privateIp, cmdPort);
+ if (result != null) {
+ s_logger.error("Can not ping System vm " + vmName + "due to:" + result);
+ return new CheckSshAnswer(cmd, "Can not ping System vm " + vmName + "due to:" + result);
+ }
+ } catch (Exception e) {
+ s_logger.error("Can not ping System vm " + vmName + "due to exception");
+ return new CheckSshAnswer(cmd, e);
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Ping command port succeeded for vm " + vmName);
+ }
+
+ if (VirtualMachineName.isValidRouterName(vmName)) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Execute network usage setup command on " + vmName);
+ }
+ networkUsage(privateIp, "create", null);
+ }
+
+ return new CheckSshAnswer(cmd);
+ }
+
+ private VolumeTO[] validateDisks(VolumeTO[] disks) {
+ List<VolumeTO> validatedDisks = new ArrayList<VolumeTO>();
+
+ for (VolumeTO vol : disks) {
+ if (vol.getPoolUuid() != null && !vol.getPoolUuid().isEmpty()) {
+ validatedDisks.add(vol);
+ } else if (vol.getPoolType() == StoragePoolType.ISO && (vol.getPath() != null && !vol.getPath().isEmpty())) {
+ validatedDisks.add(vol);
+ } else {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Drop invalid disk option, volumeTO: " + _gson.toJson(vol));
+ }
+ }
+ }
+
+ return validatedDisks.toArray(new VolumeTO[0]);
+ }
+
+ protected StartAnswer execute(StartCommand cmd) {
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource StartCommand: " + _gson.toJson(cmd));
+ }
+
+ VirtualMachineTO vmSpec = cmd.getVirtualMachine();
+ String vmName = vmSpec.getName();
+
+ State state = State.Stopped;
+ VmwareContext context = getServiceContext();
+ try {
+ VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+
+ // mark VM as starting state so that sync() can know not to report stopped too early
+ synchronized (_vms) {
+ _vms.put(vmName, State.Starting);
+ }
+
+ VirtualEthernetCardType nicDeviceType = VirtualEthernetCardType.valueOf(vmSpec.getDetails().get(VmDetailConstants.NIC_ADAPTER));
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("VM " + vmName + " will be started with NIC device type: " + nicDeviceType);
+
+ VmwareHypervisorHost hyperHost = getHyperHost(context);
+ VolumeTO[] disks = validateDisks(vmSpec.getDisks());
+ assert (disks.length > 0);
+ NicTO[] nics = vmSpec.getNics();
+
+ HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails = inferDatastoreDetailsFromDiskInfo(hyperHost, context, disks);
+ if ((dataStoresDetails == null) || (dataStoresDetails.isEmpty()) ){
+ String msg = "Unable to locate datastore details of the volumes to be attached";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+ if (vmMo != null) {
+ s_logger.info("VM " + vmName + " already exists, tear down devices for reconfiguration");
+ if (getVmState(vmMo) != State.Stopped)
+ vmMo.safePowerOff(_shutdown_waitMs);
+ vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
+ vmMo.ensureScsiDeviceController();
+ } else {
+ ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
+ assert (morDc != null);
+
+ vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
+ if (vmMo != null) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Found vm " + vmName + " at other host, relocate to " + hyperHost.getHyperHostName());
+ }
+
+ takeVmFromOtherHyperHost(hyperHost, vmName);
+
+ if (getVmState(vmMo) != State.Stopped)
+ vmMo.safePowerOff(_shutdown_waitMs);
+ vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
+ vmMo.ensureScsiDeviceController();
+ } else {
+ int ramMb = (int) (vmSpec.getMinRam() / (1024 * 1024));
+ Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
+ for (VolumeTO vol : disks) {
+ if (vol.getType() == Volume.Type.ROOT) {
+ rootDiskDataStoreDetails = dataStoresDetails.get(vol.getPoolUuid());
+ }
+ }
+
+ assert (vmSpec.getSpeed() != null) && (rootDiskDataStoreDetails != null);
+ if (!hyperHost.createBlankVm(vmName, vmSpec.getCpus(), vmSpec.getSpeed().intValue(),
+ getReserveCpuMHz(vmSpec.getSpeed().intValue()), vmSpec.getLimitCpuUse(), ramMb, getReserveMemMB(ramMb),
+ translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).toString(), rootDiskDataStoreDetails.first(), false)) {
+ throw new Exception("Failed to create VM. vmName: " + vmName);
+ }
+ }
+
+ vmMo = hyperHost.findVmOnHyperHost(vmName);
+ if (vmMo == null) {
+ throw new Exception("Failed to find the newly create or relocated VM. vmName: " + vmName);
+ }
+ }
+
+ int totalChangeDevices = disks.length + nics.length;
+ VolumeTO volIso = null;
+ if (vmSpec.getType() != VirtualMachine.Type.User) {
+ // system VM needs a patch ISO
+ totalChangeDevices++;
+ } else {
+ for (VolumeTO vol : disks) {
+ if (vol.getType() == Volume.Type.ISO) {
+ volIso = vol;
+ break;
+ }
+ }
+
+ if (volIso == null)
+ totalChangeDevices++;
+ }
+
+ VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
+ int ramMb = (int) (vmSpec.getMinRam() / (1024 * 1024));
+ VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getSpeed().intValue(),
+ getReserveCpuMHz(vmSpec.getSpeed().intValue()), ramMb, getReserveMemMB(ramMb),
+ translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).toString(), vmSpec.getLimitCpuUse());
+
+ VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[totalChangeDevices];
+ int i = 0;
+ int ideControllerKey = vmMo.getIDEDeviceControllerKey();
+ int scsiControllerKey = vmMo.getScsiDeviceControllerKey();
+ int controllerKey;
+ String datastoreDiskPath;
+
+ // prepare systemvm patch ISO
+ if (vmSpec.getType() != VirtualMachine.Type.User) {
+ // attach ISO (for patching of system VM)
+ String secStoreUrl = mgr.getSecondaryStorageStoreUrl(Long.parseLong(_dcId));
+ if(secStoreUrl == null) {
+ String msg = "secondary storage for dc " + _dcId + " is not ready yet?";
+ throw new Exception(msg);
+ }
+ mgr.prepareSecondaryStorageStore(secStoreUrl);
+
+ ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnHost(secStoreUrl);
+ if (morSecDs == null) {
+ String msg = "Failed to prepare secondary storage on host, secondary store url: " + secStoreUrl;
+ throw new Exception(msg);
+ }
+ DatastoreMO secDsMo = new DatastoreMO(hyperHost.getContext(), morSecDs);
+
+ deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
+ Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, String.format("[%s] systemvm/%s", secDsMo.getName(), mgr.getSystemVMIsoFileNameOnDatastore()),
+ secDsMo.getMor(), true, true, i, i + 1);
+ deviceConfigSpecArray[i].setDevice(isoInfo.first());
+ if (isoInfo.second()) {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first()));
+ deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.add);
+ } else {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
+ deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.edit);
+ }
+ i++;
+ } else {
+ // we will always plugin a CDROM device
+ if (volIso != null && volIso.getPath() != null && !volIso.getPath().isEmpty()) {
+ Pair<String, ManagedObjectReference> isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, volIso.getPath());
+ assert (isoDatastoreInfo != null);
+ assert (isoDatastoreInfo.second() != null);
+
+ deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
+ Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, i, i + 1);
+ deviceConfigSpecArray[i].setDevice(isoInfo.first());
+ if (isoInfo.second()) {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first()));
+ deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.add);
+ } else {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
+ deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.edit);
+ }
+ } else {
+ deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
+ Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, null, true, true, i, i + 1);
+ deviceConfigSpecArray[i].setDevice(isoInfo.first());
+ if (isoInfo.second()) {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
+
+ deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.add);
+ } else {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
+
+ deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.edit);
+ }
+ }
+ i++;
+ }
+
+ for (VolumeTO vol : sortVolumesByDeviceId(disks)) {
+ deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
+
+ if (vol.getType() == Volume.Type.ISO) {
+ controllerKey = ideControllerKey;
+ } else {
+ if(vol.getType() == Volume.Type.ROOT) {
+ if(vmSpec.getDetails() != null && vmSpec.getDetails().get(VmDetailConstants.ROOK_DISK_CONTROLLER) != null)
+ {
+ if(vmSpec.getDetails().get(VmDetailConstants.ROOK_DISK_CONTROLLER).equalsIgnoreCase("scsi"))
+ controllerKey = scsiControllerKey;
+ else
+ controllerKey = ideControllerKey;
+ } else {
+ controllerKey = scsiControllerKey;
+ }
+ } else {
+ // DATA volume always use SCSI device
+ controllerKey = scsiControllerKey;
+ }
+ }
+
+ if (vol.getType() != Volume.Type.ISO) {
+ Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(vol.getPoolUuid());
+ assert (volumeDsDetails != null);
+ VirtualDevice device;
+ datastoreDiskPath = String.format("[%s] %s.vmdk", volumeDsDetails.second().getName(), vol.getPath());
+ String chainInfo = vol.getChainInfo();
+
+ if (chainInfo != null && !chainInfo.isEmpty()) {
+ String[] diskChain = _gson.fromJson(chainInfo, String[].class);
+ if (diskChain == null || diskChain.length < 1) {
+ s_logger.warn("Empty previously-saved chain info, fall back to the original");
+ device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), i, i + 1);
+ } else {
+ s_logger.info("Attach the disk with stored chain info: " + chainInfo);
+ for (int j = 0; j < diskChain.length; j++) {
+ diskChain[j] = String.format("[%s] %s", volumeDsDetails.second().getName(), diskChain[j]);
+ }
+
+ device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, diskChain, volumeDsDetails.first(), i, i + 1);
+ }
+ } else {
+ device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), i, i + 1);
+ }
+ deviceConfigSpecArray[i].setDevice(device);
+ deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.add);
+
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Prepare volume at new device " + _gson.toJson(device));
+
+ i++;
+ }
+ }
+
+ VirtualDevice nic;
+ int nicMask = 0;
+ int nicCount = 0;
+ for (NicTO nicTo : sortNicsByDeviceId(nics)) {
+ s_logger.info("Prepare NIC device based on NicTO: " + _gson.toJson(nicTo));
+
+ Pair<ManagedObjectReference, String> networkInfo = prepareNetworkFromNicInfo(vmMo.getRunningHost(), nicTo);
+ if (mgr.getNexusVSwitchGlobalParameter()) {
+ String dvSwitchUuid;
+ ManagedObjectReference dcMor = hyperHost.getHyperHostDatacenter();
+ DatacenterMO dataCenterMo = new DatacenterMO(context, dcMor);
+ ManagedObjectReference dvsMor = dataCenterMo.getDvSwitchMor(networkInfo.first());
+ dvSwitchUuid = dataCenterMo.getDvSwitchUuid(dvsMor);
+ s_logger.info("Preparing NIC device on dvSwitch : " + dvSwitchUuid);
+ nic = VmwareHelper.prepareDvNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), dvSwitchUuid, nicTo.getMac(), i, i + 1, true, true);
+ } else {
+ s_logger.info("Preparing NIC device on network " + networkInfo.second());
+ nic = VmwareHelper.prepareNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), nicTo.getMac(), i, i + 1, true, true);
+ }
+
+ deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
+ deviceConfigSpecArray[i].setDevice(nic);
+ deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.add);
+
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Prepare NIC at new device " + _gson.toJson(deviceConfigSpecArray[i]));
+
+ // this is really a hacking for DomR, upon DomR startup, we will reset all the NIC allocation after eth3
+ if(nicCount < 3)
+ nicMask |= (1 << nicCount);
+
+ i++;
+ nicCount++;
+ }
+
+ vmConfigSpec.setDeviceChange(deviceConfigSpecArray);
+
+ // pass boot arguments through machine.id & perform customized options to VMX
+
+ Map<String, String> vmDetailOptions = validateVmDetails(vmSpec.getDetails());
+ OptionValue[] extraOptions = new OptionValue[2 + vmDetailOptions.size()];
+ extraOptions[0] = new OptionValue();
+ extraOptions[0].setKey("machine.id");
+ extraOptions[0].setValue(vmSpec.getBootArgs());
+
+ extraOptions[1] = new OptionValue();
+ extraOptions[1].setKey("devices.hotplug");
+ extraOptions[1].setValue("true");
+
+ int j = 2;
+ for(Map.Entry<String, String> entry : vmDetailOptions.entrySet()) {
+ extraOptions[j] = new OptionValue();
+ extraOptions[j].setKey(entry.getKey());
+ extraOptions[j].setValue(entry.getValue());
+ j++;
+ }
+
+ String keyboardLayout = null;
+ if(vmSpec.getDetails() != null)
+ keyboardLayout = vmSpec.getDetails().get(VmDetailConstants.KEYBOARD);
+ vmConfigSpec.setExtraConfig(configureVnc(extraOptions, hyperHost, vmName, vmSpec.getVncPassword(), keyboardLayout));
+
+ if (!vmMo.configureVm(vmConfigSpec)) {
+ throw new Exception("Failed to configure VM before start. vmName: " + vmName);
+ }
+
+ vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMask));
+
+ if (!vmMo.powerOn()) {
+ throw new Exception("Failed to start VM. vmName: " + vmName);
+ }
+
+ state = State.Running;
+ return new StartAnswer(cmd);
+ } catch (Throwable e) {
+ if (e instanceof RemoteException) {
+ s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+ invalidateServiceContext();
+ }
+
+ String msg = "StartCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.warn(msg, e);
+ return new StartAnswer(cmd, msg);
+ } finally {
+ synchronized (_vms) {
+ if (state != State.Stopped) {
+ _vms.put(vmName, state);
+ } else {
+ _vms.remove(vmName);
+ }
+ }
+ }
+ }
+
+ private Map<String, String> validateVmDetails(Map<String, String> vmDetails) {
+ Map<String, String> validatedDetails = new HashMap<String, String>();
+
+ if(vmDetails != null && vmDetails.size() > 0) {
+ for(Map.Entry<String, String> entry : vmDetails.entrySet()) {
+ if("machine.id".equalsIgnoreCase(entry.getKey()))
+ continue;
+ else if("devices.hotplug".equalsIgnoreCase(entry.getKey()))
+ continue;
+ else if("RemoteDisplay.vnc.enabled".equalsIgnoreCase(entry.getKey()))
+ continue;
+ else if("RemoteDisplay.vnc.password".equalsIgnoreCase(entry.getKey()))
+ continue;
+ else if("RemoteDisplay.vnc.port".equalsIgnoreCase(entry.getKey()))
+ continue;
+ else if("RemoteDisplay.vnc.keymap".equalsIgnoreCase(entry.getKey()))
+ continue;
+ else
+ validatedDetails.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return validatedDetails;
+ }
+
+ private int getReserveCpuMHz(int cpuMHz) {
+ if(this._reserveCpu) {
+ return (int)(cpuMHz / this._cpuOverprovisioningFactor);
+ }
+
+ return 0;
+ }
+
+ private int getReserveMemMB(int memMB) {
+ if(this._reserveMem) {
+ return (int)(memMB / this._memOverprovisioningFactor);
+ }
+
+ return 0;
+ }
+
+ private NicTO[] sortNicsByDeviceId(NicTO[] nics) {
+
+ List<NicTO> listForSort = new ArrayList<NicTO>();
+ for (NicTO nic : nics) {
+ listForSort.add(nic);
+ }
+ Collections.sort(listForSort, new Comparator<NicTO>() {
+
+ @Override
+ public int compare(NicTO arg0, NicTO arg1) {
+ if (arg0.getDeviceId() < arg1.getDeviceId()) {
+ return -1;
+ } else if (arg0.getDeviceId() == arg1.getDeviceId()) {
+ return 0;
+ }
+
+ return 1;
+ }
+ });
+
+ return listForSort.toArray(new NicTO[0]);
+ }
+
+ private VolumeTO[] sortVolumesByDeviceId(VolumeTO[] volumes) {
+
+ List<VolumeTO> listForSort = new ArrayList<VolumeTO>();
+ for (VolumeTO vol : volumes) {
+ listForSort.add(vol);
+ }
+ Collections.sort(listForSort, new Comparator<VolumeTO>() {
+
+ @Override
+ public int compare(VolumeTO arg0, VolumeTO arg1) {
+ if (arg0.getDeviceId() < arg1.getDeviceId()) {
+ return -1;
+ } else if (arg0.getDeviceId() == arg1.getDeviceId()) {
+ return 0;
+ }
+
+ return 1;
+ }
+ });
+
+ return listForSort.toArray(new VolumeTO[0]);
+ }
+
+ private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context, VolumeTO[] disks) throws Exception {
+ HashMap<String ,Pair<ManagedObjectReference, DatastoreMO>> poolMors = new HashMap<String, Pair<ManagedObjectReference, DatastoreMO>>();
+
+ assert (hyperHost != null) && (context != null);
+ for (VolumeTO vol : disks) {
+ if (vol.getType() != Volume.Type.ISO) {
+ String poolUuid = vol.getPoolUuid();
+ if(poolMors.get(poolUuid) == null) {
+ ManagedObjectReference morDataStore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid);
+ if (morDataStore == null) {
+ String msg = "Failed to get the mounted datastore for the volume's pool " + poolUuid;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+ poolMors.put(vol.getPoolUuid(), new Pair<ManagedObjectReference, DatastoreMO> (morDataStore, new DatastoreMO(context, morDataStore)));
+ }
+ }
+ }
+ return poolMors;
+ }
+
+ private String getVlanInfo(NicTO nicTo, String defaultVlan) {
+ if (nicTo.getBroadcastType() == BroadcastDomainType.Native) {
+ return defaultVlan;
+ }
+
+ if (nicTo.getBroadcastType() == BroadcastDomainType.Vlan) {
+ if (nicTo.getBroadcastUri() != null) {
+ return nicTo.getBroadcastUri().getHost();
+ } else {
+ s_logger.warn("BroadcastType is not claimed as VLAN, but without vlan info in broadcast URI. Use vlan info from labeling: " + defaultVlan);
+ return defaultVlan;
+ }
+ }
+
+ s_logger.warn("Unrecognized broadcast type in VmwareResource, type: " + nicTo.getBroadcastType().toString() + ". Use vlan info from labeling: " + defaultVlan);
+ return defaultVlan;
+ }
+
+ private Pair<ManagedObjectReference, String> prepareNetworkFromNicInfo(HostMO hostMo, NicTO nicTo) throws Exception {
+
+ Pair<String, String> switchName = getTargetSwitch(nicTo);
+ String namePrefix = getNetworkNamePrefix(nicTo);
+ Pair<ManagedObjectReference, String> networkInfo = null;
+
+ s_logger.info("Prepare network on vSwitch: " + switchName + " with name prefix: " + namePrefix);
+
+ if(!_nexusVSwitch) {
+ networkInfo = HypervisorHostHelper.prepareNetwork(switchName.first(), namePrefix, hostMo, getVlanInfo(nicTo, switchName.second()),
+ nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout,
+ !namePrefix.startsWith("cloud.private"));
+ }
+ else {
+ networkInfo = HypervisorHostHelper.prepareNetwork(switchName.first(), namePrefix, hostMo, getVlanInfo(nicTo, switchName.second()),
+ nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout);
+ }
+
+ return networkInfo;
+ }
+
+ // return Pair<switch name, vlan tagging>
+ private Pair<String, String> getTargetSwitch(NicTO nicTo) throws Exception {
+ if(nicTo.getName() != null && !nicTo.getName().isEmpty()) {
+ String[] tokens = nicTo.getName().split(",");
+
+ if(tokens.length == 2) {
+ return new Pair<String, String>(tokens[0], tokens[1]);
+ } else {
+ return new Pair<String, String>(nicTo.getName(), Vlan.UNTAGGED);
+ }
+ }
+
+ if (nicTo.getType() == Networks.TrafficType.Guest) {
+ return new Pair<String, String>(this._guestNetworkVSwitchName, Vlan.UNTAGGED);
+ } else if (nicTo.getType() == Networks.TrafficType.Control || nicTo.getType() == Networks.TrafficType.Management) {
+ return new Pair<String, String>(this._privateNetworkVSwitchName, Vlan.UNTAGGED);
+ } else if (nicTo.getType() == Networks.TrafficType.Public) {
+ return new Pair<String, String>(this._publicNetworkVSwitchName, Vlan.UNTAGGED);
+ } else if (nicTo.getType() == Networks.TrafficType.Storage) {
+ return new Pair<String, String>(this._privateNetworkVSwitchName, Vlan.UNTAGGED);
+ } else if (nicTo.getType() == Networks.TrafficType.Vpn) {
+ throw new Exception("Unsupported traffic type: " + nicTo.getType().toString());
+ } else {
+ throw new Exception("Unsupported traffic type: " + nicTo.getType().toString());
+ }
+ }
+
+ private String getNetworkNamePrefix(NicTO nicTo) throws Exception {
+ if (nicTo.getType() == Networks.TrafficType.Guest) {
+ return "cloud.guest";
+ } else if (nicTo.getType() == Networks.TrafficType.Control || nicTo.getType() == Networks.TrafficType.Management) {
+ return "cloud.private";
+ } else if (nicTo.getType() == Networks.TrafficType.Public) {
+ return "cloud.public";
+ } else if (nicTo.getType() == Networks.TrafficType.Storage) {
+ return "cloud.storage";
+ } else if (nicTo.getType() == Networks.TrafficType.Vpn) {
+ throw new Exception("Unsupported traffic type: " + nicTo.getType().toString());
+ } else {
+ throw new Exception("Unsupported traffic type: " + nicTo.getType().toString());
+ }
+ }
+
+ protected synchronized Answer execute(final RemoteAccessVpnCfgCommand cmd) {
+ String controlIp = getRouterSshControlIp(cmd);
+ StringBuffer argsBuf = new StringBuffer();
+ if (cmd.isCreate()) {
+ argsBuf.append(" -r ").append(cmd.getIpRange()).append(" -p ").append(cmd.getPresharedKey()).append(" -s ").append(cmd.getVpnServerIp()).append(" -l ").append(cmd.getLocalIp())
+ .append(" -c ");
+
+ } else {
+ argsBuf.append(" -d ").append(" -s ").append(cmd.getVpnServerIp());
+ }
+
+ try {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Executing /opt/cloud/bin/vpn_lt2p.sh ");
+ }
+
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "/opt/cloud/bin/vpn_l2tp.sh " + argsBuf.toString());
+
+ if (!result.first()) {
+ s_logger.error("RemoteAccessVpnCfg command on domR failed, message: " + result.second());
+
+ return new Answer(cmd, false, "RemoteAccessVpnCfg command failed due to " + result.second());
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("RemoteAccessVpnCfg command on domain router " + argsBuf.toString() + " completed");
+ }
+
+ } catch (Throwable e) {
+ if (e instanceof RemoteException) {
+ s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+ invalidateServiceContext();
+ }
+
+ String msg = "RemoteAccessVpnCfg command failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+
+ return new Answer(cmd);
+ }
+
+ protected synchronized Answer execute(final VpnUsersCfgCommand cmd) {
+ VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+
+ String controlIp = getRouterSshControlIp(cmd);
+ for (VpnUsersCfgCommand.UsernamePassword userpwd : cmd.getUserpwds()) {
+ StringBuffer argsBuf = new StringBuffer();
+ if (!userpwd.isAdd()) {
+ argsBuf.append(" -U ").append(userpwd.getUsername());
+ } else {
+ argsBuf.append(" -u ").append(userpwd.getUsernamePassword());
+ }
+
+ try {
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Executing /opt/cloud/bin/vpn_lt2p.sh ");
+ }
+
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "/opt/cloud/bin/vpn_l2tp.sh " + argsBuf.toString());
+
+ if (!result.first()) {
+ s_logger.error("VpnUserCfg command on domR failed, message: " + result.second());
+
+ return new Answer(cmd, false, "VpnUserCfg command failed due to " + result.second());
+ }
+ } catch (Throwable e) {
+ if (e instanceof RemoteException) {
+ s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+ invalidateServiceContext();
+ }
+
+ String msg = "VpnUserCfg command failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+ }
+
+ return new Answer(cmd);
+ }
+
+ private VirtualMachineMO takeVmFromOtherHyperHost(VmwareHypervisorHost hyperHost, String vmName) throws Exception {
+
+ VirtualMachineMO vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
+ if (vmMo != null) {
+ ManagedObjectReference morTargetPhysicalHost = hyperHost.findMigrationTarget(vmMo);
+ if (morTargetPhysicalHost == null) {
+ String msg = "VM " + vmName + " is on other host and we have no resource available to migrate and start it here";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ if (!vmMo.relocate(morTargetPhysicalHost)) {
+ String msg = "VM " + vmName + " is on other host and we failed to relocate it here";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ return vmMo;
+ }
+ return null;
+ }
+
+ // isoUrl sample content :
+ // nfs://192.168.10.231/export/home/kelven/vmware-test/secondary/template/tmpl/2/200//200-2-80f7ee58-6eff-3a2d-bcb0-59663edf6d26.iso
+ private Pair<String, ManagedObjectReference> getIsoDatastoreInfo(VmwareHypervisorHost hyperHost, String isoUrl) throws Exception {
+
+ assert (isoUrl != null);
+ int isoFileNameStartPos = isoUrl.lastIndexOf("/");
+ if (isoFileNameStartPos < 0) {
+ throw new Exception("Invalid ISO path info");
+ }
+
+ String isoFileName = isoUrl.substring(isoFileNameStartPos);
+
+ int templateRootPos = isoUrl.indexOf("template/tmpl");
+ if (templateRootPos < 0) {
+ throw new Exception("Invalid ISO path info");
+ }
+
+ String storeUrl = isoUrl.substring(0, templateRootPos - 1);
+ Strin
<TRUNCATED>