mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge branch '4.19' into 4.20
This commit is contained in:
commit
4f3e8e8c5a
@ -26,7 +26,7 @@ import com.cloud.utils.SerialVersionUID;
|
||||
public class StorageAccessException extends RuntimeException {
|
||||
private static final long serialVersionUID = SerialVersionUID.StorageAccessException;
|
||||
|
||||
public StorageAccessException(String message) {
|
||||
super(message);
|
||||
public StorageAccessException(String message, Exception causer) {
|
||||
super(message, causer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,14 +16,10 @@
|
||||
// under the License.
|
||||
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.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Storage {
|
||||
public static enum ImageFormat {
|
||||
@ -139,6 +135,21 @@ public class Storage {
|
||||
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
|
||||
* 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
|
||||
* package available on both management server and agent plugin jars.
|
||||
*/
|
||||
public static class StoragePoolType {
|
||||
private static final Map<String, StoragePoolType> map = new LinkedHashMap<>();
|
||||
public static enum StoragePoolType {
|
||||
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 overProvisioning;
|
||||
private final boolean encryption;
|
||||
private final 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;
|
||||
StoragePoolType(boolean shared, boolean overProvisioning, EncryptionSupport encryption) {
|
||||
this.shared = shared;
|
||||
this.overProvisioning = overProvisioning;
|
||||
this.encryption = encryption;
|
||||
addStoragePoolType(this);
|
||||
}
|
||||
|
||||
public boolean isShared() {
|
||||
@ -216,50 +203,12 @@ public class Storage {
|
||||
}
|
||||
|
||||
public boolean supportsEncryption() {
|
||||
return encryption == EncryptionSupport.Hypervisor || encryption == EncryptionSupport.Storage;
|
||||
}
|
||||
|
||||
public EncryptionSupport encryptionSupportMode() {
|
||||
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() {
|
||||
|
||||
@ -57,6 +57,7 @@ public class ApiConstants {
|
||||
public static final String BASE64_IMAGE = "base64image";
|
||||
public static final String BGP_PEERS = "bgppeers";
|
||||
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 BOOTABLE = "bootable";
|
||||
public static final String BIND_DN = "binddn";
|
||||
@ -476,11 +477,12 @@ public class ApiConstants {
|
||||
public static final String STATE = "state";
|
||||
public static final String STATS = "stats";
|
||||
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_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 OWNER = "owner";
|
||||
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 BAREMETAL_DISCOVER_NAME = "baremetaldiscovername";
|
||||
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 GSLB_PROVIDER = "gslbprovider";
|
||||
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 " +
|
||||
"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.";
|
||||
public static final String VMWARE_DC = "vmwaredc";
|
||||
|
||||
/**
|
||||
* This enum specifies IO Drivers, each option controls specific policies on I/O.
|
||||
|
||||
@ -152,7 +152,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
|
||||
@Deprecated
|
||||
@SerializedName("memoryallocated")
|
||||
@Param(description = "the amount of the host's memory currently allocated")
|
||||
private long memoryAllocated;
|
||||
private Long memoryAllocated;
|
||||
|
||||
@SerializedName("memoryallocatedpercentage")
|
||||
@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;
|
||||
}
|
||||
|
||||
public void setMemoryAllocated(long memoryAllocated) {
|
||||
public void setMemoryAllocated(Long memoryAllocated) {
|
||||
this.memoryAllocated = memoryAllocated;
|
||||
}
|
||||
|
||||
@ -687,8 +687,8 @@ public class HostResponse extends BaseResponseWithAnnotations {
|
||||
return memoryTotal;
|
||||
}
|
||||
|
||||
public long getMemoryAllocated() {
|
||||
return memoryAllocated;
|
||||
public Long getMemoryAllocated() {
|
||||
return memoryAllocated == null ? 0 : memoryAllocated;
|
||||
}
|
||||
|
||||
public void setMemoryAllocatedPercentage(String memoryAllocatedPercentage) {
|
||||
|
||||
46
core/src/main/java/com/cloud/agent/api/CleanupVMCommand.java
Normal file
46
core/src/main/java/com/cloud/agent/api/CleanupVMCommand.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -1807,7 +1807,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
||||
try {
|
||||
volService.grantAccess(volFactory.getVolume(newVol.getId()), host, destPool);
|
||||
} 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 {
|
||||
volService.grantAccess(volFactory.getVolume(volumeId), host, volumeStore);
|
||||
} 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 {
|
||||
volService.grantAccess(volFactory.getVolume(vol.getId()), host, store);
|
||||
} 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 {
|
||||
grantVolumeAccessToHostIfNeeded(store, vol.getId(), host, volToString);
|
||||
|
||||
@ -20,8 +20,9 @@ import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
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);
|
||||
|
||||
void persist(long clusterId, Map<String, String> details);
|
||||
|
||||
@ -28,12 +28,13 @@ import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
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> DetailSearch;
|
||||
|
||||
@ -44,11 +45,11 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long
|
||||
|
||||
protected ClusterDetailsDaoImpl() {
|
||||
ClusterSearch = createSearchBuilder();
|
||||
ClusterSearch.and("clusterId", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ);
|
||||
ClusterSearch.and("clusterId", ClusterSearch.entity().getResourceId(), SearchCriteria.Op.EQ);
|
||||
ClusterSearch.done();
|
||||
|
||||
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.done();
|
||||
}
|
||||
@ -68,6 +69,11 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long
|
||||
return detail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDetail(long resourceId, String key, String value, boolean display) {
|
||||
super.addDetail(new ClusterDetailsVO(resourceId, key, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> findDetails(long clusterId) {
|
||||
SearchCriteria<ClusterDetailsVO> sc = ClusterSearch.create();
|
||||
@ -91,7 +97,7 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long
|
||||
return new HashMap<>();
|
||||
}
|
||||
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.done();
|
||||
SearchCriteria<ClusterDetailsVO> sc = sb.create();
|
||||
|
||||
@ -23,11 +23,11 @@ import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
import org.apache.cloudstack.api.ResourceDetail;
|
||||
|
||||
@Entity
|
||||
@Table(name = "cluster_details")
|
||||
public class ClusterDetailsVO implements InternalIdentity {
|
||||
public class ClusterDetailsVO implements ResourceDetail {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@ -35,7 +35,7 @@ public class ClusterDetailsVO implements InternalIdentity {
|
||||
private long id;
|
||||
|
||||
@Column(name = "cluster_id")
|
||||
private long clusterId;
|
||||
private long resourceId;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
@ -47,13 +47,14 @@ public class ClusterDetailsVO implements InternalIdentity {
|
||||
}
|
||||
|
||||
public ClusterDetailsVO(long clusterId, String name, String value) {
|
||||
this.clusterId = clusterId;
|
||||
this.resourceId = clusterId;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public long getClusterId() {
|
||||
return clusterId;
|
||||
@Override
|
||||
public long getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@ -64,6 +65,11 @@ public class ClusterDetailsVO implements InternalIdentity {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@ -23,18 +23,18 @@ import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
import org.apache.cloudstack.api.ResourceDetail;
|
||||
|
||||
@Entity
|
||||
@Table(name = "domain_details")
|
||||
public class DomainDetailVO implements InternalIdentity {
|
||||
public class DomainDetailVO implements ResourceDetail {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id;
|
||||
|
||||
@Column(name = "domain_id")
|
||||
private long domainId;
|
||||
private long resourceId;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
@ -46,13 +46,14 @@ public class DomainDetailVO implements InternalIdentity {
|
||||
}
|
||||
|
||||
public DomainDetailVO(long domainId, String name, String value) {
|
||||
this.domainId = domainId;
|
||||
this.resourceId = domainId;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public long getDomainId() {
|
||||
return domainId;
|
||||
@Override
|
||||
public long getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@ -63,6 +64,11 @@ public class DomainDetailVO implements InternalIdentity {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@ -20,8 +20,9 @@ import java.util.Map;
|
||||
|
||||
import com.cloud.domain.DomainDetailVO;
|
||||
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);
|
||||
|
||||
void persist(long domainId, Map<String, String> details);
|
||||
@ -31,6 +32,4 @@ public interface DomainDetailsDao extends GenericDao<DomainDetailVO, Long> {
|
||||
void deleteDetails(long domainId);
|
||||
|
||||
void update(long domainId, Map<String, String> details);
|
||||
|
||||
String getActualValue(DomainDetailVO domainDetailVO);
|
||||
}
|
||||
|
||||
@ -25,19 +25,17 @@ import javax.inject.Inject;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||
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.DomainVO;
|
||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.QueryBuilder;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.SearchCriteria.Op;
|
||||
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;
|
||||
|
||||
@Inject
|
||||
@ -47,14 +45,14 @@ public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> i
|
||||
|
||||
protected DomainDetailsDaoImpl() {
|
||||
domainSearch = createSearchBuilder();
|
||||
domainSearch.and("domainId", domainSearch.entity().getDomainId(), Op.EQ);
|
||||
domainSearch.and("domainId", domainSearch.entity().getResourceId(), Op.EQ);
|
||||
domainSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> findDetails(long domainId) {
|
||||
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();
|
||||
Map<String, String> details = new HashMap<String, String>(results.size());
|
||||
for (DomainDetailVO r : results) {
|
||||
@ -80,11 +78,16 @@ public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> i
|
||||
@Override
|
||||
public DomainDetailVO findDetail(long domainId, String name) {
|
||||
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);
|
||||
return sc.find();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDetail(long resourceId, String key, String value, boolean display) {
|
||||
super.addDetail(new DomainDetailVO(resourceId, key, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDetails(long domainId) {
|
||||
SearchCriteria<DomainDetailVO> sc = domainSearch.create();
|
||||
@ -129,13 +132,4 @@ public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> i
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ public class StoragePoolDetailsDaoImpl extends ResourceDetailsDaoBase<StoragePoo
|
||||
@Override
|
||||
public String getConfigValue(long id, String key) {
|
||||
StoragePoolDetailVO vo = findDetail(id, key);
|
||||
return vo == null ? null : vo.getValue();
|
||||
return vo == null ? null : getActualValue(vo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -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;
|
||||
try {
|
||||
filePath = Files.createTempDirectory(TEMPORARY_SECONDARY_STORE).toString();
|
||||
@ -347,6 +347,9 @@ public class SystemVmTemplateRegistration {
|
||||
String templatePath = filePath + File.separator + partialDirPath;
|
||||
File templateProps = new File(templatePath + "/template.properties");
|
||||
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");
|
||||
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) {
|
||||
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);
|
||||
Long size = null;
|
||||
Long physicalSize = 0L;
|
||||
@ -574,8 +592,13 @@ public class SystemVmTemplateRegistration {
|
||||
} catch (IOException ex) {
|
||||
LOGGER.warn("Failed to read from template.properties", ex);
|
||||
}
|
||||
details.setSize(size);
|
||||
details.setPhysicalSize(physicalSize);
|
||||
return new Pair<>(size, 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) {
|
||||
@ -799,7 +822,7 @@ public class SystemVmTemplateRegistration {
|
||||
TemplateDataStoreVO templateDataStoreVO = templateDataStoreDao.findByStoreTemplate(storeUrlAndId.second(), templateId);
|
||||
if (templateDataStoreVO != null) {
|
||||
String installPath = templateDataStoreVO.getInstallPath();
|
||||
if (validateIfSeeded(storeUrlAndId.first(), installPath, nfsVersion)) {
|
||||
if (validateIfSeeded(templateDataStoreVO, storeUrlAndId.first(), installPath, nfsVersion)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,18 +23,18 @@ import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
import org.apache.cloudstack.api.ResourceDetail;
|
||||
|
||||
@Entity
|
||||
@Table(name = "account_details")
|
||||
public class AccountDetailVO implements InternalIdentity {
|
||||
public class AccountDetailVO implements ResourceDetail {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id;
|
||||
|
||||
@Column(name = "account_id")
|
||||
private long accountId;
|
||||
private long resourceId;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
@ -46,13 +46,14 @@ public class AccountDetailVO implements InternalIdentity {
|
||||
}
|
||||
|
||||
public AccountDetailVO(long accountId, String name, String value) {
|
||||
this.accountId = accountId;
|
||||
this.resourceId = accountId;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
@Override
|
||||
public long getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@ -63,6 +64,11 @@ public class AccountDetailVO implements InternalIdentity {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@ -19,8 +19,9 @@ package com.cloud.user;
|
||||
import java.util.Map;
|
||||
|
||||
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);
|
||||
|
||||
void persist(long accountId, Map<String, String> details);
|
||||
@ -34,6 +35,4 @@ public interface AccountDetailsDao extends GenericDao<AccountDetailVO, Long> {
|
||||
* they will get created
|
||||
*/
|
||||
void update(long accountId, Map<String, String> details);
|
||||
|
||||
String getActualValue(AccountDetailVO accountDetailVO);
|
||||
}
|
||||
|
||||
@ -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.ScopedConfigStorage;
|
||||
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.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.domain.dao.DomainDetailsDao;
|
||||
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.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.SearchCriteria.Op;
|
||||
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;
|
||||
|
||||
@Inject
|
||||
@ -56,16 +54,16 @@ public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long>
|
||||
|
||||
protected AccountDetailsDaoImpl() {
|
||||
accountSearch = createSearchBuilder();
|
||||
accountSearch.and("accountId", accountSearch.entity().getAccountId(), Op.EQ);
|
||||
accountSearch.and("accountId", accountSearch.entity().getResourceId(), Op.EQ);
|
||||
accountSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> findDetails(long accountId) {
|
||||
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();
|
||||
Map<String, String> details = new HashMap<String, String>(results.size());
|
||||
Map<String, String> details = new HashMap<>(results.size());
|
||||
for (AccountDetailVO r : results) {
|
||||
details.put(r.getName(), r.getValue());
|
||||
}
|
||||
@ -89,11 +87,16 @@ public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long>
|
||||
@Override
|
||||
public AccountDetailVO findDetail(long accountId, String name) {
|
||||
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);
|
||||
return sc.find();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDetail(long resourceId, String key, String value, boolean display) {
|
||||
super.addDetail(new AccountDetailVO(resourceId, key, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDetails(long accountId) {
|
||||
SearchCriteria<AccountDetailVO> sc = accountSearch.create();
|
||||
@ -153,13 +156,4 @@ public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long>
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ public interface ResourceDetailsDao<R extends ResourceDetail> extends GenericDao
|
||||
* Removes all details for the resource specified
|
||||
* @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
|
||||
* @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
|
||||
@ -84,21 +84,23 @@ public interface ResourceDetailsDao<R extends ResourceDetail> extends GenericDao
|
||||
* @param forDisplay
|
||||
* @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);
|
||||
|
||||
public Map<String, String> listDetailsKeyPairs(long resourceId, boolean forDisplay);
|
||||
Map<String, String> listDetailsKeyPairs(long resourceId, boolean forDisplay);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -21,9 +21,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.cloudstack.api.ResourceDetail;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.GenericSearchBuilder;
|
||||
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.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> {
|
||||
|
||||
@Inject
|
||||
private ConfigurationDao configDao;
|
||||
|
||||
private SearchBuilder<R> AllFieldsSearch;
|
||||
|
||||
public ResourceDetailsDaoBase() {
|
||||
@ -76,8 +86,7 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
|
||||
sc.setParameters("value", value);
|
||||
}
|
||||
|
||||
List<R> results = search(sc, null);
|
||||
return results;
|
||||
return search(sc, null);
|
||||
}
|
||||
|
||||
public Map<String, String> listDetailsKeyPairs(long resourceId) {
|
||||
@ -85,7 +94,7 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
|
||||
sc.setParameters("resourceId", resourceId);
|
||||
|
||||
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) {
|
||||
details.put(result.getName(), result.getValue());
|
||||
}
|
||||
@ -122,8 +131,7 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
|
||||
SearchCriteria<R> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("resourceId", resourceId);
|
||||
|
||||
List<R> results = search(sc, null);
|
||||
return results;
|
||||
return search(sc, null);
|
||||
}
|
||||
|
||||
public void removeDetails(long resourceId) {
|
||||
@ -185,7 +193,7 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
|
||||
sc.setParameters("display", forDisplay);
|
||||
|
||||
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) {
|
||||
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("display", forDisplay);
|
||||
|
||||
List<R> results = search(sc, null);
|
||||
return results;
|
||||
return search(sc, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -230,4 +237,13 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
|
||||
sc.setParameters("ids", ids.toArray());
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,7 +36,6 @@ import com.cloud.utils.db.TransactionLegacy;
|
||||
|
||||
@Component
|
||||
public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase<ImageStoreDetailVO> implements ImageStoreDetailsDao, ScopedConfigStorage {
|
||||
|
||||
protected final SearchBuilder<ImageStoreDetailVO> storeSearch;
|
||||
|
||||
public ImageStoreDetailsDaoImpl() {
|
||||
@ -67,7 +66,7 @@ public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase<ImageStoreD
|
||||
sc.setParameters("store", storeId);
|
||||
|
||||
List<ImageStoreDetailVO> details = listBy(sc);
|
||||
Map<String, String> detailsMap = new HashMap<String, String>();
|
||||
Map<String, String> detailsMap = new HashMap<>();
|
||||
for (ImageStoreDetailVO detail : details) {
|
||||
String name = detail.getName();
|
||||
String value = detail.getValue();
|
||||
@ -110,9 +109,14 @@ public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase<ImageStoreD
|
||||
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
|
||||
public void addDetail(long resourceId, String key, String value, boolean display) {
|
||||
super.addDetail(new ImageStoreDetailVO(resourceId, key, value, display));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -755,7 +755,7 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase<StoragePoolVO, Long>
|
||||
if (keyword != null) {
|
||||
SearchCriteria<StoragePoolVO> ssc = createSearchCriteria();
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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.DataStore;
|
||||
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.EndPoint;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||
@ -1534,6 +1535,16 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
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;
|
||||
|
||||
final boolean computeClusterSupportsVolumeClone;
|
||||
@ -1641,7 +1652,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
errMsg = "Create volume from template failed: " + ex.getMessage();
|
||||
}
|
||||
|
||||
throw new CloudRuntimeException(errMsg);
|
||||
throw new CloudRuntimeException(errMsg, ex);
|
||||
}
|
||||
finally {
|
||||
if (copyCmdAnswer == null) {
|
||||
@ -2634,7 +2645,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
catch (Exception ex) {
|
||||
errMsg = ex.getMessage();
|
||||
|
||||
throw new CloudRuntimeException(errMsg);
|
||||
throw new CloudRuntimeException(errMsg, ex);
|
||||
}
|
||||
finally {
|
||||
if (copyCmdAnswer == null) {
|
||||
|
||||
@ -622,7 +622,7 @@ public class VolumeServiceImpl implements VolumeService {
|
||||
try {
|
||||
Thread.sleep(sleepTime * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("waiting for template download been interrupted: " + e.toString());
|
||||
logger.debug("waiting for template download been interrupted: " + e);
|
||||
}
|
||||
tries--;
|
||||
}
|
||||
@ -691,7 +691,6 @@ public class VolumeServiceImpl implements VolumeService {
|
||||
}
|
||||
_tmpltPoolDao.releaseFromLockTable(templatePoolRefId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
protected Void managedCopyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, ManagedCreateBaseImageContext<VolumeApiResult> context) {
|
||||
@ -1039,7 +1038,7 @@ public class VolumeServiceImpl implements VolumeService {
|
||||
try {
|
||||
grantAccess(templateOnPrimary, destHost, destPrimaryDataStore);
|
||||
} 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);
|
||||
@ -1161,7 +1160,7 @@ public class VolumeServiceImpl implements VolumeService {
|
||||
try {
|
||||
grantAccess(srcTemplateOnPrimary, destHost, destPrimaryDataStore);
|
||||
} 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);
|
||||
@ -1408,7 +1407,7 @@ public class VolumeServiceImpl implements VolumeService {
|
||||
try {
|
||||
grantAccess(templateOnPrimary, destHost, destPrimaryDataStore);
|
||||
} 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);
|
||||
|
||||
@ -39,7 +39,7 @@ import com.cloud.utils.mgmt.ManagementBean;
|
||||
public class CloudStackExtendedLifeCycle extends AbstractBeanCollector {
|
||||
|
||||
|
||||
Map<Integer, Set<ComponentLifecycle>> sorted = new TreeMap<Integer, Set<ComponentLifecycle>>();
|
||||
Map<Integer, Set<ComponentLifecycle>> sorted = new TreeMap<>();
|
||||
|
||||
public CloudStackExtendedLifeCycle() {
|
||||
super();
|
||||
@ -80,13 +80,8 @@ public class CloudStackExtendedLifeCycle extends AbstractBeanCollector {
|
||||
ManagementBean mbean = (ManagementBean)lifecycle;
|
||||
try {
|
||||
JmxUtil.registerMBean(mbean);
|
||||
} catch (MalformedObjectNameException e) {
|
||||
logger.warn("Unable to register MBean: " + mbean.getName(), 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) {
|
||||
} catch (MalformedObjectNameException | InstanceAlreadyExistsException |
|
||||
MBeanRegistrationException | NotCompliantMBeanException e) {
|
||||
logger.warn("Unable to register MBean: " + mbean.getName(), e);
|
||||
}
|
||||
logger.info("Registered MBean: " + mbean.getName());
|
||||
@ -129,6 +124,7 @@ public class CloudStackExtendedLifeCycle extends AbstractBeanCollector {
|
||||
throw new CloudRuntimeException(e);
|
||||
} catch (Exception 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());
|
||||
|
||||
if (set == null) {
|
||||
set = new HashSet<ComponentLifecycle>();
|
||||
set = new HashSet<>();
|
||||
sorted.put(lifecycle.getRunLevel(), set);
|
||||
}
|
||||
|
||||
@ -169,12 +165,7 @@ public class CloudStackExtendedLifeCycle extends AbstractBeanCollector {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPhase() {
|
||||
return 2000;
|
||||
}
|
||||
|
||||
private static interface WithComponentLifeCycle {
|
||||
private interface WithComponentLifeCycle {
|
||||
public void with(ComponentLifecycle lifecycle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ public class RegistryLifecycle implements BeanPostProcessor, SmartLifecycle, App
|
||||
* can use this.
|
||||
*/
|
||||
String registryBeanName;
|
||||
Set<Object> beans = new HashSet<Object>();
|
||||
Set<Object> beans = new HashSet<>();
|
||||
Class<?> typeClass;
|
||||
ApplicationContext applicationContext;
|
||||
Set<String> excludes = null;
|
||||
@ -79,7 +79,7 @@ public class RegistryLifecycle implements BeanPostProcessor, SmartLifecycle, App
|
||||
|
||||
protected synchronized void loadExcluded() {
|
||||
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*")) {
|
||||
if (StringUtils.hasText(exclude)) {
|
||||
excludes.add(exclude);
|
||||
@ -109,10 +109,15 @@ public class RegistryLifecycle implements BeanPostProcessor, SmartLifecycle, App
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Object next = iter.next();
|
||||
if (registry.register(next)) {
|
||||
logger.debug("Registered " + next);
|
||||
} else {
|
||||
iter.remove();
|
||||
try {
|
||||
if (registry.register(next)) {
|
||||
logger.debug("Registered " + next);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API
|
||||
private RoleService roleService;
|
||||
|
||||
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, Pair<Role, List<RolePermission>>> rolePermissionsCache;
|
||||
@ -56,7 +56,7 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API
|
||||
protected DynamicRoleBasedAPIAccessChecker() {
|
||||
super();
|
||||
for (RoleType roleType : RoleType.values()) {
|
||||
annotationRoleBasedApisMap.put(roleType, new HashSet<String>());
|
||||
annotationRoleBasedApisMap.put(roleType, new HashSet<>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3133,7 +3133,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
disk.setLogicalBlockIOSize(pool.getSupportedLogicalBlockSize());
|
||||
disk.setPhysicalBlockIOSize(pool.getSupportedPhysicalBlockSize());
|
||||
|
||||
if (diskBusType == DiskDef.DiskBus.SCSI ) {
|
||||
if (diskBusType == DiskDef.DiskBus.SCSI || diskBusType == DiskDef.DiskBus.VIRTIOBLK) {
|
||||
disk.setQemuDriver(true);
|
||||
disk.setDiscard(DiscardType.UNMAP);
|
||||
}
|
||||
@ -3204,7 +3204,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
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());
|
||||
DiskDef.LibvirtDiskEncryptDetails encryptDetails = new DiskDef.LibvirtDiskEncryptDetails(secretUuid, QemuObject.EncryptFormat.enumValue(volumeObjectTO.getEncryptFormat()));
|
||||
disk.setLibvirtDiskEncryptDetails(encryptDetails);
|
||||
|
||||
@ -248,7 +248,9 @@ public class LibvirtVMDef {
|
||||
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");
|
||||
if (iothreads) {
|
||||
guestDef.append(String.format("<iothreads>%s</iothreads>", NUMBER_OF_IOTHREADS));
|
||||
@ -678,7 +680,7 @@ public class LibvirtVMDef {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
DiskBus(String bus) {
|
||||
|
||||
@ -122,7 +122,10 @@ public final class LibvirtGetUnmanagedInstancesCommandWrapper extends CommandWra
|
||||
instance.setName(domain.getName());
|
||||
|
||||
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) {
|
||||
instance.setCpuCoresPerSocket(parser.getCpuModeDef().getCoresPerSocket());
|
||||
|
||||
@ -125,6 +125,7 @@ import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtUtilitiesHelper;
|
||||
import com.cloud.storage.JavaStorageLayer;
|
||||
import com.cloud.storage.MigrationOptions;
|
||||
import com.cloud.storage.ScopeType;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StorageLayer;
|
||||
@ -161,7 +162,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
/**
|
||||
* Time interval before rechecking virsh commands
|
||||
*/
|
||||
private long waitDelayForVirshCommands = 1000l;
|
||||
private final long waitDelayForVirshCommands = 1000L;
|
||||
|
||||
public KVMStorageProcessor(final KVMStoragePoolManager storagePoolMgr, final LibvirtComputingResource resource) {
|
||||
this.storagePoolMgr = storagePoolMgr;
|
||||
@ -258,7 +259,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
logger.debug("Copying template to primary storage, template format is " + tmplVol.getFormat() );
|
||||
final KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
|
||||
|
||||
KVMPhysicalDisk primaryVol = null;
|
||||
KVMPhysicalDisk primaryVol;
|
||||
if (destData instanceof VolumeObjectTO) {
|
||||
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
|
||||
@ -277,8 +278,13 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
|
||||
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());
|
||||
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());
|
||||
@ -336,12 +342,13 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
}
|
||||
|
||||
private String derivePath(PrimaryDataStoreTO primaryStore, DataTO destData, Map<String, String> details) {
|
||||
String path = null;
|
||||
String path;
|
||||
if (primaryStore.getPoolType() == StoragePoolType.FiberChannel) {
|
||||
path = destData.getPath();
|
||||
} else {
|
||||
path = details != null ? details.get("managedStoreTarget") : null;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
final KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(templateVol, volUuid, primaryPool, timeout);
|
||||
return primaryVol;
|
||||
return storagePoolMgr.copyPhysicalDisk(templateVol, volUuid, primaryPool, timeout);
|
||||
} catch (final CloudRuntimeException e) {
|
||||
logger.error("Failed to download template to primary storage", e);
|
||||
return null;
|
||||
@ -410,9 +416,9 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
final DataStoreTO imageStore = template.getDataStore();
|
||||
final VolumeObjectTO volume = (VolumeObjectTO)destData;
|
||||
final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
|
||||
KVMPhysicalDisk BaseVol = null;
|
||||
KVMStoragePool primaryPool = null;
|
||||
KVMPhysicalDisk vol = null;
|
||||
KVMPhysicalDisk BaseVol;
|
||||
KVMStoragePool primaryPool;
|
||||
KVMPhysicalDisk vol;
|
||||
|
||||
try {
|
||||
primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
|
||||
@ -420,7 +426,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
String templatePath = template.getPath();
|
||||
|
||||
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());
|
||||
} if (storagePoolMgr.supportsPhysicalDiskCopy(primaryPool.getType())) {
|
||||
Map<String, String> details = primaryStore.getDetails();
|
||||
@ -778,15 +784,19 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
|
||||
KVMStoragePool secondaryStorage = null;
|
||||
|
||||
String path = null;
|
||||
try {
|
||||
// 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
|
||||
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) {
|
||||
path = details != null ? details.get(DiskTO.IQN) : 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.save();
|
||||
|
||||
storagePoolMgr.disconnectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), path);
|
||||
|
||||
TemplateObjectTO newTemplate = new TemplateObjectTO();
|
||||
|
||||
newTemplate.setPath(templateFolder + File.separator + templateName + ".qcow2");
|
||||
@ -870,6 +878,10 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
|
||||
return new CopyCmdAnswer(ex.toString());
|
||||
} finally {
|
||||
if (path != null) {
|
||||
storagePoolMgr.disconnectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), path);
|
||||
}
|
||||
|
||||
if (secondaryStorage != null) {
|
||||
secondaryStorage.delete();
|
||||
}
|
||||
@ -1045,7 +1057,9 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
command.add(NAME_OPTION, snapshotName);
|
||||
command.add("-p", snapshotDestPath);
|
||||
|
||||
descName = UUID.randomUUID().toString();
|
||||
if (isCreatedFromVmSnapshot) {
|
||||
descName = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
command.add("-t", descName);
|
||||
final String result = command.execute();
|
||||
@ -1415,12 +1429,14 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
if (disk.getDeviceType() == DeviceType.DISK) {
|
||||
if (disk.getBusType() == DiskDef.DiskBus.SCSI) {
|
||||
busT = DiskDef.DiskBus.SCSI;
|
||||
} else if (disk.getBusType() == DiskDef.DiskBus.VIRTIOBLK) {
|
||||
busT = DiskDef.DiskBus.VIRTIOBLK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
diskdef = new DiskDef();
|
||||
if (busT == DiskDef.DiskBus.SCSI) {
|
||||
if (busT == DiskDef.DiskBus.SCSI || busT == DiskDef.DiskBus.VIRTIOBLK) {
|
||||
diskdef.setQemuDriver(true);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -162,6 +162,13 @@ public abstract class MultipathSCSIAdapterBase implements StorageAdaptor {
|
||||
KVMPhysicalDisk disk = new KVMPhysicalDisk(address.getPath(), address.toString(), pool);
|
||||
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());
|
||||
disk.setSize(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
|
||||
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
|
||||
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");
|
||||
@ -510,6 +521,18 @@ public abstract class MultipathSCSIAdapterBase implements StorageAdaptor {
|
||||
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) {
|
||||
if (StringUtils.isEmpty(diskPath)) {
|
||||
return 0;
|
||||
|
||||
@ -6531,4 +6531,14 @@ public class LibvirtComputingResourceTest {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.cloud.agent.api.CleanupVMCommand;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
@ -370,6 +371,13 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
|
||||
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) {
|
||||
List<Command> commands = new ArrayList<Command>();
|
||||
List<NicVO> nicVOs = nicDao.listByVmId(vm.getId());
|
||||
|
||||
@ -22,12 +22,15 @@ import com.cloud.dc.VmwareDatacenterVO;
|
||||
import com.cloud.dc.VsphereStoragePolicy;
|
||||
import com.cloud.exception.DiscoveryException;
|
||||
import com.cloud.exception.ResourceInUseException;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.PluggableService;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
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.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.ListVsphereStoragePoliciesCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd;
|
||||
@ -53,5 +56,7 @@ public interface VmwareDatacenterService extends PluggableService {
|
||||
|
||||
List<StoragePool> listVsphereStoragePolicyCompatibleStoragePools(ListVsphereStoragePolicyCompatiblePoolsCmd cmd);
|
||||
|
||||
List<UnmanagedInstanceTO> listVMsInDatacenter(ListVmwareDcVmsCmd cmd);
|
||||
List<HostMO> listHostsInDatacenter(ListVmwareDcHostsCmd cmd);
|
||||
|
||||
Pair<String, List<UnmanagedInstanceTO>> listVMsInDatacenter(ListVmwareDcVmsCmd cmd);
|
||||
}
|
||||
|
||||
@ -19,10 +19,12 @@ package com.cloud.hypervisor.vmware.manager;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.rmi.RemoteException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
@ -43,10 +45,11 @@ import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
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.ImportVsphereStoragePoliciesCmd;
|
||||
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.ListVsphereStoragePoliciesCmd;
|
||||
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.ClusterVSMMapVO;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.VmwareDatacenter;
|
||||
import com.cloud.dc.VsphereStoragePolicy;
|
||||
import com.cloud.dc.VsphereStoragePolicyVO;
|
||||
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.vmware.LegacyZoneVO;
|
||||
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.dc.VmwareDatacenterVO;
|
||||
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.dao.UserVmCloneSettingDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
// TODO move these items upstream?
|
||||
import com.vmware.pbm.PbmProfile;
|
||||
import com.vmware.vim25.AboutInfo;
|
||||
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 {
|
||||
|
||||
@ -245,11 +257,11 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
private StorageLayer _storage;
|
||||
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 _instanceNameFlag;
|
||||
private String _serviceConsoleName;
|
||||
private String _managemetPortGroupName;
|
||||
private String _managementPortGroupName;
|
||||
private String _defaultSystemVmNicAdapterType = VirtualEthernetCardType.E1000.toString();
|
||||
private String _recycleHungWorker = "false";
|
||||
private int _additionalPortRangeStart;
|
||||
@ -263,7 +275,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
|
||||
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 GlobalLock _exclusiveOpLock = GlobalLock.getInternLock("vmware.exclusive.op");
|
||||
@ -347,9 +359,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
_serviceConsoleName = "Service Console";
|
||||
}
|
||||
|
||||
_managemetPortGroupName = _configDao.getValue(Config.VmwareManagementPortGroup.key());
|
||||
if (_managemetPortGroupName == null) {
|
||||
_managemetPortGroupName = "Management Network";
|
||||
_managementPortGroupName = _configDao.getValue(Config.VmwareManagementPortGroup.key());
|
||||
if (_managementPortGroupName == null) {
|
||||
_managementPortGroupName = "Management Network";
|
||||
}
|
||||
|
||||
_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);
|
||||
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) {
|
||||
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();
|
||||
if (about != null) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -480,7 +492,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
}
|
||||
|
||||
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) {
|
||||
return null;
|
||||
}
|
||||
@ -496,19 +508,18 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
throw new CloudRuntimeException("Invalid serviceContext");
|
||||
}
|
||||
ManagedObjectReference mor = serviceContext.getHostMorByPath(hostInventoryPath);
|
||||
String privateTrafficLabel = null;
|
||||
String privateTrafficLabel;
|
||||
privateTrafficLabel = serviceContext.getStockObject("privateTrafficLabel");
|
||||
if (privateTrafficLabel == null) {
|
||||
privateTrafficLabel = _privateNetworkVSwitchName;
|
||||
}
|
||||
|
||||
if (mor != null) {
|
||||
List<ManagedObjectReference> returnedHostList = new ArrayList<ManagedObjectReference>();
|
||||
List<ManagedObjectReference> returnedHostList = new ArrayList<>();
|
||||
|
||||
if (mor.getType().equals("ComputeResource")) {
|
||||
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
|
||||
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");
|
||||
assert (hosts != null);
|
||||
|
||||
if (hosts.size() > 0) {
|
||||
AboutInfo about = (AboutInfo)(serviceContext.getVimClient().getDynamicProperty(hosts.get(0), "config.product"));
|
||||
if (!hosts.isEmpty()) {
|
||||
AboutInfo about = serviceContext.getVimClient().getDynamicProperty(hosts.get(0), "config.product");
|
||||
String version = about.getApiVersion();
|
||||
int maxHostsPerCluster = _hvCapabilitiesDao.getMaxHostsPerCluster(HypervisorType.VMware, version);
|
||||
if (hosts.size() > maxHostsPerCluster) {
|
||||
@ -549,7 +560,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
returnedHostList.add(mor);
|
||||
return returnedHostList;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@ -614,13 +625,13 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
|
||||
@Override
|
||||
public String getManagementPortGroupName() {
|
||||
return _managemetPortGroupName;
|
||||
return _managementPortGroupName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getManagementPortGroupByHost(HostMO hostMo) throws Exception {
|
||||
if (hostMo.getHostType() == VmwareHostType.ESXi) {
|
||||
return _managemetPortGroupName;
|
||||
return _managementPortGroupName;
|
||||
}
|
||||
return _serviceConsoleName;
|
||||
}
|
||||
@ -630,7 +641,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
params.put("vmware.create.full.clone", _fullCloneFlag);
|
||||
params.put("vm.instancename.flag", _instanceNameFlag);
|
||||
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.data.disk.controller", _dataDiskController);
|
||||
params.put("vmware.recycle.hung.wokervm", _recycleHungWorker);
|
||||
@ -657,23 +668,23 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
return false;
|
||||
}
|
||||
|
||||
String tokens[] = workerTag.split("-");
|
||||
String[] tokens = workerTag.split("-");
|
||||
if (tokens.length != 3) {
|
||||
logger.error("Invalid worker VM tag " + workerTag);
|
||||
return false;
|
||||
}
|
||||
|
||||
long startTick = Long.parseLong(tokens[0]);
|
||||
long msid = Long.parseLong(tokens[1]);
|
||||
long runid = Long.parseLong(tokens[2]);
|
||||
long msId = Long.parseLong(tokens[1]);
|
||||
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())
|
||||
logger.info("Worker VM's owner management server node has been detected down from peer nodes, recycle it");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (runid != clusterManager.getManagementRunId(msid)) {
|
||||
if (runId != clusterManager.getManagementRunId(msId)) {
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("Worker VM's owner management server has changed runid, recycle it");
|
||||
return true;
|
||||
@ -710,7 +721,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
File patchFolder = new File(mountPoint + "/systemvm");
|
||||
if (!patchFolder.exists()) {
|
||||
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);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
@ -729,7 +740,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
} catch (IOException 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);
|
||||
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");
|
||||
}
|
||||
|
||||
assert (isoFile != null);
|
||||
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;
|
||||
}
|
||||
@ -788,16 +798,16 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
if (keyFile == null || !keyFile.exists()) {
|
||||
keyFile = new File("/usr/share/cloudstack-common/scripts/vm/systemvm/id_rsa.cloud");
|
||||
}
|
||||
assert (keyFile != null);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMountPoint(String storageUrl, String nfsVersion) {
|
||||
String mountPoint = null;
|
||||
String mountPoint;
|
||||
synchronized (_storageMounts) {
|
||||
mountPoint = _storageMounts.get(storageUrl);
|
||||
if (mountPoint != null) {
|
||||
@ -827,7 +837,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
String mountPoint = null;
|
||||
long mshostId = ManagementServerNode.getManagementServerId();
|
||||
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);
|
||||
if (!file.exists()) {
|
||||
if (_storage.mkdir(mntPt)) {
|
||||
@ -852,10 +862,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
for (String mountPoint : mounts) {
|
||||
logger.info("umount NFS mount from previous session: " + mountPoint);
|
||||
|
||||
String result = null;
|
||||
Script command = new Script(true, "umount", _timeout, logger);
|
||||
command.add(mountPoint);
|
||||
result = command.execute();
|
||||
String result = command.execute();
|
||||
if (result != null) {
|
||||
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()) {
|
||||
logger.info("umount NFS mount: " + mountPoint);
|
||||
|
||||
String result = null;
|
||||
Script command = new Script(true, "umount", _timeout, logger);
|
||||
command.add(mountPoint);
|
||||
result = command.execute();
|
||||
String result = command.execute();
|
||||
if (result != null) {
|
||||
logger.warn("Unable to umount " + mountPoint + " due to " + result);
|
||||
}
|
||||
@ -894,8 +902,8 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
return null;
|
||||
}
|
||||
|
||||
Script script = null;
|
||||
String result = null;
|
||||
Script script;
|
||||
String result;
|
||||
Script command = new Script(true, "mount", _timeout, logger);
|
||||
command.add("-t", "nfs");
|
||||
if (nfsVersion != null){
|
||||
@ -982,11 +990,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
|
||||
@Override
|
||||
public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) {
|
||||
if (cmd instanceof StartupCommand) {
|
||||
if (cmd != null) {
|
||||
if (host.getHypervisorType() == HypervisorType.VMware) {
|
||||
updateClusterNativeHAState(host, cmd);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1056,16 +1062,16 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
|
||||
@Override
|
||||
public Pair<Integer, Integer> getAddiionalVncPortRange() {
|
||||
return new Pair<Integer, Integer>(_additionalPortRangeStart, _additionalPortRangeSize);
|
||||
return new Pair<>(_additionalPortRangeStart, _additionalPortRangeSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getNexusVSMCredentialsByClusterId(Long clusterId) {
|
||||
CiscoNexusVSMDeviceVO nexusVSM = null;
|
||||
ClusterVSMMapVO vsmMapVO = null;
|
||||
CiscoNexusVSMDeviceVO nexusVSM;
|
||||
ClusterVSMMapVO vsmMapVO;
|
||||
|
||||
vsmMapVO = _vsmMapDao.findByClusterId(clusterId);
|
||||
long vsmId = 0;
|
||||
long vsmId;
|
||||
if (vsmMapVO != null) {
|
||||
vsmId = vsmMapVO.getVsmId();
|
||||
logger.info("vsmId is " + vsmId);
|
||||
@ -1076,7 +1082,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, String> nexusVSMCredentials = new HashMap<String, String>();
|
||||
Map<String, String> nexusVSMCredentials = new HashMap<>();
|
||||
if (nexusVSM != null) {
|
||||
nexusVSMCredentials.put("vsmip", nexusVSM.getipaddr());
|
||||
nexusVSMCredentials.put("vsmusername", nexusVSM.getUserName());
|
||||
@ -1103,7 +1109,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
|
||||
@Override
|
||||
public List<Class<?>> getCommands() {
|
||||
List<Class<?>> cmdList = new ArrayList<Class<?>>();
|
||||
List<Class<?>> cmdList = new ArrayList<>();
|
||||
cmdList.add(AddVmwareDcCmd.class);
|
||||
cmdList.add(UpdateVmwareDcCmd.class);
|
||||
cmdList.add(RemoveVmwareDcCmd.class);
|
||||
@ -1112,13 +1118,14 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
cmdList.add(ListVsphereStoragePoliciesCmd.class);
|
||||
cmdList.add(ListVsphereStoragePolicyCompatiblePoolsCmd.class);
|
||||
cmdList.add(ListVmwareDcVmsCmd.class);
|
||||
cmdList.add(ListVmwareDcHostsCmd.class);
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public VmwareDatacenterVO addVmwareDatacenter(AddVmwareDcCmd cmd) throws ResourceInUseException {
|
||||
VmwareDatacenterVO vmwareDc = null;
|
||||
VmwareDatacenterVO vmwareDc;
|
||||
Long zoneId = cmd.getZoneId();
|
||||
String userName = cmd.getUsername();
|
||||
String password = cmd.getPassword();
|
||||
@ -1174,10 +1181,10 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
checkIfDcIsUsed(vCenterHost, vmwareDcName, zoneId);
|
||||
|
||||
VmwareContext context = null;
|
||||
DatacenterMO dcMo = null;
|
||||
DatacenterMO dcMo;
|
||||
String dcCustomFieldValue;
|
||||
boolean addDcCustomFieldDef = false;
|
||||
boolean dcInUse = false;
|
||||
boolean dcInUse;
|
||||
String guid;
|
||||
ManagedObjectReference dcMor;
|
||||
try {
|
||||
@ -1210,7 +1217,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
// Map zone with vmware datacenter
|
||||
vmwareDcZoneMap = new VmwareDatacenterZoneMapVO(zoneId, vmwareDc.getId());
|
||||
|
||||
vmwareDcZoneMap = vmwareDatacenterZoneMapDao.persist(vmwareDcZoneMap);
|
||||
vmwareDatacenterZoneMapDao.persist(vmwareDcZoneMap);
|
||||
|
||||
// Set custom field for this DC
|
||||
if (addDcCustomFieldDef) {
|
||||
@ -1230,7 +1237,6 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
if (context != null) {
|
||||
context.close();
|
||||
}
|
||||
context = null;
|
||||
}
|
||||
importVsphereStoragePoliciesInternal(zoneId, vmwareDc.getId());
|
||||
return vmwareDc;
|
||||
@ -1255,9 +1261,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
* 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
|
||||
*
|
||||
* @param vCenterHost
|
||||
* @param vmwareDcName
|
||||
* @param zoneId
|
||||
* @param vCenterHost the vcenter appliance hostname
|
||||
* @param vmwareDcName the name of the vmware DC
|
||||
* @param zoneId zone that the DC should be connected to
|
||||
* @throws ResourceInUseException if the DC can not be used.
|
||||
*/
|
||||
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);
|
||||
if (vmwareDc != null) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -1274,7 +1280,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_ZONE_EDIT, eventDescription = "updating VMware datacenter")
|
||||
public VmwareDatacenter updateVmwareDatacenter(UpdateVmwareDcCmd cmd) {
|
||||
final Long zoneId = cmd.getZoneId();
|
||||
final long zoneId = cmd.getZoneId();
|
||||
final String userName = cmd.getUsername();
|
||||
final String password = cmd.getPassword();
|
||||
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()));
|
||||
|
||||
return Transaction.execute(new TransactionCallback<VmwareDatacenter>() {
|
||||
return Transaction.execute(new TransactionCallback<>() {
|
||||
@Override
|
||||
public VmwareDatacenter doInTransaction(TransactionStatus status) {
|
||||
if (vmwareDcDao.update(vmwareDc.getId(), vmwareDc)) {
|
||||
@ -1351,7 +1357,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
String vCenterHost;
|
||||
String userName;
|
||||
String password;
|
||||
DatacenterMO dcMo = null;
|
||||
DatacenterMO dcMo;
|
||||
final VmwareDatacenterZoneMapVO vmwareDcZoneMap = vmwareDatacenterZoneMapDao.findByZoneId(zoneId);
|
||||
// Check if zone is associated with VMware DC
|
||||
if (vmwareDcZoneMap == null) {
|
||||
@ -1388,11 +1394,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
throw new DiscoveryException(msg);
|
||||
}
|
||||
|
||||
assert (dcMo != null);
|
||||
|
||||
// Reset custom field property cloud.zone over this DC
|
||||
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) {
|
||||
String msg = "Unable to reset custom field property cloud.zone over DC " + vmwareDcName + " due to : " + VmwareHelper.getExceptionMessage(e);
|
||||
logger.error(msg);
|
||||
@ -1401,7 +1405,6 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
if (context != null) {
|
||||
context.close();
|
||||
}
|
||||
context = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1422,7 +1425,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
private void validateZoneWithResources(Long zoneId, String errStr) throws ResourceInUseException {
|
||||
// Check if zone has resources? - For now look for clusters
|
||||
List<ClusterVO> clusters = clusterDao.listByZoneId(zoneId);
|
||||
if (clusters != null && clusters.size() > 0) {
|
||||
if (!CollectionUtils.isNullOrEmpty(clusters)) {
|
||||
// Look for VMware hypervisor.
|
||||
for (ClusterVO cluster : clusters) {
|
||||
if (cluster.getHypervisorType().equals(HypervisorType.VMware)) {
|
||||
@ -1443,9 +1446,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends VmwareDatacenter> listVmwareDatacenters(ListVmwareDcsCmd cmd) throws CloudRuntimeException, InvalidParameterValueException {
|
||||
public List<? extends VmwareDatacenter> listVmwareDatacenters(ListVmwareDcsCmd cmd) throws CloudRuntimeException {
|
||||
Long zoneId = cmd.getZoneId();
|
||||
List<VmwareDatacenterVO> vmwareDcList = new ArrayList<VmwareDatacenterVO>();
|
||||
List<VmwareDatacenterVO> vmwareDcList = new ArrayList<>();
|
||||
VmwareDatacenterZoneMapVO vmwareDcZoneMap;
|
||||
VmwareDatacenterVO vmwareDatacenter;
|
||||
long vmwareDcId;
|
||||
@ -1503,7 +1506,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
String vCenterHost = vmwareDatacenter.getVcenterHost();
|
||||
String userName = vmwareDatacenter.getUser();
|
||||
String password = vmwareDatacenter.getPassword();
|
||||
List<PbmProfile> storageProfiles = null;
|
||||
List<PbmProfile> storageProfiles;
|
||||
try {
|
||||
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);
|
||||
@ -1531,16 +1534,15 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
List<VsphereStoragePolicyVO> allStoragePolicies = vsphereStoragePolicyDao.listAll();
|
||||
List<PbmProfile> finalStorageProfiles = storageProfiles;
|
||||
List<VsphereStoragePolicyVO> needToMarkRemoved = allStoragePolicies.stream()
|
||||
.filter(existingPolicy -> !finalStorageProfiles.stream()
|
||||
.anyMatch(storageProfile -> storageProfile.getProfileId().getUniqueId().equals(existingPolicy.getPolicyId())))
|
||||
.filter(existingPolicy -> finalStorageProfiles.stream()
|
||||
.noneMatch(storageProfile -> storageProfile.getProfileId().getUniqueId().equals(existingPolicy.getPolicyId())))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (VsphereStoragePolicyVO storagePolicy : needToMarkRemoved) {
|
||||
vsphereStoragePolicyDao.remove(storagePolicy.getId());
|
||||
}
|
||||
|
||||
List<VsphereStoragePolicyVO> storagePolicies = vsphereStoragePolicyDao.listAll();
|
||||
return storagePolicies;
|
||||
return vsphereStoragePolicyDao.listAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1586,13 +1588,87 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
}
|
||||
|
||||
@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 datacenterName = cmd.getDatacenterName();
|
||||
String username = cmd.getUsername();
|
||||
String password = cmd.getPassword();
|
||||
Long existingVcenterId = cmd.getExistingVcenterId();
|
||||
String keyword = cmd.getKeyword();
|
||||
|
||||
if ((existingVcenterId == null && StringUtils.isBlank(vcenter)) ||
|
||||
(existingVcenterId != null && StringUtils.isNotBlank(vcenter))) {
|
||||
@ -1613,37 +1689,27 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
username = vmwareDc.getUser();
|
||||
password = vmwareDc.getPassword();
|
||||
}
|
||||
VcenterData vmwaredc = new VcenterData(vcenter, datacenterName, username, password);
|
||||
return vmwaredc;
|
||||
}
|
||||
|
||||
try {
|
||||
logger.debug(String.format("Connecting to the VMware datacenter %s at vCenter %s to retrieve VMs",
|
||||
datacenterName, vcenter));
|
||||
String serviceUrl = String.format("https://%s/sdk/vimService", vcenter);
|
||||
VmwareClient vimClient = new VmwareClient(vcenter);
|
||||
vimClient.connect(serviceUrl, username, password);
|
||||
VmwareContext context = new VmwareContext(vimClient, vcenter);
|
||||
private static class VcenterData {
|
||||
public final String vcenter;
|
||||
public final String datacenterName;
|
||||
public final String username;
|
||||
public final String password;
|
||||
|
||||
DatacenterMO dcMo = new DatacenterMO(context, datacenterName);
|
||||
ManagedObjectReference dcMor = dcMo.getMor();
|
||||
if (dcMor == null) {
|
||||
String msg = String.format("Unable to find VMware datacenter %s in vCenter %s",
|
||||
datacenterName, vcenter);
|
||||
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);
|
||||
public VcenterData(String vcenter, String datacenterName, String username, String password) {
|
||||
this.vcenter = vcenter;
|
||||
this.datacenterName = datacenterName;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNexusVSM(Long clusterId) {
|
||||
ClusterVSMMapVO vsmMapVo = null;
|
||||
ClusterVSMMapVO vsmMapVo;
|
||||
|
||||
vsmMapVo = _vsmMapDao.findByClusterId(clusterId);
|
||||
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 collect all templates that
|
||||
* - are deleted from cloudstack
|
||||
|
||||
@ -45,6 +45,7 @@ import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.cloud.agent.api.CleanupVMCommand;
|
||||
import javax.naming.ConfigurationException;
|
||||
import javax.xml.datatype.XMLGregorianCalendar;
|
||||
|
||||
@ -583,6 +584,8 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
||||
return execute((ResizeVolumeCommand) cmd);
|
||||
} else if (clz == UnregisterVMCommand.class) {
|
||||
return execute((UnregisterVMCommand) cmd);
|
||||
} else if (clz == CleanupVMCommand.class) {
|
||||
return execute((CleanupVMCommand) cmd);
|
||||
} else if (cmd instanceof StorageSubSystemCommand) {
|
||||
checkStorageProcessorAndHandlerNfsVersionAttribute((StorageSubSystemCommand) cmd);
|
||||
return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd);
|
||||
@ -5796,6 +5799,26 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
||||
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) {
|
||||
VmwareContext context = getServiceContext();
|
||||
VmwareHypervisorHost hyperHost = getHyperHost(context);
|
||||
|
||||
@ -36,8 +36,8 @@ import com.cloud.dc.VmwareDatacenterVO;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@APICommand(name = "addVmwareDc", description = "Adds a VMware datacenter to specified zone", responseObject = VmwareDatacenterResponse.class,
|
||||
requestHasSensitiveInfo = true, responseHasSensitiveInfo = false)
|
||||
@APICommand(name = "addVmwareDc", description = "Adds a Vmware datacenter to specified zone",
|
||||
responseObject = VmwareDatacenterResponse.class, responseHasSensitiveInfo = false)
|
||||
public class AddVmwareDcCmd extends BaseCmd {
|
||||
|
||||
@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;
|
||||
|
||||
@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.")
|
||||
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;
|
||||
|
||||
@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;
|
||||
|
||||
@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.setObjectName("vmwaredc");
|
||||
} 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);
|
||||
} catch (DiscoveryException ex) {
|
||||
|
||||
@ -48,8 +48,6 @@ import java.util.List;
|
||||
authorized = {RoleType.Admin})
|
||||
public class ImportVsphereStoragePoliciesCmd extends BaseCmd {
|
||||
|
||||
|
||||
|
||||
@Inject
|
||||
public VmwareDatacenterService _vmwareDatacenterService;
|
||||
|
||||
@ -74,6 +72,13 @@ public class ImportVsphereStoragePoliciesCmd extends BaseCmd {
|
||||
|
||||
List<? extends VsphereStoragePolicy> storagePolicies = _vmwareDatacenterService.importVsphereStoragePolicies(this);
|
||||
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<>();
|
||||
for (VsphereStoragePolicy storagePolicy : storagePolicies) {
|
||||
final VsphereStoragePoliciesResponse storagePoliciesResponse = new VsphereStoragePoliciesResponse();
|
||||
@ -86,9 +91,7 @@ public class ImportVsphereStoragePoliciesCmd extends BaseCmd {
|
||||
|
||||
storagePoliciesResponseList.add(storagePoliciesResponse);
|
||||
}
|
||||
responseList.setResponses(storagePoliciesResponseList);
|
||||
responseList.setResponseName(getCommandName());
|
||||
setResponseObject(responseList);
|
||||
return storagePoliciesResponseList;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -23,15 +23,15 @@ import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.hypervisor.vmware.VmwareDatacenterService;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
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.Parameter;
|
||||
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.VmwareDatacenterResponse;
|
||||
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
|
||||
@ -42,10 +42,10 @@ import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@APICommand(name = "listVmwareDcVms", responseObject = UnmanagedInstanceResponse.class,
|
||||
description = "Lists the VMs in a VMware Datacenter",
|
||||
@APICommand(name = "listVmwareDcVms", responseObject = VmwareRequestResponse.class,
|
||||
description = "Lists the VMs in a Vmware Datacenter",
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class ListVmwareDcVmsCmd extends BaseListCmd {
|
||||
public class ListVmwareDcVmsCmd extends BaseCmd implements ListVmwareDcItems {
|
||||
|
||||
@Inject
|
||||
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.")
|
||||
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;
|
||||
|
||||
@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.")
|
||||
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() {
|
||||
return vcenter;
|
||||
}
|
||||
@ -82,6 +94,18 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
|
||||
return password;
|
||||
}
|
||||
|
||||
public Integer getBatchSize() {
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public String getDatacenterName() {
|
||||
return datacenterName;
|
||||
}
|
||||
@ -94,7 +118,8 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
|
||||
checkParameters();
|
||||
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<>();
|
||||
if (CollectionUtils.isNotEmpty(vms)) {
|
||||
for (UnmanagedInstanceTO vmwareVm : vms) {
|
||||
@ -102,16 +127,13 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
|
||||
baseResponseList.add(resp);
|
||||
}
|
||||
}
|
||||
List<BaseResponse> pagingList = com.cloud.utils.StringUtils.applyPagination(baseResponseList, this.getStartIndex(), this.getPageSizeVal());
|
||||
if (CollectionUtils.isEmpty(pagingList)) {
|
||||
pagingList = baseResponseList;
|
||||
}
|
||||
ListResponse<BaseResponse> response = new ListResponse<>();
|
||||
response.setResponses(pagingList, baseResponseList.size());
|
||||
VmwareRequestResponse<BaseResponse> response = new VmwareRequestResponse<>();
|
||||
response.setResponses(baseResponseList, baseResponseList.size());
|
||||
response.setResponseName(getCommandName());
|
||||
response.setToken(results.first());
|
||||
setResponseObject(response);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
@ -134,6 +156,6 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return "listvmwaredcvmsresponse";
|
||||
return "listVmwareDcVmsResponse".toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ import com.cloud.dc.VmwareDatacenter;
|
||||
import com.cloud.hypervisor.vmware.VmwareDatacenterService;
|
||||
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)
|
||||
public class ListVmwareDcsCmd extends BaseListCmd {
|
||||
|
||||
@ -50,7 +50,6 @@ public class ListVmwareDcsCmd extends BaseListCmd {
|
||||
public VmwareDatacenterService _vmwareDatacenterService;
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@ -73,20 +72,27 @@ public class ListVmwareDcsCmd extends BaseListCmd {
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
|
||||
ResourceAllocationException {
|
||||
List<? extends VmwareDatacenter> vmwareDcList = null;
|
||||
List<? extends VmwareDatacenter> vmwareDcList;
|
||||
|
||||
try {
|
||||
vmwareDcList = _vmwareDatacenterService.listVmwareDatacenters(this);
|
||||
} catch (InvalidParameterValueException ie) {
|
||||
throw new InvalidParameterValueException("Invalid zone id " + getZoneId());
|
||||
} 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>();
|
||||
List<VmwareDatacenterResponse> vmwareDcResponses = new ArrayList<VmwareDatacenterResponse>();
|
||||
ListResponse<VmwareDatacenterResponse> response = new ListResponse<>();
|
||||
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) {
|
||||
VmwareDatacenterResponse vmwareDcResponse = new VmwareDatacenterResponse();
|
||||
|
||||
@ -94,14 +100,12 @@ public class ListVmwareDcsCmd extends BaseListCmd {
|
||||
vmwareDcResponse.setVcenter(vmwareDc.getVcenterHost());
|
||||
vmwareDcResponse.setName(vmwareDc.getVmwareDatacenterName());
|
||||
vmwareDcResponse.setZoneId(getZoneId());
|
||||
vmwareDcResponse.setObjectName("VMwareDC");
|
||||
vmwareDcResponse.setObjectName(ApiConstants.VMWARE_DC);
|
||||
|
||||
vmwareDcResponses.add(vmwareDcResponse);
|
||||
}
|
||||
}
|
||||
response.setResponses(vmwareDcResponses);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
return vmwareDcResponses;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -47,8 +47,6 @@ import java.util.List;
|
||||
authorized = {RoleType.Admin})
|
||||
public class ListVsphereStoragePoliciesCmd extends BaseCmd {
|
||||
|
||||
|
||||
|
||||
@Inject
|
||||
public VmwareDatacenterService _vmwareDatacenterService;
|
||||
|
||||
@ -73,6 +71,13 @@ public class ListVsphereStoragePoliciesCmd extends BaseCmd {
|
||||
|
||||
List<? extends VsphereStoragePolicy> storagePolicies = _vmwareDatacenterService.listVsphereStoragePolicies(this);
|
||||
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<>();
|
||||
for (VsphereStoragePolicy storagePolicy : storagePolicies) {
|
||||
final VsphereStoragePoliciesResponse storagePoliciesResponse = new VsphereStoragePoliciesResponse();
|
||||
@ -81,13 +86,11 @@ public class ListVsphereStoragePoliciesCmd extends BaseCmd {
|
||||
storagePoliciesResponse.setName(storagePolicy.getName());
|
||||
storagePoliciesResponse.setPolicyId(storagePolicy.getPolicyId());
|
||||
storagePoliciesResponse.setDescription(storagePolicy.getDescription());
|
||||
storagePoliciesResponse.setObjectName("StoragePolicy");
|
||||
storagePoliciesResponse.setObjectName(ApiConstants.STORAGE_POLICY);
|
||||
|
||||
storagePoliciesResponseList.add(storagePoliciesResponse);
|
||||
}
|
||||
responseList.setResponses(storagePoliciesResponseList);
|
||||
responseList.setResponseName(getCommandName());
|
||||
setResponseObject(responseList);
|
||||
return storagePoliciesResponseList;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -68,7 +68,7 @@ public class ListVsphereStoragePolicyCompatiblePoolsCmd extends BaseListCmd {
|
||||
List<StoragePoolResponse> poolResponses = new ArrayList<>();
|
||||
for (StoragePool pool : pools) {
|
||||
StoragePoolResponse poolResponse = _responseGenerator.createStoragePoolForMigrationResponse(pool);
|
||||
poolResponse.setObjectName("storagepool");
|
||||
poolResponse.setObjectName(ApiConstants.STORAGE_POOL);
|
||||
poolResponses.add(poolResponse);
|
||||
}
|
||||
response.setResponses(poolResponses);
|
||||
|
||||
@ -34,7 +34,7 @@ import com.cloud.hypervisor.vmware.VmwareDatacenterService;
|
||||
import com.cloud.user.Account;
|
||||
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)
|
||||
public class RemoveVmwareDcCmd extends BaseCmd {
|
||||
|
||||
@ -47,7 +47,7 @@ public class RemoveVmwareDcCmd extends BaseCmd {
|
||||
type = CommandType.UUID,
|
||||
entityType = ZoneResponse.class,
|
||||
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;
|
||||
|
||||
public Long getZoneId() {
|
||||
@ -63,7 +63,7 @@ public class RemoveVmwareDcCmd extends BaseCmd {
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} 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) {
|
||||
logger.warn("The zone has one or more resources (like cluster), hence not able to remove VMware datacenter from zone."
|
||||
|
||||
@ -33,12 +33,11 @@ import com.cloud.dc.VmwareDatacenter;
|
||||
import com.cloud.hypervisor.vmware.VmwareDatacenterService;
|
||||
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,
|
||||
since = "4.12.0", authorized = {RoleType.Admin})
|
||||
public class UpdateVmwareDcCmd extends BaseCmd {
|
||||
|
||||
|
||||
@Inject
|
||||
public VmwareDatacenterService vmwareDatacenterService;
|
||||
|
||||
@ -51,7 +50,7 @@ public class UpdateVmwareDcCmd extends BaseCmd {
|
||||
private Long zoneId;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING,
|
||||
description = "VMware datacenter name.")
|
||||
description = "Vmware datacenter name.")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.VCENTER, type = CommandType.STRING,
|
||||
@ -106,13 +105,13 @@ public class UpdateVmwareDcCmd extends BaseCmd {
|
||||
public void execute() {
|
||||
final VmwareDatacenter vmwareDatacenter = vmwareDatacenterService.updateVmwareDatacenter(this);
|
||||
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();
|
||||
response.setId(vmwareDatacenter.getUuid());
|
||||
response.setName(vmwareDatacenter.getVmwareDatacenterName());
|
||||
response.setResponseName(getCommandName());
|
||||
response.setObjectName("vmwaredc");
|
||||
response.setObjectName(ApiConstants.VMWARE_DC);
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -23,10 +23,8 @@ import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -206,14 +204,12 @@ public class KubernetesClusterActionWorker {
|
||||
|
||||
protected String getControlNodeLoginUser() {
|
||||
List<KubernetesClusterVmMapVO> vmMapVOList = getKubernetesClusterVMMaps();
|
||||
if (vmMapVOList.size() > 0) {
|
||||
if (!vmMapVOList.isEmpty()) {
|
||||
long vmId = vmMapVOList.get(0).getVmId();
|
||||
UserVmVO userVM = userVmDao.findById(vmId);
|
||||
if (userVM == null) {
|
||||
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);
|
||||
if (vmDetail != null && !org.apache.commons.lang3.StringUtils.isEmpty(vmDetail.getValue())) {
|
||||
return vmDetail.getValue();
|
||||
@ -309,7 +305,7 @@ public class KubernetesClusterActionWorker {
|
||||
}
|
||||
|
||||
protected KubernetesClusterVmMapVO addKubernetesClusterVm(final long kubernetesClusterId, final long vmId, boolean isControlNode) {
|
||||
return Transaction.execute(new TransactionCallback<KubernetesClusterVmMapVO>() {
|
||||
return Transaction.execute(new TransactionCallback<>() {
|
||||
@Override
|
||||
public KubernetesClusterVmMapVO doInTransaction(TransactionStatus status) {
|
||||
KubernetesClusterVmMapVO newClusterVmMap = new KubernetesClusterVmMapVO(kubernetesClusterId, vmId, isControlNode);
|
||||
@ -361,7 +357,12 @@ public class KubernetesClusterActionWorker {
|
||||
}
|
||||
IpAddress address = ipAddressDao.findByUuid(detailsVO.getValue());
|
||||
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 address;
|
||||
@ -517,8 +518,7 @@ public class KubernetesClusterActionWorker {
|
||||
}
|
||||
|
||||
protected List<KubernetesClusterVmMapVO> getKubernetesClusterVMMaps() {
|
||||
List<KubernetesClusterVmMapVO> clusterVMs = kubernetesClusterVmMapDao.listByClusterId(kubernetesCluster.getId());
|
||||
return clusterVMs;
|
||||
return kubernetesClusterVmMapDao.listByClusterId(kubernetesCluster.getId());
|
||||
}
|
||||
|
||||
protected List<KubernetesClusterVmMapVO> getKubernetesClusterVMMapsForNodes(List<Long> nodeIds) {
|
||||
|
||||
@ -193,7 +193,7 @@ public class KubernetesClusterUtil {
|
||||
while (System.currentTimeMillis() < timeoutTime) {
|
||||
try {
|
||||
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);
|
||||
|
||||
if (result.first() && StringUtils.isNotEmpty(result.second())) {
|
||||
|
||||
@ -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/),
|
||||
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]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Volume snapshots on zfs used the wrong dataset path to hide/unhide snapdev
|
||||
|
||||
## [2024-12-19]
|
||||
|
||||
### Added
|
||||
- Native CloudStack encryption support
|
||||
|
||||
## [2024-12-13]
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -97,18 +97,23 @@ public final class LinstorBackupSnapshotCommandWrapper
|
||||
// NOTE: the qemu img will also contain the drbd metadata at the end
|
||||
final QemuImg qemu = new QemuImg(waitMilliSeconds);
|
||||
qemu.convert(srcFile, dstFile);
|
||||
LOGGER.info("Backup snapshot " + srcFile + " to " + dstPath);
|
||||
LOGGER.info("Backup snapshot '{}' to '{}'", srcPath, dstPath);
|
||||
return dstPath;
|
||||
}
|
||||
|
||||
private SnapshotObjectTO setCorrectSnapshotSize(final SnapshotObjectTO dst, final String 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();
|
||||
snapshot.setPath(dst.getPath() + File.separator + dst.getName());
|
||||
snapshot.setPhysicalSize(size);
|
||||
return snapshot;
|
||||
dst.setPath(dst.getPath() + File.separator + dst.getName());
|
||||
dst.setPhysicalSize(size);
|
||||
return dst;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -158,6 +163,7 @@ public final class LinstorBackupSnapshotCommandWrapper
|
||||
LOGGER.info("Backup shrunk " + dstPath + " to actual size " + src.getVolume().getSize());
|
||||
|
||||
SnapshotObjectTO snapshot = setCorrectSnapshotSize(dst, dstPath);
|
||||
LOGGER.info("Actual file size for '{}' is {}", dstPath, snapshot.getPhysicalSize());
|
||||
return new CopyCmdAnswer(snapshot);
|
||||
} catch (final Exception e) {
|
||||
final String error = String.format("Failed to backup snapshot with id [%s] with a pool %s, due to %s",
|
||||
|
||||
@ -61,6 +61,11 @@ import com.linbit.linstor.api.model.Volume;
|
||||
import com.linbit.linstor.api.model.VolumeDefinition;
|
||||
|
||||
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 {
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
@ -202,10 +207,10 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
||||
final DevelopersApi api = getLinstorAPI(pool);
|
||||
|
||||
try {
|
||||
List<ResourceDefinition> definitionList = api.resourceDefinitionList(
|
||||
Collections.singletonList(rscName), null, null, null);
|
||||
ResourceDefinition resourceDefinition = LinstorUtil.findResourceDefinition(
|
||||
api, rscName, lpool.getResourceGroup());
|
||||
|
||||
if (definitionList.isEmpty()) {
|
||||
if (resourceDefinition == null) {
|
||||
ResourceGroupSpawn rgSpawn = new ResourceGroupSpawn();
|
||||
rgSpawn.setResourceDefinitionName(rscName);
|
||||
rgSpawn.addVolumeSizesItem(size / 1024); // linstor uses KiB
|
||||
@ -215,22 +220,28 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
||||
handleLinstorApiAnswers(answers, "Linstor: Unable to spawn resource.");
|
||||
}
|
||||
|
||||
String foundRscName = resourceDefinition != null ? resourceDefinition.getName() : rscName;
|
||||
|
||||
// query linstor for the device path
|
||||
List<ResourceWithVolumes> resources = api.viewResources(
|
||||
Collections.emptyList(),
|
||||
Collections.singletonList(rscName),
|
||||
Collections.singletonList(foundRscName),
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
makeResourceAvailable(api, rscName, false);
|
||||
makeResourceAvailable(api, foundRscName, false);
|
||||
|
||||
if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty()) {
|
||||
final String devPath = resources.get(0).getVolumes().get(0).getDevicePath();
|
||||
logger.info("Linstor: Created drbd device: " + devPath);
|
||||
final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devPath, name, pool);
|
||||
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;
|
||||
} else {
|
||||
logger.error("Linstor: viewResources didn't return resources or volumes.");
|
||||
@ -410,7 +421,7 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
||||
if (rsc.getFlags() != null &&
|
||||
rsc.getFlags().contains(ApiConsts.FLAG_DRBD_DISKLESS) &&
|
||||
!rsc.getFlags().contains(ApiConsts.FLAG_TIE_BREAKER)) {
|
||||
ApiCallRcList delAnswers = api.resourceDelete(rsc.getName(), localNodeName);
|
||||
ApiCallRcList delAnswers = api.resourceDelete(rsc.getName(), localNodeName, true);
|
||||
logLinstorAnswers(delAnswers);
|
||||
}
|
||||
} catch (ApiException apiEx) {
|
||||
@ -473,21 +484,56 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
||||
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
|
||||
public boolean deletePhysicalDisk(String name, KVMStoragePool pool, Storage.ImageFormat format)
|
||||
{
|
||||
logger.debug("Linstor: deletePhysicalDisk " + name);
|
||||
final DevelopersApi api = getLinstorAPI(pool);
|
||||
final String rscName = getLinstorRscName(name);
|
||||
final LinstorStoragePool linstorPool = (LinstorStoragePool) pool;
|
||||
String rscGrpName = linstorPool.getResourceGroup();
|
||||
|
||||
try {
|
||||
final String rscName = getLinstorRscName(name);
|
||||
logger.debug("Linstor: delete resource definition " + rscName);
|
||||
ApiCallRcList answers = api.resourceDefinitionDelete(rscName);
|
||||
handleLinstorApiAnswers(answers, "Linstor: Unable to delete resource definition " + rscName);
|
||||
return deRefOrDeleteResource(api, rscName, rscGrpName);
|
||||
} catch (ApiException apiEx) {
|
||||
logger.error("Linstor: ApiEx - " + apiEx.getMessage());
|
||||
throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -561,6 +607,56 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
||||
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
|
||||
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);
|
||||
|
||||
final DevelopersApi api = getLinstorAPI(destPools);
|
||||
applyAuxProps(api, name, disk.getDispName(), disk.getVmName());
|
||||
setRscDfnAuxProperties(api, disk, destPools, name);
|
||||
|
||||
logger.debug("Linstor.copyPhysicalDisk: dstPath: {}", dstDisk.getPath());
|
||||
final QemuImgFile destFile = new QemuImgFile(dstDisk.getPath());
|
||||
destFile.setFormat(dstDisk.getFormat());
|
||||
destFile.setSize(disk.getVirtualSize());
|
||||
|
||||
boolean zeroedDevice = resourceSupportZeroBlocks(destPools, LinstorUtil.RSC_PREFIX + name);
|
||||
|
||||
boolean zeroedDevice = resourceSupportZeroBlocks(destPools, getLinstorRscName(name));
|
||||
try {
|
||||
final QemuImg qemu = new QemuImg(timeout, zeroedDevice, true);
|
||||
qemu.convert(srcFile, destFile);
|
||||
|
||||
@ -21,11 +21,16 @@ import com.linbit.linstor.api.CloneWaiter;
|
||||
import com.linbit.linstor.api.DevelopersApi;
|
||||
import com.linbit.linstor.api.model.ApiCallRc;
|
||||
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.ResourceDefinition;
|
||||
import com.linbit.linstor.api.model.ResourceDefinitionCloneRequest;
|
||||
import com.linbit.linstor.api.model.ResourceDefinitionCloneStarted;
|
||||
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.ResourceMakeAvailable;
|
||||
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 javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -43,6 +49,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
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.StoragePool;
|
||||
import com.cloud.storage.VMTemplateStoragePoolVO;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VolumeDetailVO;
|
||||
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.DataStore;
|
||||
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.SnapshotInfo;
|
||||
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.storage.RemoteHostEndPoint;
|
||||
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.CreateObjectAnswer;
|
||||
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.VolumeObjectTO;
|
||||
import org.apache.cloudstack.storage.volume.VolumeObject;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver {
|
||||
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);
|
||||
}
|
||||
logger.info(String.format("Linstor: Deleted resource %s", rscDefName));
|
||||
logger.info("Linstor: Deleted resource {}", rscDefName);
|
||||
} catch (ApiException apiEx)
|
||||
{
|
||||
logger.error("Linstor: ApiEx - " + apiEx.getMessage());
|
||||
@ -394,22 +408,166 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||
storagePoolVO.getUserInfo() : "DfltRscGrp";
|
||||
}
|
||||
|
||||
private String createResourceBase(
|
||||
String rscName, long sizeInBytes, String volName, String vmName, DevelopersApi api, String rscGrp) {
|
||||
ResourceGroupSpawn rscGrpSpawn = new ResourceGroupSpawn();
|
||||
rscGrpSpawn.setResourceDefinitionName(rscName);
|
||||
rscGrpSpawn.addVolumeSizesItem(sizeInBytes / 1024);
|
||||
/**
|
||||
* Returns the layerlist of the resourceGroup with encryption(LUKS) added above STORAGE.
|
||||
* If the resourceGroup layer list already contains LUKS this layer list will be returned.
|
||||
* @param api Linstor developers API
|
||||
* @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
|
||||
{
|
||||
logger.info("Linstor: Spawn resource " + rscName);
|
||||
ApiCallRcList answers = api.resourceGroupSpawn(rscGrp, rscGrpSpawn);
|
||||
checkLinstorAnswersThrow(answers);
|
||||
logger.debug("createRscBase: {} :: {} :: {}", rscName, rscGrp, isTemplate);
|
||||
List<Pair<ResourceDefinition, ResourceGroup>> existingRDs = LinstorUtil.getRDAndRGListStartingWith(api, rscName);
|
||||
|
||||
answers = LinstorUtil.applyAuxProps(api, rscName, volName, vmName);
|
||||
checkLinstorAnswersThrow(answers);
|
||||
|
||||
return LinstorUtil.getDevicePath(api, rscName);
|
||||
String fullRscName = String.format("%s-%d", rscName, poolId);
|
||||
boolean alreadyCreated = existingRDs.stream()
|
||||
.anyMatch(p -> p.first().getName().equalsIgnoreCase(fullRscName)) ||
|
||||
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)
|
||||
{
|
||||
logger.error("Linstor: ApiEx - " + apiEx.getMessage());
|
||||
@ -422,8 +580,9 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||
final String rscGrp = getRscGrp(storagePoolVO);
|
||||
|
||||
final String rscName = LinstorUtil.RSC_PREFIX + vol.getUuid();
|
||||
String deviceName = createResourceBase(
|
||||
rscName, vol.getSize(), vol.getName(), vol.getAttachedVmName(), linstorApi, rscGrp);
|
||||
createResourceBase(
|
||||
rscName, vol.getSize(), vol.getName(), vol.getAttachedVmName(), vol.getPassphraseId(), vol.getPassphrase(),
|
||||
linstorApi, rscGrp, storagePoolVO.getId(), false);
|
||||
|
||||
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) {
|
||||
// get the cached template on this storage
|
||||
VMTemplateStoragePoolVO tmplPoolRef = _vmTemplatePoolDao.findByPoolTemplate(
|
||||
storagePoolVO.getId(), csCloneId, 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 DevelopersApi linstorApi = LinstorUtil.getLinstorAPI(storagePoolVO.getHostAddress());
|
||||
|
||||
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();
|
||||
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(
|
||||
cloneRes, cloneRequest);
|
||||
|
||||
@ -479,6 +701,9 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||
resizeResource(linstorApi, rscName, volumeInfo.getSize());
|
||||
}
|
||||
|
||||
updateRscGrpIfNecessary(linstorApi, rscName, getRscGrp(storagePoolVO));
|
||||
|
||||
deleteTemplateForProps(linstorApi, rscName);
|
||||
LinstorUtil.applyAuxProps(linstorApi, rscName, volumeInfo.getName(), volumeInfo.getAttachedVmName());
|
||||
applyQoSSettings(storagePoolVO, linstorApi, rscName, volumeInfo.getMaxIops());
|
||||
|
||||
@ -906,41 +1131,74 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
||||
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) {
|
||||
TemplateInfo tInfo = (TemplateInfo) dstData;
|
||||
final StoragePoolVO pool = _storagePoolDao.findById(dstData.getDataStore().getId());
|
||||
final DevelopersApi api = LinstorUtil.getLinstorAPI(pool.getHostAddress());
|
||||
final String rscName = LinstorUtil.RSC_PREFIX + dstData.getUuid();
|
||||
createResourceBase(
|
||||
boolean newCreated = createResourceBase(
|
||||
LinstorUtil.RSC_PREFIX + dstData.getUuid(),
|
||||
tInfo.getSize(),
|
||||
tInfo.getName(),
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
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;
|
||||
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 {
|
||||
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, rscName);
|
||||
if (optEP.isPresent()) {
|
||||
answer = optEP.get().sendMessage(cmd);
|
||||
}
|
||||
else {
|
||||
answer = new Answer(cmd, false, "Unable to get matching Linstor endpoint.");
|
||||
try {
|
||||
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, rscName);
|
||||
if (optEP.isPresent()) {
|
||||
answer = optEP.get().sendMessage(cmd);
|
||||
} else {
|
||||
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);
|
||||
throw new CloudRuntimeException(exc.getBestMessage());
|
||||
}
|
||||
} catch (ApiException exc) {
|
||||
logger.error("copy template failed: ", exc);
|
||||
deleteResourceDefinition(pool, rscName);
|
||||
throw new CloudRuntimeException(exc.getBestMessage());
|
||||
} else {
|
||||
updateTemplateSpoolRef(dstData.getId(), tInfo.getUuid(), dstData.getDataStore().getId(), srcData.getSize());
|
||||
answer = new Answer(new CopyCmdAnswer(dstData.getTO()));
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ 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.Resource;
|
||||
import com.linbit.linstor.api.model.ResourceDefinition;
|
||||
import com.linbit.linstor.api.model.ResourceDefinitionModify;
|
||||
import com.linbit.linstor.api.model.ResourceGroup;
|
||||
import com.linbit.linstor.api.model.ResourceWithVolumes;
|
||||
@ -37,8 +38,11 @@ import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -49,6 +53,7 @@ public class LinstorUtil {
|
||||
public final static String PROVIDER_NAME = "Linstor";
|
||||
public static final String RSC_PREFIX = "cs-";
|
||||
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";
|
||||
|
||||
@ -288,4 +293,114 @@ public class LinstorUtil {
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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"));
|
||||
}
|
||||
}
|
||||
@ -146,16 +146,18 @@ public class PrimeraAdapter implements ProviderAdapter {
|
||||
}
|
||||
|
||||
// determine volume type based on offering
|
||||
// THIN: tpvv=true, reduce=false
|
||||
// SPARSE: tpvv=true, reduce=true
|
||||
// THICK: tpvv=false, tpZeroFill=true (not supported)
|
||||
// tpvv -- thin provisioned virtual volume (no deduplication)
|
||||
// reduce -- thin provisioned virtual volume (with duplication and compression, also known as DECO)
|
||||
// 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.getType() == ProvisioningType.THIN) {
|
||||
request.setTpvv(true);
|
||||
request.setReduce(false);
|
||||
} else if (diskOffering.getType() == ProvisioningType.SPARSE) {
|
||||
request.setTpvv(false);
|
||||
request.setReduce(true);
|
||||
} else if (diskOffering.getType() == ProvisioningType.SPARSE) {
|
||||
request.setTpvv(true);
|
||||
request.setReduce(false);
|
||||
} else if (diskOffering.getType() == ProvisioningType.FAT) {
|
||||
throw new RuntimeException("This storage provider does not support FAT provisioned volumes");
|
||||
}
|
||||
@ -166,8 +168,16 @@ public class PrimeraAdapter implements ProviderAdapter {
|
||||
}
|
||||
} else {
|
||||
// default to deduplicated volume
|
||||
request.setReduce(true);
|
||||
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));
|
||||
@ -185,8 +195,11 @@ public class PrimeraAdapter implements ProviderAdapter {
|
||||
if (host == null) {
|
||||
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.setAutoLun(true);
|
||||
// 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) {
|
||||
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) {
|
||||
// hostString can be a hostname OR "set:<hostsetname>". It is stored this way
|
||||
// in the appliance and returned as the vlun's name/string.
|
||||
|
||||
2
pom.xml
2
pom.xml
@ -175,7 +175,7 @@
|
||||
<cs.nitro.version>10.1</cs.nitro.version>
|
||||
<cs.opensaml.version>2.6.6</cs.opensaml.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.servicemix.version>3.4.4_1</cs.servicemix.version>
|
||||
<cs.servlet.version>4.0.1</cs.servlet.version>
|
||||
|
||||
@ -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)
|
||||
|
||||
for WWID in $(multipathd list maps status | awk '{ if ($4 == 0) { print substr($1,2); }}'); do
|
||||
./removeVolume.sh ${WWID}
|
||||
./disconnectVolume.sh ${WWID}
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
||||
@ -66,6 +66,9 @@ fi
|
||||
|
||||
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"
|
||||
|
||||
exit 0
|
||||
|
||||
@ -355,263 +355,263 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
private static final String ID_FIELD = "id";
|
||||
|
||||
@Inject
|
||||
private AccountManager accountMgr;
|
||||
AccountManager accountMgr;
|
||||
|
||||
@Inject
|
||||
private ProjectManager _projectMgr;
|
||||
ProjectManager _projectMgr;
|
||||
|
||||
@Inject
|
||||
private DomainDao _domainDao;
|
||||
DomainDao _domainDao;
|
||||
|
||||
@Inject
|
||||
private DomainJoinDao _domainJoinDao;
|
||||
DomainJoinDao _domainJoinDao;
|
||||
|
||||
@Inject
|
||||
private UserAccountJoinDao _userAccountJoinDao;
|
||||
UserAccountJoinDao _userAccountJoinDao;
|
||||
|
||||
@Inject
|
||||
private EventDao eventDao;
|
||||
EventDao eventDao;
|
||||
|
||||
@Inject
|
||||
private EventJoinDao _eventJoinDao;
|
||||
EventJoinDao _eventJoinDao;
|
||||
|
||||
@Inject
|
||||
private ResourceTagJoinDao _resourceTagJoinDao;
|
||||
ResourceTagJoinDao _resourceTagJoinDao;
|
||||
|
||||
@Inject
|
||||
private InstanceGroupJoinDao _vmGroupJoinDao;
|
||||
InstanceGroupJoinDao _vmGroupJoinDao;
|
||||
|
||||
@Inject
|
||||
private UserVmJoinDao _userVmJoinDao;
|
||||
UserVmJoinDao _userVmJoinDao;
|
||||
|
||||
@Inject
|
||||
private UserVmDao userVmDao;
|
||||
UserVmDao userVmDao;
|
||||
|
||||
@Inject
|
||||
private VMInstanceDao _vmInstanceDao;
|
||||
VMInstanceDao _vmInstanceDao;
|
||||
|
||||
@Inject
|
||||
private SecurityGroupJoinDao _securityGroupJoinDao;
|
||||
SecurityGroupJoinDao _securityGroupJoinDao;
|
||||
|
||||
@Inject
|
||||
private SecurityGroupVMMapDao securityGroupVMMapDao;
|
||||
SecurityGroupVMMapDao securityGroupVMMapDao;
|
||||
|
||||
@Inject
|
||||
private DomainRouterJoinDao _routerJoinDao;
|
||||
DomainRouterJoinDao _routerJoinDao;
|
||||
|
||||
@Inject
|
||||
private ProjectInvitationJoinDao _projectInvitationJoinDao;
|
||||
ProjectInvitationJoinDao _projectInvitationJoinDao;
|
||||
|
||||
@Inject
|
||||
private ProjectJoinDao _projectJoinDao;
|
||||
ProjectJoinDao _projectJoinDao;
|
||||
|
||||
@Inject
|
||||
private ProjectDao _projectDao;
|
||||
ProjectDao _projectDao;
|
||||
|
||||
@Inject
|
||||
private ProjectAccountDao _projectAccountDao;
|
||||
ProjectAccountDao _projectAccountDao;
|
||||
|
||||
@Inject
|
||||
private ProjectAccountJoinDao _projectAccountJoinDao;
|
||||
ProjectAccountJoinDao _projectAccountJoinDao;
|
||||
|
||||
@Inject
|
||||
private HostJoinDao hostJoinDao;
|
||||
HostJoinDao hostJoinDao;
|
||||
|
||||
@Inject
|
||||
private VolumeJoinDao _volumeJoinDao;
|
||||
VolumeJoinDao _volumeJoinDao;
|
||||
|
||||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
AccountDao _accountDao;
|
||||
|
||||
@Inject
|
||||
private AccountJoinDao _accountJoinDao;
|
||||
AccountJoinDao _accountJoinDao;
|
||||
|
||||
@Inject
|
||||
private AsyncJobJoinDao _jobJoinDao;
|
||||
AsyncJobJoinDao _jobJoinDao;
|
||||
|
||||
@Inject
|
||||
private StoragePoolJoinDao _poolJoinDao;
|
||||
StoragePoolJoinDao _poolJoinDao;
|
||||
|
||||
@Inject
|
||||
private StoragePoolTagsDao _storageTagDao;
|
||||
StoragePoolTagsDao _storageTagDao;
|
||||
|
||||
@Inject
|
||||
private HostTagsDao _hostTagDao;
|
||||
HostTagsDao _hostTagDao;
|
||||
|
||||
@Inject
|
||||
private ImageStoreJoinDao _imageStoreJoinDao;
|
||||
ImageStoreJoinDao _imageStoreJoinDao;
|
||||
|
||||
@Inject
|
||||
private DiskOfferingJoinDao _diskOfferingJoinDao;
|
||||
DiskOfferingJoinDao _diskOfferingJoinDao;
|
||||
|
||||
@Inject
|
||||
private DiskOfferingDetailsDao _diskOfferingDetailsDao;
|
||||
DiskOfferingDetailsDao _diskOfferingDetailsDao;
|
||||
|
||||
@Inject
|
||||
private ServiceOfferingJoinDao _srvOfferingJoinDao;
|
||||
ServiceOfferingJoinDao _srvOfferingJoinDao;
|
||||
|
||||
@Inject
|
||||
private ServiceOfferingDao _srvOfferingDao;
|
||||
ServiceOfferingDao _srvOfferingDao;
|
||||
|
||||
@Inject
|
||||
private ServiceOfferingDetailsDao _srvOfferingDetailsDao;
|
||||
ServiceOfferingDetailsDao _srvOfferingDetailsDao;
|
||||
|
||||
@Inject
|
||||
private DiskOfferingDao _diskOfferingDao;
|
||||
DiskOfferingDao _diskOfferingDao;
|
||||
|
||||
@Inject
|
||||
private DataCenterJoinDao _dcJoinDao;
|
||||
DataCenterJoinDao _dcJoinDao;
|
||||
|
||||
@Inject
|
||||
private DomainRouterDao _routerDao;
|
||||
DomainRouterDao _routerDao;
|
||||
|
||||
@Inject
|
||||
private HighAvailabilityManager _haMgr;
|
||||
HighAvailabilityManager _haMgr;
|
||||
|
||||
@Inject
|
||||
private VMTemplateDao _templateDao;
|
||||
VMTemplateDao _templateDao;
|
||||
|
||||
@Inject
|
||||
private TemplateJoinDao _templateJoinDao;
|
||||
TemplateJoinDao _templateJoinDao;
|
||||
|
||||
@Inject
|
||||
private ResourceManager _resourceMgr;
|
||||
ResourceManager _resourceMgr;
|
||||
@Inject
|
||||
private ResourceMetaDataService _resourceMetaDataMgr;
|
||||
ResourceMetaDataService _resourceMetaDataMgr;
|
||||
|
||||
@Inject
|
||||
private ResourceManagerUtil resourceManagerUtil;
|
||||
ResourceManagerUtil resourceManagerUtil;
|
||||
|
||||
@Inject
|
||||
private AffinityGroupVMMapDao _affinityGroupVMMapDao;
|
||||
AffinityGroupVMMapDao _affinityGroupVMMapDao;
|
||||
|
||||
@Inject
|
||||
private AffinityGroupJoinDao _affinityGroupJoinDao;
|
||||
AffinityGroupJoinDao _affinityGroupJoinDao;
|
||||
|
||||
@Inject
|
||||
private DedicatedResourceDao _dedicatedDao;
|
||||
DedicatedResourceDao _dedicatedDao;
|
||||
|
||||
@Inject
|
||||
private DomainManager _domainMgr;
|
||||
DomainManager _domainMgr;
|
||||
|
||||
@Inject
|
||||
private AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
|
||||
AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
|
||||
|
||||
@Inject
|
||||
private ResourceTagDao resourceTagDao;
|
||||
ResourceTagDao resourceTagDao;
|
||||
|
||||
@Inject
|
||||
private DataStoreManager dataStoreManager;
|
||||
DataStoreManager dataStoreManager;
|
||||
|
||||
@Inject
|
||||
ManagementServerJoinDao managementServerJoinDao;
|
||||
|
||||
@Inject
|
||||
public VpcVirtualNetworkApplianceService routerService;
|
||||
VpcVirtualNetworkApplianceService routerService;
|
||||
|
||||
@Inject
|
||||
private ResponseGenerator responseGenerator;
|
||||
ResponseGenerator responseGenerator;
|
||||
|
||||
@Inject
|
||||
private RouterHealthCheckResultDao routerHealthCheckResultDao;
|
||||
RouterHealthCheckResultDao routerHealthCheckResultDao;
|
||||
|
||||
@Inject
|
||||
private PrimaryDataStoreDao storagePoolDao;
|
||||
PrimaryDataStoreDao storagePoolDao;
|
||||
|
||||
@Inject
|
||||
private StoragePoolDetailsDao _storagePoolDetailsDao;
|
||||
StoragePoolDetailsDao _storagePoolDetailsDao;
|
||||
|
||||
@Inject
|
||||
private ProjectInvitationDao projectInvitationDao;
|
||||
ProjectInvitationDao projectInvitationDao;
|
||||
|
||||
@Inject
|
||||
private TemplateDataStoreDao templateDataStoreDao;
|
||||
TemplateDataStoreDao templateDataStoreDao;
|
||||
|
||||
@Inject
|
||||
private VMTemplatePoolDao templatePoolDao;
|
||||
VMTemplatePoolDao templatePoolDao;
|
||||
|
||||
@Inject
|
||||
private SnapshotDataStoreDao snapshotDataStoreDao;
|
||||
SnapshotDataStoreDao snapshotDataStoreDao;
|
||||
|
||||
@Inject
|
||||
private UserDao userDao;
|
||||
UserDao userDao;
|
||||
|
||||
@Inject
|
||||
private VirtualMachineManager virtualMachineManager;
|
||||
VirtualMachineManager virtualMachineManager;
|
||||
|
||||
@Inject
|
||||
private VolumeDao volumeDao;
|
||||
VolumeDao volumeDao;
|
||||
|
||||
@Inject
|
||||
private ResourceIconDao resourceIconDao;
|
||||
ResourceIconDao resourceIconDao;
|
||||
@Inject
|
||||
StorageManager storageManager;
|
||||
|
||||
@Inject
|
||||
private ManagementServerHostDao msHostDao;
|
||||
ManagementServerHostDao msHostDao;
|
||||
|
||||
@Inject
|
||||
private SecondaryStorageHeuristicDao secondaryStorageHeuristicDao;
|
||||
SecondaryStorageHeuristicDao secondaryStorageHeuristicDao;
|
||||
|
||||
@Inject
|
||||
private NetworkDao networkDao;
|
||||
NetworkDao networkDao;
|
||||
|
||||
@Inject
|
||||
private IPAddressDao ipAddressDao;
|
||||
IPAddressDao ipAddressDao;
|
||||
|
||||
@Inject
|
||||
private NicDao nicDao;
|
||||
NicDao nicDao;
|
||||
|
||||
@Inject
|
||||
private HostDao hostDao;
|
||||
HostDao hostDao;
|
||||
|
||||
@Inject
|
||||
private OutOfBandManagementDao outOfBandManagementDao;
|
||||
OutOfBandManagementDao outOfBandManagementDao;
|
||||
|
||||
@Inject
|
||||
private InstanceGroupVMMapDao instanceGroupVMMapDao;
|
||||
InstanceGroupVMMapDao instanceGroupVMMapDao;
|
||||
|
||||
@Inject
|
||||
private AffinityGroupVMMapDao affinityGroupVMMapDao;
|
||||
AffinityGroupVMMapDao affinityGroupVMMapDao;
|
||||
|
||||
@Inject
|
||||
private UserVmDetailsDao userVmDetailsDao;
|
||||
UserVmDetailsDao userVmDetailsDao;
|
||||
|
||||
@Inject
|
||||
private SSHKeyPairDao sshKeyPairDao;
|
||||
SSHKeyPairDao sshKeyPairDao;
|
||||
|
||||
@Inject
|
||||
private BackupOfferingDao backupOfferingDao;
|
||||
BackupOfferingDao backupOfferingDao;
|
||||
|
||||
@Inject
|
||||
private AutoScaleVmGroupDao autoScaleVmGroupDao;
|
||||
AutoScaleVmGroupDao autoScaleVmGroupDao;
|
||||
|
||||
@Inject
|
||||
private AutoScaleVmGroupVmMapDao autoScaleVmGroupVmMapDao;
|
||||
AutoScaleVmGroupVmMapDao autoScaleVmGroupVmMapDao;
|
||||
|
||||
@Inject
|
||||
private SnapshotJoinDao snapshotJoinDao;
|
||||
SnapshotJoinDao snapshotJoinDao;
|
||||
|
||||
@Inject
|
||||
private ObjectStoreDao objectStoreDao;
|
||||
ObjectStoreDao objectStoreDao;
|
||||
|
||||
@Inject
|
||||
private BucketDao bucketDao;
|
||||
BucketDao bucketDao;
|
||||
|
||||
@Inject
|
||||
EntityManager entityManager;
|
||||
|
||||
@Inject
|
||||
private PublicIpQuarantineDao publicIpQuarantineDao;
|
||||
PublicIpQuarantineDao publicIpQuarantineDao;
|
||||
|
||||
@Inject
|
||||
private StoragePoolHostDao storagePoolHostDao;
|
||||
StoragePoolHostDao storagePoolHostDao;
|
||||
|
||||
@Inject
|
||||
private ClusterDao clusterDao;
|
||||
ClusterDao clusterDao;
|
||||
|
||||
@Inject
|
||||
private ManagementServerHostPeerJoinDao mshostPeerJoinDao;
|
||||
ManagementServerHostPeerJoinDao mshostPeerJoinDao;
|
||||
|
||||
|
||||
private SearchCriteria<ServiceOfferingJoinVO> getMinimumCpuServiceOfferingJoinSearchCriteria(int cpu) {
|
||||
@ -663,7 +663,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Override
|
||||
public ListResponse<UserResponse> searchForUsers(ResponseView responseView, ListUsersCmd cmd) throws PermissionDeniedException {
|
||||
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) {
|
||||
responseView = ResponseView.Full;
|
||||
}
|
||||
@ -833,7 +833,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Override
|
||||
public ListResponse<EventResponse> searchForEvents(ListEventsCmd 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()]));
|
||||
response.setResponses(eventResponses, result.second());
|
||||
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);
|
||||
Long domainId = domainIdRecursiveListProject.first();
|
||||
Boolean isRecursive = domainIdRecursiveListProject.second();
|
||||
@ -996,7 +996,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
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
|
||||
// searchAndCount should be good enough.
|
||||
if ((entryTime != null) && (duration != null)) {
|
||||
@ -1033,7 +1033,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Override
|
||||
public ListResponse<ResourceTagResponse> listTags(ListTagsCmd 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()]));
|
||||
response.setResponses(tagResponses, tags.second());
|
||||
return response;
|
||||
@ -1041,7 +1041,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
|
||||
private Pair<List<ResourceTagJoinVO>, Integer> listTagsInternal(ListTagsCmd cmd) {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<Long> permittedAccounts = new ArrayList<Long>();
|
||||
List<Long> permittedAccounts = new ArrayList<>();
|
||||
String key = cmd.getKey();
|
||||
String value = cmd.getValue();
|
||||
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);
|
||||
Long domainId = domainIdRecursiveListProject.first();
|
||||
@ -1113,14 +1113,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
sc.setParameters("customer", customerName);
|
||||
}
|
||||
|
||||
Pair<List<ResourceTagJoinVO>, Integer> result = _resourceTagJoinDao.searchAndCount(sc, searchFilter);
|
||||
return result;
|
||||
return _resourceTagJoinDao.searchAndCount(sc, searchFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListResponse<InstanceGroupResponse> searchForVmGroups(ListVMGroupsCmd 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()]));
|
||||
response.setResponses(grpResponses, groups.second());
|
||||
return response;
|
||||
@ -1132,9 +1131,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
String keyword = cmd.getKeyword();
|
||||
|
||||
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);
|
||||
Long domainId = domainIdRecursiveListProject.first();
|
||||
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());
|
||||
|
||||
List<Long> ids = null;
|
||||
List<Long> ids;
|
||||
if (cmd.getId() != null) {
|
||||
if (cmd.getIds() != null && !cmd.getIds().isEmpty()) {
|
||||
throw new InvalidParameterValueException("Specify either id or ids but not both parameters");
|
||||
@ -1694,7 +1693,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Override
|
||||
public ListResponse<SecurityGroupResponse> searchForSecurityGroups(ListSecurityGroupsCmd 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());
|
||||
response.setResponses(routerResponses, result.second());
|
||||
return response;
|
||||
@ -1706,7 +1705,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
String securityGroup = cmd.getSecurityGroupName();
|
||||
Long id = cmd.getId();
|
||||
Object keyword = cmd.getKeyword();
|
||||
List<Long> permittedAccounts = new ArrayList<Long>();
|
||||
List<Long> permittedAccounts = new ArrayList<>();
|
||||
Map<String, String> tags = cmd.getTags();
|
||||
|
||||
if (instanceId != null) {
|
||||
@ -1718,7 +1717,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
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);
|
||||
Long domainId = domainIdRecursiveListProject.first();
|
||||
Boolean isRecursive = domainIdRecursiveListProject.second();
|
||||
@ -1777,7 +1776,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
sgIds[i++] = v.getId();
|
||||
}
|
||||
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) {
|
||||
@ -1786,7 +1785,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
Integer count = sgVmMappingPair.second();
|
||||
if (count.intValue() == 0) {
|
||||
// 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();
|
||||
Long[] sgIds = new Long[sgVmMappings.size()];
|
||||
@ -1795,14 +1794,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
sgIds[i++] = sgVm.getSecurityGroupId();
|
||||
}
|
||||
List<SecurityGroupJoinVO> sgs = _securityGroupJoinDao.searchByIds(sgIds);
|
||||
return new Pair<List<SecurityGroupJoinVO>, Integer>(sgs, count);
|
||||
return new Pair<>(sgs, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
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(),
|
||||
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()]));
|
||||
if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) {
|
||||
for (DomainRouterResponse res : routerResponses) {
|
||||
@ -1822,7 +1821,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
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(),
|
||||
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()]));
|
||||
if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) {
|
||||
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) {
|
||||
|
||||
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);
|
||||
Long domainId = domainIdRecursiveListProject.first();
|
||||
Boolean isRecursive = domainIdRecursiveListProject.second();
|
||||
@ -1901,7 +1900,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
sb.and("routerId", sb.entity().getId(), SearchCriteria.Op.NIN);
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
List<DomainRouterJoinVO> vrs = _routerJoinDao.searchByIds(vrIds);
|
||||
return new Pair<List<DomainRouterJoinVO>, Integer>(vrs, count);
|
||||
return new Pair<>(vrs, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListResponse<ProjectResponse> listProjects(ListProjectsCmd 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()]));
|
||||
response.setResponses(projectResponses, projects.second());
|
||||
return response;
|
||||
@ -2155,13 +2154,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
prjIds[i++] = v.getId();
|
||||
}
|
||||
List<ProjectJoinVO> prjs = _projectJoinDao.searchByIds(prjIds);
|
||||
return new Pair<List<ProjectJoinVO>, Integer>(prjs, count);
|
||||
return new Pair<>(prjs, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListResponse<ProjectInvitationResponse> listProjectInvitations(ListProjectInvitationsCmd 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()]));
|
||||
|
||||
response.setResponses(projectInvitationResponses, invites.second());
|
||||
@ -2183,9 +2182,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
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);
|
||||
domainId = domainIdRecursiveListProject.first();
|
||||
isRecursive = domainIdRecursiveListProject.second();
|
||||
@ -2237,7 +2236,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Override
|
||||
public ListResponse<ProjectAccountResponse> listProjectAccounts(ListProjectAccountsCmd 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()]));
|
||||
response.setResponses(projectResponses, projectAccounts.second());
|
||||
return response;
|
||||
@ -2311,7 +2310,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
// Right now it is handled separately outside this QueryService
|
||||
logger.debug(">>>Searching for hosts>>>");
|
||||
Pair<List<HostJoinVO>, Integer> hosts = searchForServersInternal(cmd);
|
||||
ListResponse<HostResponse> response = new ListResponse<HostResponse>();
|
||||
ListResponse<HostResponse> response = new ListResponse<>();
|
||||
logger.debug(">>>Generating Response>>>");
|
||||
List<HostResponse> hostResponses = ViewResponseHelper.createHostResponse(cmd.getDetails(), hosts.first().toArray(new HostJoinVO[hosts.first().size()]));
|
||||
response.setResponses(hostResponses, hosts.second());
|
||||
@ -2723,7 +2722,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Override
|
||||
public ListResponse<DomainResponse> searchForDomains(ListDomainsCmd cmd) {
|
||||
Pair<List<DomainJoinVO>, Integer> result = searchForDomainsInternal(cmd);
|
||||
ListResponse<DomainResponse> response = new ListResponse<DomainResponse>();
|
||||
ListResponse<DomainResponse> response = new ListResponse<>();
|
||||
|
||||
ResponseView respView = ResponseView.Restricted;
|
||||
if (cmd instanceof ListDomainsCmdByAdmin) {
|
||||
@ -2825,7 +2824,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Override
|
||||
public ListResponse<AccountResponse> searchForAccounts(ListAccountsCmd cmd) {
|
||||
Pair<List<AccountJoinVO>, Integer> result = searchForAccountsInternal(cmd);
|
||||
ListResponse<AccountResponse> response = new ListResponse<AccountResponse>();
|
||||
ListResponse<AccountResponse> response = new ListResponse<>();
|
||||
|
||||
ResponseView respView = ResponseView.Restricted;
|
||||
if (cmd instanceof ListAccountsCmdByAdmin) {
|
||||
@ -3011,7 +3010,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Override
|
||||
public ListResponse<AsyncJobResponse> searchForAsyncJobs(ListAsyncJobsCmd 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()]));
|
||||
response.setResponses(jobResponses, result.second());
|
||||
return response;
|
||||
@ -3021,9 +3020,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
|
||||
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);
|
||||
Long domainId = domainIdRecursiveListProject.first();
|
||||
Boolean isRecursive = domainIdRecursiveListProject.second();
|
||||
@ -3183,7 +3182,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Override
|
||||
public ListResponse<StorageTagResponse> searchForStorageTags(ListStorageTagsCmd 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()]));
|
||||
|
||||
response.setResponses(tagResponses, result.second());
|
||||
@ -3218,13 +3217,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
|
||||
List<StoragePoolTagVO> vrs = _storageTagDao.searchByIds(vrIds);
|
||||
|
||||
return new Pair<List<StoragePoolTagVO>, Integer>(vrs, count);
|
||||
return new Pair<>(vrs, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListResponse<HostTagResponse> searchForHostTags(ListHostTagsCmd 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()]));
|
||||
|
||||
response.setResponses(tagResponses, result.second());
|
||||
@ -3259,7 +3258,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
|
||||
List<HostTagVO> vrs = _hostTagDao.searchByIds(vrIds);
|
||||
|
||||
return new Pair<List<HostTagVO>, Integer>(vrs, count);
|
||||
return new Pair<>(vrs, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -3342,14 +3341,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
vrIds[i++] = v.getId();
|
||||
}
|
||||
List<ImageStoreJoinVO> vrs = _imageStoreJoinDao.searchByIds(vrIds);
|
||||
return new Pair<List<ImageStoreJoinVO>, Integer>(vrs, count);
|
||||
return new Pair<>(vrs, count);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListResponse<ImageStoreResponse> searchForSecondaryStagingStores(ListSecondaryStagingStoresCmd 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()]));
|
||||
response.setResponses(poolResponses, result.second());
|
||||
@ -3421,7 +3420,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
vrIds[i++] = v.getId();
|
||||
}
|
||||
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
|
||||
public ListResponse<ZoneResponse> listDataCenters(ListZonesCmd cmd) {
|
||||
Pair<List<DataCenterJoinVO>, Integer> result = listDataCentersInternal(cmd);
|
||||
ListResponse<ZoneResponse> response = new ListResponse<ZoneResponse>();
|
||||
ListResponse<ZoneResponse> response = new ListResponse<>();
|
||||
|
||||
ResponseView respView = ResponseView.Restricted;
|
||||
if (cmd instanceof ListZonesCmdByAdmin || CallContext.current().getCallingAccount().getType() == Account.Type.ADMIN) {
|
||||
@ -4332,7 +4331,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
// list
|
||||
|
||||
// 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());
|
||||
if (domainRecord == null) {
|
||||
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
|
||||
// everything above till root, as well as zones till the domain
|
||||
// leaf
|
||||
List<Long> domainIds = new ArrayList<Long>();
|
||||
List<Long> domainIds = new ArrayList<>();
|
||||
DomainVO domainRecord = _domainDao.findById(account.getDomainId());
|
||||
if (domainRecord == null) {
|
||||
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
|
||||
Boolean available = cmd.isAvailable();
|
||||
if (account != null) {
|
||||
if ((available != null) && Boolean.FALSE.equals(available)) {
|
||||
Set<Long> dcIds = new HashSet<Long>(); // data centers with
|
||||
if (Boolean.FALSE.equals(available)) {
|
||||
Set<Long> dcIds = new HashSet<>(); // data centers with
|
||||
// at least one VM
|
||||
// running
|
||||
List<DomainRouterVO> routers = _routerDao.listBy(account.getId());
|
||||
@ -4421,7 +4420,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
dcIds.add(router.getDataCenterId());
|
||||
}
|
||||
if (dcIds.size() == 0) {
|
||||
return new Pair<List<DataCenterJoinVO>, Integer>(new ArrayList<DataCenterJoinVO>(), 0);
|
||||
return new Pair<>(new ArrayList<>(), 0);
|
||||
} else {
|
||||
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) {
|
||||
// remove dedicated zone of other domain
|
||||
List<Long> dedicatedZoneIds = new ArrayList<Long>();
|
||||
List<Long> dedicatedZoneIds = new ArrayList<>();
|
||||
List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listZonesNotInDomainIds(domainIds);
|
||||
for (DedicatedResourceVO dr : dedicatedResources) {
|
||||
if (dr != null) {
|
||||
@ -4486,7 +4485,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
@Override
|
||||
public ListResponse<TemplateResponse> listTemplates(ListTemplatesCmd cmd) {
|
||||
Pair<List<TemplateJoinVO>, Integer> result = searchForTemplatesInternal(cmd);
|
||||
ListResponse<TemplateResponse> response = new ListResponse<TemplateResponse>();
|
||||
ListResponse<TemplateResponse> response = new ListResponse<>();
|
||||
|
||||
ResponseView respView = ResponseView.Restricted;
|
||||
if (cmd instanceof ListTemplatesCmdByAdmin) {
|
||||
@ -4514,14 +4513,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
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);
|
||||
accountMgr.buildACLSearchParameters(
|
||||
caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds,
|
||||
domainIdRecursiveListProject, listAll, false
|
||||
);
|
||||
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
|
||||
List<Account> permittedAccounts = new ArrayList<Account>();
|
||||
List<Account> permittedAccounts = new ArrayList<>();
|
||||
for (Long accountId : permittedAccountIds) {
|
||||
permittedAccounts.add(accountMgr.getAccount(accountId));
|
||||
}
|
||||
@ -4559,11 +4558,11 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
if (!isIso) {
|
||||
hypers = _resourceMgr.listAvailHypervisorInZone(null);
|
||||
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);
|
||||
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);
|
||||
} else {
|
||||
|
||||
DomainVO domain = null;
|
||||
DomainVO domain;
|
||||
if (!permittedAccounts.isEmpty()) {
|
||||
domain = _domainDao.findById(permittedAccounts.get(0).getDomainId());
|
||||
} else {
|
||||
@ -4656,15 +4655,15 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
sc.addAnd("domainPath", SearchCriteria.Op.LIKE, domain.getPath() + "%");
|
||||
}
|
||||
|
||||
List<Long> relatedDomainIds = new ArrayList<Long>();
|
||||
List<Long> permittedAccountIds = new ArrayList<Long>();
|
||||
List<Long> relatedDomainIds = new ArrayList<>();
|
||||
List<Long> permittedAccountIds = new ArrayList<>();
|
||||
if (!permittedAccounts.isEmpty()) {
|
||||
for (Account account : permittedAccounts) {
|
||||
permittedAccountIds.add(account.getId());
|
||||
boolean publicTemplates = (templateFilter == TemplateFilter.featured || templateFilter == TemplateFilter.community);
|
||||
|
||||
// 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 (publicTemplates) {
|
||||
domainTreeNode = _domainDao.findById(Domain.ROOT_DOMAIN);
|
||||
@ -4895,7 +4894,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
// sc.addAnd("removed", SearchCriteria.Op.NULL);
|
||||
|
||||
// search unique templates and find details by Ids
|
||||
Pair<List<TemplateJoinVO>, Integer> uniqueTmplPair = null;
|
||||
Pair<List<TemplateJoinVO>, Integer> uniqueTmplPair;
|
||||
if (showRemovedTmpl) {
|
||||
uniqueTmplPair = _templateJoinDao.searchIncludingRemovedAndCount(sc, searchFilter);
|
||||
} else {
|
||||
@ -4926,7 +4925,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
return templateDataPair;
|
||||
}
|
||||
List<TemplateJoinVO> templateData = templateDataPair.first();
|
||||
List<TemplateJoinVO> templates = null;
|
||||
List<TemplateJoinVO> templates;
|
||||
if (showUnique) {
|
||||
Long[] templateIds = templateData.stream().map(template -> template.getId()).toArray(Long[]::new);
|
||||
templates = _templateJoinDao.findByDistinctIds(templateIds);
|
||||
@ -4935,7 +4934,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
templates = _templateJoinDao.searchByTemplateZonePair(showRemoved, templateZonePairs);
|
||||
}
|
||||
|
||||
return new Pair<List<TemplateJoinVO>, Integer>(templates, count);
|
||||
return new Pair<>(templates, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -5056,7 +5055,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
if (HypervisorType.KVM.equals(hypervisorType)) {
|
||||
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.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_RAM, Collections.emptyList());
|
||||
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);
|
||||
}
|
||||
|
||||
List<Long> permittedAccounts = new ArrayList<Long>();
|
||||
Ternary<Long, Boolean, ListProjectResourcesCriteria> ternary = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(domainId, isRecursive, null);
|
||||
List<Long> permittedAccounts = new ArrayList<>();
|
||||
Ternary<Long, Boolean, ListProjectResourcesCriteria> ternary = new Ternary<>(domainId, isRecursive, null);
|
||||
|
||||
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);
|
||||
|
||||
// search group details by ids
|
||||
List<AffinityGroupJoinVO> affinityGroups = new ArrayList<AffinityGroupJoinVO>();
|
||||
List<AffinityGroupJoinVO> affinityGroups = new ArrayList<>();
|
||||
|
||||
Integer count = uniqueGroupsPair.second();
|
||||
if (count.intValue() != 0) {
|
||||
@ -5143,7 +5142,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
if (!permittedAccounts.isEmpty()) {
|
||||
// add domain level affinity groups
|
||||
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);
|
||||
Pair<List<AffinityGroupJoinVO>, Integer> groupsPair = listDomainLevelAffinityGroups(scDomain, searchFilter, domainId);
|
||||
affinityGroups.addAll(groupsPair.first());
|
||||
@ -5152,7 +5151,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
|
||||
for (Long permAcctId : permittedAccounts) {
|
||||
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);
|
||||
Pair<List<AffinityGroupJoinVO>, Integer> groupsPair = listDomainLevelAffinityGroups(scDomain, searchFilter, permittedAcct.getDomainId());
|
||||
affinityGroups.addAll(groupsPair.first());
|
||||
@ -5161,14 +5160,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
}
|
||||
} else if (((permittedAccounts.isEmpty()) && (domainId != null) && isRecursive)) {
|
||||
// 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);
|
||||
Pair<List<AffinityGroupJoinVO>, Integer> groupsPair = listDomainLevelAffinityGroups(scDomain, searchFilter, domainId);
|
||||
affinityGroups.addAll(groupsPair.first());
|
||||
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();
|
||||
if (count.intValue() == 0) {
|
||||
// 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();
|
||||
Long[] agIds = new Long[agVmMappings.size()];
|
||||
@ -5263,11 +5262,11 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
agIds[i++] = agVm.getAffinityGroupId();
|
||||
}
|
||||
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) {
|
||||
List<Long> affinityGroupIds = new ArrayList<Long>();
|
||||
List<Long> affinityGroupIds = new ArrayList<>();
|
||||
Set<Long> allowedDomains = _domainMgr.getDomainParentIds(domainId);
|
||||
List<AffinityGroupDomainMapVO> maps = _affinityGroupDomainMapDao.listByDomain(allowedDomains.toArray());
|
||||
|
||||
@ -5290,7 +5289,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
Integer count = uniqueGroupsPair.second();
|
||||
if (count.intValue() == 0) {
|
||||
// empty result
|
||||
return new Pair<>(new ArrayList<AffinityGroupJoinVO>(), 0);
|
||||
return new Pair<>(new ArrayList<>(), 0);
|
||||
}
|
||||
List<AffinityGroupJoinVO> uniqueGroups = uniqueGroupsPair.first();
|
||||
Long[] vrIds = new Long[uniqueGroups.size()];
|
||||
@ -5301,7 +5300,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
List<AffinityGroupJoinVO> vrs = _affinityGroupJoinDao.searchByIds(vrIds);
|
||||
return new Pair<>(vrs, count);
|
||||
} 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;
|
||||
|
||||
if (key == null) {
|
||||
@ -5346,7 +5345,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
detailList = _resourceMetaDataMgr.getDetails(resourceType, key, value, forDisplay);
|
||||
}
|
||||
|
||||
List<ResourceDetailResponse> responseList = new ArrayList<ResourceDetailResponse>();
|
||||
List<ResourceDetailResponse> responseList = new ArrayList<>();
|
||||
if (requestedDetail != null) {
|
||||
ResourceDetailResponse detailResponse = createResourceDetailsResponse(requestedDetail, resourceType);
|
||||
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);
|
||||
|
||||
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);
|
||||
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
|
||||
domainId = domainIdRecursiveListProject.first();
|
||||
@ -5729,7 +5728,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
|
||||
Integer count = snapshotDataPair.second();
|
||||
if (count == 0) {
|
||||
// empty result
|
||||
return snapshotDataPair;
|
||||
}
|
||||
List<SnapshotJoinVO> snapshotData = snapshotDataPair.first();
|
||||
@ -5739,13 +5737,12 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
} else {
|
||||
snapshots = snapshotJoinDao.searchBySnapshotStorePair(snapshotData.stream().map(SnapshotJoinVO::getSnapshotStorePair).toArray(String[]::new));
|
||||
}
|
||||
|
||||
return new Pair<>(snapshots, count);
|
||||
}
|
||||
|
||||
public ListResponse<ObjectStoreResponse> searchForObjectStores(ListObjectStoragePoolsCmd 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()]));
|
||||
response.setResponses(poolResponses, result.second());
|
||||
@ -5830,7 +5827,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
Long startIndex = cmd.getStartIndex();
|
||||
Long pageSize = cmd.getPageSizeVal();
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<Long> permittedAccounts = new ArrayList<Long>();
|
||||
List<Long> permittedAccounts = new ArrayList<>();
|
||||
|
||||
// Verify parameters
|
||||
if (id != null) {
|
||||
@ -5842,7 +5839,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
|
||||
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);
|
||||
accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
|
||||
Long domainId = domainIdRecursiveListProject.first();
|
||||
|
||||
@ -23,10 +23,7 @@ import org.apache.cloudstack.api.ResponseObject;
|
||||
import org.apache.cloudstack.api.response.SnapshotResponse;
|
||||
|
||||
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.SearchCriteria;
|
||||
|
||||
public interface SnapshotJoinDao extends GenericDao<SnapshotJoinVO, Long> {
|
||||
|
||||
@ -34,8 +31,7 @@ public interface SnapshotJoinDao extends GenericDao<SnapshotJoinVO, Long> {
|
||||
|
||||
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> findByDistinctIds(Long zoneId, Long... ids);
|
||||
}
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
package com.cloud.api.query.dao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
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.query.QueryService;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import com.cloud.api.ApiDBUtils;
|
||||
import com.cloud.api.ApiResponseHelper;
|
||||
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.user.Account;
|
||||
import com.cloud.user.AccountService;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
@ -53,11 +56,11 @@ import com.cloud.vm.VMInstanceVO;
|
||||
public class SnapshotJoinDaoImpl extends GenericDaoBaseWithTagInformation<SnapshotJoinVO, SnapshotResponse> implements SnapshotJoinDao {
|
||||
|
||||
@Inject
|
||||
private AccountService accountService;
|
||||
AccountService accountService;
|
||||
@Inject
|
||||
private AnnotationDao annotationDao;
|
||||
AnnotationDao annotationDao;
|
||||
@Inject
|
||||
private ConfigurationDao configDao;
|
||||
ConfigurationDao configDao;
|
||||
@Inject
|
||||
SnapshotDataFactory snapshotDataFactory;
|
||||
|
||||
@ -85,7 +88,7 @@ public class SnapshotJoinDaoImpl extends GenericDaoBaseWithTagInformation<Snapsh
|
||||
if (snapshot.getDataCenterId() == null) {
|
||||
return;
|
||||
}
|
||||
SnapshotInfo snapshotInfo = null;
|
||||
SnapshotInfo snapshotInfo;
|
||||
snapshotInfo = snapshotDataFactory.getSnapshotWithRoleAndZone(snapshot.getId(), snapshot.getStoreRole(), snapshot.getDataCenterId());
|
||||
if (snapshotInfo == null) {
|
||||
logger.debug("Unable to find info for image store snapshot {}", snapshot);
|
||||
@ -192,13 +195,6 @@ public class SnapshotJoinDaoImpl extends GenericDaoBaseWithTagInformation<Snapsh
|
||||
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
|
||||
public List<SnapshotJoinVO> searchBySnapshotStorePair(String... pairs) {
|
||||
// set detail batch query size
|
||||
@ -243,14 +239,33 @@ public class SnapshotJoinDaoImpl extends GenericDaoBaseWithTagInformation<Snapsh
|
||||
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
|
||||
public List<SnapshotJoinVO> findByDistinctIds(Long zoneId, Long... ids) {
|
||||
if (ids == null || ids.length == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
if (ids.length == 1) {
|
||||
return findById(zoneId, ids[0]);
|
||||
}
|
||||
Filter searchFilter = new Filter(SnapshotJoinVO.class, "snapshotStorePair", QueryService.SortKeyAscending.value(), null, null);
|
||||
|
||||
SearchCriteria<SnapshotJoinVO> sc = snapshotIdsSearch.create();
|
||||
if (zoneId != null) {
|
||||
sc.setParameters("zoneId", zoneId);
|
||||
|
||||
@ -7225,10 +7225,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
sc.addAnd("id", SearchCriteria.Op.EQ, id);
|
||||
}
|
||||
|
||||
if (tags != null) {
|
||||
sc.addAnd("tags", SearchCriteria.Op.EQ, tags);
|
||||
}
|
||||
|
||||
if (isTagged != null) {
|
||||
if (isTagged) {
|
||||
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) {
|
||||
SearchBuilder<NetworkOfferingJoinVO> sb = networkOfferingJoinDao.createSearchBuilder();
|
||||
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;
|
||||
List<Service> checkForProviders = new ArrayList<Service>();
|
||||
|
||||
if (checkForTags && ! checkNetworkOfferingTags(pNtwkTags, allowNullTag, offering.getTags())) {
|
||||
if (checkForTags && !checkNetworkOfferingTags(pNtwkTags, allowNullTag, offering.getTags())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -934,8 +934,12 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
|
||||
|
||||
@Override
|
||||
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) {
|
||||
logger.debug("Network " + network + " doesn't support service " + Service.UserData.getName());
|
||||
return null;
|
||||
|
||||
@ -325,8 +325,12 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle
|
||||
try {
|
||||
final Network network = _networkMgr.getNetwork(nic.getNetworkId());
|
||||
final UserDataServiceProvider userDataUpdateProvider = _networkModel.getUserDataUpdateProvider(network);
|
||||
if (userDataUpdateProvider == null) {
|
||||
logger.warn("Failed to get user data provider");
|
||||
return false;
|
||||
}
|
||||
final Provider provider = userDataUpdateProvider.getProvider();
|
||||
if (provider.equals(Provider.ConfigDrive)) {
|
||||
if (Provider.ConfigDrive.equals(provider)) {
|
||||
try {
|
||||
return deleteConfigDriveIso(vm);
|
||||
} catch (ResourceUnavailableException e) {
|
||||
@ -341,8 +345,13 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle
|
||||
|
||||
@Override
|
||||
public boolean prepareMigration(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) {
|
||||
if (_networkModel.getUserDataUpdateProvider(network).getProvider().equals(Provider.ConfigDrive)) {
|
||||
logger.trace(String.format("[prepareMigration] for vm: %s", vm));
|
||||
final UserDataServiceProvider userDataUpdateProvider = _networkModel.getUserDataUpdateProvider(network);
|
||||
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 {
|
||||
if (isConfigDriveIsoOnHostCache(vm.getId())) {
|
||||
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 {
|
||||
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;
|
||||
for (DiskTO disk : vm.getDisks()) {
|
||||
if (disk.getType() == Volume.Type.ISO && disk.getPath() != null && disk.getPath().contains("configdrive")) {
|
||||
|
||||
@ -769,7 +769,12 @@ NetworkMigrationResponder, AggregatedCommandExecutor, RedundantResource, DnsServ
|
||||
|
||||
@Override
|
||||
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();
|
||||
UserVmVO destVm = _userVmDao.findById(uvm.getId());
|
||||
VirtualMachineProfile profile = null;
|
||||
|
||||
@ -3622,8 +3622,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
||||
templateVO = _templateStoreDao.findByStoreTemplate(store.getId(), templateId);
|
||||
if (templateVO != null) {
|
||||
try {
|
||||
if (SystemVmTemplateRegistration.validateIfSeeded(
|
||||
url, templateVO.getInstallPath(), nfsVersion)) {
|
||||
if (systemVmTemplateRegistration.validateIfSeeded(
|
||||
templateVO, url, templateVO.getInstallPath(), nfsVersion)) {
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
@ -2482,10 +2482,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
||||
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());
|
||||
Pair<Long, Long> clusterHostId = virtualMachineManager.findClusterAndHostIdForVm(vm, false);
|
||||
long podId = vm.getPodIdToDeployIn();
|
||||
Long podId = vm.getPodIdToDeployIn();
|
||||
if (clusterHostId.first() != null) {
|
||||
Cluster cluster = clusterDao.findById(clusterHostId.first());
|
||||
podId = cluster.getPodId();
|
||||
@ -2497,12 +2497,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
||||
offering.isUseLocalStorage(), offering.isRecreatable(),
|
||||
volumeToAttach.getTemplateId());
|
||||
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());
|
||||
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) {
|
||||
@ -2520,7 +2516,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
||||
}
|
||||
}
|
||||
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 {
|
||||
if (volumeOnSecondary && Storage.StoragePoolType.PowerFlex.equals(destPrimaryStorage.getPoolType())) {
|
||||
|
||||
@ -498,8 +498,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
|
||||
if (apiNameList == null) {
|
||||
long startTime = System.nanoTime();
|
||||
apiNameList = new ArrayList<String>();
|
||||
Set<Class<?>> cmdClasses = new LinkedHashSet<Class<?>>();
|
||||
apiNameList = new ArrayList<>();
|
||||
Set<Class<?>> cmdClasses = new LinkedHashSet<>();
|
||||
for (PluggableService service : services) {
|
||||
logger.debug(String.format("getting api commands of service: %s", service.getClass().getName()));
|
||||
cmdClasses.addAll(service.getCommands());
|
||||
@ -513,7 +513,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
}
|
||||
|
||||
protected List<String> createApiNameList(Set<Class<?>> cmdClasses) {
|
||||
List<String> apiNameList = new ArrayList<String>();
|
||||
List<String> apiNameList = new ArrayList<>();
|
||||
|
||||
for (Class<?> cmdClass : cmdClasses) {
|
||||
APICommand apiCmdAnnotation = cmdClass.getAnnotation(APICommand.class);
|
||||
@ -698,7 +698,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<Long, List<ControlledEntity>> domains = new HashMap<Long, List<ControlledEntity>>();
|
||||
HashMap<Long, List<ControlledEntity>> domains = new HashMap<>();
|
||||
|
||||
for (ControlledEntity entity : entities) {
|
||||
long domainId = entity.getDomainId();
|
||||
@ -713,7 +713,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId());
|
||||
// for templates, we don't have to do cross domains check
|
||||
if (toBeChecked == null) {
|
||||
toBeChecked = new ArrayList<ControlledEntity>();
|
||||
toBeChecked = new ArrayList<>();
|
||||
domains.put(domainId, toBeChecked);
|
||||
}
|
||||
toBeChecked.add(entity);
|
||||
@ -722,7 +722,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
for (SecurityChecker checker : _securityCheckers) {
|
||||
if (checker.checkAccess(caller, entity, accessType, apiName)) {
|
||||
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;
|
||||
break;
|
||||
@ -1023,12 +1027,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
logger.debug("Deleting networks for account {}", account);
|
||||
List<NetworkVO> networks = _networkDao.listByOwner(accountId);
|
||||
if (networks != null) {
|
||||
Collections.sort(networks, new Comparator<NetworkVO>() {
|
||||
Collections.sort(networks, new Comparator<>() {
|
||||
@Override
|
||||
public int compare(NetworkVO network1, NetworkVO network2) {
|
||||
if (network1.getGuestType() != network2.getGuestType() && Network.GuestType.Isolated.equals(network2.getGuestType())) {
|
||||
return -1;
|
||||
};
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
@ -1300,7 +1304,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
final String accountNameFinal = accountName;
|
||||
final Long domainIdFinal = domainId;
|
||||
final String accountUUIDFinal = accountUUID;
|
||||
Pair<Long, Account> pair = Transaction.execute(new TransactionCallback<Pair<Long, Account>>() {
|
||||
Pair<Long, Account> pair = Transaction.execute(new TransactionCallback<>() {
|
||||
@Override
|
||||
public Pair<Long, Account> doInTransaction(TransactionStatus status) {
|
||||
// create account
|
||||
@ -1323,7 +1327,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
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
|
||||
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));
|
||||
_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)) {
|
||||
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);
|
||||
return user;
|
||||
}
|
||||
@ -1731,7 +1735,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
Long callingUserId = CallContext.current().getCallingUserId();
|
||||
Account callingAccount = CallContext.current().getCallingAccount();
|
||||
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());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
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();
|
||||
Account callingAccount = CallContext.current().getCallingAccount();
|
||||
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());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
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);
|
||||
|
||||
boolean success = Transaction.execute(new TransactionCallback<Boolean>() {
|
||||
boolean success = Transaction.execute(new TransactionCallback<>() {
|
||||
@Override
|
||||
public Boolean doInTransaction(TransactionStatus status) {
|
||||
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
|
||||
// if the user is either locked already or disabled already, don't change state...only lock currently enabled
|
||||
// users
|
||||
boolean success = true;
|
||||
boolean success;
|
||||
if (user.getState().equals(State.LOCKED)) {
|
||||
// already locked...no-op
|
||||
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) {
|
||||
|
||||
// Check if account exists
|
||||
Account account = null;
|
||||
Account account;
|
||||
if (accountId != null) {
|
||||
account = _accountDao.findById(accountId);
|
||||
} else {
|
||||
@ -2021,7 +2025,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
|
||||
return _accountDao.findById(account.getId());
|
||||
} 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) {
|
||||
Account caller = getCurrentCallingAccount();
|
||||
|
||||
Account account = null;
|
||||
Account account;
|
||||
if (accountId != null) {
|
||||
account = _accountDao.findById(accountId);
|
||||
} else {
|
||||
@ -2051,7 +2055,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
CallContext.current().putContextParameter(Account.class, account.getUuid());
|
||||
return _accountDao.findById(account.getId());
|
||||
} 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 {
|
||||
Account caller = getCurrentCallingAccount();
|
||||
|
||||
Account account = null;
|
||||
Account account;
|
||||
if (accountId != null) {
|
||||
account = _accountDao.findById(accountId);
|
||||
} else {
|
||||
@ -2097,8 +2101,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
String networkDomain = cmd.getNetworkDomain();
|
||||
final Map<String, String> details = cmd.getDetails();
|
||||
|
||||
boolean success = false;
|
||||
Account account = null;
|
||||
boolean success;
|
||||
Account account;
|
||||
if (accountId != null) {
|
||||
account = _accountDao.findById(accountId);
|
||||
} else {
|
||||
@ -2159,7 +2163,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
if (roleNotFound) {
|
||||
throw new InvalidParameterValueException(String.format("Role with ID '%s' is not " +
|
||||
"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);
|
||||
@ -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 Transaction.execute(new TransactionCallback<Boolean>() {
|
||||
return Transaction.execute(new TransactionCallback<>() {
|
||||
@Override
|
||||
public Boolean doInTransaction(TransactionStatus status) {
|
||||
UserVO newUser = new UserVO(user);
|
||||
@ -2560,7 +2564,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
}
|
||||
|
||||
// Create the account
|
||||
return Transaction.execute(new TransactionCallback<AccountVO>() {
|
||||
return Transaction.execute(new TransactionCallback<>() {
|
||||
@Override
|
||||
public AccountVO doInTransaction(TransactionStatus status) {
|
||||
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);
|
||||
String signature = null;
|
||||
long timestamp = 0L;
|
||||
String unsignedRequest = null;
|
||||
String unsignedRequest;
|
||||
StringBuffer unsignedRequestBuffer = new StringBuffer();
|
||||
|
||||
// - build a request string with sorted params, make sure it's all lowercase
|
||||
// - 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()) {
|
||||
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);
|
||||
|
||||
boolean authenticated = false;
|
||||
HashSet<ActionOnFailedAuthentication> actionsOnFailedAuthenticaion = new HashSet<ActionOnFailedAuthentication>();
|
||||
HashSet<ActionOnFailedAuthentication> actionsOnFailedAuthenticaion = new HashSet<>();
|
||||
User.Source userSource = userAccount != null ? userAccount.getSource() : User.Source.UNKNOWN;
|
||||
for (UserAuthenticator authenticator : _userAuthenticators) {
|
||||
final String[] secretCodeArray = (String[])requestParameters.get(ApiConstants.SECRET_CODE);
|
||||
@ -2886,7 +2890,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
preventRootDomainAdminAccessToRootAdminKeys(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("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) {
|
||||
@ -2999,8 +3003,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
try {
|
||||
UserVO updatedUser = _userDao.createForUpdate();
|
||||
|
||||
String encodedKey = null;
|
||||
Pair<User, Account> userAcct = null;
|
||||
String encodedKey;
|
||||
Pair<User, Account> userAcct;
|
||||
int retryLimit = 10;
|
||||
do {
|
||||
// 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) {
|
||||
try {
|
||||
UserVO updatedUser = _userDao.createForUpdate();
|
||||
String encodedKey = null;
|
||||
String encodedKey;
|
||||
int retryLimit = 10;
|
||||
UserVO userBySecretKey = null;
|
||||
UserVO userBySecretKey;
|
||||
do {
|
||||
KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
|
||||
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");
|
||||
}
|
||||
|
||||
Account userAccount = null;
|
||||
Domain domain = null;
|
||||
Account userAccount;
|
||||
Domain domain;
|
||||
if (domainId != null) {
|
||||
userAccount = _accountDao.findActiveAccount(accountName, domainId);
|
||||
domain = _domainDao.findById(domainId);
|
||||
@ -3262,7 +3266,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
@Override
|
||||
public List<String> listAclGroupsByAccount(Long accountId) {
|
||||
if (_querySelectors == null || _querySelectors.size() == 0) {
|
||||
return new ArrayList<String>();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
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) {
|
||||
UserVO userVO = null;
|
||||
UserVO userVO;
|
||||
if (userId != null) {
|
||||
userVO = validateUser(userId);
|
||||
owner = _accountService.getActiveAccountById(userVO.getAccountId());
|
||||
|
||||
@ -134,8 +134,8 @@ import org.apache.cloudstack.storage.template.VnfTemplateManager;
|
||||
import org.apache.cloudstack.userdata.UserDataManager;
|
||||
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
|
||||
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.UnmanagedVMsManager;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
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");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@ -4526,7 +4526,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
}
|
||||
|
||||
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);
|
||||
return rootDiskSize;
|
||||
} else {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -2038,13 +2038,13 @@ public class VolumeApiServiceImplTest {
|
||||
when(volumeToAttach.getDiskOfferingId()).thenReturn(1L);
|
||||
when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(1L), eq(2L), eq(vm), eq(Collections.emptySet())))
|
||||
.thenReturn(pool);
|
||||
StoragePool result = volumeApiServiceImpl.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
StoragePool result = volumeApiServiceImpl.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
Assert.assertNotNull(result);
|
||||
Assert.assertEquals(pool, result);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void testGetPoolForAllocatedOrUploadedVolumeForAttach_NoPoolFound_ThrowsException() {
|
||||
@Test
|
||||
public void testGetPoolForAllocatedOrUploadedVolumeForAttach_NoSuitablePoolFound_ReturnsNull() {
|
||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
||||
DataCenterVO zone = mockZone();
|
||||
@ -2059,11 +2059,11 @@ public class VolumeApiServiceImplTest {
|
||||
when(volumeToAttach.getDiskOfferingId()).thenReturn(1L);
|
||||
when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(1L), eq(2L), eq(vm), eq(Collections.emptySet())))
|
||||
.thenReturn(null);
|
||||
volumeApiServiceImpl.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
Assert.assertNull(volumeApiServiceImpl.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPoolForAllocatedOrUploadedVolumeForAttach_NoCluster() {
|
||||
public void testGetSuitablePoolForAllocatedOrUploadedVolumeForAttach_NoCluster() {
|
||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
||||
DataCenterVO zone = mockZone();
|
||||
@ -2077,7 +2077,7 @@ public class VolumeApiServiceImplTest {
|
||||
when(volumeToAttach.getDiskOfferingId()).thenReturn(1L);
|
||||
when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(null), eq(2L), eq(vm), eq(Collections.emptySet())))
|
||||
.thenReturn(pool);
|
||||
StoragePool result = volumeApiServiceImpl.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
StoragePool result = volumeApiServiceImpl.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
Assert.assertNotNull(result);
|
||||
Assert.assertEquals(pool, result);
|
||||
}
|
||||
@ -2123,7 +2123,7 @@ public class VolumeApiServiceImplTest {
|
||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
||||
StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class);
|
||||
Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl)
|
||||
.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
VolumeInfo newVolumeOnPrimaryStorage = Mockito.mock(VolumeInfo.class);
|
||||
try {
|
||||
Mockito.when(volumeOrchestrationService.createVolumeOnPrimaryStorage(
|
||||
@ -2134,7 +2134,7 @@ public class VolumeApiServiceImplTest {
|
||||
}
|
||||
VolumeInfo result = volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null);
|
||||
Assert.assertSame(newVolumeOnPrimaryStorage, result);
|
||||
verify(volumeApiServiceImpl).getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
verify(volumeApiServiceImpl).getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
@ -2145,7 +2145,7 @@ public class VolumeApiServiceImplTest {
|
||||
StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class);
|
||||
when(destPrimaryStorage.getPoolType()).thenReturn(Storage.StoragePoolType.PowerFlex);
|
||||
Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl)
|
||||
.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null);
|
||||
}
|
||||
|
||||
@ -2157,7 +2157,7 @@ public class VolumeApiServiceImplTest {
|
||||
StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class);
|
||||
Mockito.when(destPrimaryStorage.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem);
|
||||
Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl)
|
||||
.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
.getSuitablePoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
||||
try {
|
||||
Mockito.when(volumeOrchestrationService.createVolumeOnPrimaryStorage(vm, volumeToAttach, vm.getHypervisorType(), destPrimaryStorage))
|
||||
.thenThrow(new NoTransitionException("Mocked exception"));
|
||||
@ -2169,4 +2169,35 @@ public class VolumeApiServiceImplTest {
|
||||
);
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,11 +40,6 @@ public class LocalNfsSecondaryStorageResource extends NfsSecondaryStorageResourc
|
||||
this._inSystemVM = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParentPath(String path) {
|
||||
this._parent = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
return super.executeRequest(cmd);
|
||||
@ -57,7 +52,7 @@ public class LocalNfsSecondaryStorageResource extends NfsSecondaryStorageResourc
|
||||
String dir = mountUri(uri, nfsVersion);
|
||||
return _parent + "/" + dir;
|
||||
} 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);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
@ -75,14 +70,14 @@ public class LocalNfsSecondaryStorageResource extends NfsSecondaryStorageResourc
|
||||
|
||||
// Change permissions for the mountpoint - seems to bypass authentication
|
||||
Script script = new Script(true, "chmod", _timeout, logger);
|
||||
script.add("777", localRootPath);
|
||||
script.add("1777", localRootPath);
|
||||
String result = script.execute();
|
||||
if (result != null) {
|
||||
String errMsg = "Unable to set permissions for " + localRootPath + " due to " + result;
|
||||
logger.error(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
|
||||
// to move it somewhere more logical later.
|
||||
|
||||
@ -19,15 +19,16 @@ import logging
|
||||
from netaddr import IPAddress, IPNetwork
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from . import CsHelper
|
||||
from .CsDatabag import CsDataBag
|
||||
from .CsApp import CsApache, CsDnsmasq, CsPasswdSvc
|
||||
from .CsRoute import CsRoute
|
||||
from .CsRule import CsRule
|
||||
from .CsStaticRoutes import CsStaticRoutes
|
||||
|
||||
VRRP_TYPES = ['guest']
|
||||
|
||||
|
||||
class CsAddress(CsDataBag):
|
||||
|
||||
def compare(self):
|
||||
@ -556,8 +557,10 @@ class CsIP:
|
||||
(self.dev, guestNetworkCidr, self.address['gateway'], self.dev)])
|
||||
|
||||
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.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(["mangle", "",
|
||||
"-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",
|
||||
"-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:])))])
|
||||
|
||||
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"]:
|
||||
self.fw.append(["nat", "front",
|
||||
"-A POSTROUTING -o %s -j SNAT --to-source %s" %
|
||||
|
||||
@ -139,8 +139,7 @@ class CsDhcp(CsDataBag):
|
||||
# Listen Address
|
||||
if self.cl.is_redundant():
|
||||
listen_address.append(gateway)
|
||||
else:
|
||||
listen_address.append(ip)
|
||||
listen_address.append(ip)
|
||||
# Add localized "data-server" records in /etc/hosts for VPC routers
|
||||
if self.config.is_vpc() or self.config.is_router():
|
||||
self.add_host(gateway, "%s data-server" % CsHelper.get_hostname())
|
||||
|
||||
@ -74,6 +74,7 @@ class TestData(object):
|
||||
"listApis": "allow",
|
||||
"listAccounts": "allow",
|
||||
"listClusters": "deny",
|
||||
"*VmwareDc*": "allow",
|
||||
"*VM*": "allow",
|
||||
"*Host*": "deny"
|
||||
}
|
||||
|
||||
@ -3263,6 +3263,7 @@
|
||||
"message.license.agreements.not.accepted": "License agreements not accepted.",
|
||||
"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.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.load.host.failed": "Failed to load hosts.",
|
||||
"message.loadbalancer.stickypolicy.configuration": "Customize the load balancer stickiness policy:",
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
import { shallowRef, defineAsyncComponent } from 'vue'
|
||||
import store from '@/store'
|
||||
import { isZoneCreated } from '@/utils/zone'
|
||||
|
||||
export default {
|
||||
name: 'compute',
|
||||
@ -100,6 +101,7 @@ export default {
|
||||
label: 'label.vm.add',
|
||||
docHelp: 'adminguide/virtual_machines.html#creating-vms',
|
||||
listView: true,
|
||||
show: isZoneCreated,
|
||||
component: () => import('@/views/compute/DeployVM.vue')
|
||||
},
|
||||
{
|
||||
@ -225,6 +227,10 @@ export default {
|
||||
args: ['virtualmachineid', 'backupofferingid'],
|
||||
show: (record) => { return !record.backupofferingid },
|
||||
mapping: {
|
||||
backupofferingid: {
|
||||
api: 'listBackupOfferings',
|
||||
params: (record) => { return { zoneid: record.zoneid } }
|
||||
},
|
||||
virtualmachineid: {
|
||||
value: (record, params) => { return record.id }
|
||||
}
|
||||
@ -569,6 +575,7 @@ export default {
|
||||
docHelp: 'plugins/cloudstack-kubernetes-service.html#creating-a-new-kubernetes-cluster',
|
||||
listView: true,
|
||||
popup: true,
|
||||
show: isZoneCreated,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/compute/CreateKubernetesCluster.vue')))
|
||||
},
|
||||
{
|
||||
@ -697,6 +704,7 @@ export default {
|
||||
icon: 'plus-outlined',
|
||||
label: 'label.new.autoscale.vmgroup',
|
||||
listView: true,
|
||||
show: isZoneCreated,
|
||||
component: () => import('@/views/compute/CreateAutoScaleVmGroup.vue')
|
||||
},
|
||||
{
|
||||
@ -787,6 +795,7 @@ export default {
|
||||
icon: 'plus-outlined',
|
||||
label: 'label.new.instance.group',
|
||||
listView: true,
|
||||
show: isZoneCreated,
|
||||
args: ['name']
|
||||
},
|
||||
{
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
import { shallowRef, defineAsyncComponent } from 'vue'
|
||||
import store from '@/store'
|
||||
import { isZoneCreated } from '@/utils/zone'
|
||||
|
||||
export default {
|
||||
name: 'image',
|
||||
@ -110,16 +111,17 @@ export default {
|
||||
docHelp: 'adminguide/templates.html#uploading-templates-from-a-remote-http-server',
|
||||
listView: true,
|
||||
popup: true,
|
||||
show: isZoneCreated,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadTemplate.vue')))
|
||||
},
|
||||
{
|
||||
api: 'registerTemplate',
|
||||
icon: 'cloud-upload-outlined',
|
||||
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',
|
||||
listView: true,
|
||||
popup: true,
|
||||
show: () => { return isZoneCreated() && 'getUploadParamsForTemplate' in store.getters.apis },
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadTemplate.vue')))
|
||||
},
|
||||
{
|
||||
@ -270,13 +272,14 @@ export default {
|
||||
docHelp: 'adminguide/templates.html#id10',
|
||||
listView: true,
|
||||
popup: true,
|
||||
show: isZoneCreated,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/image/RegisterOrUploadIso.vue')))
|
||||
},
|
||||
{
|
||||
api: 'registerIso',
|
||||
icon: 'cloud-upload-outlined',
|
||||
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',
|
||||
listView: true,
|
||||
popup: true,
|
||||
@ -389,6 +392,7 @@ export default {
|
||||
label: 'label.kubernetes.version.add',
|
||||
listView: true,
|
||||
popup: true,
|
||||
show: isZoneCreated,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/image/AddKubernetesSupportedVersion.vue')))
|
||||
},
|
||||
{
|
||||
|
||||
@ -19,6 +19,7 @@ import { shallowRef, defineAsyncComponent } from 'vue'
|
||||
import store from '@/store'
|
||||
import tungsten from '@/assets/icons/tungsten.svg?inline'
|
||||
import { isAdmin } from '@/role'
|
||||
import { isZoneCreated } from '@/utils/zone'
|
||||
|
||||
export default {
|
||||
name: 'network',
|
||||
@ -123,7 +124,7 @@ export default {
|
||||
listView: true,
|
||||
popup: true,
|
||||
show: () => {
|
||||
if (!store.getters.zones || store.getters.zones.length === 0) {
|
||||
if (!isZoneCreated()) {
|
||||
return false
|
||||
}
|
||||
const AdvancedZones = store.getters.zones.filter(zone => zone.networktype === 'Advanced')
|
||||
@ -245,6 +246,7 @@ export default {
|
||||
icon: 'plus-outlined',
|
||||
label: 'label.add.vpc',
|
||||
docHelp: 'adminguide/networking_and_traffic.html#adding-a-virtual-private-cloud',
|
||||
show: isZoneCreated,
|
||||
listView: true,
|
||||
popup: true,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/CreateVpc.vue')))
|
||||
@ -306,7 +308,7 @@ export default {
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/IngressEgressRuleConfigure.vue')))
|
||||
}],
|
||||
show: () => {
|
||||
if (!store.getters.zones || store.getters.zones.length === 0) {
|
||||
if (!isZoneCreated()) {
|
||||
return false
|
||||
}
|
||||
const listZoneHaveSGEnabled = store.getters.zones.filter(zone => zone.securitygroupsenabled === true)
|
||||
@ -394,6 +396,7 @@ export default {
|
||||
label: 'label.vnf.appliance.add',
|
||||
docHelp: 'adminguide/networking/vnf_templates_appliances.html#deploying-vnf-appliances',
|
||||
listView: true,
|
||||
show: isZoneCreated,
|
||||
component: () => import('@/views/compute/DeployVnfAppliance.vue')
|
||||
},
|
||||
{
|
||||
@ -941,6 +944,7 @@ export default {
|
||||
label: 'label.add.vpn.gateway',
|
||||
docHelp: 'adminguide/networking_and_traffic.html#creating-a-vpn-gateway-for-the-vpc',
|
||||
listView: true,
|
||||
show: isZoneCreated,
|
||||
args: ['vpcid']
|
||||
},
|
||||
{
|
||||
@ -1116,6 +1120,7 @@ export default {
|
||||
icon: 'plus-outlined',
|
||||
label: 'label.add.vpn.user',
|
||||
listView: true,
|
||||
show: isZoneCreated,
|
||||
args: (record, store) => {
|
||||
if (store.userInfo.roletype === 'User') {
|
||||
return ['username', 'password']
|
||||
@ -1195,6 +1200,7 @@ export default {
|
||||
docHelp: 'adminguide/networking_and_traffic.html#creating-and-updating-a-vpn-customer-gateway',
|
||||
listView: true,
|
||||
popup: true,
|
||||
show: isZoneCreated,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/CreateVpnCustomerGateway.vue')))
|
||||
},
|
||||
{
|
||||
@ -1384,12 +1390,7 @@ export default {
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/GuestVlanNetworksTab.vue'))),
|
||||
show: (record) => { return (record.allocationstate === 'Allocated') }
|
||||
}],
|
||||
show: () => {
|
||||
if (!store.getters.zones || store.getters.zones.length === 0) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
show: isZoneCreated
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
import { shallowRef, defineAsyncComponent } from 'vue'
|
||||
import store from '@/store'
|
||||
import { isZoneCreated } from '@/utils/zone'
|
||||
|
||||
export default {
|
||||
name: 'storage',
|
||||
@ -103,6 +104,7 @@ export default {
|
||||
icon: 'plus-outlined',
|
||||
docHelp: 'adminguide/storage.html#creating-a-new-volume',
|
||||
label: 'label.action.create.volume',
|
||||
show: isZoneCreated,
|
||||
listView: true,
|
||||
popup: true,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/storage/CreateVolume.vue')))
|
||||
@ -112,7 +114,7 @@ export default {
|
||||
icon: 'cloud-upload-outlined',
|
||||
docHelp: 'adminguide/storage.html#uploading-an-existing-volume-to-a-virtual-machine',
|
||||
label: 'label.upload.volume.from.local',
|
||||
show: () => { return 'getUploadParamsForVolume' in store.getters.apis },
|
||||
show: () => { return isZoneCreated() && 'getUploadParamsForVolume' in store.getters.apis },
|
||||
listView: true,
|
||||
popup: true,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/storage/UploadLocalVolume.vue')))
|
||||
@ -122,6 +124,7 @@ export default {
|
||||
icon: 'link-outlined',
|
||||
docHelp: 'adminguide/storage.html#uploading-an-existing-volume-to-a-virtual-machine',
|
||||
label: 'label.upload.volume.from.url',
|
||||
show: isZoneCreated,
|
||||
listView: true,
|
||||
popup: true,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/storage/UploadVolume.vue')))
|
||||
|
||||
25
ui/src/utils/zone.js
Normal file
25
ui/src/utils/zone.js
Normal 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
|
||||
}
|
||||
@ -793,6 +793,10 @@ export default {
|
||||
if (this.scopeType === 'domain') {
|
||||
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.networkOfferings = []
|
||||
api('listNetworkOfferings', params).then(json => {
|
||||
|
||||
@ -1198,6 +1198,7 @@ export default {
|
||||
} else {
|
||||
params.existingvcenterid = this.selectedVmwareVcenter.existingvcenterid
|
||||
}
|
||||
params.host = this.selectedVmwareVcenter.host
|
||||
}
|
||||
|
||||
api(apiName, params).then(json => {
|
||||
|
||||
@ -89,6 +89,7 @@
|
||||
<a-input
|
||||
v-model:value="vcenter"
|
||||
:placeholder="apiParams.vcenter.description"
|
||||
@change="onSelectExternalVmwareDatacenter"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item ref="datacenter" name="datacenter">
|
||||
@ -98,6 +99,7 @@
|
||||
<a-input
|
||||
v-model:value="datacenter"
|
||||
:placeholder="apiParams.datacentername.description"
|
||||
@change="onSelectExternalVmwareDatacenter"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item ref="username" name="username">
|
||||
@ -107,6 +109,7 @@
|
||||
<a-input
|
||||
v-model:value="username"
|
||||
:placeholder="apiParams.username.description"
|
||||
@change="onSelectExternalVmwareDatacenter"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item ref="password" name="password">
|
||||
@ -116,14 +119,36 @@
|
||||
<a-input-password
|
||||
v-model:value="password"
|
||||
:placeholder="apiParams.password.description"
|
||||
@change="onSelectExternalVmwareDatacenter"
|
||||
/>
|
||||
</a-form-item>
|
||||
</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">
|
||||
<a-button
|
||||
v-if="vcenterSelectedOption == 'existing' || vcenterSelectedOption == 'new'"
|
||||
:disabled="(vcenterSelectedOption === 'new' && (vcenter === '' || datacentername === '' || username === '' || password === '')) ||
|
||||
(vcenterSelectedOption === 'existing' && selectedExistingVcenterId === '')"
|
||||
(vcenterSelectedOption === 'existing' && selectedExistingVcenterId === '') && host === ''"
|
||||
:loading="loading"
|
||||
type="primary"
|
||||
@click="listVmwareDatacenterVms">{{ $t('label.list.vmware.vcenter.vms') }}</a-button>
|
||||
@ -154,6 +179,8 @@ export default {
|
||||
zones: {},
|
||||
vcenterSelectedOption: '',
|
||||
existingvcenter: [],
|
||||
hosts: [],
|
||||
selectedHost: '',
|
||||
selectedExistingVcenterId: '',
|
||||
selectedPoweredOnVm: false,
|
||||
vmwareDcVms: [],
|
||||
@ -217,6 +244,7 @@ export default {
|
||||
} else {
|
||||
params.existingvcenterid = this.selectedExistingVcenterId
|
||||
}
|
||||
params.host = this.selectedHost
|
||||
api('listVmwareDcVms', params).then(json => {
|
||||
const obj = {
|
||||
params: params,
|
||||
@ -246,8 +274,29 @@ export default {
|
||||
listZoneVmwareDcs () {
|
||||
this.loading = true
|
||||
api('listVmwareDcs', { zoneid: this.sourcezoneid }).then(response => {
|
||||
if (response.listvmwaredcsresponse.VMwareDC && response.listvmwaredcsresponse.VMwareDC.length > 0) {
|
||||
this.existingvcenter = response.listvmwaredcsresponse.VMwareDC
|
||||
if (response.listvmwaredcsresponse.vmwaredc && response.listvmwaredcsresponse.vmwaredc.length > 0) {
|
||||
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 => {
|
||||
this.$notifyError(error)
|
||||
@ -257,6 +306,15 @@ export default {
|
||||
},
|
||||
onSelectExistingVmwareDatacenter (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 () {
|
||||
this.$emit('onVcenterTypeChanged', this.vcenterSelectedOption)
|
||||
|
||||
@ -19,14 +19,25 @@ package com.cloud.hypervisor.vmware.mo;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
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.CustomFieldStringValue;
|
||||
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 {
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
protected static Logger logger = LogManager.getLogger(BaseMO.class);
|
||||
|
||||
protected VmwareContext _context;
|
||||
protected ManagedObjectReference _mor;
|
||||
@ -51,6 +62,15 @@ public class BaseMO {
|
||||
_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() {
|
||||
return _context;
|
||||
}
|
||||
@ -61,12 +81,12 @@ public class BaseMO {
|
||||
}
|
||||
|
||||
public ManagedObjectReference getParentMor() throws Exception {
|
||||
return (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "parent");
|
||||
return _context.getVimClient().getDynamicProperty(_mor, "parent");
|
||||
}
|
||||
|
||||
public String getName() throws Exception {
|
||||
if (_name == null)
|
||||
_name = (String)_context.getVimClient().getDynamicProperty(_mor, "name");
|
||||
_name = _context.getVimClient().getDynamicProperty(_mor, "name");
|
||||
|
||||
return _name;
|
||||
}
|
||||
@ -83,7 +103,7 @@ public class BaseMO {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
@ -100,7 +120,7 @@ public class BaseMO {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
return true;
|
||||
} 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;
|
||||
}
|
||||
@ -131,18 +151,18 @@ public class BaseMO {
|
||||
if (key == 0)
|
||||
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)
|
||||
return cfValue.getValue();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ManagedObjectReference cfmMor = _context.getServiceContent().getCustomFieldsManager();
|
||||
@ -154,4 +174,30 @@ public class BaseMO {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,11 +16,14 @@
|
||||
// under the License.
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
|
||||
import com.vmware.vim25.CustomFieldDef;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.PrivilegePolicyDef;
|
||||
import com.vmware.vim25.InvalidPropertyFaultMsg;
|
||||
import com.vmware.vim25.RuntimeFaultFaultMsg;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
|
||||
@ -50,12 +53,12 @@ public class CustomFieldsManagerMO extends BaseMO {
|
||||
_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");
|
||||
}
|
||||
|
||||
@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();
|
||||
if (fields != null) {
|
||||
for (CustomFieldDef field : fields) {
|
||||
|
||||
@ -17,11 +17,12 @@
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
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.commons.collections.CollectionUtils;
|
||||
|
||||
@ -38,6 +39,10 @@ import com.vmware.vim25.PropertySpec;
|
||||
import com.vmware.vim25.SelectionSpec;
|
||||
import com.vmware.vim25.TraversalSpec;
|
||||
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.utils.Pair;
|
||||
@ -52,35 +57,18 @@ public class DatacenterMO extends BaseMO {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public DatacenterMO(VmwareContext context, String dcName) throws Exception {
|
||||
public DatacenterMO(VmwareContext context, String dcName) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
|
||||
super(context, null);
|
||||
|
||||
_mor = _context.getVimClient().getDecendentMoRef(_context.getRootFolder(), "Datacenter", dcName);
|
||||
if (_mor == null) {
|
||||
logger.error("Unable to locate DC " + dcName);
|
||||
logger.error("Unable to locate DC {}", dcName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() throws Exception {
|
||||
return (String)_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 String getName() throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
|
||||
return _context.getVimClient().getDynamicProperty(_mor, "name");
|
||||
}
|
||||
|
||||
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 ?!");
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@ -98,10 +86,10 @@ public class DatacenterMO extends BaseMO {
|
||||
int key = cfmMo.getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_UUID);
|
||||
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)});
|
||||
if (ocs != null && ocs.size() > 0) {
|
||||
List<ObjectContent> ocs = getVmProperties(new String[] {"name", String.format("value[%d]", key)});
|
||||
if (CollectionUtils.isNotEmpty(ocs)) {
|
||||
for (ObjectContent oc : ocs) {
|
||||
List<DynamicProperty> props = oc.getPropSet();
|
||||
if (props != null) {
|
||||
@ -133,8 +121,8 @@ public class DatacenterMO extends BaseMO {
|
||||
logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!");
|
||||
}
|
||||
|
||||
List<ObjectContent> ocs = getVmPropertiesOnDatacenterVmFolder(new String[] {"name", String.format("value[%d]", key)});
|
||||
if (ocs != null && ocs.size() > 0) {
|
||||
List<ObjectContent> ocs = getVmProperties(new String[] {"name", String.format("value[%d]", key)});
|
||||
if (CollectionUtils.isNotEmpty(ocs)) {
|
||||
for (ObjectContent oc : ocs) {
|
||||
List<DynamicProperty> props = oc.getPropSet();
|
||||
if (props != null) {
|
||||
@ -159,31 +147,18 @@ public class DatacenterMO extends BaseMO {
|
||||
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<ObjectContent> ocs = getVmPropertiesOnDatacenterVmFolder(new String[] {"name"});
|
||||
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(String.format("Unexpected error checking unmanaged instance %s, excluding it: %s", vmMo.getVmName(), e.getMessage()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
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<ObjectContent> ocs = getHostPropertiesOnDatacenterHostFolder(new String[] {"name"});
|
||||
@ -210,21 +185,7 @@ public class DatacenterMO extends BaseMO {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ManagedObjectReference listDatastore(String name) throws Exception {
|
||||
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 {
|
||||
public ManagedObjectReference findHost(String name) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
|
||||
List<ObjectContent> ocs = getHostPropertiesOnDatacenterHostFolder(new String[] {"name"});
|
||||
|
||||
if (ocs != null) {
|
||||
@ -238,10 +199,10 @@ public class DatacenterMO extends BaseMO {
|
||||
}
|
||||
|
||||
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();
|
||||
pSpec.setType("HostSystem");
|
||||
pSpec.getPathSet().addAll(Arrays.asList(propertyPaths));
|
||||
@ -275,7 +236,7 @@ public class DatacenterMO extends BaseMO {
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.getPropSet().add(pSpec);
|
||||
pfSpec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
|
||||
pfSpecArr.add(pfSpec);
|
||||
|
||||
return _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
|
||||
@ -301,14 +262,37 @@ public class DatacenterMO extends BaseMO {
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.getPropSet().add(pSpec);
|
||||
pfSpec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
|
||||
pfSpecArr.add(pfSpec);
|
||||
|
||||
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();
|
||||
pSpec.setType("VirtualMachine");
|
||||
pSpec.getPathSet().addAll(Arrays.asList(propertyPaths));
|
||||
@ -336,10 +320,16 @@ public class DatacenterMO extends BaseMO {
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.getPropSet().add(pSpec);
|
||||
pfSpec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
|
||||
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 {
|
||||
@ -364,18 +354,18 @@ public class DatacenterMO extends BaseMO {
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.getPropSet().add(pSpec);
|
||||
pfSpec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
|
||||
pfSpecArr.add(pfSpec);
|
||||
|
||||
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).getPropSet().get(0) != null);
|
||||
assert (ocs.get(0).getPropSet().get(0).getVal() != null);
|
||||
|
||||
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 {
|
||||
@ -396,7 +386,7 @@ public class DatacenterMO extends BaseMO {
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.getPropSet().add(pSpec);
|
||||
pfSpec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
|
||||
pfSpecArr.add(pfSpec);
|
||||
|
||||
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 {
|
||||
ManagedObjectReference morNetwork = getDvPortGroupMor(dvPortGroupName);
|
||||
if (morNetwork != null)
|
||||
return true;
|
||||
return false;
|
||||
return morNetwork != null;
|
||||
}
|
||||
|
||||
public DVPortgroupConfigInfo getDvPortGroupSpec(String dvPortGroupName) throws Exception {
|
||||
@ -443,7 +431,7 @@ public class DatacenterMO extends BaseMO {
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.getPropSet().add(pSpec);
|
||||
pfSpec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
|
||||
pfSpecArr.add(pfSpec);
|
||||
|
||||
List<ObjectContent> ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
|
||||
@ -460,7 +448,7 @@ public class DatacenterMO extends BaseMO {
|
||||
nameProperty = prop.getVal().toString();
|
||||
}
|
||||
}
|
||||
if (nameProperty.equalsIgnoreCase(dvPortGroupName)) {
|
||||
if (nameProperty != null && nameProperty.equalsIgnoreCase(dvPortGroupName)) {
|
||||
return configSpec;
|
||||
}
|
||||
}
|
||||
@ -490,7 +478,7 @@ public class DatacenterMO extends BaseMO {
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.getPropSet().add(pSpec);
|
||||
pfSpec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
|
||||
pfSpecArr.add(pfSpec);
|
||||
|
||||
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 {
|
||||
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 {
|
||||
@ -536,8 +524,8 @@ public class DatacenterMO extends BaseMO {
|
||||
}
|
||||
|
||||
public ManagedObjectReference getDvSwitchMor(String dvSwitchName) throws Exception {
|
||||
ManagedObjectReference dvSwitchMor = null;
|
||||
ManagedObjectReference networkFolderMor = null;
|
||||
ManagedObjectReference dvSwitchMor;
|
||||
ManagedObjectReference networkFolderMor;
|
||||
networkFolderMor = _context.getVimClient().getMoRefProp(_mor, "networkFolder");
|
||||
dvSwitchMor = _context.getVimClient().getDecendentMoRef(networkFolderMor, "VmwareDistributedVirtualSwitch", dvSwitchName);
|
||||
return dvSwitchMor;
|
||||
@ -549,7 +537,6 @@ public class DatacenterMO extends BaseMO {
|
||||
}
|
||||
|
||||
public DatacenterConfigInfo getDatacenterConfigInfo() throws Exception {
|
||||
DatacenterConfigInfo configInfo = (DatacenterConfigInfo)_context.getVimClient().getDynamicProperty(_mor, "configuration");
|
||||
return configInfo;
|
||||
return _context.getVimClient().getDynamicProperty(_mor, "configuration");
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
// under the License.
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -24,10 +25,19 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
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.lang3.StringUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import com.vmware.vim25.AboutInfo;
|
||||
import com.vmware.vim25.AlreadyExistsFaultMsg;
|
||||
import com.vmware.vim25.ClusterDasConfigInfo;
|
||||
@ -57,6 +67,7 @@ import com.vmware.vim25.HostRuntimeInfo;
|
||||
import com.vmware.vim25.HostSystemConnectionState;
|
||||
import com.vmware.vim25.HostVirtualNic;
|
||||
import com.vmware.vim25.HostVirtualSwitch;
|
||||
import com.vmware.vim25.InvalidPropertyFaultMsg;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.NasDatastoreInfo;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
@ -64,16 +75,15 @@ import com.vmware.vim25.ObjectSpec;
|
||||
import com.vmware.vim25.OptionValue;
|
||||
import com.vmware.vim25.PropertyFilterSpec;
|
||||
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.VirtualMachineConfigSpec;
|
||||
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 {
|
||||
Map<String, VirtualMachineMO> _vmCache = new HashMap<String, VirtualMachineMO>();
|
||||
Map<String, VirtualMachineMO> _vmCache = new HashMap<>();
|
||||
|
||||
//Map<String, String> _vmInternalNameMapCache = new HashMap<String, String>();
|
||||
|
||||
@ -87,12 +97,11 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
|
||||
public HostHardwareSummary getHostHardwareSummary() throws Exception {
|
||||
HostConnectInfo hostInfo = _context.getService().queryHostConnectionInfo(_mor);
|
||||
HostHardwareSummary hardwareSummary = hostInfo.getHost().getHardware();
|
||||
return hardwareSummary;
|
||||
return hostInfo.getHost().getHardware();
|
||||
}
|
||||
|
||||
public HostConfigManager getHostConfigManager() throws Exception {
|
||||
return (HostConfigManager)_context.getVimClient().getDynamicProperty(_mor, "configManager");
|
||||
return _context.getVimClient().getDynamicProperty(_mor, "configManager");
|
||||
}
|
||||
|
||||
public List<VirtualNicManagerNetConfig> getHostVirtualNicManagerNetConfig() throws Exception {
|
||||
@ -104,15 +113,15 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
}
|
||||
|
||||
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 {
|
||||
return (HostHyperThreadScheduleInfo)_context.getVimClient().getDynamicProperty(_mor, "config.hyperThread");
|
||||
return _context.getVimClient().getDynamicProperty(_mor, "config.hyperThread");
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -142,7 +151,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<HostPortGroupSpec> portGroupSpecs = new ArrayList<HostPortGroupSpec>();
|
||||
List<HostPortGroupSpec> portGroupSpecs = new ArrayList<>();
|
||||
for (HostPortGroup portGroup : portGroups) {
|
||||
if (!isVMKernelPort(portGroup)) {
|
||||
portGroupSpecs.add(portGroup.getSpec());
|
||||
@ -216,20 +225,20 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {"name"});
|
||||
if (ocs != null && ocs.length > 0) {
|
||||
if (ocs != null) {
|
||||
for (ObjectContent oc : ocs) {
|
||||
List<DynamicProperty> objProps = oc.getPropSet();
|
||||
if (objProps != null) {
|
||||
@ -267,13 +276,13 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference getHyperHostOwnerResourcePool() throws Exception {
|
||||
ManagedObjectReference morComputerResource = (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "parent");
|
||||
return (ManagedObjectReference)_context.getVimClient().getDynamicProperty(morComputerResource, "resourcePool");
|
||||
ManagedObjectReference morComputerResource = _context.getVimClient().getDynamicProperty(_mor, "parent");
|
||||
return _context.getVimClient().getDynamicProperty(morComputerResource, "resourcePool");
|
||||
}
|
||||
|
||||
@Override
|
||||
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")) {
|
||||
return morParent;
|
||||
@ -285,10 +294,10 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
|
||||
public ManagedObjectReference[] getHostLocalDatastore() throws Exception {
|
||||
List<ManagedObjectReference> datastores = _context.getVimClient().getDynamicProperty(_mor, "datastore");
|
||||
List<ManagedObjectReference> l = new ArrayList<ManagedObjectReference>();
|
||||
List<ManagedObjectReference> l = new ArrayList<>();
|
||||
if (datastores != null) {
|
||||
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())
|
||||
l.add(mor);
|
||||
}
|
||||
@ -313,7 +322,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -507,7 +516,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.getPropSet().add(pSpec);
|
||||
pfSpec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
|
||||
pfSpecArr.add(pfSpec);
|
||||
|
||||
List<ObjectContent> ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
|
||||
@ -533,18 +542,22 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getHostName() throws Exception {
|
||||
return (String)_context.getVimClient().getDynamicProperty(_mor, "name");
|
||||
public String getHostName() throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
|
||||
return _context.getVimClient().getDynamicProperty(_mor, "name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<VirtualMachineMO> listVmsOnHyperHostWithHypervisorName(String vmName) throws Exception {
|
||||
public synchronized List<VirtualMachineMO> listVmsOnHyperHostWithHypervisorName(String vmName) throws VmwareClientException {
|
||||
List<VirtualMachineMO> vms = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(vmName)) {
|
||||
vms.add(findVmOnHyperHostWithHypervisorName(vmName));
|
||||
} else {
|
||||
loadVmCache();
|
||||
vms.addAll(_vmCache.values());
|
||||
try {
|
||||
if (StringUtils.isNotEmpty(vmName)) {
|
||||
vms.add(findVmOnHyperHostWithHypervisorName(vmName));
|
||||
} else {
|
||||
loadVmCache();
|
||||
vms.addAll(_vmCache.values());
|
||||
}
|
||||
} catch (InvalidPropertyFaultMsg | RuntimeFaultFaultMsg | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
|
||||
throw new VmwareClientException("problem loading vm cache.", e);
|
||||
}
|
||||
return vms;
|
||||
}
|
||||
@ -580,9 +593,8 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadVmCache() throws Exception {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("load VM cache on host");
|
||||
private void loadVmCache() throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
|
||||
logger.debug("load VM cache on host");
|
||||
|
||||
_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
|
||||
// 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 + "]"});
|
||||
if (ocs != null && ocs.length > 0) {
|
||||
if (ocs != null) {
|
||||
for (ObjectContent oc : ocs) {
|
||||
List<DynamicProperty> props = oc.getPropSet();
|
||||
if (props != null) {
|
||||
@ -608,7 +620,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
vmInternalCSName = ((CustomFieldStringValue)prop.getVal()).getValue();
|
||||
}
|
||||
}
|
||||
String vmName = null;
|
||||
String vmName;
|
||||
if (vmInternalCSName != null && isUserVMInternalCSName(vmInternalCSName)) {
|
||||
vmName = vmInternalCSName;
|
||||
} 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 + "]"});
|
||||
|
||||
HashMap<String, Integer> portInfo = new HashMap<String, Integer>();
|
||||
if (ocs != null && ocs.length > 0) {
|
||||
HashMap<String, Integer> portInfo = new HashMap<>();
|
||||
if (ocs != null) {
|
||||
for (ObjectContent oc : ocs) {
|
||||
List<DynamicProperty> objProps = oc.getPropSet();
|
||||
if (objProps != null) {
|
||||
@ -702,11 +714,16 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectContent[] getVmPropertiesOnHyperHost(String[] propertyPaths) throws Exception {
|
||||
if (logger.isTraceEnabled())
|
||||
public ObjectContent[] getVmPropertiesOnHyperHost(String[] propertyPaths) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
|
||||
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: " +
|
||||
new Gson().toJson(propertyPaths));
|
||||
|
||||
}
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("VirtualMachine");
|
||||
pSpec.getPathSet().addAll(Arrays.asList(propertyPaths));
|
||||
@ -724,14 +741,18 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.getPropSet().add(pSpec);
|
||||
pfSpec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
|
||||
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())
|
||||
logger.trace("vCenter API trace - retrieveProperties() done");
|
||||
return properties.toArray(new ObjectContent[properties.size()]);
|
||||
RetrieveResult result = _context.getService().retrievePropertiesEx(_context.getPropertyCollector(), pfSpecArr, ro);
|
||||
|
||||
logger.trace("vCenter API trace - retrieveProperties() done");
|
||||
return createReturnObjectPair(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -757,7 +778,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.getPropSet().add(pSpec);
|
||||
pfSpec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> pfSpecArr = new ArrayList<>();
|
||||
pfSpecArr.add(pfSpec);
|
||||
|
||||
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 {
|
||||
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())});
|
||||
if (ocs != null) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -781,7 +802,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
}
|
||||
|
||||
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"});
|
||||
if (ocs != null) {
|
||||
@ -792,7 +813,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
String name = (String)VmwareHelper.getPropValue(oc, "name");
|
||||
|
||||
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;
|
||||
}
|
||||
// Next, get all the NAS datastores from this array of datastores.
|
||||
if (morArray.size() > 0) {
|
||||
if (!morArray.isEmpty()) {
|
||||
int i;
|
||||
for (i = 0; i < morArray.size(); i++) {
|
||||
NasDatastoreInfo nasDS;
|
||||
@ -978,7 +999,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference findMigrationTarget(VirtualMachineMO vmMo) throws Exception {
|
||||
public ManagedObjectReference findMigrationTarget(VirtualMachineMO vmMo) {
|
||||
return _mor;
|
||||
}
|
||||
|
||||
@ -1102,7 +1123,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1316,9 +1337,8 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
return false;
|
||||
}
|
||||
|
||||
private synchronized VirtualMachineMO findVmOnHyperHostWithHypervisorName(String vmName) throws Exception {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("find VM hypervisor name: " + vmName + " on host");
|
||||
private synchronized VirtualMachineMO findVmOnHyperHostWithHypervisorName(String vmName) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
|
||||
logger.debug("find VM hypervisor name: {} on host", vmName );
|
||||
|
||||
VirtualMachineMO vmMo = getVmWithHypervisorName(_vmCache.values(), vmName);
|
||||
if (vmMo != null) {
|
||||
@ -1348,4 +1368,24 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -16,8 +16,10 @@
|
||||
// under the License.
|
||||
package com.cloud.hypervisor.vmware.util;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
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.PortInfo;
|
||||
|
||||
|
||||
import org.apache.cloudstack.utils.security.SSLUtils;
|
||||
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.PbmService;
|
||||
import com.vmware.pbm.PbmServiceInstanceContent;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import com.vmware.vim25.DynamicProperty;
|
||||
import com.vmware.vim25.InvalidCollectorVersionFaultMsg;
|
||||
import com.vmware.vim25.InvalidLocaleFaultMsg;
|
||||
import com.vmware.vim25.InvalidLoginFaultMsg;
|
||||
import com.vmware.vim25.InvalidPropertyFaultMsg;
|
||||
import com.vmware.vim25.InvalidStateFaultMsg;
|
||||
import com.vmware.vim25.LocalizedMethodFault;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.MethodFault;
|
||||
@ -93,12 +100,10 @@ public class VmwareClient {
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,7 +164,7 @@ public class VmwareClient {
|
||||
* @throws 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.setValue(SVC_INST_NAME);
|
||||
|
||||
@ -189,7 +194,7 @@ public class VmwareClient {
|
||||
if (cookies == null) {
|
||||
String msg = "Login successful, but failed to get server cookies from url :[" + url + "]";
|
||||
LOGGER.error(msg);
|
||||
throw new Exception(msg);
|
||||
throw new VmwareClientException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,14 +203,14 @@ public class VmwareClient {
|
||||
cookieValue = tokenizer.nextToken();
|
||||
String pathData = "$" + tokenizer.nextToken();
|
||||
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));
|
||||
((BindingProvider)vimPort).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, map);
|
||||
pbmConnect(url, cookieValue);
|
||||
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);
|
||||
String pbmurl = "https://" + uri.getHost() + "/pbm";
|
||||
String[] tokens = cookieValue.split("=");
|
||||
@ -215,8 +220,8 @@ public class VmwareClient {
|
||||
@Override
|
||||
public List<Handler> getHandlerChain(PortInfo portInfo) {
|
||||
VcenterSessionHandler VcSessionHandler = new VcenterSessionHandler(extractedCookie);
|
||||
List<Handler> handlerChain = new ArrayList<Handler>();
|
||||
handlerChain.add((Handler)VcSessionHandler);
|
||||
List<Handler> handlerChain = new ArrayList<>();
|
||||
handlerChain.add(VcSessionHandler);
|
||||
return handlerChain;
|
||||
}
|
||||
};
|
||||
@ -257,6 +262,7 @@ public class VmwareClient {
|
||||
try {
|
||||
return vimPort.retrieveServiceContent(svcInstRef);
|
||||
} catch (RuntimeFaultFaultMsg e) {
|
||||
// ignored
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -275,6 +281,7 @@ public class VmwareClient {
|
||||
try {
|
||||
return pbmPort.pbmRetrieveServiceContent(pbmSvcInstRef);
|
||||
} catch (com.vmware.pbm.RuntimeFaultFaultMsg e) {
|
||||
// ignored
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -323,12 +330,12 @@ public class VmwareClient {
|
||||
PropertyFilterSpec spec = new PropertyFilterSpec();
|
||||
spec.getPropSet().add(pSpec);
|
||||
spec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> specArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> specArr = new ArrayList<>();
|
||||
specArr.add(spec);
|
||||
|
||||
try {
|
||||
List<ObjectContent> ocary = vimPort.retrieveProperties(getPropCol(), specArr);
|
||||
if (ocary != null && ocary.size() > 0)
|
||||
if (ocary != null && !ocary.isEmpty())
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
@ -345,19 +352,17 @@ public class VmwareClient {
|
||||
* @param propertyName
|
||||
* property name.
|
||||
* @return property value.
|
||||
* @throws Exception
|
||||
* in case of error.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getDynamicProperty(ManagedObjectReference mor, String propertyName) throws Exception {
|
||||
List<String> props = new ArrayList<String>();
|
||||
public <T> T getDynamicProperty(ManagedObjectReference mor, String propertyName) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
List<String> props = new ArrayList<>();
|
||||
props.add(propertyName);
|
||||
List<ObjectContent> objContent = retrieveMoRefProperties(mor, props);
|
||||
|
||||
Object propertyValue = null;
|
||||
if (objContent != null && objContent.size() > 0) {
|
||||
if (objContent != null && !objContent.isEmpty()) {
|
||||
List<DynamicProperty> dynamicProperty = objContent.get(0).getPropSet();
|
||||
if (dynamicProperty != null && dynamicProperty.size() > 0) {
|
||||
if (dynamicProperty != null && !dynamicProperty.isEmpty()) {
|
||||
DynamicProperty dp = dynamicProperty.get(0);
|
||||
propertyValue = dp.getVal();
|
||||
/*
|
||||
@ -369,7 +374,7 @@ public class VmwareClient {
|
||||
*/
|
||||
Class dpCls = propertyValue.getClass();
|
||||
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());
|
||||
|
||||
Method getMorMethod = dpCls.getDeclaredMethod(methodName, null);
|
||||
@ -380,7 +385,7 @@ public class VmwareClient {
|
||||
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();
|
||||
pSpec.setAll(false);
|
||||
pSpec.setType(mObj.getType());
|
||||
@ -392,7 +397,7 @@ public class VmwareClient {
|
||||
PropertyFilterSpec spec = new PropertyFilterSpec();
|
||||
spec.getPropSet().add(pSpec);
|
||||
spec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> specArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> specArr = new ArrayList<>();
|
||||
specArr.add(spec);
|
||||
|
||||
return vimPort.retrieveProperties(getPropCol(), specArr);
|
||||
@ -410,7 +415,7 @@ public class VmwareClient {
|
||||
* @throws RuntimeFaultFaultMsg
|
||||
* @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;
|
||||
|
||||
@ -665,7 +670,7 @@ public class VmwareClient {
|
||||
visitFolders.setPath("childEntity");
|
||||
visitFolders.setSkip(Boolean.FALSE);
|
||||
visitFolders.setName("VisitFolders");
|
||||
List<SelectionSpec> sspecarrvf = new ArrayList<SelectionSpec>();
|
||||
List<SelectionSpec> sspecarrvf = new ArrayList<>();
|
||||
sspecarrvf.add(getSelectionSpec("crToRp"));
|
||||
sspecarrvf.add(getSelectionSpec("crToH"));
|
||||
sspecarrvf.add(getSelectionSpec("dcToVmf"));
|
||||
@ -679,7 +684,7 @@ public class VmwareClient {
|
||||
|
||||
visitFolders.getSelectSet().addAll(sspecarrvf);
|
||||
|
||||
List<SelectionSpec> resultspec = new ArrayList<SelectionSpec>();
|
||||
List<SelectionSpec> resultspec = new ArrayList<>();
|
||||
resultspec.add(visitFolders);
|
||||
resultspec.add(crToRp);
|
||||
resultspec.add(crToH);
|
||||
@ -705,8 +710,8 @@ public class VmwareClient {
|
||||
*
|
||||
* @return First ManagedObjectReference of the type / name pair found
|
||||
*/
|
||||
public ManagedObjectReference getDecendentMoRef(ManagedObjectReference root, String type, String name) throws Exception {
|
||||
if (name == null || name.length() == 0) {
|
||||
public ManagedObjectReference getDecendentMoRef(ManagedObjectReference root, String type, String name) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
|
||||
if (name == null || name.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -725,13 +730,13 @@ public class VmwareClient {
|
||||
PropertyFilterSpec spec = new PropertyFilterSpec();
|
||||
spec.getPropSet().add(pSpec);
|
||||
spec.getObjectSet().add(oSpec);
|
||||
List<PropertyFilterSpec> specArr = new ArrayList<PropertyFilterSpec>();
|
||||
List<PropertyFilterSpec> specArr = new ArrayList<>();
|
||||
specArr.add(spec);
|
||||
|
||||
ManagedObjectReference propCollector = getPropCol();
|
||||
List<ObjectContent> ocary = vimPort.retrieveProperties(propCollector, specArr);
|
||||
|
||||
if (ocary == null || ocary.size() == 0) {
|
||||
if (ocary == null || ocary.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -740,19 +745,16 @@ public class VmwareClient {
|
||||
ManagedObjectReference mor = oc.getObj();
|
||||
List<DynamicProperty> propary = oc.getPropSet();
|
||||
if (type == null || type.equals(mor.getType())) {
|
||||
if (propary.size() > 0) {
|
||||
if (!propary.isEmpty()) {
|
||||
String propval = (String)propary.get(0).getVal();
|
||||
if (propval != null && name.equalsIgnoreCase(propval))
|
||||
if (name.equalsIgnoreCase(propval))
|
||||
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());
|
||||
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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user