From 748b575af8a66c58b0d52e7457e4d4e1e875231f Mon Sep 17 00:00:00 2001 From: Tim Mackey Date: Thu, 10 Apr 2014 15:57:24 -0400 Subject: [PATCH] Cleanup of Xen and XenServer terms. Removed xen plugin and created xenserver plugin Signed-off-by: Tim Mackey Signed-off-by: Sebastien Goasguen --- .../xenserver/findbugsExcludeFilter.xml | 31 + plugins/hypervisors/xenserver/pom.xml | 44 + .../xenserver-compute/module.properties | 18 + .../spring-xenserver-compute-context.xml | 28 + .../xenserver-discoverer/module.properties | 18 + .../spring-xenserver-discoverer-context.xml | 25 + .../src/com/cloud/ha/XenServerFencer.java | 129 + .../com/cloud/hypervisor/XenServerGuru.java | 160 + .../discoverer/XcpServerDiscoverer.java | 726 ++ .../xenserver/resource/CitrixHelper.java | 2404 ++++++ .../resource/CitrixResourceBase.java | 7553 +++++++++++++++++ .../xenserver/resource/XcpOssResource.java | 195 + .../resource/XcpServer16Resource.java | 32 + .../xenserver/resource/XcpServerResource.java | 160 + .../resource/XenServer56FP1Resource.java | 168 + .../resource/XenServer56Resource.java | 328 + .../resource/XenServer56SP2Resource.java | 89 + .../resource/XenServer600Resource.java | 87 + .../resource/XenServer602Resource.java | 64 + .../resource/XenServer610Resource.java | 434 + .../resource/XenServer620Resource.java | 108 + .../resource/XenServer620SP1Resource.java | 185 + .../resource/XenServerConnectionPool.java | 503 ++ .../xenserver/resource/XenServerPoolVms.java | 90 + .../resource/XenServerStorageProcessor.java | 1699 ++++ .../resource/Xenserver625Resource.java | 160 + .../Xenserver625StorageProcessor.java | 822 ++ .../xenserver/XenServerResourceNewBase.java | 345 + .../xenserver/XenserverConfigs.java | 25 + .../XenServerStorageMotionStrategy.java | 249 + .../com/cloud/ha/XenServerFencerTest.java | 39 + .../resource/CitrixResourceBaseTest.java | 190 + 32 files changed, 17108 insertions(+) create mode 100644 plugins/hypervisors/xenserver/findbugsExcludeFilter.xml create mode 100644 plugins/hypervisors/xenserver/pom.xml create mode 100644 plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/module.properties create mode 100644 plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/spring-xenserver-compute-context.xml create mode 100644 plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/module.properties create mode 100644 plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/spring-xenserver-discoverer-context.xml create mode 100755 plugins/hypervisors/xenserver/src/com/cloud/ha/XenServerFencer.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/XenServerGuru.java create mode 100755 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixHelper.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServer16Resource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServerResource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56FP1Resource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56Resource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56SP2Resource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer600Resource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer602Resource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620Resource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerConnectionPool.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerPoolVms.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625Resource.java create mode 100644 plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java create mode 100644 plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenServerResourceNewBase.java create mode 100644 plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenserverConfigs.java create mode 100644 plugins/hypervisors/xenserver/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java create mode 100644 plugins/hypervisors/xenserver/test/com/cloud/ha/XenServerFencerTest.java create mode 100644 plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/CitrixResourceBaseTest.java diff --git a/plugins/hypervisors/xenserver/findbugsExcludeFilter.xml b/plugins/hypervisors/xenserver/findbugsExcludeFilter.xml new file mode 100644 index 00000000000..b341889e9d4 --- /dev/null +++ b/plugins/hypervisors/xenserver/findbugsExcludeFilter.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + diff --git a/plugins/hypervisors/xenserver/pom.xml b/plugins/hypervisors/xenserver/pom.xml new file mode 100644 index 00000000000..0bdb04afef0 --- /dev/null +++ b/plugins/hypervisors/xenserver/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + cloud-plugin-hypervisor-xenserver + Apache CloudStack Plugin - Hypervisor XenServer + + org.apache.cloudstack + cloudstack-plugins + 4.5.0-SNAPSHOT + ../../pom.xml + + + + org.apache.cloudstack + cloud-engine-storage + ${project.version} + + + org.apache.cloudstack + cloud-plugin-network-ovs + ${project.version} + + + org.apache.httpcomponents + httpclient + compile + + + net.java.dev.vcc.thirdparty + xen-api + ${cs.xapi.version} + + + diff --git a/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/module.properties b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/module.properties new file mode 100644 index 00000000000..c6c91f658fc --- /dev/null +++ b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/module.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with 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. +name=xenserver-compute +parent=compute \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/spring-xenserver-compute-context.xml b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/spring-xenserver-compute-context.xml new file mode 100644 index 00000000000..e024ad837c8 --- /dev/null +++ b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-compute/spring-xenserver-compute-context.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + diff --git a/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/module.properties b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/module.properties new file mode 100644 index 00000000000..10d0ecdf729 --- /dev/null +++ b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/module.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with 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. +name=xenserver-discoverer +parent=discoverer \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/spring-xenserver-discoverer-context.xml b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/spring-xenserver-discoverer-context.xml new file mode 100644 index 00000000000..767e2d0e9a1 --- /dev/null +++ b/plugins/hypervisors/xenserver/resources/META-INF/cloudstack/xenserver-discoverer/spring-xenserver-discoverer-context.xml @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/plugins/hypervisors/xenserver/src/com/cloud/ha/XenServerFencer.java b/plugins/hypervisors/xenserver/src/com/cloud/ha/XenServerFencer.java new file mode 100755 index 00000000000..28cba2b98c4 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/ha/XenServerFencer.java @@ -0,0 +1,129 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.ha; + +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.FenceAnswer; +import com.cloud.agent.api.FenceCommand; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; +import com.cloud.utils.component.AdapterBase; +import com.cloud.vm.VirtualMachine; + +@Local(value = FenceBuilder.class) +public class XenServerFencer extends AdapterBase implements FenceBuilder { + private static final Logger s_logger = Logger.getLogger(XenServerFencer.class); + + @Inject + HostDao _hostDao; + @Inject + AgentManager _agentMgr; + @Inject + ResourceManager _resourceMgr; + + @Override + public Boolean fenceOff(VirtualMachine vm, Host host) { + if (host.getHypervisorType() != HypervisorType.XenServer) { + s_logger.debug("Don't know how to fence non XenServer hosts " + host.getHypervisorType()); + return null; + } + + List hosts = _resourceMgr.listAllHostsInCluster(host.getClusterId()); + FenceCommand fence = new FenceCommand(vm, host); + + for (HostVO h : hosts) { + if (h.getHypervisorType() == HypervisorType.XenServer) { + if (h.getStatus() != Status.Up) { + continue; + } + if (h.getId() == host.getId()) { + continue; + } + FenceAnswer answer; + try { + Answer ans = _agentMgr.send(h.getId(), fence); + if (!(ans instanceof FenceAnswer)) { + s_logger.debug("Answer is not fenceanswer. Result = " + ans.getResult() + "; Details = " + ans.getDetails()); + continue; + } + answer = (FenceAnswer)ans; + } catch (AgentUnavailableException e) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Moving on to the next host because " + h.toString() + " is unavailable"); + } + continue; + } catch (OperationTimedoutException e) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Moving on to the next host because " + h.toString() + " is unavailable"); + } + continue; + } + if (answer != null && answer.getResult()) { + return true; + } + } + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Unable to fence off " + vm.toString() + " on " + host.toString()); + } + + return false; + } + + public XenServerFencer() { + super(); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + _name = name; + return true; + } + + @Override + public String getName() { + return _name; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } + +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/XenServerGuru.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/XenServerGuru.java new file mode 100644 index 00000000000..89e4ab5d94b --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/XenServerGuru.java @@ -0,0 +1,160 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor; + +import java.util.ArrayList; +import java.util.List; + +import javax.ejb.Local; +import javax.inject.Inject; + +import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.template.VirtualMachineTemplate.BootloaderType; +import com.cloud.utils.Pair; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +import org.apache.cloudstack.hypervisor.xenserver.XenserverConfigs; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.DettachCommand; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; + +@Local(value = HypervisorGuru.class) +public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru { + @Inject + GuestOSDao _guestOsDao; + @Inject + EndPointSelector endPointSelector; + @Inject + HostDao hostDao; + @Inject + VolumeDao _volumeDao; + @Inject + PrimaryDataStoreDao _storagePoolDao; + @Inject + VolumeDataFactory _volFactory; + + protected XenServerGuru() { + super(); + } + + @Override + public HypervisorType getHypervisorType() { + return HypervisorType.XenServer; + } + + @Override + public VirtualMachineTO implement(VirtualMachineProfile vm) { + BootloaderType bt = BootloaderType.PyGrub; + if (vm.getBootLoaderType() == BootloaderType.CD) { + bt = vm.getBootLoaderType(); + } + VirtualMachineTO to = toVirtualMachineTO(vm); + to.setBootloader(bt); + + // Determine the VM's OS description + GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId()); + to.setOs(guestOS.getDisplayName()); + + return to; + } + + @Override + public boolean trackVmHostChange() { + return true; + } + + @Override + public List finalizeExpungeVolumes(VirtualMachine vm) { + List commands = new ArrayList(); + + List volumes = _volumeDao.findByInstance(vm.getId()); + + // it's OK in this case to send a detach command to the host for a root volume as this + // will simply lead to the SR that supports the root volume being removed + if (volumes != null) { + for (VolumeVO volume : volumes) { + StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId()); + + // storagePool should be null if we are expunging a volume that was never + // attached to a VM that was started (the "trick" for storagePool to be null + // is that none of the VMs this volume may have been attached to were ever started, + // so the volume was never assigned to a storage pool) + if (storagePool != null && storagePool.isManaged()) { + DataTO volTO = _volFactory.getVolume(volume.getId()).getTO(); + DiskTO disk = new DiskTO(volTO, volume.getDeviceId(), volume.getPath(), volume.getVolumeType()); + + DettachCommand cmd = new DettachCommand(disk, vm.getInstanceName()); + + cmd.setManaged(true); + + cmd.setStorageHost(storagePool.getHostAddress()); + cmd.setStoragePort(storagePool.getPort()); + + cmd.set_iScsiName(volume.get_iScsiName()); + + commands.add(cmd); + } + } + } + + return commands; + } + + @Override + public Pair getCommandHostDelegation(long hostId, Command cmd) { + if (cmd instanceof CopyCommand) { + CopyCommand cpyCommand = (CopyCommand)cmd; + DataTO srcData = cpyCommand.getSrcTO(); + DataTO destData = cpyCommand.getDestTO(); + + if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType() == DataObjectType.TEMPLATE) { + DataStoreTO srcStore = srcData.getDataStore(); + DataStoreTO destStore = destData.getDataStore(); + if (srcStore instanceof NfsTO && destStore instanceof NfsTO) { + HostVO host = hostDao.findById(hostId); + EndPoint ep = endPointSelector.selectHypervisorHost(new ZoneScope(host.getDataCenterId())); + host = hostDao.findById(ep.getId()); + hostDao.loadDetails(host); + String snapshotHotFixVersion = host.getDetail(XenserverConfigs.XS620HotFix); + if (snapshotHotFixVersion != null && snapshotHotFixVersion.equalsIgnoreCase(XenserverConfigs.XSHotFix62ESP1004)) { + return new Pair(Boolean.TRUE, new Long(ep.getId())); + } + } + } + } + return new Pair(Boolean.FALSE, new Long(hostId)); + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java new file mode 100755 index 00000000000..630edb5038d --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java @@ -0,0 +1,726 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.discoverer; + +import java.net.InetAddress; +import java.net.URI; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import javax.persistence.EntityExistsException; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.Listener; +import com.cloud.agent.api.AgentControlAnswer; +import com.cloud.agent.api.AgentControlCommand; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.SetupAnswer; +import com.cloud.agent.api.SetupCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.alert.AlertManager; +import com.cloud.configuration.Config; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.HostPodVO; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.ConnectionException; +import com.cloud.exception.DiscoveredWithErrorException; +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.HostEnvironment; +import com.cloud.host.HostInfo; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.hypervisor.xenserver.resource.XcpOssResource; +import com.cloud.hypervisor.xenserver.resource.XcpServer16Resource; +import com.cloud.hypervisor.xenserver.resource.XcpServerResource; +import com.cloud.hypervisor.xenserver.resource.XenServer56FP1Resource; +import com.cloud.hypervisor.xenserver.resource.XenServer56Resource; +import com.cloud.hypervisor.xenserver.resource.XenServer56SP2Resource; +import com.cloud.hypervisor.xenserver.resource.XenServer600Resource; +import com.cloud.hypervisor.xenserver.resource.XenServer602Resource; +import com.cloud.hypervisor.xenserver.resource.XenServer610Resource; +import com.cloud.hypervisor.xenserver.resource.XenServer620Resource; +import com.cloud.hypervisor.xenserver.resource.XenServer620SP1Resource; +import com.cloud.hypervisor.xenserver.resource.XenServerConnectionPool; +import com.cloud.hypervisor.xenserver.resource.Xenserver625Resource; +import org.apache.cloudstack.hypervisor.xenserver.XenserverConfigs; +import com.cloud.resource.Discoverer; +import com.cloud.resource.DiscovererBase; +import com.cloud.resource.ResourceStateAdapter; +import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.user.Account; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.db.QueryBuilder; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.exception.HypervisorVersionChangedException; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Pool; +import com.xensource.xenapi.Session; +import com.xensource.xenapi.PoolPatch; +import com.xensource.xenapi.HostPatch; +import com.xensource.xenapi.Types.SessionAuthenticationFailed; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.Types.UuidInvalid; + + +@Local(value = Discoverer.class) +public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter { + private static final Logger s_logger = Logger.getLogger(XcpServerDiscoverer.class); + protected String _publicNic; + protected String _privateNic; + protected String _storageNic1; + protected String _storageNic2; + protected int _wait; + protected XenServerConnectionPool _connPool; + protected boolean _checkHvm; + protected String _guestNic; + protected boolean _setupMultipath; + protected String _instance; + private String xs620snapshothotfix = "Xenserver-Vdi-Copy-HotFix"; + + @Inject + protected AlertManager _alertMgr; + @Inject + protected AgentManager _agentMgr; + @Inject + VMTemplateDao _tmpltDao; + @Inject + HostPodDao _podDao; + + protected XcpServerDiscoverer() { + } + + void setClusterGuid(ClusterVO cluster, String guid) { + cluster.setGuid(guid); + try { + _clusterDao.update(cluster.getId(), cluster); + } catch (EntityExistsException e) { + QueryBuilder sc = QueryBuilder.create(ClusterVO.class); + sc.and(sc.entity().getGuid(), Op.EQ, guid); + List clusters = sc.list(); + ClusterVO clu = clusters.get(0); + List clusterHosts = _resourceMgr.listAllHostsInCluster(clu.getId()); + if (clusterHosts == null || clusterHosts.size() == 0) { + clu.setGuid(null); + _clusterDao.update(clu.getId(), clu); + _clusterDao.update(cluster.getId(), cluster); + return; + } + throw e; + } + } + + protected boolean poolHasHotFix(Connection conn, String hostIp, String hotFixUuid) { + try { + Map hosts = Host.getAllRecords(conn); + for (Map.Entry entry : hosts.entrySet()) { + + Host.Record re = entry.getValue(); + if (!re.address.equalsIgnoreCase(hostIp)){ + continue; + } + Set patches = re.patches; + PoolPatch poolPatch = PoolPatch.getByUuid(conn, hotFixUuid); + for(HostPatch patch : patches) { + PoolPatch pp = patch.getPoolPatch(conn); + if (pp.equals(poolPatch) && patch.getApplied(conn)) { + s_logger.debug("host " + hostIp + " does have " + hotFixUuid +" Hotfix."); + return true; + } + } + } + return false; + } catch (UuidInvalid e) { + s_logger.debug("host " + hostIp + " doesn't have " + hotFixUuid + " Hotfix"); + } catch (Exception e) { + s_logger.debug("can't get patches information, consider it doesn't have " + hotFixUuid + " Hotfix"); + } + return false; + } + + + + @Override + public Map> + find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List hostTags) throws DiscoveryException { + Map> resources = new HashMap>(); + Connection conn = null; + if (!url.getScheme().equals("http")) { + String msg = "urlString is not http so we're not taking care of the discovery for this: " + url; + s_logger.debug(msg); + return null; + } + if (clusterId == null) { + String msg = "must specify cluster Id when add host"; + s_logger.debug(msg); + throw new RuntimeException(msg); + } + + if (podId == null) { + String msg = "must specify pod Id when add host"; + s_logger.debug(msg); + throw new RuntimeException(msg); + } + + ClusterVO cluster = _clusterDao.findById(clusterId); + if (cluster == null || cluster.getHypervisorType() != HypervisorType.XenServer) { + if (s_logger.isInfoEnabled()) + s_logger.info("invalid cluster id or cluster is not for XenServer hypervisors"); + return null; + } + + try { + String hostname = url.getHost(); + InetAddress ia = InetAddress.getByName(hostname); + String hostIp = ia.getHostAddress(); + Queue pass = new LinkedList(); + pass.add(password); + conn = _connPool.getConnect(hostIp, username, pass); + if (conn == null) { + String msg = "Unable to get a connection to " + url; + s_logger.debug(msg); + throw new DiscoveryException(msg); + } + + Set pools = Pool.getAll(conn); + Pool pool = pools.iterator().next(); + Pool.Record pr = pool.getRecord(conn); + String poolUuid = pr.uuid; + Map hosts = Host.getAllRecords(conn); + String latestHotFix = ""; + if (poolHasHotFix(conn, hostIp, XenserverConfigs.XSHotFix62ESP1004)) { + latestHotFix = XenserverConfigs.XSHotFix62ESP1004; + } else if (poolHasHotFix(conn, hostIp, XenserverConfigs.XSHotFix62ESP1)) { + latestHotFix = XenserverConfigs.XSHotFix62ESP1; + } + + /*set cluster hypervisor type to xenserver*/ + ClusterVO clu = _clusterDao.findById(clusterId); + if (clu.getGuid() == null) { + setClusterGuid(clu, poolUuid); + } else { + List clusterHosts = _resourceMgr.listAllHostsInCluster(clusterId); + if (clusterHosts != null && clusterHosts.size() > 0) { + if (!clu.getGuid().equals(poolUuid)) { + String msg = "Please join the host " + hostIp + " to XS pool " + + clu.getGuid() + " through XC/XS before adding it through CS UI"; + s_logger.warn(msg); + throw new DiscoveryException(msg); + } + } else { + setClusterGuid(clu, poolUuid); + } + } + // can not use this conn after this point, because this host may join a pool, this conn is retired + if (conn != null) { + try { + Session.logout(conn); + } catch (Exception e) { + } + conn.dispose(); + conn = null; + } + + poolUuid = clu.getGuid(); + _clusterDao.update(clusterId, clu); + + if (_checkHvm) { + for (Map.Entry entry : hosts.entrySet()) { + Host.Record record = entry.getValue(); + + boolean support_hvm = false; + for (String capability : record.capabilities) { + if (capability.contains("hvm")) { + support_hvm = true; + break; + } + } + if (!support_hvm) { + String msg = "Unable to add host " + record.address + " because it doesn't support hvm"; + _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, dcId, podId, msg, msg); + s_logger.debug(msg); + throw new RuntimeException(msg); + } + } + } + + for (Map.Entry entry : hosts.entrySet()) { + Host.Record record = entry.getValue(); + String hostAddr = record.address; + + String prodVersion = record.softwareVersion.get("product_version"); + if (prodVersion == null) { + prodVersion = record.softwareVersion.get("platform_version"); + } + String xenVersion = record.softwareVersion.get("xenserver"); + String hostOS = record.softwareVersion.get("product_brand"); + if (hostOS == null) { + hostOS = record.softwareVersion.get("platform_name"); + } + + String hostOSVer = prodVersion; + String hostKernelVer = record.softwareVersion.get("linux"); + + if (_resourceMgr.findHostByGuid(record.uuid) != null) { + s_logger.debug("Skipping " + record.address + " because " + record.uuid + " is already in the database."); + continue; + } + + CitrixResourceBase resource = createServerResource(dcId, podId, record, latestHotFix); + s_logger.info("Found host " + record.hostname + " ip=" + record.address + " product version=" + prodVersion); + + Map details = new HashMap(); + Map params = new HashMap(); + details.put("url", hostAddr); + details.put("username", username); + params.put("username", username); + details.put("password", password); + params.put("password", password); + params.put("zone", Long.toString(dcId)); + params.put("guid", record.uuid); + params.put("pod", podId.toString()); + params.put("cluster", clusterId.toString()); + params.put("pool", poolUuid); + params.put("ipaddress", record.address); + + details.put(HostInfo.HOST_OS, hostOS); + details.put(HostInfo.HOST_OS_VERSION, hostOSVer); + details.put(HostInfo.HOST_OS_KERNEL_VERSION, hostKernelVer); + details.put(HostInfo.HYPERVISOR_VERSION, xenVersion); + + String privateNetworkLabel = _networkMgr.getDefaultManagementTrafficLabel(dcId, HypervisorType.XenServer); + String storageNetworkLabel = _networkMgr.getDefaultStorageTrafficLabel(dcId, HypervisorType.XenServer); + + if (!params.containsKey("private.network.device") && privateNetworkLabel != null) { + params.put("private.network.device", privateNetworkLabel); + details.put("private.network.device", privateNetworkLabel); + } + + if (!params.containsKey("storage.network.device1") && storageNetworkLabel != null) { + params.put("storage.network.device1", storageNetworkLabel); + details.put("storage.network.device1", storageNetworkLabel); + } + + DataCenterVO zone = _dcDao.findById(dcId); + boolean securityGroupEnabled = zone.isSecurityGroupEnabled(); + params.put("securitygroupenabled", Boolean.toString(securityGroupEnabled)); + + params.put("wait", Integer.toString(_wait)); + details.put("wait", Integer.toString(_wait)); + params.put("migratewait", _configDao.getValue(Config.MigrateWait.toString())); + params.put(Config.XenMaxNics.toString().toLowerCase(), _configDao.getValue(Config.XenMaxNics.toString())); + params.put(Config.XenHeartBeatInterval.toString().toLowerCase(), _configDao.getValue(Config.XenHeartBeatInterval.toString())); + params.put(Config.InstanceName.toString().toLowerCase(), _instance); + details.put(Config.InstanceName.toString().toLowerCase(), _instance); + try { + resource.configure("Xen Server", params); + } catch (ConfigurationException e) { + _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, dcId, podId, "Unable to add " + record.address, "Error is " + e.getMessage()); + s_logger.warn("Unable to instantiate " + record.address, e); + continue; + } + resource.start(); + resources.put(resource, details); + } + } catch (SessionAuthenticationFailed e) { + throw new DiscoveredWithErrorException("Authentication error"); + } catch (XenAPIException e) { + s_logger.warn("XenAPI exception", e); + return null; + } catch (XmlRpcException e) { + s_logger.warn("Xml Rpc Exception", e); + return null; + } catch (UnknownHostException e) { + s_logger.warn("Unable to resolve the host name", e); + return null; + } catch (Exception e) { + s_logger.debug("other exceptions: " + e.toString(), e); + return null; + } + return resources; + } + + String getPoolUuid(Connection conn) throws XenAPIException, XmlRpcException { + Map pools = Pool.getAllRecords(conn); + assert pools.size() == 1 : "Pools size is " + pools.size(); + return pools.values().iterator().next().uuid; + } + + protected void addSamePool(Connection conn, Map> resources) throws XenAPIException, XmlRpcException { + Map hps = Pool.getAllRecords(conn); + assert (hps.size() == 1) : "How can it be more than one but it's actually " + hps.size(); + + // This is the pool. + String poolUuid = hps.values().iterator().next().uuid; + + for (Map details : resources.values()) { + details.put("pool", poolUuid); + } + } + + + protected CitrixResourceBase createServerResource(long dcId, Long podId, Host.Record record, String hotfix) { + String prodBrand = record.softwareVersion.get("product_brand"); + if (prodBrand == null) { + prodBrand = record.softwareVersion.get("platform_name").trim(); + } else { + prodBrand = prodBrand.trim(); + } + + String prodVersion = record.softwareVersion.get("product_version"); + if (prodVersion == null) { + prodVersion = record.softwareVersion.get("platform_version").trim(); + } else { + prodVersion = prodVersion.trim(); + } + + // Xen Cloud Platform group of hypervisors + if (prodBrand.equals("XCP") && (prodVersion.equals("1.0.0") || prodVersion.equals("1.1.0") || prodVersion.equals("5.6.100") || prodVersion.startsWith("1.4"))) { + return new XcpServerResource(); + } else if (prodBrand.equals("XCP") && prodVersion.startsWith("1.6")) { + return new XcpServer16Resource(); + } // Citrix Xenserver group of hypervisors + else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.0")) + return new XenServer56Resource(); + else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.0")) + return new XenServer600Resource(); + else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.2")) + return new XenServer602Resource(); + else if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.0")) + return new XenServer610Resource(); + else if (prodBrand.equals("XenServer") && prodVersion.equals("6.2.0")) { + if (hotfix.equals(XenserverConfigs.XSHotFix62ESP1004)) { + return new Xenserver625Resource(); + } else if (hotfix.equals(XenserverConfigs.XSHotFix62ESP1)) { + return new XenServer620SP1Resource(); + } else { + return new XenServer620Resource(); + } + } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) { + String prodVersionTextShort = record.softwareVersion.get("product_version_text_short").trim(); + if ("5.6 SP2".equals(prodVersionTextShort)) { + return new XenServer56SP2Resource(); + } else if ("5.6 FP1".equals(prodVersionTextShort)) { + return new XenServer56FP1Resource(); + } + } else if (prodBrand.equals("XCP_Kronos")) { + return new XcpOssResource(); + } + + String msg = + "Only support XCP 1.0.0, 1.1.0, 1.4.x, 1.5 beta, 1.6.x; XenServer 5.6, XenServer 5.6 FP1, XenServer 5.6 SP2, Xenserver 6.0, 6.0.2, 6.1.0, 6.2.0 but this one is " + + prodBrand + " " + prodVersion; + _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, dcId, podId, msg, msg); + s_logger.debug(msg); + throw new RuntimeException(msg); + } + + protected void serverConfig() { + String value = _params.get(Config.XenSetupMultipath.key()); + _setupMultipath = Boolean.parseBoolean(value); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + serverConfig(); + + _publicNic = _params.get(Config.XenPublicNetwork.key()); + _privateNic = _params.get(Config.XenPrivateNetwork.key()); + + _storageNic1 = _params.get(Config.XenStorageNetwork1.key()); + _storageNic2 = _params.get(Config.XenStorageNetwork2.key()); + + _guestNic = _params.get(Config.XenGuestNetwork.key()); + + String value = _params.get(Config.XapiWait.toString()); + _wait = NumbersUtil.parseInt(value, Integer.parseInt(Config.XapiWait.getDefaultValue())); + + _instance = _params.get(Config.InstanceName.key()); + + value = _params.get(Config.XenSetupMultipath.key()); + Boolean.parseBoolean(value); + + value = _params.get("xenserver.check.hvm"); + _checkHvm = false; + _connPool = XenServerConnectionPool.getInstance(); + + _agentMgr.registerForHostEvents(this, true, false, true); + + createXsToolsISO(); + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); + return true; + } + + @Override + public boolean matchHypervisor(String hypervisor) { + if (hypervisor == null) + return true; + return Hypervisor.HypervisorType.XenServer.toString().equalsIgnoreCase(hypervisor); + } + + @Override + public Hypervisor.HypervisorType getHypervisorType() { + return Hypervisor.HypervisorType.XenServer; + } + + @Override + public void postDiscovery(List hosts, long msId) throws DiscoveryException { + //do nothing + } + + @Override + public int getTimeout() { + return 0; + } + + @Override + public boolean isRecurring() { + return false; + } + + @Override + public boolean processAnswers(long agentId, long seq, Answer[] answers) { + return false; + } + + @Override + public boolean processCommands(long agentId, long seq, Command[] commands) { + return false; + } + + private void createXsToolsISO() { + String isoName = "xs-tools.iso"; + VMTemplateVO tmplt = _tmpltDao.findByTemplateName(isoName); + Long id; + if (tmplt == null) { + id = _tmpltDao.getNextInSequence(Long.class, "id"); + VMTemplateVO template = + VMTemplateVO.createPreHostIso(id, isoName, isoName, ImageFormat.ISO, true, true, TemplateType.PERHOST, null, null, true, 64, Account.ACCOUNT_ID_SYSTEM, + null, "xen-pv-drv-iso", false, 1, false, HypervisorType.XenServer); + _tmpltDao.persist(template); + } else { + id = tmplt.getId(); + tmplt.setTemplateType(TemplateType.PERHOST); + tmplt.setUrl(null); + _tmpltDao.update(id, tmplt); + } + } + + @Override + public void processConnect(com.cloud.host.Host agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + if (!(cmd instanceof StartupRoutingCommand)) { + return; + } + long agentId = agent.getId(); + + StartupRoutingCommand startup = (StartupRoutingCommand)cmd; + if (startup.getHypervisorType() != HypervisorType.XenServer) { + s_logger.debug("Not XenServer so moving on."); + return; + } + + HostVO host = _hostDao.findById(agentId); + + ClusterVO cluster = _clusterDao.findById(host.getClusterId()); + if (cluster.getGuid() == null) { + cluster.setGuid(startup.getPool()); + _clusterDao.update(cluster.getId(), cluster); + } else if (!cluster.getGuid().equals(startup.getPool())) { + String msg = "pool uuid for cluster " + cluster.getId() + " changed from " + cluster.getGuid() + " to " + startup.getPool(); + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + String resource = null; + Map details = startup.getHostDetails(); + String prodBrand = details.get("product_brand").trim(); + String prodVersion = details.get("product_version").trim(); + + if (prodBrand.equals("XCP") && (prodVersion.equals("1.0.0") || prodVersion.equals("1.1.0") || prodVersion.equals("5.6.100") || prodVersion.startsWith("1.4"))) { + resource = XcpServerResource.class.getName(); + } else if (prodBrand.equals("XCP") && prodVersion.startsWith("1.6")) { + resource = XcpServer16Resource.class.getName(); + } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.0")) { + resource = XenServer56Resource.class.getName(); + } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.0")) { + resource = XenServer600Resource.class.getName(); + } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.2")) { + resource = XenServer602Resource.class.getName(); + } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.0")) { + resource = XenServer610Resource.class.getName(); + } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.2.0")) { + String hotfix = details.get(XenserverConfigs.XS620HotFix); + if (hotfix != null && hotfix.equalsIgnoreCase(XenserverConfigs.XSHotFix62ESP1004)) { + resource = Xenserver625Resource.class.getName(); + } else if (hotfix != null && hotfix.equalsIgnoreCase(XenserverConfigs.XSHotFix62ESP1)){ + resource = XenServer620SP1Resource.class.getName(); + } else { + resource = XenServer620Resource.class.getName(); + } + } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) { + String prodVersionTextShort = details.get("product_version_text_short").trim(); + if ("5.6 SP2".equals(prodVersionTextShort)) { + resource = XenServer56SP2Resource.class.getName(); + } else if ("5.6 FP1".equals(prodVersionTextShort)) { + resource = XenServer56FP1Resource.class.getName(); + } + } else if (prodBrand.equals("XCP_Kronos")) { + resource = XcpOssResource.class.getName(); + } + + if (resource == null) { + String msg = + "Only support XCP 1.0.0, 1.1.0, 1.4.x, 1.5 beta, 1.6.x; XenServer 5.6, 5.6 FP1, 5.6 SP2 and Xenserver 6.0 , 6.0.2, 6.1.0, 6.2.0 but this one is " + + prodBrand + " " + prodVersion; + s_logger.debug(msg); + throw new RuntimeException(msg); + } + if (!resource.equals(host.getResource())) { + String msg = "host " + host.getPrivateIpAddress() + " changed from " + host.getResource() + " to " + resource; + s_logger.debug(msg); + host.setResource(resource); + host.setSetup(false); + _hostDao.update(agentId, host); + throw new HypervisorVersionChangedException(msg); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Setting up host " + agentId); + } + HostEnvironment env = new HostEnvironment(); + + SetupCommand setup = new SetupCommand(env); + if (_setupMultipath) { + setup.setMultipathOn(); + } + if (!host.isSetup()) { + setup.setNeedSetup(true); + } + + try { + Answer answer = _agentMgr.send(agentId, setup); + if (answer != null && answer.getResult() && answer instanceof SetupAnswer) { + host.setSetup(true); + host.setLastPinged((System.currentTimeMillis() >> 10) - 5 * 60); + _hostDao.update(host.getId(), host); + if (((SetupAnswer)answer).needReconnect()) { + throw new ConnectionException(false, "Reinitialize agent after setup."); + } + return; + } else { + s_logger.warn("Unable to setup agent " + agentId + " due to " + ((answer != null) ? answer.getDetails() : "return null")); + } + } catch (AgentUnavailableException e) { + s_logger.warn("Unable to setup agent " + agentId + " because it became unavailable.", e); + } catch (OperationTimedoutException e) { + s_logger.warn("Unable to setup agent " + agentId + " because it timed out", e); + } + throw new ConnectionException(true, "Reinitialize agent after setup."); + } + + @Override + public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) { + return null; + } + + @Override + public boolean processDisconnect(long agentId, Status state) { + return false; + } + + @Override + public boolean processTimeout(long agentId, long seq) { + return false; + } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, List hostTags) { + StartupCommand firstCmd = startup[0]; + if (!(firstCmd instanceof StartupRoutingCommand)) { + return null; + } + + StartupRoutingCommand ssCmd = ((StartupRoutingCommand)firstCmd); + if (ssCmd.getHypervisorType() != HypervisorType.XenServer) { + return null; + } + + HostPodVO pod = _podDao.findById(host.getPodId()); + DataCenterVO dc = _dcDao.findById(host.getDataCenterId()); + s_logger.info("Host: " + host.getName() + " connected with hypervisor type: " + HypervisorType.XenServer + ". Checking CIDR..."); + _resourceMgr.checkCIDR(pod, dc, ssCmd.getPrivateIpAddress(), ssCmd.getPrivateNetmask()); + return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.XenServer, details, hostTags); + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + if (host.getType() != com.cloud.host.Host.Type.Routing || host.getHypervisorType() != HypervisorType.XenServer) { + return null; + } + + _resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage); + return new DeleteHostAnswer(true); + } + + @Override + protected HashMap buildConfigParams(HostVO host) { + HashMap params = super.buildConfigParams(host); + DataCenterVO zone = _dcDao.findById(host.getDataCenterId()); + if (zone != null) { + boolean securityGroupEnabled = zone.isSecurityGroupEnabled(); + params.put("securitygroupenabled", Boolean.toString(securityGroupEnabled)); + } + return params; + } + + @Override + public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); + return super.stop(); + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixHelper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixHelper.java new file mode 100644 index 00000000000..96fafec8320 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixHelper.java @@ -0,0 +1,2404 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +/** + * Reduce bloat inside CitrixResourceBase + * + */ +public class CitrixHelper { + private static final Logger s_logger = Logger.getLogger(CitrixHelper.class); + + private static final HashMap Xcp100GuestOsMap = new HashMap(70); + private static final HashMap Xcp160GuestOsMap = new HashMap(70); + private static final HashMap XenServerGuestOsMap = new HashMap(70); + private static final HashMap XenServer56FP1GuestOsMap = new HashMap(70); + private static final HashMap XenServer56FP2GuestOsMap = new HashMap(70); + private static final HashMap XenServer600GuestOsMap = new HashMap(70); + private static final HashMap XenServer602GuestOsMap = new HashMap(70); + private static final HashMap XenServer610GuestOsMap = new HashMap(70); + private static final HashMap XenServer620GuestOsMap = new HashMap(70); + private static final HashMap XenServer620SP1GuestOsMap = new HashMap(70); + private static final HashMap XenServer620GuestOsMemoryMap = new HashMap(70); + private static final HashMap XenServer620SP1GuestOsMemoryMap = new HashMap(70); + private static final HashMap XenServer610GuestOsMemoryMap = new HashMap(70); + private static final HashMap XenServer602GuestOsMemoryMap = new HashMap(70); + private static final HashMap XenServer600GuestOsMemoryMap = new HashMap(70); + private static final HashMap XenServer56SP2GuestOsMemoryMap = new HashMap(70); + private static final HashMap XenServer56FP1GuestOsMemoryMap = new HashMap(70); + private static final ArrayList GuestOsList = new ArrayList(70); + + static { + Xcp100GuestOsMap.put("CentOS 4.5 (32-bit)", "CentOS 4.5 (32-bit)"); + Xcp100GuestOsMap.put("CentOS 4.6 (32-bit)", "CentOS 4.6 (32-bit)"); + Xcp100GuestOsMap.put("CentOS 4.7 (32-bit)", "CentOS 4.7 (32-bit)"); + Xcp100GuestOsMap.put("CentOS 4.8 (32-bit)", "CentOS 4.8 (32-bit)"); + Xcp100GuestOsMap.put("CentOS 5.0 (32-bit)", "CentOS 5 (32-bit)"); + Xcp100GuestOsMap.put("CentOS 5.0 (64-bit)", "CentOS 5 (64-bit)"); + Xcp100GuestOsMap.put("CentOS 5.1 (32-bit)", "CentOS 5 (32-bit)"); + Xcp100GuestOsMap.put("CentOS 5.1 (64-bit)", "CentOS 5 (64-bit)"); + Xcp100GuestOsMap.put("CentOS 5.2 (32-bit)", "CentOS 5 (32-bit)"); + Xcp100GuestOsMap.put("CentOS 5.2 (64-bit)", "CentOS 5 (64-bit)"); + Xcp100GuestOsMap.put("CentOS 5.3 (32-bit)", "CentOS 5 (32-bit)"); + Xcp100GuestOsMap.put("CentOS 5.3 (64-bit)", "CentOS 5 (64-bit)"); + Xcp100GuestOsMap.put("CentOS 5.4 (32-bit)", "CentOS 5 (32-bit)"); + Xcp100GuestOsMap.put("CentOS 5.4 (64-bit)", "CentOS 5 (64-bit)"); + Xcp100GuestOsMap.put("CentOS 5.5 (32-bit)", "CentOS 5 (32-bit)"); + Xcp100GuestOsMap.put("CentOS 5.5 (64-bit)", "CentOS 5 (64-bit)"); + Xcp100GuestOsMap.put("Debian GNU/Linux 5.0 (32-bit)", "Debian Lenny 5.0 (32-bit)"); + Xcp100GuestOsMap.put("Debian GNU/Linux 6(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + Xcp100GuestOsMap.put("Debian GNU/Linux 6(64-bit)", "Debian Squeeze 6.0 (64-bit) (experimental)"); + Xcp100GuestOsMap.put("Debian GNU/Linux 7(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + Xcp100GuestOsMap.put("Debian GNU/Linux 7(64-bit)", "Debian Squeeze 6.0 (64-bit) (experimental)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.0 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.0 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.1 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.1 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.2 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.2 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.3 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.3 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.4 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.4 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.5 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Oracle Enterprise Linux 5.5 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", "Red Hat Enterprise Linux 4.5 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", "Red Hat Enterprise Linux 4.6 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", "Red Hat Enterprise Linux 4.7 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", "Red Hat Enterprise Linux 4.8 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + Xcp100GuestOsMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + Xcp100GuestOsMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", "SUSE Linux Enterprise Server 9 SP4"); + Xcp100GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", "SUSE Linux Enterprise Server 10 SP1"); + Xcp100GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", "SUSE Linux Enterprise Server 10 SP1 x64"); + Xcp100GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", "SUSE Linux Enterprise Server 10 SP2"); + Xcp100GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", "SUSE Linux Enterprise Server 10 SP2 x64"); + Xcp100GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", "Other install media"); + Xcp100GuestOsMap.put("SUSE Linux Enterprise Server 11 (32-bit)", "SUSE Linux Enterprise Server 11"); + Xcp100GuestOsMap.put("SUSE Linux Enterprise Server 11 (64-bit)", "SUSE Linux Enterprise Server 11 x64"); + Xcp100GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", "SUSE Linux Enterprise Server 11 SP1 (32-bit)"); + Xcp100GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", "SUSE Linux Enterprise Server 11 SP1 (64-bit)"); + Xcp100GuestOsMap.put("Windows 7 (32-bit)", "Windows 7 (32-bit)"); + Xcp100GuestOsMap.put("Windows 7 (64-bit)", "Windows 7 (64-bit)"); + Xcp100GuestOsMap.put("Windows Server 2003 (32-bit)", "Windows Server 2003 (32-bit)"); + Xcp100GuestOsMap.put("Windows Server 2003 (64-bit)", "Windows Server 2003 (64-bit)"); + Xcp100GuestOsMap.put("Windows Server 2003 Enterprise Edition(32-bit)", "Windows Server 2003 (32-bit)"); + Xcp100GuestOsMap.put("Windows Server 2003 Enterprise Edition(64-bit)", "Windows Server 2003 (64-bit)"); + Xcp100GuestOsMap.put("Windows Server 2003 DataCenter Edition(32-bit)", "Windows Server 2003 (32-bit)"); + Xcp100GuestOsMap.put("Windows Server 2003 DataCenter Edition(64-bit)", "Windows Server 2003 (64-bit)"); + Xcp100GuestOsMap.put("Windows Server 2003 Standard Edition(32-bit)", "Windows Server 2003 (32-bit)"); + Xcp100GuestOsMap.put("Windows Server 2003 Standard Edition(64-bit)", "Windows Server 2003 (64-bit)"); + Xcp100GuestOsMap.put("Windows Server 2008 (32-bit)", "Windows Server 2008 (32-bit)"); + Xcp100GuestOsMap.put("Windows Server 2008 (64-bit)", "Windows Server 2008 (64-bit)"); + Xcp100GuestOsMap.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + Xcp100GuestOsMap.put("Windows XP SP3 (32-bit)", "Windows XP SP3 (32-bit)"); + Xcp100GuestOsMap.put("Windows Vista (32-bit)", "Windows Vista (32-bit)"); + Xcp100GuestOsMap.put("Ubuntu 10.04 (32-bit)", "Ubuntu Lucid Lynx 10.04 (32-bit) (experimental)"); + Xcp100GuestOsMap.put("Ubuntu 10.04 (64-bit)", "Ubuntu Lucid Lynx 10.04 (64-bit) (experimental)"); + Xcp100GuestOsMap.put("Other Linux (32-bit)", "Other install media"); + Xcp100GuestOsMap.put("Other Linux (64-bit)", "Other install media"); + Xcp100GuestOsMap.put("Other PV (32-bit)", "CentOS 5 (32-bit)"); + Xcp100GuestOsMap.put("Other PV (64-bit)", "CentOS 5 (64-bit)"); + } + + static { + Xcp160GuestOsMap.put("CentOS 4.5 (32-bit)", "CentOS 4.5 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 4.6 (32-bit)", "CentOS 4.6 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 4.7 (32-bit)", "CentOS 4.7 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 4.8 (32-bit)", "CentOS 4.8 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 5.0 (32-bit)", "CentOS 5 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 5.0 (64-bit)", "CentOS 5 (64-bit)"); + Xcp160GuestOsMap.put("CentOS 5.1 (32-bit)", "CentOS 5 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 5.1 (64-bit)", "CentOS 5 (64-bit)"); + Xcp160GuestOsMap.put("CentOS 5.2 (32-bit)", "CentOS 5 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 5.2 (64-bit)", "CentOS 5 (64-bit)"); + Xcp160GuestOsMap.put("CentOS 5.3 (32-bit)", "CentOS 5 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 5.3 (64-bit)", "CentOS 5 (64-bit)"); + Xcp160GuestOsMap.put("CentOS 5.4 (32-bit)", "CentOS 5 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 5.4 (64-bit)", "CentOS 5 (64-bit)"); + Xcp160GuestOsMap.put("CentOS 5.5 (32-bit)", "CentOS 5 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 5.5 (64-bit)", "CentOS 5 (64-bit)"); + Xcp160GuestOsMap.put("CentOS 5.6 (32-bit)", "CentOS 5 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 5.6 (64-bit)", "CentOS 5 (64-bit)"); + Xcp160GuestOsMap.put("CentOS 5.7 (32-bit)", "CentOS 5 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 5.7 (64-bit)", "CentOS 5 (64-bit)"); + Xcp160GuestOsMap.put("CentOS 6.0 (32-bit)", "CentOS 6 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 6.0 (64-bit)", "CentOS 6 (64-bit)"); + Xcp160GuestOsMap.put("CentOS 6.1 (32-bit)", "CentOS 6 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 6.1 (64-bit)", "CentOS 6 (64-bit)"); + Xcp160GuestOsMap.put("CentOS 6.2 (32-bit)", "CentOS 6 (32-bit)"); + Xcp160GuestOsMap.put("CentOS 6.2 (64-bit)", "CentOS 6 (64-bit)"); + Xcp160GuestOsMap.put("Debian GNU/Linux 5.0 (32-bit)", "Debian Lenny 5.0 (32-bit)"); + Xcp160GuestOsMap.put("Debian GNU/Linux 6(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + Xcp160GuestOsMap.put("Debian GNU/Linux 6(64-bit)", "Debian Squeeze 6.0 (64-bit)"); + Xcp160GuestOsMap.put("Debian GNU/Linux 7(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + Xcp160GuestOsMap.put("Debian GNU/Linux 7(64-bit)", "Debian Squeeze 6.0 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.0 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.0 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.1 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.1 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.2 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.2 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.3 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.3 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.4 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.4 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.5 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.5 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.6 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.6 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.7 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 5.7 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 6.0 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 6.0 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 6.1 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 6.1 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 6.2 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + Xcp160GuestOsMap.put("Oracle Enterprise Linux 6.2 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", "Red Hat Enterprise Linux 4.5 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", "Red Hat Enterprise Linux 4.6 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", "Red Hat Enterprise Linux 4.7 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", "Red Hat Enterprise Linux 4.8 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + Xcp160GuestOsMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + Xcp160GuestOsMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", "SUSE Linux Enterprise Server 9 SP4"); + Xcp160GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", "SUSE Linux Enterprise Server 10 SP1"); + Xcp160GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", "SUSE Linux Enterprise Server 10 SP1 x64"); + Xcp160GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", "SUSE Linux Enterprise Server 10 SP2"); + Xcp160GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", "SUSE Linux Enterprise Server 10 SP2 x64"); + Xcp160GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", "Other install media"); + Xcp160GuestOsMap.put("SUSE Linux Enterprise Server 11 (32-bit)", "SUSE Linux Enterprise Server 11"); + Xcp160GuestOsMap.put("SUSE Linux Enterprise Server 11 (64-bit)", "SUSE Linux Enterprise Server 11 x64"); + Xcp160GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", "SUSE Linux Enterprise Server 11 SP1 (32-bit)"); + Xcp160GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", "SUSE Linux Enterprise Server 11 SP1 (64-bit)"); + Xcp160GuestOsMap.put("Windows 7 (32-bit)", "Windows 7 (32-bit)"); + Xcp160GuestOsMap.put("Windows 7 (64-bit)", "Windows 7 (64-bit)"); + Xcp160GuestOsMap.put("Windows Server 2003 (32-bit)", "Windows Server 2003 (32-bit)"); + Xcp160GuestOsMap.put("Windows Server 2003 (64-bit)", "Windows Server 2003 (64-bit)"); + Xcp160GuestOsMap.put("Windows Server 2003 Enterprise Edition(32-bit)", "Windows Server 2003 (32-bit)"); + Xcp160GuestOsMap.put("Windows Server 2003 Enterprise Edition(64-bit)", "Windows Server 2003 (64-bit)"); + Xcp160GuestOsMap.put("Windows Server 2003 DataCenter Edition(32-bit)", "Windows Server 2003 (32-bit)"); + Xcp160GuestOsMap.put("Windows Server 2003 DataCenter Edition(64-bit)", "Windows Server 2003 (64-bit)"); + Xcp160GuestOsMap.put("Windows Server 2003 Standard Edition(32-bit)", "Windows Server 2003 (32-bit)"); + Xcp160GuestOsMap.put("Windows Server 2003 Standard Edition(64-bit)", "Windows Server 2003 (64-bit)"); + Xcp160GuestOsMap.put("Windows Server 2008 (32-bit)", "Windows Server 2008 (32-bit)"); + Xcp160GuestOsMap.put("Windows Server 2008 (64-bit)", "Windows Server 2008 (64-bit)"); + Xcp160GuestOsMap.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + Xcp160GuestOsMap.put("Windows XP SP3 (32-bit)", "Windows XP SP3 (32-bit)"); + Xcp160GuestOsMap.put("Windows Vista (32-bit)", "Windows Vista (32-bit)"); + Xcp160GuestOsMap.put("Ubuntu 10.04 (32-bit)", "Ubuntu Lucid Lynx 10.04 (32-bit)"); + Xcp160GuestOsMap.put("Ubuntu 10.04 (64-bit)", "Ubuntu Lucid Lynx 10.04 (64-bit)"); + Xcp160GuestOsMap.put("Ubuntu 12.04 (32-bit)", "Ubuntu Precise Pangolin 12.04 (32-bit)"); + Xcp160GuestOsMap.put("Ubuntu 12.04 (64-bit)", "Ubuntu Precise Pangolin 12.04 (64-bit)"); + Xcp160GuestOsMap.put("Other Linux (32-bit)", "Other install media"); + Xcp160GuestOsMap.put("Other Linux (64-bit)", "Other install media"); + Xcp160GuestOsMap.put("Other PV (32-bit)", "CentOS 5 (32-bit)"); + Xcp160GuestOsMap.put("Other PV (64-bit)", "CentOS 5 (64-bit)"); + } + + static { + XenServerGuestOsMap.put("CentOS 4.5 (32-bit)", "CentOS 4.5 (32-bit)"); + XenServerGuestOsMap.put("CentOS 4.6 (32-bit)", "CentOS 4.6 (32-bit)"); + XenServerGuestOsMap.put("CentOS 4.7 (32-bit)", "CentOS 4.7 (32-bit)"); + XenServerGuestOsMap.put("CentOS 4.8 (32-bit)", "CentOS 4.8 (32-bit)"); + XenServerGuestOsMap.put("CentOS 5.0 (32-bit)", "CentOS 5.0 (32-bit)"); + XenServerGuestOsMap.put("CentOS 5.0 (64-bit)", "CentOS 5.0 (64-bit)"); + XenServerGuestOsMap.put("CentOS 5.1 (32-bit)", "CentOS 5.1 (32-bit)"); + XenServerGuestOsMap.put("CentOS 5.1 (64-bit)", "CentOS 5.1 (64-bit)"); + XenServerGuestOsMap.put("CentOS 5.2 (32-bit)", "CentOS 5.2 (32-bit)"); + XenServerGuestOsMap.put("CentOS 5.2 (64-bit)", "CentOS 5.2 (64-bit)"); + XenServerGuestOsMap.put("CentOS 5.3 (32-bit)", "CentOS 5.3 (32-bit)"); + XenServerGuestOsMap.put("CentOS 5.3 (64-bit)", "CentOS 5.3 (64-bit)"); + XenServerGuestOsMap.put("CentOS 5.4 (32-bit)", "CentOS 5.4 (32-bit)"); + XenServerGuestOsMap.put("CentOS 5.4 (64-bit)", "CentOS 5.4 (64-bit)"); + XenServerGuestOsMap.put("Debian GNU/Linux 5.0 (32-bit)", "Debian Lenny 5.0 (32-bit)"); + XenServerGuestOsMap.put("Debian GNU/Linux 6(32-bit)", "Debian Lenny 5.0 (32-bit)"); // This is to support Debian 6.0 in XS 5.6 + XenServerGuestOsMap.put("Debian GNU/Linux 7(32-bit)", "Debian Lenny 5.0 (32-bit)"); // This is to support Debian 7.0 in XS 5.6 + XenServerGuestOsMap.put("Oracle Enterprise Linux 5.0 (32-bit)", "Oracle Enterprise Linux 5.0 (32-bit)"); + XenServerGuestOsMap.put("Oracle Enterprise Linux 5.0 (64-bit)", "Oracle Enterprise Linux 5.0 (64-bit)"); + XenServerGuestOsMap.put("Oracle Enterprise Linux 5.1 (32-bit)", "Oracle Enterprise Linux 5.1 (32-bit)"); + XenServerGuestOsMap.put("Oracle Enterprise Linux 5.1 (64-bit)", "Oracle Enterprise Linux 5.1 (64-bit)"); + XenServerGuestOsMap.put("Oracle Enterprise Linux 5.2 (32-bit)", "Oracle Enterprise Linux 5.2 (32-bit)"); + XenServerGuestOsMap.put("Oracle Enterprise Linux 5.2 (64-bit)", "Oracle Enterprise Linux 5.2 (64-bit)"); + XenServerGuestOsMap.put("Oracle Enterprise Linux 5.3 (32-bit)", "Oracle Enterprise Linux 5.3 (32-bit)"); + XenServerGuestOsMap.put("Oracle Enterprise Linux 5.3 (64-bit)", "Oracle Enterprise Linux 5.3 (64-bit)"); + XenServerGuestOsMap.put("Oracle Enterprise Linux 5.4 (32-bit)", "Oracle Enterprise Linux 5.4 (32-bit)"); + XenServerGuestOsMap.put("Oracle Enterprise Linux 5.4 (64-bit)", "Oracle Enterprise Linux 5.4 (64-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", "Red Hat Enterprise Linux 4.5 (32-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", "Red Hat Enterprise Linux 4.6 (32-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", "Red Hat Enterprise Linux 4.7 (32-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", "Red Hat Enterprise Linux 4.8 (32-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", "Red Hat Enterprise Linux 5.0 (32-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", "Red Hat Enterprise Linux 5.0 (64-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", "Red Hat Enterprise Linux 5.1 (32-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", "Red Hat Enterprise Linux 5.1 (64-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", "Red Hat Enterprise Linux 5.2 (32-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", "Red Hat Enterprise Linux 5.2 (64-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", "Red Hat Enterprise Linux 5.3 (32-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", "Red Hat Enterprise Linux 5.3 (64-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", "Red Hat Enterprise Linux 5.4 (32-bit)"); + XenServerGuestOsMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", "Red Hat Enterprise Linux 5.4 (64-bit)"); + XenServerGuestOsMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", "SUSE Linux Enterprise Server 9 SP4 (32-bit)"); + XenServerGuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", "SUSE Linux Enterprise Server 10 SP1 (32-bit)"); + XenServerGuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", "SUSE Linux Enterprise Server 10 SP1 (64-bit)"); + XenServerGuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", "SUSE Linux Enterprise Server 10 SP2 (32-bit)"); + XenServerGuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", "SUSE Linux Enterprise Server 10 SP2 (64-bit)"); + XenServerGuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", "SUSE Linux Enterprise Server 10 SP3 (64-bit)"); + XenServerGuestOsMap.put("SUSE Linux Enterprise Server 11 (32-bit)", "SUSE Linux Enterprise Server 11 (32-bit)"); + XenServerGuestOsMap.put("SUSE Linux Enterprise Server 11 (64-bit)", "SUSE Linux Enterprise Server 11 (64-bit)"); + XenServerGuestOsMap.put("Windows 7 (32-bit)", "Windows 7 (32-bit)"); + XenServerGuestOsMap.put("Windows 7 (64-bit)", "Windows 7 (64-bit)"); + XenServerGuestOsMap.put("Windows Server 2003 (32-bit)", "Windows Server 2003 (32-bit)"); + XenServerGuestOsMap.put("Windows Server 2003 (64-bit)", "Windows Server 2003 (64-bit)"); + XenServerGuestOsMap.put("Windows Server 2003 Enterprise Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServerGuestOsMap.put("Windows Server 2003 Enterprise Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServerGuestOsMap.put("Windows Server 2003 DataCenter Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServerGuestOsMap.put("Windows Server 2003 DataCenter Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServerGuestOsMap.put("Windows Server 2008 (32-bit)", "Windows Server 2008 (32-bit)"); + XenServerGuestOsMap.put("Windows Server 2008 (64-bit)", "Windows Server 2008 (64-bit)"); + XenServerGuestOsMap.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + XenServerGuestOsMap.put("Windows 2000 SP4 (32-bit)", "Windows 2000 SP4 (32-bit)"); + XenServerGuestOsMap.put("Windows 2000 Server SP4 (32-bit)", "Windows 2000 SP4 (32-bit)"); + XenServerGuestOsMap.put("Windows Vista (32-bit)", "Windows Vista (32-bit)"); + XenServerGuestOsMap.put("Windows XP SP2 (32-bit)", "Windows XP SP2 (32-bit)"); + XenServerGuestOsMap.put("Windows XP SP3 (32-bit)", "Windows XP SP3 (32-bit)"); + XenServerGuestOsMap.put("Other Linux (32-bit)", "Other install media"); + XenServerGuestOsMap.put("Other Linux (64-bit)", "Other install media"); + XenServerGuestOsMap.put("Other PV (32-bit)", "CentOS 5.4 (32-bit)"); + XenServerGuestOsMap.put("Other PV (64-bit)", "CentOS 5.4 (64-bit)"); + } + + static { + XenServer56FP1GuestOsMap.put("CentOS 4.5 (32-bit)", "CentOS 4.5 (32-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 4.6 (32-bit)", "CentOS 4.6 (32-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 4.7 (32-bit)", "CentOS 4.7 (32-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 4.8 (32-bit)", "CentOS 4.8 (32-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.0 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.0 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.1 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.1 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.2 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.2 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.3 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.3 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.4 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.4 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.5 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("CentOS 5.5 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Debian GNU/Linux 5.0 (32-bit)", "Debian Lenny 5.0 (32-bit)"); + XenServer56FP1GuestOsMap.put("Debian GNU/Linux 6(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + XenServer56FP1GuestOsMap.put("Debian GNU/Linux 6(64-bit)", "Debian Squeeze 6.0 (64-bit) (experimental)"); + XenServer56FP1GuestOsMap.put("Debian GNU/Linux 7(32-bit)", "Debian Squeeze 6.0 (32-bit)"); // This is to support Debian 7.0 in XS 5.6FP1 + XenServer56FP1GuestOsMap.put("Debian GNU/Linux 7(64-bit)", "Debian Squeeze 6.0 (64-bit) (experimental)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.0 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.0 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.1 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.1 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.2 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.2 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.3 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.3 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.4 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.4 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.5 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Oracle Enterprise Linux 5.5 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", "Red Hat Enterprise Linux 4.5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", "Red Hat Enterprise Linux 4.6 (32-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", "Red Hat Enterprise Linux 4.7 (32-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", "Red Hat Enterprise Linux 4.8 (32-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit) (experimental)"); + XenServer56FP1GuestOsMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit) (experimental)"); + XenServer56FP1GuestOsMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", "SUSE Linux Enterprise Server 9 SP4 (32-bit)"); + XenServer56FP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", "SUSE Linux Enterprise Server 10 SP1 (32-bit)"); + XenServer56FP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", "SUSE Linux Enterprise Server 10 SP1 (64-bit)"); + XenServer56FP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", "SUSE Linux Enterprise Server 10 SP2 (32-bit)"); + XenServer56FP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", "SUSE Linux Enterprise Server 10 SP2 (64-bit)"); + XenServer56FP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", "SUSE Linux Enterprise Server 10 SP3 (64-bit)"); + XenServer56FP1GuestOsMap.put("SUSE Linux Enterprise Server 11 (32-bit)", "SUSE Linux Enterprise Server 11 (32-bit)"); + XenServer56FP1GuestOsMap.put("SUSE Linux Enterprise Server 11 (64-bit)", "SUSE Linux Enterprise Server 11 (64-bit)"); + XenServer56FP1GuestOsMap.put("Windows 7 (32-bit)", "Windows 7 (32-bit)"); + XenServer56FP1GuestOsMap.put("Windows 7 (64-bit)", "Windows 7 (64-bit)"); + XenServer56FP1GuestOsMap.put("Windows Server 2003 (32-bit)", "Windows Server 2003 (32-bit)"); + XenServer56FP1GuestOsMap.put("Windows Server 2003 (64-bit)", "Windows Server 2003 (64-bit)"); + XenServer56FP1GuestOsMap.put("Windows Server 2003 Enterprise Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer56FP1GuestOsMap.put("Windows Server 2003 Enterprise Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer56FP1GuestOsMap.put("Windows Server 2003 DataCenter Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer56FP1GuestOsMap.put("Windows Server 2003 DataCenter Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer56FP1GuestOsMap.put("Windows Server 2008 (32-bit)", "Windows Server 2008 (32-bit)"); + XenServer56FP1GuestOsMap.put("Windows Server 2008 (64-bit)", "Windows Server 2008 (64-bit)"); + XenServer56FP1GuestOsMap.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + XenServer56FP1GuestOsMap.put("Windows 2000 SP4 (32-bit)", "Windows 2000 SP4 (32-bit)"); + XenServer56FP1GuestOsMap.put("Windows 2000 Server SP4 (32-bit)", "Windows 2000 SP4 (32-bit)"); + XenServer56FP1GuestOsMap.put("Windows Vista (32-bit)", "Windows Vista (32-bit)"); + XenServer56FP1GuestOsMap.put("Windows XP SP3 (32-bit)", "Windows XP SP3 (32-bit)"); + XenServer56FP1GuestOsMap.put("Ubuntu 10.04 (32-bit)", "Ubuntu Lucid Lynx 10.04 (32-bit) (experimental)"); + XenServer56FP1GuestOsMap.put("Ubuntu 10.04 (64-bit)", "Ubuntu Lucid Lynx 10.04 (64-bit) (experimental)"); + XenServer56FP1GuestOsMap.put("Other Linux (32-bit)", "Other install media"); + XenServer56FP1GuestOsMap.put("Other Linux (64-bit)", "Other install media"); + XenServer56FP1GuestOsMap.put("Other PV (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP1GuestOsMap.put("Other PV (64-bit)", "CentOS 5 (64-bit)"); + } + + static { + XenServer56FP1GuestOsMemoryMap.put("CentOS 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("CentOS 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Debian GNU/Linux 6(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Debian GNU/Linux 6(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Debian GNU/Linux 7(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Debian GNU/Linux 7(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + // XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", new MemoryValues(512l, 16*1024l));// ?? + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", new MemoryValues(512l, 128*1024l)); //? + //_xenServer56FP1GuestOsMemoryMap.put("Windows 7 (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer56FP1GuestOsMemoryMap.put("Windows 7 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer56FP1GuestOsMemoryMap.put("Windows 8 (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer56FP1GuestOsMemoryMap.put("Windows 8 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2003 (32-bit)", new MemoryValues(256l, 64*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2003 (64-bit)", new MemoryValues(256l, 128*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2003 PAE (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2003 Enterprise Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2003 Enterprise Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2003 DataCenter Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2003 DataCenter Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2003 Standard Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2003 Standard Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2008 (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Windows Server 2008 (64-bit)", new MemoryValues(512l, 16*1024l)); + XenServer56FP1GuestOsMemoryMap.put("Windows Server 2008 R2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Windows Server 2012 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Windows Server 8 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Windows Vista (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Windows XP SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Ubuntu 10.04 (32-bit)", new MemoryValues(128l, 512l)); + XenServer56FP1GuestOsMemoryMap.put("Ubuntu 10.04 (64-bit)", new MemoryValues(128l, 32 * 1024l)); + // XenServer56FP1GuestOsMemoryMap.put("Ubuntu 10.10 (32-bit)", new MemoryValues(512l, 16*1024l));//? + //_xenServer56FP1GuestOsMemoryMap.put("Ubuntu 10.10 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + XenServer56FP1GuestOsMemoryMap.put("Ubuntu 12.04 (32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer56FP1GuestOsMemoryMap.put("Ubuntu 12.04 (64-bit)", new MemoryValues(128l, 128 * 1024l)); + // XenServer56FP1GuestOsMemoryMap.put("Other Linux (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56FP1GuestOsMemoryMap.put("Other Linux (64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Other (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Other (64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Other CentOS (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Other CentOS (64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Other Ubuntu (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Other Ubuntu (64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Other SUSE Linux(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Other SUSE Linux(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Other PV (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56FP1GuestOsMemoryMap.put("Other PV (64-bit)", new MemoryValues(512l, 16*1024l)); + } + + static { + XenServer56FP2GuestOsMap.put("CentOS 4.5 (32-bit)", "CentOS 4.5 (32-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 4.6 (32-bit)", "CentOS 4.6 (32-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 4.7 (32-bit)", "CentOS 4.7 (32-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 4.8 (32-bit)", "CentOS 4.8 (32-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.0 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.0 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.1 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.1 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.2 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.2 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.3 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.3 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.4 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.4 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.5 (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("CentOS 5.5 (64-bit)", "CentOS 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Debian GNU/Linux 5.0 (32-bit)", "Debian Lenny 5.0 (32-bit)"); + XenServer56FP2GuestOsMap.put("Debian GNU/Linux 6(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + XenServer56FP2GuestOsMap.put("Debian GNU/Linux 6(64-bit)", "Debian Squeeze 6.0 (64-bit) (experimental)"); + XenServer56FP2GuestOsMap.put("Debian GNU/Linux 7(32-bit)", "Debian Squeeze 6.0 (32-bit)"); // This is to support Debian 7.0 in XS 5.6FP2 + XenServer56FP2GuestOsMap.put("Debian GNU/Linux 7(64-bit)", "Debian Squeeze 6.0 (64-bit) (experimental)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.0 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.0 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.1 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.1 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.2 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.2 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.3 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.3 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.4 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.4 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.5 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Oracle Enterprise Linux 5.5 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", "Red Hat Enterprise Linux 4.5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", "Red Hat Enterprise Linux 4.6 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", "Red Hat Enterprise Linux 4.7 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", "Red Hat Enterprise Linux 4.8 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer56FP2GuestOsMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer56FP2GuestOsMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", "SUSE Linux Enterprise Server 9 SP4 (32-bit)"); + XenServer56FP2GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", "SUSE Linux Enterprise Server 10 SP1 (32-bit)"); + XenServer56FP2GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", "SUSE Linux Enterprise Server 10 SP1 (64-bit)"); + XenServer56FP2GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", "SUSE Linux Enterprise Server 10 SP2 (32-bit)"); + XenServer56FP2GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", "SUSE Linux Enterprise Server 10 SP2 (64-bit)"); + XenServer56FP2GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", "SUSE Linux Enterprise Server 10 SP3 (64-bit)"); + XenServer56FP2GuestOsMap.put("SUSE Linux Enterprise Server 11 (32-bit)", "SUSE Linux Enterprise Server 11 (32-bit)"); + XenServer56FP2GuestOsMap.put("SUSE Linux Enterprise Server 11 (64-bit)", "SUSE Linux Enterprise Server 11 (64-bit)"); + XenServer56FP2GuestOsMap.put("Windows 7 (32-bit)", "Windows 7 (32-bit)"); + XenServer56FP2GuestOsMap.put("Windows 7 (64-bit)", "Windows 7 (64-bit)"); + XenServer56FP2GuestOsMap.put("Windows Server 2003 (32-bit)", "Windows Server 2003 (32-bit)"); + XenServer56FP2GuestOsMap.put("Windows Server 2003 (64-bit)", "Windows Server 2003 (64-bit)"); + XenServer56FP2GuestOsMap.put("Windows Server 2008 (32-bit)", "Windows Server 2008 (32-bit)"); + XenServer56FP2GuestOsMap.put("Windows Server 2008 (64-bit)", "Windows Server 2008 (64-bit)"); + XenServer56FP2GuestOsMap.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + XenServer56FP2GuestOsMap.put("Windows Vista (32-bit)", "Windows Vista (32-bit)"); + XenServer56FP2GuestOsMap.put("Windows XP SP3 (32-bit)", "Windows XP SP3 (32-bit)"); + XenServer56FP2GuestOsMap.put("Ubuntu 10.04 (32-bit)", "Ubuntu Lucid Lynx 10.04 (32-bit) (experimental)"); + XenServer56FP2GuestOsMap.put("Ubuntu 10.04 (64-bit)", "Ubuntu Lucid Lynx 10.04 (64-bit) (experimental)"); + XenServer56FP2GuestOsMap.put("Other Linux (32-bit)", "Other install media"); + XenServer56FP2GuestOsMap.put("Other Linux (64-bit)", "Other install media"); + XenServer56FP2GuestOsMap.put("Other PV (32-bit)", "CentOS 5 (32-bit)"); + XenServer56FP2GuestOsMap.put("Other PV (64-bit)", "CentOS 5 (64-bit)"); + } + + static { + XenServer56SP2GuestOsMemoryMap.put("CentOS 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("CentOS 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Debian GNU/Linux 6(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Debian GNU/Linux 6(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Debian GNU/Linux 7(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Debian GNU/Linux 7(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", new MemoryValues(512l, 16*1024l));// ?? + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", new MemoryValues(512l, 128*1024l)); //? + //_xenServer56SP2GuestOsMemoryMap.put("Windows 7 (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer56SP2GuestOsMemoryMap.put("Windows 7 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer56SP2GuestOsMemoryMap.put("Windows 8 (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer56SP2GuestOsMemoryMap.put("Windows 8 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + // XenServer56SP2GuestOsMemoryMap.put("Windows Server 2003 (32-bit)", new MemoryValues(256l, 64*1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Windows Server 2003 (64-bit)", new MemoryValues(256l, 128*1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Windows Server 2003 PAE (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Windows Server 2003 Enterprise Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Windows Server 2003 Enterprise Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Windows Server 2003 DataCenter Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Windows Server 2003 DataCenter Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Windows Server 2003 Standard Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Windows Server 2003 Standard Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Windows Server 2008 (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Windows Server 2008 (64-bit)", new MemoryValues(512l, 16*1024l)); + XenServer56SP2GuestOsMemoryMap.put("Windows Server 2008 R2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Windows Server 2012 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Windows Server 8 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Windows Vista (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Windows XP SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Ubuntu 10.04 (32-bit)", new MemoryValues(128l, 512l)); + XenServer56SP2GuestOsMemoryMap.put("Ubuntu 10.04 (64-bit)", new MemoryValues(128l, 32 * 1024l)); + //_xenServer56SP2GuestOsMemoryMap.put("Ubuntu 10.10 (32-bit)", new MemoryValues(512l, 16*1024l));//? + //_xenServer56SP2GuestOsMemoryMap.put("Ubuntu 10.10 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + XenServer56SP2GuestOsMemoryMap.put("Ubuntu 12.04 (32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer56SP2GuestOsMemoryMap.put("Ubuntu 12.04 (64-bit)", new MemoryValues(128l, 128 * 1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other Linux (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other Linux (64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other (64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other CentOS (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other CentOS (64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other Ubuntu (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other Ubuntu (64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other SUSE Linux(32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other SUSE Linux(64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other PV (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer56SP2GuestOsMemoryMap.put("Other PV (64-bit)", new MemoryValues(512l, 16*1024l)); + } + + static { + XenServer600GuestOsMap.put("CentOS 4.5 (32-bit)", "CentOS 4.5 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 4.6 (32-bit)", "CentOS 4.6 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 4.7 (32-bit)", "CentOS 4.7 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 4.8 (32-bit)", "CentOS 4.8 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 5.0 (32-bit)", "CentOS 5 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 5.0 (64-bit)", "CentOS 5 (64-bit)"); + XenServer600GuestOsMap.put("CentOS 5.1 (32-bit)", "CentOS 5 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 5.1 (64-bit)", "CentOS 5 (64-bit)"); + XenServer600GuestOsMap.put("CentOS 5.2 (32-bit)", "CentOS 5 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 5.2 (64-bit)", "CentOS 5 (64-bit)"); + XenServer600GuestOsMap.put("CentOS 5.3 (32-bit)", "CentOS 5 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 5.3 (64-bit)", "CentOS 5 (64-bit)"); + XenServer600GuestOsMap.put("CentOS 5.4 (32-bit)", "CentOS 5 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 5.4 (64-bit)", "CentOS 5 (64-bit)"); + XenServer600GuestOsMap.put("CentOS 5.5 (32-bit)", "CentOS 5 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 5.5 (64-bit)", "CentOS 5 (64-bit)"); + XenServer600GuestOsMap.put("CentOS 5.6 (32-bit)", "CentOS 5 (32-bit)"); + XenServer600GuestOsMap.put("CentOS 5.6 (64-bit)", "CentOS 5 (64-bit)"); + XenServer600GuestOsMap.put("CentOS 6.0 (32-bit)", "CentOS 6.0 (32-bit) (experimental)"); + XenServer600GuestOsMap.put("CentOS 6.0 (64-bit)", "CentOS 6.0 (64-bit) (experimental)"); + XenServer600GuestOsMap.put("Debian GNU/Linux 5.0 (32-bit)", "Debian Lenny 5.0 (32-bit)"); + XenServer600GuestOsMap.put("Debian GNU/Linux 6(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + XenServer600GuestOsMap.put("Debian GNU/Linux 6(64-bit)", "Debian Squeeze 6.0 (64-bit)"); + XenServer600GuestOsMap.put("Debian GNU/Linux 7(32-bit)", "Debian Squeeze 6.0 (32-bit)"); // This is to support Debian 7.0 in XS 6.0 + XenServer600GuestOsMap.put("Debian GNU/Linux 7(64-bit)", "Debian Squeeze 6.0 (64-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.0 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.0 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.1 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.1 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.2 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.2 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.3 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.3 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.4 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.4 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.5 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.5 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.6 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 5.6 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 6.0 (32-bit)", "Oracle Enterprise Linux 6.0 (32-bit)"); + XenServer600GuestOsMap.put("Oracle Enterprise Linux 6.0 (64-bit)", "Oracle Enterprise Linux 6.0 (64-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", "Red Hat Enterprise Linux 4.5 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", "Red Hat Enterprise Linux 4.6 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", "Red Hat Enterprise Linux 4.7 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", "Red Hat Enterprise Linux 4.8 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", "Red Hat Enterprise Linux 6.0 (32-bit)"); + XenServer600GuestOsMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", "Red Hat Enterprise Linux 6.0 (64-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", "SUSE Linux Enterprise Server 9 SP4 (32-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", "SUSE Linux Enterprise Server 10 SP1 (32-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", "SUSE Linux Enterprise Server 10 SP1 (64-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", "SUSE Linux Enterprise Server 10 SP2 (32-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", "SUSE Linux Enterprise Server 10 SP2 (64-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", "SUSE Linux Enterprise Server 10 SP3 (32-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", "SUSE Linux Enterprise Server 10 SP3 (64-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", "SUSE Linux Enterprise Server 10 SP4 (32-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", "SUSE Linux Enterprise Server 10 SP4 (64-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 11 (32-bit)", "SUSE Linux Enterprise Server 11 (32-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 11 (64-bit)", "SUSE Linux Enterprise Server 11 (64-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", "SUSE Linux Enterprise Server 11 SP1 (32-bit)"); + XenServer600GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", "SUSE Linux Enterprise Server 11 SP1 (64-bit)"); + XenServer600GuestOsMap.put("Windows 7 (32-bit)", "Windows 7 (32-bit)"); + XenServer600GuestOsMap.put("Windows 7 (64-bit)", "Windows 7 (64-bit)"); + XenServer600GuestOsMap.put("Windows Server 2003 (32-bit)", "Windows Server 2003 (32-bit)"); + XenServer600GuestOsMap.put("Windows Server 2003 (64-bit)", "Windows Server 2003 (64-bit)"); + XenServer600GuestOsMap.put("Windows Server 2003 Enterprise Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer600GuestOsMap.put("Windows Server 2003 Enterprise Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer600GuestOsMap.put("Windows Server 2003 DataCenter Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer600GuestOsMap.put("Windows Server 2003 DataCenter Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer600GuestOsMap.put("Windows Server 2003 Standard Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer600GuestOsMap.put("Windows Server 2003 Standard Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer600GuestOsMap.put("Windows Server 2008 (32-bit)", "Windows Server 2008 (32-bit)"); + XenServer600GuestOsMap.put("Windows Server 2008 (64-bit)", "Windows Server 2008 (64-bit)"); + XenServer600GuestOsMap.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + XenServer600GuestOsMap.put("Windows Vista (32-bit)", "Windows Vista (32-bit)"); + XenServer600GuestOsMap.put("Windows XP SP3 (32-bit)", "Windows XP SP3 (32-bit)"); + XenServer600GuestOsMap.put("Ubuntu 10.04 (32-bit)", "Ubuntu Lucid Lynx 10.04 (32-bit)"); + XenServer600GuestOsMap.put("Ubuntu 10.04 (64-bit)", "Ubuntu Lucid Lynx 10.04 (64-bit)"); + XenServer600GuestOsMap.put("Ubuntu 10.10 (32-bit)", "Ubuntu Maverick Meerkat 10.10 (32-bit) (experimental)"); + XenServer600GuestOsMap.put("Ubuntu 10.10 (64-bit)", "Ubuntu Maverick Meerkat 10.10 (64-bit) (experimental)"); + XenServer600GuestOsMap.put("Other Linux (32-bit)", "Other install media"); + XenServer600GuestOsMap.put("Other Linux (64-bit)", "Other install media"); + XenServer600GuestOsMap.put("Other (32-bit)", "Other install media"); + XenServer600GuestOsMap.put("Other (64-bit)", "Other install media"); + XenServer600GuestOsMap.put("Other CentOS (32-bit)", "Other install media"); + XenServer600GuestOsMap.put("Other CentOS (64-bit)", "Other install media"); + XenServer600GuestOsMap.put("Other Ubuntu (32-bit)", "Other install media"); + XenServer600GuestOsMap.put("Other Ubuntu (64-bit)", "Other install media"); + XenServer600GuestOsMap.put("Other SUSE Linux(32-bit)", "Other install media"); + XenServer600GuestOsMap.put("Other SUSE Linux(64-bit)", "Other install media"); + XenServer600GuestOsMap.put("Other PV (32-bit)", "CentOS 5 (32-bit)"); + XenServer600GuestOsMap.put("Other PV (64-bit)", "CentOS 5 (64-bit)"); + } + + static { + XenServer600GuestOsMemoryMap.put("CentOS 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("CentOS 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("Debian GNU/Linux 6(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("Debian GNU/Linux 6(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("Debian GNU/Linux 7(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("Debian GNU/Linux 7(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + //_xenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", new MemoryValues(512l, 16*1024l));// ?? + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + //_xenServer600GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", new MemoryValues(512l, 128*1024l)); //? + //_xenServer600GuestOsMemoryMap.put("Windows 7 (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer600GuestOsMemoryMap.put("Windows 7 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer600GuestOsMemoryMap.put("Windows 8 (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer600GuestOsMemoryMap.put("Windows 8 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + // XenServer600GuestOsMemoryMap.put("Windows Server 2003 (32-bit)", new MemoryValues(256l, 64*1024l)); + //_xenServer600GuestOsMemoryMap.put("Windows Server 2003 (64-bit)", new MemoryValues(256l, 128*1024l)); + //_xenServer600GuestOsMemoryMap.put("Windows Server 2003 PAE (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Windows Server 2003 Enterprise Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Windows Server 2003 Enterprise Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Windows Server 2003 DataCenter Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Windows Server 2003 DataCenter Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Windows Server 2003 Standard Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Windows Server 2003 Standard Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Windows Server 2008 (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Windows Server 2008 (64-bit)", new MemoryValues(512l, 16*1024l)); + XenServer600GuestOsMemoryMap.put("Windows Server 2008 R2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Windows Server 2012 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Windows Server 8 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Windows Vista (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Windows XP SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer600GuestOsMemoryMap.put("Ubuntu 10.04 (32-bit)", new MemoryValues(128l, 512l)); + XenServer600GuestOsMemoryMap.put("Ubuntu 10.04 (64-bit)", new MemoryValues(128l, 32 * 1024l)); + //_xenServer600GuestOsMemoryMap.put("Ubuntu 10.10 (32-bit)", new MemoryValues(512l, 16*1024l));//? + //_xenServer600GuestOsMemoryMap.put("Ubuntu 10.10 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + XenServer600GuestOsMemoryMap.put("Ubuntu 12.04 (32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer600GuestOsMemoryMap.put("Ubuntu 12.04 (64-bit)", new MemoryValues(128l, 128 * 1024l)); + //_xenServer600GuestOsMemoryMap.put("Other Linux (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other Linux (64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other (64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other CentOS (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other CentOS (64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other Ubuntu (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other Ubuntu (64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other SUSE Linux(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other SUSE Linux(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other PV (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer600GuestOsMemoryMap.put("Other PV (64-bit)", new MemoryValues(512l, 16*1024l)); + } + + static { + XenServer602GuestOsMap.put("CentOS 4.5 (32-bit)", "CentOS 4.5 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 4.6 (32-bit)", "CentOS 4.6 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 4.7 (32-bit)", "CentOS 4.7 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 4.8 (32-bit)", "CentOS 4.8 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 5.0 (32-bit)", "CentOS 5 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 5.0 (64-bit)", "CentOS 5 (64-bit)"); + XenServer602GuestOsMap.put("CentOS 5.1 (32-bit)", "CentOS 5 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 5.1 (64-bit)", "CentOS 5 (64-bit)"); + XenServer602GuestOsMap.put("CentOS 5.2 (32-bit)", "CentOS 5 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 5.2 (64-bit)", "CentOS 5 (64-bit)"); + XenServer602GuestOsMap.put("CentOS 5.3 (32-bit)", "CentOS 5 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 5.3 (64-bit)", "CentOS 5 (64-bit)"); + XenServer602GuestOsMap.put("CentOS 5.4 (32-bit)", "CentOS 5 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 5.4 (64-bit)", "CentOS 5 (64-bit)"); + XenServer602GuestOsMap.put("CentOS 5.5 (32-bit)", "CentOS 5 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 5.5 (64-bit)", "CentOS 5 (64-bit)"); + XenServer602GuestOsMap.put("CentOS 5.6 (32-bit)", "CentOS 5 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 5.6 (64-bit)", "CentOS 5 (64-bit)"); + XenServer602GuestOsMap.put("CentOS 5.7 (32-bit)", "CentOS 5 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 5.7 (64-bit)", "CentOS 5 (64-bit)"); + XenServer602GuestOsMap.put("CentOS 6.0 (32-bit)", "CentOS 6.0 (32-bit)"); + XenServer602GuestOsMap.put("CentOS 6.0 (64-bit)", "CentOS 6.0 (64-bit)"); + XenServer602GuestOsMap.put("Debian GNU/Linux 5.0 (32-bit)", "Debian Lenny 5.0 (32-bit)"); + XenServer602GuestOsMap.put("Debian GNU/Linux 6(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + XenServer602GuestOsMap.put("Debian GNU/Linux 6(64-bit)", "Debian Squeeze 6.0 (64-bit)"); + XenServer602GuestOsMap.put("Debian GNU/Linux 7(32-bit)", "Debian Squeeze 6.0 (32-bit)"); // This is to support Debian 7.0 in XS 6.0.2 + XenServer602GuestOsMap.put("Debian GNU/Linux 7(64-bit)", "Debian Squeeze 6.0 (64-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.0 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.0 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.1 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.1 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.2 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.2 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.3 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.3 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.4 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.4 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.5 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.5 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.6 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.6 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.7 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 5.7 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 6.0 (32-bit)", "Oracle Enterprise Linux 6.0 (32-bit)"); + XenServer602GuestOsMap.put("Oracle Enterprise Linux 6.0 (64-bit)", "Oracle Enterprise Linux 6.0 (64-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", "Red Hat Enterprise Linux 4.5 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", "Red Hat Enterprise Linux 4.6 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", "Red Hat Enterprise Linux 4.7 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", "Red Hat Enterprise Linux 4.8 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", "Red Hat Enterprise Linux 6.0 (32-bit)"); + XenServer602GuestOsMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", "Red Hat Enterprise Linux 6.0 (64-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", "SUSE Linux Enterprise Server 10 SP1 (32-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", "SUSE Linux Enterprise Server 10 SP1 (32-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", "SUSE Linux Enterprise Server 10 SP1 (64-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", "SUSE Linux Enterprise Server 10 SP2 (32-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", "SUSE Linux Enterprise Server 10 SP2 (64-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", "SUSE Linux Enterprise Server 10 SP3 (32-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", "SUSE Linux Enterprise Server 10 SP3 (64-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", "SUSE Linux Enterprise Server 10 SP4 (32-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", "SUSE Linux Enterprise Server 10 SP4 (64-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 11 (32-bit)", "SUSE Linux Enterprise Server 11 (32-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 11 (64-bit)", "SUSE Linux Enterprise Server 11 (64-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", "SUSE Linux Enterprise Server 11 SP1 (32-bit)"); + XenServer602GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", "SUSE Linux Enterprise Server 11 SP1 (64-bit)"); + XenServer602GuestOsMap.put("Windows 7 (32-bit)", "Windows 7 (32-bit)"); + XenServer602GuestOsMap.put("Windows 7 (64-bit)", "Windows 7 (64-bit)"); + XenServer602GuestOsMap.put("Windows 8 (32-bit)", "Windows 8 (32-bit) (experimental)"); + XenServer602GuestOsMap.put("Windows 8 (64-bit)", "Windows 8 (64-bit) (experimental)"); + XenServer602GuestOsMap.put("Windows Server 2003 (32-bit)", "Windows Server 2003 (32-bit)"); + XenServer602GuestOsMap.put("Windows Server 2003 (64-bit)", "Windows Server 2003 (64-bit)"); + XenServer602GuestOsMap.put("Windows Server 2003 PAE (32-bit)", "Windows Server 2003 PAE (32-bit)"); + XenServer602GuestOsMap.put("Windows Server 2003 Enterprise Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer602GuestOsMap.put("Windows Server 2003 Enterprise Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer602GuestOsMap.put("Windows Server 2003 DataCenter Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer602GuestOsMap.put("Windows Server 2003 DataCenter Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer602GuestOsMap.put("Windows Server 2003 Standard Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer602GuestOsMap.put("Windows Server 2003 Standard Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer602GuestOsMap.put("Windows Server 2008 (32-bit)", "Windows Server 2008 (32-bit)"); + XenServer602GuestOsMap.put("Windows Server 2008 (64-bit)", "Windows Server 2008 (64-bit)"); + XenServer602GuestOsMap.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + XenServer602GuestOsMap.put("Windows Server 8 (64-bit)", "Windows Server 8 (64-bit) (experimental)"); + XenServer602GuestOsMap.put("Windows Vista (32-bit)", "Windows Vista (32-bit)"); + XenServer602GuestOsMap.put("Windows XP SP3 (32-bit)", "Windows XP SP3 (32-bit)"); + XenServer602GuestOsMap.put("Ubuntu 10.04 (32-bit)", "Ubuntu Lucid Lynx 10.04 (32-bit)"); + XenServer602GuestOsMap.put("Ubuntu 10.04 (64-bit)", "Ubuntu Lucid Lynx 10.04 (64-bit)"); + XenServer602GuestOsMap.put("Ubuntu 10.10 (32-bit)", "Ubuntu Maverick Meerkat 10.10 (32-bit) (experimental)"); + XenServer602GuestOsMap.put("Ubuntu 10.10 (64-bit)", "Ubuntu Maverick Meerkat 10.10 (64-bit) (experimental)"); + XenServer602GuestOsMap.put("Other Linux (32-bit)", "Other install media"); + XenServer602GuestOsMap.put("Other Linux (64-bit)", "Other install media"); + XenServer602GuestOsMap.put("Other (32-bit)", "Other install media"); + XenServer602GuestOsMap.put("Other (64-bit)", "Other install media"); + XenServer602GuestOsMap.put("Other CentOS (32-bit)", "Other install media"); + XenServer602GuestOsMap.put("Other CentOS (64-bit)", "Other install media"); + XenServer602GuestOsMap.put("Other Ubuntu (32-bit)", "Other install media"); + XenServer602GuestOsMap.put("Other Ubuntu (64-bit)", "Other install media"); + XenServer602GuestOsMap.put("Other SUSE Linux(32-bit)", "Other install media"); + XenServer602GuestOsMap.put("Other SUSE Linux(64-bit)", "Other install media"); + XenServer602GuestOsMap.put("Other PV (32-bit)", "CentOS 5 (32-bit)"); + XenServer602GuestOsMap.put("Other PV (64-bit)", "CentOS 5 (64-bit)"); + } + + static { + XenServer602GuestOsMemoryMap.put("CentOS 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("CentOS 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("Debian GNU/Linux 5.0 (32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("Debian GNU/Linux 6(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("Debian GNU/Linux 6(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("Debian GNU/Linux 7(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("Debian GNU/Linux 7(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + // XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", new MemoryValues(512l, 16*1024l));// ?? + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + //_xenServer602GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", new MemoryValues(512l, 128*1024l)); //? + //_xenServer602GuestOsMemoryMap.put("Windows 7 (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer602GuestOsMemoryMap.put("Windows 7 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer602GuestOsMemoryMap.put("Windows 8 (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer602GuestOsMemoryMap.put("Windows 8 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer602GuestOsMemoryMap.put("Windows Server 2003 (32-bit)", new MemoryValues(256l, 64*1024l)); + //_xenServer602GuestOsMemoryMap.put("Windows Server 2003 (64-bit)", new MemoryValues(256l, 128*1024l)); + //_xenServer602GuestOsMemoryMap.put("Windows Server 2003 PAE (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer602GuestOsMemoryMap.put("Windows Server 2003 Enterprise Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer602GuestOsMemoryMap.put("Windows Server 2003 Enterprise Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer602GuestOsMemoryMap.put("Windows Server 2003 DataCenter Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer602GuestOsMemoryMap.put("Windows Server 2003 DataCenter Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer602GuestOsMemoryMap.put("Windows Server 2003 Standard Edition(32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer602GuestOsMemoryMap.put("Windows Server 2003 Standard Edition(64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer602GuestOsMemoryMap.put("Windows Server 2008 (32-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer602GuestOsMemoryMap.put("Windows Server 2008 (64-bit)", new MemoryValues(512l, 16*1024l)); + XenServer602GuestOsMemoryMap.put("Windows Server 2008 R2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Windows Server 2012 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Windows Server 8 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Windows Vista (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Windows XP SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer602GuestOsMemoryMap.put("Ubuntu 10.04 (32-bit)", new MemoryValues(128l, 512l)); + XenServer602GuestOsMemoryMap.put("Ubuntu 10.04 (64-bit)", new MemoryValues(128l, 32 * 1024l)); + //_xenServer602GuestOsMemoryMap.put("Ubuntu 10.10 (32-bit)", new MemoryValues(512l, 16*1024l));//? + //_xenServer602GuestOsMemoryMap.put("Ubuntu 10.10 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + XenServer602GuestOsMemoryMap.put("Ubuntu 12.04 (32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer602GuestOsMemoryMap.put("Ubuntu 12.04 (64-bit)", new MemoryValues(128l, 128 * 1024l)); + // XenServer602GuestOsMemoryMap.put("Other Linux (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other Linux (64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other (64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other CentOS (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other CentOS (64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other Ubuntu (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other Ubuntu (64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other SUSE Linux(32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other SUSE Linux(64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other PV (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer602GuestOsMemoryMap.put("Other PV (64-bit)", new MemoryValues(512l, 16*1024l)); + } + + static { + XenServer610GuestOsMap.put("CentOS 4.5 (32-bit)", "CentOS 4.5 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 4.6 (32-bit)", "CentOS 4.6 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 4.7 (32-bit)", "CentOS 4.7 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 4.8 (32-bit)", "CentOS 4.8 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 5.0 (32-bit)", "CentOS 5 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 5.0 (64-bit)", "CentOS 5 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 5.1 (32-bit)", "CentOS 5 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 5.1 (64-bit)", "CentOS 5 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 5.2 (32-bit)", "CentOS 5 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 5.2 (64-bit)", "CentOS 5 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 5.3 (32-bit)", "CentOS 5 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 5.3 (64-bit)", "CentOS 5 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 5.4 (32-bit)", "CentOS 5 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 5.4 (64-bit)", "CentOS 5 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 5.5 (32-bit)", "CentOS 5 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 5.5 (64-bit)", "CentOS 5 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 5.6 (32-bit)", "CentOS 5 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 5.6 (64-bit)", "CentOS 5 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 5.7 (32-bit)", "CentOS 5 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 5.7 (64-bit)", "CentOS 5 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 6.0 (32-bit)", "CentOS 6 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 6.0 (64-bit)", "CentOS 6 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 6.1 (32-bit)", "CentOS 6 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 6.1 (64-bit)", "CentOS 6 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 6.2 (32-bit)", "CentOS 6 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 6.2 (64-bit)", "CentOS 6 (64-bit)"); + XenServer610GuestOsMap.put("CentOS 6.3 (32-bit)", "CentOS 6 (32-bit)"); + XenServer610GuestOsMap.put("CentOS 6.3 (64-bit)", "CentOS 6 (64-bit)"); + XenServer610GuestOsMap.put("Debian GNU/Linux 6(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + XenServer610GuestOsMap.put("Debian GNU/Linux 6(64-bit)", "Debian Squeeze 6.0 (64-bit)"); + XenServer610GuestOsMap.put("Debian GNU/Linux 7(32-bit)", "Debian Squeeze 6.0 (32-bit)"); // This is to support Debian 7.0 in XS 6.1 + XenServer610GuestOsMap.put("Debian GNU/Linux 7(64-bit)", "Debian Squeeze 6.0 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.0 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.0 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.1 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.1 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.2 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.2 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.3 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.3 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.4 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.4 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.5 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.5 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.6 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.6 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.7 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 5.7 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 6.0 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 6.0 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 6.1 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 6.1 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 6.2 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer610GuestOsMap.put("Oracle Enterprise Linux 6.2 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", "Red Hat Enterprise Linux 4.5 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", "Red Hat Enterprise Linux 4.6 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", "Red Hat Enterprise Linux 4.7 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", "Red Hat Enterprise Linux 4.8 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer610GuestOsMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", "SUSE Linux Enterprise Server 10 SP1 (32-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", "SUSE Linux Enterprise Server 10 SP1 (32-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", "SUSE Linux Enterprise Server 10 SP1 (64-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", "SUSE Linux Enterprise Server 10 SP2 (32-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", "SUSE Linux Enterprise Server 10 SP2 (64-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", "SUSE Linux Enterprise Server 10 SP3 (32-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", "SUSE Linux Enterprise Server 10 SP3 (64-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", "SUSE Linux Enterprise Server 10 SP4 (32-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", "SUSE Linux Enterprise Server 10 SP4 (64-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 11 (32-bit)", "SUSE Linux Enterprise Server 11 (32-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 11 (64-bit)", "SUSE Linux Enterprise Server 11 (64-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", "SUSE Linux Enterprise Server 11 SP1 (32-bit)"); + XenServer610GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", "SUSE Linux Enterprise Server 11 SP1 (64-bit)"); + XenServer610GuestOsMap.put("Windows 7 (32-bit)", "Windows 7 (32-bit)"); + XenServer610GuestOsMap.put("Windows 7 (64-bit)", "Windows 7 (64-bit)"); + XenServer610GuestOsMap.put("Windows 8 (32-bit)", "Windows 8 (32-bit) (experimental)"); + XenServer610GuestOsMap.put("Windows 8 (64-bit)", "Windows 8 (64-bit) (experimental)"); + XenServer610GuestOsMap.put("Windows Server 2003 (32-bit)", "Windows Server 2003 (32-bit)"); + XenServer610GuestOsMap.put("Windows Server 2003 (64-bit)", "Windows Server 2003 (64-bit)"); + XenServer610GuestOsMap.put("Windows Server 2003 PAE (32-bit)", "Windows Server 2003 PAE (32-bit)"); + XenServer610GuestOsMap.put("Windows Server 2003 Enterprise Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer610GuestOsMap.put("Windows Server 2003 Enterprise Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer610GuestOsMap.put("Windows Server 2003 DataCenter Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer610GuestOsMap.put("Windows Server 2003 DataCenter Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer610GuestOsMap.put("Windows Server 2003 Standard Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer610GuestOsMap.put("Windows Server 2003 Standard Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer610GuestOsMap.put("Windows Server 2008 (32-bit)", "Windows Server 2008 (32-bit)"); + XenServer610GuestOsMap.put("Windows Server 2008 (64-bit)", "Windows Server 2008 (64-bit)"); + XenServer610GuestOsMap.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + XenServer610GuestOsMap.put("Windows Server 2012 (64-bit)", "Windows Server 2012 (64-bit) (experimental)"); + XenServer610GuestOsMap.put("Windows Server 8 (64-bit)", "Windows Server 2012 (64-bit) (experimental)"); + XenServer610GuestOsMap.put("Windows Vista (32-bit)", "Windows Vista (32-bit)"); + XenServer610GuestOsMap.put("Windows XP SP3 (32-bit)", "Windows XP SP3 (32-bit)"); + XenServer610GuestOsMap.put("Ubuntu 10.04 (32-bit)", "Ubuntu Lucid Lynx 10.04 (32-bit)"); + XenServer610GuestOsMap.put("Ubuntu 10.04 (64-bit)", "Ubuntu Lucid Lynx 10.04 (64-bit)"); + XenServer610GuestOsMap.put("Ubuntu 10.10 (32-bit)", "Ubuntu Maverick Meerkat 10.10 (32-bit) (experimental)"); + XenServer610GuestOsMap.put("Ubuntu 10.10 (64-bit)", "Ubuntu Maverick Meerkat 10.10 (64-bit) (experimental)"); + XenServer610GuestOsMap.put("Ubuntu 12.04 (32-bit)", "Ubuntu Precise Pangolin 12.04 (32-bit)"); + XenServer610GuestOsMap.put("Ubuntu 12.04 (64-bit)", "Ubuntu Precise Pangolin 12.04 (64-bit)"); + XenServer610GuestOsMap.put("Ubuntu 11.04 (32-bit)", "Other install media"); + XenServer610GuestOsMap.put("Ubuntu 11.04 (64-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other Linux (32-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other Linux (64-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other (32-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other (64-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other CentOS (32-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other CentOS (64-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other Ubuntu (32-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other Ubuntu (64-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other SUSE Linux(32-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other SUSE Linux(64-bit)", "Other install media"); + XenServer610GuestOsMap.put("Other PV (32-bit)", "CentOS 5 (32-bit)"); + XenServer610GuestOsMap.put("Other PV (64-bit)", "CentOS 5 (64-bit)"); + } + + static { + XenServer620GuestOsMap.put("CentOS 4.5 (32-bit)", "CentOS 4.5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 4.6 (32-bit)", "CentOS 4.6 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 4.7 (32-bit)", "CentOS 4.7 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 4.8 (32-bit)", "CentOS 4.8 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.0 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.0 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 5.1 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.1 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 5.2 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.2 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 5.3 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.3 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 5.4 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.4 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 5.5 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.5 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 5.6 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.6 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 5.7 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.7 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 5.8 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.8 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 5.9 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 5.9 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 6.0 (32-bit)", "CentOS 6 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 6.0 (64-bit)", "CentOS 6 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 6.1 (32-bit)", "CentOS 6 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 6.1 (64-bit)", "CentOS 6 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 6.2 (32-bit)", "CentOS 6 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 6.2 (64-bit)", "CentOS 6 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 6.3 (32-bit)", "CentOS 6 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 6.3 (64-bit)", "CentOS 6 (64-bit)"); + XenServer620GuestOsMap.put("CentOS 6.4 (32-bit)", "CentOS 6 (32-bit)"); + XenServer620GuestOsMap.put("CentOS 6.4 (64-bit)", "CentOS 6 (64-bit)"); + XenServer620GuestOsMap.put("Debian GNU/Linux 6(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + XenServer620GuestOsMap.put("Debian GNU/Linux 6(64-bit)", "Debian Squeeze 6.0 (64-bit)"); + XenServer620GuestOsMap.put("Debian GNU/Linux 7(32-bit)", "Debian Wheezy 7.0 (32-bit)"); + XenServer620GuestOsMap.put("Debian GNU/Linux 7(64-bit)", "Debian Wheezy 7.0 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.0 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.0 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.1 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.1 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.2 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.2 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.3 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.3 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.4 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.4 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.5 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.5 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.6 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.6 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.7 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.7 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.8 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.8 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.9 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 5.9 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 6.0 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 6.0 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 6.1 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 6.1 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 6.2 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 6.2 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 6.3 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 6.3 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 6.4 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer620GuestOsMap.put("Oracle Enterprise Linux 6.4 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", "Red Hat Enterprise Linux 4.5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", "Red Hat Enterprise Linux 4.6 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", "Red Hat Enterprise Linux 4.7 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", "Red Hat Enterprise Linux 4.8 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.8 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.8 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.9 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 5.9 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 6.3 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 6.3 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 6.4 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer620GuestOsMap.put("Red Hat Enterprise Linux 6.4 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", "SUSE Linux Enterprise Server 10 SP1 (32-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", "SUSE Linux Enterprise Server 10 SP1 (64-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", "SUSE Linux Enterprise Server 10 SP2 (32-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", "SUSE Linux Enterprise Server 10 SP2 (64-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", "SUSE Linux Enterprise Server 10 SP3 (32-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", "SUSE Linux Enterprise Server 10 SP3 (64-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", "SUSE Linux Enterprise Server 10 SP4 (32-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", "SUSE Linux Enterprise Server 10 SP4 (64-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 11 (32-bit)", "SUSE Linux Enterprise Server 11 (32-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 11 (64-bit)", "SUSE Linux Enterprise Server 11 (64-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", "SUSE Linux Enterprise Server 11 SP1 (32-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", "SUSE Linux Enterprise Server 11 SP1 (64-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 11 SP2 (32-bit)", "SUSE Linux Enterprise Server 11 SP2 (32-bit)"); + XenServer620GuestOsMap.put("SUSE Linux Enterprise Server 11 SP2 (64-bit)", "SUSE Linux Enterprise Server 11 SP2 (64-bit)"); + XenServer620GuestOsMap.put("Windows 7 (32-bit)", "Windows 7 (32-bit)"); + XenServer620GuestOsMap.put("Windows 7 (64-bit)", "Windows 7 (64-bit)"); + XenServer620GuestOsMap.put("Windows 7 SP1 (32-bit)", "Windows 7 SP1 (32-bit)"); + XenServer620GuestOsMap.put("Windows 7 SP1 (64-bit)", "Windows 7 SP1 (64-bit)"); + XenServer620GuestOsMap.put("Windows 8 (32-bit)", "Windows 8 (32-bit)"); + XenServer620GuestOsMap.put("Windows 8 (64-bit)", "Windows 8 (64-bit)"); + XenServer620GuestOsMap.put("Windows Server 2003 SP2 (32-bit)", "Windows Server 2003 SP2 (32-bit)"); + XenServer620GuestOsMap.put("Windows Server 2003 SP2 (64-bit)", "Windows Server 2003 SP2 (64-bit)"); + XenServer620GuestOsMap.put("Windows Server 2003 PAE (32-bit)", "Windows Server 2003 PAE (32-bit)"); + XenServer620GuestOsMap.put("Windows Server 2003 Enterprise Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer620GuestOsMap.put("Windows Server 2003 Enterprise Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer620GuestOsMap.put("Windows Server 2003 DataCenter Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer620GuestOsMap.put("Windows Server 2003 DataCenter Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer620GuestOsMap.put("Windows Server 2003 Standard Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer620GuestOsMap.put("Windows Server 2003 Standard Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer620GuestOsMap.put("Windows Server 2008 SP2 (32-bit)", "Windows Server 2008 SP2 (32-bit)"); + XenServer620GuestOsMap.put("Windows Server 2008 SP2 (64-bit)", "Windows Server 2008 SP2 (64-bit)"); + XenServer620GuestOsMap.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + XenServer620GuestOsMap.put("Windows Server 2008 R2 SP1 (64-bit)", "Windows Server 2008 R2 SP1 (64-bit)"); + XenServer620GuestOsMap.put("Windows Server 2012 (64-bit)", "Windows Server 2012 (64-bit)"); + XenServer620GuestOsMap.put("Windows Vista SP2 (32-bit)", "Windows Vista (32-bit)"); + XenServer620GuestOsMap.put("Windows XP SP3 (32-bit)", "Windows XP SP3 (32-bit)"); + XenServer620GuestOsMap.put("Ubuntu 10.04 (32-bit)", "Ubuntu Lucid Lynx 10.04 (32-bit)"); + XenServer620GuestOsMap.put("Ubuntu 10.04 (64-bit)", "Ubuntu Lucid Lynx 10.04 (64-bit)"); + XenServer620GuestOsMap.put("Ubuntu 10.10 (32-bit)", "Ubuntu Maverick Meerkat 10.10 (32-bit) (experimental)"); + XenServer620GuestOsMap.put("Ubuntu 10.10 (64-bit)", "Ubuntu Maverick Meerkat 10.10 (64-bit) (experimental)"); + XenServer620GuestOsMap.put("Ubuntu 12.04 (32-bit)", "Ubuntu Precise Pangolin 12.04 (32-bit)"); + XenServer620GuestOsMap.put("Ubuntu 12.04 (64-bit)", "Ubuntu Precise Pangolin 12.04 (64-bit)"); + XenServer620GuestOsMap.put("Ubuntu 11.04 (32-bit)", "Other install media"); + XenServer620GuestOsMap.put("Ubuntu 11.04 (64-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other Linux (32-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other Linux (64-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other (32-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other (64-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other CentOS (32-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other CentOS (64-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other Ubuntu (32-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other Ubuntu (64-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other SUSE Linux(32-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other SUSE Linux(64-bit)", "Other install media"); + XenServer620GuestOsMap.put("Other PV (32-bit)", "CentOS 5 (32-bit)"); + XenServer620GuestOsMap.put("Other PV (64-bit)", "CentOS 5 (64-bit)"); + } + + static { + XenServer620SP1GuestOsMap.put("CentOS 4.5 (32-bit)", "CentOS 4.5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 4.6 (32-bit)", "CentOS 4.6 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 4.7 (32-bit)", "CentOS 4.7 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 4.8 (32-bit)", "CentOS 4.8 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.0 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.0 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.1 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.1 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.2 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.2 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.3 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.3 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.4 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.4 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.5 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.5 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.6 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.6 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.7 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.7 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.8 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.8 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.9 (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 5.9 (64-bit)", "CentOS 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 6.0 (32-bit)", "CentOS 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 6.0 (64-bit)", "CentOS 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 6.1 (32-bit)", "CentOS 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 6.1 (64-bit)", "CentOS 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 6.2 (32-bit)", "CentOS 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 6.2 (64-bit)", "CentOS 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 6.3 (32-bit)", "CentOS 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 6.3 (64-bit)", "CentOS 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 6.4 (32-bit)", "CentOS 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("CentOS 6.4 (64-bit)", "CentOS 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("Debian GNU/Linux 6(32-bit)", "Debian Squeeze 6.0 (32-bit)"); + XenServer620SP1GuestOsMap.put("Debian GNU/Linux 6(64-bit)", "Debian Squeeze 6.0 (64-bit)"); + XenServer620SP1GuestOsMap.put("Debian GNU/Linux 7(32-bit)", "Debian Wheezy 7.0 (32-bit)"); + XenServer620SP1GuestOsMap.put("Debian GNU/Linux 7(64-bit)", "Debian Wheezy 7.0 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.0 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.0 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.1 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.1 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.2 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.2 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.3 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.3 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.4 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.4 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.5 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.5 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.6 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.6 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.7 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.7 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.8 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.8 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.9 (32-bit)", "Oracle Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 5.9 (64-bit)", "Oracle Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 6.0 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 6.0 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 6.1 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 6.1 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 6.2 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 6.2 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 6.3 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 6.3 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 6.4 (32-bit)", "Oracle Enterprise Linux 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Oracle Enterprise Linux 6.4 (64-bit)", "Oracle Enterprise Linux 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", "Red Hat Enterprise Linux 4.5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", "Red Hat Enterprise Linux 4.6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", "Red Hat Enterprise Linux 4.7 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", "Red Hat Enterprise Linux 4.8 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.8 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.8 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.9 (32-bit)", "Red Hat Enterprise Linux 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 5.9 (64-bit)", "Red Hat Enterprise Linux 5 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 6.3 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 6.3 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 6.4 (32-bit)", "Red Hat Enterprise Linux 6 (32-bit)"); + XenServer620SP1GuestOsMap.put("Red Hat Enterprise Linux 6.4 (64-bit)", "Red Hat Enterprise Linux 6 (64-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", "SUSE Linux Enterprise Server 10 SP1 (32-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", "SUSE Linux Enterprise Server 10 SP1 (64-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", "SUSE Linux Enterprise Server 10 SP2 (32-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", "SUSE Linux Enterprise Server 10 SP2 (64-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", "SUSE Linux Enterprise Server 10 SP3 (32-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", "SUSE Linux Enterprise Server 10 SP3 (64-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", "SUSE Linux Enterprise Server 10 SP4 (32-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", "SUSE Linux Enterprise Server 10 SP4 (64-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 11 (32-bit)", "SUSE Linux Enterprise Server 11 (32-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 11 (64-bit)", "SUSE Linux Enterprise Server 11 (64-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", "SUSE Linux Enterprise Server 11 SP1 (32-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", "SUSE Linux Enterprise Server 11 SP1 (64-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 11 SP2 (32-bit)", "SUSE Linux Enterprise Server 11 SP2 (32-bit)"); + XenServer620SP1GuestOsMap.put("SUSE Linux Enterprise Server 11 SP2 (64-bit)", "SUSE Linux Enterprise Server 11 SP2 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows 7 (32-bit)", "Windows 7 (32-bit)"); + XenServer620SP1GuestOsMap.put("Windows 7 (64-bit)", "Windows 7 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows 7 SP1 (32-bit)", "Windows 7 (32-bit)"); + XenServer620SP1GuestOsMap.put("Windows 7 SP1 (64-bit)", "Windows 7 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows 8 (32-bit)", "Windows 8 (32-bit)"); + XenServer620SP1GuestOsMap.put("Windows 8 (64-bit)", "Windows 8 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2003 SP2 (32-bit)", "Windows Server 2003 (32-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2003 SP2 (64-bit)", "Windows Server 2003 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2003 PAE (32-bit)", "Windows Server 2003 (32-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2003 Enterprise Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2003 Enterprise Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2003 DataCenter Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2003 DataCenter Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2003 Standard Edition(32-bit)", "Windows Server 2003 (32-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2003 Standard Edition(64-bit)", "Windows Server 2003 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2008 SP2 (32-bit)", "Windows Server 2008 (34-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2008 SP2 (64-bit)", "Windows Server 2008 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2008 R2 SP1 (64-bit)", "Windows Server 2008 R2 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2012 (64-bit)", "Windows Server 2012 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows Server 2012 R2 (64-bit)", "Windows Server 2012 (64-bit)"); + XenServer620SP1GuestOsMap.put("Windows Vista SP2 (32-bit)", "Windows Vista (32-bit)"); + XenServer620SP1GuestOsMap.put("Windows XP SP3 (32-bit)", "Windows XP SP3 (32-bit)"); + XenServer620SP1GuestOsMap.put("Ubuntu 10.04 (32-bit)", "Ubuntu Lucid Lynx 10.04 (32-bit)"); + XenServer620SP1GuestOsMap.put("Ubuntu 10.04 (64-bit)", "Ubuntu Lucid Lynx 10.04 (64-bit)"); + XenServer620SP1GuestOsMap.put("Ubuntu 10.10 (32-bit)", "Ubuntu Maverick Meerkat 10.10 (32-bit) (experimental)"); + XenServer620SP1GuestOsMap.put("Ubuntu 10.10 (64-bit)", "Ubuntu Maverick Meerkat 10.10 (64-bit) (experimental)"); + XenServer620SP1GuestOsMap.put("Ubuntu 12.04 (32-bit)", "Ubuntu Precise Pangolin 12.04 (32-bit)"); + XenServer620SP1GuestOsMap.put("Ubuntu 12.04 (64-bit)", "Ubuntu Precise Pangolin 12.04 (64-bit)"); + XenServer620SP1GuestOsMap.put("Ubuntu 11.04 (32-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Ubuntu 11.04 (64-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other Linux (32-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other Linux (64-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other (32-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other (64-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other CentOS (32-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other CentOS (64-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other Ubuntu (32-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other Ubuntu (64-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other SUSE Linux(32-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other SUSE Linux(64-bit)", "Other install media"); + XenServer620SP1GuestOsMap.put("Other PV (32-bit)", "CentOS 5 (32-bit)"); + XenServer620SP1GuestOsMap.put("Other PV (64-bit)", "CentOS 5 (64-bit)"); + } + + public static class MemoryValues { + long max; + long min; + + public MemoryValues(long min, long max) { + this.min = min * 1024 * 1024; + this.max = max * 1024 * 1024; + } + + public long getMax() { + return max; + } + + public long getMin() { + return min; + } + } + + static { + XenServer610GuestOsMemoryMap.put("CentOS 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("CentOS 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Debian GNU/Linux 6(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("Debian GNU/Linux 6(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("Debian GNU/Linux 7(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("Debian GNU/Linux 7(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 9 SP4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer610GuestOsMemoryMap.put("Windows 7 (32-bit)", new MemoryValues(1024l, 4 * 1024l)); + XenServer610GuestOsMemoryMap.put("Windows 7 (64-bit)", new MemoryValues(2 * 1024l, 128 * 1024l)); + //_xenServer610GuestOsMemoryMap.put("Windows 8 (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows 8 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2003 (32-bit)", new MemoryValues(256l, 64*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2003 (64-bit)", new MemoryValues(256l, 128*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2003 PAE (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2003 Enterprise Edition(32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2003 Enterprise Edition(64-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2003 DataCenter Edition(32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2003 DataCenter Edition(64-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2003 Standard Edition(32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2003 Standard Edition(64-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2008 (32-bit)", new MemoryValues(512l, 16*1024l)); //? + //_xenServer610GuestOsMemoryMap.put("Windows Server 2008 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + XenServer610GuestOsMemoryMap.put("Windows Server 2008 R2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + //_xenServer610GuestOsMemoryMap.put("Windows Server 2012 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + XenServer610GuestOsMemoryMap.put("Windows Server 8 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer610GuestOsMemoryMap.put("Windows Vista (32-bit)", new MemoryValues(1024l, 4 * 1024l)); + XenServer610GuestOsMemoryMap.put("Windows XP SP3 (32-bit)", new MemoryValues(256l, 4 * 1024l)); + XenServer610GuestOsMemoryMap.put("Ubuntu 10.04 (32-bit)", new MemoryValues(128l, 512l)); + XenServer610GuestOsMemoryMap.put("Ubuntu 10.04 (64-bit)", new MemoryValues(128l, 32 * 1024l)); + //_xenServer610GuestOsMemoryMap.put("Ubuntu 10.10 (32-bit)", new MemoryValues(512l, 16*1024l));//? + //_xenServer610GuestOsMemoryMap.put("Ubuntu 10.10 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + XenServer610GuestOsMemoryMap.put("Ubuntu 12.04 (32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer610GuestOsMemoryMap.put("Ubuntu 12.04 (64-bit)", new MemoryValues(128l, 128 * 1024l)); + // XenServer610GuestOsMemoryMap.put("Other Linux (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer610GuestOsMemoryMap.put("Other Linux (64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer610GuestOsMemoryMap.put("Other (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer610GuestOsMemoryMap.put("Other (64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer610GuestOsMemoryMap.put("Other CentOS (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer610GuestOsMemoryMap.put("Other CentOS (64-bit)", new MemoryValues(512l, 16*1024l)); + //_xenServer610GuestOsMemoryMap.put("Other Ubuntu (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer610GuestOsMemoryMap.put("Other Ubuntu (64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer610GuestOsMemoryMap.put("Other SUSE Linux(32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer610GuestOsMemoryMap.put("Other SUSE Linux(64-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer610GuestOsMemoryMap.put("Other PV (32-bit)", new MemoryValues(512l, 16*1024l)); + // XenServer610GuestOsMemoryMap.put("Other PV (64-bit)", new MemoryValues(512l, 16*1024l)); + } + + static { + XenServer620GuestOsMemoryMap.put("CentOS 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.8 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.8 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.9 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 5.9 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 6.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 6.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 6.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("CentOS 6.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Debian GNU/Linux 6(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer620GuestOsMemoryMap.put("Debian GNU/Linux 6(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer620GuestOsMemoryMap.put("Debian GNU/Linux 7(32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Debian GNU/Linux 7(64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.8 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.8 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.9 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 5.9 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 6.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 6.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 6.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Oracle Enterprise Linux 6.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.8 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.8 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.9 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.9 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + + XenServer620GuestOsMemoryMap.put("Windows 7 (32-bit)", new MemoryValues(1024l, 4 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows 7 (64-bit)", new MemoryValues(2 * 1024l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows 7 SP1 (32-bit)", new MemoryValues(1024l, 4 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows 7 SP1 (64-bit)", new MemoryValues(2 * 1024l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows 8 (32-bit)", new MemoryValues(1024l, 4 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows 8 (64-bit)", new MemoryValues(2 * 1024l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows Server 2003 SP2 (32-bit)", new MemoryValues(256l, 64 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows Server 2003 SP2 (64-bit)", new MemoryValues(256l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows Server 2008 SP2 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows Server 2008 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows Server 2008 R2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows Server 2008 R2 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows Server 2012 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows Vista SP2 (32-bit)", new MemoryValues(1024l, 4 * 1024l)); + XenServer620GuestOsMemoryMap.put("Windows XP SP3 (32-bit)", new MemoryValues(256l, 4 * 1024l)); + XenServer620GuestOsMemoryMap.put("Ubuntu 10.04 (32-bit)", new MemoryValues(128l, 512l)); + XenServer620GuestOsMemoryMap.put("Ubuntu 10.04 (64-bit)", new MemoryValues(128l, 32 * 1024l)); + //_xenServer620GuestOsMemoryMap.put("Ubuntu 10.10 (32-bit)", new MemoryValues(512l, 16*1024l));//? + //_xenServer620GuestOsMemoryMap.put("Ubuntu 10.10 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + XenServer620GuestOsMemoryMap.put("Ubuntu 12.04 (32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer620GuestOsMemoryMap.put("Ubuntu 12.04 (64-bit)", new MemoryValues(128l, 128 * 1024l)); + } + + + static { + XenServer620SP1GuestOsMemoryMap.put("CentOS 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.8 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.8 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.9 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 5.9 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 6.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 6.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 6.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("CentOS 6.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Debian GNU/Linux 6(32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Debian GNU/Linux 6(64-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Debian GNU/Linux 7(32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Debian GNU/Linux 7(64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.8 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.8 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.9 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 5.9 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Oracle Enterprise Linux 6.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.5 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.6 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.7 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 4.8 (32-bit)", new MemoryValues(256l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.0 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.1 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.2 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.3 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.4 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.5 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.6 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.7 (64-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.8 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.8 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.9 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 5.9 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.0 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (32-bit)", new MemoryValues(512l, 8 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.1 (64-bit)", new MemoryValues(512l, 32 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Red Hat Enterprise Linux 6.4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP2 (32-bit)", new MemoryValues(512l, 16 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("SUSE Linux Enterprise Server 11 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + + XenServer620SP1GuestOsMemoryMap.put("Windows 7 (32-bit)", new MemoryValues(1024l, 4 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows 7 (64-bit)", new MemoryValues(2 * 1024l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows 7 SP1 (32-bit)", new MemoryValues(1024l, 4 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows 7 SP1 (64-bit)", new MemoryValues(2 * 1024l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows 8 (32-bit)", new MemoryValues(1024l, 4 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows 8 (64-bit)", new MemoryValues(2 * 1024l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows Server 2003 SP2 (32-bit)", new MemoryValues(256l, 64 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows Server 2003 SP2 (64-bit)", new MemoryValues(256l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows Server 2008 SP2 (32-bit)", new MemoryValues(512l, 64 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows Server 2008 SP2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows Server 2008 R2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows Server 2008 R2 SP1 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows Server 2012 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows Server 2012 R2 (64-bit)", new MemoryValues(512l, 128 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows Vista SP2 (32-bit)", new MemoryValues(1024l, 4 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Windows XP SP3 (32-bit)", new MemoryValues(256l, 4 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Ubuntu 10.04 (32-bit)", new MemoryValues(128l, 512l)); + XenServer620SP1GuestOsMemoryMap.put("Ubuntu 10.04 (64-bit)", new MemoryValues(128l, 32 * 1024l)); + //_xenServer620GuestOsMemoryMap.put("Ubuntu 10.10 (32-bit)", new MemoryValues(512l, 16*1024l));//? + //_xenServer620GuestOsMemoryMap.put("Ubuntu 10.10 (64-bit)", new MemoryValues(512l, 16*1024l)); //? + XenServer620SP1GuestOsMemoryMap.put("Ubuntu 12.04 (32-bit)", new MemoryValues(128l, 32 * 1024l)); + XenServer620SP1GuestOsMemoryMap.put("Ubuntu 12.04 (64-bit)", new MemoryValues(128l, 128 * 1024l)); + } + + + public static String getXcpGuestOsType(String stdType) { + String guestOS = Xcp100GuestOsMap.get(stdType); + if (guestOS == null) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XCP's guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } + return guestOS; + } + + public static String getXcp160GuestOsType(String stdType) { + String guestOS = Xcp160GuestOsMap.get(stdType); + if (guestOS == null) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XCP's guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } + return guestOS; + } + + public static String getXenServerGuestOsType(String stdType, boolean bootFromCD) { + String guestOS = XenServerGuestOsMap.get(stdType); + if (guestOS == null) { + if (!bootFromCD) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XenServer 5.6 guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } else { + String msg = "XenServer 5.6 doesn't support Guest OS type " + stdType; + s_logger.warn(msg); + } + } + return guestOS; + } + + public static String getXenServer56FP1GuestOsType(String stdType, boolean bootFromCD) { + String guestOS = XenServer56FP1GuestOsMap.get(stdType); + if (guestOS == null) { + if (!bootFromCD) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XenServer 5.6 FP1 guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } else { + String msg = "XenServer 5.6 FP1 DOES NOT support Guest OS type " + stdType; + s_logger.warn(msg); + } + } + return guestOS; + } + + public static long getXenServer56FP1StaticMax(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer56FP1GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMax(); + } + + public static long getXenServer56FP1StaticMin(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer56FP1GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMin(); + } + + public static String getXenServer56SP2GuestOsType(String stdType, boolean bootFromCD) { + String guestOS = XenServer56FP2GuestOsMap.get(stdType); + if (guestOS == null) { + if (!bootFromCD) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XenServer 5.6 SP2 guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } else { + String msg = "XenServer 5.6 SP2 DOES NOT support Guest OS type " + stdType; + s_logger.warn(msg); + } + } + return guestOS; + } + + public static long getXenServer56SP2StaticMax(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer56SP2GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMax(); + } + + public static long getXenServer56SP2StaticMin(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer56SP2GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMin(); + } + + public static String getXenServer600GuestOsType(String stdType, boolean bootFromCD) { + String guestOS = XenServer600GuestOsMap.get(stdType); + if (guestOS == null) { + if (!bootFromCD) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XenServer 6.0.2 guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } else { + String msg = "XenServer 6.0.2 DOES NOT support Guest OS type " + stdType; + s_logger.warn(msg); + } + + } + return guestOS; + } + + public static long getXenServer600StaticMax(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer600GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMax(); + } + + public static long getXenServer600StaticMin(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer600GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMin(); + } + + public static String getXenServer602GuestOsType(String stdType, boolean bootFromCD) { + String guestOS = XenServer602GuestOsMap.get(stdType); + if (guestOS == null) { + if (!bootFromCD) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XenServer 6.0.2 guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } else { + String msg = "XenServer 6.0.2 DOES NOT support Guest OS type " + stdType; + s_logger.warn(msg); + } + + } + return guestOS; + } + + public static long getXenServer602StaticMax(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer602GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMax(); + } + + public static long getXenServer602StaticMin(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer602GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMin(); + } + + public static String getXenServer610GuestOsType(String stdType, boolean bootFromCD) { + String guestOS = XenServer610GuestOsMap.get(stdType); + if (guestOS == null) { + if (!bootFromCD) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XenServer 6.1.0 guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } else { + String msg = "XenServer 6.1.0 DOES NOT support Guest OS type " + stdType; + s_logger.warn(msg); + } + } + return guestOS; + } + + public static long getXenServer610StaticMax(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer610GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMax(); + } + + public static long getXenServer610StaticMin(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer610GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMin(); + } + + public static String getXenServer620GuestOsType(String stdType, boolean bootFromCD) { + String guestOS = XenServer620GuestOsMap.get(stdType); + if (guestOS == null) { + if (!bootFromCD) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XenServer 6.2.0 guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } else { + String msg = "XenServer 6.2.0 DOES NOT support Guest OS type " + stdType; + s_logger.warn(msg); + } + } + return guestOS; + } + + public static String getXenServer620SP1GuestOsType(String stdType, boolean bootFromCD) { + String guestOS = XenServer620SP1GuestOsMap.get(stdType); + if (guestOS == null) { + if (!bootFromCD) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XenServer 6.2.0 SP1 guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } else { + String msg = "XenServer 6.2.0 SP1 DOES NOT support Guest OS type " + stdType; + s_logger.warn(msg); + } + } + return guestOS; + } + + public static String getXenServer625GuestOsType(String stdType, boolean bootFromCD) { + String guestOS = XenServer620SP1GuestOsMap.get(stdType); + if (guestOS == null) { + if (!bootFromCD) { + s_logger.debug("Can't find the guest os: " + stdType + " mapping into XenServer 6.2.5 guestOS type, start it as HVM guest"); + guestOS = "Other install media"; + } else { + String msg = "XenServer 6.2.5 DOES NOT support Guest OS type " + stdType; + s_logger.warn(msg); + } + } + return guestOS; + } + + public static long getXenServer620StaticMax(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer620GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMax(); + } + + public static long getXenServer620StaticMin(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer620GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMin(); + } + + public static long getXenServer620SP1StaticMax(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer620SP1GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMax(); + } + + public static long getXenServer620SP1StaticMin(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer620SP1GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMin(); + } + + public static long getXenServer625StaticMax(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer620SP1GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMax(); + } + + public static long getXenServer625StaticMin(String stdType, boolean bootFromCD) { + MemoryValues recommendedMaxMinMemory = XenServer620SP1GuestOsMemoryMap.get(stdType); + if (recommendedMaxMinMemory == null) { + return 0l; + } + return recommendedMaxMinMemory.getMin(); + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java new file mode 100644 index 00000000000..4213508f712 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -0,0 +1,7553 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; + +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.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.CheckVirtualMachineAnswer; +import com.cloud.agent.api.CheckVirtualMachineCommand; +import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.agent.api.ClusterSyncAnswer; +import com.cloud.agent.api.ClusterSyncCommand; +import com.cloud.agent.api.ClusterVMMetaDataSyncAnswer; +import com.cloud.agent.api.ClusterVMMetaDataSyncCommand; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.CreateVMSnapshotAnswer; +import com.cloud.agent.api.CreateVMSnapshotCommand; +import com.cloud.agent.api.DeleteStoragePoolCommand; +import com.cloud.agent.api.DeleteVMSnapshotAnswer; +import com.cloud.agent.api.DeleteVMSnapshotCommand; +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.GetVmDiskStatsAnswer; +import com.cloud.agent.api.GetVmDiskStatsCommand; +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.HostVmStateReportEntry; +import com.cloud.agent.api.MaintainAnswer; +import com.cloud.agent.api.MaintainCommand; +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.NetworkRulesSystemVmCommand; +import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand; +import com.cloud.agent.api.OvsCreateGreTunnelAnswer; +import com.cloud.agent.api.OvsCreateGreTunnelCommand; +import com.cloud.agent.api.OvsCreateTunnelAnswer; +import com.cloud.agent.api.OvsCreateTunnelCommand; +import com.cloud.agent.api.OvsDeleteFlowCommand; +import com.cloud.agent.api.OvsDestroyBridgeCommand; +import com.cloud.agent.api.OvsDestroyTunnelCommand; +import com.cloud.agent.api.OvsFetchInterfaceAnswer; +import com.cloud.agent.api.OvsFetchInterfaceCommand; +import com.cloud.agent.api.OvsSetTagAndFlowAnswer; +import com.cloud.agent.api.OvsSetTagAndFlowCommand; +import com.cloud.agent.api.OvsSetupBridgeCommand; +import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand; +import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand; +import com.cloud.agent.api.PerformanceMonitorAnswer; +import com.cloud.agent.api.PerformanceMonitorCommand; +import com.cloud.agent.api.PingCommand; +import com.cloud.agent.api.PingRoutingCommand; +import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; +import com.cloud.agent.api.PingRoutingWithOvsCommand; +import com.cloud.agent.api.PingTestCommand; +import com.cloud.agent.api.PlugNicAnswer; +import com.cloud.agent.api.PlugNicCommand; +import com.cloud.agent.api.PrepareForMigrationAnswer; +import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.PvlanSetupCommand; +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.RevertToVMSnapshotAnswer; +import com.cloud.agent.api.RevertToVMSnapshotCommand; +import com.cloud.agent.api.ScaleVmAnswer; +import com.cloud.agent.api.ScaleVmCommand; +import com.cloud.agent.api.SecurityGroupRuleAnswer; +import com.cloud.agent.api.SecurityGroupRulesCmd; +import com.cloud.agent.api.SetupAnswer; +import com.cloud.agent.api.SetupCommand; +import com.cloud.agent.api.SetupGuestNetworkCommand; +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.UnPlugNicAnswer; +import com.cloud.agent.api.UnPlugNicCommand; +import com.cloud.agent.api.UpdateHostPasswordCommand; +import com.cloud.agent.api.UpgradeSnapshotCommand; +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.proxy.CheckConsoleProxyLoadCommand; +import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer; +import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; +import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.IpAssocVpcCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.SetNetworkACLCommand; +import com.cloud.agent.api.routing.SetSourceNatCommand; +import com.cloud.agent.api.storage.CreateAnswer; +import com.cloud.agent.api.storage.CreateCommand; +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.storage.ResizeVolumeAnswer; +import com.cloud.agent.api.storage.ResizeVolumeCommand; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.GPUDeviceTO; +import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.resource.virtualnetwork.VirtualRouterDeployer; +import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; +import com.cloud.exception.InternalErrorException; +import com.cloud.host.Host.Type; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.network.Networks; +import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.IsolationType; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.PhysicalNetworkSetupInfo; +import com.cloud.resource.ServerResource; +import com.cloud.resource.hypervisor.HypervisorResource; +import com.cloud.storage.Storage; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.resource.StorageSubsystemCommandHandler; +import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase; +import com.cloud.storage.template.TemplateProp; +import com.cloud.template.VirtualMachineTemplate.BootloaderType; +import com.cloud.utils.ExecutionResult; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.Pair; +import com.cloud.utils.StringUtils; +import com.cloud.utils.Ternary; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.NetUtils; +import com.cloud.utils.ssh.SSHCmdHelper; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.PowerState; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.snapshot.VMSnapshot; +import com.trilead.ssh2.SCPClient; +import com.xensource.xenapi.Bond; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Console; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.HostCpu; +import com.xensource.xenapi.HostMetrics; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.PBD; +import com.xensource.xenapi.PIF; +import com.xensource.xenapi.Pool; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Session; +import com.xensource.xenapi.Task; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.BadServerResponse; +import com.xensource.xenapi.Types.VmPowerState; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VBDMetrics; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VGPU; +import com.xensource.xenapi.VIF; +import com.xensource.xenapi.VLAN; +import com.xensource.xenapi.VM; +import com.xensource.xenapi.VMGuestMetrics; +import com.xensource.xenapi.XenAPIObject; +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Queue; +import java.util.Random; +import java.util.Set; +import java.util.UUID; + +/** + * CitrixResourceBase encapsulates the calls to the XenServer Xapi process + * to perform the required functionalities for CloudStack. + * + * ==============> READ THIS <============== + * Because the XenServer objects can expire when the session expires, we cannot + * keep any of the actual XenServer objects in this class. The only + * thing that is constant is the UUID of the XenServer objects but not the + * objects themselves! This is very important before you do any changes in + * this code here. + * + */ +@Local(value = ServerResource.class) +public abstract class CitrixResourceBase implements ServerResource, HypervisorResource, VirtualRouterDeployer { + private static final Logger s_logger = Logger.getLogger(CitrixResourceBase.class); + protected static final XenServerConnectionPool ConnPool = XenServerConnectionPool.getInstance(); + protected String _name; + protected String _username; + protected Queue _password = new LinkedList(); + protected final int _retry = 100; + protected final int _sleep = 10000; + protected long _dcId; + protected String _pod; + protected String _cluster; + protected static final XenServerPoolVms s_vms = new XenServerPoolVms(); + protected String _privateNetworkName; + protected String _linkLocalPrivateNetworkName; + protected String _publicNetworkName; + protected String _storageNetworkName1; + protected String _storageNetworkName2; + protected String _guestNetworkName; + protected int _wait; + protected int _migratewait; + protected String _instance; //instance name (default is usually "VM") + static final Random Rand = new Random(System.currentTimeMillis()); + protected boolean _securityGroupEnabled; + + protected IAgentControl _agentControl; + + final int _maxWeight = 256; + protected int _heartbeatInterval = 60; + protected final XsHost _host = new XsHost(); + + // Guest and Host Performance Statistics + protected String _consolidationFunction = "AVERAGE"; + protected int _pollingIntervalInSeconds = 60; + + //Hypervisor specific params with generic value, may need to be overridden for specific versions + long _xsMemoryUsed = 128 * 1024 * 1024L; // xen hypervisor used 128 M + double _xsVirtualizationFactor = 63.0 / 64.0; // 1 - virtualization overhead + + //static min values for guests on xen + private static final long mem_128m = 134217728L; + + protected boolean _canBridgeFirewall = false; + protected boolean _isOvs = false; + protected List _tmpDom0Vif = new ArrayList(); + protected StorageSubsystemCommandHandler storageHandler; + protected int _maxNics = 7; + + protected VirtualRoutingResource _vrResource; + + public enum SRType { + NFS, LVM, ISCSI, ISO, LVMOISCSI, LVMOHBA, EXT, FILE; + + String _str; + + private SRType() { + _str = super.toString().toLowerCase(); + } + + @Override + public String toString() { + return _str; + } + + public boolean equals(String type) { + return _str.equalsIgnoreCase(type); + } + } + + protected static final HashMap s_powerStatesTable; + static { + s_powerStatesTable = new HashMap(); + s_powerStatesTable.put(Types.VmPowerState.HALTED, PowerState.PowerOff); + s_powerStatesTable.put(Types.VmPowerState.PAUSED, PowerState.PowerOff); + s_powerStatesTable.put(Types.VmPowerState.RUNNING, PowerState.PowerOn); + s_powerStatesTable.put(Types.VmPowerState.SUSPENDED, PowerState.PowerOff); + s_powerStatesTable.put(Types.VmPowerState.UNRECOGNIZED, PowerState.PowerUnknown); + } + + // TODO vmsync { + protected static final HashMap s_statesTable; + static { + s_statesTable = new HashMap(); + s_statesTable.put(Types.VmPowerState.HALTED, State.Stopped); + s_statesTable.put(Types.VmPowerState.PAUSED, State.Running); + s_statesTable.put(Types.VmPowerState.RUNNING, State.Running); + s_statesTable.put(Types.VmPowerState.SUSPENDED, State.Running); + s_statesTable.put(Types.VmPowerState.UNRECOGNIZED, State.Unknown); + } + + // TODO vmsync } + + public XsHost getHost() { + return _host; + } + + private static boolean isAlienVm(VM vm, Connection conn) throws XenAPIException, XmlRpcException { + // TODO : we need a better way to tell whether or not the VM belongs to CloudStack + String vmName = vm.getNameLabel(conn); + if (vmName.matches("^[ivs]-\\d+-.+")) + return false; + + return true; + } + + protected boolean cleanupHaltedVms(Connection conn) throws XenAPIException, XmlRpcException { + Host host = Host.getByUuid(conn, _host.uuid); + Map vms = VM.getAllRecords(conn); + boolean success = true; + for (Map.Entry entry : vms.entrySet()) { + VM vm = entry.getKey(); + VM.Record vmRec = entry.getValue(); + if (vmRec.isATemplate || vmRec.isControlDomain) { + continue; + } + + if (VmPowerState.HALTED.equals(vmRec.powerState) && vmRec.affinity.equals(host) && !isAlienVm(vm, conn)) { + try { + vm.destroy(conn); + } catch (Exception e) { + s_logger.warn("Catch Exception " + e.getClass().getName() + ": unable to destroy VM " + vmRec.nameLabel + " due to ", e); + success = false; + } + } + } + return success; + } + + protected boolean isRefNull(XenAPIObject object) { + return (object == null || object.toWireString().equals("OpaqueRef:NULL") || object.toWireString().equals("")); + } + + @Override + public void disconnected() { + } + + protected boolean pingdomr(Connection conn, String host, String port) { + String status; + status = callHostPlugin(conn, "vmops", "pingdomr", "host", host, "port", port); + + if (status == null || status.isEmpty()) { + return false; + } + + return true; + + } + + protected boolean pingXAPI() { + Connection conn = getConnection(); + try { + Host host = Host.getByUuid(conn, _host.uuid); + if( !host.getEnabled(conn) ) { + s_logger.debug("Host " + _host.ip + " is not enabled!"); + return false; + } + } catch (Exception e) { + s_logger.debug("cannot get host enabled status, host " + _host.ip + " due to " + e.toString(), e); + return false; + } + try { + callHostPlugin(conn, "echo", "main"); + } catch (Exception e) { + s_logger.debug("cannot ping host " + _host.ip + " due to " + e.toString(), e); + return false; + } + return true; + } + + + protected String logX(XenAPIObject obj, String msg) { + return new StringBuilder("Host ").append(_host.ip).append(" ").append(obj.toWireString()).append(": ").append(msg).toString(); + } + + @Override + public Answer executeRequest(Command cmd) { + Class clazz = cmd.getClass(); + if (clazz == CreateCommand.class) { + return execute((CreateCommand)cmd); + } else if (cmd instanceof NetworkElementCommand) { + return _vrResource.executeRequest((NetworkElementCommand)cmd); + } else if (clazz == CheckConsoleProxyLoadCommand.class) { + return execute((CheckConsoleProxyLoadCommand)cmd); + } else if (clazz == WatchConsoleProxyLoadCommand.class) { + return execute((WatchConsoleProxyLoadCommand)cmd); + } else if (clazz == ReadyCommand.class) { + return execute((ReadyCommand)cmd); + } else if (clazz == GetHostStatsCommand.class) { + return execute((GetHostStatsCommand)cmd); + } else if (clazz == GetVmStatsCommand.class) { + return execute((GetVmStatsCommand)cmd); + } else if (clazz == GetVmDiskStatsCommand.class) { + return execute((GetVmDiskStatsCommand)cmd); + } else if (clazz == CheckHealthCommand.class) { + return execute((CheckHealthCommand)cmd); + } else if (clazz == StopCommand.class) { + return execute((StopCommand)cmd); + } else if (clazz == RebootRouterCommand.class) { + return execute((RebootRouterCommand)cmd); + } else if (clazz == RebootCommand.class) { + return execute((RebootCommand)cmd); + } else if (clazz == CheckVirtualMachineCommand.class) { + return execute((CheckVirtualMachineCommand)cmd); + } else if (clazz == PrepareForMigrationCommand.class) { + return execute((PrepareForMigrationCommand)cmd); + } else if (clazz == MigrateCommand.class) { + return execute((MigrateCommand)cmd); + } else if (clazz == DestroyCommand.class) { + return execute((DestroyCommand)cmd); + } else if (clazz == CreateStoragePoolCommand.class) { + return execute((CreateStoragePoolCommand)cmd); + } else if (clazz == ModifyStoragePoolCommand.class) { + return execute((ModifyStoragePoolCommand)cmd); + } else if (clazz == DeleteStoragePoolCommand.class) { + return execute((DeleteStoragePoolCommand) cmd); + }else if (clazz == ResizeVolumeCommand.class) { + return execute((ResizeVolumeCommand) cmd); + } else if (clazz == AttachVolumeCommand.class) { + return execute((AttachVolumeCommand)cmd); + } else if (clazz == AttachIsoCommand.class) { + return execute((AttachIsoCommand) cmd); + } else if (clazz == UpgradeSnapshotCommand.class) { + return execute((UpgradeSnapshotCommand)cmd); + } else if (clazz == GetStorageStatsCommand.class) { + return execute((GetStorageStatsCommand)cmd); + } else if (clazz == PrimaryStorageDownloadCommand.class) { + return execute((PrimaryStorageDownloadCommand)cmd); + } else if (clazz == GetVncPortCommand.class) { + return execute((GetVncPortCommand)cmd); + } else if (clazz == SetupCommand.class) { + return execute((SetupCommand)cmd); + } else if (clazz == MaintainCommand.class) { + return execute((MaintainCommand)cmd); + } else if (clazz == PingTestCommand.class) { + return execute((PingTestCommand)cmd); + } else if (clazz == CheckOnHostCommand.class) { + return execute((CheckOnHostCommand)cmd); + } else if (clazz == ModifySshKeysCommand.class) { + return execute((ModifySshKeysCommand)cmd); + } else if (clazz == StartCommand.class) { + return execute((StartCommand)cmd); + } else if (clazz == CheckSshCommand.class) { + return execute((CheckSshCommand)cmd); + } else if (clazz == SecurityGroupRulesCmd.class) { + return execute((SecurityGroupRulesCmd)cmd); + } else if (clazz == OvsFetchInterfaceCommand.class) { + return execute((OvsFetchInterfaceCommand)cmd); + } else if (clazz == OvsCreateGreTunnelCommand.class) { + return execute((OvsCreateGreTunnelCommand)cmd); + } else if (clazz == OvsSetTagAndFlowCommand.class) { + return execute((OvsSetTagAndFlowCommand)cmd); + } else if (clazz == OvsDeleteFlowCommand.class) { + return execute((OvsDeleteFlowCommand)cmd); + } else if (clazz == OvsVpcPhysicalTopologyConfigCommand.class) { + return execute((OvsVpcPhysicalTopologyConfigCommand) cmd); + } else if (clazz == OvsVpcRoutingPolicyConfigCommand.class) { + return execute((OvsVpcRoutingPolicyConfigCommand) cmd); + } else if (clazz == CleanupNetworkRulesCmd.class) { + return execute((CleanupNetworkRulesCmd)cmd); + } else if (clazz == NetworkRulesSystemVmCommand.class) { + return execute((NetworkRulesSystemVmCommand)cmd); + } else if (clazz == OvsCreateTunnelCommand.class) { + return execute((OvsCreateTunnelCommand)cmd); + } else if (clazz == OvsSetupBridgeCommand.class) { + return execute((OvsSetupBridgeCommand)cmd); + } else if (clazz == OvsDestroyBridgeCommand.class) { + return execute((OvsDestroyBridgeCommand)cmd); + } else if (clazz == OvsDestroyTunnelCommand.class) { + return execute((OvsDestroyTunnelCommand)cmd); + } else if (clazz == UpdateHostPasswordCommand.class) { + return execute((UpdateHostPasswordCommand)cmd); + } else if (cmd instanceof ClusterSyncCommand) { + return execute((ClusterSyncCommand)cmd); + } else if (cmd instanceof ClusterVMMetaDataSyncCommand) { + return execute((ClusterVMMetaDataSyncCommand)cmd); + } else if (clazz == CheckNetworkCommand.class) { + return execute((CheckNetworkCommand)cmd); + } else if (clazz == PlugNicCommand.class) { + return execute((PlugNicCommand)cmd); + } else if (clazz == UnPlugNicCommand.class) { + return execute((UnPlugNicCommand) cmd); + } else if (cmd instanceof StorageSubSystemCommand) { + return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); + } else if (clazz == CreateVMSnapshotCommand.class) { + return execute((CreateVMSnapshotCommand) cmd); + } else if (clazz == DeleteVMSnapshotCommand.class) { + return execute((DeleteVMSnapshotCommand) cmd); + } else if (clazz == RevertToVMSnapshotCommand.class) { + return execute((RevertToVMSnapshotCommand) cmd); + } else if (clazz == NetworkRulesVmSecondaryIpCommand.class) { + return execute((NetworkRulesVmSecondaryIpCommand) cmd); + } else if (clazz == ScaleVmCommand.class) { + return execute((ScaleVmCommand)cmd); + } else if (clazz == PvlanSetupCommand.class) { + return execute((PvlanSetupCommand)cmd); + } else if (clazz == PerformanceMonitorCommand.class) { + return execute((PerformanceMonitorCommand)cmd); + } else { + return Answer.createUnsupportedCommandAnswer(cmd); + } + } + + @Override + public ExecutionResult executeInVR(String routerIP, String script, String args, int timeout) { + Connection conn = getConnection(); + String rc = callHostPluginAsync(conn, "vmops", "routerProxy", timeout, "args", script + " " + routerIP + " " + args); + // Fail case would be start with "fail#" + return new ExecutionResult(rc.startsWith("succ#"), rc.substring(5)); + } + + @Override + public ExecutionResult executeInVR(String routerIP, String script, String args) { + // Timeout is 120 seconds by default + return executeInVR(routerIP, script, args, 120); + } + + @Override + public ExecutionResult createFileInVR(String routerIp, String path, String filename, String content) { + Connection conn = getConnection(); + String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "filepath", path + filename, "filecontents", content); + // Fail case would be start with "fail#" + return new ExecutionResult(rc.startsWith("succ#"), rc.substring(5)); + } + + @Override + public ExecutionResult prepareCommand(NetworkElementCommand cmd) { + //Update IP used to access router + cmd.setRouterAccessIp(cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP)); + assert cmd.getRouterAccessIp() != null; + + if (cmd instanceof IpAssocVpcCommand) { + return prepareNetworkElementCommand((IpAssocVpcCommand)cmd); + } else if (cmd instanceof IpAssocCommand) { + return prepareNetworkElementCommand((IpAssocCommand)cmd); + } else if (cmd instanceof SetupGuestNetworkCommand) { + return prepareNetworkElementCommand((SetupGuestNetworkCommand)cmd); + } else if (cmd instanceof SetSourceNatCommand) { + return prepareNetworkElementCommand((SetSourceNatCommand)cmd); + } else if (cmd instanceof SetNetworkACLCommand) { + return prepareNetworkElementCommand((SetNetworkACLCommand)cmd); + } + return new ExecutionResult(true, null); + } + + @Override + public ExecutionResult cleanupCommand(NetworkElementCommand cmd) { + if (cmd instanceof IpAssocCommand && !(cmd instanceof IpAssocVpcCommand)) { + return cleanupNetworkElementCommand((IpAssocCommand)cmd); + } + return new ExecutionResult(true, null); + } + + private Answer execute(PerformanceMonitorCommand cmd) { + Connection conn = getConnection(); + String perfMon = getPerfMon(conn, cmd.getParams(), cmd.getWait()); + if (perfMon == null) { + return new PerformanceMonitorAnswer(cmd, false, perfMon); + } else + return new PerformanceMonitorAnswer(cmd, true, perfMon); + } + + private String getPerfMon(Connection conn, Map params, + int wait) { + String result = null; + try { + result = callHostPluginAsync(conn, "vmopspremium", "asmonitor", 60, + params); + if (result != null) + return result; + } catch (Exception e) { + s_logger.error("Can not get performance monitor for AS due to ", e); + } + return null; + } + + protected String callHostPluginAsync(Connection conn, String plugin, + String cmd, int wait, Map params) { + int timeout = wait * 1000; + Map args = new HashMap(); + Task task = null; + try { + for (String key : params.keySet()) { + args.put(key, params.get(key)); + } + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin executing for command " + cmd + + " with " + getArgsString(args)); + } + Host host = Host.getByUuid(conn, _host.uuid); + task = host.callPluginAsync(conn, plugin, cmd, args); + // poll every 1 seconds + waitForTask(conn, task, 1000, timeout); + checkForSuccess(conn, task); + String result = task.getResult(conn); + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin Result: " + result); + } + return result.replace("", "").replace("", "") + .replace("\n", ""); + } catch (Types.HandleInvalid e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + + " with args " + getArgsString(args) + + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + + e.handle); + } catch (XenAPIException e) { + s_logger.warn( + "callHostPlugin failed for cmd: " + cmd + " with args " + + getArgsString(args) + " due to " + e.toString(), + e); + } catch (XmlRpcException e) { + s_logger.warn( + "callHostPlugin failed for cmd: " + cmd + " with args " + + getArgsString(args) + " due to " + e.getMessage(), + e); + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (Exception e1) { + s_logger.warn("unable to destroy task(" + task.toString() + + ") on host(" + _host.uuid + ") due to ", e1); + } + } + } + return null; + } + + protected void scaleVM(Connection conn, VM vm, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException { + + Long staticMemoryMax = vm.getMemoryStaticMax(conn); + Long staticMemoryMin = vm.getMemoryStaticMin(conn); + Long newDynamicMemoryMin = vmSpec.getMinRam(); + Long newDynamicMemoryMax = vmSpec.getMaxRam(); + if (staticMemoryMin > newDynamicMemoryMin || newDynamicMemoryMax > staticMemoryMax) { + throw new CloudRuntimeException("Cannot scale up the vm because of memory constraint violation: " + "0 <= memory-static-min(" + staticMemoryMin + + ") <= memory-dynamic-min(" + newDynamicMemoryMin + ") <= memory-dynamic-max(" + newDynamicMemoryMax + ") <= memory-static-max(" + staticMemoryMax + ")"); + } + + vm.setMemoryDynamicRange(conn, newDynamicMemoryMin, newDynamicMemoryMax); + vm.setVCPUsNumberLive(conn, (long)vmSpec.getCpus()); + + Integer speed = vmSpec.getMinSpeed(); + if (speed != null) { + + int cpuWeight = _maxWeight; //cpu_weight + + // weight based allocation + + cpuWeight = (int)((speed * 0.99) / _host.speed * _maxWeight); + if (cpuWeight > _maxWeight) { + cpuWeight = _maxWeight; + } + + if (vmSpec.getLimitCpuUse()) { + long utilization = 0; // max CPU cap, default is unlimited + utilization = (int)((vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus()) / _host.speed * 100); + //vm.addToVCPUsParamsLive(conn, "cap", Long.toString(utilization)); currently xenserver doesnot support Xapi to add VCPUs params live. + callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", Long.toString(utilization), "vmname", vmSpec.getName()); + } + //vm.addToVCPUsParamsLive(conn, "weight", Integer.toString(cpuWeight)); + callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", Integer.toString(cpuWeight), "vmname", vmSpec.getName()); + } + } + + public ScaleVmAnswer execute(ScaleVmCommand cmd) { + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + String vmName = vmSpec.getName(); + try { + Connection conn = getConnection(); + Set vms = VM.getByNameLabel(conn, vmName); + Host host = Host.getByUuid(conn, _host.uuid); + + // If DMC is not enable then don't execute this command. + if (!isDmcEnabled(conn, host)) { + throw new CloudRuntimeException("Unable to scale the vm: " + vmName + " as DMC - Dynamic memory control is not enabled for the XenServer:" + _host.uuid + + " ,check your license and hypervisor version."); + } + + // stop vm which is running on this host or is in halted state + Iterator iter = vms.iterator(); + while (iter.hasNext()) { + VM vm = iter.next(); + VM.Record vmr = vm.getRecord(conn); + + if ((vmr.powerState == VmPowerState.HALTED) || + (vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.uuid))) { + iter.remove(); + } + } + + if (vms.size() == 0) { + s_logger.info("No running VM " + vmName + " exists on XenServer" + _host.uuid); + return new ScaleVmAnswer(cmd, false, "VM does not exist"); + } + + for (VM vm : vms) { + vm.getRecord(conn); + try { + scaleVM(conn, vm, vmSpec, host); + } catch (Exception e) { + String msg = "Catch exception " + e.getClass().getName() + " when scaling VM:" + vmName + " due to " + e.toString(); + s_logger.debug(msg); + return new ScaleVmAnswer(cmd, false, msg); + } + + } + String msg = "scaling VM " + vmName + " is successful on host " + host; + s_logger.debug(msg); + return new ScaleVmAnswer(cmd, true, msg); + + } catch (XenAPIException e) { + String msg = "Upgrade Vm " + vmName + " fail due to " + e.toString(); + s_logger.warn(msg, e); + return new ScaleVmAnswer(cmd, false, msg); + } catch (XmlRpcException e) { + String msg = "Upgrade Vm " + vmName + " fail due to " + e.getMessage(); + s_logger.warn(msg, e); + return new ScaleVmAnswer(cmd, false, msg); + } catch (Exception e) { + String msg = "Unable to upgrade " + vmName + " due to " + e.getMessage(); + s_logger.warn(msg, e); + return new ScaleVmAnswer(cmd, false, msg); + } + } + + private Answer execute(RevertToVMSnapshotCommand cmd) { + String vmName = cmd.getVmName(); + List listVolumeTo = cmd.getVolumeTOs(); + VMSnapshot.Type vmSnapshotType = cmd.getTarget().getType(); + Boolean snapshotMemory = vmSnapshotType == VMSnapshot.Type.DiskAndMemory; + Connection conn = getConnection(); + VirtualMachine.State vmState = null; + VM vm = null; + try { + + // remove vm from s_vms, for delta sync + s_vms.remove(_cluster, _name, vmName); + + Set vmSnapshots = VM.getByNameLabel(conn, cmd.getTarget().getSnapshotName()); + if (vmSnapshots.size() == 0) + return new RevertToVMSnapshotAnswer(cmd, false, "Cannot find vmSnapshot with name: " + cmd.getTarget().getSnapshotName()); + + VM vmSnapshot = vmSnapshots.iterator().next(); + + // find target VM or creating a work VM + try { + vm = getVM(conn, vmName); + } catch (Exception e) { + vm = createWorkingVM(conn, vmName, cmd.getGuestOSType(), listVolumeTo); + } + + if (vm == null) { + return new RevertToVMSnapshotAnswer(cmd, false, "Revert to VM Snapshot Failed due to can not find vm: " + vmName); + } + + // call plugin to execute revert + revertToSnapshot(conn, vmSnapshot, vmName, vm.getUuid(conn), snapshotMemory, _host.uuid); + vm = getVM(conn, vmName); + Set vbds = vm.getVBDs(conn); + Map vdiMap = new HashMap(); + // get vdi:vbdr to a map + for (VBD vbd : vbds) { + VBD.Record vbdr = vbd.getRecord(conn); + if (vbdr.type == Types.VbdType.DISK) { + VDI vdi = vbdr.VDI; + vdiMap.put(vbdr.userdevice, vdi); + } + } + + if (!snapshotMemory) { + vm.destroy(conn); + vmState = VirtualMachine.State.Stopped; + } else { + s_vms.put(_cluster, _name, vmName, State.Running); + vmState = VirtualMachine.State.Running; + } + + // after revert, VM's volumes path have been changed, need to report to manager + for (VolumeObjectTO volumeTo : listVolumeTo) { + Long deviceId = volumeTo.getDeviceId(); + VDI vdi = vdiMap.get(deviceId.toString()); + volumeTo.setPath(vdi.getUuid(conn)); + } + + return new RevertToVMSnapshotAnswer(cmd, listVolumeTo, vmState); + } catch (Exception e) { + s_logger.error("revert vm " + vmName + " to snapshot " + cmd.getTarget().getSnapshotName() + " failed due to " + e.getMessage()); + return new RevertToVMSnapshotAnswer(cmd, false, e.getMessage()); + } + } + + protected String revertToSnapshot(Connection conn, VM vmSnapshot, String vmName, String oldVmUuid, Boolean snapshotMemory, String hostUUID) throws XenAPIException, + XmlRpcException { + + String results = + callHostPluginAsync(conn, "vmopsSnapshot", "revert_memory_snapshot", 10 * 60 * 1000, "snapshotUUID", vmSnapshot.getUuid(conn), "vmName", vmName, "oldVmUuid", + oldVmUuid, "snapshotMemory", snapshotMemory.toString(), "hostUUID", hostUUID); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = "revert_memory_snapshot return null"; + } else { + if (results.equals("0")) { + return results; + } else { + errMsg = "revert_memory_snapshot exception"; + } + } + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); + } + + protected XsLocalNetwork getNativeNetworkForTraffic(Connection conn, TrafficType type, String name) throws XenAPIException, XmlRpcException { + if (name != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Looking for network named " + name); + } + return getNetworkByName(conn, name); + } + + if (type == TrafficType.Guest) { + return new XsLocalNetwork(Network.getByUuid(conn, _host.guestNetwork), null, PIF.getByUuid(conn, _host.guestPif), null); + } else if (type == TrafficType.Control) { + setupLinkLocalNetwork(conn); + return new XsLocalNetwork(Network.getByUuid(conn, _host.linkLocalNetwork)); + } else if (type == TrafficType.Management) { + return new XsLocalNetwork(Network.getByUuid(conn, _host.privateNetwork), null, PIF.getByUuid(conn, _host.privatePif), null); + } else if (type == TrafficType.Public) { + return new XsLocalNetwork(Network.getByUuid(conn, _host.publicNetwork), null, PIF.getByUuid(conn, _host.publicPif), null); + } else if (type == TrafficType.Storage) { + /* TrafficType.Storage is for secondary storage, while storageNetwork1 is for primary storage, we need better name here */ + return new XsLocalNetwork(Network.getByUuid(conn, _host.storageNetwork1), null, PIF.getByUuid(conn, _host.storagePif1), null); + } + + throw new CloudRuntimeException("Unsupported network type: " + type); + } + + /** + * This is a tricky to create network in xenserver. + * if you create a network then create bridge by brctl or openvswitch yourself, + * then you will get an expection that is "REQUIRED_NETWROK" when you start a + * vm with this network. The soultion is, create a vif of dom0 and plug it in + * network, xenserver will create the bridge on behalf of you + * @throws XmlRpcException + * @throws XenAPIException + */ + private void enableXenServerNetwork(Connection conn, Network nw, String vifNameLabel, String networkDesc) throws XenAPIException, XmlRpcException { + /* Make sure there is a physical bridge on this network */ + VIF dom0vif = null; + Pair vm = getControlDomain(conn); + VM dom0 = vm.first(); + // Create a VIF unless there's not already another VIF + Set dom0Vifs = dom0.getVIFs(conn); + for (VIF vif : dom0Vifs) { + vif.getRecord(conn); + if (vif.getNetwork(conn).getUuid(conn).equals(nw.getUuid(conn))) { + dom0vif = vif; + s_logger.debug("A VIF for dom0 has already been found - No need to create one"); + } + } + if (dom0vif == null) { + s_logger.debug("Create a vif on dom0 for " + networkDesc); + VIF.Record vifr = new VIF.Record(); + vifr.VM = dom0; + vifr.device = getLowestAvailableVIFDeviceNum(conn, dom0); + if (vifr.device == null) { + s_logger.debug("Failed to create " + networkDesc + ", no vif available"); + return; + } + Map config = new HashMap(); + config.put("nameLabel", vifNameLabel); + vifr.otherConfig = config; + vifr.MAC = "FE:FF:FF:FF:FF:FF"; + vifr.network = nw; + + vifr.lockingMode = Types.VifLockingMode.NETWORK_DEFAULT; + dom0vif = VIF.create(conn, vifr); + } + // At this stage we surely have a VIF + dom0vif.plug(conn); + dom0vif.unplug(conn); + synchronized (_tmpDom0Vif) { + _tmpDom0Vif.add(dom0vif); + } + + } + + private synchronized Network setupvSwitchNetwork(Connection conn) { + try { + if (_host.vswitchNetwork == null) { + Network vswitchNw = null; + Network.Record rec = new Network.Record(); + String nwName = Networks.BroadcastScheme.VSwitch.toString(); + Set networks = Network.getByNameLabel(conn, nwName); + + if (networks.size() == 0) { + rec.nameDescription = "vswitch network for " + nwName; + rec.nameLabel = nwName; + vswitchNw = Network.create(conn, rec); + } else { + vswitchNw = networks.iterator().next(); + } + if (!is_xcp()) + enableXenServerNetwork(conn, vswitchNw, "vswitch", "vswitch network"); + _host.vswitchNetwork = vswitchNw; + } + return _host.vswitchNetwork; + } catch (BadServerResponse e) { + s_logger.error("Failed to setup vswitch network", e); + } catch (XenAPIException e) { + s_logger.error("Failed to setup vswitch network", e); + } catch (XmlRpcException e) { + s_logger.error("Failed to setup vswitch network", e); + } + + return null; + } + + /** + * This method just creates a XenServer network following the tunnel network naming convention + */ + private synchronized Network findOrCreateTunnelNetwork(Connection conn, String nwName) { + try { + Network nw = null; + Network.Record rec = new Network.Record(); + Set networks = Network.getByNameLabel(conn, nwName); + + if (networks.size() == 0) { + rec.nameDescription = "tunnel network id# " + nwName; + rec.nameLabel = nwName; + //Initialize the ovs-host-setup to avoid error when doing get-param in plugin + Map otherConfig = new HashMap(); + otherConfig.put("ovs-host-setup", ""); + rec.otherConfig = otherConfig; + nw = Network.create(conn, rec); + // Plug dom0 vif only when creating network + if (!is_xcp()) + enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + nwName); + s_logger.debug("### Xen Server network for tunnels created:" + nwName); + } else { + nw = networks.iterator().next(); + s_logger.debug("Xen Server network for tunnels found:" + nwName); + } + return nw; + } catch (Exception e) { + s_logger.warn("createTunnelNetwork failed", e); + return null; + } + } + + /** + * This method creates a XenServer network and configures it for being used as a L2-in-L3 tunneled network + */ + private synchronized Network configureTunnelNetwork(Connection conn, Long networkId, long hostId, String bridgeName) { + try { + Network nw = findOrCreateTunnelNetwork(conn, bridgeName); + String nwName = bridgeName; + //Invoke plugin to setup the bridge which will be used by this network + String bridge = nw.getBridge(conn); + Map nwOtherConfig = nw.getOtherConfig(conn); + String configuredHosts = nwOtherConfig.get("ovs-host-setup"); + boolean configured = false; + if (configuredHosts != null) { + String hostIdsStr[] = configuredHosts.split(","); + for (String hostIdStr : hostIdsStr) { + if (hostIdStr.equals(((Long)hostId).toString())) { + configured = true; + break; + } + } + } + if (!configured) { + // Plug dom0 vif only if not done before for network and host + if (!is_xcp()) + enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + bridgeName); + String result; + if (bridgeName.startsWith("OVS-DR-VPC-Bridge")) { + result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge_for_distributed_routing", "bridge", bridge, + "key", bridgeName, + "xs_nw_uuid", nw.getUuid(conn), + "cs_host_id", ((Long)hostId).toString()); + } else { + result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge, + "key", bridgeName, + "xs_nw_uuid", nw.getUuid(conn), + "cs_host_id", ((Long)hostId).toString()); + } + + //Note down the fact that the ovs bridge has been setup + String[] res = result.split(":"); + if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) { + //TODO: Should make this error not fatal? + throw new CloudRuntimeException("Unable to pre-configure OVS bridge " + bridge ); + } + } + return nw; + } catch (Exception e) { + s_logger.warn("createandConfigureTunnelNetwork failed", e); + return null; + } + } + + private synchronized void destroyTunnelNetwork(Connection conn, String bridgeName) { + try { + Network nw = findOrCreateTunnelNetwork(conn, bridgeName); + String bridge = nw.getBridge(conn); + String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge); + String[] res = result.split(":"); + if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) { + //TODO: Should make this error not fatal? + //Can Concurrent VM shutdown/migration/reboot events can cause this method + //to be executed on a bridge which has already been removed? + throw new CloudRuntimeException("Unable to remove OVS bridge " + bridge + ":" + res); + } + return; + } catch (Exception e) { + s_logger.warn("destroyTunnelNetwork failed:", e); + return; + } + } + + protected Network getNetwork(Connection conn, NicTO nic) throws XenAPIException, XmlRpcException { + String name = nic.getName(); + XsLocalNetwork network = getNativeNetworkForTraffic(conn, nic.getType(), name); + if (network == null) { + s_logger.error("Network is not configured on the backend for nic " + nic.toString()); + throw new CloudRuntimeException("Network for the backend is not configured correctly for network broadcast domain: " + nic.getBroadcastUri()); + } + URI uri = nic.getBroadcastUri(); + BroadcastDomainType type = nic.getBroadcastType(); + if (uri != null && uri.toString().contains("untagged")) { + return network.getNetwork(); + } else if (type == BroadcastDomainType.Vlan) { + assert (BroadcastDomainType.getSchemeValue(uri) == BroadcastDomainType.Vlan); + long vlan = Long.parseLong(BroadcastDomainType.getValue(uri)); + return enableVlanNetwork(conn, vlan, network); + } else if (type == BroadcastDomainType.Native || type == BroadcastDomainType.LinkLocal) { + return network.getNetwork(); + } else if (type == BroadcastDomainType.Vswitch) { + String header = uri.toString().substring(Networks.BroadcastDomainType.Vswitch.scheme().length() + "://".length()); + if (header.startsWith("vlan")) { + _isOvs = true; + return setupvSwitchNetwork(conn); + } else { + return findOrCreateTunnelNetwork(conn, getOvsTunnelNetworkName(uri.getAuthority())); + } + } else if (type == BroadcastDomainType.Storage) { + if (uri == null) { + return network.getNetwork(); + } else { + long vlan = Long.parseLong(BroadcastDomainType.getValue(uri)); + return enableVlanNetwork(conn, vlan, network); + } + } else if (type == BroadcastDomainType.Lswitch) { + // Nicira Logical Switch + return network.getNetwork(); + } else if (type == BroadcastDomainType.Pvlan) { + assert BroadcastDomainType.getSchemeValue(uri) == BroadcastDomainType.Pvlan; + // should we consider moving this NetUtils method to BroadcastDomainType? + long vlan = Long.parseLong(NetUtils.getPrimaryPvlanFromUri(uri)); + return enableVlanNetwork(conn, vlan, network); + } + + throw new CloudRuntimeException("Unable to support this type of network broadcast domain: " + nic.getBroadcastUri()); + } + + private String getOvsTunnelNetworkName(String broadcastUri) { + if (broadcastUri.contains(".")) { + String[] parts = broadcastUri.split("\\."); + return "OVS-DR-VPC-Bridge"+parts[0]; + } else { + try { + return "OVSTunnel" + broadcastUri; + } catch (Exception e) { + return null; + } + } + } + + protected VIF createVif(Connection conn, String vmName, VM vm, VirtualMachineTO vmSpec, NicTO nic) throws XmlRpcException, XenAPIException { + assert (nic.getUuid() != null) : "Nic should have a uuid value"; + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating VIF for " + vmName + " on nic " + nic); + } + VIF.Record vifr = new VIF.Record(); + vifr.VM = vm; + vifr.device = Integer.toString(nic.getDeviceId()); + vifr.MAC = nic.getMac(); + + // Nicira needs these IDs to find the NIC + vifr.otherConfig = new HashMap(); + vifr.otherConfig.put("nicira-iface-id", nic.getUuid()); + vifr.otherConfig.put("nicira-vm-id", vm.getUuid(conn)); + // Provide XAPI with the cloudstack vm and nic uids. + vifr.otherConfig.put("cloudstack-nic-id", nic.getUuid()); + if (vmSpec != null) { + vifr.otherConfig.put("cloudstack-vm-id", vmSpec.getUuid()); + } + + // OVS plugin looks at network UUID in the vif 'otherconfig' details to group VIF's & tunnel ports as part of tier + // when bridge is setup for distributed routing + vifr.otherConfig.put("cloudstack-network-id", nic.getNetworkUuid()); + + vifr.network = getNetwork(conn, nic); + + if (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) { + vifr.qosAlgorithmType = "ratelimit"; + vifr.qosAlgorithmParams = new HashMap(); + // convert mbs to kilobyte per second + vifr.qosAlgorithmParams.put("kbps", Integer.toString(nic.getNetworkRateMbps() * 128)); + } + + vifr.lockingMode = Types.VifLockingMode.NETWORK_DEFAULT; + VIF vif = VIF.create(conn, vifr); + if (s_logger.isDebugEnabled()) { + vifr = vif.getRecord(conn); + s_logger.debug("Created a vif " + vifr.uuid + " on " + nic.getDeviceId()); + } + + return vif; + } + + protected void prepareISO(Connection conn, String vmName) throws XmlRpcException, XenAPIException { + + Set vms = VM.getByNameLabel(conn, vmName); + if (vms == null || vms.size() != 1) { + throw new CloudRuntimeException("There are " + ((vms == null) ? "0" : vms.size()) + " VMs named " + vmName); + } + VM vm = vms.iterator().next(); + Set vbds = vm.getVBDs(conn); + for (VBD vbd : vbds) { + VBD.Record vbdr = vbd.getRecord(conn); + if (vbdr.type == Types.VbdType.CD && vbdr.empty == false) { + VDI vdi = vbdr.VDI; + SR sr = vdi.getSR(conn); + Set pbds = sr.getPBDs(conn); + if (pbds == null) { + throw new CloudRuntimeException("There is no pbd for sr " + sr); + } + for (PBD pbd : pbds) { + PBD.Record pbdr = pbd.getRecord(conn); + if (pbdr.host.getUuid(conn).equals(_host.uuid)) { + return; + } + } + sr.setShared(conn, true); + Host host = Host.getByUuid(conn, _host.uuid); + PBD.Record pbdr = pbds.iterator().next().getRecord(conn); + pbdr.host = host; + pbdr.uuid = ""; + PBD pbd = PBD.create(conn, pbdr); + pbdPlug(conn, pbd, pbd.getUuid(conn)); + break; + } + } + } + + protected VDI mount(Connection conn, String vmName, DiskTO volume) throws XmlRpcException, XenAPIException { + DataTO data = volume.getData(); + Volume.Type type = volume.getType(); + if (type == Volume.Type.ISO) { + TemplateObjectTO iso = (TemplateObjectTO)data; + DataStoreTO store = iso.getDataStore(); + + if (store == null) { + //It's a fake iso + return null; + } + + //corer case, xenserver pv driver iso + String templateName = iso.getName(); + if (templateName.startsWith("xs-tools")) { + try { + Set vdis = VDI.getByNameLabel(conn, templateName); + if (vdis.isEmpty()) { + throw new CloudRuntimeException("Could not find ISO with URL: " + templateName); + } + return vdis.iterator().next(); + } catch (XenAPIException e) { + throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString()); + } catch (Exception e) { + throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString()); + } + } + + if (!(store instanceof NfsTO)) { + throw new CloudRuntimeException("only support mount iso on nfs"); + } + NfsTO nfsStore = (NfsTO)store; + String isoPath = nfsStore.getUrl() + File.separator + iso.getPath(); + int index = isoPath.lastIndexOf("/"); + + String mountpoint = isoPath.substring(0, index); + URI uri; + try { + uri = new URI(mountpoint); + } catch (URISyntaxException e) { + throw new CloudRuntimeException("Incorrect uri " + mountpoint, e); + } + SR isoSr = createIsoSRbyURI(conn, uri, vmName, false); + + String isoname = isoPath.substring(index + 1); + + VDI isoVdi = getVDIbyLocationandSR(conn, isoname, isoSr); + + if (isoVdi == null) { + throw new CloudRuntimeException("Unable to find ISO " + isoPath); + } + return isoVdi; + } else { + VolumeObjectTO vol = (VolumeObjectTO)data; + return VDI.getByUuid(conn, vol.getPath()); + } + } + + protected VBD createVbd(Connection conn, DiskTO volume, String vmName, VM vm, BootloaderType bootLoaderType, VDI vdi) throws XmlRpcException, XenAPIException { + Volume.Type type = volume.getType(); + + if (vdi == null) { + vdi = mount(conn, vmName, volume); + } + + if (vdi != null) { + if ("detached".equals(vdi.getNameLabel(conn))) { + vdi.setNameLabel(conn, vmName + "-DATA"); + } + + Map smConfig = vdi.getSmConfig(conn); + for (String key : smConfig.keySet()) { + if (key.startsWith("host_")) { + vdi.removeFromSmConfig(conn, key); + break; + } + } + } + VBD.Record vbdr = new VBD.Record(); + vbdr.VM = vm; + if (vdi != null) { + vbdr.VDI = vdi; + } else { + vbdr.empty = true; + } + if (type == Volume.Type.ROOT && bootLoaderType == BootloaderType.PyGrub) { + vbdr.bootable = true; + } else if (type == Volume.Type.ISO && bootLoaderType == BootloaderType.CD) { + vbdr.bootable = true; + } + + vbdr.userdevice = Long.toString(volume.getDiskSeq()); + if (volume.getType() == Volume.Type.ISO) { + vbdr.mode = Types.VbdMode.RO; + vbdr.type = Types.VbdType.CD; + } else if (volume.getType() == Volume.Type.ROOT) { + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + vbdr.unpluggable = false; + } else { + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + vbdr.unpluggable = true; + } + VBD vbd = VBD.create(conn, vbdr); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("VBD " + vbd.getUuid(conn) + " created for " + volume); + } + + return vbd; + } + + public long getStaticMax(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + return dynamicMaxRam; + } + + public long getStaticMin(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + return dynamicMinRam; + } + + protected HashMap> getGPUGroupDetails(Connection conn) throws XenAPIException, XmlRpcException { + return null; + } + + protected void createVGPU(Connection conn, StartCommand cmd, VM vm, GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException { + } + + protected VM createVmFromTemplate(Connection conn, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException { + String guestOsTypeName = getGuestOsType(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD); + Set templates = VM.getByNameLabel(conn, guestOsTypeName); + assert templates.size() == 1 : "Should only have 1 template but found " + templates.size(); + VM template = templates.iterator().next(); + + VM.Record vmr = template.getRecord(conn); + vmr.affinity = host; + vmr.otherConfig.remove("disks"); + vmr.otherConfig.remove("default_template"); + vmr.otherConfig.remove("mac_seed"); + vmr.isATemplate = false; + vmr.nameLabel = vmSpec.getName(); + vmr.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY; + vmr.actionsAfterShutdown = Types.OnNormalExit.DESTROY; + + if (isDmcEnabled(conn, host) && vmSpec.isEnableDynamicallyScaleVm()) { + //scaling is allowed + vmr.memoryStaticMin = getStaticMin(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD, vmSpec.getMinRam(), vmSpec.getMaxRam()); + vmr.memoryStaticMax = getStaticMax(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD, vmSpec.getMinRam(), vmSpec.getMaxRam()); + vmr.memoryDynamicMin = vmSpec.getMinRam(); + vmr.memoryDynamicMax = vmSpec.getMaxRam(); + } else { + //scaling disallowed, set static memory target + if (vmSpec.isEnableDynamicallyScaleVm() && !isDmcEnabled(conn, host)) { + s_logger.warn("Host " + host.getHostname(conn) + " does not support dynamic scaling, so the vm " + vmSpec.getName() + " is not dynamically scalable"); + } + vmr.memoryStaticMin = vmSpec.getMinRam(); + vmr.memoryStaticMax = vmSpec.getMaxRam(); + vmr.memoryDynamicMin = vmSpec.getMinRam(); + vmr.memoryDynamicMax = vmSpec.getMaxRam(); + } + + if (guestOsTypeName.toLowerCase().contains("windows")) { + vmr.VCPUsMax = (long)vmSpec.getCpus(); + } else { + // XenServer has a documented limit of 16 vcpus per vm + vmr.VCPUsMax = 2L * vmSpec.getCpus(); + if (vmr.VCPUsMax > 16) + { + vmr.VCPUsMax = 16L; + } + } + + vmr.VCPUsAtStartup = (long)vmSpec.getCpus(); + vmr.consoles.clear(); + + VM vm = VM.create(conn, vmr); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Created VM " + vm.getUuid(conn) + " for " + vmSpec.getName()); + } + + Map vcpuParams = new HashMap(); + + Integer speed = vmSpec.getMinSpeed(); + if (speed != null) { + + int cpuWeight = _maxWeight; // cpu_weight + int utilization = 0; // max CPU cap, default is unlimited + + // weight based allocation, CPU weight is calculated per VCPU + cpuWeight = (int)((speed * 0.99) / _host.speed * _maxWeight); + if (cpuWeight > _maxWeight) { + cpuWeight = _maxWeight; + } + + if (vmSpec.getLimitCpuUse()) { + // CPU cap is per VM, so need to assign cap based on the number of vcpus + utilization = (int)((vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus()) / _host.speed * 100); + } + + vcpuParams.put("weight", Integer.toString(cpuWeight)); + vcpuParams.put("cap", Integer.toString(utilization)); + + } + + if (vcpuParams.size() > 0) { + vm.setVCPUsParams(conn, vcpuParams); + } + + String bootArgs = vmSpec.getBootArgs(); + if (bootArgs != null && bootArgs.length() > 0) { + String pvargs = vm.getPVArgs(conn); + pvargs = pvargs + vmSpec.getBootArgs().replaceAll(" ", "%"); + if (s_logger.isDebugEnabled()) { + s_logger.debug("PV args are " + pvargs); + } + vm.setPVArgs(conn, pvargs); + } + + if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) { + if (vmSpec.getBootloader() == BootloaderType.CD) { + DiskTO[] disks = vmSpec.getDisks(); + for (DiskTO disk : disks) { + if (disk.getType() == Volume.Type.ISO) { + TemplateObjectTO iso = (TemplateObjectTO)disk.getData(); + String osType = iso.getGuestOsType(); + if (osType != null) { + String isoGuestOsName = getGuestOsType(osType, vmSpec.getBootloader() == BootloaderType.CD); + if (!isoGuestOsName.equals(guestOsTypeName)) { + vmSpec.setBootloader(BootloaderType.PyGrub); + } + } + } + } + } + if (vmSpec.getBootloader() == BootloaderType.CD) { + vm.setPVBootloader(conn, "eliloader"); + if (!vm.getOtherConfig(conn).containsKey("install-repository")) { + vm.addToOtherConfig(conn, "install-repository", "cdrom"); + } + } else if (vmSpec.getBootloader() == BootloaderType.PyGrub) { + vm.setPVBootloader(conn, "pygrub"); + } else { + vm.destroy(conn); + throw new CloudRuntimeException("Unable to handle boot loader type: " + vmSpec.getBootloader()); + } + } + try { + finalizeVmMetaData(vm, conn, vmSpec); + } catch (Exception e) { + throw new CloudRuntimeException("Unable to finalize VM MetaData: " + vmSpec); + } + return vm; + } + + + protected void finalizeVmMetaData(VM vm, Connection conn, VirtualMachineTO vmSpec) throws Exception { + + Map details = vmSpec.getDetails(); + if (details != null) { + String platformstring = details.get("platform"); + if (platformstring != null && !platformstring.isEmpty()) { + Map platform = StringUtils.stringToMap(platformstring); + vm.setPlatform(conn, platform); + } else { + String timeoffset = details.get("timeoffset"); + if (timeoffset != null) { + Map platform = vm.getPlatform(conn); + platform.put("timeoffset", timeoffset); + vm.setPlatform(conn, platform); + } + String coresPerSocket = details.get("cpu.corespersocket"); + if (coresPerSocket != null) { + Map platform = vm.getPlatform(conn); + platform.put("cores-per-socket", coresPerSocket); + vm.setPlatform(conn, platform); + } + } + String xentoolsversion = details.get("hypervisortoolsversion"); + if (xentoolsversion == null || !xentoolsversion.equalsIgnoreCase("xenserver61")) { + Map platform = vm.getPlatform(conn); + platform.remove("device_id"); + vm.setPlatform(conn, platform); + } + } + } + + protected String handleVmStartFailure(Connection conn, String vmName, VM vm, String message, Throwable th) { + String msg = "Unable to start " + vmName + " due to " + message; + s_logger.warn(msg, th); + + if (vm == null) { + return msg; + } + + try { + VM.Record vmr = vm.getRecord(conn); + List networks = new ArrayList(); + for (VIF vif : vmr.VIFs) { + try { + VIF.Record rec = vif.getRecord(conn); + networks.add(rec.network); + } catch (Exception e) { + s_logger.warn("Unable to cleanup VIF", e); + } + } + if (vmr.powerState == VmPowerState.RUNNING) { + try { + vm.hardShutdown(conn); + } catch (Exception e) { + s_logger.warn("VM hardshutdown failed due to ", e); + } + } + if (vm.getPowerState(conn) == VmPowerState.HALTED) { + try { + vm.destroy(conn); + } catch (Exception e) { + s_logger.warn("VM destroy failed due to ", e); + } + } + for (VBD vbd : vmr.VBDs) { + try { + vbd.unplug(conn); + vbd.destroy(conn); + } catch (Exception e) { + s_logger.warn("Unable to clean up VBD due to ", e); + } + } + for (VIF vif : vmr.VIFs) { + try { + vif.unplug(conn); + vif.destroy(conn); + } catch (Exception e) { + s_logger.warn("Unable to cleanup VIF", e); + } + } + for (Network network : networks) { + if (network.getNameLabel(conn).startsWith("VLAN")) { + disableVlanNetwork(conn, network); + } + } + } catch (Exception e) { + s_logger.warn("VM getRecord failed due to ", e); + } + + return msg; + } + + protected VBD createPatchVbd(Connection conn, String vmName, VM vm) throws XmlRpcException, XenAPIException { + + if (_host.systemvmisouuid == null) { + Set srs = SR.getByNameLabel(conn, "XenServer Tools"); + if (srs.size() != 1) { + throw new CloudRuntimeException("There are " + srs.size() + " SRs with name XenServer Tools"); + } + SR sr = srs.iterator().next(); + sr.scan(conn); + + SR.Record srr = sr.getRecord(conn); + + if (_host.systemvmisouuid == null) { + for (VDI vdi : srr.VDIs) { + VDI.Record vdir = vdi.getRecord(conn); + if (vdir.nameLabel.contains("systemvm.iso")) { + _host.systemvmisouuid = vdir.uuid; + break; + } + } + } + if (_host.systemvmisouuid == null) { + throw new CloudRuntimeException("can not find systemvmiso"); + } + } + + VBD.Record cdromVBDR = new VBD.Record(); + cdromVBDR.VM = vm; + cdromVBDR.empty = true; + cdromVBDR.bootable = false; + cdromVBDR.userdevice = "3"; + cdromVBDR.mode = Types.VbdMode.RO; + cdromVBDR.type = Types.VbdType.CD; + VBD cdromVBD = VBD.create(conn, cdromVBDR); + cdromVBD.insert(conn, VDI.getByUuid(conn, _host.systemvmisouuid)); + + return cdromVBD; + } + + protected void destroyPatchVbd(Connection conn, String vmName) throws XmlRpcException, XenAPIException { + try { + if (!vmName.startsWith("r-") && !vmName.startsWith("s-") && !vmName.startsWith("v-")) { + return; + } + Set vms = VM.getByNameLabel(conn, vmName); + for (VM vm : vms) { + Set vbds = vm.getVBDs(conn); + for (VBD vbd : vbds) { + if (vbd.getType(conn) == Types.VbdType.CD) { + vbd.eject(conn); + vbd.destroy(conn); + break; + } + } + } + } catch (Exception e) { + s_logger.debug("Cannot destory CD-ROM device for VM " + vmName + " due to " + e.toString(), e); + } + } + + protected CheckSshAnswer execute(CheckSshCommand cmd) { + Connection conn = getConnection(); + 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(conn, cmd.getName(), privateIp, cmdPort); + if (result != null) { + return new CheckSshAnswer(cmd, "Can not ping System vm " + vmName + "due to:" + result); + } + destroyPatchVbd(conn, vmName); + } catch (Exception e) { + return new CheckSshAnswer(cmd, e); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Ping command port succeeded for vm " + vmName); + } + + return new CheckSshAnswer(cmd); + } + + private HashMap parseDefaultOvsRuleComamnd(String str) { + HashMap cmd = new HashMap(); + String[] sarr = str.split("/"); + for (int i = 0; i < sarr.length; i++) { + String c = sarr[i]; + c = c.startsWith("/") ? c.substring(1) : c; + c = c.endsWith("/") ? c.substring(0, c.length() - 1) : c; + String[] p = c.split(";"); + if (p.length != 2) { + continue; + } + if (p[0].equalsIgnoreCase("vlans")) { + p[1] = p[1].replace("@", "["); + p[1] = p[1].replace("#", "]"); + } + cmd.put(p[0], p[1]); + } + return cmd; + } + + private void cleanUpTmpDomVif(Connection conn) { + List vifs; + synchronized (_tmpDom0Vif) { + vifs = _tmpDom0Vif; + _tmpDom0Vif = new ArrayList(); + } + + for (VIF v : vifs) { + String vifName = "unkown"; + try { + VIF.Record vifr = v.getRecord(conn); + Map config = vifr.otherConfig; + vifName = config.get("nameLabel"); + v.destroy(conn); + s_logger.debug("Destroy temp dom0 vif" + vifName + " success"); + } catch (Exception e) { + s_logger.warn("Destroy temp dom0 vif " + vifName + "failed", e); + } + } + } + + private Answer execute(PvlanSetupCommand cmd) { + Connection conn = getConnection(); + + String primaryPvlan = cmd.getPrimary(); + String isolatedPvlan = cmd.getIsolated(); + String op = cmd.getOp(); + String dhcpName = cmd.getDhcpName(); + String dhcpMac = cmd.getDhcpMac(); + String dhcpIp = cmd.getDhcpIp(); + String vmMac = cmd.getVmMac(); + String networkTag = cmd.getNetworkTag(); + + XsLocalNetwork nw = null; + String nwNameLabel = null; + try { + nw = getNativeNetworkForTraffic(conn, TrafficType.Guest, networkTag); + nwNameLabel = nw.getNetwork().getNameLabel(conn); + } catch (XenAPIException e) { + s_logger.warn("Fail to get network", e); + return new Answer(cmd, false, e.toString()); + } catch (XmlRpcException e) { + s_logger.warn("Fail to get network", e); + return new Answer(cmd, false, e.toString()); + } + + String result = null; + if (cmd.getType() == PvlanSetupCommand.Type.DHCP) { + result = + callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-dhcp", "op", op, "nw-label", nwNameLabel, "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, + "dhcp-name", dhcpName, "dhcp-ip", dhcpIp, "dhcp-mac", dhcpMac); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac); + return new Answer(cmd, false, result); + } else { + s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac); + } + } else if (cmd.getType() == PvlanSetupCommand.Type.VM) { + result = + callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm", "op", op, "nw-label", nwNameLabel, "primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, + "vm-mac", vmMac); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program pvlan for vm with mac " + vmMac); + return new Answer(cmd, false, result); + } else { + s_logger.info("Programmed pvlan for vm with mac " + vmMac); + } + } + return new Answer(cmd, true, result); + } + + @Override + public StartAnswer execute(StartCommand cmd) { + Connection conn = getConnection(); + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + String vmName = vmSpec.getName(); + State state = State.Stopped; + VM vm = null; + // if a VDI is created, record its UUID to send back to the CS MS + Map iqnToPath = new HashMap(); + try { + Set vms = VM.getByNameLabel(conn, vmName); + if (vms != null) { + for (VM v : vms) { + VM.Record vRec = v.getRecord(conn); + if (vRec.powerState == VmPowerState.HALTED) { + v.destroy(conn); + } else if (vRec.powerState == VmPowerState.RUNNING) { + String host = vRec.residentOn.getUuid(conn); + String msg = "VM " + vmName + " is runing on host " + host; + s_logger.debug(msg); + return new StartAnswer(cmd, msg, host); + } else { + String msg = "There is already a VM having the same name " + vmName + " vm record " + vRec.toString(); + s_logger.warn(msg); + return new StartAnswer(cmd, msg); + } + } + } + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, State.Starting); + } + s_logger.debug("1. The VM " + vmName + " is in Starting state."); + + Host host = Host.getByUuid(conn, _host.uuid); + vm = createVmFromTemplate(conn, vmSpec, host); + + GPUDeviceTO gpuDevice = vmSpec.getGpuDevice(); + if (gpuDevice != null) { + s_logger.debug("Creating VGPU for of VGPU type: " + gpuDevice.getVgpuType() + " in GPU group " + + gpuDevice.getGpuGroup() + " for VM " + vmName ); + createVGPU(conn, cmd, vm, gpuDevice); + } + + for (DiskTO disk : vmSpec.getDisks()) { + VDI newVdi = prepareManagedDisk(conn, disk, vmName); + + if (newVdi != null) { + String path = newVdi.getUuid(conn); + + iqnToPath.put(disk.getDetails().get(DiskTO.IQN), path); + } + + createVbd(conn, disk, vmName, vm, vmSpec.getBootloader(), newVdi); + } + + if (vmSpec.getType() != VirtualMachine.Type.User) { + createPatchVbd(conn, vmName, vm); + } + + for (NicTO nic : vmSpec.getNics()) { + createVif(conn, vmName, vm, vmSpec, nic); + } + + startVM(conn, host, vm, vmName); + + if (_isOvs) { + // TODO(Salvatore-orlando): This code should go + for (NicTO nic : vmSpec.getNics()) { + if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vswitch) { + HashMap args = parseDefaultOvsRuleComamnd(BroadcastDomainType.getValue(nic.getBroadcastUri())); + OvsSetTagAndFlowCommand flowCmd = + new OvsSetTagAndFlowCommand(args.get("vmName"), args.get("tag"), args.get("vlans"), args.get("seqno"), Long.parseLong(args.get("vmId"))); + OvsSetTagAndFlowAnswer r = execute(flowCmd); + if (!r.getResult()) { + s_logger.warn("Failed to set flow for VM " + r.getVmId()); + } else { + s_logger.info("Success to set flow for VM " + r.getVmId()); + } + } + } + } + cleanUpTmpDomVif(conn); + + if (_canBridgeFirewall) { + String result = null; + if (vmSpec.getType() != VirtualMachine.Type.User) { + NicTO[] nics = vmSpec.getNics(); + boolean secGrpEnabled = false; + for (NicTO nic : nics) { + if (nic.isSecurityGroupEnabled() || + (nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString()))) { + secGrpEnabled = true; + break; + } + } + if (secGrpEnabled) { + result = callHostPlugin(conn, "vmops", "default_network_rules_systemvm", "vmName", vmName); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program default network rules for " + vmName); + } else { + s_logger.info("Programmed default network rules for " + vmName); + } + } + + } else { + //For user vm, program the rules for each nic if the isolation uri scheme is ec2 + NicTO[] nics = vmSpec.getNics(); + for (NicTO nic : nics) { + if (nic.isSecurityGroupEnabled() || nic.getIsolationUri() != null && + nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { + List nicSecIps = nic.getNicSecIps(); + String secIpsStr; + StringBuilder sb = new StringBuilder(); + if (nicSecIps != null) { + for (String ip : nicSecIps) { + sb.append(ip).append(":"); + } + secIpsStr = sb.toString(); + } else { + secIpsStr = "0:"; + } + result = + callHostPlugin(conn, "vmops", "default_network_rules", "vmName", vmName, "vmIP", nic.getIp(), "vmMAC", nic.getMac(), "vmID", + Long.toString(vmSpec.getId()), "secIps", secIpsStr); + + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program default network rules for " + vmName + " on nic with ip:" + nic.getIp() + " mac:" + nic.getMac()); + } else { + s_logger.info("Programmed default network rules for " + vmName + " on nic with ip:" + nic.getIp() + " mac:" + nic.getMac()); + } + } + } + } + } + + state = State.Running; + + StartAnswer startAnswer = new StartAnswer(cmd); + + startAnswer.setIqnToPath(iqnToPath); + + return startAnswer; + } catch (Exception e) { + s_logger.warn("Catch Exception: " + e.getClass().toString() + " due to " + e.toString(), e); + String msg = handleVmStartFailure(conn, vmName, vm, "", e); + + StartAnswer startAnswer = new StartAnswer(cmd, msg); + + startAnswer.setIqnToPath(iqnToPath); + + return startAnswer; + } finally { + synchronized (_cluster.intern()) { + if (state != State.Stopped) { + s_vms.put(_cluster, _name, vmName, state); + s_logger.debug("2. The VM " + vmName + " is in " + state + " state."); + } else { + s_vms.remove(_cluster, _name, vmName); + s_logger.debug("The VM is in stopped state, detected problem during startup : " + vmName); + } + } + } + } + + // the idea here is to see if the DiskTO in question is from managed storage and + // does not yet have an SR + // if no SR, create it and create a VDI in it + private VDI prepareManagedDisk(Connection conn, DiskTO disk, String vmName) throws Exception { + Map details = disk.getDetails(); + + if (details == null) { + return null; + } + + boolean isManaged = new Boolean(details.get(DiskTO.MANAGED)).booleanValue(); + + if (!isManaged) { + return null; + } + + String iqn = details.get(DiskTO.IQN); + + Set srNameLabels = SR.getByNameLabel(conn, iqn); + + if (srNameLabels.size() != 0) { + return null; + } + + String vdiNameLabel = vmName + "-DATA"; + + return prepareManagedStorage(conn, details, null, vdiNameLabel); + } + + protected SR prepareManagedSr(Connection conn, Map details) { + String iScsiName = details.get(DiskTO.IQN); + String storageHost = details.get(DiskTO.STORAGE_HOST); + String chapInitiatorUsername = details.get(DiskTO.CHAP_INITIATOR_USERNAME); + String chapInitiatorSecret = details.get(DiskTO.CHAP_INITIATOR_SECRET); + + return getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true); + } + + protected VDI prepareManagedStorage(Connection conn, Map details, String path, String vdiNameLabel) throws Exception { + SR sr = prepareManagedSr(conn, details); + + VDI vdi = getVDIbyUuid(conn, path, false); + + if (vdi == null) { + Long volumeSize = Long.parseLong(details.get(DiskTO.VOLUME_SIZE)); + + vdi = createVdi(sr, vdiNameLabel, volumeSize); + } + + return vdi; + } + + protected Answer execute(ModifySshKeysCommand cmd) { + return new Answer(cmd); + } + + private boolean doPingTest(Connection conn, final String computingHostIp) { + com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.ip, 22); + try { + sshConnection.connect(null, 60000, 60000); + if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { + throw new CloudRuntimeException("Unable to authenticate"); + } + + String cmd = "ping -c 2 " + computingHostIp; + if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) { + throw new CloudRuntimeException("Cannot ping host " + computingHostIp + " from host " + _host.ip); + } + return true; + } catch (Exception e) { + s_logger.warn("Catch exception " + e.toString(), e); + return false; + } finally { + sshConnection.close(); + } + } + + protected CheckOnHostAnswer execute(CheckOnHostCommand cmd) { + return new CheckOnHostAnswer(cmd, null, "Not Implmeneted"); + } + + private boolean doPingTest(Connection conn, final String domRIp, final String vmIp) { + String args = "-i " + domRIp + " -p " + vmIp; + String result = callHostPlugin(conn, "vmops", "pingtest", "args", args); + if (result == null || result.isEmpty()) { + return false; + } + return true; + } + + private Answer execute(PingTestCommand cmd) { + Connection conn = getConnection(); + boolean result = false; + final String computingHostIp = cmd.getComputingHostIp(); + + if (computingHostIp != null) { + result = doPingTest(conn, computingHostIp); + } else { + result = doPingTest(conn, cmd.getRouterIp(), cmd.getPrivateIp()); + } + + if (!result) { + return new Answer(cmd, false, "PingTestCommand failed"); + } + return new Answer(cmd); + } + + protected MaintainAnswer execute(MaintainCommand cmd) { + Connection conn = getConnection(); + try { + + Host host = Host.getByUuid(conn, _host.uuid); + // remove all tags cloud stack + Host.Record hr = host.getRecord(conn); + Iterator it = hr.tags.iterator(); + while (it.hasNext()) { + String tag = it.next(); + if (tag.contains("cloud")) { + it.remove(); + } + } + host.setTags(conn, hr.tags); + return new MaintainAnswer(cmd); + } catch (XenAPIException e) { + s_logger.warn("Unable to put server in maintainence mode", e); + return new MaintainAnswer(cmd, false, e.getMessage()); + } catch (XmlRpcException e) { + s_logger.warn("Unable to put server in maintainence mode", e); + return new MaintainAnswer(cmd, false, e.getMessage()); + } + } + + protected String networkUsage(Connection conn, final String privateIpAddress, final String option, final String vif) { + if (option.equals("get")) { + return "0:0"; + } + return null; + } + + protected ExecutionResult prepareNetworkElementCommand(IpAssocCommand cmd) { + Connection conn = getConnection(); + String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + + try { + IpAddressTO[] ips = cmd.getIpAddresses(); + for (IpAddressTO ip : ips) { + + VM router = getVM(conn, routerName); + + NicTO nic = new NicTO(); + nic.setMac(ip.getVifMacAddress()); + nic.setType(ip.getTrafficType()); + if (ip.getBroadcastUri()== null) { + nic.setBroadcastType(BroadcastDomainType.Native); + } else { + URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); + nic.setBroadcastType(BroadcastDomainType.getSchemeValue(uri)); + nic.setBroadcastUri(uri); + } + nic.setDeviceId(0); + nic.setNetworkRateMbps(ip.getNetworkRate()); + nic.setName(ip.getNetworkName()); + + Network network = getNetwork(conn, nic); + + // Determine the correct VIF on DomR to associate/disassociate the + // IP address with + VIF correctVif = getCorrectVif(conn, router, network); + + // If we are associating an IP address and DomR doesn't have a VIF + // for the specified vlan ID, we need to add a VIF + // If we are disassociating the last IP address in the VLAN, we need + // to remove a VIF + boolean addVif = false; + if (ip.isAdd() && correctVif == null) { + addVif = true; + } + + if (addVif) { + // Add a new VIF to DomR + String vifDeviceNum = getLowestAvailableVIFDeviceNum(conn, router); + + if (vifDeviceNum == null) { + throw new InternalErrorException("There were no more available slots for a new VIF on router: " + router.getNameLabel(conn)); + } + + nic.setDeviceId(Integer.valueOf(vifDeviceNum)); + + correctVif = createVif(conn, routerName, router, null, nic); + correctVif.plug(conn); + // Add iptables rule for network usage + networkUsage(conn, routerIp, "addVif", "eth" + correctVif.getDevice(conn)); + } + + if (correctVif == null) { + throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with."); + } + + ip.setNicDevId(Integer.valueOf(correctVif.getDevice(conn))); + ip.setNewNic(addVif); + } + } catch (InternalErrorException e) { + s_logger.error("Ip Assoc failure on applying one ip due to exception: ", e); + return new ExecutionResult(false, e.getMessage()); + } catch (Exception e) { + return new ExecutionResult(false, e.getMessage()); + } + return new ExecutionResult(true, null); + } + + protected ExecutionResult cleanupNetworkElementCommand(IpAssocCommand cmd) { + Connection conn = getConnection(); + String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + try { + IpAddressTO[] ips = cmd.getIpAddresses(); + int ipsCount = ips.length; + for (IpAddressTO ip : ips) { + + VM router = getVM(conn, routerName); + + NicTO nic = new NicTO(); + nic.setMac(ip.getVifMacAddress()); + nic.setType(ip.getTrafficType()); + if (ip.getBroadcastUri()== null) { + nic.setBroadcastType(BroadcastDomainType.Native); + } else { + URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); + nic.setBroadcastType(BroadcastDomainType.getSchemeValue(uri)); + nic.setBroadcastUri(uri); + } + nic.setDeviceId(0); + nic.setNetworkRateMbps(ip.getNetworkRate()); + nic.setName(ip.getNetworkName()); + + Network network = getNetwork(conn, nic); + + // Determine the correct VIF on DomR to associate/disassociate the + // IP address with + VIF correctVif = getCorrectVif(conn, router, network); + + // If we are disassociating the last IP address in the VLAN, we need + // to remove a VIF + boolean removeVif = false; + + //there is only one ip in this public vlan and removing it, so remove the nic + if (ipsCount == 1 && !ip.isAdd()) { + removeVif = true; + } + + if (correctVif == null) { + throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with."); + } + + if (removeVif) { + network = correctVif.getNetwork(conn); + + // Mark this vif to be removed from network usage + networkUsage(conn, routerIp, "deleteVif", "eth" + correctVif.getDevice(conn)); + + // Remove the VIF from DomR + correctVif.unplug(conn); + correctVif.destroy(conn); + + // Disable the VLAN network if necessary + disableVlanNetwork(conn, network); + } + } + } catch (InternalErrorException e) { + s_logger.error("Ip Assoc failure on applying one ip due to exception: ", e); + return new ExecutionResult(false, e.getMessage()); + } catch (Exception e) { + return new ExecutionResult(false, e.getMessage()); + } + return new ExecutionResult(true, null); + } + + protected GetVncPortAnswer execute(GetVncPortCommand cmd) { + Connection conn = getConnection(); + try { + Set vms = VM.getByNameLabel(conn, cmd.getName()); + if (vms.size() == 1) { + String consoleurl; + consoleurl = "consoleurl=" + getVncUrl(conn, vms.iterator().next()) + "&" + "sessionref=" + conn.getSessionReference(); + return new GetVncPortAnswer(cmd, consoleurl, -1); + } else { + return new GetVncPortAnswer(cmd, "There are " + vms.size() + " VMs named " + cmd.getName()); + } + } catch (Exception e) { + String msg = "Unable to get vnc port due to " + e.toString(); + s_logger.warn(msg, e); + return new GetVncPortAnswer(cmd, msg); + } + } + + protected Storage.StorageResourceType getStorageResourceType() { + return Storage.StorageResourceType.STORAGE_POOL; + } + + protected CheckHealthAnswer execute(CheckHealthCommand cmd) { + boolean result = pingXAPI(); + return new CheckHealthAnswer(cmd, result); + } + + protected long[] getNetworkStats(Connection conn, String privateIP) { + String result = networkUsage(conn, privateIP, "get", null); + long[] stats = new long[2]; + if (result != null) { + String[] splitResult = result.split(":"); + int i = 0; + while (i < splitResult.length - 1) { + stats[0] += (new Long(splitResult[i++])).longValue(); + stats[1] += (new Long(splitResult[i++])).longValue(); + } + } + return stats; + } + + /** + * This is the method called for getting the HOST stats + * + * @param cmd + * @return + */ + protected GetHostStatsAnswer execute(GetHostStatsCommand cmd) { + Connection conn = getConnection(); + try { + HostStatsEntry hostStats = getHostStats(conn, cmd, cmd.getHostGuid(), cmd.getHostId()); + return new GetHostStatsAnswer(cmd, hostStats); + } catch (Exception e) { + String msg = "Unable to get Host stats" + e.toString(); + s_logger.warn(msg, e); + return new GetHostStatsAnswer(cmd, null); + } + } + + protected HostStatsEntry getHostStats(Connection conn, GetHostStatsCommand cmd, String hostGuid, long hostId) { + + HostStatsEntry hostStats = new HostStatsEntry(hostId, 0, 0, 0, "host", 0, 0, 0, 0); + Object[] rrdData = getRRDData(conn, 1); // call rrd method with 1 for host + + if (rrdData == null) { + return null; + } + + Integer numRows = (Integer)rrdData[0]; + Integer numColumns = (Integer)rrdData[1]; + Node legend = (Node)rrdData[2]; + Node dataNode = (Node)rrdData[3]; + + NodeList legendChildren = legend.getChildNodes(); + for (int col = 0; col < numColumns; col++) { + + if (legendChildren == null || legendChildren.item(col) == null) { + continue; + } + + String columnMetadata = getXMLNodeValue(legendChildren.item(col)); + + if (columnMetadata == null) { + continue; + } + + String[] columnMetadataList = columnMetadata.split(":"); + + if (columnMetadataList.length != 4) { + continue; + } + + String type = columnMetadataList[1]; + String param = columnMetadataList[3]; + + if (type.equalsIgnoreCase("host")) { + + if (param.contains("pif_eth0_rx")) { + hostStats.setNetworkReadKBs(getDataAverage(dataNode, col, numRows)); + } + + if (param.contains("pif_eth0_tx")) { + hostStats.setNetworkWriteKBs(getDataAverage(dataNode, col, numRows)); + } + + if (param.contains("memory_total_kib")) { + hostStats.setTotalMemoryKBs(getDataAverage(dataNode, col, numRows)); + } + + if (param.contains("memory_free_kib")) { + hostStats.setFreeMemoryKBs(getDataAverage(dataNode, col, numRows)); + } + + if (param.contains("cpu")) { + // hostStats.setNumCpus(hostStats.getNumCpus() + 1); + hostStats.setCpuUtilization(hostStats.getCpuUtilization() + getDataAverage(dataNode, col, numRows)); + } + + /* + if (param.contains("loadavg")) { + hostStats.setAverageLoad((hostStats.getAverageLoad() + getDataAverage(dataNode, col, numRows))); + } + */ + } + } + + // add the host cpu utilization + /* + if (hostStats.getNumCpus() != 0) { + hostStats.setCpuUtilization(hostStats.getCpuUtilization() / hostStats.getNumCpus()); + s_logger.debug("Host cpu utilization " + hostStats.getCpuUtilization()); + } + */ + + return hostStats; + } + + protected GetVmStatsAnswer execute(GetVmStatsCommand cmd) { + Connection conn = getConnection(); + List vmNames = cmd.getVmNames(); + HashMap vmStatsNameMap = new HashMap(); + if (vmNames.size() == 0) { + return new GetVmStatsAnswer(cmd, vmStatsNameMap); + } + try { + + // Determine the UUIDs of the requested VMs + List vmUUIDs = new ArrayList(); + + for (String vmName : vmNames) { + VM vm = getVM(conn, vmName); + vmUUIDs.add(vm.getUuid(conn)); + } + + HashMap vmStatsUUIDMap = getVmStats(conn, cmd, vmUUIDs, cmd.getHostGuid()); + if (vmStatsUUIDMap == null) { + return new GetVmStatsAnswer(cmd, vmStatsNameMap); + } + + for (String vmUUID : vmStatsUUIDMap.keySet()) { + vmStatsNameMap.put(vmNames.get(vmUUIDs.indexOf(vmUUID)), vmStatsUUIDMap.get(vmUUID)); + } + + return new GetVmStatsAnswer(cmd, vmStatsNameMap); + } catch (XenAPIException e) { + String msg = "Unable to get VM stats" + e.toString(); + s_logger.warn(msg, e); + return new GetVmStatsAnswer(cmd, vmStatsNameMap); + } catch (XmlRpcException e) { + String msg = "Unable to get VM stats" + e.getMessage(); + s_logger.warn(msg, e); + return new GetVmStatsAnswer(cmd, vmStatsNameMap); + } + } + + protected HashMap getVmStats(Connection conn, GetVmStatsCommand cmd, List vmUUIDs, String hostGuid) { + HashMap vmResponseMap = new HashMap(); + + for (String vmUUID : vmUUIDs) { + vmResponseMap.put(vmUUID, new VmStatsEntry(0, 0, 0, 0, "vm")); + } + + Object[] rrdData = getRRDData(conn, 2); // call rrddata with 2 for vm + + if (rrdData == null) { + return null; + } + + Integer numRows = (Integer)rrdData[0]; + Integer numColumns = (Integer)rrdData[1]; + Node legend = (Node)rrdData[2]; + Node dataNode = (Node)rrdData[3]; + + NodeList legendChildren = legend.getChildNodes(); + for (int col = 0; col < numColumns; col++) { + + if (legendChildren == null || legendChildren.item(col) == null) { + continue; + } + + String columnMetadata = getXMLNodeValue(legendChildren.item(col)); + + if (columnMetadata == null) { + continue; + } + + String[] columnMetadataList = columnMetadata.split(":"); + + if (columnMetadataList.length != 4) { + continue; + } + + String type = columnMetadataList[1]; + String uuid = columnMetadataList[2]; + String param = columnMetadataList[3]; + + if (type.equals("vm") && vmResponseMap.keySet().contains(uuid)) { + VmStatsEntry vmStatsAnswer = vmResponseMap.get(uuid); + + vmStatsAnswer.setEntityType("vm"); + + if (param.contains("cpu")) { + vmStatsAnswer.setNumCPUs(vmStatsAnswer.getNumCPUs() + 1); + vmStatsAnswer.setCPUUtilization(((vmStatsAnswer.getCPUUtilization() + getDataAverage(dataNode, col, numRows)))); + } else if (param.matches("vif_\\d_rx")) { + vmStatsAnswer.setNetworkReadKBs(vmStatsAnswer.getNetworkReadKBs() + (getDataAverage(dataNode, col, numRows) / (8 * 2))); + } else if (param.matches("vif_\\d_tx")) { + vmStatsAnswer.setNetworkWriteKBs(vmStatsAnswer.getNetworkWriteKBs() + (getDataAverage(dataNode, col, numRows) / (8 * 2))); + } + } + + } + + for (String vmUUID : vmResponseMap.keySet()) { + VmStatsEntry vmStatsAnswer = vmResponseMap.get(vmUUID); + + if (vmStatsAnswer.getNumCPUs() != 0) { + vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization() / vmStatsAnswer.getNumCPUs()); + } + + vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization() * 100); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Vm cpu utilization " + vmStatsAnswer.getCPUUtilization()); + } + } + + try { + for (String vmUUID : vmUUIDs) { + VM vm = VM.getByUuid(conn, vmUUID); + VmStatsEntry stats = vmResponseMap.get(vmUUID); + double diskReadKBs = 0; + double diskWriteKBs = 0; + for (VBD vbd : vm.getVBDs(conn)) { + VBDMetrics vbdmetrics = vbd.getMetrics(conn); + if (!isRefNull(vbdmetrics)) { + try { + diskReadKBs += vbdmetrics.getIoReadKbs(conn); + diskWriteKBs += vbdmetrics.getIoWriteKbs(conn); + } catch (Types.HandleInvalid e) { + s_logger.debug("vbdmetrics doesn't exist "); + } + } + } + if (stats == null) { + stats = new VmStatsEntry(); + } + stats.setDiskReadKBs(diskReadKBs); + stats.setDiskWriteKBs(diskWriteKBs); + vmResponseMap.put(vmUUID, stats); + } + } catch (Exception e) { + s_logger.warn("Error while collecting disk stats from : ", e); + return null; + } + + return vmResponseMap; + } + + protected GetVmDiskStatsAnswer execute(GetVmDiskStatsCommand cmd) { + return new GetVmDiskStatsAnswer(cmd, null, null, null); + } + + + protected Document getStatsRawXML(Connection conn, boolean host) { + Date currentDate = new Date(); + String urlStr = "http://" + _host.ip + "/rrd_updates?"; + urlStr += "session_id=" + conn.getSessionReference(); + urlStr += "&host=" + (host ? "true" : "false"); + urlStr += "&cf=" + _consolidationFunction; + urlStr += "&interval=" + _pollingIntervalInSeconds; + urlStr += "&start=" + (currentDate.getTime() / 1000 - 1000 - 100); + + URL url; + BufferedReader in = null; + try { + url = new URL(urlStr); + url.openConnection(); + URLConnection uc = url.openConnection(); + in = new BufferedReader(new InputStreamReader(uc.getInputStream())); + InputSource statsSource = new InputSource(in); + return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(statsSource); + } catch (MalformedURLException e) { + s_logger.warn("Malformed URL? come on...." + urlStr); + return null; + } catch (IOException e) { + s_logger.warn("Problems getting stats using " + urlStr, e); + return null; + } catch (SAXException e) { + s_logger.warn("Problems getting stats using " + urlStr, e); + return null; + } catch (ParserConfigurationException e) { + s_logger.warn("Problems getting stats using " + urlStr, e); + return null; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + s_logger.warn("Unable to close the buffer ", e); + } + } + } + } + + + + protected Object[] getRRDData(Connection conn, int flag) { + + /* + * Note: 1 => called from host, hence host stats 2 => called from vm, hence vm stats + */ + Document doc = null; + + try { + doc = getStatsRawXML(conn, flag == 1 ? true : false); + } catch (Exception e1) { + s_logger.warn("Error whilst collecting raw stats from plugin: ", e1); + return null; + } + + if (doc == null) { //stats are null when the host plugin call fails (host down state) + return null; + } + + NodeList firstLevelChildren = doc.getChildNodes(); + NodeList secondLevelChildren = (firstLevelChildren.item(0)).getChildNodes(); + Node metaNode = secondLevelChildren.item(0); + Node dataNode = secondLevelChildren.item(1); + + Integer numRows = 0; + Integer numColumns = 0; + Node legend = null; + NodeList metaNodeChildren = metaNode.getChildNodes(); + for (int i = 0; i < metaNodeChildren.getLength(); i++) { + Node n = metaNodeChildren.item(i); + if (n.getNodeName().equals("rows")) { + numRows = Integer.valueOf(getXMLNodeValue(n)); + } else if (n.getNodeName().equals("columns")) { + numColumns = Integer.valueOf(getXMLNodeValue(n)); + } else if (n.getNodeName().equals("legend")) { + legend = n; + } + } + + return new Object[] { numRows, numColumns, legend, dataNode }; + } + + protected String getXMLNodeValue(Node n) { + return n.getChildNodes().item(0).getNodeValue(); + } + + protected double getDataAverage(Node dataNode, int col, int numRows) { + double value = 0; + double dummy = 0; + int numRowsUsed = 0; + for (int row = 0; row < numRows; row++) { + Node data = dataNode.getChildNodes().item(numRows - 1 - row).getChildNodes().item(col + 1); + Double currentDataAsDouble = Double.valueOf(getXMLNodeValue(data)); + if (!currentDataAsDouble.equals(Double.NaN)) { + numRowsUsed += 1; + value += currentDataAsDouble; + } + } + + if (numRowsUsed == 0) { + if ((!Double.isInfinite(value)) && (!Double.isNaN(value))) { + return value; + } else { + s_logger.warn("Found an invalid value (infinity/NaN) in getDataAverage(), numRows=0"); + return dummy; + } + } else { + if ((!Double.isInfinite(value / numRowsUsed)) && (!Double.isNaN(value / numRowsUsed))) { + return (value / numRowsUsed); + } else { + s_logger.warn("Found an invalid value (infinity/NaN) in getDataAverage(), numRows>0"); + return dummy; + } + } + + } + + protected State convertToState(Types.VmPowerState ps) { + final State state = s_statesTable.get(ps); + return state == null ? State.Unknown : state; + } + + private static PowerState convertPowerState(Types.VmPowerState powerState) { + return s_powerStatesTable.get(powerState); + } + + protected HashMap getHostVmStateReport(Connection conn) { + + // TODO : new VM sync model does not require a cluster-scope report, we need to optimize + // the report accordingly + final HashMap vmStates = new HashMap(); + Map vm_map = null; + for (int i = 0; i < 2; i++) { + try { + vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER + break; + } catch (final Throwable e) { + s_logger.warn("Unable to get vms", e); + } + try { + Thread.sleep(1000); + } catch (final InterruptedException ex) { + + } + } + + if (vm_map == null) { + return vmStates; + } + for (VM.Record record : vm_map.values()) { + if (record.isControlDomain || record.isASnapshot || record.isATemplate) { + continue; // Skip DOM0 + } + + VmPowerState ps = record.powerState; + Host host = record.residentOn; + String host_uuid = null; + if (!isRefNull(host)) { + try { + host_uuid = host.getUuid(conn); + } catch (BadServerResponse e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } catch (XenAPIException e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } catch (XmlRpcException e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } + + if (host_uuid.equalsIgnoreCase(_host.uuid)) { + vmStates.put( + record.nameLabel, + new HostVmStateReportEntry(convertPowerState(ps), host_uuid) + ); + } + } + } + + return vmStates; + } + + // TODO vmsync { + protected HashMap> getAllVms(Connection conn) { + final HashMap> vmStates = new HashMap>(); + Map vm_map = null; + for (int i = 0; i < 2; i++) { + try { + vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER + break; + } catch (final Throwable e) { + s_logger.warn("Unable to get vms", e); + } + try { + Thread.sleep(1000); + } catch (final InterruptedException ex) { + + } + } + + if (vm_map == null) { + return null; + } + for (VM.Record record : vm_map.values()) { + if (record.isControlDomain || record.isASnapshot || record.isATemplate) { + continue; // Skip DOM0 + } + + VmPowerState ps = record.powerState; + final State state = convertToState(ps); + if (s_logger.isTraceEnabled()) { + s_logger.trace("VM " + record.nameLabel + ": powerstate = " + ps + "; vm state=" + state.toString()); + } + Host host = record.residentOn; + String host_uuid = null; + if (!isRefNull(host)) { + try { + host_uuid = host.getUuid(conn); + } catch (BadServerResponse e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } catch (XenAPIException e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } catch (XmlRpcException e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } + vmStates.put(record.nameLabel, new Pair(host_uuid, state)); + } + } + + return vmStates; + } + + // TODO vmsync } + + protected State getVmState(Connection conn, final String vmName) { + int retry = 3; + while (retry-- > 0) { + try { + Set vms = VM.getByNameLabel(conn, vmName); + for (final VM vm : vms) { + return convertToState(vm.getPowerState(conn)); + } + } catch (final BadServerResponse e) { + // There is a race condition within xenserver such that if a vm is + // deleted and we + // happen to ask for it, it throws this stupid response. So + // if this happens, + // we take a nap and try again which then avoids the race + // condition because + // the vm's information is now cleaned up by xenserver. The error + // is as follows + // com.xensource.xenapi.Types$BadServerResponse + // [HANDLE_INVALID, VM, + // 3dde93f9-c1df-55a7-2cde-55e1dce431ab] + s_logger.info("Unable to get a vm PowerState due to " + e.toString() + ". We are retrying. Count: " + retry); + try { + Thread.sleep(3000); + } catch (final InterruptedException ex) { + + } + } catch (XenAPIException e) { + String msg = "Unable to get a vm PowerState due to " + e.toString(); + s_logger.warn(msg, e); + break; + } catch (final XmlRpcException e) { + String msg = "Unable to get a vm PowerState due to " + e.getMessage(); + s_logger.warn(msg, e); + break; + } + } + + return State.Stopped; + } + + protected CheckVirtualMachineAnswer execute(final CheckVirtualMachineCommand cmd) { + Connection conn = getConnection(); + final String vmName = cmd.getVmName(); + final State state = getVmState(conn, vmName); + Integer vncPort = null; + if (state == State.Running) { + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, State.Running); + } + s_logger.debug("3. The VM " + vmName + " is in Running state"); + } + + return new CheckVirtualMachineAnswer(cmd, state, vncPort); + } + + protected PrepareForMigrationAnswer execute(PrepareForMigrationCommand cmd) { + Connection conn = getConnection(); + + VirtualMachineTO vm = cmd.getVirtualMachine(); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Preparing host for migrating " + vm); + } + + NicTO[] nics = vm.getNics(); + try { + prepareISO(conn, vm.getName()); + + for (NicTO nic : nics) { + getNetwork(conn, nic); + } + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vm.getName(), State.Migrating); + } + s_logger.debug("4. The VM " + vm.getName() + " is in Migrating state"); + + return new PrepareForMigrationAnswer(cmd); + } catch (Exception e) { + s_logger.warn("Catch Exception " + e.getClass().getName() + " prepare for migration failed due to " + e.toString(), e); + return new PrepareForMigrationAnswer(cmd, e); + } + } + + String upgradeSnapshot(Connection conn, String templatePath, String snapshotPath) { + String results = callHostPluginAsync(conn, "vmopspremium", "upgrade_snapshot", 2 * 60 * 60, "templatePath", templatePath, "snapshotPath", snapshotPath); + + if (results == null || results.isEmpty()) { + String msg = "upgrade_snapshot return null"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + String[] tmp = results.split("#"); + String status = tmp[0]; + if (status.equals("0")) { + return results; + } else { + s_logger.warn(results); + throw new CloudRuntimeException(results); + } + } + + String createTemplateFromSnapshot(Connection conn, String templatePath, String snapshotPath, int wait) { + String tmpltLocalDir = UUID.randomUUID().toString(); + String results = + callHostPluginAsync(conn, "vmopspremium", "create_privatetemplate_from_snapshot", wait, "templatePath", templatePath, "snapshotPath", snapshotPath, + "tmpltLocalDir", tmpltLocalDir); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = "create_privatetemplate_from_snapshot return null"; + } else { + String[] tmp = results.split("#"); + String status = tmp[0]; + if (status.equals("0")) { + return results; + } else { + errMsg = "create_privatetemplate_from_snapshot failed due to " + tmp[1]; + } + } + String source = "cloud_mount/" + tmpltLocalDir; + killCopyProcess(conn, source); + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); + } + + boolean killCopyProcess(Connection conn, String nameLabel) { + String results = callHostPluginAsync(conn, "vmops", "kill_copy_process", 60, "namelabel", nameLabel); + String errMsg = null; + if (results == null || results.equals("false")) { + errMsg = "kill_copy_process failed"; + s_logger.warn(errMsg); + return false; + } else { + return true; + } + } + + void destroyVDIbyNameLabel(Connection conn, String nameLabel) { + try { + Set vdis = VDI.getByNameLabel(conn, nameLabel); + if (vdis.size() != 1) { + s_logger.warn("destoryVDIbyNameLabel failed due to there are " + vdis.size() + " VDIs with name " + nameLabel); + return; + } + for (VDI vdi : vdis) { + try { + vdi.destroy(conn); + } catch (Exception e) { + } + } + } catch (Exception e) { + } + } + + String copy_vhd_from_secondarystorage(Connection conn, String mountpoint, String sruuid, int wait) { + String nameLabel = "cloud-" + UUID.randomUUID().toString(); + String results = + callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage", wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = "copy_vhd_from_secondarystorage return null"; + } else { + String[] tmp = results.split("#"); + String status = tmp[0]; + if (status.equals("0")) { + return tmp[1]; + } else { + errMsg = tmp[1]; + } + } + String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1); + if (killCopyProcess(conn, source)) { + destroyVDIbyNameLabel(conn, nameLabel); + } + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); + } + + public PrimaryStorageDownloadAnswer execute(final PrimaryStorageDownloadCommand cmd) { + String tmplturl = cmd.getUrl(); + String poolName = cmd.getPoolUuid(); + int wait = cmd.getWait(); + try { + URI uri = new URI(tmplturl); + String tmplpath = uri.getHost() + ":" + uri.getPath(); + Connection conn = getConnection(); + SR poolsr = null; + Set srs = SR.getByNameLabel(conn, poolName); + if (srs.size() != 1) { + String msg = "There are " + srs.size() + " SRs with same name: " + poolName; + s_logger.warn(msg); + return new PrimaryStorageDownloadAnswer(msg); + } else { + poolsr = srs.iterator().next(); + } + String pUuid = poolsr.getUuid(conn); + boolean isISCSI = IsISCSI(poolsr.getType(conn)); + String uuid = copy_vhd_from_secondarystorage(conn, tmplpath, pUuid, wait); + VDI tmpl = getVDIbyUuid(conn, uuid); + VDI snapshotvdi = tmpl.snapshot(conn, new HashMap()); + String snapshotUuid = snapshotvdi.getUuid(conn); + snapshotvdi.setNameLabel(conn, "Template " + cmd.getName()); + String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI); + VDI parent = getVDIbyUuid(conn, parentuuid); + Long phySize = parent.getPhysicalUtilisation(conn); + tmpl.destroy(conn); + poolsr.scan(conn); + try { + Thread.sleep(5000); + } catch (Exception e) { + } + return new PrimaryStorageDownloadAnswer(snapshotvdi.getUuid(conn), phySize); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " on host:" + _host.uuid + " for template: " + tmplturl + " due to " + e.toString(); + s_logger.warn(msg, e); + return new PrimaryStorageDownloadAnswer(msg); + } + } + + protected String removeSRSync(Connection conn, SR sr) { + if (sr == null) { + return null; + } + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(sr, "Removing SR")); + } + long waittime = 0; + try { + Set vdis = sr.getVDIs(conn); + for (VDI vdi : vdis) { + Map currentOperation = vdi.getCurrentOperations(conn); + if (currentOperation == null || currentOperation.size() == 0) { + continue; + } + if (waittime >= 1800000) { + String msg = "This template is being used, try late time"; + s_logger.warn(msg); + return msg; + } + waittime += 30000; + try { + Thread.sleep(30000); + } catch (final InterruptedException ex) { + } + } + removeSR(conn, sr); + return null; + } catch (XenAPIException e) { + s_logger.warn(logX(sr, "Unable to get current opertions " + e.toString()), e); + } catch (XmlRpcException e) { + s_logger.warn(logX(sr, "Unable to get current opertions " + e.getMessage()), e); + } + String msg = "Remove SR failed"; + s_logger.warn(msg); + return msg; + + } + + protected void removeSR(Connection conn, SR sr) { + if (sr == null) { + return; + } + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(sr, "Removing SR")); + } + + for (int i = 0; i < 2; i++) { + try { + Set vdis = sr.getVDIs(conn); + for (VDI vdi : vdis) { + vdi.forget(conn); + } + Set pbds = sr.getPBDs(conn); + for (PBD pbd : pbds) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(pbd, "Unplugging pbd")); + } + if (pbd.getCurrentlyAttached(conn)) { + pbd.unplug(conn); + } + pbd.destroy(conn); + } + + pbds = sr.getPBDs(conn); + if (pbds.size() == 0) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(sr, "Forgetting")); + } + sr.forget(conn); + return; + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(sr, "There are still pbd attached")); + if (s_logger.isTraceEnabled()) { + for (PBD pbd : pbds) { + s_logger.trace(logX(pbd, " Still attached")); + } + } + } + } catch (XenAPIException e) { + s_logger.debug(logX(sr, "Catch XenAPIException: " + e.toString())); + } catch (XmlRpcException e) { + s_logger.debug(logX(sr, "Catch Exception: " + e.getMessage())); + } + } + s_logger.warn(logX(sr, "Unable to remove SR")); + } + + protected MigrateAnswer execute(final MigrateCommand cmd) { + Connection conn = getConnection(); + final String vmName = cmd.getVmName(); + State state = null; + + state = s_vms.getState(_cluster, vmName); + + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, State.Stopping); + } + s_logger.debug("5. The VM " + vmName + " is in Stopping state"); + try { + Set vms = VM.getByNameLabel(conn, vmName); + + String ipaddr = cmd.getDestinationIp(); + + Set hosts = Host.getAll(conn); + Host dsthost = null; + for (Host host : hosts) { + if (host.getAddress(conn).equals(ipaddr)) { + dsthost = host; + break; + } + } + if (dsthost == null) { + String msg = "Migration failed due to unable to find host " + ipaddr + " in XenServer pool " + _host.pool; + s_logger.warn(msg); + return new MigrateAnswer(cmd, false, msg, null); + } + for (VM vm : vms) { + Set vbds = vm.getVBDs(conn); + for (VBD vbd : vbds) { + VBD.Record vbdRec = vbd.getRecord(conn); + if (vbdRec.type.equals(Types.VbdType.CD) && !vbdRec.empty) { + vbd.eject(conn); + break; + } + } + migrateVM(conn, dsthost, vm, vmName); + vm.setAffinity(conn, dsthost); + state = State.Stopping; + } + return new MigrateAnswer(cmd, true, "migration succeeded", null); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + ": Migration failed due to " + e.toString(); + s_logger.warn(msg, e); + return new MigrateAnswer(cmd, false, msg, null); + } finally { + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, state); + } + s_logger.debug("6. The VM " + vmName + " is in " + state + " state"); + } + + } + + protected State getRealPowerState(Connection conn, String label) { + int i = 0; + s_logger.trace("Checking on the HALTED State"); + for (; i < 20; i++) { + try { + Set vms = VM.getByNameLabel(conn, label); + if (vms == null || vms.size() == 0) { + continue; + } + + VM vm = vms.iterator().next(); + + VmPowerState vps = vm.getPowerState(conn); + if (vps != null && vps != VmPowerState.HALTED && vps != VmPowerState.UNRECOGNIZED) { + return convertToState(vps); + } + } catch (XenAPIException e) { + String msg = "Unable to get real power state due to " + e.toString(); + s_logger.warn(msg, e); + } catch (XmlRpcException e) { + String msg = "Unable to get real power state due to " + e.getMessage(); + s_logger.warn(msg, e); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + return State.Stopped; + } + + protected Pair getControlDomain(Connection conn) throws XenAPIException, XmlRpcException { + Host host = Host.getByUuid(conn, _host.uuid); + Set vms = null; + vms = host.getResidentVMs(conn); + for (VM vm : vms) { + if (vm.getIsControlDomain(conn)) { + return new Pair(vm, vm.getRecord(conn)); + } + } + + throw new CloudRuntimeException("Com'on no control domain? What the crap?!#@!##$@"); + } + + protected void umountSnapshotDir(Connection conn, Long dcId) { + try { + callHostPlugin(conn, "vmopsSnapshot", "unmountSnapshotsDir", "dcId", dcId.toString()); + } catch (Exception e) { + s_logger.debug("Failed to umount snapshot dir",e); + } + } + + protected ReadyAnswer execute(ReadyCommand cmd) { + Connection conn = getConnection(); + Long dcId = cmd.getDataCenterId(); + // Ignore the result of the callHostPlugin. Even if unmounting the + // snapshots dir fails, let Ready command + // succeed. + umountSnapshotDir(conn, dcId); + + setupLinkLocalNetwork(conn); + // try to destroy CD-ROM device for all system VMs on this host + try { + Host host = Host.getByUuid(conn, _host.uuid); + Set vms = host.getResidentVMs(conn); + for (VM vm : vms) { + destroyPatchVbd(conn, vm.getNameLabel(conn)); + } + } catch (Exception e) { + } + try { + boolean result = cleanupHaltedVms(conn); + if (!result) { + return new ReadyAnswer(cmd, "Unable to cleanup halted vms"); + } + } catch (XenAPIException e) { + s_logger.warn("Unable to cleanup halted vms", e); + return new ReadyAnswer(cmd, "Unable to cleanup halted vms"); + } catch (XmlRpcException e) { + s_logger.warn("Unable to cleanup halted vms", e); + return new ReadyAnswer(cmd, "Unable to cleanup halted vms"); + } + + return new ReadyAnswer(cmd); + } + + protected String getVncUrl(Connection conn, VM vm) { + VM.Record record; + Console c; + try { + record = vm.getRecord(conn); + Set consoles = record.consoles; + + if (consoles.isEmpty()) { + s_logger.warn("There are no Consoles available to the vm : " + record.nameDescription); + return null; + } + Iterator i = consoles.iterator(); + while (i.hasNext()) { + c = i.next(); + if (c.getProtocol(conn) == Types.ConsoleProtocol.RFB) + return c.getLocation(conn); + } + } catch (XenAPIException e) { + String msg = "Unable to get console url due to " + e.toString(); + s_logger.warn(msg, e); + return null; + } catch (XmlRpcException e) { + String msg = "Unable to get console url due to " + e.getMessage(); + s_logger.warn(msg, e); + return null; + } + return null; + } + + @Override + public RebootAnswer execute(RebootCommand cmd) { + Connection conn = getConnection(); + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, cmd.getVmName(), State.Starting); + } + s_logger.debug("7. The VM " + cmd.getVmName() + " is in Starting state"); + try { + Set vms = null; + try { + vms = VM.getByNameLabel(conn, cmd.getVmName()); + } catch (XenAPIException e0) { + s_logger.debug("getByNameLabel failed " + e0.toString()); + return new RebootAnswer(cmd, "getByNameLabel failed " + e0.toString(), false); + } catch (Exception e0) { + s_logger.debug("getByNameLabel failed " + e0.getMessage()); + return new RebootAnswer(cmd, "getByNameLabel failed", false); + } + for (VM vm : vms) { + try { + rebootVM(conn, vm, vm.getNameLabel(conn)); + } catch (Exception e) { + String msg = e.toString(); + s_logger.warn(msg, e); + return new RebootAnswer(cmd, msg, false); + } + } + return new RebootAnswer(cmd, "reboot succeeded", true); + } finally { + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, cmd.getVmName(), State.Running); + } + s_logger.debug("8. The VM " + cmd.getVmName() + " is in Running state"); + } + } + + protected Answer execute(RebootRouterCommand cmd) { + Connection conn = getConnection(); + RebootAnswer answer = execute((RebootCommand)cmd); + if (answer.getResult()) { + String cnct = connect(conn, cmd.getVmName(), cmd.getPrivateIpAddress()); + networkUsage(conn, cmd.getPrivateIpAddress(), "create", null); + if (cnct == null) { + return answer; + } else { + return new Answer(cmd, false, cnct); + } + } + return answer; + } + + protected void startvmfailhandle(Connection conn, VM vm, List> mounts) { + if (vm != null) { + try { + + if (vm.getPowerState(conn) == VmPowerState.RUNNING) { + try { + vm.hardShutdown(conn); + } catch (Exception e) { + String msg = "VM hardshutdown failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + if (vm.getPowerState(conn) == VmPowerState.HALTED) { + try { + vm.destroy(conn); + } catch (Exception e) { + String msg = "VM destroy failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + } catch (Exception e) { + String msg = "VM getPowerState failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + if (mounts != null) { + for (Ternary mount : mounts) { + VDI vdi = mount.second(); + Set vbds = null; + try { + vbds = vdi.getVBDs(conn); + } catch (Exception e) { + String msg = "VDI getVBDS failed due to " + e.toString(); + s_logger.warn(msg, e); + continue; + } + for (VBD vbd : vbds) { + try { + vbd.unplug(conn); + vbd.destroy(conn); + } catch (Exception e) { + String msg = "VBD destroy failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + } + } + } + + /** + * WARN: static-min <= dynamic-min <= dynamic-max <= static-max + * @see XcpServerResource#setMemory(com.xensource.xenapi.Connection, com.xensource.xenapi.VM, long, long) + * @param conn + * @param vm + * @param minMemsize + * @param maxMemsize + * @throws XmlRpcException + * @throws XenAPIException + */ + protected void setMemory(Connection conn, VM vm, long minMemsize, long maxMemsize) throws XmlRpcException, XenAPIException { + vm.setMemoryLimits(conn, mem_128m, maxMemsize, minMemsize, maxMemsize); + } + + /** + * When Dynamic Memory Control (DMC) is enabled - + * xenserver allows scaling the guest memory while the guest is running + * + * By default this is disallowed, override the specific xenserver resource + * if this is enabled + */ + protected boolean isDmcEnabled(Connection conn, Host host) throws XenAPIException, XmlRpcException { + return false; + } + + protected void waitForTask(Connection c, Task task, long pollInterval, long timeout) throws XenAPIException, XmlRpcException { + long beginTime = System.currentTimeMillis(); + if (s_logger.isTraceEnabled()) { + s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") sent to " + c.getSessionReference() + " is pending completion with a " + timeout + + "ms timeout"); + } + while (task.getStatus(c) == Types.TaskStatusType.PENDING) { + try { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") is pending, sleeping for " + pollInterval + "ms"); + } + Thread.sleep(pollInterval); + } catch (InterruptedException e) { + } + if (System.currentTimeMillis() - beginTime > timeout) { + String msg = "Async " + timeout / 1000 + " seconds timeout for task " + task.toString(); + s_logger.warn(msg); + task.cancel(c); + throw new Types.BadAsyncResult(msg); + } + } + } + + protected void checkForSuccess(Connection c, Task task) throws XenAPIException, XmlRpcException { + if (task.getStatus(c) == Types.TaskStatusType.SUCCESS) { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getUuid(c) + ") completed"); + } + return; + } else { + String msg = "Task failed! Task record: " + task.getRecord(c); + s_logger.warn(msg); + task.cancel(c); + throw new Types.BadAsyncResult(msg); + } + } + + void rebootVM(Connection conn, VM vm, String vmName) throws XmlRpcException { + Task task = null; + try { + task = vm.cleanRebootAsync(conn); + try { + //poll every 1 seconds , timeout after 10 minutes + waitForTask(conn, task, 1000, 10 * 60 * 1000); + checkForSuccess(conn, task); + } catch (Types.HandleInvalid e) { + if (vm.getPowerState(conn) == Types.VmPowerState.RUNNING) { + task = null; + return; + } + throw new CloudRuntimeException("Reboot VM catch HandleInvalid and VM is not in RUNNING state"); + } + } catch (XenAPIException e) { + s_logger.debug("Unable to Clean Reboot VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString() + ", try hard reboot"); + try { + vm.hardReboot(conn); + } catch (Exception e1) { + String msg = "Unable to hard Reboot VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString(); + s_logger.warn(msg, e1); + throw new CloudRuntimeException(msg); + } + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (Exception e1) { + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e1.toString()); + } + } + } + } + + void forceShutdownVM(Connection conn, VM vm) { + try { + Long domId = vm.getDomid(conn); + callHostPlugin(conn, "vmopspremium", "forceShutdownVM", "domId", domId.toString()); + vm.powerStateReset(conn); + vm.destroy(conn); + } catch (Exception e) { + String msg = "forceShutdown failed due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } + } + + void shutdownVM(Connection conn, VM vm, String vmName) throws XmlRpcException { + Task task = null; + try { + task = vm.cleanShutdownAsync(conn); + try { + //poll every 1 seconds , timeout after 10 minutes + waitForTask(conn, task, 1000, 10 * 60 * 1000); + checkForSuccess(conn, task); + } catch (Types.HandleInvalid e) { + if (vm.getPowerState(conn) == Types.VmPowerState.HALTED) { + task = null; + return; + } + throw new CloudRuntimeException("Shutdown VM catch HandleInvalid and VM is not in HALTED state"); + } + } catch (XenAPIException e) { + s_logger.debug("Unable to cleanShutdown VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString()); + try { + Types.VmPowerState state = vm.getPowerState(conn); + if (state == Types.VmPowerState.RUNNING) { + try { + vm.hardShutdown(conn); + } catch (Exception e1) { + s_logger.debug("Unable to hardShutdown VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString()); + state = vm.getPowerState(conn); + if (state == Types.VmPowerState.RUNNING) { + forceShutdownVM(conn, vm); + } + return; + } + } else if (state == Types.VmPowerState.HALTED) { + return; + } else { + String msg = "After cleanShutdown the VM status is " + state.toString() + ", that is not expected"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + } catch (Exception e1) { + String msg = "Unable to hardShutdown VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString(); + s_logger.warn(msg, e1); + throw new CloudRuntimeException(msg); + } + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (Exception e1) { + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e1.toString()); + } + } + } + } + + void startVM(Connection conn, Host host, VM vm, String vmName) throws XmlRpcException { + Task task = null; + try { + task = vm.startOnAsync(conn, host, false, true); + try { + //poll every 1 seconds , timeout after 10 minutes + waitForTask(conn, task, 1000, 10 * 60 * 1000); + checkForSuccess(conn, task); + } catch (Types.HandleInvalid e) { + if (vm.getPowerState(conn) == Types.VmPowerState.RUNNING) { + s_logger.debug("VM " + vmName + " is in Running status"); + task = null; + return; + } + throw new CloudRuntimeException("Start VM " + vmName + " catch HandleInvalid and VM is not in RUNNING state"); + } catch (Types.BadAsyncResult e) { + if (vm.getPowerState(conn) == Types.VmPowerState.RUNNING) { + s_logger.debug("VM " + vmName + " is in Running status"); + task = null; + return; + } + throw new CloudRuntimeException("Start VM " + vmName + " catch BadAsyncResult and VM is not in RUNNING state"); + } + } catch (XenAPIException e) { + String msg = "Unable to start VM(" + vmName + ") on host(" + _host.uuid + ") due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (Exception e1) { + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e1.toString()); + } + } + } + } + + private void migrateVM(Connection conn, Host destHost, VM vm, String vmName) throws XmlRpcException { + Task task = null; + try { + Map other = new HashMap(); + other.put("live", "true"); + task = vm.poolMigrateAsync(conn, destHost, other); + try { + // poll every 1 seconds + long timeout = (_migratewait) * 1000L; + waitForTask(conn, task, 1000, timeout); + checkForSuccess(conn, task); + } catch (Types.HandleInvalid e) { + if (vm.getResidentOn(conn).equals(destHost)) { + task = null; + return; + } + throw new CloudRuntimeException("migrate VM catch HandleInvalid and VM is not running on dest host"); + } + } catch (XenAPIException e) { + String msg = "Unable to migrate VM(" + vmName + ") from host(" + _host.uuid + ") due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (Exception e1) { + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to " + e1.toString()); + } + } + } + } + + protected VDI cloudVDIcopy(Connection conn, VDI vdi, SR sr, int wait) throws XenAPIException, XmlRpcException { + Task task = null; + if (wait == 0) { + wait = 2 * 60 * 60; + } + try { + task = vdi.copyAsync(conn, sr); + // poll every 1 seconds , timeout after 2 hours + waitForTask(conn, task, 1000, wait * 1000); + checkForSuccess(conn, task); + VDI dvdi = Types.toVDI(task, conn); + return dvdi; + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (Exception e1) { + s_logger.warn("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to ", e1); + } + } + } + } + + protected String callHostPluginAsync(Connection conn, String plugin, String cmd, int wait, String... params) { + int timeout = wait * 1000; + Map args = new HashMap(); + Task task = null; + try { + for (int i = 0; i < params.length; i += 2) { + args.put(params[i], params[i + 1]); + } + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); + } + Host host = Host.getByUuid(conn, _host.uuid); + task = host.callPluginAsync(conn, plugin, cmd, args); + // poll every 1 seconds + waitForTask(conn, task, 1000, timeout); + checkForSuccess(conn, task); + String result = task.getResult(conn); + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin Result: " + result); + } + return result.replace("", "").replace("", "").replace("\n", ""); + } catch (Types.HandleInvalid e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + + e.handle); + } catch (XenAPIException e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e); + } catch (XmlRpcException e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(), e); + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (Exception e1) { + s_logger.warn("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to ", e1); + } + } + } + return null; + } + + @Override + public StopAnswer execute(StopCommand cmd) { + String vmName = cmd.getVmName(); + String platformstring = null; + try { + Connection conn = getConnection(); + Set vms = VM.getByNameLabel(conn, vmName); + // stop vm which is running on this host or is in halted state + Iterator iter = vms.iterator(); + while (iter.hasNext()) { + VM vm = iter.next(); + VM.Record vmr = vm.getRecord(conn); + if (vmr.powerState != VmPowerState.RUNNING) { + continue; + } + if (isRefNull(vmr.residentOn)) { + continue; + } + if (vmr.residentOn.getUuid(conn).equals(_host.uuid)) { + continue; + } + iter.remove(); + } + + if (vms.size() == 0) { + synchronized (_cluster.intern()) { + s_logger.info("VM does not exist on XenServer" + _host.uuid); + s_vms.remove(_cluster, _name, vmName); + } + return new StopAnswer(cmd, "VM does not exist", true); + } + for (VM vm : vms) { + VM.Record vmr = vm.getRecord(conn); + platformstring = StringUtils.mapToString(vmr.platform); + if (vmr.isControlDomain) { + String msg = "Tring to Shutdown control domain"; + s_logger.warn(msg); + return new StopAnswer(cmd, msg, false); + } + + if (vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.uuid)) { + String msg = "Stop Vm " + vmName + " failed due to this vm is not running on this host: " + _host.uuid + " but host:" + vmr.residentOn.getUuid(conn); + s_logger.warn(msg); + return new StopAnswer(cmd, msg, platformstring, false); + } + + State state = s_vms.getState(_cluster, vmName); + + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, State.Stopping); + } + s_logger.debug("9. The VM " + vmName + " is in Stopping state"); + + try { + if (vmr.powerState == VmPowerState.RUNNING) { + /* when stop a vm, set affinity to current xenserver */ + vm.setAffinity(conn, vm.getResidentOn(conn)); + + if (_canBridgeFirewall) { + String result = callHostPlugin(conn, "vmops", "destroy_network_rules_for_vm", "vmName", cmd.getVmName()); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to remove network rules for vm " + cmd.getVmName()); + } else { + s_logger.info("Removed network rules for vm " + cmd.getVmName()); + } + } + shutdownVM(conn, vm, vmName); + } + } catch (Exception e) { + String msg = "Catch exception " + e.getClass().getName() + " when stop VM:" + cmd.getVmName() + " due to " + e.toString(); + s_logger.debug(msg); + return new StopAnswer(cmd, msg, platformstring, false); + } finally { + + try { + if (vm.getPowerState(conn) == VmPowerState.HALTED) { + Set vGPUs = null; + // Get updated GPU details + try { + vGPUs = vm.getVGPUs(conn); + } catch (XenAPIException e2) { + s_logger.debug("VM " + vmName + " does not have GPU support."); + } + if (vGPUs != null && !vGPUs.isEmpty()) { + HashMap> groupDetails = getGPUGroupDetails(conn); + cmd.setGpuDevice(new GPUDeviceTO(null, null, groupDetails)); + } + + Set vifs = vm.getVIFs(conn); + List networks = new ArrayList(); + for (VIF vif : vifs) { + networks.add(vif.getNetwork(conn)); + } + vm.destroy(conn); + state = State.Stopped; + SR sr = getISOSRbyVmName(conn, cmd.getVmName()); + removeSR(conn, sr); + // Disable any VLAN networks that aren't used + // anymore + for (Network network : networks) { + try { + if (network.getNameLabel(conn).startsWith("VLAN")) { + disableVlanNetwork(conn, network); + } + } catch (Exception e) { + // network might be destroyed by other host + } + } + return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", platformstring, true); + } + } catch (Exception e) { + String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.getMessage(); + s_logger.warn(msg, e); + } finally { + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, state); + } + s_logger.debug("10. The VM " + vmName + " is in " + state + " state"); + } + } + } + + } catch (Exception e) { + String msg = "Stop Vm " + vmName + " fail due to " + e.toString(); + s_logger.warn(msg, e); + return new StopAnswer(cmd, msg, platformstring, false); + } + return new StopAnswer(cmd, "Stop VM failed", platformstring, false); + } + + private List getVdis(Connection conn, VM vm) { + List vdis = new ArrayList(); + try { + Set vbds = vm.getVBDs(conn); + for (VBD vbd : vbds) { + vdis.add(vbd.getVDI(conn)); + } + } catch (XenAPIException e) { + String msg = "getVdis can not get VPD due to " + e.toString(); + s_logger.warn(msg, e); + } catch (XmlRpcException e) { + String msg = "getVdis can not get VPD due to " + e.getMessage(); + s_logger.warn(msg, e); + } + return vdis; + } + + protected String connect(Connection conn, final String vmName, final String ipAddress, final int port) { + for (int i = 0; i <= _retry; i++) { + try { + Set vms = VM.getByNameLabel(conn, vmName); + if (vms.size() < 1) { + String msg = "VM " + vmName + " is not running"; + s_logger.warn(msg); + return msg; + } + } catch (Exception e) { + String msg = "VM.getByNameLabel " + vmName + " failed due to " + e.toString(); + s_logger.warn(msg, e); + return msg; + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Trying to connect to " + ipAddress + " attempt " + i + " of " + _retry); + } + if (pingdomr(conn, ipAddress, Integer.toString(port))) { + return null; + } + try { + Thread.sleep(_sleep); + } catch (final InterruptedException e) { + } + } + String msg = "Timeout, Unable to logon to " + ipAddress; + s_logger.debug(msg); + + return msg; + } + + protected String connect(Connection conn, final String vmname, final String ipAddress) { + return connect(conn, vmname, ipAddress, 3922); + } + + protected boolean isDeviceUsed(Connection conn, VM vm, Long deviceId) { + // Figure out the disk number to attach the VM to + + String msg = null; + try { + Set allowedVBDDevices = vm.getAllowedVBDDevices(conn); + if (allowedVBDDevices.contains(deviceId.toString())) { + return false; + } + return true; + } catch (XmlRpcException e) { + msg = "Catch XmlRpcException due to: " + e.getMessage(); + s_logger.warn(msg, e); + } catch (XenAPIException e) { + msg = "Catch XenAPIException due to: " + e.toString(); + s_logger.warn(msg, e); + } + throw new CloudRuntimeException("When check deviceId " + msg); + } + + protected String getUnusedDeviceNum(Connection conn, VM vm) { + // Figure out the disk number to attach the VM to + try { + Set allowedVBDDevices = vm.getAllowedVBDDevices(conn); + if (allowedVBDDevices.size() == 0) { + throw new CloudRuntimeException("Could not find an available slot in VM with name: " + vm.getNameLabel(conn) + " to attach a new disk."); + } + return allowedVBDDevices.iterator().next(); + } catch (XmlRpcException e) { + String msg = "Catch XmlRpcException due to: " + e.getMessage(); + s_logger.warn(msg, e); + } catch (XenAPIException e) { + String msg = "Catch XenAPIException due to: " + e.toString(); + s_logger.warn(msg, e); + } + throw new CloudRuntimeException("Could not find an available slot in VM with name to attach a new disk."); + } + + protected String callHostPlugin(Connection conn, String plugin, String cmd, String... params) { + Map args = new HashMap(); + String msg; + try { + for (int i = 0; i < params.length; i += 2) { + args.put(params[i], params[i + 1]); + } + + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); + } + Host host = Host.getByUuid(conn, _host.uuid); + String result = host.callPlugin(conn, plugin, cmd, args); + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin Result: " + result); + } + return result.replace("\n", ""); + } catch (XenAPIException e) { + msg = "callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(); + s_logger.warn(msg); + } catch (XmlRpcException e) { + msg = "callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(); + s_logger.debug(msg); + } + throw new CloudRuntimeException(msg); + } + + protected String getArgsString(Map args) { + StringBuilder argString = new StringBuilder(); + for (Map.Entry arg : args.entrySet()) { + argString.append(arg.getKey() + ": " + arg.getValue() + ", "); + } + return argString.toString(); + } + + protected boolean setIptables(Connection conn) { + String result = callHostPlugin(conn, "vmops", "setIptables"); + if (result == null || result.isEmpty()) { + return false; + } + return true; + } + + protected XsLocalNetwork getManagementNetwork(Connection conn) throws XmlRpcException, XenAPIException { + PIF mgmtPif = null; + PIF.Record mgmtPifRec = null; + Host host = Host.getByUuid(conn, _host.uuid); + Set hostPifs = host.getPIFs(conn); + for (PIF pif : hostPifs) { + PIF.Record rec = pif.getRecord(conn); + if (rec.management) { + if (rec.VLAN != null && rec.VLAN != -1) { + String msg = + new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.uuid) + .append("; pif=") + .append(rec.uuid) + .append("; vlan=") + .append(rec.VLAN) + .toString(); + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Management network is on pif=" + rec.uuid); + } + mgmtPif = pif; + mgmtPifRec = rec; + break; + } + } + if (mgmtPif == null) { + String msg = "Unable to find management network for " + _host.uuid; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + Bond bond = mgmtPifRec.bondSlaveOf; + if (!isRefNull(bond)) { + String msg = + "Management interface is on slave(" + mgmtPifRec.uuid + ") of bond(" + bond.getUuid(conn) + ") on host(" + _host.uuid + + "), please move management interface to bond!"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + Network nk = mgmtPifRec.network; + Network.Record nkRec = nk.getRecord(conn); + return new XsLocalNetwork(nk, nkRec, mgmtPif, mgmtPifRec); + } + + protected VIF getCorrectVif(Connection conn, VM router, Network network) throws XmlRpcException, XenAPIException { + Set routerVIFs = router.getVIFs(conn); + for (VIF vif : routerVIFs) { + Network vifNetwork = vif.getNetwork(conn); + if (vifNetwork.getUuid(conn).equals(network.getUuid(conn))) { + return vif; + } + } + + return null; + } + + protected VIF getCorrectVif(Connection conn, VM router, IpAddressTO ip) throws XmlRpcException, XenAPIException { + NicTO nic = new NicTO(); + nic.setType(ip.getTrafficType()); + nic.setName(ip.getNetworkName()); + if (ip.getBroadcastUri() == null) { + nic.setBroadcastType(BroadcastDomainType.Native); + } else { + URI uri = BroadcastDomainType.fromString(ip.getBroadcastUri()); + nic.setBroadcastType(BroadcastDomainType.getSchemeValue(uri)); + nic.setBroadcastUri(uri); + } + Network network = getNetwork(conn, nic); + // Determine the correct VIF on DomR to associate/disassociate the + // IP address with + Set routerVIFs = router.getVIFs(conn); + for (VIF vif : routerVIFs) { + Network vifNetwork = vif.getNetwork(conn); + if (vifNetwork.getUuid(conn).equals(network.getUuid(conn))) { + return vif; + } + } + return null; + } + + protected VIF getVifByMac(Connection conn, VM router, String mac) throws XmlRpcException, XenAPIException { + Set routerVIFs = router.getVIFs(conn); + mac = mac.trim(); + for (VIF vif : routerVIFs) { + String lmac = vif.getMAC(conn); + if (lmac.trim().equals(mac)) { + return vif; + } + } + return null; + } + + protected String getLowestAvailableVIFDeviceNum(Connection conn, VM vm) { + String vmName = ""; + try { + vmName = vm.getNameLabel(conn); + List usedDeviceNums = new ArrayList(); + Set vifs = vm.getVIFs(conn); + Iterator vifIter = vifs.iterator(); + while (vifIter.hasNext()) { + VIF vif = vifIter.next(); + try { + usedDeviceNums.add(Integer.valueOf(vif.getDevice(conn))); + } catch (NumberFormatException e) { + String msg = "Obtained an invalid value for an allocated VIF device number for VM: " + vmName; + s_logger.debug(msg, e); + throw new CloudRuntimeException(msg); + } + } + + for (Integer i = 0; i < _maxNics; i++) { + if (!usedDeviceNums.contains(i)) { + s_logger.debug("Lowest available Vif device number: " + i + " for VM: " + vmName); + return i.toString(); + } + } + } catch (XmlRpcException e) { + String msg = "Caught XmlRpcException: " + e.getMessage(); + s_logger.warn(msg, e); + } catch (XenAPIException e) { + String msg = "Caught XenAPIException: " + e.toString(); + s_logger.warn(msg, e); + } + + throw new CloudRuntimeException("Could not find available VIF slot in VM with name: " + vmName); + } + + protected VDI mount(Connection conn, StoragePoolType poolType, String volumeFolder, String volumePath) { + return getVDIbyUuid(conn, volumePath); + } + + /** + * getNetworkByName() retrieves what the server thinks is the actual + * network used by the XenServer host. This method should always be + * used to talk to retrieve a network by the name. The reason is + * because of the problems in using the name label as the way to find + * the Network. + * + * To see how we are working around these problems, take a look at + * enableVlanNetwork(). The following description assumes you have looked + * at the description on that method. + * + * In order to understand this, we have to see what type of networks are + * within a XenServer that's under CloudStack control. + * + * - Native Networks: these are networks that are untagged on the + * XenServer and are used to crate VLAN networks on. These are + * created by the user and is assumed to be one per cluster. + * - VLAN Networks: these are dynamically created by CloudStack and can + * have problems with duplicated names. + * - LinkLocal Networks: these are dynamically created by CloudStack and + * can also have problems with duplicated names but these don't have + * actual PIFs. + * + * In order to speed to retrieval of a network, we do the following: + * - We retrieve by the name. If only one network is retrieved, we + * assume we retrieved the right network. + * - If more than one network is retrieved, we check to see which one + * has the pif for the local host and use that. + * - If a pif is not found, then we look at the tags and find the + * one with the lowest timestamp. (See enableVlanNetwork()) + * + * @param conn Xapi connection + * @param name name of the network + * @return XsNic an object that contains network, network record, pif, and pif record. + * @throws XenAPIException + * @throws XmlRpcException + * + * @see CitrixResourceBase#enableVlanNetwork + */ + protected XsLocalNetwork getNetworkByName(Connection conn, String name) throws XenAPIException, XmlRpcException { + Set networks = Network.getByNameLabel(conn, name); + if (networks.size() == 1) { + return new XsLocalNetwork(networks.iterator().next(), null, null, null); + } + + if (networks.size() == 0) { + return null; + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found more than one network with the name " + name); + } + Network earliestNetwork = null; + Network.Record earliestNetworkRecord = null; + long earliestTimestamp = Long.MAX_VALUE; + int earliestRandom = Integer.MAX_VALUE; + for (Network network : networks) { + XsLocalNetwork nic = new XsLocalNetwork(network); + + if (nic.getPif(conn) != null) { + return nic; + } + + Network.Record record = network.getRecord(conn); + if (record.tags != null) { + for (String tag : record.tags) { + Pair stamp = parseTimestamp(tag); + if (stamp == null) { + continue; + } + + if (stamp.first() < earliestTimestamp || (stamp.first() == earliestTimestamp && stamp.second() < earliestRandom)) { + earliestTimestamp = stamp.first(); + earliestRandom = stamp.second(); + earliestNetwork = network; + earliestNetworkRecord = record; + } + } + } + } + + return earliestNetwork != null ? new XsLocalNetwork(earliestNetwork, earliestNetworkRecord, null, null) : null; + } + + protected String generateTimeStamp() { + return new StringBuilder("CsCreateTime-").append(System.currentTimeMillis()).append("-").append(Rand.nextInt(Integer.MAX_VALUE)).toString(); + } + + protected Pair parseTimestamp(String timeStampStr) { + String[] tokens = timeStampStr.split("-"); + if (tokens.length != 3) { + s_logger.debug("timeStamp in network has wrong pattern: " + timeStampStr); + return null; + } + if (!tokens[0].equals("CsCreateTime")) { + s_logger.debug("timeStamp in network doesn't start with CsCreateTime: " + timeStampStr); + return null; + } + return new Pair(Long.parseLong(tokens[1]), Integer.parseInt(tokens[2])); + } + + /** + * enableVlanNetwork creates a Network object, Vlan object, and thereby + * a tagged PIF object in Xapi. + * + * In XenServer, VLAN is added by + * - Create a network, which is unique cluster wide. + * - Find the PIF that you want to create the VLAN on. + * - Create a VLAN using the network and the PIF. As a result of this + * operation, a tagged PIF object is also created. + * + * Here is a list of problems with clustered Xapi implementation that + * we are trying to circumvent. + * - There can be multiple Networks with the same name-label so searching + * using name-label is not unique. + * - There are no other ways to search for Networks other than listing + * all of them which is not efficient in our implementation because + * we can have over 4000 VLAN networks. + * - In a clustered situation, it's possible for both hosts to detect + * that the Network is missing and both creates it. This causes a + * lot of problems as one host may be using one Network and another + * may be using a different network for their VMs. This causes + * problems in migration because the VMs are logically attached + * to different networks in Xapi's database but in reality, they + * are attached to the same network. + * + * To work around these problems, we do the following. + * + * - When creating the VLAN network, we name it as VLAN-UUID of the + * Network it is created on-VLAN Tag. Because VLAN tags is unique with + * one particular network, this is a unique name-label to quickly + * retrieve the the VLAN network with when we need it again. + * - When we create the VLAN network, we add a timestamp and a random + * number as a tag into the network. Then instead of creating + * VLAN on that network, we actually retrieve the Network again + * and this time uses the VLAN network with lowest timestamp or + * lowest random number as the VLAN network. This allows VLAN creation + * to happen on multiple hosts concurrently but even if two VLAN + * networks were created with the same name, only one of them is used. + * + * One cavaet about this approach is that it relies on the timestamp to + * be relatively accurate among different hosts. + * + * @param conn Xapi Connection + * @param tag VLAN tag + * @param network network on this host to create the VLAN on. + * @return VLAN Network created. + * @throws XenAPIException + * @throws XmlRpcException + */ + protected Network enableVlanNetwork(Connection conn, long tag, XsLocalNetwork network) throws XenAPIException, XmlRpcException { + Network vlanNetwork = null; + String oldName = "VLAN" + Long.toString(tag); + String newName = "VLAN-" + network.getNetworkRecord(conn).uuid + "-" + tag; + XsLocalNetwork vlanNic = getNetworkByName(conn, newName); + if (vlanNic == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Couldn't find vlan network with the new name so trying old name: " + oldName); + } + vlanNic = getNetworkByName(conn, oldName); + if (vlanNic != null) { + s_logger.info("Renaming VLAN with old name " + oldName + " to " + newName); + vlanNic.getNetwork().setNameLabel(conn, newName); + } + } + if (vlanNic == null) { // Can't find it, then create it. + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating VLAN network for " + tag + " on host " + _host.ip); + } + Network.Record nwr = new Network.Record(); + nwr.nameLabel = newName; + nwr.tags = new HashSet(); + nwr.tags.add(generateTimeStamp()); + vlanNetwork = Network.create(conn, nwr); + vlanNic = getNetworkByName(conn, newName); + } + + PIF nPif = network.getPif(conn); + PIF.Record nPifr = network.getPifRecord(conn); + + vlanNetwork = vlanNic.getNetwork(); + if (vlanNic.getPif(conn) != null) { + return vlanNetwork; + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating VLAN " + tag + " on host " + _host.ip + " on device " + nPifr.device); + } + VLAN vlan = VLAN.create(conn, nPif, tag, vlanNetwork); + VLAN.Record vlanr = vlan.getRecord(conn); + if (s_logger.isDebugEnabled()) { + s_logger.debug("VLAN is created for " + tag + ". The uuid is " + vlanr.uuid); + } + + return vlanNetwork; + } + + protected void disableVlanNetwork(Connection conn, Network network) { + } + + protected SR getLocalLVMSR(Connection conn) { + try { + Map map = SR.getAllRecords(conn); + for (Map.Entry entry : map.entrySet()) { + SR.Record srRec = entry.getValue(); + if (SRType.LVM.equals(srRec.type)) { + Set pbds = srRec.PBDs; + if (pbds == null) { + continue; + } + for (PBD pbd : pbds) { + Host host = pbd.getHost(conn); + if (!isRefNull(host) && host.getUuid(conn).equals(_host.uuid)) { + if (!pbd.getCurrentlyAttached(conn)) { + pbd.plug(conn); + } + SR sr = entry.getKey(); + sr.scan(conn); + return sr; + } + } + } + } + } catch (XenAPIException e) { + String msg = "Unable to get local LVMSR in host:" + _host.uuid + e.toString(); + s_logger.warn(msg); + } catch (XmlRpcException e) { + String msg = "Unable to get local LVMSR in host:" + _host.uuid + e.getCause(); + s_logger.warn(msg); + } + return null; + } + + protected SR getLocalEXTSR(Connection conn) { + try { + Map map = SR.getAllRecords(conn); + for (Map.Entry entry : map.entrySet()) { + SR.Record srRec = entry.getValue(); + if (SRType.FILE.equals(srRec.type) || SRType.EXT.equals(srRec.type)) { + Set pbds = srRec.PBDs; + if (pbds == null) { + continue; + } + for (PBD pbd : pbds) { + Host host = pbd.getHost(conn); + if (!isRefNull(host) && host.getUuid(conn).equals(_host.uuid)) { + if (!pbd.getCurrentlyAttached(conn)) { + pbd.plug(conn); + } + SR sr = entry.getKey(); + sr.scan(conn); + return sr; + } + } + } + } + } catch (XenAPIException e) { + String msg = "Unable to get local EXTSR in host:" + _host.uuid + e.toString(); + s_logger.warn(msg); + } catch (XmlRpcException e) { + String msg = "Unable to get local EXTSR in host:" + _host.uuid + e.getCause(); + s_logger.warn(msg); + } + return null; + } + + protected StartupStorageCommand initializeLocalSR(Connection conn) { + SR lvmsr = getLocalLVMSR(conn); + if (lvmsr != null) { + try { + _host.localSRuuid = lvmsr.getUuid(conn); + + String lvmuuid = lvmsr.getUuid(conn); + long cap = lvmsr.getPhysicalSize(conn); + if (cap > 0) { + long avail = cap - lvmsr.getPhysicalUtilisation(conn); + lvmsr.setNameLabel(conn, lvmuuid); + String name = "Cloud Stack Local LVM Storage Pool for " + _host.uuid; + lvmsr.setNameDescription(conn, name); + Host host = Host.getByUuid(conn, _host.uuid); + String address = host.getAddress(conn); + StoragePoolInfo pInfo = new StoragePoolInfo(lvmuuid, address, SRType.LVM.toString(), SRType.LVM.toString(), StoragePoolType.LVM, cap, avail); + StartupStorageCommand cmd = new StartupStorageCommand(); + cmd.setPoolInfo(pInfo); + cmd.setGuid(_host.uuid); + cmd.setDataCenter(Long.toString(_dcId)); + cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); + return cmd; + } + } catch (XenAPIException e) { + String msg = "build local LVM info err in host:" + _host.uuid + e.toString(); + s_logger.warn(msg); + } catch (XmlRpcException e) { + String msg = "build local LVM info err in host:" + _host.uuid + e.getMessage(); + s_logger.warn(msg); + } + } + + SR extsr = getLocalEXTSR(conn); + if (extsr != null) { + try { + String extuuid = extsr.getUuid(conn); + _host.localSRuuid = extuuid; + long cap = extsr.getPhysicalSize(conn); + if (cap > 0) { + long avail = cap - extsr.getPhysicalUtilisation(conn); + extsr.setNameLabel(conn, extuuid); + String name = "Cloud Stack Local EXT Storage Pool for " + _host.uuid; + extsr.setNameDescription(conn, name); + Host host = Host.getByUuid(conn, _host.uuid); + String address = host.getAddress(conn); + StoragePoolInfo pInfo = new StoragePoolInfo(extuuid, address, SRType.EXT.toString(), SRType.EXT.toString(), StoragePoolType.EXT, cap, avail); + StartupStorageCommand cmd = new StartupStorageCommand(); + cmd.setPoolInfo(pInfo); + cmd.setGuid(_host.uuid); + cmd.setDataCenter(Long.toString(_dcId)); + cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); + return cmd; + } + } catch (XenAPIException e) { + String msg = "build local EXT info err in host:" + _host.uuid + e.toString(); + s_logger.warn(msg); + } catch (XmlRpcException e) { + String msg = "build local EXT info err in host:" + _host.uuid + e.getMessage(); + s_logger.warn(msg); + } + } + return null; + } + + @Override + public PingCommand getCurrentStatus(long id) { + try { + if (!pingXAPI()) { + Thread.sleep(1000); + if (!pingXAPI()) { + s_logger.warn(" can not ping xenserver " + _host.uuid); + return null; + } + } + Connection conn = getConnection(); + if (!_canBridgeFirewall && !_isOvs) { + return new PingRoutingCommand(getType(), id, null, getHostVmStateReport(conn)); + } else if (_isOvs) { + List> ovsStates = ovsFullSyncStates(); + return new PingRoutingWithOvsCommand(getType(), id, null, getHostVmStateReport(conn), ovsStates); + } else { + HashMap> nwGrpStates = syncNetworkGroups(conn, id); + return new PingRoutingWithNwGroupsCommand(getType(), id, null, getHostVmStateReport(conn), nwGrpStates); + } + } catch (Exception e) { + s_logger.warn("Unable to get current status", e); + return null; + } + } + + private HashMap> syncNetworkGroups(Connection conn, long id) { + HashMap> states = new HashMap>(); + + String result = callHostPlugin(conn, "vmops", "get_rule_logs_for_vms", "host_uuid", _host.uuid); + s_logger.trace("syncNetworkGroups: id=" + id + " got: " + result); + String[] rulelogs = result != null ? result.split(";") : new String[0]; + for (String rulesforvm : rulelogs) { + String[] log = rulesforvm.split(","); + if (log.length != 6) { + continue; + } + //output = ','.join([vmName, vmID, vmIP, domID, signature, seqno]) + try { + states.put(log[0], new Pair(Long.parseLong(log[1]), Long.parseLong(log[5]))); + } catch (NumberFormatException nfe) { + states.put(log[0], new Pair(-1L, -1L)); + } + } + return states; + } + + @Override + public Type getType() { + return com.cloud.host.Host.Type.Routing; + } + + protected boolean getHostInfo(Connection conn) throws IllegalArgumentException { + try { + Host myself = Host.getByUuid(conn, _host.uuid); + Set hcs = null; + for (int i = 0; i < 10; i++) { + hcs = myself.getHostCPUs(conn); + _host.cpus = hcs.size(); + if (_host.cpus > 0) { + break; + } + Thread.sleep(5000); + } + if (_host.cpus <= 0) { + throw new CloudRuntimeException("Cannot get the numbers of cpu from XenServer host " + _host.ip); + } + Map cpuInfo = myself.getCpuInfo(conn); + if (cpuInfo.get("socket_count") != null) { + _host.cpuSockets = Integer.parseInt(cpuInfo.get("socket_count")); + } + for (final HostCpu hc : hcs) { + _host.speed = hc.getSpeed(conn).intValue(); + break; + } + Host.Record hr = myself.getRecord(conn); + _host.productVersion = hr.softwareVersion.get("product_version"); + if (_host.productVersion == null) { + _host.productVersion = hr.softwareVersion.get("platform_version"); + } else { + _host.productVersion = _host.productVersion.trim(); + } + + XsLocalNetwork privateNic = getManagementNetwork(conn); + _privateNetworkName = privateNic.getNetworkRecord(conn).nameLabel; + _host.privatePif = privateNic.getPifRecord(conn).uuid; + _host.privateNetwork = privateNic.getNetworkRecord(conn).uuid; + _host.systemvmisouuid = null; + + XsLocalNetwork guestNic = null; + if (_guestNetworkName != null && !_guestNetworkName.equals(_privateNetworkName)) { + guestNic = getNetworkByName(conn, _guestNetworkName); + if (guestNic == null) { + s_logger.warn("Unable to find guest network " + _guestNetworkName); + throw new IllegalArgumentException("Unable to find guest network " + _guestNetworkName + " for host " + _host.ip); + } + } else { + guestNic = privateNic; + _guestNetworkName = _privateNetworkName; + } + _host.guestNetwork = guestNic.getNetworkRecord(conn).uuid; + _host.guestPif = guestNic.getPifRecord(conn).uuid; + + XsLocalNetwork publicNic = null; + if (_publicNetworkName != null && !_publicNetworkName.equals(_guestNetworkName)) { + publicNic = getNetworkByName(conn, _publicNetworkName); + if (publicNic == null) { + s_logger.warn("Unable to find public network " + _publicNetworkName + " for host " + _host.ip); + throw new IllegalArgumentException("Unable to find public network " + _publicNetworkName + " for host " + _host.ip); + } + } else { + publicNic = guestNic; + _publicNetworkName = _guestNetworkName; + } + _host.publicPif = publicNic.getPifRecord(conn).uuid; + _host.publicNetwork = publicNic.getNetworkRecord(conn).uuid; + if (_storageNetworkName1 == null) { + _storageNetworkName1 = _guestNetworkName; + } + XsLocalNetwork storageNic1 = null; + storageNic1 = getNetworkByName(conn, _storageNetworkName1); + if (storageNic1 == null) { + s_logger.warn("Unable to find storage network " + _storageNetworkName1 + " for host " + _host.ip); + throw new IllegalArgumentException("Unable to find storage network " + _storageNetworkName1 + " for host " + _host.ip); + } else { + _host.storageNetwork1 = storageNic1.getNetworkRecord(conn).uuid; + _host.storagePif1 = storageNic1.getPifRecord(conn).uuid; + } + + XsLocalNetwork storageNic2 = null; + if (_storageNetworkName2 != null) { + storageNic2 = getNetworkByName(conn, _storageNetworkName2); + _host.storageNetwork2 = storageNic2.getNetworkRecord(conn).uuid; + _host.storagePif2 = storageNic2.getPifRecord(conn).uuid; + } + + s_logger.info("Private Network is " + _privateNetworkName + " for host " + _host.ip); + s_logger.info("Guest Network is " + _guestNetworkName + " for host " + _host.ip); + s_logger.info("Public Network is " + _publicNetworkName + " for host " + _host.ip); + + return true; + } catch (XenAPIException e) { + s_logger.warn("Unable to get host information for " + _host.ip, e); + return false; + } catch (Exception e) { + s_logger.warn("Unable to get host information for " + _host.ip, e); + return false; + } + } + + protected void plugDom0Vif(Connection conn, VIF dom0Vif) throws XmlRpcException, XenAPIException { + if (dom0Vif != null) { + dom0Vif.plug(conn); + } + } + + private void setupLinkLocalNetwork(Connection conn) { + try { + Network.Record rec = new Network.Record(); + Set networks = Network.getByNameLabel(conn, _linkLocalPrivateNetworkName); + Network linkLocal = null; + + if (networks.size() == 0) { + rec.nameDescription = "link local network used by system vms"; + rec.nameLabel = _linkLocalPrivateNetworkName; + Map configs = new HashMap(); + configs.put("ip_begin", NetUtils.getLinkLocalGateway()); + configs.put("ip_end", NetUtils.getLinkLocalIpEnd()); + configs.put("netmask", NetUtils.getLinkLocalNetMask()); + rec.otherConfig = configs; + linkLocal = Network.create(conn, rec); + + } else { + linkLocal = networks.iterator().next(); + } + + /* Make sure there is a physical bridge on this network */ + VIF dom0vif = null; + Pair vm = getControlDomain(conn); + VM dom0 = vm.first(); + Set vifs = dom0.getVIFs(conn); + if (vifs.size() != 0) { + for (VIF vif : vifs) { + Map otherConfig = vif.getOtherConfig(conn); + if (otherConfig != null) { + String nameLabel = otherConfig.get("nameLabel"); + if ((nameLabel != null) && nameLabel.equalsIgnoreCase("link_local_network_vif")) { + dom0vif = vif; + } + } + } + } + + /* create temp VIF0 */ + if (dom0vif == null) { + s_logger.debug("Can't find a vif on dom0 for link local, creating a new one"); + VIF.Record vifr = new VIF.Record(); + vifr.VM = dom0; + vifr.device = getLowestAvailableVIFDeviceNum(conn, dom0); + if (vifr.device == null) { + s_logger.debug("Failed to create link local network, no vif available"); + return; + } + Map config = new HashMap(); + config.put("nameLabel", "link_local_network_vif"); + vifr.otherConfig = config; + vifr.MAC = "FE:FF:FF:FF:FF:FF"; + vifr.network = linkLocal; + vifr.lockingMode = Types.VifLockingMode.NETWORK_DEFAULT; + dom0vif = VIF.create(conn, vifr); + plugDom0Vif(conn, dom0vif); + } else { + s_logger.debug("already have a vif on dom0 for link local network"); + if (!dom0vif.getCurrentlyAttached(conn)) { + plugDom0Vif(conn, dom0vif); + } + } + + String brName = linkLocal.getBridge(conn); + callHostPlugin(conn, "vmops", "setLinkLocalIP", "brName", brName); + _host.linkLocalNetwork = linkLocal.getUuid(conn); + + } catch (XenAPIException e) { + s_logger.warn("Unable to create local link network", e); + throw new CloudRuntimeException("Unable to create local link network due to " + e.toString(), e); + } catch (XmlRpcException e) { + s_logger.warn("Unable to create local link network", e); + throw new CloudRuntimeException("Unable to create local link network due to " + e.toString(), e); + } + } + + protected boolean transferManagementNetwork(Connection conn, Host host, PIF src, PIF.Record spr, PIF dest) throws XmlRpcException, XenAPIException { + dest.reconfigureIp(conn, spr.ipConfigurationMode, spr.IP, spr.netmask, spr.gateway, spr.DNS); + Host.managementReconfigure(conn, dest); + String hostUuid = null; + int count = 0; + while (count < 10) { + try { + Thread.sleep(10000); + hostUuid = host.getUuid(conn); + if (hostUuid != null) { + break; + } + } catch (XmlRpcException e) { + s_logger.debug("Waiting for host to come back: " + e.getMessage()); + } catch (XenAPIException e) { + s_logger.debug("Waiting for host to come back: " + e.getMessage()); + } catch (InterruptedException e) { + s_logger.debug("Gotta run"); + return false; + } + } + if (hostUuid == null) { + s_logger.warn("Unable to transfer the management network from " + spr.uuid); + return false; + } + + src.reconfigureIp(conn, Types.IpConfigurationMode.NONE, null, null, null, null); + return true; + } + + @Override + public StartupCommand[] initialize() throws IllegalArgumentException { + Connection conn = getConnection(); + if (!getHostInfo(conn)) { + s_logger.warn("Unable to get host information for " + _host.ip); + return null; + } + StartupRoutingCommand cmd = new StartupRoutingCommand(); + fillHostInfo(conn, cmd); + cmd.setHypervisorType(HypervisorType.XenServer); + cmd.setCluster(_cluster); + cmd.setPoolSync(false); + cmd.setHostVmStateReport(getHostVmStateReport(conn)); + + Pool pool; + try { + pool = Pool.getByUuid(conn, _host.pool); + Pool.Record poolr = pool.getRecord(conn); + + Host.Record hostr = poolr.master.getRecord(conn); + if (_host.uuid.equals(hostr.uuid)) { + HashMap> allStates = fullClusterSync(conn); + cmd.setClusterVMStateChanges(allStates); + } + } catch (Throwable e) { + s_logger.warn("Check for master failed, failing the FULL Cluster sync command"); + } + + StartupStorageCommand sscmd = initializeLocalSR(conn); + if (sscmd != null) { + return new StartupCommand[] {cmd, sscmd}; + } + return new StartupCommand[] {cmd}; + } + + private void cleanupTemplateSR(Connection conn) { + Set pbds = null; + try { + Host host = Host.getByUuid(conn, _host.uuid); + pbds = host.getPBDs(conn); + } catch (XenAPIException e) { + s_logger.warn("Unable to get the SRs " + e.toString(), e); + throw new CloudRuntimeException("Unable to get SRs " + e.toString(), e); + } catch (Exception e) { + throw new CloudRuntimeException("Unable to get SRs " + e.getMessage(), e); + } + for (PBD pbd : pbds) { + SR sr = null; + SR.Record srRec = null; + try { + sr = pbd.getSR(conn); + srRec = sr.getRecord(conn); + } catch (Exception e) { + s_logger.warn("pbd.getSR get Exception due to ", e); + continue; + } + String type = srRec.type; + if (srRec.shared) { + continue; + } + if (SRType.NFS.equals(type) || (SRType.ISO.equals(type) && srRec.nameDescription.contains("template"))) { + try { + pbd.unplug(conn); + pbd.destroy(conn); + sr.forget(conn); + } catch (Exception e) { + s_logger.warn("forget SR catch Exception due to ", e); + } + } + } + } + + protected boolean launchHeartBeat(Connection conn) { + String result = callHostPluginPremium(conn, "heartbeat", "host", _host.uuid, "interval", Integer + .toString(_heartbeatInterval)); + if (result == null || !result.contains("> DONE <")) { + s_logger.warn("Unable to launch the heartbeat process on " + _host.ip); + return false; + } + return true; + } + + protected SetupAnswer execute(SetupCommand cmd) { + Connection conn = getConnection(); + setupServer(conn); + try { + if (!setIptables(conn)) { + s_logger.warn("set xenserver Iptable failed"); + return null; + } + + if (_securityGroupEnabled) { + _canBridgeFirewall = can_bridge_firewall(conn); + if (!_canBridgeFirewall) { + String msg = "Failed to configure brige firewall"; + s_logger.warn(msg); + s_logger.warn("Check host " + _host.ip +" for CSP is installed or not and check network mode for bridge"); + return new SetupAnswer(cmd, msg); + } + + } + + + boolean r = launchHeartBeat(conn); + if (!r) { + return null; + } + cleanupTemplateSR(conn); + Host host = Host.getByUuid(conn, _host.uuid); + try { + if (cmd.useMultipath()) { + // the config value is set to true + host.addToOtherConfig(conn, "multipathing", "true"); + host.addToOtherConfig(conn, "multipathhandle", "dmp"); + } + + } catch (Types.MapDuplicateKey e) { + s_logger.debug("multipath is already set"); + } + + if (cmd.needSetup() ) { + String result = callHostPlugin(conn, "vmops", "setup_iscsi", "uuid", _host.uuid); + + if (!result.contains("> DONE <")) { + s_logger.warn("Unable to setup iscsi: " + result); + return new SetupAnswer(cmd, result); + } + + Pair mgmtPif = null; + Set hostPifs = host.getPIFs(conn); + for (PIF pif : hostPifs) { + PIF.Record rec = pif.getRecord(conn); + if (rec.management) { + if (rec.VLAN != null && rec.VLAN != -1) { + String msg = + new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.uuid) + .append("; pif=") + .append(rec.uuid) + .append("; vlan=") + .append(rec.VLAN) + .toString(); + s_logger.warn(msg); + return new SetupAnswer(cmd, msg); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Management network is on pif=" + rec.uuid); + } + mgmtPif = new Pair(pif, rec); + break; + } + } + + if (mgmtPif == null) { + String msg = "Unable to find management network for " + _host.uuid; + s_logger.warn(msg); + return new SetupAnswer(cmd, msg); + } + + Map networks = Network.getAllRecords(conn); + for (Network.Record network : networks.values()) { + if (network.nameLabel.equals("cloud-private")) { + for (PIF pif : network.PIFs) { + PIF.Record pr = pif.getRecord(conn); + if (_host.uuid.equals(pr.host.getUuid(conn))) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found a network called cloud-private. host=" + _host.uuid + "; Network=" + network.uuid + "; pif=" + pr.uuid); + } + if (pr.VLAN != null && pr.VLAN != -1) { + String msg = + new StringBuilder("Unsupported configuration. Network cloud-private is on a VLAN. Network=").append(network.uuid) + .append(" ; pif=") + .append(pr.uuid) + .toString(); + s_logger.warn(msg); + return new SetupAnswer(cmd, msg); + } + if (!pr.management && pr.bondMasterOf != null && pr.bondMasterOf.size() > 0) { + if (pr.bondMasterOf.size() > 1) { + String msg = + new StringBuilder("Unsupported configuration. Network cloud-private has more than one bond. Network=").append(network.uuid) + .append("; pif=") + .append(pr.uuid) + .toString(); + s_logger.warn(msg); + return new SetupAnswer(cmd, msg); + } + Bond bond = pr.bondMasterOf.iterator().next(); + Set slaves = bond.getSlaves(conn); + for (PIF slave : slaves) { + PIF.Record spr = slave.getRecord(conn); + if (spr.management) { + if (!transferManagementNetwork(conn, host, slave, spr, pif)) { + String msg = + new StringBuilder("Unable to transfer management network. slave=" + spr.uuid + "; master=" + pr.uuid + "; host=" + + _host.uuid).toString(); + s_logger.warn(msg); + return new SetupAnswer(cmd, msg); + } + break; + } + } + } + } + } + } + } + } + return new SetupAnswer(cmd, false); + + } catch (XmlRpcException e) { + s_logger.warn("Unable to setup", e); + return new SetupAnswer(cmd, e.getMessage()); + } catch (XenAPIException e) { + s_logger.warn("Unable to setup", e); + return new SetupAnswer(cmd, e.getMessage()); + } catch (Exception e) { + s_logger.warn("Unable to setup", e); + return new SetupAnswer(cmd, e.getMessage()); + } + } + + /* return : if setup is needed */ + protected boolean setupServer(Connection conn) { + String packageVersion = CitrixResourceBase.class.getPackage().getImplementationVersion(); + String version = this.getClass().getName() + "-" + (packageVersion == null ? Long.toString(System.currentTimeMillis()) : packageVersion); + + try { + Host host = Host.getByUuid(conn, _host.uuid); + /* enable host in case it is disabled somehow */ + host.enable(conn); + /* push patches to XenServer */ + Host.Record hr = host.getRecord(conn); + + Iterator it = hr.tags.iterator(); + + while (it.hasNext()) { + String tag = it.next(); + if (tag.startsWith("vmops-version-")) { + if (tag.contains(version)) { + s_logger.info(logX(host, "Host " + hr.address + " is already setup.")); + return false; + } else { + it.remove(); + } + } + } + + com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(hr.address, 22); + try { + sshConnection.connect(null, 60000, 60000); + if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { + throw new CloudRuntimeException("Unable to authenticate"); + } + + com.trilead.ssh2.Session session = sshConnection.openSession(); + + String cmd = "mkdir -p /opt/cloud/bin /var/log/cloud"; + if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) { + throw new CloudRuntimeException("Cannot create directory /opt/cloud/bin on XenServer hosts"); + } + + SCPClient scp = new SCPClient(sshConnection); + + List files = getPatchFiles(); + if (files == null || files.isEmpty()) { + throw new CloudRuntimeException("Can not find patch file"); + } + for (File file : files) { + String path = file.getParentFile().getAbsolutePath() + "/"; + Properties props = new Properties(); + props.load(new FileInputStream(file)); + + for (Map.Entry entry : props.entrySet()) { + String k = (String)entry.getKey(); + String v = (String)entry.getValue(); + + assert (k != null && k.length() > 0 && v != null && v.length() > 0) : "Problems with " + k + "=" + v; + + String[] tokens = v.split(","); + String f = null; + if (tokens.length == 3 && tokens[0].length() > 0) { + if (tokens[0].startsWith("/")) { + f = tokens[0]; + } else if (tokens[0].startsWith("~")) { + String homedir = System.getenv("HOME"); + f = homedir + tokens[0].substring(1) + k; + } else { + f = path + tokens[0] + '/' + k; + } + } else { + f = path + k; + } + String d = tokens[tokens.length - 1]; + f = f.replace('/', File.separatorChar); + + String p = "0755"; + if (tokens.length == 3) { + p = tokens[1]; + } else if (tokens.length == 2) { + p = tokens[0]; + } + + if (!new File(f).exists()) { + s_logger.warn("We cannot locate " + f); + continue; + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Copying " + f + " to " + d + " on " + hr.address + " with permission " + p); + } + try { + session.execCommand("mkdir -m 700 -p " + d); + } catch (IOException e) { + s_logger.debug("Unable to create destination path: " + d + " on " + hr.address + " but trying anyway"); + + } + scp.put(f, d, p); + + } + } + + } catch (IOException e) { + throw new CloudRuntimeException("Unable to setup the server correctly", e); + } finally { + sshConnection.close(); + } + hr.tags.add("vmops-version-" + version); + host.setTags(conn, hr.tags); + return true; + } catch (XenAPIException e) { + String msg = "Xen setup failed due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException("Unable to get host information " + e.toString(), e); + } catch (XmlRpcException e) { + String msg = "Xen setup failed due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException("Unable to get host information ", e); + } + } + + protected CheckNetworkAnswer execute(CheckNetworkCommand cmd) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Checking if network name setup is done on the resource"); + } + + List infoList = cmd.getPhysicalNetworkInfoList(); + + try { + boolean errorout = false; + String msg = ""; + for (PhysicalNetworkSetupInfo info : infoList) { + if (!isNetworkSetupByName(info.getGuestNetworkName())) { + msg = + "For Physical Network id:" + info.getPhysicalNetworkId() + ", Guest Network is not configured on the backend by name " + + info.getGuestNetworkName(); + errorout = true; + break; + } + if (!isNetworkSetupByName(info.getPrivateNetworkName())) { + msg = + "For Physical Network id:" + info.getPhysicalNetworkId() + ", Private Network is not configured on the backend by name " + + info.getPrivateNetworkName(); + errorout = true; + break; + } + if (!isNetworkSetupByName(info.getPublicNetworkName())) { + msg = + "For Physical Network id:" + info.getPhysicalNetworkId() + ", Public Network is not configured on the backend by name " + + info.getPublicNetworkName(); + errorout = true; + break; + } + /*if(!isNetworkSetupByName(info.getStorageNetworkName())){ + msg = "For Physical Network id:"+ info.getPhysicalNetworkId() + ", Storage Network is not configured on the backend by name " + info.getStorageNetworkName(); + errorout = true; + break; + }*/ + } + if (errorout) { + s_logger.error(msg); + return new CheckNetworkAnswer(cmd, false, msg); + } else { + return new CheckNetworkAnswer(cmd, true, "Network Setup check by names is done"); + } + + } catch (XenAPIException e) { + String msg = "CheckNetworkCommand failed with XenAPIException:" + e.toString() + " host:" + _host.uuid; + s_logger.warn(msg, e); + return new CheckNetworkAnswer(cmd, false, msg); + } catch (Exception e) { + String msg = "CheckNetworkCommand failed with Exception:" + e.getMessage() + " host:" + _host.uuid; + s_logger.warn(msg, e); + return new CheckNetworkAnswer(cmd, false, msg); + } + } + + protected boolean isNetworkSetupByName(String nameTag) throws XenAPIException, XmlRpcException { + if (nameTag != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Looking for network setup by name " + nameTag); + } + Connection conn = getConnection(); + XsLocalNetwork network = getNetworkByName(conn, nameTag); + if (network == null) { + return false; + } + } + return true; + } + + protected List getPatchFiles() { + return null; + } + + protected SR getSRByNameLabelandHost(Connection conn, String name) throws BadServerResponse, XenAPIException, XmlRpcException { + Set srs = SR.getByNameLabel(conn, name); + SR ressr = null; + for (SR sr : srs) { + Set pbds; + pbds = sr.getPBDs(conn); + for (PBD pbd : pbds) { + PBD.Record pbdr = pbd.getRecord(conn); + if (pbdr.host != null && pbdr.host.getUuid(conn).equals(_host.uuid)) { + if (!pbdr.currentlyAttached) { + pbd.plug(conn); + } + ressr = sr; + break; + } + } + } + return ressr; + } + + protected GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) { + Connection conn = getConnection(); + try { + Set srs = SR.getByNameLabel(conn, cmd.getStorageId()); + if (srs.size() != 1) { + String msg = "There are " + srs.size() + " storageid: " + cmd.getStorageId(); + s_logger.warn(msg); + return new GetStorageStatsAnswer(cmd, msg); + } + SR sr = srs.iterator().next(); + sr.scan(conn); + long capacity = sr.getPhysicalSize(conn); + long used = sr.getPhysicalUtilisation(conn); + return new GetStorageStatsAnswer(cmd, capacity, used); + } catch (XenAPIException e) { + String msg = "GetStorageStats Exception:" + e.toString() + "host:" + _host.uuid + "storageid: " + cmd.getStorageId(); + s_logger.warn(msg); + return new GetStorageStatsAnswer(cmd, msg); + } catch (XmlRpcException e) { + String msg = "GetStorageStats Exception:" + e.getMessage() + "host:" + _host.uuid + "storageid: " + cmd.getStorageId(); + s_logger.warn(msg); + return new GetStorageStatsAnswer(cmd, msg); + } + } + + private void pbdPlug(Connection conn, PBD pbd, String uuid) { + try { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Plugging in PBD " + uuid + " for " + _host); + } + pbd.plug(conn); + } catch (Exception e) { + String msg = "PBD " + uuid + " is not attached! and PBD plug failed due to " + e.toString() + ". Please check this PBD in " + _host; + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } + } + + protected boolean checkSR(Connection conn, SR sr) { + try { + SR.Record srr = sr.getRecord(conn); + Set pbds = sr.getPBDs(conn); + if (pbds.size() == 0) { + String msg = "There is no PBDs for this SR: " + srr.nameLabel + " on host:" + _host.uuid; + s_logger.warn(msg); + return false; + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Checking " + srr.nameLabel + " or SR " + srr.uuid + " on " + _host); + } + if (srr.shared) { + if (SRType.NFS.equals(srr.type) ){ + Map smConfig = srr.smConfig; + if( !smConfig.containsKey("nosubdir")) { + smConfig.put("nosubdir", "true"); + sr.setSmConfig(conn,smConfig); + } + } + + Host host = Host.getByUuid(conn, _host.uuid); + boolean found = false; + for (PBD pbd : pbds) { + PBD.Record pbdr = pbd.getRecord(conn); + if (host.equals(pbdr.host)) { + if (!pbdr.currentlyAttached) { + pbdPlug(conn, pbd, pbdr.uuid); + } + found = true; + break; + } + } + if (!found) { + PBD.Record pbdr = srr.PBDs.iterator().next().getRecord(conn); + pbdr.host = host; + pbdr.uuid = ""; + PBD pbd = PBD.create(conn, pbdr); + pbdPlug(conn, pbd, pbd.getUuid(conn)); + } + } else { + for (PBD pbd : pbds) { + PBD.Record pbdr = pbd.getRecord(conn); + if (!pbdr.currentlyAttached) { + pbdPlug(conn, pbd, pbdr.uuid); + } + } + } + + } catch (Exception e) { + String msg = "checkSR failed host:" + _host + " due to " + e.toString(); + s_logger.warn(msg, e); + return false; + } + return true; + } + + protected Answer execute(CreateStoragePoolCommand cmd) { + Connection conn = getConnection(); + StorageFilerTO pool = cmd.getPool(); + try { + if (pool.getType() == StoragePoolType.NetworkFilesystem) { + getNfsSR(conn, pool); + } else if (pool.getType() == StoragePoolType.IscsiLUN) { + getIscsiSR(conn, pool.getUuid(), pool.getHost(), pool.getPath(), null, null, false); + } else if (pool.getType() == StoragePoolType.PreSetup) { + } else { + return new Answer(cmd, false, "The pool type: " + pool.getType().name() + " is not supported."); + } + return new Answer(cmd, true, "success"); + } catch (Exception e) { + String msg = + "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + _host.uuid + " pool: " + + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + + } + + protected String callHostPluginThroughMaster(Connection conn, String plugin, String cmd, String... params) { + Map args = new HashMap(); + + try { + Map poolRecs = Pool.getAllRecords(conn); + if (poolRecs.size() != 1) { + throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + _host.uuid); + } + Host master = poolRecs.values().iterator().next().master; + for (int i = 0; i < params.length; i += 2) { + args.put(params[i], params[i + 1]); + } + + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); + } + String result = master.callPlugin(conn, plugin, cmd, args); + if (s_logger.isTraceEnabled()) { + s_logger.trace("callHostPlugin Result: " + result); + } + return result.replace("\n", ""); + } catch (Types.HandleInvalid e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + + e.handle); + } catch (XenAPIException e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString(), e); + } catch (XmlRpcException e) { + s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage(), e); + } + return null; + } + + protected String callHostPluginPremium(Connection conn, String cmd, String... params) { + return callHostPlugin(conn, "vmopspremium", cmd, params); + } + + protected String setupHeartbeatSr(Connection conn, SR sr, boolean force) throws XenAPIException, XmlRpcException { + SR.Record srRec = sr.getRecord(conn); + String srUuid = srRec.uuid; + if (!srRec.shared || (!SRType.LVMOHBA.equals(srRec.type) && !SRType.LVMOISCSI.equals(srRec.type) && !SRType.NFS.equals(srRec.type))) { + return srUuid; + } + String result = null; + Host host = Host.getByUuid(conn, _host.uuid); + Set tags = host.getTags(conn); + if (force || !tags.contains("cloud-heartbeat-" + srUuid)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Setting up the heartbeat sr for host " + _host.ip + " and sr " + srUuid); + } + Set pbds = sr.getPBDs(conn); + for (PBD pbd : pbds) { + PBD.Record pbdr = pbd.getRecord(conn); + if (!pbdr.currentlyAttached && pbdr.host.getUuid(conn).equals(_host.uuid)) { + pbd.plug(conn); + break; + } + } + result = callHostPluginThroughMaster(conn, "vmopspremium", "setup_heartbeat_sr", "host", _host.uuid, "sr", srUuid); + if (result == null || !result.split("#")[1].equals("0")) { + throw new CloudRuntimeException("Unable to setup heartbeat sr on SR " + srUuid + " due to " + result); + } + + if (!tags.contains("cloud-heartbeat-" + srUuid)) { + tags.add("cloud-heartbeat-" + srUuid); + host.setTags(conn, tags); + } + } + result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "true"); + if (result == null || !result.split("#")[1].equals("0")) { + throw new CloudRuntimeException("Unable to setup heartbeat file entry on SR " + srUuid + " due to " + result); + } + return srUuid; + } + + protected Answer execute(ModifyStoragePoolCommand cmd) { + Connection conn = getConnection(); + StorageFilerTO pool = cmd.getPool(); + boolean add = cmd.getAdd(); + if (add) { + try { + SR sr = getStorageRepository(conn, pool.getUuid()); + setupHeartbeatSr(conn, sr, false); + long capacity = sr.getPhysicalSize(conn); + long available = capacity - sr.getPhysicalUtilisation(conn); + if (capacity == -1) { + String msg = "Pool capacity is -1! pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg); + return new Answer(cmd, false, msg); + } + Map tInfo = new HashMap(); + ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo); + return answer; + } catch (XenAPIException e) { + String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.toString() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } catch (Exception e) { + String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + } else { + try { + SR sr = getStorageRepository(conn, pool.getUuid()); + String srUuid = sr.getUuid(conn); + String result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "false"); + if (result == null || !result.split("#")[1].equals("0")) { + throw new CloudRuntimeException("Unable to remove heartbeat file entry for SR " + srUuid + " due to " + result); + } + return new Answer(cmd, true, "seccuss"); + } catch (XenAPIException e) { + String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.toString() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } catch (Exception e) { + String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + } + + } + + protected boolean can_bridge_firewall(Connection conn) { + return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.uuid, "instance", _instance)); + } + + private Answer execute(OvsSetupBridgeCommand cmd) { + Connection conn = getConnection(); + findOrCreateTunnelNetwork(conn, cmd.getBridgeName()); + configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getHostId(), cmd.getBridgeName()); + s_logger.debug("OVS Bridge configured"); + return new Answer(cmd, true, null); + } + + private Answer execute(OvsDestroyBridgeCommand cmd) { + Connection conn = getConnection(); + destroyTunnelNetwork(conn, cmd.getBridgeName()); + s_logger.debug("OVS Bridge destroyed"); + return new Answer(cmd, true, null); + } + + private Answer execute(OvsDestroyTunnelCommand cmd) { + Connection conn = getConnection(); + try { + Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName()); + if (nw == null) { + s_logger.warn("Unable to find tunnel network for GRE key:" + cmd.getBridgeName()); + return new Answer(cmd, false, "No network found"); + } + + String bridge = nw.getBridge(conn); + String result = callHostPlugin(conn, "ovstunnel", "destroy_tunnel", "bridge", bridge, "in_port", cmd.getInPortName()); + + if (result.equalsIgnoreCase("SUCCESS")) { + return new Answer(cmd, true, result); + } else { + return new Answer(cmd, false, result); + } + } catch (Exception e) { + s_logger.warn("caught execption when destroy ovs tunnel", e); + return new Answer(cmd, false, e.getMessage()); + } + } + + public Answer execute(OvsVpcPhysicalTopologyConfigCommand cmd) { + Connection conn = getConnection(); + try { + Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName()); + String bridgeName = nw.getBridge(conn); + String result = callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_network_topology", "bridge", + bridgeName, "config", cmd.getVpcConfigInJson(), "host-id", ((Long)cmd.getHostId()).toString()); + if (result.startsWith("SUCCESS")) { + return new Answer(cmd, true, result); + } else { + return new Answer(cmd, false, result); + } + } catch (Exception e) { + s_logger.warn("caught exception while updating host with latest VPC topology", e); + return new Answer(cmd, false, e.getMessage()); + } + } + + public Answer execute(OvsVpcRoutingPolicyConfigCommand cmd) { + Connection conn = getConnection(); + try { + Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName()); + String bridgeName = nw.getBridge(conn); + + String result = callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_routing_policies", "bridge", + bridgeName, "host-id", ((Long)cmd.getHostId()).toString(), "config", + cmd.getVpcConfigInJson()); + if (result.startsWith("SUCCESS")) { + return new Answer(cmd, true, result); + } else { + return new Answer(cmd, false, result); + } + } catch (Exception e) { + s_logger.warn("caught exception while updating host with latest routing policies", e); + return new Answer(cmd, false, e.getMessage()); + } + } + + private Answer execute(UpdateHostPasswordCommand cmd) { + _password.add(cmd.getNewPassword()); + return new Answer(cmd, true, null); + } + + private OvsCreateTunnelAnswer execute(OvsCreateTunnelCommand cmd) { + Connection conn = getConnection(); + String bridge = "unknown"; + try { + Network nw = findOrCreateTunnelNetwork(conn, cmd.getNetworkName()); + if (nw == null) { + s_logger.debug("Error during bridge setup"); + return new OvsCreateTunnelAnswer(cmd, false, "Cannot create network", bridge); + } + + configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getFrom(), cmd.getNetworkName()); + bridge = nw.getBridge(conn); + String result = + callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", cmd.getRemoteIp(), + "key", cmd.getKey().toString(), "from", + cmd.getFrom().toString(), "to", cmd.getTo().toString(), "cloudstack-network-id", + cmd.getNetworkUuid()); + String[] res = result.split(":"); + if (res.length == 2 && res[0].equalsIgnoreCase("SUCCESS")) { + return new OvsCreateTunnelAnswer(cmd, true, result, res[1], bridge); + } else { + return new OvsCreateTunnelAnswer(cmd, false, result, bridge); + } + } catch (Exception e) { + s_logger.debug("Error during tunnel setup"); + s_logger.warn("Caught execption when creating ovs tunnel", e); + return new OvsCreateTunnelAnswer(cmd, false, e.getMessage(), bridge); + } + } + + private Answer execute(OvsDeleteFlowCommand cmd) { + _isOvs = true; + + Connection conn = getConnection(); + try { + Network nw = setupvSwitchNetwork(conn); + String bridge = nw.getBridge(conn); + String result = callHostPlugin(conn, "ovsgre", "ovs_delete_flow", "bridge", bridge, "vmName", cmd.getVmName()); + + if (result.equalsIgnoreCase("SUCCESS")) { + return new Answer(cmd, true, "success to delete flows for " + cmd.getVmName()); + } else { + return new Answer(cmd, false, result); + } + } catch (BadServerResponse e) { + s_logger.error("Failed to delete flow", e); + } catch (XenAPIException e) { + s_logger.error("Failed to delete flow", e); + } catch (XmlRpcException e) { + s_logger.error("Failed to delete flow", e); + } + return new Answer(cmd, false, "failed to delete flow for " + cmd.getVmName()); + } + + private List> ovsFullSyncStates() { + Connection conn = getConnection(); + String result = callHostPlugin(conn, "ovsgre", "ovs_get_vm_log", "host_uuid", _host.uuid); + String[] logs = result != null ? result.split(";") : new String[0]; + List> states = new ArrayList>(); + for (String log : logs) { + String[] info = log.split(","); + if (info.length != 5) { + s_logger.warn("Wrong element number in ovs log(" + log + ")"); + continue; + } + + //','.join([bridge, vmName, vmId, seqno, tag]) + try { + states.add(new Pair(info[0], Long.parseLong(info[3]))); + } catch (NumberFormatException nfe) { + states.add(new Pair(info[0], -1L)); + } + } + return states; + } + + private OvsSetTagAndFlowAnswer execute(OvsSetTagAndFlowCommand cmd) { + _isOvs = true; + + Connection conn = getConnection(); + try { + Network nw = setupvSwitchNetwork(conn); + String bridge = nw.getBridge(conn); + + /*If VM is domainRouter, this will try to set flow and tag on its + * none guest network nic. don't worry, it will fail silently at host + * plugin side + */ + String result = + callHostPlugin(conn, "ovsgre", "ovs_set_tag_and_flow", "bridge", bridge, "vmName", cmd.getVmName(), "tag", cmd.getTag(), "vlans", cmd.getVlans(), + "seqno", cmd.getSeqNo()); + s_logger.debug("set flow for " + cmd.getVmName() + " " + result); + + if (result.equalsIgnoreCase("SUCCESS")) { + return new OvsSetTagAndFlowAnswer(cmd, true, result); + } else { + return new OvsSetTagAndFlowAnswer(cmd, false, result); + } + } catch (BadServerResponse e) { + s_logger.error("Failed to set tag and flow", e); + } catch (XenAPIException e) { + s_logger.error("Failed to set tag and flow", e); + } catch (XmlRpcException e) { + s_logger.error("Failed to set tag and flow", e); + } + + return new OvsSetTagAndFlowAnswer(cmd, false, "EXCEPTION"); + } + + private OvsFetchInterfaceAnswer execute(OvsFetchInterfaceCommand cmd) { + + String label = cmd.getLabel(); + //FIXME: this is a tricky to pass the network checking in XCP. I temporary get default label from Host. + if (is_xcp()) { + label = getLabel(); + } + s_logger.debug("Will look for network with name-label:" + label + " on host " + _host.ip); + Connection conn = getConnection(); + try { + XsLocalNetwork nw = getNetworkByName(conn, label); + s_logger.debug("Network object:" + nw.getNetwork().getUuid(conn)); + PIF pif = nw.getPif(conn); + PIF.Record pifRec = pif.getRecord(conn); + s_logger.debug("PIF object:" + pifRec.uuid + "(" + pifRec.device + ")"); + return new OvsFetchInterfaceAnswer(cmd, true, "Interface " + pifRec.device + " retrieved successfully", pifRec.IP, pifRec.netmask, pifRec.MAC); + } catch (BadServerResponse e) { + s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.ip, e); + return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage()); + } catch (XenAPIException e) { + s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.ip, e); + return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage()); + } catch (XmlRpcException e) { + s_logger.error("An error occurred while fetching the interface for " + label + " on host " + _host.ip, e); + return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage()); + } + } + + private OvsCreateGreTunnelAnswer execute(OvsCreateGreTunnelCommand cmd) { + _isOvs = true; + + Connection conn = getConnection(); + String bridge = "unkonwn"; + try { + Network nw = setupvSwitchNetwork(conn); + bridge = nw.getBridge(conn); + + String result = + callHostPlugin(conn, "ovsgre", "ovs_create_gre", "bridge", bridge, "remoteIP", cmd.getRemoteIp(), "greKey", cmd.getKey(), "from", + Long.toString(cmd.getFrom()), "to", Long.toString(cmd.getTo())); + String[] res = result.split(":"); + if (res.length != 2 || (res.length == 2 && res[1].equalsIgnoreCase("[]"))) { + return new OvsCreateGreTunnelAnswer(cmd, false, result, _host.ip, bridge); + } else { + return new OvsCreateGreTunnelAnswer(cmd, true, result, _host.ip, bridge, Integer.parseInt(res[1])); + } + } catch (BadServerResponse e) { + s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.ip, e); + } catch (XenAPIException e) { + s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.ip, e); + } catch (XmlRpcException e) { + s_logger.error("An error occurred while creating a GRE tunnel to " + cmd.getRemoteIp() + " on host " + _host.ip, e); + } + + return new OvsCreateGreTunnelAnswer(cmd, false, "EXCEPTION", _host.ip, bridge); + } + + private Answer execute(SecurityGroupRulesCmd cmd) { + Connection conn = getConnection(); + if (s_logger.isTraceEnabled()) { + s_logger.trace("Sending network rules command to " + _host.ip); + } + + if (!_canBridgeFirewall) { + s_logger.warn("Host " + _host.ip + " cannot do bridge firewalling"); + return new SecurityGroupRuleAnswer(cmd, false, "Host " + _host.ip + " cannot do bridge firewalling", + SecurityGroupRuleAnswer.FailureReason.CANNOT_BRIDGE_FIREWALL); + } + + String result = + callHostPlugin(conn, "vmops", "network_rules", "vmName", cmd.getVmName(), "vmIP", cmd.getGuestIp(), "vmMAC", cmd.getGuestMac(), "vmID", + Long.toString(cmd.getVmId()), "signature", cmd.getSignature(), "seqno", Long.toString(cmd.getSeqNum()), "deflated", "true", "rules", + cmd.compressStringifiedRules(), "secIps", cmd.getSecIpsString()); + + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program network rules for vm " + cmd.getVmName()); + return new SecurityGroupRuleAnswer(cmd, false, "programming network rules failed"); + } else { + s_logger.info("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", ingress numrules=" + cmd.getIngressRuleSet().length + + ", egress numrules=" + cmd.getEgressRuleSet().length); + return new SecurityGroupRuleAnswer(cmd); + } + } + + protected Answer execute(DeleteStoragePoolCommand cmd) { + Connection conn = getConnection(); + StorageFilerTO poolTO = cmd.getPool(); + try { + SR sr = getStorageRepository(conn, poolTO.getUuid()); + removeSR(conn, sr); + Answer answer = new Answer(cmd, true, "success"); + return answer; + } catch (Exception e) { + String msg = "DeleteStoragePoolCommand XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + poolTO.getHost() + poolTO.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + + } + + public Connection getConnection() { + return ConnPool.connect(_host.uuid, _host.pool, _host.ip, _username, _password, _wait); + } + + + protected void fillHostInfo(Connection conn, StartupRoutingCommand cmd) { + final StringBuilder caps = new StringBuilder(); + try { + + Host host = Host.getByUuid(conn, _host.uuid); + Host.Record hr = host.getRecord(conn); + + Map details = cmd.getHostDetails(); + if (details == null) { + details = new HashMap(); + } + + String productBrand = hr.softwareVersion.get("product_brand"); + if (productBrand == null) { + productBrand = hr.softwareVersion.get("platform_name"); + } + details.put("product_brand", productBrand); + details.put("product_version", _host.productVersion); + if (hr.softwareVersion.get("product_version_text_short") != null) { + details.put("product_version_text_short", hr.softwareVersion.get("product_version_text_short")); + cmd.setHypervisorVersion(hr.softwareVersion.get("product_version_text_short")); + + cmd.setHypervisorVersion(_host.productVersion); + } + if (_privateNetworkName != null) { + details.put("private.network.device", _privateNetworkName); + } + + cmd.setHostDetails(details); + cmd.setName(hr.nameLabel); + cmd.setGuid(_host.uuid); + cmd.setPool(_host.pool); + cmd.setDataCenter(Long.toString(_dcId)); + for (final String cap : hr.capabilities) { + if (cap.length() > 0) { + caps.append(cap).append(" , "); + } + } + if (caps.length() > 0) { + caps.delete(caps.length() - 3, caps.length()); + } + cmd.setCaps(caps.toString()); + + cmd.setSpeed(_host.speed); + cmd.setCpuSockets(_host.cpuSockets); + cmd.setCpus(_host.cpus); + + HostMetrics hm = host.getMetrics(conn); + + long ram = 0; + long dom0Ram = 0; + ram = hm.getMemoryTotal(conn); + Set vms = host.getResidentVMs(conn); + for (VM vm : vms) { + if (vm.getIsControlDomain(conn)) { + dom0Ram = vm.getMemoryStaticMax(conn); + break; + } + } + + ram = (long)((ram - dom0Ram - _xsMemoryUsed) * _xsVirtualizationFactor); + cmd.setMemory(ram); + cmd.setDom0MinMemory(dom0Ram); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Total Ram: " + ram + " dom0 Ram: " + dom0Ram); + } + + PIF pif = PIF.getByUuid(conn, _host.privatePif); + PIF.Record pifr = pif.getRecord(conn); + if (pifr.IP != null && pifr.IP.length() > 0) { + cmd.setPrivateIpAddress(pifr.IP); + cmd.setPrivateMacAddress(pifr.MAC); + cmd.setPrivateNetmask(pifr.netmask); + } else { + cmd.setPrivateIpAddress(_host.ip); + cmd.setPrivateMacAddress(pifr.MAC); + cmd.setPrivateNetmask("255.255.255.0"); + } + + pif = PIF.getByUuid(conn, _host.publicPif); + pifr = pif.getRecord(conn); + if (pifr.IP != null && pifr.IP.length() > 0) { + cmd.setPublicIpAddress(pifr.IP); + cmd.setPublicMacAddress(pifr.MAC); + cmd.setPublicNetmask(pifr.netmask); + } + + if (_host.storagePif1 != null) { + pif = PIF.getByUuid(conn, _host.storagePif1); + pifr = pif.getRecord(conn); + if (pifr.IP != null && pifr.IP.length() > 0) { + cmd.setStorageIpAddress(pifr.IP); + cmd.setStorageMacAddress(pifr.MAC); + cmd.setStorageNetmask(pifr.netmask); + } + } + + if (_host.storagePif2 != null) { + pif = PIF.getByUuid(conn, _host.storagePif2); + pifr = pif.getRecord(conn); + if (pifr.IP != null && pifr.IP.length() > 0) { + cmd.setStorageIpAddressDeux(pifr.IP); + cmd.setStorageMacAddressDeux(pifr.MAC); + cmd.setStorageNetmaskDeux(pifr.netmask); + } + } + + Map configs = hr.otherConfig; + cmd.setIqn(configs.get("iscsi_iqn")); + + cmd.setPod(_pod); + cmd.setVersion(CitrixResourceBase.class.getPackage().getImplementationVersion()); + + } catch (final XmlRpcException e) { + throw new CloudRuntimeException("XML RPC Exception" + e.getMessage(), e); + } catch (XenAPIException e) { + throw new CloudRuntimeException("XenAPIException" + e.toString(), e); + } + } + + public CitrixResourceBase() { + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + _name = name; + + try { + _dcId = Long.parseLong((String)params.get("zone")); + } catch (NumberFormatException e) { + throw new ConfigurationException("Unable to get the zone " + params.get("zone")); + } + + _host.uuid = (String)params.get("guid"); + + _name = _host.uuid; + _host.ip = (String)params.get("ipaddress"); + + _username = (String)params.get("username"); + _password.add((String)params.get("password")); + _pod = (String)params.get("pod"); + _cluster = (String)params.get("cluster"); + _privateNetworkName = (String)params.get("private.network.device"); + _publicNetworkName = (String)params.get("public.network.device"); + _guestNetworkName = (String)params.get("guest.network.device"); + _instance = (String)params.get("instance.name"); + _securityGroupEnabled = Boolean.parseBoolean((String)params.get("securitygroupenabled")); + + _linkLocalPrivateNetworkName = (String)params.get("private.linkLocal.device"); + if (_linkLocalPrivateNetworkName == null) { + _linkLocalPrivateNetworkName = "cloud_link_local_network"; + } + + _storageNetworkName1 = (String)params.get("storage.network.device1"); + _storageNetworkName2 = (String)params.get("storage.network.device2"); + + _heartbeatInterval = NumbersUtil.parseInt((String)params.get("xenserver.heartbeat.interval"), 60); + + String value = (String)params.get("wait"); + _wait = NumbersUtil.parseInt(value, 600); + + value = (String)params.get("migratewait"); + _migratewait = NumbersUtil.parseInt(value, 3600); + + _maxNics = NumbersUtil.parseInt((String)params.get("xenserver.nics.max"), 7); + + if (_pod == null) { + throw new ConfigurationException("Unable to get the pod"); + } + + if (_host.ip == null) { + throw new ConfigurationException("Unable to get the host address"); + } + + if (_username == null) { + throw new ConfigurationException("Unable to get the username"); + } + + if (_password == null) { + throw new ConfigurationException("Unable to get the password"); + } + + if (_host.uuid == null) { + throw new ConfigurationException("Unable to get the uuid"); + } + + CheckXenHostInfo(); + + storageHandler = getStorageHandler(); + + _vrResource = new VirtualRoutingResource(this); + if (!_vrResource.configure(name, params)) { + throw new ConfigurationException("Unable to configure VirtualRoutingResource"); + } + return true; + } + + protected StorageSubsystemCommandHandler getStorageHandler() { + XenServerStorageProcessor processor = new XenServerStorageProcessor(this); + return new StorageSubsystemCommandHandlerBase(processor); + } + + private void CheckXenHostInfo() throws ConfigurationException { + Connection conn = ConnPool.getConnect(_host.ip, _username, _password); + if( conn == null ) { + throw new ConfigurationException("Can not create connection to " + _host.ip); + } + try { + Host.Record hostRec = null; + try { + Host host = Host.getByUuid(conn, _host.uuid); + hostRec = host.getRecord(conn); + Pool.Record poolRec = Pool.getAllRecords(conn).values().iterator().next(); + _host.pool = poolRec.uuid; + + } catch (Exception e) { + throw new ConfigurationException("Can not get host information from " + _host.ip); + } + if (!hostRec.address.equals(_host.ip)) { + String msg = "Host " + _host.ip + " seems be reinstalled, please remove this host and readd"; + s_logger.error(msg); + throw new ConfigurationException(msg); + } + } finally { + try { + Session.logout(conn); + } catch (Exception e) { + } + } + } + + + public CreateAnswer execute(CreateCommand cmd) { + Connection conn = getConnection(); + StorageFilerTO pool = cmd.getPool(); + DiskProfile dskch = cmd.getDiskCharacteristics(); + VDI vdi = null; + try { + SR poolSr = getStorageRepository(conn, pool.getUuid()); + if (cmd.getTemplateUrl() != null) { + VDI tmpltvdi = null; + + tmpltvdi = getVDIbyUuid(conn, cmd.getTemplateUrl()); + vdi = tmpltvdi.createClone(conn, new HashMap()); + vdi.setNameLabel(conn, dskch.getName()); + } else { + VDI.Record vdir = new VDI.Record(); + vdir.nameLabel = dskch.getName(); + vdir.SR = poolSr; + vdir.type = Types.VdiType.USER; + + vdir.virtualSize = dskch.getSize(); + vdi = VDI.create(conn, vdir); + } + + VDI.Record vdir; + vdir = vdi.getRecord(conn); + s_logger.debug("Succesfully created VDI for " + cmd + ". Uuid = " + vdir.uuid); + + VolumeTO vol = + new VolumeTO(cmd.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), vdir.nameLabel, pool.getPath(), vdir.uuid, vdir.virtualSize, null); + return new CreateAnswer(cmd, vol); + } catch (Exception e) { + s_logger.warn("Unable to create volume; Pool=" + pool + "; Disk: " + dskch, e); + return new CreateAnswer(cmd, e); + } + } + + public Answer execute(ResizeVolumeCommand cmd) { + Connection conn = getConnection(); + String volid = cmd.getPath(); + long newSize = cmd.getNewSize(); + + try { + VDI vdi = getVDIbyUuid(conn, volid); + vdi.resize(conn, newSize); + return new ResizeVolumeAnswer(cmd, true, "success", newSize); + } catch (Exception e) { + s_logger.warn("Unable to resize volume", e); + String error = "failed to resize volume:" + e; + return new ResizeVolumeAnswer(cmd, false, error); + } + } + + protected SR getISOSRbyVmName(Connection conn, String vmName) { + try { + Set srs = SR.getByNameLabel(conn, vmName + "-ISO"); + if (srs.size() == 0) { + return null; + } else if (srs.size() == 1) { + return srs.iterator().next(); + } else { + String msg = "getIsoSRbyVmName failed due to there are more than 1 SR having same Label"; + s_logger.warn(msg); + } + } catch (XenAPIException e) { + String msg = "getIsoSRbyVmName failed due to " + e.toString(); + s_logger.warn(msg, e); + } catch (Exception e) { + String msg = "getIsoSRbyVmName failed due to " + e.getMessage(); + s_logger.warn(msg, e); + } + return null; + } + + protected SR createNfsSRbyURI(Connection conn, URI uri, boolean shared) { + try { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating a " + (shared ? "shared SR for " : "not shared SR for ") + uri); + } + + Map deviceConfig = new HashMap(); + String path = uri.getPath(); + path = path.replace("//", "/"); + deviceConfig.put("server", uri.getHost()); + deviceConfig.put("serverpath", path); + String name = UUID.nameUUIDFromBytes(new String(uri.getHost() + path).getBytes()).toString(); + if (!shared) { + Set srs = SR.getByNameLabel(conn, name); + for (SR sr : srs) { + SR.Record record = sr.getRecord(conn); + if (SRType.NFS.equals(record.type) && record.contentType.equals("user") && !record.shared) { + removeSRSync(conn, sr); + } + } + } + + Host host = Host.getByUuid(conn, _host.uuid); + Map smConfig = new HashMap(); + smConfig.put("nosubdir", "true"); + SR sr = SR.create(conn, host, deviceConfig, new Long(0), name, uri.getHost() + uri.getPath(), SRType.NFS.toString(), "user", shared, smConfig); + + if (!checkSR(conn, sr)) { + throw new Exception("no attached PBD"); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug(logX(sr, "Created a SR; UUID is " + sr.getUuid(conn) + " device config is " + deviceConfig)); + } + sr.scan(conn); + return sr; + } catch (XenAPIException e) { + String msg = "Can not create second storage SR mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } catch (Exception e) { + String msg = "Can not create second storage SR mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + + protected SR createIsoSRbyURI(Connection conn, URI uri, String vmName, boolean shared) { + try { + Map deviceConfig = new HashMap(); + String path = uri.getPath(); + path = path.replace("//", "/"); + deviceConfig.put("location", uri.getHost() + ":" + path); + Host host = Host.getByUuid(conn, _host.uuid); + SR sr = SR.create(conn, host, deviceConfig, new Long(0), uri.getHost() + path, "iso", "iso", "iso", shared, new HashMap()); + sr.setNameLabel(conn, vmName + "-ISO"); + sr.setNameDescription(conn, deviceConfig.get("location")); + + sr.scan(conn); + return sr; + } catch (XenAPIException e) { + String msg = "createIsoSRbyURI failed! mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } catch (Exception e) { + String msg = "createIsoSRbyURI failed! mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + + protected VDI getVDIbyLocationandSR(Connection conn, String loc, SR sr) { + try { + Set vdis = sr.getVDIs(conn); + for (VDI vdi : vdis) { + if (vdi.getLocation(conn).startsWith(loc)) { + return vdi; + } + } + + String msg = "can not getVDIbyLocationandSR " + loc; + s_logger.warn(msg); + return null; + } catch (XenAPIException e) { + String msg = "getVDIbyLocationandSR exception " + loc + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } catch (Exception e) { + String msg = "getVDIbyLocationandSR exception " + loc + " due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + + } + + protected VDI getVDIbyUuid(Connection conn, String uuid) { + return getVDIbyUuid(conn, uuid, true); + } + + protected VDI getVDIbyUuid(Connection conn, String uuid, boolean throwExceptionIfNotFound) { + try { + return VDI.getByUuid(conn, uuid); + } catch (Exception e) { + if (throwExceptionIfNotFound) { + String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString(); + + s_logger.debug(msg); + + throw new CloudRuntimeException(msg, e); + } + + return null; + } + } + + protected SR getIscsiSR(Connection conn, String srNameLabel, String target, String path, String chapInitiatorUsername, String chapInitiatorPassword, + boolean ignoreIntroduceException) { + synchronized (srNameLabel.intern()) { + Map deviceConfig = new HashMap(); + try { + if (path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + + String tmp[] = path.split("/"); + if (tmp.length != 3) { + String msg = "Wrong iscsi path " + path + " it should be /targetIQN/LUN"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + String targetiqn = tmp[1].trim(); + String lunid = tmp[2].trim(); + String scsiid = ""; + + Set srs = SR.getByNameLabel(conn, srNameLabel); + for (SR sr : srs) { + if (!SRType.LVMOISCSI.equals(sr.getType(conn))) { + continue; + } + Set pbds = sr.getPBDs(conn); + if (pbds.isEmpty()) { + continue; + } + PBD pbd = pbds.iterator().next(); + Map dc = pbd.getDeviceConfig(conn); + if (dc == null) { + continue; + } + if (dc.get("target") == null) { + continue; + } + if (dc.get("targetIQN") == null) { + continue; + } + if (dc.get("lunid") == null) { + continue; + } + if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) { + throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:" + dc.get("targetIQN") + + ", lunid:" + dc.get("lunid") + " for pool " + srNameLabel + "on host:" + _host.uuid); + } + } + deviceConfig.put("target", target); + deviceConfig.put("targetIQN", targetiqn); + + if (StringUtils.isNotBlank(chapInitiatorUsername) && StringUtils.isNotBlank(chapInitiatorPassword)) { + deviceConfig.put("chapuser", chapInitiatorUsername); + deviceConfig.put("chappassword", chapInitiatorPassword); + } + + Host host = Host.getByUuid(conn, _host.uuid); + Map smConfig = new HashMap(); + String type = SRType.LVMOISCSI.toString(); + SR sr = null; + try { + sr = SR.create(conn, host, deviceConfig, new Long(0), srNameLabel, srNameLabel, type, "user", true, smConfig); + } catch (XenAPIException e) { + String errmsg = e.toString(); + if (errmsg.contains("SR_BACKEND_FAILURE_107")) { + String lun[] = errmsg.split(""); + boolean found = false; + for (int i = 1; i < lun.length; i++) { + int blunindex = lun[i].indexOf("") + 7; + int elunindex = lun[i].indexOf(""); + String ilun = lun[i].substring(blunindex, elunindex); + ilun = ilun.trim(); + if (ilun.equals(lunid)) { + int bscsiindex = lun[i].indexOf("") + 8; + int escsiindex = lun[i].indexOf(""); + scsiid = lun[i].substring(bscsiindex, escsiindex); + scsiid = scsiid.trim(); + found = true; + break; + } + } + if (!found) { + String msg = "can not find LUN " + lunid + " in " + errmsg; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + } else { + String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + deviceConfig.put("SCSIid", scsiid); + + String result = SR.probe(conn, host, deviceConfig, type, smConfig); + String pooluuid = null; + if (result.indexOf("") != -1) { + pooluuid = result.substring(result.indexOf("") + 6, result.indexOf("")).trim(); + } + + if (pooluuid == null || pooluuid.length() != 36) { + sr = SR.create(conn, host, deviceConfig, new Long(0), srNameLabel, srNameLabel, type, "user", true, smConfig); + } else { + try { + sr = SR.introduce(conn, pooluuid, srNameLabel, srNameLabel, type, "user", true, smConfig); + } catch (XenAPIException ex) { + if (ignoreIntroduceException) { + return sr; + } + + throw ex; + } + + Set setHosts = Host.getAll(conn); + + for (Host currentHost : setHosts) { + PBD.Record rec = new PBD.Record(); + + rec.deviceConfig = deviceConfig; + rec.host = currentHost; + rec.SR = sr; + + PBD pbd = PBD.create(conn, rec); + + pbd.plug(conn); + } + } + sr.scan(conn); + return sr; + } catch (XenAPIException e) { + String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } catch (Exception e) { + String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + } + + protected SR getNfsSR(Connection conn, StorageFilerTO pool) { + Map deviceConfig = new HashMap(); + try { + String server = pool.getHost(); + String serverpath = pool.getPath(); + serverpath = serverpath.replace("//", "/"); + Set srs = SR.getAll(conn); + for (SR sr : srs) { + if (!SRType.NFS.equals(sr.getType(conn))) { + continue; + } + + Set pbds = sr.getPBDs(conn); + if (pbds.isEmpty()) { + continue; + } + + PBD pbd = pbds.iterator().next(); + + Map dc = pbd.getDeviceConfig(conn); + + if (dc == null) { + continue; + } + + if (dc.get("server") == null) { + continue; + } + + if (dc.get("serverpath") == null) { + continue; + } + + if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) { + throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" + dc.get("serverpath") + + " for pool " + pool.getUuid() + "on host:" + _host.uuid); + } + + } + deviceConfig.put("server", server); + deviceConfig.put("serverpath", serverpath); + Host host = Host.getByUuid(conn, _host.uuid); + Map smConfig = new HashMap(); + smConfig.put("nosubdir", "true"); + SR sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), Long.toString(pool.getId()), SRType.NFS.toString(), "user", true, smConfig); + sr.scan(conn); + return sr; + } catch (XenAPIException e) { + throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e); + } catch (XmlRpcException e) { + throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e); + } + } + + public Answer execute(DestroyCommand cmd) { + Connection conn = getConnection(); + VolumeTO vol = cmd.getVolume(); + // Look up the VDI + String volumeUUID = vol.getPath(); + VDI vdi = null; + try { + vdi = getVDIbyUuid(conn, volumeUUID); + } catch (Exception e) { + return new Answer(cmd, true, "Success"); + } + Set vbds = null; + try { + vbds = vdi.getVBDs(conn); + } catch (Exception e) { + String msg = "VDI getVBDS for " + volumeUUID + " failed due to " + e.toString(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + for (VBD vbd : vbds) { + try { + vbd.unplug(conn); + vbd.destroy(conn); + } catch (Exception e) { + String msg = "VM destroy for " + volumeUUID + " failed due to " + e.toString(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + } + try { + Set snapshots = vdi.getSnapshots(conn); + for (VDI snapshot : snapshots) { + snapshot.destroy(conn); + } + vdi.destroy(conn); + } catch (Exception e) { + String msg = "VDI destroy for " + volumeUUID + " failed due to " + e.toString(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + + return new Answer(cmd, true, "Success"); + } + + protected VDI createVdi(SR sr, String vdiNameLabel, Long volumeSize) throws Types.XenAPIException, XmlRpcException { + VDI vdi = null; + + Connection conn = getConnection(); + + VDI.Record vdir = new VDI.Record(); + + vdir.nameLabel = vdiNameLabel; + vdir.SR = sr; + vdir.type = Types.VdiType.USER; + + long totalSrSpace = sr.getPhysicalSize(conn); + long unavailableSrSpace = sr.getPhysicalUtilisation(conn); + long availableSrSpace = totalSrSpace - unavailableSrSpace; + + if (availableSrSpace < volumeSize) { + throw new CloudRuntimeException("Available space for SR cannot be less than " + volumeSize + "."); + } + + vdir.virtualSize = volumeSize; + + long maxNumberOfTries = (totalSrSpace / unavailableSrSpace >= 1) ? (totalSrSpace / unavailableSrSpace) : 1; + long tryNumber = 0; + + while (tryNumber <= maxNumberOfTries) { + try { + vdi = VDI.create(conn, vdir); + + break; + } catch (Exception ex) { + tryNumber++; + + vdir.virtualSize -= unavailableSrSpace; + } + } + + return vdi; + } + + protected void handleSrAndVdiDetach(String iqn, Connection conn) throws Exception { + SR sr = getStorageRepository(conn, iqn); + + removeSR(conn, sr); + } + + protected AttachVolumeAnswer execute(final AttachVolumeCommand cmd) { + Connection conn = getConnection(); + boolean attach = cmd.getAttach(); + String vmName = cmd.getVmName(); + String vdiNameLabel = vmName + "-DATA"; + Long deviceId = cmd.getDeviceId(); + + String errorMsg; + if (attach) { + errorMsg = "Failed to attach volume"; + } else { + errorMsg = "Failed to detach volume"; + } + + try { + VDI vdi = null; + + if (cmd.getAttach() && cmd.isManaged()) { + SR sr = + getIscsiSR(conn, cmd.get_iScsiName(), cmd.getStorageHost(), cmd.get_iScsiName(), cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(), true); + + vdi = getVDIbyUuid(conn, cmd.getVolumePath(), false); + + if (vdi == null) { + vdi = createVdi(sr, vdiNameLabel, cmd.getVolumeSize()); + } + } else { + vdi = getVDIbyUuid(conn, cmd.getVolumePath()); + } + + // Look up the VM + VM vm = getVM(conn, vmName); + /* For HVM guest, if no pv driver installed, no attach/detach */ + boolean isHVM; + if (vm.getPVBootloader(conn).equalsIgnoreCase("")) { + isHVM = true; + } else { + isHVM = false; + } + VMGuestMetrics vgm = vm.getGuestMetrics(conn); + boolean pvDrvInstalled = false; + if (!isRefNull(vgm) && vgm.getPVDriversUpToDate(conn)) { + pvDrvInstalled = true; + } + if (isHVM && !pvDrvInstalled) { + s_logger.warn(errorMsg + ": You attempted an operation on a VM which requires PV drivers to be installed but the drivers were not detected"); + return new AttachVolumeAnswer(cmd, + "You attempted an operation that requires PV drivers to be installed on the VM. Please install them by inserting xen-pv-drv.iso."); + } + if (attach) { + // Figure out the disk number to attach the VM to + String diskNumber = null; + if (deviceId != null) { + if (deviceId.longValue() == 3) { + String msg = "Device 3 is reserved for CD-ROM, choose other device"; + return new AttachVolumeAnswer(cmd, msg); + } + if (isDeviceUsed(conn, vm, deviceId)) { + String msg = "Device " + deviceId + " is used in VM " + vmName; + return new AttachVolumeAnswer(cmd, msg); + } + diskNumber = deviceId.toString(); + } else { + diskNumber = getUnusedDeviceNum(conn, vm); + } + // Create a new VBD + VBD.Record vbdr = new VBD.Record(); + vbdr.VM = vm; + vbdr.VDI = vdi; + vbdr.bootable = false; + vbdr.userdevice = diskNumber; + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + vbdr.unpluggable = true; + VBD vbd = VBD.create(conn, vbdr); + + // Attach the VBD to the VM + vbd.plug(conn); + + // Update the VDI's label to include the VM name + vdi.setNameLabel(conn, vdiNameLabel); + + return new AttachVolumeAnswer(cmd, Long.parseLong(diskNumber), vdi.getUuid(conn)); + } else { + // Look up all VBDs for this VDI + Set vbds = vdi.getVBDs(conn); + + // Detach each VBD from its VM, and then destroy it + for (VBD vbd : vbds) { + VBD.Record vbdr = vbd.getRecord(conn); + + if (vbdr.currentlyAttached) { + vbd.unplug(conn); + } + + vbd.destroy(conn); + } + + // Update the VDI's label to be "detached" + vdi.setNameLabel(conn, "detached"); + + if (cmd.isManaged()) { + handleSrAndVdiDetach(cmd.get_iScsiName(), conn); + } + + return new AttachVolumeAnswer(cmd); + } + } catch (XenAPIException e) { + String msg = errorMsg + " for uuid: " + cmd.getVolumePath() + " due to " + e.toString(); + s_logger.warn(msg, e); + return new AttachVolumeAnswer(cmd, msg); + } catch (Exception e) { + String msg = errorMsg + " for uuid: " + cmd.getVolumePath() + " due to " + e.getMessage(); + s_logger.warn(msg, e); + return new AttachVolumeAnswer(cmd, msg); + } + + } + + protected void umount(Connection conn, VDI vdi) { + + } + + private long getVMSnapshotChainSize(Connection conn, VolumeObjectTO volumeTo, String vmName) throws BadServerResponse, XenAPIException, XmlRpcException { + Set allvolumeVDIs = VDI.getByNameLabel(conn, volumeTo.getName()); + long size = 0; + for (VDI vdi : allvolumeVDIs) { + try { + if (vdi.getIsASnapshot(conn) && vdi.getSmConfig(conn).get("vhd-parent") != null) { + String parentUuid = vdi.getSmConfig(conn).get("vhd-parent"); + VDI parentVDI = VDI.getByUuid(conn, parentUuid); + // add size of snapshot vdi node, usually this only contains meta data + size = size + vdi.getPhysicalUtilisation(conn); + // add size of snapshot vdi parent, this contains data + if (parentVDI != null) + size = size + parentVDI.getPhysicalUtilisation(conn).longValue(); + } + } catch (Exception e) { + s_logger.debug("Exception occurs when calculate " + "snapshot capacity for volumes: " + e.getMessage()); + continue; + } + } + if (volumeTo.getVolumeType() == Volume.Type.ROOT) { + Map allVMs = VM.getAllRecords(conn); + // add size of memory snapshot vdi + if (allVMs.size() > 0) { + for (VM vmr : allVMs.keySet()) { + try { + String vName = vmr.getNameLabel(conn); + if (vName != null && vName.contains(vmName) && vmr.getIsASnapshot(conn)) { + + VDI memoryVDI = vmr.getSuspendVDI(conn); + size = size + memoryVDI.getParent(conn).getPhysicalUtilisation(conn); + size = size + memoryVDI.getPhysicalUtilisation(conn); + } + } catch (Exception e) { + s_logger.debug("Exception occurs when calculate " + "snapshot capacity for memory: " + e.getMessage()); + continue; + } + } + } + } + return size; + } + + protected Answer execute(final CreateVMSnapshotCommand cmd) { + String vmName = cmd.getVmName(); + String vmSnapshotName = cmd.getTarget().getSnapshotName(); + List listVolumeTo = cmd.getVolumeTOs(); + VirtualMachine.State vmState = cmd.getVmState(); + String guestOSType = cmd.getGuestOSType(); + + boolean snapshotMemory = cmd.getTarget().getType() == VMSnapshot.Type.DiskAndMemory; + long timeout = cmd.getWait(); + + Connection conn = getConnection(); + VM vm = null; + VM vmSnapshot = null; + boolean success = false; + + try { + // check if VM snapshot already exists + Set vmSnapshots = VM.getByNameLabel(conn, cmd.getTarget().getSnapshotName()); + if (vmSnapshots.size() > 0) + return new CreateVMSnapshotAnswer(cmd, cmd.getTarget(), cmd.getVolumeTOs()); + + // check if there is already a task for this VM snapshot + Task task = null; + Set tasks = Task.getByNameLabel(conn, "Async.VM.snapshot"); + tasks.addAll(Task.getByNameLabel(conn, "Async.VM.checkpoint")); + for (Task taskItem : tasks) { + if (taskItem.getOtherConfig(conn).containsKey("CS_VM_SNAPSHOT_KEY")) { + String vmSnapshotTaskName = taskItem.getOtherConfig(conn).get("CS_VM_SNAPSHOT_KEY"); + if (vmSnapshotTaskName != null && vmSnapshotTaskName.equals(cmd.getTarget().getSnapshotName())) { + task = taskItem; + } + } + } + + // create a new task if there is no existing task for this VM snapshot + if (task == null) { + try { + vm = getVM(conn, vmName); + } catch (Exception e) { + if (!snapshotMemory) { + vm = createWorkingVM(conn, vmName, guestOSType, listVolumeTo); + } + } + + if (vm == null) { + return new CreateVMSnapshotAnswer(cmd, false, "Creating VM Snapshot Failed due to can not find vm: " + vmName); + } + + // call Xenserver API + if (!snapshotMemory) { + task = vm.snapshotAsync(conn, vmSnapshotName); + } else { + Set vbds = vm.getVBDs(conn); + Pool pool = Pool.getByUuid(conn, _host.pool); + for (VBD vbd : vbds) { + VBD.Record vbdr = vbd.getRecord(conn); + if (vbdr.userdevice.equals("0")) { + VDI vdi = vbdr.VDI; + SR sr = vdi.getSR(conn); + // store memory image on the same SR with ROOT volume + pool.setSuspendImageSR(conn, sr); + } + } + task = vm.checkpointAsync(conn, vmSnapshotName); + } + task.addToOtherConfig(conn, "CS_VM_SNAPSHOT_KEY", vmSnapshotName); + } + + waitForTask(conn, task, 1000, timeout * 1000); + checkForSuccess(conn, task); + String result = task.getResult(conn); + + // extract VM snapshot ref from result + String ref = result.substring("".length(), result.length() - "".length()); + vmSnapshot = Types.toVM(ref); + try { + Thread.sleep(5000); + } catch (final InterruptedException ex) { + + } + // calculate used capacity for this VM snapshot + for (VolumeObjectTO volumeTo : cmd.getVolumeTOs()) { + long size = getVMSnapshotChainSize(conn, volumeTo, cmd.getVmName()); + volumeTo.setSize(size); + } + + success = true; + return new CreateVMSnapshotAnswer(cmd, cmd.getTarget(), cmd.getVolumeTOs()); + } catch (Exception e) { + String msg = ""; + if (e instanceof Types.BadAsyncResult) { + String licenseKeyWord = "LICENCE_RESTRICTION"; + Types.BadAsyncResult errorResult = (Types.BadAsyncResult)e; + if (errorResult.shortDescription != null && errorResult.shortDescription.contains(licenseKeyWord)) { + msg = licenseKeyWord; + } + } else { + msg = e.getMessage(); + } + s_logger.error("Creating VM Snapshot " + cmd.getTarget().getSnapshotName() + " failed due to: " + msg); + return new CreateVMSnapshotAnswer(cmd, false, msg); + } finally { + try { + if (!success) { + if (vmSnapshot != null) { + s_logger.debug("Delete exsisting VM Snapshot " + vmSnapshotName + " after making VolumeTO failed"); + Set vbds = vmSnapshot.getVBDs(conn); + for (VBD vbd : vbds) { + VBD.Record vbdr = vbd.getRecord(conn); + if (vbdr.type == Types.VbdType.DISK) { + VDI vdi = vbdr.VDI; + vdi.destroy(conn); + } + } + vmSnapshot.destroy(conn); + } + } + if (vmState == VirtualMachine.State.Stopped) { + if (vm != null) { + vm.destroy(conn); + } + } + } catch (Exception e2) { + s_logger.error("delete snapshot error due to " + e2.getMessage()); + } + } + } + + private VM createWorkingVM(Connection conn, String vmName, String guestOSType, List listVolumeTo) throws BadServerResponse, Types.VmBadPowerState, Types.SrFull, + Types.OperationNotAllowed, XenAPIException, XmlRpcException { + String guestOsTypeName = getGuestOsType(guestOSType, false); + if (guestOsTypeName == null) { + String msg = + " Hypervisor " + this.getClass().getName() + " doesn't support guest OS type " + guestOSType + ". you can choose 'Other install media' to run it as HVM"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + VM template = getVM(conn, guestOsTypeName); + VM vm = template.createClone(conn, vmName); + vm.setIsATemplate(conn, false); + Map vdiMap = new HashMap(); + for (VolumeObjectTO volume : listVolumeTo) { + String vdiUuid = volume.getPath(); + try { + VDI vdi = VDI.getByUuid(conn, vdiUuid); + vdiMap.put(vdi, volume); + } catch (Types.UuidInvalid e) { + s_logger.warn("Unable to find vdi by uuid: " + vdiUuid + ", skip it"); + } + } + for (VDI vdi : vdiMap.keySet()) { + VolumeObjectTO volumeTO = vdiMap.get(vdi); + VBD.Record vbdr = new VBD.Record(); + vbdr.VM = vm; + vbdr.VDI = vdi; + if (volumeTO.getVolumeType() == Volume.Type.ROOT) { + vbdr.bootable = true; + vbdr.unpluggable = false; + } else { + vbdr.bootable = false; + vbdr.unpluggable = true; + } + vbdr.userdevice = Long.toString(volumeTO.getDeviceId()); + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + VBD.create(conn, vbdr); + } + return vm; + } + + protected Answer execute(final DeleteVMSnapshotCommand cmd) { + String snapshotName = cmd.getTarget().getSnapshotName(); + Connection conn = getConnection(); + + try { + List vdiList = new ArrayList(); + Set snapshots = VM.getByNameLabel(conn, snapshotName); + if (snapshots.size() == 0) { + s_logger.warn("VM snapshot with name " + snapshotName + " does not exist, assume it is already deleted"); + return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs()); + } + VM snapshot = snapshots.iterator().next(); + Set vbds = snapshot.getVBDs(conn); + for (VBD vbd : vbds) { + if (vbd.getType(conn) == Types.VbdType.DISK) { + VDI vdi = vbd.getVDI(conn); + vdiList.add(vdi); + } + } + if (cmd.getTarget().getType() == VMSnapshot.Type.DiskAndMemory) + vdiList.add(snapshot.getSuspendVDI(conn)); + snapshot.destroy(conn); + for (VDI vdi : vdiList) { + vdi.destroy(conn); + } + + try { + Thread.sleep(5000); + } catch (final InterruptedException ex) { + + } + // re-calculate used capacify for this VM snapshot + for (VolumeObjectTO volumeTo : cmd.getVolumeTOs()) { + long size = getVMSnapshotChainSize(conn, volumeTo, cmd.getVmName()); + volumeTo.setSize(size); + } + + return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs()); + } catch (Exception e) { + s_logger.warn("Catch Exception: " + e.getClass().toString() + " due to " + e.toString(), e); + return new DeleteVMSnapshotAnswer(cmd, false, e.getMessage()); + } + } + + protected Answer execute(final AttachIsoCommand cmd) { + Connection conn = getConnection(); + boolean attach = cmd.isAttach(); + String vmName = cmd.getVmName(); + String isoURL = cmd.getIsoPath(); + + String errorMsg; + if (attach) { + errorMsg = "Failed to attach ISO"; + } else { + errorMsg = "Failed to detach ISO"; + } + try { + if (attach) { + VBD isoVBD = null; + + // Find the VM + VM vm = getVM(conn, vmName); + + // Find the ISO VDI + VDI isoVDI = getIsoVDIByURL(conn, vmName, isoURL); + + // Find the VM's CD-ROM VBD + Set vbds = vm.getVBDs(conn); + for (VBD vbd : vbds) { + String userDevice = vbd.getUserdevice(conn); + Types.VbdType type = vbd.getType(conn); + + if (userDevice.equals("3") && type == Types.VbdType.CD) { + isoVBD = vbd; + break; + } + } + + if (isoVBD == null) { + throw new CloudRuntimeException("Unable to find CD-ROM VBD for VM: " + vmName); + } else { + // If an ISO is already inserted, eject it + if (isoVBD.getEmpty(conn) == false) { + isoVBD.eject(conn); + } + + // Insert the new ISO + isoVBD.insert(conn, isoVDI); + } + + return new Answer(cmd); + } else { + // Find the VM + VM vm = getVM(conn, vmName); + String vmUUID = vm.getUuid(conn); + + // Find the ISO VDI + VDI isoVDI = getIsoVDIByURL(conn, vmName, isoURL); + + SR sr = isoVDI.getSR(conn); + + // Look up all VBDs for this VDI + Set vbds = isoVDI.getVBDs(conn); + + // Iterate through VBDs, and if the VBD belongs the VM, eject + // the ISO from it + for (VBD vbd : vbds) { + VM vbdVM = vbd.getVM(conn); + String vbdVmUUID = vbdVM.getUuid(conn); + + if (vbdVmUUID.equals(vmUUID)) { + // If an ISO is already inserted, eject it + if (!vbd.getEmpty(conn)) { + vbd.eject(conn); + } + + break; + } + } + + if (!sr.getNameLabel(conn).startsWith("XenServer Tools")) { + removeSR(conn, sr); + } + + return new Answer(cmd); + } + } catch (XenAPIException e) { + s_logger.warn(errorMsg + ": " + e.toString(), e); + return new Answer(cmd, false, e.toString()); + } catch (Exception e) { + s_logger.warn(errorMsg + ": " + e.toString(), e); + return new Answer(cmd, false, e.getMessage()); + } + } + + boolean IsISCSI(String type) { + return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type); + } + + protected Answer execute(final UpgradeSnapshotCommand cmd) { + + String secondaryStorageUrl = cmd.getSecondaryStorageUrl(); + String backedUpSnapshotUuid = cmd.getSnapshotUuid(); + Long volumeId = cmd.getVolumeId(); + Long accountId = cmd.getAccountId(); + Long templateId = cmd.getTemplateId(); + Long tmpltAcountId = cmd.getTmpltAccountId(); + String version = cmd.getVersion(); + + if (!version.equals("2.1")) { + return new Answer(cmd, true, "success"); + } + try { + Connection conn = getConnection(); + URI uri = new URI(secondaryStorageUrl); + String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + String snapshotPath = secondaryStorageMountPath + "/snapshots/" + accountId + "/" + volumeId + "/" + backedUpSnapshotUuid + ".vhd"; + String templatePath = secondaryStorageMountPath + "/template/tmpl/" + tmpltAcountId + "/" + templateId; + upgradeSnapshot(conn, templatePath, snapshotPath); + return new Answer(cmd, true, "success"); + } catch (Exception e) { + String details = "upgrading snapshot " + backedUpSnapshotUuid + " failed due to " + e.toString(); + s_logger.error(details, e); + + } + return new Answer(cmd, false, "failure"); + } + + private boolean destroySnapshotOnPrimaryStorageExceptThis(Connection conn, String volumeUuid, String avoidSnapshotUuid) { + try { + VDI volume = getVDIbyUuid(conn, volumeUuid); + if (volume == null) { + throw new InternalErrorException("Could not destroy snapshot on volume " + volumeUuid + " due to can not find it"); + } + Set snapshots = volume.getSnapshots(conn); + for (VDI snapshot : snapshots) { + try { + if (!snapshot.getUuid(conn).equals(avoidSnapshotUuid)) { + snapshot.destroy(conn); + } + } catch (Exception e) { + String msg = "Destroying snapshot: " + snapshot + " on primary storage failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + s_logger.debug("Successfully destroyed snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid); + return true; + } catch (XenAPIException e) { + String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid + " failed due to " + e.toString(); + s_logger.error(msg, e); + } catch (Exception e) { + String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid + " failed due to " + e.toString(); + s_logger.warn(msg, e); + } + + return false; + } + + protected VM getVM(Connection conn, String vmName) { + // Look up VMs with the specified name + Set vms; + try { + vms = VM.getByNameLabel(conn, vmName); + } catch (XenAPIException e) { + throw new CloudRuntimeException("Unable to get " + vmName + ": " + e.toString(), e); + } catch (Exception e) { + throw new CloudRuntimeException("Unable to get " + vmName + ": " + e.getMessage(), e); + } + + // If there are no VMs, throw an exception + if (vms.size() == 0) { + throw new CloudRuntimeException("VM with name: " + vmName + " does not exist."); + } + + // If there is more than one VM, print a warning + if (vms.size() > 1) { + s_logger.warn("Found " + vms.size() + " VMs with name: " + vmName); + } + + // Return the first VM in the set + return vms.iterator().next(); + } + + protected VDI getIsoVDIByURL(Connection conn, String vmName, String isoURL) { + SR isoSR = null; + String mountpoint = null; + if (isoURL.startsWith("xs-tools")) { + try { + Set vdis = VDI.getByNameLabel(conn, isoURL); + if (vdis.isEmpty()) { + throw new CloudRuntimeException("Could not find ISO with URL: " + isoURL); + } + return vdis.iterator().next(); + + } catch (XenAPIException e) { + throw new CloudRuntimeException("Unable to get pv iso: " + isoURL + " due to " + e.toString()); + } catch (Exception e) { + throw new CloudRuntimeException("Unable to get pv iso: " + isoURL + " due to " + e.toString()); + } + } + + int index = isoURL.lastIndexOf("/"); + mountpoint = isoURL.substring(0, index); + + URI uri; + try { + uri = new URI(mountpoint); + } catch (URISyntaxException e) { + throw new CloudRuntimeException("isoURL is wrong: " + isoURL); + } + isoSR = getISOSRbyVmName(conn, vmName); + if (isoSR == null) { + isoSR = createIsoSRbyURI(conn, uri, vmName, false); + } + + String isoName = isoURL.substring(index + 1); + + VDI isoVDI = getVDIbyLocationandSR(conn, isoName, isoSR); + + if (isoVDI != null) { + return isoVDI; + } else { + throw new CloudRuntimeException("Could not find ISO with URL: " + isoURL); + } + } + + protected SR getStorageRepository(Connection conn, String srNameLabel) { + Set srs; + try { + srs = SR.getByNameLabel(conn, srNameLabel); + } catch (XenAPIException e) { + throw new CloudRuntimeException("Unable to get SR " + srNameLabel + " due to " + e.toString(), e); + } catch (Exception e) { + throw new CloudRuntimeException("Unable to get SR " + srNameLabel + " due to " + e.getMessage(), e); + } + + if (srs.size() > 1) { + throw new CloudRuntimeException("More than one storage repository was found for pool with uuid: " + srNameLabel); + } else if (srs.size() == 1) { + SR sr = srs.iterator().next(); + if (s_logger.isDebugEnabled()) { + s_logger.debug("SR retrieved for " + srNameLabel); + } + + if (checkSR(conn, sr)) { + return sr; + } + throw new CloudRuntimeException("SR check failed for storage pool: " + srNameLabel + "on host:" + _host.uuid); + } else { + throw new CloudRuntimeException("Can not see storage pool: " + srNameLabel + " from on host:" + _host.uuid); + } + } + + protected Answer execute(final CheckConsoleProxyLoadCommand cmd) { + return executeProxyLoadScan(cmd, cmd.getProxyVmId(), cmd.getProxyVmName(), cmd.getProxyManagementIp(), cmd.getProxyCmdPort()); + } + + protected Answer execute(final WatchConsoleProxyLoadCommand cmd) { + return executeProxyLoadScan(cmd, cmd.getProxyVmId(), cmd.getProxyVmName(), cmd.getProxyManagementIp(), cmd.getProxyCmdPort()); + } + + protected Answer executeProxyLoadScan(final Command cmd, final long proxyVmId, final String proxyVmName, final String proxyManagementIp, final int cmdPort) { + String result = null; + + final StringBuffer sb = new StringBuffer(); + sb.append("http://").append(proxyManagementIp).append(":" + cmdPort).append("/cmd/getstatus"); + + boolean success = true; + try { + final URL url = new URL(sb.toString()); + final URLConnection conn = url.openConnection(); + + // setting TIMEOUTs to avoid possible waiting until death situations + conn.setConnectTimeout(5000); + conn.setReadTimeout(5000); + + final InputStream is = conn.getInputStream(); + final BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + final StringBuilder sb2 = new StringBuilder(); + String line = null; + try { + while ((line = reader.readLine()) != null) { + sb2.append(line + "\n"); + } + result = sb2.toString(); + } catch (final IOException e) { + success = false; + } finally { + try { + is.close(); + } catch (final IOException e) { + s_logger.warn("Exception when closing , console proxy address : " + proxyManagementIp); + success = false; + } + } + } catch (final IOException e) { + s_logger.warn("Unable to open console proxy command port url, console proxy address : " + proxyManagementIp); + success = false; + } + + return new ConsoleProxyLoadAnswer(cmd, proxyVmId, proxyVmName, success, result); + } + + protected boolean createSecondaryStorageFolder(Connection conn, String remoteMountPath, String newFolder) { + String result = callHostPlugin(conn, "vmopsSnapshot", "create_secondary_storage_folder", "remoteMountPath", remoteMountPath, "newFolder", newFolder); + return (result != null); + } + + protected boolean deleteSecondaryStorageFolder(Connection conn, String remoteMountPath, String folder) { + String details = callHostPlugin(conn, "vmopsSnapshot", "delete_secondary_storage_folder", "remoteMountPath", remoteMountPath, "folder", folder); + return (details != null && details.equals("1")); + } + + protected boolean postCreatePrivateTemplate(Connection conn, String templatePath, String tmpltFilename, String templateName, String templateDescription, + String checksum, long size, long virtualSize, long templateId) { + + if (templateDescription == null) { + templateDescription = ""; + } + + if (checksum == null) { + checksum = ""; + } + + String result = + callHostPlugin(conn, "vmopsSnapshot", "post_create_private_template", "templatePath", templatePath, "templateFilename", tmpltFilename, "templateName", + templateName, "templateDescription", templateDescription, "checksum", checksum, "size", String.valueOf(size), "virtualSize", String.valueOf(virtualSize), + "templateId", String.valueOf(templateId)); + + boolean success = false; + if (result != null && !result.isEmpty()) { + // Else, command threw an exception which has already been logged. + + if (result.equalsIgnoreCase("1")) { + s_logger.debug("Successfully created template.properties file on secondary storage for " + tmpltFilename); + success = true; + } else { + s_logger.warn("Could not create template.properties file on secondary storage for " + tmpltFilename + " for templateId: " + templateId); + } + } + + return success; + } + + protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) { + String parentUuid = + callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", + isISCSI.toString()); + + if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) { + s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid); + // errString is already logged. + return null; + } + return parentUuid; + } + + protected String deleteSnapshotBackup(Connection conn, Long dcId, Long accountId, Long volumeId, String secondaryStorageMountPath, String backupUUID) { + + // If anybody modifies the formatting below again, I'll skin them + String result = + callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "dcId", dcId.toString(), "accountId", accountId.toString(), + "volumeId", volumeId.toString(), "secondaryStorageMountPath", secondaryStorageMountPath); + + return result; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + disconnected(); + return true; + } + + @Override + public String getName() { + return _name; + } + + @Override + public IAgentControl getAgentControl() { + return _agentControl; + } + + @Override + public void setAgentControl(IAgentControl agentControl) { + _agentControl = agentControl; + } + + private Answer execute(CleanupNetworkRulesCmd cmd) { + if (!_canBridgeFirewall) { + return new Answer(cmd, true, null); + } + Connection conn = getConnection(); + String result = callHostPlugin(conn, "vmops", "cleanup_rules", "instance", _instance); + int numCleaned = Integer.parseInt(result); + if (result == null || result.isEmpty() || (numCleaned < 0)) { + s_logger.warn("Failed to cleanup rules for host " + _host.ip); + return new Answer(cmd, false, result); + } + if (numCleaned > 0) { + s_logger.info("Cleaned up rules for " + result + " vms on host " + _host.ip); + } + return new Answer(cmd, true, result); + } + + /** + * XsNic represents a network and the host's specific PIF. + */ + protected class XsLocalNetwork { + private final Network _n; + private Network.Record _nr; + private PIF _p; + private PIF.Record _pr; + + public XsLocalNetwork(Network n) { + this(n, null, null, null); + } + + public XsLocalNetwork(Network n, Network.Record nr, PIF p, PIF.Record pr) { + _n = n; + _nr = nr; + _p = p; + _pr = pr; + } + + public Network getNetwork() { + return _n; + } + + public Network.Record getNetworkRecord(Connection conn) throws XenAPIException, XmlRpcException { + if (_nr == null) { + _nr = _n.getRecord(conn); + } + + return _nr; + } + + public PIF getPif(Connection conn) throws XenAPIException, XmlRpcException { + if (_p == null) { + Network.Record nr = getNetworkRecord(conn); + for (PIF pif : nr.PIFs) { + PIF.Record pr = pif.getRecord(conn); + if (_host.uuid.equals(pr.host.getUuid(conn))) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found a network called " + nr.nameLabel + " on host=" + _host.ip + "; Network=" + nr.uuid + "; pif=" + pr.uuid); + } + _p = pif; + _pr = pr; + break; + } + } + } + return _p; + } + + public PIF.Record getPifRecord(Connection conn) throws XenAPIException, XmlRpcException { + if (_pr == null) { + PIF p = getPif(conn); + if (_pr == null) { + _pr = p.getRecord(conn); + } + } + return _pr; + } + } + + // A list of UUIDs that are gathered from the XenServer when + // the resource first connects to XenServer. These UUIDs do + // not change over time. + protected class XsHost { + public String systemvmisouuid; + public String uuid; + public String ip; + public String publicNetwork; + public String privateNetwork; + public String linkLocalNetwork; + public Network vswitchNetwork; + public String storageNetwork1; + public String storageNetwork2; + public String guestNetwork; + public String guestPif; + public String publicPif; + public String privatePif; + public String storagePif1; + public String storagePif2; + public String pool; + public int speed; + public Integer cpuSockets; + public int cpus; + public String productVersion; + public String localSRuuid; + + @Override + public String toString() { + return new StringBuilder("XS[").append(uuid).append("-").append(ip).append("]").toString(); + } + } + + /*Override by subclass*/ + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return stdType; + } + + private Answer execute(NetworkRulesSystemVmCommand cmd) { + boolean success = true; + Connection conn = getConnection(); + if (cmd.getType() != VirtualMachine.Type.User) { + String result = callHostPlugin(conn, "vmops", "default_network_rules_systemvm", "vmName", cmd.getVmName()); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + success = false; + } + } + + return new Answer(cmd, success, ""); + } + + private Answer execute(NetworkRulesVmSecondaryIpCommand cmd) { + boolean success = true; + Connection conn = getConnection(); + + String result = + callHostPlugin(conn, "vmops", "network_rules_vmSecondaryIp", "vmName", cmd.getVmName(), "vmMac", cmd.getVmMac(), "vmSecIp", cmd.getVmSecIp(), "action", + cmd.getAction()); + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + success = false; + } + + return new Answer(cmd, success, ""); + } + + protected Answer execute(final ClusterSyncCommand cmd) { + Connection conn = getConnection(); + //check if this is master + Pool pool; + try { + pool = Pool.getByUuid(conn, _host.pool); + Pool.Record poolr = pool.getRecord(conn); + + Host.Record hostr = poolr.master.getRecord(conn); + if (!_host.uuid.equals(hostr.uuid)) { + return new Answer(cmd); + } + } catch (Throwable e) { + s_logger.warn("Check for master failed, failing the Cluster sync command"); + return new Answer(cmd); + } + HashMap> newStates = deltaClusterSync(conn); + return new ClusterSyncAnswer(cmd.getClusterId(), newStates); + } + + + protected ClusterVMMetaDataSyncAnswer execute(final ClusterVMMetaDataSyncCommand cmd) { + Connection conn = getConnection(); + //check if this is master + Pool pool; + try { + pool = Pool.getByUuid(conn, _host.pool); + Pool.Record poolr = pool.getRecord(conn); + Host.Record hostr = poolr.master.getRecord(conn); + if (!_host.uuid.equals(hostr.uuid)) { + return new ClusterVMMetaDataSyncAnswer(cmd.getClusterId(), null); + } + } catch (Throwable e) { + s_logger.warn("Check for master failed, failing the Cluster sync VMMetaData command"); + return new ClusterVMMetaDataSyncAnswer(cmd.getClusterId(), null); + } + HashMap vmMetadatum = clusterVMMetaDataSync(conn); + return new ClusterVMMetaDataSyncAnswer(cmd.getClusterId(), vmMetadatum); + } + + protected HashMap clusterVMMetaDataSync(Connection conn) { + final HashMap vmMetaDatum = new HashMap(); + try { + Map vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER + for (VM.Record record: vm_map.values()) { + if (record.isControlDomain || record.isASnapshot || record.isATemplate) { + continue; // Skip DOM0 + } + vmMetaDatum.put(record.nameLabel, StringUtils.mapToString(record.platform)); + } + } catch (final Throwable e) { + String msg = "Unable to get vms through host " + _host.uuid + " due to to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } + return vmMetaDatum; + } + + protected HashMap> fullClusterSync(Connection conn) { + synchronized (_cluster.intern()) { + s_vms.clear(_cluster); + } + try { + Map vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER + for (VM.Record record : vm_map.values()) { + if (record.isControlDomain || record.isASnapshot || record.isATemplate) { + continue; // Skip DOM0 + } + String vm_name = record.nameLabel; + VmPowerState ps = record.powerState; + final State state = convertToState(ps); + Host host = record.residentOn; + String host_uuid = null; + if (!isRefNull(host)) { + host_uuid = host.getUuid(conn); + synchronized (_cluster.intern()) { + s_vms.put(_cluster, host_uuid, vm_name, state); + } + } + if (s_logger.isTraceEnabled()) { + s_logger.trace("VM " + vm_name + ": powerstate = " + ps + "; vm state=" + state.toString()); + } + } + } catch (final Throwable e) { + String msg = "Unable to get vms through host " + _host.uuid + " due to to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg); + } + return s_vms.getClusterVmState(_cluster); + } + + protected HashMap> deltaClusterSync(Connection conn) { + final HashMap> changes = new HashMap>(); + + synchronized (_cluster.intern()) { + HashMap> newStates = getAllVms(conn); + if (newStates == null) { + s_logger.warn("Unable to get the vm states so no state sync at this point."); + return null; + } + HashMap> oldStates = new HashMap>(s_vms.size(_cluster)); + oldStates.putAll(s_vms.getClusterVmState(_cluster)); + + for (final Map.Entry> entry : newStates.entrySet()) { + final String vm = entry.getKey(); + State newState = entry.getValue().second(); + String host_uuid = entry.getValue().first(); + final Pair oldState = oldStates.remove(vm); + + //check if host is changed + if (host_uuid != null && oldState != null) { + if (!host_uuid.equals(oldState.first()) && newState != State.Stopped && newState != State.Stopping) { + s_logger.warn("Detecting a change in host for " + vm); + changes.put(vm, new Pair(host_uuid, newState)); + + s_logger.debug("11. The VM " + vm + " is in " + newState + " state"); + s_vms.put(_cluster, host_uuid, vm, newState); + continue; + } + } + + if (newState == State.Stopped && oldState != null && oldState.second() != State.Stopping && oldState.second() != State.Stopped) { + newState = getRealPowerState(conn, vm); + } + + if (s_logger.isTraceEnabled()) { + s_logger.trace("VM " + vm + ": xenserver has state " + newState + " and we have state " + (oldState != null ? oldState.toString() : "null")); + } + + if (vm.startsWith("migrating")) { + s_logger.warn("Migrating from xenserver detected. Skipping"); + continue; + } + if (oldState == null) { + s_vms.put(_cluster, host_uuid, vm, newState); + s_logger.warn("Detecting a new state but couldn't find a old state so adding it to the changes: " + vm); + changes.put(vm, new Pair(host_uuid, newState)); + } else if (oldState.second() == State.Starting) { + if (newState == State.Running) { + s_logger.debug("12. The VM " + vm + " is in " + State.Running + " state"); + s_vms.put(_cluster, host_uuid, vm, newState); + } else if (newState == State.Stopped) { + s_logger.warn("Ignoring vm " + vm + " because of a lag in starting the vm."); + } + } else if (oldState.second() == State.Migrating) { + if (newState == State.Running) { + s_logger.debug("Detected that an migrating VM is now running: " + vm); + s_vms.put(_cluster, host_uuid, vm, newState); + } + } else if (oldState.second() == State.Stopping) { + if (newState == State.Stopped) { + s_logger.debug("13. The VM " + vm + " is in " + State.Stopped + " state"); + s_vms.put(_cluster, host_uuid, vm, newState); + } else if (newState == State.Running) { + s_logger.warn("Ignoring vm " + vm + " because of a lag in stopping the vm. "); + } + } else if (oldState.second() != newState) { + s_logger.debug("14. The VM " + vm + " is in " + newState + " state was " + oldState.second()); + s_vms.put(_cluster, host_uuid, vm, newState); + if (newState == State.Stopped) { + /* + * if (s_vmsKilled.remove(vm)) { s_logger.debug("VM " + vm + " has been killed for storage. "); + * newState = State.Error; } + */ + } + changes.put(vm, new Pair(host_uuid, newState)); + } + } + + for (final Map.Entry> entry : oldStates.entrySet()) { + final String vm = entry.getKey(); + final State oldState = entry.getValue().second(); + String host_uuid = entry.getValue().first(); + + if (s_logger.isTraceEnabled()) { + s_logger.trace("VM " + vm + " is now missing from xenserver so reporting stopped"); + } + + if (oldState == State.Stopping) { + s_logger.warn("Ignoring VM " + vm + " in transition state stopping."); + s_vms.remove(_cluster, host_uuid, vm); + } else if (oldState == State.Starting) { + s_logger.warn("Ignoring VM " + vm + " in transition state starting."); + } else if (oldState == State.Stopped) { + s_logger.debug("VM missing " + vm + " old state stopped so removing."); + s_vms.remove(_cluster, host_uuid, vm); + } else if (oldState == State.Migrating) { + s_logger.warn("Ignoring VM " + vm + " in migrating state."); + } else { + State newState = State.Stopped; + s_logger.warn("The VM is now missing marking it as Stopped " + vm); + changes.put(vm, new Pair(host_uuid, newState)); + } + } + } + return changes; + } + + /** + * @param cmd + * @return + */ + private UnPlugNicAnswer execute(UnPlugNicCommand cmd) { + Connection conn = getConnection(); + String vmName = cmd.getVmName(); + try { + Set vms = VM.getByNameLabel(conn, vmName); + if (vms == null || vms.isEmpty()) { + return new UnPlugNicAnswer(cmd, false, "Can not find VM " + vmName); + } + VM vm = vms.iterator().next(); + NicTO nic = cmd.getNic(); + String mac = nic.getMac(); + VIF vif = getVifByMac(conn, vm, mac); + if (vif != null) { + vif.unplug(conn); + Network network = vif.getNetwork(conn); + vif.destroy(conn); + try { + if (network.getNameLabel(conn).startsWith("VLAN")) { + disableVlanNetwork(conn, network); + } + } catch (Exception e) { + } + } + return new UnPlugNicAnswer(cmd, true, "success"); + } catch (Exception e) { + String msg = " UnPlug Nic failed due to " + e.toString(); + s_logger.warn(msg, e); + return new UnPlugNicAnswer(cmd, false, msg); + } + } + + /** + * @param cmd + * @return + */ + private PlugNicAnswer execute(PlugNicCommand cmd) { + Connection conn = getConnection(); + String vmName = cmd.getVmName(); + try { + Set vms = VM.getByNameLabel(conn, vmName); + if (vms == null || vms.isEmpty()) { + return new PlugNicAnswer(cmd, false, "Can not find VM " + vmName); + } + VM vm = vms.iterator().next(); + NicTO nic = cmd.getNic(); + VIF vif = getVifByMac(conn, vm, nic.getMac()); + if (vif != null) { + String msg = " Plug Nic failed due to a VIF with the same mac " + nic.getMac() + " exists"; + s_logger.warn(msg); + return new PlugNicAnswer(cmd, false, msg); + } + String deviceId = getLowestAvailableVIFDeviceNum(conn, vm); + nic.setDeviceId(Integer.parseInt(deviceId)); + vif = createVif(conn, vmName, vm, null, nic); + vif.plug(conn); + return new PlugNicAnswer(cmd, true, "success"); + } catch (Exception e) { + String msg = " Plug Nic failed due to " + e.toString(); + s_logger.warn(msg, e); + return new PlugNicAnswer(cmd, false, msg); + } + } + + /** + * @param cmd + * @return + */ + private ExecutionResult prepareNetworkElementCommand(SetupGuestNetworkCommand cmd) { + Connection conn = getConnection(); + NicTO nic = cmd.getNic(); + String domrName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + try { + Set vms = VM.getByNameLabel(conn, domrName); + if (vms == null || vms.isEmpty()) { + return new ExecutionResult(false, "Can not find VM " + domrName); + } + VM vm = vms.iterator().next(); + String mac = nic.getMac(); + VIF domrVif = null; + for (VIF vif : vm.getVIFs(conn)) { + String lmac = vif.getMAC(conn); + if (lmac.equals(mac)) { + domrVif = vif; + break; + } + } + if (domrVif == null) { + return new ExecutionResult(false, "Can not find vif with mac " + mac + " for VM " + domrName); + } + + nic.setDeviceId(Integer.valueOf(domrVif.getDevice(conn))); + } catch (Exception e) { + String msg = "Creating guest network failed due to " + e.toString(); + s_logger.warn(msg, e); + return new ExecutionResult(false, msg); + } + return new ExecutionResult(true, null); + } + + protected ExecutionResult prepareNetworkElementCommand(IpAssocVpcCommand cmd) { + Connection conn = getConnection(); + String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + try { + IpAddressTO[] ips = cmd.getIpAddresses(); + for (IpAddressTO ip : ips) { + + VM router = getVM(conn, routerName); + + VIF correctVif = getVifByMac(conn, router, ip.getVifMacAddress()); + setNicDevIdIfCorrectVifIsNotNull(conn, ip, correctVif); + } + } catch (Exception e) { + s_logger.error("Ip Assoc failure on applying one ip due to exception: ", e); + return new ExecutionResult(false, e.getMessage()); + } + + return new ExecutionResult(true, null); + } + + protected void setNicDevIdIfCorrectVifIsNotNull(Connection conn, IpAddressTO ip, VIF correctVif) throws InternalErrorException, BadServerResponse, XenAPIException, + XmlRpcException { + if (correctVif == null) { + if (ip.isAdd()) { + throw new InternalErrorException("Failed to find DomR VIF to associate IP with."); + } else { + s_logger.debug("VIF to deassociate IP with does not exist, return success"); + } + } else { + ip.setNicDevId(Integer.valueOf(correctVif.getDevice(conn))); + } + } + + protected ExecutionResult prepareNetworkElementCommand(SetSourceNatCommand cmd) { + Connection conn = getConnection(); + String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + IpAddressTO pubIp = cmd.getIpAddress(); + try { + VM router = getVM(conn, routerName); + + VIF correctVif = getCorrectVif(conn, router, pubIp); + + pubIp.setNicDevId(Integer.valueOf(correctVif.getDevice(conn))); + + } catch (Exception e) { + String msg = "Ip SNAT failure due to " + e.toString(); + s_logger.error(msg, e); + return new ExecutionResult(false, msg); + } + return new ExecutionResult(true, null); + } + + protected ExecutionResult prepareNetworkElementCommand(SetNetworkACLCommand cmd) { + Connection conn = getConnection(); + String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + + try { + VM router = getVM(conn, routerName); + + NicTO nic = cmd.getNic(); + VIF vif = getVifByMac(conn, router, nic.getMac()); + + nic.setDeviceId(Integer.valueOf(vif.getDevice(conn))); + } catch (Exception e) { + String msg = "Prepare SetNetworkACL failed due to " + e.toString(); + s_logger.error(msg, e); + return new ExecutionResult(false, msg); + } + return new ExecutionResult(true, null); + } + + @Override + public void setName(String name) { + } + + @Override + public void setConfigParams(Map params) { + } + + @Override + public Map getConfigParams() { + return null; + } + + @Override + public int getRunLevel() { + return 0; + } + + @Override + public void setRunLevel(int level) { + } + + private boolean is_xcp() { + Connection conn = getConnection(); + String result = callHostPlugin(conn, "ovstunnel", "is_xcp"); + if (result.equals("XCP")) + return true; + return false; + } + + private String getLabel() { + Connection conn = getConnection(); + String result = callHostPlugin(conn, "ovstunnel", "getLabel"); + return result; + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java new file mode 100644 index 00000000000..170730e9fe1 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpOssResource.java @@ -0,0 +1,195 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// 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. + +package com.cloud.hypervisor.xenserver.resource; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.NetworkUsageAnswer; +import com.cloud.agent.api.NetworkUsageCommand; +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.resource.ServerResource; +import com.cloud.storage.Storage; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; + +@Local(value = ServerResource.class) +public class XcpOssResource extends CitrixResourceBase { + private final static Logger s_logger = Logger.getLogger(XcpOssResource.class); + private static final long mem_32m = 33554432L; + + @Override + protected List getPatchFiles() { + List files = new ArrayList(); + String patch = "scripts/vm/hypervisor/xenserver/xcposs/patch"; + String patchfilePath = Script.findScript("", patch); + if (patchfilePath == null) { + throw new CloudRuntimeException("Unable to find patch file " + patch); + } + File file = new File(patchfilePath); + files.add(file); + return files; + } + + @Override + protected void fillHostInfo(Connection conn, StartupRoutingCommand cmd) { + super.fillHostInfo(conn, cmd); + cmd.setCaps(cmd.getCapabilities() + " , hvm"); + } + + @Override + protected boolean launchHeartBeat(Connection conn) { + return true; + } + + protected StartupStorageCommand initializeLocalSR(Connection conn) { + SR extsr = getLocalEXTSR(conn); + if (extsr != null) { + try { + String extuuid = extsr.getUuid(conn); + _host.localSRuuid = extuuid; + long cap = extsr.getPhysicalSize(conn); + if (cap > 0) { + long avail = cap - extsr.getPhysicalUtilisation(conn); + String name = "Cloud Stack Local EXT Storage Pool for " + _host.uuid; + extsr.setNameDescription(conn, name); + Host host = Host.getByUuid(conn, _host.uuid); + String address = host.getAddress(conn); + StoragePoolInfo pInfo = new StoragePoolInfo(extsr.getNameLabel(conn), address, SRType.EXT.toString(), SRType.EXT.toString(), Storage.StoragePoolType.EXT, cap, avail); + StartupStorageCommand cmd = new StartupStorageCommand(); + cmd.setPoolInfo(pInfo); + cmd.setGuid(_host.uuid); + cmd.setDataCenter(Long.toString(_dcId)); + cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); + return cmd; + } + } catch (XenAPIException e) { + String msg = "build local EXT info err in host:" + _host.uuid + e.toString(); + s_logger.warn(msg); + } catch (XmlRpcException e) { + String msg = "build local EXT info err in host:" + _host.uuid + e.getMessage(); + s_logger.warn(msg); + } + } + return null; + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + if (stdType.equalsIgnoreCase("Debian GNU/Linux 6(64-bit)")) { + return "Debian Squeeze 6.0 (64-bit)"; + } else if (stdType.equalsIgnoreCase("CentOS 5.6 (64-bit)")) { + return "CentOS 5 (64-bit)"; + } else { + return CitrixHelper.getXcpGuestOsType(stdType); + } + } + + @Override + protected synchronized VBD createPatchVbd(Connection conn, String vmName, VM vm) throws XmlRpcException, XenAPIException { + if (_host.localSRuuid != null) { + //create an iso vdi on it + String result = callHostPlugin(conn, "vmops", "createISOVHD", "uuid", _host.localSRuuid); + if (result == null || result.equalsIgnoreCase("Failed")) { + throw new CloudRuntimeException("can not create systemvm vdi"); + } + + Set vdis = VDI.getByNameLabel(conn, "systemvm-vdi"); + if (vdis.size() != 1) { + throw new CloudRuntimeException("can not find systemvmiso"); + } + VDI systemvmVDI = vdis.iterator().next(); + + VBD.Record cdromVBDR = new VBD.Record(); + cdromVBDR.VM = vm; + cdromVBDR.empty = false; + cdromVBDR.bootable = false; + cdromVBDR.userdevice = "3"; + cdromVBDR.mode = Types.VbdMode.RO; + cdromVBDR.type = Types.VbdType.DISK; + cdromVBDR.VDI = systemvmVDI; + VBD cdromVBD = VBD.create(conn, cdromVBDR); + return cdromVBD; + } else { + throw new CloudRuntimeException("can not find local sr"); + } + } + + protected NetworkUsageAnswer execute(NetworkUsageCommand cmd) { + try { + Connection conn = getConnection(); + if (cmd.getOption() != null && cmd.getOption().equals("create")) { + String result = networkUsage(conn, cmd.getPrivateIP(), "create", null); + NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, result, 0L, 0L); + return answer; + } + long[] stats = getNetworkStats(conn, cmd.getPrivateIP()); + NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, "", stats[0], stats[1]); + return answer; + } catch (Exception ex) { + s_logger.warn("Failed to get network usage stats due to ", ex); + return new NetworkUsageAnswer(cmd, ex); + } + } + + @Override + public Answer executeRequest(Command cmd) { + if (cmd instanceof NetworkUsageCommand) { + return execute((NetworkUsageCommand) cmd); + } else { + return super.executeRequest(cmd); + } + } + + @Override + public StopAnswer execute(StopCommand cmd) { + StopAnswer answer = super.execute(cmd); + String vmName = cmd.getVmName(); + if (vmName.startsWith("v-")) { + Connection conn = getConnection(); + callHostPlugin(conn, "vmops", "setDNATRule", "add", "false"); + } + return answer; + } + + @Override + protected void setMemory(Connection conn, VM vm, long minMemsize, long maxMemsize) throws XmlRpcException, XenAPIException { + vm.setMemoryLimits(conn, mem_32m, maxMemsize, minMemsize, maxMemsize); + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServer16Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServer16Resource.java new file mode 100644 index 00000000000..f5bede815ab --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServer16Resource.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with 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. + */ + +package com.cloud.hypervisor.xenserver.resource; + +public class XcpServer16Resource extends XcpServerResource { + + public XcpServer16Resource() { + super(); + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXcp160GuestOsType(stdType); + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServerResource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServerResource.java new file mode 100644 index 00000000000..28250084df6 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XcpServerResource.java @@ -0,0 +1,160 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VM; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.NetworkUsageAnswer; +import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.resource.ServerResource; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +@Local(value = ServerResource.class) +public class XcpServerResource extends CitrixResourceBase { + private final static Logger s_logger = Logger.getLogger(XcpServerResource.class); + private static final long mem_32m = 33554432L; + private String version; + + public XcpServerResource() { + super(); + } + + @Override + public Answer executeRequest(Command cmd) { + if (cmd instanceof NetworkUsageCommand) { + return execute((NetworkUsageCommand)cmd); + } else { + return super.executeRequest(cmd); + } + } + + @Override + protected List getPatchFiles() { + List files = new ArrayList(); + String patch = "scripts/vm/hypervisor/xenserver/xcpserver/patch"; + String patchfilePath = Script.findScript("", patch); + if (patchfilePath == null) { + throw new CloudRuntimeException("Unable to find patch file " + patch); + } + File file = new File(patchfilePath); + files.add(file); + return files; + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXcpGuestOsType(stdType); + } + + protected NetworkUsageAnswer execute(NetworkUsageCommand cmd) { + try { + Connection conn = getConnection(); + if (cmd.getOption() != null && cmd.getOption().equals("create")) { + String result = networkUsage(conn, cmd.getPrivateIP(), "create", null); + NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, result, 0L, 0L); + return answer; + } + long[] stats = getNetworkStats(conn, cmd.getPrivateIP()); + NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, "", stats[0], stats[1]); + return answer; + } catch (Exception ex) { + s_logger.warn("Failed to get network usage stats due to ", ex); + return new NetworkUsageAnswer(cmd, ex); + } + } + + /** + XCP provides four memory configuration fields through which + administrators can control this behaviour: + + * static-min + * dynamic-min + * dynamic-max + * static-max + + The fields static-{min,max} act as *hard* lower and upper + bounds for a guest's memory. For a running guest: + * it's not possible to assign the guest more memory than + static-max without first shutting down the guest. + * it's not possible to assign the guest less memory than + static-min without first shutting down the guest. + + The fields dynamic-{min,max} act as *soft* lower and upper + bounds for a guest's memory. It's possible to change these + fields even when a guest is running. + + The dynamic range must lie wholly within the static range. To + put it another way, XCP at all times ensures that: + + static-min <= dynamic-min <= dynamic-max <= static-max + + At all times, XCP will attempt to keep a guest's memory usage + between dynamic-min and dynamic-max. + + If dynamic-min = dynamic-max, then XCP will attempt to keep + a guest's memory allocation at a constant size. + + If dynamic-min < dynamic-max, then XCP will attempt to give + the guest as much memory as possible, while keeping the guest + within dynamic-min and dynamic-max. + + If there is enough memory on a given host to give all resident + guests dynamic-max, then XCP will attempt do so. + + If there is not enough memory to give all guests dynamic-max, + then XCP will ask each of the guests (on that host) to use + an amount of memory that is the same *proportional* distance + between dynamic-min and dynamic-max. + + XCP will refuse to start guests if starting those guests would + cause the sum of all the dynamic-min values to exceed the total + host memory (taking into account various memory overheads). + + cf: https://wiki.xenserver.org/index.php?title=XCP_FAQ_Dynamic_Memory_Control + */ + @Override + protected void setMemory(Connection conn, VM vm, long minMemsize, long maxMemsize) throws XmlRpcException, XenAPIException { + //setMemoryLimits(staticMin, staticMax, dynamicMin, dynamicMax) + if (s_logger.isDebugEnabled()) { + s_logger.debug("Memory Limits for VM [" + vm.getNameLabel(conn) + "[staticMin:" + mem_32m + ", staticMax:" + maxMemsize + ", dynamicMin: " + minMemsize + + ", dynamicMax:" + maxMemsize + "]]"); + } + vm.setMemoryLimits(conn, mem_32m, maxMemsize, minMemsize, maxMemsize); + } + + @Override + protected boolean isDmcEnabled(Connection conn, Host host) { + //Dynamic Memory Control (DMC) is a technology provided by Xen Cloud Platform (XCP), starting from the 0.5 release + //For the supported XCPs dmc is default enabled, XCP 1.0.0, 1.1.0, 1.4.x, 1.5 beta, 1.6.x; + return true; + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56FP1Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56FP1Resource.java new file mode 100644 index 00000000000..ddedaf5fcdc --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56FP1Resource.java @@ -0,0 +1,168 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; + +import com.cloud.agent.api.FenceAnswer; +import com.cloud.agent.api.FenceCommand; +import com.cloud.resource.ServerResource; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +@Local(value = ServerResource.class) +public class XenServer56FP1Resource extends XenServer56Resource { + private static final long mem_128m = 134217728L; + private static final Logger s_logger = Logger.getLogger(XenServer56FP1Resource.class); + + public XenServer56FP1Resource() { + super(); + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXenServer56FP1GuestOsType(stdType, bootFromCD); + } + + @Override + protected List getPatchFiles() { + List files = new ArrayList(); + String patch = "scripts/vm/hypervisor/xenserver/xenserver56fp1/patch"; + String patchfilePath = Script.findScript("", patch); + if (patchfilePath == null) { + throw new CloudRuntimeException("Unable to find patch file " + patch); + } + File file = new File(patchfilePath); + files.add(file); + return files; + } + + @Override + protected FenceAnswer execute(FenceCommand cmd) { + Connection conn = getConnection(); + try { + Boolean alive = check_heartbeat(cmd.getHostGuid()); + if ( alive == null ) { + s_logger.debug("Failed to check heartbeat, so unable to fence"); + return new FenceAnswer(cmd, false, "Failed to check heartbeat, so unable to fence"); + } + if ( alive ) { + s_logger.debug("Heart beat is still going so unable to fence"); + return new FenceAnswer(cmd, false, "Heartbeat is still going on unable to fence"); + } + Set vms = VM.getByNameLabel(conn, cmd.getVmName()); + for (VM vm : vms) { + Set vdis = new HashSet(); + Set vbds = vm.getVBDs(conn); + for (VBD vbd : vbds) { + VDI vdi = vbd.getVDI(conn); + if (!isRefNull(vdi)) { + vdis.add(vdi); + } + } + synchronized (_cluster.intern()) { + s_vms.remove(_cluster, _name, vm.getNameLabel(conn)); + } + s_logger.info("Fence command for VM " + cmd.getVmName()); + vm.powerStateReset(conn); + vm.destroy(conn); + for (VDI vdi : vdis) { + Map smConfig = vdi.getSmConfig(conn); + for (String key : smConfig.keySet()) { + if (key.startsWith("host_")) { + vdi.removeFromSmConfig(conn, key); + break; + } + } + } + } + return new FenceAnswer(cmd); + } catch (XmlRpcException e) { + s_logger.warn("Unable to fence", e); + return new FenceAnswer(cmd, false, e.getMessage()); + } catch (XenAPIException e) { + s_logger.warn("Unable to fence", e); + return new FenceAnswer(cmd, false, e.getMessage()); + } + } + + @Override + public long getStaticMax(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer56FP1StaticMax(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); + return dynamicMaxRam; + } + + long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability + if (dynamicMaxRam > staticMax) { // XS contraint that dynamic max <= static max + s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + + ", can lead to stability issues. Setting static max as much as dynamic max "); + return dynamicMaxRam; + } + return staticMax; + } + + @Override + public long getStaticMin(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer56FP1StaticMin(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic min"); + return dynamicMinRam; + } + + if (dynamicMinRam < recommendedValue) { // XS contraint that dynamic min > static min + s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues."); + } + return dynamicMinRam; + } + + /** + * When Dynamic Memory Control (DMC) is enabled - + * xenserver allows scaling the guest memory while the guest is running + * + * This is determined by the 'restrict_dmc' option on the host. + * When false, scaling is allowed hence DMC is enabled + */ + @Override + protected boolean isDmcEnabled(Connection conn, Host host) throws XenAPIException, XmlRpcException { + Map hostParams = new HashMap(); + hostParams = host.getLicenseParams(conn); + + Boolean isDmcEnabled = hostParams.get("restrict_dmc").equalsIgnoreCase("false"); + + return isDmcEnabled; + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56Resource.java new file mode 100644 index 00000000000..d3651f6a012 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56Resource.java @@ -0,0 +1,328 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckOnHostAnswer; +import com.cloud.agent.api.CheckOnHostCommand; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.FenceAnswer; +import com.cloud.agent.api.FenceCommand; +import com.cloud.agent.api.NetworkUsageAnswer; +import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.resource.ServerResource; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import com.cloud.utils.ssh.SSHCmdHelper; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.PIF; +import com.xensource.xenapi.Types.IpConfigurationMode; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VLAN; +import com.xensource.xenapi.VM; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import javax.ejb.Local; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +@Local(value = ServerResource.class) +public class XenServer56Resource extends CitrixResourceBase { + private final static Logger s_logger = Logger.getLogger(XenServer56Resource.class); + + @Override + public Answer executeRequest(Command cmd) { + if (cmd instanceof FenceCommand) { + return execute((FenceCommand)cmd); + } else if (cmd instanceof NetworkUsageCommand) { + return execute((NetworkUsageCommand)cmd); + } else { + return super.executeRequest(cmd); + } + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXenServerGuestOsType(stdType, bootFromCD); + } + + @Override + protected List getPatchFiles() { + List files = new ArrayList(); + String patch = "scripts/vm/hypervisor/xenserver/xenserver56/patch"; + String patchfilePath = Script.findScript("", patch); + if (patchfilePath == null) { + throw new CloudRuntimeException("Unable to find patch file " + patch); + } + File file = new File(patchfilePath); + files.add(file); + + return files; + } + + @Override + protected void disableVlanNetwork(Connection conn, Network network) { + try { + Network.Record networkr = network.getRecord(conn); + if (!networkr.nameLabel.startsWith("VLAN")) { + return; + } + String bridge = networkr.bridge.trim(); + for (PIF pif : networkr.PIFs) { + PIF.Record pifr = pif.getRecord(conn); + if (!pifr.host.getUuid(conn).equalsIgnoreCase(_host.uuid)) { + continue; + } + + VLAN vlan = pifr.VLANMasterOf; + if (vlan != null) { + String vlannum = pifr.VLAN.toString(); + String device = pifr.device.trim(); + if (vlannum.equals("-1")) { + return; + } + try { + vlan.destroy(conn); + Host host = Host.getByUuid(conn, _host.uuid); + host.forgetDataSourceArchives(conn, "pif_" + bridge + "_tx"); + host.forgetDataSourceArchives(conn, "pif_" + bridge + "_rx"); + host.forgetDataSourceArchives(conn, "pif_" + device + "." + vlannum + "_tx"); + host.forgetDataSourceArchives(conn, "pif_" + device + "." + vlannum + "_rx"); + } catch (XenAPIException e) { + s_logger.info("Catch " + e.getClass().getName() + ": failed to destory VLAN " + device + " on host " + _host.uuid + " due to " + e.toString()); + } + } + return; + } + } catch (XenAPIException e) { + String msg = "Unable to disable VLAN network due to " + e.toString(); + s_logger.warn(msg, e); + } catch (Exception e) { + String msg = "Unable to disable VLAN network due to " + e.getMessage(); + s_logger.warn(msg, e); + } + } + + @Override + protected String networkUsage(Connection conn, final String privateIpAddress, final String option, final String vif) { + String args = ""; + if (option.equals("get")) { + args += "-g"; + } else if (option.equals("create")) { + args += "-c"; + } else if (option.equals("reset")) { + args += "-r"; + } else if (option.equals("addVif")) { + args += "-a "; + args += vif; + } else if (option.equals("deleteVif")) { + args += "-d "; + args += vif; + } + + return executeInVR(privateIpAddress, "netusage.sh", args).getDetails(); + } + + protected NetworkUsageAnswer VPCNetworkUsage(NetworkUsageCommand cmd) { + try { + Connection conn = getConnection(); + String option = cmd.getOption(); + String publicIp = cmd.getGatewayIP(); + + String args = " -l " + publicIp + " "; + if (option.equals("get")) { + args += "-g"; + } else if (option.equals("create")) { + args += "-c"; + String vpcCIDR = cmd.getVpcCIDR(); + args += " -v " + vpcCIDR; + } else if (option.equals("reset")) { + args += "-r"; + } else if (option.equals("vpn")) { + args += "-n"; + } else if (option.equals("remove")) { + args += "-d"; + } else { + return new NetworkUsageAnswer(cmd, "success", 0L, 0L); + } + + String result = executeInVR(cmd.getPrivateIP(), "vpc_netusage.sh", args).getDetails(); + if (option.equals("get") || option.equals("vpn")) { + long[] stats = new long[2]; + if (result != null) { + String[] splitResult = result.split(":"); + int i = 0; + while (i < splitResult.length - 1) { + stats[0] += (new Long(splitResult[i++])).longValue(); + stats[1] += (new Long(splitResult[i++])).longValue(); + } + return new NetworkUsageAnswer(cmd, "success", stats[0], stats[1]); + } + } + if (result == null || result.isEmpty()) { + throw new Exception(" vpc network usage plugin call failed "); + } + return new NetworkUsageAnswer(cmd, "success", 0L, 0L); + } catch (Exception ex) { + s_logger.warn("Failed to get network usage stats due to ", ex); + return new NetworkUsageAnswer(cmd, ex); + } + } + + protected NetworkUsageAnswer execute(NetworkUsageCommand cmd) { + if (cmd.isForVpc()) { + return VPCNetworkUsage(cmd); + } + try { + Connection conn = getConnection(); + if (cmd.getOption() != null && cmd.getOption().equals("create")) { + String result = networkUsage(conn, cmd.getPrivateIP(), "create", null); + NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, result, 0L, 0L); + return answer; + } + long[] stats = getNetworkStats(conn, cmd.getPrivateIP()); + NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, "", stats[0], stats[1]); + return answer; + } catch (Exception ex) { + s_logger.warn("Failed to get network usage stats due to ", ex); + return new NetworkUsageAnswer(cmd, ex); + } + } + + protected Boolean check_heartbeat(String hostuuid) { + com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.ip, 22); + try { + sshConnection.connect(null, 60000, 60000); + if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { + throw new CloudRuntimeException("Unable to authenticate"); + } + + String shcmd = "/opt/cloud/bin/check_heartbeat.sh " + hostuuid + " " + + Integer.toString(_heartbeatInterval * 2); + if (!SSHCmdHelper.sshExecuteCmd(sshConnection, shcmd)) { + s_logger.debug("Heart beat is gone so dead."); + return false; + } + s_logger.debug("Heart beat is still going"); + return true; + } catch (Exception e) { + s_logger.debug("health check failed due to catch exception " + e.toString()); + return null; + } finally { + sshConnection.close(); + } + } + + protected FenceAnswer execute(FenceCommand cmd) { + Connection conn = getConnection(); + try { + Boolean alive = check_heartbeat(cmd.getHostGuid()); + if ( alive == null ) { + s_logger.debug("Failed to check heartbeat, so unable to fence"); + return new FenceAnswer(cmd, false, "Failed to check heartbeat, so unable to fence"); + } + if ( alive ) { + s_logger.debug("Heart beat is still going so unable to fence"); + return new FenceAnswer(cmd, false, "Heartbeat is still going on unable to fence"); + } + Set vms = VM.getByNameLabel(conn, cmd.getVmName()); + for (VM vm : vms) { + synchronized (_cluster.intern()) { + s_vms.remove(_cluster, _name, vm.getNameLabel(conn)); + } + s_logger.info("Fence command for VM " + cmd.getVmName()); + vm.powerStateReset(conn); + vm.destroy(conn); + } + return new FenceAnswer(cmd); + } catch (XmlRpcException e) { + s_logger.warn("Unable to fence", e); + return new FenceAnswer(cmd, false, e.getMessage()); + } catch (XenAPIException e) { + s_logger.warn("Unable to fence", e); + return new FenceAnswer(cmd, false, e.getMessage()); + } + } + + + @Override + protected boolean transferManagementNetwork(Connection conn, Host host, PIF src, PIF.Record spr, PIF dest) throws XmlRpcException, XenAPIException { + dest.reconfigureIp(conn, spr.ipConfigurationMode, spr.IP, spr.netmask, spr.gateway, spr.DNS); + Host.managementReconfigure(conn, dest); + String hostUuid = null; + int count = 0; + while (count < 10) { + try { + Thread.sleep(10000); + hostUuid = host.getUuid(conn); + if (hostUuid != null) { + break; + } + } catch (XmlRpcException e) { + s_logger.debug("Waiting for host to come back: " + e.getMessage()); + } catch (XenAPIException e) { + s_logger.debug("Waiting for host to come back: " + e.getMessage()); + } catch (InterruptedException e) { + s_logger.debug("Gotta run"); + return false; + } + } + if (hostUuid == null) { + s_logger.warn("Unable to transfer the management network from " + spr.uuid); + return false; + } + + src.reconfigureIp(conn, IpConfigurationMode.NONE, null, null, null, null); + return true; + } + + @Override + public StartupCommand[] initialize() { + pingXAPI(); + StartupCommand[] cmds = super.initialize(); + return cmds; + } + + + @Override + protected CheckOnHostAnswer execute(CheckOnHostCommand cmd) { + Boolean alive = check_heartbeat(cmd.getHost().getGuid()); + String msg = ""; + if (alive == null) { + msg = " cannot determine "; + } else if ( alive == true) { + msg = "Heart beat is still going"; + } else { + msg = "Heart beat is gone so dead."; + } + s_logger.debug(msg); + return new CheckOnHostAnswer(cmd, alive, msg); + + } + + + public XenServer56Resource() { + super(); + } + +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56SP2Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56SP2Resource.java new file mode 100644 index 00000000000..cfe6f159186 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer56SP2Resource.java @@ -0,0 +1,89 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; + +import com.cloud.resource.ServerResource; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +@Local(value = ServerResource.class) +public class XenServer56SP2Resource extends XenServer56FP1Resource { + private static final Logger s_logger = Logger.getLogger(XenServer56SP2Resource.class); + + public XenServer56SP2Resource() { + super(); + _xsMemoryUsed = 128 * 1024 * 1024L; + _xsVirtualizationFactor = 62.0 / 64.0; + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXenServer56SP2GuestOsType(stdType, bootFromCD); + } + + @Override + protected List getPatchFiles() { + List files = new ArrayList(); + String patch = "scripts/vm/hypervisor/xenserver/xenserver56fp1/patch"; + String patchfilePath = Script.findScript("", patch); + if (patchfilePath == null) { + throw new CloudRuntimeException("Unable to find patch file " + patch); + } + File file = new File(patchfilePath); + files.add(file); + return files; + } + + @Override + public long getStaticMax(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer56SP2StaticMax(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); + return dynamicMaxRam; + } + long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability + if (dynamicMaxRam > staticMax) { // XS contraint that dynamic max <= static max + s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + + ", can lead to stability issues. Setting static max as much as dynamic max "); + return dynamicMaxRam; + } + return staticMax; + } + + @Override + public long getStaticMin(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer56SP2StaticMin(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic min"); + return dynamicMinRam; + } + + if (dynamicMinRam < recommendedValue) { // XS contraint that dynamic min > static min + s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues"); + } + return dynamicMinRam; + } + +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer600Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer600Resource.java new file mode 100644 index 00000000000..777dc900268 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer600Resource.java @@ -0,0 +1,87 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; + +import com.cloud.resource.ServerResource; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +@Local(value = ServerResource.class) +public class XenServer600Resource extends XenServer56FP1Resource { + private static final Logger s_logger = Logger.getLogger(XenServer600Resource.class); + + public XenServer600Resource() { + super(); + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXenServer600GuestOsType(stdType, bootFromCD); + } + + @Override + public long getStaticMax(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer600StaticMax(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); + return dynamicMaxRam; + } + long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability + if (dynamicMaxRam > staticMax) { // XS contraint that dynamic max <= static max + s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + + ", can lead to stability issues. Setting static max as much as dynamic max "); + return dynamicMaxRam; + } + return staticMax; + } + + @Override + public long getStaticMin(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer600StaticMin(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic min"); + return dynamicMinRam; + } + + if (dynamicMinRam < recommendedValue) { // XS contraint that dynamic min > static min + s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues"); + } + return dynamicMinRam; + } + + @Override + protected List getPatchFiles() { + List files = new ArrayList(); + String patch = "scripts/vm/hypervisor/xenserver/xenserver60/patch"; + String patchfilePath = Script.findScript("", patch); + if (patchfilePath == null) { + throw new CloudRuntimeException("Unable to find patch file " + patch); + } + File file = new File(patchfilePath); + files.add(file); + return files; + } + +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer602Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer602Resource.java new file mode 100644 index 00000000000..2c7122d8150 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer602Resource.java @@ -0,0 +1,64 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; +import javax.ejb.Local; +import org.apache.log4j.Logger; +import com.cloud.resource.ServerResource; + +@Local(value = ServerResource.class) +public class XenServer602Resource extends XenServer56FP1Resource { + private static final Logger s_logger = Logger.getLogger(XenServer602Resource.class); + + public XenServer602Resource() { + super(); + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXenServer602GuestOsType(stdType, bootFromCD); + } + + @Override + public long getStaticMax(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer602StaticMax(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); + return dynamicMaxRam; + } + long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability + if (dynamicMaxRam > staticMax) { // XS contraint that dynamic max <= static max + s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + + ", can lead to stability issues. Setting static max as much as dynamic max "); + return dynamicMaxRam; + } + return staticMax; + } + + @Override + public long getStaticMin(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer602StaticMin(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic min"); + return dynamicMinRam; + } + if (dynamicMinRam < recommendedValue) { // XS contraint that dynamic min > static min + s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues"); + } + return dynamicMinRam; + } + +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java new file mode 100644 index 00000000000..843735cdb6a --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java @@ -0,0 +1,434 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Task; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VIF; +import com.xensource.xenapi.VM; + +import org.apache.cloudstack.storage.to.VolumeObjectTO; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.MigrateWithStorageAnswer; +import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.MigrateWithStorageCompleteAnswer; +import com.cloud.agent.api.MigrateWithStorageCompleteCommand; +import com.cloud.agent.api.MigrateWithStorageReceiveAnswer; +import com.cloud.agent.api.MigrateWithStorageReceiveCommand; +import com.cloud.agent.api.MigrateWithStorageSendAnswer; +import com.cloud.agent.api.MigrateWithStorageSendCommand; +import com.cloud.agent.api.storage.MigrateVolumeAnswer; +import com.cloud.agent.api.storage.MigrateVolumeCommand; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.network.Networks.TrafficType; +import com.cloud.resource.ServerResource; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachine.State; + +@Local(value = ServerResource.class) +public class XenServer610Resource extends XenServer56FP1Resource { + private static final Logger s_logger = Logger.getLogger(XenServer610Resource.class); + + public XenServer610Resource() { + super(); + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXenServer610GuestOsType(stdType, bootFromCD); + } + + @Override + public Answer executeRequest(Command cmd) { + if (cmd instanceof MigrateWithStorageCommand) { + return execute((MigrateWithStorageCommand)cmd); + } else if (cmd instanceof MigrateWithStorageReceiveCommand) { + return execute((MigrateWithStorageReceiveCommand)cmd); + } else if (cmd instanceof MigrateWithStorageSendCommand) { + return execute((MigrateWithStorageSendCommand)cmd); + } else if (cmd instanceof MigrateWithStorageCompleteCommand) { + return execute((MigrateWithStorageCompleteCommand)cmd); + } else if (cmd instanceof MigrateVolumeCommand) { + return execute((MigrateVolumeCommand)cmd); + } else { + return super.executeRequest(cmd); + } + } + + private List getUpdatedVolumePathsOfMigratedVm(Connection connection, VM migratedVm, DiskTO[] volumes) throws CloudRuntimeException { + List volumeToList = new ArrayList(); + + try { + // Volume paths would have changed. Return that information. + Set vbds = migratedVm.getVBDs(connection); + Map deviceIdToVdiMap = new HashMap(); + // get vdi:vbdr to a map + for (VBD vbd : vbds) { + VBD.Record vbdr = vbd.getRecord(connection); + if (vbdr.type == Types.VbdType.DISK) { + VDI vdi = vbdr.VDI; + deviceIdToVdiMap.put(vbdr.userdevice, vdi); + } + } + + for (DiskTO volumeTo : volumes) { + VolumeObjectTO vol = (VolumeObjectTO)volumeTo.getData(); + Long deviceId = volumeTo.getDiskSeq(); + VDI vdi = deviceIdToVdiMap.get(deviceId.toString()); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(vdi.getUuid(connection)); + newVol.setId(vol.getId()); + volumeToList.add(newVol); + } + } catch (Exception e) { + s_logger.error("Unable to get the updated VDI paths of the migrated vm " + e.toString(), e); + throw new CloudRuntimeException("Unable to get the updated VDI paths of the migrated vm " + e.toString(), e); + } + + return volumeToList; + } + + protected MigrateWithStorageAnswer execute(MigrateWithStorageCommand cmd) { + Connection connection = getConnection(); + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + Map volumeToFiler = cmd.getVolumeToFiler(); + final String vmName = vmSpec.getName(); + State state = s_vms.getState(_cluster, vmName); + Task task = null; + + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, State.Stopping); + } + + try { + prepareISO(connection, vmSpec.getName()); + Map other = new HashMap(); + other.put("live", "true"); + Network networkForSm = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork(); + Host host = Host.getByUuid(connection, _host.uuid); + Map token = host.migrateReceive(connection, networkForSm, other); + + // Get the vm to migrate. + Set vms = VM.getByNameLabel(connection, vmSpec.getName()); + VM vmToMigrate = vms.iterator().next(); + + // Create the vif map. The vm stays in the same cluster so we have to pass an empty vif map. + Map vifMap = new HashMap(); + Map vdiMap = new HashMap(); + for (Map.Entry entry : volumeToFiler.entrySet()) { + vdiMap.put(getVDIbyUuid(connection, entry.getKey().getPath()), getStorageRepository(connection, entry.getValue().getUuid())); + } + + // Check migration with storage is possible. + task = vmToMigrate.assertCanMigrateAsync(connection, token, true, vdiMap, vifMap, other); + try { + // poll every 1 seconds + long timeout = (_migratewait) * 1000L; + waitForTask(connection, task, 1000, timeout); + checkForSuccess(connection, task); + } catch (Types.HandleInvalid e) { + s_logger.error("Error while checking if vm " + vmName + " can be migrated to the destination host " + host, e); + throw new CloudRuntimeException("Error while checking if vm " + vmName + " can be migrated to the " + "destination host " + host, e); + } + + // Migrate now. + task = vmToMigrate.migrateSendAsync(connection, token, true, vdiMap, vifMap, other); + try { + // poll every 1 seconds. + long timeout = (_migratewait) * 1000L; + waitForTask(connection, task, 1000, timeout); + checkForSuccess(connection, task); + } catch (Types.HandleInvalid e) { + s_logger.error("Error while migrating vm " + vmName + " to the destination host " + host, e); + throw new CloudRuntimeException("Error while migrating vm " + vmName + " to the destination host " + host, e); + } + + // Volume paths would have changed. Return that information. + List volumeToList = getUpdatedVolumePathsOfMigratedVm(connection, vmToMigrate, vmSpec.getDisks()); + vmToMigrate.setAffinity(connection, host); + state = State.Stopping; + + return new MigrateWithStorageAnswer(cmd, volumeToList); + } catch (Exception e) { + s_logger.warn("Catch Exception " + e.getClass().getName() + ". Storage motion failed due to " + e.toString(), e); + return new MigrateWithStorageAnswer(cmd, e); + } finally { + if (task != null) { + try { + task.destroy(connection); + } catch (Exception e) { + s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.uuid + " due to " + e.toString()); + } + } + + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, state); + } + } + } + + protected MigrateWithStorageReceiveAnswer execute(MigrateWithStorageReceiveCommand cmd) { + Connection connection = getConnection(); + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + Map volumeToFiler = cmd.getVolumeToFiler(); + + try { + // Get a map of all the SRs to which the vdis will be migrated. + Map volumeToSr = new HashMap(); + for (Map.Entry entry : volumeToFiler.entrySet()) { + SR sr = getStorageRepository(connection, entry.getValue().getUuid()); + volumeToSr.put(entry.getKey(), sr); + } + + // Get the list of networks to which the vifs will attach. + Map nicToNetwork = new HashMap(); + for (NicTO nicTo : vmSpec.getNics()) { + Network network = getNetwork(connection, nicTo); + nicToNetwork.put(nicTo, network); + } + + Map other = new HashMap(); + other.put("live", "true"); + Network network = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork(); + Host host = Host.getByUuid(connection, _host.uuid); + Map token = host.migrateReceive(connection, network, other); + + return new MigrateWithStorageReceiveAnswer(cmd, volumeToSr, nicToNetwork, token); + } catch (CloudRuntimeException e) { + s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageReceiveAnswer(cmd, e); + } catch (Exception e) { + s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageReceiveAnswer(cmd, e); + } + } + + protected MigrateWithStorageSendAnswer execute(MigrateWithStorageSendCommand cmd) { + Connection connection = getConnection(); + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + Map volumeToSr = cmd.getVolumeToSr(); + Map nicToNetwork = cmd.getNicToNetwork(); + Map token = cmd.getToken(); + final String vmName = vmSpec.getName(); + State state = s_vms.getState(_cluster, vmName); + Set volumeToSet = null; + boolean migrated = false; + Task task = null; + + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, State.Stopping); + } + + try { + Set vms = VM.getByNameLabel(connection, vmSpec.getName()); + VM vmToMigrate = vms.iterator().next(); + Map other = new HashMap(); + other.put("live", "true"); + + // Create the vdi map which tells what volumes of the vm need to go on which sr on the destination. + Map vdiMap = new HashMap(); + for (Map.Entry entry : volumeToSr.entrySet()) { + if (entry.getValue() instanceof SR) { + SR sr = (SR)entry.getValue(); + VDI vdi = getVDIbyUuid(connection, entry.getKey().getPath()); + vdiMap.put(vdi, sr); + } else { + throw new CloudRuntimeException("The object " + entry.getValue() + " passed is not of type SR."); + } + } + + // Create the vif map. + Map vifMap = new HashMap(); + for (Map.Entry entry : nicToNetwork.entrySet()) { + if (entry.getValue() instanceof Network) { + Network network = (Network)entry.getValue(); + VIF vif = getVifByMac(connection, vmToMigrate, entry.getKey().getMac()); + vifMap.put(vif, network); + } else { + throw new CloudRuntimeException("The object " + entry.getValue() + " passed is not of type Network."); + } + } + + // Check migration with storage is possible. + task = vmToMigrate.assertCanMigrateAsync(connection, token, true, vdiMap, vifMap, other); + try { + // poll every 1 seconds. + long timeout = (_migratewait) * 1000L; + waitForTask(connection, task, 1000, timeout); + checkForSuccess(connection, task); + } catch (Types.HandleInvalid e) { + s_logger.error("Error while checking if vm " + vmName + " can be migrated.", e); + throw new CloudRuntimeException("Error while checking if vm " + vmName + " can be migrated.", e); + } + + // Migrate now. + task = vmToMigrate.migrateSendAsync(connection, token, true, vdiMap, vifMap, other); + try { + // poll every 1 seconds. + long timeout = (_migratewait) * 1000L; + waitForTask(connection, task, 1000, timeout); + checkForSuccess(connection, task); + } catch (Types.HandleInvalid e) { + s_logger.error("Error while migrating vm " + vmName, e); + throw new CloudRuntimeException("Error while migrating vm " + vmName, e); + } + + migrated = true; + return new MigrateWithStorageSendAnswer(cmd, volumeToSet); + } catch (CloudRuntimeException e) { + s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageSendAnswer(cmd, e); + } catch (Exception e) { + s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageSendAnswer(cmd, e); + } finally { + if (task != null) { + try { + task.destroy(connection); + } catch (Exception e) { + s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.uuid + " due to " + e.toString()); + } + } + + // Keep cluster/vm sync happy. + synchronized (_cluster.intern()) { + if (migrated) { + s_vms.remove(_cluster, _name, vmName); + } else { + s_vms.put(_cluster, _name, vmName, state); + } + } + } + } + + protected MigrateWithStorageCompleteAnswer execute(MigrateWithStorageCompleteCommand cmd) { + Connection connection = getConnection(); + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + + try { + Host host = Host.getByUuid(connection, _host.uuid); + Set vms = VM.getByNameLabel(connection, vmSpec.getName()); + VM migratedVm = vms.iterator().next(); + + // Check the vm is present on the new host. + if (migratedVm == null) { + throw new CloudRuntimeException("Couldn't find the migrated vm " + vmSpec.getName() + " on the destination host."); + } + + // Volume paths would have changed. Return that information. + List volumeToSet = getUpdatedVolumePathsOfMigratedVm(connection, migratedVm, vmSpec.getDisks()); + migratedVm.setAffinity(connection, host); + + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmSpec.getName(), State.Running); + } + + return new MigrateWithStorageCompleteAnswer(cmd, volumeToSet); + } catch (CloudRuntimeException e) { + s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageCompleteAnswer(cmd, e); + } catch (Exception e) { + s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageCompleteAnswer(cmd, e); + } + } + + protected MigrateVolumeAnswer execute(MigrateVolumeCommand cmd) { + Connection connection = getConnection(); + String volumeUUID = cmd.getVolumePath(); + StorageFilerTO poolTO = cmd.getPool(); + + try { + SR destinationPool = getStorageRepository(connection, poolTO.getUuid()); + VDI srcVolume = getVDIbyUuid(connection, volumeUUID); + Map other = new HashMap(); + other.put("live", "true"); + + // Live migrate the vdi across pool. + Task task = srcVolume.poolMigrateAsync(connection, destinationPool, other); + long timeout = (_migratewait) * 1000L; + waitForTask(connection, task, 1000, timeout); + checkForSuccess(connection, task); + VDI dvdi = Types.toVDI(task, connection); + + return new MigrateVolumeAnswer(cmd, true, null, dvdi.getUuid(connection)); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); + s_logger.error(msg, e); + return new MigrateVolumeAnswer(cmd, false, msg, null); + } + } + + @Override + public long getStaticMax(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer610StaticMax(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); + return dynamicMaxRam; + } + long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability + if (dynamicMaxRam > staticMax) { // XS contraint that dynamic max <= static max + s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + + ", can lead to stability issues. Setting static max as much as dynamic max "); + return dynamicMaxRam; + } + return staticMax; + } + + @Override + public long getStaticMin(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer610StaticMin(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic min"); + return dynamicMinRam; + } + + if (dynamicMinRam < recommendedValue) { // XS contraint that dynamic min > static min + s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues"); + } + return dynamicMinRam; + } + + @Override + protected void plugDom0Vif(Connection conn, VIF dom0Vif) throws XmlRpcException, XenAPIException { + // do nothing. In xenserver 6.1 and beyond this step isn't needed. + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620Resource.java new file mode 100644 index 00000000000..0c8cc0beeb5 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620Resource.java @@ -0,0 +1,108 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.HostPatch; +import com.xensource.xenapi.PoolPatch; +import org.apache.cloudstack.hypervisor.xenserver.XenserverConfigs; +import java.util.Map; +import java.util.Set; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.resource.ServerResource; + +@Local(value = ServerResource.class) +public class XenServer620Resource extends XenServer610Resource { + private static final Logger s_logger = Logger.getLogger(XenServer620Resource.class); + + public XenServer620Resource() { + super(); + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXenServer620GuestOsType(stdType, bootFromCD); + } + + @Override + public long getStaticMax(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer620StaticMax(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); + return dynamicMaxRam; + } + long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability + if (dynamicMaxRam > staticMax) { // XS contraint that dynamic max <= static max + s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + + ", can lead to stability issues. Setting static max as much as dynamic max "); + return dynamicMaxRam; + } + return staticMax; + } + + @Override + public long getStaticMin(String os, boolean b, long dynamicMinRam, long dynamicMaxRam) { + long recommendedValue = CitrixHelper.getXenServer620StaticMin(os, b); + if (recommendedValue == 0) { + s_logger.warn("No recommended value found for dynamic min"); + return dynamicMinRam; + } + + if (dynamicMinRam < recommendedValue) { // XS contraint that dynamic min > static min + s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues"); + } + return dynamicMinRam; + } + + protected boolean hostHasHotFix(Connection conn, String hotFixUuid) { + try { + Host host = Host.getByUuid(conn, _host.uuid); + Host.Record re = host.getRecord(conn); + Set patches = re.patches; + PoolPatch poolPatch = PoolPatch.getByUuid(conn, hotFixUuid); + for(HostPatch patch : patches) { + PoolPatch pp = patch.getPoolPatch(conn); + if (pp.equals(poolPatch) && patch.getApplied(conn)) { + return true; + } + } + } catch (Exception e) { + s_logger.debug("can't get patches information for hotFix: " + hotFixUuid); + } + return false; + } + + protected void fillHostInfo(Connection conn, StartupRoutingCommand cmd) { + super.fillHostInfo(conn, cmd); + Map details = cmd.getHostDetails(); + Boolean hotFix62ESP1004 = hostHasHotFix(conn, XenserverConfigs.XSHotFix62ESP1004); + if( hotFix62ESP1004 != null && hotFix62ESP1004 ) { + details.put(XenserverConfigs.XS620HotFix , XenserverConfigs.XSHotFix62ESP1004); + } else { + Boolean hotFix62ESP1 = hostHasHotFix(conn, XenserverConfigs.XSHotFix62ESP1); + if( hotFix62ESP1 != null && hotFix62ESP1 ) { + details.put(XenserverConfigs.XS620HotFix , XenserverConfigs.XSHotFix62ESP1); + } + } + cmd.setHostDetails(details); + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java new file mode 100644 index 00000000000..b89e3387657 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer620SP1Resource.java @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with 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. + */ +package com.cloud.hypervisor.xenserver.resource; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.GetGPUStatsAnswer; +import com.cloud.agent.api.GetGPUStatsCommand; +import com.cloud.agent.api.StartCommand; +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.to.GPUDeviceTO; +import com.cloud.resource.ServerResource; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.GPUGroup; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.PGPU; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VGPU; +import com.xensource.xenapi.VGPUType; +import com.xensource.xenapi.VM; + +@Local(value=ServerResource.class) +public class XenServer620SP1Resource extends XenServer620Resource { + private static final Logger s_logger = Logger.getLogger(XenServer620SP1Resource.class); + + public XenServer620SP1Resource() { + super(); + } + + @Override + public Answer executeRequest(Command cmd) { + Class clazz = cmd.getClass(); + if (clazz == GetGPUStatsCommand.class) { + return execute((GetGPUStatsCommand) cmd); + } else { + return super.executeRequest(cmd); + } + } + + protected GetGPUStatsAnswer execute(GetGPUStatsCommand cmd) { + Connection conn = getConnection(); + HashMap> groupDetails = new HashMap>(); + try { + groupDetails = getGPUGroupDetails(conn); + } catch (Exception e) { + String msg = "Unable to get GPU stats" + e.toString(); + s_logger.warn(msg, e); + } + return new GetGPUStatsAnswer(cmd, groupDetails); + } + + @Override + protected void fillHostInfo(Connection conn, StartupRoutingCommand cmd) { + super.fillHostInfo(conn, cmd); + try { + HashMap> groupDetails = getGPUGroupDetails(conn); + cmd.setGpuGroupDetails(groupDetails); + } catch (Exception e) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Error while getting GPU device info from host " + cmd.getName(), e); + } + } + } + + @Override + protected HashMap> getGPUGroupDetails(Connection conn) throws XenAPIException, XmlRpcException { + HashMap> groupDetails = new HashMap>(); + Host host = Host.getByUuid(conn, _host.uuid); + Set pgpus = host.getPGPUs(conn); + Iterator iter = pgpus.iterator(); + while (iter.hasNext()) { + PGPU pgpu = iter.next(); + GPUGroup gpuGroup = pgpu.getGPUGroup(conn); + Set enabledVGPUTypes = gpuGroup.getEnabledVGPUTypes(conn); + String groupName = gpuGroup.getNameLabel(conn); + HashMap gpuCapacity = new HashMap(); + if (groupDetails.get(groupName) != null) { + gpuCapacity = groupDetails.get(groupName); + } + // Get remaining capacity of all the enabled VGPU in a PGPU + if(enabledVGPUTypes != null) { + Iterator it = enabledVGPUTypes.iterator(); + while (it.hasNext()) { + VGPUType type = it.next(); + String modelName = type.getModelName(conn); + Long remainingCapacity = pgpu.getRemainingCapacity(conn, type); + if (gpuCapacity.get(modelName) != null) { + long newRemainingCapacity = gpuCapacity.get(modelName) + remainingCapacity; + gpuCapacity.put(modelName, newRemainingCapacity); + } else { + gpuCapacity.put(modelName, remainingCapacity); + } + } + } + groupDetails.put(groupName, gpuCapacity); + } + return groupDetails; + } + + @Override + protected void createVGPU(Connection conn, StartCommand cmd, VM vm, GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException { + Set groups = GPUGroup.getByNameLabel(conn, gpuDevice.getGpuGroup()); + assert groups.size() == 1 : "Should only have 1 group but found " + groups.size(); + GPUGroup gpuGroup = groups.iterator().next(); + + Set vgpuTypes = gpuGroup.getEnabledVGPUTypes(conn); + Iterator iter = vgpuTypes.iterator(); + VGPUType vgpuType = null; + while (iter.hasNext()) { + VGPUType entry = iter.next(); + if (entry.getModelName(conn).equals(gpuDevice.getVgpuType())) { + vgpuType = entry; + } + } + String device = "0"; // Only allow device = "0" for now, as XenServer supports just a single vGPU per VM. + Map other_config = new HashMap(); + VGPU.create(conn, vm, gpuGroup, device, other_config, vgpuType); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Created VGPU of VGPU type [ " + gpuDevice.getVgpuType() + " ] for VM " + cmd.getVirtualMachine().getName()); + } + // Calculate and set remaining GPU capacity in the host. + cmd.getVirtualMachine().getGpuDevice().setGroupDetails(getGPUGroupDetails(conn)); + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXenServer620SP1GuestOsType(stdType, bootFromCD); + } + + @Override + public long getStaticMax(String os, boolean b, long dynamicMinRam, long dynamicMaxRam){ + long recommendedValue = CitrixHelper.getXenServer620SP1StaticMax(os, b); + if(recommendedValue == 0){ + s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); + return dynamicMaxRam; + } + long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability + if (dynamicMaxRam > staticMax){ // XS contraint that dynamic max <= static max + s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + ", can lead to stability issues. Setting static max as much as dynamic max "); + return dynamicMaxRam; + } + return staticMax; + } + + @Override + public long getStaticMin(String os, boolean b, long dynamicMinRam, long dynamicMaxRam){ + long recommendedValue = CitrixHelper.getXenServer620SP1StaticMin(os, b); + if(recommendedValue == 0){ + s_logger.warn("No recommended value found for dynamic min"); + return dynamicMinRam; + } + + if(dynamicMinRam < recommendedValue){ // XS contraint that dynamic min > static min + s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues"); + } + return dynamicMinRam; + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerConnectionPool.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerConnectionPool.java new file mode 100644 index 00000000000..ae065d20ea2 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerConnectionPool.java @@ -0,0 +1,503 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.Queue; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClientException; + +import com.xensource.xenapi.APIVersion; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Pool; +import com.xensource.xenapi.Session; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.BadServerResponse; +import com.xensource.xenapi.Types.XenAPIException; + +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.PropertiesUtil; +import com.cloud.utils.exception.CloudRuntimeException; + +public class XenServerConnectionPool { + private static final Logger s_logger = Logger.getLogger(XenServerConnectionPool.class); + protected HashMap _conns = new HashMap(); + protected int _retries; + protected int _interval; + protected int _connWait = 5; + protected static long s_sleepOnError = 10 * 1000; // in ms + static { + File file = PropertiesUtil.findConfigFile("environment.properties"); + if (file == null) { + s_logger.debug("Unable to find environment.properties"); + } else { + FileInputStream finputstream; + try { + finputstream = new FileInputStream(file); + final Properties props = new Properties(); + props.load(finputstream); + finputstream.close(); + String search = props.getProperty("sleep.interval.on.error"); + if (search != null) { + s_sleepOnError = NumbersUtil.parseInterval(search, 10) * 1000; + } + s_logger.info("XenServer Connection Pool Configs: sleep.interval.on.error=" + s_sleepOnError); + } catch (FileNotFoundException e) { + s_logger.debug("File is not found", e); + } catch (IOException e) { + s_logger.debug("IO Exception while reading file", e); + } + } + try { + javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; + javax.net.ssl.TrustManager tm = new TrustAllManager(); + trustAllCerts[0] = tm; + javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("TLS"); + sc.init(null, trustAllCerts, null); + javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HostnameVerifier hv = new HostnameVerifier() { + @Override + public boolean verify(String hostName, SSLSession session) { + return true; + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(hv); + } catch (Exception e) { + } + } + + protected XenServerConnectionPool() { + _retries = 1; + _interval = 3; + } + + private void addConnect(String poolUuid, XenServerConnection conn) { + if (poolUuid == null) + return; + if (s_logger.isDebugEnabled()) { + s_logger.debug("Add master connection through " + conn.getIp() + " for pool(" + conn.getPoolUuid() + ")"); + } + synchronized (_conns) { + _conns.put(poolUuid, conn); + } + } + + private XenServerConnection getConnect(String poolUuid) { + if (poolUuid == null) + return null; + synchronized (_conns) { + return _conns.get(poolUuid); + } + } + + private void removeConnect(String poolUuid) { + if (poolUuid == null) { + return; + } + XenServerConnection conn = null; + synchronized (_conns) { + conn = _conns.remove(poolUuid); + } + if (conn != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Remove master connection through " + conn.getIp() + " for pool(" + conn.getPoolUuid() + ")"); + } + + } + } + + static void forceSleep(long sec) { + long firetime = System.currentTimeMillis() + (sec * 1000); + long msec = sec * 1000; + while (true) { + if (msec < 100) + break; + try { + Thread.sleep(msec); + return; + } catch (InterruptedException e) { + msec = firetime - System.currentTimeMillis(); + } + } + } + + public Connection getConnect(String ip, String username, Queue password) { + Connection conn = new Connection(getURL(ip), 10, _connWait); + try { + loginWithPassword(conn, username, password, APIVersion.latest().toString()); + } catch (Types.HostIsSlave e) { + String maddress = e.masterIPAddress; + conn = new Connection(getURL(maddress), 10, _connWait); + try { + loginWithPassword(conn, username, password, APIVersion.latest().toString()); + } catch (Exception e1) { + String msg = "Unable to create master connection to host(" + maddress +") , due to " + e1.toString(); + s_logger.debug(msg); + throw new CloudRuntimeException(msg, e1); + } + } catch (Exception e) { + String msg = "Unable to create master connection to host(" + ip +") , due to " + e.toString(); + s_logger.debug(msg); + throw new CloudRuntimeException(msg, e); + } + return conn; + } + + public URL getURL(String ip) { + try { + return new URL("https://" + ip); + } catch (Exception e) { + String msg = "Unable to convert IP " + ip + " to URL due to " + e.toString(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(msg); + } + throw new CloudRuntimeException(msg, e); + } + } + + public Connection connect(String hostUuid, String poolUuid, String ipAddress, + String username, Queue password, int wait) { + XenServerConnection mConn = null; + if (hostUuid == null || poolUuid == null || ipAddress == null || username == null || password == null) { + String msg = "Connect some parameter are null hostUuid:" + hostUuid + " ,poolUuid:" + poolUuid + + " ,ipAddress:" + ipAddress; + s_logger.debug(msg); + throw new CloudRuntimeException(msg); + } + synchronized (poolUuid.intern()) { + mConn = getConnect(poolUuid); + if (mConn != null){ + try{ + Host host = Host.getByUuid(mConn, hostUuid); + if (!host.getEnabled(mConn)) { + String msg = "Cannot connect this host " + ipAddress + " due to the host is not enabled"; + s_logger.debug(msg); + if (mConn.getIp().equalsIgnoreCase(ipAddress)) { + removeConnect(poolUuid); + mConn = null; + } + throw new CloudRuntimeException(msg); + } + return mConn; + } catch (CloudRuntimeException e) { + throw e; + } catch (Exception e) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("connect through IP(" + mConn.getIp() + " for pool(" + poolUuid + ") is broken due to " + e.toString()); + } + removeConnect(poolUuid); + mConn = null; + } + } + + if ( mConn == null ) { + try { + Connection conn = new Connection(getURL(ipAddress), 5, _connWait); + Session sess = loginWithPassword(conn, username, password, APIVersion.latest().toString()); + Host host = sess.getThisHost(conn); + Boolean hostenabled = host.getEnabled(conn); + if( sess != null ){ + try{ + Session.logout(conn); + } catch (Exception e) { + } + conn.dispose(); + } + if (!hostenabled) { + String msg = "Unable to create master connection, due to master Host " + ipAddress + " is not enabled"; + s_logger.debug(msg); + throw new CloudRuntimeException(msg); + } + mConn = new XenServerConnection(getURL(ipAddress), ipAddress, username, password, _retries, _interval, wait, _connWait); + loginWithPassword(mConn, username, password, APIVersion.latest().toString()); + } catch (Types.HostIsSlave e) { + String maddress = e.masterIPAddress; + mConn = new XenServerConnection(getURL(maddress), maddress, username, password, _retries, _interval, wait, _connWait); + try { + Session session = loginWithPassword(mConn, username, password, APIVersion.latest().toString()); + Host host = session.getThisHost(mConn); + if (!host.getEnabled(mConn)) { + String msg = "Unable to create master connection, due to master Host " + maddress + " is not enabled"; + s_logger.debug(msg); + throw new CloudRuntimeException(msg); + } + } catch (Exception e1) { + String msg = "Unable to create master connection to host(" + maddress +") , due to " + e1.toString(); + s_logger.debug(msg); + throw new CloudRuntimeException(msg, e1); + + } + } catch (CloudRuntimeException e) { + throw e; + } catch (Exception e) { + String msg = "Unable to create master connection to host(" + ipAddress +") , due to " + e.toString(); + s_logger.debug(msg); + throw new CloudRuntimeException(msg, e); + } + addConnect(poolUuid, mConn); + } + } + return mConn; + } + + + + protected Session slaveLocalLoginWithPassword(Connection conn, String username, Queue password) throws BadServerResponse, XenAPIException, XmlRpcException { + Session s = null; + boolean logged_in = false; + Exception ex = null; + while (!logged_in) { + try { + s = Session.slaveLocalLoginWithPassword(conn, username, password.peek()); + logged_in = true; + } catch (BadServerResponse e) { + logged_in = false; + ex = e; + } catch (XenAPIException e) { + logged_in = false; + ex = e; + } catch (XmlRpcException e) { + logged_in = false; + ex = e; + } + if (logged_in && conn != null) { + break; + } else { + if (password.size() > 1) { + password.remove(); + continue; + } else { + // the last password did not work leave it and flag error + if (ex instanceof BadServerResponse) { + throw (BadServerResponse)ex; + } else if (ex instanceof XmlRpcException) { + throw (XmlRpcException)ex; + } else if (ex instanceof Types.SessionAuthenticationFailed) { + throw (Types.SessionAuthenticationFailed)ex; + } else if (ex instanceof XenAPIException) { + throw (XenAPIException)ex; + } + break; + } + } + } + return s; + } + + protected Session loginWithPassword(Connection conn, String username, Queue password, String version) throws BadServerResponse, XenAPIException, + XmlRpcException { + Session s = null; + boolean logged_in = false; + Exception ex = null; + while (!logged_in) { + try { + s = Session.loginWithPassword(conn, username, password.peek(), APIVersion.latest().toString()); + logged_in = true; + } catch (BadServerResponse e) { + logged_in = false; + ex = e; + } catch (XenAPIException e) { + logged_in = false; + ex = e; + } catch (XmlRpcException e) { + logged_in = false; + ex = e; + } + + if (logged_in && conn != null) { + break; + } else { + if (password.size() > 1) { + password.remove(); + continue; + } else { + // the last password did not work leave it and flag error + if (ex instanceof BadServerResponse) { + throw (BadServerResponse)ex; + } else if (ex instanceof XmlRpcException) { + throw (XmlRpcException)ex; + } else if (ex instanceof Types.SessionAuthenticationFailed) { + throw (Types.SessionAuthenticationFailed)ex; + } else if (ex instanceof XenAPIException) { + throw (XenAPIException)ex; + } + } + } + } + return s; + } + + protected void join(Connection conn, String masterIp, String username, Queue password) throws BadServerResponse, XenAPIException, XmlRpcException, + Types.JoiningHostCannotContainSharedSrs { + + boolean logged_in = false; + Exception ex = null; + while (!logged_in) { + try { + Pool.join(conn, masterIp, username, password.peek()); + logged_in = true; + } catch (BadServerResponse e) { + logged_in = false; + ex = e; + } catch (XenAPIException e) { + logged_in = false; + ex = e; + } catch (XmlRpcException e) { + logged_in = false; + ex = e; + } + if (logged_in && conn != null) { + break; + } else { + if (password.size() > 1) { + password.remove(); + continue; + } else { + // the last password did not work leave it and flag error + if (ex instanceof BadServerResponse) { + throw (BadServerResponse)ex; + } else if (ex instanceof XmlRpcException) { + throw (XmlRpcException)ex; + } else if (ex instanceof Types.SessionAuthenticationFailed) { + throw (Types.SessionAuthenticationFailed)ex; + } else if (ex instanceof XenAPIException) { + throw (XenAPIException)ex; + } + break; + } + } + } + } + + static public Pool.Record getPoolRecord(Connection conn) throws XmlRpcException, XenAPIException { + Map pools = Pool.getAllRecords(conn); + assert pools.size() == 1 : "Pool size is not one....hmmm....wth? " + pools.size(); + + return pools.values().iterator().next(); + } + + private static final XenServerConnectionPool s_instance = new XenServerConnectionPool(); + + public static XenServerConnectionPool getInstance() { + return s_instance; + } + + public class XenServerConnection extends Connection { + long _interval; + int _retries; + String _ip; + String _username; + Queue _password; + String _poolUuid; + + public XenServerConnection(URL url, String ip, String username, Queue password, int retries, int interval, int wait, int connwait) { + super(url, wait, connwait); + _ip = ip; + _retries = retries; + _username = username; + _password = password; + _interval = (long)interval * 1000; + + } + + public String getPoolUuid() { + return _poolUuid; + } + + public String getUsername() { + return _username; + } + + public Queue getPassword() { + return _password; + } + + public String getIp() { + return _ip; + } + + @Override + protected Map dispatch(String methodcall, Object[] methodparams) throws XmlRpcException, XenAPIException { + if (methodcall.equals("session.local_logout") + || methodcall.equals("session.slave_local_login_with_password") + || methodcall.equals("session.logout") + || methodcall.equals("session.login_with_password")) { + return super.dispatch(methodcall, methodparams); + } + + try { + return super.dispatch(methodcall, methodparams); + } catch (Types.SessionInvalid e) { + s_logger.debug("Session is invalid for method: " + methodcall + " due to " + e.toString()); + removeConnect(_poolUuid); + throw e; + } catch (XmlRpcClientException e) { + s_logger.debug("XmlRpcClientException for method: " + methodcall + " due to " + e.toString()); + removeConnect(_poolUuid); + throw e; + } catch (XmlRpcException e) { + s_logger.debug("XmlRpcException for method: " + methodcall + " due to " + e.toString()); + removeConnect(_poolUuid); + throw e; + } catch (Types.HostIsSlave e) { + s_logger.debug("HostIsSlave Exception for method: " + methodcall + " due to " + e.toString()); + removeConnect(_poolUuid); + throw e; + } + } + } + + public static class TrustAllManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + + public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) { + return true; + } + + public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) { + return true; + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { + return; + } + + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { + return; + } + } + +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerPoolVms.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerPoolVms.java new file mode 100644 index 00000000000..804220904bc --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerPoolVms.java @@ -0,0 +1,90 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package com.cloud.hypervisor.xenserver.resource; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.log4j.Logger; + +import com.cloud.utils.Pair; +import com.cloud.vm.VirtualMachine.State; + +public class XenServerPoolVms { + private static final Logger s_logger = Logger.getLogger(XenServerPoolVms.class); + private final Map>> _clusterVms = + new ConcurrentHashMap>>(); + + public HashMap> getClusterVmState(String clusterId) { + HashMap> _vms = _clusterVms.get(clusterId); + if (_vms == null) { + HashMap> vmStates = new HashMap>(); + _clusterVms.put(clusterId, vmStates); + return vmStates; + } else + return _vms; + } + + public void clear(String clusterId) { + HashMap> _vms = getClusterVmState(clusterId); + _vms.clear(); + } + + public State getState(String clusterId, String name) { + HashMap> vms = getClusterVmState(clusterId); + Pair pv = vms.get(name); + return pv == null ? State.Stopped : pv.second(); // if a VM is absent on the cluster, it is effectively in stopped state. + } + + public Pair get(String clusterId, String name) { + HashMap> vms = getClusterVmState(clusterId); + return vms.get(name); + } + + public void put(String clusterId, String hostUuid, String name, State state) { + HashMap> vms = getClusterVmState(clusterId); + vms.put(name, new Pair(hostUuid, state)); + } + + public void remove(String clusterId, String hostUuid, String name) { + HashMap> vms = getClusterVmState(clusterId); + vms.remove(name); + } + + public void putAll(String clusterId, HashMap> newVms) { + HashMap> vms = getClusterVmState(clusterId); + vms.putAll(newVms); + } + + public int size(String clusterId) { + HashMap> vms = getClusterVmState(clusterId); + return vms.size(); + } + + @Override + public String toString() { + StringBuilder sbuf = new StringBuilder("PoolVms="); + for (HashMap> clusterVM : _clusterVms.values()) { + for (String vmname : clusterVM.keySet()) { + sbuf.append(vmname).append("-").append(clusterVM.get(vmname).second()).append(","); + } + } + return sbuf.toString(); + } + +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java new file mode 100644 index 00000000000..89a323946a7 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java @@ -0,0 +1,1699 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with 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. + */ +package com.cloud.hypervisor.xenserver.resource; + +import static com.cloud.utils.ReflectUtil.flattenProperties; +import static com.google.common.collect.Lists.newArrayList; + +import java.io.File; +import java.net.URI; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.cloudstack.storage.command.AttachAnswer; +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer; +import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; +import org.apache.cloudstack.storage.command.CreateObjectCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DettachAnswer; +import org.apache.cloudstack.storage.command.DettachCommand; +import org.apache.cloudstack.storage.command.ForgetObjectCmd; +import org.apache.cloudstack.storage.command.IntroduceObjectAnswer; +import org.apache.cloudstack.storage.command.IntroduceObjectCmd; +import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol; +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.S3TO; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.SwiftTO; +import com.cloud.exception.InternalErrorException; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase.SRType; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.resource.StorageProcessor; +import com.cloud.utils.S3Utils; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.storage.encoding.DecodedDataObject; +import com.cloud.utils.storage.encoding.DecodedDataStore; +import com.cloud.utils.storage.encoding.Decoder; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.PBD; +import com.xensource.xenapi.Pool; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.BadServerResponse; +import com.xensource.xenapi.Types.VmPowerState; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VM; +import com.xensource.xenapi.VMGuestMetrics; + +public class XenServerStorageProcessor implements StorageProcessor { + private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class); + protected CitrixResourceBase hypervisorResource; + protected String BaseMountPointOnHost = "/var/run/cloud_mount"; + + public XenServerStorageProcessor(CitrixResourceBase resource) { + hypervisorResource = resource; + } + + @Override + public AttachAnswer attachIso(AttachCommand cmd) { + DiskTO disk = cmd.getDisk(); + DataTO data = disk.getData(); + DataStoreTO store = data.getDataStore(); + + String isoURL = null; + if (store == null) { + TemplateObjectTO iso = (TemplateObjectTO) disk.getData(); + isoURL = iso.getName(); + } else { + if (!(store instanceof NfsTO)) { + s_logger.debug("Can't attach a iso which is not created on nfs: "); + return new AttachAnswer("Can't attach a iso which is not created on nfs: "); + } + NfsTO nfsStore = (NfsTO) store; + isoURL = nfsStore.getUrl() + File.separator + data.getPath(); + } + + String vmName = cmd.getVmName(); + try { + Connection conn = hypervisorResource.getConnection(); + + VBD isoVBD = null; + + // Find the VM + VM vm = hypervisorResource.getVM(conn, vmName); + // Find the ISO VDI + VDI isoVDI = hypervisorResource.getIsoVDIByURL(conn, vmName, isoURL); + + // Find the VM's CD-ROM VBD + Set vbds = vm.getVBDs(conn); + for (VBD vbd : vbds) { + String userDevice = vbd.getUserdevice(conn); + Types.VbdType type = vbd.getType(conn); + + if (userDevice.equals("3") && type == Types.VbdType.CD) { + isoVBD = vbd; + break; + } + } + + if (isoVBD == null) { + throw new CloudRuntimeException("Unable to find CD-ROM VBD for VM: " + vmName); + } else { + // If an ISO is already inserted, eject it + if (!isoVBD.getEmpty(conn)) { + isoVBD.eject(conn); + } + + // Insert the new ISO + isoVBD.insert(conn, isoVDI); + } + + return new AttachAnswer(disk); + + } catch (XenAPIException e) { + s_logger.warn("Failed to attach iso" + ": " + e.toString(), e); + return new AttachAnswer(e.toString()); + } catch (Exception e) { + s_logger.warn("Failed to attach iso" + ": " + e.toString(), e); + return new AttachAnswer(e.toString()); + } + } + + @Override + public AttachAnswer attachVolume(AttachCommand cmd) { + DiskTO disk = cmd.getDisk(); + DataTO data = disk.getData(); + + try { + String vmName = cmd.getVmName(); + String vdiNameLabel = vmName + "-DATA"; + + Connection conn = this.hypervisorResource.getConnection(); + VM vm = null; + + boolean vmNotRunning = true; + + try { + vm = this.hypervisorResource.getVM(conn, vmName); + + VM.Record vmr = vm.getRecord(conn); + + vmNotRunning = vmr.powerState != VmPowerState.RUNNING; + } catch (CloudRuntimeException ex) { + } + + Map details = disk.getDetails(); + boolean isManaged = Boolean.parseBoolean(details.get(DiskTO.MANAGED)); + + // if the VM is not running and we're not dealing with managed storage, just return success (nothing to do here) + // this should probably never actually happen + if (vmNotRunning && !isManaged) { + return new AttachAnswer(disk); + } + + VDI vdi = null; + + if (isManaged) { + vdi = hypervisorResource.prepareManagedStorage(conn, details, data.getPath(), vdiNameLabel); + + if (vmNotRunning) { + DiskTO newDisk = new DiskTO(disk.getData(), disk.getDiskSeq(), vdi.getUuid(conn), disk.getType()); + + return new AttachAnswer(newDisk); + } + } else { + vdi = hypervisorResource.mount(conn, null, null, data.getPath()); + } + + /* For HVM guest, if no pv driver installed, no attach/detach */ + boolean isHVM = vm.getPVBootloader(conn).equalsIgnoreCase(""); + + VMGuestMetrics vgm = vm.getGuestMetrics(conn); + boolean pvDrvInstalled = false; + + if (!this.hypervisorResource.isRefNull(vgm) && vgm.getPVDriversUpToDate(conn)) { + pvDrvInstalled = true; + } + + if (isHVM && !pvDrvInstalled) { + s_logger.warn(": You attempted an operation on a VM which requires PV drivers to be installed but the drivers were not detected"); + + return new AttachAnswer("You attempted an operation that requires PV drivers to be installed on the VM. Please install them by inserting xen-pv-drv.iso."); + } + + // Figure out the disk number to attach the VM to + String diskNumber = null; + Long deviceId = disk.getDiskSeq(); + + if (deviceId != null) { + if (deviceId.longValue() == 3) { + String msg = "Device 3 is reserved for CD-ROM, choose other device"; + + return new AttachAnswer(msg); + } + + if (hypervisorResource.isDeviceUsed(conn, vm, deviceId)) { + String msg = "Device " + deviceId + " is used in VM " + vmName; + + return new AttachAnswer(msg); + } + + diskNumber = deviceId.toString(); + } else { + diskNumber = hypervisorResource.getUnusedDeviceNum(conn, vm); + } + + VBD.Record vbdr = new VBD.Record(); + + vbdr.VM = vm; + vbdr.VDI = vdi; + vbdr.bootable = false; + vbdr.userdevice = diskNumber; + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + vbdr.unpluggable = true; + + VBD vbd = VBD.create(conn, vbdr); + + // Attach the VBD to the VM + vbd.plug(conn); + + // Update the VDI's label to include the VM name + vdi.setNameLabel(conn, vdiNameLabel); + + DiskTO newDisk = new DiskTO(disk.getData(), Long.parseLong(diskNumber), vdi.getUuid(conn), disk.getType()); + + return new AttachAnswer(newDisk); + } catch (XenAPIException e) { + String msg = "Failed to attach volume" + " for uuid: " + data.getPath() + " due to " + e.toString(); + s_logger.warn(msg, e); + return new AttachAnswer(msg); + } catch (Exception e) { + String msg = "Failed to attach volume" + " for uuid: " + data.getPath() + " due to " + e.getMessage(); + s_logger.warn(msg, e); + return new AttachAnswer(msg); + } + } + + @Override + public Answer dettachIso(DettachCommand cmd) { + DiskTO disk = cmd.getDisk(); + DataTO data = disk.getData(); + DataStoreTO store = data.getDataStore(); + + String isoURL = null; + if (store == null) { + TemplateObjectTO iso = (TemplateObjectTO) disk.getData(); + isoURL = iso.getName(); + } else { + if (!(store instanceof NfsTO)) { + s_logger.debug("Can't attach a iso which is not created on nfs: "); + return new AttachAnswer("Can't attach a iso which is not created on nfs: "); + } + NfsTO nfsStore = (NfsTO) store; + isoURL = nfsStore.getUrl() + File.separator + data.getPath(); + } + + try { + Connection conn = hypervisorResource.getConnection(); + // Find the VM + VM vm = hypervisorResource.getVM(conn, cmd.getVmName()); + String vmUUID = vm.getUuid(conn); + + // Find the ISO VDI + VDI isoVDI = hypervisorResource.getIsoVDIByURL(conn, cmd.getVmName(), isoURL); + + SR sr = isoVDI.getSR(conn); + + // Look up all VBDs for this VDI + Set vbds = isoVDI.getVBDs(conn); + + // Iterate through VBDs, and if the VBD belongs the VM, eject + // the ISO from it + for (VBD vbd : vbds) { + VM vbdVM = vbd.getVM(conn); + String vbdVmUUID = vbdVM.getUuid(conn); + + if (vbdVmUUID.equals(vmUUID)) { + // If an ISO is already inserted, eject it + if (!vbd.getEmpty(conn)) { + vbd.eject(conn); + } + break; + } + } + + if (!sr.getNameLabel(conn).startsWith("XenServer Tools")) { + hypervisorResource.removeSR(conn, sr); + } + + return new DettachAnswer(disk); + } catch (XenAPIException e) { + String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.toString(); + s_logger.warn(msg, e); + return new DettachAnswer(msg); + } catch (Exception e) { + String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.getMessage(); + s_logger.warn(msg, e); + return new DettachAnswer(msg); + } + } + + @Override + public Answer dettachVolume(DettachCommand cmd) { + DiskTO disk = cmd.getDisk(); + DataTO data = disk.getData(); + + try { + Connection conn = this.hypervisorResource.getConnection(); + + String vmName = cmd.getVmName(); + VM vm = null; + + boolean vmNotRunning = true; + + try { + vm = this.hypervisorResource.getVM(conn, vmName); + + VM.Record vmr = vm.getRecord(conn); + + vmNotRunning = vmr.powerState != VmPowerState.RUNNING; + } catch (CloudRuntimeException ex) { + } + + // if the VM is not running and we're not dealing with managed storage, just return success (nothing to do here) + // this should probably never actually happen + if (vmNotRunning && !cmd.isManaged()) { + return new DettachAnswer(disk); + } + + if (!vmNotRunning) { + /* For HVM guest, if no pv driver installed, no attach/detach */ + boolean isHVM = vm.getPVBootloader(conn).equalsIgnoreCase(""); + + VMGuestMetrics vgm = vm.getGuestMetrics(conn); + boolean pvDrvInstalled = false; + + if (!this.hypervisorResource.isRefNull(vgm) && vgm.getPVDriversUpToDate(conn)) { + pvDrvInstalled = true; + } + + if (isHVM && !pvDrvInstalled) { + s_logger.warn(": You attempted an operation on a VM which requires PV drivers to be installed but the drivers were not detected"); + return new DettachAnswer("You attempted an operation that requires PV drivers to be installed on the VM. Please install them by inserting xen-pv-drv.iso."); + } + + VDI vdi = this.hypervisorResource.mount(conn, null, null, data.getPath()); + + // Look up all VBDs for this VDI + Set vbds = vdi.getVBDs(conn); + + // Detach each VBD from its VM, and then destroy it + for (VBD vbd : vbds) { + VBD.Record vbdr = vbd.getRecord(conn); + + if (vbdr.currentlyAttached) { + vbd.unplug(conn); + } + + vbd.destroy(conn); + } + + // Update the VDI's label to be "detached" + vdi.setNameLabel(conn, "detached"); + + this.hypervisorResource.umount(conn, vdi); + } + + if (cmd.isManaged()) { + hypervisorResource.handleSrAndVdiDetach(cmd.get_iScsiName(), conn); + } + + return new DettachAnswer(disk); + } catch (Exception e) { + s_logger.warn("Failed dettach volume: " + data.getPath()); + return new DettachAnswer("Failed dettach volume: " + data.getPath() + ", due to " + e.toString()); + } + } + + protected SR getSRByNameLabel(Connection conn, String nameLabel) throws BadServerResponse, XenAPIException, XmlRpcException { + Set srs = SR.getByNameLabel(conn, nameLabel); + if (srs.size() != 1) { + throw new CloudRuntimeException("storage uuid: " + nameLabel + " is not unique"); + } + SR poolsr = srs.iterator().next(); + return poolsr; + } + + protected VDI createVdi(Connection conn, String vdiName, SR sr, long size) throws BadServerResponse, XenAPIException, XmlRpcException { + VDI.Record vdir = new VDI.Record(); + vdir.nameLabel = vdiName; + vdir.SR = sr; + vdir.type = Types.VdiType.USER; + + vdir.virtualSize = size; + VDI vdi = VDI.create(conn, vdir); + return vdi; + } + + protected void deleteVDI(Connection conn, VDI vdi) throws BadServerResponse, XenAPIException, XmlRpcException { + vdi.destroy(conn); + } + + @Override + public Answer createSnapshot(CreateObjectCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + SnapshotObjectTO snapshotTO = (SnapshotObjectTO) cmd.getData(); + long snapshotId = snapshotTO.getId(); + String snapshotName = snapshotTO.getName(); + String details = "create snapshot operation Failed for snapshotId: " + snapshotId; + String snapshotUUID = null; + + try { + String volumeUUID = snapshotTO.getVolume().getPath(); + VDI volume = VDI.getByUuid(conn, volumeUUID); + + VDI snapshot = volume.snapshot(conn, new HashMap()); + + if (snapshotName != null) { + snapshot.setNameLabel(conn, snapshotName); + } + + snapshotUUID = snapshot.getUuid(conn); + String preSnapshotUUID = snapshotTO.getParentSnapshotPath(); + //check if it is a empty snapshot + if (preSnapshotUUID != null) { + SR sr = volume.getSR(conn); + String srUUID = sr.getUuid(conn); + String type = sr.getType(conn); + Boolean isISCSI = IsISCSI(type); + String snapshotParentUUID = getVhdParent(conn, srUUID, snapshotUUID, isISCSI); + + try { + String preSnapshotParentUUID = getVhdParent(conn, srUUID, preSnapshotUUID, isISCSI); + if (snapshotParentUUID != null && snapshotParentUUID.equals(preSnapshotParentUUID)) { + // this is empty snapshot, remove it + snapshot.destroy(conn); + snapshotUUID = preSnapshotUUID; + } + } catch (Exception e) { + s_logger.debug("Failed to get parent snapshot", e); + } + } + SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + newSnapshot.setPath(snapshotUUID); + return new CreateObjectAnswer(newSnapshot); + } catch (XenAPIException e) { + details += ", reason: " + e.toString(); + s_logger.warn(details, e); + } catch (Exception e) { + details += ", reason: " + e.toString(); + s_logger.warn(details, e); + } + + return new CreateObjectAnswer(details); + } + + @Override + public Answer deleteVolume(DeleteCommand cmd) { + DataTO volume = cmd.getData(); + Connection conn = hypervisorResource.getConnection(); + String errorMsg = null; + try { + VDI vdi = VDI.getByUuid(conn, volume.getPath()); + deleteVDI(conn, vdi); + return new Answer(null); + } catch (BadServerResponse e) { + s_logger.debug("Failed to delete volume", e); + errorMsg = e.toString(); + } catch (XenAPIException e) { + s_logger.debug("Failed to delete volume", e); + errorMsg = e.toString(); + } catch (XmlRpcException e) { + s_logger.debug("Failed to delete volume", e); + errorMsg = e.toString(); + } + return new Answer(null, false, errorMsg); + } + + protected SR getNfsSR(Connection conn, StorageFilerTO pool) { + Map deviceConfig = new HashMap(); + try { + String server = pool.getHost(); + String serverpath = pool.getPath(); + serverpath = serverpath.replace("//", "/"); + Set srs = SR.getAll(conn); + for (SR sr : srs) { + if (!SRType.NFS.equals(sr.getType(conn))) { + continue; + } + + Set pbds = sr.getPBDs(conn); + if (pbds.isEmpty()) { + continue; + } + + PBD pbd = pbds.iterator().next(); + + Map dc = pbd.getDeviceConfig(conn); + + if (dc == null) { + continue; + } + + if (dc.get("server") == null) { + continue; + } + + if (dc.get("serverpath") == null) { + continue; + } + + if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) { + throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" + dc.get("serverpath") + + " for pool " + pool.getUuid() + "on host:" + hypervisorResource.getHost().uuid); + } + + } + deviceConfig.put("server", server); + deviceConfig.put("serverpath", serverpath); + Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid); + Map smConfig = new HashMap(); + smConfig.put("nosubdir", "true"); + SR sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), Long.toString(pool.getId()), SRType.NFS.toString(), "user", true, smConfig); + sr.scan(conn); + return sr; + } catch (XenAPIException e) { + throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e); + } catch (XmlRpcException e) { + throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e); + } + } + + protected SR getIscsiSR(Connection conn, StorageFilerTO pool) { + synchronized (pool.getUuid().intern()) { + Map deviceConfig = new HashMap(); + try { + String target = pool.getHost(); + String path = pool.getPath(); + if (path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + + String tmp[] = path.split("/"); + if (tmp.length != 3) { + String msg = "Wrong iscsi path " + pool.getPath() + " it should be /targetIQN/LUN"; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + String targetiqn = tmp[1].trim(); + String lunid = tmp[2].trim(); + String scsiid = ""; + + Set srs = SR.getByNameLabel(conn, pool.getUuid()); + for (SR sr : srs) { + if (!SRType.LVMOISCSI.equals(sr.getType(conn))) { + continue; + } + Set pbds = sr.getPBDs(conn); + if (pbds.isEmpty()) { + continue; + } + PBD pbd = pbds.iterator().next(); + Map dc = pbd.getDeviceConfig(conn); + if (dc == null) { + continue; + } + if (dc.get("target") == null) { + continue; + } + if (dc.get("targetIQN") == null) { + continue; + } + if (dc.get("lunid") == null) { + continue; + } + if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) { + throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:" + dc.get("targetIQN") + + ", lunid:" + dc.get("lunid") + " for pool " + pool.getUuid() + "on host:" + hypervisorResource.getHost().uuid); + } + } + deviceConfig.put("target", target); + deviceConfig.put("targetIQN", targetiqn); + + Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid); + Map smConfig = new HashMap(); + String type = SRType.LVMOISCSI.toString(); + String poolId = Long.toString(pool.getId()); + SR sr = null; + try { + sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true, smConfig); + } catch (XenAPIException e) { + String errmsg = e.toString(); + if (errmsg.contains("SR_BACKEND_FAILURE_107")) { + String lun[] = errmsg.split(""); + boolean found = false; + for (int i = 1; i < lun.length; i++) { + int blunindex = lun[i].indexOf("") + 7; + int elunindex = lun[i].indexOf(""); + String ilun = lun[i].substring(blunindex, elunindex); + ilun = ilun.trim(); + if (ilun.equals(lunid)) { + int bscsiindex = lun[i].indexOf("") + 8; + int escsiindex = lun[i].indexOf(""); + scsiid = lun[i].substring(bscsiindex, escsiindex); + scsiid = scsiid.trim(); + found = true; + break; + } + } + if (!found) { + String msg = "can not find LUN " + lunid + " in " + errmsg; + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + } else { + String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + deviceConfig.put("SCSIid", scsiid); + + String result = SR.probe(conn, host, deviceConfig, type, smConfig); + String pooluuid = null; + if (result.indexOf("") != -1) { + pooluuid = result.substring(result.indexOf("") + 6, result.indexOf("")).trim(); + } + if (pooluuid == null || pooluuid.length() != 36) { + sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true, smConfig); + } else { + sr = SR.introduce(conn, pooluuid, pool.getUuid(), poolId, type, "user", true, smConfig); + Pool.Record pRec = XenServerConnectionPool.getPoolRecord(conn); + PBD.Record rec = new PBD.Record(); + rec.deviceConfig = deviceConfig; + rec.host = pRec.master; + rec.SR = sr; + PBD pbd = PBD.create(conn, rec); + pbd.plug(conn); + } + sr.scan(conn); + return sr; + } catch (XenAPIException e) { + String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } catch (Exception e) { + String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.getMessage(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + } + + protected Answer execute(CreateStoragePoolCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + StorageFilerTO pool = cmd.getPool(); + try { + if (pool.getType() == StoragePoolType.NetworkFilesystem) { + getNfsSR(conn, pool); + } else if (pool.getType() == StoragePoolType.IscsiLUN) { + getIscsiSR(conn, pool); + } else if (pool.getType() == StoragePoolType.PreSetup) { + } else { + return new Answer(cmd, false, "The pool type: " + pool.getType().name() + " is not supported."); + } + return new Answer(cmd, true, "success"); + } catch (Exception e) { + String msg = + "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + + hypervisorResource.getHost().uuid + " pool: " + pool.getHost() + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + + } + + protected Answer directDownloadHttpTemplate(CopyCommand cmd, DecodedDataObject srcObj, DecodedDataObject destObj) { + Connection conn = hypervisorResource.getConnection(); + SR poolsr = null; + VDI vdi = null; + boolean result = false; + try { + if (destObj.getPath() == null) { + //need to create volume at first + + } + vdi = VDI.getByUuid(conn, destObj.getPath()); + if (vdi == null) { + throw new CloudRuntimeException("can't find volume: " + destObj.getPath()); + } + String destStoreUuid = destObj.getStore().getUuid(); + Set srs = SR.getByNameLabel(conn, destStoreUuid); + if (srs.size() != 1) { + throw new CloudRuntimeException("storage uuid: " + destStoreUuid + " is not unique"); + } + poolsr = srs.iterator().next(); + VDI.Record vdir = vdi.getRecord(conn); + String vdiLocation = vdir.location; + String pbdLocation = null; + if (destObj.getStore().getScheme().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) { + pbdLocation = "/run/sr-mount/" + poolsr.getUuid(conn); + } else { + Set pbds = poolsr.getPBDs(conn); + if (pbds.size() != 1) { + throw new CloudRuntimeException("Don't how to handle multiple pbds:" + pbds.size() + " for sr: " + poolsr.getUuid(conn)); + } + PBD pbd = pbds.iterator().next(); + Map deviceCfg = pbd.getDeviceConfig(conn); + pbdLocation = deviceCfg.get("location"); + } + if (pbdLocation == null) { + throw new CloudRuntimeException("Can't get pbd location"); + } + + String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd"; + //download a url into vdipath + //downloadHttpToLocalFile(vdiPath, template.getPath()); + hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", srcObj.getPath()); + result = true; + //return new CopyCmdAnswer(cmd, vdi.getUuid(conn)); + } catch (BadServerResponse e) { + s_logger.debug("Failed to download template", e); + } catch (XenAPIException e) { + s_logger.debug("Failed to download template", e); + } catch (XmlRpcException e) { + s_logger.debug("Failed to download template", e); + } catch (Exception e) { + s_logger.debug("Failed to download template", e); + } finally { + if (!result && vdi != null) { + try { + vdi.destroy(conn); + } catch (BadServerResponse e) { + s_logger.debug("Failed to cleanup newly created vdi"); + } catch (XenAPIException e) { + s_logger.debug("Failed to cleanup newly created vdi"); + } catch (XmlRpcException e) { + s_logger.debug("Failed to cleanup newly created vdi"); + } + } + } + return new Answer(cmd, false, "Failed to download template"); + } + + protected Answer execute(AttachPrimaryDataStoreCmd cmd) { + String dataStoreUri = cmd.getDataStore(); + Connection conn = hypervisorResource.getConnection(); + try { + DecodedDataObject obj = Decoder.decode(dataStoreUri); + + DecodedDataStore store = obj.getStore(); + + SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid()); + hypervisorResource.setupHeartbeatSr(conn, sr, false); + long capacity = sr.getPhysicalSize(conn); + long available = capacity - sr.getPhysicalUtilisation(conn); + if (capacity == -1) { + String msg = "Pool capacity is -1! pool: "; + s_logger.warn(msg); + return new Answer(cmd, false, msg); + } + AttachPrimaryDataStoreAnswer answer = new AttachPrimaryDataStoreAnswer(cmd); + answer.setCapacity(capacity); + answer.setUuid(sr.getUuid(conn)); + answer.setAvailable(available); + return answer; + } catch (XenAPIException e) { + String msg = "AttachPrimaryDataStoreCmd add XenAPIException:" + e.toString(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } catch (Exception e) { + String msg = "AttachPrimaryDataStoreCmd failed:" + e.getMessage(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + } + + protected boolean IsISCSI(String type) { + return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type); + } + + private String copy_vhd_from_secondarystorage(Connection conn, String mountpoint, String sruuid, int wait) { + String nameLabel = "cloud-" + UUID.randomUUID().toString(); + String results = + hypervisorResource.callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage", wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", + nameLabel); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = "copy_vhd_from_secondarystorage return null"; + } else { + String[] tmp = results.split("#"); + String status = tmp[0]; + if (status.equals("0")) { + return tmp[1]; + } else { + errMsg = tmp[1]; + } + } + String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1); + if (hypervisorResource.killCopyProcess(conn, source)) { + destroyVDIbyNameLabel(conn, nameLabel); + } + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); + } + + private void destroyVDIbyNameLabel(Connection conn, String nameLabel) { + try { + Set vdis = VDI.getByNameLabel(conn, nameLabel); + if (vdis.size() != 1) { + s_logger.warn("destoryVDIbyNameLabel failed due to there are " + vdis.size() + " VDIs with name " + nameLabel); + return; + } + for (VDI vdi : vdis) { + try { + vdi.destroy(conn); + } catch (Exception e) { + } + } + } catch (Exception e) { + } + } + + protected VDI getVDIbyUuid(Connection conn, String uuid) { + try { + return VDI.getByUuid(conn, uuid); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString(); + s_logger.debug(msg); + throw new CloudRuntimeException(msg, e); + } + } + + protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) { + String parentUuid = + hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, + "isISCSI", isISCSI.toString()); + + if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) { + s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid); + // errString is already logged. + return null; + } + return parentUuid; + } + + @Override + public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) { + DataTO srcDataTo = cmd.getSrcTO(); + DataTO destDataTo = cmd.getDestTO(); + int wait = cmd.getWait(); + DataStoreTO srcDataStoreTo = srcDataTo.getDataStore(); + + try { + if ((srcDataStoreTo instanceof NfsTO) && (srcDataTo.getObjectType() == DataObjectType.TEMPLATE)) { + NfsTO srcImageStore = (NfsTO) srcDataStoreTo; + TemplateObjectTO srcTemplateObjectTo = (TemplateObjectTO) srcDataTo; + String storeUrl = srcImageStore.getUrl(); + URI uri = new URI(storeUrl); + String tmplPath = uri.getHost() + ":" + uri.getPath() + "/" + srcDataTo.getPath(); + DataStoreTO destDataStoreTo = destDataTo.getDataStore(); + + boolean managed = false; + String storageHost = null; + String managedStoragePoolName = null; + String managedStoragePoolRootVolumeName = null; + String managedStoragePoolRootVolumeSize = null; + String chapInitiatorUsername = null; + String chapInitiatorSecret = null; + + if (destDataStoreTo instanceof PrimaryDataStoreTO) { + PrimaryDataStoreTO destPrimaryDataStoreTo = (PrimaryDataStoreTO)destDataStoreTo; + + Map details = destPrimaryDataStoreTo.getDetails(); + + if (details != null) { + managed = Boolean.parseBoolean(details.get(PrimaryDataStoreTO.MANAGED)); + + if (managed) { + storageHost = details.get(PrimaryDataStoreTO.STORAGE_HOST); + managedStoragePoolName = details.get(PrimaryDataStoreTO.MANAGED_STORE_TARGET); + managedStoragePoolRootVolumeName = details.get(PrimaryDataStoreTO.MANAGED_STORE_TARGET_ROOT_VOLUME); + managedStoragePoolRootVolumeSize = details.get(PrimaryDataStoreTO.VOLUME_SIZE); + chapInitiatorUsername = details.get(PrimaryDataStoreTO.CHAP_INITIATOR_USERNAME); + chapInitiatorSecret = details.get(PrimaryDataStoreTO.CHAP_INITIATOR_SECRET); + } + } + } + + Connection conn = hypervisorResource.getConnection(); + + final SR sr; + + if (managed) { + Map details = new HashMap(); + + details.put(DiskTO.STORAGE_HOST, storageHost); + details.put(DiskTO.IQN, managedStoragePoolName); + details.put(DiskTO.VOLUME_SIZE, managedStoragePoolRootVolumeSize); + details.put(DiskTO.CHAP_INITIATOR_USERNAME, chapInitiatorUsername); + details.put(DiskTO.CHAP_INITIATOR_SECRET, chapInitiatorSecret); + + sr = hypervisorResource.prepareManagedSr(conn, details); + } else { + String srName = destDataStoreTo.getUuid(); + Set srs = SR.getByNameLabel(conn, srName); + + if (srs.size() != 1) { + String msg = "There are " + srs.size() + " SRs with same name: " + srName; + + s_logger.warn(msg); + + return new CopyCmdAnswer(msg); + } else { + sr = srs.iterator().next(); + } + } + + String srUuid = sr.getUuid(conn); + String tmplUuid = copy_vhd_from_secondarystorage(conn, tmplPath, srUuid, wait); + VDI tmplVdi = getVDIbyUuid(conn, tmplUuid); + + final String uuidToReturn; + + if (managed) { + uuidToReturn = tmplUuid; + + tmplVdi.setNameLabel(conn, managedStoragePoolRootVolumeName); + } else { + VDI snapshotVdi = tmplVdi.snapshot(conn, new HashMap()); + + uuidToReturn = snapshotVdi.getUuid(conn); + + snapshotVdi.setNameLabel(conn, "Template " + srcTemplateObjectTo.getName()); + + tmplVdi.destroy(conn); + } + + sr.scan(conn); + + try { + Thread.sleep(5000); + } catch (Exception e) { + } + + TemplateObjectTO newVol = new TemplateObjectTO(); + + newVol.setUuid(uuidToReturn); + newVol.setPath(uuidToReturn); + newVol.setFormat(ImageFormat.VHD); + + return new CopyCmdAnswer(newVol); + } + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString(); + + s_logger.warn(msg, e); + + return new CopyCmdAnswer(msg); + } + + return new CopyCmdAnswer("not implemented yet"); + } + + @Override + public Answer createVolume(CreateObjectCommand cmd) { + DataTO data = cmd.getData(); + VolumeObjectTO volume = (VolumeObjectTO) data; + + try { + Connection conn = hypervisorResource.getConnection(); + SR poolSr = hypervisorResource.getStorageRepository(conn, data.getDataStore().getUuid()); + VDI.Record vdir = new VDI.Record(); + vdir.nameLabel = volume.getName(); + vdir.SR = poolSr; + vdir.type = Types.VdiType.USER; + + vdir.virtualSize = volume.getSize(); + VDI vdi; + + vdi = VDI.create(conn, vdir); + vdir = vdi.getRecord(conn); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setName(vdir.nameLabel); + newVol.setSize(vdir.virtualSize); + newVol.setPath(vdir.uuid); + + return new CreateObjectAnswer(newVol); + } catch (Exception e) { + s_logger.debug("create volume failed: " + e.toString()); + return new CreateObjectAnswer(e.toString()); + } + } + + @Override + public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + VolumeObjectTO volume = (VolumeObjectTO) destData; + VDI vdi = null; + try { + VDI tmpltvdi = null; + + tmpltvdi = getVDIbyUuid(conn, srcData.getPath()); + vdi = tmpltvdi.createClone(conn, new HashMap()); + vdi.setNameLabel(conn, volume.getName()); + + VDI.Record vdir; + vdir = vdi.getRecord(conn); + s_logger.debug("Succesfully created VDI: Uuid = " + vdir.uuid); + + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setName(vdir.nameLabel); + newVol.setSize(vdir.virtualSize); + newVol.setPath(vdir.uuid); + + return new CopyCmdAnswer(newVol); + } catch (Exception e) { + s_logger.warn("Unable to create volume; Pool=" + destData + "; Disk: ", e); + return new CopyCmdAnswer(e.toString()); + } + } + + @Override + public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + int wait = cmd.getWait(); + VolumeObjectTO srcVolume = (VolumeObjectTO) srcData; + VolumeObjectTO destVolume = (VolumeObjectTO) destData; + DataStoreTO srcStore = srcVolume.getDataStore(); + + if (srcStore instanceof NfsTO) { + NfsTO nfsStore = (NfsTO) srcStore; + try { + SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, destVolume.getDataStore().getUuid()); + String srUuid = primaryStoragePool.getUuid(conn); + URI uri = new URI(nfsStore.getUrl()); + String volumePath = uri.getHost() + ":" + uri.getPath() + File.separator + srcVolume.getPath(); + String uuid = copy_vhd_from_secondarystorage(conn, volumePath, srUuid, wait); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(uuid); + newVol.setSize(srcVolume.getSize()); + + return new CopyCmdAnswer(newVol); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); + s_logger.warn(msg, e); + return new CopyCmdAnswer(e.toString()); + } + } + + s_logger.debug("unsupported protocol"); + return new CopyCmdAnswer("unsupported protocol"); + } + + @Override + public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + VolumeObjectTO srcVolume = (VolumeObjectTO) cmd.getSrcTO(); + VolumeObjectTO destVolume = (VolumeObjectTO) cmd.getDestTO(); + int wait = cmd.getWait(); + DataStoreTO destStore = destVolume.getDataStore(); + + if (destStore instanceof NfsTO) { + SR secondaryStorage = null; + try { + NfsTO nfsStore = (NfsTO) destStore; + URI uri = new URI(nfsStore.getUrl()); + // Create the volume folder + if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) { + throw new InternalErrorException("Failed to create the volume folder."); + } + + // Create a SR for the volume UUID folder + secondaryStorage = hypervisorResource.createNfsSRbyURI(conn, new URI(nfsStore.getUrl() + File.separator + destVolume.getPath()), false); + // Look up the volume on the source primary storage pool + VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath()); + // Copy the volume to secondary storage + VDI destVdi = hypervisorResource.cloudVDIcopy(conn, srcVdi, secondaryStorage, wait); + String destVolumeUUID = destVdi.getUuid(conn); + + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(destVolume.getPath() + File.separator + destVolumeUUID + ".vhd"); + newVol.setSize(srcVolume.getSize()); + return new CopyCmdAnswer(newVol); + } catch (Exception e) { + s_logger.debug("Failed to copy volume to secondary: " + e.toString()); + return new CopyCmdAnswer("Failed to copy volume to secondary: " + e.toString()); + } finally { + hypervisorResource.removeSR(conn, secondaryStorage); + } + } + return new CopyCmdAnswer("unsupported protocol"); + } + + boolean swiftUpload(Connection conn, SwiftTO swift, String container, String ldir, String lfilename, Boolean isISCSI, int wait) { + String result = null; + try { + result = + hypervisorResource.callHostPluginAsync(conn, "swiftxenserver", "swift", wait, "op", "upload", "url", swift.getUrl(), "account", swift.getAccount(), "username", + swift.getUserName(), "key", swift.getKey(), "container", container, "ldir", ldir, "lfilename", lfilename, "isISCSI", isISCSI.toString()); + if (result != null && result.equals("true")) { + return true; + } + } catch (Exception e) { + s_logger.warn("swift upload failed due to " + e.toString(), e); + } + return false; + } + + protected String deleteSnapshotBackup(Connection conn, String localMountPoint, String path, String secondaryStorageMountPath, String backupUUID) { + + // If anybody modifies the formatting below again, I'll skin them + String result = + hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "path", path, "secondaryStorageMountPath", + secondaryStorageMountPath, "localMountPoint", localMountPoint); + + return result; + } + + public String swiftBackupSnapshot(Connection conn, SwiftTO swift, String srUuid, String snapshotUuid, String container, Boolean isISCSI, int wait) { + String lfilename; + String ldir; + if (isISCSI) { + ldir = "/dev/VG_XenStorage-" + srUuid; + lfilename = "VHD-" + snapshotUuid; + } else { + ldir = "/var/run/sr-mount/" + srUuid; + lfilename = snapshotUuid + ".vhd"; + } + swiftUpload(conn, swift, container, ldir, lfilename, isISCSI, wait); + return lfilename; + } + + protected String backupSnapshotToS3(final Connection connection, final S3TO s3, final String srUuid, final String folder, final String snapshotUuid, + final Boolean iSCSIFlag, final int wait) { + + final String filename = iSCSIFlag ? "VHD-" + snapshotUuid : snapshotUuid + ".vhd"; + final String dir = (iSCSIFlag ? "/dev/VG_XenStorage-" : "/var/run/sr-mount/") + srUuid; + final String key = folder + "/" + filename; // String.format("/snapshots/%1$s", snapshotUuid); + + try { + + final List parameters = newArrayList(flattenProperties(s3, S3Utils.ClientOptions.class)); + // https workaround for Introspector bug that does not + // recognize Boolean accessor methods ... + + parameters.addAll(Arrays.asList("operation", "put", "filename", dir + "/" + filename, "iSCSIFlag", iSCSIFlag.toString(), "bucket", s3.getBucketName(), "key", + key, "https", s3.isHttps() != null ? s3.isHttps().toString() : "null", "maxSingleUploadSizeInBytes", String.valueOf(s3.getMaxSingleUploadSizeInBytes()))); + final String result = hypervisorResource.callHostPluginAsync(connection, "s3xenserver", "s3", wait, parameters.toArray(new String[parameters.size()])); + + if (result != null && result.equals("true")) { + return key; + } + return null; + + } catch (Exception e) { + s_logger.error(String.format("S3 upload failed of snapshot %1$s due to %2$s.", snapshotUuid, e.toString()), e); + } + + return null; + + } + + protected Long getSnapshotSize(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI, int wait) { + String physicalSize = hypervisorResource.callHostPluginAsync(conn, "vmopsSnapshot", "getSnapshotSize", wait, + "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString()); + if (physicalSize == null || physicalSize.isEmpty()) { + return (long) 0; + } else { + return Long.parseLong(physicalSize); + } + } + + protected String backupSnapshot(Connection conn, String primaryStorageSRUuid, String localMountPoint, String path, String secondaryStorageMountPath, + String snapshotUuid, String prevBackupUuid, Boolean isISCSI, int wait) { + String backupSnapshotUuid = null; + + if (prevBackupUuid == null) { + prevBackupUuid = ""; + } + + // Each argument is put in a separate line for readability. + // Using more lines does not harm the environment. + String backupUuid = UUID.randomUUID().toString(); + String results = + hypervisorResource.callHostPluginAsync(conn, "vmopsSnapshot", "backupSnapshot", wait, "primaryStorageSRUuid", primaryStorageSRUuid, "path", path, + "secondaryStorageMountPath", secondaryStorageMountPath, "snapshotUuid", snapshotUuid, "prevBackupUuid", prevBackupUuid, "backupUuid", backupUuid, + "isISCSI", isISCSI.toString(), "localMountPoint", localMountPoint); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = + "Could not copy backupUuid: " + backupSnapshotUuid + " from primary storage " + primaryStorageSRUuid + " to secondary storage " + + secondaryStorageMountPath + " due to null"; + } else { + + String[] tmp = results.split("#"); + String status = tmp[0]; + backupSnapshotUuid = tmp[1]; + // status == "1" if and only if backupSnapshotUuid != null + // So we don't rely on status value but return backupSnapshotUuid as an + // indicator of success. + if (status != null && status.equalsIgnoreCase("1") && backupSnapshotUuid != null) { + s_logger.debug("Successfully copied backupUuid: " + backupSnapshotUuid + " to secondary storage"); + return results; + } else { + errMsg = + "Could not copy backupUuid: " + backupSnapshotUuid + " from primary storage " + primaryStorageSRUuid + " to secondary storage " + + secondaryStorageMountPath + " due to " + tmp[1]; + } + } + String source = backupUuid + ".vhd"; + hypervisorResource.killCopyProcess(conn, source); + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); + } + + protected boolean destroySnapshotOnPrimaryStorageExceptThis(Connection conn, String volumeUuid, String avoidSnapshotUuid) { + try { + VDI volume = getVDIbyUuid(conn, volumeUuid); + if (volume == null) { + throw new InternalErrorException("Could not destroy snapshot on volume " + volumeUuid + " due to can not find it"); + } + Set snapshots = volume.getSnapshots(conn); + for (VDI snapshot : snapshots) { + try { + if (!snapshot.getUuid(conn).equals(avoidSnapshotUuid)) { + snapshot.destroy(conn); + } + } catch (Exception e) { + String msg = "Destroying snapshot: " + snapshot + " on primary storage failed due to " + e.toString(); + s_logger.warn(msg, e); + } + } + s_logger.debug("Successfully destroyed snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid); + return true; + } catch (XenAPIException e) { + String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid + " failed due to " + e.toString(); + s_logger.error(msg, e); + } catch (Exception e) { + String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot " + avoidSnapshotUuid + " failed due to " + e.toString(); + s_logger.warn(msg, e); + } + + return false; + } + + private boolean destroySnapshotOnPrimaryStorage(Connection conn, String lastSnapshotUuid) { + try { + VDI snapshot = getVDIbyUuid(conn, lastSnapshotUuid); + if (snapshot == null) { + // since this is just used to cleanup leftover bad snapshots, no need to throw exception + s_logger.warn("Could not destroy snapshot " + lastSnapshotUuid + " due to can not find it"); + return false; + } + snapshot.destroy(conn); + return true; + } catch (XenAPIException e) { + String msg = "Destroying snapshot: " + lastSnapshotUuid + " failed due to " + e.toString(); + s_logger.error(msg, e); + } catch (Exception e) { + String msg = "Destroying snapshot: " + lastSnapshotUuid + " failed due to " + e.toString(); + s_logger.warn(msg, e); + } + return false; + } + + @Override + public Answer backupSnapshot(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + DataTO cacheData = cmd.getCacheTO(); + DataTO destData = cmd.getDestTO(); + int wait = cmd.getWait(); + String primaryStorageNameLabel = srcData.getDataStore().getUuid(); + String secondaryStorageUrl = null; + NfsTO cacheStore = null; + String destPath = null; + if (cacheData != null) { + cacheStore = (NfsTO) cacheData.getDataStore(); + secondaryStorageUrl = cacheStore.getUrl(); + destPath = cacheData.getPath(); + } else { + cacheStore = (NfsTO) destData.getDataStore(); + secondaryStorageUrl = cacheStore.getUrl(); + destPath = destData.getPath(); + } + + SnapshotObjectTO snapshotTO = (SnapshotObjectTO) srcData; + SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO) destData; + String snapshotUuid = snapshotTO.getPath(); + String volumeUuid = snapshotTO.getVolume().getPath(); + + String prevBackupUuid = snapshotOnImage.getParentSnapshotPath(); + String prevSnapshotUuid = snapshotTO.getParentSnapshotPath(); + + // By default assume failure + String details = null; + String snapshotBackupUuid = null; + Long physicalSize = null; + Map options = cmd.getOptions(); + boolean fullbackup = Boolean.parseBoolean(options.get("fullSnapshot")); + boolean result = false; + try { + SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); + if (primaryStorageSR == null) { + throw new InternalErrorException("Could not backup snapshot because the primary Storage SR could not be created from the name label: " + + primaryStorageNameLabel); + } + String psUuid = primaryStorageSR.getUuid(conn); + Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn)); + + VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid); + String snapshotPaUuid = null; + + if (prevSnapshotUuid != null && !fullbackup) { + try { + snapshotPaUuid = getVhdParent(conn, psUuid, snapshotUuid, isISCSI); + if (snapshotPaUuid != null) { + String snashotPaPaPaUuid = getVhdParent(conn, psUuid, snapshotPaUuid, isISCSI); + String prevSnashotPaUuid = getVhdParent(conn, psUuid, prevSnapshotUuid, isISCSI); + if (snashotPaPaPaUuid != null && prevSnashotPaUuid != null && prevSnashotPaUuid.equals(snashotPaPaPaUuid)) { + fullbackup = false; + } else { + fullbackup = true; + } + } + } catch (Exception e) { + s_logger.debug("Failed to get parent snapshots, take full snapshot", e); + fullbackup = true; + } + } + + URI uri = new URI(secondaryStorageUrl); + String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + DataStoreTO destStore = destData.getDataStore(); + String folder = destPath; + String finalPath = null; + + String localMountPoint = BaseMountPointOnHost + File.separator + UUID.nameUUIDFromBytes(secondaryStorageUrl.getBytes()).toString(); + if (fullbackup) { + // the first snapshot is always a full snapshot + + if (!hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, folder)) { + details = " Filed to create folder " + folder + " in secondary storage"; + s_logger.warn(details); + return new CopyCmdAnswer(details); + } + String snapshotMountpoint = secondaryStorageUrl + "/" + folder; + SR snapshotSr = null; + try { + snapshotSr = hypervisorResource.createNfsSRbyURI(conn, new URI(snapshotMountpoint), false); + VDI backedVdi = hypervisorResource.cloudVDIcopy(conn, snapshotVdi, snapshotSr, wait); + snapshotBackupUuid = backedVdi.getUuid(conn); + String primarySRuuid = snapshotSr.getUuid(conn); + physicalSize = getSnapshotSize(conn, primarySRuuid, snapshotBackupUuid, isISCSI, wait); + + if (destStore instanceof SwiftTO) { + try { + String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); + String destSnapshotName = swiftBackupSnapshot(conn, (SwiftTO) destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, container, false, wait); + String swiftPath = container + File.separator + destSnapshotName; + finalPath = swiftPath; + } finally { + try { + deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid); + } catch (Exception e) { + s_logger.debug("Failed to delete snapshot on cache storages", e); + } + } + + } else if (destStore instanceof S3TO) { + try { + finalPath = backupSnapshotToS3(conn, (S3TO) destStore, snapshotSr.getUuid(conn), folder, snapshotBackupUuid, isISCSI, wait); + if (finalPath == null) { + throw new CloudRuntimeException("S3 upload of snapshots " + snapshotBackupUuid + " failed"); + } + } finally { + try { + deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid); + } catch (Exception e) { + s_logger.debug("Failed to delete snapshot on cache storages", e); + } + } + // finalPath = folder + File.separator + snapshotBackupUuid; + } else { + finalPath = folder + File.separator + snapshotBackupUuid; + } + + } finally { + if (snapshotSr != null) { + hypervisorResource.removeSR(conn, snapshotSr); + } + } + } else { + String primaryStorageSRUuid = primaryStorageSR.getUuid(conn); + if (destStore instanceof SwiftTO) { + String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); + snapshotBackupUuid = + swiftBackupSnapshot(conn, (SwiftTO) destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), + isISCSI, wait); + finalPath = container + File.separator + snapshotBackupUuid; + } else if (destStore instanceof S3TO) { + finalPath = backupSnapshotToS3(conn, (S3TO) destStore, primaryStorageSRUuid, folder, snapshotPaUuid, isISCSI, wait); + if (finalPath == null) { + throw new CloudRuntimeException("S3 upload of snapshots " + snapshotPaUuid + " failed"); + } + } else { + String results = + backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder, secondaryStorageMountPath, snapshotUuid, prevBackupUuid, isISCSI, wait); + + String[] tmp = results.split("#"); + snapshotBackupUuid = tmp[1]; + physicalSize = Long.parseLong(tmp[2]); + finalPath = folder + File.separator + snapshotBackupUuid; + } + } + // delete primary snapshots with only the last one left + destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid); + + SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + newSnapshot.setPath(finalPath); + newSnapshot.setPhysicalSize(physicalSize); + if (fullbackup) { + newSnapshot.setParentSnapshotPath(null); + } else { + newSnapshot.setParentSnapshotPath(prevBackupUuid); + } + result = true; + return new CopyCmdAnswer(newSnapshot); + } catch (XenAPIException e) { + details = "BackupSnapshot Failed due to " + e.toString(); + s_logger.warn(details, e); + } catch (Exception e) { + details = "BackupSnapshot Failed due to " + e.getMessage(); + s_logger.warn(details, e); + } finally { + if (!result) { + // remove last bad primary snapshot when exception happens + try { + destroySnapshotOnPrimaryStorage(conn, snapshotUuid); + } catch (Exception e) { + s_logger.debug("clean up snapshot failed", e); + } + } + } + + return new CopyCmdAnswer(details); + } + + @Override + public Answer createTemplateFromVolume(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + VolumeObjectTO volume = (VolumeObjectTO) cmd.getSrcTO(); + TemplateObjectTO template = (TemplateObjectTO) cmd.getDestTO(); + NfsTO destStore = (NfsTO) cmd.getDestTO().getDataStore(); + int wait = cmd.getWait(); + + String secondaryStoragePoolURL = destStore.getUrl(); + String volumeUUID = volume.getPath(); + + String userSpecifiedName = template.getName(); + + String details = null; + SR tmpltSR = null; + boolean result = false; + String secondaryStorageMountPath = null; + String installPath = null; + try { + URI uri = new URI(secondaryStoragePoolURL); + secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + installPath = template.getPath(); + if (!hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) { + details = " Filed to create folder " + installPath + " in secondary storage"; + s_logger.warn(details); + return new CopyCmdAnswer(details); + } + + VDI vol = getVDIbyUuid(conn, volumeUUID); + // create template SR + URI tmpltURI = new URI(secondaryStoragePoolURL + "/" + installPath); + tmpltSR = hypervisorResource.createNfsSRbyURI(conn, tmpltURI, false); + + // copy volume to template SR + VDI tmpltVDI = hypervisorResource.cloudVDIcopy(conn, vol, tmpltSR, wait); + // scan makes XenServer pick up VDI physicalSize + tmpltSR.scan(conn); + if (userSpecifiedName != null) { + tmpltVDI.setNameLabel(conn, userSpecifiedName); + } + + String tmpltUUID = tmpltVDI.getUuid(conn); + String tmpltFilename = tmpltUUID + ".vhd"; + long virtualSize = tmpltVDI.getVirtualSize(conn); + long physicalSize = tmpltVDI.getPhysicalUtilisation(conn); + // create the template.properties file + String templatePath = secondaryStorageMountPath + "/" + installPath; + result = + hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, + template.getId()); + if (!result) { + throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + tmpltURI); + } + installPath = installPath + "/" + tmpltFilename; + hypervisorResource.removeSR(conn, tmpltSR); + tmpltSR = null; + TemplateObjectTO newTemplate = new TemplateObjectTO(); + newTemplate.setPath(installPath); + newTemplate.setFormat(ImageFormat.VHD); + newTemplate.setSize(virtualSize); + newTemplate.setPhysicalSize(physicalSize); + newTemplate.setName(tmpltUUID); + CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate); + return answer; + } catch (Exception e) { + if (tmpltSR != null) { + hypervisorResource.removeSR(conn, tmpltSR); + } + if (secondaryStorageMountPath != null) { + hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath); + } + details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString(); + s_logger.error(details, e); + } + return new CopyCmdAnswer(details); + } + + @Override + public Answer createTemplateFromSnapshot(CopyCommand cmd) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Answer createVolumeFromSnapshot(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + SnapshotObjectTO snapshot = (SnapshotObjectTO) srcData; + DataTO destData = cmd.getDestTO(); + DataStoreTO imageStore = srcData.getDataStore(); + + if (!(imageStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + + NfsTO nfsImageStore = (NfsTO) imageStore; + String primaryStorageNameLabel = destData.getDataStore().getUuid(); + String secondaryStorageUrl = nfsImageStore.getUrl(); + int wait = cmd.getWait(); + boolean result = false; + // Generic error message. + String details = null; + String volumeUUID = null; + + if (secondaryStorageUrl == null) { + details += " because the URL passed: " + secondaryStorageUrl + " is invalid."; + return new CopyCmdAnswer(details); + } + try { + SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); + if (primaryStorageSR == null) { + throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: " + + primaryStorageNameLabel); + } + // Get the absolute path of the snapshot on the secondary storage. + String snapshotInstallPath = snapshot.getPath(); + int index = snapshotInstallPath.lastIndexOf(File.separator); + String snapshotName = snapshotInstallPath.substring(index + 1); + + if (!snapshotName.startsWith("VHD-") && !snapshotName.endsWith(".vhd")) { + snapshotInstallPath = snapshotInstallPath + ".vhd"; + } + URI snapshotURI = new URI(secondaryStorageUrl + File.separator + snapshotInstallPath); + String snapshotPath = snapshotURI.getHost() + ":" + snapshotURI.getPath(); + String srUuid = primaryStorageSR.getUuid(conn); + volumeUUID = copy_vhd_from_secondarystorage(conn, snapshotPath, srUuid, wait); + result = true; + VDI volume = VDI.getByUuid(conn, volumeUUID); + VDI.Record vdir = volume.getRecord(conn); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(volumeUUID); + newVol.setSize(vdir.virtualSize); + return new CopyCmdAnswer(newVol); + } catch (XenAPIException e) { + details += " due to " + e.toString(); + s_logger.warn(details, e); + } catch (Exception e) { + details += " due to " + e.getMessage(); + s_logger.warn(details, e); + } + if (!result) { + // Is this logged at a higher level? + s_logger.error(details); + } + + // In all cases return something. + return new CopyCmdAnswer(details); + } + + @Override + public Answer deleteSnapshot(DeleteCommand cmd) { + SnapshotObjectTO snapshot = (SnapshotObjectTO) cmd.getData(); + DataStoreTO store = snapshot.getDataStore(); + if (store.getRole() == DataStoreRole.Primary) { + Connection conn = hypervisorResource.getConnection(); + VDI snapshotVdi = getVDIbyUuid(conn, snapshot.getPath()); + if (snapshotVdi == null) { + return new Answer(null); + } + String errMsg = null; + try { + deleteVDI(conn, snapshotVdi); + } catch (BadServerResponse e) { + s_logger.debug("delete snapshot failed:" + e.toString()); + errMsg = e.toString(); + } catch (XenAPIException e) { + s_logger.debug("delete snapshot failed:" + e.toString()); + errMsg = e.toString(); + } catch (XmlRpcException e) { + s_logger.debug("delete snapshot failed:" + e.toString()); + errMsg = e.toString(); + } + return new Answer(cmd, false, errMsg); + } + return new Answer(cmd, false, "unsupported storage type"); + } + + @Override + public Answer introduceObject(IntroduceObjectCmd cmd) { + try { + Connection conn = hypervisorResource.getConnection(); + DataStoreTO store = cmd.getDataTO().getDataStore(); + SR poolSr = hypervisorResource.getStorageRepository(conn, store.getUuid()); + poolSr.scan(conn); + return new IntroduceObjectAnswer(cmd.getDataTO()); + } catch (Exception e) { + s_logger.debug("Failed to introduce object", e); + return new Answer(cmd, false, e.toString()); + } + } + + @Override + public Answer forgetObject(ForgetObjectCmd cmd) { + try { + Connection conn = hypervisorResource.getConnection(); + DataTO data = cmd.getDataTO(); + VDI vdi = VDI.getByUuid(conn, data.getPath()); + vdi.forget(conn); + return new IntroduceObjectAnswer(cmd.getDataTO()); + } catch (Exception e) { + s_logger.debug("Failed to introduce object", e); + return new Answer(cmd, false, e.toString()); + } + } +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625Resource.java new file mode 100644 index 00000000000..5c8006288c6 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625Resource.java @@ -0,0 +1,160 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with 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. + */ +package com.cloud.hypervisor.xenserver.resource; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.VM; + +import org.apache.cloudstack.hypervisor.xenserver.XenServerResourceNewBase; + +import com.cloud.resource.ServerResource; +import com.cloud.storage.resource.StorageSubsystemCommandHandler; +import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import com.cloud.utils.ssh.SSHCmdHelper; + +@Local(value=ServerResource.class) +public class Xenserver625Resource extends XenServerResourceNewBase { + private static final Logger s_logger = Logger.getLogger(Xenserver625Resource.class); + + public Xenserver625Resource() { + super(); + } + + @Override + protected String getGuestOsType(String stdType, boolean bootFromCD) { + return CitrixHelper.getXenServer625GuestOsType(stdType, bootFromCD); + } + + @Override + protected List getPatchFiles() { + List files = new ArrayList(); + String patch = "scripts/vm/hypervisor/xenserver/xenserver62/patch"; + String patchfilePath = Script.findScript("", patch); + if (patchfilePath == null) { + throw new CloudRuntimeException("Unable to find patch file " + patch); + } + File file = new File(patchfilePath); + files.add(file); + return files; + } + + @Override + public long getStaticMax(String os, boolean b, long dynamicMinRam, long dynamicMaxRam){ + long recommendedValue = CitrixHelper.getXenServer625StaticMax(os, b); + if(recommendedValue == 0){ + s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal"); + return dynamicMaxRam; + } + long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam); // XS constraint for stability + if (dynamicMaxRam > staticMax){ // XS contraint that dynamic max <= static max + s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + ", can lead to stability issues. Setting static max as much as dynamic max "); + return dynamicMaxRam; + } + return staticMax; + } + + @Override + public long getStaticMin(String os, boolean b, long dynamicMinRam, long dynamicMaxRam){ + long recommendedValue = CitrixHelper.getXenServer625StaticMin(os, b); + if(recommendedValue == 0){ + s_logger.warn("No recommended value found for dynamic min"); + return dynamicMinRam; + } + + if(dynamicMinRam < recommendedValue){ // XS contraint that dynamic min > static min + s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues"); + } + return dynamicMinRam; + } + + @Override + protected StorageSubsystemCommandHandler getStorageHandler() { + XenServerStorageProcessor processor = new Xenserver625StorageProcessor(this); + return new StorageSubsystemCommandHandlerBase(processor); + } + + @Override + protected void umountSnapshotDir(Connection conn, Long dcId) { + + } + + @Override + protected boolean setupServer(Connection conn) { + com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_host.ip, 22); + try { + sshConnection.connect(null, 60000, 60000); + if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { + throw new CloudRuntimeException("Unable to authenticate"); + } + + String cmd = "rm -f /opt/xensource/sm/hostvmstats.py " + + "/opt/xensource/bin/copy_vhd_to_secondarystorage.sh " + + "/opt/xensource/bin/copy_vhd_from_secondarystorage.sh " + + "/opt/xensource/bin/create_privatetemplate_from_snapshot.sh " + + "/opt/xensource/bin/vhd-util " + + "/opt/cloud/bin/copy_vhd_to_secondarystorage.sh " + + "/opt/cloud/bin/copy_vhd_from_secondarystorage.sh " + + "/opt/cloud/bin/create_privatetemplate_from_snapshot.sh " + + "/opt/cloud/bin/vhd-util"; + + SSHCmdHelper.sshExecuteCmd(sshConnection, cmd); + } catch (Exception e) { + s_logger.debug("Catch exception " + e.toString(), e); + } finally { + sshConnection.close(); + } + return super.setupServer(conn); + } + + @Override + protected String revertToSnapshot(Connection conn, VM vmSnapshot, + String vmName, String oldVmUuid, Boolean snapshotMemory, String hostUUID) + throws Types.XenAPIException, XmlRpcException { + + String results = callHostPluginAsync(conn, "cloud-plugin-storage", + "revert_memory_snapshot", 10 * 60 * 1000, "snapshotUUID", + vmSnapshot.getUuid(conn), "vmName", vmName, "oldVmUuid", + oldVmUuid, "snapshotMemory", snapshotMemory.toString(), "hostUUID", hostUUID); + String errMsg = null; + if (results == null || results.isEmpty()) { + errMsg = "revert_memory_snapshot return null"; + } else { + if (results.equals("0")) { + return results; + } else { + errMsg = "revert_memory_snapshot exception"; + } + } + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); + } + +} diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java new file mode 100644 index 00000000000..5eb991ed298 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java @@ -0,0 +1,822 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with 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. + */ +package com.cloud.hypervisor.xenserver.resource; + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.S3TO; +import com.cloud.agent.api.to.SwiftTO; +import com.cloud.exception.InternalErrorException; +import com.cloud.storage.Storage; +import com.cloud.utils.exception.CloudRuntimeException; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.PBD; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Task; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.VDI; + +public class Xenserver625StorageProcessor extends XenServerStorageProcessor { + private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class); + + public Xenserver625StorageProcessor(CitrixResourceBase resource) { + super(resource); + } + protected boolean mountNfs(Connection conn, String remoteDir, String localDir) { + if (localDir == null) { + localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remoteDir.getBytes()); + } + String results = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", 100 * 1000, + "localDir", localDir, "remoteDir", remoteDir); + if (results == null || results.isEmpty()) { + String errMsg = "Could not mount secondary storage " + remoteDir + " on host "; + s_logger.warn(errMsg); + throw new CloudRuntimeException(errMsg); + } + return true; + } + + protected boolean makeDirectory(Connection conn, String path) { + String result = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "makeDirectory", "path", path); + if (result == null || result.isEmpty()) { + return false; + } + return true; + } + + protected SR createFileSR(Connection conn, String path) { + SR sr = null; + PBD pbd = null; + try { + Map smConfig = new HashMap(); + Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid); + String uuid = UUID.randomUUID().toString(); + + sr = SR.introduce(conn,uuid, uuid, uuid, "file", "file", false, smConfig); + PBD.Record record = new PBD.Record(); + record.host = host; + record.SR = sr; + smConfig.put("location", path); + record.deviceConfig = smConfig; + pbd = PBD.create(conn, record); + pbd.plug(conn); + sr.scan(conn); + return sr; + } catch (Exception e) { + try { + if (pbd != null) { + pbd.destroy(conn); + } + } catch (Exception e1) { + s_logger.debug("Failed to destroy pbd", e); + } + try { + if (sr != null) { + sr.forget(conn); + } + } catch (Exception e2) { + s_logger.error("Failed to forget sr", e); + } + String msg = "createFileSR failed! due to " + e.toString(); + s_logger.warn(msg, e); + throw new CloudRuntimeException(msg, e); + } + } + + protected SR createFileSr(Connection conn, String remotePath, String dir) { + String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remotePath.getBytes()); + mountNfs(conn, remotePath, localDir); + SR sr = createFileSR(conn, localDir + "/" + dir); + return sr; + } + + @Override + public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + int wait = cmd.getWait(); + DataStoreTO srcStore = srcData.getDataStore(); + Connection conn = hypervisorResource.getConnection(); + SR srcSr = null; + try { + if ((srcStore instanceof NfsTO) && (srcData.getObjectType() == DataObjectType.TEMPLATE)) { + NfsTO srcImageStore = (NfsTO)srcStore; + TemplateObjectTO srcTemplate = (TemplateObjectTO)srcData; + String storeUrl = srcImageStore.getUrl(); + URI uri = new URI(storeUrl); + String volumePath = srcData.getPath(); + volumePath = StringUtils.stripEnd(volumePath, "/"); + String[] splits = volumePath.split("/"); + String volumeDirectory = volumePath; + if (splits.length > 4) { + //"template/tmpl/dcid/templateId/templatename" + int index = volumePath.lastIndexOf("/"); + volumeDirectory = volumePath.substring(0, index); + } + srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory); + Set vdis = srcSr.getVDIs(conn); + if (vdis.size() != 1) { + return new CopyCmdAnswer("Can't find template VDI under: " + uri.getHost() + ":" + uri.getPath() + "/" + volumeDirectory); + } + + VDI srcVdi = vdis.iterator().next(); + + PrimaryDataStoreTO destStore = (PrimaryDataStoreTO)destData.getDataStore(); + String poolName = destStore.getUuid(); + + + SR poolsr = null; + Set srs = SR.getByNameLabel(conn, poolName); + if (srs.size() != 1) { + String msg = "There are " + srs.size() + " SRs with same name: " + poolName; + s_logger.warn(msg); + return new CopyCmdAnswer(msg); + } else { + poolsr = srs.iterator().next(); + } + String pUuid = poolsr.getUuid(conn); + boolean isISCSI = IsISCSI(poolsr.getType(conn)); + Task task = srcVdi.copyAsync(conn, poolsr, null, null); + // poll every 1 seconds , + hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); + hypervisorResource.checkForSuccess(conn, task); + VDI tmpl = Types.toVDI(task, conn); + VDI snapshotvdi = tmpl.snapshot(conn, new HashMap()); + snapshotvdi.setNameLabel(conn, "Template " + srcTemplate.getName()); + tmpl.destroy(conn); + poolsr.scan(conn); + try{ + Thread.sleep(5000); + } catch (Exception e) { + } + + TemplateObjectTO newVol = new TemplateObjectTO(); + newVol.setUuid(snapshotvdi.getUuid(conn)); + newVol.setPath(newVol.getUuid()); + newVol.setFormat(Storage.ImageFormat.VHD); + return new CopyCmdAnswer(newVol); + } + }catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString(); + s_logger.warn(msg, e); + return new CopyCmdAnswer(msg); + } finally { + if (srcSr != null) { + hypervisorResource.removeSR(conn, srcSr); + } + } + return new CopyCmdAnswer("not implemented yet"); + } + + protected String backupSnapshot(Connection conn, String primaryStorageSRUuid, String localMountPoint, String path, String secondaryStorageMountPath, String snapshotUuid, String prevBackupUuid, String prevSnapshotUuid, Boolean isISCSI, int wait) { + String errMsg = null; + boolean mounted = false; + boolean filesrcreated = false; + boolean copied = false; + if (prevBackupUuid == null) { + prevBackupUuid = ""; + } + SR ssSR = null; + + String remoteDir = secondaryStorageMountPath; + + try { + ssSR = createFileSr(conn, remoteDir, path); + filesrcreated = true; + + VDI snapshotvdi = VDI.getByUuid(conn, snapshotUuid); + Task task = null; + if (wait == 0) { + wait = 2 * 60 * 60; + } + VDI dvdi = null; + try { + VDI previousSnapshotVdi = null; + if (prevSnapshotUuid != null) { + previousSnapshotVdi = VDI.getByUuid(conn,prevSnapshotUuid); + } + task = snapshotvdi.copyAsync(conn, ssSR, previousSnapshotVdi, null); + // poll every 1 seconds , + hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); + hypervisorResource.checkForSuccess(conn, task); + dvdi = Types.toVDI(task, conn); + copied = true; + } finally { + if (task != null) { + try { + task.destroy(conn); + } catch (Exception e1) { + s_logger.warn("unable to destroy task(" + task.toString() + ") on host(" + + ") due to ", e1); + } + } + } + String backupUuid = dvdi.getUuid(conn); + return backupUuid; + } catch (Exception e) { + String msg = "Exception in backupsnapshot stage due to " + e.toString(); + s_logger.debug(msg); + throw new CloudRuntimeException(msg, e); + } finally { + try { + if (filesrcreated && ssSR != null) { + hypervisorResource.removeSR(conn, ssSR); + } + } catch (Exception e) { + s_logger.debug("Exception in backupsnapshot cleanup stage due to " + e.toString()); + } + } + } + + @Override + protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) { + String parentUuid = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, + "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString()); + + if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) { + s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid); + // errString is already logged. + return null; + } + return parentUuid; + } + + @Override + public Answer backupSnapshot(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + DataTO cacheData = cmd.getCacheTO(); + DataTO destData = cmd.getDestTO(); + int wait = cmd.getWait(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcData.getDataStore(); + String primaryStorageNameLabel = primaryStore.getUuid(); + String secondaryStorageUrl = null; + NfsTO cacheStore = null; + String destPath = null; + if (cacheData != null) { + cacheStore = (NfsTO)cacheData.getDataStore(); + secondaryStorageUrl = cacheStore.getUrl(); + destPath = cacheData.getPath(); + } else { + cacheStore = (NfsTO)destData.getDataStore(); + secondaryStorageUrl = cacheStore.getUrl(); + destPath = destData.getPath(); + } + + SnapshotObjectTO snapshotTO = (SnapshotObjectTO)srcData; + SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO)destData; + String snapshotUuid = snapshotTO.getPath(); + + String prevBackupUuid = snapshotOnImage.getParentSnapshotPath(); + String prevSnapshotUuid = snapshotTO.getParentSnapshotPath(); + Map options = cmd.getOptions(); + // By default assume failure + String details = null; + String snapshotBackupUuid = null; + boolean fullbackup = Boolean.parseBoolean(options.get("fullSnapshot")); + try { + SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); + if (primaryStorageSR == null) { + throw new InternalErrorException("Could not backup snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel); + } + String psUuid = primaryStorageSR.getUuid(conn); + Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn)); + + VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid); + String snapshotPaUuid = null; + + URI uri = new URI(secondaryStorageUrl); + String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + DataStoreTO destStore = destData.getDataStore(); + String folder = destPath; + String finalPath = null; + + String localMountPoint = BaseMountPointOnHost + File.separator + UUID.nameUUIDFromBytes(secondaryStorageUrl.getBytes()).toString(); + if (fullbackup) { + SR snapshotSr = null; + try { + String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes()); + mountNfs(conn, secondaryStorageMountPath, localDir); + boolean result = makeDirectory(conn, localDir + "/" + folder); + if (!result) { + details = " Filed to create folder " + folder + " in secondary storage"; + s_logger.warn(details); + return new CopyCmdAnswer(details); + } + + snapshotSr = createFileSr(conn, secondaryStorageMountPath, folder); + + Task task = snapshotVdi.copyAsync(conn, snapshotSr, null, null); + // poll every 1 seconds , + hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); + hypervisorResource.checkForSuccess(conn, task); + VDI backedVdi = Types.toVDI(task, conn); + snapshotBackupUuid = backedVdi.getUuid(conn); + + if( destStore instanceof SwiftTO) { + try { + String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); + String destSnapshotName = swiftBackupSnapshot(conn, (SwiftTO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, container, false, wait); + String swiftPath = container + File.separator + destSnapshotName; + finalPath = swiftPath; + } finally { + try { + deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid); + } catch (Exception e) { + s_logger.debug("Failed to delete snapshot on cache storages" ,e); + } + } + + } else if (destStore instanceof S3TO) { + try { + finalPath = backupSnapshotToS3(conn, (S3TO) destStore, snapshotSr.getUuid(conn), folder, snapshotBackupUuid, isISCSI, wait); + if (finalPath == null) { + throw new CloudRuntimeException("S3 upload of snapshots " + snapshotBackupUuid + " failed"); + } + } finally { + try { + deleteSnapshotBackup(conn, localMountPoint, folder, secondaryStorageMountPath, snapshotBackupUuid); + } catch (Exception e) { + s_logger.debug("Failed to delete snapshot on cache storages" ,e); + } + } + // finalPath = folder + File.separator + snapshotBackupUuid; + } else { + finalPath = folder + File.separator + snapshotBackupUuid; + } + + } finally { + if( snapshotSr != null) { + hypervisorResource.removeSR(conn, snapshotSr); + } + } + } else { + String primaryStorageSRUuid = primaryStorageSR.getUuid(conn); + if( destStore instanceof SwiftTO ) { + String container = "S-" + snapshotTO.getVolume().getVolumeId().toString(); + snapshotBackupUuid = swiftBackupSnapshot(conn, (SwiftTO)destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait); + finalPath = container + File.separator + snapshotBackupUuid; + } else if (destStore instanceof S3TO ) { + finalPath = backupSnapshotToS3(conn, (S3TO) destStore, primaryStorageSRUuid, folder, snapshotPaUuid, isISCSI, wait); + if (finalPath == null) { + throw new CloudRuntimeException("S3 upload of snapshots " + snapshotPaUuid + " failed"); + } + } else { + snapshotBackupUuid = backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder, + secondaryStorageMountPath, snapshotUuid, prevBackupUuid, prevSnapshotUuid, isISCSI, wait); + + finalPath = folder + File.separator + snapshotBackupUuid; + } + } + String volumeUuid = snapshotTO.getVolume().getPath(); + destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid); + + SnapshotObjectTO newSnapshot = new SnapshotObjectTO(); + newSnapshot.setPath(finalPath); + if (fullbackup) { + newSnapshot.setParentSnapshotPath(null); + } else { + newSnapshot.setParentSnapshotPath(prevBackupUuid); + } + return new CopyCmdAnswer(newSnapshot); + } catch (Types.XenAPIException e) { + details = "BackupSnapshot Failed due to " + e.toString(); + s_logger.warn(details, e); + } catch (Exception e) { + details = "BackupSnapshot Failed due to " + e.getMessage(); + s_logger.warn(details, e); + } + + return new CopyCmdAnswer(details); + } + + @Override + public Answer createTemplateFromVolume(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO(); + TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO(); + NfsTO destStore = (NfsTO)cmd.getDestTO().getDataStore(); + int wait = cmd.getWait(); + + String secondaryStoragePoolURL = destStore.getUrl(); + String volumeUUID = volume.getPath(); + + String userSpecifiedName = template.getName(); + + + String details = null; + SR tmpltSR = null; + boolean result = false; + String secondaryStorageMountPath = null; + String installPath = null; + try { + URI uri = new URI(secondaryStoragePoolURL); + secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); + installPath = template.getPath(); + if( !hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) { + details = " Filed to create folder " + installPath + " in secondary storage"; + s_logger.warn(details); + return new CopyCmdAnswer(details); + } + + VDI vol = getVDIbyUuid(conn, volumeUUID); + // create template SR + tmpltSR = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), installPath); + + // copy volume to template SR + Task task = vol.copyAsync(conn, tmpltSR, null, null); + // poll every 1 seconds , + hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); + hypervisorResource.checkForSuccess(conn, task); + VDI tmpltVDI = Types.toVDI(task, conn); + // scan makes XenServer pick up VDI physicalSize + tmpltSR.scan(conn); + if (userSpecifiedName != null) { + tmpltVDI.setNameLabel(conn, userSpecifiedName); + } + + String tmpltUUID = tmpltVDI.getUuid(conn); + String tmpltFilename = tmpltUUID + ".vhd"; + long virtualSize = tmpltVDI.getVirtualSize(conn); + long physicalSize = tmpltVDI.getPhysicalUtilisation(conn); + // create the template.properties file + String templatePath = secondaryStorageMountPath + "/" + installPath; + result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId()); + if (!result) { + throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir"); + } + installPath = installPath + "/" + tmpltFilename; + hypervisorResource.removeSR(conn, tmpltSR); + tmpltSR = null; + TemplateObjectTO newTemplate = new TemplateObjectTO(); + newTemplate.setPath(installPath); + newTemplate.setFormat(Storage.ImageFormat.VHD); + newTemplate.setSize(virtualSize); + newTemplate.setPhysicalSize(physicalSize); + newTemplate.setName(tmpltUUID); + CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate); + return answer; + } catch (Exception e) { + if (tmpltSR != null) { + hypervisorResource.removeSR(conn, tmpltSR); + } + if ( secondaryStorageMountPath != null) { + hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath); + } + details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString(); + s_logger.error(details, e); + } + return new CopyCmdAnswer(details); + } + + protected String getSnapshotUuid(String snapshotPath) { + int index = snapshotPath.lastIndexOf(File.separator); + String snapshotUuid = snapshotPath.substring(index + 1); + index = snapshotUuid.lastIndexOf("."); + if (index != -1) { + snapshotUuid = snapshotUuid.substring(0, index); + } + return snapshotUuid; + } + + @Override + public Answer createVolumeFromSnapshot(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + SnapshotObjectTO snapshot = (SnapshotObjectTO)srcData; + DataTO destData = cmd.getDestTO(); + PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore(); + VolumeObjectTO volume = (VolumeObjectTO)destData; + DataStoreTO imageStore = srcData.getDataStore(); + + if (!(imageStore instanceof NfsTO)) { + return new CopyCmdAnswer("unsupported protocol"); + } + + NfsTO nfsImageStore = (NfsTO)imageStore; + String primaryStorageNameLabel = pool.getUuid(); + String secondaryStorageUrl = nfsImageStore.getUrl(); + int wait = cmd.getWait(); + boolean result = false; + // Generic error message. + String details = null; + String volumeUUID = null; + + if (secondaryStorageUrl == null) { + details += " because the URL passed: " + secondaryStorageUrl + " is invalid."; + return new CopyCmdAnswer(details); + } + SR srcSr = null; + VDI destVdi = null; + try { + SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel); + if (primaryStorageSR == null) { + throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: " + + primaryStorageNameLabel); + } + String nameLabel = "cloud-" + UUID.randomUUID().toString(); + destVdi = createVdi(conn, nameLabel, primaryStorageSR, volume.getSize()); + volumeUUID = destVdi.getUuid(conn); + String snapshotInstallPath = snapshot.getPath(); + int index = snapshotInstallPath.lastIndexOf(File.separator); + String snapshotDirectory = snapshotInstallPath.substring(0, index); + String snapshotUuid = getSnapshotUuid(snapshotInstallPath); + + URI uri = new URI(secondaryStorageUrl); + srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), snapshotDirectory); + + String[] parents = snapshot.getParents(); + List snapshotChains = new ArrayList(); + if (parents != null) { + for(int i = 0; i < parents.length; i++) { + String snChainPath = parents[i]; + String uuid = getSnapshotUuid(snChainPath); + VDI chain = VDI.getByUuid(conn, uuid); + snapshotChains.add(chain); + } + } + + VDI snapshotVdi = VDI.getByUuid(conn, snapshotUuid); + snapshotChains.add(snapshotVdi); + + for(VDI snapChain : snapshotChains) { + Task task = snapChain.copyAsync(conn, null, null, destVdi); + // poll every 1 seconds , + hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); + hypervisorResource.checkForSuccess(conn, task); + } + + result = true; + destVdi = VDI.getByUuid(conn, volumeUUID); + VDI.Record vdir = destVdi.getRecord(conn); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(volumeUUID); + newVol.setSize(vdir.virtualSize); + return new CopyCmdAnswer(newVol); + } catch (Types.XenAPIException e) { + details += " due to " + e.toString(); + s_logger.warn(details, e); + } catch (Exception e) { + details += " due to " + e.getMessage(); + s_logger.warn(details, e); + } finally { + if (srcSr != null) { + hypervisorResource.removeSR(conn, srcSr); + } + if (!result && destVdi != null) { + try { + destVdi.destroy(conn); + } catch (Exception e) { + s_logger.debug("destroy dest vdi failed", e); + } + } + } + if (!result) { + // Is this logged at a higher level? + s_logger.error(details); + } + + // In all cases return something. + return new CopyCmdAnswer(details); + } + + @Override + public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO(); + VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO(); + int wait = cmd.getWait(); + DataStoreTO destStore = destVolume.getDataStore(); + + if (destStore instanceof NfsTO) { + SR secondaryStorage = null; + try { + NfsTO nfsStore = (NfsTO)destStore; + URI uri = new URI(nfsStore.getUrl()); + // Create the volume folder + if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) { + throw new InternalErrorException("Failed to create the volume folder."); + } + + // Create a SR for the volume UUID folder + secondaryStorage = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath()); + // Look up the volume on the source primary storage pool + VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath()); + // Copy the volume to secondary storage + Task task = srcVdi.copyAsync(conn, secondaryStorage, null, null); + // poll every 1 seconds , + hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); + hypervisorResource.checkForSuccess(conn, task); + VDI destVdi = Types.toVDI(task, conn); + String destVolumeUUID = destVdi.getUuid(conn); + + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(destVolume.getPath() + File.separator + destVolumeUUID + ".vhd"); + newVol.setSize(srcVolume.getSize()); + return new CopyCmdAnswer(newVol); + } catch (Exception e) { + s_logger.debug("Failed to copy volume to secondary: " + e.toString()); + return new CopyCmdAnswer("Failed to copy volume to secondary: " + e.toString()); + } finally { + hypervisorResource.removeSR(conn, secondaryStorage); + } + } + return new CopyCmdAnswer("unsupported protocol"); + } + + @Override + public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + int wait = cmd.getWait(); + VolumeObjectTO srcVolume = (VolumeObjectTO)srcData; + VolumeObjectTO destVolume = (VolumeObjectTO)destData; + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destVolume.getDataStore(); + DataStoreTO srcStore = srcVolume.getDataStore(); + + if (srcStore instanceof NfsTO) { + NfsTO nfsStore = (NfsTO)srcStore; + String volumePath = srcVolume.getPath(); + int index = volumePath.lastIndexOf("/"); + String volumeDirectory = volumePath.substring(0, index); + String volumeUuid = volumePath.substring(index + 1); + index = volumeUuid.indexOf("."); + if (index != -1) { + volumeUuid = volumeUuid.substring(0, index); + } + URI uri = null; + try { + uri = new URI(nfsStore.getUrl()); + } catch (Exception e) { + return new CopyCmdAnswer(e.toString()); + } + SR srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory); + try { + SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid()); + VDI srcVdi = VDI.getByUuid(conn, volumeUuid); + Task task = srcVdi.copyAsync(conn, primaryStoragePool, null, null); + // poll every 1 seconds , + hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); + hypervisorResource.checkForSuccess(conn, task); + VDI destVdi = Types.toVDI(task, conn); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setPath(destVdi.getUuid(conn)); + newVol.setSize(srcVolume.getSize()); + + return new CopyCmdAnswer(newVol); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); + s_logger.warn(msg, e); + return new CopyCmdAnswer(e.toString()); + } finally { + if (srcSr != null) { + hypervisorResource.removeSR(conn, srcSr); + } + } + } + + s_logger.debug("unsupported protocol"); + return new CopyCmdAnswer("unsupported protocol"); + } + + @Override + public Answer createTemplateFromSnapshot(CopyCommand cmd) { + Connection conn = hypervisorResource.getConnection(); + DataTO srcData = cmd.getSrcTO(); + DataTO destData = cmd.getDestTO(); + int wait = cmd.getWait(); + SnapshotObjectTO srcObj = (SnapshotObjectTO)srcData; + TemplateObjectTO destObj = (TemplateObjectTO)destData; + NfsTO srcStore = (NfsTO)srcObj.getDataStore(); + NfsTO destStore = (NfsTO)destObj.getDataStore(); + + URI srcUri = null; + URI destUri = null; + try { + srcUri = new URI(srcStore.getUrl()); + destUri = new URI(destStore.getUrl()); + } catch (Exception e) { + s_logger.debug("incorrect url", e); + return new CopyCmdAnswer("incorrect url" + e.toString()); + } + + String srcPath = srcObj.getPath(); + int index = srcPath.lastIndexOf("/"); + String srcDir = srcPath.substring(0, index); + String destDir = destObj.getPath(); + SR srcSr = null; + SR destSr = null; + VDI destVdi = null; + boolean result = false; + try { + srcSr = createFileSr(conn, srcUri.getHost() + ":" + srcUri.getPath(), srcDir); + + String destNfsPath = destUri.getHost() + ":" + destUri.getPath(); + String localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(destNfsPath.getBytes()); + mountNfs(conn, destUri.getHost() + ":" + destUri.getPath(), localDir); + makeDirectory(conn, localDir + "/" + destDir); + destSr = createFileSR(conn, localDir + "/" + destDir); + + String nameLabel = "cloud-" + UUID.randomUUID().toString(); + + String[] parents = srcObj.getParents(); + List snapshotChains = new ArrayList(); + if (parents != null) { + for(int i = 0; i < parents.length; i++) { + String snChainPath = parents[i]; + String uuid = getSnapshotUuid(snChainPath); + VDI chain = VDI.getByUuid(conn, uuid); + snapshotChains.add(chain); + } + } + String snapshotUuid = getSnapshotUuid(srcPath); + VDI snapshotVdi = VDI.getByUuid(conn, snapshotUuid); + snapshotChains.add(snapshotVdi); + + long templateVirtualSize = snapshotChains.get(0).getVirtualSize(conn); + destVdi = createVdi(conn, nameLabel, destSr, templateVirtualSize); + String destVdiUuid = destVdi.getUuid(conn); + + for(VDI snapChain : snapshotChains) { + Task task = snapChain.copyAsync(conn, null, null, destVdi); + // poll every 1 seconds , + hypervisorResource.waitForTask(conn, task, 1000, wait * 1000); + hypervisorResource.checkForSuccess(conn, task); + } + + destVdi = VDI.getByUuid(conn, destVdiUuid); + String templatePath = destDir + "/" + destVdiUuid + ".vhd"; + templatePath = templatePath.replaceAll("//","/"); + TemplateObjectTO newTemplate = new TemplateObjectTO(); + newTemplate.setPath(templatePath); + newTemplate.setFormat(Storage.ImageFormat.VHD); + newTemplate.setSize(destVdi.getVirtualSize(conn)); + newTemplate.setPhysicalSize(destVdi.getPhysicalUtilisation(conn)); + newTemplate.setName(destVdiUuid); + + result = true; + return new CopyCmdAnswer(newTemplate); + } catch (Exception e) { + s_logger.error("Failed create template from snapshot", e); + return new CopyCmdAnswer("Failed create template from snapshot " + e.toString()); + } finally { + if (!result) { + if (destVdi != null) { + try { + destVdi.destroy(conn); + } catch (Exception e) { + s_logger.debug("Clean up left over on dest storage failed: ", e); + } + } + } + + if (destSr != null) { + hypervisorResource.removeSR(conn, destSr); + } + + if (srcSr != null) { + hypervisorResource.removeSR(conn, srcSr); + } + } + } + +} diff --git a/plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenServerResourceNewBase.java b/plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenServerResourceNewBase.java new file mode 100644 index 00000000000..2a9186a2b13 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenServerResourceNewBase.java @@ -0,0 +1,345 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. +package org.apache.cloudstack.hypervisor.xenserver; + + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.TimeoutException; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Event; +import com.xensource.xenapi.EventBatch; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Pool; +import com.xensource.xenapi.Task; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VM; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.ClusterSyncAnswer; +import com.cloud.agent.api.ClusterSyncCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.hypervisor.xenserver.resource.XenServer620SP1Resource; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineName; + +/** + * + * XenServerResourceNewBase is an abstract base class that encapsulates how + * CloudStack should interact with XenServer after a special XenServer + * 6.2 hotfix. From here on, every Resource for future versions of + * XenServer should use this as the base class. This base class lessens + * the amount of load CloudStack places on Xapi because it doesn't use + * polling as a means to collect data and figure out task completion. + * + * This base class differs from CitrixResourceBase in the following ways: + * - VM states are detected using Event.from instead of polling. This + * increases the number of threads CloudStack uses but the threads + * are mostly idle just waiting for events from XenServer. + * - stats are collected through the http interface rather than Xapi plugin. + * This change may be promoted to CitrixResourceBase as it's also possible + * in previous versions of XenServer. + * - Asynchronous task completion is done throught Event.from rather than + * polling. + * + */ +public class XenServerResourceNewBase extends XenServer620SP1Resource { + private static final Logger s_logger = Logger.getLogger(XenServerResourceNewBase.class); + protected VmEventListener _listener = null; + + @Override + public StartupCommand[] initialize() throws IllegalArgumentException { + StartupCommand[] cmds = super.initialize(); + + Connection conn = getConnection(); + Pool pool; + try { + pool = Pool.getByUuid(conn, _host.pool); + Pool.Record poolr = pool.getRecord(conn); + + Host.Record masterRecord = poolr.master.getRecord(conn); + if (_host.uuid.equals(masterRecord.uuid)) { + _listener = new VmEventListener(true); + + // + // TODO disable event listener for now. Wait until everything else is ready + // + + // _listener.start(); + } else { + _listener = new VmEventListener(false); + } + } catch (XenAPIException e) { + throw new CloudRuntimeException("Unable to determine who is the master", e); + } catch (XmlRpcException e) { + throw new CloudRuntimeException("Unable to determine who is the master", e); + } + return cmds; + } + + protected void waitForTask2(Connection c, Task task, long pollInterval, long timeout) throws XenAPIException, XmlRpcException, TimeoutException { + long beginTime = System.currentTimeMillis(); + if (s_logger.isTraceEnabled()) { + s_logger.trace("Task " + task.getNameLabel(c) + " (" + task.getType(c) + ") sent to " + c.getSessionReference() + " is pending completion with a " + timeout + + "ms timeout"); + } + Set classes = new HashSet(); + classes.add("Task/" + task.toString()); + String token = ""; + Double t = new Double(timeout / 1000); + while (true) { + EventBatch map = Event.from(c, classes, token, t); + token = map.token; + @SuppressWarnings("unchecked") + Set events = map.events; + if (events.size() == 0) { + String msg = "Async " + timeout / 1000 + " seconds timeout for task " + task.toString(); + s_logger.warn(msg); + task.cancel(c); + throw new TimeoutException(msg); + } + for (Event.Record rec : events) { + if (!(rec.snapshot instanceof Task.Record)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Skipping over " + rec); + } + continue; + } + + Task.Record taskRecord = (Task.Record)rec.snapshot; + + if (taskRecord.status != Types.TaskStatusType.PENDING) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Task is done " + taskRecord.status); + } + return; + } else { + s_logger.debug("Task is not done " + taskRecord); + } + } + } + } + + @Override + protected Answer execute(final ClusterSyncCommand cmd) { + if (!_listener.isListening()) { + return new Answer(cmd); + } + + HashMap> newStates = _listener.getChanges(); + return new ClusterSyncAnswer(cmd.getClusterId(), newStates); + } + + protected class VmEventListener extends Thread { + boolean _stop = false; + HashMap> _changes = new HashMap>(); + boolean _isMaster; + Set _classes; + String _token = ""; + + public VmEventListener(boolean isMaster) { + _isMaster = isMaster; + _classes = new HashSet(); + _classes.add("VM"); + } + + @Override + public void run() { + setName("XS-Listener-" + _host.ip); + while (!_stop) { + try { + Connection conn = getConnection(); + EventBatch results; + try { + results = Event.from(conn, _classes, _token, new Double(30)); + } catch (Exception e) { + s_logger.error("Retrying the waiting on VM events due to: ", e); + continue; + } + + _token = results.token; + @SuppressWarnings("unchecked") + Set events = results.events; + for (Event.Record event : events) { + try { + if (!(event.snapshot instanceof VM.Record)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("The snapshot is not a VM: " + event); + } + continue; + } + VM.Record vm = (VM.Record)event.snapshot; + + String hostUuid = null; + if (vm.residentOn != null && !vm.residentOn.toWireString().contains("OpaqueRef:NULL")) { + hostUuid = vm.residentOn.getUuid(conn); + } + recordChanges(conn, vm, hostUuid); + } catch (Exception e) { + s_logger.error("Skipping over " + event, e); + } + } + } catch (Throwable th) { + s_logger.error("Exception caught in eventlistener thread: ", th); + } + } + } + + protected void recordChanges(Connection conn, VM.Record rec, String hostUuid) { + String vm = rec.nameLabel; + if (!VirtualMachineName.isValidCloudStackVmName(vm, _instance)) { + s_logger.debug("Skipping over VMs that does not conform to CloudStack naming convention: " + vm); + return; + } + + VirtualMachine.State currentState = convertToState(rec.powerState); + if (vm.startsWith("migrating")) { + s_logger.warn("Skipping " + vm + " because it is migrating."); + return; + } + + if (currentState == VirtualMachine.State.Stopped) { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Double check the power state to make sure we got the correct state for " + vm); + } + currentState = getRealPowerState(conn, vm); + } + + boolean updateMap = false; + boolean reportChange = false; + + // NOTE: For now we only record change when the VM is stopped. We don't find out any VMs starting for now. + synchronized (_cluster.intern()) { + Pair oldState = s_vms.get(_cluster, vm); + if (oldState == null) { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Unable to find " + vm + " from previous map. Assuming it was in Stopped state."); + } + oldState = new Pair(null, VirtualMachine.State.Stopped); + } + + if (s_logger.isTraceEnabled()) { + s_logger.trace(vm + ": current state=" + currentState + ", previous state=" + oldState); + } + + if (oldState.second() == VirtualMachine.State.Starting) { + if (currentState == VirtualMachine.State.Running) { + updateMap = true; + reportChange = false; + } else if (currentState == VirtualMachine.State.Stopped) { + updateMap = false; + reportChange = false; + } + } else if (oldState.second() == VirtualMachine.State.Migrating) { + updateMap = true; + reportChange = false; + } else if (oldState.second() == VirtualMachine.State.Stopping) { + if (currentState == VirtualMachine.State.Stopped) { + updateMap = true; + reportChange = false; + } else if (currentState == VirtualMachine.State.Running) { + updateMap = false; + reportChange = false; + } + } else if (oldState.second() != currentState) { + updateMap = true; + reportChange = true; + } else if (hostUuid != null && !hostUuid.equals(oldState.first())) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Detecting " + vm + " moved from " + oldState.first() + " to " + hostUuid); + } + reportChange = true; + updateMap = true; + } + + if (updateMap) { + s_vms.put(_cluster, hostUuid, vm, currentState); + if (s_logger.isTraceEnabled()) { + s_logger.trace("Updated " + vm + " to [" + hostUuid + ", " + currentState); + } + } + if (reportChange) { + Pair change = _changes.get(vm); + if (hostUuid == null) { + // This is really strange code. It looks like the sync + // code wants this to be set, which is extremely weird + // for VMs that are dead. Why would I want to set the + // hostUuid if the VM is stopped. + hostUuid = oldState.first(); + if (hostUuid == null) { + hostUuid = _host.uuid; + } + } + if (change == null) { + change = new Pair(hostUuid, currentState); + } else { + change.first(hostUuid); + change.second(currentState); + } + _changes.put(vm, change); + } + } + } + + @Override + public void start() { + if (_isMaster) { + // Throw away the initial set of events because they're history + Connection conn = getConnection(); + EventBatch results; + try { + results = Event.from(conn, _classes, _token, new Double(30)); + } catch (Exception e) { + s_logger.error("Retrying the waiting on VM events due to: ", e); + throw new CloudRuntimeException("Unable to start a listener thread to listen to VM events", e); + } + _token = results.token; + s_logger.debug("Starting the event listener thread for " + _host.uuid); + super.start(); + } + } + + public boolean isListening() { + return _isMaster; + } + + public HashMap> getChanges() { + synchronized (_cluster.intern()) { + if (_changes.size() == 0) { + return null; + } + HashMap> diff = _changes; + _changes = new HashMap>(); + return diff; + } + } + + public void signalStop() { + _stop = true; + interrupt(); + } + } + +} diff --git a/plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenserverConfigs.java b/plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenserverConfigs.java new file mode 100644 index 00000000000..bec47401895 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/org/apache/cloudstack/hypervisor/xenserver/XenserverConfigs.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with 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. + */ +package org.apache.cloudstack.hypervisor.xenserver; + +public final class XenserverConfigs { + public static final String XS620HotFix = "xs620hotfix"; + public static final String XSHotFix62ESP1 = "0850b186-4d47-11e3-a720-001b2151a503"; + public static final String XSHotFix62ESP1004 = "996dd2e7-ad95-49cc-a0be-2c9adc4dfb0b"; +} diff --git a/plugins/hypervisors/xenserver/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java b/plugins/hypervisors/xenserver/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java new file mode 100644 index 00000000000..975deec531f --- /dev/null +++ b/plugins/hypervisors/xenserver/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java @@ -0,0 +1,249 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with 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. + */ +package org.apache.cloudstack.storage.motion; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.to.VolumeObjectTO; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.MigrateWithStorageAnswer; +import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.MigrateWithStorageCompleteAnswer; +import com.cloud.agent.api.MigrateWithStorageCompleteCommand; +import com.cloud.agent.api.MigrateWithStorageReceiveAnswer; +import com.cloud.agent.api.MigrateWithStorageReceiveCommand; +import com.cloud.agent.api.MigrateWithStorageSendAnswer; +import com.cloud.agent.api.MigrateWithStorageSendCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.Host; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.StoragePool; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.dao.VMInstanceDao; + +@Component +public class XenServerStorageMotionStrategy implements DataMotionStrategy { + private static final Logger s_logger = Logger.getLogger(XenServerStorageMotionStrategy.class); + @Inject + AgentManager agentMgr; + @Inject + VolumeDao volDao; + @Inject + VolumeDataFactory volFactory; + @Inject + PrimaryDataStoreDao storagePoolDao; + @Inject + VMInstanceDao instanceDao; + + @Override + public StrategyPriority canHandle(DataObject srcData, DataObject destData) { + return StrategyPriority.CANT_HANDLE; + } + + @Override + public StrategyPriority canHandle(Map volumeMap, Host srcHost, Host destHost) { + if (srcHost.getHypervisorType() == HypervisorType.XenServer && destHost.getHypervisorType() == HypervisorType.XenServer) { + return StrategyPriority.HYPERVISOR; + } + + return StrategyPriority.CANT_HANDLE; + } + + @Override + public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback callback) { + throw new UnsupportedOperationException(); + } + + @Override + public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { + CopyCommandResult result = new CopyCommandResult(null, null); + result.setResult("Unsupported operation requested for copying data."); + callback.complete(result); + + return null; + } + + @Override + public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback callback) { + Answer answer = null; + String errMsg = null; + try { + VMInstanceVO instance = instanceDao.findById(vmTo.getId()); + if (instance != null) { + if (srcHost.getClusterId().equals(destHost.getClusterId())) { + answer = migrateVmWithVolumesWithinCluster(instance, vmTo, srcHost, destHost, volumeMap); + } else { + answer = migrateVmWithVolumesAcrossCluster(instance, vmTo, srcHost, destHost, volumeMap); + } + } else { + throw new CloudRuntimeException("Unsupported operation requested for moving data."); + } + } catch (Exception e) { + s_logger.error("copy failed", e); + errMsg = e.toString(); + } + + CopyCommandResult result = new CopyCommandResult(null, answer); + result.setResult(errMsg); + callback.complete(result); + return null; + } + + private Answer migrateVmWithVolumesAcrossCluster(VMInstanceVO vm, VirtualMachineTO to, Host srcHost, Host destHost, Map volumeToPool) + throws AgentUnavailableException { + + // Initiate migration of a virtual machine with it's volumes. + try { + Map volumeToFilerto = new HashMap(); + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeInfo volume = entry.getKey(); + VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId())); + StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue()); + volumeToFilerto.put(volumeTo, filerTo); + } + + // Migration across cluster needs to be done in three phases. + // 1. Send a migrate receive command to the destination host so that it is ready to receive a vm. + // 2. Send a migrate send command to the source host. This actually migrates the vm to the destination. + // 3. Complete the process. Update the volume details. + MigrateWithStorageReceiveCommand receiveCmd = new MigrateWithStorageReceiveCommand(to, volumeToFilerto); + MigrateWithStorageReceiveAnswer receiveAnswer = (MigrateWithStorageReceiveAnswer)agentMgr.send(destHost.getId(), receiveCmd); + if (receiveAnswer == null) { + s_logger.error("Migration with storage of vm " + vm + " to host " + destHost + " failed."); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost); + } else if (!receiveAnswer.getResult()) { + s_logger.error("Migration with storage of vm " + vm + " failed. Details: " + receiveAnswer.getDetails()); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + ". " + receiveAnswer.getDetails()); + } + + MigrateWithStorageSendCommand sendCmd = + new MigrateWithStorageSendCommand(to, receiveAnswer.getVolumeToSr(), receiveAnswer.getNicToNetwork(), receiveAnswer.getToken()); + MigrateWithStorageSendAnswer sendAnswer = (MigrateWithStorageSendAnswer)agentMgr.send(srcHost.getId(), sendCmd); + if (sendAnswer == null) { + s_logger.error("Migration with storage of vm " + vm + " to host " + destHost + " failed."); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost); + } else if (!sendAnswer.getResult()) { + s_logger.error("Migration with storage of vm " + vm + " failed. Details: " + sendAnswer.getDetails()); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + ". " + sendAnswer.getDetails()); + } + + MigrateWithStorageCompleteCommand command = new MigrateWithStorageCompleteCommand(to); + MigrateWithStorageCompleteAnswer answer = (MigrateWithStorageCompleteAnswer)agentMgr.send(destHost.getId(), command); + if (answer == null) { + s_logger.error("Migration with storage of vm " + vm + " failed."); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost); + } else if (!answer.getResult()) { + s_logger.error("Migration with storage of vm " + vm + " failed. Details: " + answer.getDetails()); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + ". " + answer.getDetails()); + } else { + // Update the volume details after migration. + updateVolumePathsAfterMigration(volumeToPool, answer.getVolumeTos()); + } + + return answer; + } catch (OperationTimedoutException e) { + s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e); + throw new AgentUnavailableException("Operation timed out on storage motion for " + vm, destHost.getId()); + } + } + + private Answer migrateVmWithVolumesWithinCluster(VMInstanceVO vm, VirtualMachineTO to, Host srcHost, Host destHost, Map volumeToPool) + throws AgentUnavailableException { + + // Initiate migration of a virtual machine with it's volumes. + try { + Map volumeToFilerto = new HashMap(); + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeInfo volume = entry.getKey(); + VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId())); + StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue()); + volumeToFilerto.put(volumeTo, filerTo); + } + + MigrateWithStorageCommand command = new MigrateWithStorageCommand(to, volumeToFilerto); + MigrateWithStorageAnswer answer = (MigrateWithStorageAnswer)agentMgr.send(destHost.getId(), command); + if (answer == null) { + s_logger.error("Migration with storage of vm " + vm + " failed."); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost); + } else if (!answer.getResult()) { + s_logger.error("Migration with storage of vm " + vm + " failed. Details: " + answer.getDetails()); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + ". " + answer.getDetails()); + } else { + // Update the volume details after migration. + updateVolumePathsAfterMigration(volumeToPool, answer.getVolumeTos()); + } + + return answer; + } catch (OperationTimedoutException e) { + s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e); + throw new AgentUnavailableException("Operation timed out on storage motion for " + vm, destHost.getId()); + } + } + + private void updateVolumePathsAfterMigration(Map volumeToPool, List volumeTos) { + for (Map.Entry entry : volumeToPool.entrySet()) { + boolean updated = false; + VolumeInfo volume = entry.getKey(); + StoragePool pool = (StoragePool)entry.getValue(); + for (VolumeObjectTO volumeTo : volumeTos) { + if (volume.getId() == volumeTo.getId()) { + VolumeVO volumeVO = volDao.findById(volume.getId()); + Long oldPoolId = volumeVO.getPoolId(); + volumeVO.setPath(volumeTo.getPath()); + volumeVO.setFolder(pool.getPath()); + volumeVO.setPodId(pool.getPodId()); + volumeVO.setPoolId(pool.getId()); + volumeVO.setLastPoolId(oldPoolId); + volDao.update(volume.getId(), volumeVO); + updated = true; + break; + } + } + + if (!updated) { + s_logger.error("Volume path wasn't updated for volume " + volume + " after it was migrated."); + } + } + } +} diff --git a/plugins/hypervisors/xenserver/test/com/cloud/ha/XenServerFencerTest.java b/plugins/hypervisors/xenserver/test/com/cloud/ha/XenServerFencerTest.java new file mode 100644 index 00000000000..bd1d8f80b23 --- /dev/null +++ b/plugins/hypervisors/xenserver/test/com/cloud/ha/XenServerFencerTest.java @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with 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. + +package com.cloud.ha; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + + +public class XenServerFencerTest { + + @Test + public void testSetAndGetName() throws Exception { + XenServerFencer xenServerFencer = new XenServerFencer(); + String name = "name"; + + xenServerFencer.setName(name); + String actual = xenServerFencer.getName(); + + assertEquals(name, actual); + + } + +} diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/CitrixResourceBaseTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/CitrixResourceBaseTest.java new file mode 100644 index 00000000000..0c2944c8d8f --- /dev/null +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/CitrixResourceBaseTest.java @@ -0,0 +1,190 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with 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. + */ + +package com.cloud.hypervisor.xenserver.resource; + +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.apache.xmlrpc.XmlRpcException; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.VIF; +import com.xensource.xenapi.VM; +import com.xensource.xenapi.XenAPIObject; + +import com.cloud.agent.api.ScaleVmAnswer; +import com.cloud.agent.api.ScaleVmCommand; +import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase.XsHost; + +public class CitrixResourceBaseTest { + + @Spy + CitrixResourceBase _resource = new CitrixResourceBase() { + + @Override + public ScaleVmAnswer execute(ScaleVmCommand cmd) { + return super.execute(cmd); + } + + @Override + public String callHostPlugin(Connection conn, String plugin, String cmd, String... params) { + return "Success"; + } + + @Override + protected void scaleVM(Connection conn, VM vm, VirtualMachineTO vmSpec, Host host) throws Types.XenAPIException, XmlRpcException { + _host.speed = 500; + super.scaleVM(conn, vm, vmSpec, host); + } + + @Override + protected boolean isDmcEnabled(Connection conn, Host host) throws Types.XenAPIException, XmlRpcException { + return true; + } + }; + @Mock + XsHost _host; + @Mock + Host host; + @Mock + ScaleVmCommand cmd; + @Mock + VirtualMachineTO vmSpec; + @Mock + Connection conn; + @Mock + VM vm; + + @Before + public void setup() { + + MockitoAnnotations.initMocks(this); + + doReturn(vmSpec).when(cmd).getVirtualMachine(); + doReturn("i-2-3-VM").when(vmSpec).getName(); + + } + + // Expecting XmlRpcException while trying to get the record of vm using connection + @Test(expected = XmlRpcException.class) + public void testScaleVMF1() throws Types.BadServerResponse, Types.XenAPIException, XmlRpcException { + doReturn(conn).when(_resource).getConnection(); + Set vms = mock(Set.class); + + Iterator iter = mock(Iterator.class); + doReturn(iter).when(vms).iterator(); + when(iter.hasNext()).thenReturn(true).thenReturn(false); + doReturn(vm).when(iter).next(); + VM.Record vmr = mock(VM.Record.class); + when(vm.getRecord(conn)).thenThrow(new XmlRpcException("XmlRpcException")); + when(vm.getRecord(conn)).thenReturn(vmr); + vmr.powerState = Types.VmPowerState.RUNNING; + vmr.residentOn = mock(Host.class); + XenAPIObject object = mock(XenAPIObject.class); + doReturn(new String("OpaqueRef:NULL")).when(object).toWireString(); + doNothing().when(_resource).scaleVM(conn, vm, vmSpec, host); + + _resource.execute(cmd); + verify(iter, times(2)).hasNext(); + verify(iter, times(2)).next(); + + } + + // Test to scale vm "i-2-3-VM" cpu-cap disabled + @Test + public void testScaleVMF2() throws Types.XenAPIException, XmlRpcException { + + when(vm.getMemoryStaticMax(conn)).thenReturn(1073741824L); + when(vm.getMemoryStaticMin(conn)).thenReturn(268435456L); + doReturn(536870912L).when(vmSpec).getMinRam(); + doReturn(536870912L).when(vmSpec).getMaxRam(); + doNothing().when(vm).setMemoryDynamicRange(conn, 536870912L, 536870912L); + doReturn(1).when(vmSpec).getCpus(); + doNothing().when(vm).setVCPUsNumberLive(conn, 1L); + doReturn(500).when(vmSpec).getMinSpeed(); + doReturn(false).when(vmSpec).getLimitCpuUse(); + Map args = mock(HashMap.class); + when(host.callPlugin(conn, "vmops", "add_to_VCPUs_params_live", args)).thenReturn("Success"); + doReturn(null).when(_resource).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", "253", "vmname", "i-2-3-VM"); + + _resource.scaleVM(conn, vm, vmSpec, host); + + verify(vmSpec, times(1)).getLimitCpuUse(); + verify(_resource, times(1)).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", "253", "vmname", "i-2-3-VM"); + } + + // Test to scale vm "i-2-3-VM" cpu-cap enabled + @Test + public void testScaleVMF3() throws Types.XenAPIException, XmlRpcException { + + when(vm.getMemoryStaticMax(conn)).thenReturn(1073741824L); + when(vm.getMemoryStaticMin(conn)).thenReturn(268435456L); + doReturn(536870912L).when(vmSpec).getMinRam(); + doReturn(536870912L).when(vmSpec).getMaxRam(); + doNothing().when(vm).setMemoryDynamicRange(conn, 536870912L, 536870912L); + doReturn(1).when(vmSpec).getCpus(); + doNothing().when(vm).setVCPUsNumberLive(conn, 1L); + doReturn(500).when(vmSpec).getMinSpeed(); + doReturn(500).when(vmSpec).getMaxSpeed(); + doReturn(true).when(vmSpec).getLimitCpuUse(); + doReturn(null).when(_resource).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", "99", "vmname", "i-2-3-VM"); + Map args = mock(HashMap.class); + when(host.callPlugin(conn, "vmops", "add_to_VCPUs_params_live", args)).thenReturn("Success"); + doReturn(null).when(_resource).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", "253", "vmname", "i-2-3-VM"); + + _resource.scaleVM(conn, vm, vmSpec, host); + + verify(vmSpec, times(1)).getLimitCpuUse(); + verify(_resource, times(1)).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "weight", "value", "253", "vmname", "i-2-3-VM"); + verify(_resource, times(1)).callHostPlugin(conn, "vmops", "add_to_VCPUs_params_live", "key", "cap", "value", "99", "vmname", "i-2-3-VM"); + } + + + @Test + public void testSetNicDevIdIfCorrectVifIsNotNull() throws Exception { + IpAddressTO ip = mock(IpAddressTO.class); + when(ip.isAdd()).thenReturn(false); + VIF correctVif = null; + try { + _resource.setNicDevIdIfCorrectVifIsNotNull(conn, ip, correctVif); + } catch (NullPointerException e) { + fail("this test is meant to show that null pointer is not thrown"); + } + } +}