mirror of https://github.com/apache/cloudstack.git
Merge branch 'main' into disk-controller-mappings
This commit is contained in:
commit
cd77162761
|
|
@ -447,3 +447,6 @@ iscsi.session.cleanup.enabled=false
|
|||
|
||||
# Timeout (in seconds) to wait for the incremental snapshot to complete.
|
||||
# incremental.snapshot.timeout=10800
|
||||
|
||||
# If set to true, creates VMs as full clones of their templates on KVM hypervisor. Creates as linked clones otherwise.
|
||||
# create.full.clone=false
|
||||
|
|
|
|||
|
|
@ -97,7 +97,6 @@ import com.cloud.utils.nio.Link;
|
|||
import com.cloud.utils.nio.NioClient;
|
||||
import com.cloud.utils.nio.NioConnection;
|
||||
import com.cloud.utils.nio.Task;
|
||||
import com.cloud.utils.script.OutputInterpreter;
|
||||
import com.cloud.utils.script.Script;
|
||||
|
||||
/**
|
||||
|
|
@ -476,7 +475,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
|
|||
return;
|
||||
}
|
||||
|
||||
logger.info("Scheduling a recurring preferred host checker task with lb algorithm '{}' and host.lb.interval={} ms", lbAlgorithm, checkInterval);
|
||||
logger.info("Scheduling a recurring preferred host checker task with host.lb.interval={} ms", checkInterval);
|
||||
hostLbCheckExecutor = Executors.newSingleThreadScheduledExecutor((new NamedThreadFactory(name)));
|
||||
hostLbCheckExecutor.scheduleAtFixedRate(new PreferredHostCheckerTask(), checkInterval, checkInterval,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
|
@ -614,9 +613,9 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
|
|||
}
|
||||
|
||||
protected String getAgentArch() {
|
||||
final Script command = new Script("/usr/bin/arch", 500, logger);
|
||||
final OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser();
|
||||
return command.execute(parser);
|
||||
String arch = Script.runSimpleBashScript(Script.getExecutableAbsolutePath("arch"), 1000);
|
||||
logger.debug("Arch for agent: {} found: {}", _name, arch);
|
||||
return arch;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -968,9 +967,11 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
|
|||
if (CollectionUtils.isNotEmpty(cmd.getMsList())) {
|
||||
processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval(), false);
|
||||
}
|
||||
Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("MigrateAgentConnection-Job")).schedule(() -> {
|
||||
ScheduledExecutorService migrateAgentConnectionService = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("MigrateAgentConnection-Job"));
|
||||
migrateAgentConnectionService.schedule(() -> {
|
||||
migrateAgentConnection(cmd.getAvoidMsList());
|
||||
}, 3, TimeUnit.SECONDS);
|
||||
migrateAgentConnectionService.shutdown();
|
||||
} catch (Exception e) {
|
||||
String errMsg = "Migrate agent connection failed, due to " + e.getMessage();
|
||||
logger.debug(errMsg, e);
|
||||
|
|
|
|||
|
|
@ -863,6 +863,14 @@ public class AgentProperties{
|
|||
* */
|
||||
public static final Property<Integer> REVERT_SNAPSHOT_TIMEOUT = new Property<>("revert.snapshot.timeout", 10800);
|
||||
|
||||
/**
|
||||
* If set to true, creates VMs as full clones of their templates on KVM hypervisor. Creates as linked clones otherwise. <br>
|
||||
* Data type: Boolean. <br>
|
||||
* Default value: <code>false</code>
|
||||
*/
|
||||
public static final Property<Boolean> CREATE_FULL_CLONE = new Property<>("create.full.clone", false);
|
||||
|
||||
|
||||
public static class Property <T>{
|
||||
private String name;
|
||||
private T defaultValue;
|
||||
|
|
|
|||
|
|
@ -34,13 +34,17 @@ public interface Capacity extends InternalIdentity, Identity {
|
|||
public static final short CAPACITY_TYPE_LOCAL_STORAGE = 9;
|
||||
public static final short CAPACITY_TYPE_VIRTUAL_NETWORK_IPV6_SUBNET = 10;
|
||||
public static final short CAPACITY_TYPE_GPU = 19;
|
||||
public static final short CAPACITY_TYPE_OBJECT_STORAGE = 20;
|
||||
public static final short CAPACITY_TYPE_BACKUP_STORAGE = 21;
|
||||
|
||||
public static final short CAPACITY_TYPE_CPU_CORE = 90;
|
||||
|
||||
public static final List<Short> STORAGE_CAPACITY_TYPES = List.of(CAPACITY_TYPE_STORAGE,
|
||||
CAPACITY_TYPE_STORAGE_ALLOCATED,
|
||||
CAPACITY_TYPE_SECONDARY_STORAGE,
|
||||
CAPACITY_TYPE_LOCAL_STORAGE);
|
||||
CAPACITY_TYPE_LOCAL_STORAGE,
|
||||
CAPACITY_TYPE_BACKUP_STORAGE,
|
||||
CAPACITY_TYPE_OBJECT_STORAGE);
|
||||
|
||||
public Long getHostOrPoolId();
|
||||
|
||||
|
|
|
|||
|
|
@ -632,11 +632,13 @@ public class EventTypes {
|
|||
public static final String EVENT_VM_BACKUP_CREATE = "BACKUP.CREATE";
|
||||
public static final String EVENT_VM_BACKUP_RESTORE = "BACKUP.RESTORE";
|
||||
public static final String EVENT_VM_BACKUP_DELETE = "BACKUP.DELETE";
|
||||
public static final String EVENT_VM_BACKUP_OFFERING_REMOVED_AND_BACKUPS_DELETED = "BACKUP.OFFERING.BACKUPS.DEL";
|
||||
public static final String EVENT_VM_BACKUP_RESTORE_VOLUME_TO_VM = "BACKUP.RESTORE.VOLUME.TO.VM";
|
||||
public static final String EVENT_VM_BACKUP_SCHEDULE_CONFIGURE = "BACKUP.SCHEDULE.CONFIGURE";
|
||||
public static final String EVENT_VM_BACKUP_SCHEDULE_DELETE = "BACKUP.SCHEDULE.DELETE";
|
||||
public static final String EVENT_VM_BACKUP_USAGE_METRIC = "BACKUP.USAGE.METRIC";
|
||||
public static final String EVENT_VM_BACKUP_EDIT = "BACKUP.OFFERING.EDIT";
|
||||
public static final String EVENT_VM_CREATE_FROM_BACKUP = "VM.CREATE.FROM.BACKUP";
|
||||
|
||||
// external network device events
|
||||
public static final String EVENT_EXTERNAL_NVP_CONTROLLER_ADD = "PHYSICAL.NVPCONTROLLER.ADD";
|
||||
|
|
|
|||
|
|
@ -272,5 +272,7 @@ public interface NetworkService {
|
|||
|
||||
boolean handleCksIsoOnNetworkVirtualRouter(Long virtualRouterId, boolean mount) throws ResourceUnavailableException;
|
||||
|
||||
IpAddresses getIpAddressesFromIps(String ipAddress, String ip6Address, String macAddress);
|
||||
|
||||
String getNicVlanValueForExternalVm(NicTO nic);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,13 @@ public class DiskOfferingInfo {
|
|||
_diskOffering = diskOffering;
|
||||
}
|
||||
|
||||
public DiskOfferingInfo(DiskOffering diskOffering, Long size, Long minIops, Long maxIops) {
|
||||
_diskOffering = diskOffering;
|
||||
_size = size;
|
||||
_minIops = minIops;
|
||||
_maxIops = maxIops;
|
||||
}
|
||||
|
||||
public void setDiskOffering(DiskOffering diskOffering) {
|
||||
_diskOffering = diskOffering;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ public interface StorageService {
|
|||
|
||||
void removeSecondaryStorageHeuristic(RemoveSecondaryStorageSelectorCmd cmd);
|
||||
|
||||
ObjectStore discoverObjectStore(String name, String url, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
|
||||
ObjectStore discoverObjectStore(String name, String url, Long size, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
|
||||
|
||||
boolean deleteObjectStore(DeleteObjectStoragePoolCmd cmd);
|
||||
|
||||
|
|
|
|||
|
|
@ -113,10 +113,10 @@ public interface VolumeApiService {
|
|||
|
||||
Volume detachVolumeFromVM(DetachVolumeCmd cmd);
|
||||
|
||||
Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup, Map<String, String> tags, List<Long> zoneIds)
|
||||
Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup, Map<String, String> tags, List<Long> zoneIds, List<Long> poolIds, Boolean useStorageReplication)
|
||||
throws ResourceAllocationException;
|
||||
|
||||
Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, List<Long> zoneIds) throws ResourceAllocationException;
|
||||
Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, List<Long> zoneIds, List<Long> storagePoolIds, Boolean useStorageReplication) throws ResourceAllocationException;
|
||||
|
||||
Volume updateVolume(long volumeId, String path, String state, Long storageId,
|
||||
Boolean displayVolume, Boolean deleteProtection,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
|
|||
import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.CreateVMFromBackupCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.RebootVMCmd;
|
||||
|
|
@ -220,7 +221,7 @@ public interface UserVmService {
|
|||
* available.
|
||||
*/
|
||||
UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> securityGroupIdList,
|
||||
Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
|
||||
Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, List<VmDiskInfo> dataDiskInfoList, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
|
||||
String userData, Long userDataId, String userDataDetails, List<String> sshKeyPairs, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIp, Boolean displayVm, String keyboard,
|
||||
List<Long> affinityGroupIdList, Map<String, String> customParameter, String customId, Map<String, Map<Integer, String>> dhcpOptionMap,
|
||||
Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap,
|
||||
|
|
@ -297,7 +298,7 @@ public interface UserVmService {
|
|||
* available.
|
||||
*/
|
||||
UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList,
|
||||
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
|
||||
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, List<VmDiskInfo> dataDiskInfoList, String group, HypervisorType hypervisor,
|
||||
HTTPMethod httpmethod, String userData, Long userDataId, String userDataDetails, List<String> sshKeyPairs, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard,
|
||||
List<Long> affinityGroupIdList, Map<String, String> customParameters, String customId, Map<String, Map<Integer, String>> dhcpOptionMap,
|
||||
Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap, Map<String, String> userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId, String vmType, Volume volume, Snapshot snapshot) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
|
||||
|
|
@ -369,7 +370,7 @@ public interface UserVmService {
|
|||
* available.
|
||||
*/
|
||||
UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, Account owner,
|
||||
String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData,
|
||||
String hostName, String displayName, Long diskOfferingId, Long diskSize, List<VmDiskInfo> dataDiskInfoList, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData,
|
||||
Long userDataId, String userDataDetails, List<String> sshKeyPairs, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, List<Long> affinityGroupIdList,
|
||||
Map<String, String> customParameters, String customId, Map<String, Map<Integer, String>> dhcpOptionMap, Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap,
|
||||
Map<String, String> templateOvfPropertiesMap, boolean dynamicScalingEnabled, String vmType, Long overrideDiskOfferingId, Volume volume, Snapshot snapshot)
|
||||
|
|
@ -516,4 +517,8 @@ public interface UserVmService {
|
|||
* @return true if the VM is successfully unmanaged, false if not.
|
||||
*/
|
||||
boolean unmanageUserVM(Long vmId);
|
||||
|
||||
UserVm allocateVMFromBackup(CreateVMFromBackupCmd cmd) throws InsufficientCapacityException, ResourceAllocationException, ResourceUnavailableException;
|
||||
|
||||
UserVm restoreVMFromBackup(CreateVMFromBackupCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,6 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Partition,
|
|||
s_fsm.addTransition(new Transition<State, Event>(State.Error, VirtualMachine.Event.DestroyRequested, State.Expunging, null));
|
||||
s_fsm.addTransition(new Transition<State, Event>(State.Error, VirtualMachine.Event.ExpungeOperation, State.Expunging, null));
|
||||
s_fsm.addTransition(new Transition<State, Event>(State.Stopped, Event.RestoringRequested, State.Restoring, null));
|
||||
s_fsm.addTransition(new Transition<State, Event>(State.Expunging, Event.RestoringRequested, State.Restoring, null));
|
||||
s_fsm.addTransition(new Transition<State, Event>(State.Destroyed, Event.RestoringRequested, State.Restoring, null));
|
||||
s_fsm.addTransition(new Transition<State, Event>(State.Restoring, Event.RestoringSuccess, State.Stopped, null));
|
||||
s_fsm.addTransition(new Transition<State, Event>(State.Restoring, Event.RestoringFailed, State.Stopped, null));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.cloud.vm;
|
||||
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.offering.DiskOfferingInfo;
|
||||
|
||||
public class VmDiskInfo extends DiskOfferingInfo {
|
||||
private Long _deviceId;
|
||||
|
||||
public VmDiskInfo(DiskOffering diskOffering, Long size, Long minIops, Long maxIops) {
|
||||
super(diskOffering, size, minIops, maxIops);
|
||||
}
|
||||
|
||||
public VmDiskInfo(DiskOffering diskOffering, Long size, Long minIops, Long maxIops, Long deviceId) {
|
||||
super(diskOffering, size, minIops, maxIops);
|
||||
_deviceId = deviceId;
|
||||
}
|
||||
|
||||
public Long getDeviceId() {
|
||||
return _deviceId;
|
||||
}
|
||||
}
|
||||
|
|
@ -74,6 +74,8 @@ public interface AlertService {
|
|||
public static final AlertType ALERT_TYPE_VR_PUBLIC_IFACE_MTU = new AlertType((short)32, "ALERT.VR.PUBLIC.IFACE.MTU", true);
|
||||
public static final AlertType ALERT_TYPE_VR_PRIVATE_IFACE_MTU = new AlertType((short)32, "ALERT.VR.PRIVATE.IFACE.MTU", true);
|
||||
public static final AlertType ALERT_TYPE_EXTENSION_PATH_NOT_READY = new AlertType((short)33, "ALERT.TYPE.EXTENSION.PATH.NOT.READY", true);
|
||||
public static final AlertType ALERT_TYPE_BACKUP_STORAGE = new AlertType(Capacity.CAPACITY_TYPE_BACKUP_STORAGE, "ALERT.STORAGE.BACKUP", true);
|
||||
public static final AlertType ALERT_TYPE_OBJECT_STORAGE = new AlertType(Capacity.CAPACITY_TYPE_OBJECT_STORAGE, "ALERT.STORAGE.OBJECT", true);
|
||||
|
||||
public short getType() {
|
||||
return type;
|
||||
|
|
|
|||
|
|
@ -23,12 +23,14 @@ public class ApiConstants {
|
|||
public static final String ACCOUNT_ID = "accountid";
|
||||
public static final String ACCOUNT_IDS = "accountids";
|
||||
public static final String ACCUMULATE = "accumulate";
|
||||
public static final String ACQUIRED = "acquired";
|
||||
public static final String ACTIVATION_RULE = "activationrule";
|
||||
public static final String ACTIVITY = "activity";
|
||||
public static final String ADAPTER_TYPE = "adaptertype";
|
||||
public static final String ADDRESS = "address";
|
||||
public static final String ALGORITHM = "algorithm";
|
||||
public static final String ALIAS = "alias";
|
||||
public static final String ALLOCATED = "allocated";
|
||||
public static final String ALLOCATED_DATE = "allocateddate";
|
||||
public static final String ALLOCATED_ONLY = "allocatedonly";
|
||||
public static final String ALLOCATED_TIME = "allocated";
|
||||
|
|
@ -60,6 +62,7 @@ public class ApiConstants {
|
|||
public static final String BACKUP_STORAGE_AVAILABLE = "backupstorageavailable";
|
||||
public static final String BACKUP_STORAGE_LIMIT = "backupstoragelimit";
|
||||
public static final String BACKUP_STORAGE_TOTAL = "backupstoragetotal";
|
||||
public static final String BACKUP_VM_OFFERING_REMOVED = "vmbackupofferingremoved";
|
||||
public static final String BACKUP_TOTAL = "backuptotal";
|
||||
public static final String BASE64_IMAGE = "base64image";
|
||||
public static final String BGP_PEERS = "bgppeers";
|
||||
|
|
@ -92,9 +95,11 @@ public class ApiConstants {
|
|||
public static final String CONVERT_INSTANCE_HOST_ID = "convertinstancehostid";
|
||||
public static final String CONVERT_INSTANCE_STORAGE_POOL_ID = "convertinstancepoolid";
|
||||
public static final String ENABLED_REVOCATION_CHECK = "enabledrevocationcheck";
|
||||
public static final String CLIENT_ADDRESS = "clientaddress";
|
||||
public static final String COMBINED_CAPACITY_ORDERING = "COMBINED";
|
||||
public static final String CONTROLLER = "controller";
|
||||
public static final String CONTROLLER_UNIT = "controllerunit";
|
||||
public static final String CONSOLE_ENDPOINT_CREATOR_ADDRESS = "consoleendpointcreatoraddress";
|
||||
public static final String COPY_IMAGE_TAGS = "copyimagetags";
|
||||
public static final String CPU_OVERCOMMIT_RATIO = "cpuOvercommitRatio";
|
||||
public static final String CSR = "csr";
|
||||
|
|
@ -155,6 +160,7 @@ public class ApiConstants {
|
|||
public static final String MAX_IOPS = "maxiops";
|
||||
public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve";
|
||||
public static final String DATACENTER_NAME = "datacentername";
|
||||
public static final String DATADISKS_DETAILS = "datadisksdetails";
|
||||
public static final String DATADISK_OFFERING_LIST = "datadiskofferinglist";
|
||||
public static final String DEFAULT_VALUE = "defaultvalue";
|
||||
public static final String DELETE_PROTECTION = "deleteprotection";
|
||||
|
|
@ -163,6 +169,7 @@ public class ApiConstants {
|
|||
public static final String DESTINATION_ZONE_ID = "destzoneid";
|
||||
public static final String DETAILS = "details";
|
||||
public static final String DEVICE_ID = "deviceid";
|
||||
public static final String DEVICE_IDS = "deviceids";
|
||||
public static final String DEVICE_NAME = "devicename";
|
||||
public static final String DIRECT_DOWNLOAD = "directdownload";
|
||||
public static final String DISK = "disk";
|
||||
|
|
@ -305,6 +312,7 @@ public class ApiConstants {
|
|||
public static final String IP_ADDRESS = "ipaddress";
|
||||
public static final String IP_ADDRESSES = "ipaddresses";
|
||||
public static final String IP6_ADDRESS = "ip6address";
|
||||
public static final String IP6_ADDRESSES = "ip6addresses";
|
||||
public static final String IP_ADDRESS_ID = "ipaddressid";
|
||||
public static final String IS_2FA_ENABLED = "is2faenabled";
|
||||
public static final String IS_2FA_VERIFIED = "is2faverified";
|
||||
|
|
@ -356,6 +364,7 @@ public class ApiConstants {
|
|||
public static final String LBID = "lbruleid";
|
||||
public static final String LB_PROVIDER = "lbprovider";
|
||||
public static final String MAC_ADDRESS = "macaddress";
|
||||
public static final String MAC_ADDRESSES = "macaddresses";
|
||||
public static final String MANUAL_UPGRADE = "manualupgrade";
|
||||
public static final String MAX = "max";
|
||||
public static final String MAX_SNAPS = "maxsnaps";
|
||||
|
|
@ -383,6 +392,7 @@ public class ApiConstants {
|
|||
public static final String NETMASK = "netmask";
|
||||
public static final String NEW_NAME = "newname";
|
||||
public static final String NIC = "nic";
|
||||
public static final String NICS = "nics";
|
||||
public static final String NIC_NETWORK_LIST = "nicnetworklist";
|
||||
public static final String NIC_IP_ADDRESS_LIST = "nicipaddresslist";
|
||||
public static final String NIC_MULTIQUEUE_NUMBER = "nicmultiqueuenumber";
|
||||
|
|
@ -459,6 +469,7 @@ public class ApiConstants {
|
|||
public static final String POWER_STATE = "powerstate";
|
||||
public static final String PRECEDENCE = "precedence";
|
||||
public static final String PREPARE_VM = "preparevm";
|
||||
public static final String PRESERVE_IP = "preserveip";
|
||||
public static final String PRIVATE_INTERFACE = "privateinterface";
|
||||
public static final String PRIVATE_IP = "privateip";
|
||||
public static final String PRIVATE_PORT = "privateport";
|
||||
|
|
@ -494,6 +505,7 @@ public class ApiConstants {
|
|||
public static final String REGISTERED = "registered";
|
||||
public static final String QUALIFIERS = "qualifiers";
|
||||
public static final String QUERY_FILTER = "queryfilter";
|
||||
public static final String QUIESCE_VM = "quiescevm";
|
||||
public static final String SCHEDULE = "schedule";
|
||||
public static final String SCHEDULE_ID = "scheduleid";
|
||||
public static final String SCOPE = "scope";
|
||||
|
|
@ -509,6 +521,7 @@ public class ApiConstants {
|
|||
public static final String SERIAL = "serial";
|
||||
public static final String SERVICE_IP = "serviceip";
|
||||
public static final String SERVICE_OFFERING_ID = "serviceofferingid";
|
||||
public static final String SERVICE_OFFERING_NAME = "serviceofferingname";
|
||||
public static final String SESSIONKEY = "sessionkey";
|
||||
public static final String SHOW_CAPACITIES = "showcapacities";
|
||||
public static final String SHOW_REMOVED = "showremoved";
|
||||
|
|
@ -526,6 +539,9 @@ public class ApiConstants {
|
|||
public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid";
|
||||
public static final String SNAPSHOT_TYPE = "snapshottype";
|
||||
public static final String SNAPSHOT_QUIESCEVM = "quiescevm";
|
||||
|
||||
public static final String USE_STORAGE_REPLICATION = "usestoragereplication";
|
||||
|
||||
public static final String SOURCE_CIDR_LIST = "sourcecidrlist";
|
||||
public static final String SOURCE_ZONE_ID = "sourcezoneid";
|
||||
public static final String SSL_VERIFICATION = "sslverification";
|
||||
|
|
@ -576,6 +592,7 @@ public class ApiConstants {
|
|||
public static final String TRUST_STORE_PASSWORD = "truststorepass";
|
||||
public static final String URL = "url";
|
||||
public static final String USAGE_INTERFACE = "usageinterface";
|
||||
public static final String USED = "used";
|
||||
public static final String USED_SUBNETS = "usedsubnets";
|
||||
public static final String USED_IOPS = "usediops";
|
||||
public static final String USER_DATA = "userdata";
|
||||
|
|
@ -634,8 +651,10 @@ public class ApiConstants {
|
|||
public static final String IS_DEDICATED = "isdedicated";
|
||||
public static final String TAKEN = "taken";
|
||||
public static final String VM_AVAILABLE = "vmavailable";
|
||||
public static final String VM_DETAILS = "vmdetails";
|
||||
public static final String VM_LIMIT = "vmlimit";
|
||||
public static final String VM_TOTAL = "vmtotal";
|
||||
public static final String VM_SETTINGS = "vmsettings";
|
||||
public static final String VM_TYPE = "vmtype";
|
||||
public static final String VNET = "vnet";
|
||||
public static final String IS_VOLATILE = "isvolatile";
|
||||
|
|
@ -817,6 +836,7 @@ public class ApiConstants {
|
|||
public static final String LIST_ALL = "listall";
|
||||
public static final String LIST_ONLY_REMOVED = "listonlyremoved";
|
||||
public static final String LIST_SYSTEM_VMS = "listsystemvms";
|
||||
public static final String LIST_VM_DETAILS = "listvmdetails";
|
||||
public static final String IP_RANGES = "ipranges";
|
||||
public static final String IPV4_ROUTING = "ip4routing";
|
||||
public static final String IPV4_ROUTES = "ip4routes";
|
||||
|
|
@ -1129,6 +1149,7 @@ public class ApiConstants {
|
|||
public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans";
|
||||
public static final String METADATA = "metadata";
|
||||
public static final String PHYSICAL_SIZE = "physicalsize";
|
||||
public static final String CHAIN_SIZE = "chainsize";
|
||||
public static final String OVM3_POOL = "ovm3pool";
|
||||
public static final String OVM3_CLUSTER = "ovm3cluster";
|
||||
public static final String OVM3_VIP = "ovm3vip";
|
||||
|
|
@ -1141,6 +1162,7 @@ public class ApiConstants {
|
|||
|
||||
public static final String ZONE_ID_LIST = "zoneids";
|
||||
public static final String DESTINATION_ZONE_ID_LIST = "destzoneids";
|
||||
public static final String STORAGE_ID_LIST = "storageids";
|
||||
public static final String ADMIN = "admin";
|
||||
public static final String CHECKSUM_PARAMETER_PREFIX_DESCRIPTION = "The parameter containing the checksum will be considered a MD5sum if it is not prefixed\n"
|
||||
+ " and just a plain ascii/utf8 representation of a hexadecimal string. If it is required to\n"
|
||||
|
|
@ -1254,6 +1276,7 @@ public class ApiConstants {
|
|||
public static final String NETRIS_DETAIL_KEY = "forNetris";
|
||||
public static final String NETRIS_TAG = "netristag";
|
||||
public static final String NETRIS_VXLAN_ID = "netrisvxlanid";
|
||||
public static final String NETRIS_URL = "netrisurl";
|
||||
public static final String DISK_PATH = "diskpath";
|
||||
public static final String IMPORT_SOURCE = "importsource";
|
||||
public static final String TEMP_PATH = "temppath";
|
||||
|
|
@ -1307,6 +1330,10 @@ public class ApiConstants {
|
|||
"however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " +
|
||||
"added, it will be interpreted as \"23:59:59\"). If the recommended format is not used, the date will be considered in the server timezone.";
|
||||
|
||||
public static final String PARAMETER_DESCRIPTION_MAX_BACKUPS = "The maximum number of backups to keep for a VM. " +
|
||||
"If \"0\", no retention policy will be applied and, thus, no backups from the schedule will be automatically deleted. " +
|
||||
"This parameter is only supported for the Dummy, NAS and EMC Networker backup provider.";
|
||||
|
||||
public static final String VMWARE_DC = "vmwaredc";
|
||||
|
||||
public static final String CSS = "css";
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.cloudstack.api.response.ConsoleSessionResponse;
|
||||
import org.apache.cloudstack.consoleproxy.ConsoleSession;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
import org.apache.cloudstack.api.ApiConstants.HostDetails;
|
||||
|
|
@ -38,7 +40,6 @@ import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse;
|
|||
import org.apache.cloudstack.api.response.AutoScaleVmProfileResponse;
|
||||
import org.apache.cloudstack.api.response.BackupOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.BackupRepositoryResponse;
|
||||
import org.apache.cloudstack.api.response.BackupResponse;
|
||||
import org.apache.cloudstack.api.response.BackupScheduleResponse;
|
||||
import org.apache.cloudstack.api.response.BucketResponse;
|
||||
import org.apache.cloudstack.api.response.CapacityResponse;
|
||||
|
|
@ -142,7 +143,6 @@ import org.apache.cloudstack.api.response.VpcOfferingResponse;
|
|||
import org.apache.cloudstack.api.response.VpcResponse;
|
||||
import org.apache.cloudstack.api.response.VpnUsersResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
import org.apache.cloudstack.backup.Backup;
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
import org.apache.cloudstack.backup.BackupRepository;
|
||||
import org.apache.cloudstack.backup.BackupSchedule;
|
||||
|
|
@ -534,8 +534,6 @@ public interface ResponseGenerator {
|
|||
|
||||
UserDataResponse createUserDataResponse(UserData userData);
|
||||
|
||||
BackupResponse createBackupResponse(Backup backup);
|
||||
|
||||
BackupScheduleResponse createBackupScheduleResponse(BackupSchedule backup);
|
||||
|
||||
BackupOfferingResponse createBackupOfferingResponse(BackupOffering policy);
|
||||
|
|
@ -583,4 +581,6 @@ public interface ResponseGenerator {
|
|||
void updateTemplateIsoResponsesForIcons(List<TemplateResponse> responses, ResourceTag.ResourceObjectType type);
|
||||
|
||||
GuiThemeResponse createGuiThemeResponse(GuiThemeJoin guiThemeJoin);
|
||||
|
||||
ConsoleSessionResponse createConsoleSessionResponse(ConsoleSession consoleSession, ResponseView responseView);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public class ListProjectRolesCmd extends BaseListCmd {
|
|||
|
||||
@Override
|
||||
public void execute() {
|
||||
List<ProjectRole> projectRoles;
|
||||
List<ProjectRole> projectRoles = new ArrayList<>();
|
||||
if (getProjectId() != null && getProjectRoleId() != null) {
|
||||
projectRoles = Collections.singletonList(projRoleService.findProjectRole(getProjectRoleId(), getProjectId()));
|
||||
} else if (StringUtils.isNotBlank(getRoleName())) {
|
||||
|
|
|
|||
|
|
@ -132,11 +132,12 @@ public class ListCapacityCmd extends BaseListCmd {
|
|||
Collections.sort(capacityResponses, new Comparator<CapacityResponse>() {
|
||||
public int compare(CapacityResponse resp1, CapacityResponse resp2) {
|
||||
int res = resp1.getZoneName().compareTo(resp2.getZoneName());
|
||||
// Group by zone
|
||||
if (res != 0) {
|
||||
return res;
|
||||
} else {
|
||||
return resp1.getCapacityType().compareTo(resp2.getCapacityType());
|
||||
}
|
||||
// Sort by capacity type only if not already sorted by usage
|
||||
return (getSortBy() != null) ? 0 : resp1.getCapacityType().compareTo(resp2.getCapacityType());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ public class AddObjectStoragePoolCmd extends BaseCmd {
|
|||
@Parameter(name = ApiConstants.TAGS, type = CommandType.STRING, description = "the tags for the storage pool")
|
||||
private String tags;
|
||||
|
||||
@Parameter(name = ApiConstants.SIZE, type = CommandType.LONG, description = "the total size of the object store in GiB. Used for tracking capacity and sending alerts", since = "4.21")
|
||||
private Long size;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -68,6 +71,10 @@ public class AddObjectStoragePoolCmd extends BaseCmd {
|
|||
return name;
|
||||
}
|
||||
|
||||
public Long getTotalSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public Map<String, String> getDetails() {
|
||||
Map<String, String> detailsMap = null;
|
||||
if (details != null && !details.isEmpty()) {
|
||||
|
|
@ -112,7 +119,7 @@ public class AddObjectStoragePoolCmd extends BaseCmd {
|
|||
@Override
|
||||
public void execute(){
|
||||
try{
|
||||
ObjectStore result = _storageService.discoverObjectStore(getName(), getUrl(), getProviderName(), getDetails());
|
||||
ObjectStore result = _storageService.discoverObjectStore(getName(), getUrl(), getTotalSize(), getProviderName(), getDetails());
|
||||
ObjectStoreResponse storeResponse = null;
|
||||
if (result != null) {
|
||||
storeResponse = _responseGenerator.createObjectStoreResponse(result);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ public class UpdateObjectStoragePoolCmd extends BaseCmd {
|
|||
@Parameter(name = ApiConstants.URL, type = CommandType.STRING, description = "the url for the object store")
|
||||
private String url;
|
||||
|
||||
@Parameter(name = ApiConstants.SIZE, type = CommandType.LONG, description = "the total size of the object store in GiB. Used for tracking capacity and sending alerts. Set to 0 to stop tracking.", since = "4.21")
|
||||
private Long size;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
|
|
@ -61,6 +63,10 @@ public class UpdateObjectStoragePoolCmd extends BaseCmd {
|
|||
return url;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
// 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.vm;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ResponseObject;
|
||||
import org.apache.cloudstack.api.command.admin.AdminCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.CreateVMFromBackupCmd;
|
||||
import org.apache.cloudstack.api.response.ClusterResponse;
|
||||
import org.apache.cloudstack.api.response.PodResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
@APICommand(name = "createVMFromBackup",
|
||||
description = "Creates and automatically starts a VM from a backup.",
|
||||
responseObject = UserVmResponse.class,
|
||||
responseView = ResponseObject.ResponseView.Full,
|
||||
entityType = {VirtualMachine.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true,
|
||||
since = "4.21.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class CreateVMFromBackupCmdByAdmin extends CreateVMFromBackupCmd implements AdminCmd {
|
||||
|
||||
@Parameter(name = ApiConstants.POD_ID, type = CommandType.UUID, entityType = PodResponse.class, description = "destination Pod ID to deploy the VM to - parameter available for root admin only", since = "4.21")
|
||||
private Long podId;
|
||||
|
||||
@Parameter(name = ApiConstants.CLUSTER_ID, type = CommandType.UUID, entityType = ClusterResponse.class, description = "destination Cluster ID to deploy the VM to - parameter available for root admin only", since = "4.21")
|
||||
private Long clusterId;
|
||||
|
||||
public Long getPodId() {
|
||||
return podId;
|
||||
}
|
||||
|
||||
public Long getClusterId() {
|
||||
return clusterId;
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.backup;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.storage.Snapshot;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
|
|
@ -28,7 +27,6 @@ import org.apache.cloudstack.api.ApiErrorCode;
|
|||
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.BackupScheduleResponse;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.backup.BackupManager;
|
||||
|
|
@ -62,12 +60,26 @@ public class CreateBackupCmd extends BaseAsyncCreateCmd {
|
|||
description = "ID of the VM")
|
||||
private Long vmId;
|
||||
|
||||
@Parameter(name = ApiConstants.SCHEDULE_ID,
|
||||
type = CommandType.LONG,
|
||||
entityType = BackupScheduleResponse.class,
|
||||
description = "backup schedule ID of the VM, if this is null, it indicates that it is a manual backup.",
|
||||
@Parameter(name = ApiConstants.NAME,
|
||||
type = CommandType.STRING,
|
||||
description = "the name of the backup",
|
||||
since = "4.21.0")
|
||||
private Long scheduleId;
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.DESCRIPTION,
|
||||
type = CommandType.STRING,
|
||||
description = "the description for the backup",
|
||||
since = "4.21.0")
|
||||
private String description;
|
||||
|
||||
@Parameter(name = ApiConstants.QUIESCE_VM,
|
||||
type = CommandType.BOOLEAN,
|
||||
required = false,
|
||||
description = "Quiesce the instance before checkpointing the disks for backup. Applicable only to NAS backup provider. " +
|
||||
"The filesystem is frozen before the backup starts and thawed immediately after. " +
|
||||
"Requires the instance to have the QEMU Guest Agent installed and running.",
|
||||
since = "4.21.0")
|
||||
private Boolean quiesceVM;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
|
|
@ -77,12 +89,16 @@ public class CreateBackupCmd extends BaseAsyncCreateCmd {
|
|||
return vmId;
|
||||
}
|
||||
|
||||
public Long getScheduleId() {
|
||||
if (scheduleId != null) {
|
||||
return scheduleId;
|
||||
} else {
|
||||
return Snapshot.MANUAL_POLICY_ID;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Boolean getQuiesceVM() {
|
||||
return quiesceVM;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -92,7 +108,7 @@ public class CreateBackupCmd extends BaseAsyncCreateCmd {
|
|||
@Override
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
|
||||
try {
|
||||
boolean result = backupManager.createBackup(getVmId(), getScheduleId());
|
||||
boolean result = backupManager.createBackup(this, getJob());
|
||||
if (result) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
response.setResponseName(getCommandName());
|
||||
|
|
|
|||
|
|
@ -75,12 +75,19 @@ public class CreateBackupScheduleCmd extends BaseCmd {
|
|||
description = "Specifies a timezone for this command. For more information on the timezone parameter, see TimeZone Format.")
|
||||
private String timezone;
|
||||
|
||||
@Parameter(name = ApiConstants.MAX_BACKUPS,
|
||||
type = CommandType.INTEGER,
|
||||
description = "maximum number of backups to retain",
|
||||
since = "4.21.0")
|
||||
@Parameter(name = ApiConstants.MAX_BACKUPS, type = CommandType.INTEGER,
|
||||
since = "4.21.0", description = ApiConstants.PARAMETER_DESCRIPTION_MAX_BACKUPS)
|
||||
private Integer maxBackups;
|
||||
|
||||
@Parameter(name = ApiConstants.QUIESCE_VM,
|
||||
type = CommandType.BOOLEAN,
|
||||
required = false,
|
||||
description = "Quiesce the instance before checkpointing the disks for backup. Applicable only to NAS backup provider. " +
|
||||
"The filesystem is frozen before the backup starts and thawed immediately after. " +
|
||||
"Requires the instance to have the QEMU Guest Agent installed and running.",
|
||||
since = "4.21.0")
|
||||
private Boolean quiesceVM;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -105,6 +112,10 @@ public class CreateBackupScheduleCmd extends BaseCmd {
|
|||
return maxBackups;
|
||||
}
|
||||
|
||||
public Boolean getQuiesceVM() {
|
||||
return quiesceVM;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import org.apache.cloudstack.api.ApiErrorCode;
|
|||
import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.BackupOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.BackupResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
|
|
@ -75,6 +76,25 @@ public class ListBackupsCmd extends BaseListProjectAndAccountResourcesCmd {
|
|||
description = "list backups by zone id")
|
||||
private Long zoneId;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME,
|
||||
type = CommandType.STRING,
|
||||
since = "4.21.0",
|
||||
description = "list backups by name")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.BACKUP_OFFERING_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = BackupOfferingResponse.class,
|
||||
since = "4.21.0",
|
||||
description = "list backups by backup offering")
|
||||
private Long backupOfferingId;
|
||||
|
||||
@Parameter(name = ApiConstants.LIST_VM_DETAILS,
|
||||
type = CommandType.BOOLEAN,
|
||||
since = "4.21.0",
|
||||
description = "list backups with VM details")
|
||||
private Boolean listVmDetails;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -87,10 +107,22 @@ public class ListBackupsCmd extends BaseListProjectAndAccountResourcesCmd {
|
|||
return vmId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Long getBackupOfferingId() {
|
||||
return backupOfferingId;
|
||||
}
|
||||
|
||||
public Long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public Boolean getListVmDetails() {
|
||||
return listVmDetails;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -101,7 +133,7 @@ public class ListBackupsCmd extends BaseListProjectAndAccountResourcesCmd {
|
|||
if (backup == null) {
|
||||
continue;
|
||||
}
|
||||
BackupResponse backupResponse = _responseGenerator.createBackupResponse(backup);
|
||||
BackupResponse backupResponse = backupManager.createBackupResponse(backup, this.getListVmDetails());
|
||||
responses.add(backupResponse);
|
||||
}
|
||||
final ListResponse<BackupResponse> response = new ListResponse<>();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,182 @@
|
|||
// 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 org.apache.cloudstack.context.CallContext;
|
||||
package org.apache.cloudstack.api.command.user.consoleproxy;
|
||||
|
||||
import org.apache.cloudstack.consoleproxy.ConsoleSession;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountService;
|
||||
import com.cloud.user.UserAccount;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.ConsoleSessionResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.HostResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.UserResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.consoleproxy.ConsoleAccessManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Date;
|
||||
|
||||
@APICommand(name = "listConsoleSessions", description = "Lists console sessions.", responseObject = ConsoleSessionResponse.class,
|
||||
entityType = {ConsoleSession.class}, since = "4.21.0",
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
authorized = {RoleType.Admin, RoleType.DomainAdmin, RoleType.ResourceAdmin, RoleType.User})
|
||||
public class ListConsoleSessionsCmd extends BaseListCmd {
|
||||
@Inject
|
||||
private AccountService accountService;
|
||||
|
||||
@Inject
|
||||
private ConsoleAccessManager consoleAccessManager;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ConsoleSessionResponse.class, description = "The ID of the console session.")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "The domain ID of the account that created the console endpoint.")
|
||||
private Long domainId;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "The ID of the account that created the console endpoint.")
|
||||
private Long accountId;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.USER_ID, type = CommandType.UUID, entityType = UserResponse.class, description = "The ID of the user that created the console endpoint.")
|
||||
private Long userId;
|
||||
|
||||
@Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, authorized = {RoleType.Admin}, description = "Lists console sessions from the specified host.")
|
||||
private Long hostId;
|
||||
|
||||
@Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, description = "Lists console sessions generated from this date onwards. " +
|
||||
ApiConstants.PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS)
|
||||
private Date startDate;
|
||||
|
||||
@Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "Lists console sessions generated up until this date. " +
|
||||
ApiConstants.PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS)
|
||||
private Date endDate;
|
||||
|
||||
@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, description = "The ID of the virtual machine.")
|
||||
private Long vmId;
|
||||
|
||||
@Parameter(name = ApiConstants.CONSOLE_ENDPOINT_CREATOR_ADDRESS, type = CommandType.STRING, description = "IP address of the creator of the console endpoint.")
|
||||
private String consoleEndpointCreatorAddress;
|
||||
|
||||
@Parameter(name = ApiConstants.CLIENT_ADDRESS, type = CommandType.STRING, description = "IP address of the client that accessed the console session.")
|
||||
private String clientAddress;
|
||||
|
||||
@Parameter(name = ApiConstants.ACTIVE_ONLY, type = CommandType.BOOLEAN,
|
||||
description = "Lists only active console sessions, defaults to true. Active sessions are the ones that have been acquired and have not been removed.")
|
||||
private boolean activeOnly = true;
|
||||
|
||||
@Parameter(name = ApiConstants.ACQUIRED, type = CommandType.BOOLEAN,
|
||||
description = "Lists acquired console sessions, defaults to false. Acquired console sessions are the ones that have been accessed. " +
|
||||
"The 'activeonly' parameter has precedence over the 'acquired' parameter, i.e., when the 'activeonly' parameter is 'true', the 'acquired' parameter value will be ignored.")
|
||||
private boolean acquired = false;
|
||||
|
||||
@Parameter(name = ApiConstants.IS_RECURSIVE, type = CommandType.BOOLEAN,
|
||||
description = "Lists console sessions recursively per domain. If an account ID is informed, only the account's console sessions will be listed. Defaults to false.")
|
||||
private boolean recursive = false;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public Long getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public Long getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
||||
public String getConsoleEndpointCreatorAddress() {
|
||||
return consoleEndpointCreatorAddress;
|
||||
}
|
||||
|
||||
public String getClientAddress() {
|
||||
return clientAddress;
|
||||
}
|
||||
|
||||
public boolean isActiveOnly() {
|
||||
return activeOnly;
|
||||
}
|
||||
|
||||
public boolean getAcquired() {
|
||||
return acquired;
|
||||
}
|
||||
|
||||
public boolean isRecursive() {
|
||||
return recursive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ListResponse<ConsoleSessionResponse> response = consoleAccessManager.listConsoleSessions(this);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
if (getId() != null) {
|
||||
ConsoleSession consoleSession = consoleAccessManager.listConsoleSessionById(getId());
|
||||
if (consoleSession != null) {
|
||||
return consoleSession.getAccountId();
|
||||
}
|
||||
}
|
||||
|
||||
if (getAccountId() != null) {
|
||||
return getAccountId();
|
||||
}
|
||||
|
||||
if (getUserId() != null) {
|
||||
UserAccount userAccount = accountService.getUserAccountById(getUserId());
|
||||
if (userAccount != null) {
|
||||
return userAccount.getAccountId();
|
||||
}
|
||||
}
|
||||
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -73,6 +73,9 @@ public class ListEventsCmd extends BaseListProjectAndAccountResourcesCmd {
|
|||
@Parameter(name = ApiConstants.ARCHIVED, type = CommandType.BOOLEAN, description = "true to list archived events otherwise false", since="4.19.0")
|
||||
private Boolean archived;
|
||||
|
||||
@Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "The state of the events", since="4.21.0")
|
||||
private String state;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -121,6 +124,10 @@ public class ListEventsCmd extends BaseListProjectAndAccountResourcesCmd {
|
|||
return archived != null && archived;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public class ListIsosCmd extends BaseListTaggedResourcesCmd implements UserCmd {
|
|||
@Parameter(name = ApiConstants.IS_PUBLIC, type = CommandType.BOOLEAN, description = "true if the ISO is publicly available to all users, false otherwise.")
|
||||
private Boolean publicIso;
|
||||
|
||||
@Parameter(name = ApiConstants.IS_READY, type = CommandType.BOOLEAN, description = "true if this ISO is ready to be deployed")
|
||||
@Parameter(name = ApiConstants.IS_READY, type = CommandType.BOOLEAN, description = "list ISOs that are ready to be deployed")
|
||||
private Boolean ready;
|
||||
|
||||
@Parameter(name = ApiConstants.ISO_FILTER,
|
||||
|
|
|
|||
|
|
@ -17,9 +17,13 @@
|
|||
|
||||
package org.apache.cloudstack.api.command.user.snapshot;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.user.Account;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
|
|
@ -31,26 +35,24 @@ import org.apache.cloudstack.api.ResponseObject;
|
|||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.user.UserCmd;
|
||||
import org.apache.cloudstack.api.response.SnapshotResponse;
|
||||
import org.apache.cloudstack.api.response.StoragePoolResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.user.Account;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@APICommand(name = "copySnapshot", description = "Copies a snapshot from one zone to another.",
|
||||
responseObject = SnapshotResponse.class, responseView = ResponseObject.ResponseView.Restricted,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class CopySnapshotCmd extends BaseAsyncCmd implements UserCmd {
|
||||
public static final Logger logger = LogManager.getLogger(CopySnapshotCmd.class.getName());
|
||||
private Snapshot snapshot;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
|
|
@ -84,6 +86,20 @@ public class CopySnapshotCmd extends BaseAsyncCmd implements UserCmd {
|
|||
"Do not specify destzoneid and destzoneids together, however one of them is required.")
|
||||
protected List<Long> destZoneIds;
|
||||
|
||||
@Parameter(name = ApiConstants.STORAGE_ID_LIST,
|
||||
type=CommandType.LIST,
|
||||
collectionType = CommandType.UUID,
|
||||
entityType = StoragePoolResponse.class,
|
||||
required = false,
|
||||
authorized = RoleType.Admin,
|
||||
since = "4.21.0",
|
||||
description = "A comma-separated list of IDs of the storage pools in other zones in which the snapshot will be made available. " +
|
||||
"The snapshot will always be made available in the zone in which the volume is present. Currently supported for StorPool only")
|
||||
protected List<Long> storagePoolIds;
|
||||
|
||||
@Parameter (name = ApiConstants.USE_STORAGE_REPLICATION, type=CommandType.BOOLEAN, required = false, since = "4.21.0", description = "This parameter enables the option the snapshot to be copied to supported primary storage")
|
||||
protected Boolean useStorageReplication;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -106,7 +122,15 @@ public class CopySnapshotCmd extends BaseAsyncCmd implements UserCmd {
|
|||
destIds.add(destZoneId);
|
||||
return destIds;
|
||||
}
|
||||
return null;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<Long> getStoragePoolIds() {
|
||||
return storagePoolIds;
|
||||
}
|
||||
|
||||
public Boolean useStorageReplication() {
|
||||
return BooleanUtils.toBoolean(useStorageReplication);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -152,7 +176,7 @@ public class CopySnapshotCmd extends BaseAsyncCmd implements UserCmd {
|
|||
@Override
|
||||
public void execute() throws ResourceUnavailableException {
|
||||
try {
|
||||
if (destZoneId == null && CollectionUtils.isEmpty(destZoneIds))
|
||||
if (destZoneId == null && CollectionUtils.isEmpty(destZoneIds) && useStorageReplication())
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
|
||||
"Either destzoneid or destzoneids parameters have to be specified.");
|
||||
|
||||
|
|
@ -161,7 +185,7 @@ public class CopySnapshotCmd extends BaseAsyncCmd implements UserCmd {
|
|||
"Both destzoneid and destzoneids cannot be specified at the same time.");
|
||||
|
||||
CallContext.current().setEventDetails(getEventDescription());
|
||||
Snapshot snapshot = _snapshotService.copySnapshot(this);
|
||||
snapshot = _snapshotService.copySnapshot(this);
|
||||
|
||||
if (snapshot != null) {
|
||||
SnapshotResponse response = _queryService.listSnapshot(this);
|
||||
|
|
@ -177,6 +201,13 @@ public class CopySnapshotCmd extends BaseAsyncCmd implements UserCmd {
|
|||
logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Snapshot getSnapshot() {
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
public void setSnapshot(Snapshot snapshot) {
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.user.snapshot;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
|
|
@ -32,6 +34,7 @@ import org.apache.cloudstack.api.ServerApiException;
|
|||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.SnapshotPolicyResponse;
|
||||
import org.apache.cloudstack.api.response.SnapshotResponse;
|
||||
import org.apache.cloudstack.api.response.StoragePoolResponse;
|
||||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
|
|
@ -99,6 +102,19 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
|
|||
since = "4.19.0")
|
||||
protected List<Long> zoneIds;
|
||||
|
||||
@Parameter(name = ApiConstants.STORAGE_ID_LIST,
|
||||
type=CommandType.LIST,
|
||||
collectionType = CommandType.UUID,
|
||||
entityType = StoragePoolResponse.class,
|
||||
authorized = RoleType.Admin,
|
||||
description = "A comma-separated list of IDs of the storage pools in other zones in which the snapshot will be made available. " +
|
||||
"The snapshot will always be made available in the zone in which the volume is present.",
|
||||
since = "4.21.0")
|
||||
protected List<Long> storagePoolIds;
|
||||
|
||||
@Parameter (name = ApiConstants.USE_STORAGE_REPLICATION, type=CommandType.BOOLEAN, required = false, description = "This parameter enables the option the snapshot to be copied to supported primary storage")
|
||||
protected Boolean useStorageReplication;
|
||||
|
||||
private String syncObjectType = BaseAsyncCmd.snapshotHostSyncObject;
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
|
|
@ -161,6 +177,17 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
|
|||
return zoneIds;
|
||||
}
|
||||
|
||||
public List<Long> getStoragePoolIds() {
|
||||
return storagePoolIds == null ? new ArrayList<>() : storagePoolIds;
|
||||
}
|
||||
|
||||
public Boolean useStorageReplication() {
|
||||
if (useStorageReplication == null) {
|
||||
return false;
|
||||
}
|
||||
return useStorageReplication;
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// ///////////// API Implementation///////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
|
|
@ -209,7 +236,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
|
|||
|
||||
@Override
|
||||
public void create() throws ResourceAllocationException {
|
||||
Snapshot snapshot = _volumeService.allocSnapshot(getVolumeId(), getPolicyId(), getSnapshotName(), getLocationType(), getZoneIds());
|
||||
Snapshot snapshot = _volumeService.allocSnapshot(getVolumeId(), getPolicyId(), getSnapshotName(), getLocationType(), getZoneIds(), getStoragePoolIds(), useStorageReplication());
|
||||
if (snapshot != null) {
|
||||
setEntityId(snapshot.getId());
|
||||
setEntityUuid(snapshot.getUuid());
|
||||
|
|
@ -223,7 +250,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
|
|||
Snapshot snapshot;
|
||||
try {
|
||||
snapshot =
|
||||
_volumeService.takeSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()), getQuiescevm(), getLocationType(), getAsyncBackup(), getTags(), getZoneIds());
|
||||
_volumeService.takeSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()), getQuiescevm(), getLocationType(), getAsyncBackup(), getTags(), getZoneIds(), getStoragePoolIds(), useStorageReplication());
|
||||
|
||||
if (snapshot != null) {
|
||||
SnapshotResponse response = _responseGenerator.createSnapshotResponse(snapshot);
|
||||
|
|
@ -243,7 +270,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
|
|||
}
|
||||
}
|
||||
|
||||
private Snapshot.LocationType getLocationType() {
|
||||
public Snapshot.LocationType getLocationType() {
|
||||
|
||||
if (Snapshot.LocationType.values() == null || Snapshot.LocationType.values().length == 0 || locationType == null) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.user.snapshot;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.projects.Project;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.snapshot.SnapshotPolicy;
|
||||
import com.cloud.user.Account;
|
||||
import java.util.ArrayList;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
|
|
@ -30,16 +32,16 @@ import org.apache.cloudstack.api.BaseCmd;
|
|||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.SnapshotPolicyResponse;
|
||||
import org.apache.cloudstack.api.response.StoragePoolResponse;
|
||||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.projects.Project;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.snapshot.SnapshotPolicy;
|
||||
import com.cloud.user.Account;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
||||
@APICommand(name = "createSnapshotPolicy", description = "Creates a snapshot policy for the account.", responseObject = SnapshotPolicyResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
|
|
@ -83,6 +85,17 @@ public class CreateSnapshotPolicyCmd extends BaseCmd {
|
|||
"The snapshots will always be made available in the zone in which the volume is present.")
|
||||
protected List<Long> zoneIds;
|
||||
|
||||
@Parameter(name = ApiConstants.STORAGE_ID_LIST,
|
||||
type=CommandType.LIST,
|
||||
collectionType = CommandType.UUID,
|
||||
entityType = StoragePoolResponse.class,
|
||||
description = "A comma-separated list of IDs of the storage pools in other zones in which the snapshot will be made available. " +
|
||||
"The snapshot will always be made available in the zone in which the volume is present.",
|
||||
since = "4.21.0")
|
||||
protected List<Long> storagePoolIds;
|
||||
|
||||
@Parameter (name = ApiConstants.USE_STORAGE_REPLICATION, type=CommandType.BOOLEAN, required = false, since = "4.21.0", description = "This parameter enables the option the snapshot to be copied to supported primary storage")
|
||||
protected Boolean useStorageReplication;
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -119,6 +132,14 @@ public class CreateSnapshotPolicyCmd extends BaseCmd {
|
|||
return zoneIds;
|
||||
}
|
||||
|
||||
public List<Long> getStoragePoolIds() {
|
||||
return storagePoolIds == null ? new ArrayList<>() : storagePoolIds;
|
||||
}
|
||||
|
||||
public Boolean useStorageReplication() {
|
||||
return BooleanUtils.toBoolean(useStorageReplication);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User
|
|||
since = "4.21.0")
|
||||
private Long extensionId;
|
||||
|
||||
@Parameter(name = ApiConstants.IS_READY, type = CommandType.BOOLEAN, description = "list templates that are ready to be deployed", since = "4.21.0")
|
||||
private Boolean ready;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -195,6 +198,13 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User
|
|||
boolean onlyReady =
|
||||
(templateFilter == TemplateFilter.featured) || (templateFilter == TemplateFilter.selfexecutable) || (templateFilter == TemplateFilter.sharedexecutable) ||
|
||||
(templateFilter == TemplateFilter.executable && isAccountSpecific) || (templateFilter == TemplateFilter.community);
|
||||
|
||||
if (!onlyReady) {
|
||||
if (isReady() != null && isReady().booleanValue() != onlyReady) {
|
||||
onlyReady = isReady().booleanValue();
|
||||
}
|
||||
}
|
||||
|
||||
return onlyReady;
|
||||
}
|
||||
|
||||
|
|
@ -230,6 +240,10 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User
|
|||
return extensionId;
|
||||
}
|
||||
|
||||
public Boolean isReady() {
|
||||
return ready;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,848 @@
|
|||
// 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.user.vm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.ApiArgValidator;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiConstants.IoDriverPolicy;
|
||||
import org.apache.cloudstack.api.BaseAsyncCreateCustomIdCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.command.user.UserCmd;
|
||||
import org.apache.cloudstack.api.response.DiskOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.HostResponse;
|
||||
import org.apache.cloudstack.api.response.NetworkResponse;
|
||||
import org.apache.cloudstack.api.response.ProjectResponse;
|
||||
import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
||||
import org.apache.cloudstack.api.response.UserDataResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.vm.lease.VMLeaseManager;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.EnumUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.agent.api.LogLevel;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Network.IpAddresses;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.VmDetailConstants;
|
||||
import com.cloud.vm.VmDiskInfo;
|
||||
import com.cloud.utils.net.Dhcp;
|
||||
|
||||
public abstract class BaseDeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityGroupAction, UserCmd {
|
||||
|
||||
private static final String s_name = "deployvirtualmachineresponse";
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "availability zone for the virtual machine")
|
||||
private Long zoneId;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "host name for the virtual machine", validations = {ApiArgValidator.RFCComplianceDomainName})
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.DISPLAY_NAME, type = CommandType.STRING, description = "an optional user generated name for the virtual machine")
|
||||
private String displayName;
|
||||
|
||||
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, description="The password of the virtual machine. If null, a random password will be generated for the VM.",
|
||||
since="4.19.0.0")
|
||||
protected String password;
|
||||
|
||||
//Owner information
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional account for the virtual machine. Must be used with domainId.")
|
||||
private String accountName;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "an optional domainId for the virtual machine. If the account parameter is used, domainId must also be used. If account is NOT provided then virtual machine will be assigned to the caller account and domain.")
|
||||
private Long domainId;
|
||||
|
||||
//Network information
|
||||
//@ACL(accessType = AccessType.UseEntry)
|
||||
@Parameter(name = ApiConstants.NETWORK_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = NetworkResponse.class, description = "list of network ids used by virtual machine. Can't be specified with ipToNetworkList parameter")
|
||||
private List<Long> networkIds;
|
||||
|
||||
@Parameter(name = ApiConstants.BOOT_TYPE, type = CommandType.STRING, required = false, description = "Guest VM Boot option either custom[UEFI] or default boot [BIOS]. Not applicable with VMware if the template is marked as deploy-as-is, as we honour what is defined in the template.", since = "4.14.0.0")
|
||||
private String bootType;
|
||||
|
||||
@Parameter(name = ApiConstants.BOOT_MODE, type = CommandType.STRING, required = false, description = "Boot Mode [Legacy] or [Secure] Applicable when Boot Type Selected is UEFI, otherwise Legacy only for BIOS. Not applicable with VMware if the template is marked as deploy-as-is, as we honour what is defined in the template.", since = "4.14.0.0")
|
||||
private String bootMode;
|
||||
|
||||
@Parameter(name = ApiConstants.BOOT_INTO_SETUP, type = CommandType.BOOLEAN, required = false, description = "Boot into hardware setup or not (ignored if startVm = false, only valid for vmware)", since = "4.15.0.0")
|
||||
private Boolean bootIntoSetup;
|
||||
|
||||
//DataDisk information
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.DISK_OFFERING_ID, type = CommandType.UUID, entityType = DiskOfferingResponse.class, description = "the ID of the disk offering for the virtual machine. If the template is of ISO format,"
|
||||
+ " the diskOfferingId is for the root disk volume. Otherwise this parameter is used to indicate the "
|
||||
+ "offering for the data disk volume. If the templateId parameter passed is from a Template object,"
|
||||
+ " the diskOfferingId refers to a DATA Disk Volume created. If the templateId parameter passed is "
|
||||
+ "from an ISO object, the diskOfferingId refers to a ROOT Disk Volume created.")
|
||||
private Long diskOfferingId;
|
||||
|
||||
@Parameter(name = ApiConstants.SIZE, type = CommandType.LONG, description = "the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId")
|
||||
private Long size;
|
||||
|
||||
@Parameter(name = ApiConstants.ROOT_DISK_SIZE,
|
||||
type = CommandType.LONG,
|
||||
description = "Optional field to resize root disk on deploy. Value is in GB. Only applies to template-based deployments. Analogous to details[0].rootdisksize, which takes precedence over this parameter if both are provided",
|
||||
since = "4.4")
|
||||
private Long rootdisksize;
|
||||
|
||||
@Parameter(name = ApiConstants.DATADISKS_DETAILS,
|
||||
type = CommandType.MAP,
|
||||
since = "4.21.0",
|
||||
description = "Disk offering details for creating multiple data volumes. Mutually exclusive with diskOfferingId." +
|
||||
" Example: datadisksdetails[0].diskofferingid=a2a73a84-19db-4852-8930-dfddef053341&datadisksdetails[0].size=10&datadisksdetails[0].miniops=100&datadisksdetails[0].maxiops=200")
|
||||
private Map dataDisksDetails;
|
||||
|
||||
@Parameter(name = ApiConstants.GROUP, type = CommandType.STRING, description = "an optional group for the virtual machine")
|
||||
private String group;
|
||||
|
||||
@Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, description = "the hypervisor on which to deploy the virtual machine. "
|
||||
+ "The parameter is required and respected only when hypervisor info is not set on the ISO/Template passed to the call")
|
||||
private String hypervisor;
|
||||
|
||||
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.STRING,
|
||||
description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. " +
|
||||
"This binary data must be base64 encoded before adding it to the request. " +
|
||||
"Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. " +
|
||||
"Using HTTP POST (via POST body), you can send up to 1MB of data after base64 encoding. " +
|
||||
"You also need to change vm.userdata.max.length value",
|
||||
length = 1048576)
|
||||
private String userData;
|
||||
|
||||
@Parameter(name = ApiConstants.USER_DATA_ID, type = CommandType.UUID, entityType = UserDataResponse.class, description = "the ID of the Userdata", since = "4.18")
|
||||
private Long userdataId;
|
||||
|
||||
@Parameter(name = ApiConstants.USER_DATA_DETAILS, type = CommandType.MAP, description = "used to specify the parameters values for the variables in userdata.", since = "4.18")
|
||||
private Map userdataDetails;
|
||||
|
||||
@Deprecated
|
||||
@Parameter(name = ApiConstants.SSH_KEYPAIR, type = CommandType.STRING, description = "name of the ssh key pair used to login to the virtual machine")
|
||||
private String sshKeyPairName;
|
||||
|
||||
@Parameter(name = ApiConstants.SSH_KEYPAIRS, type = CommandType.LIST, collectionType = CommandType.STRING, since="4.17", description = "names of the ssh key pairs used to login to the virtual machine")
|
||||
private List<String> sshKeyPairNames;
|
||||
|
||||
@Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, description = "destination Host ID to deploy the VM to - parameter available for root admin only")
|
||||
private Long hostId;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.SECURITY_GROUP_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = SecurityGroupResponse.class, description = "comma separated list of security groups id that going to be applied to the virtual machine. "
|
||||
+ "Should be passed only when vm is created from a zone with Basic Network support." + " Mutually exclusive with securitygroupnames parameter")
|
||||
private List<Long> securityGroupIdList;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.SECURITY_GROUP_NAMES, type = CommandType.LIST, collectionType = CommandType.STRING, entityType = SecurityGroupResponse.class, description = "comma separated list of security groups names that going to be applied to the virtual machine."
|
||||
+ " Should be passed only when vm is created from a zone with Basic Network support. " + "Mutually exclusive with securitygroupids parameter")
|
||||
private List<String> securityGroupNameList;
|
||||
|
||||
@Parameter(name = ApiConstants.IP_NETWORK_LIST, type = CommandType.MAP, description = "ip to network mapping. Can't be specified with networkIds parameter."
|
||||
+ " Example: iptonetworklist[0].ip=10.10.10.11&iptonetworklist[0].ipv6=fc00:1234:5678::abcd&iptonetworklist[0].networkid=uuid&iptonetworklist[0].mac=aa:bb:cc:dd:ee::ff - requests to use ip 10.10.10.11 in network id=uuid")
|
||||
private Map ipToNetworkList;
|
||||
|
||||
@Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, description = "the ip address for default vm's network")
|
||||
private String ipAddress;
|
||||
|
||||
@Parameter(name = ApiConstants.IP6_ADDRESS, type = CommandType.STRING, description = "the ipv6 address for default vm's network")
|
||||
private String ip6Address;
|
||||
|
||||
@Parameter(name = ApiConstants.MAC_ADDRESS, type = CommandType.STRING, description = "the mac address for default vm's network")
|
||||
private String macAddress;
|
||||
|
||||
@Parameter(name = ApiConstants.KEYBOARD, type = CommandType.STRING, description = "an optional keyboard device type for the virtual machine. valid value can be one of de,de-ch,es,fi,fr,fr-be,fr-ch,is,it,jp,nl-be,no,pt,uk,us")
|
||||
private String keyboard;
|
||||
|
||||
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "Deploy vm for the project")
|
||||
private Long projectId;
|
||||
|
||||
@Parameter(name = ApiConstants.START_VM, type = CommandType.BOOLEAN, description = "true if start vm after creating; defaulted to true if not specified")
|
||||
private Boolean startVm;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.AFFINITY_GROUP_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups id that are going to be applied to the virtual machine."
|
||||
+ " Mutually exclusive with affinitygroupnames parameter")
|
||||
private List<Long> affinityGroupIdList;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.AFFINITY_GROUP_NAMES, type = CommandType.LIST, collectionType = CommandType.STRING, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups names that are going to be applied to the virtual machine."
|
||||
+ "Mutually exclusive with affinitygroupids parameter")
|
||||
private List<String> affinityGroupNameList;
|
||||
|
||||
@Parameter(name = ApiConstants.DISPLAY_VM, type = CommandType.BOOLEAN, since = "4.2", description = "an optional field, whether to the display the vm to the end user or not.", authorized = {RoleType.Admin})
|
||||
private Boolean displayVm;
|
||||
|
||||
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, since = "4.3", description = "used to specify the custom parameters. 'extraconfig' is not allowed to be passed in details")
|
||||
private Map details;
|
||||
|
||||
@Parameter(name = ApiConstants.DEPLOYMENT_PLANNER, type = CommandType.STRING, description = "Deployment planner to use for vm allocation. Available to ROOT admin only", since = "4.4", authorized = { RoleType.Admin })
|
||||
private String deploymentPlanner;
|
||||
|
||||
@Parameter(name = ApiConstants.DHCP_OPTIONS_NETWORK_LIST, type = CommandType.MAP, description = "DHCP options which are passed to the VM on start up"
|
||||
+ " Example: dhcpoptionsnetworklist[0].dhcp:114=url&dhcpoptionsetworklist[0].networkid=networkid&dhcpoptionsetworklist[0].dhcp:66=www.test.com")
|
||||
private Map dhcpOptionsNetworkList;
|
||||
|
||||
@Parameter(name = ApiConstants.DATADISK_OFFERING_LIST, type = CommandType.MAP, since = "4.11", description = "datadisk template to disk-offering mapping;" +
|
||||
" an optional parameter used to create additional data disks from datadisk templates; can't be specified with diskOfferingId parameter")
|
||||
private Map dataDiskTemplateToDiskOfferingList;
|
||||
|
||||
@Parameter(name = ApiConstants.EXTRA_CONFIG, type = CommandType.STRING, since = "4.12", description = "an optional URL encoded string that can be passed to the virtual machine upon successful deployment", length = 5120)
|
||||
private String extraConfig;
|
||||
|
||||
@Parameter(name = ApiConstants.COPY_IMAGE_TAGS, type = CommandType.BOOLEAN, since = "4.13", description = "if true the image tags (if any) will be copied to the VM, default value is false")
|
||||
private Boolean copyImageTags;
|
||||
|
||||
@Parameter(name = ApiConstants.PROPERTIES, type = CommandType.MAP, since = "4.15",
|
||||
description = "used to specify the vApp properties.")
|
||||
@LogLevel(LogLevel.Log4jLevel.Off)
|
||||
private Map vAppProperties;
|
||||
|
||||
@Parameter(name = ApiConstants.NIC_NETWORK_LIST, type = CommandType.MAP, since = "4.15",
|
||||
description = "VMware only: used to specify network mapping of a vApp VMware template registered \"as-is\"." +
|
||||
" Example nicnetworklist[0].ip=Nic-101&nicnetworklist[0].network=uuid")
|
||||
@LogLevel(LogLevel.Log4jLevel.Off)
|
||||
private Map vAppNetworks;
|
||||
|
||||
@Parameter(name = ApiConstants.DYNAMIC_SCALING_ENABLED, type = CommandType.BOOLEAN, since = "4.16",
|
||||
description = "true if virtual machine needs to be dynamically scalable")
|
||||
protected Boolean dynamicScalingEnabled;
|
||||
|
||||
@Parameter(name = ApiConstants.OVERRIDE_DISK_OFFERING_ID, type = CommandType.UUID, since = "4.17", entityType = DiskOfferingResponse.class, description = "the ID of the disk offering for the virtual machine to be used for root volume instead of the disk offering mapped in service offering." +
|
||||
"In case of virtual machine deploying from ISO, then the diskofferingid specified for root volume is ignored and uses this override disk offering id")
|
||||
private Long overrideDiskOfferingId;
|
||||
|
||||
@Parameter(name = ApiConstants.IOTHREADS_ENABLED, type = CommandType.BOOLEAN, required = false,
|
||||
description = "IOThreads are dedicated event loop threads for supported disk devices to perform block I/O requests in order to improve scalability especially on an SMP host/guest with many LUNs.")
|
||||
private Boolean iothreadsEnabled;
|
||||
|
||||
@Parameter(name = ApiConstants.IO_DRIVER_POLICY, type = CommandType.STRING, description = "Controls specific policies on IO")
|
||||
private String ioDriverPolicy;
|
||||
|
||||
@Parameter(name = ApiConstants.NIC_MULTIQUEUE_NUMBER, type = CommandType.INTEGER, since = "4.18",
|
||||
description = "The number of queues for multiqueue NICs.")
|
||||
private Integer nicMultiqueueNumber;
|
||||
|
||||
@Parameter(name = ApiConstants.NIC_PACKED_VIRTQUEUES_ENABLED, type = CommandType.BOOLEAN, since = "4.18",
|
||||
description = "Enable packed virtqueues or not.")
|
||||
private Boolean nicPackedVirtQueues;
|
||||
|
||||
@Parameter(name = ApiConstants.INSTANCE_LEASE_DURATION, type = CommandType.INTEGER, since = "4.21.0",
|
||||
description = "Number of days instance is leased for.")
|
||||
private Integer leaseDuration;
|
||||
|
||||
@Parameter(name = ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION, type = CommandType.STRING, since = "4.21.0",
|
||||
description = "Lease expiry action, valid values are STOP and DESTROY")
|
||||
private String leaseExpiryAction;
|
||||
|
||||
@Parameter(name = ApiConstants.EXTERNAL_DETAILS,
|
||||
type = CommandType.MAP,
|
||||
description = "Details in key/value pairs using format externaldetails[i].keyname=keyvalue. Example: externaldetails[0].server.type=typevalue",
|
||||
since = "4.21.0")
|
||||
protected Map externalDetails;
|
||||
|
||||
private List<VmDiskInfo> dataDiskInfoList;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
if (accountName == null) {
|
||||
return CallContext.current().getCallingAccount().getAccountName();
|
||||
}
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public Long getDiskOfferingId() {
|
||||
return diskOfferingId;
|
||||
}
|
||||
|
||||
public String getDeploymentPlanner() {
|
||||
return deploymentPlanner;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
if (domainId == null) {
|
||||
return CallContext.current().getCallingAccount().getDomainId();
|
||||
}
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public ApiConstants.BootType getBootType() {
|
||||
if (StringUtils.isNotBlank(bootType)) {
|
||||
try {
|
||||
String type = bootType.trim().toUpperCase();
|
||||
return ApiConstants.BootType.valueOf(type);
|
||||
} catch (IllegalArgumentException e) {
|
||||
String errMesg = "Invalid bootType " + bootType + "Specified for vm " + getName()
|
||||
+ " Valid values are: " + Arrays.toString(ApiConstants.BootType.values());
|
||||
logger.warn(errMesg);
|
||||
throw new InvalidParameterValueException(errMesg);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, String> getDetails() {
|
||||
Map<String, String> customparameterMap = convertDetailsToMap(details);
|
||||
|
||||
if (getBootType() != null) {
|
||||
customparameterMap.put(getBootType().toString(), getBootMode().toString());
|
||||
}
|
||||
|
||||
if (rootdisksize != null && !customparameterMap.containsKey(VmDetailConstants.ROOT_DISK_SIZE)) {
|
||||
customparameterMap.put(VmDetailConstants.ROOT_DISK_SIZE, rootdisksize.toString());
|
||||
}
|
||||
|
||||
IoDriverPolicy ioPolicy = getIoDriverPolicy();
|
||||
if (ioPolicy != null) {
|
||||
customparameterMap.put(VmDetailConstants.IO_POLICY, ioPolicy.toString());
|
||||
}
|
||||
|
||||
if (BooleanUtils.toBoolean(iothreadsEnabled)) {
|
||||
customparameterMap.put(VmDetailConstants.IOTHREADS, BooleanUtils.toStringTrueFalse(iothreadsEnabled));
|
||||
}
|
||||
|
||||
if (nicMultiqueueNumber != null) {
|
||||
customparameterMap.put(VmDetailConstants.NIC_MULTIQUEUE_NUMBER, nicMultiqueueNumber.toString());
|
||||
}
|
||||
|
||||
if (BooleanUtils.toBoolean(nicPackedVirtQueues)) {
|
||||
customparameterMap.put(VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED, BooleanUtils.toStringTrueFalse(nicPackedVirtQueues));
|
||||
}
|
||||
|
||||
if (MapUtils.isNotEmpty(externalDetails)) {
|
||||
customparameterMap.putAll(getExternalDetails());
|
||||
}
|
||||
return customparameterMap;
|
||||
}
|
||||
|
||||
public Map<String, String> getExternalDetails() {
|
||||
return convertExternalDetailsToMap(externalDetails);
|
||||
}
|
||||
|
||||
public ApiConstants.BootMode getBootMode() {
|
||||
if (StringUtils.isNotBlank(bootMode)) {
|
||||
try {
|
||||
String mode = bootMode.trim().toUpperCase();
|
||||
return ApiConstants.BootMode.valueOf(mode);
|
||||
} catch (IllegalArgumentException e) {
|
||||
String msg = String.format("Invalid %s: %s specified for VM: %s. Valid values are: %s",
|
||||
ApiConstants.BOOT_MODE, bootMode, getName(), Arrays.toString(ApiConstants.BootMode.values()));
|
||||
logger.error(msg);
|
||||
throw new InvalidParameterValueException(msg);
|
||||
}
|
||||
}
|
||||
if (ApiConstants.BootType.UEFI.equals(getBootType())) {
|
||||
String msg = String.format("%s must be specified for the VM with boot type: %s. Valid values are: %s",
|
||||
ApiConstants.BOOT_MODE, getBootType(), Arrays.toString(ApiConstants.BootMode.values()));
|
||||
logger.error(msg);
|
||||
throw new InvalidParameterValueException(msg);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, String> getVmProperties() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
if (MapUtils.isNotEmpty(vAppProperties)) {
|
||||
Collection parameterCollection = vAppProperties.values();
|
||||
Iterator iterator = parameterCollection.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
HashMap<String, String> entry = (HashMap<String, String>)iterator.next();
|
||||
map.put(entry.get("key"), entry.get("value"));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public Map<Integer, Long> getVmNetworkMap() {
|
||||
Map<Integer, Long> map = new HashMap<>();
|
||||
if (MapUtils.isNotEmpty(vAppNetworks)) {
|
||||
Collection parameterCollection = vAppNetworks.values();
|
||||
Iterator iterator = parameterCollection.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
HashMap<String, String> entry = (HashMap<String, String>) iterator.next();
|
||||
Integer nic;
|
||||
try {
|
||||
nic = Integer.valueOf(entry.get(VmDetailConstants.NIC));
|
||||
} catch (NumberFormatException nfe) {
|
||||
nic = null;
|
||||
}
|
||||
String networkUuid = entry.get(VmDetailConstants.NETWORK);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("nic, '%s', goes on net, '%s'", nic, networkUuid));
|
||||
}
|
||||
if (nic == null || StringUtils.isEmpty(networkUuid) || _entityMgr.findByUuid(Network.class, networkUuid) == null) {
|
||||
throw new InvalidParameterValueException(String.format("Network ID: %s for NIC ID: %s is invalid", networkUuid, nic));
|
||||
}
|
||||
map.put(nic, _entityMgr.findByUuid(Network.class, networkUuid).getId());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public HypervisorType getHypervisor() {
|
||||
return HypervisorType.getType(hypervisor);
|
||||
}
|
||||
|
||||
public Boolean isDisplayVm() {
|
||||
return displayVm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplay() {
|
||||
if(displayVm == null)
|
||||
return true;
|
||||
else
|
||||
return displayVm;
|
||||
}
|
||||
|
||||
public List<String> getSecurityGroupNameList() {
|
||||
return securityGroupNameList;
|
||||
}
|
||||
|
||||
public List<Long> getSecurityGroupIdList() {
|
||||
return securityGroupIdList;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public String getUserData() {
|
||||
return userData;
|
||||
}
|
||||
|
||||
public Long getUserdataId() {
|
||||
return userdataId;
|
||||
}
|
||||
|
||||
public Map<String, String> getUserdataDetails() {
|
||||
return convertDetailsToMap(userdataDetails);
|
||||
}
|
||||
|
||||
public Long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public Integer getLeaseDuration() {
|
||||
return leaseDuration;
|
||||
}
|
||||
|
||||
public VMLeaseManager.ExpiryAction getLeaseExpiryAction() {
|
||||
if (StringUtils.isBlank(leaseExpiryAction)) {
|
||||
return null;
|
||||
}
|
||||
VMLeaseManager.ExpiryAction action = EnumUtils.getEnumIgnoreCase(VMLeaseManager.ExpiryAction.class, leaseExpiryAction);
|
||||
if (action == null) {
|
||||
throw new InvalidParameterValueException("Invalid value configured for leaseexpiryaction, valid values are: " +
|
||||
com.cloud.utils.EnumUtils.listValues(VMLeaseManager.ExpiryAction.values()));
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
public List<Long> getNetworkIds() {
|
||||
if (MapUtils.isNotEmpty(vAppNetworks)) {
|
||||
if (CollectionUtils.isNotEmpty(networkIds) || ipAddress != null || getIp6Address() != null || MapUtils.isNotEmpty(ipToNetworkList)) {
|
||||
throw new InvalidParameterValueException(String.format("%s can't be specified along with %s, %s, %s", ApiConstants.NIC_NETWORK_LIST, ApiConstants.NETWORK_IDS, ApiConstants.IP_ADDRESS, ApiConstants.IP_NETWORK_LIST));
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
if (ipToNetworkList != null && !ipToNetworkList.isEmpty()) {
|
||||
if ((networkIds != null && !networkIds.isEmpty()) || ipAddress != null || getIp6Address() != null) {
|
||||
throw new InvalidParameterValueException("ipToNetworkMap can't be specified along with networkIds or ipAddress");
|
||||
} else {
|
||||
List<Long> networks = new ArrayList<Long>();
|
||||
networks.addAll(getIpToNetworkMap().keySet());
|
||||
return networks;
|
||||
}
|
||||
}
|
||||
return networkIds;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<String> getSSHKeyPairNames() {
|
||||
List<String> sshKeyPairs = new ArrayList<String>();
|
||||
if(sshKeyPairNames != null) {
|
||||
sshKeyPairs = sshKeyPairNames;
|
||||
}
|
||||
if(sshKeyPairName != null && !sshKeyPairName.isEmpty()) {
|
||||
sshKeyPairs.add(sshKeyPairName);
|
||||
}
|
||||
return sshKeyPairs;
|
||||
}
|
||||
|
||||
public List<VmDiskInfo> getDataDiskInfoList() {
|
||||
if (this.dataDiskInfoList != null) {
|
||||
return this.dataDiskInfoList;
|
||||
}
|
||||
if (dataDisksDetails == null || dataDisksDetails.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (dataDiskTemplateToDiskOfferingList != null) {
|
||||
throw new InvalidParameterValueException("datadisktemplatetodiskofferinglist parameter can't be specified along with datadisksdetails parameter");
|
||||
}
|
||||
List<VmDiskInfo> vmDiskInfoList = new ArrayList<>();
|
||||
Collection dataDisksCollection = dataDisksDetails.values();
|
||||
Iterator iter = dataDisksCollection.iterator();
|
||||
while (iter.hasNext()) {
|
||||
HashMap<String, String> dataDisk = (HashMap<String, String>)iter.next();
|
||||
String diskOfferingUuid = dataDisk.get(ApiConstants.DISK_OFFERING_ID);
|
||||
if (diskOfferingUuid == null) {
|
||||
throw new InvalidParameterValueException("diskofferingid parameter is required for datadiskdetails");
|
||||
}
|
||||
DiskOffering diskOffering = _entityMgr.findByUuid(DiskOffering.class, diskOfferingUuid);
|
||||
if (diskOffering == null) {
|
||||
throw new InvalidParameterValueException("Unable to find disk offering " + diskOfferingUuid);
|
||||
}
|
||||
if (diskOffering.isComputeOnly()) {
|
||||
throw new InvalidParameterValueException(String.format("The disk offering id %d provided is directly mapped to a service offering, please provide an individual disk offering", diskOffering.getUuid()));
|
||||
}
|
||||
|
||||
Long size = null;
|
||||
Long minIops = null;
|
||||
Long maxIops = null;
|
||||
if (dataDisk.get(ApiConstants.DEVICE_ID) == null) {
|
||||
throw new InvalidParameterValueException("deviceid parameter is required for datadiskdetails");
|
||||
}
|
||||
Long deviceId = Long.parseLong(dataDisk.get(ApiConstants.DEVICE_ID));
|
||||
if (diskOffering.isCustomized()) {
|
||||
if (dataDisk.get(ApiConstants.SIZE) == null) {
|
||||
throw new InvalidParameterValueException("Size is required for custom disk offering");
|
||||
}
|
||||
size = Long.parseLong(dataDisk.get(ApiConstants.SIZE));
|
||||
} else {
|
||||
size = diskOffering.getDiskSize() / (1024 * 1024 * 1024);
|
||||
}
|
||||
if (diskOffering.isCustomizedIops() != null && diskOffering.isCustomizedIops()) {
|
||||
if (dataDisk.get(ApiConstants.MIN_IOPS) == null) {
|
||||
throw new InvalidParameterValueException("Min IOPS is required for custom disk offering");
|
||||
}
|
||||
if (dataDisk.get(ApiConstants.MAX_IOPS) == null) {
|
||||
throw new InvalidParameterValueException("Max IOPS is required for custom disk offering");
|
||||
}
|
||||
minIops = Long.parseLong(dataDisk.get(ApiConstants.MIN_IOPS));
|
||||
maxIops = Long.parseLong(dataDisk.get(ApiConstants.MAX_IOPS));
|
||||
}
|
||||
VmDiskInfo vmDiskInfo = new VmDiskInfo(diskOffering, size, minIops, maxIops, deviceId);
|
||||
vmDiskInfoList.add(vmDiskInfo);
|
||||
}
|
||||
this.dataDiskInfoList = vmDiskInfoList;
|
||||
return dataDiskInfoList;
|
||||
}
|
||||
|
||||
public Long getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
||||
public boolean getStartVm() {
|
||||
return startVm == null ? true : startVm;
|
||||
}
|
||||
|
||||
public Map<Long, IpAddresses> getIpToNetworkMap() {
|
||||
if ((networkIds != null || ipAddress != null || getIp6Address() != null) && ipToNetworkList != null) {
|
||||
throw new InvalidParameterValueException("NetworkIds and ipAddress can't be specified along with ipToNetworkMap parameter");
|
||||
}
|
||||
LinkedHashMap<Long, IpAddresses> ipToNetworkMap = null;
|
||||
if (ipToNetworkList != null && !ipToNetworkList.isEmpty()) {
|
||||
ipToNetworkMap = new LinkedHashMap<Long, IpAddresses>();
|
||||
Collection ipsCollection = ipToNetworkList.values();
|
||||
Iterator iter = ipsCollection.iterator();
|
||||
while (iter.hasNext()) {
|
||||
HashMap<String, String> ips = (HashMap<String, String>)iter.next();
|
||||
Long networkId = getNetworkIdFomIpMap(ips);
|
||||
IpAddresses addrs = getIpAddressesFromIpMap(ips);
|
||||
ipToNetworkMap.put(networkId, addrs);
|
||||
}
|
||||
}
|
||||
|
||||
return ipToNetworkMap;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private IpAddresses getIpAddressesFromIpMap(HashMap<String, String> ips) {
|
||||
String requestedIp = ips.get("ip");
|
||||
String requestedIpv6 = ips.get("ipv6");
|
||||
String requestedMac = ips.get("mac");
|
||||
if (requestedIpv6 != null) {
|
||||
requestedIpv6 = NetUtils.standardizeIp6Address(requestedIpv6);
|
||||
}
|
||||
if (requestedMac != null) {
|
||||
if(!NetUtils.isValidMac(requestedMac)) {
|
||||
throw new InvalidParameterValueException("Mac address is not valid: " + requestedMac);
|
||||
} else if(!NetUtils.isUnicastMac(requestedMac)) {
|
||||
throw new InvalidParameterValueException("Mac address is not unicast: " + requestedMac);
|
||||
}
|
||||
requestedMac = NetUtils.standardizeMacAddress(requestedMac);
|
||||
}
|
||||
return new IpAddresses(requestedIp, requestedIpv6, requestedMac);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Long getNetworkIdFomIpMap(HashMap<String, String> ips) {
|
||||
Long networkId;
|
||||
final String networkid = ips.get("networkid");
|
||||
Network network = _networkService.getNetwork(networkid);
|
||||
if (network != null) {
|
||||
networkId = network.getId();
|
||||
} else {
|
||||
try {
|
||||
networkId = Long.parseLong(networkid);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new InvalidParameterValueException("Unable to translate and find entity with networkId: " + networkid);
|
||||
}
|
||||
}
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
public String getIp6Address() {
|
||||
if (ip6Address == null) {
|
||||
return null;
|
||||
}
|
||||
return NetUtils.standardizeIp6Address(ip6Address);
|
||||
}
|
||||
|
||||
|
||||
public String getMacAddress() {
|
||||
if (macAddress == null) {
|
||||
return null;
|
||||
}
|
||||
if(!NetUtils.isValidMac(macAddress)) {
|
||||
throw new InvalidParameterValueException("Mac address is not valid: " + macAddress);
|
||||
} else if(!NetUtils.isUnicastMac(macAddress)) {
|
||||
throw new InvalidParameterValueException("Mac address is not unicast: " + macAddress);
|
||||
}
|
||||
return NetUtils.standardizeMacAddress(macAddress);
|
||||
}
|
||||
|
||||
public List<Long> getAffinityGroupIdList() {
|
||||
if (affinityGroupNameList != null && affinityGroupIdList != null) {
|
||||
throw new InvalidParameterValueException("affinitygroupids parameter is mutually exclusive with affinitygroupnames parameter");
|
||||
}
|
||||
|
||||
// transform group names to ids here
|
||||
if (affinityGroupNameList != null) {
|
||||
List<Long> affinityGroupIds = new ArrayList<Long>();
|
||||
for (String groupName : affinityGroupNameList) {
|
||||
Long groupId = _responseGenerator.getAffinityGroupId(groupName, getEntityOwnerId());
|
||||
if (groupId == null) {
|
||||
throw new InvalidParameterValueException("Unable to find affinity group by name " + groupName);
|
||||
} else {
|
||||
affinityGroupIds.add(groupId);
|
||||
}
|
||||
}
|
||||
return affinityGroupIds;
|
||||
} else {
|
||||
return affinityGroupIdList;
|
||||
}
|
||||
}
|
||||
|
||||
public String getKeyboard() {
|
||||
// TODO Auto-generated method stub
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
public Map<String, Map<Integer, String>> getDhcpOptionsMap() {
|
||||
Map<String, Map<Integer, String>> dhcpOptionsMap = new HashMap<>();
|
||||
if (dhcpOptionsNetworkList != null && !dhcpOptionsNetworkList.isEmpty()) {
|
||||
|
||||
Collection<Map<String, String>> paramsCollection = this.dhcpOptionsNetworkList.values();
|
||||
for (Map<String, String> dhcpNetworkOptions : paramsCollection) {
|
||||
String networkId = dhcpNetworkOptions.get(ApiConstants.NETWORK_ID);
|
||||
|
||||
if (networkId == null) {
|
||||
throw new IllegalArgumentException("No networkid specified when providing extra dhcp options.");
|
||||
}
|
||||
|
||||
Map<Integer, String> dhcpOptionsForNetwork = new HashMap<>();
|
||||
dhcpOptionsMap.put(networkId, dhcpOptionsForNetwork);
|
||||
|
||||
for (String key : dhcpNetworkOptions.keySet()) {
|
||||
if (key.startsWith(ApiConstants.DHCP_PREFIX)) {
|
||||
int dhcpOptionValue = Integer.parseInt(key.replaceFirst(ApiConstants.DHCP_PREFIX, ""));
|
||||
dhcpOptionsForNetwork.put(dhcpOptionValue, dhcpNetworkOptions.get(key));
|
||||
} else if (!key.equals(ApiConstants.NETWORK_ID)) {
|
||||
Dhcp.DhcpOptionCode dhcpOptionEnum = Dhcp.DhcpOptionCode.valueOfString(key);
|
||||
dhcpOptionsForNetwork.put(dhcpOptionEnum.getCode(), dhcpNetworkOptions.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return dhcpOptionsMap;
|
||||
}
|
||||
|
||||
public Map<Long, DiskOffering> getDataDiskTemplateToDiskOfferingMap() {
|
||||
if (diskOfferingId != null && dataDiskTemplateToDiskOfferingList != null) {
|
||||
throw new InvalidParameterValueException("diskofferingid parameter can't be specified along with datadisktemplatetodiskofferinglist parameter");
|
||||
}
|
||||
if (MapUtils.isEmpty(dataDiskTemplateToDiskOfferingList)) {
|
||||
return new HashMap<Long, DiskOffering>();
|
||||
}
|
||||
|
||||
HashMap<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap = new HashMap<Long, DiskOffering>();
|
||||
for (Object objDataDiskTemplates : dataDiskTemplateToDiskOfferingList.values()) {
|
||||
HashMap<String, String> dataDiskTemplates = (HashMap<String, String>) objDataDiskTemplates;
|
||||
Long dataDiskTemplateId;
|
||||
DiskOffering dataDiskOffering = null;
|
||||
VirtualMachineTemplate dataDiskTemplate= _entityMgr.findByUuid(VirtualMachineTemplate.class, dataDiskTemplates.get("datadisktemplateid"));
|
||||
if (dataDiskTemplate == null) {
|
||||
dataDiskTemplate = _entityMgr.findById(VirtualMachineTemplate.class, dataDiskTemplates.get("datadisktemplateid"));
|
||||
if (dataDiskTemplate == null)
|
||||
throw new InvalidParameterValueException("Unable to translate and find entity with datadisktemplateid " + dataDiskTemplates.get("datadisktemplateid"));
|
||||
}
|
||||
dataDiskTemplateId = dataDiskTemplate.getId();
|
||||
dataDiskOffering = _entityMgr.findByUuid(DiskOffering.class, dataDiskTemplates.get("diskofferingid"));
|
||||
if (dataDiskOffering == null) {
|
||||
dataDiskOffering = _entityMgr.findById(DiskOffering.class, dataDiskTemplates.get("diskofferingid"));
|
||||
if (dataDiskOffering == null)
|
||||
throw new InvalidParameterValueException("Unable to translate and find entity with diskofferingId " + dataDiskTemplates.get("diskofferingid"));
|
||||
}
|
||||
dataDiskTemplateToDiskOfferingMap.put(dataDiskTemplateId, dataDiskOffering);
|
||||
}
|
||||
return dataDiskTemplateToDiskOfferingMap;
|
||||
}
|
||||
|
||||
public String getExtraConfig() {
|
||||
return extraConfig;
|
||||
}
|
||||
|
||||
public boolean getCopyImageTags() {
|
||||
return copyImageTags == null ? false : copyImageTags;
|
||||
}
|
||||
|
||||
public Boolean getBootIntoSetup() {
|
||||
return bootIntoSetup;
|
||||
}
|
||||
|
||||
public boolean isDynamicScalingEnabled() {
|
||||
return dynamicScalingEnabled == null ? true : dynamicScalingEnabled;
|
||||
}
|
||||
|
||||
public Long getOverrideDiskOfferingId() {
|
||||
return overrideDiskOfferingId;
|
||||
}
|
||||
|
||||
public IoDriverPolicy getIoDriverPolicy() {
|
||||
if (StringUtils.isNotBlank(ioDriverPolicy)) {
|
||||
try {
|
||||
String policyType = ioDriverPolicy.trim().toUpperCase();
|
||||
return IoDriverPolicy.valueOf(policyType);
|
||||
} catch (IllegalArgumentException e) {
|
||||
String errMesg = String.format("Invalid io policy %s specified for vm %s. Valid values are: %s", ioDriverPolicy, getName(), Arrays.toString(IoDriverPolicy.values()));
|
||||
logger.warn(errMesg);
|
||||
throw new InvalidParameterValueException(errMesg);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public static String getResultObjectName() {
|
||||
return "virtualmachine";
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Long accountId = _accountService.finalyzeAccountId(accountName, domainId, projectId, true);
|
||||
if (accountId == null) {
|
||||
return CallContext.current().getCallingAccount().getId();
|
||||
}
|
||||
|
||||
return accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_VM_CREATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateEventType() {
|
||||
return EventTypes.EVENT_VM_CREATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateEventDescription() {
|
||||
return "creating Vm";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
if(getStartVm()) {
|
||||
return "starting Vm. Vm Id: " + getEntityUuid();
|
||||
}
|
||||
return "deploying Vm. Vm Id: " + getEntityUuid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiCommandResourceType getApiResourceType() {
|
||||
return ApiCommandResourceType.VirtualMachine;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
// 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.user.vm;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ResponseObject;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.BackupResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.TemplateResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.InsufficientServerCapacityException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
@APICommand(name = "createVMFromBackup",
|
||||
description = "Creates and automatically starts a VM from a backup.",
|
||||
responseObject = UserVmResponse.class,
|
||||
responseView = ResponseObject.ResponseView.Restricted,
|
||||
entityType = {VirtualMachine.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true,
|
||||
since = "4.21.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
public class CreateVMFromBackupCmd extends BaseDeployVMCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.BACKUP_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = BackupResponse.class,
|
||||
required = true,
|
||||
description = "backup ID to create the VM from")
|
||||
private Long backupId;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.SERVICE_OFFERING_ID, type = CommandType.UUID, entityType = ServiceOfferingResponse.class, description = "the ID of the service offering for the virtual machine")
|
||||
private Long serviceOfferingId;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.TEMPLATE_ID, type = CommandType.UUID, entityType = TemplateResponse.class, description = "the ID of the template for the virtual machine")
|
||||
private Long templateId;
|
||||
|
||||
@Parameter(name = ApiConstants.PRESERVE_IP, type = CommandType.BOOLEAN, description = "Use the same IP/MAC addresses as stored in the backup metadata. Works only if the original Instance is deleted and the IP/MAC address is available.")
|
||||
private Boolean preserveIp;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getBackupId() {
|
||||
return backupId;
|
||||
}
|
||||
|
||||
public Long getServiceOfferingId() {
|
||||
return serviceOfferingId;
|
||||
}
|
||||
|
||||
public Long getTemplateId() {
|
||||
return templateId;
|
||||
}
|
||||
|
||||
public boolean getPreserveIp() {
|
||||
return (preserveIp != null) ? preserveIp : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
UserVm vm;
|
||||
try {
|
||||
vm = _userVmService.allocateVMFromBackup(this);
|
||||
if (vm != null) {
|
||||
setEntityId(vm.getId());
|
||||
setEntityUuid(vm.getUuid());
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to deploy vm");
|
||||
}
|
||||
} catch (InsufficientCapacityException ex) {
|
||||
logger.info(ex);
|
||||
logger.trace(ex.getMessage(), ex);
|
||||
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage());
|
||||
} catch (ResourceUnavailableException ex) {
|
||||
logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
|
||||
} catch (ConcurrentOperationException ex) {
|
||||
logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
|
||||
} catch (ResourceAllocationException ex) {
|
||||
logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute () {
|
||||
UserVm vm = null;
|
||||
try {
|
||||
vm = _userVmService.restoreVMFromBackup(this);
|
||||
} catch (ResourceUnavailableException ex) {
|
||||
logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
|
||||
} catch (ResourceAllocationException ex) {
|
||||
logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
|
||||
} catch (ConcurrentOperationException ex) {
|
||||
logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
|
||||
} catch (InsufficientCapacityException ex) {
|
||||
StringBuilder message = new StringBuilder(ex.getMessage());
|
||||
if (ex instanceof InsufficientServerCapacityException) {
|
||||
if (((InsufficientServerCapacityException)ex).isAffinityApplied()) {
|
||||
message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them");
|
||||
}
|
||||
}
|
||||
logger.info(String.format("%s: %s", message.toString(), ex.getLocalizedMessage()));
|
||||
logger.debug(message.toString(), ex);
|
||||
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, message.toString());
|
||||
}
|
||||
|
||||
if (vm != null) {
|
||||
UserVmResponse response = _responseGenerator.createUserVmResponse(getResponseView(), "virtualmachine", vm).get(0);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to deploy vm uuid:"+getEntityUuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,87 +16,40 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.user.vm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiArgValidator;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiConstants.IoDriverPolicy;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseAsyncCreateCustomIdCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ResponseObject.ResponseView;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.user.UserCmd;
|
||||
import org.apache.cloudstack.api.response.DiskOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.HostResponse;
|
||||
import org.apache.cloudstack.api.response.NetworkResponse;
|
||||
import org.apache.cloudstack.api.response.ProjectResponse;
|
||||
import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.SnapshotResponse;
|
||||
import org.apache.cloudstack.api.response.TemplateResponse;
|
||||
import org.apache.cloudstack.api.response.UserDataResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.vm.lease.VMLeaseManager;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.EnumUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.agent.api.LogLevel;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.InsufficientServerCapacityException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Network.IpAddresses;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.net.Dhcp;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VmDetailConstants;
|
||||
|
||||
@APICommand(name = "deployVirtualMachine", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class},
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
|
||||
public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityGroupAction, UserCmd {
|
||||
|
||||
private static final String s_name = "deployvirtualmachineresponse";
|
||||
public class DeployVMCmd extends BaseDeployVMCmd {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "availability zone for the virtual machine")
|
||||
private Long zoneId;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.SERVICE_OFFERING_ID, type = CommandType.UUID, entityType = ServiceOfferingResponse.class, required = true, description = "the ID of the service offering for the virtual machine")
|
||||
private Long serviceOfferingId;
|
||||
|
|
@ -105,672 +58,24 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
|
|||
@Parameter(name = ApiConstants.TEMPLATE_ID, type = CommandType.UUID, entityType = TemplateResponse.class, description = "the ID of the template for the virtual machine")
|
||||
private Long templateId;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "host name for the virtual machine", validations = {ApiArgValidator.RFCComplianceDomainName})
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.DISPLAY_NAME, type = CommandType.STRING, description = "an optional user generated name for the virtual machine")
|
||||
private String displayName;
|
||||
|
||||
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, description="The password of the virtual machine. If null, a random password will be generated for the VM.",
|
||||
since="4.19.0.0")
|
||||
protected String password;
|
||||
|
||||
//Owner information
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional account for the virtual machine. Must be used with domainId.")
|
||||
private String accountName;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "an optional domainId for the virtual machine. If the account parameter is used, domainId must also be used. If account is NOT provided then virtual machine will be assigned to the caller account and domain.")
|
||||
private Long domainId;
|
||||
|
||||
//Network information
|
||||
//@ACL(accessType = AccessType.UseEntry)
|
||||
@Parameter(name = ApiConstants.NETWORK_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = NetworkResponse.class, description = "list of network ids used by virtual machine. Can't be specified with ipToNetworkList parameter")
|
||||
private List<Long> networkIds;
|
||||
|
||||
@Parameter(name = ApiConstants.BOOT_TYPE, type = CommandType.STRING, required = false, description = "Guest VM Boot option either custom[UEFI] or default boot [BIOS]. Not applicable with VMware if the template is marked as deploy-as-is, as we honour what is defined in the template.", since = "4.14.0.0")
|
||||
private String bootType;
|
||||
|
||||
@Parameter(name = ApiConstants.BOOT_MODE, type = CommandType.STRING, required = false, description = "Boot Mode [Legacy] or [Secure] Applicable when Boot Type Selected is UEFI, otherwise Legacy only for BIOS. Not applicable with VMware if the template is marked as deploy-as-is, as we honour what is defined in the template.", since = "4.14.0.0")
|
||||
private String bootMode;
|
||||
|
||||
@Parameter(name = ApiConstants.BOOT_INTO_SETUP, type = CommandType.BOOLEAN, required = false, description = "Boot into hardware setup or not (ignored if startVm = false, only valid for vmware)", since = "4.15.0.0")
|
||||
private Boolean bootIntoSetup;
|
||||
|
||||
//DataDisk information
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.DISK_OFFERING_ID, type = CommandType.UUID, entityType = DiskOfferingResponse.class, description = "the ID of the disk offering for the virtual machine. If the template is of ISO format,"
|
||||
+ " the diskOfferingId is for the root disk volume. Otherwise this parameter is used to indicate the "
|
||||
+ "offering for the data disk volume. If the templateId parameter passed is from a Template object,"
|
||||
+ " the diskOfferingId refers to a DATA Disk Volume created. If the templateId parameter passed is "
|
||||
+ "from an ISO object, the diskOfferingId refers to a ROOT Disk Volume created.")
|
||||
private Long diskOfferingId;
|
||||
|
||||
@Parameter(name = ApiConstants.SIZE, type = CommandType.LONG, description = "the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId")
|
||||
private Long size;
|
||||
|
||||
@Parameter(name = ApiConstants.ROOT_DISK_SIZE,
|
||||
type = CommandType.LONG,
|
||||
description = "Optional field to resize root disk on deploy. Value is in GB. Only applies to template-based deployments. Analogous to details[0].rootdisksize, which takes precedence over this parameter if both are provided",
|
||||
since = "4.4")
|
||||
private Long rootdisksize;
|
||||
|
||||
@Parameter(name = ApiConstants.GROUP, type = CommandType.STRING, description = "an optional group for the virtual machine")
|
||||
private String group;
|
||||
|
||||
@Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, description = "the hypervisor on which to deploy the virtual machine. "
|
||||
+ "The parameter is required and respected only when hypervisor info is not set on the ISO/Template passed to the call")
|
||||
private String hypervisor;
|
||||
|
||||
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.STRING,
|
||||
description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. " +
|
||||
"This binary data must be base64 encoded before adding it to the request. " +
|
||||
"Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. " +
|
||||
"Using HTTP POST (via POST body), you can send up to 1MB of data after base64 encoding. " +
|
||||
"You also need to change vm.userdata.max.length value",
|
||||
length = 1048576)
|
||||
private String userData;
|
||||
|
||||
@Parameter(name = ApiConstants.USER_DATA_ID, type = CommandType.UUID, entityType = UserDataResponse.class, description = "the ID of the Userdata", since = "4.18")
|
||||
private Long userdataId;
|
||||
|
||||
@Parameter(name = ApiConstants.USER_DATA_DETAILS, type = CommandType.MAP, description = "used to specify the parameters values for the variables in userdata.", since = "4.18")
|
||||
private Map userdataDetails;
|
||||
|
||||
@Deprecated
|
||||
@Parameter(name = ApiConstants.SSH_KEYPAIR, type = CommandType.STRING, description = "name of the ssh key pair used to login to the virtual machine")
|
||||
private String sshKeyPairName;
|
||||
|
||||
@Parameter(name = ApiConstants.SSH_KEYPAIRS, type = CommandType.LIST, collectionType = CommandType.STRING, since="4.17", description = "names of the ssh key pairs used to login to the virtual machine")
|
||||
private List<String> sshKeyPairNames;
|
||||
|
||||
@Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, description = "destination Host ID to deploy the VM to - parameter available for root admin only")
|
||||
private Long hostId;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.SECURITY_GROUP_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = SecurityGroupResponse.class, description = "comma separated list of security groups id that going to be applied to the virtual machine. "
|
||||
+ "Should be passed only when vm is created from a zone with Basic Network support." + " Mutually exclusive with securitygroupnames parameter")
|
||||
private List<Long> securityGroupIdList;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.SECURITY_GROUP_NAMES, type = CommandType.LIST, collectionType = CommandType.STRING, entityType = SecurityGroupResponse.class, description = "comma separated list of security groups names that going to be applied to the virtual machine."
|
||||
+ " Should be passed only when vm is created from a zone with Basic Network support. " + "Mutually exclusive with securitygroupids parameter")
|
||||
private List<String> securityGroupNameList;
|
||||
|
||||
@Parameter(name = ApiConstants.IP_NETWORK_LIST, type = CommandType.MAP, description = "ip to network mapping. Can't be specified with networkIds parameter."
|
||||
+ " Example: iptonetworklist[0].ip=10.10.10.11&iptonetworklist[0].ipv6=fc00:1234:5678::abcd&iptonetworklist[0].networkid=uuid&iptonetworklist[0].mac=aa:bb:cc:dd:ee::ff - requests to use ip 10.10.10.11 in network id=uuid")
|
||||
private Map ipToNetworkList;
|
||||
|
||||
@Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, description = "the ip address for default vm's network")
|
||||
private String ipAddress;
|
||||
|
||||
@Parameter(name = ApiConstants.IP6_ADDRESS, type = CommandType.STRING, description = "the ipv6 address for default vm's network")
|
||||
private String ip6Address;
|
||||
|
||||
@Parameter(name = ApiConstants.MAC_ADDRESS, type = CommandType.STRING, description = "the mac address for default vm's network")
|
||||
private String macAddress;
|
||||
|
||||
@Parameter(name = ApiConstants.KEYBOARD, type = CommandType.STRING, description = "an optional keyboard device type for the virtual machine. valid value can be one of de,de-ch,es,fi,fr,fr-be,fr-ch,is,it,jp,nl-be,no,pt,uk,us")
|
||||
private String keyboard;
|
||||
|
||||
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "Deploy vm for the project")
|
||||
private Long projectId;
|
||||
|
||||
@Parameter(name = ApiConstants.START_VM, type = CommandType.BOOLEAN, description = "true if start vm after creating; defaulted to true if not specified")
|
||||
private Boolean startVm;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.AFFINITY_GROUP_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups id that are going to be applied to the virtual machine."
|
||||
+ " Mutually exclusive with affinitygroupnames parameter")
|
||||
private List<Long> affinityGroupIdList;
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.AFFINITY_GROUP_NAMES, type = CommandType.LIST, collectionType = CommandType.STRING, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups names that are going to be applied to the virtual machine."
|
||||
+ "Mutually exclusive with affinitygroupids parameter")
|
||||
private List<String> affinityGroupNameList;
|
||||
|
||||
@Parameter(name = ApiConstants.DISPLAY_VM, type = CommandType.BOOLEAN, since = "4.2", description = "an optional field, whether to the display the vm to the end user or not.", authorized = {RoleType.Admin})
|
||||
private Boolean displayVm;
|
||||
|
||||
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, since = "4.3", description = "used to specify the custom parameters. 'extraconfig' is not allowed to be passed in details")
|
||||
private Map details;
|
||||
|
||||
@Parameter(name = ApiConstants.DEPLOYMENT_PLANNER, type = CommandType.STRING, description = "Deployment planner to use for vm allocation. Available to ROOT admin only", since = "4.4", authorized = { RoleType.Admin })
|
||||
private String deploymentPlanner;
|
||||
|
||||
@Parameter(name = ApiConstants.DHCP_OPTIONS_NETWORK_LIST, type = CommandType.MAP, description = "DHCP options which are passed to the VM on start up"
|
||||
+ " Example: dhcpoptionsnetworklist[0].dhcp:114=url&dhcpoptionsetworklist[0].networkid=networkid&dhcpoptionsetworklist[0].dhcp:66=www.test.com")
|
||||
private Map dhcpOptionsNetworkList;
|
||||
|
||||
@Parameter(name = ApiConstants.DATADISK_OFFERING_LIST, type = CommandType.MAP, since = "4.11", description = "datadisk template to disk-offering mapping;" +
|
||||
" an optional parameter used to create additional data disks from datadisk templates; can't be specified with diskOfferingId parameter")
|
||||
private Map dataDiskTemplateToDiskOfferingList;
|
||||
|
||||
@Parameter(name = ApiConstants.EXTRA_CONFIG, type = CommandType.STRING, since = "4.12", description = "an optional URL encoded string that can be passed to the virtual machine upon successful deployment", length = 5120)
|
||||
private String extraConfig;
|
||||
|
||||
@Parameter(name = ApiConstants.COPY_IMAGE_TAGS, type = CommandType.BOOLEAN, since = "4.13", description = "if true the image tags (if any) will be copied to the VM, default value is false")
|
||||
private Boolean copyImageTags;
|
||||
|
||||
@Parameter(name = ApiConstants.PROPERTIES, type = CommandType.MAP, since = "4.15",
|
||||
description = "used to specify the vApp properties.")
|
||||
@LogLevel(LogLevel.Log4jLevel.Off)
|
||||
private Map vAppProperties;
|
||||
|
||||
@Parameter(name = ApiConstants.NIC_NETWORK_LIST, type = CommandType.MAP, since = "4.15",
|
||||
description = "VMware only: used to specify network mapping of a vApp VMware template registered \"as-is\"." +
|
||||
" Example nicnetworklist[0].ip=Nic-101&nicnetworklist[0].network=uuid")
|
||||
@LogLevel(LogLevel.Log4jLevel.Off)
|
||||
private Map vAppNetworks;
|
||||
|
||||
@Parameter(name = ApiConstants.DYNAMIC_SCALING_ENABLED, type = CommandType.BOOLEAN, since = "4.16",
|
||||
description = "true if virtual machine needs to be dynamically scalable")
|
||||
protected Boolean dynamicScalingEnabled;
|
||||
|
||||
@Parameter(name = ApiConstants.OVERRIDE_DISK_OFFERING_ID, type = CommandType.UUID, since = "4.17", entityType = DiskOfferingResponse.class, description = "the ID of the disk offering for the virtual machine to be used for root volume instead of the disk offering mapped in service offering." +
|
||||
"In case of virtual machine deploying from ISO, then the diskofferingid specified for root volume is ignored and uses this override disk offering id")
|
||||
private Long overrideDiskOfferingId;
|
||||
|
||||
@Parameter(name = ApiConstants.IOTHREADS_ENABLED, type = CommandType.BOOLEAN, required = false,
|
||||
description = "IOThreads are dedicated event loop threads for supported disk devices to perform block I/O requests in order to improve scalability especially on an SMP host/guest with many LUNs.")
|
||||
private Boolean iothreadsEnabled;
|
||||
|
||||
@Parameter(name = ApiConstants.IO_DRIVER_POLICY, type = CommandType.STRING, description = "Controls specific policies on IO")
|
||||
private String ioDriverPolicy;
|
||||
|
||||
@Parameter(name = ApiConstants.NIC_MULTIQUEUE_NUMBER, type = CommandType.INTEGER, since = "4.18",
|
||||
description = "The number of queues for multiqueue NICs.")
|
||||
private Integer nicMultiqueueNumber;
|
||||
|
||||
@Parameter(name = ApiConstants.NIC_PACKED_VIRTQUEUES_ENABLED, type = CommandType.BOOLEAN, since = "4.18",
|
||||
description = "Enable packed virtqueues or not.")
|
||||
private Boolean nicPackedVirtQueues;
|
||||
|
||||
@Parameter(name = ApiConstants.INSTANCE_LEASE_DURATION, type = CommandType.INTEGER, since = "4.21.0",
|
||||
description = "Number of days instance is leased for.")
|
||||
private Integer leaseDuration;
|
||||
|
||||
@Parameter(name = ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION, type = CommandType.STRING, since = "4.21.0",
|
||||
description = "Lease expiry action, valid values are STOP and DESTROY")
|
||||
private String leaseExpiryAction;
|
||||
|
||||
@Parameter(name = ApiConstants.VOLUME_ID, type = CommandType.UUID, entityType = VolumeResponse.class, since = "4.21")
|
||||
private Long volumeId;
|
||||
|
||||
@Parameter(name = ApiConstants.SNAPSHOT_ID, type = CommandType.UUID, entityType = SnapshotResponse.class, since = "4.21")
|
||||
private Long snapshotId;
|
||||
|
||||
@Parameter(name = ApiConstants.EXTERNAL_DETAILS,
|
||||
type = CommandType.MAP,
|
||||
description = "Details in key/value pairs using format externaldetails[i].keyname=keyvalue. Example: externaldetails[0].server.type=typevalue",
|
||||
since = "4.21.0")
|
||||
protected Map externalDetails;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public String getAccountName() {
|
||||
if (accountName == null) {
|
||||
return CallContext.current().getCallingAccount().getAccountName();
|
||||
}
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public Long getDiskOfferingId() {
|
||||
return diskOfferingId;
|
||||
}
|
||||
|
||||
public String getDeploymentPlanner() {
|
||||
return deploymentPlanner;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
if (domainId == null) {
|
||||
return CallContext.current().getCallingAccount().getDomainId();
|
||||
}
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public ApiConstants.BootType getBootType() {
|
||||
if (StringUtils.isNotBlank(bootType)) {
|
||||
try {
|
||||
String type = bootType.trim().toUpperCase();
|
||||
return ApiConstants.BootType.valueOf(type);
|
||||
} catch (IllegalArgumentException e) {
|
||||
String errMesg = "Invalid bootType " + bootType + "Specified for vm " + getName()
|
||||
+ " Valid values are: " + Arrays.toString(ApiConstants.BootType.values());
|
||||
logger.warn(errMesg);
|
||||
throw new InvalidParameterValueException(errMesg);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, String> getDetails() {
|
||||
Map<String, String> customparameterMap = convertDetailsToMap(details);
|
||||
|
||||
if (getBootType() != null) {
|
||||
customparameterMap.put(getBootType().toString(), getBootMode().toString());
|
||||
}
|
||||
|
||||
if (rootdisksize != null && !customparameterMap.containsKey(VmDetailConstants.ROOT_DISK_SIZE)) {
|
||||
customparameterMap.put(VmDetailConstants.ROOT_DISK_SIZE, rootdisksize.toString());
|
||||
}
|
||||
|
||||
IoDriverPolicy ioPolicy = getIoDriverPolicy();
|
||||
if (ioPolicy != null) {
|
||||
customparameterMap.put(VmDetailConstants.IO_POLICY, ioPolicy.toString());
|
||||
}
|
||||
|
||||
if (BooleanUtils.toBoolean(iothreadsEnabled)) {
|
||||
customparameterMap.put(VmDetailConstants.IOTHREADS, BooleanUtils.toStringTrueFalse(iothreadsEnabled));
|
||||
}
|
||||
|
||||
if (nicMultiqueueNumber != null) {
|
||||
customparameterMap.put(VmDetailConstants.NIC_MULTIQUEUE_NUMBER, nicMultiqueueNumber.toString());
|
||||
}
|
||||
|
||||
if (BooleanUtils.toBoolean(nicPackedVirtQueues)) {
|
||||
customparameterMap.put(VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED, BooleanUtils.toStringTrueFalse(nicPackedVirtQueues));
|
||||
}
|
||||
|
||||
if (MapUtils.isNotEmpty(externalDetails)) {
|
||||
customparameterMap.putAll(getExternalDetails());
|
||||
}
|
||||
|
||||
return customparameterMap;
|
||||
}
|
||||
|
||||
public Map<String, String> getExternalDetails() {
|
||||
return convertExternalDetailsToMap(externalDetails);
|
||||
}
|
||||
|
||||
public ApiConstants.BootMode getBootMode() {
|
||||
if (StringUtils.isNotBlank(bootMode)) {
|
||||
try {
|
||||
String mode = bootMode.trim().toUpperCase();
|
||||
return ApiConstants.BootMode.valueOf(mode);
|
||||
} catch (IllegalArgumentException e) {
|
||||
String msg = String.format("Invalid %s: %s specified for VM: %s. Valid values are: %s",
|
||||
ApiConstants.BOOT_MODE, bootMode, getName(), Arrays.toString(ApiConstants.BootMode.values()));
|
||||
logger.error(msg);
|
||||
throw new InvalidParameterValueException(msg);
|
||||
}
|
||||
}
|
||||
if (ApiConstants.BootType.UEFI.equals(getBootType())) {
|
||||
String msg = String.format("%s must be specified for the VM with boot type: %s. Valid values are: %s",
|
||||
ApiConstants.BOOT_MODE, getBootType(), Arrays.toString(ApiConstants.BootMode.values()));
|
||||
logger.error(msg);
|
||||
throw new InvalidParameterValueException(msg);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, String> getVmProperties() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
if (MapUtils.isNotEmpty(vAppProperties)) {
|
||||
Collection parameterCollection = vAppProperties.values();
|
||||
Iterator iterator = parameterCollection.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
HashMap<String, String> entry = (HashMap<String, String>)iterator.next();
|
||||
map.put(entry.get("key"), entry.get("value"));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public Map<Integer, Long> getVmNetworkMap() {
|
||||
Map<Integer, Long> map = new HashMap<>();
|
||||
if (MapUtils.isNotEmpty(vAppNetworks)) {
|
||||
Collection parameterCollection = vAppNetworks.values();
|
||||
Iterator iterator = parameterCollection.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
HashMap<String, String> entry = (HashMap<String, String>) iterator.next();
|
||||
Integer nic;
|
||||
try {
|
||||
nic = Integer.valueOf(entry.get(VmDetailConstants.NIC));
|
||||
} catch (NumberFormatException nfe) {
|
||||
nic = null;
|
||||
}
|
||||
String networkUuid = entry.get(VmDetailConstants.NETWORK);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("nic, '%s', goes on net, '%s'", nic, networkUuid));
|
||||
}
|
||||
if (nic == null || StringUtils.isEmpty(networkUuid) || _entityMgr.findByUuid(Network.class, networkUuid) == null) {
|
||||
throw new InvalidParameterValueException(String.format("Network ID: %s for NIC ID: %s is invalid", networkUuid, nic));
|
||||
}
|
||||
map.put(nic, _entityMgr.findByUuid(Network.class, networkUuid).getId());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public HypervisorType getHypervisor() {
|
||||
return HypervisorType.getType(hypervisor);
|
||||
}
|
||||
|
||||
public Boolean isDisplayVm() {
|
||||
return displayVm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplay() {
|
||||
if(displayVm == null)
|
||||
return true;
|
||||
else
|
||||
return displayVm;
|
||||
}
|
||||
|
||||
public List<String> getSecurityGroupNameList() {
|
||||
return securityGroupNameList;
|
||||
}
|
||||
|
||||
public List<Long> getSecurityGroupIdList() {
|
||||
return securityGroupIdList;
|
||||
}
|
||||
|
||||
public Long getServiceOfferingId() {
|
||||
return serviceOfferingId;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public Long getTemplateId() {
|
||||
return templateId;
|
||||
}
|
||||
|
||||
public String getUserData() {
|
||||
return userData;
|
||||
}
|
||||
|
||||
public Long getUserdataId() {
|
||||
return userdataId;
|
||||
}
|
||||
|
||||
public Map<String, String> getUserdataDetails() {
|
||||
return convertDetailsToMap(userdataDetails);
|
||||
}
|
||||
|
||||
public Long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public Integer getLeaseDuration() {
|
||||
return leaseDuration;
|
||||
}
|
||||
|
||||
public VMLeaseManager.ExpiryAction getLeaseExpiryAction() {
|
||||
if (StringUtils.isBlank(leaseExpiryAction)) {
|
||||
return null;
|
||||
}
|
||||
VMLeaseManager.ExpiryAction action = EnumUtils.getEnumIgnoreCase(VMLeaseManager.ExpiryAction.class, leaseExpiryAction);
|
||||
if (action == null) {
|
||||
throw new InvalidParameterValueException("Invalid value configured for leaseexpiryaction, valid values are: " +
|
||||
com.cloud.utils.EnumUtils.listValues(VMLeaseManager.ExpiryAction.values()));
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
public List<Long> getNetworkIds() {
|
||||
if (MapUtils.isNotEmpty(vAppNetworks)) {
|
||||
if (CollectionUtils.isNotEmpty(networkIds) || ipAddress != null || getIp6Address() != null || MapUtils.isNotEmpty(ipToNetworkList)) {
|
||||
throw new InvalidParameterValueException(String.format("%s can't be specified along with %s, %s, %s", ApiConstants.NIC_NETWORK_LIST, ApiConstants.NETWORK_IDS, ApiConstants.IP_ADDRESS, ApiConstants.IP_NETWORK_LIST));
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
if (ipToNetworkList != null && !ipToNetworkList.isEmpty()) {
|
||||
if ((networkIds != null && !networkIds.isEmpty()) || ipAddress != null || getIp6Address() != null) {
|
||||
throw new InvalidParameterValueException("ipToNetworkMap can't be specified along with networkIds or ipAddress");
|
||||
} else {
|
||||
List<Long> networks = new ArrayList<Long>();
|
||||
networks.addAll(getIpToNetworkMap().keySet());
|
||||
return networks;
|
||||
}
|
||||
}
|
||||
return networkIds;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<String> getSSHKeyPairNames() {
|
||||
List<String> sshKeyPairs = new ArrayList<String>();
|
||||
if(sshKeyPairNames != null) {
|
||||
sshKeyPairs = sshKeyPairNames;
|
||||
}
|
||||
if(sshKeyPairName != null && !sshKeyPairName.isEmpty()) {
|
||||
sshKeyPairs.add(sshKeyPairName);
|
||||
}
|
||||
return sshKeyPairs;
|
||||
}
|
||||
|
||||
public Long getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
||||
public boolean getStartVm() {
|
||||
return startVm == null ? true : startVm;
|
||||
}
|
||||
|
||||
public Map<Long, IpAddresses> getIpToNetworkMap() {
|
||||
if ((networkIds != null || ipAddress != null || getIp6Address() != null) && ipToNetworkList != null) {
|
||||
throw new InvalidParameterValueException("NetworkIds and ipAddress can't be specified along with ipToNetworkMap parameter");
|
||||
}
|
||||
LinkedHashMap<Long, IpAddresses> ipToNetworkMap = null;
|
||||
if (ipToNetworkList != null && !ipToNetworkList.isEmpty()) {
|
||||
ipToNetworkMap = new LinkedHashMap<Long, IpAddresses>();
|
||||
Collection ipsCollection = ipToNetworkList.values();
|
||||
Iterator iter = ipsCollection.iterator();
|
||||
while (iter.hasNext()) {
|
||||
HashMap<String, String> ips = (HashMap<String, String>)iter.next();
|
||||
Long networkId = getNetworkIdFomIpMap(ips);
|
||||
IpAddresses addrs = getIpAddressesFromIpMap(ips);
|
||||
ipToNetworkMap.put(networkId, addrs);
|
||||
}
|
||||
}
|
||||
|
||||
return ipToNetworkMap;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private IpAddresses getIpAddressesFromIpMap(HashMap<String, String> ips) {
|
||||
String requestedIp = ips.get("ip");
|
||||
String requestedIpv6 = ips.get("ipv6");
|
||||
String requestedMac = ips.get("mac");
|
||||
if (requestedIpv6 != null) {
|
||||
requestedIpv6 = NetUtils.standardizeIp6Address(requestedIpv6);
|
||||
}
|
||||
if (requestedMac != null) {
|
||||
if(!NetUtils.isValidMac(requestedMac)) {
|
||||
throw new InvalidParameterValueException("Mac address is not valid: " + requestedMac);
|
||||
} else if(!NetUtils.isUnicastMac(requestedMac)) {
|
||||
throw new InvalidParameterValueException("Mac address is not unicast: " + requestedMac);
|
||||
}
|
||||
requestedMac = NetUtils.standardizeMacAddress(requestedMac);
|
||||
}
|
||||
return new IpAddresses(requestedIp, requestedIpv6, requestedMac);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Long getNetworkIdFomIpMap(HashMap<String, String> ips) {
|
||||
Long networkId;
|
||||
final String networkid = ips.get("networkid");
|
||||
Network network = _networkService.getNetwork(networkid);
|
||||
if (network != null) {
|
||||
networkId = network.getId();
|
||||
} else {
|
||||
try {
|
||||
networkId = Long.parseLong(networkid);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new InvalidParameterValueException("Unable to translate and find entity with networkId: " + networkid);
|
||||
}
|
||||
}
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
public String getIp6Address() {
|
||||
if (ip6Address == null) {
|
||||
return null;
|
||||
}
|
||||
return NetUtils.standardizeIp6Address(ip6Address);
|
||||
}
|
||||
|
||||
|
||||
public String getMacAddress() {
|
||||
if (macAddress == null) {
|
||||
return null;
|
||||
}
|
||||
if(!NetUtils.isValidMac(macAddress)) {
|
||||
throw new InvalidParameterValueException("Mac address is not valid: " + macAddress);
|
||||
} else if(!NetUtils.isUnicastMac(macAddress)) {
|
||||
throw new InvalidParameterValueException("Mac address is not unicast: " + macAddress);
|
||||
}
|
||||
return NetUtils.standardizeMacAddress(macAddress);
|
||||
}
|
||||
|
||||
public List<Long> getAffinityGroupIdList() {
|
||||
if (affinityGroupNameList != null && affinityGroupIdList != null) {
|
||||
throw new InvalidParameterValueException("affinitygroupids parameter is mutually exclusive with affinitygroupnames parameter");
|
||||
}
|
||||
|
||||
// transform group names to ids here
|
||||
if (affinityGroupNameList != null) {
|
||||
List<Long> affinityGroupIds = new ArrayList<Long>();
|
||||
for (String groupName : affinityGroupNameList) {
|
||||
Long groupId = _responseGenerator.getAffinityGroupId(groupName, getEntityOwnerId());
|
||||
if (groupId == null) {
|
||||
throw new InvalidParameterValueException("Unable to find affinity group by name " + groupName);
|
||||
} else {
|
||||
affinityGroupIds.add(groupId);
|
||||
}
|
||||
}
|
||||
return affinityGroupIds;
|
||||
} else {
|
||||
return affinityGroupIdList;
|
||||
}
|
||||
}
|
||||
|
||||
public String getKeyboard() {
|
||||
// TODO Auto-generated method stub
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
public Map<String, Map<Integer, String>> getDhcpOptionsMap() {
|
||||
Map<String, Map<Integer, String>> dhcpOptionsMap = new HashMap<>();
|
||||
if (dhcpOptionsNetworkList != null && !dhcpOptionsNetworkList.isEmpty()) {
|
||||
|
||||
Collection<Map<String, String>> paramsCollection = this.dhcpOptionsNetworkList.values();
|
||||
for (Map<String, String> dhcpNetworkOptions : paramsCollection) {
|
||||
String networkId = dhcpNetworkOptions.get(ApiConstants.NETWORK_ID);
|
||||
|
||||
if (networkId == null) {
|
||||
throw new IllegalArgumentException("No networkid specified when providing extra dhcp options.");
|
||||
}
|
||||
|
||||
Map<Integer, String> dhcpOptionsForNetwork = new HashMap<>();
|
||||
dhcpOptionsMap.put(networkId, dhcpOptionsForNetwork);
|
||||
|
||||
for (String key : dhcpNetworkOptions.keySet()) {
|
||||
if (key.startsWith(ApiConstants.DHCP_PREFIX)) {
|
||||
int dhcpOptionValue = Integer.parseInt(key.replaceFirst(ApiConstants.DHCP_PREFIX, ""));
|
||||
dhcpOptionsForNetwork.put(dhcpOptionValue, dhcpNetworkOptions.get(key));
|
||||
} else if (!key.equals(ApiConstants.NETWORK_ID)) {
|
||||
Dhcp.DhcpOptionCode dhcpOptionEnum = Dhcp.DhcpOptionCode.valueOfString(key);
|
||||
dhcpOptionsForNetwork.put(dhcpOptionEnum.getCode(), dhcpNetworkOptions.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return dhcpOptionsMap;
|
||||
}
|
||||
|
||||
public Map<Long, DiskOffering> getDataDiskTemplateToDiskOfferingMap() {
|
||||
if (diskOfferingId != null && dataDiskTemplateToDiskOfferingList != null) {
|
||||
throw new InvalidParameterValueException("diskofferingid parameter can't be specified along with datadisktemplatetodiskofferinglist parameter");
|
||||
}
|
||||
if (MapUtils.isEmpty(dataDiskTemplateToDiskOfferingList)) {
|
||||
return new HashMap<Long, DiskOffering>();
|
||||
}
|
||||
|
||||
HashMap<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap = new HashMap<Long, DiskOffering>();
|
||||
for (Object objDataDiskTemplates : dataDiskTemplateToDiskOfferingList.values()) {
|
||||
HashMap<String, String> dataDiskTemplates = (HashMap<String, String>) objDataDiskTemplates;
|
||||
Long dataDiskTemplateId;
|
||||
DiskOffering dataDiskOffering = null;
|
||||
VirtualMachineTemplate dataDiskTemplate= _entityMgr.findByUuid(VirtualMachineTemplate.class, dataDiskTemplates.get("datadisktemplateid"));
|
||||
if (dataDiskTemplate == null) {
|
||||
dataDiskTemplate = _entityMgr.findById(VirtualMachineTemplate.class, dataDiskTemplates.get("datadisktemplateid"));
|
||||
if (dataDiskTemplate == null)
|
||||
throw new InvalidParameterValueException("Unable to translate and find entity with datadisktemplateid " + dataDiskTemplates.get("datadisktemplateid"));
|
||||
}
|
||||
dataDiskTemplateId = dataDiskTemplate.getId();
|
||||
dataDiskOffering = _entityMgr.findByUuid(DiskOffering.class, dataDiskTemplates.get("diskofferingid"));
|
||||
if (dataDiskOffering == null) {
|
||||
dataDiskOffering = _entityMgr.findById(DiskOffering.class, dataDiskTemplates.get("diskofferingid"));
|
||||
if (dataDiskOffering == null)
|
||||
throw new InvalidParameterValueException("Unable to translate and find entity with diskofferingId " + dataDiskTemplates.get("diskofferingid"));
|
||||
}
|
||||
dataDiskTemplateToDiskOfferingMap.put(dataDiskTemplateId, dataDiskOffering);
|
||||
}
|
||||
return dataDiskTemplateToDiskOfferingMap;
|
||||
}
|
||||
|
||||
public String getExtraConfig() {
|
||||
return extraConfig;
|
||||
}
|
||||
|
||||
public boolean getCopyImageTags() {
|
||||
return copyImageTags == null ? false : copyImageTags;
|
||||
}
|
||||
|
||||
public Boolean getBootIntoSetup() {
|
||||
return bootIntoSetup;
|
||||
}
|
||||
|
||||
public boolean isDynamicScalingEnabled() {
|
||||
return dynamicScalingEnabled == null ? true : dynamicScalingEnabled;
|
||||
}
|
||||
|
||||
public Long getOverrideDiskOfferingId() {
|
||||
return overrideDiskOfferingId;
|
||||
}
|
||||
|
||||
public ApiConstants.IoDriverPolicy getIoDriverPolicy() {
|
||||
if (StringUtils.isNotBlank(ioDriverPolicy)) {
|
||||
try {
|
||||
String policyType = ioDriverPolicy.trim().toUpperCase();
|
||||
return ApiConstants.IoDriverPolicy.valueOf(policyType);
|
||||
} catch (IllegalArgumentException e) {
|
||||
String errMesg = String.format("Invalid io policy %s specified for vm %s. Valid values are: %s", ioDriverPolicy, getName(), Arrays.toString(ApiConstants.IoDriverPolicy.values()));
|
||||
logger.warn(errMesg);
|
||||
throw new InvalidParameterValueException(errMesg);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getVolumeId() {
|
||||
return volumeId;
|
||||
}
|
||||
|
|
@ -782,57 +87,6 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
|
|||
public boolean isVolumeOrSnapshotProvided() {
|
||||
return volumeId != null || snapshotId != null;
|
||||
}
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
public static String getResultObjectName() {
|
||||
return "virtualmachine";
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Long accountId = _accountService.finalyzeAccountId(accountName, domainId, projectId, true);
|
||||
if (accountId == null) {
|
||||
return CallContext.current().getCallingAccount().getId();
|
||||
}
|
||||
|
||||
return accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_VM_CREATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateEventType() {
|
||||
return EventTypes.EVENT_VM_CREATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreateEventDescription() {
|
||||
return "creating Vm";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
if(getStartVm()) {
|
||||
return "starting Vm. Vm Id: " + getEntityUuid();
|
||||
}
|
||||
return "deploying Vm. Vm Id: " + getEntityUuid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiCommandResourceType getApiResourceType() {
|
||||
return ApiCommandResourceType.VirtualMachine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
UserVm result;
|
||||
|
|
@ -875,7 +129,6 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void create() throws ResourceAllocationException {
|
||||
if (Stream.of(templateId, snapshotId, volumeId).filter(Objects::nonNull).count() != 1) {
|
||||
|
|
|
|||
|
|
@ -140,7 +140,8 @@ public class DestroyVMCmd extends BaseAsyncCmd implements UserCmd {
|
|||
if (responses != null && !responses.isEmpty()) {
|
||||
response = responses.get(0);
|
||||
}
|
||||
response.setResponseName("virtualmachine");
|
||||
response.setResponseName(getCommandName());
|
||||
response.setObjectName("virtualmachine");
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to destroy vm");
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ public class BackupOfferingResponse extends BaseResponse {
|
|||
@Param(description = "description for the backup offering")
|
||||
private String description;
|
||||
|
||||
@SerializedName(ApiConstants.PROVIDER)
|
||||
@Param(description = "provider name", since = "4.21.0")
|
||||
private String provider;
|
||||
|
||||
@SerializedName(ApiConstants.EXTERNAL_ID)
|
||||
@Param(description = "external ID on the provider side")
|
||||
private String externalId;
|
||||
|
|
@ -69,6 +73,10 @@ public class BackupOfferingResponse extends BaseResponse {
|
|||
this.externalId = externalId;
|
||||
}
|
||||
|
||||
public void setProvider(String provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.cloud.serializer.Param;
|
|||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@EntityReference(value = Backup.class)
|
||||
public class BackupResponse extends BaseResponse {
|
||||
|
|
@ -34,6 +35,14 @@ public class BackupResponse extends BaseResponse {
|
|||
@Param(description = "ID of the VM backup")
|
||||
private String id;
|
||||
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "name of the backup", since = "4.21.0")
|
||||
private String name;
|
||||
|
||||
@SerializedName(ApiConstants.DESCRIPTION)
|
||||
@Param(description = "description for the backup", since = "4.21.0")
|
||||
private String description;
|
||||
|
||||
@SerializedName(ApiConstants.VIRTUAL_MACHINE_ID)
|
||||
@Param(description = "ID of the VM")
|
||||
private String vmId;
|
||||
|
|
@ -102,6 +111,18 @@ public class BackupResponse extends BaseResponse {
|
|||
@Param(description = "zone name")
|
||||
private String zone;
|
||||
|
||||
@SerializedName(ApiConstants.VM_DETAILS)
|
||||
@Param(description = "Lists the vm specific details for the backup", since = "4.21.0")
|
||||
private Map<String, String> vmDetails;
|
||||
|
||||
@SerializedName(ApiConstants.INTERVAL_TYPE)
|
||||
@Param(description = "Interval type of the backup", since = "4.21.0")
|
||||
private String intervalType;
|
||||
|
||||
@SerializedName(ApiConstants.BACKUP_VM_OFFERING_REMOVED)
|
||||
@Param(description = "The backup offering corresponding to this backup was removed from the VM", since = "4.21.0")
|
||||
private Boolean vmOfferingRemoved;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
|
@ -110,6 +131,22 @@ public class BackupResponse extends BaseResponse {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
|
@ -245,4 +282,28 @@ public class BackupResponse extends BaseResponse {
|
|||
public void setZone(String zone) {
|
||||
this.zone = zone;
|
||||
}
|
||||
|
||||
public Map<String, String> getVmDetails() {
|
||||
return vmDetails;
|
||||
}
|
||||
|
||||
public void setVmDetails(Map<String, String> vmDetails) {
|
||||
this.vmDetails = vmDetails;
|
||||
}
|
||||
|
||||
public String getIntervalType() {
|
||||
return this.intervalType;
|
||||
}
|
||||
|
||||
public void setIntervalType(String intervalType) {
|
||||
this.intervalType = intervalType;
|
||||
}
|
||||
|
||||
public Boolean getVmOfferingRemoved() {
|
||||
return this.vmOfferingRemoved;
|
||||
}
|
||||
|
||||
public void setVmOfferingRemoved(Boolean vmOfferingRemoved) {
|
||||
this.vmOfferingRemoved = vmOfferingRemoved;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ public class BackupScheduleResponse extends BaseResponse {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
@SerializedName(ApiConstants.QUIESCE_VM)
|
||||
@Param(description = "quiesce the instance before checkpointing the disks for backup")
|
||||
private Boolean quiesceVM;
|
||||
|
||||
public String getVmName() {
|
||||
return vmName;
|
||||
}
|
||||
|
|
@ -103,4 +107,8 @@ public class BackupScheduleResponse extends BaseResponse {
|
|||
public void setMaxBackups(Integer maxBackups) {
|
||||
this.maxBackups = maxBackups;
|
||||
}
|
||||
|
||||
public void setQuiesceVM(Boolean quiesceVM) {
|
||||
this.quiesceVM = quiesceVM;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,236 @@
|
|||
// 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 org.apache.cloudstack.context.CallContext;
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import org.apache.cloudstack.consoleproxy.ConsoleSession;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.api.EntityReference;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@EntityReference(value = ConsoleSession.class)
|
||||
public class ConsoleSessionResponse extends BaseResponse {
|
||||
|
||||
@SerializedName(ApiConstants.ID)
|
||||
@Param(description = "ID of the console session.")
|
||||
private String id;
|
||||
|
||||
@SerializedName(ApiConstants.CREATED)
|
||||
@Param(description = "Date when the console session's endpoint was created.")
|
||||
private Date created;
|
||||
|
||||
@SerializedName(ApiConstants.DOMAIN)
|
||||
@Param(description = "Domain of the account that created the console endpoint.")
|
||||
private String domain;
|
||||
|
||||
@SerializedName(ApiConstants.DOMAIN_PATH)
|
||||
@Param(description = "Domain path of the account that created the console endpoint.")
|
||||
private String domainPath;
|
||||
|
||||
@SerializedName(ApiConstants.DOMAIN_ID)
|
||||
@Param(description = "Domain ID of the account that created the console endpoint.")
|
||||
private String domainId;
|
||||
|
||||
@SerializedName(ApiConstants.ACCOUNT)
|
||||
@Param(description = "Account that created the console endpoint.")
|
||||
private String account;
|
||||
|
||||
@SerializedName(ApiConstants.ACCOUNT_ID)
|
||||
@Param(description = "ID of the account that created the console endpoint.")
|
||||
private String accountId;
|
||||
|
||||
@SerializedName(ApiConstants.USER)
|
||||
@Param(description = "User that created the console endpoint.")
|
||||
private String user;
|
||||
|
||||
@SerializedName(ApiConstants.USER_ID)
|
||||
@Param(description = "ID of the user that created the console endpoint.")
|
||||
private String userId;
|
||||
|
||||
@SerializedName(ApiConstants.VIRTUAL_MACHINE_ID)
|
||||
@Param(description = "ID of the virtual machine.")
|
||||
private String vmId;
|
||||
|
||||
@SerializedName(ApiConstants.VIRTUAL_MACHINE_NAME)
|
||||
@Param(description = "Name of the virtual machine.")
|
||||
private String vmName;
|
||||
|
||||
@SerializedName(ApiConstants.HOST_ID)
|
||||
@Param(description = "ID of the host.")
|
||||
private String hostId;
|
||||
|
||||
@SerializedName(ApiConstants.HOST_NAME)
|
||||
@Param(description = "Name of the host.")
|
||||
private String hostName;
|
||||
|
||||
@SerializedName(ApiConstants.ACQUIRED)
|
||||
@Param(description = "Date when the console session was acquired.")
|
||||
private Date acquired;
|
||||
|
||||
@SerializedName(ApiConstants.REMOVED)
|
||||
@Param(description = "Date when the console session was removed.")
|
||||
private Date removed;
|
||||
|
||||
@SerializedName(ApiConstants.CONSOLE_ENDPOINT_CREATOR_ADDRESS)
|
||||
@Param(description = "IP address of the creator of the console endpoint.")
|
||||
private String consoleEndpointCreatorAddress;
|
||||
|
||||
@SerializedName(ApiConstants.CLIENT_ADDRESS)
|
||||
@Param(description = "IP address of the client that created the console session.")
|
||||
private String clientAddress;
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public void setDomain(String domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public void setDomainPath(String domainPath) {
|
||||
this.domainPath = domainPath;
|
||||
}
|
||||
|
||||
public void setDomainId(String domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public void setAccount(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public void setAccountId(String accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public void setVmId(String vmId) {
|
||||
this.vmId = vmId;
|
||||
}
|
||||
|
||||
public void setVmName(String vmName) {
|
||||
this.vmName = vmName;
|
||||
}
|
||||
|
||||
public void setHostId(String hostId) {
|
||||
this.hostId = hostId;
|
||||
}
|
||||
|
||||
public void setHostName(String hostName) {
|
||||
this.hostName = hostName;
|
||||
}
|
||||
|
||||
public void setAcquired(Date acquired) {
|
||||
this.acquired = acquired;
|
||||
}
|
||||
|
||||
public void setRemoved(Date removed) {
|
||||
this.removed = removed;
|
||||
}
|
||||
|
||||
public void setConsoleEndpointCreatorAddress(String consoleEndpointCreatorAddress) {
|
||||
this.consoleEndpointCreatorAddress = consoleEndpointCreatorAddress;
|
||||
}
|
||||
|
||||
public void setClientAddress(String clientAddress) {
|
||||
this.clientAddress = clientAddress;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public String getDomainPath() {
|
||||
return domainPath;
|
||||
}
|
||||
|
||||
public String getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public String getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public String getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
||||
public String getVmName() {
|
||||
return vmName;
|
||||
}
|
||||
|
||||
public String getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
||||
public String getHostName() {
|
||||
return hostName;
|
||||
}
|
||||
|
||||
public Date getAcquired() {
|
||||
return acquired;
|
||||
}
|
||||
|
||||
public Date getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public String getConsoleEndpointCreatorAddress() {
|
||||
return consoleEndpointCreatorAddress;
|
||||
}
|
||||
|
||||
public String getClientAddress() {
|
||||
return clientAddress;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,8 @@
|
|||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.storage.object.ObjectStore;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
|
||||
|
|
@ -24,15 +26,15 @@ import org.apache.cloudstack.api.EntityReference;
|
|||
|
||||
@EntityReference(value = ObjectStore.class)
|
||||
public class ObjectStoreResponse extends BaseResponseWithAnnotations {
|
||||
@SerializedName("id")
|
||||
@SerializedName(ApiConstants.ID)
|
||||
@Param(description = "the ID of the object store")
|
||||
private String id;
|
||||
|
||||
@SerializedName("name")
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "the name of the object store")
|
||||
private String name;
|
||||
|
||||
@SerializedName("url")
|
||||
@SerializedName(ApiConstants.URL)
|
||||
@Param(description = "the url of the object store")
|
||||
private String url;
|
||||
|
||||
|
|
@ -44,6 +46,10 @@ public class ObjectStoreResponse extends BaseResponseWithAnnotations {
|
|||
@Param(description = "the total size of the object store")
|
||||
private Long storageTotal;
|
||||
|
||||
@SerializedName("storageallocated")
|
||||
@Param(description = "the allocated size of the object store")
|
||||
private Long storageAllocated;
|
||||
|
||||
@SerializedName("storageused")
|
||||
@Param(description = "the object store currently used size")
|
||||
private Long storageUsed;
|
||||
|
|
@ -96,6 +102,14 @@ public class ObjectStoreResponse extends BaseResponseWithAnnotations {
|
|||
this.storageTotal = storageTotal;
|
||||
}
|
||||
|
||||
public Long getStorageAllocated() {
|
||||
return storageAllocated;
|
||||
}
|
||||
|
||||
public void setStorageAllocated(Long storageAllocated) {
|
||||
this.storageAllocated = storageAllocated;
|
||||
}
|
||||
|
||||
public Long getStorageUsed() {
|
||||
return storageUsed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,17 +16,16 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.cloud.storage.snapshot.SnapshotPolicy;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponseWithTagInformation;
|
||||
import org.apache.cloudstack.api.EntityReference;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.cloud.storage.snapshot.SnapshotPolicy;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@EntityReference(value = SnapshotPolicy.class)
|
||||
public class SnapshotPolicyResponse extends BaseResponseWithTagInformation {
|
||||
|
|
@ -62,9 +61,14 @@ public class SnapshotPolicyResponse extends BaseResponseWithTagInformation {
|
|||
@Param(description = "The list of zones in which snapshot backup is scheduled", responseObject = ZoneResponse.class, since = "4.19.0")
|
||||
protected Set<ZoneResponse> zones;
|
||||
|
||||
@SerializedName(ApiConstants.STORAGE)
|
||||
@Param(description = "The list of pools in which snapshot backup is scheduled", responseObject = StoragePoolResponse.class, since = "4.21.0")
|
||||
protected Set<StoragePoolResponse> storagePools;
|
||||
|
||||
public SnapshotPolicyResponse() {
|
||||
tags = new LinkedHashSet<ResourceTagResponse>();
|
||||
zones = new LinkedHashSet<>();
|
||||
storagePools = new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
|
|
@ -130,4 +134,6 @@ public class SnapshotPolicyResponse extends BaseResponseWithTagInformation {
|
|||
public void setZones(Set<ZoneResponse> zones) {
|
||||
this.zones = zones;
|
||||
}
|
||||
|
||||
public void setStoragePools(Set<StoragePoolResponse> pools) { this.storagePools = pools; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,6 +107,10 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements
|
|||
@Param(description = "physical size of backedup snapshot on image store")
|
||||
private long physicalSize;
|
||||
|
||||
@SerializedName(ApiConstants.CHAIN_SIZE)
|
||||
@Param(description = "chain size of snapshot including all parent snapshots. Shown only for incremental snapshots if snapshot.show.chain.size setting is set to true", since = "4.21.0")
|
||||
private Long chainSize;
|
||||
|
||||
@SerializedName(ApiConstants.ZONE_ID)
|
||||
@Param(description = "id of the availability zone")
|
||||
private String zoneId;
|
||||
|
|
@ -244,6 +248,10 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements
|
|||
this.physicalSize = physicalSize;
|
||||
}
|
||||
|
||||
public void setChainSize(long chainSize) {
|
||||
this.chainSize = chainSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProjectId(String projectId) {
|
||||
this.projectId = projectId;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.apache.cloudstack.backup;
|
|||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.api.Identity;
|
||||
|
|
@ -33,28 +34,6 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity {
|
|||
Allocated, Queued, BackingUp, BackedUp, Error, Failed, Restoring, Removed, Expunged
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
MANUAL, HOURLY, DAILY, WEEKLY, MONTHLY;
|
||||
private int max = 8;
|
||||
|
||||
public void setMax(int max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name();
|
||||
}
|
||||
|
||||
public boolean equals(String snapshotType) {
|
||||
return this.toString().equalsIgnoreCase(snapshotType);
|
||||
}
|
||||
}
|
||||
|
||||
class Metric {
|
||||
private Long backupSize = 0L;
|
||||
private Long dataSize = 0L;
|
||||
|
|
@ -85,6 +64,8 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity {
|
|||
private String id;
|
||||
private Date created;
|
||||
private String type;
|
||||
private Long backupSize = 0L;
|
||||
private Long dataSize = 0L;
|
||||
|
||||
public RestorePoint(String id, Date created, String type) {
|
||||
this.id = id;
|
||||
|
|
@ -92,6 +73,12 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity {
|
|||
this.type = type;
|
||||
}
|
||||
|
||||
public RestorePoint(String id, Date created, String type, Long backupSize, Long dataSize) {
|
||||
this(id, created, type);
|
||||
this.backupSize = backupSize;
|
||||
this.dataSize = dataSize;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
|
@ -115,6 +102,22 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity {
|
|||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Long getBackupSize() {
|
||||
return backupSize;
|
||||
}
|
||||
|
||||
public void setBackupSize(Long backupSize) {
|
||||
this.backupSize = backupSize;
|
||||
}
|
||||
|
||||
public Long getDataSize() {
|
||||
return dataSize;
|
||||
}
|
||||
|
||||
public void setDataSize(Long dataSize) {
|
||||
this.dataSize = dataSize;
|
||||
}
|
||||
}
|
||||
|
||||
class VolumeInfo {
|
||||
|
|
@ -122,12 +125,20 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity {
|
|||
private Volume.Type type;
|
||||
private Long size;
|
||||
private String path;
|
||||
private Long deviceId;
|
||||
private String diskOfferingId;
|
||||
private Long minIops;
|
||||
private Long maxIops;
|
||||
|
||||
public VolumeInfo(String uuid, String path, Volume.Type type, Long size) {
|
||||
public VolumeInfo(String uuid, String path, Volume.Type type, Long size, Long deviceId, String diskOfferingId, Long minIops, Long maxIops) {
|
||||
this.uuid = uuid;
|
||||
this.type = type;
|
||||
this.size = size;
|
||||
this.path = path;
|
||||
this.deviceId = deviceId;
|
||||
this.diskOfferingId = diskOfferingId;
|
||||
this.minIops = minIops;
|
||||
this.maxIops = maxIops;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
|
|
@ -150,13 +161,29 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity {
|
|||
return size;
|
||||
}
|
||||
|
||||
public Long getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public String getDiskOfferingId() {
|
||||
return diskOfferingId;
|
||||
}
|
||||
|
||||
public Long getMinIops() {
|
||||
return minIops;
|
||||
}
|
||||
|
||||
public Long getMaxIops() {
|
||||
return maxIops;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return StringUtils.join(":", uuid, path, type, size);
|
||||
return StringUtils.join(":", uuid, path, type, size, deviceId, diskOfferingId, minIops, maxIops);
|
||||
}
|
||||
}
|
||||
|
||||
long getVmId();
|
||||
Long getVmId();
|
||||
long getBackupOfferingId();
|
||||
String getExternalId();
|
||||
String getType();
|
||||
|
|
@ -164,6 +191,12 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity {
|
|||
Backup.Status getStatus();
|
||||
Long getSize();
|
||||
Long getProtectedSize();
|
||||
void setName(String name);
|
||||
String getDescription();
|
||||
void setDescription(String description);
|
||||
List<VolumeInfo> getBackedUpVolumes();
|
||||
long getZoneId();
|
||||
Map<String, String> getDetails();
|
||||
String getDetail(String name);
|
||||
Long getBackupScheduleId();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,20 +18,29 @@
|
|||
package org.apache.cloudstack.backup;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.capacity.Capacity;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import org.apache.cloudstack.api.command.admin.backup.ImportBackupOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.CreateBackupCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.ListBackupOfferingsCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.ListBackupsCmd;
|
||||
import org.apache.cloudstack.api.response.BackupResponse;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.component.PluggableService;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VmDiskInfo;
|
||||
|
||||
/**
|
||||
* Backup and Recover Manager Interface
|
||||
|
|
@ -58,38 +67,6 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
|
|||
"false",
|
||||
"Enable volume attach/detach operations for VMs that are assigned to Backup Offerings.", true);
|
||||
|
||||
ConfigKey<Integer> BackupHourlyMax = new ConfigKey<Integer>("Advanced", Integer.class,
|
||||
"backup.max.hourly",
|
||||
"8",
|
||||
"Maximum recurring hourly backups to be retained for an instance. If the limit is reached, early backups from the start of the hour are deleted so that newer ones can be saved. This limit does not apply to manual backups. If set to 0, recurring hourly backups can not be scheduled.",
|
||||
false,
|
||||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
|
||||
ConfigKey<Integer> BackupDailyMax = new ConfigKey<Integer>("Advanced", Integer.class,
|
||||
"backup.max.daily",
|
||||
"8",
|
||||
"Maximum recurring daily backups to be retained for an instance. If the limit is reached, backups from the start of the day are deleted so that newer ones can be saved. This limit does not apply to manual backups. If set to 0, recurring daily backups can not be scheduled.",
|
||||
false,
|
||||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
|
||||
ConfigKey<Integer> BackupWeeklyMax = new ConfigKey<Integer>("Advanced", Integer.class,
|
||||
"backup.max.weekly",
|
||||
"8",
|
||||
"Maximum recurring weekly backups to be retained for an instance. If the limit is reached, backups from the beginning of the week are deleted so that newer ones can be saved. This limit does not apply to manual backups. If set to 0, recurring weekly backups can not be scheduled.",
|
||||
false,
|
||||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
|
||||
ConfigKey<Integer> BackupMonthlyMax = new ConfigKey<Integer>("Advanced", Integer.class,
|
||||
"backup.max.monthly",
|
||||
"8",
|
||||
"Maximum recurring monthly backups to be retained for an instance. If the limit is reached, backups from the beginning of the month are deleted so that newer ones can be saved. This limit does not apply to manual backups. If set to 0, recurring monthly backups can not be scheduled.",
|
||||
false,
|
||||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
|
||||
ConfigKey<Long> DefaultMaxAccountBackups = new ConfigKey<Long>("Account Defaults", Long.class,
|
||||
"max.account.backups",
|
||||
"20",
|
||||
|
|
@ -138,6 +115,14 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
|
|||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
|
||||
ConfigKey<Float> BackupStorageCapacityThreshold = new ConfigKey<>("Alert", Float.class,
|
||||
"zone.backupStorage.capacity.notificationthreshold",
|
||||
"0.75",
|
||||
"Percentage (as a value between 0 and 1) of backup storage utilization above which alerts will be sent about low storage available.",
|
||||
true,
|
||||
ConfigKey.Scope.Zone,
|
||||
null);
|
||||
|
||||
/**
|
||||
* List backup provider offerings
|
||||
* @param zoneId zone id
|
||||
|
|
@ -200,11 +185,11 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
|
|||
|
||||
/**
|
||||
* Creates backup of a VM
|
||||
* @param vmId Virtual Machine ID
|
||||
* @param scheduleId Virtual Machine Backup Schedule ID
|
||||
* @param cmd CreateBackupCmd
|
||||
* @param job The async job associated with the backup retention
|
||||
* @return returns operation success
|
||||
*/
|
||||
boolean createBackup(final Long vmId, final Long scheduleId) throws ResourceAllocationException;
|
||||
boolean createBackup(CreateBackupCmd cmd, Object job) throws ResourceAllocationException;
|
||||
|
||||
/**
|
||||
* List existing backups for a VM
|
||||
|
|
@ -216,6 +201,15 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
|
|||
*/
|
||||
boolean restoreBackup(final Long backupId);
|
||||
|
||||
Map<Long, Network.IpAddresses> getIpToNetworkMapFromBackup(Backup backup, boolean preserveIps, List<Long> networkIds);
|
||||
|
||||
Boolean canCreateInstanceFromBackup(Long backupId);
|
||||
|
||||
/**
|
||||
* Restore a backup to a new Instance
|
||||
*/
|
||||
boolean restoreBackupToVM(Long backupId, Long vmId) throws ResourceUnavailableException;
|
||||
|
||||
/**
|
||||
* Restore a backed up volume and attach it to a VM
|
||||
*/
|
||||
|
|
@ -229,5 +223,25 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
|
|||
*/
|
||||
boolean deleteBackup(final Long backupId, final Boolean forced);
|
||||
|
||||
void validateBackupForZone(Long zoneId);
|
||||
|
||||
BackupOffering updateBackupOffering(UpdateBackupOfferingCmd updateBackupOfferingCmd);
|
||||
|
||||
VmDiskInfo getRootDiskInfoFromBackup(Backup backup);
|
||||
|
||||
List<VmDiskInfo> getDataDiskInfoListFromBackup(Backup backup);
|
||||
|
||||
void checkVmDisksSizeAgainstBackup(List<VmDiskInfo> vmDiskInfoList, Backup backup);
|
||||
|
||||
Map<String, String> getBackupDetailsFromVM(VirtualMachine vm);
|
||||
|
||||
String createVolumeInfoFromVolumes(List<Volume> vmVolumes);
|
||||
|
||||
String getBackupNameFromVM(VirtualMachine vm);
|
||||
|
||||
BackupResponse createBackupResponse(Backup backup, Boolean listVmDetails);
|
||||
|
||||
Capacity getBackupStorageUsedStats(Long zoneId);
|
||||
|
||||
void checkAndRemoveBackupOfferingBeforeExpunge(VirtualMachine vm);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package org.apache.cloudstack.backup;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
|
@ -71,10 +70,12 @@ public interface BackupProvider {
|
|||
/**
|
||||
* Starts and creates an adhoc backup process
|
||||
* for a previously registered VM backup
|
||||
* @param vm the machine to make a backup of
|
||||
*
|
||||
* @param vm the machine to make a backup of
|
||||
* @param quiesceVM instance will be quiesced for checkpointing for backup. Applicable only to NAS plugin.
|
||||
* @return the result and {code}Backup{code} {code}Object{code}
|
||||
*/
|
||||
Pair<Boolean, Backup> takeBackup(VirtualMachine vm);
|
||||
Pair<Boolean, Backup> takeBackup(VirtualMachine vm, Boolean quiesceVM);
|
||||
|
||||
/**
|
||||
* Delete an existing backup
|
||||
|
|
@ -84,6 +85,8 @@ public interface BackupProvider {
|
|||
*/
|
||||
boolean deleteBackup(Backup backup, boolean forced);
|
||||
|
||||
boolean restoreBackupToVM(VirtualMachine vm, Backup backup, String hostIp, String dataStoreUuid);
|
||||
|
||||
/**
|
||||
* Restore VM from backup
|
||||
*/
|
||||
|
|
@ -92,27 +95,44 @@ public interface BackupProvider {
|
|||
/**
|
||||
* Restore a volume from a backup
|
||||
*/
|
||||
Pair<Boolean, String> restoreBackedUpVolume(Backup backup, String volumeUuid, String hostIp, String dataStoreUuid, Pair<String, VirtualMachine.State> vmNameAndState);
|
||||
Pair<Boolean, String> restoreBackedUpVolume(Backup backup, Backup.VolumeInfo backupVolumeInfo, String hostIp, String dataStoreUuid, Pair<String, VirtualMachine.State> vmNameAndState);
|
||||
|
||||
/**
|
||||
* Returns backup metrics for a list of VMs in a zone
|
||||
* Syncs backup metrics (backup size, protected size) from the plugin and stores it within the provider
|
||||
* @param zoneId the zone for which to return metrics
|
||||
* @param vms a list of machines to get measurements for
|
||||
* @return a map of machine -> backup metrics
|
||||
*/
|
||||
Map<VirtualMachine, Backup.Metric> getBackupMetrics(Long zoneId, List<VirtualMachine> vms);
|
||||
void syncBackupMetrics(Long zoneId);
|
||||
|
||||
/**
|
||||
* This method should TODO
|
||||
* @param vm the machine to get restore point for
|
||||
* Returns a list of Backup.RestorePoint
|
||||
* @param vm the machine to get the restore points for
|
||||
*/
|
||||
List<Backup.RestorePoint> listRestorePoints(VirtualMachine vm);
|
||||
|
||||
/**
|
||||
* This method should TODO
|
||||
* Creates and returns an entry in the backups table by getting the information from restorePoint and vm.
|
||||
*
|
||||
* @param restorePoint the restore point to create a backup for
|
||||
* @param vm The machine for which to create a backup
|
||||
* @param metric the metric object to update with the new backup data
|
||||
* @param vm The machine for which to create a backup
|
||||
*/
|
||||
Backup createNewBackupEntryForRestorePoint(Backup.RestorePoint restorePoint, VirtualMachine vm, Backup.Metric metric);
|
||||
Backup createNewBackupEntryForRestorePoint(Backup.RestorePoint restorePoint, VirtualMachine vm);
|
||||
|
||||
/**
|
||||
* Returns if the backup provider supports creating new instance from backup
|
||||
*/
|
||||
boolean supportsInstanceFromBackup();
|
||||
|
||||
/**
|
||||
* Returns the backup storage usage (Used, Total) for a backup provider
|
||||
* @param zoneId the zone for which to return metrics
|
||||
* @return a pair of Used size and Total size for the backup storage
|
||||
*/
|
||||
Pair<Long, Long> getBackupStorageStats(Long zoneId);
|
||||
|
||||
/**
|
||||
* Gets the backup storage usage (Used, Total) from the plugin and stores it in db
|
||||
* @param zoneId the zone for which to return metrics
|
||||
*/
|
||||
void syncBackupStorageStats(Long zoneId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ public interface BackupRepository extends InternalIdentity, Identity {
|
|||
String getType();
|
||||
String getAddress();
|
||||
String getMountOptions();
|
||||
void setUsedBytes(Long usedBytes);
|
||||
Long getCapacityBytes();
|
||||
Long getUsedBytes();
|
||||
void setCapacityBytes(Long capacityBytes);
|
||||
Date getCreated();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public interface BackupSchedule extends InternalIdentity {
|
|||
String getTimezone();
|
||||
Date getScheduledTimestamp();
|
||||
Long getAsyncJobId();
|
||||
Integer getMaxBackups();
|
||||
Boolean getQuiesceVM();
|
||||
int getMaxBackups();
|
||||
String getUuid();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ package org.apache.cloudstack.consoleproxy;
|
|||
|
||||
import com.cloud.utils.component.Manager;
|
||||
import org.apache.cloudstack.api.command.user.consoleproxy.ConsoleEndpoint;
|
||||
import org.apache.cloudstack.api.command.user.consoleproxy.ListConsoleSessionsCmd;
|
||||
import org.apache.cloudstack.api.response.ConsoleSessionResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import java.util.Date;
|
||||
|
|
@ -48,4 +51,8 @@ public interface ConsoleAccessManager extends Manager, Configurable {
|
|||
|
||||
String genAccessTicket(String host, String port, String sid, String tag, String sessionUuid);
|
||||
String genAccessTicket(String host, String port, String sid, String tag, Date normalizedHashTime, String sessionUuid);
|
||||
|
||||
ListResponse<ConsoleSessionResponse> listConsoleSessions(ListConsoleSessionsCmd cmd);
|
||||
|
||||
ConsoleSession listConsoleSessionById(long id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
// 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.consoleproxy;
|
||||
|
||||
import org.apache.cloudstack.api.Identity;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface ConsoleSession extends InternalIdentity, Identity {
|
||||
|
||||
Date getCreated();
|
||||
|
||||
long getDomainId();
|
||||
|
||||
long getAccountId();
|
||||
|
||||
long getUserId();
|
||||
|
||||
long getInstanceId();
|
||||
|
||||
long getHostId();
|
||||
|
||||
Date getRemoved();
|
||||
|
||||
Date getAcquired();
|
||||
|
||||
String getConsoleEndpointCreatorAddress();
|
||||
|
||||
String getClientAddress();
|
||||
}
|
||||
|
|
@ -158,7 +158,7 @@ public interface RoutedIpv4Manager extends PluggableService, Configurable {
|
|||
|
||||
boolean isRoutedVpc(Vpc vpc);
|
||||
|
||||
boolean isVpcVirtualRouterGateway(VpcOffering vpcOffering);
|
||||
boolean isValidGateway(VpcOffering vpcOffering);
|
||||
|
||||
BgpPeer createBgpPeer(CreateBgpPeerCmd createBgpPeerCmd);
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ public class AddObjectStoragePoolCmdTest {
|
|||
|
||||
String provider = "Simulator";
|
||||
|
||||
Long size = 10L;
|
||||
|
||||
Map<String, String> details;
|
||||
|
||||
private AutoCloseable closeable;
|
||||
|
|
@ -74,6 +76,7 @@ public class AddObjectStoragePoolCmdTest {
|
|||
ReflectionTestUtils.setField(addObjectStoragePoolCmdSpy, "url", url);
|
||||
ReflectionTestUtils.setField(addObjectStoragePoolCmdSpy, "providerName", provider);
|
||||
ReflectionTestUtils.setField(addObjectStoragePoolCmdSpy, "details", details);
|
||||
ReflectionTestUtils.setField(addObjectStoragePoolCmdSpy, "size", size);
|
||||
addObjectStoragePoolCmdSpy._storageService = storageService;
|
||||
addObjectStoragePoolCmdSpy._responseGenerator = responseGenerator;
|
||||
}
|
||||
|
|
@ -87,12 +90,12 @@ public class AddObjectStoragePoolCmdTest {
|
|||
@Test
|
||||
public void testAddObjectStore() throws DiscoveryException {
|
||||
Mockito.doReturn(objectStore).when(storageService).discoverObjectStore(Mockito.anyString(),
|
||||
Mockito.anyString(), Mockito.anyString(), any());
|
||||
Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(), any());
|
||||
ObjectStoreResponse objectStoreResponse = new ObjectStoreResponse();
|
||||
Mockito.doReturn(objectStoreResponse).when(responseGenerator).createObjectStoreResponse(any());
|
||||
addObjectStoragePoolCmdSpy.execute();
|
||||
|
||||
Mockito.verify(storageService, Mockito.times(1))
|
||||
.discoverObjectStore(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
.discoverObjectStore(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public class CreateSnapshotCmdTest extends TestCase {
|
|||
Snapshot snapshot = Mockito.mock(Snapshot.class);
|
||||
try {
|
||||
Mockito.when(volumeApiService.takeSnapshot(nullable(Long.class), nullable(Long.class), isNull(),
|
||||
nullable(Account.class), nullable(Boolean.class), nullable(Snapshot.LocationType.class), nullable(Boolean.class), nullable(Map.class), nullable(List.class))).thenReturn(snapshot);
|
||||
nullable(Account.class), nullable(Boolean.class), nullable(Snapshot.LocationType.class), nullable(Boolean.class), nullable(Map.class), nullable(List.class), nullable(List.class), Mockito.anyBoolean())).thenReturn(snapshot);
|
||||
|
||||
} catch (Exception e) {
|
||||
Assert.fail("Received exception when success expected " + e.getMessage());
|
||||
|
|
@ -126,7 +126,7 @@ public class CreateSnapshotCmdTest extends TestCase {
|
|||
|
||||
try {
|
||||
Mockito.when(volumeApiService.takeSnapshot(nullable(Long.class), nullable(Long.class), nullable(Long.class),
|
||||
nullable(Account.class), nullable(Boolean.class), nullable(Snapshot.LocationType.class), nullable(Boolean.class), any(), Mockito.anyList())).thenReturn(null);
|
||||
nullable(Account.class), nullable(Boolean.class), nullable(Snapshot.LocationType.class), nullable(Boolean.class), any(), Mockito.anyList(), Mockito.anyList(), Mockito.anyBoolean())).thenReturn(null);
|
||||
} catch (Exception e) {
|
||||
Assert.fail("Received exception when success expected " + e.getMessage());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,124 @@
|
|||
// 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 org.apache.cloudstack.context.CallContext;
|
||||
package org.apache.cloudstack.api.command.user.consoleproxy;
|
||||
|
||||
import org.apache.cloudstack.consoleproxy.ConsoleSession;
|
||||
import com.cloud.user.AccountService;
|
||||
|
||||
import com.cloud.user.UserAccount;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.consoleproxy.ConsoleAccessManager;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ListConsoleSessionsCmdTest {
|
||||
@Mock
|
||||
private AccountService accountServiceMock;
|
||||
|
||||
@Mock
|
||||
private ConsoleAccessManager consoleAccessManagerMock;
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
private ListConsoleSessionsCmd listConsoleSessionsCmdSpy;
|
||||
|
||||
@Test
|
||||
public void executeTestApiExecutionShouldCallServiceLayer() {
|
||||
Mockito.when(consoleAccessManagerMock.listConsoleSessions(listConsoleSessionsCmdSpy)).thenReturn(new ListResponse<>());
|
||||
listConsoleSessionsCmdSpy.execute();
|
||||
Mockito.verify(consoleAccessManagerMock).listConsoleSessions(listConsoleSessionsCmdSpy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntityOwnerIdTestReturnConsoleSessionIdIfProvided() {
|
||||
ConsoleSession consoleSessionMock = Mockito.mock(ConsoleSession.class);
|
||||
long consoleSessionId = 2L;
|
||||
long accountId = 2L;
|
||||
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getId()).thenReturn(consoleSessionId);
|
||||
Mockito.when(consoleAccessManagerMock.listConsoleSessionById(consoleSessionId)).thenReturn(consoleSessionMock);
|
||||
Mockito.when(consoleSessionMock.getAccountId()).thenReturn(accountId);
|
||||
|
||||
Assert.assertEquals(accountId, listConsoleSessionsCmdSpy.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntityOwnerIdTestReturnAccountIdWhenNoConsoleSessionIdIsProvided() {
|
||||
long accountId = 2L;
|
||||
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getId()).thenReturn(null);
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getAccountId()).thenReturn(accountId);
|
||||
|
||||
Assert.assertEquals(accountId, listConsoleSessionsCmdSpy.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntityOwnerIdTestReturnUserIdWhenNoConsoleSessionIdAndAccountIdAreProvided() {
|
||||
UserAccount userAccountMock = Mockito.mock(UserAccount.class);
|
||||
long userId = 2L;
|
||||
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getId()).thenReturn(null);
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getAccountId()).thenReturn(null);
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getUserId()).thenReturn(userId);
|
||||
Mockito.when(accountServiceMock.getUserAccountById(userId)).thenReturn(userAccountMock);
|
||||
Mockito.when(userAccountMock.getAccountId()).thenReturn(userId);
|
||||
|
||||
Assert.assertEquals(userId, listConsoleSessionsCmdSpy.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntityOwnerIdTestReturnSystemAccountIdWhenNoConsoleSessionIdAndAccountIdAndUserIdAreProvided() {
|
||||
long systemAccountId = 1L;
|
||||
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getId()).thenReturn(null);
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getAccountId()).thenReturn(null);
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getUserId()).thenReturn(null);
|
||||
|
||||
Assert.assertEquals(systemAccountId, listConsoleSessionsCmdSpy.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntityOwnerIdTestReturnSystemAccountIdWhenConsoleSessionDoesNotExist() {
|
||||
long consoleSessionId = 2L;
|
||||
long systemAccountId = 1L;
|
||||
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getId()).thenReturn(consoleSessionId);
|
||||
Mockito.when(consoleAccessManagerMock.listConsoleSessionById(consoleSessionId)).thenReturn(null);
|
||||
|
||||
Assert.assertEquals(systemAccountId, listConsoleSessionsCmdSpy.getEntityOwnerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntityOwnerIdTestReturnSystemAccountIdWhenUserAccountDoesNotExist() {
|
||||
long userId = 2L;
|
||||
long systemAccountId = 1L;
|
||||
|
||||
Mockito.when(listConsoleSessionsCmdSpy.getUserId()).thenReturn(userId);
|
||||
Mockito.when(accountServiceMock.getUserAccountById(userId)).thenReturn(null);
|
||||
|
||||
Assert.assertEquals(systemAccountId, listConsoleSessionsCmdSpy.getEntityOwnerId());
|
||||
}
|
||||
}
|
||||
|
|
@ -87,7 +87,12 @@ public class CopySnapshotCmdTest {
|
|||
|
||||
@Test (expected = ServerApiException.class)
|
||||
public void testExecuteWrongNoParams() {
|
||||
UUIDManager uuidManager = Mockito.mock(UUIDManager.class);
|
||||
SnapshotApiService snapshotApiService = Mockito.mock(SnapshotApiService.class);
|
||||
final CopySnapshotCmd cmd = new CopySnapshotCmd();
|
||||
cmd._uuidMgr = uuidManager;
|
||||
cmd._snapshotService = snapshotApiService;
|
||||
|
||||
try {
|
||||
cmd.execute();
|
||||
} catch (ResourceUnavailableException e) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,483 @@
|
|||
// 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.user.vm;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiConstants.BootMode;
|
||||
import org.apache.cloudstack.api.ApiConstants.BootType;
|
||||
import org.apache.cloudstack.api.ApiConstants.IoDriverPolicy;
|
||||
import org.apache.cloudstack.vm.lease.VMLeaseManager;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.network.NetworkService;
|
||||
import com.cloud.utils.db.EntityManager;
|
||||
import com.cloud.vm.VmDetailConstants;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.network.Network.IpAddresses;
|
||||
import com.cloud.vm.VmDiskInfo;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DeployVMCmdTest {
|
||||
|
||||
@Spy
|
||||
private DeployVMCmd cmd = new DeployVMCmd();
|
||||
|
||||
@Test
|
||||
public void testGetBootType_ValidUEFI() {
|
||||
ReflectionTestUtils.setField(cmd, "bootType", "UEFI");
|
||||
|
||||
BootType result = cmd.getBootType();
|
||||
|
||||
assertEquals(BootType.UEFI, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBootTypeValidBIOS() {
|
||||
ReflectionTestUtils.setField(cmd, "bootType", "BIOS");
|
||||
|
||||
BootType result = cmd.getBootType();
|
||||
|
||||
assertEquals(BootType.BIOS, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBootTypeInvalidValue() {
|
||||
ReflectionTestUtils.setField(cmd, "bootType", "INVALID");
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getBootType();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("Invalid bootType INVALID"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBootTypeNullValue() {
|
||||
ReflectionTestUtils.setField(cmd, "bootType", null);
|
||||
|
||||
BootType result = cmd.getBootType();
|
||||
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBootModeValidSecure() {
|
||||
ReflectionTestUtils.setField(cmd, "bootMode", "SECURE");
|
||||
ReflectionTestUtils.setField(cmd, "bootType", "UEFI");
|
||||
|
||||
BootMode result = cmd.getBootMode();
|
||||
|
||||
assertEquals(BootMode.SECURE, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBootModeValidLegacy() {
|
||||
ReflectionTestUtils.setField(cmd, "bootMode", "LEGACY");
|
||||
ReflectionTestUtils.setField(cmd, "bootType", "UEFI");
|
||||
|
||||
BootMode result = cmd.getBootMode();
|
||||
|
||||
assertEquals(BootMode.LEGACY, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBootModeInvalidValue() {
|
||||
ReflectionTestUtils.setField(cmd, "bootMode", "INVALID");
|
||||
ReflectionTestUtils.setField(cmd, "bootType", "UEFI");
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getBootMode();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("Invalid bootmode: INVALID specified for VM: null. Valid values are: [LEGACY, SECURE]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBootModeUEFIWithoutBootMode() {
|
||||
ReflectionTestUtils.setField(cmd, "bootMode", null);
|
||||
ReflectionTestUtils.setField(cmd, "bootType", "UEFI");
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getBootMode();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("bootmode must be specified for the VM with boot type: UEFI. Valid values are: [LEGACY, SECURE]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDetails() {
|
||||
ReflectionTestUtils.setField(cmd, "bootType", "UEFI");
|
||||
ReflectionTestUtils.setField(cmd, "bootMode", "SECURE");
|
||||
ReflectionTestUtils.setField(cmd, "rootdisksize", 100L);
|
||||
ReflectionTestUtils.setField(cmd, "ioDriverPolicy", "native");
|
||||
ReflectionTestUtils.setField(cmd, "iothreadsEnabled", true);
|
||||
ReflectionTestUtils.setField(cmd, "nicMultiqueueNumber", null);
|
||||
ReflectionTestUtils.setField(cmd, "nicPackedVirtQueues", null);
|
||||
ReflectionTestUtils.setField(cmd, "details", new HashMap<>());
|
||||
|
||||
Map<String, String> result = cmd.getDetails();
|
||||
|
||||
assertEquals("SECURE", result.get("UEFI"));
|
||||
assertEquals("100", result.get(VmDetailConstants.ROOT_DISK_SIZE));
|
||||
assertEquals("native", result.get(VmDetailConstants.IO_POLICY));
|
||||
assertEquals("true", result.get(VmDetailConstants.IOTHREADS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLeaseExpiryActionValidStop() {
|
||||
ReflectionTestUtils.setField(cmd, "leaseExpiryAction", "STOP");
|
||||
|
||||
VMLeaseManager.ExpiryAction result = cmd.getLeaseExpiryAction();
|
||||
|
||||
assertEquals(VMLeaseManager.ExpiryAction.STOP, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLeaseExpiryActionValidDestroy() {
|
||||
ReflectionTestUtils.setField(cmd, "leaseExpiryAction", "DESTROY");
|
||||
|
||||
VMLeaseManager.ExpiryAction result = cmd.getLeaseExpiryAction();
|
||||
|
||||
assertEquals(VMLeaseManager.ExpiryAction.DESTROY, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLeaseExpiryActionInvalidValue() {
|
||||
ReflectionTestUtils.setField(cmd, "leaseExpiryAction", "INVALID");
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getLeaseExpiryAction();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("Invalid value configured for leaseexpiryaction"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLeaseExpiryActionNullValue() {
|
||||
ReflectionTestUtils.setField(cmd, "leaseExpiryAction", null);
|
||||
|
||||
VMLeaseManager.ExpiryAction result = cmd.getLeaseExpiryAction();
|
||||
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIoDriverPolicyValidThrottle() {
|
||||
ReflectionTestUtils.setField(cmd, "ioDriverPolicy", "native");
|
||||
|
||||
IoDriverPolicy result = cmd.getIoDriverPolicy();
|
||||
|
||||
assertEquals(IoDriverPolicy.valueOf("NATIVE"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIoDriverPolicyInvalidValue() {
|
||||
ReflectionTestUtils.setField(cmd, "ioDriverPolicy", "INVALID");
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getIoDriverPolicy();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("Invalid io policy INVALID"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNetworkIds() {
|
||||
List<Long> networkIds = Arrays.asList(1L, 2L, 3L);
|
||||
ReflectionTestUtils.setField(cmd, "networkIds", networkIds);
|
||||
ReflectionTestUtils.setField(cmd, "vAppNetworks", null);
|
||||
ReflectionTestUtils.setField(cmd, "ipToNetworkList", null);
|
||||
|
||||
List<Long> result = cmd.getNetworkIds();
|
||||
|
||||
assertEquals(networkIds, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNetworkIdsVAppNetworks() {
|
||||
Map<String, Object> vAppNetworks = new HashMap<>();
|
||||
vAppNetworks.put("network1", new HashMap<String, String>());
|
||||
ReflectionTestUtils.setField(cmd, "vAppNetworks", vAppNetworks);
|
||||
ReflectionTestUtils.setField(cmd, "networkIds", null);
|
||||
ReflectionTestUtils.setField(cmd, "ipToNetworkList", null);
|
||||
ReflectionTestUtils.setField(cmd, "ipAddress", null);
|
||||
ReflectionTestUtils.setField(cmd, "ip6Address", null);
|
||||
|
||||
List<Long> result = cmd.getNetworkIds();
|
||||
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNetworkIdsVAppNetworksAndNetworkIds() {
|
||||
Map<String, Object> vAppNetworks = new HashMap<>();
|
||||
vAppNetworks.put("network1", new HashMap<String, String>());
|
||||
ReflectionTestUtils.setField(cmd, "vAppNetworks", vAppNetworks);
|
||||
ReflectionTestUtils.setField(cmd, "networkIds", Arrays.asList(1L, 2L));
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getNetworkIds();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("nicnetworklist can't be specified along with networkids"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNetworkIdsIpToNetworkListAndNetworkIds() {
|
||||
Map<String, Object> ipToNetworkList = new HashMap<>();
|
||||
ipToNetworkList.put("0", new HashMap<String, String>());
|
||||
ReflectionTestUtils.setField(cmd, "ipToNetworkList", ipToNetworkList);
|
||||
ReflectionTestUtils.setField(cmd, "networkIds", Arrays.asList(1L, 2L));
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getNetworkIds();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("ipToNetworkMap can't be specified along with networkIds or ipAddress"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpToNetworkMap_WithNetworkIds() {
|
||||
ReflectionTestUtils.setField(cmd, "networkIds", Arrays.asList(1L, 2L));
|
||||
ReflectionTestUtils.setField(cmd, "ipToNetworkList", new HashMap<>());
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getIpToNetworkMap();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("NetworkIds and ipAddress can't be specified along with ipToNetworkMap parameter"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpToNetworkMap_WithIpAddress() {
|
||||
ReflectionTestUtils.setField(cmd, "ipAddress", "192.168.1.1");
|
||||
ReflectionTestUtils.setField(cmd, "ipToNetworkList", new HashMap<>());
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getIpToNetworkMap();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("NetworkIds and ipAddress can't be specified along with ipToNetworkMap parameter"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpToNetworkMap_WithEmptyIpToNetworkList() {
|
||||
ReflectionTestUtils.setField(cmd, "networkIds", null);
|
||||
ReflectionTestUtils.setField(cmd, "ipAddress", null);
|
||||
ReflectionTestUtils.setField(cmd, "ipToNetworkList", new HashMap<>());
|
||||
|
||||
Map<Long, IpAddresses> result = cmd.getIpToNetworkMap();
|
||||
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpToNetworkMap_WithNullIpToNetworkList() {
|
||||
ReflectionTestUtils.setField(cmd, "networkIds", null);
|
||||
ReflectionTestUtils.setField(cmd, "ipAddress", null);
|
||||
ReflectionTestUtils.setField(cmd, "ipToNetworkList", null);
|
||||
|
||||
Map<Long, IpAddresses> result = cmd.getIpToNetworkMap();
|
||||
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDataDiskInfoList() {
|
||||
Map<String, Object> dataDisksDetails = new HashMap<>();
|
||||
Map<String, String> dataDisk = new HashMap<>();
|
||||
dataDisk.put(ApiConstants.DISK_OFFERING_ID, "offering-uuid");
|
||||
dataDisk.put(ApiConstants.DEVICE_ID, "0");
|
||||
dataDisk.put(ApiConstants.MIN_IOPS, "1000");
|
||||
dataDisk.put(ApiConstants.MAX_IOPS, "2000");
|
||||
dataDisksDetails.put("0", dataDisk);
|
||||
|
||||
ReflectionTestUtils.setField(cmd, "dataDisksDetails", dataDisksDetails);
|
||||
|
||||
EntityManager entityMgr = mock(EntityManager.class);
|
||||
ReflectionTestUtils.setField(cmd, "_entityMgr", entityMgr);
|
||||
DiskOffering diskOffering = mock(DiskOffering.class);
|
||||
when(diskOffering.getDiskSize()).thenReturn(1024 * 1024 * 1024L);
|
||||
when(diskOffering.isCustomizedIops()).thenReturn(true);
|
||||
when(entityMgr.findByUuid(DiskOffering.class, "offering-uuid")).thenReturn(diskOffering);
|
||||
|
||||
List<VmDiskInfo> result = cmd.getDataDiskInfoList();
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(diskOffering, result.get(0).getDiskOffering());
|
||||
assertEquals(1L, result.get(0).getSize().longValue());
|
||||
assertEquals(1000L, result.get(0).getMinIops().longValue());
|
||||
assertEquals(2000L, result.get(0).getMaxIops().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpAddressesFromIpMap() {
|
||||
Map<String, Object> ipToNetworkList = new HashMap<>();
|
||||
Map<String, String> ipMap = new HashMap<>();
|
||||
ipMap.put("ip", "192.168.1.100");
|
||||
ipMap.put("mac", "00:11:22:33:44:55");
|
||||
ipMap.put("networkid", "1");
|
||||
ipToNetworkList.put("0", ipMap);
|
||||
|
||||
ReflectionTestUtils.setField(cmd, "ipToNetworkList", ipToNetworkList);
|
||||
ReflectionTestUtils.setField(cmd, "networkIds", null);
|
||||
ReflectionTestUtils.setField(cmd, "ipAddress", null);
|
||||
|
||||
Network mockNetwork = mock(Network.class);
|
||||
NetworkService networkServiceMock = mock(NetworkService.class);
|
||||
ReflectionTestUtils.setField(cmd, "_networkService", networkServiceMock);
|
||||
|
||||
Map<Long, IpAddresses> result = cmd.getIpToNetworkMap();
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.containsKey(1L));
|
||||
assertEquals(result.get(1L).getIp4Address(), "192.168.1.100");
|
||||
assertEquals(result.get(1L).getMacAddress(), "00:11:22:33:44:55");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIpAddressesFromIpMapInvalidMac() {
|
||||
Map<String, Object> ipToNetworkList = new HashMap<>();
|
||||
Map<String, String> ipMap = new HashMap<>();
|
||||
ipMap.put("ip", "192.168.1.100");
|
||||
ipMap.put("mac", "invalid-mac");
|
||||
ipMap.put("networkid", "1");
|
||||
ipToNetworkList.put("0", ipMap);
|
||||
|
||||
ReflectionTestUtils.setField(cmd, "ipToNetworkList", ipToNetworkList);
|
||||
ReflectionTestUtils.setField(cmd, "networkIds", null);
|
||||
ReflectionTestUtils.setField(cmd, "ipAddress", null);
|
||||
|
||||
Network mockNetwork = mock(Network.class);
|
||||
NetworkService networkServiceMock = mock(NetworkService.class);
|
||||
ReflectionTestUtils.setField(cmd, "_networkService", networkServiceMock);
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getIpToNetworkMap();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("Mac address is not valid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDhcpOptionsMap() {
|
||||
Map<String, Object> dhcpOptionsNetworkList = new HashMap<>();
|
||||
Map<String, String> dhcpOptions = new HashMap<>();
|
||||
dhcpOptions.put("networkid", "network-1");
|
||||
dhcpOptions.put("dhcp:114", "url-value");
|
||||
dhcpOptions.put("dhcp:66", "www.test.com");
|
||||
dhcpOptionsNetworkList.put("0", dhcpOptions);
|
||||
|
||||
ReflectionTestUtils.setField(cmd, "dhcpOptionsNetworkList", dhcpOptionsNetworkList);
|
||||
|
||||
Map<String, Map<Integer, String>> result = cmd.getDhcpOptionsMap();
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.containsKey("network-1"));
|
||||
Map<Integer, String> networkOptions = result.get("network-1");
|
||||
assertEquals("url-value", networkOptions.get(114));
|
||||
assertEquals("www.test.com", networkOptions.get(66));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDhcpOptionsMap_WithMissingNetworkId() {
|
||||
Map<String, Object> dhcpOptionsNetworkList = new HashMap<>();
|
||||
Map<String, String> dhcpOptions = new HashMap<>();
|
||||
dhcpOptions.put("dhcp:114", "url-value");
|
||||
dhcpOptionsNetworkList.put("0", dhcpOptions);
|
||||
|
||||
ReflectionTestUtils.setField(cmd, "dhcpOptionsNetworkList", dhcpOptionsNetworkList);
|
||||
|
||||
IllegalArgumentException thrownException = assertThrows(IllegalArgumentException.class, () -> {
|
||||
cmd.getDhcpOptionsMap();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("No networkid specified when providing extra dhcp options"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDataDiskTemplateToDiskOfferingMap() {
|
||||
ReflectionTestUtils.setField(cmd, "diskOfferingId", null);
|
||||
|
||||
Map<String, Object> dataDiskTemplateToDiskOfferingList = new HashMap<>();
|
||||
Map<String, String> dataDiskTemplate = new HashMap<>();
|
||||
dataDiskTemplate.put("datadisktemplateid", "template-uuid");
|
||||
dataDiskTemplate.put("diskofferingid", "offering-uuid");
|
||||
dataDiskTemplateToDiskOfferingList.put("0", dataDiskTemplate);
|
||||
|
||||
ReflectionTestUtils.setField(cmd, "dataDiskTemplateToDiskOfferingList", dataDiskTemplateToDiskOfferingList);
|
||||
|
||||
VirtualMachineTemplate mockTemplate = mock(VirtualMachineTemplate.class);
|
||||
when(mockTemplate.getId()).thenReturn(1L);
|
||||
|
||||
DiskOffering mockOffering = mock(DiskOffering.class);
|
||||
|
||||
EntityManager entityMgr = mock(EntityManager.class);
|
||||
ReflectionTestUtils.setField(cmd, "_entityMgr", entityMgr);
|
||||
when(entityMgr.findByUuid(VirtualMachineTemplate.class, "template-uuid")).thenReturn(mockTemplate);
|
||||
when(entityMgr.findByUuid(DiskOffering.class, "offering-uuid")).thenReturn(mockOffering);
|
||||
|
||||
Map<Long, DiskOffering> result = cmd.getDataDiskTemplateToDiskOfferingMap();
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(mockOffering, result.get(1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDataDiskTemplateToDiskOfferingMapWithDiskOfferingId() {
|
||||
ReflectionTestUtils.setField(cmd, "diskOfferingId", 1L);
|
||||
ReflectionTestUtils.setField(cmd, "dataDiskTemplateToDiskOfferingList", new HashMap<>());
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getDataDiskTemplateToDiskOfferingMap();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("diskofferingid parameter can't be specified along with datadisktemplatetodiskofferinglist parameter"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDataDiskTemplateToDiskOfferingMapInvalidTemplateId() {
|
||||
ReflectionTestUtils.setField(cmd, "diskOfferingId", null);
|
||||
|
||||
Map<String, Object> dataDiskTemplateToDiskOfferingList = new HashMap<>();
|
||||
Map<String, String> dataDiskTemplate = new HashMap<>();
|
||||
dataDiskTemplate.put("datadisktemplateid", "invalid-template");
|
||||
dataDiskTemplate.put("diskofferingid", "offering-uuid");
|
||||
dataDiskTemplateToDiskOfferingList.put("0", dataDiskTemplate);
|
||||
|
||||
ReflectionTestUtils.setField(cmd, "dataDiskTemplateToDiskOfferingList", dataDiskTemplateToDiskOfferingList);
|
||||
|
||||
EntityManager entityMgr = mock(EntityManager.class);
|
||||
ReflectionTestUtils.setField(cmd, "_entityMgr", entityMgr);
|
||||
when(entityMgr.findByUuid(VirtualMachineTemplate.class, "invalid-template")).thenReturn(null);
|
||||
when(entityMgr.findById(VirtualMachineTemplate.class, "invalid-template")).thenReturn(null);
|
||||
|
||||
InvalidParameterValueException thrownException = assertThrows(InvalidParameterValueException.class, () -> {
|
||||
cmd.getDataDiskTemplateToDiskOfferingMap();
|
||||
});
|
||||
assertTrue(thrownException.getMessage().contains("Unable to translate and find entity with datadisktemplateid"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
//
|
||||
// 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;
|
||||
|
||||
import com.cloud.utils.StringUtils;
|
||||
import org.eclipse.jetty.server.NCSARequestLog;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
import org.eclipse.jetty.util.DateCache;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static org.apache.commons.configuration.DataConfiguration.DEFAULT_DATE_FORMAT;
|
||||
|
||||
public class ACSRequestLog extends NCSARequestLog {
|
||||
private static final ThreadLocal<StringBuilder> buffers =
|
||||
ThreadLocal.withInitial(() -> new StringBuilder(256));
|
||||
|
||||
private final DateCache dateCache;
|
||||
|
||||
public ACSRequestLog() {
|
||||
super();
|
||||
|
||||
TimeZone timeZone = TimeZone.getTimeZone("GMT");
|
||||
Locale locale = Locale.getDefault();
|
||||
dateCache = new DateCache(DEFAULT_DATE_FORMAT, locale, timeZone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Request request, Response response) {
|
||||
String requestURI = StringUtils.cleanString(request.getOriginalURI());
|
||||
try {
|
||||
StringBuilder sb = buffers.get();
|
||||
sb.setLength(0);
|
||||
|
||||
sb.append(request.getHttpChannel().getEndPoint()
|
||||
.getRemoteAddress().getAddress()
|
||||
.getHostAddress())
|
||||
.append(" - - [")
|
||||
.append(dateCache.format(request.getTimeStamp()))
|
||||
.append("] \"")
|
||||
.append(request.getMethod())
|
||||
.append(" ")
|
||||
.append(requestURI)
|
||||
.append(" ")
|
||||
.append(request.getProtocol())
|
||||
.append("\" ")
|
||||
.append(response.getStatus())
|
||||
.append(" ")
|
||||
.append(response.getHttpChannel().getBytesWritten()) // apply filter here?
|
||||
.append(" \"-\" \"")
|
||||
.append(request.getHeader("User-Agent"))
|
||||
.append("\"");
|
||||
|
||||
write(sb.toString());
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Unable to log request", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stop(LifeCycle lifeCycle) throws Exception {
|
||||
buffers.remove();
|
||||
super.stop(lifeCycle);
|
||||
}
|
||||
}
|
||||
|
|
@ -24,15 +24,17 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.cloud.api.ApiServer;
|
||||
import org.apache.commons.daemon.Daemon;
|
||||
import org.apache.commons.daemon.DaemonContext;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.jetty.jmx.MBeanContainer;
|
||||
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.NCSARequestLog;
|
||||
import org.eclipse.jetty.server.RequestLog;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
|
@ -185,6 +187,7 @@ public class ServerDaemon implements Daemon {
|
|||
httpConfig.setResponseHeaderSize(8192);
|
||||
httpConfig.setSendServerVersion(false);
|
||||
httpConfig.setSendDateHeader(false);
|
||||
addForwardingCustomiser(httpConfig);
|
||||
|
||||
// HTTP Connector
|
||||
createHttpConnector(httpConfig);
|
||||
|
|
@ -207,6 +210,21 @@ public class ServerDaemon implements Daemon {
|
|||
server.join();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a ForwardedRequestCustomizer to the HTTP configuration to handle forwarded headers.
|
||||
* The header used for forwarding is determined by the ApiServer.listOfForwardHeaders property.
|
||||
* Only non empty headers are considered and only the first of the comma-separated list is used.
|
||||
* @param httpConfig the HTTP configuration to which the customizer will be added
|
||||
*/
|
||||
private static void addForwardingCustomiser(HttpConfiguration httpConfig) {
|
||||
ForwardedRequestCustomizer customiser = new ForwardedRequestCustomizer();
|
||||
String header = Arrays.stream(ApiServer.listOfForwardHeaders.value().split(",")).findFirst().orElse(null);
|
||||
if (com.cloud.utils.StringUtils.isNotEmpty(header)) {
|
||||
customiser.setForwardedForHeader(header);
|
||||
}
|
||||
httpConfig.addCustomizer(customiser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws Exception {
|
||||
server.stop();
|
||||
|
|
@ -299,7 +317,7 @@ public class ServerDaemon implements Daemon {
|
|||
}
|
||||
|
||||
private RequestLog createRequestLog() {
|
||||
final NCSARequestLog log = new NCSARequestLog();
|
||||
final ACSRequestLog log = new ACSRequestLog();
|
||||
final File logPath = new File(accessLogFile);
|
||||
final File parentFile = logPath.getParentFile();
|
||||
if (parentFile != null) {
|
||||
|
|
|
|||
|
|
@ -26,10 +26,6 @@ import java.util.List;
|
|||
public class ReadyCommand extends Command {
|
||||
private String _details;
|
||||
|
||||
public ReadyCommand() {
|
||||
super();
|
||||
}
|
||||
|
||||
private Long dcId;
|
||||
private Long hostId;
|
||||
private String hostUuid;
|
||||
|
|
@ -41,6 +37,10 @@ public class ReadyCommand extends Command {
|
|||
private Boolean enableHumanReadableSizes;
|
||||
private String arch;
|
||||
|
||||
public ReadyCommand() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ReadyCommand(Long dcId) {
|
||||
super();
|
||||
this.dcId = dcId;
|
||||
|
|
@ -95,7 +95,7 @@ public class ReadyCommand extends Command {
|
|||
return avoidMsHostList;
|
||||
}
|
||||
|
||||
public void setAvoidMsHostList(List<String> msHostList) {
|
||||
public void setAvoidMsHostList(List<String> avoidMsHostList) {
|
||||
this.avoidMsHostList = avoidMsHostList;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ public class BackupAnswer extends Answer {
|
|||
private Long size;
|
||||
private Long virtualSize;
|
||||
private Map<String, String> volumes;
|
||||
Boolean needsCleanup;
|
||||
|
||||
public BackupAnswer(final Command command, final boolean success, final String details) {
|
||||
super(command, success, details);
|
||||
|
|
@ -56,4 +57,15 @@ public class BackupAnswer extends Answer {
|
|||
public void setVolumes(Map<String, String> volumes) {
|
||||
this.volumes = volumes;
|
||||
}
|
||||
|
||||
public Boolean getNeedsCleanup() {
|
||||
if (needsCleanup == null) {
|
||||
return false;
|
||||
}
|
||||
return needsCleanup;
|
||||
}
|
||||
|
||||
public void setNeedsCleanup(Boolean needsCleanup) {
|
||||
this.needsCleanup = needsCleanup;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// 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.backup;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public class BackupStorageStatsAnswer extends Answer {
|
||||
private Long totalSize;
|
||||
private Long usedSize;
|
||||
|
||||
public BackupStorageStatsAnswer(final Command command, final boolean success, final String details) {
|
||||
super(command, success, details);
|
||||
this.totalSize = 0L;
|
||||
this.usedSize = 0L;
|
||||
}
|
||||
|
||||
public Long getTotalSize() {
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
public void setTotalSize(Long totalSize) {
|
||||
this.totalSize = totalSize;
|
||||
}
|
||||
|
||||
public Long getUsedSize() {
|
||||
return usedSize;
|
||||
}
|
||||
|
||||
public void setUsedSize(Long usedSize) {
|
||||
this.usedSize = usedSize;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// 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.backup;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.LogLevel;
|
||||
|
||||
public class GetBackupStorageStatsCommand extends Command {
|
||||
private String backupRepoType;
|
||||
private String backupRepoAddress;
|
||||
@LogLevel(LogLevel.Log4jLevel.Off)
|
||||
private String mountOptions;
|
||||
|
||||
public GetBackupStorageStatsCommand(String backupRepoType, String backupRepoAddress, String mountOptions) {
|
||||
super();
|
||||
this.backupRepoType = backupRepoType;
|
||||
this.backupRepoAddress = backupRepoAddress;
|
||||
this.mountOptions = mountOptions;
|
||||
}
|
||||
|
||||
public String getBackupRepoType() {
|
||||
return backupRepoType;
|
||||
}
|
||||
|
||||
public void setBackupRepoType(String backupRepoType) {
|
||||
this.backupRepoType = backupRepoType;
|
||||
}
|
||||
|
||||
public String getBackupRepoAddress() {
|
||||
return backupRepoAddress;
|
||||
}
|
||||
|
||||
public void setBackupRepoAddress(String backupRepoAddress) {
|
||||
this.backupRepoAddress = backupRepoAddress;
|
||||
}
|
||||
|
||||
public String getMountOptions() {
|
||||
return mountOptions == null ? "" : mountOptions;
|
||||
}
|
||||
|
||||
public void setMountOptions(String mountOptions) {
|
||||
this.mountOptions = mountOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -30,7 +30,8 @@ public class RestoreBackupCommand extends Command {
|
|||
private String backupPath;
|
||||
private String backupRepoType;
|
||||
private String backupRepoAddress;
|
||||
private List<String> volumePaths;
|
||||
private List<String> backupVolumesUUIDs;
|
||||
private List<String> restoreVolumePaths;
|
||||
private String diskType;
|
||||
private Boolean vmExists;
|
||||
private String restoreVolumeUUID;
|
||||
|
|
@ -72,12 +73,12 @@ public class RestoreBackupCommand extends Command {
|
|||
this.backupRepoAddress = backupRepoAddress;
|
||||
}
|
||||
|
||||
public List<String> getVolumePaths() {
|
||||
return volumePaths;
|
||||
public List<String> getRestoreVolumePaths() {
|
||||
return restoreVolumePaths;
|
||||
}
|
||||
|
||||
public void setVolumePaths(List<String> volumePaths) {
|
||||
this.volumePaths = volumePaths;
|
||||
public void setRestoreVolumePaths(List<String> restoreVolumePaths) {
|
||||
this.restoreVolumePaths = restoreVolumePaths;
|
||||
}
|
||||
|
||||
public Boolean isVmExists() {
|
||||
|
|
@ -127,4 +128,12 @@ public class RestoreBackupCommand extends Command {
|
|||
public boolean executeInSequence() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<String> getBackupVolumesUUIDs() {
|
||||
return backupVolumesUUIDs;
|
||||
}
|
||||
|
||||
public void setBackupVolumesUUIDs(List<String> backupVolumesUUIDs) {
|
||||
this.backupVolumesUUIDs = backupVolumesUUIDs;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public class TakeBackupCommand extends Command {
|
|||
private String backupRepoType;
|
||||
private String backupRepoAddress;
|
||||
private List<String> volumePaths;
|
||||
private Boolean quiesce;
|
||||
@LogLevel(LogLevel.Log4jLevel.Off)
|
||||
private String mountOptions;
|
||||
|
||||
|
|
@ -87,6 +88,14 @@ public class TakeBackupCommand extends Command {
|
|||
this.volumePaths = volumePaths;
|
||||
}
|
||||
|
||||
public Boolean getQuiesce() {
|
||||
return quiesce;
|
||||
}
|
||||
|
||||
public void setQuiesce(Boolean quiesce) {
|
||||
this.quiesce = quiesce;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ public interface VirtualMachineManager extends Manager {
|
|||
* @param defaultNetwork The default network for the VM.
|
||||
* @param rootDiskOffering For created VMs not based on templates, root disk offering specifies the root disk.
|
||||
* @param dataDiskOfferings Data disks to attach to the VM.
|
||||
* @param dataDiskDeviceIds Device Ids to assign the data disks to.
|
||||
* @param auxiliaryNetworks additional networks to attach the VMs to.
|
||||
* @param plan How to deploy the VM.
|
||||
* @param hyperType Hypervisor type
|
||||
|
|
@ -131,7 +132,7 @@ public interface VirtualMachineManager extends Manager {
|
|||
* @throws InsufficientCapacityException If there are insufficient capacity to deploy this vm.
|
||||
*/
|
||||
void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering, DiskOfferingInfo rootDiskOfferingInfo,
|
||||
List<DiskOfferingInfo> dataDiskOfferings, LinkedHashMap<? extends Network, List<? extends NicProfile>> auxiliaryNetworks, DeploymentPlan plan,
|
||||
List<DiskOfferingInfo> dataDiskOfferings, List<Long> dataDiskDeviceIds, LinkedHashMap<? extends Network, List<? extends NicProfile>> auxiliaryNetworks, DeploymentPlan plan,
|
||||
HypervisorType hyperType, Map<String, Map<Integer, String>> extraDhcpOptions, Map<Long, DiskOffering> datadiskTemplateToDiskOfferingMap, Volume volume, Snapshot snapshot) throws InsufficientCapacityException;
|
||||
|
||||
void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import com.cloud.exception.InsufficientCapacityException;
|
|||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.VmDiskInfo;
|
||||
|
||||
@Path("orchestration")
|
||||
@Produces({"application/json", "application/xml"})
|
||||
|
|
@ -69,15 +70,17 @@ public interface OrchestrationService {
|
|||
@QueryParam("compute-tags") List<String> computeTags, @QueryParam("root-disk-tags") List<String> rootDiskTags,
|
||||
@QueryParam("network-nic-map") Map<String, List<NicProfile>> networkNicMap, @QueryParam("deploymentplan") DeploymentPlan plan,
|
||||
@QueryParam("root-disk-size") Long rootDiskSize, @QueryParam("extra-dhcp-option-map") Map<String, Map<Integer, String>> extraDhcpOptionMap,
|
||||
@QueryParam("datadisktemplate-diskoffering-map") Map<Long, DiskOffering> datadiskTemplateToDiskOfferingMap, @QueryParam("disk-offering-id") Long diskOfferingId, @QueryParam("root-disk-offering-id") Long rootDiskOfferingId, Volume volume, Snapshot snapshot) throws InsufficientCapacityException;
|
||||
@QueryParam("datadisktemplate-diskoffering-map") Map<Long, DiskOffering> datadiskTemplateToDiskOfferingMap, @QueryParam("disk-offering-id") Long diskOfferingId,
|
||||
@QueryParam("root-disk-offering-id") Long rootDiskOfferingId, List<VmDiskInfo> dataDiskInfoList, Volume volume, Snapshot snapshot) throws InsufficientCapacityException;
|
||||
|
||||
@POST
|
||||
VirtualMachineEntity createVirtualMachineFromScratch(@QueryParam("id") String id, @QueryParam("owner") String owner, @QueryParam("iso-id") String isoId,
|
||||
@QueryParam("host-name") String hostName, @QueryParam("display-name") String displayName, @QueryParam("hypervisor") String hypervisor,
|
||||
@QueryParam("os") String os, @QueryParam("cpu") int cpu, @QueryParam("speed") int speed, @QueryParam("ram") long memory, @QueryParam("disk-size") Long diskSize,
|
||||
@QueryParam("compute-tags") List<String> computeTags, @QueryParam("root-disk-tags") List<String> rootDiskTags,
|
||||
@QueryParam("network-nic-map") Map<String, List<NicProfile>> networkNicMap, @QueryParam("deploymentplan") DeploymentPlan plan,
|
||||
@QueryParam("extra-dhcp-option-map") Map<String, Map<Integer, String>> extraDhcpOptionMap, @QueryParam("disk-offering-id") Long diskOfferingId, Volume volume, Snapshot snapshot) throws InsufficientCapacityException;
|
||||
@QueryParam("host-name") String hostName, @QueryParam("display-name") String displayName, @QueryParam("hypervisor") String hypervisor,
|
||||
@QueryParam("os") String os, @QueryParam("cpu") int cpu, @QueryParam("speed") int speed, @QueryParam("ram") long memory, @QueryParam("disk-size") Long diskSize,
|
||||
@QueryParam("compute-tags") List<String> computeTags, @QueryParam("root-disk-tags") List<String> rootDiskTags,
|
||||
@QueryParam("network-nic-map") Map<String, List<NicProfile>> networkNicMap, @QueryParam("deploymentplan") DeploymentPlan plan,
|
||||
@QueryParam("extra-dhcp-option-map") Map<String, Map<Integer, String>> extraDhcpOptionMap, @QueryParam("disk-offering-id") Long diskOfferingId,
|
||||
@QueryParam("data-disks-offering-info") List<VmDiskInfo> dataDiskInfoList, Volume volume, Snapshot snapshot) throws InsufficientCapacityException;
|
||||
|
||||
@POST
|
||||
NetworkEntity createNetwork(String id, String name, String domainName, String cidr, String gateway);
|
||||
|
|
|
|||
|
|
@ -40,5 +40,13 @@ public enum DataStoreCapabilities {
|
|||
/**
|
||||
* indicates that this driver supports reverting a volume to a snapshot state
|
||||
*/
|
||||
CAN_REVERT_VOLUME_TO_SNAPSHOT
|
||||
CAN_REVERT_VOLUME_TO_SNAPSHOT,
|
||||
/**
|
||||
* indicates that the driver supports copying snapshot between zones on pools of the same type
|
||||
*/
|
||||
CAN_COPY_SNAPSHOT_BETWEEN_ZONES_AND_SAME_POOL_TYPE,
|
||||
/**
|
||||
* indicates that this driver supports the option to create a template from the back-end snapshot
|
||||
*/
|
||||
CAN_CREATE_TEMPLATE_FROM_SNAPSHOT
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,4 +46,6 @@ public interface SnapshotService {
|
|||
AsyncCallFuture<SnapshotResult> copySnapshot(SnapshotInfo snapshot, String copyUrl, DataStore dataStore) throws ResourceUnavailableException;
|
||||
|
||||
AsyncCallFuture<CreateCmdResult> queryCopySnapshot(SnapshotInfo snapshot) throws ResourceUnavailableException;
|
||||
|
||||
AsyncCallFuture<SnapshotResult> copySnapshot(SnapshotInfo sourceSnapshot, SnapshotInfo destSnapshot, SnapshotStrategy strategy);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,12 +16,14 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||
|
||||
|
||||
import com.cloud.storage.Snapshot;
|
||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
|
||||
public interface SnapshotStrategy {
|
||||
|
||||
enum SnapshotOperation {
|
||||
TAKE, BACKUP, DELETE, REVERT
|
||||
TAKE, BACKUP, DELETE, REVERT, COPY
|
||||
}
|
||||
|
||||
SnapshotInfo takeSnapshot(SnapshotInfo snapshot);
|
||||
|
|
@ -35,4 +37,7 @@ public interface SnapshotStrategy {
|
|||
StrategyPriority canHandle(Snapshot snapshot, Long zoneId, SnapshotOperation op);
|
||||
|
||||
void postSnapshotCreation(SnapshotInfo snapshot);
|
||||
|
||||
default void copySnapshot(DataObject snapshotSource, DataObject snapshotDest, AsyncCompletionCallback<CreateCmdResult> caller) {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,6 +220,14 @@ public interface StorageManager extends StorageService {
|
|||
"storage.pool.host.connect.workers", "1",
|
||||
"Number of worker threads to be used to connect hosts to a primary storage", true);
|
||||
|
||||
ConfigKey<Float> ObjectStorageCapacityThreshold = new ConfigKey<>("Alert", Float.class,
|
||||
"objectStorage.capacity.notificationthreshold",
|
||||
"0.75",
|
||||
"Percentage (as a value between 0 and 1) of object storage utilization above which alerts will be sent about low storage available.",
|
||||
true,
|
||||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
|
||||
/**
|
||||
* should we execute in sequence not involving any storages?
|
||||
* @return tru if commands should execute in sequence
|
||||
|
|
@ -415,4 +423,6 @@ public interface StorageManager extends StorageService {
|
|||
Pair<Boolean, String> checkIfReadyVolumeFitsInStoragePoolWithStorageAccessGroups(StoragePool destPool, Volume volume);
|
||||
|
||||
String[] getStorageAccessGroups(Long zoneId, Long podId, Long clusterId, Long hostId);
|
||||
|
||||
CapacityVO getObjectStorageUsedStats(Long zoneId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,12 +30,12 @@ public class VmWorkTakeVolumeSnapshot extends VmWork {
|
|||
private boolean quiesceVm;
|
||||
private Snapshot.LocationType locationType;
|
||||
private boolean asyncBackup;
|
||||
|
||||
private List<Long> poolIds;
|
||||
private List<Long> zoneIds;
|
||||
|
||||
public VmWorkTakeVolumeSnapshot(long userId, long accountId, long vmId, String handlerName,
|
||||
Long volumeId, Long policyId, Long snapshotId, boolean quiesceVm, Snapshot.LocationType locationType,
|
||||
boolean asyncBackup, List<Long> zoneIds) {
|
||||
boolean asyncBackup, List<Long> zoneIds, List<Long> poolIds) {
|
||||
super(userId, accountId, vmId, handlerName);
|
||||
this.volumeId = volumeId;
|
||||
this.policyId = policyId;
|
||||
|
|
@ -44,6 +44,7 @@ public class VmWorkTakeVolumeSnapshot extends VmWork {
|
|||
this.locationType = locationType;
|
||||
this.asyncBackup = asyncBackup;
|
||||
this.zoneIds = zoneIds;
|
||||
this.poolIds = poolIds;
|
||||
}
|
||||
|
||||
public Long getVolumeId() {
|
||||
|
|
@ -71,4 +72,8 @@ public class VmWorkTakeVolumeSnapshot extends VmWork {
|
|||
public List<Long> getZoneIds() {
|
||||
return zoneIds;
|
||||
}
|
||||
|
||||
public List<Long> getPoolIds() {
|
||||
return poolIds;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,8 +26,9 @@ public class VmWorkTakeVolumeSnapshotTest {
|
|||
@Test
|
||||
public void testVmWorkTakeVolumeSnapshotZoneIds() {
|
||||
List<Long> zoneIds = List.of(10L, 20L);
|
||||
List<Long> poolIds = List.of(10L, 20L);
|
||||
VmWorkTakeVolumeSnapshot work = new VmWorkTakeVolumeSnapshot(1L, 1L, 1L, "handler",
|
||||
1L, 1L, 1L, false, null, false, zoneIds);
|
||||
1L, 1L, 1L, false, null, false, zoneIds, poolIds);
|
||||
Assert.assertNotNull(work.getZoneIds());
|
||||
Assert.assertEquals(zoneIds.size(), work.getZoneIds().size());
|
||||
Assert.assertEquals(zoneIds.get(0), work.getZoneIds().get(0));
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import java.util.Date;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
|
@ -758,15 +759,15 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
|
|||
}
|
||||
}
|
||||
|
||||
protected AgentAttache notifyMonitorsOfConnection(final AgentAttache attache, final StartupCommand[] cmd, final boolean forRebalance) throws ConnectionException {
|
||||
protected AgentAttache notifyMonitorsOfConnection(final AgentAttache attache, final StartupCommand[] cmds, final boolean forRebalance) throws ConnectionException {
|
||||
final long hostId = attache.getId();
|
||||
final HostVO host = _hostDao.findById(hostId);
|
||||
for (final Pair<Integer, Listener> monitor : _hostMonitors) {
|
||||
logger.debug("Sending Connect to listener: {}, for rebalance: {}", monitor.second().getClass().getSimpleName(), forRebalance);
|
||||
for (int i = 0; i < cmd.length; i++) {
|
||||
for (StartupCommand cmd : cmds) {
|
||||
try {
|
||||
logger.debug("process connection to issue: {} for host: {}, forRebalance: {}, connection transferred: {}", ReflectionToStringBuilderUtils.reflectCollection(cmd[i]), hostId, forRebalance, cmd[i].isConnectionTransferred());
|
||||
monitor.second().processConnect(host, cmd[i], forRebalance);
|
||||
logger.debug("process connection to issue: {} for host: {}, forRebalance: {}", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(cmd, "id", "type", "msHostList", "connectionTransferred"), hostId, forRebalance);
|
||||
monitor.second().processConnect(host, cmd, forRebalance);
|
||||
} catch (final ConnectionException ce) {
|
||||
if (ce.isSetupError()) {
|
||||
logger.warn("Monitor {} says there is an error in the connect process for {} due to {}", monitor.second().getClass().getSimpleName(), hostId, ce.getMessage());
|
||||
|
|
@ -1040,39 +1041,50 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
|
|||
|
||||
protected boolean handleDisconnectWithoutInvestigation(final AgentAttache attache, final Status.Event event, final boolean transitState, final boolean removeAgent) {
|
||||
final long hostId = attache.getId();
|
||||
|
||||
final HostVO host = _hostDao.findById(hostId);
|
||||
boolean result = false;
|
||||
GlobalLock joinLock = getHostJoinLock(hostId);
|
||||
if (joinLock.lock(60)) {
|
||||
try {
|
||||
logger.info("Host {} is disconnecting with event {}",
|
||||
attache, event);
|
||||
Status nextStatus;
|
||||
final HostVO host = _hostDao.findById(hostId);
|
||||
if (host == null) {
|
||||
logger.warn("Can't find host with {} ({})", hostId, attache);
|
||||
nextStatus = Status.Removed;
|
||||
} else {
|
||||
nextStatus = getNextStatusOnDisconnection(host, event);
|
||||
caService.purgeHostCertificate(host);
|
||||
}
|
||||
logger.debug("Deregistering link for {} with state {}", attache, nextStatus);
|
||||
|
||||
removeAgent(attache, nextStatus);
|
||||
|
||||
if (host != null && transitState) {
|
||||
// update the state for host in DB as per the event
|
||||
disconnectAgent(host, event, _nodeId);
|
||||
}
|
||||
} finally {
|
||||
joinLock.unlock();
|
||||
try {
|
||||
if (!joinLock.lock(60)) {
|
||||
logger.debug("Unable to acquire lock on host {} to process agent disconnection", Objects.toString(host, String.valueOf(hostId)));
|
||||
return result;
|
||||
}
|
||||
|
||||
logger.debug("Acquired lock on host {}, to process agent disconnection", Objects.toString(host, String.valueOf(hostId)));
|
||||
disconnectHostAgent(attache, event, host, transitState, joinLock);
|
||||
result = true;
|
||||
} finally {
|
||||
joinLock.releaseRef();
|
||||
}
|
||||
joinLock.releaseRef();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void disconnectHostAgent(final AgentAttache attache, final Status.Event event, final HostVO host, final boolean transitState, final GlobalLock joinLock) {
|
||||
try {
|
||||
logger.info("Host {} is disconnecting with event {}", attache, event);
|
||||
final long hostId = attache.getId();
|
||||
Status nextStatus;
|
||||
if (host == null) {
|
||||
logger.warn("Can't find host with {} ({})", hostId, attache);
|
||||
nextStatus = Status.Removed;
|
||||
} else {
|
||||
nextStatus = getNextStatusOnDisconnection(host, event);
|
||||
caService.purgeHostCertificate(host);
|
||||
}
|
||||
logger.debug("Deregistering link for {} with state {}", attache, nextStatus);
|
||||
|
||||
removeAgent(attache, nextStatus);
|
||||
|
||||
if (host != null && transitState) {
|
||||
// update the state for host in DB as per the event
|
||||
disconnectAgent(host, event, _nodeId);
|
||||
}
|
||||
} finally {
|
||||
joinLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean handleDisconnectWithInvestigation(final AgentAttache attache, Status.Event event) {
|
||||
final long hostId = attache.getId();
|
||||
HostVO host = _hostDao.findById(hostId);
|
||||
|
|
@ -1341,45 +1353,58 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
|
|||
return attache;
|
||||
}
|
||||
|
||||
private AgentAttache sendReadyAndGetAttache(HostVO host, ReadyCommand ready, Link link, StartupCommand[] startup) throws ConnectionException {
|
||||
final List<String> agentMSHostList = new ArrayList<>();
|
||||
String lbAlgorithm = null;
|
||||
if (startup != null && startup.length > 0) {
|
||||
final String agentMSHosts = startup[0].getMsHostList();
|
||||
if (StringUtils.isNotEmpty(agentMSHosts)) {
|
||||
String[] msHosts = agentMSHosts.split("@");
|
||||
if (msHosts.length > 1) {
|
||||
lbAlgorithm = msHosts[1];
|
||||
}
|
||||
agentMSHostList.addAll(Arrays.asList(msHosts[0].split(",")));
|
||||
}
|
||||
}
|
||||
ready.setArch(host.getArch().getType());
|
||||
private AgentAttache sendReadyAndGetAttache(HostVO host, ReadyCommand ready, Link link, StartupCommand[] startupCmds) throws ConnectionException {
|
||||
AgentAttache attache;
|
||||
GlobalLock joinLock = getHostJoinLock(host.getId());
|
||||
if (joinLock.lock(60)) {
|
||||
try {
|
||||
|
||||
if (!indirectAgentLB.compareManagementServerList(host.getId(), host.getDataCenterId(), agentMSHostList, lbAlgorithm)) {
|
||||
final List<String> newMSList = indirectAgentLB.getManagementServerList(host.getId(), host.getDataCenterId(), null);
|
||||
ready.setMsHostList(newMSList);
|
||||
final List<String> avoidMsList = _mshostDao.listNonUpStateMsIPs();
|
||||
ready.setAvoidMsHostList(avoidMsList);
|
||||
ready.setLbAlgorithm(indirectAgentLB.getLBAlgorithmName());
|
||||
ready.setLbCheckInterval(indirectAgentLB.getLBPreferredHostCheckInterval(host.getClusterId()));
|
||||
logger.debug("Agent's management server host list is not up to date, sending list update: {}", newMSList);
|
||||
}
|
||||
|
||||
attache = createAttacheForConnect(host, link);
|
||||
attache = notifyMonitorsOfConnection(attache, startup, false);
|
||||
} finally {
|
||||
joinLock.unlock();
|
||||
try {
|
||||
if (!joinLock.lock(60)) {
|
||||
throw new ConnectionException(true, String.format("Unable to acquire lock on host %s, to process agent connection", host));
|
||||
}
|
||||
} else {
|
||||
throw new ConnectionException(true,
|
||||
String.format("Unable to acquire lock on host %s", host));
|
||||
|
||||
logger.debug("Acquired lock on host {}, to process agent connection", host);
|
||||
attache = connectHostAgent(host, ready, link, startupCmds, joinLock);
|
||||
} finally {
|
||||
joinLock.releaseRef();
|
||||
}
|
||||
joinLock.releaseRef();
|
||||
|
||||
return attache;
|
||||
}
|
||||
|
||||
private AgentAttache connectHostAgent(HostVO host, ReadyCommand ready, Link link, StartupCommand[] startupCmds, GlobalLock joinLock) throws ConnectionException {
|
||||
AgentAttache attache;
|
||||
try {
|
||||
final List<String> agentMSHostList = new ArrayList<>();
|
||||
String lbAlgorithm = null;
|
||||
if (startupCmds != null && startupCmds.length > 0) {
|
||||
final String agentMSHosts = startupCmds[0].getMsHostList();
|
||||
if (StringUtils.isNotEmpty(agentMSHosts)) {
|
||||
String[] msHosts = agentMSHosts.split("@");
|
||||
if (msHosts.length > 1) {
|
||||
lbAlgorithm = msHosts[1];
|
||||
}
|
||||
agentMSHostList.addAll(Arrays.asList(msHosts[0].split(",")));
|
||||
}
|
||||
}
|
||||
|
||||
if (!indirectAgentLB.compareManagementServerListAndLBAlgorithm(host.getId(), host.getDataCenterId(), agentMSHostList, lbAlgorithm)) {
|
||||
final List<String> newMSList = indirectAgentLB.getManagementServerList(host.getId(), host.getDataCenterId(), null);
|
||||
ready.setMsHostList(newMSList);
|
||||
String newLBAlgorithm = indirectAgentLB.getLBAlgorithmName();
|
||||
ready.setLbAlgorithm(newLBAlgorithm);
|
||||
logger.debug("Agent's management server host list or lb algorithm is not up to date, sending list and algorithm update: {}, {}", newMSList, newLBAlgorithm);
|
||||
}
|
||||
|
||||
final List<String> avoidMsList = _mshostDao.listNonUpStateMsIPs();
|
||||
ready.setAvoidMsHostList(avoidMsList);
|
||||
ready.setLbCheckInterval(indirectAgentLB.getLBPreferredHostCheckInterval(host.getClusterId()));
|
||||
ready.setArch(host.getArch().getType());
|
||||
|
||||
attache = createAttacheForConnect(host, link);
|
||||
attache = notifyMonitorsOfConnection(attache, startupCmds, false);
|
||||
} finally {
|
||||
joinLock.unlock();
|
||||
}
|
||||
|
||||
return attache;
|
||||
}
|
||||
|
||||
|
|
@ -1666,7 +1691,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
|
|||
logger.debug("Not processing {} for agent id={}; can't find the host in the DB", PingRoutingCommand.class.getSimpleName(), cmdHostId);
|
||||
}
|
||||
}
|
||||
if (host!= null && host.getStatus() != Status.Up && gatewayAccessible) {
|
||||
if (host != null && host.getStatus() != Status.Up && gatewayAccessible) {
|
||||
requestStartupCommand = true;
|
||||
}
|
||||
final List<String> avoidMsList = _mshostDao.listNonUpStateMsIPs();
|
||||
|
|
@ -1821,11 +1846,11 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
|
|||
return false;
|
||||
}
|
||||
|
||||
private void disconnectInternal(final long hostId, final Status.Event event, final boolean invstigate) {
|
||||
private void disconnectInternal(final long hostId, final Status.Event event, final boolean investigate) {
|
||||
final AgentAttache attache = findAttache(hostId);
|
||||
|
||||
if (attache != null) {
|
||||
if (!invstigate) {
|
||||
if (!investigate) {
|
||||
disconnectWithoutInvestigation(attache, event);
|
||||
} else {
|
||||
disconnectWithInvestigation(attache, event);
|
||||
|
|
|
|||
|
|
@ -54,8 +54,10 @@ public class ConnectedAgentAttache extends AgentAttache {
|
|||
@Override
|
||||
public void disconnect(final Status state) {
|
||||
synchronized (this) {
|
||||
logger.debug("Processing Disconnect.");
|
||||
logger.debug("Processing disconnect [id: {}, uuid: {}, name: {}]", _id, _uuid, _name);
|
||||
|
||||
if (_link != null) {
|
||||
logger.debug("Disconnecting from {}, Socket Address: {}", _link.getIpAddress(), _link.getSocketAddress());
|
||||
_link.close();
|
||||
_link.terminated();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ import org.apache.cloudstack.api.ApiConstants;
|
|||
import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd;
|
||||
import org.apache.cloudstack.api.command.admin.volume.MigrateVolumeCmdByAdmin;
|
||||
import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
|
||||
import org.apache.cloudstack.backup.BackupManager;
|
||||
import org.apache.cloudstack.backup.dao.BackupDao;
|
||||
import org.apache.cloudstack.ca.CAManager;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
|
|
@ -437,6 +439,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
VmWorkJobDao vmWorkJobDao;
|
||||
@Inject
|
||||
DataStoreProviderManager dataStoreProviderManager;
|
||||
@Inject
|
||||
BackupManager backupManager;
|
||||
@Inject
|
||||
BackupDao backupDao;
|
||||
|
||||
private SingleCache<List<Long>> vmIdsInProgressCache;
|
||||
|
||||
|
|
@ -525,8 +531,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
@Override
|
||||
@DB
|
||||
public void allocate(final String vmInstanceName, final VirtualMachineTemplate template, final ServiceOffering serviceOffering,
|
||||
final DiskOfferingInfo rootDiskOfferingInfo, final List<DiskOfferingInfo> dataDiskOfferings,
|
||||
final LinkedHashMap<? extends Network, List<? extends NicProfile>> auxiliaryNetworks, final DeploymentPlan plan, final HypervisorType hyperType, final Map<String, Map<Integer, String>> extraDhcpOptions, final Map<Long, DiskOffering> datadiskTemplateToDiskOfferingMap, Volume volume, Snapshot snapshot)
|
||||
final DiskOfferingInfo rootDiskOfferingInfo, final List<DiskOfferingInfo> dataDiskOfferings, List<Long> dataDiskDeviceIds,
|
||||
final LinkedHashMap<? extends Network, List<? extends NicProfile>> auxiliaryNetworks,final DeploymentPlan plan, final HypervisorType hyperType,
|
||||
final Map<String, Map<Integer, String>> extraDhcpOptions, final Map<Long, DiskOffering> datadiskTemplateToDiskOfferingMap, Volume volume, Snapshot snapshot)
|
||||
throws InsufficientCapacityException {
|
||||
|
||||
logger.info("allocating virtual machine from template: {} with hostname: {} and {} networks", template, vmInstanceName, auxiliaryNetworks.size());
|
||||
|
|
@ -570,19 +577,22 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
CallContext volumeContext = CallContext.register(CallContext.current(), ApiCommandResourceType.Volume);
|
||||
try {
|
||||
if (dataDiskOfferings != null) {
|
||||
int index = 0;
|
||||
for (final DiskOfferingInfo dataDiskOfferingInfo : dataDiskOfferings) {
|
||||
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + persistedVm.getId(), dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(),
|
||||
dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), persistedVm, template, owner, null);
|
||||
Long deviceId = dataDiskDeviceIds.get(index++);
|
||||
String volumeName = deviceId == null ? "DATA-" + persistedVm.getId() : "DATA-" + persistedVm.getId() + "-" + String.valueOf(deviceId);
|
||||
volumeMgr.allocateRawVolume(Type.DATADISK, volumeName, dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(),
|
||||
dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), persistedVm, template, owner, deviceId);
|
||||
}
|
||||
}
|
||||
if (datadiskTemplateToDiskOfferingMap != null && !datadiskTemplateToDiskOfferingMap.isEmpty()) {
|
||||
int diskNumber = 1;
|
||||
Long diskNumber = 1L;
|
||||
for (Entry<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap : datadiskTemplateToDiskOfferingMap.entrySet()) {
|
||||
DiskOffering diskOffering = dataDiskTemplateToDiskOfferingMap.getValue();
|
||||
long diskOfferingSize = diskOffering.getDiskSize() / (1024 * 1024 * 1024);
|
||||
VMTemplateVO dataDiskTemplate = _templateDao.findById(dataDiskTemplateToDiskOfferingMap.getKey());
|
||||
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + persistedVm.getId() + "-" + String.valueOf(diskNumber), diskOffering, diskOfferingSize, null, null,
|
||||
persistedVm, dataDiskTemplate, owner, Long.valueOf(diskNumber));
|
||||
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + persistedVm.getId() + "-" + String.valueOf( diskNumber), diskOffering, diskOfferingSize, null, null,
|
||||
persistedVm, dataDiskTemplate, owner, diskNumber);
|
||||
diskNumber++;
|
||||
}
|
||||
}
|
||||
|
|
@ -629,7 +639,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
public void allocate(final String vmInstanceName, final VirtualMachineTemplate template, final ServiceOffering serviceOffering,
|
||||
final LinkedHashMap<? extends Network, List<? extends NicProfile>> networks, final DeploymentPlan plan, final HypervisorType hyperType, Volume volume, Snapshot snapshot) throws InsufficientCapacityException {
|
||||
DiskOffering diskOffering = _diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
||||
allocate(vmInstanceName, template, serviceOffering, new DiskOfferingInfo(diskOffering), new ArrayList<>(), networks, plan, hyperType, null, null, volume, snapshot);
|
||||
allocate(vmInstanceName, template, serviceOffering, new DiskOfferingInfo(diskOffering), new ArrayList<>(), new ArrayList<>(), networks, plan, hyperType, null, null, volume, snapshot);
|
||||
}
|
||||
|
||||
VirtualMachineGuru getVmGuru(final VirtualMachine vm) {
|
||||
|
|
@ -2589,6 +2599,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
throw new CloudRuntimeException("Unable to destroy " + vm);
|
||||
} else {
|
||||
if (expunge) {
|
||||
backupManager.checkAndRemoveBackupOfferingBeforeExpunge(vm);
|
||||
if (!stateTransitTo(vm, VirtualMachine.Event.ExpungeOperation, vm.getHostId())) {
|
||||
logger.debug("Unable to expunge the vm because it is not in the correct state: {}", vm);
|
||||
throw new CloudRuntimeException("Unable to expunge " + vm);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ import com.cloud.utils.component.ComponentContext;
|
|||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.VmDiskInfo;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
|
@ -162,7 +163,8 @@ public class CloudOrchestrator implements OrchestrationService {
|
|||
@Override
|
||||
public VirtualMachineEntity createVirtualMachine(String id, String owner, String templateId, String hostName, String displayName, String hypervisor, int cpu,
|
||||
int speed, long memory, Long diskSize, List<String> computeTags, List<String> rootDiskTags, Map<String, List<NicProfile>> networkNicMap, DeploymentPlan plan,
|
||||
Long rootDiskSize, Map<String, Map<Integer, String>> extraDhcpOptionMap, Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap, Long dataDiskOfferingId, Long rootDiskOfferingId, Volume volume, Snapshot snapshot) throws InsufficientCapacityException {
|
||||
Long rootDiskSize, Map<String, Map<Integer, String>> extraDhcpOptionMap, Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap, Long dataDiskOfferingId, Long rootDiskOfferingId,
|
||||
List<VmDiskInfo> dataDiskInfoList, Volume volume, Snapshot snapshot) throws InsufficientCapacityException {
|
||||
|
||||
// VirtualMachineEntityImpl vmEntity = new VirtualMachineEntityImpl(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, networks,
|
||||
// vmEntityManager);
|
||||
|
|
@ -187,7 +189,6 @@ public class CloudOrchestrator implements OrchestrationService {
|
|||
// Else, a disk offering is optional, and if present will be used to create the data disk
|
||||
|
||||
DiskOfferingInfo rootDiskOfferingInfo = new DiskOfferingInfo();
|
||||
List<DiskOfferingInfo> dataDiskOfferings = new ArrayList<DiskOfferingInfo>();
|
||||
|
||||
ServiceOfferingVO computeOffering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
|
||||
|
||||
|
|
@ -210,6 +211,8 @@ public class CloudOrchestrator implements OrchestrationService {
|
|||
}
|
||||
}
|
||||
|
||||
List<DiskOfferingInfo> dataDiskOfferings = new ArrayList<DiskOfferingInfo>();
|
||||
List<Long> dataDiskDeviceIds = new ArrayList<>();
|
||||
if (dataDiskOfferingId != null) {
|
||||
DiskOfferingVO diskOffering = _diskOfferingDao.findById(dataDiskOfferingId);
|
||||
if (diskOffering == null) {
|
||||
|
|
@ -243,6 +246,12 @@ public class CloudOrchestrator implements OrchestrationService {
|
|||
}
|
||||
|
||||
dataDiskOfferings.add(dataDiskOfferingInfo);
|
||||
dataDiskDeviceIds.add(null);
|
||||
}
|
||||
} else if (dataDiskInfoList != null){
|
||||
dataDiskOfferings.addAll(dataDiskInfoList);
|
||||
for (VmDiskInfo dataDiskInfo : dataDiskInfoList) {
|
||||
dataDiskDeviceIds.add(dataDiskInfo.getDeviceId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -262,8 +271,8 @@ public class CloudOrchestrator implements OrchestrationService {
|
|||
template = _templateDao.findByIdIncludingRemoved(new Long(templateId));
|
||||
} else
|
||||
template = _templateDao.findById(new Long(templateId));
|
||||
_itMgr.allocate(vm.getInstanceName(), template, computeOffering, rootDiskOfferingInfo, dataDiskOfferings, networkIpMap, plan,
|
||||
hypervisorType, extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap, volume, snapshot);
|
||||
_itMgr.allocate(vm.getInstanceName(), template, computeOffering, rootDiskOfferingInfo, dataDiskOfferings, dataDiskDeviceIds,
|
||||
networkIpMap, plan, hypervisorType, extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap, volume, snapshot);
|
||||
|
||||
return vmEntity;
|
||||
}
|
||||
|
|
@ -271,7 +280,7 @@ public class CloudOrchestrator implements OrchestrationService {
|
|||
@Override
|
||||
public VirtualMachineEntity createVirtualMachineFromScratch(String id, String owner, String isoId, String hostName, String displayName, String hypervisor, String os,
|
||||
int cpu, int speed, long memory, Long diskSize, List<String> computeTags, List<String> rootDiskTags, Map<String, List<NicProfile>> networkNicMap, DeploymentPlan plan,
|
||||
Map<String, Map<Integer, String>> extraDhcpOptionMap, Long diskOfferingId, Volume volume, Snapshot snapshot)
|
||||
Map<String, Map<Integer, String>> extraDhcpOptionMap, Long diskOfferingId, List<VmDiskInfo> dataDiskInfoList, Volume volume, Snapshot snapshot)
|
||||
throws InsufficientCapacityException {
|
||||
|
||||
// VirtualMachineEntityImpl vmEntity = new VirtualMachineEntityImpl(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, networks, vmEntityManager);
|
||||
|
|
@ -317,6 +326,14 @@ public class CloudOrchestrator implements OrchestrationService {
|
|||
rootDiskOfferingInfo.setMaxIops(maxIops != null && maxIops.trim().length() > 0 ? Long.parseLong(maxIops) : null);
|
||||
}
|
||||
}
|
||||
List<DiskOfferingInfo> dataDiskOfferings = new ArrayList<>();
|
||||
List<Long> dataDiskDeviceIds = new ArrayList<>();
|
||||
if (dataDiskInfoList != null) {
|
||||
dataDiskOfferings.addAll(dataDiskInfoList);
|
||||
for (VmDiskInfo dataDiskInfo : dataDiskInfoList) {
|
||||
dataDiskDeviceIds.add(dataDiskInfo.getDeviceId());
|
||||
}
|
||||
}
|
||||
|
||||
LinkedHashMap<Network, List<? extends NicProfile>> networkIpMap = new LinkedHashMap<Network, List<? extends NicProfile>>();
|
||||
for (String uuid : networkNicMap.keySet()) {
|
||||
|
|
@ -328,7 +345,8 @@ public class CloudOrchestrator implements OrchestrationService {
|
|||
|
||||
HypervisorType hypervisorType = HypervisorType.valueOf(hypervisor);
|
||||
|
||||
_itMgr.allocate(vm.getInstanceName(), _templateDao.findByIdIncludingRemoved(new Long(isoId)), computeOffering, rootDiskOfferingInfo, new ArrayList<DiskOfferingInfo>(), networkIpMap, plan, hypervisorType, extraDhcpOptionMap, null, volume, snapshot);
|
||||
_itMgr.allocate(vm.getInstanceName(), _templateDao.findByIdIncludingRemoved(new Long(isoId)), computeOffering, rootDiskOfferingInfo, dataDiskOfferings, dataDiskDeviceIds,
|
||||
networkIpMap, plan, hypervisorType, extraDhcpOptionMap, null, volume, snapshot);
|
||||
|
||||
return vmEntity;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -577,14 +577,18 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||
}
|
||||
|
||||
VolumeInfo vol = volFactory.getVolume(volume.getId());
|
||||
long zoneId = volume.getDataCenterId();
|
||||
DataStore store = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
|
||||
DataStoreRole dataStoreRole = snapshotHelper.getDataStoreRole(snapshot);
|
||||
SnapshotInfo snapInfo = snapshotFactory.getSnapshotWithRoleAndZone(snapshot.getId(), dataStoreRole, volume.getDataCenterId());
|
||||
DataStoreRole dataStoreRole = snapshotHelper.getDataStoreRole(snapshot, zoneId);
|
||||
SnapshotInfo snapInfo = snapshotFactory.getSnapshotWithRoleAndZone(snapshot.getId(), dataStoreRole, zoneId);
|
||||
|
||||
boolean kvmSnapshotOnlyInPrimaryStorage = snapshotHelper.isKvmSnapshotOnlyInPrimaryStorage(snapshot, dataStoreRole);
|
||||
boolean kvmSnapshotOnlyInPrimaryStorage = snapshotHelper.isKvmSnapshotOnlyInPrimaryStorage(snapshot, dataStoreRole, volume.getDataCenterId());
|
||||
boolean storageSupportSnapshotToTemplateEnabled = snapshotHelper.isStorageSupportSnapshotToTemplate(snapInfo);
|
||||
|
||||
try {
|
||||
snapInfo = snapshotHelper.backupSnapshotToSecondaryStorageIfNotExists(snapInfo, dataStoreRole, snapshot, kvmSnapshotOnlyInPrimaryStorage);
|
||||
if (!storageSupportSnapshotToTemplateEnabled) {
|
||||
snapInfo = snapshotHelper.backupSnapshotToSecondaryStorageIfNotExists(snapInfo, dataStoreRole, snapshot, kvmSnapshotOnlyInPrimaryStorage);
|
||||
}
|
||||
} catch (CloudRuntimeException e) {
|
||||
snapshotHelper.expungeTemporarySnapshot(kvmSnapshotOnlyInPrimaryStorage, snapInfo);
|
||||
throw e;
|
||||
|
|
@ -596,7 +600,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||
}
|
||||
|
||||
// don't try to perform a sync if the DataStoreRole of the snapshot is equal to DataStoreRole.Primary
|
||||
if (!DataStoreRole.Primary.equals(dataStoreRole) || kvmSnapshotOnlyInPrimaryStorage) {
|
||||
if (!DataStoreRole.Primary.equals(dataStoreRole) || !storageSupportSnapshotToTemplateEnabled) {
|
||||
try {
|
||||
// sync snapshot to region store if necessary
|
||||
DataStore snapStore = snapInfo.getDataStore();
|
||||
|
|
|
|||
|
|
@ -254,6 +254,8 @@ public class CapacityVO implements Capacity {
|
|||
capacityNames.put(CAPACITY_TYPE_GPU, "GPU");
|
||||
capacityNames.put(CAPACITY_TYPE_CPU_CORE, "CPU_CORE");
|
||||
capacityNames.put(CAPACITY_TYPE_VIRTUAL_NETWORK_IPV6_SUBNET, "VIRTUAL_NETWORK_IPV6_SUBNET");
|
||||
capacityNames.put(CAPACITY_TYPE_BACKUP_STORAGE, "BACKUP_STORAGE");
|
||||
capacityNames.put(CAPACITY_TYPE_OBJECT_STORAGE, "OBJECT_STORAGE");
|
||||
}
|
||||
|
||||
public static String getCapacityName (Short capacityType) {
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<
|
|||
|
||||
VMTemplateVO findSystemVMTemplate(long zoneId);
|
||||
|
||||
VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType);
|
||||
VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType, String preferredArch);
|
||||
|
||||
List<VMTemplateVO> findSystemVMReadyTemplates(long zoneId, HypervisorType hypervisorType, String preferredArch);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.Date;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
|
@ -621,11 +622,19 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||
}
|
||||
|
||||
@Override
|
||||
public VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType) {
|
||||
public VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType, String preferredArch) {
|
||||
List<VMTemplateVO> templates = listAllReadySystemVMTemplates(zoneId);
|
||||
if (CollectionUtils.isEmpty(templates)) {
|
||||
return null;
|
||||
}
|
||||
if (StringUtils.isNotBlank(preferredArch)) {
|
||||
// Sort the templates by preferred architecture first
|
||||
templates = templates.stream()
|
||||
.sorted(Comparator.comparing(
|
||||
x -> !x.getArch().getType().equalsIgnoreCase(preferredArch)
|
||||
))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
if (hypervisorType == HypervisorType.Any) {
|
||||
return templates.get(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,11 +64,14 @@ import com.cloud.dc.dao.DataCenterDao;
|
|||
import com.cloud.dc.dao.DataCenterDaoImpl;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.VMTemplateZoneVO;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.storage.dao.GuestOSDaoImpl;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VMTemplateDaoImpl;
|
||||
import com.cloud.storage.dao.VMTemplateZoneDao;
|
||||
|
|
@ -102,15 +105,13 @@ public class SystemVmTemplateRegistration {
|
|||
private static final String PARTIAL_TEMPLATE_FOLDER = String.format("/template/tmpl/%d/", Account.ACCOUNT_ID_SYSTEM);
|
||||
private static final String storageScriptsDir = "scripts/storage/secondary";
|
||||
private static final Integer OTHER_LINUX_ID = 99;
|
||||
private static final Integer LINUX_5_ID = 15;
|
||||
private static final Integer LINUX_7_ID = 183;
|
||||
private static Integer LINUX_12_ID = 363;
|
||||
private static final Integer SCRIPT_TIMEOUT = 1800000;
|
||||
private static final Integer LOCK_WAIT_TIMEOUT = 1200;
|
||||
protected static final List<CPU.CPUArch> DOWNLOADABLE_TEMPLATE_ARCH_TYPES = Arrays.asList(
|
||||
CPU.CPUArch.arm64
|
||||
);
|
||||
|
||||
|
||||
public static String CS_MAJOR_VERSION = null;
|
||||
public static String CS_TINY_VERSION = null;
|
||||
|
||||
|
|
@ -132,6 +133,8 @@ public class SystemVmTemplateRegistration {
|
|||
ClusterDao clusterDao;
|
||||
@Inject
|
||||
ConfigurationDao configurationDao;
|
||||
@Inject
|
||||
private GuestOSDao guestOSDao;
|
||||
|
||||
private String systemVmTemplateVersion;
|
||||
|
||||
|
|
@ -147,6 +150,7 @@ public class SystemVmTemplateRegistration {
|
|||
imageStoreDetailsDao = new ImageStoreDetailsDaoImpl();
|
||||
clusterDao = new ClusterDaoImpl();
|
||||
configurationDao = new ConfigurationDaoImpl();
|
||||
guestOSDao = new GuestOSDaoImpl();
|
||||
tempDownloadDir = new File(System.getProperty("java.io.tmpdir"));
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +324,7 @@ public class SystemVmTemplateRegistration {
|
|||
|
||||
public static final Map<String, MetadataTemplateDetails> NewTemplateMap = new HashMap<>();
|
||||
|
||||
public static final Map<Hypervisor.HypervisorType, String> RouterTemplateConfigurationNames = new HashMap<Hypervisor.HypervisorType, String>() {
|
||||
public static final Map<Hypervisor.HypervisorType, String> RouterTemplateConfigurationNames = new HashMap<>() {
|
||||
{
|
||||
put(Hypervisor.HypervisorType.KVM, "router.template.kvm");
|
||||
put(Hypervisor.HypervisorType.VMware, "router.template.vmware");
|
||||
|
|
@ -331,14 +335,14 @@ public class SystemVmTemplateRegistration {
|
|||
}
|
||||
};
|
||||
|
||||
public static final Map<Hypervisor.HypervisorType, Integer> hypervisorGuestOsMap = new HashMap<Hypervisor.HypervisorType, Integer>() {
|
||||
public static Map<Hypervisor.HypervisorType, Integer> hypervisorGuestOsMap = new HashMap<>() {
|
||||
{
|
||||
put(Hypervisor.HypervisorType.KVM, LINUX_5_ID);
|
||||
put(Hypervisor.HypervisorType.KVM, LINUX_12_ID);
|
||||
put(Hypervisor.HypervisorType.XenServer, OTHER_LINUX_ID);
|
||||
put(Hypervisor.HypervisorType.VMware, OTHER_LINUX_ID);
|
||||
put(Hypervisor.HypervisorType.Hyperv, LINUX_5_ID);
|
||||
put(Hypervisor.HypervisorType.LXC, LINUX_5_ID);
|
||||
put(Hypervisor.HypervisorType.Ovm3, LINUX_7_ID);
|
||||
put(Hypervisor.HypervisorType.Hyperv, LINUX_12_ID);
|
||||
put(Hypervisor.HypervisorType.LXC, LINUX_12_ID);
|
||||
put(Hypervisor.HypervisorType.Ovm3, LINUX_12_ID);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -595,6 +599,23 @@ public class SystemVmTemplateRegistration {
|
|||
vmInstanceDao.updateSystemVmTemplateId(templateId, hypervisorType);
|
||||
}
|
||||
|
||||
private void updateSystemVmTemplateGuestOsId() {
|
||||
String systemVmGuestOsName = "Debian GNU/Linux 12 (64-bit)"; // default
|
||||
try {
|
||||
GuestOSVO guestOS = guestOSDao.findOneByDisplayName(systemVmGuestOsName);
|
||||
if (guestOS != null) {
|
||||
LOGGER.debug("Updating SystemVM Template Guest OS [{}] id", systemVmGuestOsName);
|
||||
SystemVmTemplateRegistration.LINUX_12_ID = Math.toIntExact(guestOS.getId());
|
||||
hypervisorGuestOsMap.put(Hypervisor.HypervisorType.KVM, LINUX_12_ID);
|
||||
hypervisorGuestOsMap.put(Hypervisor.HypervisorType.Hyperv, LINUX_12_ID);
|
||||
hypervisorGuestOsMap.put(Hypervisor.HypervisorType.LXC, LINUX_12_ID);
|
||||
hypervisorGuestOsMap.put(Hypervisor.HypervisorType.Ovm3, LINUX_12_ID);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Couldn't update SystemVM Template Guest OS id, due to {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void updateConfigurationParams(Map<String, String> configParams) {
|
||||
for (Map.Entry<String, String> config : configParams.entrySet()) {
|
||||
boolean updated = configurationDao.update(config.getKey(), config.getValue());
|
||||
|
|
@ -813,7 +834,8 @@ public class SystemVmTemplateRegistration {
|
|||
section.get("filename"),
|
||||
section.get("downloadurl"),
|
||||
section.get("checksum"),
|
||||
hypervisorType.second()));
|
||||
hypervisorType.second(),
|
||||
section.get("guestos")));
|
||||
}
|
||||
Ini.Section defaultSection = ini.get("default");
|
||||
return defaultSection.get("version").trim();
|
||||
|
|
@ -965,6 +987,10 @@ public class SystemVmTemplateRegistration {
|
|||
private void updateRegisteredTemplateDetails(Long templateId, MetadataTemplateDetails templateDetails) {
|
||||
VMTemplateVO templateVO = vmTemplateDao.findById(templateId);
|
||||
templateVO.setTemplateType(Storage.TemplateType.SYSTEM);
|
||||
GuestOSVO guestOS = guestOSDao.findOneByDisplayName(templateDetails.getGuestOs());
|
||||
if (guestOS != null) {
|
||||
templateVO.setGuestOSId(guestOS.getId());
|
||||
}
|
||||
boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO);
|
||||
if (!updated) {
|
||||
String errMsg = String.format("updateSystemVmTemplates:Exception while updating template with id %s to be marked as 'system'", templateId);
|
||||
|
|
@ -980,9 +1006,13 @@ public class SystemVmTemplateRegistration {
|
|||
updateConfigurationParams(configParams);
|
||||
}
|
||||
|
||||
private void updateTemplateUrlAndChecksum(VMTemplateVO templateVO, MetadataTemplateDetails templateDetails) {
|
||||
private void updateTemplateUrlChecksumAndGuestOsId(VMTemplateVO templateVO, MetadataTemplateDetails templateDetails) {
|
||||
templateVO.setUrl(templateDetails.getUrl());
|
||||
templateVO.setChecksum(templateDetails.getChecksum());
|
||||
GuestOSVO guestOS = guestOSDao.findOneByDisplayName(templateDetails.getGuestOs());
|
||||
if (guestOS != null) {
|
||||
templateVO.setGuestOSId(guestOS.getId());
|
||||
}
|
||||
boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO);
|
||||
if (!updated) {
|
||||
String errMsg = String.format("updateSystemVmTemplates:Exception while updating 'url' and 'checksum' for hypervisor type %s", templateDetails.getHypervisorType());
|
||||
|
|
@ -1020,7 +1050,7 @@ public class SystemVmTemplateRegistration {
|
|||
VMTemplateVO templateVO = vmTemplateDao.findLatestTemplateByTypeAndHypervisorAndArch(
|
||||
templateDetails.getHypervisorType(), templateDetails.getArch(), Storage.TemplateType.SYSTEM);
|
||||
if (templateVO != null) {
|
||||
updateTemplateUrlAndChecksum(templateVO, templateDetails);
|
||||
updateTemplateUrlChecksumAndGuestOsId(templateVO, templateDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1029,6 +1059,7 @@ public class SystemVmTemplateRegistration {
|
|||
|
||||
public void updateSystemVmTemplates(final Connection conn) {
|
||||
LOGGER.debug("Updating System Vm template IDs");
|
||||
updateSystemVmTemplateGuestOsId();
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(final TransactionStatus status) {
|
||||
|
|
@ -1076,15 +1107,17 @@ public class SystemVmTemplateRegistration {
|
|||
private final String checksum;
|
||||
private final CPU.CPUArch arch;
|
||||
private String downloadedFilePath;
|
||||
private final String guestOs;
|
||||
|
||||
MetadataTemplateDetails(Hypervisor.HypervisorType hypervisorType, String name, String filename, String url,
|
||||
String checksum, CPU.CPUArch arch) {
|
||||
String checksum, CPU.CPUArch arch, String guestOs) {
|
||||
this.hypervisorType = hypervisorType;
|
||||
this.name = name;
|
||||
this.filename = filename;
|
||||
this.url = url;
|
||||
this.checksum = checksum;
|
||||
this.arch = arch;
|
||||
this.guestOs = guestOs;
|
||||
}
|
||||
|
||||
public Hypervisor.HypervisorType getHypervisorType() {
|
||||
|
|
@ -1111,6 +1144,10 @@ public class SystemVmTemplateRegistration {
|
|||
return arch;
|
||||
}
|
||||
|
||||
public String getGuestOs() {
|
||||
return guestOs;
|
||||
}
|
||||
|
||||
public String getDownloadedFilePath() {
|
||||
return downloadedFilePath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import com.cloud.usage.UsageBackupVO;
|
|||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface UsageBackupDao extends GenericDao<UsageBackupVO, Long> {
|
||||
void updateMetrics(Long vmId, Long size, Long virtualSize);
|
||||
void removeUsage(Long accountId, Long vmId, Date eventDate);
|
||||
void updateMetrics(Long vmId, Long backupOfferingId, Long size, Long virtualSize);
|
||||
void removeUsage(Long accountId, Long vmId, Long backupOfferingId, Date eventDate);
|
||||
List<UsageBackupVO> getUsageRecords(Long accountId, Date startDate, Date endDate);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,16 +36,17 @@ import com.cloud.utils.db.TransactionLegacy;
|
|||
|
||||
@Component
|
||||
public class UsageBackupDaoImpl extends GenericDaoBase<UsageBackupVO, Long> implements UsageBackupDao {
|
||||
protected static final String UPDATE_DELETED = "UPDATE usage_backup SET removed = ? WHERE account_id = ? AND vm_id = ? and removed IS NULL";
|
||||
protected static final String UPDATE_DELETED = "UPDATE usage_backup SET removed = ? WHERE account_id = ? AND vm_id = ? and backup_offering_id = ? and removed IS NULL";
|
||||
protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT id, zone_id, account_id, domain_id, vm_id, backup_offering_id, size, protected_size, created, removed FROM usage_backup WHERE " +
|
||||
" account_id = ? AND ((removed IS NULL AND created <= ?) OR (created BETWEEN ? AND ?) OR (removed BETWEEN ? AND ?) " +
|
||||
" OR ((created <= ?) AND (removed >= ?)))";
|
||||
|
||||
@Override
|
||||
public void updateMetrics(final Long vmId, final Long size, final Long virtualSize) {
|
||||
public void updateMetrics(final Long vmId, Long backupOfferingId, final Long size, final Long virtualSize) {
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
SearchCriteria<UsageBackupVO> sc = this.createSearchCriteria();
|
||||
sc.addAnd("vmId", SearchCriteria.Op.EQ, vmId);
|
||||
sc.addAnd("backupOfferingId", SearchCriteria.Op.EQ, backupOfferingId);
|
||||
UsageBackupVO vo = findOneBy(sc);
|
||||
if (vo != null) {
|
||||
vo.setSize(size);
|
||||
|
|
@ -58,7 +59,7 @@ public class UsageBackupDaoImpl extends GenericDaoBase<UsageBackupVO, Long> impl
|
|||
}
|
||||
|
||||
@Override
|
||||
public void removeUsage(Long accountId, Long vmId, Date eventDate) {
|
||||
public void removeUsage(Long accountId, Long vmId, Long backupOfferingId, Date eventDate) {
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
txn.start();
|
||||
|
|
@ -67,6 +68,7 @@ public class UsageBackupDaoImpl extends GenericDaoBase<UsageBackupVO, Long> impl
|
|||
pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), eventDate));
|
||||
pstmt.setLong(2, accountId);
|
||||
pstmt.setLong(3, vmId);
|
||||
pstmt.setLong(3, backupOfferingId);
|
||||
pstmt.executeUpdate();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package com.cloud.vm;
|
||||
|
||||
import org.apache.cloudstack.consoleproxy.ConsoleSession;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
|
|
@ -32,7 +34,7 @@ import javax.persistence.TemporalType;
|
|||
|
||||
@Entity
|
||||
@Table(name = "console_session")
|
||||
public class ConsoleSessionVO {
|
||||
public class ConsoleSessionVO implements ConsoleSession {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
|
|
@ -45,6 +47,9 @@ public class ConsoleSessionVO {
|
|||
@Column(name = "created")
|
||||
private Date created;
|
||||
|
||||
@Column(name = "domain_id")
|
||||
private long domainId;
|
||||
|
||||
@Column(name = "account_id")
|
||||
private long accountId;
|
||||
|
||||
|
|
@ -86,6 +91,7 @@ public class ConsoleSessionVO {
|
|||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
|
@ -94,6 +100,16 @@ public class ConsoleSessionVO {
|
|||
this.created = created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
|
@ -102,6 +118,7 @@ public class ConsoleSessionVO {
|
|||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
|
@ -110,6 +127,7 @@ public class ConsoleSessionVO {
|
|||
this.userId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInstanceId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
|
@ -118,6 +136,7 @@ public class ConsoleSessionVO {
|
|||
this.instanceId = instanceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
|
@ -126,6 +145,7 @@ public class ConsoleSessionVO {
|
|||
this.hostId = hostId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
|
@ -134,6 +154,7 @@ public class ConsoleSessionVO {
|
|||
this.removed = removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getAcquired() {
|
||||
return acquired;
|
||||
}
|
||||
|
|
@ -142,6 +163,7 @@ public class ConsoleSessionVO {
|
|||
this.acquired = acquired;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConsoleEndpointCreatorAddress() {
|
||||
return consoleEndpointCreatorAddress;
|
||||
}
|
||||
|
|
@ -150,6 +172,7 @@ public class ConsoleSessionVO {
|
|||
this.consoleEndpointCreatorAddress = consoleEndpointCreatorAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientAddress() {
|
||||
return clientAddress;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package com.cloud.vm.dao;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.vm.ConsoleSessionVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
|
|
@ -36,4 +37,9 @@ public interface ConsoleSessionDao extends GenericDao<ConsoleSessionVO, Long> {
|
|||
void acquireSession(String sessionUuid, String clientAddress);
|
||||
|
||||
int expungeByVmList(List<Long> vmIds, Long batchSize);
|
||||
|
||||
Pair<List<ConsoleSessionVO>, Integer> listConsoleSessions(Long id, List<Long> domainIds, Long accountId, Long userId, Long hostId,
|
||||
Date startDate, Date endDate, Long instanceId,
|
||||
String consoleEndpointCreatorAddress, String clientAddress,
|
||||
boolean activeOnly, boolean acquired, Long pageSizeVal, Long startIndex);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ package com.cloud.vm.dao;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
|
|
@ -30,13 +32,28 @@ import com.cloud.utils.db.SearchCriteria;
|
|||
import com.cloud.vm.ConsoleSessionVO;
|
||||
|
||||
public class ConsoleSessionDaoImpl extends GenericDaoBase<ConsoleSessionVO, Long> implements ConsoleSessionDao {
|
||||
private static final String ID = "id";
|
||||
private static final String DOMAIN_IDS = "domainIds";
|
||||
private static final String ACCOUNT_ID = "accountId";
|
||||
private static final String USER_ID = "userId";
|
||||
private static final String HOST_ID = "hostId";
|
||||
private static final String INSTANCE_ID = "instanceId";
|
||||
private static final String VM_IDS = "vmIds";
|
||||
private static final String START_DATE = "startDate";
|
||||
private static final String END_DATE = "endDate";
|
||||
private static final String CREATOR_ADDRESS = "creatorAddress";
|
||||
private static final String CLIENT_ADDRESS = "clientAddress";
|
||||
private static final String ACQUIRED = "acquired";
|
||||
private static final String CREATED = "created";
|
||||
private static final String REMOVED = "removed";
|
||||
private static final String REMOVED_NOT_NULL = "removedNotNull";
|
||||
|
||||
private final SearchBuilder<ConsoleSessionVO> searchByRemovedDate;
|
||||
|
||||
public ConsoleSessionDaoImpl() {
|
||||
searchByRemovedDate = createSearchBuilder();
|
||||
searchByRemovedDate.and("removedNotNull", searchByRemovedDate.entity().getRemoved(), SearchCriteria.Op.NNULL);
|
||||
searchByRemovedDate.and("removed", searchByRemovedDate.entity().getRemoved(), SearchCriteria.Op.LTEQ);
|
||||
searchByRemovedDate.and(REMOVED_NOT_NULL, searchByRemovedDate.entity().getRemoved(), SearchCriteria.Op.NNULL);
|
||||
searchByRemovedDate.and(REMOVED, searchByRemovedDate.entity().getRemoved(), SearchCriteria.Op.LTEQ);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -57,7 +74,7 @@ public class ConsoleSessionDaoImpl extends GenericDaoBase<ConsoleSessionVO, Long
|
|||
@Override
|
||||
public int expungeSessionsOlderThanDate(Date date) {
|
||||
SearchCriteria<ConsoleSessionVO> searchCriteria = searchByRemovedDate.create();
|
||||
searchCriteria.setParameters("removed", date);
|
||||
searchCriteria.setParameters(REMOVED, date);
|
||||
return expunge(searchCriteria);
|
||||
}
|
||||
|
||||
|
|
@ -75,9 +92,66 @@ public class ConsoleSessionDaoImpl extends GenericDaoBase<ConsoleSessionVO, Long
|
|||
return 0;
|
||||
}
|
||||
SearchBuilder<ConsoleSessionVO> sb = createSearchBuilder();
|
||||
sb.and("vmIds", sb.entity().getInstanceId(), SearchCriteria.Op.IN);
|
||||
sb.and(VM_IDS, sb.entity().getInstanceId(), SearchCriteria.Op.IN);
|
||||
SearchCriteria<ConsoleSessionVO> sc = sb.create();
|
||||
sc.setParameters("vmIds", vmIds.toArray());
|
||||
sc.setParameters(VM_IDS, vmIds.toArray());
|
||||
return batchExpunge(sc, batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<ConsoleSessionVO>, Integer> listConsoleSessions(Long id, List<Long> domainIds, Long accountId, Long userId, Long hostId,
|
||||
Date startDate, Date endDate, Long instanceId,
|
||||
String consoleEndpointCreatorAddress, String clientAddress,
|
||||
boolean activeOnly, boolean acquired, Long pageSizeVal, Long startIndex) {
|
||||
Filter filter = new Filter(ConsoleSessionVO.class, CREATED, false, startIndex, pageSizeVal);
|
||||
SearchCriteria<ConsoleSessionVO> searchCriteria = createListConsoleSessionsSearchCriteria(id, domainIds, accountId, userId, hostId,
|
||||
startDate, endDate, instanceId, consoleEndpointCreatorAddress, clientAddress, activeOnly, acquired);
|
||||
|
||||
return searchAndCount(searchCriteria, filter, true);
|
||||
}
|
||||
|
||||
private SearchCriteria<ConsoleSessionVO> createListConsoleSessionsSearchCriteria(Long id, List<Long> domainIds, Long accountId, Long userId, Long hostId,
|
||||
Date startDate, Date endDate, Long instanceId,
|
||||
String consoleEndpointCreatorAddress, String clientAddress,
|
||||
boolean activeOnly, boolean acquired) {
|
||||
SearchCriteria<ConsoleSessionVO> searchCriteria = createListConsoleSessionsSearchBuilder(activeOnly, acquired).create();
|
||||
|
||||
searchCriteria.setParametersIfNotNull(ID, id);
|
||||
searchCriteria.setParametersIfNotNull(DOMAIN_IDS, domainIds.toArray());
|
||||
searchCriteria.setParametersIfNotNull(ACCOUNT_ID, accountId);
|
||||
searchCriteria.setParametersIfNotNull(USER_ID, userId);
|
||||
searchCriteria.setParametersIfNotNull(HOST_ID, hostId);
|
||||
searchCriteria.setParametersIfNotNull(INSTANCE_ID, instanceId);
|
||||
searchCriteria.setParametersIfNotNull(START_DATE, startDate);
|
||||
searchCriteria.setParametersIfNotNull(END_DATE, endDate);
|
||||
searchCriteria.setParametersIfNotNull(CREATOR_ADDRESS, consoleEndpointCreatorAddress);
|
||||
searchCriteria.setParametersIfNotNull(CLIENT_ADDRESS, clientAddress);
|
||||
|
||||
return searchCriteria;
|
||||
}
|
||||
|
||||
private SearchBuilder<ConsoleSessionVO> createListConsoleSessionsSearchBuilder(boolean activeOnly, boolean acquired) {
|
||||
SearchBuilder<ConsoleSessionVO> searchBuilder = createSearchBuilder();
|
||||
|
||||
searchBuilder.and(ID, searchBuilder.entity().getId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and(DOMAIN_IDS, searchBuilder.entity().getDomainId(), SearchCriteria.Op.IN);
|
||||
searchBuilder.and(ACCOUNT_ID, searchBuilder.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and(USER_ID, searchBuilder.entity().getUserId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and(HOST_ID, searchBuilder.entity().getHostId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and(INSTANCE_ID, searchBuilder.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and(START_DATE, searchBuilder.entity().getCreated(), SearchCriteria.Op.GTEQ);
|
||||
searchBuilder.and(END_DATE, searchBuilder.entity().getCreated(), SearchCriteria.Op.LTEQ);
|
||||
searchBuilder.and(CREATOR_ADDRESS, searchBuilder.entity().getConsoleEndpointCreatorAddress(), SearchCriteria.Op.EQ);
|
||||
searchBuilder.and(CLIENT_ADDRESS, searchBuilder.entity().getClientAddress(), SearchCriteria.Op.EQ);
|
||||
|
||||
if (activeOnly) {
|
||||
searchBuilder.and(ACQUIRED, searchBuilder.entity().getAcquired(), SearchCriteria.Op.NNULL);
|
||||
searchBuilder.and(REMOVED, searchBuilder.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
} else if (acquired) {
|
||||
searchBuilder.and(ACQUIRED, searchBuilder.entity().getAcquired(), SearchCriteria.Op.NNULL);
|
||||
}
|
||||
|
||||
searchBuilder.done();
|
||||
return searchBuilder;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
|
|||
|
||||
List<VMInstanceVO> listVmsMigratingFromHost(Long hostId);
|
||||
|
||||
List<VMInstanceVO> listByZoneWithBackups(Long zoneId, Long backupOfferingId);
|
||||
List<VMInstanceVO> listByZoneAndBackupOffering(Long zoneId, Long backupOfferingId);
|
||||
|
||||
public Long countActiveByHostId(long hostId);
|
||||
|
||||
|
|
@ -187,4 +187,5 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
|
|||
|
||||
Map<String, Long> getNameIdMapForVmIds(Collection<Long> ids);
|
||||
|
||||
List<VMInstanceVO> listByIdsIncludingRemoved(List<Long> ids);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -661,7 +661,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listByZoneWithBackups(Long zoneId, Long backupOfferingId) {
|
||||
public List<VMInstanceVO> listByZoneAndBackupOffering(Long zoneId, Long backupOfferingId) {
|
||||
SearchCriteria<VMInstanceVO> sc = BackupSearch.create();
|
||||
sc.setParameters("zone_id", zoneId);
|
||||
if (backupOfferingId != null) {
|
||||
|
|
@ -1246,4 +1246,14 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
|||
return vms.stream()
|
||||
.collect(Collectors.toMap(VMInstanceVO::getInstanceName, VMInstanceVO::getId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listByIdsIncludingRemoved(List<Long> ids) {
|
||||
SearchBuilder<VMInstanceVO> idsSearch = createSearchBuilder();
|
||||
idsSearch.and("ids", idsSearch.entity().getId(), SearchCriteria.Op.IN);
|
||||
idsSearch.done();
|
||||
SearchCriteria<VMInstanceVO> sc = idsSearch.create();
|
||||
sc.setParameters("ids", ids.toArray());
|
||||
return listIncludingRemovedBy(sc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
// 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.backup;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.api.ResourceDetail;
|
||||
|
||||
@Entity
|
||||
@Table(name = "backup_details")
|
||||
public class BackupDetailVO implements ResourceDetail {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id;
|
||||
|
||||
@Column(name = "backup_id")
|
||||
private long resourceId;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "value", length = 65536)
|
||||
private String value;
|
||||
|
||||
@Column(name = "display")
|
||||
private boolean display = true;
|
||||
|
||||
public BackupDetailVO() {
|
||||
}
|
||||
|
||||
public BackupDetailVO(long backupId, String name, String value, boolean display) {
|
||||
this.resourceId = backupId;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplay() {
|
||||
return display;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setResourceId(long resourceId) {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -144,11 +144,21 @@ public class BackupRepositoryVO implements BackupRepository {
|
|||
return usedBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsedBytes(Long usedBytes) {
|
||||
this.usedBytes = usedBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getCapacityBytes() {
|
||||
return capacityBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCapacityBytes(Long capacityBytes) {
|
||||
this.capacityBytes = capacityBytes;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,18 +63,22 @@ public class BackupScheduleVO implements BackupSchedule {
|
|||
Long asyncJobId;
|
||||
|
||||
@Column(name = "max_backups")
|
||||
Integer maxBackups = 0;
|
||||
private int maxBackups = 0;
|
||||
|
||||
@Column(name = "quiescevm")
|
||||
Boolean quiesceVM = false;
|
||||
|
||||
public BackupScheduleVO() {
|
||||
}
|
||||
|
||||
public BackupScheduleVO(Long vmId, DateUtil.IntervalType scheduleType, String schedule, String timezone, Date scheduledTimestamp, Integer maxBackups) {
|
||||
public BackupScheduleVO(Long vmId, DateUtil.IntervalType scheduleType, String schedule, String timezone, Date scheduledTimestamp, int maxBackups, Boolean quiesceVM) {
|
||||
this.vmId = vmId;
|
||||
this.scheduleType = (short) scheduleType.ordinal();
|
||||
this.schedule = schedule;
|
||||
this.timezone = timezone;
|
||||
this.scheduledTimestamp = scheduledTimestamp;
|
||||
this.maxBackups = maxBackups;
|
||||
this.quiesceVM = quiesceVM;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -142,11 +146,19 @@ public class BackupScheduleVO implements BackupSchedule {
|
|||
this.asyncJobId = asyncJobId;
|
||||
}
|
||||
|
||||
public Integer getMaxBackups() {
|
||||
public int getMaxBackups() {
|
||||
return maxBackups;
|
||||
}
|
||||
|
||||
public void setMaxBackups(Integer maxBackups) {
|
||||
public void setMaxBackups(int maxBackups) {
|
||||
this.maxBackups = maxBackups;
|
||||
}
|
||||
|
||||
public void setQuiesceVM(Boolean quiesceVM) {
|
||||
this.quiesceVM = quiesceVM;
|
||||
}
|
||||
|
||||
public Boolean getQuiesceVM() {
|
||||
return quiesceVM;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.apache.cloudstack.backup;
|
|||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
|
@ -26,6 +27,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.Column;
|
||||
|
|
@ -38,6 +40,7 @@ import javax.persistence.Id;
|
|||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
@Entity
|
||||
@Table(name = "backups")
|
||||
|
|
@ -47,11 +50,17 @@ public class BackupVO implements Backup {
|
|||
@Column(name = "id")
|
||||
private long id;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
@Column(name = "uuid")
|
||||
private String uuid;
|
||||
|
||||
@Column(name = "vm_id")
|
||||
private long vmId;
|
||||
private Long vmId;
|
||||
|
||||
@Column(name = "external_id")
|
||||
private String externalId;
|
||||
|
|
@ -88,12 +97,15 @@ public class BackupVO implements Backup {
|
|||
@Column(name = "zone_id")
|
||||
private long zoneId;
|
||||
|
||||
@Column(name = "backup_interval_type")
|
||||
private short backupIntervalType;
|
||||
|
||||
@Column(name = "backed_volumes", length = 65535)
|
||||
protected String backedUpVolumes;
|
||||
|
||||
@Column(name = "backup_schedule_id")
|
||||
private Long backupScheduleId;
|
||||
|
||||
@Transient
|
||||
Map<String, String> details;
|
||||
|
||||
public BackupVO() {
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
|
@ -115,11 +127,11 @@ public class BackupVO implements Backup {
|
|||
}
|
||||
|
||||
@Override
|
||||
public long getVmId() {
|
||||
public Long getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
||||
public void setVmId(long vmId) {
|
||||
public void setVmId(Long vmId) {
|
||||
this.vmId = vmId;
|
||||
}
|
||||
|
||||
|
|
@ -211,14 +223,6 @@ public class BackupVO implements Backup {
|
|||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
public short getBackupIntervalType() {
|
||||
return backupIntervalType;
|
||||
}
|
||||
|
||||
public void setBackupIntervalType(short backupIntervalType) {
|
||||
this.backupIntervalType = backupIntervalType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEntityType() {
|
||||
return Backup.class;
|
||||
|
|
@ -226,7 +230,22 @@ public class BackupVO implements Backup {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public List<VolumeInfo> getBackedUpVolumes() {
|
||||
|
|
@ -240,11 +259,33 @@ public class BackupVO implements Backup {
|
|||
this.backedUpVolumes = backedUpVolumes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetail(String name) {
|
||||
return this.details.get(name);
|
||||
}
|
||||
|
||||
public void setDetails(Map<String, String> details) {
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public Date getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void setRemoved(Date removed) {
|
||||
this.removed = removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getBackupScheduleId() {
|
||||
return backupScheduleId;
|
||||
}
|
||||
|
||||
public void setBackupScheduleId(Long backupScheduleId) {
|
||||
this.backupScheduleId = backupScheduleId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package org.apache.cloudstack.backup.dao;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.response.BackupResponse;
|
||||
import org.apache.cloudstack.backup.Backup;
|
||||
import org.apache.cloudstack.backup.BackupVO;
|
||||
|
||||
|
|
@ -33,12 +32,14 @@ public interface BackupDao extends GenericDao<BackupVO, Long> {
|
|||
List<Backup> listByVmId(Long zoneId, Long vmId);
|
||||
List<Backup> listByAccountId(Long accountId);
|
||||
List<Backup> syncBackups(Long zoneId, Long vmId, List<Backup> externalBackups);
|
||||
List<Backup> listByVmIdAndOffering(Long zoneId, Long vmId, Long offeringId);
|
||||
List<BackupVO> searchByVmIds(List<Long> vmIds);
|
||||
BackupVO getBackupVO(Backup backup);
|
||||
List<Backup> listByOfferingId(Long backupOfferingId);
|
||||
|
||||
List<BackupVO> listBackupsByVMandIntervalType(Long vmId, Backup.Type backupType);
|
||||
|
||||
BackupResponse newBackupResponse(Backup backup);
|
||||
List<Long> listVmIdsWithBackupsInZone(Long zoneId);
|
||||
public Long countBackupsForAccount(long accountId);
|
||||
public Long calculateBackupStorageForAccount(long accountId);
|
||||
void loadDetails(BackupVO backup);
|
||||
void saveDetails(BackupVO backup);
|
||||
List<BackupVO> listBySchedule(Long backupScheduleId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,29 +19,31 @@ package org.apache.cloudstack.backup.dao;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericSearchBuilder;
|
||||
import org.apache.cloudstack.api.response.BackupResponse;
|
||||
import org.apache.cloudstack.backup.Backup;
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
import org.apache.cloudstack.backup.BackupVO;
|
||||
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import org.apache.cloudstack.backup.Backup;
|
||||
import org.apache.cloudstack.backup.BackupDetailVO;
|
||||
import org.apache.cloudstack.backup.BackupVO;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.google.gson.Gson;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
|
||||
public class BackupDaoImpl extends GenericDaoBase<BackupVO, Long> implements BackupDao {
|
||||
|
||||
|
|
@ -57,13 +59,26 @@ public class BackupDaoImpl extends GenericDaoBase<BackupVO, Long> implements Bac
|
|||
@Inject
|
||||
VMInstanceDao vmInstanceDao;
|
||||
|
||||
@Inject
|
||||
private VMTemplateDao templateDao;
|
||||
|
||||
@Inject
|
||||
BackupOfferingDao backupOfferingDao;
|
||||
|
||||
@Inject
|
||||
BackupDetailsDao backupDetailsDao;
|
||||
|
||||
@Inject
|
||||
ServiceOfferingDao serviceOfferingDao;
|
||||
|
||||
@Inject
|
||||
NetworkDao networkDao;
|
||||
|
||||
private SearchBuilder<BackupVO> backupSearch;
|
||||
private GenericSearchBuilder<BackupVO, Long> CountBackupsByAccount;
|
||||
private GenericSearchBuilder<BackupVO, SumCount> CalculateBackupStorageByAccount;
|
||||
private SearchBuilder<BackupVO> ListBackupsByVMandIntervalType;
|
||||
private SearchBuilder<BackupVO> listBackupsBySchedule;
|
||||
private GenericSearchBuilder<BackupVO, Long> backupVmSearchInZone;
|
||||
|
||||
public BackupDaoImpl() {
|
||||
}
|
||||
|
|
@ -77,6 +92,11 @@ public class BackupDaoImpl extends GenericDaoBase<BackupVO, Long> implements Bac
|
|||
backupSearch.and("zone_id", backupSearch.entity().getZoneId(), SearchCriteria.Op.EQ);
|
||||
backupSearch.done();
|
||||
|
||||
backupVmSearchInZone = createSearchBuilder(Long.class);
|
||||
backupVmSearchInZone.select(null, SearchCriteria.Func.DISTINCT, backupVmSearchInZone.entity().getVmId());
|
||||
backupVmSearchInZone.and("zone_id", backupVmSearchInZone.entity().getZoneId(), SearchCriteria.Op.EQ);
|
||||
backupVmSearchInZone.done();
|
||||
|
||||
CountBackupsByAccount = createSearchBuilder(Long.class);
|
||||
CountBackupsByAccount.select(null, SearchCriteria.Func.COUNT, null);
|
||||
CountBackupsByAccount.and("account", CountBackupsByAccount.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
|
|
@ -91,12 +111,11 @@ public class BackupDaoImpl extends GenericDaoBase<BackupVO, Long> implements Bac
|
|||
CalculateBackupStorageByAccount.and("removed", CalculateBackupStorageByAccount.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
CalculateBackupStorageByAccount.done();
|
||||
|
||||
ListBackupsByVMandIntervalType = createSearchBuilder();
|
||||
ListBackupsByVMandIntervalType.and("vmId", ListBackupsByVMandIntervalType.entity().getVmId(), SearchCriteria.Op.EQ);
|
||||
ListBackupsByVMandIntervalType.and("intervalType", ListBackupsByVMandIntervalType.entity().getBackupIntervalType(), SearchCriteria.Op.EQ);
|
||||
ListBackupsByVMandIntervalType.and("status", ListBackupsByVMandIntervalType.entity().getStatus(), SearchCriteria.Op.EQ);
|
||||
ListBackupsByVMandIntervalType.and("removed", ListBackupsByVMandIntervalType.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
ListBackupsByVMandIntervalType.done();
|
||||
listBackupsBySchedule = createSearchBuilder();
|
||||
listBackupsBySchedule.and("backup_schedule_id", listBackupsBySchedule.entity().getBackupScheduleId(), SearchCriteria.Op.EQ);
|
||||
listBackupsBySchedule.and("status", listBackupsBySchedule.entity().getStatus(), SearchCriteria.Op.EQ);
|
||||
listBackupsBySchedule.and("removed", listBackupsBySchedule.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
listBackupsBySchedule.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -130,6 +149,17 @@ public class BackupDaoImpl extends GenericDaoBase<BackupVO, Long> implements Bac
|
|||
return new ArrayList<>(listBy(sc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Backup> listByVmIdAndOffering(Long zoneId, Long vmId, Long offeringId) {
|
||||
SearchCriteria<BackupVO> sc = backupSearch.create();
|
||||
sc.setParameters("vm_id", vmId);
|
||||
if (zoneId != null) {
|
||||
sc.setParameters("zone_id", zoneId);
|
||||
}
|
||||
sc.setParameters("backup_offering_id", offeringId);
|
||||
return new ArrayList<>(listBy(sc));
|
||||
}
|
||||
|
||||
private Backup findByExternalId(Long zoneId, String externalId) {
|
||||
SearchCriteria<BackupVO> sc = backupSearch.create();
|
||||
sc.setParameters("external_id", externalId);
|
||||
|
|
@ -137,6 +167,18 @@ public class BackupDaoImpl extends GenericDaoBase<BackupVO, Long> implements Bac
|
|||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BackupVO> searchByVmIds(List<Long> vmIds) {
|
||||
if (CollectionUtils.isEmpty(vmIds)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
SearchBuilder<BackupVO> sb = createSearchBuilder();
|
||||
sb.and("vmIds", sb.entity().getVmId(), SearchCriteria.Op.IN);
|
||||
SearchCriteria<BackupVO> sc = sb.create();
|
||||
sc.setParameters("vmIds", vmIds.toArray());
|
||||
return search(sc, null);
|
||||
}
|
||||
|
||||
public BackupVO getBackupVO(Backup backup) {
|
||||
BackupVO backupVO = new BackupVO();
|
||||
backupVO.setExternalId(backup.getExternalId());
|
||||
|
|
@ -158,6 +200,27 @@ public class BackupDaoImpl extends GenericDaoBase<BackupVO, Long> implements Bac
|
|||
expunge(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackupVO persist(BackupVO backup) {
|
||||
return Transaction.execute((TransactionCallback<BackupVO>) status -> {
|
||||
BackupVO backupDb = super.persist(backup);
|
||||
saveDetails(backup);
|
||||
loadDetails(backupDb);
|
||||
return backupDb;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Long id, BackupVO backup) {
|
||||
return Transaction.execute((TransactionCallback<Boolean>) status -> {
|
||||
boolean result = super.update(id, backup);
|
||||
if (result) {
|
||||
saveDetails(backup);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Backup> syncBackups(Long zoneId, Long vmId, List<Backup> externalBackups) {
|
||||
for (Backup backup : externalBackups) {
|
||||
|
|
@ -171,7 +234,7 @@ public class BackupDaoImpl extends GenericDaoBase<BackupVO, Long> implements Bac
|
|||
public Long countBackupsForAccount(long accountId) {
|
||||
SearchCriteria<Long> sc = CountBackupsByAccount.create();
|
||||
sc.setParameters("account", accountId);
|
||||
sc.setParameters("status", Backup.Status.Error, Backup.Status.Failed, Backup.Status.Removed, Backup.Status.Expunged);
|
||||
sc.setParameters("status", Backup.Status.Failed, Backup.Status.Removed, Backup.Status.Expunged);
|
||||
return customSearch(sc, null).get(0);
|
||||
}
|
||||
|
||||
|
|
@ -179,58 +242,42 @@ public class BackupDaoImpl extends GenericDaoBase<BackupVO, Long> implements Bac
|
|||
public Long calculateBackupStorageForAccount(long accountId) {
|
||||
SearchCriteria<SumCount> sc = CalculateBackupStorageByAccount.create();
|
||||
sc.setParameters("account", accountId);
|
||||
sc.setParameters("status", Backup.Status.Error, Backup.Status.Failed, Backup.Status.Removed, Backup.Status.Expunged);
|
||||
sc.setParameters("status", Backup.Status.Failed, Backup.Status.Removed, Backup.Status.Expunged);
|
||||
return customSearch(sc, null).get(0).sum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BackupVO> listBackupsByVMandIntervalType(Long vmId, Backup.Type backupType) {
|
||||
SearchCriteria<BackupVO> sc = ListBackupsByVMandIntervalType.create();
|
||||
sc.setParameters("vmId", vmId);
|
||||
sc.setParameters("type", backupType.ordinal());
|
||||
public List<BackupVO> listBySchedule(Long backupScheduleId) {
|
||||
SearchCriteria<BackupVO> sc = listBackupsBySchedule.create();
|
||||
sc.setParameters("backup_schedule_id", backupScheduleId);
|
||||
sc.setParameters("status", Backup.Status.BackedUp);
|
||||
return listBy(sc, null);
|
||||
return listBy(sc, new Filter(BackupVO.class, "date", true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackupResponse newBackupResponse(Backup backup) {
|
||||
VMInstanceVO vm = vmInstanceDao.findByIdIncludingRemoved(backup.getVmId());
|
||||
AccountVO account = accountDao.findByIdIncludingRemoved(vm.getAccountId());
|
||||
DomainVO domain = domainDao.findByIdIncludingRemoved(vm.getDomainId());
|
||||
DataCenterVO zone = dataCenterDao.findByIdIncludingRemoved(vm.getDataCenterId());
|
||||
Long offeringId = backup.getBackupOfferingId();
|
||||
if (offeringId == null) {
|
||||
offeringId = vm.getBackupOfferingId();
|
||||
}
|
||||
BackupOffering offering = backupOfferingDao.findByIdIncludingRemoved(offeringId);
|
||||
public void loadDetails(BackupVO backup) {
|
||||
Map<String, String> details = backupDetailsDao.listDetailsKeyPairs(backup.getId());
|
||||
backup.setDetails(details);
|
||||
}
|
||||
|
||||
BackupResponse response = new BackupResponse();
|
||||
response.setId(backup.getUuid());
|
||||
response.setVmId(vm.getUuid());
|
||||
response.setVmName(vm.getHostName());
|
||||
response.setExternalId(backup.getExternalId());
|
||||
response.setType(backup.getType());
|
||||
response.setDate(backup.getDate());
|
||||
response.setSize(backup.getSize());
|
||||
response.setProtectedSize(backup.getProtectedSize());
|
||||
response.setStatus(backup.getStatus());
|
||||
// ACS 4.20: For backups taken prior this release the backup.backed_volumes column would be empty hence use vm_instance.backup_volumes
|
||||
String backedUpVolumes;
|
||||
if (Objects.isNull(backup.getBackedUpVolumes())) {
|
||||
backedUpVolumes = new Gson().toJson(vm.getBackupVolumeList().toArray(), Backup.VolumeInfo[].class);
|
||||
} else {
|
||||
backedUpVolumes = new Gson().toJson(backup.getBackedUpVolumes().toArray(), Backup.VolumeInfo[].class);
|
||||
@Override
|
||||
public void saveDetails(BackupVO backup) {
|
||||
Map<String, String> detailsStr = backup.getDetails();
|
||||
if (detailsStr == null) {
|
||||
return;
|
||||
}
|
||||
response.setVolumes(backedUpVolumes);
|
||||
response.setBackupOfferingId(offering.getUuid());
|
||||
response.setBackupOffering(offering.getName());
|
||||
response.setAccountId(account.getUuid());
|
||||
response.setAccount(account.getAccountName());
|
||||
response.setDomainId(domain.getUuid());
|
||||
response.setDomain(domain.getName());
|
||||
response.setZoneId(zone.getUuid());
|
||||
response.setZone(zone.getName());
|
||||
response.setObjectName("backup");
|
||||
return response;
|
||||
List<BackupDetailVO> details = new ArrayList<BackupDetailVO>();
|
||||
for (String key : detailsStr.keySet()) {
|
||||
BackupDetailVO detail = new BackupDetailVO(backup.getId(), key, detailsStr.get(key), true);
|
||||
details.add(detail);
|
||||
}
|
||||
backupDetailsDao.saveDetails(details);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> listVmIdsWithBackupsInZone(Long zoneId) {
|
||||
SearchCriteria<Long> sc = backupVmSearchInZone.create();
|
||||
sc.setParameters("zone_id", zoneId);
|
||||
return customSearchIncludingRemoved(sc, null);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
// 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.backup.dao;
|
||||
|
||||
import org.apache.cloudstack.backup.BackupDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface BackupDetailsDao extends GenericDao<BackupDetailVO, Long>, ResourceDetailsDao<BackupDetailVO> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// 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.backup.dao;
|
||||
|
||||
|
||||
import org.apache.cloudstack.backup.BackupDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class BackupDetailsDaoImpl extends ResourceDetailsDaoBase<BackupDetailVO> implements BackupDetailsDao {
|
||||
|
||||
@Override
|
||||
public void addDetail(long resourceId, String key, String value, boolean display) {
|
||||
super.addDetail(new BackupDetailVO(resourceId, key, value, display));
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +58,7 @@ public class BackupOfferingDaoImpl extends GenericDaoBase<BackupOfferingVO, Long
|
|||
response.setName(offering.getName());
|
||||
response.setDescription(offering.getDescription());
|
||||
response.setExternalId(offering.getExternalId());
|
||||
response.setProvider(offering.getProvider());
|
||||
response.setUserDrivenBackups(offering.isUserDrivenBackupAllowed());
|
||||
if (zone != null) {
|
||||
response.setZoneId(zone.getUuid());
|
||||
|
|
|
|||
|
|
@ -28,4 +28,6 @@ public interface BackupRepositoryDao extends GenericDao<BackupRepositoryVO, Long
|
|||
List<BackupRepository> listByZoneAndProvider(Long zoneId, String provider);
|
||||
|
||||
BackupRepository findByBackupOfferingId(Long backupOfferingId);
|
||||
|
||||
boolean updateCapacity(BackupRepository backupRepository, Long capacityBytes, Long usedBytes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,4 +64,12 @@ public class BackupRepositoryDaoImpl extends GenericDaoBase<BackupRepositoryVO,
|
|||
}
|
||||
return findByUuid(offering.getExternalId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateCapacity(BackupRepository backupRepository, Long capacityBytes, Long usedBytes) {
|
||||
BackupRepositoryVO repository = findById(backupRepository.getId());
|
||||
repository.setCapacityBytes(capacityBytes);
|
||||
repository.setUsedBytes(usedBytes);
|
||||
return update(repository.getId(), repository);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,9 @@ public class BackupScheduleDaoImpl extends GenericDaoBase<BackupScheduleVO, Long
|
|||
response.setSchedule(schedule.getSchedule());
|
||||
response.setTimezone(schedule.getTimezone());
|
||||
response.setMaxBackups(schedule.getMaxBackups());
|
||||
if (schedule.getQuiesceVM() != null) {
|
||||
response.setQuiesceVM(schedule.getQuiesceVM());
|
||||
}
|
||||
response.setObjectName("backupschedule");
|
||||
return response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,13 @@ public interface ResourceDetailsDao<R extends ResourceDetail> extends GenericDao
|
|||
*/
|
||||
R findDetail(long resourceId, String name);
|
||||
|
||||
/**
|
||||
* Find details by key
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
List<R> findDetails(String key);
|
||||
|
||||
/**
|
||||
* Find details by resourceId and key
|
||||
* @param resourceId
|
||||
|
|
|
|||
|
|
@ -65,6 +65,12 @@ public abstract class ResourceDetailsDaoBase<R extends ResourceDetail> extends G
|
|||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
public List<R> findDetails(String key) {
|
||||
SearchCriteria<R> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("name", key);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
public List<R> findDetails(long resourceId, String key) {
|
||||
SearchCriteria<R> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("resourceId", resourceId);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue