Merge branch '4.19' into 4.20

This commit is contained in:
Daan Hoogland 2025-02-12 15:00:51 +01:00
commit 4f3e8e8c5a
93 changed files with 2741 additions and 1504 deletions

View File

@ -26,7 +26,7 @@ import com.cloud.utils.SerialVersionUID;
public class StorageAccessException extends RuntimeException { public class StorageAccessException extends RuntimeException {
private static final long serialVersionUID = SerialVersionUID.StorageAccessException; private static final long serialVersionUID = SerialVersionUID.StorageAccessException;
public StorageAccessException(String message) { public StorageAccessException(String message, Exception causer) {
super(message); super(message, causer);
} }
} }

View File

@ -16,14 +16,10 @@
// under the License. // under the License.
package com.cloud.storage; package com.cloud.storage;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.commons.lang.NotImplementedException; import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class Storage { public class Storage {
public static enum ImageFormat { public static enum ImageFormat {
@ -139,6 +135,21 @@ public class Storage {
ISODISK /* Template corresponding to a iso (non root disk) present in an OVA */ ISODISK /* Template corresponding to a iso (non root disk) present in an OVA */
} }
public enum EncryptionSupport {
/**
* Encryption not supported.
*/
Unsupported,
/**
* Will use hypervisor encryption driver (qemu -> luks)
*/
Hypervisor,
/**
* Storage pool handles encryption and just provides an encrypted volume
*/
Storage
}
/** /**
* StoragePoolTypes carry some details about the format and capabilities of a storage pool. While not necessarily a * StoragePoolTypes carry some details about the format and capabilities of a storage pool. While not necessarily a
* 1:1 with PrimaryDataStoreDriver (and for KVM agent, KVMStoragePool and StorageAdaptor) implementations, it is * 1:1 with PrimaryDataStoreDriver (and for KVM agent, KVMStoragePool and StorageAdaptor) implementations, it is
@ -150,61 +161,37 @@ public class Storage {
* ensure this is available on the agent side as well. This is best done by defining the StoragePoolType in a common * ensure this is available on the agent side as well. This is best done by defining the StoragePoolType in a common
* package available on both management server and agent plugin jars. * package available on both management server and agent plugin jars.
*/ */
public static class StoragePoolType { public static enum StoragePoolType {
private static final Map<String, StoragePoolType> map = new LinkedHashMap<>(); Filesystem(false, true, EncryptionSupport.Hypervisor), // local directory
NetworkFilesystem(true, true, EncryptionSupport.Hypervisor), // NFS
IscsiLUN(true, false, EncryptionSupport.Unsupported), // shared LUN, with a clusterfs overlay
Iscsi(true, false, EncryptionSupport.Unsupported), // for e.g., ZFS Comstar
ISO(false, false, EncryptionSupport.Unsupported), // for iso image
LVM(false, false, EncryptionSupport.Unsupported), // XenServer local LVM SR
CLVM(true, false, EncryptionSupport.Unsupported),
RBD(true, true, EncryptionSupport.Unsupported), // http://libvirt.org/storage.html#StorageBackendRBD
SharedMountPoint(true, true, EncryptionSupport.Hypervisor),
VMFS(true, true, EncryptionSupport.Unsupported), // VMware VMFS storage
PreSetup(true, true, EncryptionSupport.Unsupported), // for XenServer, Storage Pool is set up by customers.
EXT(false, true, EncryptionSupport.Unsupported), // XenServer local EXT SR
OCFS2(true, false, EncryptionSupport.Unsupported),
SMB(true, false, EncryptionSupport.Unsupported),
Gluster(true, false, EncryptionSupport.Unsupported),
PowerFlex(true, true, EncryptionSupport.Hypervisor), // Dell EMC PowerFlex/ScaleIO (formerly VxFlexOS)
ManagedNFS(true, false, EncryptionSupport.Unsupported),
Linstor(true, true, EncryptionSupport.Storage),
DatastoreCluster(true, true, EncryptionSupport.Unsupported), // for VMware, to abstract pool of clusters
StorPool(true, true, EncryptionSupport.Hypervisor),
FiberChannel(true, true, EncryptionSupport.Unsupported); // Fiber Channel Pool for KVM hypervisors is used to find the volume by WWN value (/dev/disk/by-id/wwn-<wwnvalue>)
public static final StoragePoolType Filesystem = new StoragePoolType("Filesystem", false, true, true);
public static final StoragePoolType NetworkFilesystem = new StoragePoolType("NetworkFilesystem", true, true, true);
public static final StoragePoolType IscsiLUN = new StoragePoolType("IscsiLUN", true, false, false);
public static final StoragePoolType Iscsi = new StoragePoolType("Iscsi", true, false, false);
public static final StoragePoolType ISO = new StoragePoolType("ISO", false, false, false);
public static final StoragePoolType LVM = new StoragePoolType("LVM", false, false, false);
public static final StoragePoolType CLVM = new StoragePoolType("CLVM", true, false, false);
public static final StoragePoolType RBD = new StoragePoolType("RBD", true, true, false);
public static final StoragePoolType SharedMountPoint = new StoragePoolType("SharedMountPoint", true, true, true);
public static final StoragePoolType VMFS = new StoragePoolType("VMFS", true, true, false);
public static final StoragePoolType PreSetup = new StoragePoolType("PreSetup", true, true, false);
public static final StoragePoolType EXT = new StoragePoolType("EXT", false, true, false);
public static final StoragePoolType OCFS2 = new StoragePoolType("OCFS2", true, false, false);
public static final StoragePoolType SMB = new StoragePoolType("SMB", true, false, false);
public static final StoragePoolType Gluster = new StoragePoolType("Gluster", true, false, false);
public static final StoragePoolType PowerFlex = new StoragePoolType("PowerFlex", true, true, true);
public static final StoragePoolType ManagedNFS = new StoragePoolType("ManagedNFS", true, false, false);
public static final StoragePoolType Linstor = new StoragePoolType("Linstor", true, true, false);
public static final StoragePoolType DatastoreCluster = new StoragePoolType("DatastoreCluster", true, true, false);
public static final StoragePoolType StorPool = new StoragePoolType("StorPool", true,true,true);
public static final StoragePoolType FiberChannel = new StoragePoolType("FiberChannel", true,true,false);
private final String name;
private final boolean shared; private final boolean shared;
private final boolean overProvisioning; private final boolean overProvisioning;
private final boolean encryption; private final EncryptionSupport encryption;
/** StoragePoolType(boolean shared, boolean overProvisioning, EncryptionSupport encryption) {
* New StoragePoolType, set the name to check with it in Dao (Note: Do not register it into the map of pool types).
* @param name name of the StoragePoolType.
*/
public StoragePoolType(String name) {
this.name = name;
this.shared = false;
this.overProvisioning = false;
this.encryption = false;
}
/**
* Define a new StoragePoolType, and register it into the map of pool types known to the management server.
* @param name Simple unique name of the StoragePoolType.
* @param shared Storage pool is shared/accessible to multiple hypervisors
* @param overProvisioning Storage pool supports overProvisioning
* @param encryption Storage pool supports encrypted volumes
*/
public StoragePoolType(String name, boolean shared, boolean overProvisioning, boolean encryption) {
this.name = name;
this.shared = shared; this.shared = shared;
this.overProvisioning = overProvisioning; this.overProvisioning = overProvisioning;
this.encryption = encryption; this.encryption = encryption;
addStoragePoolType(this);
} }
public boolean isShared() { public boolean isShared() {
@ -216,50 +203,12 @@ public class Storage {
} }
public boolean supportsEncryption() { public boolean supportsEncryption() {
return encryption == EncryptionSupport.Hypervisor || encryption == EncryptionSupport.Storage;
}
public EncryptionSupport encryptionSupportMode() {
return encryption; return encryption;
} }
private static void addStoragePoolType(StoragePoolType storagePoolType) {
map.putIfAbsent(storagePoolType.name, storagePoolType);
}
public static StoragePoolType[] values() {
return map.values().toArray(StoragePoolType[]::new).clone();
}
public static StoragePoolType valueOf(String name) {
if (StringUtils.isBlank(name)) {
return null;
}
StoragePoolType storage = map.get(name);
if (storage == null) {
throw new IllegalArgumentException("StoragePoolType '" + name + "' not found");
}
return storage;
}
@Override
public String toString() {
return name;
}
public String name() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StoragePoolType that = (StoragePoolType) o;
return Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
} }
public static List<StoragePoolType> getNonSharedStoragePoolTypes() { public static List<StoragePoolType> getNonSharedStoragePoolTypes() {

View File

@ -57,6 +57,7 @@ public class ApiConstants {
public static final String BASE64_IMAGE = "base64image"; public static final String BASE64_IMAGE = "base64image";
public static final String BGP_PEERS = "bgppeers"; public static final String BGP_PEERS = "bgppeers";
public static final String BGP_PEER_IDS = "bgppeerids"; public static final String BGP_PEER_IDS = "bgppeerids";
public static final String BATCH_SIZE = "batchsize";
public static final String BITS = "bits"; public static final String BITS = "bits";
public static final String BOOTABLE = "bootable"; public static final String BOOTABLE = "bootable";
public static final String BIND_DN = "binddn"; public static final String BIND_DN = "binddn";
@ -476,11 +477,12 @@ public class ApiConstants {
public static final String STATE = "state"; public static final String STATE = "state";
public static final String STATS = "stats"; public static final String STATS = "stats";
public static final String STATUS = "status"; public static final String STATUS = "status";
public static final String STORAGE_TYPE = "storagetype";
public static final String STORAGE_POLICY = "storagepolicy";
public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled";
public static final String STORAGE_CAPABILITIES = "storagecapabilities"; public static final String STORAGE_CAPABILITIES = "storagecapabilities";
public static final String STORAGE_CUSTOM_STATS = "storagecustomstats"; public static final String STORAGE_CUSTOM_STATS = "storagecustomstats";
public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled";
public static final String STORAGE_POLICY = "storagepolicy";
public static final String STORAGE_POOL = "storagepool";
public static final String STORAGE_TYPE = "storagetype";
public static final String SUBNET = "subnet"; public static final String SUBNET = "subnet";
public static final String OWNER = "owner"; public static final String OWNER = "owner";
public static final String SWAP_OWNER = "swapowner"; public static final String SWAP_OWNER = "swapowner";
@ -953,7 +955,6 @@ public class ApiConstants {
public static final String AUTOSCALE_VMGROUP_NAME = "autoscalevmgroupname"; public static final String AUTOSCALE_VMGROUP_NAME = "autoscalevmgroupname";
public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername"; public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername";
public static final String BAREMETAL_RCT_URL = "baremetalrcturl"; public static final String BAREMETAL_RCT_URL = "baremetalrcturl";
public static final String BATCH_SIZE = "batchsize";
public static final String UCS_DN = "ucsdn"; public static final String UCS_DN = "ucsdn";
public static final String GSLB_PROVIDER = "gslbprovider"; public static final String GSLB_PROVIDER = "gslbprovider";
public static final String EXCLUSIVE_GSLB_PROVIDER = "isexclusivegslbprovider"; public static final String EXCLUSIVE_GSLB_PROVIDER = "isexclusivegslbprovider";
@ -1190,6 +1191,7 @@ public class ApiConstants {
"a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " + "a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " +
"numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " + "numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " +
"value will be applied."; "value will be applied.";
public static final String VMWARE_DC = "vmwaredc";
/** /**
* This enum specifies IO Drivers, each option controls specific policies on I/O. * This enum specifies IO Drivers, each option controls specific policies on I/O.

View File

@ -152,7 +152,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
@Deprecated @Deprecated
@SerializedName("memoryallocated") @SerializedName("memoryallocated")
@Param(description = "the amount of the host's memory currently allocated") @Param(description = "the amount of the host's memory currently allocated")
private long memoryAllocated; private Long memoryAllocated;
@SerializedName("memoryallocatedpercentage") @SerializedName("memoryallocatedpercentage")
@Param(description = "the amount of the host's memory currently allocated in percentage") @Param(description = "the amount of the host's memory currently allocated in percentage")
@ -407,7 +407,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
this.memWithOverprovisioning=memWithOverprovisioning; this.memWithOverprovisioning=memWithOverprovisioning;
} }
public void setMemoryAllocated(long memoryAllocated) { public void setMemoryAllocated(Long memoryAllocated) {
this.memoryAllocated = memoryAllocated; this.memoryAllocated = memoryAllocated;
} }
@ -687,8 +687,8 @@ public class HostResponse extends BaseResponseWithAnnotations {
return memoryTotal; return memoryTotal;
} }
public long getMemoryAllocated() { public Long getMemoryAllocated() {
return memoryAllocated; return memoryAllocated == null ? 0 : memoryAllocated;
} }
public void setMemoryAllocatedPercentage(String memoryAllocatedPercentage) { public void setMemoryAllocatedPercentage(String memoryAllocatedPercentage) {

View File

@ -0,0 +1,46 @@
//
// 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.agent.api;
/**
* This command will destroy a leftover VM during the expunge process if it wasn't destroyed before.
*
*/
public class CleanupVMCommand extends Command {
String vmName;
boolean executeInSequence;
public CleanupVMCommand(String vmName) {
this(vmName, false);
}
public CleanupVMCommand(String vmName, boolean executeInSequence) {
this.vmName = vmName;
this.executeInSequence = executeInSequence;
}
@Override
public boolean executeInSequence() {
return executeInSequence;
}
public String getVmName() {
return vmName;
}
}

View File

@ -1807,7 +1807,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
try { try {
volService.grantAccess(volFactory.getVolume(newVol.getId()), host, destPool); volService.grantAccess(volFactory.getVolume(newVol.getId()), host, destPool);
} catch (Exception e) { } catch (Exception e) {
throw new StorageAccessException(String.format("Unable to grant access to the volume [%s] on host [%s].", newVolToString, host)); throw new StorageAccessException(String.format("Unable to grant access to the volume [%s] on host [%s].", newVolToString, host), e);
} }
} }
@ -1847,7 +1847,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
try { try {
volService.grantAccess(volFactory.getVolume(volumeId), host, volumeStore); volService.grantAccess(volFactory.getVolume(volumeId), host, volumeStore);
} catch (Exception e) { } catch (Exception e) {
throw new StorageAccessException(String.format("Unable to grant access to volume [%s] on host [%s].", volToString, host)); throw new StorageAccessException(String.format("Unable to grant access to volume [%s] on host [%s].", volToString, host), e);
} }
} }
@ -1928,7 +1928,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
try { try {
volService.grantAccess(volFactory.getVolume(vol.getId()), host, store); volService.grantAccess(volFactory.getVolume(vol.getId()), host, store);
} catch (Exception e) { } catch (Exception e) {
throw new StorageAccessException(String.format("Unable to grant access to volume [%s] on host [%s].", volToString, host)); throw new StorageAccessException(String.format("Unable to grant access to volume [%s] on host [%s].", volToString, host), e);
} }
} else { } else {
grantVolumeAccessToHostIfNeeded(store, vol.getId(), host, volToString); grantVolumeAccessToHostIfNeeded(store, vol.getId(), host, volToString);

View File

@ -20,8 +20,9 @@ import java.util.Collection;
import java.util.Map; import java.util.Map;
import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
public interface ClusterDetailsDao extends GenericDao<ClusterDetailsVO, Long> { public interface ClusterDetailsDao extends GenericDao<ClusterDetailsVO, Long>, ResourceDetailsDao<ClusterDetailsVO> {
Map<String, String> findDetails(long clusterId); Map<String, String> findDetails(long clusterId);
void persist(long clusterId, Map<String, String> details); void persist(long clusterId, Map<String, String> details);

View File

@ -28,12 +28,13 @@ import org.apache.cloudstack.framework.config.ScopedConfigStorage;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import com.cloud.utils.crypt.DBEncryptionUtil; import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.db.TransactionLegacy;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
public class ClusterDetailsDaoImpl extends ResourceDetailsDaoBase<ClusterDetailsVO> implements ClusterDetailsDao, ScopedConfigStorage {
public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long> implements ClusterDetailsDao, ScopedConfigStorage {
protected final SearchBuilder<ClusterDetailsVO> ClusterSearch; protected final SearchBuilder<ClusterDetailsVO> ClusterSearch;
protected final SearchBuilder<ClusterDetailsVO> DetailSearch; protected final SearchBuilder<ClusterDetailsVO> DetailSearch;
@ -44,11 +45,11 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long
protected ClusterDetailsDaoImpl() { protected ClusterDetailsDaoImpl() {
ClusterSearch = createSearchBuilder(); ClusterSearch = createSearchBuilder();
ClusterSearch.and("clusterId", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ); ClusterSearch.and("clusterId", ClusterSearch.entity().getResourceId(), SearchCriteria.Op.EQ);
ClusterSearch.done(); ClusterSearch.done();
DetailSearch = createSearchBuilder(); DetailSearch = createSearchBuilder();
DetailSearch.and("clusterId", DetailSearch.entity().getClusterId(), SearchCriteria.Op.EQ); DetailSearch.and("clusterId", DetailSearch.entity().getResourceId(), SearchCriteria.Op.EQ);
DetailSearch.and("name", DetailSearch.entity().getName(), SearchCriteria.Op.EQ); DetailSearch.and("name", DetailSearch.entity().getName(), SearchCriteria.Op.EQ);
DetailSearch.done(); DetailSearch.done();
} }
@ -68,6 +69,11 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long
return detail; return detail;
} }
@Override
public void addDetail(long resourceId, String key, String value, boolean display) {
super.addDetail(new ClusterDetailsVO(resourceId, key, value));
}
@Override @Override
public Map<String, String> findDetails(long clusterId) { public Map<String, String> findDetails(long clusterId) {
SearchCriteria<ClusterDetailsVO> sc = ClusterSearch.create(); SearchCriteria<ClusterDetailsVO> sc = ClusterSearch.create();
@ -91,7 +97,7 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long
return new HashMap<>(); return new HashMap<>();
} }
SearchBuilder<ClusterDetailsVO> sb = createSearchBuilder(); SearchBuilder<ClusterDetailsVO> sb = createSearchBuilder();
sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); sb.and("clusterId", sb.entity().getResourceId(), SearchCriteria.Op.EQ);
sb.and("name", sb.entity().getName(), SearchCriteria.Op.IN); sb.and("name", sb.entity().getName(), SearchCriteria.Op.IN);
sb.done(); sb.done();
SearchCriteria<ClusterDetailsVO> sc = sb.create(); SearchCriteria<ClusterDetailsVO> sc = sb.create();

View File

@ -23,11 +23,11 @@ import javax.persistence.GenerationType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.api.ResourceDetail;
@Entity @Entity
@Table(name = "cluster_details") @Table(name = "cluster_details")
public class ClusterDetailsVO implements InternalIdentity { public class ClusterDetailsVO implements ResourceDetail {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@ -35,7 +35,7 @@ public class ClusterDetailsVO implements InternalIdentity {
private long id; private long id;
@Column(name = "cluster_id") @Column(name = "cluster_id")
private long clusterId; private long resourceId;
@Column(name = "name") @Column(name = "name")
private String name; private String name;
@ -47,13 +47,14 @@ public class ClusterDetailsVO implements InternalIdentity {
} }
public ClusterDetailsVO(long clusterId, String name, String value) { public ClusterDetailsVO(long clusterId, String name, String value) {
this.clusterId = clusterId; this.resourceId = clusterId;
this.name = name; this.name = name;
this.value = value; this.value = value;
} }
public long getClusterId() { @Override
return clusterId; public long getResourceId() {
return resourceId;
} }
public String getName() { public String getName() {
@ -64,6 +65,11 @@ public class ClusterDetailsVO implements InternalIdentity {
return value; return value;
} }
@Override
public boolean isDisplay() {
return true;
}
public void setValue(String value) { public void setValue(String value) {
this.value = value; this.value = value;
} }

View File

@ -23,18 +23,18 @@ import javax.persistence.GenerationType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.api.ResourceDetail;
@Entity @Entity
@Table(name = "domain_details") @Table(name = "domain_details")
public class DomainDetailVO implements InternalIdentity { public class DomainDetailVO implements ResourceDetail {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id") @Column(name = "id")
private long id; private long id;
@Column(name = "domain_id") @Column(name = "domain_id")
private long domainId; private long resourceId;
@Column(name = "name") @Column(name = "name")
private String name; private String name;
@ -46,13 +46,14 @@ public class DomainDetailVO implements InternalIdentity {
} }
public DomainDetailVO(long domainId, String name, String value) { public DomainDetailVO(long domainId, String name, String value) {
this.domainId = domainId; this.resourceId = domainId;
this.name = name; this.name = name;
this.value = value; this.value = value;
} }
public long getDomainId() { @Override
return domainId; public long getResourceId() {
return resourceId;
} }
public String getName() { public String getName() {
@ -63,6 +64,11 @@ public class DomainDetailVO implements InternalIdentity {
return value; return value;
} }
@Override
public boolean isDisplay() {
return true;
}
public void setValue(String value) { public void setValue(String value) {
this.value = value; this.value = value;
} }

View File

@ -20,8 +20,9 @@ import java.util.Map;
import com.cloud.domain.DomainDetailVO; import com.cloud.domain.DomainDetailVO;
import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
public interface DomainDetailsDao extends GenericDao<DomainDetailVO, Long> { public interface DomainDetailsDao extends GenericDao<DomainDetailVO, Long>, ResourceDetailsDao<DomainDetailVO> {
Map<String, String> findDetails(long domainId); Map<String, String> findDetails(long domainId);
void persist(long domainId, Map<String, String> details); void persist(long domainId, Map<String, String> details);
@ -31,6 +32,4 @@ public interface DomainDetailsDao extends GenericDao<DomainDetailVO, Long> {
void deleteDetails(long domainId); void deleteDetails(long domainId);
void update(long domainId, Map<String, String> details); void update(long domainId, Map<String, String> details);
String getActualValue(DomainDetailVO domainDetailVO);
} }

View File

@ -25,19 +25,17 @@ import javax.inject.Inject;
import org.apache.cloudstack.framework.config.ConfigKey.Scope; import org.apache.cloudstack.framework.config.ConfigKey.Scope;
import org.apache.cloudstack.framework.config.ScopedConfigStorage; import org.apache.cloudstack.framework.config.ScopedConfigStorage;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
import com.cloud.domain.DomainDetailVO; import com.cloud.domain.DomainDetailVO;
import com.cloud.domain.DomainVO; import com.cloud.domain.DomainVO;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.QueryBuilder; import com.cloud.utils.db.QueryBuilder;
import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.db.TransactionLegacy;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> implements DomainDetailsDao, ScopedConfigStorage { public class DomainDetailsDaoImpl extends ResourceDetailsDaoBase<DomainDetailVO> implements DomainDetailsDao, ScopedConfigStorage {
protected final SearchBuilder<DomainDetailVO> domainSearch; protected final SearchBuilder<DomainDetailVO> domainSearch;
@Inject @Inject
@ -47,14 +45,14 @@ public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> i
protected DomainDetailsDaoImpl() { protected DomainDetailsDaoImpl() {
domainSearch = createSearchBuilder(); domainSearch = createSearchBuilder();
domainSearch.and("domainId", domainSearch.entity().getDomainId(), Op.EQ); domainSearch.and("domainId", domainSearch.entity().getResourceId(), Op.EQ);
domainSearch.done(); domainSearch.done();
} }
@Override @Override
public Map<String, String> findDetails(long domainId) { public Map<String, String> findDetails(long domainId) {
QueryBuilder<DomainDetailVO> sc = QueryBuilder.create(DomainDetailVO.class); QueryBuilder<DomainDetailVO> sc = QueryBuilder.create(DomainDetailVO.class);
sc.and(sc.entity().getDomainId(), Op.EQ, domainId); sc.and(sc.entity().getResourceId(), Op.EQ, domainId);
List<DomainDetailVO> results = sc.list(); List<DomainDetailVO> results = sc.list();
Map<String, String> details = new HashMap<String, String>(results.size()); Map<String, String> details = new HashMap<String, String>(results.size());
for (DomainDetailVO r : results) { for (DomainDetailVO r : results) {
@ -80,11 +78,16 @@ public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> i
@Override @Override
public DomainDetailVO findDetail(long domainId, String name) { public DomainDetailVO findDetail(long domainId, String name) {
QueryBuilder<DomainDetailVO> sc = QueryBuilder.create(DomainDetailVO.class); QueryBuilder<DomainDetailVO> sc = QueryBuilder.create(DomainDetailVO.class);
sc.and(sc.entity().getDomainId(), Op.EQ, domainId); sc.and(sc.entity().getResourceId(), Op.EQ, domainId);
sc.and(sc.entity().getName(), Op.EQ, name); sc.and(sc.entity().getName(), Op.EQ, name);
return sc.find(); return sc.find();
} }
@Override
public void addDetail(long resourceId, String key, String value, boolean display) {
super.addDetail(new DomainDetailVO(resourceId, key, value));
}
@Override @Override
public void deleteDetails(long domainId) { public void deleteDetails(long domainId) {
SearchCriteria<DomainDetailVO> sc = domainSearch.create(); SearchCriteria<DomainDetailVO> sc = domainSearch.create();
@ -129,13 +132,4 @@ public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> i
} }
return vo == null ? null : getActualValue(vo); return vo == null ? null : getActualValue(vo);
} }
@Override
public String getActualValue(DomainDetailVO domainDetailVO) {
ConfigurationVO configurationVO = _configDao.findByName(domainDetailVO.getName());
if (configurationVO != null && configurationVO.isEncrypted()) {
return DBEncryptionUtil.decrypt(domainDetailVO.getValue());
}
return domainDetailVO.getValue();
}
} }

View File

@ -46,7 +46,7 @@ public class StoragePoolDetailsDaoImpl extends ResourceDetailsDaoBase<StoragePoo
@Override @Override
public String getConfigValue(long id, String key) { public String getConfigValue(long id, String key) {
StoragePoolDetailVO vo = findDetail(id, key); StoragePoolDetailVO vo = findDetail(id, key);
return vo == null ? null : vo.getValue(); return vo == null ? null : getActualValue(vo);
} }
@Override @Override

View File

@ -334,7 +334,7 @@ public class SystemVmTemplateRegistration {
} }
}; };
public static boolean validateIfSeeded(String url, String path, String nfsVersion) { public boolean validateIfSeeded(TemplateDataStoreVO templDataStoreVO, String url, String path, String nfsVersion) {
String filePath = null; String filePath = null;
try { try {
filePath = Files.createTempDirectory(TEMPORARY_SECONDARY_STORE).toString(); filePath = Files.createTempDirectory(TEMPORARY_SECONDARY_STORE).toString();
@ -347,6 +347,9 @@ public class SystemVmTemplateRegistration {
String templatePath = filePath + File.separator + partialDirPath; String templatePath = filePath + File.separator + partialDirPath;
File templateProps = new File(templatePath + "/template.properties"); File templateProps = new File(templatePath + "/template.properties");
if (templateProps.exists()) { if (templateProps.exists()) {
Pair<Long, Long> templateSizes = readTemplatePropertiesSizes(templatePath + "/template.properties");
updateSeededTemplateDetails(templDataStoreVO.getTemplateId(), templDataStoreVO.getDataStoreId(),
templateSizes.first(), templateSizes.second());
LOGGER.info("SystemVM template already seeded, skipping registration"); LOGGER.info("SystemVM template already seeded, skipping registration");
return true; return true;
} }
@ -542,6 +545,21 @@ public class SystemVmTemplateRegistration {
} }
} }
public void updateSeededTemplateDetails(long templateId, long storeId, long size, long physicalSize) {
VMTemplateVO template = vmTemplateDao.findById(templateId);
template.setSize(size);
vmTemplateDao.update(template.getId(), template);
TemplateDataStoreVO templateDataStoreVO = templateDataStoreDao.findByStoreTemplate(storeId, template.getId());
templateDataStoreVO.setSize(size);
templateDataStoreVO.setPhysicalSize(physicalSize);
templateDataStoreVO.setLastUpdated(new Date(DateUtil.currentGMTTime().getTime()));
boolean updated = templateDataStoreDao.update(templateDataStoreVO.getId(), templateDataStoreVO);
if (!updated) {
throw new CloudRuntimeException("Failed to update template_store_ref entry for seeded systemVM template");
}
}
public void updateSystemVMEntries(Long templateId, Hypervisor.HypervisorType hypervisorType) { public void updateSystemVMEntries(Long templateId, Hypervisor.HypervisorType hypervisorType) {
vmInstanceDao.updateSystemVmTemplateId(templateId, hypervisorType); vmInstanceDao.updateSystemVmTemplateId(templateId, hypervisorType);
} }
@ -555,7 +573,7 @@ public class SystemVmTemplateRegistration {
} }
} }
private static void readTemplateProperties(String path, SystemVMTemplateDetails details) { private static Pair<Long, Long> readTemplatePropertiesSizes(String path) {
File tmpFile = new File(path); File tmpFile = new File(path);
Long size = null; Long size = null;
Long physicalSize = 0L; Long physicalSize = 0L;
@ -574,8 +592,13 @@ public class SystemVmTemplateRegistration {
} catch (IOException ex) { } catch (IOException ex) {
LOGGER.warn("Failed to read from template.properties", ex); LOGGER.warn("Failed to read from template.properties", ex);
} }
details.setSize(size); return new Pair<>(size, physicalSize);
details.setPhysicalSize(physicalSize); }
public static void readTemplateProperties(String path, SystemVMTemplateDetails details) {
Pair<Long, Long> templateSizes = readTemplatePropertiesSizes(path);
details.setSize(templateSizes.first());
details.setPhysicalSize(templateSizes.second());
} }
private void updateTemplateTablesOnFailure(long templateId) { private void updateTemplateTablesOnFailure(long templateId) {
@ -799,7 +822,7 @@ public class SystemVmTemplateRegistration {
TemplateDataStoreVO templateDataStoreVO = templateDataStoreDao.findByStoreTemplate(storeUrlAndId.second(), templateId); TemplateDataStoreVO templateDataStoreVO = templateDataStoreDao.findByStoreTemplate(storeUrlAndId.second(), templateId);
if (templateDataStoreVO != null) { if (templateDataStoreVO != null) {
String installPath = templateDataStoreVO.getInstallPath(); String installPath = templateDataStoreVO.getInstallPath();
if (validateIfSeeded(storeUrlAndId.first(), installPath, nfsVersion)) { if (validateIfSeeded(templateDataStoreVO, storeUrlAndId.first(), installPath, nfsVersion)) {
continue; continue;
} }
} }

View File

@ -23,18 +23,18 @@ import javax.persistence.GenerationType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.api.ResourceDetail;
@Entity @Entity
@Table(name = "account_details") @Table(name = "account_details")
public class AccountDetailVO implements InternalIdentity { public class AccountDetailVO implements ResourceDetail {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id") @Column(name = "id")
private long id; private long id;
@Column(name = "account_id") @Column(name = "account_id")
private long accountId; private long resourceId;
@Column(name = "name") @Column(name = "name")
private String name; private String name;
@ -46,13 +46,14 @@ public class AccountDetailVO implements InternalIdentity {
} }
public AccountDetailVO(long accountId, String name, String value) { public AccountDetailVO(long accountId, String name, String value) {
this.accountId = accountId; this.resourceId = accountId;
this.name = name; this.name = name;
this.value = value; this.value = value;
} }
public long getAccountId() { @Override
return accountId; public long getResourceId() {
return resourceId;
} }
public String getName() { public String getName() {
@ -63,6 +64,11 @@ public class AccountDetailVO implements InternalIdentity {
return value; return value;
} }
@Override
public boolean isDisplay() {
return true;
}
public void setValue(String value) { public void setValue(String value) {
this.value = value; this.value = value;
} }

View File

@ -19,8 +19,9 @@ package com.cloud.user;
import java.util.Map; import java.util.Map;
import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
public interface AccountDetailsDao extends GenericDao<AccountDetailVO, Long> { public interface AccountDetailsDao extends GenericDao<AccountDetailVO, Long>, ResourceDetailsDao<AccountDetailVO> {
Map<String, String> findDetails(long accountId); Map<String, String> findDetails(long accountId);
void persist(long accountId, Map<String, String> details); void persist(long accountId, Map<String, String> details);
@ -34,6 +35,4 @@ public interface AccountDetailsDao extends GenericDao<AccountDetailVO, Long> {
* they will get created * they will get created
*/ */
void update(long accountId, Map<String, String> details); void update(long accountId, Map<String, String> details);
String getActualValue(AccountDetailVO accountDetailVO);
} }

View File

@ -27,22 +27,20 @@ import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.ConfigKey.Scope; import org.apache.cloudstack.framework.config.ConfigKey.Scope;
import org.apache.cloudstack.framework.config.ScopedConfigStorage; import org.apache.cloudstack.framework.config.ScopedConfigStorage;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
import com.cloud.domain.DomainDetailVO; import com.cloud.domain.DomainDetailVO;
import com.cloud.domain.DomainVO; import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao; import com.cloud.domain.dao.DomainDao;
import com.cloud.domain.dao.DomainDetailsDao; import com.cloud.domain.dao.DomainDetailsDao;
import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.AccountDao;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.QueryBuilder; import com.cloud.utils.db.QueryBuilder;
import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.db.TransactionLegacy;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long> implements AccountDetailsDao, ScopedConfigStorage { public class AccountDetailsDaoImpl extends ResourceDetailsDaoBase<AccountDetailVO> implements AccountDetailsDao, ScopedConfigStorage {
protected final SearchBuilder<AccountDetailVO> accountSearch; protected final SearchBuilder<AccountDetailVO> accountSearch;
@Inject @Inject
@ -56,16 +54,16 @@ public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long>
protected AccountDetailsDaoImpl() { protected AccountDetailsDaoImpl() {
accountSearch = createSearchBuilder(); accountSearch = createSearchBuilder();
accountSearch.and("accountId", accountSearch.entity().getAccountId(), Op.EQ); accountSearch.and("accountId", accountSearch.entity().getResourceId(), Op.EQ);
accountSearch.done(); accountSearch.done();
} }
@Override @Override
public Map<String, String> findDetails(long accountId) { public Map<String, String> findDetails(long accountId) {
QueryBuilder<AccountDetailVO> sc = QueryBuilder.create(AccountDetailVO.class); QueryBuilder<AccountDetailVO> sc = QueryBuilder.create(AccountDetailVO.class);
sc.and(sc.entity().getAccountId(), Op.EQ, accountId); sc.and(sc.entity().getResourceId(), Op.EQ, accountId);
List<AccountDetailVO> results = sc.list(); List<AccountDetailVO> results = sc.list();
Map<String, String> details = new HashMap<String, String>(results.size()); Map<String, String> details = new HashMap<>(results.size());
for (AccountDetailVO r : results) { for (AccountDetailVO r : results) {
details.put(r.getName(), r.getValue()); details.put(r.getName(), r.getValue());
} }
@ -89,11 +87,16 @@ public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long>
@Override @Override
public AccountDetailVO findDetail(long accountId, String name) { public AccountDetailVO findDetail(long accountId, String name) {
QueryBuilder<AccountDetailVO> sc = QueryBuilder.create(AccountDetailVO.class); QueryBuilder<AccountDetailVO> sc = QueryBuilder.create(AccountDetailVO.class);
sc.and(sc.entity().getAccountId(), Op.EQ, accountId); sc.and(sc.entity().getResourceId(), Op.EQ, accountId);
sc.and(sc.entity().getName(), Op.EQ, name); sc.and(sc.entity().getName(), Op.EQ, name);
return sc.find(); return sc.find();
} }
@Override
public void addDetail(long resourceId, String key, String value, boolean display) {
super.addDetail(new AccountDetailVO(resourceId, key, value));
}
@Override @Override
public void deleteDetails(long accountId) { public void deleteDetails(long accountId) {
SearchCriteria<AccountDetailVO> sc = accountSearch.create(); SearchCriteria<AccountDetailVO> sc = accountSearch.create();
@ -153,13 +156,4 @@ public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long>
} }
return value; return value;
} }
@Override
public String getActualValue(AccountDetailVO accountDetailVO) {
ConfigurationVO configurationVO = _configDao.findByName(accountDetailVO.getName());
if (configurationVO != null && configurationVO.isEncrypted()) {
return DBEncryptionUtil.decrypt(accountDetailVO.getValue());
}
return accountDetailVO.getValue();
}
} }

View File

@ -53,7 +53,7 @@ public interface ResourceDetailsDao<R extends ResourceDetail> extends GenericDao
* Removes all details for the resource specified * Removes all details for the resource specified
* @param resourceId * @param resourceId
*/ */
public void removeDetails(long resourceId); void removeDetails(long resourceId);
/** /**
@ -76,7 +76,7 @@ public interface ResourceDetailsDao<R extends ResourceDetail> extends GenericDao
* @param resourceId * @param resourceId
* @return list of details each implementing ResourceDetail interface * @return list of details each implementing ResourceDetail interface
*/ */
public List<R> listDetails(long resourceId); List<R> listDetails(long resourceId);
/** /**
* List details for resourceId having display field = forDisplay value passed in * List details for resourceId having display field = forDisplay value passed in
@ -84,21 +84,23 @@ public interface ResourceDetailsDao<R extends ResourceDetail> extends GenericDao
* @param forDisplay * @param forDisplay
* @return * @return
*/ */
public List<R> listDetails(long resourceId, boolean forDisplay); List<R> listDetails(long resourceId, boolean forDisplay);
public Map<String, String> listDetailsKeyPairs(long resourceId); Map<String, String> listDetailsKeyPairs(long resourceId);
Map<String, String> listDetailsKeyPairs(long resourceId, List<String> keys); Map<String, String> listDetailsKeyPairs(long resourceId, List<String> keys);
public Map<String, String> listDetailsKeyPairs(long resourceId, boolean forDisplay); Map<String, String> listDetailsKeyPairs(long resourceId, boolean forDisplay);
Map<String, Boolean> listDetailsVisibility(long resourceId); Map<String, Boolean> listDetailsVisibility(long resourceId);
public void saveDetails(List<R> details); void saveDetails(List<R> details);
public void addDetail(long resourceId, String key, String value, boolean display); void addDetail(long resourceId, String key, String value, boolean display);
public List<Long> findResourceIdsByNameAndValueIn(String name, Object[] values); List<Long> findResourceIdsByNameAndValueIn(String name, Object[] values);
public long batchExpungeForResources(List<Long> ids, Long batchSize); long batchExpungeForResources(List<Long> ids, Long batchSize);
String getActualValue(ResourceDetail resourceDetail);
} }

View File

@ -21,9 +21,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.cloudstack.api.ResourceDetail;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchBuilder;
@ -31,7 +31,17 @@ import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.db.TransactionLegacy;
import org.apache.cloudstack.api.ResourceDetail;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
import javax.inject.Inject;
public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends GenericDaoBase<R, Long> implements ResourceDetailsDao<R> { public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends GenericDaoBase<R, Long> implements ResourceDetailsDao<R> {
@Inject
private ConfigurationDao configDao;
private SearchBuilder<R> AllFieldsSearch; private SearchBuilder<R> AllFieldsSearch;
public ResourceDetailsDaoBase() { public ResourceDetailsDaoBase() {
@ -76,8 +86,7 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
sc.setParameters("value", value); sc.setParameters("value", value);
} }
List<R> results = search(sc, null); return search(sc, null);
return results;
} }
public Map<String, String> listDetailsKeyPairs(long resourceId) { public Map<String, String> listDetailsKeyPairs(long resourceId) {
@ -85,7 +94,7 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
sc.setParameters("resourceId", resourceId); sc.setParameters("resourceId", resourceId);
List<R> results = search(sc, null); List<R> results = search(sc, null);
Map<String, String> details = new HashMap<String, String>(results.size()); Map<String, String> details = new HashMap<>(results.size());
for (R result : results) { for (R result : results) {
details.put(result.getName(), result.getValue()); details.put(result.getName(), result.getValue());
} }
@ -122,8 +131,7 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
SearchCriteria<R> sc = AllFieldsSearch.create(); SearchCriteria<R> sc = AllFieldsSearch.create();
sc.setParameters("resourceId", resourceId); sc.setParameters("resourceId", resourceId);
List<R> results = search(sc, null); return search(sc, null);
return results;
} }
public void removeDetails(long resourceId) { public void removeDetails(long resourceId) {
@ -185,7 +193,7 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
sc.setParameters("display", forDisplay); sc.setParameters("display", forDisplay);
List<R> results = search(sc, null); List<R> results = search(sc, null);
Map<String, String> details = new HashMap<String, String>(results.size()); Map<String, String> details = new HashMap<>(results.size());
for (R result : results) { for (R result : results) {
details.put(result.getName(), result.getValue()); details.put(result.getName(), result.getValue());
} }
@ -197,8 +205,7 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
sc.setParameters("resourceId", resourceId); sc.setParameters("resourceId", resourceId);
sc.setParameters("display", forDisplay); sc.setParameters("display", forDisplay);
List<R> results = search(sc, null); return search(sc, null);
return results;
} }
@Override @Override
@ -230,4 +237,13 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
sc.setParameters("ids", ids.toArray()); sc.setParameters("ids", ids.toArray());
return batchExpunge(sc, batchSize); return batchExpunge(sc, batchSize);
} }
@Override
public String getActualValue(ResourceDetail resourceDetail) {
ConfigurationVO configurationVO = configDao.findByName(resourceDetail.getName());
if (configurationVO != null && configurationVO.isEncrypted()) {
return DBEncryptionUtil.decrypt(resourceDetail.getValue());
}
return resourceDetail.getValue();
}
} }

View File

@ -36,7 +36,6 @@ import com.cloud.utils.db.TransactionLegacy;
@Component @Component
public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase<ImageStoreDetailVO> implements ImageStoreDetailsDao, ScopedConfigStorage { public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase<ImageStoreDetailVO> implements ImageStoreDetailsDao, ScopedConfigStorage {
protected final SearchBuilder<ImageStoreDetailVO> storeSearch; protected final SearchBuilder<ImageStoreDetailVO> storeSearch;
public ImageStoreDetailsDaoImpl() { public ImageStoreDetailsDaoImpl() {
@ -67,7 +66,7 @@ public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase<ImageStoreD
sc.setParameters("store", storeId); sc.setParameters("store", storeId);
List<ImageStoreDetailVO> details = listBy(sc); List<ImageStoreDetailVO> details = listBy(sc);
Map<String, String> detailsMap = new HashMap<String, String>(); Map<String, String> detailsMap = new HashMap<>();
for (ImageStoreDetailVO detail : details) { for (ImageStoreDetailVO detail : details) {
String name = detail.getName(); String name = detail.getName();
String value = detail.getValue(); String value = detail.getValue();
@ -110,9 +109,14 @@ public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase<ImageStoreD
return vo == null ? null : vo.getValue(); return vo == null ? null : vo.getValue();
} }
@Override
public String getConfigValue(long id, ConfigKey<?> key) {
ImageStoreDetailVO vo = findDetail(id, key.key());
return vo == null ? null : getActualValue(vo);
}
@Override @Override
public void addDetail(long resourceId, String key, String value, boolean display) { public void addDetail(long resourceId, String key, String value, boolean display) {
super.addDetail(new ImageStoreDetailVO(resourceId, key, value, display)); super.addDetail(new ImageStoreDetailVO(resourceId, key, value, display));
} }
} }

View File

@ -755,7 +755,7 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase<StoragePoolVO, Long>
if (keyword != null) { if (keyword != null) {
SearchCriteria<StoragePoolVO> ssc = createSearchCriteria(); SearchCriteria<StoragePoolVO> ssc = createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("poolType", SearchCriteria.Op.LIKE, new Storage.StoragePoolType("%" + keyword + "%")); ssc.addOr("poolType", SearchCriteria.Op.LIKE, "%" + keyword + "%");
sc.addAnd("name", SearchCriteria.Op.SC, ssc); sc.addAnd("name", SearchCriteria.Op.SC, ssc);
} }

View File

@ -40,6 +40,7 @@ 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.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; 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.EndPointSelector;
@ -1534,6 +1535,16 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
verifyFormat(templateInfo.getFormat()); verifyFormat(templateInfo.getFormat());
} }
// this blurb handles the case where the storage system can clone a volume from a template
String canCloneVolumeFromTemplate = templateInfo.getDataStore().getDriver().getCapabilities().get("CAN_CLONE_VOLUME_FROM_TEMPLATE");
if (canCloneVolumeFromTemplate != null && canCloneVolumeFromTemplate.toLowerCase().equals("true")) {
DataStoreDriver driver = templateInfo.getDataStore().getDriver();
driver.createAsync(volumeInfo.getDataStore(), volumeInfo, null);
volumeInfo = _volumeDataFactory.getVolume(volumeInfo.getId(), volumeInfo.getDataStore());
driver.copyAsync(templateInfo, volumeInfo, null);
return;
}
HostVO hostVO = null; HostVO hostVO = null;
final boolean computeClusterSupportsVolumeClone; final boolean computeClusterSupportsVolumeClone;
@ -1641,7 +1652,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
errMsg = "Create volume from template failed: " + ex.getMessage(); errMsg = "Create volume from template failed: " + ex.getMessage();
} }
throw new CloudRuntimeException(errMsg); throw new CloudRuntimeException(errMsg, ex);
} }
finally { finally {
if (copyCmdAnswer == null) { if (copyCmdAnswer == null) {
@ -2634,7 +2645,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
catch (Exception ex) { catch (Exception ex) {
errMsg = ex.getMessage(); errMsg = ex.getMessage();
throw new CloudRuntimeException(errMsg); throw new CloudRuntimeException(errMsg, ex);
} }
finally { finally {
if (copyCmdAnswer == null) { if (copyCmdAnswer == null) {

View File

@ -622,7 +622,7 @@ public class VolumeServiceImpl implements VolumeService {
try { try {
Thread.sleep(sleepTime * 1000); Thread.sleep(sleepTime * 1000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
logger.debug("waiting for template download been interrupted: " + e.toString()); logger.debug("waiting for template download been interrupted: " + e);
} }
tries--; tries--;
} }
@ -691,7 +691,6 @@ public class VolumeServiceImpl implements VolumeService {
} }
_tmpltPoolDao.releaseFromLockTable(templatePoolRefId); _tmpltPoolDao.releaseFromLockTable(templatePoolRefId);
} }
return;
} }
protected Void managedCopyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, ManagedCreateBaseImageContext<VolumeApiResult> context) { protected Void managedCopyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, ManagedCreateBaseImageContext<VolumeApiResult> context) {
@ -1039,7 +1038,7 @@ public class VolumeServiceImpl implements VolumeService {
try { try {
grantAccess(templateOnPrimary, destHost, destPrimaryDataStore); grantAccess(templateOnPrimary, destHost, destPrimaryDataStore);
} catch (Exception e) { } catch (Exception e) {
throw new StorageAccessException(String.format("Unable to grant access to template: %s on host: %s", templateOnPrimary.getImage(), destHost)); throw new StorageAccessException(String.format("Unable to grant access to template: %s on host: %s", templateOnPrimary.getImage(), destHost), e);
} }
templateOnPrimary.processEvent(Event.CopyingRequested); templateOnPrimary.processEvent(Event.CopyingRequested);
@ -1161,7 +1160,7 @@ public class VolumeServiceImpl implements VolumeService {
try { try {
grantAccess(srcTemplateOnPrimary, destHost, destPrimaryDataStore); grantAccess(srcTemplateOnPrimary, destHost, destPrimaryDataStore);
} catch (Exception e) { } catch (Exception e) {
throw new StorageAccessException(String.format("Unable to grant access to src template: %s on host: %s", srcTemplateOnPrimary, destHost)); throw new StorageAccessException(String.format("Unable to grant access to src template: %s on host: %s", srcTemplateOnPrimary, destHost), e);
} }
_volumeDetailsDao.addDetail(volumeInfo.getId(), volumeDetailKey, String.valueOf(templatePoolRef.getId()), false); _volumeDetailsDao.addDetail(volumeInfo.getId(), volumeDetailKey, String.valueOf(templatePoolRef.getId()), false);
@ -1408,7 +1407,7 @@ public class VolumeServiceImpl implements VolumeService {
try { try {
grantAccess(templateOnPrimary, destHost, destPrimaryDataStore); grantAccess(templateOnPrimary, destHost, destPrimaryDataStore);
} catch (Exception e) { } catch (Exception e) {
throw new StorageAccessException(String.format("Unable to grant access to template: %s on host: %s", templateOnPrimary, destHost)); throw new StorageAccessException(String.format("Unable to grant access to template: %s on host: %s", templateOnPrimary, destHost), e);
} }
templateOnPrimary.processEvent(Event.CopyingRequested); templateOnPrimary.processEvent(Event.CopyingRequested);

View File

@ -39,7 +39,7 @@ import com.cloud.utils.mgmt.ManagementBean;
public class CloudStackExtendedLifeCycle extends AbstractBeanCollector { public class CloudStackExtendedLifeCycle extends AbstractBeanCollector {
Map<Integer, Set<ComponentLifecycle>> sorted = new TreeMap<Integer, Set<ComponentLifecycle>>(); Map<Integer, Set<ComponentLifecycle>> sorted = new TreeMap<>();
public CloudStackExtendedLifeCycle() { public CloudStackExtendedLifeCycle() {
super(); super();
@ -80,13 +80,8 @@ public class CloudStackExtendedLifeCycle extends AbstractBeanCollector {
ManagementBean mbean = (ManagementBean)lifecycle; ManagementBean mbean = (ManagementBean)lifecycle;
try { try {
JmxUtil.registerMBean(mbean); JmxUtil.registerMBean(mbean);
} catch (MalformedObjectNameException e) { } catch (MalformedObjectNameException | InstanceAlreadyExistsException |
logger.warn("Unable to register MBean: " + mbean.getName(), e); MBeanRegistrationException | NotCompliantMBeanException e) {
} catch (InstanceAlreadyExistsException e) {
logger.warn("Unable to register MBean: " + mbean.getName(), e);
} catch (MBeanRegistrationException e) {
logger.warn("Unable to register MBean: " + mbean.getName(), e);
} catch (NotCompliantMBeanException e) {
logger.warn("Unable to register MBean: " + mbean.getName(), e); logger.warn("Unable to register MBean: " + mbean.getName(), e);
} }
logger.info("Registered MBean: " + mbean.getName()); logger.info("Registered MBean: " + mbean.getName());
@ -129,6 +124,7 @@ public class CloudStackExtendedLifeCycle extends AbstractBeanCollector {
throw new CloudRuntimeException(e); throw new CloudRuntimeException(e);
} catch (Exception e) { } catch (Exception e) {
logger.error("Error on configuring bean {} - {}", lifecycle.getName(), e.getMessage(), e); logger.error("Error on configuring bean {} - {}", lifecycle.getName(), e.getMessage(), e);
throw new CloudRuntimeException(e);
} }
} }
}); });
@ -141,7 +137,7 @@ public class CloudStackExtendedLifeCycle extends AbstractBeanCollector {
Set<ComponentLifecycle> set = sorted.get(lifecycle.getRunLevel()); Set<ComponentLifecycle> set = sorted.get(lifecycle.getRunLevel());
if (set == null) { if (set == null) {
set = new HashSet<ComponentLifecycle>(); set = new HashSet<>();
sorted.put(lifecycle.getRunLevel(), set); sorted.put(lifecycle.getRunLevel(), set);
} }
@ -169,12 +165,7 @@ public class CloudStackExtendedLifeCycle extends AbstractBeanCollector {
} }
} }
@Override private interface WithComponentLifeCycle {
public int getPhase() {
return 2000;
}
private static interface WithComponentLifeCycle {
public void with(ComponentLifecycle lifecycle); public void with(ComponentLifecycle lifecycle);
} }
} }

View File

@ -48,7 +48,7 @@ public class RegistryLifecycle implements BeanPostProcessor, SmartLifecycle, App
* can use this. * can use this.
*/ */
String registryBeanName; String registryBeanName;
Set<Object> beans = new HashSet<Object>(); Set<Object> beans = new HashSet<>();
Class<?> typeClass; Class<?> typeClass;
ApplicationContext applicationContext; ApplicationContext applicationContext;
Set<String> excludes = null; Set<String> excludes = null;
@ -79,7 +79,7 @@ public class RegistryLifecycle implements BeanPostProcessor, SmartLifecycle, App
protected synchronized void loadExcluded() { protected synchronized void loadExcluded() {
Properties props = applicationContext.getBean("DefaultConfigProperties", Properties.class); Properties props = applicationContext.getBean("DefaultConfigProperties", Properties.class);
excludes = new HashSet<String>(); excludes = new HashSet<>();
for (String exclude : props.getProperty(EXTENSION_EXCLUDE, "").trim().split("\\s*,\\s*")) { for (String exclude : props.getProperty(EXTENSION_EXCLUDE, "").trim().split("\\s*,\\s*")) {
if (StringUtils.hasText(exclude)) { if (StringUtils.hasText(exclude)) {
excludes.add(exclude); excludes.add(exclude);
@ -109,10 +109,15 @@ public class RegistryLifecycle implements BeanPostProcessor, SmartLifecycle, App
while (iter.hasNext()) { while (iter.hasNext()) {
Object next = iter.next(); Object next = iter.next();
if (registry.register(next)) { try {
logger.debug("Registered " + next); if (registry.register(next)) {
} else { logger.debug("Registered " + next);
iter.remove(); } else {
logger.warn("Bean registration failed for " + next.toString());
iter.remove();
}
} catch (Throwable e) {
logger.warn("Bean registration attempt resulted in an exception for " + next.toString(), e);
} }
} }
} }

View File

@ -47,7 +47,7 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API
private RoleService roleService; private RoleService roleService;
private List<PluggableService> services; private List<PluggableService> services;
private Map<RoleType, Set<String>> annotationRoleBasedApisMap = new HashMap<RoleType, Set<String>>(); private Map<RoleType, Set<String>> annotationRoleBasedApisMap = new HashMap<>();
private LazyCache<Long, Account> accountCache; private LazyCache<Long, Account> accountCache;
private LazyCache<Long, Pair<Role, List<RolePermission>>> rolePermissionsCache; private LazyCache<Long, Pair<Role, List<RolePermission>>> rolePermissionsCache;
@ -56,7 +56,7 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API
protected DynamicRoleBasedAPIAccessChecker() { protected DynamicRoleBasedAPIAccessChecker() {
super(); super();
for (RoleType roleType : RoleType.values()) { for (RoleType roleType : RoleType.values()) {
annotationRoleBasedApisMap.put(roleType, new HashSet<String>()); annotationRoleBasedApisMap.put(roleType, new HashSet<>());
} }
} }

View File

@ -3133,7 +3133,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
disk.setLogicalBlockIOSize(pool.getSupportedLogicalBlockSize()); disk.setLogicalBlockIOSize(pool.getSupportedLogicalBlockSize());
disk.setPhysicalBlockIOSize(pool.getSupportedPhysicalBlockSize()); disk.setPhysicalBlockIOSize(pool.getSupportedPhysicalBlockSize());
if (diskBusType == DiskDef.DiskBus.SCSI ) { if (diskBusType == DiskDef.DiskBus.SCSI || diskBusType == DiskDef.DiskBus.VIRTIOBLK) {
disk.setQemuDriver(true); disk.setQemuDriver(true);
disk.setDiscard(DiscardType.UNMAP); disk.setDiscard(DiscardType.UNMAP);
} }
@ -3204,7 +3204,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
disk.setCacheMode(DiskDef.DiskCacheMode.valueOf(volumeObjectTO.getCacheMode().toString().toUpperCase())); disk.setCacheMode(DiskDef.DiskCacheMode.valueOf(volumeObjectTO.getCacheMode().toString().toUpperCase()));
} }
if (volumeObjectTO.requiresEncryption()) { if (volumeObjectTO.requiresEncryption() &&
pool.getType().encryptionSupportMode() == Storage.EncryptionSupport.Hypervisor ) {
String secretUuid = createLibvirtVolumeSecret(conn, volumeObjectTO.getPath(), volumeObjectTO.getPassphrase()); String secretUuid = createLibvirtVolumeSecret(conn, volumeObjectTO.getPath(), volumeObjectTO.getPassphrase());
DiskDef.LibvirtDiskEncryptDetails encryptDetails = new DiskDef.LibvirtDiskEncryptDetails(secretUuid, QemuObject.EncryptFormat.enumValue(volumeObjectTO.getEncryptFormat())); DiskDef.LibvirtDiskEncryptDetails encryptDetails = new DiskDef.LibvirtDiskEncryptDetails(secretUuid, QemuObject.EncryptFormat.enumValue(volumeObjectTO.getEncryptFormat()));
disk.setLibvirtDiskEncryptDetails(encryptDetails); disk.setLibvirtDiskEncryptDetails(encryptDetails);

View File

@ -248,7 +248,9 @@ public class LibvirtVMDef {
guestDef.append("<boot dev='" + bo + "'/>\n"); guestDef.append("<boot dev='" + bo + "'/>\n");
} }
} }
guestDef.append("<smbios mode='sysinfo'/>\n"); if (_arch == null || !_arch.equals("aarch64")) {
guestDef.append("<smbios mode='sysinfo'/>\n");
}
guestDef.append("</os>\n"); guestDef.append("</os>\n");
if (iothreads) { if (iothreads) {
guestDef.append(String.format("<iothreads>%s</iothreads>", NUMBER_OF_IOTHREADS)); guestDef.append(String.format("<iothreads>%s</iothreads>", NUMBER_OF_IOTHREADS));
@ -678,7 +680,7 @@ public class LibvirtVMDef {
} }
public enum DiskBus { public enum DiskBus {
IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML("uml"), FDC("fdc"), SATA("sata"); IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML("uml"), FDC("fdc"), SATA("sata"), VIRTIOBLK("virtio-blk");
String _bus; String _bus;
DiskBus(String bus) { DiskBus(String bus) {

View File

@ -122,7 +122,10 @@ public final class LibvirtGetUnmanagedInstancesCommandWrapper extends CommandWra
instance.setName(domain.getName()); instance.setName(domain.getName());
instance.setCpuCores((int) LibvirtComputingResource.countDomainRunningVcpus(domain)); instance.setCpuCores((int) LibvirtComputingResource.countDomainRunningVcpus(domain));
instance.setCpuSpeed(parser.getCpuTuneDef().getShares()/instance.getCpuCores());
if (parser.getCpuTuneDef() != null && instance.getCpuCores() != null) {
instance.setCpuSpeed(parser.getCpuTuneDef().getShares()/instance.getCpuCores());
}
if (parser.getCpuModeDef() != null) { if (parser.getCpuModeDef() != null) {
instance.setCpuCoresPerSocket(parser.getCpuModeDef().getCoresPerSocket()); instance.setCpuCoresPerSocket(parser.getCpuModeDef().getCoresPerSocket());

View File

@ -125,6 +125,7 @@ import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtUtilitiesHelper;
import com.cloud.storage.JavaStorageLayer; import com.cloud.storage.JavaStorageLayer;
import com.cloud.storage.MigrationOptions; import com.cloud.storage.MigrationOptions;
import com.cloud.storage.ScopeType; import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageLayer; import com.cloud.storage.StorageLayer;
@ -161,7 +162,7 @@ public class KVMStorageProcessor implements StorageProcessor {
/** /**
* Time interval before rechecking virsh commands * Time interval before rechecking virsh commands
*/ */
private long waitDelayForVirshCommands = 1000l; private final long waitDelayForVirshCommands = 1000L;
public KVMStorageProcessor(final KVMStoragePoolManager storagePoolMgr, final LibvirtComputingResource resource) { public KVMStorageProcessor(final KVMStoragePoolManager storagePoolMgr, final LibvirtComputingResource resource) {
this.storagePoolMgr = storagePoolMgr; this.storagePoolMgr = storagePoolMgr;
@ -258,7 +259,7 @@ public class KVMStorageProcessor implements StorageProcessor {
logger.debug("Copying template to primary storage, template format is " + tmplVol.getFormat() ); logger.debug("Copying template to primary storage, template format is " + tmplVol.getFormat() );
final KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid()); final KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
KVMPhysicalDisk primaryVol = null; KVMPhysicalDisk primaryVol;
if (destData instanceof VolumeObjectTO) { if (destData instanceof VolumeObjectTO) {
final VolumeObjectTO volume = (VolumeObjectTO)destData; final VolumeObjectTO volume = (VolumeObjectTO)destData;
// pass along volume's target size if it's bigger than template's size, for storage types that copy template rather than cloning on deploy // pass along volume's target size if it's bigger than template's size, for storage types that copy template rather than cloning on deploy
@ -277,8 +278,13 @@ public class KVMStorageProcessor implements StorageProcessor {
String path = derivePath(primaryStore, destData, details); String path = derivePath(primaryStore, destData, details);
if (!storagePoolMgr.connectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), path, details)) { if (path == null) {
path = destTempl.getUuid();
}
if (path != null && !storagePoolMgr.connectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), path, details)) {
logger.warn("Failed to connect physical disk at path: {}, in storage pool [id: {}, name: {}]", path, primaryStore.getUuid(), primaryStore.getName()); logger.warn("Failed to connect physical disk at path: {}, in storage pool [id: {}, name: {}]", path, primaryStore.getUuid(), primaryStore.getName());
return new PrimaryStorageDownloadAnswer("Failed to spool template disk at path: " + path + ", in storage pool id: " + primaryStore.getUuid());
} }
primaryVol = storagePoolMgr.copyPhysicalDisk(tmplVol, path != null ? path : destTempl.getUuid(), primaryPool, cmd.getWaitInMillSeconds()); primaryVol = storagePoolMgr.copyPhysicalDisk(tmplVol, path != null ? path : destTempl.getUuid(), primaryPool, cmd.getWaitInMillSeconds());
@ -336,12 +342,13 @@ public class KVMStorageProcessor implements StorageProcessor {
} }
private String derivePath(PrimaryDataStoreTO primaryStore, DataTO destData, Map<String, String> details) { private String derivePath(PrimaryDataStoreTO primaryStore, DataTO destData, Map<String, String> details) {
String path = null; String path;
if (primaryStore.getPoolType() == StoragePoolType.FiberChannel) { if (primaryStore.getPoolType() == StoragePoolType.FiberChannel) {
path = destData.getPath(); path = destData.getPath();
} else { } else {
path = details != null ? details.get("managedStoreTarget") : null; path = details != null ? details.get("managedStoreTarget") : null;
} }
return path; return path;
} }
@ -390,8 +397,7 @@ public class KVMStorageProcessor implements StorageProcessor {
logger.debug("Using templates disk size of " + toHumanReadableSize(templateVol.getVirtualSize()) + "since size passed was " + toHumanReadableSize(size)); logger.debug("Using templates disk size of " + toHumanReadableSize(templateVol.getVirtualSize()) + "since size passed was " + toHumanReadableSize(size));
} }
final KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(templateVol, volUuid, primaryPool, timeout); return storagePoolMgr.copyPhysicalDisk(templateVol, volUuid, primaryPool, timeout);
return primaryVol;
} catch (final CloudRuntimeException e) { } catch (final CloudRuntimeException e) {
logger.error("Failed to download template to primary storage", e); logger.error("Failed to download template to primary storage", e);
return null; return null;
@ -410,9 +416,9 @@ public class KVMStorageProcessor implements StorageProcessor {
final DataStoreTO imageStore = template.getDataStore(); final DataStoreTO imageStore = template.getDataStore();
final VolumeObjectTO volume = (VolumeObjectTO)destData; final VolumeObjectTO volume = (VolumeObjectTO)destData;
final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore(); final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
KVMPhysicalDisk BaseVol = null; KVMPhysicalDisk BaseVol;
KVMStoragePool primaryPool = null; KVMStoragePool primaryPool;
KVMPhysicalDisk vol = null; KVMPhysicalDisk vol;
try { try {
primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid()); primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
@ -420,7 +426,7 @@ public class KVMStorageProcessor implements StorageProcessor {
String templatePath = template.getPath(); String templatePath = template.getPath();
if (primaryPool.getType() == StoragePoolType.CLVM) { if (primaryPool.getType() == StoragePoolType.CLVM) {
templatePath = ((NfsTO)imageStore).getUrl() + File.separator + templatePath; templatePath = imageStore.getUrl() + File.separator + templatePath;
vol = templateToPrimaryDownload(templatePath, primaryPool, volume.getUuid(), volume.getSize(), cmd.getWaitInMillSeconds()); vol = templateToPrimaryDownload(templatePath, primaryPool, volume.getUuid(), volume.getSize(), cmd.getWaitInMillSeconds());
} if (storagePoolMgr.supportsPhysicalDiskCopy(primaryPool.getType())) { } if (storagePoolMgr.supportsPhysicalDiskCopy(primaryPool.getType())) {
Map<String, String> details = primaryStore.getDetails(); Map<String, String> details = primaryStore.getDetails();
@ -778,15 +784,19 @@ public class KVMStorageProcessor implements StorageProcessor {
KVMStoragePool secondaryStorage = null; KVMStoragePool secondaryStorage = null;
String path = null;
try { try {
// look for options indicating an overridden path or IQN. Used when snapshots have to be // look for options indicating an overridden path or IQN. Used when snapshots have to be
// temporarily copied on the manaaged storage device before the actual copy to target object // temporarily copied on the manaaged storage device before the actual copy to target object
Map<String, String> details = cmd.getOptions(); Map<String, String> details = cmd.getOptions();
String path = details != null ? details.get(DiskTO.PATH) : null; path = details != null ? details.get(DiskTO.PATH) : null;
if (path == null) { if (path == null) {
path = details != null ? details.get(DiskTO.IQN) : null; path = details != null ? details.get(DiskTO.IQN) : null;
if (path == null) { if (path == null) {
new CloudRuntimeException("The 'path' or 'iqn' field must be specified."); path = srcData.getPath();
if (path == null) {
new CloudRuntimeException("The 'path' or 'iqn' field must be specified.");
}
} }
} }
@ -849,8 +859,6 @@ public class KVMStorageProcessor implements StorageProcessor {
loc.addFormat(info); loc.addFormat(info);
loc.save(); loc.save();
storagePoolMgr.disconnectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), path);
TemplateObjectTO newTemplate = new TemplateObjectTO(); TemplateObjectTO newTemplate = new TemplateObjectTO();
newTemplate.setPath(templateFolder + File.separator + templateName + ".qcow2"); newTemplate.setPath(templateFolder + File.separator + templateName + ".qcow2");
@ -870,6 +878,10 @@ public class KVMStorageProcessor implements StorageProcessor {
return new CopyCmdAnswer(ex.toString()); return new CopyCmdAnswer(ex.toString());
} finally { } finally {
if (path != null) {
storagePoolMgr.disconnectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), path);
}
if (secondaryStorage != null) { if (secondaryStorage != null) {
secondaryStorage.delete(); secondaryStorage.delete();
} }
@ -1045,7 +1057,9 @@ public class KVMStorageProcessor implements StorageProcessor {
command.add(NAME_OPTION, snapshotName); command.add(NAME_OPTION, snapshotName);
command.add("-p", snapshotDestPath); command.add("-p", snapshotDestPath);
descName = UUID.randomUUID().toString(); if (isCreatedFromVmSnapshot) {
descName = UUID.randomUUID().toString();
}
command.add("-t", descName); command.add("-t", descName);
final String result = command.execute(); final String result = command.execute();
@ -1415,12 +1429,14 @@ public class KVMStorageProcessor implements StorageProcessor {
if (disk.getDeviceType() == DeviceType.DISK) { if (disk.getDeviceType() == DeviceType.DISK) {
if (disk.getBusType() == DiskDef.DiskBus.SCSI) { if (disk.getBusType() == DiskDef.DiskBus.SCSI) {
busT = DiskDef.DiskBus.SCSI; busT = DiskDef.DiskBus.SCSI;
} else if (disk.getBusType() == DiskDef.DiskBus.VIRTIOBLK) {
busT = DiskDef.DiskBus.VIRTIOBLK;
} }
break; break;
} }
} }
diskdef = new DiskDef(); diskdef = new DiskDef();
if (busT == DiskDef.DiskBus.SCSI) { if (busT == DiskDef.DiskBus.SCSI || busT == DiskDef.DiskBus.VIRTIOBLK) {
diskdef.setQemuDriver(true); diskdef.setQemuDriver(true);
diskdef.setDiscard(DiscardType.UNMAP); diskdef.setDiscard(DiscardType.UNMAP);
} }
@ -1459,7 +1475,8 @@ public class KVMStorageProcessor implements StorageProcessor {
} }
} }
if (encryptDetails != null) { if (encryptDetails != null &&
attachingPool.getType().encryptionSupportMode() == Storage.EncryptionSupport.Hypervisor) {
diskdef.setLibvirtDiskEncryptDetails(encryptDetails); diskdef.setLibvirtDiskEncryptDetails(encryptDetails);
} }

View File

@ -162,6 +162,13 @@ public abstract class MultipathSCSIAdapterBase implements StorageAdaptor {
KVMPhysicalDisk disk = new KVMPhysicalDisk(address.getPath(), address.toString(), pool); KVMPhysicalDisk disk = new KVMPhysicalDisk(address.getPath(), address.toString(), pool);
disk.setFormat(QemuImg.PhysicalDiskFormat.RAW); disk.setFormat(QemuImg.PhysicalDiskFormat.RAW);
// validate we have a connection, if not we need to connect first.
if (!isConnected(address.getPath())) {
if (!connectPhysicalDisk(address, pool, null)) {
throw new CloudRuntimeException("Unable to connect to volume " + address.getPath());
}
}
long diskSize = getPhysicalDiskSize(address.getPath()); long diskSize = getPhysicalDiskSize(address.getPath());
disk.setSize(diskSize); disk.setSize(diskSize);
disk.setVirtualSize(diskSize); disk.setVirtualSize(diskSize);
@ -199,6 +206,10 @@ public abstract class MultipathSCSIAdapterBase implements StorageAdaptor {
// we expect WWN values in the volumePath so need to convert it to an actual physical path // we expect WWN values in the volumePath so need to convert it to an actual physical path
AddressInfo address = this.parseAndValidatePath(volumePath); AddressInfo address = this.parseAndValidatePath(volumePath);
return connectPhysicalDisk(address, pool, details);
}
private boolean connectPhysicalDisk(AddressInfo address, KVMStoragePool pool, Map<String, String> details) {
// validate we have a connection id - we can't proceed without that // validate we have a connection id - we can't proceed without that
if (address.getConnectionId() == null) { if (address.getConnectionId() == null) {
LOGGER.error("Unable to connect volume with address [" + address.getPath() + "] of the storage pool: " + pool.getUuid() + " - connection id is not set in provided path"); LOGGER.error("Unable to connect volume with address [" + address.getPath() + "] of the storage pool: " + pool.getUuid() + " - connection id is not set in provided path");
@ -510,6 +521,18 @@ public abstract class MultipathSCSIAdapterBase implements StorageAdaptor {
return false; return false;
} }
boolean isConnected(String path) {
// run a command to test if this is a binary device at this path
Script blockTest = new Script("/bin/test", LOGGER);
blockTest.add("-b", path);
blockTest.execute();
int rc = blockTest.getExitValue();
if (rc == 0) {
return true;
}
return false;
}
long getPhysicalDiskSize(String diskPath) { long getPhysicalDiskSize(String diskPath) {
if (StringUtils.isEmpty(diskPath)) { if (StringUtils.isEmpty(diskPath)) {
return 0; return 0;

View File

@ -6531,4 +6531,14 @@ public class LibvirtComputingResourceTest {
assertEquals(DiskDef.DiscardType.UNMAP, rootDisk.getDiscard()); assertEquals(DiskDef.DiscardType.UNMAP, rootDisk.getDiscard());
} }
} }
@Test
public void testGetDiskModelFromVMDetailVirtioBlk() {
VirtualMachineTO virtualMachineTO = Mockito.mock(VirtualMachineTO.class);
Map<String, String> details = new HashMap<>();
details.put(VmDetailConstants.ROOT_DISK_CONTROLLER, "virtio-blk");
Mockito.when(virtualMachineTO.getDetails()).thenReturn(details);
DiskDef.DiskBus diskBus = libvirtComputingResourceSpy.getDiskModelFromVMDetail(virtualMachineTO);
assertEquals(DiskDef.DiskBus.VIRTIOBLK, diskBus);
}
} }

View File

@ -27,6 +27,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import com.cloud.agent.api.CleanupVMCommand;
import javax.inject.Inject; import javax.inject.Inject;
import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.NfsTO;
@ -370,6 +371,13 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
return tokens[0] + "@" + vCenterIp; return tokens[0] + "@" + vCenterIp;
} }
@Override public List<Command> finalizeExpunge(VirtualMachine vm) {
List<Command> commands = new ArrayList<Command>();
final CleanupVMCommand cleanupVMCommand = new CleanupVMCommand(vm.getInstanceName(), true);
commands.add(cleanupVMCommand);
return commands;
}
@Override public List<Command> finalizeExpungeNics(VirtualMachine vm, List<NicProfile> nics) { @Override public List<Command> finalizeExpungeNics(VirtualMachine vm, List<NicProfile> nics) {
List<Command> commands = new ArrayList<Command>(); List<Command> commands = new ArrayList<Command>();
List<NicVO> nicVOs = nicDao.listByVmId(vm.getId()); List<NicVO> nicVOs = nicDao.listByVmId(vm.getId());

View File

@ -22,12 +22,15 @@ import com.cloud.dc.VmwareDatacenterVO;
import com.cloud.dc.VsphereStoragePolicy; import com.cloud.dc.VsphereStoragePolicy;
import com.cloud.exception.DiscoveryException; import com.cloud.exception.DiscoveryException;
import com.cloud.exception.ResourceInUseException; import com.cloud.exception.ResourceInUseException;
import com.cloud.hypervisor.vmware.mo.HostMO;
import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePool;
import com.cloud.utils.Pair;
import com.cloud.utils.component.PluggableService; import com.cloud.utils.component.PluggableService;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd; import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcVmsCmd; import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcVmsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcHostsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd; import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePoliciesCmd; import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePoliciesCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd; import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd;
@ -53,5 +56,7 @@ public interface VmwareDatacenterService extends PluggableService {
List<StoragePool> listVsphereStoragePolicyCompatibleStoragePools(ListVsphereStoragePolicyCompatiblePoolsCmd cmd); List<StoragePool> listVsphereStoragePolicyCompatibleStoragePools(ListVsphereStoragePolicyCompatiblePoolsCmd cmd);
List<UnmanagedInstanceTO> listVMsInDatacenter(ListVmwareDcVmsCmd cmd); List<HostMO> listHostsInDatacenter(ListVmwareDcHostsCmd cmd);
Pair<String, List<UnmanagedInstanceTO>> listVMsInDatacenter(ListVmwareDcVmsCmd cmd);
} }

View File

@ -19,10 +19,12 @@ package com.cloud.hypervisor.vmware.manager;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.rmi.RemoteException; import java.rmi.RemoteException;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
@ -43,10 +45,11 @@ import javax.inject.Inject;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import javax.persistence.EntityExistsException; import javax.persistence.EntityExistsException;
import com.cloud.hypervisor.vmware.util.VmwareClient;
import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd; import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcVmsCmd; import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcVmsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcHostsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcItems;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd; import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePoliciesCmd; import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePoliciesCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd; import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd;
@ -86,6 +89,7 @@ import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.ClusterVO; import com.cloud.dc.ClusterVO;
import com.cloud.dc.ClusterVSMMapVO; import com.cloud.dc.ClusterVSMMapVO;
import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenterVO;
import com.cloud.dc.VmwareDatacenter;
import com.cloud.dc.VsphereStoragePolicy; import com.cloud.dc.VsphereStoragePolicy;
import com.cloud.dc.VsphereStoragePolicyVO; import com.cloud.dc.VsphereStoragePolicyVO;
import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.ClusterDao;
@ -111,7 +115,8 @@ import com.cloud.hypervisor.HypervisorGuruManager;
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
import com.cloud.hypervisor.vmware.LegacyZoneVO; import com.cloud.hypervisor.vmware.LegacyZoneVO;
import com.cloud.hypervisor.vmware.VmwareCleanupMaid; import com.cloud.hypervisor.vmware.VmwareCleanupMaid;
import com.cloud.dc.VmwareDatacenter; import com.cloud.hypervisor.vmware.util.VmwareClient;
import com.cloud.hypervisor.vmware.util.VmwareClientException;
import com.cloud.hypervisor.vmware.VmwareDatacenterService; import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.dc.VmwareDatacenterVO; import com.cloud.dc.VmwareDatacenterVO;
import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMap; import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMap;
@ -168,9 +173,16 @@ import com.cloud.utils.ssh.SshHelper;
import com.cloud.vm.DomainRouterVO; import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.dao.UserVmCloneSettingDao; import com.cloud.vm.dao.UserVmCloneSettingDao;
import com.cloud.vm.dao.VMInstanceDao; import com.cloud.vm.dao.VMInstanceDao;
// TODO move these items upstream?
import com.vmware.pbm.PbmProfile; import com.vmware.pbm.PbmProfile;
import com.vmware.vim25.AboutInfo; import com.vmware.vim25.AboutInfo;
import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.InvalidLocaleFaultMsg;
import com.vmware.vim25.InvalidLoginFaultMsg;
import com.vmware.vim25.RuntimeFaultFaultMsg;
import com.vmware.vim25.InvalidPropertyFaultMsg;
import org.jetbrains.annotations.NotNull;
public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener, VmwareDatacenterService, Configurable { public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener, VmwareDatacenterService, Configurable {
@ -245,11 +257,11 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
private StorageLayer _storage; private StorageLayer _storage;
private final String _privateNetworkVSwitchName = "vSwitch0"; private final String _privateNetworkVSwitchName = "vSwitch0";
private int _portsPerDvPortGroup = DEFAULT_PORTS_PER_DV_PORT_GROUP; private final int _portsPerDvPortGroup = DEFAULT_PORTS_PER_DV_PORT_GROUP;
private boolean _fullCloneFlag; private boolean _fullCloneFlag;
private boolean _instanceNameFlag; private boolean _instanceNameFlag;
private String _serviceConsoleName; private String _serviceConsoleName;
private String _managemetPortGroupName; private String _managementPortGroupName;
private String _defaultSystemVmNicAdapterType = VirtualEthernetCardType.E1000.toString(); private String _defaultSystemVmNicAdapterType = VirtualEthernetCardType.E1000.toString();
private String _recycleHungWorker = "false"; private String _recycleHungWorker = "false";
private int _additionalPortRangeStart; private int _additionalPortRangeStart;
@ -263,7 +275,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
private final Random _rand = new Random(System.currentTimeMillis()); private final Random _rand = new Random(System.currentTimeMillis());
private static ScheduledExecutorService templateCleanupScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vmware-FullyClonedTemplateCheck"));; private static final ScheduledExecutorService templateCleanupScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vmware-FullyClonedTemplateCheck"));
private final VmwareStorageManager _storageMgr; private final VmwareStorageManager _storageMgr;
private final GlobalLock _exclusiveOpLock = GlobalLock.getInternLock("vmware.exclusive.op"); private final GlobalLock _exclusiveOpLock = GlobalLock.getInternLock("vmware.exclusive.op");
@ -347,9 +359,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
_serviceConsoleName = "Service Console"; _serviceConsoleName = "Service Console";
} }
_managemetPortGroupName = _configDao.getValue(Config.VmwareManagementPortGroup.key()); _managementPortGroupName = _configDao.getValue(Config.VmwareManagementPortGroup.key());
if (_managemetPortGroupName == null) { if (_managementPortGroupName == null) {
_managemetPortGroupName = "Management Network"; _managementPortGroupName = "Management Network";
} }
_defaultSystemVmNicAdapterType = _configDao.getValue(Config.VmwareSystemVmNicDeviceType.key()); _defaultSystemVmNicAdapterType = _configDao.getValue(Config.VmwareSystemVmNicDeviceType.key());
@ -448,7 +460,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
logger.info("Preparing network on host " + hostMo.getContext().toString() + " for " + privateTrafficLabel); logger.info("Preparing network on host " + hostMo.getContext().toString() + " for " + privateTrafficLabel);
VirtualSwitchType vsType = VirtualSwitchType.getType(vSwitchType); VirtualSwitchType vsType = VirtualSwitchType.getType(vSwitchType);
//The management network is probably always going to be a physical network with islation type of vlans, so assume BroadcastDomainType VLAN //The management network is probably always going to be a physical network with isolation type of vlans, so assume BroadcastDomainType VLAN
if (VirtualSwitchType.StandardVirtualSwitch == vsType) { if (VirtualSwitchType.StandardVirtualSwitch == vsType) {
HypervisorHostHelper.prepareNetwork(vSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false, BroadcastDomainType.Vlan, null, null); HypervisorHostHelper.prepareNetwork(vSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false, BroadcastDomainType.Vlan, null, null);
} }
@ -457,7 +469,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
AboutInfo about = hostMo.getHostAboutInfo(); AboutInfo about = hostMo.getHostAboutInfo();
if (about != null) { if (about != null) {
String version = about.getApiVersion(); String version = about.getApiVersion();
if (version != null && (version.equals("4.0") || version.equals("4.1")) && _portsPerDvPortGroup < DEFAULT_PORTS_PER_DV_PORT_GROUP_VSPHERE4_x) { if (version != null && (version.equals("4.0") || version.equals("4.1")) ) { // && _portsPerDvPortGroup < DEFAULT_PORTS_PER_DV_PORT_GROUP_VSPHERE4_x)
portsPerDvPortGroup = DEFAULT_PORTS_PER_DV_PORT_GROUP_VSPHERE4_x; portsPerDvPortGroup = DEFAULT_PORTS_PER_DV_PORT_GROUP_VSPHERE4_x;
} }
} }
@ -480,7 +492,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
} }
URI uriForHost = new URI(UriUtils.encodeURIComponent(clusterDetails.get("url") + "/" + host.getName())); URI uriForHost = new URI(UriUtils.encodeURIComponent(clusterDetails.get("url") + "/" + host.getName()));
morSrcHost = serviceContext.getHostMorByPath(URLDecoder.decode(uriForHost.getPath(), "UTF-8")); morSrcHost = serviceContext.getHostMorByPath(URLDecoder.decode(uriForHost.getPath(), StandardCharsets.UTF_8));
if (morSrcHost == null) { if (morSrcHost == null) {
return null; return null;
} }
@ -496,19 +508,18 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
throw new CloudRuntimeException("Invalid serviceContext"); throw new CloudRuntimeException("Invalid serviceContext");
} }
ManagedObjectReference mor = serviceContext.getHostMorByPath(hostInventoryPath); ManagedObjectReference mor = serviceContext.getHostMorByPath(hostInventoryPath);
String privateTrafficLabel = null; String privateTrafficLabel;
privateTrafficLabel = serviceContext.getStockObject("privateTrafficLabel"); privateTrafficLabel = serviceContext.getStockObject("privateTrafficLabel");
if (privateTrafficLabel == null) { if (privateTrafficLabel == null) {
privateTrafficLabel = _privateNetworkVSwitchName; privateTrafficLabel = _privateNetworkVSwitchName;
} }
if (mor != null) { if (mor != null) {
List<ManagedObjectReference> returnedHostList = new ArrayList<ManagedObjectReference>(); List<ManagedObjectReference> returnedHostList = new ArrayList<>();
if (mor.getType().equals("ComputeResource")) { if (mor.getType().equals("ComputeResource")) {
List<ManagedObjectReference> hosts = serviceContext.getVimClient().getDynamicProperty(mor, "host"); List<ManagedObjectReference> hosts = serviceContext.getVimClient().getDynamicProperty(mor, "host");
assert (hosts != null && hosts.size() > 0); assert (CollectionUtils.isNullOrEmpty(hosts));
// For ESX host, we need to enable host firewall to allow VNC access // For ESX host, we need to enable host firewall to allow VNC access
HostMO hostMo = new HostMO(serviceContext, hosts.get(0)); HostMO hostMo = new HostMO(serviceContext, hosts.get(0));
@ -519,8 +530,8 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
List<ManagedObjectReference> hosts = serviceContext.getVimClient().getDynamicProperty(mor, "host"); List<ManagedObjectReference> hosts = serviceContext.getVimClient().getDynamicProperty(mor, "host");
assert (hosts != null); assert (hosts != null);
if (hosts.size() > 0) { if (!hosts.isEmpty()) {
AboutInfo about = (AboutInfo)(serviceContext.getVimClient().getDynamicProperty(hosts.get(0), "config.product")); AboutInfo about = serviceContext.getVimClient().getDynamicProperty(hosts.get(0), "config.product");
String version = about.getApiVersion(); String version = about.getApiVersion();
int maxHostsPerCluster = _hvCapabilitiesDao.getMaxHostsPerCluster(HypervisorType.VMware, version); int maxHostsPerCluster = _hvCapabilitiesDao.getMaxHostsPerCluster(HypervisorType.VMware, version);
if (hosts.size() > maxHostsPerCluster) { if (hosts.size() > maxHostsPerCluster) {
@ -549,7 +560,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
returnedHostList.add(mor); returnedHostList.add(mor);
return returnedHostList; return returnedHostList;
} else { } else {
logger.error("Unsupport host type " + mor.getType() + ":" + mor.getValue() + " from inventory path: " + hostInventoryPath); logger.error("Unsupport host type {}:{} from inventory path: {}", mor.getType(), mor.getValue(), hostInventoryPath);
return null; return null;
} }
} }
@ -614,13 +625,13 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override @Override
public String getManagementPortGroupName() { public String getManagementPortGroupName() {
return _managemetPortGroupName; return _managementPortGroupName;
} }
@Override @Override
public String getManagementPortGroupByHost(HostMO hostMo) throws Exception { public String getManagementPortGroupByHost(HostMO hostMo) throws Exception {
if (hostMo.getHostType() == VmwareHostType.ESXi) { if (hostMo.getHostType() == VmwareHostType.ESXi) {
return _managemetPortGroupName; return _managementPortGroupName;
} }
return _serviceConsoleName; return _serviceConsoleName;
} }
@ -630,7 +641,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
params.put("vmware.create.full.clone", _fullCloneFlag); params.put("vmware.create.full.clone", _fullCloneFlag);
params.put("vm.instancename.flag", _instanceNameFlag); params.put("vm.instancename.flag", _instanceNameFlag);
params.put("service.console.name", _serviceConsoleName); params.put("service.console.name", _serviceConsoleName);
params.put("management.portgroup.name", _managemetPortGroupName); params.put("management.portgroup.name", _managementPortGroupName);
params.put("vmware.root.disk.controller", _rootDiskController); params.put("vmware.root.disk.controller", _rootDiskController);
params.put("vmware.data.disk.controller", _dataDiskController); params.put("vmware.data.disk.controller", _dataDiskController);
params.put("vmware.recycle.hung.wokervm", _recycleHungWorker); params.put("vmware.recycle.hung.wokervm", _recycleHungWorker);
@ -657,23 +668,23 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
return false; return false;
} }
String tokens[] = workerTag.split("-"); String[] tokens = workerTag.split("-");
if (tokens.length != 3) { if (tokens.length != 3) {
logger.error("Invalid worker VM tag " + workerTag); logger.error("Invalid worker VM tag " + workerTag);
return false; return false;
} }
long startTick = Long.parseLong(tokens[0]); long startTick = Long.parseLong(tokens[0]);
long msid = Long.parseLong(tokens[1]); long msId = Long.parseLong(tokens[1]);
long runid = Long.parseLong(tokens[2]); long runId = Long.parseLong(tokens[2]);
if (msHostPeerDao.countStateSeenInPeers(msid, runid, ManagementServerHost.State.Down) > 0) { if (msHostPeerDao.countStateSeenInPeers(msId, runId, ManagementServerHost.State.Down) > 0) {
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("Worker VM's owner management server node has been detected down from peer nodes, recycle it"); logger.info("Worker VM's owner management server node has been detected down from peer nodes, recycle it");
return true; return true;
} }
if (runid != clusterManager.getManagementRunId(msid)) { if (runId != clusterManager.getManagementRunId(msId)) {
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("Worker VM's owner management server has changed runid, recycle it"); logger.info("Worker VM's owner management server has changed runid, recycle it");
return true; return true;
@ -710,7 +721,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
File patchFolder = new File(mountPoint + "/systemvm"); File patchFolder = new File(mountPoint + "/systemvm");
if (!patchFolder.exists()) { if (!patchFolder.exists()) {
if (!patchFolder.mkdirs()) { if (!patchFolder.mkdirs()) {
String msg = "Unable to create systemvm folder on secondary storage. location: " + patchFolder.toString(); String msg = "Unable to create systemvm folder on secondary storage. location: " + patchFolder;
logger.error(msg); logger.error(msg);
throw new CloudRuntimeException(msg); throw new CloudRuntimeException(msg);
} }
@ -729,7 +740,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
} catch (IOException e) { } catch (IOException e) {
logger.error("Unexpected exception ", e); logger.error("Unexpected exception ", e);
String msg = "Unable to copy systemvm ISO on secondary storage. src location: " + srcIso.toString() + ", dest location: " + destIso; String msg = "Unable to copy systemvm ISO on secondary storage. src location: " + srcIso + ", dest location: " + destIso;
logger.error(msg); logger.error(msg);
throw new CloudRuntimeException(msg); throw new CloudRuntimeException(msg);
} }
@ -771,9 +782,8 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
isoFile = new File("/usr/share/cloudstack-common/vms/systemvm.iso"); isoFile = new File("/usr/share/cloudstack-common/vms/systemvm.iso");
} }
assert (isoFile != null);
if (!isoFile.exists()) { if (!isoFile.exists()) {
logger.error("Unable to locate systemvm.iso in your setup at " + isoFile.toString()); logger.error("Unable to locate systemvm.iso in your setup at " + isoFile);
} }
return isoFile; return isoFile;
} }
@ -788,16 +798,16 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
if (keyFile == null || !keyFile.exists()) { if (keyFile == null || !keyFile.exists()) {
keyFile = new File("/usr/share/cloudstack-common/scripts/vm/systemvm/id_rsa.cloud"); keyFile = new File("/usr/share/cloudstack-common/scripts/vm/systemvm/id_rsa.cloud");
} }
assert (keyFile != null);
if (!keyFile.exists()) { if (!keyFile.exists()) {
logger.error("Unable to locate id_rsa.cloud in your setup at " + keyFile.toString()); logger.error("Unable to locate id_rsa.cloud in your setup at " + keyFile);
} }
return keyFile; return keyFile;
} }
@Override @Override
public String getMountPoint(String storageUrl, String nfsVersion) { public String getMountPoint(String storageUrl, String nfsVersion) {
String mountPoint = null; String mountPoint;
synchronized (_storageMounts) { synchronized (_storageMounts) {
mountPoint = _storageMounts.get(storageUrl); mountPoint = _storageMounts.get(storageUrl);
if (mountPoint != null) { if (mountPoint != null) {
@ -827,7 +837,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
String mountPoint = null; String mountPoint = null;
long mshostId = ManagementServerNode.getManagementServerId(); long mshostId = ManagementServerNode.getManagementServerId();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
String mntPt = parent + File.separator + String.valueOf(mshostId) + "." + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE)); String mntPt = parent + File.separator + mshostId + "." + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE));
File file = new File(mntPt); File file = new File(mntPt);
if (!file.exists()) { if (!file.exists()) {
if (_storage.mkdir(mntPt)) { if (_storage.mkdir(mntPt)) {
@ -852,10 +862,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
for (String mountPoint : mounts) { for (String mountPoint : mounts) {
logger.info("umount NFS mount from previous session: " + mountPoint); logger.info("umount NFS mount from previous session: " + mountPoint);
String result = null;
Script command = new Script(true, "umount", _timeout, logger); Script command = new Script(true, "umount", _timeout, logger);
command.add(mountPoint); command.add(mountPoint);
result = command.execute(); String result = command.execute();
if (result != null) { if (result != null) {
logger.warn("Unable to umount " + mountPoint + " due to " + result); logger.warn("Unable to umount " + mountPoint + " due to " + result);
} }
@ -873,10 +882,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
for (String mountPoint : _storageMounts.values()) { for (String mountPoint : _storageMounts.values()) {
logger.info("umount NFS mount: " + mountPoint); logger.info("umount NFS mount: " + mountPoint);
String result = null;
Script command = new Script(true, "umount", _timeout, logger); Script command = new Script(true, "umount", _timeout, logger);
command.add(mountPoint); command.add(mountPoint);
result = command.execute(); String result = command.execute();
if (result != null) { if (result != null) {
logger.warn("Unable to umount " + mountPoint + " due to " + result); logger.warn("Unable to umount " + mountPoint + " due to " + result);
} }
@ -894,8 +902,8 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
return null; return null;
} }
Script script = null; Script script;
String result = null; String result;
Script command = new Script(true, "mount", _timeout, logger); Script command = new Script(true, "mount", _timeout, logger);
command.add("-t", "nfs"); command.add("-t", "nfs");
if (nfsVersion != null){ if (nfsVersion != null){
@ -982,11 +990,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override @Override
public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) { public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) {
if (cmd instanceof StartupCommand) { if (cmd != null) {
if (host.getHypervisorType() == HypervisorType.VMware) { if (host.getHypervisorType() == HypervisorType.VMware) {
updateClusterNativeHAState(host, cmd); updateClusterNativeHAState(host, cmd);
} else {
return;
} }
} }
} }
@ -1056,16 +1062,16 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override @Override
public Pair<Integer, Integer> getAddiionalVncPortRange() { public Pair<Integer, Integer> getAddiionalVncPortRange() {
return new Pair<Integer, Integer>(_additionalPortRangeStart, _additionalPortRangeSize); return new Pair<>(_additionalPortRangeStart, _additionalPortRangeSize);
} }
@Override @Override
public Map<String, String> getNexusVSMCredentialsByClusterId(Long clusterId) { public Map<String, String> getNexusVSMCredentialsByClusterId(Long clusterId) {
CiscoNexusVSMDeviceVO nexusVSM = null; CiscoNexusVSMDeviceVO nexusVSM;
ClusterVSMMapVO vsmMapVO = null; ClusterVSMMapVO vsmMapVO;
vsmMapVO = _vsmMapDao.findByClusterId(clusterId); vsmMapVO = _vsmMapDao.findByClusterId(clusterId);
long vsmId = 0; long vsmId;
if (vsmMapVO != null) { if (vsmMapVO != null) {
vsmId = vsmMapVO.getVsmId(); vsmId = vsmMapVO.getVsmId();
logger.info("vsmId is " + vsmId); logger.info("vsmId is " + vsmId);
@ -1076,7 +1082,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
return null; return null;
} }
Map<String, String> nexusVSMCredentials = new HashMap<String, String>(); Map<String, String> nexusVSMCredentials = new HashMap<>();
if (nexusVSM != null) { if (nexusVSM != null) {
nexusVSMCredentials.put("vsmip", nexusVSM.getipaddr()); nexusVSMCredentials.put("vsmip", nexusVSM.getipaddr());
nexusVSMCredentials.put("vsmusername", nexusVSM.getUserName()); nexusVSMCredentials.put("vsmusername", nexusVSM.getUserName());
@ -1103,7 +1109,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override @Override
public List<Class<?>> getCommands() { public List<Class<?>> getCommands() {
List<Class<?>> cmdList = new ArrayList<Class<?>>(); List<Class<?>> cmdList = new ArrayList<>();
cmdList.add(AddVmwareDcCmd.class); cmdList.add(AddVmwareDcCmd.class);
cmdList.add(UpdateVmwareDcCmd.class); cmdList.add(UpdateVmwareDcCmd.class);
cmdList.add(RemoveVmwareDcCmd.class); cmdList.add(RemoveVmwareDcCmd.class);
@ -1112,13 +1118,14 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
cmdList.add(ListVsphereStoragePoliciesCmd.class); cmdList.add(ListVsphereStoragePoliciesCmd.class);
cmdList.add(ListVsphereStoragePolicyCompatiblePoolsCmd.class); cmdList.add(ListVsphereStoragePolicyCompatiblePoolsCmd.class);
cmdList.add(ListVmwareDcVmsCmd.class); cmdList.add(ListVmwareDcVmsCmd.class);
cmdList.add(ListVmwareDcHostsCmd.class);
return cmdList; return cmdList;
} }
@Override @Override
@DB @DB
public VmwareDatacenterVO addVmwareDatacenter(AddVmwareDcCmd cmd) throws ResourceInUseException { public VmwareDatacenterVO addVmwareDatacenter(AddVmwareDcCmd cmd) throws ResourceInUseException {
VmwareDatacenterVO vmwareDc = null; VmwareDatacenterVO vmwareDc;
Long zoneId = cmd.getZoneId(); Long zoneId = cmd.getZoneId();
String userName = cmd.getUsername(); String userName = cmd.getUsername();
String password = cmd.getPassword(); String password = cmd.getPassword();
@ -1174,10 +1181,10 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
checkIfDcIsUsed(vCenterHost, vmwareDcName, zoneId); checkIfDcIsUsed(vCenterHost, vmwareDcName, zoneId);
VmwareContext context = null; VmwareContext context = null;
DatacenterMO dcMo = null; DatacenterMO dcMo;
String dcCustomFieldValue; String dcCustomFieldValue;
boolean addDcCustomFieldDef = false; boolean addDcCustomFieldDef = false;
boolean dcInUse = false; boolean dcInUse;
String guid; String guid;
ManagedObjectReference dcMor; ManagedObjectReference dcMor;
try { try {
@ -1210,7 +1217,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
// Map zone with vmware datacenter // Map zone with vmware datacenter
vmwareDcZoneMap = new VmwareDatacenterZoneMapVO(zoneId, vmwareDc.getId()); vmwareDcZoneMap = new VmwareDatacenterZoneMapVO(zoneId, vmwareDc.getId());
vmwareDcZoneMap = vmwareDatacenterZoneMapDao.persist(vmwareDcZoneMap); vmwareDatacenterZoneMapDao.persist(vmwareDcZoneMap);
// Set custom field for this DC // Set custom field for this DC
if (addDcCustomFieldDef) { if (addDcCustomFieldDef) {
@ -1230,7 +1237,6 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
if (context != null) { if (context != null) {
context.close(); context.close();
} }
context = null;
} }
importVsphereStoragePoliciesInternal(zoneId, vmwareDc.getId()); importVsphereStoragePoliciesInternal(zoneId, vmwareDc.getId());
return vmwareDc; return vmwareDc;
@ -1255,9 +1261,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
* Check if DC is already part of zone * Check if DC is already part of zone
* In that case vmware_data_center table should have the DC and a dc zone mapping should exist * In that case vmware_data_center table should have the DC and a dc zone mapping should exist
* *
* @param vCenterHost * @param vCenterHost the vcenter appliance hostname
* @param vmwareDcName * @param vmwareDcName the name of the vmware DC
* @param zoneId * @param zoneId zone that the DC should be connected to
* @throws ResourceInUseException if the DC can not be used. * @throws ResourceInUseException if the DC can not be used.
*/ */
private void checkIfDcIsUsed(String vCenterHost, String vmwareDcName, Long zoneId) throws ResourceInUseException { private void checkIfDcIsUsed(String vCenterHost, String vmwareDcName, Long zoneId) throws ResourceInUseException {
@ -1265,7 +1271,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
vmwareDc = vmwareDcDao.getVmwareDatacenterByGuid(vmwareDcName + "@" + vCenterHost); vmwareDc = vmwareDcDao.getVmwareDatacenterByGuid(vmwareDcName + "@" + vCenterHost);
if (vmwareDc != null) { if (vmwareDc != null) {
VmwareDatacenterZoneMapVO mapping = vmwareDatacenterZoneMapDao.findByVmwareDcId(vmwareDc.getId()); VmwareDatacenterZoneMapVO mapping = vmwareDatacenterZoneMapDao.findByVmwareDcId(vmwareDc.getId());
if (mapping != null && Long.compare(zoneId, mapping.getZoneId()) == 0) { if (mapping != null && zoneId == mapping.getZoneId()) {
throw new ResourceInUseException(String.format("This DC (%s) is already part of other CloudStack zone (%d). Cannot add this DC to more zones.", vmwareDc.getUuid(), zoneId)); throw new ResourceInUseException(String.format("This DC (%s) is already part of other CloudStack zone (%d). Cannot add this DC to more zones.", vmwareDc.getUuid(), zoneId));
} }
} }
@ -1274,7 +1280,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override @Override
@ActionEvent(eventType = EventTypes.EVENT_ZONE_EDIT, eventDescription = "updating VMware datacenter") @ActionEvent(eventType = EventTypes.EVENT_ZONE_EDIT, eventDescription = "updating VMware datacenter")
public VmwareDatacenter updateVmwareDatacenter(UpdateVmwareDcCmd cmd) { public VmwareDatacenter updateVmwareDatacenter(UpdateVmwareDcCmd cmd) {
final Long zoneId = cmd.getZoneId(); final long zoneId = cmd.getZoneId();
final String userName = cmd.getUsername(); final String userName = cmd.getUsername();
final String password = cmd.getPassword(); final String password = cmd.getPassword();
final String vCenterHost = cmd.getVcenter(); final String vCenterHost = cmd.getVcenter();
@ -1302,7 +1308,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
} }
vmwareDc.setGuid(String.format("%s@%s", vmwareDc.getVmwareDatacenterName(), vmwareDc.getVcenterHost())); vmwareDc.setGuid(String.format("%s@%s", vmwareDc.getVmwareDatacenterName(), vmwareDc.getVcenterHost()));
return Transaction.execute(new TransactionCallback<VmwareDatacenter>() { return Transaction.execute(new TransactionCallback<>() {
@Override @Override
public VmwareDatacenter doInTransaction(TransactionStatus status) { public VmwareDatacenter doInTransaction(TransactionStatus status) {
if (vmwareDcDao.update(vmwareDc.getId(), vmwareDc)) { if (vmwareDcDao.update(vmwareDc.getId(), vmwareDc)) {
@ -1351,7 +1357,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
String vCenterHost; String vCenterHost;
String userName; String userName;
String password; String password;
DatacenterMO dcMo = null; DatacenterMO dcMo;
final VmwareDatacenterZoneMapVO vmwareDcZoneMap = vmwareDatacenterZoneMapDao.findByZoneId(zoneId); final VmwareDatacenterZoneMapVO vmwareDcZoneMap = vmwareDatacenterZoneMapDao.findByZoneId(zoneId);
// Check if zone is associated with VMware DC // Check if zone is associated with VMware DC
if (vmwareDcZoneMap == null) { if (vmwareDcZoneMap == null) {
@ -1388,11 +1394,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
throw new DiscoveryException(msg); throw new DiscoveryException(msg);
} }
assert (dcMo != null);
// Reset custom field property cloud.zone over this DC // Reset custom field property cloud.zone over this DC
dcMo.setCustomFieldValue(CustomFieldConstants.CLOUD_ZONE, "false"); dcMo.setCustomFieldValue(CustomFieldConstants.CLOUD_ZONE, "false");
logger.info("Sucessfully reset custom field property cloud.zone over DC " + vmwareDcName); logger.info("Sucessfully reset custom field property cloud.zone over DC {}", vmwareDcName);
} catch (Exception e) { } catch (Exception e) {
String msg = "Unable to reset custom field property cloud.zone over DC " + vmwareDcName + " due to : " + VmwareHelper.getExceptionMessage(e); String msg = "Unable to reset custom field property cloud.zone over DC " + vmwareDcName + " due to : " + VmwareHelper.getExceptionMessage(e);
logger.error(msg); logger.error(msg);
@ -1401,7 +1405,6 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
if (context != null) { if (context != null) {
context.close(); context.close();
} }
context = null;
} }
return true; return true;
} }
@ -1422,7 +1425,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
private void validateZoneWithResources(Long zoneId, String errStr) throws ResourceInUseException { private void validateZoneWithResources(Long zoneId, String errStr) throws ResourceInUseException {
// Check if zone has resources? - For now look for clusters // Check if zone has resources? - For now look for clusters
List<ClusterVO> clusters = clusterDao.listByZoneId(zoneId); List<ClusterVO> clusters = clusterDao.listByZoneId(zoneId);
if (clusters != null && clusters.size() > 0) { if (!CollectionUtils.isNullOrEmpty(clusters)) {
// Look for VMware hypervisor. // Look for VMware hypervisor.
for (ClusterVO cluster : clusters) { for (ClusterVO cluster : clusters) {
if (cluster.getHypervisorType().equals(HypervisorType.VMware)) { if (cluster.getHypervisorType().equals(HypervisorType.VMware)) {
@ -1443,9 +1446,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
} }
@Override @Override
public List<? extends VmwareDatacenter> listVmwareDatacenters(ListVmwareDcsCmd cmd) throws CloudRuntimeException, InvalidParameterValueException { public List<? extends VmwareDatacenter> listVmwareDatacenters(ListVmwareDcsCmd cmd) throws CloudRuntimeException {
Long zoneId = cmd.getZoneId(); Long zoneId = cmd.getZoneId();
List<VmwareDatacenterVO> vmwareDcList = new ArrayList<VmwareDatacenterVO>(); List<VmwareDatacenterVO> vmwareDcList = new ArrayList<>();
VmwareDatacenterZoneMapVO vmwareDcZoneMap; VmwareDatacenterZoneMapVO vmwareDcZoneMap;
VmwareDatacenterVO vmwareDatacenter; VmwareDatacenterVO vmwareDatacenter;
long vmwareDcId; long vmwareDcId;
@ -1503,7 +1506,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
String vCenterHost = vmwareDatacenter.getVcenterHost(); String vCenterHost = vmwareDatacenter.getVcenterHost();
String userName = vmwareDatacenter.getUser(); String userName = vmwareDatacenter.getUser();
String password = vmwareDatacenter.getPassword(); String password = vmwareDatacenter.getPassword();
List<PbmProfile> storageProfiles = null; List<PbmProfile> storageProfiles;
try { try {
logger.debug(String.format("Importing vSphere Storage Policies for the vmware DC %d in zone %d", vmwareDcId, zoneId)); logger.debug(String.format("Importing vSphere Storage Policies for the vmware DC %d in zone %d", vmwareDcId, zoneId));
VmwareContext context = VmwareContextFactory.getContext(vCenterHost, userName, password); VmwareContext context = VmwareContextFactory.getContext(vCenterHost, userName, password);
@ -1531,16 +1534,15 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
List<VsphereStoragePolicyVO> allStoragePolicies = vsphereStoragePolicyDao.listAll(); List<VsphereStoragePolicyVO> allStoragePolicies = vsphereStoragePolicyDao.listAll();
List<PbmProfile> finalStorageProfiles = storageProfiles; List<PbmProfile> finalStorageProfiles = storageProfiles;
List<VsphereStoragePolicyVO> needToMarkRemoved = allStoragePolicies.stream() List<VsphereStoragePolicyVO> needToMarkRemoved = allStoragePolicies.stream()
.filter(existingPolicy -> !finalStorageProfiles.stream() .filter(existingPolicy -> finalStorageProfiles.stream()
.anyMatch(storageProfile -> storageProfile.getProfileId().getUniqueId().equals(existingPolicy.getPolicyId()))) .noneMatch(storageProfile -> storageProfile.getProfileId().getUniqueId().equals(existingPolicy.getPolicyId())))
.collect(Collectors.toList()); .collect(Collectors.toList());
for (VsphereStoragePolicyVO storagePolicy : needToMarkRemoved) { for (VsphereStoragePolicyVO storagePolicy : needToMarkRemoved) {
vsphereStoragePolicyDao.remove(storagePolicy.getId()); vsphereStoragePolicyDao.remove(storagePolicy.getId());
} }
List<VsphereStoragePolicyVO> storagePolicies = vsphereStoragePolicyDao.listAll(); return vsphereStoragePolicyDao.listAll();
return storagePolicies;
} }
@Override @Override
@ -1586,13 +1588,87 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
} }
@Override @Override
public List<UnmanagedInstanceTO> listVMsInDatacenter(ListVmwareDcVmsCmd cmd) { public List<HostMO> listHostsInDatacenter(ListVmwareDcHostsCmd cmd) {
VcenterData vmwaredc = getVcenterData(cmd);
try {
VmwareContext context = getVmwareContext(vmwaredc);
DatacenterMO dcMo = getDatacenterMO(context, vmwaredc);
return dcMo.getAllHostsOnDatacenter();
} catch (RuntimeFaultFaultMsg | URISyntaxException | VmwareClientException | InvalidLocaleFaultMsg |
InvalidLoginFaultMsg | InvalidPropertyFaultMsg e) {
String errorMsg = String.format("Error retrieving stopped VMs from the VMware VC %s datacenter %s: %s",
vmwaredc.vcenter, vmwaredc.datacenterName, e.getMessage());
logger.error(errorMsg, e);
throw new CloudRuntimeException(errorMsg);
}
}
@Override
public Pair<String, List<UnmanagedInstanceTO>> listVMsInDatacenter(ListVmwareDcVmsCmd cmd) {
Integer maxObjects = cmd.getBatchSize();
String token = cmd.getToken();
String host = cmd.getHost();
VcenterData vmwaredc = getVcenterData(cmd);
try {
VmwareContext context = getVmwareContext(vmwaredc);
DatacenterMO dcMo = getDatacenterMO(context, vmwaredc);
if (com.cloud.utils.StringUtils.isNotBlank(host)) {
ManagedObjectReference hostMor = dcMo.findHost(host);
if (hostMor == null) {
throw new VmwareClientException(String.format("No host '%s' found on DC: %s.", host, dcMo.getName()));
}
HostMO hostMo = new HostMO(context, hostMor);
return hostMo.getVms(maxObjects, token);
} else {
return dcMo.getVms(maxObjects, token);
}
} catch (InvalidParameterValueException | VmwareClientException | InvalidLocaleFaultMsg | InvalidLoginFaultMsg |
RuntimeFaultFaultMsg | URISyntaxException | InvalidPropertyFaultMsg | InvocationTargetException |
NoSuchMethodException | IllegalAccessException e) {
String errorMsg = String.format("Error retrieving stopped VMs from the VMware VC %s datacenter %s: %s",
vmwaredc.vcenter, vmwaredc.datacenterName, e.getMessage());
logger.error(errorMsg, e);
throw new CloudRuntimeException(errorMsg);
}
}
@NotNull
private DatacenterMO getDatacenterMO(VmwareContext context, VcenterData vmwaredc) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
DatacenterMO dcMo = new DatacenterMO(context, vmwaredc.datacenterName);
ManagedObjectReference dcMor = dcMo.getMor();
if (dcMor == null) {
String msg = String.format("Unable to find VMware datacenter %s in vCenter %s",
vmwaredc.datacenterName, vmwaredc.vcenter);
logger.error(msg);
throw new InvalidParameterValueException(msg);
}
return dcMo;
}
@NotNull
private VmwareContext getVmwareContext(VcenterData vmwaredc) throws RuntimeFaultFaultMsg, URISyntaxException, VmwareClientException, InvalidLocaleFaultMsg, InvalidLoginFaultMsg {
logger.debug(String.format("Connecting to the VMware datacenter %s at vCenter %s to retrieve VMs",
vmwaredc.datacenterName, vmwaredc.vcenter));
String serviceUrl = String.format("https://%s/sdk/vimService", vmwaredc.vcenter);
VmwareClient vimClient = new VmwareClient(vmwaredc.vcenter);
vimClient.connect(serviceUrl, vmwaredc.username, vmwaredc.password);
VmwareContext context = new VmwareContext(vimClient, vmwaredc.vcenter);
return context;
}
@NotNull
private VcenterData getVcenterData(ListVmwareDcItems cmd) {
String vcenter = cmd.getVcenter(); String vcenter = cmd.getVcenter();
String datacenterName = cmd.getDatacenterName(); String datacenterName = cmd.getDatacenterName();
String username = cmd.getUsername(); String username = cmd.getUsername();
String password = cmd.getPassword(); String password = cmd.getPassword();
Long existingVcenterId = cmd.getExistingVcenterId(); Long existingVcenterId = cmd.getExistingVcenterId();
String keyword = cmd.getKeyword();
if ((existingVcenterId == null && StringUtils.isBlank(vcenter)) || if ((existingVcenterId == null && StringUtils.isBlank(vcenter)) ||
(existingVcenterId != null && StringUtils.isNotBlank(vcenter))) { (existingVcenterId != null && StringUtils.isNotBlank(vcenter))) {
@ -1613,37 +1689,27 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
username = vmwareDc.getUser(); username = vmwareDc.getUser();
password = vmwareDc.getPassword(); password = vmwareDc.getPassword();
} }
VcenterData vmwaredc = new VcenterData(vcenter, datacenterName, username, password);
return vmwaredc;
}
try { private static class VcenterData {
logger.debug(String.format("Connecting to the VMware datacenter %s at vCenter %s to retrieve VMs", public final String vcenter;
datacenterName, vcenter)); public final String datacenterName;
String serviceUrl = String.format("https://%s/sdk/vimService", vcenter); public final String username;
VmwareClient vimClient = new VmwareClient(vcenter); public final String password;
vimClient.connect(serviceUrl, username, password);
VmwareContext context = new VmwareContext(vimClient, vcenter);
DatacenterMO dcMo = new DatacenterMO(context, datacenterName); public VcenterData(String vcenter, String datacenterName, String username, String password) {
ManagedObjectReference dcMor = dcMo.getMor(); this.vcenter = vcenter;
if (dcMor == null) { this.datacenterName = datacenterName;
String msg = String.format("Unable to find VMware datacenter %s in vCenter %s", this.username = username;
datacenterName, vcenter); this.password = password;
logger.error(msg);
throw new InvalidParameterValueException(msg);
}
List<UnmanagedInstanceTO> instances = dcMo.getAllVmsOnDatacenter();
return StringUtils.isBlank(keyword) ? instances :
instances.stream().filter(x -> x.getName().toLowerCase().contains(keyword.toLowerCase())).collect(Collectors.toList());
} catch (Exception e) {
String errorMsg = String.format("Error retrieving stopped VMs from the VMware VC %s datacenter %s: %s",
vcenter, datacenterName, e.getMessage());
logger.error(errorMsg, e);
throw new CloudRuntimeException(errorMsg);
} }
} }
@Override @Override
public boolean hasNexusVSM(Long clusterId) { public boolean hasNexusVSM(Long clusterId) {
ClusterVSMMapVO vsmMapVo = null; ClusterVSMMapVO vsmMapVo;
vsmMapVo = _vsmMapDao.findByClusterId(clusterId); vsmMapVo = _vsmMapDao.findByClusterId(clusterId);
if (vsmMapVo == null) { if (vsmMapVo == null) {
@ -1693,7 +1759,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
} }
/** /**
* This task is to cleanup templates from primary storage that are otherwise not cleaned by the {@link com.cloud.storage.StorageManagerImpl.StorageGarbageCollector}. * This task is to clean-up templates from primary storage that are otherwise not cleaned by the {@see com.cloud.storage.StorageManagerImpl.StorageGarbageCollector}.
* it is called at regular intervals when storage.template.cleanup.enabled == true * it is called at regular intervals when storage.template.cleanup.enabled == true
* It collect all templates that * It collect all templates that
* - are deleted from cloudstack * - are deleted from cloudstack

View File

@ -45,6 +45,7 @@ import java.util.TimeZone;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.cloud.agent.api.CleanupVMCommand;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.datatype.XMLGregorianCalendar;
@ -583,6 +584,8 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
return execute((ResizeVolumeCommand) cmd); return execute((ResizeVolumeCommand) cmd);
} else if (clz == UnregisterVMCommand.class) { } else if (clz == UnregisterVMCommand.class) {
return execute((UnregisterVMCommand) cmd); return execute((UnregisterVMCommand) cmd);
} else if (clz == CleanupVMCommand.class) {
return execute((CleanupVMCommand) cmd);
} else if (cmd instanceof StorageSubSystemCommand) { } else if (cmd instanceof StorageSubSystemCommand) {
checkStorageProcessorAndHandlerNfsVersionAttribute((StorageSubSystemCommand) cmd); checkStorageProcessorAndHandlerNfsVersionAttribute((StorageSubSystemCommand) cmd);
return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd);
@ -5796,6 +5799,26 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
return new Answer(cmd, true, "success"); return new Answer(cmd, true, "success");
} }
protected Answer execute(CleanupVMCommand cmd) {
VmwareContext context = getServiceContext();
VmwareHypervisorHost hyperHost = getHyperHost(context);
try {
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(cmd.getVmName());
if (vmMo == null) {
String msg = String.format("VM [%s] not found on vCenter, cleanup not needed.", cmd.getVmName());
logger.debug(msg);
return new Answer(cmd, true, msg);
}
vmMo.destroy();
String msg = String.format("VM [%s] remnants on vCenter cleaned up.", cmd.getVmName());
logger.debug(msg);
return new Answer(cmd, true, msg);
} catch (Exception e) {
return new Answer(cmd, false, createLogMessageException(e, cmd));
}
}
protected Answer execute(UnregisterVMCommand cmd) { protected Answer execute(UnregisterVMCommand cmd) {
VmwareContext context = getServiceContext(); VmwareContext context = getServiceContext();
VmwareHypervisorHost hyperHost = getHyperHost(context); VmwareHypervisorHost hyperHost = getHyperHost(context);

View File

@ -36,8 +36,8 @@ import com.cloud.dc.VmwareDatacenterVO;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
@APICommand(name = "addVmwareDc", description = "Adds a VMware datacenter to specified zone", responseObject = VmwareDatacenterResponse.class, @APICommand(name = "addVmwareDc", description = "Adds a Vmware datacenter to specified zone",
requestHasSensitiveInfo = true, responseHasSensitiveInfo = false) responseObject = VmwareDatacenterResponse.class, responseHasSensitiveInfo = false)
public class AddVmwareDcCmd extends BaseCmd { public class AddVmwareDcCmd extends BaseCmd {
@Inject @Inject
@ -45,7 +45,7 @@ public class AddVmwareDcCmd extends BaseCmd {
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Name of VMware datacenter to be added to specified zone.") @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Name of Vmware datacenter to be added to specified zone.")
private String name; private String name;
@Parameter(name = ApiConstants.VCENTER, @Parameter(name = ApiConstants.VCENTER,
@ -54,10 +54,10 @@ public class AddVmwareDcCmd extends BaseCmd {
description = "The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.") description = "The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.")
private String vCenter; private String vCenter;
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, required = false, description = "The Username required to connect to resource.") @Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "The Username required to connect to resource.")
private String username; private String username;
@Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, required = false, description = "The password for specified username.") @Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, description = "The password for specified username.")
private String password; private String password;
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "The Zone ID.") @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "The Zone ID.")
@ -99,7 +99,7 @@ public class AddVmwareDcCmd extends BaseCmd {
response.setResponseName(getCommandName()); response.setResponseName(getCommandName());
response.setObjectName("vmwaredc"); response.setObjectName("vmwaredc");
} else { } else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add VMware Datacenter to zone."); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Vmware Datacenter to zone.");
} }
this.setResponseObject(response); this.setResponseObject(response);
} catch (DiscoveryException ex) { } catch (DiscoveryException ex) {

View File

@ -48,8 +48,6 @@ import java.util.List;
authorized = {RoleType.Admin}) authorized = {RoleType.Admin})
public class ImportVsphereStoragePoliciesCmd extends BaseCmd { public class ImportVsphereStoragePoliciesCmd extends BaseCmd {
@Inject @Inject
public VmwareDatacenterService _vmwareDatacenterService; public VmwareDatacenterService _vmwareDatacenterService;
@ -74,6 +72,13 @@ public class ImportVsphereStoragePoliciesCmd extends BaseCmd {
List<? extends VsphereStoragePolicy> storagePolicies = _vmwareDatacenterService.importVsphereStoragePolicies(this); List<? extends VsphereStoragePolicy> storagePolicies = _vmwareDatacenterService.importVsphereStoragePolicies(this);
final ListResponse<VsphereStoragePoliciesResponse> responseList = new ListResponse<>(); final ListResponse<VsphereStoragePoliciesResponse> responseList = new ListResponse<>();
final List<VsphereStoragePoliciesResponse> storagePoliciesResponseList = getVsphereStoragePoliciesResponses(storagePolicies, dataCenter);
responseList.setResponses(storagePoliciesResponseList);
responseList.setResponseName(getCommandName());
setResponseObject(responseList);
}
private static List<VsphereStoragePoliciesResponse> getVsphereStoragePoliciesResponses(List<? extends VsphereStoragePolicy> storagePolicies, DataCenter dataCenter) {
final List<VsphereStoragePoliciesResponse> storagePoliciesResponseList = new ArrayList<>(); final List<VsphereStoragePoliciesResponse> storagePoliciesResponseList = new ArrayList<>();
for (VsphereStoragePolicy storagePolicy : storagePolicies) { for (VsphereStoragePolicy storagePolicy : storagePolicies) {
final VsphereStoragePoliciesResponse storagePoliciesResponse = new VsphereStoragePoliciesResponse(); final VsphereStoragePoliciesResponse storagePoliciesResponse = new VsphereStoragePoliciesResponse();
@ -86,9 +91,7 @@ public class ImportVsphereStoragePoliciesCmd extends BaseCmd {
storagePoliciesResponseList.add(storagePoliciesResponse); storagePoliciesResponseList.add(storagePoliciesResponse);
} }
responseList.setResponses(storagePoliciesResponseList); return storagePoliciesResponseList;
responseList.setResponseName(getCommandName());
setResponseObject(responseList);
} }
@Override @Override

View File

@ -0,0 +1,144 @@
// 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.api.command.admin.zone;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.hypervisor.vmware.mo.HostMO;
import com.cloud.user.Account;
import com.cloud.utils.exception.CloudRuntimeException;
import com.vmware.vim25.InvalidPropertyFaultMsg;
import com.vmware.vim25.RuntimeFaultFaultMsg;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.VmwareDatacenterResponse;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import javax.inject.Inject;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
@APICommand(name = "listVmwareDcHosts", responseObject = VmwareRequestResponse.class,
description = "Lists the VMs in a Vmware Datacenter",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListVmwareDcHostsCmd extends BaseCmd implements ListVmwareDcItems {
@Inject
public VmwareDatacenterService _vmwareDatacenterService;
@Parameter(name = ApiConstants.EXISTING_VCENTER_ID,
type = CommandType.UUID,
entityType = VmwareDatacenterResponse.class,
description = "UUID of a linked existing vCenter")
private Long existingVcenterId;
@Parameter(name = ApiConstants.VCENTER,
type = CommandType.STRING,
description = "The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.")
private String vcenter;
@Parameter(name = ApiConstants.DATACENTER_NAME, type = CommandType.STRING, description = "Name of Vmware datacenter.")
private String datacenterName;
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "The Username required to connect to resource.")
private String username;
@Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, description = "The password for specified username.")
private String password;
public String getVcenter() {
return vcenter;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getDatacenterName() {
return datacenterName;
}
public Long getExistingVcenterId() {
return existingVcenterId;
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
checkParameters();
try {
List<HostMO> hosts = _vmwareDatacenterService.listHostsInDatacenter(this);
List<BaseResponse> baseResponseList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(hosts)) {
for (HostMO vmwareHost : hosts) {
HostResponse resp = createHostResponse(vmwareHost);
baseResponseList.add(resp);
}
}
VmwareRequestResponse<BaseResponse> response = new VmwareRequestResponse<>();
response.setResponses(baseResponseList, baseResponseList.size());
response.setResponseName(getCommandName());
setResponseObject(response);
} catch (CloudRuntimeException | InvalidPropertyFaultMsg | RuntimeFaultFaultMsg | InvocationTargetException |
NoSuchMethodException | IllegalAccessException e) {
String errorMsg = String.format("Error retrieving VMs from Vmware VC: %s", e.getMessage());
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg);
}
}
private HostResponse createHostResponse(HostMO hostInstance) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
HostResponse response = new HostResponse();
response.setHypervisor(Hypervisor.HypervisorType.VMware.toString());
response.setName(hostInstance.getHostName());
response.setObjectName("host");
return response;
}
private void checkParameters() {
if ((existingVcenterId == null && vcenter == null) || (existingVcenterId != null && vcenter != null)) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
"Please provide an existing vCenter ID or a vCenter IP/Name, parameters are mutually exclusive");
}
if (existingVcenterId == null && StringUtils.isAnyBlank(vcenter, datacenterName, username, password)) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
"Please set all the information for a vCenter IP/Name, datacenter, username and password");
}
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
}

View File

@ -0,0 +1,29 @@
// 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.api.command.admin.zone;
public interface ListVmwareDcItems {
String getVcenter();
String getDatacenterName();
String getUsername();
String getPassword();
Long getExistingVcenterId();
}

View File

@ -23,15 +23,15 @@ import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.vmware.VmwareDatacenterService; import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; import org.apache.cloudstack.api.response.UnmanagedInstanceResponse;
import org.apache.cloudstack.api.response.VmwareDatacenterResponse; import org.apache.cloudstack.api.response.VmwareDatacenterResponse;
import org.apache.cloudstack.vm.UnmanagedInstanceTO; import org.apache.cloudstack.vm.UnmanagedInstanceTO;
@ -42,10 +42,10 @@ import javax.inject.Inject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@APICommand(name = "listVmwareDcVms", responseObject = UnmanagedInstanceResponse.class, @APICommand(name = "listVmwareDcVms", responseObject = VmwareRequestResponse.class,
description = "Lists the VMs in a VMware Datacenter", description = "Lists the VMs in a Vmware Datacenter",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListVmwareDcVmsCmd extends BaseListCmd { public class ListVmwareDcVmsCmd extends BaseCmd implements ListVmwareDcItems {
@Inject @Inject
public VmwareDatacenterService _vmwareDatacenterService; public VmwareDatacenterService _vmwareDatacenterService;
@ -61,7 +61,7 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
description = "The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.") description = "The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.")
private String vcenter; private String vcenter;
@Parameter(name = ApiConstants.DATACENTER_NAME, type = CommandType.STRING, description = "Name of VMware datacenter.") @Parameter(name = ApiConstants.DATACENTER_NAME, type = CommandType.STRING, description = "Name of Vmware datacenter.")
private String datacenterName; private String datacenterName;
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "The Username required to connect to resource.") @Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "The Username required to connect to resource.")
@ -70,6 +70,18 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
@Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, description = "The password for specified username.") @Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, description = "The password for specified username.")
private String password; private String password;
@Parameter(name = ApiConstants.HOST, type = CommandType.STRING, description = "get only the VMs from the specified host.")
private String host;
@Parameter(name = ApiConstants.BATCH_SIZE, type = CommandType.INTEGER, description = "The maximum number of results to return.")
private Integer batchSize;
@Parameter(name = ApiConstants.TOKEN, type = CommandType.STRING,
description = "For listVmwareDcVms, if the maximum number of results (the `batchsize`) is exceeded, " +
" a token is returned. This token can be used in subsequent calls to retrieve more results." +
" As long as a token is returned, more results can be retrieved.")
private String token;
public String getVcenter() { public String getVcenter() {
return vcenter; return vcenter;
} }
@ -82,6 +94,18 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
return password; return password;
} }
public Integer getBatchSize() {
return batchSize;
}
public String getHost() {
return host;
}
public String getToken() {
return token;
}
public String getDatacenterName() { public String getDatacenterName() {
return datacenterName; return datacenterName;
} }
@ -94,7 +118,8 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
checkParameters(); checkParameters();
try { try {
List<UnmanagedInstanceTO> vms = _vmwareDatacenterService.listVMsInDatacenter(this); Pair<String, List<UnmanagedInstanceTO>> results = _vmwareDatacenterService.listVMsInDatacenter(this);
List<UnmanagedInstanceTO> vms = results.second();
List<BaseResponse> baseResponseList = new ArrayList<>(); List<BaseResponse> baseResponseList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(vms)) { if (CollectionUtils.isNotEmpty(vms)) {
for (UnmanagedInstanceTO vmwareVm : vms) { for (UnmanagedInstanceTO vmwareVm : vms) {
@ -102,16 +127,13 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
baseResponseList.add(resp); baseResponseList.add(resp);
} }
} }
List<BaseResponse> pagingList = com.cloud.utils.StringUtils.applyPagination(baseResponseList, this.getStartIndex(), this.getPageSizeVal()); VmwareRequestResponse<BaseResponse> response = new VmwareRequestResponse<>();
if (CollectionUtils.isEmpty(pagingList)) { response.setResponses(baseResponseList, baseResponseList.size());
pagingList = baseResponseList;
}
ListResponse<BaseResponse> response = new ListResponse<>();
response.setResponses(pagingList, baseResponseList.size());
response.setResponseName(getCommandName()); response.setResponseName(getCommandName());
response.setToken(results.first());
setResponseObject(response); setResponseObject(response);
} catch (CloudRuntimeException e) { } catch (CloudRuntimeException e) {
String errorMsg = String.format("Error retrieving VMs from VMware VC: %s", e.getMessage()); String errorMsg = String.format("Error retrieving VMs from Vmware VC: %s", e.getMessage());
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg);
} }
} }
@ -134,6 +156,6 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
@Override @Override
public String getCommandName() { public String getCommandName() {
return "listvmwaredcvmsresponse"; return "listVmwareDcVmsResponse".toLowerCase();
} }
} }

View File

@ -42,7 +42,7 @@ import com.cloud.dc.VmwareDatacenter;
import com.cloud.hypervisor.vmware.VmwareDatacenterService; import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.user.Account; import com.cloud.user.Account;
@APICommand(name = "listVmwareDcs", responseObject = VmwareDatacenterResponse.class, description = "Retrieves VMware DC(s) associated with a zone.", @APICommand(name = "listVmwareDcs", responseObject = VmwareDatacenterResponse.class, description = "Retrieves Vmware DC(s) associated with a zone.",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListVmwareDcsCmd extends BaseListCmd { public class ListVmwareDcsCmd extends BaseListCmd {
@ -50,7 +50,6 @@ public class ListVmwareDcsCmd extends BaseListCmd {
public VmwareDatacenterService _vmwareDatacenterService; public VmwareDatacenterService _vmwareDatacenterService;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
//////////////// API parameters ///////////////////// //////////////// API parameters /////////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -73,20 +72,27 @@ public class ListVmwareDcsCmd extends BaseListCmd {
@Override @Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException { ResourceAllocationException {
List<? extends VmwareDatacenter> vmwareDcList = null; List<? extends VmwareDatacenter> vmwareDcList;
try { try {
vmwareDcList = _vmwareDatacenterService.listVmwareDatacenters(this); vmwareDcList = _vmwareDatacenterService.listVmwareDatacenters(this);
} catch (InvalidParameterValueException ie) { } catch (InvalidParameterValueException ie) {
throw new InvalidParameterValueException("Invalid zone id " + getZoneId()); throw new InvalidParameterValueException("Invalid zone id " + getZoneId());
} catch (Exception e) { } catch (Exception e) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to find associated VMware DCs associated with zone " + getZoneId()); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to find associated Vmware DCs associated with zone " + getZoneId());
} }
ListResponse<VmwareDatacenterResponse> response = new ListResponse<VmwareDatacenterResponse>(); ListResponse<VmwareDatacenterResponse> response = new ListResponse<>();
List<VmwareDatacenterResponse> vmwareDcResponses = new ArrayList<VmwareDatacenterResponse>(); List<VmwareDatacenterResponse> vmwareDcResponses = getVmwareDatacenterResponses(vmwareDcList);
response.setResponses(vmwareDcResponses);
response.setResponseName(getCommandName());
setResponseObject(response);
}
if (vmwareDcList != null && vmwareDcList.size() > 0) { private List<VmwareDatacenterResponse> getVmwareDatacenterResponses(List<? extends VmwareDatacenter> vmwareDcList) {
List<VmwareDatacenterResponse> vmwareDcResponses = new ArrayList<>();
if (vmwareDcList != null && !vmwareDcList.isEmpty()) {
for (VmwareDatacenter vmwareDc : vmwareDcList) { for (VmwareDatacenter vmwareDc : vmwareDcList) {
VmwareDatacenterResponse vmwareDcResponse = new VmwareDatacenterResponse(); VmwareDatacenterResponse vmwareDcResponse = new VmwareDatacenterResponse();
@ -94,14 +100,12 @@ public class ListVmwareDcsCmd extends BaseListCmd {
vmwareDcResponse.setVcenter(vmwareDc.getVcenterHost()); vmwareDcResponse.setVcenter(vmwareDc.getVcenterHost());
vmwareDcResponse.setName(vmwareDc.getVmwareDatacenterName()); vmwareDcResponse.setName(vmwareDc.getVmwareDatacenterName());
vmwareDcResponse.setZoneId(getZoneId()); vmwareDcResponse.setZoneId(getZoneId());
vmwareDcResponse.setObjectName("VMwareDC"); vmwareDcResponse.setObjectName(ApiConstants.VMWARE_DC);
vmwareDcResponses.add(vmwareDcResponse); vmwareDcResponses.add(vmwareDcResponse);
} }
} }
response.setResponses(vmwareDcResponses); return vmwareDcResponses;
response.setResponseName(getCommandName());
setResponseObject(response);
} }
@Override @Override

View File

@ -47,8 +47,6 @@ import java.util.List;
authorized = {RoleType.Admin}) authorized = {RoleType.Admin})
public class ListVsphereStoragePoliciesCmd extends BaseCmd { public class ListVsphereStoragePoliciesCmd extends BaseCmd {
@Inject @Inject
public VmwareDatacenterService _vmwareDatacenterService; public VmwareDatacenterService _vmwareDatacenterService;
@ -73,6 +71,13 @@ public class ListVsphereStoragePoliciesCmd extends BaseCmd {
List<? extends VsphereStoragePolicy> storagePolicies = _vmwareDatacenterService.listVsphereStoragePolicies(this); List<? extends VsphereStoragePolicy> storagePolicies = _vmwareDatacenterService.listVsphereStoragePolicies(this);
final ListResponse<VsphereStoragePoliciesResponse> responseList = new ListResponse<>(); final ListResponse<VsphereStoragePoliciesResponse> responseList = new ListResponse<>();
final List<VsphereStoragePoliciesResponse> storagePoliciesResponseList = getVsphereStoragePoliciesResponses(storagePolicies, dataCenter);
responseList.setResponses(storagePoliciesResponseList);
responseList.setResponseName(getCommandName());
setResponseObject(responseList);
}
private static List<VsphereStoragePoliciesResponse> getVsphereStoragePoliciesResponses(List<? extends VsphereStoragePolicy> storagePolicies, DataCenter dataCenter) {
final List<VsphereStoragePoliciesResponse> storagePoliciesResponseList = new ArrayList<>(); final List<VsphereStoragePoliciesResponse> storagePoliciesResponseList = new ArrayList<>();
for (VsphereStoragePolicy storagePolicy : storagePolicies) { for (VsphereStoragePolicy storagePolicy : storagePolicies) {
final VsphereStoragePoliciesResponse storagePoliciesResponse = new VsphereStoragePoliciesResponse(); final VsphereStoragePoliciesResponse storagePoliciesResponse = new VsphereStoragePoliciesResponse();
@ -81,13 +86,11 @@ public class ListVsphereStoragePoliciesCmd extends BaseCmd {
storagePoliciesResponse.setName(storagePolicy.getName()); storagePoliciesResponse.setName(storagePolicy.getName());
storagePoliciesResponse.setPolicyId(storagePolicy.getPolicyId()); storagePoliciesResponse.setPolicyId(storagePolicy.getPolicyId());
storagePoliciesResponse.setDescription(storagePolicy.getDescription()); storagePoliciesResponse.setDescription(storagePolicy.getDescription());
storagePoliciesResponse.setObjectName("StoragePolicy"); storagePoliciesResponse.setObjectName(ApiConstants.STORAGE_POLICY);
storagePoliciesResponseList.add(storagePoliciesResponse); storagePoliciesResponseList.add(storagePoliciesResponse);
} }
responseList.setResponses(storagePoliciesResponseList); return storagePoliciesResponseList;
responseList.setResponseName(getCommandName());
setResponseObject(responseList);
} }
@Override @Override

View File

@ -68,7 +68,7 @@ public class ListVsphereStoragePolicyCompatiblePoolsCmd extends BaseListCmd {
List<StoragePoolResponse> poolResponses = new ArrayList<>(); List<StoragePoolResponse> poolResponses = new ArrayList<>();
for (StoragePool pool : pools) { for (StoragePool pool : pools) {
StoragePoolResponse poolResponse = _responseGenerator.createStoragePoolForMigrationResponse(pool); StoragePoolResponse poolResponse = _responseGenerator.createStoragePoolForMigrationResponse(pool);
poolResponse.setObjectName("storagepool"); poolResponse.setObjectName(ApiConstants.STORAGE_POOL);
poolResponses.add(poolResponse); poolResponses.add(poolResponse);
} }
response.setResponses(poolResponses); response.setResponses(poolResponses);

View File

@ -34,7 +34,7 @@ import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
@APICommand(name = "removeVmwareDc", responseObject = SuccessResponse.class, description = "Remove a VMware datacenter from a zone.", @APICommand(name = "removeVmwareDc", responseObject = SuccessResponse.class, description = "Remove a Vmware datacenter from a zone.",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class RemoveVmwareDcCmd extends BaseCmd { public class RemoveVmwareDcCmd extends BaseCmd {
@ -47,7 +47,7 @@ public class RemoveVmwareDcCmd extends BaseCmd {
type = CommandType.UUID, type = CommandType.UUID,
entityType = ZoneResponse.class, entityType = ZoneResponse.class,
required = true, required = true,
description = "The id of Zone from which VMware datacenter has to be removed.") description = "The id of Zone from which Vmware datacenter has to be removed.")
private Long zoneId; private Long zoneId;
public Long getZoneId() { public Long getZoneId() {
@ -63,7 +63,7 @@ public class RemoveVmwareDcCmd extends BaseCmd {
response.setResponseName(getCommandName()); response.setResponseName(getCommandName());
setResponseObject(response); setResponseObject(response);
} else { } else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove VMware datacenter from zone"); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove Vmware datacenter from zone");
} }
} catch (ResourceInUseException ex) { } catch (ResourceInUseException ex) {
logger.warn("The zone has one or more resources (like cluster), hence not able to remove VMware datacenter from zone." logger.warn("The zone has one or more resources (like cluster), hence not able to remove VMware datacenter from zone."

View File

@ -33,12 +33,11 @@ import com.cloud.dc.VmwareDatacenter;
import com.cloud.hypervisor.vmware.VmwareDatacenterService; import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.user.Account; import com.cloud.user.Account;
@APICommand(name = "updateVmwareDc", description = "Updates a VMware datacenter details for a zone", @APICommand(name = "updateVmwareDc", description = "Updates a Vmware datacenter details for a zone",
responseObject = VmwareDatacenterResponse.class, responseHasSensitiveInfo = false, responseObject = VmwareDatacenterResponse.class, responseHasSensitiveInfo = false,
since = "4.12.0", authorized = {RoleType.Admin}) since = "4.12.0", authorized = {RoleType.Admin})
public class UpdateVmwareDcCmd extends BaseCmd { public class UpdateVmwareDcCmd extends BaseCmd {
@Inject @Inject
public VmwareDatacenterService vmwareDatacenterService; public VmwareDatacenterService vmwareDatacenterService;
@ -51,7 +50,7 @@ public class UpdateVmwareDcCmd extends BaseCmd {
private Long zoneId; private Long zoneId;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, @Parameter(name = ApiConstants.NAME, type = CommandType.STRING,
description = "VMware datacenter name.") description = "Vmware datacenter name.")
private String name; private String name;
@Parameter(name = ApiConstants.VCENTER, type = CommandType.STRING, @Parameter(name = ApiConstants.VCENTER, type = CommandType.STRING,
@ -106,13 +105,13 @@ public class UpdateVmwareDcCmd extends BaseCmd {
public void execute() { public void execute() {
final VmwareDatacenter vmwareDatacenter = vmwareDatacenterService.updateVmwareDatacenter(this); final VmwareDatacenter vmwareDatacenter = vmwareDatacenterService.updateVmwareDatacenter(this);
if (vmwareDatacenter == null) { if (vmwareDatacenter == null) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update VMware datacenter"); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update Vmware datacenter");
} }
final VmwareDatacenterResponse response = new VmwareDatacenterResponse(); final VmwareDatacenterResponse response = new VmwareDatacenterResponse();
response.setId(vmwareDatacenter.getUuid()); response.setId(vmwareDatacenter.getUuid());
response.setName(vmwareDatacenter.getVmwareDatacenterName()); response.setName(vmwareDatacenter.getVmwareDatacenterName());
response.setResponseName(getCommandName()); response.setResponseName(getCommandName());
response.setObjectName("vmwaredc"); response.setObjectName(ApiConstants.VMWARE_DC);
setResponseObject(response); setResponseObject(response);
} }

View File

@ -0,0 +1,38 @@
// 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.api.command.admin.zone;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.response.ListResponse;
public class VmwareRequestResponse<T extends ResponseObject> extends ListResponse<T> {
@SerializedName(ApiConstants.TOKEN)
@Param(description = "The Vmware API token to use for retrieving further responses with")
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}

View File

@ -23,10 +23,8 @@ import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.inject.Inject; import javax.inject.Inject;
@ -206,14 +204,12 @@ public class KubernetesClusterActionWorker {
protected String getControlNodeLoginUser() { protected String getControlNodeLoginUser() {
List<KubernetesClusterVmMapVO> vmMapVOList = getKubernetesClusterVMMaps(); List<KubernetesClusterVmMapVO> vmMapVOList = getKubernetesClusterVMMaps();
if (vmMapVOList.size() > 0) { if (!vmMapVOList.isEmpty()) {
long vmId = vmMapVOList.get(0).getVmId(); long vmId = vmMapVOList.get(0).getVmId();
UserVmVO userVM = userVmDao.findById(vmId); UserVmVO userVM = userVmDao.findById(vmId);
if (userVM == null) { if (userVM == null) {
throw new CloudRuntimeException("Failed to find login user, Unable to log in to node to fetch details"); throw new CloudRuntimeException("Failed to find login user, Unable to log in to node to fetch details");
} }
Set<String> vm = new HashSet<>();
vm.add(userVM.getName());
UserVmDetailVO vmDetail = userVmDetailsDao.findDetail(vmId, VmDetailConstants.CKS_CONTROL_NODE_LOGIN_USER); UserVmDetailVO vmDetail = userVmDetailsDao.findDetail(vmId, VmDetailConstants.CKS_CONTROL_NODE_LOGIN_USER);
if (vmDetail != null && !org.apache.commons.lang3.StringUtils.isEmpty(vmDetail.getValue())) { if (vmDetail != null && !org.apache.commons.lang3.StringUtils.isEmpty(vmDetail.getValue())) {
return vmDetail.getValue(); return vmDetail.getValue();
@ -309,7 +305,7 @@ public class KubernetesClusterActionWorker {
} }
protected KubernetesClusterVmMapVO addKubernetesClusterVm(final long kubernetesClusterId, final long vmId, boolean isControlNode) { protected KubernetesClusterVmMapVO addKubernetesClusterVm(final long kubernetesClusterId, final long vmId, boolean isControlNode) {
return Transaction.execute(new TransactionCallback<KubernetesClusterVmMapVO>() { return Transaction.execute(new TransactionCallback<>() {
@Override @Override
public KubernetesClusterVmMapVO doInTransaction(TransactionStatus status) { public KubernetesClusterVmMapVO doInTransaction(TransactionStatus status) {
KubernetesClusterVmMapVO newClusterVmMap = new KubernetesClusterVmMapVO(kubernetesClusterId, vmId, isControlNode); KubernetesClusterVmMapVO newClusterVmMap = new KubernetesClusterVmMapVO(kubernetesClusterId, vmId, isControlNode);
@ -361,7 +357,12 @@ public class KubernetesClusterActionWorker {
} }
IpAddress address = ipAddressDao.findByUuid(detailsVO.getValue()); IpAddress address = ipAddressDao.findByUuid(detailsVO.getValue());
if (address == null || !Objects.equals(network.getVpcId(), address.getVpcId())) { if (address == null || !Objects.equals(network.getVpcId(), address.getVpcId())) {
logger.warn(String.format("Public IP with ID: %s linked to the Kubernetes cluster: %s is not usable", detailsVO.getValue(), kubernetesCluster.getName())); logger.warn("Public IP with ID: {} linked to the Kubernetes cluster: {} is not usable", detailsVO.getValue(), kubernetesCluster.getName());
if (address == null) {
logger.warn("Public IP with ID: {} was not found by uuid", detailsVO.getValue());
} else {
logger.warn("Public IP with ID: {} was associated with vpc {} instead of {}", detailsVO.getValue(), address.getVpcId(), network.getVpcId());
}
return null; return null;
} }
return address; return address;
@ -517,8 +518,7 @@ public class KubernetesClusterActionWorker {
} }
protected List<KubernetesClusterVmMapVO> getKubernetesClusterVMMaps() { protected List<KubernetesClusterVmMapVO> getKubernetesClusterVMMaps() {
List<KubernetesClusterVmMapVO> clusterVMs = kubernetesClusterVmMapDao.listByClusterId(kubernetesCluster.getId()); return kubernetesClusterVmMapDao.listByClusterId(kubernetesCluster.getId());
return clusterVMs;
} }
protected List<KubernetesClusterVmMapVO> getKubernetesClusterVMMapsForNodes(List<Long> nodeIds) { protected List<KubernetesClusterVmMapVO> getKubernetesClusterVMMapsForNodes(List<Long> nodeIds) {

View File

@ -193,7 +193,7 @@ public class KubernetesClusterUtil {
while (System.currentTimeMillis() < timeoutTime) { while (System.currentTimeMillis() < timeoutTime) {
try { try {
Pair<Boolean, String> result = SshHelper.sshExecute(ipAddress, port, user, Pair<Boolean, String> result = SshHelper.sshExecute(ipAddress, port, user,
sshKeyFile, null, "sudo cat /etc/kubernetes/admin.conf", sshKeyFile, null, "sudo cat /etc/kubernetes/user.conf 2>/dev/null || sudo cat /etc/kubernetes/admin.conf",
10000, 10000, 10000); 10000, 10000, 10000);
if (result.first() && StringUtils.isNotEmpty(result.second())) { if (result.first() && StringUtils.isNotEmpty(result.second())) {

View File

@ -5,12 +5,23 @@ All notable changes to Linstor CloudStack plugin will be documented in this file
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2025-01-27]
### Fixed
- Use of multiple primary storages on the same linstor controller
## [2025-01-20] ## [2025-01-20]
### Fixed ### Fixed
- Volume snapshots on zfs used the wrong dataset path to hide/unhide snapdev - Volume snapshots on zfs used the wrong dataset path to hide/unhide snapdev
## [2024-12-19]
### Added
- Native CloudStack encryption support
## [2024-12-13] ## [2024-12-13]
### Fixed ### Fixed

View File

@ -97,18 +97,23 @@ public final class LinstorBackupSnapshotCommandWrapper
// NOTE: the qemu img will also contain the drbd metadata at the end // NOTE: the qemu img will also contain the drbd metadata at the end
final QemuImg qemu = new QemuImg(waitMilliSeconds); final QemuImg qemu = new QemuImg(waitMilliSeconds);
qemu.convert(srcFile, dstFile); qemu.convert(srcFile, dstFile);
LOGGER.info("Backup snapshot " + srcFile + " to " + dstPath); LOGGER.info("Backup snapshot '{}' to '{}'", srcPath, dstPath);
return dstPath; return dstPath;
} }
private SnapshotObjectTO setCorrectSnapshotSize(final SnapshotObjectTO dst, final String dstPath) { private SnapshotObjectTO setCorrectSnapshotSize(final SnapshotObjectTO dst, final String dstPath) {
final File snapFile = new File(dstPath); final File snapFile = new File(dstPath);
final long size = snapFile.exists() ? snapFile.length() : 0; long size;
if (snapFile.exists()) {
size = snapFile.length();
} else {
LOGGER.warn("Snapshot file {} does not exist. Reporting size 0", dstPath);
size = 0;
}
final SnapshotObjectTO snapshot = new SnapshotObjectTO(); dst.setPath(dst.getPath() + File.separator + dst.getName());
snapshot.setPath(dst.getPath() + File.separator + dst.getName()); dst.setPhysicalSize(size);
snapshot.setPhysicalSize(size); return dst;
return snapshot;
} }
@Override @Override
@ -158,6 +163,7 @@ public final class LinstorBackupSnapshotCommandWrapper
LOGGER.info("Backup shrunk " + dstPath + " to actual size " + src.getVolume().getSize()); LOGGER.info("Backup shrunk " + dstPath + " to actual size " + src.getVolume().getSize());
SnapshotObjectTO snapshot = setCorrectSnapshotSize(dst, dstPath); SnapshotObjectTO snapshot = setCorrectSnapshotSize(dst, dstPath);
LOGGER.info("Actual file size for '{}' is {}", dstPath, snapshot.getPhysicalSize());
return new CopyCmdAnswer(snapshot); return new CopyCmdAnswer(snapshot);
} catch (final Exception e) { } catch (final Exception e) {
final String error = String.format("Failed to backup snapshot with id [%s] with a pool %s, due to %s", final String error = String.format("Failed to backup snapshot with id [%s] with a pool %s, due to %s",

View File

@ -61,6 +61,11 @@ import com.linbit.linstor.api.model.Volume;
import com.linbit.linstor.api.model.VolumeDefinition; import com.linbit.linstor.api.model.VolumeDefinition;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class LinstorStorageAdaptor implements StorageAdaptor { public class LinstorStorageAdaptor implements StorageAdaptor {
protected Logger logger = LogManager.getLogger(getClass()); protected Logger logger = LogManager.getLogger(getClass());
@ -202,10 +207,10 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
final DevelopersApi api = getLinstorAPI(pool); final DevelopersApi api = getLinstorAPI(pool);
try { try {
List<ResourceDefinition> definitionList = api.resourceDefinitionList( ResourceDefinition resourceDefinition = LinstorUtil.findResourceDefinition(
Collections.singletonList(rscName), null, null, null); api, rscName, lpool.getResourceGroup());
if (definitionList.isEmpty()) { if (resourceDefinition == null) {
ResourceGroupSpawn rgSpawn = new ResourceGroupSpawn(); ResourceGroupSpawn rgSpawn = new ResourceGroupSpawn();
rgSpawn.setResourceDefinitionName(rscName); rgSpawn.setResourceDefinitionName(rscName);
rgSpawn.addVolumeSizesItem(size / 1024); // linstor uses KiB rgSpawn.addVolumeSizesItem(size / 1024); // linstor uses KiB
@ -215,22 +220,28 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
handleLinstorApiAnswers(answers, "Linstor: Unable to spawn resource."); handleLinstorApiAnswers(answers, "Linstor: Unable to spawn resource.");
} }
String foundRscName = resourceDefinition != null ? resourceDefinition.getName() : rscName;
// query linstor for the device path // query linstor for the device path
List<ResourceWithVolumes> resources = api.viewResources( List<ResourceWithVolumes> resources = api.viewResources(
Collections.emptyList(), Collections.emptyList(),
Collections.singletonList(rscName), Collections.singletonList(foundRscName),
Collections.emptyList(), Collections.emptyList(),
null, null,
null, null,
null); null);
makeResourceAvailable(api, rscName, false); makeResourceAvailable(api, foundRscName, false);
if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty()) { if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty()) {
final String devPath = resources.get(0).getVolumes().get(0).getDevicePath(); final String devPath = resources.get(0).getVolumes().get(0).getDevicePath();
logger.info("Linstor: Created drbd device: " + devPath); logger.info("Linstor: Created drbd device: " + devPath);
final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devPath, name, pool); final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devPath, name, pool);
kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW); kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW);
long allocatedKib = resources.get(0).getVolumes().get(0).getAllocatedSizeKib() != null ?
resources.get(0).getVolumes().get(0).getAllocatedSizeKib() : 0;
kvmDisk.setSize(allocatedKib >= 0 ? allocatedKib * 1024 : 0);
kvmDisk.setVirtualSize(size);
return kvmDisk; return kvmDisk;
} else { } else {
logger.error("Linstor: viewResources didn't return resources or volumes."); logger.error("Linstor: viewResources didn't return resources or volumes.");
@ -410,7 +421,7 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
if (rsc.getFlags() != null && if (rsc.getFlags() != null &&
rsc.getFlags().contains(ApiConsts.FLAG_DRBD_DISKLESS) && rsc.getFlags().contains(ApiConsts.FLAG_DRBD_DISKLESS) &&
!rsc.getFlags().contains(ApiConsts.FLAG_TIE_BREAKER)) { !rsc.getFlags().contains(ApiConsts.FLAG_TIE_BREAKER)) {
ApiCallRcList delAnswers = api.resourceDelete(rsc.getName(), localNodeName); ApiCallRcList delAnswers = api.resourceDelete(rsc.getName(), localNodeName, true);
logLinstorAnswers(delAnswers); logLinstorAnswers(delAnswers);
} }
} catch (ApiException apiEx) { } catch (ApiException apiEx) {
@ -473,21 +484,56 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
return false; return false;
} }
/**
* Decrements the aux property key for template resource and deletes or just deletes if not template resource.
* @param api
* @param rscName
* @param rscGrpName
* @return
* @throws ApiException
*/
private boolean deRefOrDeleteResource(DevelopersApi api, String rscName, String rscGrpName) throws ApiException {
boolean deleted = false;
List<ResourceDefinition> existingRDs = LinstorUtil.getRDListStartingWith(api, rscName);
for (ResourceDefinition rd : existingRDs) {
int expectedProps = 0; // if it is a non template resource, we don't expect any _cs-template-for- prop
String propKey = LinstorUtil.getTemplateForAuxPropKey(rscGrpName);
if (rd.getProps().containsKey(propKey)) {
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
rdm.deleteProps(Collections.singletonList(propKey));
api.resourceDefinitionModify(rd.getName(), rdm);
expectedProps = 1;
}
// if there is only one template-for property left for templates, the template isn't needed anymore
// or if it isn't a template anyway, it will not have this Aux property
// _cs-template-for- poperties work like a ref-count.
if (rd.getProps().keySet().stream()
.filter(key -> key.startsWith("Aux/" + LinstorUtil.CS_TEMPLATE_FOR_PREFIX))
.count() == expectedProps) {
ApiCallRcList answers = api.resourceDefinitionDelete(rd.getName());
checkLinstorAnswersThrow(answers);
deleted = true;
}
}
return deleted;
}
@Override @Override
public boolean deletePhysicalDisk(String name, KVMStoragePool pool, Storage.ImageFormat format) public boolean deletePhysicalDisk(String name, KVMStoragePool pool, Storage.ImageFormat format)
{ {
logger.debug("Linstor: deletePhysicalDisk " + name); logger.debug("Linstor: deletePhysicalDisk " + name);
final DevelopersApi api = getLinstorAPI(pool); final DevelopersApi api = getLinstorAPI(pool);
final String rscName = getLinstorRscName(name);
final LinstorStoragePool linstorPool = (LinstorStoragePool) pool;
String rscGrpName = linstorPool.getResourceGroup();
try { try {
final String rscName = getLinstorRscName(name); return deRefOrDeleteResource(api, rscName, rscGrpName);
logger.debug("Linstor: delete resource definition " + rscName);
ApiCallRcList answers = api.resourceDefinitionDelete(rscName);
handleLinstorApiAnswers(answers, "Linstor: Unable to delete resource definition " + rscName);
} catch (ApiException apiEx) { } catch (ApiException apiEx) {
logger.error("Linstor: ApiEx - " + apiEx.getMessage());
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx); throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
} }
return true;
} }
@Override @Override
@ -561,6 +607,56 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
return false; return false;
} }
/**
* Checks if the given disk is the SystemVM template, by checking its properties file in the same directory.
* The initial systemvm template resource isn't created on the management server, but
* we now need to know if the systemvm template is used, while copying.
* @param disk
* @return True if it is the systemvm template disk, else false.
*/
private static boolean isSystemTemplate(KVMPhysicalDisk disk) {
Path diskPath = Paths.get(disk.getPath());
Path propFile = diskPath.getParent().resolve("template.properties");
if (Files.exists(propFile)) {
java.util.Properties templateProps = new java.util.Properties();
try {
templateProps.load(new FileInputStream(propFile.toFile()));
String desc = templateProps.getProperty("description");
if (desc.startsWith("SystemVM Template")) {
return true;
}
} catch (IOException e) {
return false;
}
}
return false;
}
/**
* Conditionally sets the correct aux properties for templates or basic resources.
* @param api
* @param srcDisk
* @param destPool
* @param name
*/
private void setRscDfnAuxProperties(
DevelopersApi api, KVMPhysicalDisk srcDisk, KVMStoragePool destPool, String name) {
// if it is the initial systemvm disk copy, we need to apply the _cs-template-for property.
if (isSystemTemplate(srcDisk)) {
applyAuxProps(api, name, "SystemVM Template", null);
LinstorStoragePool linPool = (LinstorStoragePool) destPool;
final String rscName = getLinstorRscName(name);
try {
LinstorUtil.setAuxTemplateForProperty(api, rscName, linPool.getResourceGroup());
} catch (ApiException apiExc) {
logger.error("Error setting aux template for property for {}", rscName);
logLinstorAnswers(apiExc.getApiCallRcList());
}
} else {
applyAuxProps(api, name, srcDisk.getDispName(), srcDisk.getVmName());
}
}
@Override @Override
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMStoragePool destPools, int timeout, byte[] srcPassphrase, byte[] destPassphrase, Storage.ProvisioningType provisioningType) public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMStoragePool destPools, int timeout, byte[] srcPassphrase, byte[] destPassphrase, Storage.ProvisioningType provisioningType)
{ {
@ -574,15 +670,14 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
name, QemuImg.PhysicalDiskFormat.RAW, provisioningType, disk.getVirtualSize(), null); name, QemuImg.PhysicalDiskFormat.RAW, provisioningType, disk.getVirtualSize(), null);
final DevelopersApi api = getLinstorAPI(destPools); final DevelopersApi api = getLinstorAPI(destPools);
applyAuxProps(api, name, disk.getDispName(), disk.getVmName()); setRscDfnAuxProperties(api, disk, destPools, name);
logger.debug("Linstor.copyPhysicalDisk: dstPath: {}", dstDisk.getPath()); logger.debug("Linstor.copyPhysicalDisk: dstPath: {}", dstDisk.getPath());
final QemuImgFile destFile = new QemuImgFile(dstDisk.getPath()); final QemuImgFile destFile = new QemuImgFile(dstDisk.getPath());
destFile.setFormat(dstDisk.getFormat()); destFile.setFormat(dstDisk.getFormat());
destFile.setSize(disk.getVirtualSize()); destFile.setSize(disk.getVirtualSize());
boolean zeroedDevice = resourceSupportZeroBlocks(destPools, LinstorUtil.RSC_PREFIX + name); boolean zeroedDevice = resourceSupportZeroBlocks(destPools, getLinstorRscName(name));
try { try {
final QemuImg qemu = new QemuImg(timeout, zeroedDevice, true); final QemuImg qemu = new QemuImg(timeout, zeroedDevice, true);
qemu.convert(srcFile, destFile); qemu.convert(srcFile, destFile);

View File

@ -21,11 +21,16 @@ import com.linbit.linstor.api.CloneWaiter;
import com.linbit.linstor.api.DevelopersApi; import com.linbit.linstor.api.DevelopersApi;
import com.linbit.linstor.api.model.ApiCallRc; import com.linbit.linstor.api.model.ApiCallRc;
import com.linbit.linstor.api.model.ApiCallRcList; import com.linbit.linstor.api.model.ApiCallRcList;
import com.linbit.linstor.api.model.AutoSelectFilter;
import com.linbit.linstor.api.model.LayerType;
import com.linbit.linstor.api.model.Properties; import com.linbit.linstor.api.model.Properties;
import com.linbit.linstor.api.model.ResourceDefinition; import com.linbit.linstor.api.model.ResourceDefinition;
import com.linbit.linstor.api.model.ResourceDefinitionCloneRequest; import com.linbit.linstor.api.model.ResourceDefinitionCloneRequest;
import com.linbit.linstor.api.model.ResourceDefinitionCloneStarted; import com.linbit.linstor.api.model.ResourceDefinitionCloneStarted;
import com.linbit.linstor.api.model.ResourceDefinitionCreate; import com.linbit.linstor.api.model.ResourceDefinitionCreate;
import com.linbit.linstor.api.model.ResourceDefinitionModify;
import com.linbit.linstor.api.model.ResourceGroup;
import com.linbit.linstor.api.model.ResourceGroupSpawn; import com.linbit.linstor.api.model.ResourceGroupSpawn;
import com.linbit.linstor.api.model.ResourceMakeAvailable; import com.linbit.linstor.api.model.ResourceMakeAvailable;
import com.linbit.linstor.api.model.Snapshot; import com.linbit.linstor.api.model.Snapshot;
@ -34,6 +39,7 @@ import com.linbit.linstor.api.model.VolumeDefinition;
import com.linbit.linstor.api.model.VolumeDefinitionModify; import com.linbit.linstor.api.model.VolumeDefinitionModify;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.Arrays; import java.util.Arrays;
@ -43,6 +49,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.ResizeVolumeAnswer; import com.cloud.agent.api.storage.ResizeVolumeAnswer;
@ -66,6 +73,7 @@ import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageManager; import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePool;
import com.cloud.storage.VMTemplateStoragePoolVO; import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.Volume; import com.cloud.storage.Volume;
import com.cloud.storage.VolumeDetailVO; import com.cloud.storage.VolumeDetailVO;
import com.cloud.storage.VolumeVO; import com.cloud.storage.VolumeVO;
@ -85,6 +93,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; 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.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
@ -93,6 +102,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.storage.RemoteHostEndPoint; import org.apache.cloudstack.storage.RemoteHostEndPoint;
import org.apache.cloudstack.storage.command.CommandResult; import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.CreateObjectAnswer; import org.apache.cloudstack.storage.command.CreateObjectAnswer;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
@ -103,8 +113,12 @@ import org.apache.cloudstack.storage.snapshot.SnapshotObject;
import org.apache.cloudstack.storage.to.SnapshotObjectTO; import org.apache.cloudstack.storage.to.SnapshotObjectTO;
import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.cloudstack.storage.volume.VolumeObject; import org.apache.cloudstack.storage.volume.VolumeObject;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.commons.collections.CollectionUtils;
import java.nio.charset.StandardCharsets;
public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver { public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver {
protected Logger logger = LogManager.getLogger(getClass()); protected Logger logger = LogManager.getLogger(getClass());
@ -216,7 +230,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
} }
throw new CloudRuntimeException("Linstor: Unable to delete resource definition: " + rscDefName); throw new CloudRuntimeException("Linstor: Unable to delete resource definition: " + rscDefName);
} }
logger.info(String.format("Linstor: Deleted resource %s", rscDefName)); logger.info("Linstor: Deleted resource {}", rscDefName);
} catch (ApiException apiEx) } catch (ApiException apiEx)
{ {
logger.error("Linstor: ApiEx - " + apiEx.getMessage()); logger.error("Linstor: ApiEx - " + apiEx.getMessage());
@ -394,22 +408,166 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
storagePoolVO.getUserInfo() : "DfltRscGrp"; storagePoolVO.getUserInfo() : "DfltRscGrp";
} }
private String createResourceBase( /**
String rscName, long sizeInBytes, String volName, String vmName, DevelopersApi api, String rscGrp) { * Returns the layerlist of the resourceGroup with encryption(LUKS) added above STORAGE.
ResourceGroupSpawn rscGrpSpawn = new ResourceGroupSpawn(); * If the resourceGroup layer list already contains LUKS this layer list will be returned.
rscGrpSpawn.setResourceDefinitionName(rscName); * @param api Linstor developers API
rscGrpSpawn.addVolumeSizesItem(sizeInBytes / 1024); * @param resourceGroup Resource group to get the encryption layer list
* @return layer list with LUKS added
*/
public List<LayerType> getEncryptedLayerList(DevelopersApi api, String resourceGroup) {
try {
List<ResourceGroup> rscGrps = api.resourceGroupList(
Collections.singletonList(resourceGroup), Collections.emptyList(), null, null);
if (CollectionUtils.isEmpty(rscGrps)) {
throw new CloudRuntimeException(
String.format("Resource Group %s not found on Linstor cluster.", resourceGroup));
}
final ResourceGroup rscGrp = rscGrps.get(0);
List<LayerType> layers = Arrays.asList(LayerType.DRBD, LayerType.LUKS, LayerType.STORAGE);
List<String> curLayerStack = rscGrp.getSelectFilter() != null ?
rscGrp.getSelectFilter().getLayerStack() : Collections.emptyList();
if (CollectionUtils.isNotEmpty(curLayerStack)) {
layers = curLayerStack.stream().map(LayerType::valueOf).collect(Collectors.toList());
if (!layers.contains(LayerType.LUKS)) {
layers.add(layers.size() - 1, LayerType.LUKS); // lowest layer is STORAGE
}
}
return layers;
} catch (ApiException e) {
throw new CloudRuntimeException(
String.format("Resource Group %s not found on Linstor cluster.", resourceGroup));
}
}
/**
* Spawns a new Linstor resource with the given arguments.
* @param api
* @param newRscName
* @param sizeInBytes
* @param isTemplate
* @param rscGrpName
* @param volName
* @param vmName
* @throws ApiException
*/
private void spawnResource(
DevelopersApi api, String newRscName, long sizeInBytes, boolean isTemplate, String rscGrpName,
String volName, String vmName, @Nullable Long passPhraseId, @Nullable byte[] passPhrase) throws ApiException
{
ResourceGroupSpawn rscGrpSpawn = new ResourceGroupSpawn();
rscGrpSpawn.setResourceDefinitionName(newRscName);
rscGrpSpawn.addVolumeSizesItem(sizeInBytes / 1024);
if (passPhraseId != null) {
AutoSelectFilter asf = new AutoSelectFilter();
List<LayerType> luksLayers = getEncryptedLayerList(api, rscGrpName);
asf.setLayerStack(luksLayers.stream().map(LayerType::toString).collect(Collectors.toList()));
rscGrpSpawn.setSelectFilter(asf);
if (passPhrase != null) {
String utf8Passphrase = new String(passPhrase, StandardCharsets.UTF_8);
rscGrpSpawn.setVolumePassphrases(Collections.singletonList(utf8Passphrase));
}
}
if (isTemplate) {
Properties props = new Properties();
props.put(LinstorUtil.getTemplateForAuxPropKey(rscGrpName), "true");
rscGrpSpawn.setResourceDefinitionProps(props);
}
logger.info("Linstor: Spawn resource " + newRscName);
ApiCallRcList answers = api.resourceGroupSpawn(rscGrpName, rscGrpSpawn);
checkLinstorAnswersThrow(answers);
answers = LinstorUtil.applyAuxProps(api, newRscName, volName, vmName);
checkLinstorAnswersThrow(answers);
}
/**
* Condition if a template resource can be shared with the given resource group.
* @param tgtRscGrp
* @param tgtLayerStack
* @param rg
* @return True if the template resource can be shared, else false.
*/
private boolean canShareTemplateForResourceGroup(
ResourceGroup tgtRscGrp, List<String> tgtLayerStack, ResourceGroup rg) {
List<String> rgLayerStack = rg.getSelectFilter() != null ?
rg.getSelectFilter().getLayerStack() : null;
return Objects.equals(tgtLayerStack, rgLayerStack) &&
Objects.equals(tgtRscGrp.getSelectFilter().getStoragePoolList(),
rg.getSelectFilter().getStoragePoolList());
}
/**
* Searches for a shareable template for this rscGrpName and sets the aux template property.
* @param api
* @param rscName
* @param rscGrpName
* @param existingRDs
* @return
* @throws ApiException
*/
private boolean foundShareableTemplate(
DevelopersApi api, String rscName, String rscGrpName,
List<Pair<ResourceDefinition, ResourceGroup>> existingRDs) throws ApiException {
if (!existingRDs.isEmpty()) {
ResourceGroup tgtRscGrp = api.resourceGroupList(
Collections.singletonList(rscGrpName), null, null, null).get(0);
List<String> tgtLayerStack = tgtRscGrp.getSelectFilter() != null ?
tgtRscGrp.getSelectFilter().getLayerStack() : null;
// check if there is already a template copy, that we could reuse
// this means if select filters are similar enough to allow cloning from
for (Pair<ResourceDefinition, ResourceGroup> rdPair : existingRDs) {
ResourceGroup rg = rdPair.second();
if (canShareTemplateForResourceGroup(tgtRscGrp, tgtLayerStack, rg)) {
LinstorUtil.setAuxTemplateForProperty(api, rscName, rscGrpName);
return true;
}
}
}
return false;
}
/**
* Creates a new Linstor resource.
* @param rscName
* @param sizeInBytes
* @param volName
* @param vmName
* @param api
* @param rscGrp
* @param poolId
* @param isTemplate indicates if the resource is a template
* @return true if a new resource was created, false if it already existed or was reused.
*/
private boolean createResourceBase(
String rscName, long sizeInBytes, String volName, String vmName,
@Nullable Long passPhraseId, @Nullable byte[] passPhrase, DevelopersApi api,
String rscGrp, long poolId, boolean isTemplate)
{
try try
{ {
logger.info("Linstor: Spawn resource " + rscName); logger.debug("createRscBase: {} :: {} :: {}", rscName, rscGrp, isTemplate);
ApiCallRcList answers = api.resourceGroupSpawn(rscGrp, rscGrpSpawn); List<Pair<ResourceDefinition, ResourceGroup>> existingRDs = LinstorUtil.getRDAndRGListStartingWith(api, rscName);
checkLinstorAnswersThrow(answers);
answers = LinstorUtil.applyAuxProps(api, rscName, volName, vmName); String fullRscName = String.format("%s-%d", rscName, poolId);
checkLinstorAnswersThrow(answers); boolean alreadyCreated = existingRDs.stream()
.anyMatch(p -> p.first().getName().equalsIgnoreCase(fullRscName)) ||
return LinstorUtil.getDevicePath(api, rscName); existingRDs.stream().anyMatch(p -> p.first().getProps().containsKey(LinstorUtil.getTemplateForAuxPropKey(rscGrp)));
if (!alreadyCreated) {
boolean createNewRsc = !foundShareableTemplate(api, rscName, rscGrp, existingRDs);
if (createNewRsc) {
String newRscName = existingRDs.isEmpty() ? rscName : fullRscName;
spawnResource(api, newRscName, sizeInBytes, isTemplate, rscGrp,
volName, vmName, passPhraseId, passPhrase);
}
return createNewRsc;
}
return false;
} catch (ApiException apiEx) } catch (ApiException apiEx)
{ {
logger.error("Linstor: ApiEx - " + apiEx.getMessage()); logger.error("Linstor: ApiEx - " + apiEx.getMessage());
@ -422,8 +580,9 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
final String rscGrp = getRscGrp(storagePoolVO); final String rscGrp = getRscGrp(storagePoolVO);
final String rscName = LinstorUtil.RSC_PREFIX + vol.getUuid(); final String rscName = LinstorUtil.RSC_PREFIX + vol.getUuid();
String deviceName = createResourceBase( createResourceBase(
rscName, vol.getSize(), vol.getName(), vol.getAttachedVmName(), linstorApi, rscGrp); rscName, vol.getSize(), vol.getName(), vol.getAttachedVmName(), vol.getPassphraseId(), vol.getPassphrase(),
linstorApi, rscGrp, storagePoolVO.getId(), false);
try try
{ {
@ -450,20 +609,83 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
} }
} }
/**
* Update resource-definitions resource-group to the correct one if it isn't already the intended.
* @param api Linstor api
* @param rscName resource name to check the resource group
* @param tgtRscGrp resource group name to set
* @throws ApiException exception if any api error occurred
*/
private void updateRscGrpIfNecessary(DevelopersApi api, String rscName, String tgtRscGrp) throws ApiException {
List<ResourceDefinition> rscDfns = api.resourceDefinitionList(
Collections.singletonList(rscName), null, null, null);
if (rscDfns != null && !rscDfns.isEmpty()) {
ResourceDefinition rscDfn = rscDfns.get(0);
if (!rscDfn.getResourceGroupName().equalsIgnoreCase(tgtRscGrp)) {
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
rdm.setResourceGroup(tgtRscGrp);
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
if (answers.hasError()) {
String bestError = LinstorUtil.getBestErrorMessage(answers);
logger.error("Update resource group on {} error: {}", rscName, bestError);
throw new CloudRuntimeException(bestError);
} else {
logger.info("Successfully changed resource group to {} on {}", tgtRscGrp, rscName);
}
}
}
}
/**
* If a resource is cloned, all properties are cloned too, but the _cs-template-for properties,
* should only stay on the template resource, so delete them in this method.
* @param api
* @param rscName
* @throws ApiException
*/
private void deleteTemplateForProps(
DevelopersApi api, String rscName) throws ApiException {
List<ResourceDefinition> rdList = api.resourceDefinitionList(
Collections.singletonList(rscName), null, null, null);
if (CollectionUtils.isNotEmpty(rdList)) {
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
List<String> deleteProps = rdList.get(0).getProps().keySet().stream()
.filter(key -> key.startsWith("Aux/" + LinstorUtil.CS_TEMPLATE_FOR_PREFIX))
.collect(Collectors.toList());
rdm.deleteProps(deleteProps);
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
checkLinstorAnswers(answers);
}
}
private String cloneResource(long csCloneId, VolumeInfo volumeInfo, StoragePoolVO storagePoolVO) { private String cloneResource(long csCloneId, VolumeInfo volumeInfo, StoragePoolVO storagePoolVO) {
// get the cached template on this storage // get the cached template on this storage
VMTemplateStoragePoolVO tmplPoolRef = _vmTemplatePoolDao.findByPoolTemplate( VMTemplateStoragePoolVO tmplPoolRef = _vmTemplatePoolDao.findByPoolTemplate(
storagePoolVO.getId(), csCloneId, null); storagePoolVO.getId(), csCloneId, null);
if (tmplPoolRef != null) { if (tmplPoolRef != null) {
final String cloneRes = LinstorUtil.RSC_PREFIX + tmplPoolRef.getLocalDownloadPath(); final String templateRscName = LinstorUtil.RSC_PREFIX + tmplPoolRef.getLocalDownloadPath();
final String rscName = LinstorUtil.RSC_PREFIX + volumeInfo.getUuid(); final String rscName = LinstorUtil.RSC_PREFIX + volumeInfo.getUuid();
final DevelopersApi linstorApi = LinstorUtil.getLinstorAPI(storagePoolVO.getHostAddress()); final DevelopersApi linstorApi = LinstorUtil.getLinstorAPI(storagePoolVO.getHostAddress());
try { try {
logger.info("Clone resource definition " + cloneRes + " to " + rscName); ResourceDefinition templateRD = LinstorUtil.findResourceDefinition(
linstorApi, templateRscName, getRscGrp(storagePoolVO));
final String cloneRes = templateRD != null ? templateRD.getName() : templateRscName;
logger.info("Clone resource definition {} to {}", cloneRes, rscName);
ResourceDefinitionCloneRequest cloneRequest = new ResourceDefinitionCloneRequest(); ResourceDefinitionCloneRequest cloneRequest = new ResourceDefinitionCloneRequest();
cloneRequest.setName(rscName); cloneRequest.setName(rscName);
if (volumeInfo.getPassphraseId() != null) {
List<LayerType> encryptionLayer = getEncryptedLayerList(linstorApi, getRscGrp(storagePoolVO));
cloneRequest.setLayerList(encryptionLayer);
if (volumeInfo.getPassphrase() != null) {
String utf8Passphrase = new String(volumeInfo.getPassphrase(), StandardCharsets.UTF_8);
cloneRequest.setVolumePassphrases(Collections.singletonList(utf8Passphrase));
}
}
ResourceDefinitionCloneStarted cloneStarted = linstorApi.resourceDefinitionClone( ResourceDefinitionCloneStarted cloneStarted = linstorApi.resourceDefinitionClone(
cloneRes, cloneRequest); cloneRes, cloneRequest);
@ -479,6 +701,9 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
resizeResource(linstorApi, rscName, volumeInfo.getSize()); resizeResource(linstorApi, rscName, volumeInfo.getSize());
} }
updateRscGrpIfNecessary(linstorApi, rscName, getRscGrp(storagePoolVO));
deleteTemplateForProps(linstorApi, rscName);
LinstorUtil.applyAuxProps(linstorApi, rscName, volumeInfo.getName(), volumeInfo.getAttachedVmName()); LinstorUtil.applyAuxProps(linstorApi, rscName, volumeInfo.getName(), volumeInfo.getAttachedVmName());
applyQoSSettings(storagePoolVO, linstorApi, rscName, volumeInfo.getMaxIops()); applyQoSSettings(storagePoolVO, linstorApi, rscName, volumeInfo.getMaxIops());
@ -906,41 +1131,74 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
return LinstorUtil.getDevicePath(api, restoredName); return LinstorUtil.getDevicePath(api, restoredName);
} }
/**
* Updates the template_spool_ref DB entry to indicate that this template was fully downloaded and is ready.
* @param templateId
* @param destTemplateInfoUuid
* @param destDataStoreId
* @param templateSize
*/
private void updateTemplateSpoolRef(
long templateId, String destTemplateInfoUuid, long destDataStoreId, long templateSize) {
VMTemplateStoragePoolVO destVolumeTemplateStoragePoolVO = _vmTemplatePoolDao.findByPoolTemplate(
destDataStoreId, templateId, null);
if (destVolumeTemplateStoragePoolVO == null) {
throw new CloudRuntimeException(
String.format("Unable to find template_spool_ref entry for pool_id %d and template_id %d",
destDataStoreId, templateId));
}
destVolumeTemplateStoragePoolVO.setDownloadPercent(100);
destVolumeTemplateStoragePoolVO.setDownloadState(VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
destVolumeTemplateStoragePoolVO.setState(ObjectInDataStoreStateMachine.State.Ready);
destVolumeTemplateStoragePoolVO.setTemplateSize(templateSize);
destVolumeTemplateStoragePoolVO.setLocalDownloadPath(destTemplateInfoUuid);
destVolumeTemplateStoragePoolVO.setInstallPath(destTemplateInfoUuid);
_vmTemplatePoolDao.persist(destVolumeTemplateStoragePoolVO);
}
private Answer copyTemplate(DataObject srcData, DataObject dstData) { private Answer copyTemplate(DataObject srcData, DataObject dstData) {
TemplateInfo tInfo = (TemplateInfo) dstData; TemplateInfo tInfo = (TemplateInfo) dstData;
final StoragePoolVO pool = _storagePoolDao.findById(dstData.getDataStore().getId()); final StoragePoolVO pool = _storagePoolDao.findById(dstData.getDataStore().getId());
final DevelopersApi api = LinstorUtil.getLinstorAPI(pool.getHostAddress()); final DevelopersApi api = LinstorUtil.getLinstorAPI(pool.getHostAddress());
final String rscName = LinstorUtil.RSC_PREFIX + dstData.getUuid(); final String rscName = LinstorUtil.RSC_PREFIX + dstData.getUuid();
createResourceBase( boolean newCreated = createResourceBase(
LinstorUtil.RSC_PREFIX + dstData.getUuid(), LinstorUtil.RSC_PREFIX + dstData.getUuid(),
tInfo.getSize(), tInfo.getSize(),
tInfo.getName(), tInfo.getName(),
"", "",
null,
null,
api, api,
getRscGrp(pool)); getRscGrp(pool),
pool.getId(),
true);
int nMaxExecutionMinutes = NumbersUtil.parseInt(
_configDao.getValue(Config.SecStorageCmdExecutionTimeMax.key()), 30);
CopyCommand cmd = new CopyCommand(
srcData.getTO(),
dstData.getTO(),
nMaxExecutionMinutes * 60 * 1000,
VirtualMachineManager.ExecuteInSequence.value());
Answer answer; Answer answer;
if (newCreated) {
int nMaxExecutionMinutes = NumbersUtil.parseInt(
_configDao.getValue(Config.SecStorageCmdExecutionTimeMax.key()), 30);
CopyCommand cmd = new CopyCommand(
srcData.getTO(),
dstData.getTO(),
nMaxExecutionMinutes * 60 * 1000,
VirtualMachineManager.ExecuteInSequence.value());
try { try {
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, rscName); Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, rscName);
if (optEP.isPresent()) { if (optEP.isPresent()) {
answer = optEP.get().sendMessage(cmd); answer = optEP.get().sendMessage(cmd);
} } else {
else { answer = new Answer(cmd, false, "Unable to get matching Linstor endpoint.");
answer = new Answer(cmd, false, "Unable to get matching Linstor endpoint."); deleteResourceDefinition(pool, rscName);
}
} catch (ApiException exc) {
logger.error("copy template failed: ", exc);
deleteResourceDefinition(pool, rscName); deleteResourceDefinition(pool, rscName);
throw new CloudRuntimeException(exc.getBestMessage());
} }
} catch (ApiException exc) { } else {
logger.error("copy template failed: ", exc); updateTemplateSpoolRef(dstData.getId(), tInfo.getUuid(), dstData.getDataStore().getId(), srcData.getSize());
deleteResourceDefinition(pool, rscName); answer = new Answer(new CopyCmdAnswer(dstData.getTO()));
throw new CloudRuntimeException(exc.getBestMessage());
} }
return answer; return answer;
} }

View File

@ -26,6 +26,7 @@ import com.linbit.linstor.api.model.Node;
import com.linbit.linstor.api.model.Properties; import com.linbit.linstor.api.model.Properties;
import com.linbit.linstor.api.model.ProviderKind; import com.linbit.linstor.api.model.ProviderKind;
import com.linbit.linstor.api.model.Resource; import com.linbit.linstor.api.model.Resource;
import com.linbit.linstor.api.model.ResourceDefinition;
import com.linbit.linstor.api.model.ResourceDefinitionModify; import com.linbit.linstor.api.model.ResourceDefinitionModify;
import com.linbit.linstor.api.model.ResourceGroup; import com.linbit.linstor.api.model.ResourceGroup;
import com.linbit.linstor.api.model.ResourceWithVolumes; import com.linbit.linstor.api.model.ResourceWithVolumes;
@ -37,8 +38,11 @@ import javax.annotation.Nonnull;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@ -49,6 +53,7 @@ public class LinstorUtil {
public final static String PROVIDER_NAME = "Linstor"; public final static String PROVIDER_NAME = "Linstor";
public static final String RSC_PREFIX = "cs-"; public static final String RSC_PREFIX = "cs-";
public static final String RSC_GROUP = "resourceGroup"; public static final String RSC_GROUP = "resourceGroup";
public static final String CS_TEMPLATE_FOR_PREFIX = "_cs-template-for-";
public static final String TEMP_VOLUME_ID = "tempVolumeId"; public static final String TEMP_VOLUME_ID = "tempVolumeId";
@ -288,4 +293,114 @@ public class LinstorUtil {
} }
return answers; return answers;
} }
/**
* Returns all resource definitions that start with the given `startWith` name.
* @param api
* @param startWith startWith String
* @return a List with all ResourceDefinition starting with `startWith`
* @throws ApiException
*/
public static List<ResourceDefinition> getRDListStartingWith(DevelopersApi api, String startWith)
throws ApiException
{
List<ResourceDefinition> rscDfns = api.resourceDefinitionList(null, null, null, null);
return rscDfns.stream()
.filter(rscDfn -> rscDfn.getName().toLowerCase().startsWith(startWith.toLowerCase()))
.collect(Collectors.toList());
}
/**
* Returns a pair list of resource-definitions with ther 1:1 mapped resource-group objects that start with the
* resource name `startWith`
* @param api
* @param startWith
* @return
* @throws ApiException
*/
public static List<Pair<ResourceDefinition, ResourceGroup>> getRDAndRGListStartingWith(DevelopersApi api, String startWith)
throws ApiException
{
List<ResourceDefinition> foundRDs = getRDListStartingWith(api, startWith);
List<String> rscGrpStrings = foundRDs.stream()
.map(ResourceDefinition::getResourceGroupName)
.collect(Collectors.toList());
Map<String, ResourceGroup> rscGrps = api.resourceGroupList(rscGrpStrings, null, null, null).stream()
.collect(Collectors.toMap(ResourceGroup::getName, rscGrp -> rscGrp));
return foundRDs.stream()
.map(rd -> new Pair<>(rd, rscGrps.get(rd.getResourceGroupName())))
.collect(Collectors.toList());
}
/**
* The full name of template-for aux property key.
* @param rscGrpName
* @return
*/
public static String getTemplateForAuxPropKey(String rscGrpName) {
return String.format("Aux/%s%s", CS_TEMPLATE_FOR_PREFIX, rscGrpName);
}
/**
* Template resource should have a _cs-template-for-... property, that indicates to which resource-group
* this template belongs, it works like a refcount to keep it alive if there are still such properties on the
* template resource. That methods set the correct property on the given resource.
* @param api
* @param rscName Resource name to set the property.
* @param rscGrpName Resource group this template should belong too.
* @throws ApiException
*/
public static void setAuxTemplateForProperty(DevelopersApi api, String rscName, String rscGrpName)
throws ApiException
{
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
Properties props = new Properties();
String propKey = LinstorUtil.getTemplateForAuxPropKey(rscGrpName);
props.put(propKey, "true");
rdm.setOverrideProps(props);
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
if (answers.hasError()) {
String bestError = LinstorUtil.getBestErrorMessage(answers);
LOGGER.error("Set {} on {} error: {}", propKey, rscName, bestError);
throw new CloudRuntimeException(bestError);
} else {
LOGGER.info("Set {} property on {}", propKey, rscName);
}
}
/**
* Find the correct resource definition to clone from.
* There could be multiple resource definitions for the same template, with the same prefix.
* This method searches for which resource group the resource definition was intended and returns that.
* If no exact resource definition could be found, we return the first with a similar name as a fallback.
* If there is not even one with the correct prefix, we return null.
* @param api
* @param rscName
* @param rscGrpName
* @return The resource-definition to clone from, if no template and no match, return null.
* @throws ApiException
*/
public static ResourceDefinition findResourceDefinition(DevelopersApi api, String rscName, String rscGrpName)
throws ApiException {
List<ResourceDefinition> rscDfns = api.resourceDefinitionList(null, null, null, null);
List<ResourceDefinition> rdsStartingWith = rscDfns.stream()
.filter(rscDfn -> rscDfn.getName().toLowerCase().startsWith(rscName.toLowerCase()))
.collect(Collectors.toList());
if (rdsStartingWith.isEmpty()) {
return null;
}
Optional<ResourceDefinition> rd = rdsStartingWith.stream()
.filter(rscDfn -> rscDfn.getProps().containsKey(LinstorUtil.getTemplateForAuxPropKey(rscGrpName)))
.findFirst();
return rd.orElseGet(() -> rdsStartingWith.get(0));
}
} }

View File

@ -0,0 +1,87 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.storage.datastore.driver;
import com.linbit.linstor.api.ApiException;
import com.linbit.linstor.api.DevelopersApi;
import com.linbit.linstor.api.model.AutoSelectFilter;
import com.linbit.linstor.api.model.LayerType;
import com.linbit.linstor.api.model.ResourceGroup;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class LinstorPrimaryDataStoreDriverImplTest {
private DevelopersApi api;
@InjectMocks
private LinstorPrimaryDataStoreDriverImpl linstorPrimaryDataStoreDriver;
@Before
public void setUp() {
api = mock(DevelopersApi.class);
}
@Test
public void testGetEncryptedLayerList() throws ApiException {
ResourceGroup dfltRscGrp = new ResourceGroup();
dfltRscGrp.setName("DfltRscGrp");
ResourceGroup bCacheRscGrp = new ResourceGroup();
bCacheRscGrp.setName("BcacheGrp");
AutoSelectFilter asf = new AutoSelectFilter();
asf.setLayerStack(Arrays.asList(LayerType.DRBD.name(), LayerType.BCACHE.name(), LayerType.STORAGE.name()));
asf.setStoragePool("nvmePool");
bCacheRscGrp.setSelectFilter(asf);
ResourceGroup encryptedGrp = new ResourceGroup();
encryptedGrp.setName("EncryptedGrp");
AutoSelectFilter asf2 = new AutoSelectFilter();
asf2.setLayerStack(Arrays.asList(LayerType.DRBD.name(), LayerType.LUKS.name(), LayerType.STORAGE.name()));
asf2.setStoragePool("ssdPool");
encryptedGrp.setSelectFilter(asf2);
when(api.resourceGroupList(Collections.singletonList("DfltRscGrp"), Collections.emptyList(), null, null))
.thenReturn(Collections.singletonList(dfltRscGrp));
when(api.resourceGroupList(Collections.singletonList("BcacheGrp"), Collections.emptyList(), null, null))
.thenReturn(Collections.singletonList(bCacheRscGrp));
when(api.resourceGroupList(Collections.singletonList("EncryptedGrp"), Collections.emptyList(), null, null))
.thenReturn(Collections.singletonList(encryptedGrp));
List<LayerType> layers = linstorPrimaryDataStoreDriver.getEncryptedLayerList(api, "DfltRscGrp");
Assert.assertEquals(Arrays.asList(LayerType.DRBD, LayerType.LUKS, LayerType.STORAGE), layers);
layers = linstorPrimaryDataStoreDriver.getEncryptedLayerList(api, "BcacheGrp");
Assert.assertEquals(Arrays.asList(LayerType.DRBD, LayerType.BCACHE, LayerType.LUKS, LayerType.STORAGE), layers);
layers = linstorPrimaryDataStoreDriver.getEncryptedLayerList(api, "EncryptedGrp");
Assert.assertEquals(Arrays.asList(LayerType.DRBD, LayerType.LUKS, LayerType.STORAGE), layers);
}
}

View File

@ -0,0 +1,127 @@
// 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.datastore.util;
import com.linbit.linstor.api.ApiException;
import com.linbit.linstor.api.DevelopersApi;
import com.linbit.linstor.api.model.AutoSelectFilter;
import com.linbit.linstor.api.model.Node;
import com.linbit.linstor.api.model.Properties;
import com.linbit.linstor.api.model.ProviderKind;
import com.linbit.linstor.api.model.ResourceGroup;
import com.linbit.linstor.api.model.StoragePool;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class LinstorUtilTest {
private static final String LINSTOR_URL_TEST = "devnull.com:3370";
private DevelopersApi api;
private Node mockNode(String name) {
Node nodeMock = new Node();
nodeMock.setName(name);
return nodeMock;
}
private StoragePool mockStoragePool(String name, String node, ProviderKind kind) {
StoragePool sp = new StoragePool();
sp.setStoragePoolName(name);
sp.setNodeName(node);
sp.setProviderKind(kind);
return sp;
}
@Before
public void setUp() throws ApiException {
api = mock(DevelopersApi.class);
when(api.nodeList(Collections.emptyList(), Collections.emptyList(), null, null))
.thenReturn(Arrays.asList(mockNode("nodeA"), mockNode("nodeB"), mockNode("nodeC")));
ResourceGroup csGroup = new ResourceGroup();
csGroup.setName("cloudstack");
AutoSelectFilter asf = new AutoSelectFilter();
asf.setPlaceCount(2);
csGroup.setSelectFilter(asf);
when(api.resourceGroupList(Collections.singletonList("cloudstack"), null, null, null))
.thenReturn(Collections.singletonList(csGroup));
when(api.viewStoragePools(Collections.emptyList(), null, null, null, null, true))
.thenReturn(Arrays.asList(
mockStoragePool("thinpool", "nodeA", ProviderKind.LVM_THIN),
mockStoragePool("thinpool", "nodeB", ProviderKind.LVM_THIN),
mockStoragePool("thinpool", "nodeC", ProviderKind.LVM_THIN)
));
// when(LinstorUtil.getLinstorAPI(LINSTOR_URL_TEST)).thenReturn(api);
}
@Test
public void testGetLinstorNodeNames() throws ApiException {
List<String> linstorNodes = LinstorUtil.getLinstorNodeNames(api);
Assert.assertEquals(Arrays.asList("nodeA", "nodeB", "nodeC"), linstorNodes);
}
@Test
public void testGetSnapshotPath() {
{
StoragePool spLVMThin = new StoragePool();
Properties lvmThinProps = new Properties();
lvmThinProps.put("StorDriver/StorPoolName", "storage/storage-thin");
spLVMThin.setProps(lvmThinProps);
spLVMThin.setProviderKind(ProviderKind.LVM_THIN);
String snapPath = LinstorUtil.getSnapshotPath(spLVMThin, "cs-cb32532a-dd8f-47e0-a81c-8a75573d3545", "snap3");
Assert.assertEquals("/dev/mapper/storage-cs--cb32532a--dd8f--47e0--a81c--8a75573d3545_00000_snap3", snapPath);
}
{
StoragePool spZFS = new StoragePool();
Properties zfsProps = new Properties();
zfsProps.put("StorDriver/StorPoolName", "linstorPool");
spZFS.setProps(zfsProps);
spZFS.setProviderKind(ProviderKind.ZFS);
String snapPath = LinstorUtil.getSnapshotPath(spZFS, "cs-cb32532a-dd8f-47e0-a81c-8a75573d3545", "snap2");
Assert.assertEquals("zfs://linstorPool/cs-cb32532a-dd8f-47e0-a81c-8a75573d3545_00000@snap2", snapPath);
}
}
@Test
public void testGetRscGroupStoragePools() throws ApiException {
List<StoragePool> storagePools = LinstorUtil.getRscGroupStoragePools(api, "cloudstack");
List<String> names = storagePools.stream()
.map(sp -> String.format("%s::%s", sp.getNodeName(), sp.getStoragePoolName()))
.collect(Collectors.toList());
Assert.assertEquals(names, Arrays.asList("nodeA::thinpool", "nodeB::thinpool", "nodeC::thinpool"));
}
}

View File

@ -146,16 +146,18 @@ public class PrimeraAdapter implements ProviderAdapter {
} }
// determine volume type based on offering // determine volume type based on offering
// THIN: tpvv=true, reduce=false // tpvv -- thin provisioned virtual volume (no deduplication)
// SPARSE: tpvv=true, reduce=true // reduce -- thin provisioned virtual volume (with duplication and compression, also known as DECO)
// THICK: tpvv=false, tpZeroFill=true (not supported) // these are the only choices with newer Primera devices
// we will use THIN for the deduplicated/compressed type and SPARSE for thin-only without dedup/compress
// note: DECO/reduce type must be at least 16GB in size
if (diskOffering != null) { if (diskOffering != null) {
if (diskOffering.getType() == ProvisioningType.THIN) { if (diskOffering.getType() == ProvisioningType.THIN) {
request.setTpvv(true);
request.setReduce(false);
} else if (diskOffering.getType() == ProvisioningType.SPARSE) {
request.setTpvv(false); request.setTpvv(false);
request.setReduce(true); request.setReduce(true);
} else if (diskOffering.getType() == ProvisioningType.SPARSE) {
request.setTpvv(true);
request.setReduce(false);
} else if (diskOffering.getType() == ProvisioningType.FAT) { } else if (diskOffering.getType() == ProvisioningType.FAT) {
throw new RuntimeException("This storage provider does not support FAT provisioned volumes"); throw new RuntimeException("This storage provider does not support FAT provisioned volumes");
} }
@ -166,8 +168,16 @@ public class PrimeraAdapter implements ProviderAdapter {
} }
} else { } else {
// default to deduplicated volume // default to deduplicated volume
request.setReduce(true);
request.setTpvv(false); request.setTpvv(false);
request.setReduce(true);
}
if (request.getReduce() == true) {
// check if sizeMiB is less than 16GB adjust up to 16GB. The AdaptiveDatastoreDriver will automatically
// update this on the cloudstack side to match
if (request.getSizeMiB() < 16 * 1024) {
request.setSizeMiB(16 * 1024);
}
} }
request.setComment(ProviderVolumeNamer.generateObjectComment(context, dataIn)); request.setComment(ProviderVolumeNamer.generateObjectComment(context, dataIn));
@ -185,8 +195,11 @@ public class PrimeraAdapter implements ProviderAdapter {
if (host == null) { if (host == null) {
throw new RuntimeException("Unable to find host " + hostname + " on storage provider"); throw new RuntimeException("Unable to find host " + hostname + " on storage provider");
} }
request.setHostname(host.getName());
// check if we already have a vlun for requested host
Integer vlun = hasVlun(hostname, hostname);
if (vlun == null) {
request.setHostname(host.getName());
request.setVolumeName(dataIn.getExternalName()); request.setVolumeName(dataIn.getExternalName());
request.setAutoLun(true); request.setAutoLun(true);
// auto-lun returned here: Location: /api/v1/vluns/test_vv02,252,mysystem,2:2:4 // auto-lun returned here: Location: /api/v1/vluns/test_vv02,252,mysystem,2:2:4
@ -198,7 +211,13 @@ public class PrimeraAdapter implements ProviderAdapter {
if (toks.length <2) { if (toks.length <2) {
throw new RuntimeException("Attach volume failed with invalid location response to vlun add command on storage provider. Provided location: " + location); throw new RuntimeException("Attach volume failed with invalid location response to vlun add command on storage provider. Provided location: " + location);
} }
return toks[1]; try {
vlun = Integer.parseInt(toks[1]);
} catch (NumberFormatException e) {
throw new RuntimeException("VLUN attach request succeeded but the VLUN value is not a valid number: " + toks[1]);
}
}
return vlun.toString();
} }
/** /**
@ -233,6 +252,20 @@ public class PrimeraAdapter implements ProviderAdapter {
} }
} }
private Integer hasVlun(String externalName, String hostname) {
PrimeraVlunList list = getVluns(externalName);
if (list != null && list.getMembers().size() > 0) {
for (PrimeraVlun vlun: list.getMembers()) {
if (hostname != null) {
if (vlun.getHostname().equals(hostname) || vlun.getHostname().equals(hostname.split("\\.")[0])) {
return vlun.getLun();
}
}
}
}
return null;
}
public void removeVlun(String name, Integer lunid, String hostString) { public void removeVlun(String name, Integer lunid, String hostString) {
// hostString can be a hostname OR "set:<hostsetname>". It is stored this way // hostString can be a hostname OR "set:<hostsetname>". It is stored this way
// in the appliance and returned as the vlun's name/string. // in the appliance and returned as the vlun's name/string.

View File

@ -175,7 +175,7 @@
<cs.nitro.version>10.1</cs.nitro.version> <cs.nitro.version>10.1</cs.nitro.version>
<cs.opensaml.version>2.6.6</cs.opensaml.version> <cs.opensaml.version>2.6.6</cs.opensaml.version>
<cs.rados-java.version>0.6.0</cs.rados-java.version> <cs.rados-java.version>0.6.0</cs.rados-java.version>
<cs.java-linstor.version>0.5.2</cs.java-linstor.version> <cs.java-linstor.version>0.6.0</cs.java-linstor.version>
<cs.reflections.version>0.10.2</cs.reflections.version> <cs.reflections.version>0.10.2</cs.reflections.version>
<cs.servicemix.version>3.4.4_1</cs.servicemix.version> <cs.servicemix.version>3.4.4_1</cs.servicemix.version>
<cs.servlet.version>4.0.1</cs.servlet.version> <cs.servlet.version>4.0.1</cs.servlet.version>

View File

@ -22,10 +22,18 @@
# #
############################################################################################# #############################################################################################
SCRIPT_NAME=$(basename "$0")
if [[ $(pgrep -f ${SCRIPT_NAME}) != "$$" ]]; then
echo "Another instance of ${SCRIPT_NAME} is already running! Exiting"
exit
fi
cd $(dirname $0) cd $(dirname $0)
for WWID in $(multipathd list maps status | awk '{ if ($4 == 0) { print substr($1,2); }}'); do for WWID in $(multipathd list maps status | awk '{ if ($4 == 0) { print substr($1,2); }}'); do
./removeVolume.sh ${WWID} ./disconnectVolume.sh ${WWID}
done done
exit 0 exit 0

View File

@ -66,6 +66,9 @@ fi
logger -t CS_SCSI_VOL_REMOVE "${WWID} successfully purged from multipath along with slave devices" logger -t CS_SCSI_VOL_REMOVE "${WWID} successfully purged from multipath along with slave devices"
# Added to give time for the event to be fired to the server
sleep 10
echo "$(date): ${WWID} removed" echo "$(date): ${WWID} removed"
exit 0 exit 0

View File

@ -355,263 +355,263 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
private static final String ID_FIELD = "id"; private static final String ID_FIELD = "id";
@Inject @Inject
private AccountManager accountMgr; AccountManager accountMgr;
@Inject @Inject
private ProjectManager _projectMgr; ProjectManager _projectMgr;
@Inject @Inject
private DomainDao _domainDao; DomainDao _domainDao;
@Inject @Inject
private DomainJoinDao _domainJoinDao; DomainJoinDao _domainJoinDao;
@Inject @Inject
private UserAccountJoinDao _userAccountJoinDao; UserAccountJoinDao _userAccountJoinDao;
@Inject @Inject
private EventDao eventDao; EventDao eventDao;
@Inject @Inject
private EventJoinDao _eventJoinDao; EventJoinDao _eventJoinDao;
@Inject @Inject
private ResourceTagJoinDao _resourceTagJoinDao; ResourceTagJoinDao _resourceTagJoinDao;
@Inject @Inject
private InstanceGroupJoinDao _vmGroupJoinDao; InstanceGroupJoinDao _vmGroupJoinDao;
@Inject @Inject
private UserVmJoinDao _userVmJoinDao; UserVmJoinDao _userVmJoinDao;
@Inject @Inject
private UserVmDao userVmDao; UserVmDao userVmDao;
@Inject @Inject
private VMInstanceDao _vmInstanceDao; VMInstanceDao _vmInstanceDao;
@Inject @Inject
private SecurityGroupJoinDao _securityGroupJoinDao; SecurityGroupJoinDao _securityGroupJoinDao;
@Inject @Inject
private SecurityGroupVMMapDao securityGroupVMMapDao; SecurityGroupVMMapDao securityGroupVMMapDao;
@Inject @Inject
private DomainRouterJoinDao _routerJoinDao; DomainRouterJoinDao _routerJoinDao;
@Inject @Inject
private ProjectInvitationJoinDao _projectInvitationJoinDao; ProjectInvitationJoinDao _projectInvitationJoinDao;
@Inject @Inject
private ProjectJoinDao _projectJoinDao; ProjectJoinDao _projectJoinDao;
@Inject @Inject
private ProjectDao _projectDao; ProjectDao _projectDao;
@Inject @Inject
private ProjectAccountDao _projectAccountDao; ProjectAccountDao _projectAccountDao;
@Inject @Inject
private ProjectAccountJoinDao _projectAccountJoinDao; ProjectAccountJoinDao _projectAccountJoinDao;
@Inject @Inject
private HostJoinDao hostJoinDao; HostJoinDao hostJoinDao;
@Inject @Inject
private VolumeJoinDao _volumeJoinDao; VolumeJoinDao _volumeJoinDao;
@Inject @Inject
private AccountDao _accountDao; AccountDao _accountDao;
@Inject @Inject
private AccountJoinDao _accountJoinDao; AccountJoinDao _accountJoinDao;
@Inject @Inject
private AsyncJobJoinDao _jobJoinDao; AsyncJobJoinDao _jobJoinDao;
@Inject @Inject
private StoragePoolJoinDao _poolJoinDao; StoragePoolJoinDao _poolJoinDao;
@Inject @Inject
private StoragePoolTagsDao _storageTagDao; StoragePoolTagsDao _storageTagDao;
@Inject @Inject
private HostTagsDao _hostTagDao; HostTagsDao _hostTagDao;
@Inject @Inject
private ImageStoreJoinDao _imageStoreJoinDao; ImageStoreJoinDao _imageStoreJoinDao;
@Inject @Inject
private DiskOfferingJoinDao _diskOfferingJoinDao; DiskOfferingJoinDao _diskOfferingJoinDao;
@Inject @Inject
private DiskOfferingDetailsDao _diskOfferingDetailsDao; DiskOfferingDetailsDao _diskOfferingDetailsDao;
@Inject @Inject
private ServiceOfferingJoinDao _srvOfferingJoinDao; ServiceOfferingJoinDao _srvOfferingJoinDao;
@Inject @Inject
private ServiceOfferingDao _srvOfferingDao; ServiceOfferingDao _srvOfferingDao;
@Inject @Inject
private ServiceOfferingDetailsDao _srvOfferingDetailsDao; ServiceOfferingDetailsDao _srvOfferingDetailsDao;
@Inject @Inject
private DiskOfferingDao _diskOfferingDao; DiskOfferingDao _diskOfferingDao;
@Inject @Inject
private DataCenterJoinDao _dcJoinDao; DataCenterJoinDao _dcJoinDao;
@Inject @Inject
private DomainRouterDao _routerDao; DomainRouterDao _routerDao;
@Inject @Inject
private HighAvailabilityManager _haMgr; HighAvailabilityManager _haMgr;
@Inject @Inject
private VMTemplateDao _templateDao; VMTemplateDao _templateDao;
@Inject @Inject
private TemplateJoinDao _templateJoinDao; TemplateJoinDao _templateJoinDao;
@Inject @Inject
private ResourceManager _resourceMgr; ResourceManager _resourceMgr;
@Inject @Inject
private ResourceMetaDataService _resourceMetaDataMgr; ResourceMetaDataService _resourceMetaDataMgr;
@Inject @Inject
private ResourceManagerUtil resourceManagerUtil; ResourceManagerUtil resourceManagerUtil;
@Inject @Inject
private AffinityGroupVMMapDao _affinityGroupVMMapDao; AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Inject @Inject
private AffinityGroupJoinDao _affinityGroupJoinDao; AffinityGroupJoinDao _affinityGroupJoinDao;
@Inject @Inject
private DedicatedResourceDao _dedicatedDao; DedicatedResourceDao _dedicatedDao;
@Inject @Inject
private DomainManager _domainMgr; DomainManager _domainMgr;
@Inject @Inject
private AffinityGroupDomainMapDao _affinityGroupDomainMapDao; AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
@Inject @Inject
private ResourceTagDao resourceTagDao; ResourceTagDao resourceTagDao;
@Inject @Inject
private DataStoreManager dataStoreManager; DataStoreManager dataStoreManager;
@Inject @Inject
ManagementServerJoinDao managementServerJoinDao; ManagementServerJoinDao managementServerJoinDao;
@Inject @Inject
public VpcVirtualNetworkApplianceService routerService; VpcVirtualNetworkApplianceService routerService;
@Inject @Inject
private ResponseGenerator responseGenerator; ResponseGenerator responseGenerator;
@Inject @Inject
private RouterHealthCheckResultDao routerHealthCheckResultDao; RouterHealthCheckResultDao routerHealthCheckResultDao;
@Inject @Inject
private PrimaryDataStoreDao storagePoolDao; PrimaryDataStoreDao storagePoolDao;
@Inject @Inject
private StoragePoolDetailsDao _storagePoolDetailsDao; StoragePoolDetailsDao _storagePoolDetailsDao;
@Inject @Inject
private ProjectInvitationDao projectInvitationDao; ProjectInvitationDao projectInvitationDao;
@Inject @Inject
private TemplateDataStoreDao templateDataStoreDao; TemplateDataStoreDao templateDataStoreDao;
@Inject @Inject
private VMTemplatePoolDao templatePoolDao; VMTemplatePoolDao templatePoolDao;
@Inject @Inject
private SnapshotDataStoreDao snapshotDataStoreDao; SnapshotDataStoreDao snapshotDataStoreDao;
@Inject @Inject
private UserDao userDao; UserDao userDao;
@Inject @Inject
private VirtualMachineManager virtualMachineManager; VirtualMachineManager virtualMachineManager;
@Inject @Inject
private VolumeDao volumeDao; VolumeDao volumeDao;
@Inject @Inject
private ResourceIconDao resourceIconDao; ResourceIconDao resourceIconDao;
@Inject @Inject
StorageManager storageManager; StorageManager storageManager;
@Inject @Inject
private ManagementServerHostDao msHostDao; ManagementServerHostDao msHostDao;
@Inject @Inject
private SecondaryStorageHeuristicDao secondaryStorageHeuristicDao; SecondaryStorageHeuristicDao secondaryStorageHeuristicDao;
@Inject @Inject
private NetworkDao networkDao; NetworkDao networkDao;
@Inject @Inject
private IPAddressDao ipAddressDao; IPAddressDao ipAddressDao;
@Inject @Inject
private NicDao nicDao; NicDao nicDao;
@Inject @Inject
private HostDao hostDao; HostDao hostDao;
@Inject @Inject
private OutOfBandManagementDao outOfBandManagementDao; OutOfBandManagementDao outOfBandManagementDao;
@Inject @Inject
private InstanceGroupVMMapDao instanceGroupVMMapDao; InstanceGroupVMMapDao instanceGroupVMMapDao;
@Inject @Inject
private AffinityGroupVMMapDao affinityGroupVMMapDao; AffinityGroupVMMapDao affinityGroupVMMapDao;
@Inject @Inject
private UserVmDetailsDao userVmDetailsDao; UserVmDetailsDao userVmDetailsDao;
@Inject @Inject
private SSHKeyPairDao sshKeyPairDao; SSHKeyPairDao sshKeyPairDao;
@Inject @Inject
private BackupOfferingDao backupOfferingDao; BackupOfferingDao backupOfferingDao;
@Inject @Inject
private AutoScaleVmGroupDao autoScaleVmGroupDao; AutoScaleVmGroupDao autoScaleVmGroupDao;
@Inject @Inject
private AutoScaleVmGroupVmMapDao autoScaleVmGroupVmMapDao; AutoScaleVmGroupVmMapDao autoScaleVmGroupVmMapDao;
@Inject @Inject
private SnapshotJoinDao snapshotJoinDao; SnapshotJoinDao snapshotJoinDao;
@Inject @Inject
private ObjectStoreDao objectStoreDao; ObjectStoreDao objectStoreDao;
@Inject @Inject
private BucketDao bucketDao; BucketDao bucketDao;
@Inject @Inject
EntityManager entityManager; EntityManager entityManager;
@Inject @Inject
private PublicIpQuarantineDao publicIpQuarantineDao; PublicIpQuarantineDao publicIpQuarantineDao;
@Inject @Inject
private StoragePoolHostDao storagePoolHostDao; StoragePoolHostDao storagePoolHostDao;
@Inject @Inject
private ClusterDao clusterDao; ClusterDao clusterDao;
@Inject @Inject
private ManagementServerHostPeerJoinDao mshostPeerJoinDao; ManagementServerHostPeerJoinDao mshostPeerJoinDao;
private SearchCriteria<ServiceOfferingJoinVO> getMinimumCpuServiceOfferingJoinSearchCriteria(int cpu) { private SearchCriteria<ServiceOfferingJoinVO> getMinimumCpuServiceOfferingJoinSearchCriteria(int cpu) {
@ -663,7 +663,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<UserResponse> searchForUsers(ResponseView responseView, ListUsersCmd cmd) throws PermissionDeniedException { public ListResponse<UserResponse> searchForUsers(ResponseView responseView, ListUsersCmd cmd) throws PermissionDeniedException {
Pair<List<UserAccountJoinVO>, Integer> result = searchForUsersInternal(cmd); Pair<List<UserAccountJoinVO>, Integer> result = searchForUsersInternal(cmd);
ListResponse<UserResponse> response = new ListResponse<UserResponse>(); ListResponse<UserResponse> response = new ListResponse<>();
if (CallContext.current().getCallingAccount().getType() == Account.Type.ADMIN) { if (CallContext.current().getCallingAccount().getType() == Account.Type.ADMIN) {
responseView = ResponseView.Full; responseView = ResponseView.Full;
} }
@ -833,7 +833,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<EventResponse> searchForEvents(ListEventsCmd cmd) { public ListResponse<EventResponse> searchForEvents(ListEventsCmd cmd) {
Pair<List<EventJoinVO>, Integer> result = searchForEventsInternal(cmd); Pair<List<EventJoinVO>, Integer> result = searchForEventsInternal(cmd);
ListResponse<EventResponse> response = new ListResponse<EventResponse>(); ListResponse<EventResponse> response = new ListResponse<>();
List<EventResponse> eventResponses = ViewResponseHelper.createEventResponse(result.first().toArray(new EventJoinVO[result.first().size()])); List<EventResponse> eventResponses = ViewResponseHelper.createEventResponse(result.first().toArray(new EventJoinVO[result.first().size()]));
response.setResponses(eventResponses, result.second()); response.setResponses(eventResponses, result.second());
return response; return response;
@ -905,7 +905,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
} }
} }
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null);
accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
Long domainId = domainIdRecursiveListProject.first(); Long domainId = domainIdRecursiveListProject.first();
Boolean isRecursive = domainIdRecursiveListProject.second(); Boolean isRecursive = domainIdRecursiveListProject.second();
@ -996,7 +996,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.setParameters("archived", cmd.getArchived()); sc.setParameters("archived", cmd.getArchived());
} }
Pair<List<Long>, Integer> eventPair = null; Pair<List<Long>, Integer> eventPair;
// event_view will not have duplicate rows for each event, so // event_view will not have duplicate rows for each event, so
// searchAndCount should be good enough. // searchAndCount should be good enough.
if ((entryTime != null) && (duration != null)) { if ((entryTime != null) && (duration != null)) {
@ -1033,7 +1033,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<ResourceTagResponse> listTags(ListTagsCmd cmd) { public ListResponse<ResourceTagResponse> listTags(ListTagsCmd cmd) {
Pair<List<ResourceTagJoinVO>, Integer> tags = listTagsInternal(cmd); Pair<List<ResourceTagJoinVO>, Integer> tags = listTagsInternal(cmd);
ListResponse<ResourceTagResponse> response = new ListResponse<ResourceTagResponse>(); ListResponse<ResourceTagResponse> response = new ListResponse<>();
List<ResourceTagResponse> tagResponses = ViewResponseHelper.createResourceTagResponse(false, tags.first().toArray(new ResourceTagJoinVO[tags.first().size()])); List<ResourceTagResponse> tagResponses = ViewResponseHelper.createResourceTagResponse(false, tags.first().toArray(new ResourceTagJoinVO[tags.first().size()]));
response.setResponses(tagResponses, tags.second()); response.setResponses(tagResponses, tags.second());
return response; return response;
@ -1041,7 +1041,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
private Pair<List<ResourceTagJoinVO>, Integer> listTagsInternal(ListTagsCmd cmd) { private Pair<List<ResourceTagJoinVO>, Integer> listTagsInternal(ListTagsCmd cmd) {
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
List<Long> permittedAccounts = new ArrayList<Long>(); List<Long> permittedAccounts = new ArrayList<>();
String key = cmd.getKey(); String key = cmd.getKey();
String value = cmd.getValue(); String value = cmd.getValue();
String resourceId = cmd.getResourceId(); String resourceId = cmd.getResourceId();
@ -1061,7 +1061,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
} }
} }
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null);
accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), projectId, permittedAccounts, domainIdRecursiveListProject, listAll, false); accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), projectId, permittedAccounts, domainIdRecursiveListProject, listAll, false);
Long domainId = domainIdRecursiveListProject.first(); Long domainId = domainIdRecursiveListProject.first();
@ -1113,14 +1113,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.setParameters("customer", customerName); sc.setParameters("customer", customerName);
} }
Pair<List<ResourceTagJoinVO>, Integer> result = _resourceTagJoinDao.searchAndCount(sc, searchFilter); return _resourceTagJoinDao.searchAndCount(sc, searchFilter);
return result;
} }
@Override @Override
public ListResponse<InstanceGroupResponse> searchForVmGroups(ListVMGroupsCmd cmd) { public ListResponse<InstanceGroupResponse> searchForVmGroups(ListVMGroupsCmd cmd) {
Pair<List<InstanceGroupJoinVO>, Integer> groups = searchForVmGroupsInternal(cmd); Pair<List<InstanceGroupJoinVO>, Integer> groups = searchForVmGroupsInternal(cmd);
ListResponse<InstanceGroupResponse> response = new ListResponse<InstanceGroupResponse>(); ListResponse<InstanceGroupResponse> response = new ListResponse<>();
List<InstanceGroupResponse> grpResponses = ViewResponseHelper.createInstanceGroupResponse(groups.first().toArray(new InstanceGroupJoinVO[groups.first().size()])); List<InstanceGroupResponse> grpResponses = ViewResponseHelper.createInstanceGroupResponse(groups.first().toArray(new InstanceGroupJoinVO[groups.first().size()]));
response.setResponses(grpResponses, groups.second()); response.setResponses(grpResponses, groups.second());
return response; return response;
@ -1132,9 +1131,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
String keyword = cmd.getKeyword(); String keyword = cmd.getKeyword();
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
List<Long> permittedAccounts = new ArrayList<Long>(); List<Long> permittedAccounts = new ArrayList<>();
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null);
accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
Long domainId = domainIdRecursiveListProject.first(); Long domainId = domainIdRecursiveListProject.first();
Boolean isRecursive = domainIdRecursiveListProject.second(); Boolean isRecursive = domainIdRecursiveListProject.second();
@ -1328,7 +1327,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Filter searchFilter = new Filter(UserVmVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); Filter searchFilter = new Filter(UserVmVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
List<Long> ids = null; List<Long> ids;
if (cmd.getId() != null) { if (cmd.getId() != null) {
if (cmd.getIds() != null && !cmd.getIds().isEmpty()) { if (cmd.getIds() != null && !cmd.getIds().isEmpty()) {
throw new InvalidParameterValueException("Specify either id or ids but not both parameters"); throw new InvalidParameterValueException("Specify either id or ids but not both parameters");
@ -1694,7 +1693,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<SecurityGroupResponse> searchForSecurityGroups(ListSecurityGroupsCmd cmd) { public ListResponse<SecurityGroupResponse> searchForSecurityGroups(ListSecurityGroupsCmd cmd) {
Pair<List<SecurityGroupJoinVO>, Integer> result = searchForSecurityGroupsInternal(cmd); Pair<List<SecurityGroupJoinVO>, Integer> result = searchForSecurityGroupsInternal(cmd);
ListResponse<SecurityGroupResponse> response = new ListResponse<SecurityGroupResponse>(); ListResponse<SecurityGroupResponse> response = new ListResponse<>();
List<SecurityGroupResponse> routerResponses = ViewResponseHelper.createSecurityGroupResponses(result.first()); List<SecurityGroupResponse> routerResponses = ViewResponseHelper.createSecurityGroupResponses(result.first());
response.setResponses(routerResponses, result.second()); response.setResponses(routerResponses, result.second());
return response; return response;
@ -1706,7 +1705,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
String securityGroup = cmd.getSecurityGroupName(); String securityGroup = cmd.getSecurityGroupName();
Long id = cmd.getId(); Long id = cmd.getId();
Object keyword = cmd.getKeyword(); Object keyword = cmd.getKeyword();
List<Long> permittedAccounts = new ArrayList<Long>(); List<Long> permittedAccounts = new ArrayList<>();
Map<String, String> tags = cmd.getTags(); Map<String, String> tags = cmd.getTags();
if (instanceId != null) { if (instanceId != null) {
@ -1718,7 +1717,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
return listSecurityGroupRulesByVM(instanceId.longValue(), cmd.getStartIndex(), cmd.getPageSizeVal()); return listSecurityGroupRulesByVM(instanceId.longValue(), cmd.getStartIndex(), cmd.getPageSizeVal());
} }
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null);
accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
Long domainId = domainIdRecursiveListProject.first(); Long domainId = domainIdRecursiveListProject.first();
Boolean isRecursive = domainIdRecursiveListProject.second(); Boolean isRecursive = domainIdRecursiveListProject.second();
@ -1777,7 +1776,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sgIds[i++] = v.getId(); sgIds[i++] = v.getId();
} }
List<SecurityGroupJoinVO> sgs = _securityGroupJoinDao.searchByIds(sgIds); List<SecurityGroupJoinVO> sgs = _securityGroupJoinDao.searchByIds(sgIds);
return new Pair<List<SecurityGroupJoinVO>, Integer>(sgs, count); return new Pair<>(sgs, count);
} }
private Pair<List<SecurityGroupJoinVO>, Integer> listSecurityGroupRulesByVM(long vmId, long pageInd, long pageSize) { private Pair<List<SecurityGroupJoinVO>, Integer> listSecurityGroupRulesByVM(long vmId, long pageInd, long pageSize) {
@ -1786,7 +1785,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Integer count = sgVmMappingPair.second(); Integer count = sgVmMappingPair.second();
if (count.intValue() == 0) { if (count.intValue() == 0) {
// handle empty result cases // handle empty result cases
return new Pair<List<SecurityGroupJoinVO>, Integer>(new ArrayList<SecurityGroupJoinVO>(), count); return new Pair<>(new ArrayList<>(), count);
} }
List<SecurityGroupVMMapVO> sgVmMappings = sgVmMappingPair.first(); List<SecurityGroupVMMapVO> sgVmMappings = sgVmMappingPair.first();
Long[] sgIds = new Long[sgVmMappings.size()]; Long[] sgIds = new Long[sgVmMappings.size()];
@ -1795,14 +1794,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sgIds[i++] = sgVm.getSecurityGroupId(); sgIds[i++] = sgVm.getSecurityGroupId();
} }
List<SecurityGroupJoinVO> sgs = _securityGroupJoinDao.searchByIds(sgIds); List<SecurityGroupJoinVO> sgs = _securityGroupJoinDao.searchByIds(sgIds);
return new Pair<List<SecurityGroupJoinVO>, Integer>(sgs, count); return new Pair<>(sgs, count);
} }
@Override @Override
public ListResponse<DomainRouterResponse> searchForRouters(ListRoutersCmd cmd) { public ListResponse<DomainRouterResponse> searchForRouters(ListRoutersCmd cmd) {
Pair<List<DomainRouterJoinVO>, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), cmd.getClusterId(), Pair<List<DomainRouterJoinVO>, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), cmd.getClusterId(),
cmd.getHostId(), cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), cmd.getVersion(), cmd.isHealthCheckFailed()); cmd.getHostId(), cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), cmd.getVersion(), cmd.isHealthCheckFailed());
ListResponse<DomainRouterResponse> response = new ListResponse<DomainRouterResponse>(); ListResponse<DomainRouterResponse> response = new ListResponse<>();
List<DomainRouterResponse> routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()])); List<DomainRouterResponse> routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()]));
if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) { if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) {
for (DomainRouterResponse res : routerResponses) { for (DomainRouterResponse res : routerResponses) {
@ -1822,7 +1821,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
public ListResponse<DomainRouterResponse> searchForInternalLbVms(ListInternalLBVMsCmd cmd) { public ListResponse<DomainRouterResponse> searchForInternalLbVms(ListInternalLBVMsCmd cmd) {
Pair<List<DomainRouterJoinVO>, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, cmd.getHostId(), Pair<List<DomainRouterJoinVO>, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, cmd.getHostId(),
cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), null, null); cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), null, null);
ListResponse<DomainRouterResponse> response = new ListResponse<DomainRouterResponse>(); ListResponse<DomainRouterResponse> response = new ListResponse<>();
List<DomainRouterResponse> routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()])); List<DomainRouterResponse> routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()]));
if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) { if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) {
for (DomainRouterResponse res : routerResponses) { for (DomainRouterResponse res : routerResponses) {
@ -1843,9 +1842,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Long hostId, String keyword, Long networkId, Long vpcId, Boolean forVpc, String role, String version, Boolean isHealthCheckFailed) { Long hostId, String keyword, Long networkId, Long vpcId, Boolean forVpc, String role, String version, Boolean isHealthCheckFailed) {
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
List<Long> permittedAccounts = new ArrayList<Long>(); List<Long> permittedAccounts = new ArrayList<>();
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null);
accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
Long domainId = domainIdRecursiveListProject.first(); Long domainId = domainIdRecursiveListProject.first();
Boolean isRecursive = domainIdRecursiveListProject.second(); Boolean isRecursive = domainIdRecursiveListProject.second();
@ -1901,7 +1900,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sb.and("routerId", sb.entity().getId(), SearchCriteria.Op.NIN); sb.and("routerId", sb.entity().getId(), SearchCriteria.Op.NIN);
} }
} else if (isHealthCheckFailed) { } else if (isHealthCheckFailed) {
return new Pair<List<DomainRouterJoinVO>, Integer>(Collections.emptyList(), 0); return new Pair<>(Collections.emptyList(), 0);
} }
} }
@ -1981,13 +1980,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
vrIds[i++] = v.getId(); vrIds[i++] = v.getId();
} }
List<DomainRouterJoinVO> vrs = _routerJoinDao.searchByIds(vrIds); List<DomainRouterJoinVO> vrs = _routerJoinDao.searchByIds(vrIds);
return new Pair<List<DomainRouterJoinVO>, Integer>(vrs, count); return new Pair<>(vrs, count);
} }
@Override @Override
public ListResponse<ProjectResponse> listProjects(ListProjectsCmd cmd) { public ListResponse<ProjectResponse> listProjects(ListProjectsCmd cmd) {
Pair<List<ProjectJoinVO>, Integer> projects = listProjectsInternal(cmd); Pair<List<ProjectJoinVO>, Integer> projects = listProjectsInternal(cmd);
ListResponse<ProjectResponse> response = new ListResponse<ProjectResponse>(); ListResponse<ProjectResponse> response = new ListResponse<>();
List<ProjectResponse> projectResponses = ViewResponseHelper.createProjectResponse(cmd.getDetails(), projects.first().toArray(new ProjectJoinVO[projects.first().size()])); List<ProjectResponse> projectResponses = ViewResponseHelper.createProjectResponse(cmd.getDetails(), projects.first().toArray(new ProjectJoinVO[projects.first().size()]));
response.setResponses(projectResponses, projects.second()); response.setResponses(projectResponses, projects.second());
return response; return response;
@ -2155,13 +2154,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
prjIds[i++] = v.getId(); prjIds[i++] = v.getId();
} }
List<ProjectJoinVO> prjs = _projectJoinDao.searchByIds(prjIds); List<ProjectJoinVO> prjs = _projectJoinDao.searchByIds(prjIds);
return new Pair<List<ProjectJoinVO>, Integer>(prjs, count); return new Pair<>(prjs, count);
} }
@Override @Override
public ListResponse<ProjectInvitationResponse> listProjectInvitations(ListProjectInvitationsCmd cmd) { public ListResponse<ProjectInvitationResponse> listProjectInvitations(ListProjectInvitationsCmd cmd) {
Pair<List<ProjectInvitationJoinVO>, Integer> invites = listProjectInvitationsInternal(cmd); Pair<List<ProjectInvitationJoinVO>, Integer> invites = listProjectInvitationsInternal(cmd);
ListResponse<ProjectInvitationResponse> response = new ListResponse<ProjectInvitationResponse>(); ListResponse<ProjectInvitationResponse> response = new ListResponse<>();
List<ProjectInvitationResponse> projectInvitationResponses = ViewResponseHelper.createProjectInvitationResponse(invites.first().toArray(new ProjectInvitationJoinVO[invites.first().size()])); List<ProjectInvitationResponse> projectInvitationResponses = ViewResponseHelper.createProjectInvitationResponse(invites.first().toArray(new ProjectInvitationJoinVO[invites.first().size()]));
response.setResponses(projectInvitationResponses, invites.second()); response.setResponses(projectInvitationResponses, invites.second());
@ -2183,9 +2182,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
User callingUser = CallContext.current().getCallingUser(); User callingUser = CallContext.current().getCallingUser();
List<Long> permittedAccounts = new ArrayList<Long>(); List<Long> permittedAccounts = new ArrayList<>();
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(domainId, isRecursive, null); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(domainId, isRecursive, null);
accountMgr.buildACLSearchParameters(caller, id, accountName, projectId, permittedAccounts, domainIdRecursiveListProject, listAll, true); accountMgr.buildACLSearchParameters(caller, id, accountName, projectId, permittedAccounts, domainIdRecursiveListProject, listAll, true);
domainId = domainIdRecursiveListProject.first(); domainId = domainIdRecursiveListProject.first();
isRecursive = domainIdRecursiveListProject.second(); isRecursive = domainIdRecursiveListProject.second();
@ -2237,7 +2236,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<ProjectAccountResponse> listProjectAccounts(ListProjectAccountsCmd cmd) { public ListResponse<ProjectAccountResponse> listProjectAccounts(ListProjectAccountsCmd cmd) {
Pair<List<ProjectAccountJoinVO>, Integer> projectAccounts = listProjectAccountsInternal(cmd); Pair<List<ProjectAccountJoinVO>, Integer> projectAccounts = listProjectAccountsInternal(cmd);
ListResponse<ProjectAccountResponse> response = new ListResponse<ProjectAccountResponse>(); ListResponse<ProjectAccountResponse> response = new ListResponse<>();
List<ProjectAccountResponse> projectResponses = ViewResponseHelper.createProjectAccountResponse(projectAccounts.first().toArray(new ProjectAccountJoinVO[projectAccounts.first().size()])); List<ProjectAccountResponse> projectResponses = ViewResponseHelper.createProjectAccountResponse(projectAccounts.first().toArray(new ProjectAccountJoinVO[projectAccounts.first().size()]));
response.setResponses(projectResponses, projectAccounts.second()); response.setResponses(projectResponses, projectAccounts.second());
return response; return response;
@ -2311,7 +2310,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
// Right now it is handled separately outside this QueryService // Right now it is handled separately outside this QueryService
logger.debug(">>>Searching for hosts>>>"); logger.debug(">>>Searching for hosts>>>");
Pair<List<HostJoinVO>, Integer> hosts = searchForServersInternal(cmd); Pair<List<HostJoinVO>, Integer> hosts = searchForServersInternal(cmd);
ListResponse<HostResponse> response = new ListResponse<HostResponse>(); ListResponse<HostResponse> response = new ListResponse<>();
logger.debug(">>>Generating Response>>>"); logger.debug(">>>Generating Response>>>");
List<HostResponse> hostResponses = ViewResponseHelper.createHostResponse(cmd.getDetails(), hosts.first().toArray(new HostJoinVO[hosts.first().size()])); List<HostResponse> hostResponses = ViewResponseHelper.createHostResponse(cmd.getDetails(), hosts.first().toArray(new HostJoinVO[hosts.first().size()]));
response.setResponses(hostResponses, hosts.second()); response.setResponses(hostResponses, hosts.second());
@ -2723,7 +2722,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<DomainResponse> searchForDomains(ListDomainsCmd cmd) { public ListResponse<DomainResponse> searchForDomains(ListDomainsCmd cmd) {
Pair<List<DomainJoinVO>, Integer> result = searchForDomainsInternal(cmd); Pair<List<DomainJoinVO>, Integer> result = searchForDomainsInternal(cmd);
ListResponse<DomainResponse> response = new ListResponse<DomainResponse>(); ListResponse<DomainResponse> response = new ListResponse<>();
ResponseView respView = ResponseView.Restricted; ResponseView respView = ResponseView.Restricted;
if (cmd instanceof ListDomainsCmdByAdmin) { if (cmd instanceof ListDomainsCmdByAdmin) {
@ -2825,7 +2824,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<AccountResponse> searchForAccounts(ListAccountsCmd cmd) { public ListResponse<AccountResponse> searchForAccounts(ListAccountsCmd cmd) {
Pair<List<AccountJoinVO>, Integer> result = searchForAccountsInternal(cmd); Pair<List<AccountJoinVO>, Integer> result = searchForAccountsInternal(cmd);
ListResponse<AccountResponse> response = new ListResponse<AccountResponse>(); ListResponse<AccountResponse> response = new ListResponse<>();
ResponseView respView = ResponseView.Restricted; ResponseView respView = ResponseView.Restricted;
if (cmd instanceof ListAccountsCmdByAdmin) { if (cmd instanceof ListAccountsCmdByAdmin) {
@ -3011,7 +3010,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<AsyncJobResponse> searchForAsyncJobs(ListAsyncJobsCmd cmd) { public ListResponse<AsyncJobResponse> searchForAsyncJobs(ListAsyncJobsCmd cmd) {
Pair<List<AsyncJobJoinVO>, Integer> result = searchForAsyncJobsInternal(cmd); Pair<List<AsyncJobJoinVO>, Integer> result = searchForAsyncJobsInternal(cmd);
ListResponse<AsyncJobResponse> response = new ListResponse<AsyncJobResponse>(); ListResponse<AsyncJobResponse> response = new ListResponse<>();
List<AsyncJobResponse> jobResponses = ViewResponseHelper.createAsyncJobResponse(result.first().toArray(new AsyncJobJoinVO[result.first().size()])); List<AsyncJobResponse> jobResponses = ViewResponseHelper.createAsyncJobResponse(result.first().toArray(new AsyncJobJoinVO[result.first().size()]));
response.setResponses(jobResponses, result.second()); response.setResponses(jobResponses, result.second());
return response; return response;
@ -3021,9 +3020,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
List<Long> permittedAccounts = new ArrayList<Long>(); List<Long> permittedAccounts = new ArrayList<>();
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null);
accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), null, permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), null, permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
Long domainId = domainIdRecursiveListProject.first(); Long domainId = domainIdRecursiveListProject.first();
Boolean isRecursive = domainIdRecursiveListProject.second(); Boolean isRecursive = domainIdRecursiveListProject.second();
@ -3183,7 +3182,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<StorageTagResponse> searchForStorageTags(ListStorageTagsCmd cmd) { public ListResponse<StorageTagResponse> searchForStorageTags(ListStorageTagsCmd cmd) {
Pair<List<StoragePoolTagVO>, Integer> result = searchForStorageTagsInternal(cmd); Pair<List<StoragePoolTagVO>, Integer> result = searchForStorageTagsInternal(cmd);
ListResponse<StorageTagResponse> response = new ListResponse<StorageTagResponse>(); ListResponse<StorageTagResponse> response = new ListResponse<>();
List<StorageTagResponse> tagResponses = ViewResponseHelper.createStorageTagResponse(result.first().toArray(new StoragePoolTagVO[result.first().size()])); List<StorageTagResponse> tagResponses = ViewResponseHelper.createStorageTagResponse(result.first().toArray(new StoragePoolTagVO[result.first().size()]));
response.setResponses(tagResponses, result.second()); response.setResponses(tagResponses, result.second());
@ -3218,13 +3217,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
List<StoragePoolTagVO> vrs = _storageTagDao.searchByIds(vrIds); List<StoragePoolTagVO> vrs = _storageTagDao.searchByIds(vrIds);
return new Pair<List<StoragePoolTagVO>, Integer>(vrs, count); return new Pair<>(vrs, count);
} }
@Override @Override
public ListResponse<HostTagResponse> searchForHostTags(ListHostTagsCmd cmd) { public ListResponse<HostTagResponse> searchForHostTags(ListHostTagsCmd cmd) {
Pair<List<HostTagVO>, Integer> result = searchForHostTagsInternal(cmd); Pair<List<HostTagVO>, Integer> result = searchForHostTagsInternal(cmd);
ListResponse<HostTagResponse> response = new ListResponse<HostTagResponse>(); ListResponse<HostTagResponse> response = new ListResponse<>();
List<HostTagResponse> tagResponses = ViewResponseHelper.createHostTagResponse(result.first().toArray(new HostTagVO[result.first().size()])); List<HostTagResponse> tagResponses = ViewResponseHelper.createHostTagResponse(result.first().toArray(new HostTagVO[result.first().size()]));
response.setResponses(tagResponses, result.second()); response.setResponses(tagResponses, result.second());
@ -3259,7 +3258,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
List<HostTagVO> vrs = _hostTagDao.searchByIds(vrIds); List<HostTagVO> vrs = _hostTagDao.searchByIds(vrIds);
return new Pair<List<HostTagVO>, Integer>(vrs, count); return new Pair<>(vrs, count);
} }
@Override @Override
@ -3342,14 +3341,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
vrIds[i++] = v.getId(); vrIds[i++] = v.getId();
} }
List<ImageStoreJoinVO> vrs = _imageStoreJoinDao.searchByIds(vrIds); List<ImageStoreJoinVO> vrs = _imageStoreJoinDao.searchByIds(vrIds);
return new Pair<List<ImageStoreJoinVO>, Integer>(vrs, count); return new Pair<>(vrs, count);
} }
@Override @Override
public ListResponse<ImageStoreResponse> searchForSecondaryStagingStores(ListSecondaryStagingStoresCmd cmd) { public ListResponse<ImageStoreResponse> searchForSecondaryStagingStores(ListSecondaryStagingStoresCmd cmd) {
Pair<List<ImageStoreJoinVO>, Integer> result = searchForCacheStoresInternal(cmd); Pair<List<ImageStoreJoinVO>, Integer> result = searchForCacheStoresInternal(cmd);
ListResponse<ImageStoreResponse> response = new ListResponse<ImageStoreResponse>(); ListResponse<ImageStoreResponse> response = new ListResponse<>();
List<ImageStoreResponse> poolResponses = ViewResponseHelper.createImageStoreResponse(result.first().toArray(new ImageStoreJoinVO[result.first().size()])); List<ImageStoreResponse> poolResponses = ViewResponseHelper.createImageStoreResponse(result.first().toArray(new ImageStoreJoinVO[result.first().size()]));
response.setResponses(poolResponses, result.second()); response.setResponses(poolResponses, result.second());
@ -3421,7 +3420,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
vrIds[i++] = v.getId(); vrIds[i++] = v.getId();
} }
List<ImageStoreJoinVO> vrs = _imageStoreJoinDao.searchByIds(vrIds); List<ImageStoreJoinVO> vrs = _imageStoreJoinDao.searchByIds(vrIds);
return new Pair<List<ImageStoreJoinVO>, Integer>(vrs, count); return new Pair<>(vrs, count);
} }
@ -4245,7 +4244,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<ZoneResponse> listDataCenters(ListZonesCmd cmd) { public ListResponse<ZoneResponse> listDataCenters(ListZonesCmd cmd) {
Pair<List<DataCenterJoinVO>, Integer> result = listDataCentersInternal(cmd); Pair<List<DataCenterJoinVO>, Integer> result = listDataCentersInternal(cmd);
ListResponse<ZoneResponse> response = new ListResponse<ZoneResponse>(); ListResponse<ZoneResponse> response = new ListResponse<>();
ResponseView respView = ResponseView.Restricted; ResponseView respView = ResponseView.Restricted;
if (cmd instanceof ListZonesCmdByAdmin || CallContext.current().getCallingAccount().getType() == Account.Type.ADMIN) { if (cmd instanceof ListZonesCmdByAdmin || CallContext.current().getCallingAccount().getType() == Account.Type.ADMIN) {
@ -4332,7 +4331,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
// list // list
// find all domain Id up to root domain for this account // find all domain Id up to root domain for this account
List<Long> domainIds = new ArrayList<Long>(); List<Long> domainIds = new ArrayList<>();
DomainVO domainRecord = _domainDao.findById(account.getDomainId()); DomainVO domainRecord = _domainDao.findById(account.getDomainId());
if (domainRecord == null) { if (domainRecord == null) {
logger.error("Could not find the domainId for account: {}", account); logger.error("Could not find the domainId for account: {}", account);
@ -4372,7 +4371,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
// it was decided to return all zones for the domain admin, and // it was decided to return all zones for the domain admin, and
// everything above till root, as well as zones till the domain // everything above till root, as well as zones till the domain
// leaf // leaf
List<Long> domainIds = new ArrayList<Long>(); List<Long> domainIds = new ArrayList<>();
DomainVO domainRecord = _domainDao.findById(account.getDomainId()); DomainVO domainRecord = _domainDao.findById(account.getDomainId());
if (domainRecord == null) { if (domainRecord == null) {
logger.error("Could not find the domainId for account: {}", account); logger.error("Could not find the domainId for account: {}", account);
@ -4412,8 +4411,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
// one VM running there // one VM running there
Boolean available = cmd.isAvailable(); Boolean available = cmd.isAvailable();
if (account != null) { if (account != null) {
if ((available != null) && Boolean.FALSE.equals(available)) { if (Boolean.FALSE.equals(available)) {
Set<Long> dcIds = new HashSet<Long>(); // data centers with Set<Long> dcIds = new HashSet<>(); // data centers with
// at least one VM // at least one VM
// running // running
List<DomainRouterVO> routers = _routerDao.listBy(account.getId()); List<DomainRouterVO> routers = _routerDao.listBy(account.getId());
@ -4421,7 +4420,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
dcIds.add(router.getDataCenterId()); dcIds.add(router.getDataCenterId());
} }
if (dcIds.size() == 0) { if (dcIds.size() == 0) {
return new Pair<List<DataCenterJoinVO>, Integer>(new ArrayList<DataCenterJoinVO>(), 0); return new Pair<>(new ArrayList<>(), 0);
} else { } else {
sc.addAnd("id", SearchCriteria.Op.IN, dcIds.toArray()); sc.addAnd("id", SearchCriteria.Op.IN, dcIds.toArray());
} }
@ -4445,7 +4444,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
private List<Long> removeDedicatedZoneNotSuitabe(List<Long> domainIds) { private List<Long> removeDedicatedZoneNotSuitabe(List<Long> domainIds) {
// remove dedicated zone of other domain // remove dedicated zone of other domain
List<Long> dedicatedZoneIds = new ArrayList<Long>(); List<Long> dedicatedZoneIds = new ArrayList<>();
List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listZonesNotInDomainIds(domainIds); List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listZonesNotInDomainIds(domainIds);
for (DedicatedResourceVO dr : dedicatedResources) { for (DedicatedResourceVO dr : dedicatedResources) {
if (dr != null) { if (dr != null) {
@ -4486,7 +4485,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override @Override
public ListResponse<TemplateResponse> listTemplates(ListTemplatesCmd cmd) { public ListResponse<TemplateResponse> listTemplates(ListTemplatesCmd cmd) {
Pair<List<TemplateJoinVO>, Integer> result = searchForTemplatesInternal(cmd); Pair<List<TemplateJoinVO>, Integer> result = searchForTemplatesInternal(cmd);
ListResponse<TemplateResponse> response = new ListResponse<TemplateResponse>(); ListResponse<TemplateResponse> response = new ListResponse<>();
ResponseView respView = ResponseView.Restricted; ResponseView respView = ResponseView.Restricted;
if (cmd instanceof ListTemplatesCmdByAdmin) { if (cmd instanceof ListTemplatesCmdByAdmin) {
@ -4514,14 +4513,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
listAll = true; listAll = true;
} }
List<Long> permittedAccountIds = new ArrayList<Long>(); List<Long> permittedAccountIds = new ArrayList<>();
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null);
accountMgr.buildACLSearchParameters( accountMgr.buildACLSearchParameters(
caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds,
domainIdRecursiveListProject, listAll, false domainIdRecursiveListProject, listAll, false
); );
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
List<Account> permittedAccounts = new ArrayList<Account>(); List<Account> permittedAccounts = new ArrayList<>();
for (Long accountId : permittedAccountIds) { for (Long accountId : permittedAccountIds) {
permittedAccounts.add(accountMgr.getAccount(accountId)); permittedAccounts.add(accountMgr.getAccount(accountId));
} }
@ -4559,11 +4558,11 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
if (!isIso) { if (!isIso) {
hypers = _resourceMgr.listAvailHypervisorInZone(null); hypers = _resourceMgr.listAvailHypervisorInZone(null);
if (hypers == null || hypers.isEmpty()) { if (hypers == null || hypers.isEmpty()) {
return new Pair<List<TemplateJoinVO>, Integer>(new ArrayList<TemplateJoinVO>(), 0); return new Pair<>(new ArrayList<>(), 0);
} }
} }
VMTemplateVO template = null; VMTemplateVO template;
Filter searchFilter = new Filter(TemplateJoinVO.class, "sortKey", SortKeyAscending.value(), startIndex, pageSize); Filter searchFilter = new Filter(TemplateJoinVO.class, "sortKey", SortKeyAscending.value(), startIndex, pageSize);
searchFilter.addOrderBy(TemplateJoinVO.class, "tempZonePair", SortKeyAscending.value()); searchFilter.addOrderBy(TemplateJoinVO.class, "tempZonePair", SortKeyAscending.value());
@ -4634,7 +4633,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.addAnd("id", SearchCriteria.Op.EQ, templateId); sc.addAnd("id", SearchCriteria.Op.EQ, templateId);
} else { } else {
DomainVO domain = null; DomainVO domain;
if (!permittedAccounts.isEmpty()) { if (!permittedAccounts.isEmpty()) {
domain = _domainDao.findById(permittedAccounts.get(0).getDomainId()); domain = _domainDao.findById(permittedAccounts.get(0).getDomainId());
} else { } else {
@ -4656,15 +4655,15 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.addAnd("domainPath", SearchCriteria.Op.LIKE, domain.getPath() + "%"); sc.addAnd("domainPath", SearchCriteria.Op.LIKE, domain.getPath() + "%");
} }
List<Long> relatedDomainIds = new ArrayList<Long>(); List<Long> relatedDomainIds = new ArrayList<>();
List<Long> permittedAccountIds = new ArrayList<Long>(); List<Long> permittedAccountIds = new ArrayList<>();
if (!permittedAccounts.isEmpty()) { if (!permittedAccounts.isEmpty()) {
for (Account account : permittedAccounts) { for (Account account : permittedAccounts) {
permittedAccountIds.add(account.getId()); permittedAccountIds.add(account.getId());
boolean publicTemplates = (templateFilter == TemplateFilter.featured || templateFilter == TemplateFilter.community); boolean publicTemplates = (templateFilter == TemplateFilter.featured || templateFilter == TemplateFilter.community);
// get all parent domain ID's all the way till root domain // get all parent domain ID's all the way till root domain
DomainVO domainTreeNode = null; DomainVO domainTreeNode;
//if template filter is featured, or community, all child domains should be included in search //if template filter is featured, or community, all child domains should be included in search
if (publicTemplates) { if (publicTemplates) {
domainTreeNode = _domainDao.findById(Domain.ROOT_DOMAIN); domainTreeNode = _domainDao.findById(Domain.ROOT_DOMAIN);
@ -4895,7 +4894,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
// sc.addAnd("removed", SearchCriteria.Op.NULL); // sc.addAnd("removed", SearchCriteria.Op.NULL);
// search unique templates and find details by Ids // search unique templates and find details by Ids
Pair<List<TemplateJoinVO>, Integer> uniqueTmplPair = null; Pair<List<TemplateJoinVO>, Integer> uniqueTmplPair;
if (showRemovedTmpl) { if (showRemovedTmpl) {
uniqueTmplPair = _templateJoinDao.searchIncludingRemovedAndCount(sc, searchFilter); uniqueTmplPair = _templateJoinDao.searchIncludingRemovedAndCount(sc, searchFilter);
} else { } else {
@ -4926,7 +4925,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
return templateDataPair; return templateDataPair;
} }
List<TemplateJoinVO> templateData = templateDataPair.first(); List<TemplateJoinVO> templateData = templateDataPair.first();
List<TemplateJoinVO> templates = null; List<TemplateJoinVO> templates;
if (showUnique) { if (showUnique) {
Long[] templateIds = templateData.stream().map(template -> template.getId()).toArray(Long[]::new); Long[] templateIds = templateData.stream().map(template -> template.getId()).toArray(Long[]::new);
templates = _templateJoinDao.findByDistinctIds(templateIds); templates = _templateJoinDao.findByDistinctIds(templateIds);
@ -4935,7 +4934,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
templates = _templateJoinDao.searchByTemplateZonePair(showRemoved, templateZonePairs); templates = _templateJoinDao.searchByTemplateZonePair(showRemoved, templateZonePairs);
} }
return new Pair<List<TemplateJoinVO>, Integer>(templates, count); return new Pair<>(templates, count);
} }
@Override @Override
@ -5056,7 +5055,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
if (HypervisorType.KVM.equals(hypervisorType)) { if (HypervisorType.KVM.equals(hypervisorType)) {
options.put(VmDetailConstants.CPU_THREAD_PER_CORE, Collections.emptyList()); options.put(VmDetailConstants.CPU_THREAD_PER_CORE, Collections.emptyList());
options.put(VmDetailConstants.NIC_ADAPTER, Arrays.asList("e1000", "virtio", "rtl8139", "vmxnet3", "ne2k_pci")); options.put(VmDetailConstants.NIC_ADAPTER, Arrays.asList("e1000", "virtio", "rtl8139", "vmxnet3", "ne2k_pci"));
options.put(VmDetailConstants.ROOT_DISK_CONTROLLER, Arrays.asList("osdefault", "ide", "scsi", "virtio")); options.put(VmDetailConstants.ROOT_DISK_CONTROLLER, Arrays.asList("osdefault", "ide", "scsi", "virtio", "virtio-blk"));
options.put(VmDetailConstants.VIDEO_HARDWARE, Arrays.asList("cirrus", "vga", "qxl", "virtio")); options.put(VmDetailConstants.VIDEO_HARDWARE, Arrays.asList("cirrus", "vga", "qxl", "virtio"));
options.put(VmDetailConstants.VIDEO_RAM, Collections.emptyList()); options.put(VmDetailConstants.VIDEO_RAM, Collections.emptyList());
options.put(VmDetailConstants.IO_POLICY, Arrays.asList("threads", "native", "io_uring", "storage_specific")); options.put(VmDetailConstants.IO_POLICY, Arrays.asList("threads", "native", "io_uring", "storage_specific"));
@ -5110,8 +5109,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize); return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize);
} }
List<Long> permittedAccounts = new ArrayList<Long>(); List<Long> permittedAccounts = new ArrayList<>();
Ternary<Long, Boolean, ListProjectResourcesCriteria> ternary = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(domainId, isRecursive, null); Ternary<Long, Boolean, ListProjectResourcesCriteria> ternary = new Ternary<>(domainId, isRecursive, null);
accountMgr.buildACLSearchParameters(caller, affinityGroupId, accountName, projectId, permittedAccounts, ternary, listAll, false); accountMgr.buildACLSearchParameters(caller, affinityGroupId, accountName, projectId, permittedAccounts, ternary, listAll, false);
@ -5127,7 +5126,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc, searchFilter); Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc, searchFilter);
// search group details by ids // search group details by ids
List<AffinityGroupJoinVO> affinityGroups = new ArrayList<AffinityGroupJoinVO>(); List<AffinityGroupJoinVO> affinityGroups = new ArrayList<>();
Integer count = uniqueGroupsPair.second(); Integer count = uniqueGroupsPair.second();
if (count.intValue() != 0) { if (count.intValue() != 0) {
@ -5143,7 +5142,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
if (!permittedAccounts.isEmpty()) { if (!permittedAccounts.isEmpty()) {
// add domain level affinity groups // add domain level affinity groups
if (domainId != null) { if (domainId != null) {
SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<Long>(), listProjectResourcesCriteria, affinityGroupId, SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<>(), listProjectResourcesCriteria, affinityGroupId,
affinityGroupName, affinityGroupType, keyword); affinityGroupName, affinityGroupType, keyword);
Pair<List<AffinityGroupJoinVO>, Integer> groupsPair = listDomainLevelAffinityGroups(scDomain, searchFilter, domainId); Pair<List<AffinityGroupJoinVO>, Integer> groupsPair = listDomainLevelAffinityGroups(scDomain, searchFilter, domainId);
affinityGroups.addAll(groupsPair.first()); affinityGroups.addAll(groupsPair.first());
@ -5152,7 +5151,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
for (Long permAcctId : permittedAccounts) { for (Long permAcctId : permittedAccounts) {
Account permittedAcct = _accountDao.findById(permAcctId); Account permittedAcct = _accountDao.findById(permAcctId);
SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<Long>(), listProjectResourcesCriteria, affinityGroupId, SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<>(), listProjectResourcesCriteria, affinityGroupId,
affinityGroupName, affinityGroupType, keyword); affinityGroupName, affinityGroupType, keyword);
Pair<List<AffinityGroupJoinVO>, Integer> groupsPair = listDomainLevelAffinityGroups(scDomain, searchFilter, permittedAcct.getDomainId()); Pair<List<AffinityGroupJoinVO>, Integer> groupsPair = listDomainLevelAffinityGroups(scDomain, searchFilter, permittedAcct.getDomainId());
affinityGroups.addAll(groupsPair.first()); affinityGroups.addAll(groupsPair.first());
@ -5161,14 +5160,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
} }
} else if (((permittedAccounts.isEmpty()) && (domainId != null) && isRecursive)) { } else if (((permittedAccounts.isEmpty()) && (domainId != null) && isRecursive)) {
// list all domain level affinity groups for the domain admin case // list all domain level affinity groups for the domain admin case
SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<Long>(), listProjectResourcesCriteria, affinityGroupId, affinityGroupName, SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<>(), listProjectResourcesCriteria, affinityGroupId, affinityGroupName,
affinityGroupType, keyword); affinityGroupType, keyword);
Pair<List<AffinityGroupJoinVO>, Integer> groupsPair = listDomainLevelAffinityGroups(scDomain, searchFilter, domainId); Pair<List<AffinityGroupJoinVO>, Integer> groupsPair = listDomainLevelAffinityGroups(scDomain, searchFilter, domainId);
affinityGroups.addAll(groupsPair.first()); affinityGroups.addAll(groupsPair.first());
count += groupsPair.second(); count += groupsPair.second();
} }
return new Pair<List<AffinityGroupJoinVO>, Integer>(affinityGroups, count); return new Pair<>(affinityGroups, count);
} }
@ -5254,7 +5253,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Integer count = agVmMappingPair.second(); Integer count = agVmMappingPair.second();
if (count.intValue() == 0) { if (count.intValue() == 0) {
// handle empty result cases // handle empty result cases
return new Pair<List<AffinityGroupJoinVO>, Integer>(new ArrayList<AffinityGroupJoinVO>(), count); return new Pair<>(new ArrayList<>(), count);
} }
List<AffinityGroupVMMapVO> agVmMappings = agVmMappingPair.first(); List<AffinityGroupVMMapVO> agVmMappings = agVmMappingPair.first();
Long[] agIds = new Long[agVmMappings.size()]; Long[] agIds = new Long[agVmMappings.size()];
@ -5263,11 +5262,11 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
agIds[i++] = agVm.getAffinityGroupId(); agIds[i++] = agVm.getAffinityGroupId();
} }
List<AffinityGroupJoinVO> ags = _affinityGroupJoinDao.searchByIds(agIds); List<AffinityGroupJoinVO> ags = _affinityGroupJoinDao.searchByIds(agIds);
return new Pair<List<AffinityGroupJoinVO>, Integer>(ags, count); return new Pair<>(ags, count);
} }
private Pair<List<AffinityGroupJoinVO>, Integer> listDomainLevelAffinityGroups(SearchCriteria<AffinityGroupJoinVO> sc, Filter searchFilter, long domainId) { private Pair<List<AffinityGroupJoinVO>, Integer> listDomainLevelAffinityGroups(SearchCriteria<AffinityGroupJoinVO> sc, Filter searchFilter, long domainId) {
List<Long> affinityGroupIds = new ArrayList<Long>(); List<Long> affinityGroupIds = new ArrayList<>();
Set<Long> allowedDomains = _domainMgr.getDomainParentIds(domainId); Set<Long> allowedDomains = _domainMgr.getDomainParentIds(domainId);
List<AffinityGroupDomainMapVO> maps = _affinityGroupDomainMapDao.listByDomain(allowedDomains.toArray()); List<AffinityGroupDomainMapVO> maps = _affinityGroupDomainMapDao.listByDomain(allowedDomains.toArray());
@ -5290,7 +5289,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Integer count = uniqueGroupsPair.second(); Integer count = uniqueGroupsPair.second();
if (count.intValue() == 0) { if (count.intValue() == 0) {
// empty result // empty result
return new Pair<>(new ArrayList<AffinityGroupJoinVO>(), 0); return new Pair<>(new ArrayList<>(), 0);
} }
List<AffinityGroupJoinVO> uniqueGroups = uniqueGroupsPair.first(); List<AffinityGroupJoinVO> uniqueGroups = uniqueGroupsPair.first();
Long[] vrIds = new Long[uniqueGroups.size()]; Long[] vrIds = new Long[uniqueGroups.size()];
@ -5301,7 +5300,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
List<AffinityGroupJoinVO> vrs = _affinityGroupJoinDao.searchByIds(vrIds); List<AffinityGroupJoinVO> vrs = _affinityGroupJoinDao.searchByIds(vrIds);
return new Pair<>(vrs, count); return new Pair<>(vrs, count);
} else { } else {
return new Pair<>(new ArrayList<AffinityGroupJoinVO>(), 0); return new Pair<>(new ArrayList<>(), 0);
} }
} }
@ -5332,7 +5331,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
} }
} }
List<? extends ResourceDetail> detailList = new ArrayList<ResourceDetail>(); List<? extends ResourceDetail> detailList = new ArrayList<>();
ResourceDetail requestedDetail = null; ResourceDetail requestedDetail = null;
if (key == null) { if (key == null) {
@ -5346,7 +5345,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
detailList = _resourceMetaDataMgr.getDetails(resourceType, key, value, forDisplay); detailList = _resourceMetaDataMgr.getDetails(resourceType, key, value, forDisplay);
} }
List<ResourceDetailResponse> responseList = new ArrayList<ResourceDetailResponse>(); List<ResourceDetailResponse> responseList = new ArrayList<>();
if (requestedDetail != null) { if (requestedDetail != null) {
ResourceDetailResponse detailResponse = createResourceDetailsResponse(requestedDetail, resourceType); ResourceDetailResponse detailResponse = createResourceDetailsResponse(requestedDetail, resourceType);
responseList.add(detailResponse); responseList.add(detailResponse);
@ -5596,7 +5595,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Filter searchFilter = new Filter(SnapshotJoinVO.class, "snapshotStorePair", SortKeyAscending.value(), startIndex, pageSize); Filter searchFilter = new Filter(SnapshotJoinVO.class, "snapshotStorePair", SortKeyAscending.value(), startIndex, pageSize);
List<Long> permittedAccountIds = new ArrayList<>(); List<Long> permittedAccountIds = new ArrayList<>();
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(domainId, isRecursive, null); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(domainId, isRecursive, null);
accountMgr.buildACLSearchParameters(caller, id, accountName, projectId, permittedAccountIds, domainIdRecursiveListProject, listAll, false); accountMgr.buildACLSearchParameters(caller, id, accountName, projectId, permittedAccountIds, domainIdRecursiveListProject, listAll, false);
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
domainId = domainIdRecursiveListProject.first(); domainId = domainIdRecursiveListProject.first();
@ -5729,7 +5728,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Integer count = snapshotDataPair.second(); Integer count = snapshotDataPair.second();
if (count == 0) { if (count == 0) {
// empty result
return snapshotDataPair; return snapshotDataPair;
} }
List<SnapshotJoinVO> snapshotData = snapshotDataPair.first(); List<SnapshotJoinVO> snapshotData = snapshotDataPair.first();
@ -5739,13 +5737,12 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
} else { } else {
snapshots = snapshotJoinDao.searchBySnapshotStorePair(snapshotData.stream().map(SnapshotJoinVO::getSnapshotStorePair).toArray(String[]::new)); snapshots = snapshotJoinDao.searchBySnapshotStorePair(snapshotData.stream().map(SnapshotJoinVO::getSnapshotStorePair).toArray(String[]::new));
} }
return new Pair<>(snapshots, count); return new Pair<>(snapshots, count);
} }
public ListResponse<ObjectStoreResponse> searchForObjectStores(ListObjectStoragePoolsCmd cmd) { public ListResponse<ObjectStoreResponse> searchForObjectStores(ListObjectStoragePoolsCmd cmd) {
Pair<List<ObjectStoreVO>, Integer> result = searchForObjectStoresInternal(cmd); Pair<List<ObjectStoreVO>, Integer> result = searchForObjectStoresInternal(cmd);
ListResponse<ObjectStoreResponse> response = new ListResponse<ObjectStoreResponse>(); ListResponse<ObjectStoreResponse> response = new ListResponse<>();
List<ObjectStoreResponse> poolResponses = ViewResponseHelper.createObjectStoreResponse(result.first().toArray(new ObjectStoreVO[result.first().size()])); List<ObjectStoreResponse> poolResponses = ViewResponseHelper.createObjectStoreResponse(result.first().toArray(new ObjectStoreVO[result.first().size()]));
response.setResponses(poolResponses, result.second()); response.setResponses(poolResponses, result.second());
@ -5830,7 +5827,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Long startIndex = cmd.getStartIndex(); Long startIndex = cmd.getStartIndex();
Long pageSize = cmd.getPageSizeVal(); Long pageSize = cmd.getPageSizeVal();
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
List<Long> permittedAccounts = new ArrayList<Long>(); List<Long> permittedAccounts = new ArrayList<>();
// Verify parameters // Verify parameters
if (id != null) { if (id != null) {
@ -5842,7 +5839,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
List<Long> ids = getIdsListFromCmd(cmd.getId(), cmd.getIds()); List<Long> ids = getIdsListFromCmd(cmd.getId(), cmd.getIds());
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(),
cmd.isRecursive(), null); cmd.isRecursive(), null);
accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
Long domainId = domainIdRecursiveListProject.first(); Long domainId = domainIdRecursiveListProject.first();

View File

@ -23,10 +23,7 @@ import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.response.SnapshotResponse; import org.apache.cloudstack.api.response.SnapshotResponse;
import com.cloud.api.query.vo.SnapshotJoinVO; import com.cloud.api.query.vo.SnapshotJoinVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.SearchCriteria;
public interface SnapshotJoinDao extends GenericDao<SnapshotJoinVO, Long> { public interface SnapshotJoinDao extends GenericDao<SnapshotJoinVO, Long> {
@ -34,8 +31,7 @@ public interface SnapshotJoinDao extends GenericDao<SnapshotJoinVO, Long> {
SnapshotResponse setSnapshotResponse(SnapshotResponse snapshotResponse, SnapshotJoinVO snapshot); SnapshotResponse setSnapshotResponse(SnapshotResponse snapshotResponse, SnapshotJoinVO snapshot);
Pair<List<SnapshotJoinVO>, Integer> searchIncludingRemovedAndCount(final SearchCriteria<SnapshotJoinVO> sc, final Filter filter);
List<SnapshotJoinVO> searchBySnapshotStorePair(String... pairs); List<SnapshotJoinVO> searchBySnapshotStorePair(String... pairs);
List<SnapshotJoinVO> findByDistinctIds(Long zoneId, Long... ids); List<SnapshotJoinVO> findByDistinctIds(Long zoneId, Long... ids);
} }

View File

@ -18,6 +18,8 @@
package com.cloud.api.query.dao; package com.cloud.api.query.dao;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -34,6 +36,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.query.QueryService; import org.apache.cloudstack.query.QueryService;
import org.apache.commons.collections.CollectionUtils;
import com.cloud.api.ApiDBUtils; import com.cloud.api.ApiDBUtils;
import com.cloud.api.ApiResponseHelper; import com.cloud.api.ApiResponseHelper;
import com.cloud.api.query.vo.SnapshotJoinVO; import com.cloud.api.query.vo.SnapshotJoinVO;
@ -44,7 +48,6 @@ import com.cloud.storage.Volume.Type;
import com.cloud.storage.VolumeVO; import com.cloud.storage.VolumeVO;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.user.AccountService; import com.cloud.user.AccountService;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter; import com.cloud.utils.db.Filter;
import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria;
@ -53,11 +56,11 @@ import com.cloud.vm.VMInstanceVO;
public class SnapshotJoinDaoImpl extends GenericDaoBaseWithTagInformation<SnapshotJoinVO, SnapshotResponse> implements SnapshotJoinDao { public class SnapshotJoinDaoImpl extends GenericDaoBaseWithTagInformation<SnapshotJoinVO, SnapshotResponse> implements SnapshotJoinDao {
@Inject @Inject
private AccountService accountService; AccountService accountService;
@Inject @Inject
private AnnotationDao annotationDao; AnnotationDao annotationDao;
@Inject @Inject
private ConfigurationDao configDao; ConfigurationDao configDao;
@Inject @Inject
SnapshotDataFactory snapshotDataFactory; SnapshotDataFactory snapshotDataFactory;
@ -85,7 +88,7 @@ public class SnapshotJoinDaoImpl extends GenericDaoBaseWithTagInformation<Snapsh
if (snapshot.getDataCenterId() == null) { if (snapshot.getDataCenterId() == null) {
return; return;
} }
SnapshotInfo snapshotInfo = null; SnapshotInfo snapshotInfo;
snapshotInfo = snapshotDataFactory.getSnapshotWithRoleAndZone(snapshot.getId(), snapshot.getStoreRole(), snapshot.getDataCenterId()); snapshotInfo = snapshotDataFactory.getSnapshotWithRoleAndZone(snapshot.getId(), snapshot.getStoreRole(), snapshot.getDataCenterId());
if (snapshotInfo == null) { if (snapshotInfo == null) {
logger.debug("Unable to find info for image store snapshot {}", snapshot); logger.debug("Unable to find info for image store snapshot {}", snapshot);
@ -192,13 +195,6 @@ public class SnapshotJoinDaoImpl extends GenericDaoBaseWithTagInformation<Snapsh
return snapshotResponse; return snapshotResponse;
} }
@Override
public Pair<List<SnapshotJoinVO>, Integer> searchIncludingRemovedAndCount(final SearchCriteria<SnapshotJoinVO> sc, final Filter filter) {
List<SnapshotJoinVO> objects = searchIncludingRemoved(sc, filter, null, false);
Integer count = getDistinctCount(sc);
return new Pair<>(objects, count);
}
@Override @Override
public List<SnapshotJoinVO> searchBySnapshotStorePair(String... pairs) { public List<SnapshotJoinVO> searchBySnapshotStorePair(String... pairs) {
// set detail batch query size // set detail batch query size
@ -243,14 +239,33 @@ public class SnapshotJoinDaoImpl extends GenericDaoBaseWithTagInformation<Snapsh
return uvList; return uvList;
} }
protected List<SnapshotJoinVO> findById(Long zoneId, long id) {
SearchBuilder<SnapshotJoinVO> sb = createSearchBuilder();
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<SnapshotJoinVO> sc = sb.create();
sc.setParameters("id", id);
if (zoneId != null) {
sc.setParameters("zoneId", zoneId);
}
List<SnapshotJoinVO> snapshotJoinVOS = search(sc, null);
if (CollectionUtils.isEmpty(snapshotJoinVOS)) {
return null;
}
snapshotJoinVOS.sort(Comparator.comparing(SnapshotJoinVO::getSnapshotStorePair));
return Collections.singletonList(snapshotJoinVOS.get(0));
}
@Override @Override
public List<SnapshotJoinVO> findByDistinctIds(Long zoneId, Long... ids) { public List<SnapshotJoinVO> findByDistinctIds(Long zoneId, Long... ids) {
if (ids == null || ids.length == 0) { if (ids == null || ids.length == 0) {
return new ArrayList<>(); return new ArrayList<>();
} }
if (ids.length == 1) {
return findById(zoneId, ids[0]);
}
Filter searchFilter = new Filter(SnapshotJoinVO.class, "snapshotStorePair", QueryService.SortKeyAscending.value(), null, null); Filter searchFilter = new Filter(SnapshotJoinVO.class, "snapshotStorePair", QueryService.SortKeyAscending.value(), null, null);
SearchCriteria<SnapshotJoinVO> sc = snapshotIdsSearch.create(); SearchCriteria<SnapshotJoinVO> sc = snapshotIdsSearch.create();
if (zoneId != null) { if (zoneId != null) {
sc.setParameters("zoneId", zoneId); sc.setParameters("zoneId", zoneId);

View File

@ -7225,10 +7225,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
sc.addAnd("id", SearchCriteria.Op.EQ, id); sc.addAnd("id", SearchCriteria.Op.EQ, id);
} }
if (tags != null) {
sc.addAnd("tags", SearchCriteria.Op.EQ, tags);
}
if (isTagged != null) { if (isTagged != null) {
if (isTagged) { if (isTagged) {
sc.addAnd("tags", SearchCriteria.Op.NNULL); sc.addAnd("tags", SearchCriteria.Op.NNULL);
@ -7237,6 +7233,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
} }
} }
if (tags != null) {
if (GuestType.Shared.name().equalsIgnoreCase(guestIpType)) {
SearchCriteria<NetworkOfferingJoinVO> tagsSc = networkOfferingJoinDao.createSearchCriteria();
tagsSc.addAnd("tags", SearchCriteria.Op.EQ, tags);
tagsSc.addOr("isDefault", SearchCriteria.Op.EQ, true);
sc.addAnd("tags", SearchCriteria.Op.SC, tagsSc);
} else {
sc.addAnd("tags", SearchCriteria.Op.EQ, tags);
}
}
if (zoneId != null) { if (zoneId != null) {
SearchBuilder<NetworkOfferingJoinVO> sb = networkOfferingJoinDao.createSearchBuilder(); SearchBuilder<NetworkOfferingJoinVO> sb = networkOfferingJoinDao.createSearchBuilder();
sb.and("zoneId", sb.entity().getZoneId(), SearchCriteria.Op.FIND_IN_SET); sb.and("zoneId", sb.entity().getZoneId(), SearchCriteria.Op.FIND_IN_SET);
@ -7297,7 +7304,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
boolean addOffering = true; boolean addOffering = true;
List<Service> checkForProviders = new ArrayList<Service>(); List<Service> checkForProviders = new ArrayList<Service>();
if (checkForTags && ! checkNetworkOfferingTags(pNtwkTags, allowNullTag, offering.getTags())) { if (checkForTags && !checkNetworkOfferingTags(pNtwkTags, allowNullTag, offering.getTags())) {
continue; continue;
} }

View File

@ -934,8 +934,12 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
@Override @Override
public UserDataServiceProvider getUserDataUpdateProvider(Network network) { public UserDataServiceProvider getUserDataUpdateProvider(Network network) {
String userDataProvider = _ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Service.UserData); if (network == null) {
logger.warn("No network details, can't fetch user data provider");
return null;
}
String userDataProvider = _ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Service.UserData);
if (userDataProvider == null) { if (userDataProvider == null) {
logger.debug("Network " + network + " doesn't support service " + Service.UserData.getName()); logger.debug("Network " + network + " doesn't support service " + Service.UserData.getName());
return null; return null;

View File

@ -325,8 +325,12 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle
try { try {
final Network network = _networkMgr.getNetwork(nic.getNetworkId()); final Network network = _networkMgr.getNetwork(nic.getNetworkId());
final UserDataServiceProvider userDataUpdateProvider = _networkModel.getUserDataUpdateProvider(network); final UserDataServiceProvider userDataUpdateProvider = _networkModel.getUserDataUpdateProvider(network);
if (userDataUpdateProvider == null) {
logger.warn("Failed to get user data provider");
return false;
}
final Provider provider = userDataUpdateProvider.getProvider(); final Provider provider = userDataUpdateProvider.getProvider();
if (provider.equals(Provider.ConfigDrive)) { if (Provider.ConfigDrive.equals(provider)) {
try { try {
return deleteConfigDriveIso(vm); return deleteConfigDriveIso(vm);
} catch (ResourceUnavailableException e) { } catch (ResourceUnavailableException e) {
@ -341,8 +345,13 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle
@Override @Override
public boolean prepareMigration(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) { public boolean prepareMigration(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) {
if (_networkModel.getUserDataUpdateProvider(network).getProvider().equals(Provider.ConfigDrive)) { final UserDataServiceProvider userDataUpdateProvider = _networkModel.getUserDataUpdateProvider(network);
logger.trace(String.format("[prepareMigration] for vm: %s", vm)); if (userDataUpdateProvider == null) {
logger.warn("Failed to prepare for migration, can't get user data provider");
return false;
}
if (Provider.ConfigDrive.equals(userDataUpdateProvider.getProvider())) {
logger.trace(String.format("[prepareMigration] for vm: %s", vm.getInstanceName()));
try { try {
if (isConfigDriveIsoOnHostCache(vm.getId())) { if (isConfigDriveIsoOnHostCache(vm.getId())) {
vm.setConfigDriveLocation(Location.HOST); vm.setConfigDriveLocation(Location.HOST);
@ -392,7 +401,11 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle
} }
private void recreateConfigDriveIso(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest) throws ResourceUnavailableException { private void recreateConfigDriveIso(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest) throws ResourceUnavailableException {
if (nic.isDefaultNic() && _networkModel.getUserDataUpdateProvider(network).getProvider().equals(Provider.ConfigDrive)) { final UserDataServiceProvider userDataUpdateProvider = _networkModel.getUserDataUpdateProvider(network);
if (userDataUpdateProvider == null) {
return;
}
if (nic.isDefaultNic() && Provider.ConfigDrive.equals(userDataUpdateProvider.getProvider())) {
DiskTO diskToUse = null; DiskTO diskToUse = null;
for (DiskTO disk : vm.getDisks()) { for (DiskTO disk : vm.getDisks()) {
if (disk.getType() == Volume.Type.ISO && disk.getPath() != null && disk.getPath().contains("configdrive")) { if (disk.getType() == Volume.Type.ISO && disk.getPath() != null && disk.getPath().contains("configdrive")) {

View File

@ -769,7 +769,12 @@ NetworkMigrationResponder, AggregatedCommandExecutor, RedundantResource, DnsServ
@Override @Override
public boolean saveHypervisorHostname(NicProfile nicProfile, Network network, VirtualMachineProfile vm, DeployDestination dest) throws ResourceUnavailableException { public boolean saveHypervisorHostname(NicProfile nicProfile, Network network, VirtualMachineProfile vm, DeployDestination dest) throws ResourceUnavailableException {
if (_networkModel.getUserDataUpdateProvider(network).getProvider().equals(Provider.VirtualRouter) && vm.getVirtualMachine().getType() == VirtualMachine.Type.User) { final UserDataServiceProvider userDataUpdateProvider = _networkModel.getUserDataUpdateProvider(network);
if (userDataUpdateProvider == null) {
logger.warn("Failed to update hypervisor host details, can't get user data provider");
return false;
}
if (Provider.VirtualRouter.equals(userDataUpdateProvider.getProvider()) && vm.getVirtualMachine().getType() == VirtualMachine.Type.User) {
VirtualMachine uvm = vm.getVirtualMachine(); VirtualMachine uvm = vm.getVirtualMachine();
UserVmVO destVm = _userVmDao.findById(uvm.getId()); UserVmVO destVm = _userVmDao.findById(uvm.getId());
VirtualMachineProfile profile = null; VirtualMachineProfile profile = null;

View File

@ -3622,8 +3622,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
templateVO = _templateStoreDao.findByStoreTemplate(store.getId(), templateId); templateVO = _templateStoreDao.findByStoreTemplate(store.getId(), templateId);
if (templateVO != null) { if (templateVO != null) {
try { try {
if (SystemVmTemplateRegistration.validateIfSeeded( if (systemVmTemplateRegistration.validateIfSeeded(
url, templateVO.getInstallPath(), nfsVersion)) { templateVO, url, templateVO.getInstallPath(), nfsVersion)) {
continue; continue;
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -2482,10 +2482,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
return existingVolumeOfVm; return existingVolumeOfVm;
} }
protected StoragePool getPoolForAllocatedOrUploadedVolumeForAttach(final VolumeInfo volumeToAttach, final UserVmVO vm) { protected StoragePool getSuitablePoolForAllocatedOrUploadedVolumeForAttach(final VolumeInfo volumeToAttach, final UserVmVO vm) {
DataCenter zone = _dcDao.findById(vm.getDataCenterId()); DataCenter zone = _dcDao.findById(vm.getDataCenterId());
Pair<Long, Long> clusterHostId = virtualMachineManager.findClusterAndHostIdForVm(vm, false); Pair<Long, Long> clusterHostId = virtualMachineManager.findClusterAndHostIdForVm(vm, false);
long podId = vm.getPodIdToDeployIn(); Long podId = vm.getPodIdToDeployIn();
if (clusterHostId.first() != null) { if (clusterHostId.first() != null) {
Cluster cluster = clusterDao.findById(clusterHostId.first()); Cluster cluster = clusterDao.findById(clusterHostId.first());
podId = cluster.getPodId(); podId = cluster.getPodId();
@ -2497,12 +2497,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
offering.isUseLocalStorage(), offering.isRecreatable(), offering.isUseLocalStorage(), offering.isRecreatable(),
volumeToAttach.getTemplateId()); volumeToAttach.getTemplateId());
diskProfile.setHyperType(vm.getHypervisorType()); diskProfile.setHyperType(vm.getHypervisorType());
StoragePool pool = _volumeMgr.findStoragePool(diskProfile, zone, pod, clusterHostId.first(), return _volumeMgr.findStoragePool(diskProfile, zone, pod, clusterHostId.first(),
clusterHostId.second(), vm, Collections.emptySet()); clusterHostId.second(), vm, Collections.emptySet());
if (pool == null) {
throw new CloudRuntimeException(String.format("Failed to find a primary storage for volume in state: %s", volumeToAttach.getState()));
}
return pool;
} }
protected VolumeInfo createVolumeOnPrimaryForAttachIfNeeded(final VolumeInfo volumeToAttach, final UserVmVO vm, VolumeVO existingVolumeOfVm) { protected VolumeInfo createVolumeOnPrimaryForAttachIfNeeded(final VolumeInfo volumeToAttach, final UserVmVO vm, VolumeVO existingVolumeOfVm) {
@ -2520,7 +2516,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
} }
} }
if (destPrimaryStorage == null) { if (destPrimaryStorage == null) {
destPrimaryStorage = getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm); destPrimaryStorage = getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
if (destPrimaryStorage == null) {
if (Volume.State.Allocated.equals(volumeToAttach.getState()) && State.Stopped.equals(vm.getState())) {
return newVolumeOnPrimaryStorage;
}
throw new CloudRuntimeException(String.format("Failed to find a primary storage for volume in state: %s", volumeToAttach.getState()));
}
} }
try { try {
if (volumeOnSecondary && Storage.StoragePoolType.PowerFlex.equals(destPrimaryStorage.getPoolType())) { if (volumeOnSecondary && Storage.StoragePoolType.PowerFlex.equals(destPrimaryStorage.getPoolType())) {

View File

@ -498,8 +498,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (apiNameList == null) { if (apiNameList == null) {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
apiNameList = new ArrayList<String>(); apiNameList = new ArrayList<>();
Set<Class<?>> cmdClasses = new LinkedHashSet<Class<?>>(); Set<Class<?>> cmdClasses = new LinkedHashSet<>();
for (PluggableService service : services) { for (PluggableService service : services) {
logger.debug(String.format("getting api commands of service: %s", service.getClass().getName())); logger.debug(String.format("getting api commands of service: %s", service.getClass().getName()));
cmdClasses.addAll(service.getCommands()); cmdClasses.addAll(service.getCommands());
@ -513,7 +513,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
} }
protected List<String> createApiNameList(Set<Class<?>> cmdClasses) { protected List<String> createApiNameList(Set<Class<?>> cmdClasses) {
List<String> apiNameList = new ArrayList<String>(); List<String> apiNameList = new ArrayList<>();
for (Class<?> cmdClass : cmdClasses) { for (Class<?> cmdClass : cmdClasses) {
APICommand apiCmdAnnotation = cmdClass.getAnnotation(APICommand.class); APICommand apiCmdAnnotation = cmdClass.getAnnotation(APICommand.class);
@ -698,7 +698,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
return; return;
} }
HashMap<Long, List<ControlledEntity>> domains = new HashMap<Long, List<ControlledEntity>>(); HashMap<Long, List<ControlledEntity>> domains = new HashMap<>();
for (ControlledEntity entity : entities) { for (ControlledEntity entity : entities) {
long domainId = entity.getDomainId(); long domainId = entity.getDomainId();
@ -713,7 +713,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId()); List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId());
// for templates, we don't have to do cross domains check // for templates, we don't have to do cross domains check
if (toBeChecked == null) { if (toBeChecked == null) {
toBeChecked = new ArrayList<ControlledEntity>(); toBeChecked = new ArrayList<>();
domains.put(domainId, toBeChecked); domains.put(domainId, toBeChecked);
} }
toBeChecked.add(entity); toBeChecked.add(entity);
@ -722,7 +722,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
for (SecurityChecker checker : _securityCheckers) { for (SecurityChecker checker : _securityCheckers) {
if (checker.checkAccess(caller, entity, accessType, apiName)) { if (checker.checkAccess(caller, entity, accessType, apiName)) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Access to " + entity + " granted to " + caller + " by " + checker.getName()); User user = CallContext.current().getCallingUser();
String userName = "";
if (user != null)
userName = user.getUsername();
logger.debug("Access to {} granted to {} by {} on behalf of user {}", entity, caller, checker.getName(), userName);
} }
granted = true; granted = true;
break; break;
@ -1023,12 +1027,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
logger.debug("Deleting networks for account {}", account); logger.debug("Deleting networks for account {}", account);
List<NetworkVO> networks = _networkDao.listByOwner(accountId); List<NetworkVO> networks = _networkDao.listByOwner(accountId);
if (networks != null) { if (networks != null) {
Collections.sort(networks, new Comparator<NetworkVO>() { Collections.sort(networks, new Comparator<>() {
@Override @Override
public int compare(NetworkVO network1, NetworkVO network2) { public int compare(NetworkVO network1, NetworkVO network2) {
if (network1.getGuestType() != network2.getGuestType() && Network.GuestType.Isolated.equals(network2.getGuestType())) { if (network1.getGuestType() != network2.getGuestType() && Network.GuestType.Isolated.equals(network2.getGuestType())) {
return -1; return -1;
}; }
return 1; return 1;
} }
}); });
@ -1300,7 +1304,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
final String accountNameFinal = accountName; final String accountNameFinal = accountName;
final Long domainIdFinal = domainId; final Long domainIdFinal = domainId;
final String accountUUIDFinal = accountUUID; final String accountUUIDFinal = accountUUID;
Pair<Long, Account> pair = Transaction.execute(new TransactionCallback<Pair<Long, Account>>() { Pair<Long, Account> pair = Transaction.execute(new TransactionCallback<>() {
@Override @Override
public Pair<Long, Account> doInTransaction(TransactionStatus status) { public Pair<Long, Account> doInTransaction(TransactionStatus status) {
// create account // create account
@ -1323,7 +1327,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
user.setRegistrationToken(registrationToken); user.setRegistrationToken(registrationToken);
} }
return new Pair<Long, Account>(user.getId(), account); return new Pair<>(user.getId(), account);
} }
}); });
@ -1332,7 +1336,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
// create correct account and group association based on accountType // create correct account and group association based on accountType
if (accountType != Account.Type.PROJECT) { if (accountType != Account.Type.PROJECT) {
Map<Long, Long> accountGroupMap = new HashMap<Long, Long>(); Map<Long, Long> accountGroupMap = new HashMap<>();
accountGroupMap.put(account.getId(), (long) (accountType.ordinal() + 1)); accountGroupMap.put(account.getId(), (long) (accountType.ordinal() + 1));
_messageBus.publish(_name, MESSAGE_ADD_ACCOUNT_EVENT, PublishScope.LOCAL, accountGroupMap); _messageBus.publish(_name, MESSAGE_ADD_ACCOUNT_EVENT, PublishScope.LOCAL, accountGroupMap);
} }
@ -1476,7 +1480,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (!_userAccountDao.validateUsernameInDomain(userName, domainId)) { if (!_userAccountDao.validateUsernameInDomain(userName, domainId)) {
throw new CloudRuntimeException(String.format("The user %s already exists in domain %s", userName, domain)); throw new CloudRuntimeException(String.format("The user %s already exists in domain %s", userName, domain));
} }
UserVO user = null; UserVO user;
user = createUser(account.getId(), userName, password, firstName, lastName, email, timeZone, userUUID, source); user = createUser(account.getId(), userName, password, firstName, lastName, email, timeZone, userUUID, source);
return user; return user;
} }
@ -1731,7 +1735,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
Long callingUserId = CallContext.current().getCallingUserId(); Long callingUserId = CallContext.current().getCallingUserId();
Account callingAccount = CallContext.current().getCallingAccount(); Account callingAccount = CallContext.current().getCallingAccount();
ActionEventUtils.onActionEvent(callingUserId, callingAccount.getAccountId(), callingAccount.getDomainId(), ActionEventUtils.onActionEvent(callingUserId, callingAccount.getAccountId(), callingAccount.getDomainId(),
EventTypes.API_KEY_ACCESS_UPDATE, "Api key access was changed for the User to " + access.toString(), EventTypes.API_KEY_ACCESS_UPDATE, "Api key access was changed for the User to " + access,
user.getId(), ApiCommandResourceType.User.toString()); user.getId(), ApiCommandResourceType.User.toString());
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
throw new InvalidParameterValueException("ApiKeyAccess value can only be Enabled/Disabled/Inherit"); throw new InvalidParameterValueException("ApiKeyAccess value can only be Enabled/Disabled/Inherit");
@ -1747,7 +1751,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
Long callingUserId = CallContext.current().getCallingUserId(); Long callingUserId = CallContext.current().getCallingUserId();
Account callingAccount = CallContext.current().getCallingAccount(); Account callingAccount = CallContext.current().getCallingAccount();
ActionEventUtils.onActionEvent(callingUserId, callingAccount.getAccountId(), callingAccount.getDomainId(), ActionEventUtils.onActionEvent(callingUserId, callingAccount.getAccountId(), callingAccount.getDomainId(),
EventTypes.API_KEY_ACCESS_UPDATE, "Api key access was changed for the Account to " + access.toString(), EventTypes.API_KEY_ACCESS_UPDATE, "Api key access was changed for the Account to " + access,
account.getId(), ApiCommandResourceType.Account.toString()); account.getId(), ApiCommandResourceType.Account.toString());
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
throw new InvalidParameterValueException("ApiKeyAccess value can only be Enabled/Disabled/Inherit"); throw new InvalidParameterValueException("ApiKeyAccess value can only be Enabled/Disabled/Inherit");
@ -1837,7 +1841,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
checkAccess(caller, AccessType.OperateEntry, true, account); checkAccess(caller, AccessType.OperateEntry, true, account);
boolean success = Transaction.execute(new TransactionCallback<Boolean>() { boolean success = Transaction.execute(new TransactionCallback<>() {
@Override @Override
public Boolean doInTransaction(TransactionStatus status) { public Boolean doInTransaction(TransactionStatus status) {
boolean success = doSetUserStatus(userId, State.ENABLED); boolean success = doSetUserStatus(userId, State.ENABLED);
@ -1892,7 +1896,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
// make sure the account is enabled too // make sure the account is enabled too
// if the user is either locked already or disabled already, don't change state...only lock currently enabled // if the user is either locked already or disabled already, don't change state...only lock currently enabled
// users // users
boolean success = true; boolean success;
if (user.getState().equals(State.LOCKED)) { if (user.getState().equals(State.LOCKED)) {
// already locked...no-op // already locked...no-op
return _userAccountDao.findById(userId); return _userAccountDao.findById(userId);
@ -1995,7 +1999,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
public AccountVO enableAccount(String accountName, Long domainId, Long accountId) { public AccountVO enableAccount(String accountName, Long domainId, Long accountId) {
// Check if account exists // Check if account exists
Account account = null; Account account;
if (accountId != null) { if (accountId != null) {
account = _accountDao.findById(accountId); account = _accountDao.findById(accountId);
} else { } else {
@ -2021,7 +2025,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
return _accountDao.findById(account.getId()); return _accountDao.findById(account.getId());
} else { } else {
throw new CloudRuntimeException(String.format("Unable to enable account %s in domain %s", account, accountName, _domainMgr.getDomain(domainId))); throw new CloudRuntimeException(String.format("Unable to enable account %s[%s] in domain %s", accountName, account.getUuid(), _domainMgr.getDomain(domainId)));
} }
} }
@ -2030,7 +2034,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
public AccountVO lockAccount(String accountName, Long domainId, Long accountId) { public AccountVO lockAccount(String accountName, Long domainId, Long accountId) {
Account caller = getCurrentCallingAccount(); Account caller = getCurrentCallingAccount();
Account account = null; Account account;
if (accountId != null) { if (accountId != null) {
account = _accountDao.findById(accountId); account = _accountDao.findById(accountId);
} else { } else {
@ -2051,7 +2055,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
CallContext.current().putContextParameter(Account.class, account.getUuid()); CallContext.current().putContextParameter(Account.class, account.getUuid());
return _accountDao.findById(account.getId()); return _accountDao.findById(account.getId());
} else { } else {
throw new CloudRuntimeException(String.format("Unable to lock account %s by accountId: %d OR by name: %s in domain %d", account, accountId, accountName, _domainMgr.getDomain(domainId))); throw new CloudRuntimeException(String.format("Unable to lock account %s by accountId: %d OR by name: %s in domain %s", account, accountId, accountName, _domainMgr.getDomain(domainId)));
} }
} }
@ -2060,7 +2064,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
public AccountVO disableAccount(String accountName, Long domainId, Long accountId) throws ConcurrentOperationException, ResourceUnavailableException { public AccountVO disableAccount(String accountName, Long domainId, Long accountId) throws ConcurrentOperationException, ResourceUnavailableException {
Account caller = getCurrentCallingAccount(); Account caller = getCurrentCallingAccount();
Account account = null; Account account;
if (accountId != null) { if (accountId != null) {
account = _accountDao.findById(accountId); account = _accountDao.findById(accountId);
} else { } else {
@ -2097,8 +2101,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
String networkDomain = cmd.getNetworkDomain(); String networkDomain = cmd.getNetworkDomain();
final Map<String, String> details = cmd.getDetails(); final Map<String, String> details = cmd.getDetails();
boolean success = false; boolean success;
Account account = null; Account account;
if (accountId != null) { if (accountId != null) {
account = _accountDao.findById(accountId); account = _accountDao.findById(accountId);
} else { } else {
@ -2159,7 +2163,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
if (roleNotFound) { if (roleNotFound) {
throw new InvalidParameterValueException(String.format("Role with ID '%s' is not " + throw new InvalidParameterValueException(String.format("Role with ID '%s' is not " +
"found or not available for the account '%s' in the domain '%s'.", "found or not available for the account '%s' in the domain '%s'.",
roleId.toString(), account, _domainMgr.getDomain(domainId))); roleId, account, _domainMgr.getDomain(domainId)));
} }
Role role = roleService.findRole(roleId); Role role = roleService.findRole(roleId);
@ -2244,7 +2248,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
return true; // no need to create a new user object for this user return true; // no need to create a new user object for this user
} }
return Transaction.execute(new TransactionCallback<Boolean>() { return Transaction.execute(new TransactionCallback<>() {
@Override @Override
public Boolean doInTransaction(TransactionStatus status) { public Boolean doInTransaction(TransactionStatus status) {
UserVO newUser = new UserVO(user); UserVO newUser = new UserVO(user);
@ -2560,7 +2564,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
} }
// Create the account // Create the account
return Transaction.execute(new TransactionCallback<AccountVO>() { return Transaction.execute(new TransactionCallback<>() {
@Override @Override
public AccountVO doInTransaction(TransactionStatus status) { public AccountVO doInTransaction(TransactionStatus status) {
AccountVO account = _accountDao.persist(new AccountVO(accountName, domainId, networkDomain, accountType, roleId, uuid)); AccountVO account = _accountDao.persist(new AccountVO(accountName, domainId, networkDomain, accountType, roleId, uuid));
@ -2650,12 +2654,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
long tolerance = Long.parseLong(singleSignOnTolerance); long tolerance = Long.parseLong(singleSignOnTolerance);
String signature = null; String signature = null;
long timestamp = 0L; long timestamp = 0L;
String unsignedRequest = null; String unsignedRequest;
StringBuffer unsignedRequestBuffer = new StringBuffer(); StringBuffer unsignedRequestBuffer = new StringBuffer();
// - build a request string with sorted params, make sure it's all lowercase // - build a request string with sorted params, make sure it's all lowercase
// - sign the request, verify the signature is the same // - sign the request, verify the signature is the same
List<String> parameterNames = new ArrayList<String>(); List<String> parameterNames = new ArrayList<>();
for (Object paramNameObj : requestParameters.keySet()) { for (Object paramNameObj : requestParameters.keySet()) {
parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
@ -2780,7 +2784,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId); UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
boolean authenticated = false; boolean authenticated = false;
HashSet<ActionOnFailedAuthentication> actionsOnFailedAuthenticaion = new HashSet<ActionOnFailedAuthentication>(); HashSet<ActionOnFailedAuthentication> actionsOnFailedAuthenticaion = new HashSet<>();
User.Source userSource = userAccount != null ? userAccount.getSource() : User.Source.UNKNOWN; User.Source userSource = userAccount != null ? userAccount.getSource() : User.Source.UNKNOWN;
for (UserAuthenticator authenticator : _userAuthenticators) { for (UserAuthenticator authenticator : _userAuthenticators) {
final String[] secretCodeArray = (String[])requestParameters.get(ApiConstants.SECRET_CODE); final String[] secretCodeArray = (String[])requestParameters.get(ApiConstants.SECRET_CODE);
@ -2886,7 +2890,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
preventRootDomainAdminAccessToRootAdminKeys(caller, account); preventRootDomainAdminAccessToRootAdminKeys(caller, account);
checkAccess(caller, account); checkAccess(caller, account);
Map<String, String> keys = new HashMap<String, String>(); Map<String, String> keys = new HashMap<>();
keys.put("apikey", user.getApiKey()); keys.put("apikey", user.getApiKey());
keys.put("secretkey", user.getSecretKey()); keys.put("secretkey", user.getSecretKey());
@ -2898,7 +2902,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
} }
} }
return new Pair<Boolean, Map<String, String>>(apiKeyAccess, keys); return new Pair<>(apiKeyAccess, keys);
} }
protected void preventRootDomainAdminAccessToRootAdminKeys(User caller, ControlledEntity account) { protected void preventRootDomainAdminAccessToRootAdminKeys(User caller, ControlledEntity account) {
@ -2999,8 +3003,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
try { try {
UserVO updatedUser = _userDao.createForUpdate(); UserVO updatedUser = _userDao.createForUpdate();
String encodedKey = null; String encodedKey;
Pair<User, Account> userAcct = null; Pair<User, Account> userAcct;
int retryLimit = 10; int retryLimit = 10;
do { do {
// FIXME: what algorithm should we use for API keys? // FIXME: what algorithm should we use for API keys?
@ -3026,9 +3030,9 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
private String createUserSecretKey(long userId) { private String createUserSecretKey(long userId) {
try { try {
UserVO updatedUser = _userDao.createForUpdate(); UserVO updatedUser = _userDao.createForUpdate();
String encodedKey = null; String encodedKey;
int retryLimit = 10; int retryLimit = 10;
UserVO userBySecretKey = null; UserVO userBySecretKey;
do { do {
KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1"); KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
SecretKey key = generator.generateKey(); SecretKey key = generator.generateKey();
@ -3136,8 +3140,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
throw new InvalidParameterValueException("Account and projectId can't be specified together"); throw new InvalidParameterValueException("Account and projectId can't be specified together");
} }
Account userAccount = null; Account userAccount;
Domain domain = null; Domain domain;
if (domainId != null) { if (domainId != null) {
userAccount = _accountDao.findActiveAccount(accountName, domainId); userAccount = _accountDao.findActiveAccount(accountName, domainId);
domain = _domainDao.findById(domainId); domain = _domainDao.findById(domainId);
@ -3262,7 +3266,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Override @Override
public List<String> listAclGroupsByAccount(Long accountId) { public List<String> listAclGroupsByAccount(Long accountId) {
if (_querySelectors == null || _querySelectors.size() == 0) { if (_querySelectors == null || _querySelectors.size() == 0) {
return new ArrayList<String>(); return new ArrayList<>();
} }
QuerySelector qs = _querySelectors.get(0); QuerySelector qs = _querySelectors.get(0);
@ -3522,7 +3526,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
} }
protected UserTwoFactorAuthenticationSetupResponse disableTwoFactorAuthentication(Long userId, Account caller, Account owner) { protected UserTwoFactorAuthenticationSetupResponse disableTwoFactorAuthentication(Long userId, Account caller, Account owner) {
UserVO userVO = null; UserVO userVO;
if (userId != null) { if (userId != null) {
userVO = validateUser(userId); userVO = validateUser(userId);
owner = _accountService.getActiveAccountById(userVO.getAccountId()); owner = _accountService.getActiveAccountById(userVO.getAccountId());

View File

@ -134,8 +134,8 @@ import org.apache.cloudstack.storage.template.VnfTemplateManager;
import org.apache.cloudstack.userdata.UserDataManager; import org.apache.cloudstack.userdata.UserDataManager;
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils; import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
import org.apache.cloudstack.utils.security.ParserUtils; import org.apache.cloudstack.utils.security.ParserUtils;
import org.apache.cloudstack.vm.UnmanagedVMsManager;
import org.apache.cloudstack.vm.schedule.VMScheduleManager; import org.apache.cloudstack.vm.schedule.VMScheduleManager;
import org.apache.cloudstack.vm.UnmanagedVMsManager;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.math.NumberUtils;
@ -2140,7 +2140,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
throw new InvalidParameterValueException("Unable to Scale VM, since disk offering strictness flag is not same for new service offering and old service offering"); throw new InvalidParameterValueException("Unable to Scale VM, since disk offering strictness flag is not same for new service offering and old service offering");
} }
if (currentServiceOffering.getDiskOfferingStrictness() && currentServiceOffering.getDiskOfferingId() != newServiceOffering.getDiskOfferingId()) { if (currentServiceOffering.getDiskOfferingStrictness() && !currentServiceOffering.getDiskOfferingId().equals(newServiceOffering.getDiskOfferingId())) {
throw new InvalidParameterValueException("Unable to Scale VM, since disk offering id associated with the old service offering is not same for new service offering"); throw new InvalidParameterValueException("Unable to Scale VM, since disk offering id associated with the old service offering is not same for new service offering");
} }
@ -4526,7 +4526,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
if (customParameters.containsKey(VmDetailConstants.ROOT_DISK_SIZE)) { if (customParameters.containsKey(VmDetailConstants.ROOT_DISK_SIZE)) {
Long rootDiskSize = rootDiskSizeCustomParam * GiB_TO_BYTES; Long rootDiskSize = NumbersUtil.parseLong(customParameters.get(VmDetailConstants.ROOT_DISK_SIZE), -1);
if (rootDiskSize <= 0) {
throw new InvalidParameterValueException("Root disk size should be a positive number.");
}
rootDiskSize = rootDiskSizeCustomParam * GiB_TO_BYTES;
_volumeService.validateVolumeSizeInBytes(rootDiskSize); _volumeService.validateVolumeSizeInBytes(rootDiskSize);
return rootDiskSize; return rootDiskSize;
} else { } else {

View File

@ -0,0 +1,109 @@
// 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.api.query.dao;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.api.query.vo.SnapshotJoinVO;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@RunWith(MockitoJUnitRunner.class)
public class SnapshotJoinDaoImplTest {
@Spy
@InjectMocks
SnapshotJoinDaoImpl snapshotJoinDao = new SnapshotJoinDaoImpl();
@Mock
SearchCriteria<SnapshotJoinVO> mockSearchCriteria;
@Before
public void setUp() {
SnapshotJoinVO mockSnap = mock(SnapshotJoinVO.class);
SearchBuilder<SnapshotJoinVO> mockSearchBuilder = mock(SearchBuilder.class);
when(mockSearchBuilder.entity()).thenReturn(mockSnap);
doReturn(mockSearchBuilder).when(snapshotJoinDao).createSearchBuilder();
when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
}
@Test
public void testFindById_WithNullZoneId_EmptyResult() {
Long zoneId = null;
long id = 1L;
doReturn(Collections.emptyList()).when(snapshotJoinDao).search(mockSearchCriteria, null);
List<SnapshotJoinVO> result = snapshotJoinDao.findById(zoneId, id);
assertNull(result);
verify(mockSearchCriteria).setParameters("id", id);
verify(mockSearchCriteria, never()).setParameters("zoneId", zoneId);
}
@Test
public void testFindById_WithValidZoneId_EmptyResult() {
Long zoneId = 1L;
long id = 1L;
doReturn(Collections.emptyList()).when(snapshotJoinDao).search(mockSearchCriteria, null);
List<SnapshotJoinVO> result = snapshotJoinDao.findById(zoneId, id);
assertNull(result);
verify(mockSearchCriteria).setParameters("id", id);
verify(mockSearchCriteria).setParameters("zoneId", zoneId);
}
@Test
public void testFindById_WithValidResults() {
Long zoneId = 1L;
long id = 1L;
SnapshotJoinVO snapshot1 = mock(SnapshotJoinVO.class);
when(snapshot1.getSnapshotStorePair()).thenReturn("Primary_1");
SnapshotJoinVO snapshot2 = mock(SnapshotJoinVO.class);
when(snapshot2.getSnapshotStorePair()).thenReturn("Image_1");
doReturn(Arrays.asList(snapshot1, snapshot2)).when(snapshotJoinDao).search(mockSearchCriteria, null);
List<SnapshotJoinVO> result = snapshotJoinDao.findById(zoneId, id);
assertNotNull(result);
assertEquals(1, result.size());
assertEquals("Image_1", result.get(0).getSnapshotStorePair());
verify(mockSearchCriteria).setParameters("id", id);
verify(mockSearchCriteria).setParameters("zoneId", zoneId);
}
@Test
public void testFindById_WithNullResults() {
long id = 1L;
doReturn(null).when(snapshotJoinDao).search(mockSearchCriteria, null);
List<SnapshotJoinVO> result = snapshotJoinDao.findById(null, id);
assertNull(result);
}
}

View File

@ -2038,13 +2038,13 @@ public class VolumeApiServiceImplTest {
when(volumeToAttach.getDiskOfferingId()).thenReturn(1L); when(volumeToAttach.getDiskOfferingId()).thenReturn(1L);
when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(1L), eq(2L), eq(vm), eq(Collections.emptySet()))) when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(1L), eq(2L), eq(vm), eq(Collections.emptySet())))
.thenReturn(pool); .thenReturn(pool);
StoragePool result = volumeApiServiceImpl.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm); StoragePool result = volumeApiServiceImpl.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
Assert.assertNotNull(result); Assert.assertNotNull(result);
Assert.assertEquals(pool, result); Assert.assertEquals(pool, result);
} }
@Test(expected = CloudRuntimeException.class) @Test
public void testGetPoolForAllocatedOrUploadedVolumeForAttach_NoPoolFound_ThrowsException() { public void testGetPoolForAllocatedOrUploadedVolumeForAttach_NoSuitablePoolFound_ReturnsNull() {
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class); VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
UserVmVO vm = Mockito.mock(UserVmVO.class); UserVmVO vm = Mockito.mock(UserVmVO.class);
DataCenterVO zone = mockZone(); DataCenterVO zone = mockZone();
@ -2059,11 +2059,11 @@ public class VolumeApiServiceImplTest {
when(volumeToAttach.getDiskOfferingId()).thenReturn(1L); when(volumeToAttach.getDiskOfferingId()).thenReturn(1L);
when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(1L), eq(2L), eq(vm), eq(Collections.emptySet()))) when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(1L), eq(2L), eq(vm), eq(Collections.emptySet())))
.thenReturn(null); .thenReturn(null);
volumeApiServiceImpl.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm); Assert.assertNull(volumeApiServiceImpl.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm));
} }
@Test @Test
public void testGetPoolForAllocatedOrUploadedVolumeForAttach_NoCluster() { public void testGetSuitablePoolForAllocatedOrUploadedVolumeForAttach_NoCluster() {
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class); VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
UserVmVO vm = Mockito.mock(UserVmVO.class); UserVmVO vm = Mockito.mock(UserVmVO.class);
DataCenterVO zone = mockZone(); DataCenterVO zone = mockZone();
@ -2077,7 +2077,7 @@ public class VolumeApiServiceImplTest {
when(volumeToAttach.getDiskOfferingId()).thenReturn(1L); when(volumeToAttach.getDiskOfferingId()).thenReturn(1L);
when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(null), eq(2L), eq(vm), eq(Collections.emptySet()))) when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(null), eq(2L), eq(vm), eq(Collections.emptySet())))
.thenReturn(pool); .thenReturn(pool);
StoragePool result = volumeApiServiceImpl.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm); StoragePool result = volumeApiServiceImpl.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
Assert.assertNotNull(result); Assert.assertNotNull(result);
Assert.assertEquals(pool, result); Assert.assertEquals(pool, result);
} }
@ -2123,7 +2123,7 @@ public class VolumeApiServiceImplTest {
UserVmVO vm = Mockito.mock(UserVmVO.class); UserVmVO vm = Mockito.mock(UserVmVO.class);
StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class); StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class);
Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl) Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl)
.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm); .getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
VolumeInfo newVolumeOnPrimaryStorage = Mockito.mock(VolumeInfo.class); VolumeInfo newVolumeOnPrimaryStorage = Mockito.mock(VolumeInfo.class);
try { try {
Mockito.when(volumeOrchestrationService.createVolumeOnPrimaryStorage( Mockito.when(volumeOrchestrationService.createVolumeOnPrimaryStorage(
@ -2134,7 +2134,7 @@ public class VolumeApiServiceImplTest {
} }
VolumeInfo result = volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null); VolumeInfo result = volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null);
Assert.assertSame(newVolumeOnPrimaryStorage, result); Assert.assertSame(newVolumeOnPrimaryStorage, result);
verify(volumeApiServiceImpl).getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm); verify(volumeApiServiceImpl).getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
} }
@Test(expected = InvalidParameterValueException.class) @Test(expected = InvalidParameterValueException.class)
@ -2145,7 +2145,7 @@ public class VolumeApiServiceImplTest {
StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class); StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class);
when(destPrimaryStorage.getPoolType()).thenReturn(Storage.StoragePoolType.PowerFlex); when(destPrimaryStorage.getPoolType()).thenReturn(Storage.StoragePoolType.PowerFlex);
Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl) Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl)
.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm); .getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null); volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null);
} }
@ -2157,7 +2157,7 @@ public class VolumeApiServiceImplTest {
StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class); StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class);
Mockito.when(destPrimaryStorage.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); Mockito.when(destPrimaryStorage.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem);
Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl) Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl)
.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm); .getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
try { try {
Mockito.when(volumeOrchestrationService.createVolumeOnPrimaryStorage(vm, volumeToAttach, vm.getHypervisorType(), destPrimaryStorage)) Mockito.when(volumeOrchestrationService.createVolumeOnPrimaryStorage(vm, volumeToAttach, vm.getHypervisorType(), destPrimaryStorage))
.thenThrow(new NoTransitionException("Mocked exception")); .thenThrow(new NoTransitionException("Mocked exception"));
@ -2169,4 +2169,35 @@ public class VolumeApiServiceImplTest {
); );
Assert.assertTrue(exception.getMessage().contains("Failed to create volume on primary storage")); Assert.assertTrue(exception.getMessage().contains("Failed to create volume on primary storage"));
} }
@Test
public void testCreateVolumeOnSecondaryForAttachIfNeeded_NoSuitablePool_ThrowsException() {
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
Mockito.when(volumeToAttach.getState()).thenReturn(Volume.State.Uploaded);
UserVmVO vm = Mockito.mock(UserVmVO.class);
Mockito.doReturn(null).when(volumeApiServiceImpl)
.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class, () ->
volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null)
);
Assert.assertTrue(exception.getMessage().startsWith("Failed to find a primary storage for volume"));
}
@Test
public void testCreateVolumeOnSecondaryForAttachIfNeeded_NoSuitablePool_ReturnSameVolumeInfo() {
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
Mockito.when(volumeToAttach.getState()).thenReturn(Volume.State.Allocated);
UserVmVO vm = Mockito.mock(UserVmVO.class);
Mockito.when(vm.getState()).thenReturn(State.Stopped);
Mockito.doReturn(null).when(volumeApiServiceImpl)
.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
VolumeInfo result = volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null);
Assert.assertSame(volumeToAttach, result);
try {
Mockito.verify(volumeOrchestrationService, Mockito.never()).createVolumeOnPrimaryStorage(Mockito.any(),
Mockito.any(), Mockito.any(), Mockito.any());
} catch (NoTransitionException e) {
Assert.fail();
}
}
} }

View File

@ -40,11 +40,6 @@ public class LocalNfsSecondaryStorageResource extends NfsSecondaryStorageResourc
this._inSystemVM = false; this._inSystemVM = false;
} }
@Override
public void setParentPath(String path) {
this._parent = path;
}
@Override @Override
public Answer executeRequest(Command cmd) { public Answer executeRequest(Command cmd) {
return super.executeRequest(cmd); return super.executeRequest(cmd);
@ -57,7 +52,7 @@ public class LocalNfsSecondaryStorageResource extends NfsSecondaryStorageResourc
String dir = mountUri(uri, nfsVersion); String dir = mountUri(uri, nfsVersion);
return _parent + "/" + dir; return _parent + "/" + dir;
} catch (Exception e) { } catch (Exception e) {
String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString(); String msg = "GetRootDir for " + secUrl + " failed due to " + e;
logger.error(msg, e); logger.error(msg, e);
throw new CloudRuntimeException(msg); throw new CloudRuntimeException(msg);
} }
@ -75,14 +70,14 @@ public class LocalNfsSecondaryStorageResource extends NfsSecondaryStorageResourc
// Change permissions for the mountpoint - seems to bypass authentication // Change permissions for the mountpoint - seems to bypass authentication
Script script = new Script(true, "chmod", _timeout, logger); Script script = new Script(true, "chmod", _timeout, logger);
script.add("777", localRootPath); script.add("1777", localRootPath);
String result = script.execute(); String result = script.execute();
if (result != null) { if (result != null) {
String errMsg = "Unable to set permissions for " + localRootPath + " due to " + result; String errMsg = "Unable to set permissions for " + localRootPath + " due to " + result;
logger.error(errMsg); logger.error(errMsg);
throw new CloudRuntimeException(errMsg); throw new CloudRuntimeException(errMsg);
} }
logger.debug("Successfully set 777 permission for " + localRootPath); logger.debug("Successfully set 1777 permission for " + localRootPath);
// XXX: Adding the check for creation of snapshots dir here. Might have // XXX: Adding the check for creation of snapshots dir here. Might have
// to move it somewhere more logical later. // to move it somewhere more logical later.

View File

@ -19,15 +19,16 @@ import logging
from netaddr import IPAddress, IPNetwork from netaddr import IPAddress, IPNetwork
import subprocess import subprocess
import time import time
from . import CsHelper from . import CsHelper
from .CsDatabag import CsDataBag from .CsDatabag import CsDataBag
from .CsApp import CsApache, CsDnsmasq, CsPasswdSvc from .CsApp import CsApache, CsDnsmasq, CsPasswdSvc
from .CsRoute import CsRoute from .CsRoute import CsRoute
from .CsRule import CsRule from .CsRule import CsRule
from .CsStaticRoutes import CsStaticRoutes
VRRP_TYPES = ['guest'] VRRP_TYPES = ['guest']
class CsAddress(CsDataBag): class CsAddress(CsDataBag):
def compare(self): def compare(self):
@ -556,8 +557,10 @@ class CsIP:
(self.dev, guestNetworkCidr, self.address['gateway'], self.dev)]) (self.dev, guestNetworkCidr, self.address['gateway'], self.dev)])
if self.is_private_gateway(): if self.is_private_gateway():
self.fw.append(["filter", "", "-A FORWARD -d %s -o %s -j ACL_INBOUND_%s" % self.fw.append(["filter", "front", "-A FORWARD -d %s -o %s -j ACL_INBOUND_%s" %
(self.address['network'], self.dev, self.dev)]) (self.address['network'], self.dev, self.dev)])
self.fw.append(["filter", "front", "-A FORWARD -d %s -o %s -m state --state RELATED,ESTABLISHED -j ACCEPT" %
(self.address['network'], self.dev)])
self.fw.append(["filter", "", "-A ACL_INBOUND_%s -j DROP" % self.dev]) self.fw.append(["filter", "", "-A ACL_INBOUND_%s -j DROP" % self.dev])
self.fw.append(["mangle", "", self.fw.append(["mangle", "",
"-A PREROUTING -m state --state NEW -i %s -s %s ! -d %s/32 -j ACL_OUTBOUND_%s" % "-A PREROUTING -m state --state NEW -i %s -s %s ! -d %s/32 -j ACL_OUTBOUND_%s" %
@ -565,6 +568,23 @@ class CsIP:
self.fw.append(["mangle", "front", self.fw.append(["mangle", "front",
"-A PREROUTING -s %s -d %s -m state --state NEW -j MARK --set-xmark %s/0xffffffff" % "-A PREROUTING -s %s -d %s -m state --state NEW -j MARK --set-xmark %s/0xffffffff" %
(self.cl.get_vpccidr(), self.address['network'], hex(100 + int(self.dev[3:])))]) (self.cl.get_vpccidr(), self.address['network'], hex(100 + int(self.dev[3:])))])
static_routes = CsStaticRoutes("staticroutes", self.config)
if static_routes:
for item in static_routes.get_bag():
if item == "id":
continue
static_route = static_routes.get_bag()[item]
if static_route['ip_address'] == self.address['public_ip'] and not static_route['revoke']:
self.fw.append(["mangle", "",
"-A PREROUTING -m state --state NEW -i %s -s %s ! -d %s/32 -j ACL_OUTBOUND_%s" %
(self.dev, static_route['network'], static_route['ip_address'], self.dev)])
self.fw.append(["filter", "front", "-A FORWARD -d %s -o %s -j ACL_INBOUND_%s" %
(static_route['network'], self.dev, self.dev)])
self.fw.append(["filter", "front",
"-A FORWARD -d %s -o %s -m state --state RELATED,ESTABLISHED -j ACCEPT" %
(static_route['network'], self.dev)])
if self.address["source_nat"]: if self.address["source_nat"]:
self.fw.append(["nat", "front", self.fw.append(["nat", "front",
"-A POSTROUTING -o %s -j SNAT --to-source %s" % "-A POSTROUTING -o %s -j SNAT --to-source %s" %

View File

@ -139,8 +139,7 @@ class CsDhcp(CsDataBag):
# Listen Address # Listen Address
if self.cl.is_redundant(): if self.cl.is_redundant():
listen_address.append(gateway) listen_address.append(gateway)
else: listen_address.append(ip)
listen_address.append(ip)
# Add localized "data-server" records in /etc/hosts for VPC routers # Add localized "data-server" records in /etc/hosts for VPC routers
if self.config.is_vpc() or self.config.is_router(): if self.config.is_vpc() or self.config.is_router():
self.add_host(gateway, "%s data-server" % CsHelper.get_hostname()) self.add_host(gateway, "%s data-server" % CsHelper.get_hostname())

View File

@ -74,6 +74,7 @@ class TestData(object):
"listApis": "allow", "listApis": "allow",
"listAccounts": "allow", "listAccounts": "allow",
"listClusters": "deny", "listClusters": "deny",
"*VmwareDc*": "allow",
"*VM*": "allow", "*VM*": "allow",
"*Host*": "deny" "*Host*": "deny"
} }

View File

@ -3263,6 +3263,7 @@
"message.license.agreements.not.accepted": "License agreements not accepted.", "message.license.agreements.not.accepted": "License agreements not accepted.",
"message.linstor.resourcegroup.description": "Linstor resource group to use for primary storage.", "message.linstor.resourcegroup.description": "Linstor resource group to use for primary storage.",
"message.list.zone.vmware.datacenter.empty": "No VMware Datacenter exists in the selected Zone", "message.list.zone.vmware.datacenter.empty": "No VMware Datacenter exists in the selected Zone",
"message.list.zone.vmware.hosts.empty": "No VMware hosts were found in the selected Datacenter",
"message.listnsp.not.return.providerid": "error: listNetworkServiceProviders API doesn't return VirtualRouter provider ID.", "message.listnsp.not.return.providerid": "error: listNetworkServiceProviders API doesn't return VirtualRouter provider ID.",
"message.load.host.failed": "Failed to load hosts.", "message.load.host.failed": "Failed to load hosts.",
"message.loadbalancer.stickypolicy.configuration": "Customize the load balancer stickiness policy:", "message.loadbalancer.stickypolicy.configuration": "Customize the load balancer stickiness policy:",

View File

@ -17,6 +17,7 @@
import { shallowRef, defineAsyncComponent } from 'vue' import { shallowRef, defineAsyncComponent } from 'vue'
import store from '@/store' import store from '@/store'
import { isZoneCreated } from '@/utils/zone'
export default { export default {
name: 'compute', name: 'compute',
@ -100,6 +101,7 @@ export default {
label: 'label.vm.add', label: 'label.vm.add',
docHelp: 'adminguide/virtual_machines.html#creating-vms', docHelp: 'adminguide/virtual_machines.html#creating-vms',
listView: true, listView: true,
show: isZoneCreated,
component: () => import('@/views/compute/DeployVM.vue') component: () => import('@/views/compute/DeployVM.vue')
}, },
{ {
@ -225,6 +227,10 @@ export default {
args: ['virtualmachineid', 'backupofferingid'], args: ['virtualmachineid', 'backupofferingid'],
show: (record) => { return !record.backupofferingid }, show: (record) => { return !record.backupofferingid },
mapping: { mapping: {
backupofferingid: {
api: 'listBackupOfferings',
params: (record) => { return { zoneid: record.zoneid } }
},
virtualmachineid: { virtualmachineid: {
value: (record, params) => { return record.id } value: (record, params) => { return record.id }
} }
@ -569,6 +575,7 @@ export default {
docHelp: 'plugins/cloudstack-kubernetes-service.html#creating-a-new-kubernetes-cluster', docHelp: 'plugins/cloudstack-kubernetes-service.html#creating-a-new-kubernetes-cluster',
listView: true, listView: true,
popup: true, popup: true,
show: isZoneCreated,
component: shallowRef(defineAsyncComponent(() => import('@/views/compute/CreateKubernetesCluster.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/compute/CreateKubernetesCluster.vue')))
}, },
{ {
@ -697,6 +704,7 @@ export default {
icon: 'plus-outlined', icon: 'plus-outlined',
label: 'label.new.autoscale.vmgroup', label: 'label.new.autoscale.vmgroup',
listView: true, listView: true,
show: isZoneCreated,
component: () => import('@/views/compute/CreateAutoScaleVmGroup.vue') component: () => import('@/views/compute/CreateAutoScaleVmGroup.vue')
}, },
{ {
@ -787,6 +795,7 @@ export default {
icon: 'plus-outlined', icon: 'plus-outlined',
label: 'label.new.instance.group', label: 'label.new.instance.group',
listView: true, listView: true,
show: isZoneCreated,
args: ['name'] args: ['name']
}, },
{ {

View File

@ -17,6 +17,7 @@
import { shallowRef, defineAsyncComponent } from 'vue' import { shallowRef, defineAsyncComponent } from 'vue'
import store from '@/store' import store from '@/store'
import { isZoneCreated } from '@/utils/zone'
export default { export default {
name: 'image', name: 'image',
@ -110,16 +111,17 @@ export default {
docHelp: 'adminguide/templates.html#uploading-templates-from-a-remote-http-server', docHelp: 'adminguide/templates.html#uploading-templates-from-a-remote-http-server',
listView: true, listView: true,
popup: true, popup: true,
show: isZoneCreated,
component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadTemplate.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadTemplate.vue')))
}, },
{ {
api: 'registerTemplate', api: 'registerTemplate',
icon: 'cloud-upload-outlined', icon: 'cloud-upload-outlined',
label: 'label.upload.template.from.local', label: 'label.upload.template.from.local',
show: () => { return 'getUploadParamsForTemplate' in store.getters.apis },
docHelp: 'adminguide/templates.html#uploading-templates-and-isos-from-a-local-computer', docHelp: 'adminguide/templates.html#uploading-templates-and-isos-from-a-local-computer',
listView: true, listView: true,
popup: true, popup: true,
show: () => { return isZoneCreated() && 'getUploadParamsForTemplate' in store.getters.apis },
component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadTemplate.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadTemplate.vue')))
}, },
{ {
@ -270,13 +272,14 @@ export default {
docHelp: 'adminguide/templates.html#id10', docHelp: 'adminguide/templates.html#id10',
listView: true, listView: true,
popup: true, popup: true,
show: isZoneCreated,
component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadIso.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadIso.vue')))
}, },
{ {
api: 'registerIso', api: 'registerIso',
icon: 'cloud-upload-outlined', icon: 'cloud-upload-outlined',
label: 'label.upload.iso.from.local', label: 'label.upload.iso.from.local',
show: () => { return 'getUploadParamsForIso' in store.getters.apis }, show: () => { return isZoneCreated() && 'getUploadParamsForIso' in store.getters.apis },
docHelp: 'adminguide/templates.html#id10', docHelp: 'adminguide/templates.html#id10',
listView: true, listView: true,
popup: true, popup: true,
@ -389,6 +392,7 @@ export default {
label: 'label.kubernetes.version.add', label: 'label.kubernetes.version.add',
listView: true, listView: true,
popup: true, popup: true,
show: isZoneCreated,
component: shallowRef(defineAsyncComponent(() => import('@/views/image/AddKubernetesSupportedVersion.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/image/AddKubernetesSupportedVersion.vue')))
}, },
{ {

View File

@ -19,6 +19,7 @@ import { shallowRef, defineAsyncComponent } from 'vue'
import store from '@/store' import store from '@/store'
import tungsten from '@/assets/icons/tungsten.svg?inline' import tungsten from '@/assets/icons/tungsten.svg?inline'
import { isAdmin } from '@/role' import { isAdmin } from '@/role'
import { isZoneCreated } from '@/utils/zone'
export default { export default {
name: 'network', name: 'network',
@ -123,7 +124,7 @@ export default {
listView: true, listView: true,
popup: true, popup: true,
show: () => { show: () => {
if (!store.getters.zones || store.getters.zones.length === 0) { if (!isZoneCreated()) {
return false return false
} }
const AdvancedZones = store.getters.zones.filter(zone => zone.networktype === 'Advanced') const AdvancedZones = store.getters.zones.filter(zone => zone.networktype === 'Advanced')
@ -245,6 +246,7 @@ export default {
icon: 'plus-outlined', icon: 'plus-outlined',
label: 'label.add.vpc', label: 'label.add.vpc',
docHelp: 'adminguide/networking_and_traffic.html#adding-a-virtual-private-cloud', docHelp: 'adminguide/networking_and_traffic.html#adding-a-virtual-private-cloud',
show: isZoneCreated,
listView: true, listView: true,
popup: true, popup: true,
component: shallowRef(defineAsyncComponent(() => import('@/views/network/CreateVpc.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/network/CreateVpc.vue')))
@ -306,7 +308,7 @@ export default {
component: shallowRef(defineAsyncComponent(() => import('@/views/network/IngressEgressRuleConfigure.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/network/IngressEgressRuleConfigure.vue')))
}], }],
show: () => { show: () => {
if (!store.getters.zones || store.getters.zones.length === 0) { if (!isZoneCreated()) {
return false return false
} }
const listZoneHaveSGEnabled = store.getters.zones.filter(zone => zone.securitygroupsenabled === true) const listZoneHaveSGEnabled = store.getters.zones.filter(zone => zone.securitygroupsenabled === true)
@ -394,6 +396,7 @@ export default {
label: 'label.vnf.appliance.add', label: 'label.vnf.appliance.add',
docHelp: 'adminguide/networking/vnf_templates_appliances.html#deploying-vnf-appliances', docHelp: 'adminguide/networking/vnf_templates_appliances.html#deploying-vnf-appliances',
listView: true, listView: true,
show: isZoneCreated,
component: () => import('@/views/compute/DeployVnfAppliance.vue') component: () => import('@/views/compute/DeployVnfAppliance.vue')
}, },
{ {
@ -941,6 +944,7 @@ export default {
label: 'label.add.vpn.gateway', label: 'label.add.vpn.gateway',
docHelp: 'adminguide/networking_and_traffic.html#creating-a-vpn-gateway-for-the-vpc', docHelp: 'adminguide/networking_and_traffic.html#creating-a-vpn-gateway-for-the-vpc',
listView: true, listView: true,
show: isZoneCreated,
args: ['vpcid'] args: ['vpcid']
}, },
{ {
@ -1116,6 +1120,7 @@ export default {
icon: 'plus-outlined', icon: 'plus-outlined',
label: 'label.add.vpn.user', label: 'label.add.vpn.user',
listView: true, listView: true,
show: isZoneCreated,
args: (record, store) => { args: (record, store) => {
if (store.userInfo.roletype === 'User') { if (store.userInfo.roletype === 'User') {
return ['username', 'password'] return ['username', 'password']
@ -1195,6 +1200,7 @@ export default {
docHelp: 'adminguide/networking_and_traffic.html#creating-and-updating-a-vpn-customer-gateway', docHelp: 'adminguide/networking_and_traffic.html#creating-and-updating-a-vpn-customer-gateway',
listView: true, listView: true,
popup: true, popup: true,
show: isZoneCreated,
component: shallowRef(defineAsyncComponent(() => import('@/views/network/CreateVpnCustomerGateway.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/network/CreateVpnCustomerGateway.vue')))
}, },
{ {
@ -1384,12 +1390,7 @@ export default {
component: shallowRef(defineAsyncComponent(() => import('@/views/network/GuestVlanNetworksTab.vue'))), component: shallowRef(defineAsyncComponent(() => import('@/views/network/GuestVlanNetworksTab.vue'))),
show: (record) => { return (record.allocationstate === 'Allocated') } show: (record) => { return (record.allocationstate === 'Allocated') }
}], }],
show: () => { show: isZoneCreated
if (!store.getters.zones || store.getters.zones.length === 0) {
return false
}
return true
}
} }
] ]
} }

View File

@ -17,6 +17,7 @@
import { shallowRef, defineAsyncComponent } from 'vue' import { shallowRef, defineAsyncComponent } from 'vue'
import store from '@/store' import store from '@/store'
import { isZoneCreated } from '@/utils/zone'
export default { export default {
name: 'storage', name: 'storage',
@ -103,6 +104,7 @@ export default {
icon: 'plus-outlined', icon: 'plus-outlined',
docHelp: 'adminguide/storage.html#creating-a-new-volume', docHelp: 'adminguide/storage.html#creating-a-new-volume',
label: 'label.action.create.volume', label: 'label.action.create.volume',
show: isZoneCreated,
listView: true, listView: true,
popup: true, popup: true,
component: shallowRef(defineAsyncComponent(() => import('@/views/storage/CreateVolume.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/storage/CreateVolume.vue')))
@ -112,7 +114,7 @@ export default {
icon: 'cloud-upload-outlined', icon: 'cloud-upload-outlined',
docHelp: 'adminguide/storage.html#uploading-an-existing-volume-to-a-virtual-machine', docHelp: 'adminguide/storage.html#uploading-an-existing-volume-to-a-virtual-machine',
label: 'label.upload.volume.from.local', label: 'label.upload.volume.from.local',
show: () => { return 'getUploadParamsForVolume' in store.getters.apis }, show: () => { return isZoneCreated() && 'getUploadParamsForVolume' in store.getters.apis },
listView: true, listView: true,
popup: true, popup: true,
component: shallowRef(defineAsyncComponent(() => import('@/views/storage/UploadLocalVolume.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/storage/UploadLocalVolume.vue')))
@ -122,6 +124,7 @@ export default {
icon: 'link-outlined', icon: 'link-outlined',
docHelp: 'adminguide/storage.html#uploading-an-existing-volume-to-a-virtual-machine', docHelp: 'adminguide/storage.html#uploading-an-existing-volume-to-a-virtual-machine',
label: 'label.upload.volume.from.url', label: 'label.upload.volume.from.url',
show: isZoneCreated,
listView: true, listView: true,
popup: true, popup: true,
component: shallowRef(defineAsyncComponent(() => import('@/views/storage/UploadVolume.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/storage/UploadVolume.vue')))

25
ui/src/utils/zone.js Normal file
View File

@ -0,0 +1,25 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
import store from '@/store'
export function isZoneCreated () {
if (!store.getters.zones || store.getters.zones.length === 0) {
return false
}
return true
}

View File

@ -793,6 +793,10 @@ export default {
if (this.scopeType === 'domain') { if (this.scopeType === 'domain') {
params.domainid = this.selectedDomain.id params.domainid = this.selectedDomain.id
} }
console.log(params?.tags?.length === 0)
if (!params?.tags || params.tags.length === 0) {
params.istagged = false
}
this.handleNetworkOfferingChange(null) this.handleNetworkOfferingChange(null)
this.networkOfferings = [] this.networkOfferings = []
api('listNetworkOfferings', params).then(json => { api('listNetworkOfferings', params).then(json => {

View File

@ -1198,6 +1198,7 @@ export default {
} else { } else {
params.existingvcenterid = this.selectedVmwareVcenter.existingvcenterid params.existingvcenterid = this.selectedVmwareVcenter.existingvcenterid
} }
params.host = this.selectedVmwareVcenter.host
} }
api(apiName, params).then(json => { api(apiName, params).then(json => {

View File

@ -89,6 +89,7 @@
<a-input <a-input
v-model:value="vcenter" v-model:value="vcenter"
:placeholder="apiParams.vcenter.description" :placeholder="apiParams.vcenter.description"
@change="onSelectExternalVmwareDatacenter"
/> />
</a-form-item> </a-form-item>
<a-form-item ref="datacenter" name="datacenter"> <a-form-item ref="datacenter" name="datacenter">
@ -98,6 +99,7 @@
<a-input <a-input
v-model:value="datacenter" v-model:value="datacenter"
:placeholder="apiParams.datacentername.description" :placeholder="apiParams.datacentername.description"
@change="onSelectExternalVmwareDatacenter"
/> />
</a-form-item> </a-form-item>
<a-form-item ref="username" name="username"> <a-form-item ref="username" name="username">
@ -107,6 +109,7 @@
<a-input <a-input
v-model:value="username" v-model:value="username"
:placeholder="apiParams.username.description" :placeholder="apiParams.username.description"
@change="onSelectExternalVmwareDatacenter"
/> />
</a-form-item> </a-form-item>
<a-form-item ref="password" name="password"> <a-form-item ref="password" name="password">
@ -116,14 +119,36 @@
<a-input-password <a-input-password
v-model:value="password" v-model:value="password"
:placeholder="apiParams.password.description" :placeholder="apiParams.password.description"
@change="onSelectExternalVmwareDatacenter"
/> />
</a-form-item> </a-form-item>
</div> </div>
<div
v-if="selectedExistingVcenterId || (vcenterSelectedOption === 'new')">
<a-form-item :label="$t('label.vcenter.host')" ref="host" name="host" v-if="hosts.length > 0">
<a-select
v-model:value="form.host"
:loading="loading"
optionFilterProp="label"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:placeholder="$t('label.vcenter.host')"
@change="onSelectExistingVmwareHost">
<a-select-option v-for="opt in hosts" :key="opt.name">
{{ 'ESXi: ' + opt.name }}
</a-select-option>
</a-select>
</a-form-item>
<div v-else>
{{ $t('message.list.zone.vmware.hosts.empty') }}
</div>
</div>
<div class="card-footer"> <div class="card-footer">
<a-button <a-button
v-if="vcenterSelectedOption == 'existing' || vcenterSelectedOption == 'new'" v-if="vcenterSelectedOption == 'existing' || vcenterSelectedOption == 'new'"
:disabled="(vcenterSelectedOption === 'new' && (vcenter === '' || datacentername === '' || username === '' || password === '')) || :disabled="(vcenterSelectedOption === 'new' && (vcenter === '' || datacentername === '' || username === '' || password === '')) ||
(vcenterSelectedOption === 'existing' && selectedExistingVcenterId === '')" (vcenterSelectedOption === 'existing' && selectedExistingVcenterId === '') && host === ''"
:loading="loading" :loading="loading"
type="primary" type="primary"
@click="listVmwareDatacenterVms">{{ $t('label.list.vmware.vcenter.vms') }}</a-button> @click="listVmwareDatacenterVms">{{ $t('label.list.vmware.vcenter.vms') }}</a-button>
@ -154,6 +179,8 @@ export default {
zones: {}, zones: {},
vcenterSelectedOption: '', vcenterSelectedOption: '',
existingvcenter: [], existingvcenter: [],
hosts: [],
selectedHost: '',
selectedExistingVcenterId: '', selectedExistingVcenterId: '',
selectedPoweredOnVm: false, selectedPoweredOnVm: false,
vmwareDcVms: [], vmwareDcVms: [],
@ -217,6 +244,7 @@ export default {
} else { } else {
params.existingvcenterid = this.selectedExistingVcenterId params.existingvcenterid = this.selectedExistingVcenterId
} }
params.host = this.selectedHost
api('listVmwareDcVms', params).then(json => { api('listVmwareDcVms', params).then(json => {
const obj = { const obj = {
params: params, params: params,
@ -246,8 +274,29 @@ export default {
listZoneVmwareDcs () { listZoneVmwareDcs () {
this.loading = true this.loading = true
api('listVmwareDcs', { zoneid: this.sourcezoneid }).then(response => { api('listVmwareDcs', { zoneid: this.sourcezoneid }).then(response => {
if (response.listvmwaredcsresponse.VMwareDC && response.listvmwaredcsresponse.VMwareDC.length > 0) { if (response.listvmwaredcsresponse.vmwaredc && response.listvmwaredcsresponse.vmwaredc.length > 0) {
this.existingvcenter = response.listvmwaredcsresponse.VMwareDC this.existingvcenter = response.listvmwaredcsresponse.vmwaredc
}
}).catch(error => {
this.$notifyError(error)
}).finally(() => {
this.loading = false
})
},
listZoneVmwareDcHosts () {
this.loading = true
const params = {}
if (this.vcenterSelectedOption === 'new') {
params.datacentername = this.datacenter
params.vcenter = this.vcenter
params.username = this.username
params.password = this.password
} else {
params.existingvcenterid = this.selectedExistingVcenterId
}
api('listVmwareDcHosts', params).then(response => {
if (response.listvmwaredchostsresponse.host && response.listvmwaredchostsresponse.host.length > 0) {
this.hosts = response.listvmwaredchostsresponse.host
} }
}).catch(error => { }).catch(error => {
this.$notifyError(error) this.$notifyError(error)
@ -257,6 +306,15 @@ export default {
}, },
onSelectExistingVmwareDatacenter (value) { onSelectExistingVmwareDatacenter (value) {
this.selectedExistingVcenterId = value this.selectedExistingVcenterId = value
this.listZoneVmwareDcHosts()
},
onSelectExternalVmwareDatacenter (value) {
if (this.vcenterSelectedOption === 'new' && !(this.vcenter === '' || this.datacentername === '' || this.username === '' || this.password === '')) {
this.listZoneVmwareDcHosts()
}
},
onSelectExistingVmwareHost (value) {
this.selectedHost = value
}, },
onVcenterTypeChange () { onVcenterTypeChange () {
this.$emit('onVcenterTypeChanged', this.vcenterSelectedOption) this.$emit('onVcenterTypeChanged', this.vcenterSelectedOption)

View File

@ -19,14 +19,25 @@ package com.cloud.hypervisor.vmware.mo;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import com.cloud.hypervisor.vmware.util.VmwareHelper;
import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.utils.Pair;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
import com.vmware.vim25.CustomFieldDef; import com.vmware.vim25.CustomFieldDef;
import com.vmware.vim25.CustomFieldStringValue; import com.vmware.vim25.CustomFieldStringValue;
import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.InvalidPropertyFaultMsg;
import com.vmware.vim25.RuntimeFaultFaultMsg;
import com.vmware.vim25.ObjectContent;
import com.vmware.vim25.RetrieveResult;
import com.cloud.hypervisor.vmware.util.VmwareContext; import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class BaseMO { public class BaseMO {
protected Logger logger = LogManager.getLogger(getClass()); protected static Logger logger = LogManager.getLogger(BaseMO.class);
protected VmwareContext _context; protected VmwareContext _context;
protected ManagedObjectReference _mor; protected ManagedObjectReference _mor;
@ -51,6 +62,15 @@ public class BaseMO {
_mor.setValue(morValue); _mor.setValue(morValue);
} }
protected static Pair<String, List<ObjectContent>> createReturnObjectPair(RetrieveResult result) {
if (logger.isDebugEnabled()) {
logger.debug("vmware result : {} ", ReflectionToStringBuilderUtils.reflectCollection(result));
}
String tokenForRetrievingNewResults = result.getToken();
List<ObjectContent> listOfObjects = result.getObjects();
return new Pair<>(tokenForRetrievingNewResults, listOfObjects);
}
public VmwareContext getContext() { public VmwareContext getContext() {
return _context; return _context;
} }
@ -61,12 +81,12 @@ public class BaseMO {
} }
public ManagedObjectReference getParentMor() throws Exception { public ManagedObjectReference getParentMor() throws Exception {
return (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "parent"); return _context.getVimClient().getDynamicProperty(_mor, "parent");
} }
public String getName() throws Exception { public String getName() throws Exception {
if (_name == null) if (_name == null)
_name = (String)_context.getVimClient().getDynamicProperty(_mor, "name"); _name = _context.getVimClient().getDynamicProperty(_mor, "name");
return _name; return _name;
} }
@ -83,7 +103,7 @@ public class BaseMO {
_context.waitForTaskProgressDone(morTask); _context.waitForTaskProgressDone(morTask);
return true; return true;
} else { } else {
logger.error("VMware destroy_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask)); logger.error("VMware destroy_Task failed due to {}", TaskMO.getTaskFailureInfo(_context, morTask));
} }
return false; return false;
} }
@ -100,7 +120,7 @@ public class BaseMO {
_context.waitForTaskProgressDone(morTask); _context.waitForTaskProgressDone(morTask);
return true; return true;
} else { } else {
logger.error("VMware rename_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask)); logger.error("VMware rename_Task failed due to {}", TaskMO.getTaskFailureInfo(_context, morTask));
} }
return false; return false;
} }
@ -131,18 +151,18 @@ public class BaseMO {
if (key == 0) if (key == 0)
return null; return null;
CustomFieldStringValue cfValue = (CustomFieldStringValue)_context.getVimClient().getDynamicProperty(getMor(), String.format("value[%d]", key)); CustomFieldStringValue cfValue = _context.getVimClient().getDynamicProperty(getMor(), String.format("value[%d]", key));
if (cfValue != null) if (cfValue != null)
return cfValue.getValue(); return cfValue.getValue();
return null; return null;
} }
public int getCustomFieldKey(String fieldName) throws Exception { public int getCustomFieldKey(String fieldName) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
return getCustomFieldKey(getMor().getType(), fieldName); return getCustomFieldKey(getMor().getType(), fieldName);
} }
public int getCustomFieldKey(String morType, String fieldName) throws Exception { public int getCustomFieldKey(String morType, String fieldName) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
assert (morType != null); assert (morType != null);
ManagedObjectReference cfmMor = _context.getServiceContent().getCustomFieldsManager(); ManagedObjectReference cfmMor = _context.getServiceContent().getCustomFieldsManager();
@ -154,4 +174,30 @@ public class BaseMO {
return cfmMo.getCustomFieldKey(morType, fieldName); return cfmMo.getCustomFieldKey(morType, fieldName);
} }
protected Pair<String, List<ObjectContent>> retrieveNextSetOfProperties(String tokenForPriorQuery) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
RetrieveResult result = _context.getService().continueRetrievePropertiesEx(_context.getPropertyCollector(), tokenForPriorQuery);
return BaseMO.createReturnObjectPair(result);
}
protected void objectContentToUnmanagedInstanceTO(Pair<String, List<ObjectContent>> objectContents, List<UnmanagedInstanceTO> vms) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
List<ObjectContent> ocs = objectContents.second();
if (ocs != null) {
for (ObjectContent oc : ocs) {
ManagedObjectReference vmMor = oc.getObj();
if (vmMor != null) {
VirtualMachineMO vmMo = new VirtualMachineMO(_context, vmMor);
try {
if (!vmMo.isTemplate()) {
HostMO hostMO = vmMo.getRunningHost();
UnmanagedInstanceTO unmanagedInstance = VmwareHelper.getUnmanagedInstance(hostMO, vmMo);
vms.add(unmanagedInstance);
}
} catch (Exception e) {
logger.debug("Unexpected error checking unmanaged instance {}, excluding it: {}", vmMo.getVmName(), e.getMessage(), e);
}
}
}
}
}
} }

View File

@ -16,11 +16,14 @@
// under the License. // under the License.
package com.cloud.hypervisor.vmware.mo; package com.cloud.hypervisor.vmware.mo;
import java.lang.reflect.InvocationTargetException;
import java.util.List; import java.util.List;
import com.vmware.vim25.CustomFieldDef; import com.vmware.vim25.CustomFieldDef;
import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.PrivilegePolicyDef; import com.vmware.vim25.PrivilegePolicyDef;
import com.vmware.vim25.InvalidPropertyFaultMsg;
import com.vmware.vim25.RuntimeFaultFaultMsg;
import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.hypervisor.vmware.util.VmwareContext;
@ -50,12 +53,12 @@ public class CustomFieldsManagerMO extends BaseMO {
_context.getService().setField(getMor(), morEntity, key, value); _context.getService().setField(getMor(), morEntity, key, value);
} }
public List<CustomFieldDef> getFields() throws Exception { public List<CustomFieldDef> getFields() throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
return _context.getVimClient().getDynamicProperty(getMor(), "field"); return _context.getVimClient().getDynamicProperty(getMor(), "field");
} }
@Override @Override
public int getCustomFieldKey(String morType, String fieldName) throws Exception { public int getCustomFieldKey(String morType, String fieldName) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
List<CustomFieldDef> fields = getFields(); List<CustomFieldDef> fields = getFields();
if (fields != null) { if (fields != null) {
for (CustomFieldDef field : fields) { for (CustomFieldDef field : fields) {

View File

@ -17,11 +17,12 @@
package com.cloud.hypervisor.vmware.mo; package com.cloud.hypervisor.vmware.mo;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import com.cloud.hypervisor.vmware.util.VmwareHelper; import com.cloud.utils.StringUtils;
import org.apache.cloudstack.vm.UnmanagedInstanceTO; import org.apache.cloudstack.vm.UnmanagedInstanceTO;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -38,6 +39,10 @@ import com.vmware.vim25.PropertySpec;
import com.vmware.vim25.SelectionSpec; import com.vmware.vim25.SelectionSpec;
import com.vmware.vim25.TraversalSpec; import com.vmware.vim25.TraversalSpec;
import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo; import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
import com.vmware.vim25.RetrieveOptions;
import com.vmware.vim25.RetrieveResult;
import com.vmware.vim25.InvalidPropertyFaultMsg;
import com.vmware.vim25.RuntimeFaultFaultMsg;
import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
@ -52,35 +57,18 @@ public class DatacenterMO extends BaseMO {
super(context, morType, morValue); super(context, morType, morValue);
} }
public DatacenterMO(VmwareContext context, String dcName) throws Exception { public DatacenterMO(VmwareContext context, String dcName) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
super(context, null); super(context, null);
_mor = _context.getVimClient().getDecendentMoRef(_context.getRootFolder(), "Datacenter", dcName); _mor = _context.getVimClient().getDecendentMoRef(_context.getRootFolder(), "Datacenter", dcName);
if (_mor == null) { if (_mor == null) {
logger.error("Unable to locate DC " + dcName); logger.error("Unable to locate DC {}", dcName);
} }
} }
@Override @Override
public String getName() throws Exception { public String getName() throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
return (String)_context.getVimClient().getDynamicProperty(_mor, "name"); return _context.getVimClient().getDynamicProperty(_mor, "name");
}
public void registerTemplate(ManagedObjectReference morHost, String datastoreName, String templateName, String templateFileName) throws Exception {
ManagedObjectReference morFolder = (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "vmFolder");
assert (morFolder != null);
ManagedObjectReference morTask =
_context.getService()
.registerVMTask(morFolder, String.format("[%s] %s/%s", datastoreName, templateName, templateFileName), templateName, true, null, morHost);
boolean result = _context.getVimClient().waitForTask(morTask);
if (!result) {
throw new Exception("Unable to register template due to " + TaskMO.getTaskFailureInfo(_context, morTask));
} else {
_context.waitForTaskProgressDone(morTask);
}
} }
public VirtualMachineMO findVm(String vmName) throws Exception { public VirtualMachineMO findVm(String vmName) throws Exception {
@ -89,7 +77,7 @@ public class DatacenterMO extends BaseMO {
logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!");
} }
String instanceNameCustomField = "value[" + key + "]"; String instanceNameCustomField = "value[" + key + "]";
List<ObjectContent> ocs = getVmPropertiesOnDatacenterVmFolder(new String[] {"name", instanceNameCustomField}); List<ObjectContent> ocs = getVmProperties(new String[] {"name", instanceNameCustomField});
return HypervisorHostHelper.findVmFromObjectContent(_context, ocs.toArray(new ObjectContent[0]), vmName, instanceNameCustomField); return HypervisorHostHelper.findVmFromObjectContent(_context, ocs.toArray(new ObjectContent[0]), vmName, instanceNameCustomField);
} }
@ -98,10 +86,10 @@ public class DatacenterMO extends BaseMO {
int key = cfmMo.getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_UUID); int key = cfmMo.getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_UUID);
assert (key != 0); assert (key != 0);
List<VirtualMachineMO> list = new ArrayList<VirtualMachineMO>(); List<VirtualMachineMO> list = new ArrayList<>();
List<ObjectContent> ocs = getVmPropertiesOnDatacenterVmFolder(new String[] {"name", String.format("value[%d]", key)}); List<ObjectContent> ocs = getVmProperties(new String[] {"name", String.format("value[%d]", key)});
if (ocs != null && ocs.size() > 0) { if (CollectionUtils.isNotEmpty(ocs)) {
for (ObjectContent oc : ocs) { for (ObjectContent oc : ocs) {
List<DynamicProperty> props = oc.getPropSet(); List<DynamicProperty> props = oc.getPropSet();
if (props != null) { if (props != null) {
@ -133,8 +121,8 @@ public class DatacenterMO extends BaseMO {
logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!");
} }
List<ObjectContent> ocs = getVmPropertiesOnDatacenterVmFolder(new String[] {"name", String.format("value[%d]", key)}); List<ObjectContent> ocs = getVmProperties(new String[] {"name", String.format("value[%d]", key)});
if (ocs != null && ocs.size() > 0) { if (CollectionUtils.isNotEmpty(ocs)) {
for (ObjectContent oc : ocs) { for (ObjectContent oc : ocs) {
List<DynamicProperty> props = oc.getPropSet(); List<DynamicProperty> props = oc.getPropSet();
if (props != null) { if (props != null) {
@ -159,31 +147,18 @@ public class DatacenterMO extends BaseMO {
return null; return null;
} }
public List<UnmanagedInstanceTO> getAllVmsOnDatacenter() throws Exception { public Pair<String, List<UnmanagedInstanceTO>> getVms(Integer maxObjects, String token) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
List<UnmanagedInstanceTO> vms = new ArrayList<>(); List<UnmanagedInstanceTO> vms = new ArrayList<>();
List<ObjectContent> ocs = getVmPropertiesOnDatacenterVmFolder(new String[] {"name"}); Pair<String, List<ObjectContent>> objectContents = getVmProperties(new String[] {"name"}, maxObjects, token);
if (ocs != null) { logger.debug("returning token {} for future retrievals, currently {} objects retrieved.", objectContents.first(), objectContents.second().size());
for (ObjectContent oc : ocs) { Pair<String, List<UnmanagedInstanceTO>> retval = new Pair<>(objectContents.first(), vms);
ManagedObjectReference vmMor = oc.getObj();
if (vmMor != null) {
VirtualMachineMO vmMo = new VirtualMachineMO(_context, vmMor);
try {
if (!vmMo.isTemplate()) {
HostMO hostMO = vmMo.getRunningHost();
UnmanagedInstanceTO unmanagedInstance = VmwareHelper.getUnmanagedInstance(hostMO, vmMo);
vms.add(unmanagedInstance);
}
} catch (Exception e) {
logger.debug(String.format("Unexpected error checking unmanaged instance %s, excluding it: %s", vmMo.getVmName(), e.getMessage()), e);
}
}
}
}
return vms; objectContentToUnmanagedInstanceTO(objectContents, vms);
return retval;
} }
public List<HostMO> getAllHostsOnDatacenter() throws Exception { public List<HostMO> getAllHostsOnDatacenter() throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
List<HostMO> hosts = new ArrayList<>(); List<HostMO> hosts = new ArrayList<>();
List<ObjectContent> ocs = getHostPropertiesOnDatacenterHostFolder(new String[] {"name"}); List<ObjectContent> ocs = getHostPropertiesOnDatacenterHostFolder(new String[] {"name"});
@ -210,21 +185,7 @@ public class DatacenterMO extends BaseMO {
return null; return null;
} }
public ManagedObjectReference listDatastore(String name) throws Exception { public ManagedObjectReference findHost(String name) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
assert (name != null);
List<ObjectContent> ocs = getDatastorePropertiesOnDatacenter(new String[] {"name"});
if (ocs != null) {
for (ObjectContent oc : ocs) {
if (oc.getPropSet().get(0).getVal().toString().equals(name)) {
return oc.getObj();
}
}
}
return null;
}
public ManagedObjectReference findHost(String name) throws Exception {
List<ObjectContent> ocs = getHostPropertiesOnDatacenterHostFolder(new String[] {"name"}); List<ObjectContent> ocs = getHostPropertiesOnDatacenterHostFolder(new String[] {"name"});
if (ocs != null) { if (ocs != null) {
@ -238,10 +199,10 @@ public class DatacenterMO extends BaseMO {
} }
public ManagedObjectReference getVmFolder() throws Exception { public ManagedObjectReference getVmFolder() throws Exception {
return (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "vmFolder"); return _context.getVimClient().getDynamicProperty(_mor, "vmFolder");
} }
public List<ObjectContent> getHostPropertiesOnDatacenterHostFolder(String[] propertyPaths) throws Exception { public List<ObjectContent> getHostPropertiesOnDatacenterHostFolder(String[] propertyPaths) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
PropertySpec pSpec = new PropertySpec(); PropertySpec pSpec = new PropertySpec();
pSpec.setType("HostSystem"); pSpec.setType("HostSystem");
pSpec.getPathSet().addAll(Arrays.asList(propertyPaths)); pSpec.getPathSet().addAll(Arrays.asList(propertyPaths));
@ -275,7 +236,7 @@ public class DatacenterMO extends BaseMO {
PropertyFilterSpec pfSpec = new PropertyFilterSpec(); PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet().add(pSpec); pfSpec.getPropSet().add(pSpec);
pfSpec.getObjectSet().add(oSpec); pfSpec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
pfSpecArr.add(pfSpec); pfSpecArr.add(pfSpec);
return _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); return _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
@ -301,14 +262,37 @@ public class DatacenterMO extends BaseMO {
PropertyFilterSpec pfSpec = new PropertyFilterSpec(); PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet().add(pSpec); pfSpec.getPropSet().add(pSpec);
pfSpec.getObjectSet().add(oSpec); pfSpec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
pfSpecArr.add(pfSpec); pfSpecArr.add(pfSpec);
return _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); return _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
} }
public List<ObjectContent> getVmPropertiesOnDatacenterVmFolder(String[] propertyPaths) throws Exception { public List<ObjectContent> getVmProperties(String[] propertyPaths) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
return getVmProperties(propertyPaths, null, null).second();
}
/**
*
* @param propertyPaths Vmware side property names to query, for instance {"name"}
* @param maxObjects the number of objects to retrieve
* @param tokenForPriorQuery restart the query or continue a previous query
* @return The propertyPaths requested for the objects of type "VirtualMachine" in a list are found/returned by the DC
* @throws InvalidPropertyFaultMsg property does not exist as thrown by Vmware.
* @throws RuntimeFaultFaultMsg generic vmware runtime exception
*/
public Pair<String, List<ObjectContent>> getVmProperties(String[] propertyPaths, Integer maxObjects, String tokenForPriorQuery) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
if(StringUtils.isNotBlank(tokenForPriorQuery)) {
logger.debug("running repeat query with token '{}'", tokenForPriorQuery);
return retrieveNextSetOfProperties(tokenForPriorQuery);
} else {
logger.debug("running query for {} propertypaths and max {} objects", propertyPaths.length, maxObjects);
return retrieveNextSetOfProperties(propertyPaths, maxObjects);
}
}
private Pair<String, List<ObjectContent>> retrieveNextSetOfProperties(String[] propertyPaths, Integer maxObjects) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
PropertySpec pSpec = new PropertySpec(); PropertySpec pSpec = new PropertySpec();
pSpec.setType("VirtualMachine"); pSpec.setType("VirtualMachine");
pSpec.getPathSet().addAll(Arrays.asList(propertyPaths)); pSpec.getPathSet().addAll(Arrays.asList(propertyPaths));
@ -336,10 +320,16 @@ public class DatacenterMO extends BaseMO {
PropertyFilterSpec pfSpec = new PropertyFilterSpec(); PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet().add(pSpec); pfSpec.getPropSet().add(pSpec);
pfSpec.getObjectSet().add(oSpec); pfSpec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
pfSpecArr.add(pfSpec); pfSpecArr.add(pfSpec);
return _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); RetrieveOptions ro = new RetrieveOptions();
if (maxObjects != null && maxObjects > 0) {
ro.setMaxObjects(maxObjects);
}
RetrieveResult result = _context.getService().retrievePropertiesEx(_context.getPropertyCollector(), pfSpecArr, ro);
return createReturnObjectPair(result);
} }
public static Pair<DatacenterMO, String> getOwnerDatacenter(VmwareContext context, ManagedObjectReference morEntity) throws Exception { public static Pair<DatacenterMO, String> getOwnerDatacenter(VmwareContext context, ManagedObjectReference morEntity) throws Exception {
@ -364,18 +354,18 @@ public class DatacenterMO extends BaseMO {
PropertyFilterSpec pfSpec = new PropertyFilterSpec(); PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet().add(pSpec); pfSpec.getPropSet().add(pSpec);
pfSpec.getObjectSet().add(oSpec); pfSpec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
pfSpecArr.add(pfSpec); pfSpecArr.add(pfSpec);
List<ObjectContent> ocs = context.getService().retrieveProperties(context.getPropertyCollector(), pfSpecArr); List<ObjectContent> ocs = context.getService().retrieveProperties(context.getPropertyCollector(), pfSpecArr);
assert (ocs != null && ocs.size() > 0); assert (CollectionUtils.isNotEmpty(ocs));
assert (ocs.get(0).getObj() != null); assert (ocs.get(0).getObj() != null);
assert (ocs.get(0).getPropSet().get(0) != null); assert (ocs.get(0).getPropSet().get(0) != null);
assert (ocs.get(0).getPropSet().get(0).getVal() != null); assert (ocs.get(0).getPropSet().get(0).getVal() != null);
String dcName = ocs.get(0).getPropSet().get(0).getVal().toString(); String dcName = ocs.get(0).getPropSet().get(0).getVal().toString();
return new Pair<DatacenterMO, String>(new DatacenterMO(context, ocs.get(0).getObj()), dcName); return new Pair<>(new DatacenterMO(context, ocs.get(0).getObj()), dcName);
} }
public ManagedObjectReference getDvPortGroupMor(String dvPortGroupName) throws Exception { public ManagedObjectReference getDvPortGroupMor(String dvPortGroupName) throws Exception {
@ -396,7 +386,7 @@ public class DatacenterMO extends BaseMO {
PropertyFilterSpec pfSpec = new PropertyFilterSpec(); PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet().add(pSpec); pfSpec.getPropSet().add(pSpec);
pfSpec.getObjectSet().add(oSpec); pfSpec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
pfSpecArr.add(pfSpec); pfSpecArr.add(pfSpec);
List<ObjectContent> ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); List<ObjectContent> ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
@ -417,9 +407,7 @@ public class DatacenterMO extends BaseMO {
public boolean hasDvPortGroup(String dvPortGroupName) throws Exception { public boolean hasDvPortGroup(String dvPortGroupName) throws Exception {
ManagedObjectReference morNetwork = getDvPortGroupMor(dvPortGroupName); ManagedObjectReference morNetwork = getDvPortGroupMor(dvPortGroupName);
if (morNetwork != null) return morNetwork != null;
return true;
return false;
} }
public DVPortgroupConfigInfo getDvPortGroupSpec(String dvPortGroupName) throws Exception { public DVPortgroupConfigInfo getDvPortGroupSpec(String dvPortGroupName) throws Exception {
@ -443,7 +431,7 @@ public class DatacenterMO extends BaseMO {
PropertyFilterSpec pfSpec = new PropertyFilterSpec(); PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet().add(pSpec); pfSpec.getPropSet().add(pSpec);
pfSpec.getObjectSet().add(oSpec); pfSpec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
pfSpecArr.add(pfSpec); pfSpecArr.add(pfSpec);
List<ObjectContent> ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); List<ObjectContent> ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
@ -460,7 +448,7 @@ public class DatacenterMO extends BaseMO {
nameProperty = prop.getVal().toString(); nameProperty = prop.getVal().toString();
} }
} }
if (nameProperty.equalsIgnoreCase(dvPortGroupName)) { if (nameProperty != null && nameProperty.equalsIgnoreCase(dvPortGroupName)) {
return configSpec; return configSpec;
} }
} }
@ -490,7 +478,7 @@ public class DatacenterMO extends BaseMO {
PropertyFilterSpec pfSpec = new PropertyFilterSpec(); PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet().add(pSpec); pfSpec.getPropSet().add(pSpec);
pfSpec.getObjectSet().add(oSpec); pfSpec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
pfSpecArr.add(pfSpec); pfSpecArr.add(pfSpec);
List<ObjectContent> ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); List<ObjectContent> ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
@ -518,7 +506,7 @@ public class DatacenterMO extends BaseMO {
public String getDvSwitchUuid(ManagedObjectReference dvSwitchMor) throws Exception { public String getDvSwitchUuid(ManagedObjectReference dvSwitchMor) throws Exception {
assert (dvSwitchMor != null); assert (dvSwitchMor != null);
return (String)_context.getVimClient().getDynamicProperty(dvSwitchMor, "uuid"); return _context.getVimClient().getDynamicProperty(dvSwitchMor, "uuid");
} }
public VirtualEthernetCardDistributedVirtualPortBackingInfo getDvPortBackingInfo(Pair<ManagedObjectReference, String> networkInfo) throws Exception { public VirtualEthernetCardDistributedVirtualPortBackingInfo getDvPortBackingInfo(Pair<ManagedObjectReference, String> networkInfo) throws Exception {
@ -536,8 +524,8 @@ public class DatacenterMO extends BaseMO {
} }
public ManagedObjectReference getDvSwitchMor(String dvSwitchName) throws Exception { public ManagedObjectReference getDvSwitchMor(String dvSwitchName) throws Exception {
ManagedObjectReference dvSwitchMor = null; ManagedObjectReference dvSwitchMor;
ManagedObjectReference networkFolderMor = null; ManagedObjectReference networkFolderMor;
networkFolderMor = _context.getVimClient().getMoRefProp(_mor, "networkFolder"); networkFolderMor = _context.getVimClient().getMoRefProp(_mor, "networkFolder");
dvSwitchMor = _context.getVimClient().getDecendentMoRef(networkFolderMor, "VmwareDistributedVirtualSwitch", dvSwitchName); dvSwitchMor = _context.getVimClient().getDecendentMoRef(networkFolderMor, "VmwareDistributedVirtualSwitch", dvSwitchName);
return dvSwitchMor; return dvSwitchMor;
@ -549,7 +537,6 @@ public class DatacenterMO extends BaseMO {
} }
public DatacenterConfigInfo getDatacenterConfigInfo() throws Exception { public DatacenterConfigInfo getDatacenterConfigInfo() throws Exception {
DatacenterConfigInfo configInfo = (DatacenterConfigInfo)_context.getVimClient().getDynamicProperty(_mor, "configuration"); return _context.getVimClient().getDynamicProperty(_mor, "configuration");
return configInfo;
} }
} }

View File

@ -16,6 +16,7 @@
// under the License. // under the License.
package com.cloud.hypervisor.vmware.mo; package com.cloud.hypervisor.vmware.mo;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -24,10 +25,19 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
import com.cloud.hypervisor.vmware.util.VmwareClientException;
import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.hypervisor.vmware.util.VmwareHelper;
import com.cloud.utils.LogUtils;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.vmware.vim25.AboutInfo; import com.vmware.vim25.AboutInfo;
import com.vmware.vim25.AlreadyExistsFaultMsg; import com.vmware.vim25.AlreadyExistsFaultMsg;
import com.vmware.vim25.ClusterDasConfigInfo; import com.vmware.vim25.ClusterDasConfigInfo;
@ -57,6 +67,7 @@ import com.vmware.vim25.HostRuntimeInfo;
import com.vmware.vim25.HostSystemConnectionState; import com.vmware.vim25.HostSystemConnectionState;
import com.vmware.vim25.HostVirtualNic; import com.vmware.vim25.HostVirtualNic;
import com.vmware.vim25.HostVirtualSwitch; import com.vmware.vim25.HostVirtualSwitch;
import com.vmware.vim25.InvalidPropertyFaultMsg;
import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.NasDatastoreInfo; import com.vmware.vim25.NasDatastoreInfo;
import com.vmware.vim25.ObjectContent; import com.vmware.vim25.ObjectContent;
@ -64,16 +75,15 @@ import com.vmware.vim25.ObjectSpec;
import com.vmware.vim25.OptionValue; import com.vmware.vim25.OptionValue;
import com.vmware.vim25.PropertyFilterSpec; import com.vmware.vim25.PropertyFilterSpec;
import com.vmware.vim25.PropertySpec; import com.vmware.vim25.PropertySpec;
import com.vmware.vim25.RetrieveOptions;
import com.vmware.vim25.RetrieveResult;
import com.vmware.vim25.RuntimeFaultFaultMsg;
import com.vmware.vim25.TraversalSpec; import com.vmware.vim25.TraversalSpec;
import com.vmware.vim25.VirtualMachineConfigSpec; import com.vmware.vim25.VirtualMachineConfigSpec;
import com.vmware.vim25.VirtualNicManagerNetConfig; import com.vmware.vim25.VirtualNicManagerNetConfig;
import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.hypervisor.vmware.util.VmwareHelper;
import com.cloud.utils.LogUtils;
import com.cloud.utils.Pair;
public class HostMO extends BaseMO implements VmwareHypervisorHost { public class HostMO extends BaseMO implements VmwareHypervisorHost {
Map<String, VirtualMachineMO> _vmCache = new HashMap<String, VirtualMachineMO>(); Map<String, VirtualMachineMO> _vmCache = new HashMap<>();
//Map<String, String> _vmInternalNameMapCache = new HashMap<String, String>(); //Map<String, String> _vmInternalNameMapCache = new HashMap<String, String>();
@ -87,12 +97,11 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
public HostHardwareSummary getHostHardwareSummary() throws Exception { public HostHardwareSummary getHostHardwareSummary() throws Exception {
HostConnectInfo hostInfo = _context.getService().queryHostConnectionInfo(_mor); HostConnectInfo hostInfo = _context.getService().queryHostConnectionInfo(_mor);
HostHardwareSummary hardwareSummary = hostInfo.getHost().getHardware(); return hostInfo.getHost().getHardware();
return hardwareSummary;
} }
public HostConfigManager getHostConfigManager() throws Exception { public HostConfigManager getHostConfigManager() throws Exception {
return (HostConfigManager)_context.getVimClient().getDynamicProperty(_mor, "configManager"); return _context.getVimClient().getDynamicProperty(_mor, "configManager");
} }
public List<VirtualNicManagerNetConfig> getHostVirtualNicManagerNetConfig() throws Exception { public List<VirtualNicManagerNetConfig> getHostVirtualNicManagerNetConfig() throws Exception {
@ -104,15 +113,15 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
} }
public HostListSummaryQuickStats getHostQuickStats() throws Exception { public HostListSummaryQuickStats getHostQuickStats() throws Exception {
return (HostListSummaryQuickStats)_context.getVimClient().getDynamicProperty(_mor, "summary.quickStats"); return _context.getVimClient().getDynamicProperty(_mor, "summary.quickStats");
} }
public HostHyperThreadScheduleInfo getHostHyperThreadInfo() throws Exception { public HostHyperThreadScheduleInfo getHostHyperThreadInfo() throws Exception {
return (HostHyperThreadScheduleInfo)_context.getVimClient().getDynamicProperty(_mor, "config.hyperThread"); return _context.getVimClient().getDynamicProperty(_mor, "config.hyperThread");
} }
public HostNetworkInfo getHostNetworkInfo() throws Exception { public HostNetworkInfo getHostNetworkInfo() throws Exception {
return (HostNetworkInfo)_context.getVimClient().getDynamicProperty(_mor, "config.network"); return _context.getVimClient().getDynamicProperty(_mor, "config.network");
} }
public HostPortGroupSpec getHostPortGroupSpec(String portGroupName) throws Exception { public HostPortGroupSpec getHostPortGroupSpec(String portGroupName) throws Exception {
@ -142,7 +151,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
return null; return null;
} }
List<HostPortGroupSpec> portGroupSpecs = new ArrayList<HostPortGroupSpec>(); List<HostPortGroupSpec> portGroupSpecs = new ArrayList<>();
for (HostPortGroup portGroup : portGroups) { for (HostPortGroup portGroup : portGroups) {
if (!isVMKernelPort(portGroup)) { if (!isVMKernelPort(portGroup)) {
portGroupSpecs.add(portGroup.getSpec()); portGroupSpecs.add(portGroup.getSpec());
@ -216,20 +225,20 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
} }
public HostStorageSystemMO getHostStorageSystemMO() throws Exception { public HostStorageSystemMO getHostStorageSystemMO() throws Exception {
return new HostStorageSystemMO(_context, (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "configManager.storageSystem")); return new HostStorageSystemMO(_context, _context.getVimClient().getDynamicProperty(_mor, "configManager.storageSystem"));
} }
public HostDatastoreSystemMO getHostDatastoreSystemMO() throws Exception { public HostDatastoreSystemMO getHostDatastoreSystemMO() throws Exception {
return new HostDatastoreSystemMO(_context, (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "configManager.datastoreSystem")); return new HostDatastoreSystemMO(_context, _context.getVimClient().getDynamicProperty(_mor, "configManager.datastoreSystem"));
} }
public HostDatastoreBrowserMO getHostDatastoreBrowserMO() throws Exception { public HostDatastoreBrowserMO getHostDatastoreBrowserMO() throws Exception {
return new HostDatastoreBrowserMO(_context, (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "datastoreBrowser")); return new HostDatastoreBrowserMO(_context, _context.getVimClient().getDynamicProperty(_mor, "datastoreBrowser"));
} }
private DatastoreMO getHostDatastoreMO(String datastoreName) throws Exception { private DatastoreMO getHostDatastoreMO(String datastoreName) throws Exception {
ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {"name"}); ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {"name"});
if (ocs != null && ocs.length > 0) { if (ocs != null) {
for (ObjectContent oc : ocs) { for (ObjectContent oc : ocs) {
List<DynamicProperty> objProps = oc.getPropSet(); List<DynamicProperty> objProps = oc.getPropSet();
if (objProps != null) { if (objProps != null) {
@ -267,13 +276,13 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
@Override @Override
public ManagedObjectReference getHyperHostOwnerResourcePool() throws Exception { public ManagedObjectReference getHyperHostOwnerResourcePool() throws Exception {
ManagedObjectReference morComputerResource = (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "parent"); ManagedObjectReference morComputerResource = _context.getVimClient().getDynamicProperty(_mor, "parent");
return (ManagedObjectReference)_context.getVimClient().getDynamicProperty(morComputerResource, "resourcePool"); return _context.getVimClient().getDynamicProperty(morComputerResource, "resourcePool");
} }
@Override @Override
public ManagedObjectReference getHyperHostCluster() throws Exception { public ManagedObjectReference getHyperHostCluster() throws Exception {
ManagedObjectReference morParent = (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "parent"); ManagedObjectReference morParent = _context.getVimClient().getDynamicProperty(_mor, "parent");
if (morParent.getType().equalsIgnoreCase("ClusterComputeResource")) { if (morParent.getType().equalsIgnoreCase("ClusterComputeResource")) {
return morParent; return morParent;
@ -285,10 +294,10 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
public ManagedObjectReference[] getHostLocalDatastore() throws Exception { public ManagedObjectReference[] getHostLocalDatastore() throws Exception {
List<ManagedObjectReference> datastores = _context.getVimClient().getDynamicProperty(_mor, "datastore"); List<ManagedObjectReference> datastores = _context.getVimClient().getDynamicProperty(_mor, "datastore");
List<ManagedObjectReference> l = new ArrayList<ManagedObjectReference>(); List<ManagedObjectReference> l = new ArrayList<>();
if (datastores != null) { if (datastores != null) {
for (ManagedObjectReference mor : datastores) { for (ManagedObjectReference mor : datastores) {
DatastoreSummary summary = (DatastoreSummary)_context.getVimClient().getDynamicProperty(mor, "summary"); DatastoreSummary summary = _context.getVimClient().getDynamicProperty(mor, "summary");
if (summary.getType().equalsIgnoreCase("VMFS") && !summary.isMultipleHostAccess()) if (summary.getType().equalsIgnoreCase("VMFS") && !summary.isMultipleHostAccess())
l.add(mor); l.add(mor);
} }
@ -313,7 +322,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
} }
public AboutInfo getHostAboutInfo() throws Exception { public AboutInfo getHostAboutInfo() throws Exception {
return (AboutInfo)_context.getVimClient().getDynamicProperty(_mor, "config.product"); return _context.getVimClient().getDynamicProperty(_mor, "config.product");
} }
public VmwareHostType getHostType() throws Exception { public VmwareHostType getHostType() throws Exception {
@ -507,7 +516,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
PropertyFilterSpec pfSpec = new PropertyFilterSpec(); PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet().add(pSpec); pfSpec.getPropSet().add(pSpec);
pfSpec.getObjectSet().add(oSpec); pfSpec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
pfSpecArr.add(pfSpec); pfSpecArr.add(pfSpec);
List<ObjectContent> ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); List<ObjectContent> ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
@ -533,18 +542,22 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
return null; return null;
} }
public String getHostName() throws Exception { public String getHostName() throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
return (String)_context.getVimClient().getDynamicProperty(_mor, "name"); return _context.getVimClient().getDynamicProperty(_mor, "name");
} }
@Override @Override
public synchronized List<VirtualMachineMO> listVmsOnHyperHostWithHypervisorName(String vmName) throws Exception { public synchronized List<VirtualMachineMO> listVmsOnHyperHostWithHypervisorName(String vmName) throws VmwareClientException {
List<VirtualMachineMO> vms = new ArrayList<>(); List<VirtualMachineMO> vms = new ArrayList<>();
if (StringUtils.isNotEmpty(vmName)) { try {
vms.add(findVmOnHyperHostWithHypervisorName(vmName)); if (StringUtils.isNotEmpty(vmName)) {
} else { vms.add(findVmOnHyperHostWithHypervisorName(vmName));
loadVmCache(); } else {
vms.addAll(_vmCache.values()); loadVmCache();
vms.addAll(_vmCache.values());
}
} catch (InvalidPropertyFaultMsg | RuntimeFaultFaultMsg | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
throw new VmwareClientException("problem loading vm cache.", e);
} }
return vms; return vms;
} }
@ -580,9 +593,8 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
} }
} }
private void loadVmCache() throws Exception { private void loadVmCache() throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
if (logger.isDebugEnabled()) logger.debug("load VM cache on host");
logger.debug("load VM cache on host");
_vmCache.clear(); _vmCache.clear();
@ -594,7 +606,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
// name is the name of the VM as it appears in vCenter. The CLOUD_VM_INTERNAL_NAME custom // name is the name of the VM as it appears in vCenter. The CLOUD_VM_INTERNAL_NAME custom
// field value contains the name of the VM as it is maintained internally by cloudstack (i-x-y). // field value contains the name of the VM as it is maintained internally by cloudstack (i-x-y).
ObjectContent[] ocs = getVmPropertiesOnHyperHost(new String[] {"name", "value[" + key + "]"}); ObjectContent[] ocs = getVmPropertiesOnHyperHost(new String[] {"name", "value[" + key + "]"});
if (ocs != null && ocs.length > 0) { if (ocs != null) {
for (ObjectContent oc : ocs) { for (ObjectContent oc : ocs) {
List<DynamicProperty> props = oc.getPropSet(); List<DynamicProperty> props = oc.getPropSet();
if (props != null) { if (props != null) {
@ -608,7 +620,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
vmInternalCSName = ((CustomFieldStringValue)prop.getVal()).getValue(); vmInternalCSName = ((CustomFieldStringValue)prop.getVal()).getValue();
} }
} }
String vmName = null; String vmName;
if (vmInternalCSName != null && isUserVMInternalCSName(vmInternalCSName)) { if (vmInternalCSName != null && isUserVMInternalCSName(vmInternalCSName)) {
vmName = vmInternalCSName; vmName = vmInternalCSName;
} else { } else {
@ -668,8 +680,8 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
ObjectContent[] ocs = getVmPropertiesOnHyperHost(new String[] {"name", "config.extraConfig[\"RemoteDisplay.vnc.port\"]", "value[" + key + "]"}); ObjectContent[] ocs = getVmPropertiesOnHyperHost(new String[] {"name", "config.extraConfig[\"RemoteDisplay.vnc.port\"]", "value[" + key + "]"});
HashMap<String, Integer> portInfo = new HashMap<String, Integer>(); HashMap<String, Integer> portInfo = new HashMap<>();
if (ocs != null && ocs.length > 0) { if (ocs != null) {
for (ObjectContent oc : ocs) { for (ObjectContent oc : ocs) {
List<DynamicProperty> objProps = oc.getPropSet(); List<DynamicProperty> objProps = oc.getPropSet();
if (objProps != null) { if (objProps != null) {
@ -702,11 +714,16 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
} }
@Override @Override
public ObjectContent[] getVmPropertiesOnHyperHost(String[] propertyPaths) throws Exception { public ObjectContent[] getVmPropertiesOnHyperHost(String[] propertyPaths) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
if (logger.isTraceEnabled()) List<ObjectContent> properties = getVmProperties(propertyPaths, null).second();
return properties.toArray(new ObjectContent[properties.size()]);
}
public Pair<String, List<ObjectContent>> getVmProperties(String[] propertyPaths, Integer maxObjects) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
if (logger.isTraceEnabled()) {
logger.trace("vCenter API trace - retrieveProperties() for VM properties. target MOR: " + _mor.getValue() + ", properties: " + logger.trace("vCenter API trace - retrieveProperties() for VM properties. target MOR: " + _mor.getValue() + ", properties: " +
new Gson().toJson(propertyPaths)); new Gson().toJson(propertyPaths));
}
PropertySpec pSpec = new PropertySpec(); PropertySpec pSpec = new PropertySpec();
pSpec.setType("VirtualMachine"); pSpec.setType("VirtualMachine");
pSpec.getPathSet().addAll(Arrays.asList(propertyPaths)); pSpec.getPathSet().addAll(Arrays.asList(propertyPaths));
@ -724,14 +741,18 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
PropertyFilterSpec pfSpec = new PropertyFilterSpec(); PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet().add(pSpec); pfSpec.getPropSet().add(pSpec);
pfSpec.getObjectSet().add(oSpec); pfSpec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
pfSpecArr.add(pfSpec); pfSpecArr.add(pfSpec);
List<ObjectContent> properties = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); RetrieveOptions ro = new RetrieveOptions();
if (maxObjects != null && maxObjects > 0) {
ro.setMaxObjects(maxObjects);
}
if (logger.isTraceEnabled()) RetrieveResult result = _context.getService().retrievePropertiesEx(_context.getPropertyCollector(), pfSpecArr, ro);
logger.trace("vCenter API trace - retrieveProperties() done");
return properties.toArray(new ObjectContent[properties.size()]); logger.trace("vCenter API trace - retrieveProperties() done");
return createReturnObjectPair(result);
} }
@Override @Override
@ -757,7 +778,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
PropertyFilterSpec pfSpec = new PropertyFilterSpec(); PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet().add(pSpec); pfSpec.getPropSet().add(pSpec);
pfSpec.getObjectSet().add(oSpec); pfSpec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
pfSpecArr.add(pfSpec); pfSpecArr.add(pfSpec);
List<ObjectContent> properties = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); List<ObjectContent> properties = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
@ -768,12 +789,12 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
} }
public List<Pair<ManagedObjectReference, String>> getDatastoreMountsOnHost() throws Exception { public List<Pair<ManagedObjectReference, String>> getDatastoreMountsOnHost() throws Exception {
List<Pair<ManagedObjectReference, String>> mounts = new ArrayList<Pair<ManagedObjectReference, String>>(); List<Pair<ManagedObjectReference, String>> mounts = new ArrayList<>();
ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {String.format("host[\"%s\"].mountInfo.path", _mor.getValue())}); ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {String.format("host[\"%s\"].mountInfo.path", _mor.getValue())});
if (ocs != null) { if (ocs != null) {
for (ObjectContent oc : ocs) { for (ObjectContent oc : ocs) {
Pair<ManagedObjectReference, String> mount = new Pair<ManagedObjectReference, String>(oc.getObj(), oc.getPropSet().get(0).getVal().toString()); Pair<ManagedObjectReference, String> mount = new Pair<>(oc.getObj(), oc.getPropSet().get(0).getVal().toString());
mounts.add(mount); mounts.add(mount);
} }
} }
@ -781,7 +802,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
} }
public List<Pair<ManagedObjectReference, String>> getLocalDatastoreOnHost() throws Exception { public List<Pair<ManagedObjectReference, String>> getLocalDatastoreOnHost() throws Exception {
List<Pair<ManagedObjectReference, String>> dsList = new ArrayList<Pair<ManagedObjectReference, String>>(); List<Pair<ManagedObjectReference, String>> dsList = new ArrayList<>();
ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {"name", "summary"}); ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {"name", "summary"});
if (ocs != null) { if (ocs != null) {
@ -792,7 +813,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
String name = (String)VmwareHelper.getPropValue(oc, "name"); String name = (String)VmwareHelper.getPropValue(oc, "name");
if (!name.startsWith("-iqn.") && !name.startsWith("_iqn.")) { if (!name.startsWith("-iqn.") && !name.startsWith("_iqn.")) {
dsList.add(new Pair<ManagedObjectReference, String>(morDs, name)); dsList.add(new Pair<>(morDs, name));
} }
} }
} }
@ -854,7 +875,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
return null; return null;
} }
// Next, get all the NAS datastores from this array of datastores. // Next, get all the NAS datastores from this array of datastores.
if (morArray.size() > 0) { if (!morArray.isEmpty()) {
int i; int i;
for (i = 0; i < morArray.size(); i++) { for (i = 0; i < morArray.size(); i++) {
NasDatastoreInfo nasDS; NasDatastoreInfo nasDS;
@ -978,7 +999,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
} }
@Override @Override
public ManagedObjectReference findMigrationTarget(VirtualMachineMO vmMo) throws Exception { public ManagedObjectReference findMigrationTarget(VirtualMachineMO vmMo) {
return _mor; return _mor;
} }
@ -1102,7 +1123,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
@Override @Override
public boolean isHyperHostConnected() throws Exception { public boolean isHyperHostConnected() throws Exception {
HostRuntimeInfo runtimeInfo = (HostRuntimeInfo)_context.getVimClient().getDynamicProperty(_mor, "runtime"); HostRuntimeInfo runtimeInfo = _context.getVimClient().getDynamicProperty(_mor, "runtime");
return runtimeInfo != null && runtimeInfo.getConnectionState() == HostSystemConnectionState.CONNECTED; return runtimeInfo != null && runtimeInfo.getConnectionState() == HostSystemConnectionState.CONNECTED;
} }
@ -1316,9 +1337,8 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
return false; return false;
} }
private synchronized VirtualMachineMO findVmOnHyperHostWithHypervisorName(String vmName) throws Exception { private synchronized VirtualMachineMO findVmOnHyperHostWithHypervisorName(String vmName) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
if (logger.isDebugEnabled()) logger.debug("find VM hypervisor name: {} on host", vmName );
logger.debug("find VM hypervisor name: " + vmName + " on host");
VirtualMachineMO vmMo = getVmWithHypervisorName(_vmCache.values(), vmName); VirtualMachineMO vmMo = getVmWithHypervisorName(_vmCache.values(), vmName);
if (vmMo != null) { if (vmMo != null) {
@ -1348,4 +1368,24 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
return null; return null;
} }
public Pair<String, List<UnmanagedInstanceTO>> getVms(Integer maxObjects, String token) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
List<UnmanagedInstanceTO> vms = new ArrayList<>();
Pair<String, List<ObjectContent>> objectContents = getVmProperties(new String[] {"name"}, maxObjects, token);
logger.debug("returning token {} for future retrievals, currently {} objects retrieved.", objectContents.first(), objectContents.second().size());
Pair<String, List<UnmanagedInstanceTO>> retval = new Pair<>(objectContents.first(), vms);
objectContentToUnmanagedInstanceTO(objectContents, vms);
return retval;
}
public Pair<String, List<ObjectContent>> getVmProperties(String[] propertyPaths, Integer maxObjects, String tokenForPriorQuery) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
if(com.cloud.utils.StringUtils.isNotBlank(tokenForPriorQuery)) {
logger.debug("running repeat query with token '{}'", tokenForPriorQuery);
return retrieveNextSetOfProperties(tokenForPriorQuery);
} else {
logger.debug("running query for {} propertypaths and max {} objects", propertyPaths.length, maxObjects);
return getVmProperties(propertyPaths, maxObjects);
}
}
} }

View File

@ -16,8 +16,10 @@
// under the License. // under the License.
package com.cloud.hypervisor.vmware.util; package com.cloud.hypervisor.vmware.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -36,21 +38,26 @@ import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver; import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo; import javax.xml.ws.handler.PortInfo;
import org.apache.cloudstack.utils.security.SSLUtils; import org.apache.cloudstack.utils.security.SSLUtils;
import org.apache.cloudstack.utils.security.SecureSSLSocketFactory; import org.apache.cloudstack.utils.security.SecureSSLSocketFactory;
import com.cloud.utils.StringUtils;
import org.w3c.dom.Element;
import com.vmware.pbm.PbmPortType; import com.vmware.pbm.PbmPortType;
import com.vmware.pbm.PbmService; import com.vmware.pbm.PbmService;
import com.vmware.pbm.PbmServiceInstanceContent; import com.vmware.pbm.PbmServiceInstanceContent;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.w3c.dom.Element;
import com.vmware.vim25.DynamicProperty; import com.vmware.vim25.DynamicProperty;
import com.vmware.vim25.InvalidCollectorVersionFaultMsg; import com.vmware.vim25.InvalidCollectorVersionFaultMsg;
import com.vmware.vim25.InvalidLocaleFaultMsg;
import com.vmware.vim25.InvalidLoginFaultMsg;
import com.vmware.vim25.InvalidPropertyFaultMsg; import com.vmware.vim25.InvalidPropertyFaultMsg;
import com.vmware.vim25.InvalidStateFaultMsg;
import com.vmware.vim25.LocalizedMethodFault; import com.vmware.vim25.LocalizedMethodFault;
import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.MethodFault; import com.vmware.vim25.MethodFault;
@ -93,12 +100,10 @@ public class VmwareClient {
@Override @Override
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException {
return;
} }
@Override @Override
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException {
return;
} }
} }
@ -159,7 +164,7 @@ public class VmwareClient {
* @throws Exception * @throws Exception
* the exception * the exception
*/ */
public void connect(String url, String userName, String password) throws Exception { public void connect(String url, String userName, String password) throws RuntimeFaultFaultMsg, URISyntaxException, VmwareClientException, InvalidLocaleFaultMsg, InvalidLoginFaultMsg {
svcInstRef.setType(SVC_INST_NAME); svcInstRef.setType(SVC_INST_NAME);
svcInstRef.setValue(SVC_INST_NAME); svcInstRef.setValue(SVC_INST_NAME);
@ -189,7 +194,7 @@ public class VmwareClient {
if (cookies == null) { if (cookies == null) {
String msg = "Login successful, but failed to get server cookies from url :[" + url + "]"; String msg = "Login successful, but failed to get server cookies from url :[" + url + "]";
LOGGER.error(msg); LOGGER.error(msg);
throw new Exception(msg); throw new VmwareClientException(msg);
} }
} }
@ -198,14 +203,14 @@ public class VmwareClient {
cookieValue = tokenizer.nextToken(); cookieValue = tokenizer.nextToken();
String pathData = "$" + tokenizer.nextToken(); String pathData = "$" + tokenizer.nextToken();
serviceCookie = "$Version=\"1\"; " + cookieValue + "; " + pathData; serviceCookie = "$Version=\"1\"; " + cookieValue + "; " + pathData;
Map<String, List<String>> map = new HashMap<String, List<String>>(); Map<String, List<String>> map = new HashMap<>();
map.put("Cookie", Collections.singletonList(serviceCookie)); map.put("Cookie", Collections.singletonList(serviceCookie));
((BindingProvider)vimPort).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, map); ((BindingProvider)vimPort).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, map);
pbmConnect(url, cookieValue); pbmConnect(url, cookieValue);
isConnected = true; isConnected = true;
} }
private void pbmConnect(String url, String cookieValue) throws Exception { private void pbmConnect(String url, String cookieValue) throws URISyntaxException {
URI uri = new URI(url); URI uri = new URI(url);
String pbmurl = "https://" + uri.getHost() + "/pbm"; String pbmurl = "https://" + uri.getHost() + "/pbm";
String[] tokens = cookieValue.split("="); String[] tokens = cookieValue.split("=");
@ -215,8 +220,8 @@ public class VmwareClient {
@Override @Override
public List<Handler> getHandlerChain(PortInfo portInfo) { public List<Handler> getHandlerChain(PortInfo portInfo) {
VcenterSessionHandler VcSessionHandler = new VcenterSessionHandler(extractedCookie); VcenterSessionHandler VcSessionHandler = new VcenterSessionHandler(extractedCookie);
List<Handler> handlerChain = new ArrayList<Handler>(); List<Handler> handlerChain = new ArrayList<>();
handlerChain.add((Handler)VcSessionHandler); handlerChain.add(VcSessionHandler);
return handlerChain; return handlerChain;
} }
}; };
@ -257,6 +262,7 @@ public class VmwareClient {
try { try {
return vimPort.retrieveServiceContent(svcInstRef); return vimPort.retrieveServiceContent(svcInstRef);
} catch (RuntimeFaultFaultMsg e) { } catch (RuntimeFaultFaultMsg e) {
// ignored
} }
return null; return null;
} }
@ -275,6 +281,7 @@ public class VmwareClient {
try { try {
return pbmPort.pbmRetrieveServiceContent(pbmSvcInstRef); return pbmPort.pbmRetrieveServiceContent(pbmSvcInstRef);
} catch (com.vmware.pbm.RuntimeFaultFaultMsg e) { } catch (com.vmware.pbm.RuntimeFaultFaultMsg e) {
// ignored
} }
return null; return null;
} }
@ -323,12 +330,12 @@ public class VmwareClient {
PropertyFilterSpec spec = new PropertyFilterSpec(); PropertyFilterSpec spec = new PropertyFilterSpec();
spec.getPropSet().add(pSpec); spec.getPropSet().add(pSpec);
spec.getObjectSet().add(oSpec); spec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> specArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> specArr = new ArrayList<>();
specArr.add(spec); specArr.add(spec);
try { try {
List<ObjectContent> ocary = vimPort.retrieveProperties(getPropCol(), specArr); List<ObjectContent> ocary = vimPort.retrieveProperties(getPropCol(), specArr);
if (ocary != null && ocary.size() > 0) if (ocary != null && !ocary.isEmpty())
return true; return true;
} catch (Exception e) { } catch (Exception e) {
return false; return false;
@ -345,19 +352,17 @@ public class VmwareClient {
* @param propertyName * @param propertyName
* property name. * property name.
* @return property value. * @return property value.
* @throws Exception
* in case of error.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T getDynamicProperty(ManagedObjectReference mor, String propertyName) throws Exception { public <T> T getDynamicProperty(ManagedObjectReference mor, String propertyName) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
List<String> props = new ArrayList<String>(); List<String> props = new ArrayList<>();
props.add(propertyName); props.add(propertyName);
List<ObjectContent> objContent = retrieveMoRefProperties(mor, props); List<ObjectContent> objContent = retrieveMoRefProperties(mor, props);
Object propertyValue = null; Object propertyValue = null;
if (objContent != null && objContent.size() > 0) { if (objContent != null && !objContent.isEmpty()) {
List<DynamicProperty> dynamicProperty = objContent.get(0).getPropSet(); List<DynamicProperty> dynamicProperty = objContent.get(0).getPropSet();
if (dynamicProperty != null && dynamicProperty.size() > 0) { if (dynamicProperty != null && !dynamicProperty.isEmpty()) {
DynamicProperty dp = dynamicProperty.get(0); DynamicProperty dp = dynamicProperty.get(0);
propertyValue = dp.getVal(); propertyValue = dp.getVal();
/* /*
@ -369,7 +374,7 @@ public class VmwareClient {
*/ */
Class dpCls = propertyValue.getClass(); Class dpCls = propertyValue.getClass();
String dynamicPropertyName = dpCls.getName(); String dynamicPropertyName = dpCls.getName();
if (dynamicPropertyName.indexOf("ArrayOf") != -1) { if (dynamicPropertyName.contains("ArrayOf")) {
String methodName = "get" + dynamicPropertyName.substring(dynamicPropertyName.indexOf("ArrayOf") + "ArrayOf".length(), dynamicPropertyName.length()); String methodName = "get" + dynamicPropertyName.substring(dynamicPropertyName.indexOf("ArrayOf") + "ArrayOf".length(), dynamicPropertyName.length());
Method getMorMethod = dpCls.getDeclaredMethod(methodName, null); Method getMorMethod = dpCls.getDeclaredMethod(methodName, null);
@ -380,7 +385,7 @@ public class VmwareClient {
return (T)propertyValue; return (T)propertyValue;
} }
private List<ObjectContent> retrieveMoRefProperties(ManagedObjectReference mObj, List<String> props) throws Exception { private List<ObjectContent> retrieveMoRefProperties(ManagedObjectReference mObj, List<String> props) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
PropertySpec pSpec = new PropertySpec(); PropertySpec pSpec = new PropertySpec();
pSpec.setAll(false); pSpec.setAll(false);
pSpec.setType(mObj.getType()); pSpec.setType(mObj.getType());
@ -392,7 +397,7 @@ public class VmwareClient {
PropertyFilterSpec spec = new PropertyFilterSpec(); PropertyFilterSpec spec = new PropertyFilterSpec();
spec.getPropSet().add(pSpec); spec.getPropSet().add(pSpec);
spec.getObjectSet().add(oSpec); spec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> specArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> specArr = new ArrayList<>();
specArr.add(spec); specArr.add(spec);
return vimPort.retrieveProperties(getPropCol(), specArr); return vimPort.retrieveProperties(getPropCol(), specArr);
@ -410,7 +415,7 @@ public class VmwareClient {
* @throws RuntimeFaultFaultMsg * @throws RuntimeFaultFaultMsg
* @throws InvalidPropertyFaultMsg * @throws InvalidPropertyFaultMsg
*/ */
public boolean waitForTask(ManagedObjectReference task) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvalidCollectorVersionFaultMsg, Exception { public boolean waitForTask(ManagedObjectReference task) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvalidCollectorVersionFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException, InvalidStateFaultMsg {
boolean retVal = false; boolean retVal = false;
@ -665,7 +670,7 @@ public class VmwareClient {
visitFolders.setPath("childEntity"); visitFolders.setPath("childEntity");
visitFolders.setSkip(Boolean.FALSE); visitFolders.setSkip(Boolean.FALSE);
visitFolders.setName("VisitFolders"); visitFolders.setName("VisitFolders");
List<SelectionSpec> sspecarrvf = new ArrayList<SelectionSpec>(); List<SelectionSpec> sspecarrvf = new ArrayList<>();
sspecarrvf.add(getSelectionSpec("crToRp")); sspecarrvf.add(getSelectionSpec("crToRp"));
sspecarrvf.add(getSelectionSpec("crToH")); sspecarrvf.add(getSelectionSpec("crToH"));
sspecarrvf.add(getSelectionSpec("dcToVmf")); sspecarrvf.add(getSelectionSpec("dcToVmf"));
@ -679,7 +684,7 @@ public class VmwareClient {
visitFolders.getSelectSet().addAll(sspecarrvf); visitFolders.getSelectSet().addAll(sspecarrvf);
List<SelectionSpec> resultspec = new ArrayList<SelectionSpec>(); List<SelectionSpec> resultspec = new ArrayList<>();
resultspec.add(visitFolders); resultspec.add(visitFolders);
resultspec.add(crToRp); resultspec.add(crToRp);
resultspec.add(crToH); resultspec.add(crToH);
@ -705,8 +710,8 @@ public class VmwareClient {
* *
* @return First ManagedObjectReference of the type / name pair found * @return First ManagedObjectReference of the type / name pair found
*/ */
public ManagedObjectReference getDecendentMoRef(ManagedObjectReference root, String type, String name) throws Exception { public ManagedObjectReference getDecendentMoRef(ManagedObjectReference root, String type, String name) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
if (name == null || name.length() == 0) { if (name == null || name.isEmpty()) {
return null; return null;
} }
@ -725,13 +730,13 @@ public class VmwareClient {
PropertyFilterSpec spec = new PropertyFilterSpec(); PropertyFilterSpec spec = new PropertyFilterSpec();
spec.getPropSet().add(pSpec); spec.getPropSet().add(pSpec);
spec.getObjectSet().add(oSpec); spec.getObjectSet().add(oSpec);
List<PropertyFilterSpec> specArr = new ArrayList<PropertyFilterSpec>(); List<PropertyFilterSpec> specArr = new ArrayList<>();
specArr.add(spec); specArr.add(spec);
ManagedObjectReference propCollector = getPropCol(); ManagedObjectReference propCollector = getPropCol();
List<ObjectContent> ocary = vimPort.retrieveProperties(propCollector, specArr); List<ObjectContent> ocary = vimPort.retrieveProperties(propCollector, specArr);
if (ocary == null || ocary.size() == 0) { if (ocary == null || ocary.isEmpty()) {
return null; return null;
} }
@ -740,19 +745,16 @@ public class VmwareClient {
ManagedObjectReference mor = oc.getObj(); ManagedObjectReference mor = oc.getObj();
List<DynamicProperty> propary = oc.getPropSet(); List<DynamicProperty> propary = oc.getPropSet();
if (type == null || type.equals(mor.getType())) { if (type == null || type.equals(mor.getType())) {
if (propary.size() > 0) { if (!propary.isEmpty()) {
String propval = (String)propary.get(0).getVal(); String propval = (String)propary.get(0).getVal();
if (propval != null && name.equalsIgnoreCase(propval)) if (name.equalsIgnoreCase(propval))
return mor; return mor;
} }
} }
} }
} catch (InvalidPropertyFaultMsg invalidPropertyException) { } catch (InvalidPropertyFaultMsg | RuntimeFaultFaultMsg invalidPropertyException) {
LOGGER.debug("Failed to get Vmware ManagedObjectReference for name: " + name + " and type: " + type + " due to " + invalidPropertyException.getMessage()); LOGGER.debug("Failed to get Vmware ManagedObjectReference for name: " + name + " and type: " + type + " due to " + invalidPropertyException.getMessage());
throw invalidPropertyException; throw invalidPropertyException;
} catch (RuntimeFaultFaultMsg runtimeFaultException) {
LOGGER.debug("Failed to get Vmware ManagedObjectReference for name: " + name + " and type: " + type + " due to " + runtimeFaultException.getMessage());
throw runtimeFaultException;
} }
return null; return null;

View File

@ -0,0 +1,33 @@
// 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.vmware.util;
import com.cloud.exception.CloudException;
public class VmwareClientException extends CloudException {
public VmwareClientException(String message, Throwable cause) {
super(message, cause);
}
public VmwareClientException(String msg) {
super(msg);
}
// TODO embed vmware classes in this one for use downstream
public VmwareClientException(String msg, Exception embedded) {
super(msg, embedded);
}
}