mirror of https://github.com/apache/cloudstack.git
Squashed commits
Signed-off-by: Tim Mackey <tmackey@gmail.com> Signed-off-by: Sebastien Goasguen <runseb@gmail.com>
This commit is contained in:
parent
748b575af8
commit
aded30374a
|
|
@ -375,7 +375,7 @@ public class ApiConstants {
|
|||
public static final String SECURITY_GROUP_EANBLED = "securitygroupenabled";
|
||||
public static final String LOCAL_STORAGE_ENABLED = "localstorageenabled";
|
||||
public static final String GUEST_IP_TYPE = "guestiptype";
|
||||
public static final String XEN_NETWORK_LABEL = "xennetworklabel";
|
||||
public static final String XENSERVER_NETWORK_LABEL = "xenservernetworklabel";
|
||||
public static final String KVM_NETWORK_LABEL = "kvmnetworklabel";
|
||||
public static final String VMWARE_NETWORK_LABEL = "vmwarenetworklabel";
|
||||
public static final String HYPERV_NETWORK_LABEL = "hypervnetworklabel";
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public class AddTrafficTypeCmd extends BaseAsyncCreateCmd {
|
|||
@Parameter(name = ApiConstants.TRAFFIC_TYPE, type = CommandType.STRING, required = true, description = "the trafficType to be added to the physical network")
|
||||
private String trafficType;
|
||||
|
||||
@Parameter(name = ApiConstants.XEN_NETWORK_LABEL,
|
||||
@Parameter(name = ApiConstants.XENSERVER_NETWORK_LABEL,
|
||||
type = CommandType.STRING,
|
||||
description = "The network name label of the physical device dedicated to this traffic on a XenServer host")
|
||||
private String xenLabel;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public class UpdateTrafficTypeCmd extends BaseAsyncCmd {
|
|||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = TrafficTypeResponse.class, required = true, description = "traffic type id")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.XEN_NETWORK_LABEL,
|
||||
@Parameter(name = ApiConstants.XENSERVER_NETWORK_LABEL,
|
||||
type = CommandType.STRING,
|
||||
description = "The network name label of the physical device dedicated to this traffic on a XenServer host")
|
||||
private String xenLabel;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public class TrafficTypeResponse extends BaseResponse {
|
|||
@Param(description = "the physical network this belongs to")
|
||||
private String physicalNetworkId;
|
||||
|
||||
@SerializedName(ApiConstants.XEN_NETWORK_LABEL)
|
||||
@SerializedName(ApiConstants.XENSERVER_NETWORK_LABEL)
|
||||
@Param(description = "The network name label of the physical device dedicated to this traffic on a XenServer host")
|
||||
private String xenNetworkLabel;
|
||||
|
||||
|
|
|
|||
|
|
@ -2007,9 +2007,9 @@ public class EC2Engine extends ManagerBase {
|
|||
ec2Image.setState(temp.getIsReady() ? "available" : "pending");
|
||||
ec2Image.setDomainId(temp.getDomainId());
|
||||
if (temp.getHyperVisor().equalsIgnoreCase("xenserver"))
|
||||
ec2Image.setHypervisor("xen");
|
||||
ec2Image.setHypervisor("xenserver");
|
||||
else if (temp.getHyperVisor().equalsIgnoreCase("ovm"))
|
||||
ec2Image.setHypervisor("ovm"); // valid values for hypervisor is 'ovm' and 'xen'
|
||||
ec2Image.setHypervisor("ovm"); // valid values for hypervisor is 'ovm' and 'xenserver'
|
||||
else
|
||||
ec2Image.setHypervisor("");
|
||||
if (temp.getDisplayText() == null)
|
||||
|
|
@ -2614,7 +2614,7 @@ public class EC2Engine extends ManagerBase {
|
|||
*/
|
||||
private String mapToAmazonHypervisorType(String hypervisor) {
|
||||
if (hypervisor.equalsIgnoreCase("Xenserver"))
|
||||
return ("xen");
|
||||
return ("xenserver");
|
||||
else if (hypervisor.equalsIgnoreCase("Ovm"))
|
||||
return ("ovm");
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1256,7 +1256,7 @@ label.weekly=Weekly
|
|||
label.welcome.cloud.console=Welcome to Management Console
|
||||
label.welcome=Welcome
|
||||
label.what.is.cloudstack=What is CloudStack&\#8482?
|
||||
label.xen.traffic.label=XenServer traffic label
|
||||
label.xenserver.traffic.label=XenServer traffic label
|
||||
label.yes=Yes
|
||||
label.zone.details=Zone details
|
||||
label.zone.id=Zone ID
|
||||
|
|
|
|||
|
|
@ -1178,7 +1178,7 @@ label.weekly=Hebdomadaire
|
|||
label.welcome=Bienvenue
|
||||
label.welcome.cloud.console=Bienvenue dans la Console d\\'Administration
|
||||
label.what.is.cloudstack=Qu\\'est-ce-que CloudStack&\#8482; ?
|
||||
label.xen.traffic.label=Libell\u00e9 pour le trafic XenServer
|
||||
label.xenserver.traffic.label=Libell\u00e9 pour le trafic XenServer
|
||||
label.yes=Oui
|
||||
label.zone.details=D\u00e9tails de la zone
|
||||
label.zone.id=ID de la zone
|
||||
|
|
|
|||
|
|
@ -618,7 +618,7 @@ label.vsmctrlvlanid=VLAN ID di Controllo
|
|||
label.vsmpktvlanid=VLAN ID del Pacchetto
|
||||
label.vsmstoragevlanid=VLAN ID di Storage
|
||||
label.what.is.cloudstack=Che cosa \u00e8 CloudStack&\#8482?
|
||||
label.xen.traffic.label=Etichetta del traffico via XenServer
|
||||
label.xenserver.traffic.label=Etichetta del traffico via XenServer
|
||||
label.yes=S\u00ec
|
||||
label.zone.details=Dettagli della Zona
|
||||
label.zone.name=Nome Zona
|
||||
|
|
|
|||
|
|
@ -1250,7 +1250,7 @@ label.weekly=\u6bce\u9031
|
|||
label.welcome.cloud.console=\u7ba1\u7406\u30b3\u30f3\u30bd\u30fc\u30eb\u3078\u3088\u3046\u3053\u305d
|
||||
label.welcome=\u3088\u3046\u3053\u305d
|
||||
label.what.is.cloudstack=CloudStack&\#8482; \u306b\u3064\u3044\u3066
|
||||
label.xen.traffic.label=XenServer \u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af \u30e9\u30d9\u30eb
|
||||
label.xenserver.traffic.label=XenServer \u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af \u30e9\u30d9\u30eb
|
||||
label.yes=\u306f\u3044
|
||||
label.zone.details=\u30be\u30fc\u30f3\u306e\u8a73\u7d30
|
||||
label.zone.id=\u30be\u30fc\u30f3 ID
|
||||
|
|
|
|||
|
|
@ -1100,7 +1100,7 @@ label.weekly=\ub9e4\uc8fc
|
|||
label.welcome.cloud.console=\uad00\ub9ac \ucf58\uc194\uc5d0 \uc624\uc2e0\uac83\uc744 \ud658\uc601\ud569\ub2c8\ub2e4\!
|
||||
label.welcome=\uc5b4\uc11c \uc624\uc2ed\uc2dc\uc624
|
||||
label.what.is.cloudstack=CloudStack\u2122 \uc815\ubcf4
|
||||
label.xen.traffic.label=XenServer \ud2b8\ub798\ud53d \ub77c\ubca8
|
||||
label.xenserver.traffic.label=XenServer \ud2b8\ub798\ud53d \ub77c\ubca8
|
||||
label.yes=\uc608
|
||||
label.zone.details=Zone \uc0c1\uc138
|
||||
label.zone.id=Zone ID
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ label.vm.name=VM-navn
|
|||
label.vmware.traffic.label=VMware trafikketikett
|
||||
label.volgroup=Volumgruppe
|
||||
label.what.is.cloudstack=Hva er CloudStack&\#8482?
|
||||
label.xen.traffic.label=XenServer trafikketikett
|
||||
label.xenserver.traffic.label=XenServer trafikketikett
|
||||
label.zone.details=Sonedetaljer
|
||||
label.zone.name=Sonenavn
|
||||
label.zone.type=Sonetype
|
||||
|
|
|
|||
|
|
@ -1143,7 +1143,7 @@ label.weekly=Wekelijks
|
|||
label.welcome.cloud.console=Welkom op de Management Console
|
||||
label.welcome=Welkom
|
||||
label.what.is.cloudstack=Wat is CloudStack&\#8482?
|
||||
label.xen.traffic.label=XenServer verkeerslabel
|
||||
label.xenserver.traffic.label=XenServer verkeerslabel
|
||||
label.yes=Ja
|
||||
label.zone.details=Zone details
|
||||
label.zone.id=Zone ID
|
||||
|
|
|
|||
|
|
@ -1125,7 +1125,7 @@ label.weekly=Semanal
|
|||
label.welcome=Bem-Vindo
|
||||
label.welcome.cloud.console=Painel de Controle
|
||||
label.what.is.cloudstack=O que \u00e9 o CloudStack&\#8482?
|
||||
label.xen.traffic.label=Etiqueta de tr\u00e1fego XenServer
|
||||
label.xenserver.traffic.label=Etiqueta de tr\u00e1fego XenServer
|
||||
label.yes=Sim
|
||||
label.zone.details=Detalhes de zona
|
||||
label.zone.id=ID da Zona
|
||||
|
|
|
|||
|
|
@ -1038,7 +1038,7 @@ label.weekly=\u0415\u0436\u0435\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u043e
|
|||
label.welcome.cloud.console=\u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f
|
||||
label.welcome=\u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c
|
||||
label.what.is.cloudstack=\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 CloudStack?
|
||||
label.xen.traffic.label=\u041c\u0435\u0442\u043a\u0430 \u0442\u0440\u0430\u0444\u0438\u043a\u0430 XenServer
|
||||
label.xenserver.traffic.label=\u041c\u0435\u0442\u043a\u0430 \u0442\u0440\u0430\u0444\u0438\u043a\u0430 XenServer
|
||||
label.yes=\u0414\u0430
|
||||
label.zone.details=\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u043e\u043d\u044b
|
||||
label.zone.id=ID \u0437\u043e\u043d\u044b
|
||||
|
|
|
|||
|
|
@ -1250,7 +1250,7 @@ label.weekly=\u6bcf\u5468
|
|||
label.welcome.cloud.console=\u6b22\u8fce\u4f7f\u7528\u7ba1\u7406\u63a7\u5236\u53f0
|
||||
label.welcome=\u6b22\u8fce
|
||||
label.what.is.cloudstack=\u4ec0\u4e48\u662f CloudStack&\#8482?
|
||||
label.xen.traffic.label=XenServer \u6d41\u91cf\u6807\u7b7e
|
||||
label.xenserver.traffic.label=XenServer \u6d41\u91cf\u6807\u7b7e
|
||||
label.yes=\u662f
|
||||
label.zone.details=\u8d44\u6e90\u57df\u8be6\u7ec6\u4fe1\u606f
|
||||
label.zone.id=\u8d44\u6e90\u57df ID
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-hypervisor-xen</artifactId>
|
||||
<artifactId>cloud-plugin-hypervisor-xenserver</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@
|
|||
<!--
|
||||
Discovers
|
||||
-->
|
||||
<bean id="XcpServerDiscoverer" class="com.cloud.hypervisor.xen.discoverer.XcpServerDiscoverer">
|
||||
<bean id="XcpServerDiscoverer" class="com.cloud.hypervisor.xenserver.discoverer.XcpServerDiscoverer">
|
||||
<property name="name" value="XCP Agent"/>
|
||||
</bean>
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public class PhysicalNetworkTrafficTypeVO implements PhysicalNetworkTrafficType
|
|||
@Enumerated(value = EnumType.STRING)
|
||||
TrafficType trafficType;
|
||||
|
||||
@Column(name = "xen_network_label")
|
||||
@Column(name = "xenserver_network_label")
|
||||
private String xenNetworkLabel;
|
||||
|
||||
@Column(name = "kvm_network_label")
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-hypervisor-xen</artifactId>
|
||||
<artifactId>cloud-plugin-hypervisor-xenserver</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ import com.cloud.host.dao.HostDao;
|
|||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||
import com.cloud.hypervisor.vmware.VmwareServerDiscoverer;
|
||||
import com.cloud.hypervisor.xen.resource.XcpOssResource;
|
||||
import com.cloud.hypervisor.xenserver.resource.XcpOssResource;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
|
|
|||
|
|
@ -85,17 +85,17 @@ public class DirectAgentTest extends CloudStackTestNGBase {
|
|||
|
||||
HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), getHostGateway(), getHostCidr(), 8, "test");
|
||||
pod = podDao.persist(pod);
|
||||
// create xen cluster
|
||||
// create xenserver cluster
|
||||
ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster");
|
||||
cluster.setHypervisorType(HypervisorType.XenServer.toString());
|
||||
cluster.setClusterType(ClusterType.CloudManaged);
|
||||
cluster.setManagedState(ManagedState.Managed);
|
||||
cluster = clusterDao.persist(cluster);
|
||||
clusterId = cluster.getId();
|
||||
// create xen host
|
||||
// create xenserver host
|
||||
|
||||
host = new HostVO(getHostGuid());
|
||||
host.setName("devcloud xen host");
|
||||
host.setName("devcloud xenserver host");
|
||||
host.setType(Host.Type.Routing);
|
||||
host.setHypervisorType(HypervisorType.XenServer);
|
||||
host.setPrivateIpAddress(getHostIp());
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ public class EndpointSelectorTest {
|
|||
HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), "10.223.0.1", "10.233.2.2/25", 8, "test");
|
||||
pod = podDao.persist(pod);
|
||||
podId = pod.getId();
|
||||
// create xen cluster
|
||||
// create xenserver cluster
|
||||
ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster");
|
||||
cluster.setHypervisorType(Hypervisor.HypervisorType.XenServer.toString());
|
||||
cluster.setClusterType(Cluster.ClusterType.CloudManaged);
|
||||
|
|
@ -230,7 +230,7 @@ public class EndpointSelectorTest {
|
|||
public HostVO createHost(Hypervisor.HypervisorType hypervisorType) {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
HostVO host = new HostVO(uuid);
|
||||
host.setName("devcloud xen host");
|
||||
host.setName("devcloud xenserver host");
|
||||
host.setType(Host.Type.Routing);
|
||||
host.setPrivateIpAddress(uuid);
|
||||
host.setDataCenterId(dcId);
|
||||
|
|
|
|||
|
|
@ -191,17 +191,17 @@ public class SnapshotTest extends CloudStackTestNGBase {
|
|||
HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), this.getHostCidr(), 8, "test");
|
||||
pod = podDao.persist(pod);
|
||||
podId = pod.getId();
|
||||
// create xen cluster
|
||||
// create xenserver cluster
|
||||
ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster");
|
||||
cluster.setHypervisorType(this.getHypervisor().toString());
|
||||
cluster.setClusterType(ClusterType.CloudManaged);
|
||||
cluster.setManagedState(ManagedState.Managed);
|
||||
cluster = clusterDao.persist(cluster);
|
||||
clusterId = cluster.getId();
|
||||
// create xen host
|
||||
// create xenserver host
|
||||
|
||||
host = new HostVO(this.getHostGuid());
|
||||
host.setName("devcloud xen host");
|
||||
host.setName("devcloud xenserver host");
|
||||
host.setType(Host.Type.Routing);
|
||||
host.setPrivateIpAddress(this.getHostIp());
|
||||
host.setDataCenterId(dc.getId());
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ public class SnapshotTestWithFakeData {
|
|||
HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), "10.223.0.1", "10.233.2.2/25", 8, "test");
|
||||
pod = podDao.persist(pod);
|
||||
podId = pod.getId();
|
||||
// create xen cluster
|
||||
// create xenserver cluster
|
||||
ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster");
|
||||
cluster.setHypervisorType(Hypervisor.HypervisorType.XenServer.toString());
|
||||
cluster.setClusterType(Cluster.ClusterType.CloudManaged);
|
||||
|
|
|
|||
|
|
@ -148,17 +148,17 @@ public class VolumeServiceTest extends CloudStackTestNGBase {
|
|||
HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), this.getHostCidr(), 8, "test");
|
||||
pod = podDao.persist(pod);
|
||||
podId = pod.getId();
|
||||
// create xen cluster
|
||||
// create xenserver cluster
|
||||
ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster");
|
||||
cluster.setHypervisorType(HypervisorType.XenServer.toString());
|
||||
cluster.setClusterType(ClusterType.CloudManaged);
|
||||
cluster.setManagedState(ManagedState.Managed);
|
||||
cluster = clusterDao.persist(cluster);
|
||||
clusterId = cluster.getId();
|
||||
// create xen host
|
||||
// create xenserver host
|
||||
|
||||
host = new HostVO(this.getHostGuid());
|
||||
host.setName("devcloud xen host");
|
||||
host.setName("devcloud xenserver host");
|
||||
host.setType(Host.Type.Routing);
|
||||
host.setPrivateIpAddress(this.getHostIp());
|
||||
host.setDataCenterId(dc.getId());
|
||||
|
|
|
|||
|
|
@ -167,17 +167,17 @@ public class VolumeTest extends CloudStackTestNGBase {
|
|||
HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), this.getHostCidr(), 8, "test");
|
||||
pod = podDao.persist(pod);
|
||||
podId = pod.getId();
|
||||
// create xen cluster
|
||||
// create xenserver cluster
|
||||
ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster");
|
||||
cluster.setHypervisorType(this.getHypervisor().toString());
|
||||
cluster.setClusterType(ClusterType.CloudManaged);
|
||||
cluster.setManagedState(ManagedState.Managed);
|
||||
cluster = clusterDao.persist(cluster);
|
||||
clusterId = cluster.getId();
|
||||
// create xen host
|
||||
// create xenserver host
|
||||
|
||||
host = new HostVO(this.getHostGuid());
|
||||
host.setName("devcloud xen host");
|
||||
host.setName("devcloud xenserver host");
|
||||
host.setType(Host.Type.Routing);
|
||||
host.setPrivateIpAddress(this.getHostIp());
|
||||
host.setDataCenterId(dc.getId());
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@
|
|||
</bean>
|
||||
|
||||
|
||||
<bean id="XcpServerDiscoverer" class="com.cloud.hypervisor.xen.discoverer.XcpServerDiscoverer">
|
||||
<bean id="XcpServerDiscoverer" class="com.cloud.hypervisor.xenserver.discoverer.XcpServerDiscoverer">
|
||||
<property name="name" value="XCP Agent"/>
|
||||
</bean>
|
||||
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ public class DefaultEndPointSelector implements EndPointSelector {
|
|||
}
|
||||
|
||||
protected EndPoint findEndPointForImageMove(DataStore srcStore, DataStore destStore) {
|
||||
// find any xen/kvm host in the scope
|
||||
// find any xenserver/kvm host in the scope
|
||||
Scope srcScope = srcStore.getScope();
|
||||
Scope destScope = destStore.getScope();
|
||||
Scope selectedScope = null;
|
||||
|
|
|
|||
|
|
@ -70,9 +70,9 @@
|
|||
</display>
|
||||
</interface>
|
||||
<class id="6" corner="BOTTOM_RIGHT" language="java"
|
||||
name="org.apache.cloudstack.storage.datastore.configurator.xen.XenNfsConfigurator"
|
||||
name="org.apache.cloudstack.storage.datastore.configurator.xenserver.XenNfsConfigurator"
|
||||
project="cloud-engine-storage-volume"
|
||||
file="/cloud-engine-storage-volume/src/org/apache/cloudstack/storage/datastore/configurator/xen/XenNfsConfigurator.java"
|
||||
file="/cloud-engine-storage-volume/src/org/apache/cloudstack/storage/datastore/configurator/xenserver/XenNfsConfigurator.java"
|
||||
binary="false">
|
||||
<position height="-1" width="-1" x="1482" y="448"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" visibility="true">
|
||||
|
|
@ -81,9 +81,9 @@
|
|||
</display>
|
||||
</class>
|
||||
<class id="7" corner="BOTTOM_RIGHT" language="java"
|
||||
name="org.apache.cloudstack.storage.datastore.configurator.xen.AbstractXenConfigurator"
|
||||
name="org.apache.cloudstack.storage.datastore.configurator.xenserver.AbstractXenConfigurator"
|
||||
project="cloud-engine-storage-volume"
|
||||
file="/cloud-engine-storage-volume/src/org/apache/cloudstack/storage/datastore/configurator/xen/AbstractXenConfigurator.java"
|
||||
file="/cloud-engine-storage-volume/src/org/apache/cloudstack/storage/datastore/configurator/xenserver/AbstractXenConfigurator.java"
|
||||
binary="false">
|
||||
<position height="-1" width="-1" x="1536" y="278"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" visibility="true">
|
||||
|
|
@ -134,9 +134,9 @@
|
|||
</display>
|
||||
</class>
|
||||
<class id="12" corner="BOTTOM_RIGHT" language="java"
|
||||
name="org.apache.cloudstack.storage.datastore.lifecycle.DefaultXenPrimaryDataStoreLifeCycle"
|
||||
name="org.apache.cloudstack.storage.datastore.lifecycle.DefaultXenServerPrimaryDataStoreLifeCycle"
|
||||
project="cloud-engine-storage-volume"
|
||||
file="/cloud-engine-storage-volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultXenPrimaryDataStoreLifeCycle.java"
|
||||
file="/cloud-engine-storage-volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultXenServerPrimaryDataStoreLifeCycle.java"
|
||||
binary="false">
|
||||
<position height="-1" width="-1" x="724" y="1502"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" visibility="true">
|
||||
|
|
@ -156,9 +156,9 @@
|
|||
</display>
|
||||
</class>
|
||||
<class id="14" corner="BOTTOM_RIGHT" language="java"
|
||||
name="org.apache.cloudstack.storage.datastore.configurator.xen.XenIscsiConfigurator"
|
||||
name="org.apache.cloudstack.storage.datastore.configurator.xenserver.XenServerIscsiConfigurator"
|
||||
project="cloud-engine-storage-volume"
|
||||
file="/cloud-engine-storage-volume/src/org/apache/cloudstack/storage/datastore/configurator/xen/XenIscsiConfigurator.java"
|
||||
file="/cloud-engine-storage-volume/src/org/apache/cloudstack/storage/datastore/configurator/xenserver/XenServerIscsiConfigurator.java"
|
||||
binary="false">
|
||||
<position height="-1" width="-1" x="1817" y="450"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true" visibility="true">
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<FindBugsFilter>
|
||||
|
||||
<!-- Match all XYZ violations. -->
|
||||
<Match>
|
||||
<Class name="CitrixResourceBase" />
|
||||
<Method name="getStatsRawXML" />
|
||||
<Bug pattern="DM_DEFAULT_ENCODING" />
|
||||
</Match>
|
||||
|
||||
</FindBugsFilter>
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<!-- 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. -->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cloud-plugin-hypervisor-xen</artifactId>
|
||||
<name>Apache CloudStack Plugin - Hypervisor Xen</name>
|
||||
<parent>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloudstack-plugins</artifactId>
|
||||
<version>4.5.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-engine-storage</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-network-ovs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.vcc.thirdparty</groupId>
|
||||
<artifactId>xen-api</artifactId>
|
||||
<version>${cs.xapi.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<!-- 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. -->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<bean id="XenServerFencer" class="com.cloud.ha.XenServerFencer">
|
||||
<property name="name" value="XenServerFenceBuilder" />
|
||||
</bean>
|
||||
|
||||
<bean id="XenServerGuru" class="com.cloud.hypervisor.XenServerGuru">
|
||||
<property name="name" value="XenServerGuru" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
<!-- 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. -->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<bean id="XcpServerDiscoverer"
|
||||
class="com.cloud.hypervisor.xen.discoverer.XcpServerDiscoverer">
|
||||
<property name="name" value="XCP Agent" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
// 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<HostVO> 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<String, Object> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
// 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<Command> finalizeExpungeVolumes(VirtualMachine vm) {
|
||||
List<Command> commands = new ArrayList<Command>();
|
||||
|
||||
List<VolumeVO> 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<Boolean, Long> 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, Long>(Boolean.TRUE, new Long(ep.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Pair<Boolean, Long>(Boolean.FALSE, new Long(hostId));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,726 +0,0 @@
|
|||
// 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.xen.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.xen.resource.CitrixResourceBase;
|
||||
import com.cloud.hypervisor.xen.resource.XcpOssResource;
|
||||
import com.cloud.hypervisor.xen.resource.XcpServer16Resource;
|
||||
import com.cloud.hypervisor.xen.resource.XcpServerResource;
|
||||
import com.cloud.hypervisor.xen.resource.XenServer56FP1Resource;
|
||||
import com.cloud.hypervisor.xen.resource.XenServer56Resource;
|
||||
import com.cloud.hypervisor.xen.resource.XenServer56SP2Resource;
|
||||
import com.cloud.hypervisor.xen.resource.XenServer600Resource;
|
||||
import com.cloud.hypervisor.xen.resource.XenServer602Resource;
|
||||
import com.cloud.hypervisor.xen.resource.XenServer610Resource;
|
||||
import com.cloud.hypervisor.xen.resource.XenServer620Resource;
|
||||
import com.cloud.hypervisor.xen.resource.XenServer620SP1Resource;
|
||||
import com.cloud.hypervisor.xen.resource.XenServerConnectionPool;
|
||||
import com.cloud.hypervisor.xen.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<ClusterVO> sc = QueryBuilder.create(ClusterVO.class);
|
||||
sc.and(sc.entity().getGuid(), Op.EQ, guid);
|
||||
List<ClusterVO> clusters = sc.list();
|
||||
ClusterVO clu = clusters.get(0);
|
||||
List<HostVO> 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<Host, Host.Record> hosts = Host.getAllRecords(conn);
|
||||
for (Map.Entry<Host, Host.Record> entry : hosts.entrySet()) {
|
||||
|
||||
Host.Record re = entry.getValue();
|
||||
if (!re.address.equalsIgnoreCase(hostIp)){
|
||||
continue;
|
||||
}
|
||||
Set<HostPatch> 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<? extends ServerResource, Map<String, String>>
|
||||
find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List<String> hostTags) throws DiscoveryException {
|
||||
Map<CitrixResourceBase, Map<String, String>> resources = new HashMap<CitrixResourceBase, Map<String, String>>();
|
||||
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<String> pass = new LinkedList<String>();
|
||||
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<Pool> pools = Pool.getAll(conn);
|
||||
Pool pool = pools.iterator().next();
|
||||
Pool.Record pr = pool.getRecord(conn);
|
||||
String poolUuid = pr.uuid;
|
||||
Map<Host, Host.Record> 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<HostVO> 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<Host, Host.Record> 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<Host, Host.Record> 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("xen");
|
||||
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<String, String> details = new HashMap<String, String>();
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
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<Pool, Pool.Record> 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<CitrixResourceBase, Map<String, String>> resources) throws XenAPIException, XmlRpcException {
|
||||
Map<Pool, Pool.Record> 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<String, String> 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<String, Object> 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("xen.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<HostVO> 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<String, String> 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<String, String> details, List<String> 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<String, Object> buildConfigParams(HostVO host) {
|
||||
HashMap<String, Object> 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();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,195 +0,0 @@
|
|||
// 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.xen.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<File> getPatchFiles() {
|
||||
List<File> files = new ArrayList<File>();
|
||||
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<VDI> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* 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.xen.resource;
|
||||
|
||||
public class XcpServer16Resource extends XcpServerResource {
|
||||
|
||||
public XcpServer16Resource() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getGuestOsType(String stdType, boolean bootFromCD) {
|
||||
return CitrixHelper.getXcp160GuestOsType(stdType);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
// 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.xen.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<File> getPatchFiles() {
|
||||
List<File> files = new ArrayList<File>();
|
||||
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: http://wiki.xen.org/wiki/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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
// 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.xen.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<File> getPatchFiles() {
|
||||
List<File> files = new ArrayList<File>();
|
||||
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<VM> vms = VM.getByNameLabel(conn, cmd.getVmName());
|
||||
for (VM vm : vms) {
|
||||
Set<VDI> vdis = new HashSet<VDI>();
|
||||
Set<VBD> 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<String, String> 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 -
|
||||
* xen 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<String, String> hostParams = new HashMap<String, String>();
|
||||
hostParams = host.getLicenseParams(conn);
|
||||
|
||||
Boolean isDmcEnabled = hostParams.get("restrict_dmc").equalsIgnoreCase("false");
|
||||
|
||||
return isDmcEnabled;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,328 +0,0 @@
|
|||
// 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.xen.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<File> getPatchFiles() {
|
||||
List<File> files = new ArrayList<File>();
|
||||
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<VM> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
// 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.xen.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<File> getPatchFiles() {
|
||||
List<File> files = new ArrayList<File>();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
// 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.xen.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 XenServer56SP2Resource {
|
||||
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<File> getPatchFiles() {
|
||||
List<File> files = new ArrayList<File>();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
// 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.xen.resource;
|
||||
import javax.ejb.Local;
|
||||
import org.apache.log4j.Logger;
|
||||
import com.cloud.resource.ServerResource;
|
||||
|
||||
@Local(value = ServerResource.class)
|
||||
public class XenServer602Resource extends XenServer600Resource {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,434 +0,0 @@
|
|||
// 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.xen.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 XenServer602Resource {
|
||||
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<VolumeObjectTO> getUpdatedVolumePathsOfMigratedVm(Connection connection, VM migratedVm, DiskTO[] volumes) throws CloudRuntimeException {
|
||||
List<VolumeObjectTO> volumeToList = new ArrayList<VolumeObjectTO>();
|
||||
|
||||
try {
|
||||
// Volume paths would have changed. Return that information.
|
||||
Set<VBD> vbds = migratedVm.getVBDs(connection);
|
||||
Map<String, VDI> deviceIdToVdiMap = new HashMap<String, VDI>();
|
||||
// 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<VolumeTO, StorageFilerTO> 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<String, String> other = new HashMap<String, String>();
|
||||
other.put("live", "true");
|
||||
Network networkForSm = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork();
|
||||
Host host = Host.getByUuid(connection, _host.uuid);
|
||||
Map<String, String> token = host.migrateReceive(connection, networkForSm, other);
|
||||
|
||||
// Get the vm to migrate.
|
||||
Set<VM> 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<VIF, Network> vifMap = new HashMap<VIF, Network>();
|
||||
Map<VDI, SR> vdiMap = new HashMap<VDI, SR>();
|
||||
for (Map.Entry<VolumeTO, StorageFilerTO> 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<VolumeObjectTO> 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<VolumeTO, StorageFilerTO> volumeToFiler = cmd.getVolumeToFiler();
|
||||
|
||||
try {
|
||||
// Get a map of all the SRs to which the vdis will be migrated.
|
||||
Map<VolumeTO, Object> volumeToSr = new HashMap<VolumeTO, Object>();
|
||||
for (Map.Entry<VolumeTO, StorageFilerTO> 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<NicTO, Object> nicToNetwork = new HashMap<NicTO, Object>();
|
||||
for (NicTO nicTo : vmSpec.getNics()) {
|
||||
Network network = getNetwork(connection, nicTo);
|
||||
nicToNetwork.put(nicTo, network);
|
||||
}
|
||||
|
||||
Map<String, String> other = new HashMap<String, String>();
|
||||
other.put("live", "true");
|
||||
Network network = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork();
|
||||
Host host = Host.getByUuid(connection, _host.uuid);
|
||||
Map<String, String> 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<VolumeTO, Object> volumeToSr = cmd.getVolumeToSr();
|
||||
Map<NicTO, Object> nicToNetwork = cmd.getNicToNetwork();
|
||||
Map<String, String> token = cmd.getToken();
|
||||
final String vmName = vmSpec.getName();
|
||||
State state = s_vms.getState(_cluster, vmName);
|
||||
Set<VolumeTO> volumeToSet = null;
|
||||
boolean migrated = false;
|
||||
Task task = null;
|
||||
|
||||
synchronized (_cluster.intern()) {
|
||||
s_vms.put(_cluster, _name, vmName, State.Stopping);
|
||||
}
|
||||
|
||||
try {
|
||||
Set<VM> vms = VM.getByNameLabel(connection, vmSpec.getName());
|
||||
VM vmToMigrate = vms.iterator().next();
|
||||
Map<String, String> other = new HashMap<String, String>();
|
||||
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<VDI, SR> vdiMap = new HashMap<VDI, SR>();
|
||||
for (Map.Entry<VolumeTO, Object> 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<VIF, Network> vifMap = new HashMap<VIF, Network>();
|
||||
for (Map.Entry<NicTO, Object> 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<VM> 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<VolumeObjectTO> 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<String, String> other = new HashMap<String, String>();
|
||||
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.
|
||||
}
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
// 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.xen.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<HostPatch> 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<String, String> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
* 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.xen.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.VgpuTypesInfo;
|
||||
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.VGPUType.Record;
|
||||
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<? extends Command> 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<String, HashMap<String, VgpuTypesInfo>> groupDetails = new HashMap<String, HashMap<String, VgpuTypesInfo>>();
|
||||
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<String, HashMap<String, VgpuTypesInfo>> 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<String, HashMap<String, VgpuTypesInfo>> getGPUGroupDetails(Connection conn) throws XenAPIException, XmlRpcException {
|
||||
HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = new HashMap<String, HashMap<String, VgpuTypesInfo>>();
|
||||
Host host = Host.getByUuid(conn, _host.uuid);
|
||||
Set<PGPU> pgpus = host.getPGPUs(conn);
|
||||
Iterator<PGPU> iter = pgpus.iterator();
|
||||
while (iter.hasNext()) {
|
||||
PGPU pgpu = iter.next();
|
||||
GPUGroup gpuGroup = pgpu.getGPUGroup(conn);
|
||||
Set<VGPUType> enabledVGPUTypes = gpuGroup.getEnabledVGPUTypes(conn);
|
||||
String groupName = gpuGroup.getNameLabel(conn);
|
||||
HashMap<String, VgpuTypesInfo> gpuCapacity = new HashMap<String, VgpuTypesInfo>();
|
||||
if (groupDetails.get(groupName) != null) {
|
||||
gpuCapacity = groupDetails.get(groupName);
|
||||
}
|
||||
// Get remaining capacity of all the enabled VGPU in a PGPU
|
||||
if(enabledVGPUTypes != null) {
|
||||
Iterator<VGPUType> it = enabledVGPUTypes.iterator();
|
||||
while (it.hasNext()) {
|
||||
VGPUType type = it.next();
|
||||
Record record = type.getRecord(conn);
|
||||
Long remainingCapacity = pgpu.getRemainingCapacity(conn, type);
|
||||
Long maxCapacity = pgpu.getSupportedVGPUMaxCapacities(conn).get(type);
|
||||
VgpuTypesInfo entry;
|
||||
if ((entry = gpuCapacity.get(record.modelName)) != null) {
|
||||
remainingCapacity += entry.getRemainingCapacity();
|
||||
maxCapacity += entry.getMaxCapacity();
|
||||
entry.setRemainingCapacity(remainingCapacity);
|
||||
entry.setMaxVmCapacity(maxCapacity);
|
||||
gpuCapacity.put(record.modelName, entry);
|
||||
} else {
|
||||
VgpuTypesInfo vgpuTypeRecord = new VgpuTypesInfo(record.modelName, record.framebufferSize, record.maxHeads,
|
||||
record.maxResolutionX, record.maxResolutionY, maxCapacity, remainingCapacity, maxCapacity);
|
||||
gpuCapacity.put(record.modelName, vgpuTypeRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
groupDetails.put(groupName, gpuCapacity);
|
||||
}
|
||||
return groupDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createVGPU(Connection conn, StartCommand cmd, VM vm, GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException {
|
||||
Set<GPUGroup> 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<VGPUType> vgpuTypes = gpuGroup.getEnabledVGPUTypes(conn);
|
||||
Iterator<VGPUType> 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<String, String> other_config = new HashMap<String, String>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,503 +0,0 @@
|
|||
// 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.xen.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<String /* poolUuid */, XenServerConnection> _conns = new HashMap<String, XenServerConnection>();
|
||||
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<String> 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<String> 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<String> 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<String> 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<String> 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<Pool, Pool.Record> 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<String> _password;
|
||||
String _poolUuid;
|
||||
|
||||
public XenServerConnection(URL url, String ip, String username, Queue<String> 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<String> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
// 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.xen.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<String/* clusterId */, HashMap<String/* vm name */, Pair<String/* host uuid */, State/* vm state */>>> _clusterVms =
|
||||
new ConcurrentHashMap<String, HashMap<String, Pair<String, State>>>();
|
||||
|
||||
public HashMap<String, Pair<String, State>> getClusterVmState(String clusterId) {
|
||||
HashMap<String, Pair<String, State>> _vms = _clusterVms.get(clusterId);
|
||||
if (_vms == null) {
|
||||
HashMap<String, Pair<String, State>> vmStates = new HashMap<String, Pair<String, State>>();
|
||||
_clusterVms.put(clusterId, vmStates);
|
||||
return vmStates;
|
||||
} else
|
||||
return _vms;
|
||||
}
|
||||
|
||||
public void clear(String clusterId) {
|
||||
HashMap<String, Pair<String, State>> _vms = getClusterVmState(clusterId);
|
||||
_vms.clear();
|
||||
}
|
||||
|
||||
public State getState(String clusterId, String name) {
|
||||
HashMap<String, Pair<String, State>> vms = getClusterVmState(clusterId);
|
||||
Pair<String, State> 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<String, State> get(String clusterId, String name) {
|
||||
HashMap<String, Pair<String, State>> vms = getClusterVmState(clusterId);
|
||||
return vms.get(name);
|
||||
}
|
||||
|
||||
public void put(String clusterId, String hostUuid, String name, State state) {
|
||||
HashMap<String, Pair<String, State>> vms = getClusterVmState(clusterId);
|
||||
vms.put(name, new Pair<String, State>(hostUuid, state));
|
||||
}
|
||||
|
||||
public void remove(String clusterId, String hostUuid, String name) {
|
||||
HashMap<String, Pair<String, State>> vms = getClusterVmState(clusterId);
|
||||
vms.remove(name);
|
||||
}
|
||||
|
||||
public void putAll(String clusterId, HashMap<String, Pair<String, State>> newVms) {
|
||||
HashMap<String, Pair<String, State>> vms = getClusterVmState(clusterId);
|
||||
vms.putAll(newVms);
|
||||
}
|
||||
|
||||
public int size(String clusterId) {
|
||||
HashMap<String, Pair<String, State>> vms = getClusterVmState(clusterId);
|
||||
return vms.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sbuf = new StringBuilder("PoolVms=");
|
||||
for (HashMap<String/* vm name */, Pair<String/* host uuid */, State/* vm state */>> clusterVM : _clusterVms.values()) {
|
||||
for (String vmname : clusterVM.keySet()) {
|
||||
sbuf.append(vmname).append("-").append(clusterVM.get(vmname).second()).append(",");
|
||||
}
|
||||
}
|
||||
return sbuf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,160 +0,0 @@
|
|||
/*
|
||||
* 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.xen.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<File> getPatchFiles() {
|
||||
List<File> files = new ArrayList<File>();
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,822 +0,0 @@
|
|||
/*
|
||||
* 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.xen.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<String, String> smConfig = new HashMap<String, String>();
|
||||
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<VDI> 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<SR> 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<String, String>());
|
||||
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<String, String> 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<VDI> snapshotChains = new ArrayList<VDI>();
|
||||
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<VDI> snapshotChains = new ArrayList<VDI>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,345 +0,0 @@
|
|||
// 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.xen.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<String> classes = new HashSet<String>();
|
||||
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<Event.Record> 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<String, Pair<String, VirtualMachine.State>> newStates = _listener.getChanges();
|
||||
return new ClusterSyncAnswer(cmd.getClusterId(), newStates);
|
||||
}
|
||||
|
||||
protected class VmEventListener extends Thread {
|
||||
boolean _stop = false;
|
||||
HashMap<String, Pair<String, VirtualMachine.State>> _changes = new HashMap<String, Pair<String, VirtualMachine.State>>();
|
||||
boolean _isMaster;
|
||||
Set<String> _classes;
|
||||
String _token = "";
|
||||
|
||||
public VmEventListener(boolean isMaster) {
|
||||
_isMaster = isMaster;
|
||||
_classes = new HashSet<String>();
|
||||
_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<Event.Record> 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<String, VirtualMachine.State> 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<String, VirtualMachine.State>(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<String, VirtualMachine.State> 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<String, VirtualMachine.State>(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<String, Pair<String, VirtualMachine.State>> getChanges() {
|
||||
synchronized (_cluster.intern()) {
|
||||
if (_changes.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
HashMap<String, Pair<String, VirtualMachine.State>> diff = _changes;
|
||||
_changes = new HashMap<String, Pair<String, VirtualMachine.State>>();
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
|
||||
public void signalStop() {
|
||||
_stop = true;
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* 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";
|
||||
}
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
/*
|
||||
* 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<VolumeInfo, DataStore> 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<CopyCommandResult> callback) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> 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<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, AsyncCompletionCallback<CopyCommandResult> 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<VolumeInfo, DataStore> volumeToPool)
|
||||
throws AgentUnavailableException {
|
||||
|
||||
// Initiate migration of a virtual machine with it's volumes.
|
||||
try {
|
||||
Map<VolumeTO, StorageFilerTO> volumeToFilerto = new HashMap<VolumeTO, StorageFilerTO>();
|
||||
for (Map.Entry<VolumeInfo, DataStore> 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<VolumeInfo, DataStore> volumeToPool)
|
||||
throws AgentUnavailableException {
|
||||
|
||||
// Initiate migration of a virtual machine with it's volumes.
|
||||
try {
|
||||
Map<VolumeTO, StorageFilerTO> volumeToFilerto = new HashMap<VolumeTO, StorageFilerTO>();
|
||||
for (Map.Entry<VolumeInfo, DataStore> 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<VolumeInfo, DataStore> volumeToPool, List<VolumeObjectTO> volumeTos) {
|
||||
for (Map.Entry<VolumeInfo, DataStore> 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// 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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
* 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.xen.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.xen.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<VM> 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<String, String> 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<String, String> 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -291,7 +291,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
|
|||
if (prodVersion == null) {
|
||||
prodVersion = record.softwareVersion.get("platform_version");
|
||||
}
|
||||
String xenVersion = record.softwareVersion.get("xenserver");
|
||||
String xenVersion = record.softwareVersion.get("xen");
|
||||
String hostOS = record.softwareVersion.get("product_brand");
|
||||
if (hostOS == null) {
|
||||
hostOS = record.softwareVersion.get("platform_name");
|
||||
|
|
@ -347,12 +347,12 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
|
|||
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.XenServerMaxNics.toString().toLowerCase(), _configDao.getValue(Config.XenServerMaxNics.toString()));
|
||||
params.put(Config.XenServerHeartBeatInterval.toString().toLowerCase(), _configDao.getValue(Config.XenServerHeartBeatInterval.toString()));
|
||||
params.put(Config.InstanceName.toString().toLowerCase(), _instance);
|
||||
details.put(Config.InstanceName.toString().toLowerCase(), _instance);
|
||||
try {
|
||||
resource.configure("Xen Server", params);
|
||||
resource.configure("XenServer", 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);
|
||||
|
|
@ -455,7 +455,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
|
|||
}
|
||||
|
||||
protected void serverConfig() {
|
||||
String value = _params.get(Config.XenSetupMultipath.key());
|
||||
String value = _params.get(Config.XenServerSetupMultipath.key());
|
||||
_setupMultipath = Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
|
|
@ -464,20 +464,20 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
|
|||
super.configure(name, params);
|
||||
serverConfig();
|
||||
|
||||
_publicNic = _params.get(Config.XenPublicNetwork.key());
|
||||
_privateNic = _params.get(Config.XenPrivateNetwork.key());
|
||||
_publicNic = _params.get(Config.XenServerPublicNetwork.key());
|
||||
_privateNic = _params.get(Config.XenServerPrivateNetwork.key());
|
||||
|
||||
_storageNic1 = _params.get(Config.XenStorageNetwork1.key());
|
||||
_storageNic2 = _params.get(Config.XenStorageNetwork2.key());
|
||||
_storageNic1 = _params.get(Config.XenServerStorageNetwork1.key());
|
||||
_storageNic2 = _params.get(Config.XenServerStorageNetwork2.key());
|
||||
|
||||
_guestNic = _params.get(Config.XenGuestNetwork.key());
|
||||
_guestNic = _params.get(Config.XenServerGuestNetwork.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());
|
||||
value = _params.get(Config.XenServerSetupMultipath.key());
|
||||
Boolean.parseBoolean(value);
|
||||
|
||||
value = _params.get("xenserver.check.hvm");
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ 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.VgpuTypesInfo;
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
import com.cloud.agent.api.check.CheckSshAnswer;
|
||||
import com.cloud.agent.api.check.CheckSshCommand;
|
||||
|
|
@ -170,6 +171,7 @@ 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.utils.ssh.SshHelper;
|
||||
import com.cloud.vm.DiskProfile;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.PowerState;
|
||||
|
|
@ -290,10 +292,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
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
|
||||
long _xsMemoryUsed = 128 * 1024 * 1024L; // xenserver hypervisor used 128 M
|
||||
double _xsVirtualizationFactor = 63.0 / 64.0; // 1 - virtualization overhead
|
||||
|
||||
//static min values for guests on xen
|
||||
//static min values for guests on xenserver
|
||||
private static final long mem_128m = 134217728L;
|
||||
|
||||
protected boolean _canBridgeFirewall = false;
|
||||
|
|
@ -558,10 +560,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
|
||||
@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));
|
||||
Pair<Boolean, String> result;
|
||||
try {
|
||||
result = SshHelper.sshExecute(_host.ip, 22, _username, null, _password.peek(), "/opt/cloud/bin/router_proxy.sh " + script + " " + routerIP + " " + args,
|
||||
60000, 60000, timeout * 1000);
|
||||
} catch (Exception e) {
|
||||
return new ExecutionResult(false, e.getMessage());
|
||||
}
|
||||
return new ExecutionResult(result.first(), result.second());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -913,6 +919,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
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();
|
||||
|
|
@ -930,14 +937,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
|
||||
vifr.lockingMode = Types.VifLockingMode.NETWORK_DEFAULT;
|
||||
dom0vif = VIF.create(conn, vifr);
|
||||
synchronized (_tmpDom0Vif) {
|
||||
_tmpDom0Vif.add(dom0vif);
|
||||
}
|
||||
}
|
||||
// At this stage we surely have a VIF
|
||||
dom0vif.plug(conn);
|
||||
dom0vif.unplug(conn);
|
||||
synchronized (_tmpDom0Vif) {
|
||||
_tmpDom0Vif.add(dom0vif);
|
||||
try {
|
||||
dom0vif.plug(conn);
|
||||
} catch (Exception e) {
|
||||
// though an exception is thrown here, VIF actually gets plugged-in to dom0, so just ignore the exception
|
||||
}
|
||||
|
||||
dom0vif.unplug(conn);
|
||||
}
|
||||
|
||||
private synchronized Network setupvSwitchNetwork(Connection conn) {
|
||||
|
|
@ -989,12 +999,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
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);
|
||||
enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + nwName);
|
||||
s_logger.debug("### XenServer network for tunnels created:" + nwName);
|
||||
} else {
|
||||
nw = networks.iterator().next();
|
||||
s_logger.debug("Xen Server network for tunnels found:" + nwName);
|
||||
enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + nwName);
|
||||
s_logger.debug("XenServer network for tunnels found:" + nwName);
|
||||
}
|
||||
return nw;
|
||||
} catch (Exception e) {
|
||||
|
|
@ -1026,8 +1036,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
}
|
||||
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);
|
||||
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,
|
||||
|
|
@ -1332,7 +1341,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
return dynamicMinRam;
|
||||
}
|
||||
|
||||
protected HashMap<String, HashMap<String, Long>> getGPUGroupDetails(Connection conn) throws XenAPIException, XmlRpcException {
|
||||
protected HashMap<String, HashMap<String, VgpuTypesInfo>> getGPUGroupDetails(Connection conn) throws XenAPIException, XmlRpcException {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -1488,8 +1497,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
vm.setPlatform(conn, platform);
|
||||
}
|
||||
}
|
||||
String xentoolsversion = details.get("hypervisortoolsversion");
|
||||
if (xentoolsversion == null || !xentoolsversion.equalsIgnoreCase("xenserver61")) {
|
||||
String xenservertoolsversion = details.get("hypervisortoolsversion");
|
||||
if (xenservertoolsversion == null || !xenservertoolsversion.equalsIgnoreCase("xenserver61")) {
|
||||
Map<String, String> platform = vm.getPlatform(conn);
|
||||
platform.remove("device_id");
|
||||
vm.setPlatform(conn, platform);
|
||||
|
|
@ -1665,7 +1674,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
return cmd;
|
||||
}
|
||||
|
||||
private void cleanUpTmpDomVif(Connection conn) {
|
||||
private void cleanUpTmpDomVif(Connection conn, Network nw) {
|
||||
List<VIF> vifs;
|
||||
synchronized (_tmpDom0Vif) {
|
||||
vifs = _tmpDom0Vif;
|
||||
|
|
@ -1673,13 +1682,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
}
|
||||
|
||||
for (VIF v : vifs) {
|
||||
String vifName = "unkown";
|
||||
String vifName = "unknown";
|
||||
try {
|
||||
VIF.Record vifr = v.getRecord(conn);
|
||||
Map<String, String> config = vifr.otherConfig;
|
||||
vifName = config.get("nameLabel");
|
||||
v.destroy(conn);
|
||||
s_logger.debug("Destroy temp dom0 vif" + vifName + " success");
|
||||
if (v.getNetwork(conn).getUuid(conn).equals(nw.getUuid(conn))) {
|
||||
Map<String, String> config = vifr.otherConfig;
|
||||
vifName = config.get("nameLabel");
|
||||
s_logger.debug("A VIF in dom0 for the network is found - so destroy the vif");
|
||||
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);
|
||||
}
|
||||
|
|
@ -1817,7 +1829,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
}
|
||||
}
|
||||
}
|
||||
cleanUpTmpDomVif(conn);
|
||||
|
||||
if (_canBridgeFirewall) {
|
||||
String result = null;
|
||||
|
|
@ -3617,6 +3628,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
return new StopAnswer(cmd, msg, platformstring, false);
|
||||
}
|
||||
|
||||
if (cmd.checkBeforeCleanup() && vmr.powerState == VmPowerState.RUNNING) {
|
||||
String msg = "Vm " + vmName + " is running on host and checkBeforeCleanup flag is set, so bailing out";
|
||||
s_logger.debug(msg);
|
||||
return new StopAnswer(cmd, msg, false);
|
||||
}
|
||||
|
||||
State state = s_vms.getState(_cluster, vmName);
|
||||
|
||||
synchronized (_cluster.intern()) {
|
||||
|
|
@ -3655,7 +3672,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
s_logger.debug("VM " + vmName + " does not have GPU support.");
|
||||
}
|
||||
if (vGPUs != null && !vGPUs.isEmpty()) {
|
||||
HashMap<String, HashMap<String, Long>> groupDetails = getGPUGroupDetails(conn);
|
||||
HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = getGPUGroupDetails(conn);
|
||||
cmd.setGpuDevice(new GPUDeviceTO(null, null, groupDetails));
|
||||
}
|
||||
|
||||
|
|
@ -3937,6 +3954,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
while (vifIter.hasNext()) {
|
||||
VIF vif = vifIter.next();
|
||||
try {
|
||||
String deviceId = vif.getDevice(conn);
|
||||
if(vm.getIsControlDomain(conn) || vif.getCurrentlyAttached(conn)) {
|
||||
usedDeviceNums.add(Integer.valueOf(deviceId));
|
||||
} else {
|
||||
s_logger.debug("Found unplugged VIF " + deviceId + " in VM " + vmName + " destroy it");
|
||||
vif.destroy(conn);
|
||||
}
|
||||
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;
|
||||
|
|
@ -4886,11 +4910,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
host.setTags(conn, hr.tags);
|
||||
return true;
|
||||
} catch (XenAPIException e) {
|
||||
String msg = "Xen setup failed due to " + e.toString();
|
||||
String msg = "XenServer 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();
|
||||
String msg = "XenServer setup failed due to " + e.getMessage();
|
||||
s_logger.warn(msg, e);
|
||||
throw new CloudRuntimeException("Unable to get host information ", e);
|
||||
}
|
||||
|
|
@ -5245,6 +5269,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||
|
||||
private Answer execute(OvsDestroyBridgeCommand cmd) {
|
||||
Connection conn = getConnection();
|
||||
Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName());
|
||||
cleanUpTmpDomVif(conn, nw);
|
||||
destroyTunnelNetwork(conn, cmd.getBridgeName());
|
||||
s_logger.debug("OVS Bridge destroyed");
|
||||
return new Answer(cmd, true, null);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
|||
import com.cloud.utils.script.Script;
|
||||
|
||||
@Local(value = ServerResource.class)
|
||||
public class XenServer600Resource extends XenServer56FP1Resource {
|
||||
public class XenServer600Resource extends XenServer56SP2Resource {
|
||||
private static final Logger s_logger = Logger.getLogger(XenServer600Resource.class);
|
||||
|
||||
public XenServer600Resource() {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import org.apache.log4j.Logger;
|
|||
import com.cloud.resource.ServerResource;
|
||||
|
||||
@Local(value = ServerResource.class)
|
||||
public class XenServer602Resource extends XenServer56FP1Resource {
|
||||
public class XenServer602Resource extends XenServer600Resource {
|
||||
private static final Logger s_logger = Logger.getLogger(XenServer602Resource.class);
|
||||
|
||||
public XenServer602Resource() {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
|||
import com.cloud.vm.VirtualMachine.State;
|
||||
|
||||
@Local(value = ServerResource.class)
|
||||
public class XenServer610Resource extends XenServer56FP1Resource {
|
||||
public class XenServer610Resource extends XenServer602Resource {
|
||||
private static final Logger s_logger = Logger.getLogger(XenServer610Resource.class);
|
||||
|
||||
public XenServer610Resource() {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ 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.VgpuTypesInfo;
|
||||
import com.cloud.agent.api.to.GPUDeviceTO;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.xensource.xenapi.Connection;
|
||||
|
|
@ -43,6 +44,7 @@ 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.VGPUType.Record;
|
||||
import com.xensource.xenapi.VM;
|
||||
|
||||
@Local(value=ServerResource.class)
|
||||
|
|
@ -65,7 +67,7 @@ public class XenServer620SP1Resource extends XenServer620Resource {
|
|||
|
||||
protected GetGPUStatsAnswer execute(GetGPUStatsCommand cmd) {
|
||||
Connection conn = getConnection();
|
||||
HashMap<String, HashMap<String, Long>> groupDetails = new HashMap<String, HashMap<String, Long>>();
|
||||
HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = new HashMap<String, HashMap<String, VgpuTypesInfo>>();
|
||||
try {
|
||||
groupDetails = getGPUGroupDetails(conn);
|
||||
} catch (Exception e) {
|
||||
|
|
@ -79,7 +81,7 @@ public class XenServer620SP1Resource extends XenServer620Resource {
|
|||
protected void fillHostInfo(Connection conn, StartupRoutingCommand cmd) {
|
||||
super.fillHostInfo(conn, cmd);
|
||||
try {
|
||||
HashMap<String, HashMap<String, Long>> groupDetails = getGPUGroupDetails(conn);
|
||||
HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = getGPUGroupDetails(conn);
|
||||
cmd.setGpuGroupDetails(groupDetails);
|
||||
} catch (Exception e) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
|
|
@ -89,8 +91,8 @@ public class XenServer620SP1Resource extends XenServer620Resource {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected HashMap<String, HashMap<String, Long>> getGPUGroupDetails(Connection conn) throws XenAPIException, XmlRpcException {
|
||||
HashMap<String, HashMap<String, Long>> groupDetails = new HashMap<String, HashMap<String, Long>>();
|
||||
protected HashMap<String, HashMap<String, VgpuTypesInfo>> getGPUGroupDetails(Connection conn) throws XenAPIException, XmlRpcException {
|
||||
HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = new HashMap<String, HashMap<String, VgpuTypesInfo>>();
|
||||
Host host = Host.getByUuid(conn, _host.uuid);
|
||||
Set<PGPU> pgpus = host.getPGPUs(conn);
|
||||
Iterator<PGPU> iter = pgpus.iterator();
|
||||
|
|
@ -99,7 +101,7 @@ public class XenServer620SP1Resource extends XenServer620Resource {
|
|||
GPUGroup gpuGroup = pgpu.getGPUGroup(conn);
|
||||
Set<VGPUType> enabledVGPUTypes = gpuGroup.getEnabledVGPUTypes(conn);
|
||||
String groupName = gpuGroup.getNameLabel(conn);
|
||||
HashMap<String, Long> gpuCapacity = new HashMap<String, Long>();
|
||||
HashMap<String, VgpuTypesInfo> gpuCapacity = new HashMap<String, VgpuTypesInfo>();
|
||||
if (groupDetails.get(groupName) != null) {
|
||||
gpuCapacity = groupDetails.get(groupName);
|
||||
}
|
||||
|
|
@ -108,13 +110,20 @@ public class XenServer620SP1Resource extends XenServer620Resource {
|
|||
Iterator<VGPUType> it = enabledVGPUTypes.iterator();
|
||||
while (it.hasNext()) {
|
||||
VGPUType type = it.next();
|
||||
String modelName = type.getModelName(conn);
|
||||
Record record = type.getRecord(conn);
|
||||
Long remainingCapacity = pgpu.getRemainingCapacity(conn, type);
|
||||
if (gpuCapacity.get(modelName) != null) {
|
||||
long newRemainingCapacity = gpuCapacity.get(modelName) + remainingCapacity;
|
||||
gpuCapacity.put(modelName, newRemainingCapacity);
|
||||
Long maxCapacity = pgpu.getSupportedVGPUMaxCapacities(conn).get(type);
|
||||
VgpuTypesInfo entry;
|
||||
if ((entry = gpuCapacity.get(record.modelName)) != null) {
|
||||
remainingCapacity += entry.getRemainingCapacity();
|
||||
maxCapacity += entry.getMaxCapacity();
|
||||
entry.setRemainingCapacity(remainingCapacity);
|
||||
entry.setMaxVmCapacity(maxCapacity);
|
||||
gpuCapacity.put(record.modelName, entry);
|
||||
} else {
|
||||
gpuCapacity.put(modelName, remainingCapacity);
|
||||
VgpuTypesInfo vgpuTypeRecord = new VgpuTypesInfo(record.modelName, record.framebufferSize, record.maxHeads,
|
||||
record.maxResolutionX, record.maxResolutionY, maxCapacity, remainingCapacity, maxCapacity);
|
||||
gpuCapacity.put(record.modelName, vgpuTypeRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ under the License.
|
|||
<adapter name="KVMGuru" class="com.cloud.hypervisor.KVMGuru"/>
|
||||
</adapters>
|
||||
<adapters key="com.cloud.resource.Discoverer">
|
||||
<adapter name="XCP Agent" class="com.cloud.hypervisor.xen.discoverer.XcpServerDiscoverer"/>
|
||||
<adapter name="XCP Agent" class="com.cloud.hypervisor.xenserver.discoverer.XcpServerDiscoverer"/>
|
||||
<adapter name="SecondaryStorage" class="com.cloud.storage.secondary.SecondaryStorageDiscoverer"/>
|
||||
<adapter name="KVM Agent" class="com.cloud.hypervisor.kvm.discoverer.KvmServerDiscoverer"/>
|
||||
<adapter name="Bare Metal Agent" class="com.cloud.baremetal.BareMetalDiscoverer"/>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-hypervisor-xen</artifactId>
|
||||
<artifactId>cloud-plugin-hypervisor-xenserver</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
<module>host-allocators/random</module>
|
||||
<module>dedicated-resources</module>
|
||||
<module>hypervisors/ovm</module>
|
||||
<module>hypervisors/xen</module>
|
||||
<module>hypervisors/xenserver</module>
|
||||
<module>hypervisors/kvm</module>
|
||||
<module>event-bus/rabbitmq</module>
|
||||
<module>event-bus/inmemory</module>
|
||||
|
|
|
|||
|
|
@ -1144,7 +1144,7 @@
|
|||
<File Id="fil4573D848D63904E25199DFC7C5F3C630" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\scripts\vm\hypervisor\xenserver\perfmon.py" />
|
||||
</Component>
|
||||
<Component Id="cmpD76E671ADB5BD6A4D78727948C10979D" Guid="{EA4A8C61-6B09-4489-ACE6-00B9A0F1A4BC}">
|
||||
<File Id="filD3A7AE13D824593E31FF5468A9B764AB" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\scripts\vm\hypervisor\xenserver\s3xen" />
|
||||
<File Id="filD3A7AE13D824593E31FF5468A9B764AB" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\scripts\vm\hypervisor\xenserver\s3xenserver" />
|
||||
</Component>
|
||||
<Component Id="cmpA5ACE2ABDAD485164B610A43CF7260AC" Guid="{D6BC09D7-775E-4DBE-8E97-603B00B26BC2}">
|
||||
<File Id="filA1C0191B48050912F371A13BC75AD95A" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\scripts\vm\hypervisor\xenserver\setupxenserver.sh" />
|
||||
|
|
@ -1165,7 +1165,7 @@
|
|||
<File Id="fil5C88104CC07D3894D5C6618F2480D894" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\scripts\vm\hypervisor\xenserver\swift" />
|
||||
</Component>
|
||||
<Component Id="cmp29E6175F9E42A05F0ACA5E9DEC427DA9" Guid="{08A3A34A-662E-40F5-AC4C-6224AF8E3204}">
|
||||
<File Id="fil30689D2F97C68DD797DC8681851DC4A0" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\scripts\vm\hypervisor\xenserver\swiftxen" />
|
||||
<File Id="fil30689D2F97C68DD797DC8681851DC4A0" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\scripts\vm\hypervisor\xenserver\swiftxenserver" />
|
||||
</Component>
|
||||
<Component Id="cmp795E37CA1E2B235A5F5500D0CFC92E07" Guid="{4CAFC2DE-B603-485C-B8ED-A6A016962788}">
|
||||
<File Id="filAD37A67E4680F1FFC939AE9759EA6193" KeyPath="yes" Source="!(wix.SourceClient)\WEB-INF\classes\scripts\vm\hypervisor\xenserver\upgrade_snapshot.sh" />
|
||||
|
|
@ -2411,4 +2411,4 @@
|
|||
<ComponentRef Id="cmp776899723BBC0C56DBF1EA389CF3A210" />
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
</Wix>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
rotate 20
|
||||
}
|
||||
|
||||
/var/log/cloud/ovstunnel.log /var/log/cloud/ovs-pvlan.log /var/log/cloud/swiftxen.log /var/log/cloud/s3xen /var/log/cloud/storageplugin {
|
||||
/var/log/cloud/ovstunnel.log /var/log/cloud/ovs-pvlan.log /var/log/cloud/swiftxenserver.log /var/log/cloud/s3xenserver /var/log/cloud/storageplugin {
|
||||
daily
|
||||
size 1M
|
||||
rotate 2
|
||||
|
|
|
|||
|
|
@ -497,7 +497,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
|||
if (allocationAlgorithm != null) {
|
||||
_allocationAlgorithm = allocationAlgorithm;
|
||||
}
|
||||
String value = configs.get("xen.check.hvm");
|
||||
String value = configs.get("xenserver.check.hvm");
|
||||
_checkHvm = value == null ? true : Boolean.parseBoolean(value);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1079,17 +1079,17 @@ public enum Config {
|
|||
OvmGuestNetwork("Hidden", ManagementServer.class, String.class, "ovm.guest.network.device", null, "Specify the private bridge on host for private network", null),
|
||||
|
||||
// XenServer
|
||||
XenPublicNetwork(
|
||||
XenServerPublicNetwork(
|
||||
"Hidden",
|
||||
ManagementServer.class,
|
||||
String.class,
|
||||
"xen.public.network.device",
|
||||
"xenserver.public.network.device",
|
||||
null,
|
||||
"[ONLY IF THE PUBLIC NETWORK IS ON A DEDICATED NIC]:The network name label of the physical device dedicated to the public network on a XenServer host",
|
||||
null),
|
||||
XenStorageNetwork1("Hidden", ManagementServer.class, String.class, "xen.storage.network.device1", null, "Specify when there are storage networks", null),
|
||||
XenStorageNetwork2("Hidden", ManagementServer.class, String.class, "xen.storage.network.device2", null, "Specify when there are storage networks", null),
|
||||
XenPrivateNetwork("Hidden", ManagementServer.class, String.class, "xen.private.network.device", null, "Specify when the private network name is different", null),
|
||||
XenServerStorageNetwork1("Hidden", ManagementServer.class, String.class, "xenserver.storage.network.device1", null, "Specify when there are storage networks", null),
|
||||
XenServerStorageNetwork2("Hidden", ManagementServer.class, String.class, "xenserver.storage.network.device2", null, "Specify when there are storage networks", null),
|
||||
XenServerPrivateNetwork("Hidden", ManagementServer.class, String.class, "xenserver.private.network.device", null, "Specify when the private network name is different", null),
|
||||
NetworkGuestCidrLimit(
|
||||
"Network",
|
||||
NetworkOrchestrationService.class,
|
||||
|
|
@ -1098,32 +1098,32 @@ public enum Config {
|
|||
"22",
|
||||
"size limit for guest cidr; can't be less than this value",
|
||||
null),
|
||||
XenSetupMultipath("Advanced", ManagementServer.class, String.class, "xen.setup.multipath", "false", "Setup the host to do multipath", null),
|
||||
XenBondStorageNic("Advanced", ManagementServer.class, String.class, "xen.bond.storage.nics", null, "Attempt to bond the two networks if found", null),
|
||||
XenHeartBeatInterval(
|
||||
XenServerSetupMultipath("Advanced", ManagementServer.class, String.class, "xenserver.setup.multipath", "false", "Setup the host to do multipath", null),
|
||||
XenServerBondStorageNic("Advanced", ManagementServer.class, String.class, "xenserver.bond.storage.nics", null, "Attempt to bond the two networks if found", null),
|
||||
XenServerHeartBeatInterval(
|
||||
"Advanced",
|
||||
ManagementServer.class,
|
||||
Integer.class,
|
||||
"xen.heartbeat.interval",
|
||||
"xenserver.heartbeat.interval",
|
||||
"60",
|
||||
"heartbeat to use when implementing XenServer Self Fencing",
|
||||
null),
|
||||
XenGuestNetwork("Hidden", ManagementServer.class, String.class, "xen.guest.network.device", null, "Specify for guest network name label", null),
|
||||
XenMaxNics("Advanced", AgentManager.class, Integer.class, "xen.nics.max", "7", "Maximum allowed nics for Vms created on Xen", null),
|
||||
XenPVdriverVersion(
|
||||
XenServerGuestNetwork("Hidden", ManagementServer.class, String.class, "xenserver.guest.network.device", null, "Specify for guest network name label", null),
|
||||
XenServerMaxNics("Advanced", AgentManager.class, Integer.class, "xenserver.nics.max", "7", "Maximum allowed nics for Vms created on XenServer", null),
|
||||
XenServerPVdriverVersion(
|
||||
"Advanced",
|
||||
ManagementServer.class,
|
||||
String.class,
|
||||
"xen.pvdriver.version",
|
||||
"xenserver.pvdriver.version",
|
||||
"xenserver61",
|
||||
"default Xen PV driver version for registered template, valid value:xenserver56,xenserver61 ",
|
||||
"xenserver56,xenserver61"),
|
||||
XenServerHotFix("Advanced",
|
||||
ManagementServer.class,
|
||||
Boolean.class,
|
||||
"xen.hotfix.enabled",
|
||||
"xenserver.hotfix.enabled",
|
||||
"false",
|
||||
"Enable/Disable xenserver hot fix",
|
||||
"Enable/Disable XenServer hot fix",
|
||||
null),
|
||||
|
||||
// VMware
|
||||
|
|
@ -1366,7 +1366,7 @@ public enum Config {
|
|||
"Hidden",
|
||||
ManagementServer.class,
|
||||
Boolean.class,
|
||||
"xen.create.pools.in.pod",
|
||||
"xenserver.create.pools.in.pod",
|
||||
"false",
|
||||
"Should we automatically add XenServers into pools that are inside a Pod",
|
||||
null),
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
configValuesForValidation.add("storage.stats.interval");
|
||||
configValuesForValidation.add("storage.cleanup.interval");
|
||||
configValuesForValidation.add("wait");
|
||||
configValuesForValidation.add("xen.heartbeat.interval");
|
||||
configValuesForValidation.add("xenserver.heartbeat.interval");
|
||||
configValuesForValidation.add("incorrect.login.attempts.allowed");
|
||||
}
|
||||
|
||||
|
|
@ -502,7 +502,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
|
||||
PreparedStatement pstmt = null;
|
||||
if (Config.XenGuestNetwork.key().equalsIgnoreCase(name)) {
|
||||
if (Config.XenServerGuestNetwork.key().equalsIgnoreCase(name)) {
|
||||
String sql = "update host_details set value=? where name=?";
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
|
|
@ -513,7 +513,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
} catch (Throwable e) {
|
||||
throw new CloudRuntimeException("Failed to update guest.network.device in host_details due to exception ", e);
|
||||
}
|
||||
} else if (Config.XenPrivateNetwork.key().equalsIgnoreCase(name)) {
|
||||
} else if (Config.XenServerPrivateNetwork.key().equalsIgnoreCase(name)) {
|
||||
String sql = "update host_details set value=? where name=?";
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
|
|
@ -524,7 +524,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
} catch (Throwable e) {
|
||||
throw new CloudRuntimeException("Failed to update private.network.device in host_details due to exception ", e);
|
||||
}
|
||||
} else if (Config.XenPublicNetwork.key().equalsIgnoreCase(name)) {
|
||||
} else if (Config.XenServerPublicNetwork.key().equalsIgnoreCase(name)) {
|
||||
String sql = "update host_details set value=? where name=?";
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
|
|
@ -535,7 +535,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
} catch (Throwable e) {
|
||||
throw new CloudRuntimeException("Failed to update public.network.device in host_details due to exception ", e);
|
||||
}
|
||||
} else if (Config.XenStorageNetwork1.key().equalsIgnoreCase(name)) {
|
||||
} else if (Config.XenServerStorageNetwork1.key().equalsIgnoreCase(name)) {
|
||||
String sql = "update host_details set value=? where name=?";
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
|
|
@ -546,7 +546,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
} catch (Throwable e) {
|
||||
throw new CloudRuntimeException("Failed to update storage.network.device1 in host_details due to exception ", e);
|
||||
}
|
||||
} else if (Config.XenStorageNetwork2.key().equals(name)) {
|
||||
} else if (Config.XenServerStorageNetwork2.key().equals(name)) {
|
||||
String sql = "update host_details set value=? where name=?";
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
|
|
|
|||
|
|
@ -3444,16 +3444,16 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
|
|||
String xenLabel = null;
|
||||
switch (trafficType) {
|
||||
case Public:
|
||||
xenLabel = _configDao.getValue(Config.XenPublicNetwork.key());
|
||||
xenLabel = _configDao.getValue(Config.XenServerPublicNetwork.key());
|
||||
break;
|
||||
case Guest:
|
||||
xenLabel = _configDao.getValue(Config.XenGuestNetwork.key());
|
||||
xenLabel = _configDao.getValue(Config.XenServerGuestNetwork.key());
|
||||
break;
|
||||
case Storage:
|
||||
xenLabel = _configDao.getValue(Config.XenStorageNetwork1.key());
|
||||
xenLabel = _configDao.getValue(Config.XenServerStorageNetwork1.key());
|
||||
break;
|
||||
case Management:
|
||||
xenLabel = _configDao.getValue(Config.XenPrivateNetwork.key());
|
||||
xenLabel = _configDao.getValue(Config.XenServerPrivateNetwork.key());
|
||||
break;
|
||||
case Control:
|
||||
xenLabel = "cloud_link_local_network";
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import java.util.Map;
|
|||
*
|
||||
*/
|
||||
public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkApplianceService {
|
||||
static final String RouterTemplateXenCK = "router.template.xen";
|
||||
static final String RouterTemplateXenCK = "router.template.xenserver";
|
||||
static final String RouterTemplateKvmCK = "router.template.kvm";
|
||||
static final String RouterTemplateVmwareCK = "router.template.vmware";
|
||||
static final String RouterTemplateHyperVCK = "router.template.hyperv";
|
||||
|
|
|
|||
|
|
@ -137,8 +137,8 @@ public abstract class DiscovererBase extends AdapterBase implements Discoverer {
|
|||
params.put("secondary.storage.vm", "false");
|
||||
params.put("max.template.iso.size", _configDao.getValue(Config.MaxTemplateAndIsoSize.toString()));
|
||||
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.XenServerMaxNics.toString().toLowerCase(), _configDao.getValue(Config.XenServerMaxNics.toString()));
|
||||
params.put(Config.XenServerHeartBeatInterval.toString().toLowerCase(), _configDao.getValue(Config.XenServerHeartBeatInterval.toString()));
|
||||
return params;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -361,12 +361,12 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
|
|||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
TransactionLegacy txn = TransactionLegacy.currentTxn();
|
||||
String pvdriverversion = Config.XenPVdriverVersion.getDefaultValue();
|
||||
String pvdriverversion = Config.XenServerPVdriverVersion.getDefaultValue();
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs1 = null;
|
||||
ResultSet rs2 = null;
|
||||
try {
|
||||
String oldValue = _configDao.getValue(Config.XenPVdriverVersion.key());
|
||||
String oldValue = _configDao.getValue(Config.XenServerPVdriverVersion.key());
|
||||
if (oldValue == null) {
|
||||
String sql = "select resource from host where hypervisor_type='XenServer' and removed is null and status not in ('Error', 'Removed') group by resource";
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
|
|
@ -375,17 +375,17 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
|
|||
String resouce = rs1.getString(1); //resource column
|
||||
if (resouce == null)
|
||||
continue;
|
||||
if (resouce.equalsIgnoreCase("com.cloud.hypervisor.xen.resource.XenServer56Resource")
|
||||
|| resouce.equalsIgnoreCase("com.cloud.hypervisor.xen.resource.XenServer56FP1Resource")
|
||||
|| resouce.equalsIgnoreCase("com.cloud.hypervisor.xen.resource.XenServer56SP2Resource")
|
||||
|| resouce.equalsIgnoreCase("com.cloud.hypervisor.xen.resource.XenServer600Resource")
|
||||
|| resouce.equalsIgnoreCase("com.cloud.hypervisor.xen.resource.XenServer602Resource")) {
|
||||
if (resouce.equalsIgnoreCase("com.cloud.hypervisor.xenserver.resource.XenServer56Resource")
|
||||
|| resouce.equalsIgnoreCase("com.cloud.hypervisor.xenserver.resource.XenServer56FP1Resource")
|
||||
|| resouce.equalsIgnoreCase("com.cloud.hypervisor.xenserver.resource.XenServer56SP2Resource")
|
||||
|| resouce.equalsIgnoreCase("com.cloud.hypervisor.xenserver.resource.XenServer600Resource")
|
||||
|| resouce.equalsIgnoreCase("com.cloud.hypervisor.xenserver.resource.XenServer602Resource")) {
|
||||
pvdriverversion = "xenserver56";
|
||||
break;
|
||||
}
|
||||
}
|
||||
_configDao.getValueAndInitIfNotExist(Config.XenPVdriverVersion.key(), Config.XenPVdriverVersion.getCategory(), pvdriverversion,
|
||||
Config.XenPVdriverVersion.getDescription());
|
||||
_configDao.getValueAndInitIfNotExist(Config.XenServerPVdriverVersion.key(), Config.XenServerPVdriverVersion.getCategory(), pvdriverversion,
|
||||
Config.XenServerPVdriverVersion.getDescription());
|
||||
sql = "select id from vm_template where hypervisor_type='XenServer' and format!='ISO' and removed is null";
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
rs2 = pstmt.executeQuery();
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
|
|||
if (hypervisorType.equals(Hypervisor.HypervisorType.XenServer)) {
|
||||
if (details == null || !details.containsKey("hypervisortoolsversion") || details.get("hypervisortoolsversion") == null ||
|
||||
((String)details.get("hypervisortoolsversion")).equalsIgnoreCase("none")) {
|
||||
String hpvs = _configDao.getValue(Config.XenPVdriverVersion.key());
|
||||
String hpvs = _configDao.getValue(Config.XenServerPVdriverVersion.key());
|
||||
if (hpvs != null) {
|
||||
if (details == null) {
|
||||
details = new HashMap<String, String>();
|
||||
|
|
|
|||
|
|
@ -408,7 +408,7 @@ public class PodZoneConfig {
|
|||
String defaultXenStorageNetworkLabel = getDefaultXenNetworkLabel(TrafficType.Storage);
|
||||
String defaultXenGuestNetworkLabel = getDefaultXenNetworkLabel(TrafficType.Guest);
|
||||
|
||||
String insertTraficType = "INSERT INTO `cloud`.`physical_network_traffic_types` " + "(physical_network_id, traffic_type, xen_network_label) VALUES ( ?, ?, ?)";
|
||||
String insertTraficType = "INSERT INTO `cloud`.`physical_network_traffic_types` " + "(physical_network_id, traffic_type, xenserver_network_label) VALUES ( ?, ?, ?)";
|
||||
|
||||
try {
|
||||
PreparedStatement stmt = txn.prepareAutoCloseStatement(insertTraficType);
|
||||
|
|
@ -444,16 +444,16 @@ public class PodZoneConfig {
|
|||
String configName = null;
|
||||
switch (trafficType) {
|
||||
case Public:
|
||||
configName = "xen.public.network.device";
|
||||
configName = "xenserver.public.network.device";
|
||||
break;
|
||||
case Guest:
|
||||
configName = "xen.guest.network.device";
|
||||
configName = "xenserver.guest.network.device";
|
||||
break;
|
||||
case Storage:
|
||||
configName = "xen.storage.network.device1";
|
||||
configName = "xenserver.storage.network.device1";
|
||||
break;
|
||||
case Management:
|
||||
configName = "xen.private.network.device";
|
||||
configName = "xenserver.private.network.device";
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@
|
|||
<adapter name="ClusterService" class="com.cloud.cluster.ClusterServiceServletAdapter" />
|
||||
</adapters>
|
||||
<adapters key="com.cloud.resource.Discoverer">
|
||||
<adapter name="XenServer" class="com.cloud.resource.xen.XenServerDiscoverer" />
|
||||
<adapter name="XenServer" class="com.cloud.resource.xenserver.XenServerDiscoverer" />
|
||||
<adapter name="SecondaryStorage"
|
||||
class="com.cloud.storage.secondary.SecondaryStorageDiscoverer" />
|
||||
<adapter name="DummyHostServer" class="com.cloud.resource.DummyHostDiscoverer" />
|
||||
|
|
|
|||
|
|
@ -2091,7 +2091,7 @@ CREATE TABLE `cloud`.`physical_network_traffic_types` (
|
|||
`uuid` varchar(40),
|
||||
`physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network',
|
||||
`traffic_type` varchar(32) NOT NULL COMMENT 'type of traffic going through this network',
|
||||
`xen_network_label` varchar(255) COMMENT 'The network name label of the physical device dedicated to this traffic on a XenServer host',
|
||||
`xenserver_network_label` varchar(255) COMMENT 'The network name label of the physical device dedicated to this traffic on a XenServer host',
|
||||
`kvm_network_label` varchar(255) DEFAULT 'cloudbr0' COMMENT 'The network name label of the physical device dedicated to this traffic on a KVM host',
|
||||
`vmware_network_label` varchar(255) DEFAULT 'vSwitch0' COMMENT 'The network name label of the physical device dedicated to this traffic on a VMware host',
|
||||
`simulator_network_label` varchar(255) COMMENT 'The name labels needed for identifying the simulator',
|
||||
|
|
|
|||
|
|
@ -19,4 +19,15 @@
|
|||
-- Schema cleanup from 4.4.0 to 4.5.0
|
||||
--
|
||||
|
||||
UPDATE `cloud`.`configuration`
|
||||
SET name = 'router.template.xenserver'
|
||||
Where name = 'router.template.xen';
|
||||
|
||||
UPDATE `cloud`.`configuration`
|
||||
SET name = 'xenserver.nics.max',
|
||||
description = 'Maximum allowed nics for Vms created on XenServer'
|
||||
Where name = 'xen.nics.max';
|
||||
|
||||
UPDATE `cloud`.`configuration`
|
||||
SET value = 'XenServer'
|
||||
Where value = 'Xen';
|
||||
|
|
@ -223,3 +223,6 @@ CREATE VIEW `cloud`.`volume_view` AS
|
|||
`cloud`.`async_job` ON async_job.instance_id = volumes.id
|
||||
and async_job.instance_type = 'Volume'
|
||||
and async_job.job_status = 0;
|
||||
|
||||
/* As part of the separation of Xen and XenServer, update the column for the network labels */
|
||||
ALTER TABLE `cloud`.`physical_network_traffic_types` CHANGE `xen_network_label` `xenserver_network_label` varchar(255) COMMENT 'The network name label of the physical device dedicated to this traffic on a XenServer host'
|
||||
|
|
@ -23,6 +23,6 @@ INSERT INTO `cloud`.`domain` (id, uuid, name, parent, path, owner) VALUES (1, UU
|
|||
/* Configuration Table */
|
||||
|
||||
INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) VALUES ('Hidden', 'DEFAULT', 'none', 'init', null, null);
|
||||
-- INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) VALUES ('Advanced', 'DEFAULT', 'AgentManager', 'xen.public.network.device', 'public-network', "[OPTIONAL]The name of the Xen network containing the physical network interface that is connected to the public network ");
|
||||
-- INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) VALUES ('Advanced', 'DEFAULT', 'AgentManager', 'xenserver.public.network.device', 'public-network', "[OPTIONAL]The name of the XenServer network containing the physical network interface that is connected to the public network ");
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ Note, gem may require gcc-4.2, make sure link exists:
|
|||
|
||||
# How to build SystemVMs automatically
|
||||
|
||||
Just run build.sh, it will export archived appliances for KVM, Xen,
|
||||
Just run build.sh, it will export archived appliances for KVM, XenServer,
|
||||
VMWare and HyperV in `dist`:
|
||||
|
||||
sh build.sh [systemvmtemplate|systemvmtemplate64]
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ vboxmanage modifyhd $hdd_uuid --compact
|
|||
rm -fr dist *.ova *.vhd *.vdi *.qcow* *.bz2 *.vmdk *.ovf
|
||||
mkdir dist
|
||||
|
||||
# Export for Xen
|
||||
# Export for XenServer
|
||||
which faketime >/dev/null 2>&1 && which vhd-util >/dev/null 2>&1
|
||||
if [ $? == 0 ]; then
|
||||
set -e
|
||||
|
|
@ -82,9 +82,9 @@ if [ $? == 0 ]; then
|
|||
faketime '2010-01-01' vhd-util convert -s 1 -t 2 -i stagefixed.vhd -o $appliance-$branch-xen.vhd
|
||||
rm *.bak
|
||||
bzip2 $appliance-$branch-xen.vhd
|
||||
echo "$appliance exported for Xen: dist/$appliance-$branch-xen.vhd.bz2"
|
||||
echo "$appliance exported for XenServer: dist/$appliance-$branch-xen.vhd.bz2"
|
||||
else
|
||||
echo "** Skipping $appliance export for Xen: faketime or vhd-util command is missing. **"
|
||||
echo "** Skipping $appliance export for XenServer: faketime or vhd-util command is missing. **"
|
||||
echo "** faketime source code is available from https://github.com/wolfcw/libfaketime **"
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@
|
|||
"name": "eth0",
|
||||
"traffictypes": [
|
||||
{
|
||||
"xen": "Pool-wide network associated with eth0",
|
||||
"xenserver": "Pool-wide network associated with eth0",
|
||||
"typ": "Management"
|
||||
},
|
||||
{
|
||||
"xen": "Pool-wide network associated with eth0",
|
||||
"xenserver": "Pool-wide network associated with eth0",
|
||||
"typ": "Guest"
|
||||
}
|
||||
],
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
"name": "eth1",
|
||||
"traffictypes": [
|
||||
{
|
||||
"xen": "Pool-wide network associated with eth1",
|
||||
"xenserver": "Pool-wide network associated with eth1",
|
||||
"typ": "Public"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@
|
|||
"name": "eth0",
|
||||
"traffictypes": [
|
||||
{
|
||||
"xen": "Pool-wide network associated with eth0",
|
||||
"xenserver": "Pool-wide network associated with eth0",
|
||||
"typ": "Management"
|
||||
},
|
||||
{
|
||||
"xen": "Pool-wide network associated with eth0",
|
||||
"xenserver": "Pool-wide network associated with eth0",
|
||||
"typ": "Guest"
|
||||
}
|
||||
],
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
"name": "eth1",
|
||||
"traffictypes": [
|
||||
{
|
||||
"xen": "Pool-wide network associated with eth1",
|
||||
"xenserver": "Pool-wide network associated with eth1",
|
||||
"typ": "Public"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ def cobblerHomeResolve(ip_address, param="gateway"):
|
|||
|
||||
def configureManagementServer(mgmt_host):
|
||||
"""
|
||||
We currently configure all mgmt servers on a single xen HV. In the future
|
||||
We currently configure all mgmt servers on a single xenserver HV. In the future
|
||||
replace this by launching instances via the API on a IaaS cloud using
|
||||
desired template
|
||||
"""
|
||||
|
|
@ -123,15 +123,15 @@ def configureManagementServer(mgmt_host):
|
|||
bash("puppet cert clean %s.%s"%(mgmt_host, DOMAIN))
|
||||
|
||||
#Start VM on xenserver
|
||||
xenssh = \
|
||||
sshClient.SshClient(macinfo["infraxen"]["address"],
|
||||
xenserverssh = \
|
||||
sshClient.SshClient(macinfo["infraxenserver"]["address"],
|
||||
22, "root",
|
||||
macinfo["infraxen"]["password"])
|
||||
macinfo["infraxenserver"]["password"])
|
||||
|
||||
logging.debug("bash vm-uninstall.sh -n %s"%(mgmt_host))
|
||||
xenssh.execute("xe vm-uninstall force=true vm=%s"%mgmt_host)
|
||||
xenserverssh.execute("xe vm-uninstall force=true vm=%s"%mgmt_host)
|
||||
logging.debug("bash vm-start.sh -n %s -m %s"%(mgmt_host, mgmt_vm["ethernet"]))
|
||||
out = xenssh.execute("bash vm-start.sh -n %s -m %s"%(mgmt_host,
|
||||
out = xenserverssh.execute("bash vm-start.sh -n %s -m %s"%(mgmt_host,
|
||||
mgmt_vm["ethernet"]))
|
||||
|
||||
logging.info("started mgmt server with uuid: %s. Waiting for services .."%out);
|
||||
|
|
@ -179,7 +179,7 @@ def seedSecondaryStorage(cscfg, hypervisor):
|
|||
bash("echo '/bin/bash /root/redeploy.sh -s %s -h %s' >> /etc/puppet/modules/cloudstack/files/secseeder.sh"%(spath, hypervisor))
|
||||
bash("chmod +x /etc/puppet/modules/cloudstack/files/secseeder.sh")
|
||||
|
||||
def refreshHosts(cscfg, hypervisor="xen", profile="xen602"):
|
||||
def refreshHosts(cscfg, hypervisor="xenserver", profile="xenserver602"):
|
||||
"""
|
||||
Removes cobbler system from previous run.
|
||||
Creates a new system for current run.
|
||||
|
|
@ -354,7 +354,7 @@ if __name__ == '__main__':
|
|||
dest="distro", help="management server distro")
|
||||
parser.add_argument("-v", "--hypervisor", action="store",
|
||||
dest="hypervisor", help="hypervisor type")
|
||||
parser.add_argument("-p", "--profile", action="store", default="xen602",
|
||||
parser.add_argument("-p", "--profile", action="store", default="xenserver602",
|
||||
dest="profile", help="cobbler profile for hypervisor")
|
||||
parser.add_argument("-e","--environment", help="environment properties file",
|
||||
dest="system", action="store")
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ pip -q install lib/python2.7/site-packages/marvin/
|
|||
#Deploy the configuration - yes/no
|
||||
if [[ $DEPLOY == "yes" ]]; then
|
||||
cd cloud-autodeploy
|
||||
if [[ $hypervisor == 'xen' ]];then
|
||||
profile='xen602'
|
||||
if [[ $hypervisor == 'xenserver' ]];then
|
||||
profile='xenserver602'
|
||||
else
|
||||
profile='rhel63-kvm'
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1231,7 +1231,7 @@ dictionary = {
|
|||
'label.welcome.cloud.console': '<fmt:message key="label.welcome.cloud.console" />',
|
||||
'label.welcome': '<fmt:message key="label.welcome" />',
|
||||
'label.what.is.cloudstack': '<fmt:message key="label.what.is.cloudstack" />',
|
||||
'label.xen.traffic.label': '<fmt:message key="label.xen.traffic.label" />',
|
||||
'label.xenserver.traffic.label': '<fmt:message key="label.xenserver.traffic.label" />',
|
||||
'label.yes': '<fmt:message key="label.yes" />',
|
||||
'label.zone.details': '<fmt:message key="label.zone.details" />',
|
||||
'label.zone': '<fmt:message key="label.zone" />',
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ cloudStack.docs = {
|
|||
externalLink: ''
|
||||
},
|
||||
helpDiskOfferingHypervisorSnapshotReserve: {
|
||||
desc: 'Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware) (Ex. The value 25 means 25%.)).',
|
||||
desc: 'Hypervisor snapshot reserve space as a percent of a volume (for managed storage using XenServer or VMware) (Ex. The value 25 means 25%.)).',
|
||||
},
|
||||
helpDiskOfferingCacheMode: {
|
||||
desc: 'The write caching mode to use for disks created with this disk offering. This can improve write performance.',
|
||||
|
|
|
|||
|
|
@ -127,8 +127,8 @@
|
|||
}
|
||||
});
|
||||
|
||||
if (trafficType.xennetworklabel == null || trafficType.xennetworklabel == 0)
|
||||
trafficType.xennetworklabel = dictionary[ 'label.network.label.display.for.blank.value'];
|
||||
if (trafficType.xenservernetworklabel == null || trafficType.xenservernetworklabel == 0)
|
||||
trafficType.xenservernetworklabel = dictionary[ 'label.network.label.display.for.blank.value'];
|
||||
if (trafficType.kvmnetworklabel == null || trafficType.kvmnetworklabel == 0)
|
||||
trafficType.kvmnetworklabel = dictionary[ 'label.network.label.display.for.blank.value'];
|
||||
if (trafficType.vmwarenetworklabel == null || trafficType.vmwarenetworklabel == 0)
|
||||
|
|
@ -145,8 +145,8 @@
|
|||
|
||||
var updateTrafficLabels = function (trafficType, labels, complete) {
|
||||
var array1 =[];
|
||||
if (labels.xennetworklabel != dictionary[ 'label.network.label.display.for.blank.value'])
|
||||
array1.push("&xennetworklabel=" + labels.xennetworklabel);
|
||||
if (labels.xenservernetworklabel != dictionary[ 'label.network.label.display.for.blank.value'])
|
||||
array1.push("&xenservernetworklabel=" + labels.xenservernetworklabel);
|
||||
if (labels.kvmnetworklabel != dictionary[ 'label.network.label.display.for.blank.value'])
|
||||
array1.push("&kvmnetworklabel=" + labels.kvmnetworklabel);
|
||||
if (labels.vmwarenetworklabel != dictionary[ 'label.network.label.display.for.blank.value'])
|
||||
|
|
@ -581,8 +581,8 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
xennetworklabel: {
|
||||
label: 'label.xen.traffic.label',
|
||||
xenservernetworklabel: {
|
||||
label: 'label.xenserver.traffic.label',
|
||||
isEditable: true
|
||||
},
|
||||
kvmnetworklabel: {
|
||||
|
|
@ -619,7 +619,7 @@
|
|||
selectedPublicNetworkObj = items[0];
|
||||
|
||||
// Include traffic labels
|
||||
selectedPublicNetworkObj.xennetworklabel = trafficType.xennetworklabel;
|
||||
selectedPublicNetworkObj.xenservernetworklabel = trafficType.xenservernetworklabel;
|
||||
selectedPublicNetworkObj.kvmnetworklabel = trafficType.kvmnetworklabel;
|
||||
selectedPublicNetworkObj.vmwarenetworklabel = trafficType.vmwarenetworklabel;
|
||||
selectedPublicNetworkObj.ovmnetworklabel = trafficType.ovmnetworklabel;
|
||||
|
|
@ -889,8 +889,8 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
xennetworklabel: {
|
||||
label: 'label.xen.traffic.label',
|
||||
xenservernetworklabel: {
|
||||
label: 'label.xenserver.traffic.label',
|
||||
isEditable: true
|
||||
},
|
||||
kvmnetworklabel: {
|
||||
|
|
@ -925,7 +925,7 @@
|
|||
var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Storage');
|
||||
selectedPublicNetworkObj = items[0];
|
||||
|
||||
selectedPublicNetworkObj.xennetworklabel = trafficType.xennetworklabel;
|
||||
selectedPublicNetworkObj.xenservernetworklabel = trafficType.xenservernetworklabel;
|
||||
selectedPublicNetworkObj.kvmnetworklabel = trafficType.kvmnetworklabel;
|
||||
selectedPublicNetworkObj.vmwarenetworklabel = trafficType.vmwarenetworklabel;
|
||||
selectedPublicNetworkObj.ovmnetworklabel = trafficType.ovmnetworklabel;
|
||||
|
|
@ -1101,8 +1101,8 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
xennetworklabel: {
|
||||
label: 'label.xen.traffic.label',
|
||||
xenservernetworklabel: {
|
||||
label: 'label.xenserver.traffic.label',
|
||||
isEditable: true
|
||||
},
|
||||
kvmnetworklabel: {
|
||||
|
|
@ -1135,7 +1135,7 @@
|
|||
|
||||
var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Management');
|
||||
|
||||
selectedManagementNetworkObj.xennetworklabel = trafficType.xennetworklabel;
|
||||
selectedManagementNetworkObj.xenservernetworklabel = trafficType.xenservernetworklabel;
|
||||
selectedManagementNetworkObj.kvmnetworklabel = trafficType.kvmnetworklabel;
|
||||
selectedManagementNetworkObj.vmwarenetworklabel = trafficType.vmwarenetworklabel;
|
||||
selectedManagementNetworkObj.ovmnetworklabel = trafficType.ovmnetworklabel;
|
||||
|
|
@ -1290,8 +1290,8 @@
|
|||
},
|
||||
{
|
||||
//updateTrafficType API
|
||||
xennetworklabel: {
|
||||
label: 'label.xen.traffic.label',
|
||||
xenservernetworklabel: {
|
||||
label: 'label.xenserver.traffic.label',
|
||||
isEditable: true
|
||||
},
|
||||
kvmnetworklabel: {
|
||||
|
|
@ -1343,10 +1343,10 @@
|
|||
}*/
|
||||
|
||||
//traffic type
|
||||
var xentrafficlabel, kvmtrafficlabel, vmwaretrafficlabel;
|
||||
var xenservertrafficlabel, kvmtrafficlabel, vmwaretrafficlabel;
|
||||
var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Guest');
|
||||
//refresh Guest traffic type
|
||||
selectedPhysicalNetworkObj[ "xennetworklabel"] = trafficType.xennetworklabel;
|
||||
selectedPhysicalNetworkObj[ "xenservernetworklabel"] = trafficType.xenservernetworklabel;
|
||||
selectedPhysicalNetworkObj[ "kvmnetworklabel"] = trafficType.kvmnetworklabel;
|
||||
selectedPhysicalNetworkObj[ "vmwarenetworklabel"] = trafficType.vmwarenetworklabel;
|
||||
selectedPhysicalNetworkObj[ "ovmnetworklabel"] = trafficType.ovmnetworklabel;
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@
|
|||
$.ajax({
|
||||
url: createURL('listConfigurations'),
|
||||
data: {
|
||||
name: 'xen.pvdriver.version'
|
||||
name: 'xenserver.pvdriver.version'
|
||||
},
|
||||
async: false,
|
||||
success: function (json) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue