Merge branch 'main' into disk-controller-mappings

This commit is contained in:
Fabricio Duarte 2025-07-08 13:48:16 -03:00
commit f3f7aa34f5
527 changed files with 16573 additions and 8625 deletions

View File

@ -18,19 +18,19 @@ Install tools and dependencies used for development:
# yum -y install git java-17-openjdk java-17-openjdk-devel \
mysql mysql-server mkisofs git gcc python MySQL-python openssh-clients wget
Set up Maven (3.6.0):
Set up Maven (3.9.10):
# wget https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz
# tar -zxvf apache-maven-3.9.9-bin.tar.gz -C /usr/local
# wget https://dlcdn.apache.org/maven/maven-3/3.9.10/binaries/apache-maven-3.9.10-bin.tar.gz
# sudo tar -zxvf apache-maven-3.9.10-bin.tar.gz -C /usr/local
# cd /usr/local
# ln -s apache-maven-3.9.9 maven
# sudo ln -s apache-maven-3.9.10 maven
# echo export M2_HOME=/usr/local/maven >> ~/.bashrc # or .zshrc or .profile
# echo export PATH=/usr/local/maven/bin:${PATH} >> ~/.bashrc # or .zshrc or .profile
# source ~/.bashrc
Setup up NodeJS (LTS):
Setup up Node.js 16:
# curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash -
# curl -sL https://rpm.nodesource.com/setup_16.x | sudo -E bash -
# sudo yum install nodejs
# sudo npm install -g @vue/cli npm-check-updates
@ -104,13 +104,13 @@ To install dependencies.
To build the project.
$ npm build
$ npm run build
For Development Mode.
$ npm start
Make sure to set CS_URL=http://localhost:8080/client on .env.local file on ui.
Make sure to set `CS_URL=http://localhost:8080` on the `.env.local` file on UI.
You should be able to run the management server on http://localhost:5050

View File

@ -453,22 +453,30 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
certExecutor.schedule(new PostCertificateRenewalTask(this), 5, TimeUnit.SECONDS);
}
private void scheduleHostLBCheckerTask(final long checkInterval) {
private void scheduleHostLBCheckerTask(final String lbAlgorithm, final long checkInterval) {
String name = "HostLBCheckerTask";
if (hostLbCheckExecutor != null && !hostLbCheckExecutor.isShutdown()) {
logger.info("Shutting down the preferred host checker task {}", name);
hostLbCheckExecutor.shutdown();
try {
if (!hostLbCheckExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
hostLbCheckExecutor.shutdownNow();
}
} catch (InterruptedException e) {
logger.debug("Forcing {} shutdown as it did not shutdown in the desired time due to: {}",
logger.debug("Forcing the preferred host checker task {} shutdown as it did not shutdown in the desired time due to: {}",
name, e.getMessage());
hostLbCheckExecutor.shutdownNow();
}
}
if (checkInterval > 0L) {
logger.info("Scheduling preferred host task with host.lb.interval={}ms", checkInterval);
if ("shuffle".equalsIgnoreCase(lbAlgorithm)) {
logger.info("Scheduling the preferred host checker task to trigger once (to apply lb algorithm '{}') after host.lb.interval={} ms", lbAlgorithm, checkInterval);
hostLbCheckExecutor = Executors.newSingleThreadScheduledExecutor((new NamedThreadFactory(name)));
hostLbCheckExecutor.schedule(new PreferredHostCheckerTask(), checkInterval, TimeUnit.MILLISECONDS);
return;
}
logger.info("Scheduling a recurring preferred host checker task with lb algorithm '{}' and host.lb.interval={} ms", lbAlgorithm, checkInterval);
hostLbCheckExecutor = Executors.newSingleThreadScheduledExecutor((new NamedThreadFactory(name)));
hostLbCheckExecutor.scheduleAtFixedRate(new PreferredHostCheckerTask(), checkInterval, checkInterval,
TimeUnit.MILLISECONDS);
@ -928,7 +936,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
return new SetupCertificateAnswer(true);
}
private void processManagementServerList(final List<String> msList, final List<String> avoidMsList, final String lbAlgorithm, final Long lbCheckInterval) {
private void processManagementServerList(final List<String> msList, final List<String> avoidMsList, final String lbAlgorithm, final Long lbCheckInterval, final boolean triggerHostLB) {
if (CollectionUtils.isNotEmpty(msList) && StringUtils.isNotEmpty(lbAlgorithm)) {
try {
final String newMSHosts = String.format("%s%s%s", com.cloud.utils.StringUtils.toCSVList(msList), IAgentShell.hostLbAlgorithmSeparator, lbAlgorithm);
@ -941,22 +949,24 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
}
shell.setAvoidHosts(avoidMsList);
if ("shuffle".equals(lbAlgorithm)) {
scheduleHostLBCheckerTask(0);
} else {
scheduleHostLBCheckerTask(shell.getLbCheckerInterval(lbCheckInterval));
if (triggerHostLB) {
logger.info("Triggering the preferred host checker task now");
ScheduledExecutorService hostLbExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("HostLB-Executor"));
hostLbExecutor.schedule(new PreferredHostCheckerTask(), 0, TimeUnit.MILLISECONDS);
hostLbExecutor.shutdown();
}
scheduleHostLBCheckerTask(lbAlgorithm, shell.getLbCheckerInterval(lbCheckInterval));
}
private Answer setupManagementServerList(final SetupMSListCommand cmd) {
processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval());
processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval(), cmd.getTriggerHostLb());
return new SetupMSListAnswer(true);
}
private Answer migrateAgentToOtherMS(final MigrateAgentConnectionCommand cmd) {
try {
if (CollectionUtils.isNotEmpty(cmd.getMsList())) {
processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval());
processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval(), false);
}
Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("MigrateAgentConnection-Job")).schedule(() -> {
migrateAgentConnection(cmd.getAvoidMsList());
@ -1046,7 +1056,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
verifyAgentArch(ready.getArch());
processManagementServerList(ready.getMsHostList(), ready.getAvoidMsHostList(), ready.getLbAlgorithm(), ready.getLbCheckInterval());
processManagementServerList(ready.getMsHostList(), ready.getAvoidMsHostList(), ready.getLbAlgorithm(), ready.getLbCheckInterval(), false);
logger.info("Ready command is processed for agent [id: {}, uuid: {}, name: {}]", getId(), getUuid(), getName());
}

View File

@ -31,8 +31,8 @@ public class VirtualMachineTO {
private String name;
private BootloaderType bootloader;
private VirtualMachine.State state;
Type type;
int cpus;
private Type type;
private int cpus;
/**
'speed' is still here since 4.0.X/4.1.X management servers do not support
@ -43,49 +43,50 @@ public class VirtualMachineTO {
So this is here for backwards compatibility with 4.0.X/4.1.X management servers
and newer agents.
*/
Integer speed;
Integer minSpeed;
Integer maxSpeed;
private Integer speed;
private Integer minSpeed;
private Integer maxSpeed;
long minRam;
long maxRam;
String hostName;
String arch;
String os;
String platformEmulator;
String bootArgs;
String[] bootupScripts;
boolean enableHA;
boolean limitCpuUse;
boolean enableDynamicallyScaleVm;
private long minRam;
private long maxRam;
private String hostName;
private String arch;
private String os;
private String platformEmulator;
private String bootArgs;
private String[] bootupScripts;
private boolean enableHA;
private boolean limitCpuUse;
private boolean enableDynamicallyScaleVm;
@LogLevel(LogLevel.Log4jLevel.Off)
String vncPassword;
String vncAddr;
Map<String, String> details;
String uuid;
String bootType;
String bootMode;
boolean enterHardwareSetup;
private String vncPassword;
private String vncAddr;
private Map<String, String> details;
private Map<String, String> params;
private String uuid;
private String bootType;
private String bootMode;
private boolean enterHardwareSetup;
DiskTO[] disks;
NicTO[] nics;
GPUDeviceTO gpuDevice;
Integer vcpuMaxLimit;
List<String[]> vmData = null;
private DiskTO[] disks;
private NicTO[] nics;
private GPUDeviceTO gpuDevice;
private Integer vcpuMaxLimit;
private List<String[]> vmData = null;
String configDriveLabel = null;
String configDriveIsoRootFolder = null;
String configDriveIsoFile = null;
NetworkElement.Location configDriveLocation = NetworkElement.Location.SECONDARY;
private String configDriveLabel = null;
private String configDriveIsoRootFolder = null;
private String configDriveIsoFile = null;
private NetworkElement.Location configDriveLocation = NetworkElement.Location.SECONDARY;
Double cpuQuotaPercentage = null;
private Double cpuQuotaPercentage = null;
Map<String, String> guestOsDetails = new HashMap<String, String>();
Map<String, String> extraConfig = new HashMap<>();
Map<Long, String> networkIdToNetworkNameMap = new HashMap<>();
DeployAsIsInfoTO deployAsIsInfo;
String metadataManufacturer;
String metadataProductName;
private Map<String, String> guestOsDetails = new HashMap<String, String>();
private Map<String, String> extraConfig = new HashMap<>();
private Map<Long, String> networkIdToNetworkNameMap = new HashMap<>();
private DeployAsIsInfoTO deployAsIsInfo;
private String metadataManufacturer;
private String metadataProductName;
public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader,
String os, boolean enableHA, boolean limitCpuUse, String vncPassword) {
@ -260,6 +261,10 @@ public class VirtualMachineTO {
this.bootupScripts = bootupScripts;
}
public void setEnableHA(boolean enableHA) {
this.enableHA = enableHA;
}
public DiskTO[] getDisks() {
return disks;
}
@ -435,6 +440,42 @@ public class VirtualMachineTO {
this.deployAsIsInfo = deployAsIsInfo;
}
public void setSpeed(Integer speed) {
this.speed = speed;
}
public void setMinSpeed(Integer minSpeed) {
this.minSpeed = minSpeed;
}
public void setMaxSpeed(Integer maxSpeed) {
this.maxSpeed = maxSpeed;
}
public void setMinRam(long minRam) {
this.minRam = minRam;
}
public void setMaxRam(long maxRam) {
this.maxRam = maxRam;
}
public void setLimitCpuUse(boolean limitCpuUse) {
this.limitCpuUse = limitCpuUse;
}
public Map<String, String> getParams() {
return params;
}
public void setParams(Map<String, String> params) {
this.params = params;
}
public void setExtraConfig(Map<String, String> extraConfig) {
this.extraConfig = extraConfig;
}
public String getMetadataManufacturer() {
return metadataManufacturer;
}

View File

@ -289,6 +289,8 @@ public class EventTypes {
//registering userdata events
public static final String EVENT_REGISTER_USER_DATA = "REGISTER.USER.DATA";
public static final String EVENT_REGISTER_CNI_CONFIG = "REGISTER.CNI.CONFIG";
public static final String EVENT_DELETE_CNI_CONFIG = "DELETE.CNI.CONFIG";
//register for user API and secret keys
public static final String EVENT_REGISTER_FOR_SECRET_API_KEY = "REGISTER.USER.KEY";
@ -688,6 +690,9 @@ public class EventTypes {
public static final String EVENT_EXTERNAL_OPENDAYLIGHT_CONFIGURE_CONTROLLER = "PHYSICAL.ODLCONTROLLER.CONFIGURE";
//Guest OS related events
public static final String EVENT_GUEST_OS_CATEGORY_ADD = "GUEST.OS.CATEGORY.ADD";
public static final String EVENT_GUEST_OS_CATEGORY_DELETE = "GUEST.OS.CATEGORY.DELETE";
public static final String EVENT_GUEST_OS_CATEGORY_UPDATE = "GUEST.OS.CATEGORY.UPDATE";
public static final String EVENT_GUEST_OS_ADD = "GUEST.OS.ADD";
public static final String EVENT_GUEST_OS_REMOVE = "GUEST.OS.REMOVE";
public static final String EVENT_GUEST_OS_UPDATE = "GUEST.OS.UPDATE";
@ -796,6 +801,9 @@ public class EventTypes {
// Resource Limit
public static final String EVENT_RESOURCE_LIMIT_UPDATE = "RESOURCE.LIMIT.UPDATE";
// Management Server
public static final String EVENT_MANAGEMENT_SERVER_REMOVE = "MANAGEMENT.SERVER.REMOVE";
public static final String VM_LEASE_EXPIRED = "VM.LEASE.EXPIRED";
public static final String VM_LEASE_DISABLED = "VM.LEASE.DISABLED";
public static final String VM_LEASE_CANCELLED = "VM.LEASE.CANCELLED";
@ -1296,6 +1304,9 @@ public class EventTypes {
entityEventDetails.put(EVENT_SHAREDFS_EXPUNGE, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_RECOVER, SharedFS.class);
// Management Server
entityEventDetails.put(EVENT_MANAGEMENT_SERVER_REMOVE, "ManagementServer");
// VM Lease
entityEventDetails.put(VM_LEASE_EXPIRED, VirtualMachine.class);
entityEventDetails.put(VM_LEASE_EXPIRING, VirtualMachine.class);

View File

@ -40,7 +40,7 @@ public class OperationTimedoutException extends CloudException {
boolean _isActive;
public OperationTimedoutException(Command[] cmds, long agentId, long seqId, int time, boolean isActive) {
super("Commands " + seqId + " to Host " + agentId + " timed out after " + time);
super("Commands " + seqId + " to Host " + agentId + " timed out after " + time + " secs");
_agentId = agentId;
_seqId = seqId;
_time = time;

View File

@ -53,9 +53,12 @@ public interface Host extends StateObject<Status>, Identity, Partition, HAResour
return strs;
}
}
public static final String HOST_UEFI_ENABLE = "host.uefi.enable";
public static final String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
public static final String HOST_INSTANCE_CONVERSION = "host.instance.conversion";
String HOST_UEFI_ENABLE = "host.uefi.enable";
String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
String HOST_INSTANCE_CONVERSION = "host.instance.conversion";
String HOST_OVFTOOL_VERSION = "host.ovftool.version";
String HOST_VIRTV2V_VERSION = "host.virtv2v.version";
/**
* @return name of the machine.

View File

@ -44,6 +44,8 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
AutoscaleRequested,
ScaleUpRequested,
ScaleDownRequested,
AddNodeRequested,
RemoveNodeRequested,
UpgradeRequested,
OperationSucceeded,
OperationFailed,
@ -59,6 +61,8 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
Stopped("All resources for the Kubernetes cluster are destroyed, Kubernetes cluster may still have ephemeral resource like persistent volumes provisioned"),
Scaling("Transient state in which resources are either getting scaled up/down"),
Upgrading("Transient state in which cluster is getting upgraded"),
Importing("Transient state in which additional nodes are added as worker nodes to a cluster"),
RemovingNodes("Transient state in which additional nodes are removed from a cluster"),
Alert("State to represent Kubernetes clusters which are not in expected desired state (operationally in active control place, stopped cluster VM's etc)."),
Recovering("State in which Kubernetes cluster is recovering from alert state"),
Destroyed("End state of Kubernetes cluster in which all resources are destroyed, cluster will not be usable further"),
@ -96,6 +100,17 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
s_fsm.addTransition(State.Upgrading, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Upgrading, Event.OperationFailed, State.Alert);
s_fsm.addTransition(State.Running, Event.AddNodeRequested, State.Importing);
s_fsm.addTransition(State.Alert, Event.AddNodeRequested, State.Importing);
s_fsm.addTransition(State.Importing, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Importing, Event.OperationFailed, State.Running);
s_fsm.addTransition(State.Alert, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Running, Event.RemoveNodeRequested, State.RemovingNodes);
s_fsm.addTransition(State.Alert, Event.RemoveNodeRequested, State.RemovingNodes);
s_fsm.addTransition(State.RemovingNodes, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.RemovingNodes, Event.OperationFailed, State.Running);
s_fsm.addTransition(State.Alert, Event.RecoveryRequested, State.Recovering);
s_fsm.addTransition(State.Recovering, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Recovering, Event.OperationFailed, State.Alert);
@ -142,4 +157,13 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
Long getMaxSize();
Long getSecurityGroupId();
ClusterType getClusterType();
Long getControlNodeServiceOfferingId();
Long getWorkerNodeServiceOfferingId();
Long getEtcdNodeServiceOfferingId();
Long getControlNodeTemplateId();
Long getWorkerNodeTemplateId();
Long getEtcdNodeTemplateId();
Long getEtcdNodeCount();
Long getCniConfigId();
String getCniConfigDetails();
}

View File

@ -18,14 +18,23 @@ package com.cloud.kubernetes.cluster;
import org.apache.cloudstack.acl.ControlledEntity;
import java.util.Map;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Adapter;
public interface KubernetesServiceHelper extends Adapter {
enum KubernetesClusterNodeType {
CONTROL, WORKER, ETCD, DEFAULT
}
ControlledEntity findByUuid(String uuid);
ControlledEntity findByVmId(long vmId);
void checkVmCanBeDestroyed(UserVm userVm);
boolean isValidNodeType(String nodeType);
Map<String, Long> getServiceOfferingNodeTypeMap(Map<String, Map<String, String>> serviceOfferingNodeTypeMap);
Map<String, Long> getTemplateNodeTypeMap(Map<String, Map<String, String>> templateNodeTypeMap);
void cleanupForAccount(Account account);
}

View File

@ -268,4 +268,6 @@ public interface NetworkService {
InternalLoadBalancerElementService getInternalLoadBalancerElementByNetworkServiceProviderId(long networkProviderId);
InternalLoadBalancerElementService getInternalLoadBalancerElementById(long providerId);
List<InternalLoadBalancerElementService> getInternalLoadBalancerElements();
boolean handleCksIsoOnNetworkVirtualRouter(Long virtualRouterId, boolean mount) throws ResourceUnavailableException;
}

View File

@ -105,4 +105,6 @@ public interface Vpc extends ControlledEntity, Identity, InternalIdentity {
String getIp6Dns1();
String getIp6Dns2();
boolean useRouterIpAsResolver();
}

View File

@ -48,17 +48,17 @@ public interface VpcService {
* @param vpcName
* @param displayText
* @param cidr
* @param networkDomain TODO
* @param networkDomain TODO
* @param ip4Dns1
* @param ip4Dns2
* @param displayVpc TODO
* @param displayVpc TODO
* @param useVrIpResolver
* @return
* @throws ResourceAllocationException TODO
*/
Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName, String displayText, String cidr, String networkDomain,
String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Boolean displayVpc, Integer publicMtu, Integer cidrSize,
Long asNumber, List<Long> bgpPeerIds)
throws ResourceAllocationException;
Long asNumber, List<Long> bgpPeerIds, Boolean useVrIpResolver) throws ResourceAllocationException;
/**
* Persists VPC record in the database

View File

@ -76,6 +76,10 @@ public enum ResourceState {
}
}
public static List<ResourceState> s_maintenanceStates = List.of(ResourceState.Maintenance,
ResourceState.ErrorInMaintenance, ResourceState.PrepareForMaintenance,
ResourceState.ErrorInPrepareForMaintenance);
public ResourceState getNextState(Event a) {
return s_fsm.getNextState(this, a);
}
@ -98,8 +102,7 @@ public enum ResourceState {
}
public static boolean isMaintenanceState(ResourceState state) {
return Arrays.asList(ResourceState.Maintenance, ResourceState.ErrorInMaintenance,
ResourceState.PrepareForMaintenance, ResourceState.ErrorInPrepareForMaintenance).contains(state);
return s_maintenanceStates.contains(state);
}
public static boolean canAttemptMaintenance(ResourceState state) {

View File

@ -25,16 +25,20 @@ import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
import org.apache.cloudstack.api.command.admin.config.ListCfgGroupsByCmd;
import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd;
import org.apache.cloudstack.api.command.admin.guest.AddGuestOsCategoryCmd;
import org.apache.cloudstack.api.command.admin.guest.AddGuestOsCmd;
import org.apache.cloudstack.api.command.admin.guest.AddGuestOsMappingCmd;
import org.apache.cloudstack.api.command.admin.guest.DeleteGuestOsCategoryCmd;
import org.apache.cloudstack.api.command.admin.guest.GetHypervisorGuestOsNamesCmd;
import org.apache.cloudstack.api.command.admin.guest.ListGuestOsMappingCmd;
import org.apache.cloudstack.api.command.admin.guest.RemoveGuestOsCmd;
import org.apache.cloudstack.api.command.admin.guest.RemoveGuestOsMappingCmd;
import org.apache.cloudstack.api.command.admin.guest.UpdateGuestOsCategoryCmd;
import org.apache.cloudstack.api.command.admin.guest.UpdateGuestOsCmd;
import org.apache.cloudstack.api.command.admin.guest.UpdateGuestOsMappingCmd;
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
import org.apache.cloudstack.api.command.admin.host.UpdateHostPasswordCmd;
import org.apache.cloudstack.api.command.admin.management.RemoveManagementServerCmd;
import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd;
import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd;
import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd;
@ -59,8 +63,10 @@ import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd;
import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.userdata.DeleteCniConfigurationCmd;
import org.apache.cloudstack.api.command.user.userdata.DeleteUserDataCmd;
import org.apache.cloudstack.api.command.user.userdata.ListUserDataCmd;
import org.apache.cloudstack.api.command.user.userdata.RegisterCniConfigurationCmd;
import org.apache.cloudstack.api.command.user.userdata.RegisterUserDataCmd;
import org.apache.cloudstack.api.command.user.vm.GetVMPasswordCmd;
import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
@ -168,6 +174,12 @@ public interface ManagementService {
*/
Pair<List<? extends GuestOsCategory>, Integer> listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd);
GuestOsCategory addGuestOsCategory(AddGuestOsCategoryCmd cmd);
GuestOsCategory updateGuestOsCategory(UpdateGuestOsCategoryCmd cmd);
boolean deleteGuestOsCategory(DeleteGuestOsCategoryCmd cmd);
/**
* Obtains a list of all guest OS mappings
*
@ -360,17 +372,23 @@ public interface ManagementService {
* The api command class.
* @return The list of userdatas found.
*/
Pair<List<? extends UserData>, Integer> listUserDatas(ListUserDataCmd cmd);
Pair<List<? extends UserData>, Integer> listUserDatas(ListUserDataCmd cmd, boolean forCks);
/**
* Registers a cni configuration.
*
* @param cmd The api command class.
* @return A VO with the registered user data.
*/
UserData registerCniConfiguration(RegisterCniConfigurationCmd cmd);
/**
* Registers a userdata.
*
* @param cmd
* The api command class.
* @param cmd The api command class.
* @return A VO with the registered userdata.
*/
UserData registerUserData(RegisterUserDataCmd cmd);
/**
* Deletes a userdata.
*
@ -380,6 +398,14 @@ public interface ManagementService {
*/
boolean deleteUserData(DeleteUserDataCmd cmd);
/**
* Deletes user data.
*
* @param cmd
* The api command class.
* @return True on success. False otherwise.
*/
boolean deleteCniConfiguration(DeleteCniConfigurationCmd cmd);
/**
* Search registered key pairs for the logged in user.
*
@ -481,4 +507,6 @@ public interface ManagementService {
Pair<Boolean, String> patchSystemVM(PatchSystemVMCmd cmd);
boolean removeManagementServer(RemoveManagementServerCmd cmd);
}

View File

@ -16,7 +16,9 @@
// under the License.
package com.cloud.server;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public interface ResourceIconManager {
@ -25,4 +27,8 @@ public interface ResourceIconManager {
boolean deleteResourceIcon(List<String> resourceIds, ResourceTag.ResourceObjectType resourceType);
ResourceIcon getByResourceTypeAndUuid(ResourceTag.ResourceObjectType type, String resourceId);
Map<Long, ResourceIcon> getByResourceTypeAndIds(ResourceTag.ResourceObjectType type, Collection<Long> resourceIds);
Map<String, ResourceIcon> getByResourceTypeAndUuids(ResourceTag.ResourceObjectType type, Collection<String> resourceUuids);
}

View File

@ -66,6 +66,7 @@ public interface ResourceTag extends ControlledEntity, Identity, InternalIdentit
LBStickinessPolicy(false, true),
LBHealthCheckPolicy(false, true),
SnapshotPolicy(true, true),
GuestOsCategory(false, false, true),
GuestOs(false, true),
NetworkOffering(false, true),
VpcOffering(true, false),

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.storage;
import java.util.Date;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@ -27,4 +29,7 @@ public interface GuestOsCategory extends Identity, InternalIdentity {
void setName(String name);
boolean isFeatured();
Date getCreated();
}

View File

@ -58,10 +58,23 @@ public interface TemplateApiService {
VirtualMachineTemplate prepareTemplate(long templateId, long zoneId, Long storageId);
/**
* Detach ISO from VM
* @param vmId id of the VM
* @param isoId id of the ISO (when passed). If it is not passed, it will get it from user_vm table
* @param extraParams forced, isVirtualRouter
* @return true when operation succeeds, false if not
*/
boolean detachIso(long vmId, Long isoId, Boolean... extraParams);
boolean detachIso(long vmId, boolean forced);
boolean attachIso(long isoId, long vmId, boolean forced);
/**
* Attach ISO to a VM
* @param isoId id of the ISO to attach
* @param vmId id of the VM to attach the ISO to
* @param extraParams: forced, isVirtualRouter
* @return true when operation succeeds, false if not
*/
boolean attachIso(long isoId, long vmId, Boolean... extraParams);
/**
* Deletes a template

View File

@ -145,6 +145,8 @@ public interface VirtualMachineTemplate extends ControlledEntity, Identity, Inte
boolean isDeployAsIs();
boolean isForCks();
Long getUserDataId();
UserData.UserDataOverridePolicy getUserDataOverridePolicy();

View File

@ -29,4 +29,5 @@ public interface UserData extends ControlledEntity, InternalIdentity, Identity {
String getUserData();
String getParams();
boolean isForCks();
}

View File

@ -20,6 +20,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.cloud.deploy.DeploymentPlan;
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;
@ -111,7 +112,7 @@ public interface UserVmService {
UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ResourceAllocationException;
void startVirtualMachine(UserVm vm) throws OperationTimedoutException, ResourceUnavailableException, InsufficientCapacityException;
void startVirtualMachine(UserVm vm, DeploymentPlan plan) throws OperationTimedoutException, ResourceUnavailableException, InsufficientCapacityException;
void startVirtualMachineForHA(VirtualMachine vm, Map<VirtualMachineProfile.Param, Object> params,
DeploymentPlanner planner) throws InsufficientCapacityException, ResourceUnavailableException,

View File

@ -89,6 +89,9 @@ public interface VmDetailConstants {
String DEPLOY_AS_IS_CONFIGURATION = "configurationId";
String KEY_PAIR_NAMES = "keypairnames";
String CKS_CONTROL_NODE_LOGIN_USER = "controlNodeLoginUser";
String CKS_NODE_TYPE = "node";
String OFFERING = "offering";
String TEMPLATE = "template";
// VMware to KVM VM migrations specific
String VMWARE_TO_KVM_PREFIX = "vmware-to-kvm";

View File

@ -61,6 +61,7 @@ public enum ApiCommandResourceType {
AffinityGroup(org.apache.cloudstack.affinity.AffinityGroup.class),
InternalLbVm(com.cloud.network.router.VirtualRouter.class),
DedicatedGuestVlanRange(com.cloud.network.GuestVlan.class),
GuestOsCategory(com.cloud.storage.GuestOsCategory.class),
GuestOs(com.cloud.storage.GuestOS.class),
GuestOsMapping(com.cloud.storage.GuestOSHypervisor.class),
Network(com.cloud.network.Network.class),
@ -84,7 +85,7 @@ public enum ApiCommandResourceType {
ObjectStore(org.apache.cloudstack.storage.object.ObjectStore.class),
Bucket(org.apache.cloudstack.storage.object.Bucket.class),
QuotaTariff(org.apache.cloudstack.quota.QuotaTariff.class),
KubernetesCluster(null),
KubernetesCluster(com.cloud.kubernetes.cluster.KubernetesCluster.class),
KubernetesSupportedVersion(null),
SharedFS(org.apache.cloudstack.storage.sharedfs.SharedFS.class);

View File

@ -119,6 +119,10 @@ public class ApiConstants {
public static final String CN = "cn";
public static final String COMMAND = "command";
public static final String CMD_EVENT_TYPE = "cmdeventtype";
public static final String CNI_CONFIG = "cniconfig";
public static final String CNI_CONFIG_ID = "cniconfigurationid";
public static final String CNI_CONFIG_DETAILS = "cniconfigdetails";
public static final String CNI_CONFIG_NAME = "cniconfigname";
public static final String COMPONENT = "component";
public static final String CPU_CORE_PER_SOCKET = "cpucorepersocket";
public static final String CPU_NUMBER = "cpunumber";
@ -140,6 +144,7 @@ public class ApiConstants {
public static final String ENCRYPT_FORMAT = "encryptformat";
public static final String ENCRYPT_ROOT = "encryptroot";
public static final String ENCRYPTION_SUPPORTED = "encryptionsupported";
public static final String ETCD_IPS = "etcdips";
public static final String MIN_IOPS = "miniops";
public static final String MAX_IOPS = "maxiops";
public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve";
@ -299,6 +304,7 @@ public class ApiConstants {
public static final String IS_EXTRACTABLE = "isextractable";
public static final String IS_FEATURED = "isfeatured";
public static final String IS_IMPLICIT = "isimplicit";
public static final String IS_ISO = "isiso";
public static final String IS_PORTABLE = "isportable";
public static final String IS_PUBLIC = "ispublic";
public static final String IS_PERSISTENT = "ispersistent";
@ -332,6 +338,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 MANUAL_UPGRADE = "manualupgrade";
public static final String MAX = "max";
public static final String MAX_SNAPS = "maxsnaps";
public static final String MAX_BACKUPS = "maxbackups";
@ -343,6 +350,7 @@ public class ApiConstants {
public static final String MIGRATIONS = "migrations";
public static final String MEMORY = "memory";
public static final String MODE = "mode";
public static final String MOUNT_CKS_ISO_ON_VR = "mountcksisoonvr";
public static final String MULTI_ARCH = "ismultiarch";
public static final String NSX_MODE = "nsxmode";
public static final String NETWORK_MODE = "networkmode";
@ -359,6 +367,7 @@ public class ApiConstants {
public static final String NIC_PACKED_VIRTQUEUES_ENABLED = "nicpackedvirtqueuesenabled";
public static final String NEW_START_IP = "newstartip";
public static final String NEW_END_IP = "newendip";
public static final String KUBERNETES_NODE_VERSION = "kubernetesnodeversion";
public static final String NUM_RETRIES = "numretries";
public static final String OFFER_HA = "offerha";
public static final String OS_DISTRIBUTION = "osdistribution";
@ -432,6 +441,7 @@ public class ApiConstants {
public static final String PUBLIC_END_PORT = "publicendport";
public static final String PUBLIC_ZONE = "publiczone";
public static final String PURGE_RESOURCES = "purgeresources";
public static final String REBALANCE = "rebalance";
public static final String RECEIVED_BYTES = "receivedbytes";
public static final String RECONNECT = "reconnect";
public static final String RECOVER = "recover";
@ -546,6 +556,7 @@ public class ApiConstants {
public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist";
public static final String USER_SECRET_KEY = "usersecretkey";
public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork";
public static final String USE_VIRTUAL_ROUTER_IP_RESOLVER = "userouteripresolver";
public static final String UPDATE_IN_SEQUENCE = "updateinsequence";
public static final String VALUE = "value";
public static final String VIRTUAL_MACHINE_ID = "virtualmachineid";
@ -562,6 +573,12 @@ public class ApiConstants {
public static final String VLAN = "vlan";
public static final String VLAN_RANGE = "vlanrange";
public static final String WORKER_SERVICE_OFFERING_ID = "workerofferingid";
public static final String WORKER_SERVICE_OFFERING_NAME = "workerofferingname";
public static final String CONTROL_SERVICE_OFFERING_ID = "controlofferingid";
public static final String CONTROL_SERVICE_OFFERING_NAME = "controlofferingname";
public static final String ETCD_SERVICE_OFFERING_ID = "etcdofferingid";
public static final String ETCD_SERVICE_OFFERING_NAME = "etcdofferingname";
public static final String REMOVE_VLAN = "removevlan";
public static final String VLAN_ID = "vlanid";
public static final String ISOLATED_PVLAN = "isolatedpvlan";
@ -912,6 +929,7 @@ public class ApiConstants {
public static final String SPLIT_CONNECTIONS = "splitconnections";
public static final String FOR_VPC = "forvpc";
public static final String FOR_NSX = "fornsx";
public static final String FOR_CKS = "forcks";
public static final String NSX_SUPPORT_LB = "nsxsupportlb";
public static final String NSX_SUPPORTS_INTERNAL_LB = "nsxsupportsinternallb";
public static final String FOR_TUNGSTEN = "fortungsten";
@ -1120,6 +1138,10 @@ public class ApiConstants {
public static final String MASTER_NODES = "masternodes";
public static final String NODE_IDS = "nodeids";
public static final String CONTROL_NODES = "controlnodes";
public static final String ETCD_NODES = "etcdnodes";
public static final String EXTERNAL_NODES = "externalnodes";
public static final String IS_EXTERNAL_NODE = "isexternalnode";
public static final String IS_ETCD_NODE = "isetcdnode";
public static final String MIN_SEMANTIC_VERSION = "minimumsemanticversion";
public static final String MIN_KUBERNETES_VERSION_ID = "minimumkubernetesversionid";
public static final String NODE_ROOT_DISK_SIZE = "noderootdisksize";
@ -1128,6 +1150,8 @@ public class ApiConstants {
public static final String AUTOSCALING_ENABLED = "autoscalingenabled";
public static final String MIN_SIZE = "minsize";
public static final String MAX_SIZE = "maxsize";
public static final String NODE_TYPE_OFFERING_MAP = "nodeofferings";
public static final String NODE_TYPE_TEMPLATE_MAP = "nodetemplates";
public static final String BOOT_TYPE = "boottype";
public static final String BOOT_MODE = "bootmode";

View File

@ -22,6 +22,7 @@ package org.apache.cloudstack.api;
*/
public enum ApiErrorCode {
BAD_REQUEST(400),
UNAUTHORIZED(401),
UNAUTHORIZED2FA(511),
METHOD_NOT_ALLOWED(405),

View File

@ -48,4 +48,6 @@ public interface ApiServerService {
boolean forgotPassword(UserAccount userAccount, Domain domain);
boolean resetPassword(UserAccount userAccount, String token, String password);
boolean isPostRequestsAndTimestampsEnforced();
}

View File

@ -22,20 +22,16 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import com.cloud.bgp.ASNumber;
import com.cloud.bgp.ASNumberRange;
import org.apache.cloudstack.storage.object.Bucket;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse;
import org.apache.cloudstack.api.response.ASNRangeResponse;
import org.apache.cloudstack.api.response.ASNumberResponse;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse;
import org.apache.cloudstack.api.response.AsyncJobResponse;
import org.apache.cloudstack.api.response.AutoScalePolicyResponse;
import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse;
@ -60,10 +56,10 @@ import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.DomainRouterResponse;
import org.apache.cloudstack.api.response.EventResponse;
import org.apache.cloudstack.api.response.ExtractResponse;
import org.apache.cloudstack.api.response.SharedFSResponse;
import org.apache.cloudstack.api.response.FirewallResponse;
import org.apache.cloudstack.api.response.FirewallRuleResponse;
import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse;
import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import org.apache.cloudstack.api.response.GuestOSResponse;
import org.apache.cloudstack.api.response.GuestOsMappingResponse;
import org.apache.cloudstack.api.response.GuestVlanRangeResponse;
@ -73,11 +69,11 @@ import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse;
import org.apache.cloudstack.api.response.HypervisorGuestOsNamesResponse;
import org.apache.cloudstack.api.response.IPAddressResponse;
import org.apache.cloudstack.api.response.IpQuarantineResponse;
import org.apache.cloudstack.api.response.ImageStoreResponse;
import org.apache.cloudstack.api.response.InstanceGroupResponse;
import org.apache.cloudstack.api.response.InternalLoadBalancerElementResponse;
import org.apache.cloudstack.api.response.IpForwardingRuleResponse;
import org.apache.cloudstack.api.response.IpQuarantineResponse;
import org.apache.cloudstack.api.response.IsolationMethodResponse;
import org.apache.cloudstack.api.response.LBHealthCheckResponse;
import org.apache.cloudstack.api.response.LBStickinessResponse;
@ -115,6 +111,7 @@ import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.ServiceResponse;
import org.apache.cloudstack.api.response.SharedFSResponse;
import org.apache.cloudstack.api.response.Site2SiteCustomerGatewayResponse;
import org.apache.cloudstack.api.response.Site2SiteVpnConnectionResponse;
import org.apache.cloudstack.api.response.Site2SiteVpnGatewayResponse;
@ -159,10 +156,14 @@ import org.apache.cloudstack.region.PortableIp;
import org.apache.cloudstack.region.PortableIpRange;
import org.apache.cloudstack.region.Region;
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
import org.apache.cloudstack.storage.sharedfs.SharedFS;
import org.apache.cloudstack.storage.object.Bucket;
import org.apache.cloudstack.storage.object.ObjectStore;
import org.apache.cloudstack.storage.sharedfs.SharedFS;
import org.apache.cloudstack.usage.Usage;
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
import com.cloud.bgp.ASNumber;
import com.cloud.bgp.ASNumberRange;
import com.cloud.capacity.Capacity;
import com.cloud.configuration.ResourceCount;
import com.cloud.configuration.ResourceLimit;
@ -223,10 +224,11 @@ import com.cloud.projects.ProjectAccount;
import com.cloud.projects.ProjectInvitation;
import com.cloud.region.ha.GlobalLoadBalancerRule;
import com.cloud.resource.RollingMaintenanceManager;
import com.cloud.server.ResourceTag;
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag;
import com.cloud.storage.GuestOS;
import com.cloud.storage.GuestOSHypervisor;
import com.cloud.storage.GuestOsCategory;
import com.cloud.storage.ImageStore;
import com.cloud.storage.Snapshot;
import com.cloud.storage.StoragePool;
@ -240,14 +242,13 @@ import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserData;
import com.cloud.uservm.UserVm;
import com.cloud.utils.net.Ip;
import com.cloud.utils.Pair;
import com.cloud.utils.net.Ip;
import com.cloud.vm.InstanceGroup;
import com.cloud.vm.Nic;
import com.cloud.vm.NicSecondaryIp;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.snapshot.VMSnapshot;
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
public interface ResponseGenerator {
UserResponse createUserResponse(UserAccount user);
@ -485,6 +486,10 @@ public interface ResponseGenerator {
AutoScaleVmGroupResponse createAutoScaleVmGroupResponse(AutoScaleVmGroup vmGroup);
GuestOSCategoryResponse createGuestOSCategoryResponse(GuestOsCategory guestOsCategory);
GuestOSCategoryResponse createGuestOSCategoryResponse(GuestOsCategory guestOsCategory, boolean showIcon);
GuestOSResponse createGuestOSResponse(GuestOS os);
GuestOsMappingResponse createGuestOSMappingResponse(GuestOSHypervisor osHypervisor);
@ -572,4 +577,6 @@ public interface ResponseGenerator {
BackupRepositoryResponse createBackupRepositoryResponse(BackupRepository repository);
SharedFSResponse createSharedFSResponse(ResponseView view, SharedFS sharedFS);
void updateTemplateIsoResponsesForIcons(List<TemplateResponse> responses, ResourceTag.ResourceObjectType type);
}

View File

@ -0,0 +1,93 @@
// 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.guest;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import com.cloud.storage.GuestOsCategory;
import com.cloud.user.Account;
@APICommand(name = "addOsCategory",
description = "Adds a new OS category",
responseObject = GuestOSCategoryResponse.class,
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false,
since = "4.21.0",
authorized = {RoleType.Admin})
public class AddGuestOsCategoryCmd extends BaseCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "Name of the OS category",
required = true)
private String name;
@Parameter(name = ApiConstants.IS_FEATURED, type = CommandType.BOOLEAN,
description = "Whether the category is featured or not")
private Boolean featured;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getName() {
return name;
}
public boolean isFeatured() {
return Boolean.TRUE.equals(featured);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() {
GuestOsCategory guestOs = _mgr.addGuestOsCategory(this);
if (guestOs != null) {
GuestOSCategoryResponse response = _responseGenerator.createGuestOSCategoryResponse(guestOs);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add new OS category");
}
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.GuestOsCategory;
}
}

View File

@ -0,0 +1,89 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.admin.guest;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import com.cloud.user.Account;
@APICommand(name = "deleteOsCategory",
description = "Deletes an OS category",
responseObject = SuccessResponse.class,
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false,
since = "4.21.0",
authorized = {RoleType.Admin})
public class DeleteGuestOsCategoryCmd extends BaseCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GuestOSCategoryResponse.class,
required = true, description = "ID of the OS category")
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() {
boolean result = _mgr.deleteGuestOsCategory(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove OS category");
}
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.GuestOsCategory;
}
@Override
public Long getApiResourceId() {
return getId();
}
}

View File

@ -0,0 +1,113 @@
// 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.guest;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import com.cloud.storage.GuestOsCategory;
import com.cloud.user.Account;
@APICommand(name = "updateOsCategory",
description = "Updates an OS category",
responseObject = GuestOSCategoryResponse.class,
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false,
since = "4.21.0",
authorized = {RoleType.Admin})
public class UpdateGuestOsCategoryCmd extends BaseCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GuestOSCategoryResponse.class,
required = true, description = "ID of the OS category")
private Long id;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "Name for the OS category")
private String name;
@Parameter(name = ApiConstants.IS_FEATURED, type = CommandType.BOOLEAN,
description = "Whether the category is featured or not")
private Boolean featured;
@Parameter(name = ApiConstants.SORT_KEY, type = CommandType.INTEGER,
description = "sort key of the OS category for listing")
private Integer sortKey;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public String getName() {
return name;
}
public Boolean isFeatured() {
return featured;
}
public Integer getSortKey() {
return sortKey;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public void execute() {
GuestOsCategory guestOs = _mgr.updateGuestOsCategory(this);
if (guestOs != null) {
GuestOSCategoryResponse response = _responseGenerator.createGuestOSCategoryResponse(guestOs);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update OS category");
}
}
@Override
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.GuestOsCategory;
}
@Override
public Long getApiResourceId() {
return getId();
}
}

View File

@ -16,8 +16,12 @@
// under the License.
package org.apache.cloudstack.api.command.admin.guest;
import org.apache.commons.collections.MapUtils;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
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;
@ -25,18 +29,14 @@ import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import org.apache.cloudstack.api.response.GuestOSResponse;
import org.apache.cloudstack.acl.RoleType;
import org.apache.commons.collections.MapUtils;
import com.cloud.event.EventTypes;
import com.cloud.storage.GuestOS;
import com.cloud.user.Account;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@APICommand(name = "updateGuestOs", description = "Updates the information about Guest OS", responseObject = GuestOSResponse.class,
since = "4.4.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class UpdateGuestOsCmd extends BaseAsyncCmd {
@ -50,7 +50,7 @@ public class UpdateGuestOsCmd extends BaseAsyncCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GuestOSResponse.class, required = true, description = "UUID of the Guest OS")
private Long id;
@Parameter(name = ApiConstants.OS_DISPLAY_NAME, type = CommandType.STRING, required = true, description = "Unique display name for Guest OS")
@Parameter(name = ApiConstants.OS_DISPLAY_NAME, type = CommandType.STRING, description = "Unique display name for Guest OS")
private String osDisplayName;
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, required = false, description = "Map of (key/value pairs)")
@ -59,6 +59,12 @@ public class UpdateGuestOsCmd extends BaseAsyncCmd {
@Parameter(name="forDisplay", type=CommandType.BOOLEAN, description="whether this guest OS is available for end users", authorized = {RoleType.Admin})
private Boolean display;
@Parameter(name = ApiConstants.OS_CATEGORY_ID, type = CommandType.UUID, entityType = GuestOSCategoryResponse.class,
description = "the ID of the OS category", since = "4.21.0")
private Long osCategoryId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -71,9 +77,9 @@ public class UpdateGuestOsCmd extends BaseAsyncCmd {
return osDisplayName;
}
public Map getDetails() {
Map<String, String> detailsMap = new HashMap<>();;
if (MapUtils.isNotEmpty(detailsMap)) {
public Map<String, String> getDetails() {
Map<String, String> detailsMap = new HashMap<>();
if (MapUtils.isNotEmpty(details)) {
Collection<?> servicesCollection = details.values();
Iterator<?> iter = servicesCollection.iterator();
while (iter.hasNext()) {
@ -90,6 +96,10 @@ public class UpdateGuestOsCmd extends BaseAsyncCmd {
return display;
}
public Long getOsCategoryId() {
return osCategoryId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -0,0 +1,61 @@
// 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.management;
import com.cloud.event.EventTypes;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.context.CallContext;
@APICommand(name = "removeManagementServer", description = "Removes a Management Server.", responseObject = SuccessResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = RoleType.Admin)
public class RemoveManagementServerCmd extends BaseCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ManagementServerResponse.class, required = true, description = "the ID of the Management Server")
private Long id;
public Long getId() {
return id;
}
@Override
public void execute() {
boolean result = _mgr.removeManagementServer(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove Management Server.");
}
}
@Override
public long getEntityOwnerId() {
return CallContext.current().getCallingAccountId();
}
public String getEventType() {
return EventTypes.EVENT_MANAGEMENT_SERVER_REMOVE;
}
}

View File

@ -46,7 +46,7 @@ public class PatchSystemVMCmd extends BaseAsyncCmd {
@Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN,
description = "If true, initiates copy of scripts and restart of the agent, even if the scripts version matches." +
"To be used with ID parameter only")
private Boolean force;
private Boolean forced;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -58,7 +58,7 @@ public class PatchSystemVMCmd extends BaseAsyncCmd {
}
public boolean isForced() {
return force != null && force;
return forced != null && forced;
}
/////////////////////////////////////////////////////

View File

@ -26,7 +26,9 @@ import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import com.cloud.cpu.CPU;
import com.cloud.storage.GuestOsCategory;
import com.cloud.utils.Pair;
@ -39,12 +41,48 @@ public class ListGuestOsCategoriesCmd extends BaseListCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GuestOSCategoryResponse.class, description = "list Os category by id")
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GuestOSCategoryResponse.class, description = "List OS category by id")
private Long id;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "list os category by name", since = "3.0.1")
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "List OS category by name", since = "3.0.1")
private String name;
@Parameter(name = ApiConstants.IS_FEATURED,
type = CommandType.BOOLEAN,
description = "List available OS categories by featured or not",
since = "4.21.0")
private Boolean featured;
@Parameter(name = ApiConstants.IS_ISO,
type = CommandType.BOOLEAN,
description = "List OS categories for which an ISO is available",
since = "4.21.0")
private Boolean iso;
@Parameter(name = ApiConstants.IS_VNF, type = CommandType.BOOLEAN,
description = "List OS categories for which a VNF template is available",
since = "4.21.0")
private Boolean vnf;
@Parameter(name = ApiConstants.ZONE_ID,
type = CommandType.UUID,
entityType = ZoneResponse.class,
description = "List available OS categories types for the zone",
since = "4.21.0")
private Long zoneId;
@Parameter(name = ApiConstants.ARCH,
type = CommandType.STRING,
description = "List OS categories types available for given CPU architecture",
since = "4.21.0")
private String arch;
@Parameter(name = ApiConstants.SHOW_RESOURCE_ICON,
type = CommandType.BOOLEAN,
description = "flag to display the resource image for the OS category",
since = "4.21.0")
private Boolean showIcon;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -57,6 +95,30 @@ public class ListGuestOsCategoriesCmd extends BaseListCmd {
return name;
}
public Boolean isFeatured() {
return featured;
}
public Boolean isIso() {
return iso;
}
public Boolean isVnf() {
return vnf;
}
public Long getZoneId() {
return zoneId;
}
public CPU.CPUArch getArch() {
return arch == null ? null : CPU.CPUArch.fromType(arch);
}
public boolean isShowIcon() {
return Boolean.TRUE.equals(showIcon);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -64,14 +126,11 @@ public class ListGuestOsCategoriesCmd extends BaseListCmd {
@Override
public void execute() {
Pair<List<? extends GuestOsCategory>, Integer> result = _mgr.listGuestOSCategoriesByCriteria(this);
ListResponse<GuestOSCategoryResponse> response = new ListResponse<GuestOSCategoryResponse>();
List<GuestOSCategoryResponse> osCatResponses = new ArrayList<GuestOSCategoryResponse>();
ListResponse<GuestOSCategoryResponse> response = new ListResponse<>();
List<GuestOSCategoryResponse> osCatResponses = new ArrayList<>();
for (GuestOsCategory osCategory : result.first()) {
GuestOSCategoryResponse categoryResponse = new GuestOSCategoryResponse();
categoryResponse.setId(osCategory.getUuid());
categoryResponse.setName(osCategory.getName());
categoryResponse.setObjectName("oscategory");
GuestOSCategoryResponse categoryResponse = _responseGenerator.createGuestOSCategoryResponse(osCategory,
isShowIcon());
osCatResponses.add(categoryResponse);
}

View File

@ -104,7 +104,7 @@ public class DetachIsoCmd extends BaseAsyncCmd implements UserCmd {
@Override
public void execute() {
boolean result = _templateService.detachIso(virtualMachineId, isForced());
boolean result = _templateService.detachIso(virtualMachineId, null, isForced());
if (result) {
UserVm userVm = _entityMgr.findById(UserVm.class, virtualMachineId);
UserVmResponse response = _responseGenerator.createUserVmResponse(getResponseView(), "virtualmachine", userVm).get(0);

View File

@ -16,11 +16,6 @@
// under the License.
package org.apache.cloudstack.api.command.user.iso;
import com.cloud.cpu.CPU;
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag;
import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@ -28,16 +23,17 @@ import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.TemplateResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.context.CallContext;
import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
import com.cloud.user.Account;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import com.cloud.cpu.CPU;
import com.cloud.server.ResourceTag;
import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
import com.cloud.user.Account;
@APICommand(name = "listIsos", description = "Lists all available ISO files.", responseObject = TemplateResponse.class, responseView = ResponseView.Restricted,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@ -95,6 +91,11 @@ public class ListIsosCmd extends BaseListTaggedResourcesCmd implements UserCmd {
since = "4.20")
private String arch;
@Parameter(name = ApiConstants.OS_CATEGORY_ID, type = CommandType.UUID, entityType= GuestOSCategoryResponse.class,
description = "the ID of the OS category for the ISO",
since = "4.21.0")
private Long osCategoryId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -173,6 +174,10 @@ public class ListIsosCmd extends BaseListTaggedResourcesCmd implements UserCmd {
return CPU.CPUArch.fromType(arch);
}
public Long getOsCategoryId() {
return osCategoryId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -190,24 +195,14 @@ public class ListIsosCmd extends BaseListTaggedResourcesCmd implements UserCmd {
@Override
public void execute() {
ListResponse<TemplateResponse> response = _queryService.listIsos(this);
if (response != null && response.getCount() > 0 && getShowIcon()) {
updateIsoResponse(response.getResponses());
if (response != null && getShowIcon()) {
_responseGenerator.updateTemplateIsoResponsesForIcons(response.getResponses(),
ResourceTag.ResourceObjectType.ISO);
}
response.setResponseName(getCommandName());
setResponseObject(response);
}
private void updateIsoResponse(List<TemplateResponse> response) {
for (TemplateResponse templateResponse : response) {
ResourceIcon resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.ISO, templateResponse.getId());
if (resourceIcon == null) {
continue;
}
ResourceIconResponse iconResponse = _responseGenerator.createResourceIconResponse(resourceIcon);
templateResponse.setResourceIconResponse(iconResponse);
}
}
public Long getStoragePoolId() {
return null;
};

View File

@ -99,6 +99,11 @@ public class GetUploadParamsForTemplateCmd extends AbstractGetUploadParamsCmd {
description = "(VMware only) true if VM deployments should preserve all the configurations defined for this template", since = "4.15.1")
private Boolean deployAsIs;
@Parameter(name=ApiConstants.FOR_CKS,
type = CommandType.BOOLEAN,
description = "if true, the templates would be available for deploying CKS clusters", since = "4.21.0")
protected Boolean forCks;
public String getDisplayText() {
return StringUtils.isBlank(displayText) ? getName() : displayText;
}
@ -168,6 +173,10 @@ public class GetUploadParamsForTemplateCmd extends AbstractGetUploadParamsCmd {
Boolean.TRUE.equals(deployAsIs);
}
public boolean isForCks() {
return Boolean.TRUE.equals(forCks);
}
public CPU.CPUArch getArch() {
return CPU.CPUArch.fromType(arch);
}

View File

@ -16,17 +16,11 @@
// under the License.
package org.apache.cloudstack.api.command.user.template;
import com.cloud.cpu.CPU;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag;
import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.commons.collections.CollectionUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@ -34,15 +28,20 @@ import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.TemplateResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.server.ResourceTag;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
import com.cloud.user.Account;
import org.apache.commons.lang3.StringUtils;
@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {VirtualMachineTemplate.class}, responseView = ResponseView.Restricted,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@ -106,11 +105,21 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User
since = "4.19.0")
private Boolean isVnf;
@Parameter(name = ApiConstants.FOR_CKS, type = CommandType.BOOLEAN,
description = "list templates that can be used to deploy CKS clusters",
since = "4.21.0")
private Boolean forCks;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "the CPU arch of the template. Valid options are: x86_64, aarch64",
since = "4.20")
private String arch;
@Parameter(name = ApiConstants.OS_CATEGORY_ID, type = CommandType.UUID, entityType= GuestOSCategoryResponse.class,
description = "the ID of the OS category for the template",
since = "4.21.0")
private Long osCategoryId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -198,6 +207,8 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User
return isVnf;
}
public Boolean getForCks() { return forCks; }
public CPU.CPUArch getArch() {
if (StringUtils.isBlank(arch)) {
return null;
@ -205,6 +216,10 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User
return CPU.CPUArch.fromType(arch);
}
public Long getOsCategoryId() {
return osCategoryId;
}
@Override
public String getCommandName() {
return s_name;
@ -218,24 +233,14 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User
@Override
public void execute() {
ListResponse<TemplateResponse> response = _queryService.listTemplates(this);
if (response != null && response.getCount() > 0 && getShowIcon()) {
updateTemplateResponse(response.getResponses());
if (response != null && getShowIcon()) {
_responseGenerator.updateTemplateIsoResponsesForIcons(response.getResponses(),
ResourceTag.ResourceObjectType.Template);
}
response.setResponseName(getCommandName());
setResponseObject(response);
}
private void updateTemplateResponse(List<TemplateResponse> response) {
for (TemplateResponse templateResponse : response) {
ResourceIcon resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.Template, templateResponse.getId());
if (resourceIcon == null) {
continue;
}
ResourceIconResponse iconResponse = _responseGenerator.createResourceIconResponse(resourceIcon);
templateResponse.setResourceIconResponse(iconResponse);
}
}
public List<Long> getIds() {
if (ids == null) {
return Collections.emptyList();

View File

@ -168,6 +168,11 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
description = "(VMware only) true if VM deployments should preserve all the configurations defined for this template", since = "4.15.1")
protected Boolean deployAsIs;
@Parameter(name=ApiConstants.FOR_CKS,
type = CommandType.BOOLEAN,
description = "if true, the templates would be available for deploying CKS clusters", since = "4.21.0")
protected Boolean forCks;
@Parameter(name = ApiConstants.TEMPLATE_TYPE, type = CommandType.STRING,
description = "the type of the template. Valid options are: USER/VNF (for all users) and SYSTEM/ROUTING/BUILTIN (for admins only).",
since = "4.19.0")
@ -295,6 +300,10 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
Boolean.TRUE.equals(deployAsIs);
}
public boolean isForCks() {
return Boolean.TRUE.equals(forCks);
}
public String getTemplateType() {
return templateType;
}

View File

@ -46,6 +46,11 @@ public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd implements Use
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.", since = "4.20.0")
private String templateTag;
@Parameter(name = ApiConstants.FOR_CKS, type = CommandType.BOOLEAN,
description = "indicates that the template can be used for deployment of CKS clusters",
since = "4.21.0")
private Boolean forCks;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -63,6 +68,10 @@ public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd implements Use
return templateTag;
}
public Boolean getForCks() {
return forCks;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -0,0 +1,87 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.userdata;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.NetworkModel;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public abstract class BaseRegisterUserDataCmd extends BaseCmd {
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Name of the user data")
private String name;
//Owner information
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional account for the user data. 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 user data. If the account parameter is used, domainId must also be used.")
private Long domainId;
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "an optional project for the user data")
private Long projectId;
@Parameter(name = ApiConstants.PARAMS, type = CommandType.STRING, description = "comma separated list of variables declared in user data content")
private String params;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getName() {
return name;
}
public String getAccountName() {
return accountName;
}
public Long getDomainId() {
return domainId;
}
public Long getProjectId() {
return projectId;
}
public String getParams() {
checkForVRMetadataFileNames(params);
return params;
}
public void checkForVRMetadataFileNames(String params) {
if (StringUtils.isNotEmpty(params)) {
List<String> keyValuePairs = new ArrayList<>(Arrays.asList(params.split(",")));
keyValuePairs.retainAll(NetworkModel.metadataFileNames);
if (!keyValuePairs.isEmpty()) {
throw new InvalidParameterValueException(String.format("Params passed here have a few virtual router metadata file names %s", keyValuePairs));
}
}
}
}

View File

@ -0,0 +1,74 @@
// 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.userdata;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.context.CallContext;
import com.cloud.user.Account;
import com.cloud.user.UserData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@APICommand(name = "deleteCniConfiguration", description = "Deletes a CNI Configuration", responseObject = SuccessResponse.class, entityType = {UserData.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.21.0",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class DeleteCniConfigurationCmd extends DeleteUserDataCmd {
public static final Logger logger = LogManager.getLogger(DeleteCniConfigurationCmd.class.getName());
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() {
boolean result = _mgr.deleteCniConfiguration(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
response.setSuccess(result);
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete CNI configuration");
}
}
@Override
public long getEntityOwnerId() {
Account account = CallContext.current().getCallingAccount();
Long domainId = this.getDomainId();
String accountName = this.getAccountName();
if ((account == null || _accountService.isAdmin(account.getId())) && (domainId != null && accountName != null)) {
Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
if (userAccount != null) {
return userAccount.getId();
}
}
if (account != null) {
return account.getId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
}

View File

@ -0,0 +1,59 @@
// 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.userdata;
import com.cloud.user.UserData;
import com.cloud.utils.Pair;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.UserDataResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
@APICommand(name = "listCniConfiguration", description = "List user data for CNI plugins", responseObject = UserDataResponse.class, entityType = {UserData.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.21.0",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class ListCniConfigurationCmd extends ListUserDataCmd {
public static final Logger logger = LogManager.getLogger(ListCniConfigurationCmd.class.getName());
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() {
Pair<List<? extends UserData>, Integer> resultList = _mgr.listUserDatas(this, true);
List<UserDataResponse> responses = new ArrayList<>();
for (UserData result : resultList.first()) {
UserDataResponse r = _responseGenerator.createUserDataResponse(result);
r.setObjectName(ApiConstants.CNI_CONFIG);
responses.add(r);
}
ListResponse<UserDataResponse> response = new ListResponse<>();
response.setResponses(responses, resultList.second());
response.setResponseName(getCommandName());
setResponseObject(response);
}
}

View File

@ -61,7 +61,7 @@ public class ListUserDataCmd extends BaseListProjectAndAccountResourcesCmd {
@Override
public void execute() {
Pair<List<? extends UserData>, Integer> resultList = _mgr.listUserDatas(this);
Pair<List<? extends UserData>, Integer> resultList = _mgr.listUserDatas(this, false);
List<UserDataResponse> responses = new ArrayList<>();
for (UserData result : resultList.first()) {
UserDataResponse r = _responseGenerator.createUserDataResponse(result);

View File

@ -0,0 +1,77 @@
// 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.userdata;
import com.cloud.user.UserData;
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.response.SuccessResponse;
import org.apache.cloudstack.api.response.UserDataResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@APICommand(name = "registerCniConfiguration",
description = "Register a CNI Configuration to be used with CKS cluster",
since = "4.21.0",
responseObject = SuccessResponse.class,
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false,
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class RegisterCniConfigurationCmd extends BaseRegisterUserDataCmd {
public static final Logger logger = LogManager.getLogger(RegisterCniConfigurationCmd.class.getName());
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.CNI_CONFIG, type = CommandType.STRING, description = "CNI Configuration content to be registered as User data", length = 1048576)
private String cniConfig;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getCniConfig() {
return cniConfig;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() {
UserData result = _mgr.registerCniConfiguration(this);
UserDataResponse response = _responseGenerator.createUserDataResponse(result);
response.setResponseName(getCommandName());
response.setObjectName(ApiConstants.CNI_CONFIG);
setResponseObject(response);
}
@Override
public long getEntityOwnerId() {
Long accountId = _accountService.finalyzeAccountId(getAccountName(), getDomainId(), getProjectId(), true);
if (accountId == null) {
return CallContext.current().getCallingAccount().getId();
}
return accountId;
}
}

View File

@ -16,30 +16,20 @@
// under the License.
package org.apache.cloudstack.api.command.user.userdata;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.UserDataResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.commons.lang3.StringUtils;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.NetworkModel;
import com.cloud.user.UserData;
@APICommand(name = "registerUserData",
@ -49,89 +39,28 @@ import com.cloud.user.UserData;
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false,
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class RegisterUserDataCmd extends BaseCmd {
public class RegisterUserDataCmd extends BaseRegisterUserDataCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Name of the userdata")
private String name;
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.STRING, required = true, description = "User data content", length = 1048576)
protected String userData;
//Owner information
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional account for the userdata. 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 userdata. If the account parameter is used, domainId must also be used.")
private Long domainId;
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "an optional project for the userdata")
private Long projectId;
@Parameter(name = ApiConstants.USER_DATA,
type = CommandType.STRING,
required = true,
description = "Base64 encoded userdata content. " +
"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.PARAMS, type = CommandType.STRING, description = "comma separated list of variables declared in userdata content")
private String params;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getName() {
return name;
}
public String getAccountName() {
return accountName;
}
public Long getDomainId() {
return domainId;
}
public Long getProjectId() {
return projectId;
}
public String getUserData() {
return userData;
}
public String getParams() {
checkForVRMetadataFileNames(params);
return params;
}
public void checkForVRMetadataFileNames(String params) {
if (StringUtils.isNotEmpty(params)) {
List<String> keyValuePairs = new ArrayList<>(Arrays.asList(params.split(",")));
keyValuePairs.retainAll(NetworkModel.metadataFileNames);
if (!keyValuePairs.isEmpty()) {
throw new InvalidParameterValueException(String.format("Params passed here have a few virtual router metadata file names %s", keyValuePairs));
}
}
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public long getEntityOwnerId() {
Long accountId = _accountService.finalyzeAccountId(accountName, domainId, projectId, true);
Long accountId = _accountService.finalyzeAccountId(getAccountName(), getDomainId(), getProjectId(), true);
if (accountId == null) {
return CallContext.current().getCallingAccount().getId();
}

View File

@ -16,10 +16,15 @@
// under the License.
package org.apache.cloudstack.api.command.user.vm;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
@ -54,6 +59,7 @@ import com.cloud.cpu.CPU;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag;
import com.cloud.storage.GuestOS;
import com.cloud.vm.VirtualMachine;
@ -331,22 +337,75 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements
setResponseObject(response);
}
protected void updateVMResponse(List<UserVmResponse> response) {
for (UserVmResponse vmResponse : response) {
ResourceIcon resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.UserVm, vmResponse.getId());
if (resourceIcon == null) {
ResourceTag.ResourceObjectType type = ResourceTag.ResourceObjectType.Template;
String uuid = vmResponse.getTemplateId();
if (vmResponse.getIsoId() != null) {
uuid = vmResponse.getIsoId();
type = ResourceTag.ResourceObjectType.ISO;
}
resourceIcon = resourceIconManager.getByResourceTypeAndUuid(type, uuid);
if (resourceIcon == null) {
continue;
}
protected Map<String, ResourceIcon> getResourceIconsUsingOsCategory(List<UserVmResponse> responses) {
Set<String> guestOsIds = responses.stream().map(UserVmResponse::getGuestOsId).collect(Collectors.toSet());
List<GuestOS> guestOSList = _entityMgr.listByUuids(GuestOS.class, guestOsIds);
Map<String, GuestOS> guestOSMap = guestOSList.stream()
.collect(Collectors.toMap(GuestOS::getUuid, Function.identity()));
Set<Long> guestOsCategoryIds = guestOSMap.values().stream()
.map(GuestOS::getCategoryId)
.collect(Collectors.toSet());
Map<Long, ResourceIcon> guestOsCategoryIcons =
resourceIconManager.getByResourceTypeAndIds(ResourceTag.ResourceObjectType.GuestOsCategory,
guestOsCategoryIds);
Map<String, ResourceIcon> vmIcons = new HashMap<>();
for (UserVmResponse response : responses) {
GuestOS guestOS = guestOSMap.get(response.getGuestOsId());
if (guestOS != null) {
vmIcons.put(response.getId(), guestOsCategoryIcons.get(guestOS.getCategoryId()));
}
ResourceIconResponse iconResponse = _responseGenerator.createResourceIconResponse(resourceIcon);
}
return vmIcons;
}
protected Map<String, ResourceIcon> getResourceIconsForUsingTemplateIso(List<UserVmResponse> responses) {
Map<String, String> vmTemplateIsoIdMap = new HashMap<>();
Set<String> templateUuids = new HashSet<>();
Set<String> isoUuids = new HashSet<>();
for (UserVmResponse vmResponse : responses) {
if (vmResponse.getTemplateId() != null) {
templateUuids.add(vmResponse.getTemplateId());
vmTemplateIsoIdMap.put(vmResponse.getId(), vmResponse.getTemplateId());
}
if (vmResponse.getIsoId() != null) {
isoUuids.add(vmResponse.getIsoId());
vmTemplateIsoIdMap.put(vmResponse.getId(), vmResponse.getIsoId());
}
}
Map<String, ResourceIcon> templateOrIsoIcons = resourceIconManager.getByResourceTypeAndUuids(ResourceTag.ResourceObjectType.Template, templateUuids);
templateOrIsoIcons.putAll(resourceIconManager.getByResourceTypeAndUuids(ResourceTag.ResourceObjectType.ISO, isoUuids));
Map<String, ResourceIcon> vmIcons = new HashMap<>();
List<UserVmResponse> noTemplateIsoIconResponses = new ArrayList<>();
for (UserVmResponse response : responses) {
String uuid = vmTemplateIsoIdMap.get(response.getId());
if (StringUtils.isNotBlank(uuid) && templateOrIsoIcons.containsKey(uuid)) {
vmIcons.put(response.getId(),
templateOrIsoIcons.get(vmTemplateIsoIdMap.get(response.getId())));
continue;
}
noTemplateIsoIconResponses.add(response);
}
vmIcons.putAll(getResourceIconsUsingOsCategory(noTemplateIsoIconResponses));
return vmIcons;
}
protected void updateVMResponse(List<UserVmResponse> responses) {
if (CollectionUtils.isEmpty(responses)) {
return;
}
Set<String> vmUuids = responses.stream().map(UserVmResponse::getId).collect(Collectors.toSet());
Map<String, ResourceIcon> vmIcons = resourceIconManager.getByResourceTypeAndUuids(ResourceTag.ResourceObjectType.UserVm, vmUuids);
List<UserVmResponse> noVmIconResponses = responses
.stream()
.filter(r -> !vmIcons.containsKey(r.getId()))
.collect(Collectors.toList());
vmIcons.putAll(getResourceIconsForUsingTemplateIso(noVmIconResponses));
for (UserVmResponse vmResponse : responses) {
ResourceIcon icon = vmIcons.get(vmResponse.getId());
if (icon == null) {
continue;
}
ResourceIconResponse iconResponse = _responseGenerator.createResourceIconResponse(icon);
vmResponse.setResourceIconResponse(iconResponse);
}
}

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.api.command.user.vpc;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.cloudstack.acl.RoleType;
@ -125,6 +126,10 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd implements UserCmd {
@Parameter(name=ApiConstants.AS_NUMBER, type=CommandType.LONG, since = "4.20.0", description="the AS Number of the VPC tiers")
private Long asNumber;
@Parameter(name=ApiConstants.USE_VIRTUAL_ROUTER_IP_RESOLVER, type=CommandType.BOOLEAN,
description="(optional) for NSX based VPCs: when set to true, use the VR IP as nameserver, otherwise use DNS1 and DNS2")
private Boolean useVrIpResolver;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
@ -205,6 +210,10 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd implements UserCmd {
return asNumber;
}
public boolean getUseVrIpResolver() {
return BooleanUtils.toBoolean(useVrIpResolver);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -16,6 +16,8 @@
// under the License.
package org.apache.cloudstack.api.response;
import java.util.Date;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
@ -26,7 +28,7 @@ import com.cloud.serializer.Param;
import com.cloud.storage.GuestOsCategory;
@EntityReference(value = GuestOsCategory.class)
public class GuestOSCategoryResponse extends BaseResponse {
public class GuestOSCategoryResponse extends BaseResponse implements SetResourceIconResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the ID of the OS category")
private String id;
@ -35,6 +37,18 @@ public class GuestOSCategoryResponse extends BaseResponse {
@Param(description = "the name of the OS category")
private String name;
@SerializedName(ApiConstants.IS_FEATURED)
@Param(description = "Whether the OS category is featured", since = "4.21.0")
private Boolean featured;
@SerializedName(ApiConstants.RESOURCE_ICON)
@Param(description = "Base64 string representation of the resource icon", since = "4.21.0")
private ResourceIconResponse resourceIconResponse;
@SerializedName(ApiConstants.CREATED)
@Param(description = "Date when the OS category was created." )
private Date created;
public String getId() {
return id;
}
@ -50,4 +64,17 @@ public class GuestOSCategoryResponse extends BaseResponse {
public void setName(String name) {
this.name = name;
}
public void setFeatured(Boolean featured) {
this.featured = featured;
}
@Override
public void setResourceIconResponse(ResourceIconResponse resourceIconResponse) {
this.resourceIconResponse = resourceIconResponse;
}
public void setCreated(Date created) {
this.created = created;
}
}

View File

@ -0,0 +1,51 @@
// 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.response;
import com.cloud.network.router.VirtualRouter;
import com.cloud.serializer.Param;
import com.cloud.uservm.UserVm;
import com.cloud.vm.VirtualMachine;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.EntityReference;
@EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class})
public class KubernetesUserVmResponse extends UserVmResponse {
@SerializedName(ApiConstants.IS_EXTERNAL_NODE)
@Param(description = "If the VM is an externally added node")
private boolean isExternalNode;
@SerializedName(ApiConstants.IS_ETCD_NODE)
@Param(description = "If the VM is an etcd node")
private boolean isEtcdNode;
@SerializedName(ApiConstants.KUBERNETES_NODE_VERSION)
@Param(description = "Kubernetes version of the node")
private String nodeVersion;
public void setExternalNode(boolean externalNode) {
isExternalNode = externalNode;
}
public void setEtcdNode(boolean etcdNode) {
isEtcdNode = etcdNode;
}
public void setNodeVersion(String nodeVersion) { this.nodeVersion = nodeVersion;}
}

View File

@ -93,6 +93,8 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements
@Param(description = "the name of the OS type for this template.")
private String osTypeName;
private transient Long osTypeCategoryId;
@SerializedName(ApiConstants.ACCOUNT_ID)
@Param(description = "the account id to which the template belongs")
private String accountId;
@ -208,6 +210,11 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements
since = "4.15")
private Boolean deployAsIs;
@SerializedName(ApiConstants.FOR_CKS)
@Param(description = "If true it indicates that the template can be used for CKS cluster deployments",
since = "4.21.0")
private Boolean forCks;
@SerializedName(ApiConstants.DEPLOY_AS_IS_DETAILS)
@Param(description = "VMware only: additional key/value details tied with deploy-as-is template",
since = "4.15")
@ -285,6 +292,14 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements
this.osTypeName = osTypeName;
}
public Long getOsTypeCategoryId() {
return osTypeCategoryId;
}
public void setOsTypeCategoryId(Long osTypeCategoryId) {
this.osTypeCategoryId = osTypeCategoryId;
}
public void setId(String id) {
this.id = id;
}
@ -453,6 +468,10 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements
this.deployAsIs = deployAsIs;
}
public void setForCks(Boolean forCks) {
this.forCks = forCks;
}
public void setParentTemplateId(String parentTemplateId) {
this.parentTemplateId = parentTemplateId;
}

View File

@ -0,0 +1,46 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.admin.guest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class AddGuestOsCategoryCmdTest {
@Test
public void testGetArch() {
AddGuestOsCategoryCmd cmd = new AddGuestOsCategoryCmd();
Assert.assertNull(cmd.getName());
String name = "Name";
ReflectionTestUtils.setField(cmd, "name", name);
Assert.assertEquals(name, cmd.getName());
}
@Test
public void testIsFeatured() {
AddGuestOsCategoryCmd cmd = new AddGuestOsCategoryCmd();
Assert.assertFalse(cmd.isFeatured());
ReflectionTestUtils.setField(cmd, "featured", false);
Assert.assertFalse(cmd.isFeatured());
ReflectionTestUtils.setField(cmd, "featured", true);
Assert.assertTrue(cmd.isFeatured());
}
}

View File

@ -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.guest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class UpdateGuestOsCategoryCmdTest {
@Test
public void testGetArch() {
UpdateGuestOsCategoryCmd cmd = new UpdateGuestOsCategoryCmd();
Assert.assertNull(cmd.getName());
String name = "Name";
ReflectionTestUtils.setField(cmd, "name", name);
Assert.assertEquals(name, cmd.getName());
}
@Test
public void testIsFeatured() {
UpdateGuestOsCategoryCmd cmd = new UpdateGuestOsCategoryCmd();
Assert.assertNull(cmd.isFeatured());
ReflectionTestUtils.setField(cmd, "featured", false);
Assert.assertFalse(cmd.isFeatured());
ReflectionTestUtils.setField(cmd, "featured", true);
Assert.assertTrue(cmd.isFeatured());
}
@Test
public void testGetSortKey() {
UpdateGuestOsCategoryCmd cmd = new UpdateGuestOsCategoryCmd();
Assert.assertNull(cmd.getSortKey());
Integer sortKey = 100;
ReflectionTestUtils.setField(cmd, "sortKey", sortKey);
Assert.assertEquals(sortKey, cmd.getSortKey());
}
}

View File

@ -0,0 +1,37 @@
// 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.guest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class UpdateGuestOsCmdTest {
@Test
public void testGetZoneId() {
UpdateGuestOsCmd cmd = new UpdateGuestOsCmd();
Assert.assertNull(cmd.getOsCategoryId());
Long osCategoryId = 100L;
ReflectionTestUtils.setField(cmd, "osCategoryId", osCategoryId);
Assert.assertEquals(osCategoryId, cmd.getOsCategoryId());
}
}

View File

@ -0,0 +1,87 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.guest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import com.cloud.cpu.CPU;
@RunWith(MockitoJUnitRunner.class)
public class ListGuestOsCategoriesCmdTest {
@Test
public void testIsFeatured() {
ListGuestOsCategoriesCmd cmd = new ListGuestOsCategoriesCmd();
Assert.assertNull(cmd.isFeatured());
ReflectionTestUtils.setField(cmd, "featured", false);
Assert.assertFalse(cmd.isFeatured());
ReflectionTestUtils.setField(cmd, "featured", true);
Assert.assertTrue(cmd.isFeatured());
}
@Test
public void testIsIso() {
ListGuestOsCategoriesCmd cmd = new ListGuestOsCategoriesCmd();
Assert.assertNull(cmd.isIso());
ReflectionTestUtils.setField(cmd, "iso", false);
Assert.assertFalse(cmd.isIso());
ReflectionTestUtils.setField(cmd, "iso", true);
Assert.assertTrue(cmd.isIso());
}
@Test
public void testIsVnf() {
ListGuestOsCategoriesCmd cmd = new ListGuestOsCategoriesCmd();
Assert.assertNull(cmd.isVnf());
ReflectionTestUtils.setField(cmd, "vnf", false);
Assert.assertFalse(cmd.isVnf());
ReflectionTestUtils.setField(cmd, "vnf", true);
Assert.assertTrue(cmd.isVnf());
}
@Test
public void testGetZoneId() {
ListGuestOsCategoriesCmd cmd = new ListGuestOsCategoriesCmd();
Assert.assertNull(cmd.getZoneId());
Long zoneId = 100L;
ReflectionTestUtils.setField(cmd, "zoneId", zoneId);
Assert.assertEquals(zoneId, cmd.getZoneId());
}
@Test
public void testGetArch() {
ListGuestOsCategoriesCmd cmd = new ListGuestOsCategoriesCmd();
Assert.assertNull(cmd.getArch());
CPU.CPUArch arch = CPU.CPUArch.getDefault();
ReflectionTestUtils.setField(cmd, "arch", arch.getType());
Assert.assertEquals(arch, cmd.getArch());
}
@Test
public void testIsShowIcon() {
ListGuestOsCategoriesCmd cmd = new ListGuestOsCategoriesCmd();
Assert.assertFalse(cmd.isShowIcon());
ReflectionTestUtils.setField(cmd, "showIcon", false);
Assert.assertFalse(cmd.isShowIcon());
ReflectionTestUtils.setField(cmd, "showIcon", true);
Assert.assertTrue(cmd.isShowIcon());
}
}

View File

@ -68,7 +68,7 @@ public class ListUserDataCmdTest {
Pair<List<? extends UserData>, Integer> result = new Pair<List<? extends UserData>, Integer>(userDataList, 1);
UserDataResponse userDataResponse = Mockito.mock(UserDataResponse.class);
Mockito.when(_mgr.listUserDatas(cmd)).thenReturn(result);
Mockito.when(_mgr.listUserDatas(cmd, false)).thenReturn(result);
Mockito.when(_responseGenerator.createUserDataResponse(userData)).thenReturn(userDataResponse);
cmd.execute();
@ -82,7 +82,7 @@ public class ListUserDataCmdTest {
List<UserData> userDataList = new ArrayList<UserData>();
Pair<List<? extends UserData>, Integer> result = new Pair<List<? extends UserData>, Integer>(userDataList, 0);
Mockito.when(_mgr.listUserDatas(cmd)).thenReturn(result);
Mockito.when(_mgr.listUserDatas(cmd, false)).thenReturn(result);
cmd.execute();

View File

@ -0,0 +1,223 @@
// 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.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.anyList;
import static org.mockito.Mockito.anySet;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.cloudstack.api.ResponseGenerator;
import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceIconManager;
import com.cloud.server.ResourceTag;
import com.cloud.storage.GuestOS;
import com.cloud.utils.db.EntityManager;
public class ListVMsCmdTest {
EntityManager _entityMgr;
ResourceIconManager resourceIconManager;
ResponseGenerator _responseGenerator;
ListVMsCmd cmd;
@Before
public void setup() {
_entityMgr = mock(EntityManager.class);
resourceIconManager = mock(ResourceIconManager.class);
_responseGenerator = mock(ResponseGenerator.class);
cmd = spy(ListVMsCmd.class);
cmd._entityMgr = _entityMgr;
cmd.resourceIconManager = resourceIconManager;
cmd._responseGenerator = _responseGenerator;
}
@Test
public void testUpdateVMResponse_withMixedIcons() {
String vm1Uuid = UUID.randomUUID().toString();
UserVmResponse vm1 = mock(UserVmResponse.class);
when(vm1.getId()).thenReturn(vm1Uuid);
String vm2Uuid = UUID.randomUUID().toString();
UserVmResponse vm2 = mock(UserVmResponse.class);
when(vm2.getId()).thenReturn(vm2Uuid);
List<UserVmResponse> responses = Arrays.asList(vm1, vm2);
ResourceIcon icon1 = mock(ResourceIcon.class);
ResourceIcon icon2 = mock(ResourceIcon.class);
Map<String, ResourceIcon> initialIcons = new HashMap<>();
initialIcons.put(vm1Uuid, icon1);
when(resourceIconManager.getByResourceTypeAndUuids(ResourceTag.ResourceObjectType.UserVm, Set.of(vm1Uuid, vm2Uuid)))
.thenReturn(initialIcons);
Map<String, ResourceIcon> fallbackIcons = Map.of(vm2Uuid, icon2);
doReturn(fallbackIcons).when(cmd).getResourceIconsForUsingTemplateIso(anyList());
ResourceIconResponse iconResponse1 = new ResourceIconResponse();
ResourceIconResponse iconResponse2 = new ResourceIconResponse();
when(_responseGenerator.createResourceIconResponse(icon1)).thenReturn(iconResponse1);
when(_responseGenerator.createResourceIconResponse(icon2)).thenReturn(iconResponse2);
cmd.updateVMResponse(responses);
verify(vm1).setResourceIconResponse(iconResponse1);
verify(vm2).setResourceIconResponse(iconResponse2);
}
@Test
public void testUpdateVMResponse_withEmptyList() {
cmd.updateVMResponse(Collections.emptyList());
verify(resourceIconManager, never()).getByResourceTypeAndIds(Mockito.any(), Mockito.anyCollection());
}
@Test
public void testGetResourceIconsForUsingTemplateIso_withValidData() {
String vm1Uuid = UUID.randomUUID().toString();
String template1Uuid = UUID.randomUUID().toString();
UserVmResponse vm1 = mock(UserVmResponse.class);
when(vm1.getId()).thenReturn(vm1Uuid);
when(vm1.getTemplateId()).thenReturn(template1Uuid);
when(vm1.getIsoId()).thenReturn(null);
String vm2Uuid = UUID.randomUUID().toString();
String iso2Uuid = UUID.randomUUID().toString();
UserVmResponse vm2 = mock(UserVmResponse.class);
when(vm2.getId()).thenReturn(vm2Uuid);
when(vm2.getTemplateId()).thenReturn(null);
when(vm2.getIsoId()).thenReturn(iso2Uuid);
List<UserVmResponse> responses = Arrays.asList(vm1, vm2);
Map<String, ResourceIcon> templateIcons = new HashMap<>();
templateIcons.put(template1Uuid, mock(ResourceIcon.class));
Map<String, ResourceIcon> isoIcons = new HashMap<>();
isoIcons.put(iso2Uuid, mock(ResourceIcon.class));
when(resourceIconManager.getByResourceTypeAndUuids(ResourceTag.ResourceObjectType.Template, Set.of(template1Uuid)))
.thenReturn(templateIcons);
when(resourceIconManager.getByResourceTypeAndUuids(ResourceTag.ResourceObjectType.ISO, Set.of(iso2Uuid)))
.thenReturn(isoIcons);
doReturn(Collections.emptyMap()).when(cmd).getResourceIconsUsingOsCategory(anyList());
Map<String, ResourceIcon> result = cmd.getResourceIconsForUsingTemplateIso(responses);
assertEquals(2, result.size());
assertTrue(result.containsKey(vm1Uuid));
assertTrue(result.containsKey(vm2Uuid));
assertEquals(templateIcons.get(template1Uuid), result.get(vm1Uuid));
assertEquals(isoIcons.get(iso2Uuid), result.get(vm2Uuid));
}
@Test
public void testGetResourceIconsForUsingTemplateIso_withMissingIcons() {
String vm1Uuid = UUID.randomUUID().toString();
String template1Uuid = UUID.randomUUID().toString();
UserVmResponse vm1 = mock(UserVmResponse.class);
when(vm1.getId()).thenReturn(vm1Uuid);
when(vm1.getTemplateId()).thenReturn(template1Uuid);
when(vm1.getIsoId()).thenReturn(null);
List<UserVmResponse> responses = List.of(vm1);
when(resourceIconManager.getByResourceTypeAndUuids(eq(ResourceTag.ResourceObjectType.Template), anySet()))
.thenReturn(Collections.emptyMap());
when(resourceIconManager.getByResourceTypeAndUuids(eq(ResourceTag.ResourceObjectType.ISO), anySet()))
.thenReturn(Collections.emptyMap());
Map<String, ResourceIcon> fallbackIcons = Map.of(vm1Uuid, mock(ResourceIcon.class));
doReturn(fallbackIcons).when(cmd).getResourceIconsUsingOsCategory(anyList());
Map<String, ResourceIcon> result = cmd.getResourceIconsForUsingTemplateIso(responses);
assertEquals(1, result.size());
assertEquals(fallbackIcons.get("vm1"), result.get("vm1"));
}
@Test
public void testGetResourceIconsUsingOsCategory_withValidData() {
String vm1Uuid = UUID.randomUUID().toString();
String os1Uuid = UUID.randomUUID().toString();
UserVmResponse vm1 = mock(UserVmResponse.class);
when(vm1.getGuestOsId()).thenReturn(os1Uuid);
when(vm1.getId()).thenReturn(vm1Uuid);
String vm2Uuid = UUID.randomUUID().toString();
String os2Uuid = UUID.randomUUID().toString();
UserVmResponse vm2 = mock(UserVmResponse.class);
when(vm2.getGuestOsId()).thenReturn(os2Uuid);
when(vm2.getId()).thenReturn(vm2Uuid);
List<UserVmResponse> responses = Arrays.asList(vm1, vm2);
GuestOS guestOS1 = mock(GuestOS.class);
when(guestOS1.getUuid()).thenReturn(os1Uuid);
when(guestOS1.getCategoryId()).thenReturn(10L);
GuestOS guestOS2 = mock(GuestOS.class);
when(guestOS2.getUuid()).thenReturn(os2Uuid);
when(guestOS2.getCategoryId()).thenReturn(20L);
when(_entityMgr.listByUuids(eq(GuestOS.class), anySet()))
.thenReturn(Arrays.asList(guestOS1, guestOS2));
ResourceIcon icon1 = mock(ResourceIcon.class);
ResourceIcon icon2 = mock(ResourceIcon.class);
Map<Long, ResourceIcon> categoryIcons = new HashMap<>();
categoryIcons.put(10L, icon1);
categoryIcons.put(20L, icon2);
when(resourceIconManager.getByResourceTypeAndIds(eq(ResourceTag.ResourceObjectType.GuestOsCategory), anySet()))
.thenReturn(categoryIcons);
Map<String, ResourceIcon> result = cmd.getResourceIconsUsingOsCategory(responses);
assertEquals(2, result.size());
assertEquals(icon1, result.get(vm1Uuid));
assertEquals(icon2, result.get(vm2Uuid));
}
@Test
public void testGetResourceIconsUsingOsCategory_missingGuestOS() {
String vm1Uuid = UUID.randomUUID().toString();
String os1Uuid = UUID.randomUUID().toString();
UserVmResponse vm1 = mock(UserVmResponse.class);
when(vm1.getGuestOsId()).thenReturn(vm1Uuid);
when(vm1.getId()).thenReturn(os1Uuid);
List<UserVmResponse> responses = Collections.singletonList(vm1);
when(_entityMgr.listByUuids(eq(GuestOS.class), anySet()))
.thenReturn(Collections.emptyList());
Map<String, ResourceIcon> result = cmd.getResourceIconsUsingOsCategory(responses);
assertTrue(result.isEmpty());
}
@Test
public void testGetResourceIconsUsingOsCategory_missingIcon() {
UserVmResponse vm1 = mock(UserVmResponse.class);
String vmUuid = UUID.randomUUID().toString();
String osUuid = UUID.randomUUID().toString();
when(vm1.getGuestOsId()).thenReturn(osUuid);
when(vm1.getId()).thenReturn(vmUuid);
List<UserVmResponse> responses = Collections.singletonList(vm1);
GuestOS guestOS1 = mock(GuestOS.class);
when(guestOS1.getCategoryId()).thenReturn(10L);
when(guestOS1.getUuid()).thenReturn(osUuid);
when(_entityMgr.listByUuids(eq(GuestOS.class), anySet()))
.thenReturn(Collections.singletonList(guestOS1));
when(resourceIconManager.getByResourceTypeAndIds(eq(ResourceTag.ResourceObjectType.GuestOsCategory), anySet()))
.thenReturn(Collections.emptyMap());
Map<String, ResourceIcon> result = cmd.getResourceIconsUsingOsCategory(responses);
assertTrue(result.containsKey(vmUuid));
assertNull(result.get(vmUuid));
}
}

View File

@ -0,0 +1,34 @@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
package com.cloud.agent.api;
import com.cloud.agent.api.routing.NetworkElementCommand;
public class HandleCksIsoCommand extends NetworkElementCommand {
private boolean mountCksIso;
public HandleCksIsoCommand(boolean mountCksIso) {
this.mountCksIso = mountCksIso;
}
public boolean isMountCksIso() {
return mountCksIso;
}
}

View File

@ -82,5 +82,8 @@ public class VRScripts {
public static final String VR_UPDATE_INTERFACE_CONFIG = "update_interface_config.sh";
public static final String ROUTER_FILESYSTEM_WRITABLE_CHECK = "filesystem_writable_check.py";
// CKS ISO mount
public static final String CKS_ISO_MOUNT_SERVE = "cks_iso.sh";
public static final String MANAGE_SERVICE = "manage_service.sh";
}

View File

@ -34,6 +34,7 @@ import java.util.concurrent.locks.ReentrantLock;
import javax.naming.ConfigurationException;
import com.cloud.agent.api.HandleCksIsoCommand;
import org.apache.cloudstack.agent.routing.ManageServiceCommand;
import com.cloud.agent.api.routing.UpdateNetworkCommand;
import com.cloud.agent.api.to.IpAddressTO;
@ -145,6 +146,10 @@ public class VirtualRoutingResource {
return execute((UpdateNetworkCommand) cmd);
}
if (cmd instanceof HandleCksIsoCommand) {
return execute((HandleCksIsoCommand) cmd);
}
if (cmd instanceof ManageServiceCommand) {
return execute((ManageServiceCommand) cmd);
}
@ -176,6 +181,13 @@ public class VirtualRoutingResource {
}
}
protected Answer execute(final HandleCksIsoCommand cmd) {
String routerIp = getRouterSshControlIp(cmd);
logger.info("Attempting to mount CKS ISO on Virtual Router");
ExecutionResult result = _vrDeployer.executeInVR(routerIp, VRScripts.CKS_ISO_MOUNT_SERVE, String.valueOf(cmd.isMountCksIso()));
return new Answer(cmd, result.isSuccess(), result.getDetails());
}
private Answer execute(final SetupKeyStoreCommand cmd) {
final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties " +
"/usr/local/cloud/systemvm/conf/%s " +

View File

@ -29,13 +29,15 @@ public class SetupMSListCommand extends Command {
private List<String> avoidMsList;
private String lbAlgorithm;
private Long lbCheckInterval;
private Boolean triggerHostLb;
public SetupMSListCommand(final List<String> msList, final List<String> avoidMsList, final String lbAlgorithm, final Long lbCheckInterval) {
public SetupMSListCommand(final List<String> msList, final List<String> avoidMsList, final String lbAlgorithm, final Long lbCheckInterval, final Boolean triggerHostLb) {
super();
this.msList = msList;
this.avoidMsList = avoidMsList;
this.lbAlgorithm = lbAlgorithm;
this.lbCheckInterval = lbCheckInterval;
this.triggerHostLb = triggerHostLb;
}
public List<String> getMsList() {
@ -54,9 +56,12 @@ public class SetupMSListCommand extends Command {
return lbCheckInterval;
}
public boolean getTriggerHostLb() {
return triggerHostLb;
}
@Override
public boolean executeInSequence() {
return false;
}
}

8
debian/rules vendored
View File

@ -70,6 +70,7 @@ override_dh_auto_install:
mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management/lib
mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management/setup
mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management/templates/systemvm
mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-management/cks/conf
mkdir $(DESTDIR)/var/log/$(PACKAGE)/management
mkdir $(DESTDIR)/var/cache/$(PACKAGE)/management
mkdir $(DESTDIR)/var/log/$(PACKAGE)/ipallocator
@ -83,6 +84,7 @@ override_dh_auto_install:
cp client/target/cloud-client-ui-$(VERSION).jar $(DESTDIR)/usr/share/$(PACKAGE)-management/lib/cloudstack-$(VERSION).jar
cp client/target/lib/*jar $(DESTDIR)/usr/share/$(PACKAGE)-management/lib/
cp -r engine/schema/dist/systemvm-templates/* $(DESTDIR)/usr/share/$(PACKAGE)-management/templates/systemvm/
cp -r plugins/integrations/kubernetes-service/src/main/resources/conf/* $(DESTDIR)/usr/share/$(PACKAGE)-management/cks/conf/
rm -rf $(DESTDIR)/usr/share/$(PACKAGE)-management/templates/systemvm/md5sum.txt
# Bundle cmk in cloudstack-management
@ -95,6 +97,12 @@ override_dh_auto_install:
chmod 0440 $(DESTDIR)/$(SYSCONFDIR)/sudoers.d/$(PACKAGE)
install -D client/target/utilities/bin/cloud-update-xenserver-licenses $(DESTDIR)/usr/bin/cloudstack-update-xenserver-licenses
install -D plugins/integrations/kubernetes-service/src/main/resources/conf/etcd-node.yml $(DESTDIR)/usr/share/$(PACKAGE)-management/cks/conf/etcd-node.yml
install -D plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml $(DESTDIR)/usr/share/$(PACKAGE)-management/cks/conf/k8s-control-node.yml
install -D plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml $(DESTDIR)/usr/share/$(PACKAGE)-management/cks/conf/k8s-control-node-add.yml
install -D plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml $(DESTDIR)/usr/share/$(PACKAGE)-management/cks/conf/k8s-node.yml
# Remove configuration in /ur/share/cloudstack-management/webapps/client/WEB-INF
# This should all be in /etc/cloudstack/management
ln -s ../../..$(SYSCONFDIR)/$(PACKAGE)/management $(DESTDIR)/usr/share/$(PACKAGE)-management/conf

View File

@ -171,5 +171,5 @@ public interface AgentManager {
void propagateChangeToAgents(Map<String, String> params);
boolean transferDirectAgentsFromMS(String fromMsUuid, long fromMsId, long timeoutDurationInMs);
boolean transferDirectAgentsFromMS(String fromMsUuid, long fromMsId, long timeoutDurationInMs, boolean excludeHostsInMaintenance);
}

View File

@ -62,6 +62,7 @@ import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.ThreadContext;
@ -273,8 +274,6 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
_executor = new ThreadPoolExecutor(agentTaskThreads, agentTaskThreads, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("AgentTaskPool"));
initConnectExecutor();
maxConcurrentNewAgentConnections = RemoteAgentMaxConcurrentNewConnections.value();
_connection = new NioServer("AgentManager", Port.value(), Workers.value() + 10,
@ -803,11 +802,25 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
Map<String, String> detailsMap = readyAnswer.getDetailsMap();
if (detailsMap != null) {
String uefiEnabled = detailsMap.get(Host.HOST_UEFI_ENABLE);
String virtv2vVersion = detailsMap.get(Host.HOST_VIRTV2V_VERSION);
String ovftoolVersion = detailsMap.get(Host.HOST_OVFTOOL_VERSION);
logger.debug("Got HOST_UEFI_ENABLE [{}] for host [{}]:", uefiEnabled, host);
if (uefiEnabled != null) {
if (ObjectUtils.anyNotNull(uefiEnabled, virtv2vVersion, ovftoolVersion)) {
_hostDao.loadDetails(host);
boolean updateNeeded = false;
if (!uefiEnabled.equals(host.getDetails().get(Host.HOST_UEFI_ENABLE))) {
host.getDetails().put(Host.HOST_UEFI_ENABLE, uefiEnabled);
updateNeeded = true;
}
if (StringUtils.isNotBlank(virtv2vVersion) && !virtv2vVersion.equals(host.getDetails().get(Host.HOST_VIRTV2V_VERSION))) {
host.getDetails().put(Host.HOST_VIRTV2V_VERSION, virtv2vVersion);
updateNeeded = true;
}
if (StringUtils.isNotBlank(ovftoolVersion) && !ovftoolVersion.equals(host.getDetails().get(Host.HOST_OVFTOOL_VERSION))) {
host.getDetails().put(Host.HOST_OVFTOOL_VERSION, ovftoolVersion);
updateNeeded = true;
}
if (updateNeeded) {
_hostDao.saveDetails(host);
}
}
@ -828,6 +841,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
return true;
}
initConnectExecutor();
startDirectlyConnectedHosts(false);
if (_connection != null) {
@ -2193,7 +2207,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
}
@Override
public boolean transferDirectAgentsFromMS(String fromMsUuid, long fromMsId, long timeoutDurationInMs) {
public boolean transferDirectAgentsFromMS(String fromMsUuid, long fromMsId, long timeoutDurationInMs, boolean excludeHostsInMaintenance) {
return true;
}

View File

@ -42,6 +42,7 @@ import javax.naming.ConfigurationException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import com.cloud.resource.ResourceState;
import org.apache.cloudstack.ca.CAManager;
import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.cloudstack.framework.config.ConfigKey;
@ -431,10 +432,10 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
ch = connectToPeer(peer, ch);
if (ch == null) {
try {
logD(bytes, "Unable to route to peer: " + Request.parse(bytes));
logD(bytes, "Unable to establish connection to route to peer: " + Request.parse(bytes));
} catch (ClassNotFoundException | UnsupportedVersionException e) {
// Request.parse thrown exception when we try to log it, log as much as we can
logD(bytes, "Unable to route to peer, and Request.parse further caught exception" + e.getMessage());
logD(bytes, "Unable to establish connection to route to peer, and Request.parse further caught exception" + e.getMessage());
}
return false;
}
@ -643,7 +644,6 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
final Link link = task.getLink();
if (Request.fromServer(data)) {
final AgentAttache agent = findAttache(hostId);
if (Request.isControl(data)) {
@ -691,7 +691,6 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
cancel(Long.toString(Request.getManagementServerId(data)), hostId, Request.getSequence(data), e.getMessage());
}
} else {
final long mgmtId = Request.getManagementServerId(data);
if (mgmtId != -1 && mgmtId != _nodeId) {
routeToPeer(Long.toString(mgmtId), data);
@ -1352,7 +1351,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
if (cmd instanceof PrepareForMaintenanceManagementServerHostCommand) {
logger.debug("Received PrepareForMaintenanceManagementServerHostCommand - preparing for maintenance");
try {
managementServerMaintenanceManager.prepareForMaintenance(((PrepareForMaintenanceManagementServerHostCommand) cmd).getLbAlgorithm());
managementServerMaintenanceManager.prepareForMaintenance(((PrepareForMaintenanceManagementServerHostCommand) cmd).getLbAlgorithm(), ((PrepareForMaintenanceManagementServerHostCommand) cmd).isForced());
return "Successfully prepared for maintenance";
} catch(CloudRuntimeException e) {
return e.getMessage();
@ -1399,14 +1398,14 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
}
@Override
public boolean transferDirectAgentsFromMS(String fromMsUuid, long fromMsId, long timeoutDurationInMs) {
public boolean transferDirectAgentsFromMS(String fromMsUuid, long fromMsId, long timeoutDurationInMs, boolean excludeHostsInMaintenance) {
if (timeoutDurationInMs <= 0) {
logger.debug("Not transferring direct agents from management server node {} (id: {}) to other nodes, invalid timeout duration", fromMsId, fromMsUuid);
return false;
}
long transferStartTimeInMs = System.currentTimeMillis();
if (CollectionUtils.isEmpty(getDirectAgentHosts(fromMsId))) {
if (CollectionUtils.isEmpty(getDirectAgentHosts(fromMsId, excludeHostsInMaintenance))) {
logger.info("No direct agent hosts available on management server node {} (id: {}), to transfer", fromMsId, fromMsUuid);
return true;
}
@ -1421,7 +1420,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
int agentTransferFailedCount = 0;
List<DataCenterVO> dataCenterList = dcDao.listAll();
for (DataCenterVO dc : dataCenterList) {
List<HostVO> directAgentHostsInDc = getDirectAgentHostsInDc(fromMsId, dc.getId());
List<HostVO> directAgentHostsInDc = getDirectAgentHostsInDc(fromMsId, dc.getId(), excludeHostsInMaintenance);
if (CollectionUtils.isEmpty(directAgentHostsInDc)) {
continue;
}
@ -1455,9 +1454,10 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
return (agentTransferFailedCount == 0);
}
private List<HostVO> getDirectAgentHosts(long msId) {
private List<HostVO> getDirectAgentHosts(long msId, boolean excludeHostsInMaintenance) {
List<HostVO> directAgentHosts = new ArrayList<>();
List<HostVO> hosts = _hostDao.listHostsByMs(msId);
List<ResourceState> statesToExclude = excludeHostsInMaintenance ? ResourceState.s_maintenanceStates : List.of();
List<HostVO> hosts = _hostDao.listHostsByMsResourceState(msId, statesToExclude);
for (HostVO host : hosts) {
AgentAttache agent = findAttache(host.getId());
if (agent instanceof DirectAgentAttache) {
@ -1468,9 +1468,11 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
return directAgentHosts;
}
private List<HostVO> getDirectAgentHostsInDc(long msId, long dcId) {
private List<HostVO> getDirectAgentHostsInDc(long msId, long dcId, boolean excludeHostsInMaintenance) {
List<HostVO> directAgentHosts = new ArrayList<>();
List<HostVO> hosts = _hostDao.listHostsByMsAndDc(msId, dcId);
// To exclude maintenance states use values from ResourceState as source of truth
List<ResourceState> statesToExclude = excludeHostsInMaintenance ? ResourceState.s_maintenanceStates : List.of();
List<HostVO> hosts = _hostDao.listHostsByMsDcResourceState(msId, dcId, statesToExclude);
for (HostVO host : hosts) {
AgentAttache agent = findAttache(host.getId());
if (agent instanceof DirectAgentAttache) {
@ -1506,6 +1508,10 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
public void onManagementServerCancelPreparingForMaintenance() {
logger.debug("Management server cancel preparing for maintenance");
super.onManagementServerPreparingForMaintenance();
// needed for the case when Management Server in Preparing For Maintenance but didn't go to Maintenance state
// (where this variable will be reset)
_agentLbHappened = false;
}
@Override

View File

@ -177,14 +177,24 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
List<HostVO> listHostsByMsAndDc(long msId, long dcId);
List<HostVO> listHostsByMsDcResourceState(long msId, long dcId, List<ResourceState> excludedResourceStates);
List<HostVO> listHostsByMs(long msId);
List<HostVO> listHostsByMsResourceState(long msId, List<ResourceState> excludedResourceStates);
/**
* Retrieves the number of hosts/agents this {@see ManagementServer} has responsibility over.
* @param msId the id of the {@see ManagementServer}
* @return the number of hosts/agents this {@see ManagementServer} has responsibility over
* Count Hosts by given Management Server, Host and Hypervisor Types,
* and exclude Hosts with given Resource States.
*
* @param msId Management Server Id
* @param excludedResourceStates Resource States to be excluded
* @param hostTypes Host Types
* @param hypervisorTypes Hypervisor Types
* @return Hosts count
*/
int countByMs(long msId);
int countHostsByMsResourceStateTypeAndHypervisorType(long msId, List<ResourceState> excludedResourceStates,
List<Type> hostTypes, List<HypervisorType> hypervisorTypes);
/**
* Retrieves the host ids/agents this {@see ManagementServer} has responsibility over.

View File

@ -72,6 +72,7 @@ import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.QueryBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
@ -1600,6 +1601,17 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
return listBy(sc);
}
@Override
public List<HostVO> listHostsByMsDcResourceState(long msId, long dcId, List<ResourceState> excludedResourceStates) {
QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class);
sc.and(sc.entity().getManagementServerId(), Op.EQ, msId);
sc.and(sc.entity().getDataCenterId(), Op.EQ, dcId);
if (CollectionUtils.isNotEmpty(excludedResourceStates)) {
sc.and(sc.entity().getResourceState(), Op.NIN, excludedResourceStates.toArray());
}
return listBy(sc.create());
}
@Override
public List<HostVO> listHostsByMs(long msId) {
SearchCriteria<HostVO> sc = ResponsibleMsSearch.create();
@ -1608,10 +1620,32 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
}
@Override
public int countByMs(long msId) {
SearchCriteria<HostVO> sc = ResponsibleMsSearch.create();
sc.setParameters("managementServerId", msId);
return getCount(sc);
public List<HostVO> listHostsByMsResourceState(long msId, List<ResourceState> excludedResourceStates) {
QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class);
sc.and(sc.entity().getManagementServerId(), Op.EQ, msId);
if (CollectionUtils.isNotEmpty(excludedResourceStates)) {
sc.and(sc.entity().getResourceState(), Op.NIN, excludedResourceStates.toArray());
}
return listBy(sc.create());
}
@Override
public int countHostsByMsResourceStateTypeAndHypervisorType(long msId,
List<ResourceState> excludedResourceStates,
List<Type> hostTypes,
List<HypervisorType> hypervisorTypes) {
QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class);
sc.and(sc.entity().getManagementServerId(), Op.EQ, msId);
if (CollectionUtils.isNotEmpty(excludedResourceStates)) {
sc.and(sc.entity().getResourceState(), Op.NIN, excludedResourceStates.toArray());
}
if (CollectionUtils.isNotEmpty(hostTypes)) {
sc.and(sc.entity().getType(), Op.IN, hostTypes.toArray());
}
if (CollectionUtils.isNotEmpty(hypervisorTypes)) {
sc.and(sc.entity().getHypervisorType(), Op.IN, hypervisorTypes.toArray());
}
return getCount(sc.create());
}
@Override

View File

@ -75,5 +75,7 @@ public interface FirewallRulesDao extends GenericDao<FirewallRuleVO, Long> {
void loadDestinationCidrs(FirewallRuleVO rule);
FirewallRuleVO findByNetworkIdAndPorts(long networkId, int startPort, int endPort);
List<FirewallRuleVO> listRoutingIngressFirewallRules(long networkId);
}

View File

@ -48,6 +48,7 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
protected final SearchBuilder<FirewallRuleVO> NotRevokedSearch;
protected final SearchBuilder<FirewallRuleVO> ReleaseSearch;
protected SearchBuilder<FirewallRuleVO> VmSearch;
protected SearchBuilder<FirewallRuleVO> FirewallByPortsAndNetwork;
protected final SearchBuilder<FirewallRuleVO> SystemRuleSearch;
protected final GenericSearchBuilder<FirewallRuleVO, Long> RulesByIpCount;
protected final SearchBuilder<FirewallRuleVO> RoutingFirewallRulesSearch;
@ -106,6 +107,12 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
RulesByIpCount.and("state", RulesByIpCount.entity().getState(), Op.EQ);
RulesByIpCount.done();
FirewallByPortsAndNetwork = createSearchBuilder();
FirewallByPortsAndNetwork.and("networkId", FirewallByPortsAndNetwork.entity().getNetworkId(), Op.EQ);
FirewallByPortsAndNetwork.and("sourcePortStart", FirewallByPortsAndNetwork.entity().getSourcePortStart(), Op.EQ);
FirewallByPortsAndNetwork.and("sourcePortEnd", FirewallByPortsAndNetwork.entity().getSourcePortEnd(), Op.EQ);
FirewallByPortsAndNetwork.done();
RoutingFirewallRulesSearch = createSearchBuilder();
RoutingFirewallRulesSearch.and("networkId", RoutingFirewallRulesSearch.entity().getNetworkId(), Op.EQ);
RoutingFirewallRulesSearch.and("purpose", RoutingFirewallRulesSearch.entity().getPurpose(), Op.EQ);
@ -408,6 +415,16 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
rule.setDestinationCidrsList(destCidrs);
}
@Override
public FirewallRuleVO findByNetworkIdAndPorts(long networkId, int startPort, int endPort) {
SearchCriteria<FirewallRuleVO> sc = FirewallByPortsAndNetwork.create();
sc.setParameters("networkId", networkId);
sc.setParameters("sourcePortStart", startPort);
sc.setParameters("sourcePortEnd", endPort);
return findOneBy(sc);
}
@Override
public List<FirewallRuleVO> listRoutingIngressFirewallRules(long networkId) {
SearchCriteria<FirewallRuleVO> sc = RoutingFirewallRulesSearch.create();

View File

@ -47,5 +47,7 @@ public interface PortForwardingRulesDao extends GenericDao<PortForwardingRuleVO,
PortForwardingRuleVO findByIdAndIp(long id, String secondaryIp);
List<PortForwardingRuleVO> listByNetworkAndDestIpAddr(String ip4Address, long networkId);
PortForwardingRuleVO findByNetworkAndPorts(long networkId, int startPort, int endPort);
int expungeByVmList(List<Long> vmIds, Long batchSize);
}

View File

@ -58,6 +58,8 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase<PortForwardingRul
AllFieldsSearch.and("vmId", AllFieldsSearch.entity().getVirtualMachineId(), Op.EQ);
AllFieldsSearch.and("purpose", AllFieldsSearch.entity().getPurpose(), Op.EQ);
AllFieldsSearch.and("dstIp", AllFieldsSearch.entity().getDestinationIpAddress(), Op.EQ);
AllFieldsSearch.and("sourcePortStart", AllFieldsSearch.entity().getSourcePortStart(), Op.EQ);
AllFieldsSearch.and("sourcePortEnd", AllFieldsSearch.entity().getSourcePortEnd(), Op.EQ);
AllFieldsSearch.done();
ApplicationSearch = createSearchBuilder();
@ -175,6 +177,15 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase<PortForwardingRul
return findOneBy(sc);
}
@Override
public PortForwardingRuleVO findByNetworkAndPorts(long networkId, int startPort, int endPort) {
SearchCriteria<PortForwardingRuleVO> sc = AllFieldsSearch.create();
sc.setParameters("networkId", networkId);
sc.setParameters("sourcePortStart", startPort);
sc.setParameters("sourcePortEnd", endPort);
return findOneBy(sc);
}
@Override
public int expungeByVmList(List<Long> vmIds, Long batchSize) {
if (CollectionUtils.isEmpty(vmIds)) {

View File

@ -105,6 +105,9 @@ public class VpcVO implements Vpc {
@Column(name = "ip6Dns2")
String ip6Dns2;
@Column(name = "use_router_ip_resolver")
boolean useRouterIpResolver = false;
@Transient
boolean rollingRestart = false;
@ -309,4 +312,13 @@ public class VpcVO implements Vpc {
public String getIp6Dns2() {
return ip6Dns2;
}
@Override
public boolean useRouterIpAsResolver() {
return useRouterIpResolver;
}
public void setUseRouterIpResolver(boolean useRouterIpResolver) {
this.useRouterIpResolver = useRouterIpResolver;
}
}

View File

@ -22,10 +22,13 @@ import com.cloud.server.ResourceTag;
import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.api.response.ResourceIconResponse;
import java.util.Collection;
import java.util.List;
public interface ResourceIconDao extends GenericDao<ResourceIconVO, Long> {
ResourceIconResponse newResourceIconResponse(ResourceIcon resourceIconVO);
ResourceIconVO findByResourceUuid(String resourceUuid, ResourceTag.ResourceObjectType resourceType);
List<ResourceIconVO> listByResourceTypeAndIds(ResourceTag.ResourceObjectType resourceType, Collection<Long> resourceIds);
List<ResourceIconVO> listByResourceTypeAndUuids(ResourceTag.ResourceObjectType resourceType, Collection<String> resourceUuids);
List<ResourceIconResponse> listResourceIcons(List<String> resourceUuids, ResourceTag.ResourceObjectType resourceType);
}

View File

@ -24,8 +24,10 @@ import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.commons.collections.CollectionUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ResourceIconDaoImpl extends GenericDaoBase<ResourceIconVO, Long> implements ResourceIconDao {
@ -58,11 +60,36 @@ public class ResourceIconDaoImpl extends GenericDaoBase<ResourceIconVO, Long> im
}
@Override
public List<ResourceIconResponse> listResourceIcons(List<String> resourceUuids, ResourceTag.ResourceObjectType resourceType) {
public List<ResourceIconVO> listByResourceTypeAndIds(ResourceTag.ResourceObjectType resourceType,
Collection<Long> resourceIds) {
if (CollectionUtils.isEmpty(resourceIds)) {
return new ArrayList<>();
}
SearchBuilder<ResourceIconVO> sb = createSearchBuilder();
sb.and("resourceId", sb.entity().getResourceId(), SearchCriteria.Op.IN);
sb.and("resourceType", sb.entity().getResourceType(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<ResourceIconVO> sc = sb.create();
sc.setParameters("resourceId", resourceIds.toArray());
sc.setParameters("resourceType", resourceType);
return listBy(sc);
}
@Override
public List<ResourceIconVO> listByResourceTypeAndUuids(ResourceTag.ResourceObjectType resourceType,
Collection<String> resourceUuids) {
if (CollectionUtils.isEmpty(resourceUuids)) {
return new ArrayList<>();
}
SearchCriteria<ResourceIconVO> sc = AllFieldsSearch.create();
sc.setParameters("uuid", resourceUuids.toArray());
sc.setParameters("resourceType", resourceType);
List<ResourceIconVO> resourceIcons = listBy(sc);
return listBy(sc);
}
@Override
public List<ResourceIconResponse> listResourceIcons(List<String> resourceUuids, ResourceTag.ResourceObjectType resourceType) {
List<ResourceIconVO> resourceIcons = listByResourceTypeAndUuids(resourceType, resourceUuids);
List<ResourceIconResponse> iconResponses = new ArrayList<>();
for (ResourceIconVO resourceIcon : resourceIcons) {
ResourceIconResponse response = new ResourceIconResponse();

View File

@ -16,6 +16,7 @@
// under the License.
package com.cloud.storage;
import java.util.Date;
import java.util.UUID;
import javax.persistence.Column;
@ -25,6 +26,8 @@ import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.utils.db.GenericDao;
@Entity
@Table(name = "guest_os_category")
public class GuestOSCategoryVO implements GuestOsCategory {
@ -39,6 +42,26 @@ public class GuestOSCategoryVO implements GuestOsCategory {
@Column(name = "uuid")
String uuid = UUID.randomUUID().toString();
@Column(name = "featured")
boolean featured;
@Column(name = "sort_key")
private int sortKey;
@Column(name = GenericDao.CREATED_COLUMN)
private Date created;
@Column(name = GenericDao.REMOVED_COLUMN)
private Date removed;
public GuestOSCategoryVO() {
}
public GuestOSCategoryVO(String name, boolean featured) {
this.name = name;
this.featured = featured;
}
@Override
public long getId() {
return id;
@ -59,7 +82,25 @@ public class GuestOSCategoryVO implements GuestOsCategory {
return this.uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
@Override
public boolean isFeatured() {
return featured;
}
public void setFeatured(Boolean featured) {
this.featured = featured;
}
public void setSortKey(int key) {
sortKey = key;
}
public int getSortKey() {
return sortKey;
}
@Override
public Date getCreated() {
return created;
}
}

View File

@ -162,6 +162,9 @@ public class VMTemplateVO implements VirtualMachineTemplate {
@Column(name = "deploy_as_is")
private boolean deployAsIs;
@Column(name = "for_cks")
private boolean forCks;
@Column(name = "user_data_id")
private Long userDataId;
@ -664,6 +667,14 @@ public class VMTemplateVO implements VirtualMachineTemplate {
this.deployAsIs = deployAsIs;
}
public boolean isForCks() {
return forCks;
}
public void setForCks(boolean forCks) {
this.forCks = forCks;
}
@Override
public Long getUserDataId() {
return userDataId;

View File

@ -27,7 +27,6 @@ import com.cloud.utils.db.GenericDaoBase;
public class GuestOSCategoryDaoImpl extends GenericDaoBase<GuestOSCategoryVO, Long> implements GuestOSCategoryDao {
protected GuestOSCategoryDaoImpl() {
}
@Override

View File

@ -16,14 +16,14 @@
// under the License.
package com.cloud.storage.dao;
import java.util.List;
import java.util.Set;
import com.cloud.storage.GuestOS;
import com.cloud.storage.GuestOSVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.GenericDao;
import java.util.List;
import java.util.Set;
public interface GuestOSDao extends GenericDao<GuestOSVO, Long> {
GuestOSVO findOneByDisplayName(String displayName);
@ -36,4 +36,6 @@ public interface GuestOSDao extends GenericDao<GuestOSVO, Long> {
List<GuestOSVO> listByDisplayName(String displayName);
Pair<List<? extends GuestOS>, Integer> listGuestOSByCriteria(Long startIndex, Long pageSize, Long id, Long osCategoryId, String description, String keyword, Boolean forDisplay);
List<Long> listIdsByCategoryId(final long categoryId);
}

View File

@ -25,19 +25,20 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.cloud.storage.GuestOS;
import com.cloud.utils.Pair;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;
import com.cloud.storage.GuestOS;
import com.cloud.storage.GuestOSVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
@Component
public class GuestOSDaoImpl extends GenericDaoBase<GuestOSVO, Long> implements GuestOSDao {
@ -152,4 +153,14 @@ public class GuestOSDaoImpl extends GenericDaoBase<GuestOSVO, Long> implements G
return new Pair<>(result.first(), result.second());
}
@Override
public List<Long> listIdsByCategoryId(final long categoryId) {
GenericSearchBuilder<GuestOSVO, Long> sb = createSearchBuilder(Long.class);
sb.selectFields(sb.entity().getId());
sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<Long> sc = sb.create();
sc.setParameters("categoryId", categoryId);
return customSearch(sc, null);
}
}

View File

@ -58,6 +58,8 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<
public List<VMTemplateVO> listInZoneByState(long dataCenterId, VirtualMachineTemplate.State... states);
public List<Long> listTemplateIsoByArchVnfAndZone(Long dataCenterId, CPU.CPUArch arch, Boolean isIso, Boolean isVnf);
public List<VMTemplateVO> listAllActive();
public List<VMTemplateVO> listByState(VirtualMachineTemplate.State... states);

View File

@ -17,6 +17,7 @@
package com.cloud.storage.dao;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
@ -520,6 +521,48 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
return listBy(sc);
}
@Override
public List<Long> listTemplateIsoByArchVnfAndZone(Long dataCenterId, CPU.CPUArch arch, Boolean isIso,
Boolean isVnf) {
GenericSearchBuilder<VMTemplateVO, Long> sb = createSearchBuilder(Long.class);
sb.select(null, Func.DISTINCT, sb.entity().getGuestOSId());
sb.and("state", sb.entity().getState(), SearchCriteria.Op.IN);
sb.and("type", sb.entity().getTemplateType(), SearchCriteria.Op.IN);
sb.and("arch", sb.entity().getArch(), SearchCriteria.Op.EQ);
if (isIso != null) {
sb.and("isIso", sb.entity().getFormat(), isIso ? SearchCriteria.Op.EQ : SearchCriteria.Op.NEQ);
}
if (dataCenterId != null) {
SearchBuilder<VMTemplateZoneVO> templateZoneSearch = _templateZoneDao.createSearchBuilder();
templateZoneSearch.and("removed", templateZoneSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
templateZoneSearch.and("zoneId", templateZoneSearch.entity().getZoneId(), SearchCriteria.Op.EQ);
sb.join("templateZoneSearch", templateZoneSearch, templateZoneSearch.entity().getTemplateId(),
sb.entity().getId(), JoinBuilder.JoinType.INNER);
templateZoneSearch.done();
}
sb.done();
SearchCriteria<Long> sc = sb.create();
List<TemplateType> types = new ArrayList<>(Arrays.asList(TemplateType.USER, TemplateType.BUILTIN,
TemplateType.PERHOST));
if (isVnf == null) {
types.add(TemplateType.VNF);
} else if (isVnf) {
types = Collections.singletonList(TemplateType.VNF);
}
sc.setParameters("type", types.toArray());
sc.setParameters("state", VirtualMachineTemplate.State.Active);
if (dataCenterId != null) {
sc.setJoinParameters("templateZoneSearch", "zoneId", dataCenterId);
}
if (arch != null) {
sc.setParameters("arch", arch);
}
if (isIso != null) {
sc.setParameters("isIso", ImageFormat.ISO);
}
return customSearch(sc, null);
}
@Override
public List<VMTemplateVO> listAllActive() {
SearchCriteria<VMTemplateVO> sc = ActiveTmpltSearch.create();

View File

@ -23,8 +23,12 @@ import com.cloud.utils.exception.CloudRuntimeException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.cloudstack.framework.config.ConfigKey;
@ -59,6 +63,7 @@ public class Upgrade42010to42100 extends DbUpgradeAbstractImpl implements DbUpgr
@Override
public void performDataMigration(Connection conn) {
updateKubernetesClusterNodeVersions(conn);
migrateConfigurationScopeToBitmask(conn);
}
@ -88,6 +93,95 @@ public class Upgrade42010to42100 extends DbUpgradeAbstractImpl implements DbUpgr
}
}
private void updateKubernetesClusterNodeVersions(Connection conn) {
//get list of all non removed kubernetes clusters
try {
Map<Long, String> clusterAndVersion = getKubernetesClusterIdsAndVersion(conn);
updateKubernetesNodeVersions(conn, clusterAndVersion);
} catch (Exception e) {
String errMsg = "Failed to update kubernetes cluster nodes version";
logger.error(errMsg);
throw new CloudRuntimeException(errMsg, e);
}
}
private Map<Long, String> getKubernetesClusterIdsAndVersion(Connection conn) {
String listKubernetesClusters = "SELECT c.id, v.semantic_version FROM `cloud`.`kubernetes_cluster` c JOIN `cloud`.`kubernetes_supported_version` v ON (c.kubernetes_version_id = v.id) WHERE c.removed is NULL;";
Map<Long, String> clusterAndVersion = new HashMap<>();
try {
PreparedStatement pstmt = conn.prepareStatement(listKubernetesClusters);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
clusterAndVersion.put(rs.getLong(1), rs.getString(2));
}
rs.close();
pstmt.close();
} catch (SQLException e) {
String errMsg = String.format("Failed to get all the kubernetes cluster ids due to: %s", e.getMessage());
logger.error(errMsg);
throw new CloudRuntimeException(errMsg, e);
}
return clusterAndVersion;
}
private void updateKubernetesNodeVersions(Connection conn, Map<Long, String> clusterAndVersion) {
List<Long> kubernetesClusterVmIds;
for (Map.Entry<Long, String> clusterVersionEntry : clusterAndVersion.entrySet()) {
try {
Long cksClusterId = clusterVersionEntry.getKey();
String cksVersion = clusterVersionEntry.getValue();
logger.debug(String.format("Adding CKS version %s to existing CKS cluster %s nodes", cksVersion, cksClusterId));
kubernetesClusterVmIds = getKubernetesClusterVmMapIds(conn, cksClusterId);
updateKubernetesNodeVersion(conn, kubernetesClusterVmIds, cksClusterId, cksVersion);
} catch (Exception e) {
String errMsg = String.format("Failed to update the node version for kubernetes cluster nodes for the" +
" kubernetes cluster with id: %s," +
" due to: %s", clusterVersionEntry.getKey(), e.getMessage());
logger.error(errMsg, e);
throw new CloudRuntimeException(errMsg, e);
}
}
}
private List<Long> getKubernetesClusterVmMapIds(Connection conn, Long cksClusterId) {
List<Long> kubernetesClusterVmIds = new ArrayList<>();
String getKubernetesClustersVmMap = "SELECT id FROM `cloud`.`kubernetes_cluster_vm_map` WHERE cluster_id = %s;";
try {
PreparedStatement pstmt = conn.prepareStatement(String.format(getKubernetesClustersVmMap, cksClusterId));
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
kubernetesClusterVmIds.add(rs.getLong(1));
}
rs.close();
pstmt.close();
} catch (SQLException e) {
String errMsg = String.format("Failed to get the kubernetes cluster vm map IDs for kubernetes cluster with id: %s," +
" due to: %s", cksClusterId, e.getMessage());
logger.error(errMsg, e);
throw new CloudRuntimeException(errMsg, e);
}
return kubernetesClusterVmIds;
}
private void updateKubernetesNodeVersion(Connection conn, List<Long> kubernetesClusterVmIds, Long cksClusterId, String cksVersion) {
String updateKubernetesNodeVersion = "UPDATE `cloud`.`kubernetes_cluster_vm_map` set kubernetes_node_version = ? WHERE id = ?;";
for (Long nodeVmId : kubernetesClusterVmIds) {
try {
PreparedStatement pstmt = conn.prepareStatement(updateKubernetesNodeVersion);
pstmt.setString(1, cksVersion);
pstmt.setLong(2, nodeVmId);
pstmt.executeUpdate();
pstmt.close();
} catch (Exception e) {
String errMsg = String.format("Failed to update the node version for kubernetes cluster nodes for the" +
" kubernetes cluster with id: %s," +
" due to: %s", cksClusterId, e.getMessage());
logger.error(errMsg, e);
throw new CloudRuntimeException(errMsg, e);
}
}
}
protected void migrateConfigurationScopeToBitmask(Connection conn) {
String scopeDataType = DbUpgradeUtils.getTableColumnType(conn, "configuration", "scope");
logger.info("Data type of the column scope of table configuration is {}", scopeDataType);

View File

@ -65,6 +65,9 @@ public class UserDataVO implements UserData {
@Column(name = GenericDao.REMOVED_COLUMN)
private Date removed;
@Column(name = "for_cks")
private boolean forCks;
@Override
public long getDomainId() {
return domainId;
@ -105,6 +108,11 @@ public class UserDataVO implements UserData {
return params;
}
@Override
public boolean isForCks() {
return forCks;
}
public void setAccountId(long accountId) {
this.accountId = accountId;
}
@ -132,4 +140,6 @@ public class UserDataVO implements UserData {
public Date getRemoved() {
return removed;
}
public void setForCks(boolean forCks) { this.forCks = forCks; }
}

View File

@ -34,10 +34,47 @@ INSERT INTO `cloud`.`role_permissions` (uuid, role_id, rule, permission, sort_or
SELECT uuid(), role_id, 'quotaCreditsList', permission, sort_order
FROM `cloud`.`role_permissions` rp
WHERE rp.rule = 'quotaStatement'
AND NOT EXISTS(SELECT 1 FROM cloud.role_permissions rp_ WHERE rp.role_id = rp_.role_id AND rp_.rule = 'quotaCreditsList');
AND NOT EXISTS(SELECT 1 FROM cloud.role_permissions rp_ WHERE rp.role_id = rp_.role_id AND rp_.rule = 'quotaCreditsList');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.host', 'last_mgmt_server_id', 'bigint unsigned DEFAULT NULL COMMENT "last management server this host is connected to" AFTER `mgmt_server_id`');
-----------------------------------------------------------
-- CKS Enhancements:
-----------------------------------------------------------
-- Add for_cks column to the vm_template table
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vm_template','for_cks', 'int(1) unsigned DEFAULT "0" COMMENT "if true, the template can be used for CKS cluster deployment"');
-- Add support for different node types service offerings on CKS clusters
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','control_node_service_offering_id', 'bigint unsigned COMMENT "service offering ID for Control Node(s)"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','worker_node_service_offering_id', 'bigint unsigned COMMENT "service offering ID for Worker Node(s)"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','etcd_node_service_offering_id', 'bigint unsigned COMMENT "service offering ID for etcd Nodes"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','etcd_node_count', 'bigint unsigned COMMENT "number of etcd nodes to be deployed for the Kubernetes cluster"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','control_node_template_id', 'bigint unsigned COMMENT "template id to be used for Control Node(s)"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','worker_node_template_id', 'bigint unsigned COMMENT "template id to be used for Worker Node(s)"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','etcd_node_template_id', 'bigint unsigned COMMENT "template id to be used for etcd Nodes"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','cni_config_id', 'bigint unsigned COMMENT "user data id representing the associated cni configuration"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','cni_config_details', 'varchar(4096) DEFAULT NULL COMMENT "user data details representing the values required for the cni configuration associated"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster_vm_map','etcd_node', 'tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT "indicates if the VM is an etcd node"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster_vm_map','external_node', 'tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT "indicates if the node was imported into the Kubernetes cluster"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster_vm_map','manual_upgrade', 'tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT "indicates if the node is marked for manual upgrade and excluded from the Kubernetes cluster upgrade operation"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster_vm_map','kubernetes_node_version', 'varchar(40) COMMENT "version of k8s the cluster node is on"');
ALTER TABLE `cloud`.`kubernetes_cluster` ADD CONSTRAINT `fk_cluster__control_node_service_offering_id` FOREIGN KEY `fk_cluster__control_node_service_offering_id`(`control_node_service_offering_id`) REFERENCES `service_offering`(`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`kubernetes_cluster` ADD CONSTRAINT `fk_cluster__worker_node_service_offering_id` FOREIGN KEY `fk_cluster__worker_node_service_offering_id`(`worker_node_service_offering_id`) REFERENCES `service_offering`(`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`kubernetes_cluster` ADD CONSTRAINT `fk_cluster__etcd_node_service_offering_id` FOREIGN KEY `fk_cluster__etcd_node_service_offering_id`(`etcd_node_service_offering_id`) REFERENCES `service_offering`(`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`kubernetes_cluster` ADD CONSTRAINT `fk_cluster__control_node_template_id` FOREIGN KEY `fk_cluster__control_node_template_id`(`control_node_template_id`) REFERENCES `vm_template`(`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`kubernetes_cluster` ADD CONSTRAINT `fk_cluster__worker_node_template_id` FOREIGN KEY `fk_cluster__worker_node_template_id`(`worker_node_template_id`) REFERENCES `vm_template`(`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`kubernetes_cluster` ADD CONSTRAINT `fk_cluster__etcd_node_template_id` FOREIGN KEY `fk_cluster__etcd_node_template_id`(`etcd_node_template_id`) REFERENCES `vm_template`(`id`) ON DELETE CASCADE;
-- Add for_cks column to the user_data table to represent CNI Configuration stored as userdata
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.user_data','for_cks', 'int(1) unsigned DEFAULT "0" COMMENT "if true, the user data represent CNI configuration meant for CKS use only"');
-- Add use VR IP as resolver option on VPC
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc','use_router_ip_resolver', 'tinyint(1) DEFAULT 0 COMMENT "use router ip as resolver instead of dns options"');
-----------------------------------------------------------
-- END - CKS Enhancements
-----------------------------------------------------------
-- Add table for reconcile commands
CREATE TABLE IF NOT EXISTS `cloud`.`reconcile_commands` (
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
@ -81,9 +118,95 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.cluster', 'storage_access_groups', '
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.host_pod_ref', 'storage_access_groups', 'varchar(255) DEFAULT NULL COMMENT "storage access groups for the hosts in the pod"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.data_center', 'storage_access_groups', 'varchar(255) DEFAULT NULL COMMENT "storage access groups for the hosts in the zone"');
-- Add featured, sort_key, created, removed columns for guest_os_category
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.guest_os_category', 'featured', 'tinyint(1) NOT NULL DEFAULT 0 COMMENT "whether the category is featured or not" AFTER `uuid`');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.guest_os_category', 'sort_key', 'int NOT NULL DEFAULT 0 COMMENT "sort key used for customising sort method" AFTER `featured`');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.guest_os_category', 'created', 'datetime COMMENT "date on which the category was created" AFTER `sort_key`');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.guest_os_category', 'removed', 'datetime COMMENT "date removed if not null" AFTER `created`');
-- Begin: Changes for Guest OS category cleanup
-- Add new OS categories if not present
DROP PROCEDURE IF EXISTS `cloud`.`INSERT_CATEGORY_IF_NOT_EXIST`;
CREATE PROCEDURE `cloud`.`INSERT_CATEGORY_IF_NOT_EXIST`(IN os_name VARCHAR(255))
BEGIN
IF NOT EXISTS ((SELECT 1 FROM `cloud`.`guest_os_category` WHERE name = os_name))
THEN
INSERT INTO `cloud`.`guest_os_category` (name, uuid)
VALUES (os_name, UUID())
; END IF
; END;
CALL `cloud`.`INSERT_CATEGORY_IF_NOT_EXIST`('Fedora');
CALL `cloud`.`INSERT_CATEGORY_IF_NOT_EXIST`('Rocky Linux');
CALL `cloud`.`INSERT_CATEGORY_IF_NOT_EXIST`('AlmaLinux');
-- Move existing guest OS to new categories
DROP PROCEDURE IF EXISTS `cloud`.`UPDATE_CATEGORY_FOR_GUEST_OSES`;
CREATE PROCEDURE `cloud`.`UPDATE_CATEGORY_FOR_GUEST_OSES`(IN category_name VARCHAR(255), IN os_name VARCHAR(255))
BEGIN
DECLARE category_id BIGINT
; SELECT `id` INTO category_id
FROM `cloud`.`guest_os_category`
WHERE `name` = category_name
LIMIT 1
; IF category_id IS NULL THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Category not found'
; END IF
; UPDATE `cloud`.`guest_os`
SET `category_id` = category_id
WHERE `display_name` LIKE CONCAT('%', os_name, '%')
; END;
CALL `cloud`.`UPDATE_CATEGORY_FOR_GUEST_OSES`('Rocky Linux', 'Rocky Linux');
CALL `cloud`.`UPDATE_CATEGORY_FOR_GUEST_OSES`('AlmaLinux', 'AlmaLinux');
CALL `cloud`.`UPDATE_CATEGORY_FOR_GUEST_OSES`('Fedora', 'Fedora');
-- Move existing guest OS whose category will be deleted to Other category
DROP PROCEDURE IF EXISTS `cloud`.`UPDATE_NEW_AND_DELETE_OLD_CATEGORY_FOR_GUEST_OS`;
CREATE PROCEDURE `cloud`.`UPDATE_NEW_AND_DELETE_OLD_CATEGORY_FOR_GUEST_OS`(IN to_category_name VARCHAR(255), IN from_category_name VARCHAR(255))
BEGIN
DECLARE done INT DEFAULT 0
; DECLARE to_category_id BIGINT
; SELECT id INTO to_category_id
FROM `cloud`.`guest_os_category`
WHERE `name` = to_category_name
LIMIT 1
; IF to_category_id IS NULL THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'ToCategory not found'
; END IF
; UPDATE `cloud`.`guest_os`
SET `category_id` = to_category_id
WHERE `category_id` = (SELECT `id` FROM `cloud`.`guest_os_category` WHERE `name` = from_category_name)
; UPDATE `cloud`.`guest_os_category` SET `removed`=now() WHERE `name` = from_category_name
; END;
CALL `cloud`.`UPDATE_NEW_AND_DELETE_OLD_CATEGORY_FOR_GUEST_OS`('Other', 'Novel');
CALL `cloud`.`UPDATE_NEW_AND_DELETE_OLD_CATEGORY_FOR_GUEST_OS`('Other', 'None');
CALL `cloud`.`UPDATE_NEW_AND_DELETE_OLD_CATEGORY_FOR_GUEST_OS`('Other', 'Unix');
CALL `cloud`.`UPDATE_NEW_AND_DELETE_OLD_CATEGORY_FOR_GUEST_OS`('Other', 'Mac');
-- Update featured for existing guest OS categories
UPDATE `cloud`.`guest_os_category` SET featured = 1;
-- Update sort order for all guest OS categories
UPDATE `cloud`.`guest_os_category`
SET `sort_key` = CASE
WHEN `name` = 'Ubuntu' THEN 1
WHEN `name` = 'Debian' THEN 2
WHEN `name` = 'Fedora' THEN 3
WHEN `name` = 'CentOS' THEN 4
WHEN `name` = 'Rocky Linux' THEN 5
WHEN `name` = 'AlmaLinux' THEN 6
WHEN `name` = 'Oracle' THEN 7
WHEN `name` = 'RedHat' THEN 8
WHEN `name` = 'SUSE' THEN 9
WHEN `name` = 'Windows' THEN 10
WHEN `name` = 'Other' THEN 11
ELSE `sort_key`
END;
-- End: Changes for Guest OS category cleanup
-- Disk controller mappings
CREATE TABLE IF NOT EXISTS `cloud`.`disk_controller_mapping` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`id` bigint(20) unsigned NOT NULL auto_increment,
`uuid` varchar(255) UNIQUE NOT NULL,
`name` varchar(255) NOT NULL,
`controller_reference` varchar(255) NOT NULL,

View File

@ -41,6 +41,7 @@ SELECT
`vm_template`.`guest_os_id` AS `guest_os_id`,
`guest_os`.`uuid` AS `guest_os_uuid`,
`guest_os`.`display_name` AS `guest_os_name`,
`guest_os`.`category_id` AS `guest_os_category_id`,
`vm_template`.`bootable` AS `bootable`,
`vm_template`.`prepopulate` AS `prepopulate`,
`vm_template`.`cross_zones` AS `cross_zones`,
@ -100,6 +101,7 @@ SELECT
IFNULL(`data_center`.`id`, 0)) AS `temp_zone_pair`,
`vm_template`.`direct_download` AS `direct_download`,
`vm_template`.`deploy_as_is` AS `deploy_as_is`,
`vm_template`.`for_cks` AS `for_cks`,
`user_data`.`id` AS `user_data_id`,
`user_data`.`uuid` AS `user_data_uuid`,
`user_data`.`name` AS `user_data_name`,

View File

@ -21,7 +21,11 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
@ -44,8 +48,11 @@ import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.Storage;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@ -55,6 +62,9 @@ public class VMTemplateDaoImplTest {
@Mock
HostDao hostDao;
@Mock
VMTemplateZoneDao templateZoneDao;
@Spy
@InjectMocks
VMTemplateDaoImpl templateDao = new VMTemplateDaoImpl();
@ -186,4 +196,107 @@ public class VMTemplateDaoImplTest {
VMTemplateVO result = templateDao.findLatestTemplateByTypeAndHypervisorAndArch(hypervisorType, arch, type);
assertNull(result);
}
private void mockTemplateZoneJoin() {
VMTemplateZoneVO templateZoneVO = mock(VMTemplateZoneVO.class);
SearchBuilder<VMTemplateZoneVO> templateZoneVOSearchBuilder = mock(SearchBuilder.class);
when(templateZoneVOSearchBuilder.entity()).thenReturn(templateZoneVO);
when(templateZoneDao.createSearchBuilder()).thenReturn(templateZoneVOSearchBuilder);
}
@Test
public void testListTemplateIsoByArchAndZone_WithDataCenterId() {
Long dataCenterId = 1L;
CPU.CPUArch arch = CPU.CPUArch.getDefault();
Boolean isIso = true;
VMTemplateVO templateVO = mock(VMTemplateVO.class);
GenericSearchBuilder<VMTemplateVO, Long> searchBuilder = mock(GenericSearchBuilder.class);
when(searchBuilder.entity()).thenReturn(templateVO);
SearchCriteria<Long>searchCriteria = mock(SearchCriteria.class);
when(templateDao.createSearchBuilder(Long.class)).thenReturn(searchBuilder);
when(searchBuilder.create()).thenReturn(searchCriteria);
mockTemplateZoneJoin();
doReturn(new ArrayList<>()).when(templateDao).customSearch(searchCriteria, null);
List<Long> result = templateDao.listTemplateIsoByArchVnfAndZone(dataCenterId, arch, isIso, false);
assertNotNull(result);
verify(searchBuilder, times(1)).select(null, SearchCriteria.Func.DISTINCT, templateVO.getGuestOSId());
verify(searchBuilder, times(1)).and(eq("state"), any(), eq(SearchCriteria.Op.IN));
verify(searchBuilder, times(1)).and(eq("type"), any(), eq(SearchCriteria.Op.IN));
verify(searchBuilder, times(1)).and(eq("arch"), any(), eq(SearchCriteria.Op.EQ));
verify(searchBuilder, times(1)).and(eq("isIso"), any(), eq(SearchCriteria.Op.EQ));
verify(searchBuilder, times(1)).join(eq("templateZoneSearch"), any(), any(), any(), eq(JoinBuilder.JoinType.INNER));
verify(templateDao, times(1)).customSearch(searchCriteria, null);
}
@Test
public void testListTemplateIsoByArchAndZone_WithoutDataCenterId() {
Long dataCenterId = null;
CPU.CPUArch arch = CPU.CPUArch.getDefault();
Boolean isIso = false;
VMTemplateVO templateVO = mock(VMTemplateVO.class);
GenericSearchBuilder<VMTemplateVO, Long> searchBuilder = mock(GenericSearchBuilder.class);
when(searchBuilder.entity()).thenReturn(templateVO);
SearchCriteria<Long>searchCriteria = mock(SearchCriteria.class);
when(templateDao.createSearchBuilder(Long.class)).thenReturn(searchBuilder);
when(searchBuilder.create()).thenReturn(searchCriteria);
doReturn(new ArrayList<>()).when(templateDao).customSearch(searchCriteria, null);
List<Long> result = templateDao.listTemplateIsoByArchVnfAndZone(dataCenterId, arch, isIso, false);
assertNotNull(result);
verify(searchBuilder, times(1)).select(null, SearchCriteria.Func.DISTINCT, templateVO.getGuestOSId());
verify(searchBuilder, times(1)).and(eq("state"), any(), eq(SearchCriteria.Op.IN));
verify(searchBuilder, times(1)).and(eq("type"), any(), eq(SearchCriteria.Op.IN));
verify(searchBuilder, times(1)).and(eq("arch"), any(), eq(SearchCriteria.Op.EQ));
verify(searchBuilder, times(1)).and(eq("isIso"), any(), eq(SearchCriteria.Op.NEQ));
verify(searchBuilder, never()).join(eq("templateZoneSearch"), any(), any(), any(), eq(JoinBuilder.JoinType.INNER));
verify(templateDao, times(1)).customSearch(searchCriteria, null);
}
@Test
public void testListTemplateIsoByArchAndZone_WithoutArch() {
Long dataCenterId = 1L;
CPU.CPUArch arch = null;
Boolean isIso = true;
VMTemplateVO templateVO = mock(VMTemplateVO.class);
GenericSearchBuilder<VMTemplateVO, Long> searchBuilder = mock(GenericSearchBuilder.class);
when(searchBuilder.entity()).thenReturn(templateVO);
SearchCriteria<Long>searchCriteria = mock(SearchCriteria.class);
when(templateDao.createSearchBuilder(Long.class)).thenReturn(searchBuilder);
when(searchBuilder.create()).thenReturn(searchCriteria);
mockTemplateZoneJoin();
doReturn(new ArrayList<>()).when(templateDao).customSearch(searchCriteria, null);
List<Long> result = templateDao.listTemplateIsoByArchVnfAndZone(dataCenterId, arch, isIso, false);
assertNotNull(result);
verify(searchBuilder, times(1)).select(null, SearchCriteria.Func.DISTINCT, templateVO.getGuestOSId());
verify(searchBuilder, times(1)).and(eq("state"), any(), eq(SearchCriteria.Op.IN));
verify(searchBuilder, times(1)).and(eq("type"), any(), eq(SearchCriteria.Op.IN));
verify(searchBuilder, times(1)).and(eq("arch"), any(), eq(SearchCriteria.Op.EQ));
verify(searchBuilder, times(1)).and(eq("isIso"), any(), eq(SearchCriteria.Op.EQ));
verify(searchBuilder, times(1)).join(eq("templateZoneSearch"), any(), any(), any(), eq(JoinBuilder.JoinType.INNER));
verify(templateDao, times(1)).customSearch(searchCriteria, null);
}
@Test
public void testListTemplateIsoByArchAndZone_WithoutIsIso() {
Long dataCenterId = 1L;
CPU.CPUArch arch = CPU.CPUArch.getDefault();
Boolean isIso = null;
VMTemplateVO templateVO = mock(VMTemplateVO.class);
GenericSearchBuilder<VMTemplateVO, Long> searchBuilder = mock(GenericSearchBuilder.class);
when(searchBuilder.entity()).thenReturn(templateVO);
SearchCriteria<Long>searchCriteria = mock(SearchCriteria.class);
when(templateDao.createSearchBuilder(Long.class)).thenReturn(searchBuilder);
when(searchBuilder.create()).thenReturn(searchCriteria);
mockTemplateZoneJoin();
doReturn(new ArrayList<>()).when(templateDao).customSearch(searchCriteria, null);
List<Long> result = templateDao.listTemplateIsoByArchVnfAndZone(dataCenterId, arch, isIso, false);
assertNotNull(result);
verify(searchBuilder, times(1)).select(null, SearchCriteria.Func.DISTINCT, templateVO.getGuestOSId());
verify(searchBuilder, times(1)).and(eq("state"), any(), eq(SearchCriteria.Op.IN));
verify(searchBuilder, times(1)).and(eq("type"), any(), eq(SearchCriteria.Op.IN));
verify(searchBuilder, times(1)).and(eq("arch"), any(), eq(SearchCriteria.Op.EQ));
verify(searchBuilder, never()).and(eq("isIso"), any(), eq(SearchCriteria.Op.NEQ));
verify(searchBuilder, never()).and(eq("isIso"), any(), eq(SearchCriteria.Op.EQ));
verify(searchBuilder, times(1)).join(eq("templateZoneSearch"), any(), any(), any(), eq(JoinBuilder.JoinType.INNER));
verify(templateDao, times(1)).customSearch(searchCriteria, null);
}
}

View File

@ -16,10 +16,12 @@
// under the License.
package com.cloud.upgrade.dao;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
@ -64,6 +66,12 @@ public class Upgrade42010to42100Test {
" ELSE 0" +
" END WHERE scope IS NOT NULL;";
when(txn.prepareAutoCloseStatement(sql)).thenReturn(pstmt);
PreparedStatement preparedStatement = Mockito.mock(PreparedStatement.class);
ResultSet resultSet = Mockito.mock(ResultSet.class);
Mockito.when(resultSet.next()).thenReturn(false);
Mockito.when(preparedStatement.executeQuery()).thenReturn(resultSet);
Mockito.when(conn.prepareStatement(anyString())).thenReturn(preparedStatement);
upgrade.performDataMigration(conn);
Mockito.verify(pstmt, Mockito.times(1)).executeUpdate();

View File

@ -433,6 +433,11 @@ public class TemplateObject implements TemplateInfo {
return this.imageVO.isDeployAsIs();
}
@Override
public boolean isForCks() {
return imageVO.isForCks();
}
public void setInstallPath(String installPath) {
this.installPath = installPath;
}

View File

@ -100,7 +100,7 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat
}
StoragePool storagePool = (StoragePool)dataStoreMgr.getPrimaryDataStore(pool.getId());
if (filter(avoid, storagePool, dskCh, plan)) {
logger.debug(String.format("Found suitable cluster storage pool [%s] to allocate disk [%s] to it, adding to list.", pool, dskCh));
logger.debug("Found suitable cluster storage pool [{}] to allocate disk [{}] to it, adding to list.", pool, dskCh);
suitablePools.add(storagePool);
} else {
logger.debug(String.format("Adding storage pool [%s] to avoid set during allocation of disk [%s].", pool, dskCh));

View File

@ -96,7 +96,7 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator {
}
StoragePool storagePool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(storage.getId());
if (filter(avoid, storagePool, dskCh, plan)) {
logger.debug(String.format("Found suitable zone wide storage pool [%s] to allocate disk [%s] to it, adding to list.", storagePool, dskCh));
logger.debug("Found suitable zone wide storage pool [{}] to allocate disk [{}] to it, adding to list.", storagePool, dskCh);
suitablePools.add(storagePool);
} else {
if (canAddStoragePoolToAvoidSet(storage)) {

View File

@ -70,9 +70,11 @@ public interface IndirectAgentLB {
*/
Long getLBPreferredHostCheckInterval(Long clusterId);
void propagateMSListToAgents();
void propagateMSListToAgents(boolean triggerHostLB);
boolean haveAgentBasedHosts(long msId);
void propagateMSListToAgentsInCluster(Long clusterId);
boolean migrateAgents(String fromMsUuid, long fromMsId, String lbAlgorithm, long timeoutDurationInMs);
boolean haveAgentBasedHosts(long msId, boolean excludeHostsInMaintenance);
boolean migrateAgents(String fromMsUuid, long fromMsId, String lbAlgorithm, long timeoutDurationInMs, boolean excludeHostsInMaintenance);
}

View File

@ -17,6 +17,7 @@
package com.cloud.dao;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -56,6 +57,13 @@ public class EntityManagerImpl extends ManagerBase implements EntityManager {
return dao.findByUuid(uuid);
}
@Override
public <T> List<T> listByUuids(Class<T> entityType, Collection<String> uuids) {
// Finds and returns a unique VO using uuid, null if entity not found in db
GenericDao<? extends T, String> dao = (GenericDao<? extends T, String>)GenericDaoBase.getDao(entityType);
return (List<T>)dao.listByUuids(uuids);
}
@Override
public <T> T findByUuidIncludingRemoved(Class<T> entityType, String uuid) {
// Finds and returns a unique VO using uuid, null if entity not found in db

View File

@ -17,6 +17,8 @@
package com.cloud.utils.db;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -56,6 +58,10 @@ public interface GenericDao<T, ID extends Serializable> {
// Finds one unique VO using uuid
T findByUuid(String uuid);
default List<T> listByUuids(Collection<String> uuids) {
return new ArrayList<>();
}
// Finds one unique VO using uuid including removed entities
T findByUuidIncludingRemoved(String uuid);

View File

@ -1006,6 +1006,17 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
return findOneBy(sc);
}
@Override
@DB()
public List<T> listByUuids(final Collection<String> uuids) {
if (org.apache.commons.collections.CollectionUtils.isEmpty(uuids)) {
return Collections.emptyList();
}
SearchCriteria<T> sc = createSearchCriteria();
sc.addAnd("uuid", SearchCriteria.Op.IN, uuids.toArray());
return listBy(sc);
}
@Override
@DB()
public T findByUuidIncludingRemoved(final String uuid) {

View File

@ -248,6 +248,7 @@ cp -r plugins/network-elements/cisco-vnmc/src/main/scripts/network/cisco/* ${RPM
mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/
mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/lib
mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/cks/conf
mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/systemd/system/%{name}-management.service.d
@ -273,7 +274,7 @@ wget https://github.com/apache/cloudstack-cloudmonkey/releases/download/$CMK_REL
chmod +x ${RPM_BUILD_ROOT}%{_bindir}/cmk
cp -r client/target/utilities/scripts/db/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup
cp -r plugins/integrations/kubernetes-service/src/main/resources/conf/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/cks/conf
cp -r client/target/cloud-client-ui-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/
cp -r client/target/classes/META-INF/webapp ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapp
cp ui/dist/config.json ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/
@ -308,6 +309,11 @@ touch ${RPM_BUILD_ROOT}%{_localstatedir}/run/%{name}-management.pid
#install -D server/target/conf/cloudstack-catalina.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-catalina
install -D server/target/conf/cloudstack-management.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-management
install -D plugins/integrations/kubernetes-service/src/main/resources/conf/etcd-node.yml ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/cks/conf/etcd-node.yml
install -D plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/cks/conf/k8s-control-node.yml
install -D plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/cks/conf/k8s-control-node-add.yml
install -D plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/cks/conf/k8s-node.yml
# SystemVM template
mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/templates/systemvm
cp -r engine/schema/dist/systemvm-templates/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/templates/systemvm
@ -608,6 +614,7 @@ pip3 install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz
%attr(0755,root,root) %{_bindir}/%{name}-sysvmadm
%attr(0755,root,root) %{_bindir}/%{name}-setup-encryption
%attr(0755,root,root) %{_bindir}/cmk
%{_datadir}/%{name}-management/cks/conf/*.yml
%{_datadir}/%{name}-management/setup/*.sql
%{_datadir}/%{name}-management/setup/*.sh
%{_datadir}/%{name}-management/setup/server-setup.xml

View File

@ -17,6 +17,8 @@
package com.cloud.hypervisor.kvm.resource;
import static com.cloud.host.Host.HOST_INSTANCE_CONVERSION;
import static com.cloud.host.Host.HOST_OVFTOOL_VERSION;
import static com.cloud.host.Host.HOST_VIRTV2V_VERSION;
import static com.cloud.host.Host.HOST_VOLUME_ENCRYPTION;
import static org.apache.cloudstack.utils.linux.KVMHostInfo.isHostS390x;
@ -3908,7 +3910,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
cmd.setIqn(getIqn());
cmd.getHostDetails().put(HOST_VOLUME_ENCRYPTION, String.valueOf(hostSupportsVolumeEncryption()));
cmd.setHostTags(getHostTags());
cmd.getHostDetails().put(HOST_INSTANCE_CONVERSION, String.valueOf(hostSupportsInstanceConversion()));
boolean instanceConversionSupported = hostSupportsInstanceConversion();
cmd.getHostDetails().put(HOST_INSTANCE_CONVERSION, String.valueOf(instanceConversionSupported));
if (instanceConversionSupported) {
cmd.getHostDetails().put(HOST_VIRTV2V_VERSION, getHostVirtV2vVersion());
}
if (hostSupportsOvfExport()) {
cmd.getHostDetails().put(HOST_OVFTOOL_VERSION, getHostOvfToolVersion());
}
HealthCheckResult healthCheckResult = getHostHealthCheckResult();
if (healthCheckResult != HealthCheckResult.IGNORE) {
cmd.setHostHealthCheckResult(healthCheckResult == HealthCheckResult.SUCCESS);
@ -5616,8 +5625,24 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
return exitValue == 0;
}
public String getHostVirtV2vVersion() {
if (!hostSupportsInstanceConversion()) {
return "";
}
String cmd = String.format("%s | awk '{print $2}'", INSTANCE_CONVERSION_SUPPORTED_CHECK_CMD);
String version = Script.runSimpleBashScript(cmd);
return StringUtils.isNotBlank(version) ? version.split(",")[0] : "";
}
public String getHostOvfToolVersion() {
if (!hostSupportsOvfExport()) {
return "";
}
return Script.runSimpleBashScript(OVF_EXPORT_TOOl_GET_VERSION_CMD);
}
public boolean ovfExportToolSupportsParallelThreads() {
String ovfExportToolVersion = Script.runSimpleBashScript(OVF_EXPORT_TOOl_GET_VERSION_CMD);
String ovfExportToolVersion = getHostOvfToolVersion();
if (StringUtils.isBlank(ovfExportToolVersion)) {
return false;
}

View File

@ -47,6 +47,14 @@ public final class LibvirtReadyCommandWrapper extends CommandWrapper<ReadyComman
hostDetails.put(Host.HOST_UEFI_ENABLE, Boolean.TRUE.toString());
}
if (libvirtComputingResource.hostSupportsInstanceConversion()) {
hostDetails.put(Host.HOST_VIRTV2V_VERSION, libvirtComputingResource.getHostVirtV2vVersion());
}
if (libvirtComputingResource.hostSupportsOvfExport()) {
hostDetails.put(Host.HOST_OVFTOOL_VERSION, libvirtComputingResource.getHostOvfToolVersion());
}
return new ReadyAnswer(command, hostDetails);
}

View File

@ -224,10 +224,35 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
} else {
Script.runSimpleBashScript("mv " + templateFilePath + " " + destinationFile);
}
} else if (destPool.getType() == StoragePoolType.RBD) {
String temporaryExtractFilePath = sourceFile.getParent() + File.separator + templateUuid;
extractDownloadedTemplate(templateFilePath, destPool, temporaryExtractFilePath);
createTemplateOnRBDFromDirectDownloadFile(temporaryExtractFilePath, templateUuid, destPool, timeout);
}
return destPool.getPhysicalDisk(templateUuid);
}
private void createTemplateOnRBDFromDirectDownloadFile(String srcTemplateFilePath, String templateUuid, KVMStoragePool destPool, int timeout) {
try {
QemuImg.PhysicalDiskFormat srcFileFormat = QemuImg.PhysicalDiskFormat.QCOW2;
QemuImgFile srcFile = new QemuImgFile(srcTemplateFilePath, srcFileFormat);
QemuImg qemu = new QemuImg(timeout);
Map<String, String> info = qemu.info(srcFile);
Long virtualSize = Long.parseLong(info.get(QemuImg.VIRTUAL_SIZE));
KVMPhysicalDisk destDisk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + templateUuid, templateUuid, destPool);
destDisk.setFormat(PhysicalDiskFormat.RAW);
destDisk.setSize(virtualSize);
destDisk.setVirtualSize(virtualSize);
QemuImgFile destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(destPool, destDisk.getPath()));
destFile.setFormat(PhysicalDiskFormat.RAW);
qemu.convert(srcFile, destFile);
} catch (LibvirtException | QemuImgException e) {
String err = String.format("Error creating template from direct download file on pool %s: %s", destPool.getUuid(), e.getMessage());
logger.error(err, e);
throw new CloudRuntimeException(err, e);
}
}
public StorageVol getVolume(StoragePool pool, String volName) {
StorageVol vol = null;

View File

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.cloudstack.storage.formatinspector.Qcow2Inspector;
import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
import org.libvirt.LibvirtException;
@ -53,6 +54,8 @@ public class QemuImg {
public static final long QEMU_2_10 = 2010000;
public static final long QEMU_5_10 = 5010000;
public static final int MIN_BITMAP_VERSION = 3;
/* The qemu-img binary. We expect this to be in $PATH */
public String _qemuImgPath = "qemu-img";
private String cloudQemuImgPath = "cloud-qemu-img";
@ -466,7 +469,7 @@ public class QemuImg {
script.add(srcFile.getFileName());
}
if (this.version >= QEMU_5_10 && keepBitmaps) {
if (this.version >= QEMU_5_10 && keepBitmaps && Qcow2Inspector.validateQcow2Version(srcFile.getFileName(), MIN_BITMAP_VERSION)) {
script.add("--bitmaps");
}

View File

@ -49,9 +49,12 @@ public final class CitrixResizeVolumeCommandWrapper extends CommandWrapper<Resiz
try {
if (command.getCurrentSize() >= newSize) {
logger.info("No need to resize volume: " + volId +", current size " + toHumanReadableSize(command.getCurrentSize()) + " is same as new size " + toHumanReadableSize(newSize));
if (command.getCurrentSize() == newSize) {
logger.info("No need to resize volume [{}], current size [{}] is same as new size [{}].", volId, toHumanReadableSize(command.getCurrentSize()), toHumanReadableSize(newSize));
return new ResizeVolumeAnswer(command, true, "success", newSize);
} else if (command.getCurrentSize() > newSize) {
logger.error("XenServer does not support volume shrink. Volume [{}] current size [{}] is smaller than new size [{}]", volId, toHumanReadableSize(command.getCurrentSize()), toHumanReadableSize(newSize));
return new ResizeVolumeAnswer(command, false, "operation not supported");
}
if (command.isManaged()) {
resizeSr(conn, command);

View File

@ -23,4 +23,6 @@ public class KubernetesClusterEventTypes {
public static final String EVENT_KUBERNETES_CLUSTER_STOP = "KUBERNETES.CLUSTER.STOP";
public static final String EVENT_KUBERNETES_CLUSTER_SCALE = "KUBERNETES.CLUSTER.SCALE";
public static final String EVENT_KUBERNETES_CLUSTER_UPGRADE = "KUBERNETES.CLUSTER.UPGRADE";
public static final String EVENT_KUBERNETES_CLUSTER_NODES_ADD = "KUBERNETES.CLUSTER.NODES.ADD";
public static final String EVENT_KUBERNETES_CLUSTER_NODES_REMOVE = "KUBERNETES.CLUSTER.NODES.REMOVE";
}

Some files were not shown because too many files have changed in this diff Show More