Merge branch 'main' into disk-controller-mappings

This commit is contained in:
Fabricio Duarte 2025-06-04 13:05:26 -03:00
commit 7476f60e0b
737 changed files with 40798 additions and 6682 deletions

View File

@ -54,10 +54,12 @@ github:
- gpordeus
- hsato03
- bernardodemarco
- abh1sar
- FelipeM525
- lucas-a-martins
- nicoschmdt
- abh1sar
- sudo87
- rosi-shapeblue
protected_branches: ~

View File

@ -164,7 +164,8 @@ jobs:
component/test_cpu_limits
component/test_cpu_max_limits
component/test_cpu_project_limits
component/test_deploy_vm_userdata_multi_nic",
component/test_deploy_vm_userdata_multi_nic
component/test_deploy_vm_lease",
"component/test_egress_fw_rules
component/test_invalid_gw_nm
component/test_ip_reservation",
@ -236,7 +237,7 @@ jobs:
- name: Install Python dependencies
run: |
python3 -m pip install --user --upgrade urllib3 lxml paramiko nose texttable ipmisim pyopenssl pycrypto mock flask netaddr pylint pycodestyle six astroid
python3 -m pip install --user --upgrade urllib3 lxml paramiko nose texttable ipmisim pyopenssl pycryptodome mock flask netaddr pylint pycodestyle six astroid pynose
- name: Install jacoco dependencies
run: |

View File

@ -54,7 +54,7 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
key: ${{ runner.os }}-m2-${{ hashFiles('pom.xml', '*/pom.xml', '*/*/pom.xml', '*/*/*/pom.xml') }}
restore-keys: |
${{ runner.os }}-m2

View File

@ -56,7 +56,7 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
key: ${{ runner.os }}-m2-${{ hashFiles('pom.xml', '*/pom.xml', '*/*/pom.xml', '*/*/*/pom.xml') }}
restore-keys: |
${{ runner.os }}-m2

View File

@ -4,9 +4,9 @@ Contributing to Apache CloudStack (ACS)
Summary
-------
This document covers how to contribute to the ACS project. ACS uses GitHub PRs to manage code contributions.
These instructions assume you have a GitHub.com account, so if you don't have one you will have to create one. Your proposed code changes will be published to your own fork of the ACS project and you will submit a Pull Request for your changes to be added.
These instructions assume you have a GitHub.com account, so if you don't have one you will have to create one. Your proposed code changes will be published to your own fork of the ACS project, and you will submit a Pull Request for your changes to be added.
_Lets get started!!!_
_Let's get started!!!_
Bug fixes
---------
@ -26,7 +26,7 @@ No back porting / cherry-picking features to existing branches!
PendingReleaseNotes file
------------------------
When developing a new feature or making a (major) change to a existing feature you are encouraged to append this to the PendingReleaseNotes file so that the Release Manager can
When developing a new feature or making a (major) change to an existing feature you are encouraged to append this to the PendingReleaseNotes file so that the Release Manager can
use this file as a source of information when compiling the Release Notes for a new release.
When adding information to the PendingReleaseNotes file make sure that you write a good and understandable description of the new feature or change which you have developed.
@ -38,9 +38,9 @@ Fork the code
In your browser, navigate to: [https://github.com/apache/cloudstack](https://github.com/apache/cloudstack)
Fork the repository by clicking on the 'Fork' button on the top right hand side. The fork will happen and you will be taken to your own fork of the repository. Copy the Git repository URL by clicking on the clipboard next to the URL on the right hand side of the page under '**HTTPS** clone URL'. You will paste this URL when doing the following `git clone` command.
Fork the repository by clicking on the 'Fork' button on the top right hand side. The fork will happen, and you will be taken to your own fork of the repository. Copy the Git repository URL by clicking on the clipboard next to the URL on the right hand side of the page under '**HTTPS** clone URL'. You will paste this URL when doing the following `git clone` command.
On your computer, follow these steps to setup a local repository for working on ACS:
On your computer, follow these steps to set up a local repository for working on ACS:
```bash
$ git clone https://github.com/YOUR_ACCOUNT/cloudstack.git
@ -92,9 +92,9 @@ $ git rebase main
Make a GitHub Pull Request to contribute your changes
-----------------------------------------------------
When you are happy with your changes and you are ready to contribute them, you will create a Pull Request on GitHub to do so. This is done by pushing your local changes to your forked repository (default remote name is `origin`) and then initiating a pull request on GitHub.
When you are happy with your changes, and you are ready to contribute them, you will create a Pull Request on GitHub to do so. This is done by pushing your local changes to your forked repository (default remote name is `origin`) and then initiating a pull request on GitHub.
Please include JIRA id, detailed information about the bug/feature, what all tests are executed, how the reviewer can test this feature etc. Incase of UI PRs, a screenshot is preferred.
Please include JIRA id, detailed information about the bug/feature, what all tests are executed, how the reviewer can test this feature etc. In case of UI PRs, a screenshot is preferred.
> **IMPORTANT:** Make sure you have rebased your `feature_x` branch to include the latest code from `upstream/main` _before_ you do this.

View File

@ -20,10 +20,10 @@ Install tools and dependencies used for development:
Set up Maven (3.6.0):
# wget http://www.us.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
# tar -zxvf apache-maven-3.6.3-bin.tar.gz -C /usr/local
# 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
# cd /usr/local
# ln -s apache-maven-3.6.3 maven
# ln -s apache-maven-3.9.9 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
@ -37,6 +37,7 @@ Setup up NodeJS (LTS):
Start the MySQL service:
$ service mysqld start
$ mysql_secure_installation
### Using jenv and/or pyenv for Version Management
@ -86,13 +87,33 @@ Start the management server:
If this works, you've successfully setup a single server Apache CloudStack installation.
Open the following URL on your browser to access the Management Server UI:
http://localhost:8080/client/
To access the Management Server UI, follow the following procedure:
The default credentials are; user: admin, password: password and the domain
field should be left blank which is defaulted to the ROOT domain.
## To bring up CloudStack UI
Move to UI Directory
$ cd /path/to/cloudstack/ui
To install dependencies.
$ npm install
To build the project.
$ npm build
For Development Mode.
$ npm start
Make sure to set CS_URL=http://localhost:8080/client on .env.local file on ui.
You should be able to run the management server on http://localhost:5050
## Building with non-redistributable plugins
CloudStack supports several plugins that depend on libraries with distribution restrictions.

View File

@ -20,6 +20,19 @@ import os
import logging
import sys
import socket
# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
# ---- We do this so cloud_utils can be looked up in the following order:
# ---- 1) Sources directory
# ---- 2) waf configured PYTHONDIR
# ---- 3) System Python path
for pythonpath in (
"@PYTHONDIR@",
os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
):
if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
# ---- End snippet of code ----
from cloudutils.cloudException import CloudRuntimeException, CloudInternalException
from cloudutils.utilities import initLoging, bash
from cloudutils.configFileOps import configFileOps

View File

@ -20,6 +20,19 @@ import sys
import os
import subprocess
from threading import Timer
# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
# ---- We do this so cloud_utils can be looked up in the following order:
# ---- 1) Sources directory
# ---- 2) waf configured PYTHONDIR
# ---- 3) System Python path
for pythonpath in (
"@PYTHONDIR@",
os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
):
if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
# ---- End snippet of code ----
from xml.dom.minidom import parse
from cloudutils.configFileOps import configFileOps
from cloudutils.networkConfig import networkConfig

View File

@ -441,3 +441,9 @@ iscsi.session.cleanup.enabled=false
# Wait(in seconds) during agent reconnections. When no value is set then default value of 5s will be used
#backoff.seconds=
# Timeout (in seconds) to wait for the snapshot reversion to complete.
# revert.snapshot.timeout=10800
# Timeout (in seconds) to wait for the incremental snapshot to complete.
# incremental.snapshot.timeout=10800

View File

@ -342,7 +342,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...", e);
}
}
shell.updateConnectedHost();
shell.updateConnectedHost(((NioClient)connection).getHost());
scavengeOldAgentObjects();
}
@ -617,15 +617,11 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
protected void reconnect(final Link link) {
reconnect(link, null, null, false);
reconnect(link, null, false);
}
protected void reconnect(final Link link, String preferredHost, List<String> avoidHostList, boolean forTransfer) {
protected void reconnect(final Link link, String preferredMSHost, boolean forTransfer) {
if (!(forTransfer || reconnectAllowed)) {
return;
}
if (!reconnectAllowed) {
logger.debug("Reconnect requested but it is not allowed {}", () -> getLinkLog(link));
return;
}
@ -637,19 +633,26 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
serverResource.disconnected();
logger.info("Lost connection to host: {}. Attempting reconnection while we still have {} commands in progress.", shell.getConnectedHost(), commandsInProgress.get());
stopAndCleanupConnection(true);
String host = preferredMSHost;
if (org.apache.commons.lang3.StringUtils.isBlank(host)) {
host = shell.getNextHost();
}
List<String> avoidMSHostList = shell.getAvoidHosts();
do {
final String host = shell.getNextHost();
connection = new NioClient(getAgentName(), host, shell.getPort(), shell.getWorkers(), shell.getSslHandshakeTimeout(), this);
logger.info("Reconnecting to host: {}", host);
try {
connection.start();
} catch (final NioConnectionException e) {
logger.info("Attempted to re-connect to the server, but received an unexpected exception, trying again...", e);
stopAndCleanupConnection(false);
if (CollectionUtils.isEmpty(avoidMSHostList) || !avoidMSHostList.contains(host)) {
connection = new NioClient(getAgentName(), host, shell.getPort(), shell.getWorkers(), shell.getSslHandshakeTimeout(), this);
logger.info("Reconnecting to host: {}", host);
try {
connection.start();
} catch (final NioConnectionException e) {
logger.info("Attempted to re-connect to the server, but received an unexpected exception, trying again...", e);
stopAndCleanupConnection(false);
}
}
shell.getBackoffAlgorithm().waitBeforeRetry();
host = shell.getNextHost();
} while (!connection.isStartup());
shell.updateConnectedHost();
shell.updateConnectedHost(((NioClient)connection).getHost());
logger.info("Connected to the host: {}", shell.getConnectedHost());
}
@ -797,6 +800,9 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
commandsInProgress.incrementAndGet();
try {
if (cmd.isReconcile()) {
cmd.setRequestSequence(request.getSequence());
}
answer = serverResource.executeRequest(cmd);
} finally {
commandsInProgress.decrementAndGet();
@ -922,7 +928,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
return new SetupCertificateAnswer(true);
}
private void processManagementServerList(final List<String> msList, final String lbAlgorithm, final Long lbCheckInterval) {
private void processManagementServerList(final List<String> msList, final List<String> avoidMsList, final String lbAlgorithm, final Long lbCheckInterval) {
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);
@ -934,6 +940,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
throw new CloudRuntimeException("Could not persist received management servers list", e);
}
}
shell.setAvoidHosts(avoidMsList);
if ("shuffle".equals(lbAlgorithm)) {
scheduleHostLBCheckerTask(0);
} else {
@ -942,16 +949,18 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
private Answer setupManagementServerList(final SetupMSListCommand cmd) {
processManagementServerList(cmd.getMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval());
processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval());
return new SetupMSListAnswer(true);
}
private Answer migrateAgentToOtherMS(final MigrateAgentConnectionCommand cmd) {
try {
if (CollectionUtils.isNotEmpty(cmd.getMsList())) {
processManagementServerList(cmd.getMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval());
processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval());
}
migrateAgentConnection(cmd.getAvoidMsList());
Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("MigrateAgentConnection-Job")).schedule(() -> {
migrateAgentConnection(cmd.getAvoidMsList());
}, 3, TimeUnit.SECONDS);
} catch (Exception e) {
String errMsg = "Migrate agent connection failed, due to " + e.getMessage();
logger.debug(errMsg, e);
@ -972,25 +981,26 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
throw new CloudRuntimeException("No other Management Server hosts to migrate");
}
String preferredHost = null;
String preferredMSHost = null;
for (String msHost : msHostsList) {
try (final Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(msHost, shell.getPort()), 5000);
preferredHost = msHost;
preferredMSHost = msHost;
break;
} catch (final IOException e) {
throw new CloudRuntimeException("Management server host: " + msHost + " is not reachable, to migrate connection");
}
}
if (preferredHost == null) {
if (preferredMSHost == null) {
throw new CloudRuntimeException("Management server host(s) are not reachable, to migrate connection");
}
logger.debug("Management server host " + preferredHost + " is found to be reachable, trying to reconnect");
logger.debug("Management server host " + preferredMSHost + " is found to be reachable, trying to reconnect");
shell.resetHostCounter();
shell.setAvoidHosts(avoidMsList);
shell.setConnectionTransfer(true);
reconnect(link, preferredHost, avoidMsList, true);
reconnect(link, preferredMSHost, true);
}
public void processResponse(final Response response, final Link link) {
@ -1003,14 +1013,23 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
for (final IAgentControlListener listener : controlListeners) {
listener.processControlResponse(response, (AgentControlAnswer)answer);
}
} else if (answer instanceof PingAnswer && (((PingAnswer) answer).isSendStartup()) && reconnectAllowed) {
logger.info("Management server requested startup command to reinitialize the agent");
sendStartup(link);
} else if (answer instanceof PingAnswer) {
processPingAnswer((PingAnswer) answer);
} else {
updateLastPingResponseTime();
}
}
private void processPingAnswer(final PingAnswer answer) {
if ((answer.isSendStartup()) && reconnectAllowed) {
logger.info("Management server requested startup command to reinitialize the agent");
sendStartup(link);
} else {
serverResource.processPingAnswer((PingAnswer) answer);
}
shell.setAvoidHosts(answer.getAvoidMsList());
}
public void processReadyCommand(final Command cmd) {
final ReadyCommand ready = (ReadyCommand)cmd;
// Set human readable sizes;
@ -1027,7 +1046,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
verifyAgentArch(ready.getArch());
processManagementServerList(ready.getMsHostList(), ready.getLbAlgorithm(), ready.getLbCheckInterval());
processManagementServerList(ready.getMsHostList(), ready.getAvoidMsHostList(), ready.getLbAlgorithm(), ready.getLbCheckInterval());
logger.info("Ready command is processed for agent [id: {}, uuid: {}, name: {}]", getId(), getUuid(), getName());
}
@ -1073,6 +1092,9 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
Answer answer = null;
commandsInProgress.incrementAndGet();
try {
if (command.isReconcile()) {
command.setRequestSequence(req.getSequence());
}
answer = serverResource.executeRequest(command);
} finally {
commandsInProgress.decrementAndGet();
@ -1374,26 +1396,26 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
if (msList == null || msList.length < 1) {
return;
}
final String preferredHost = msList[0];
final String preferredMSHost = msList[0];
final String connectedHost = shell.getConnectedHost();
logger.debug("Running preferred host checker task, connected host={}, preferred host={}",
connectedHost, preferredHost);
if (preferredHost == null || preferredHost.equals(connectedHost) || link == null) {
connectedHost, preferredMSHost);
if (preferredMSHost == null || preferredMSHost.equals(connectedHost) || link == null) {
return;
}
boolean isHostUp = false;
try (final Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(preferredHost, shell.getPort()), 5000);
socket.connect(new InetSocketAddress(preferredMSHost, shell.getPort()), 5000);
isHostUp = true;
} catch (final IOException e) {
logger.debug("Host: {} is not reachable", preferredHost);
logger.debug("Host: {} is not reachable", preferredMSHost);
}
if (isHostUp && link != null && commandsInProgress.get() == 0) {
if (logger.isDebugEnabled()) {
logger.debug("Preferred host {} is found to be reachable, trying to reconnect", preferredHost);
logger.debug("Preferred host {} is found to be reachable, trying to reconnect", preferredMSHost);
}
shell.resetHostCounter();
reconnect(link);
reconnect(link, preferredMSHost, false);
}
} catch (Throwable t) {
logger.error("Error caught while attempting to connect to preferred host", t);

View File

@ -66,6 +66,7 @@ public class AgentShell implements IAgentShell, Daemon {
private String _zone;
private String _pod;
private String _host;
private List<String> _avoidHosts;
private String _privateIp;
private int _port;
private int _proxyPort;
@ -76,7 +77,6 @@ public class AgentShell implements IAgentShell, Daemon {
private volatile boolean _exit = false;
private int _pingRetries;
private final List<Agent> _agents = new ArrayList<Agent>();
private String hostToConnect;
private String connectedHost;
private Long preferredHostCheckInterval;
private boolean connectionTransfer = false;
@ -121,7 +121,7 @@ public class AgentShell implements IAgentShell, Daemon {
if (_hostCounter >= hosts.length) {
_hostCounter = 0;
}
hostToConnect = hosts[_hostCounter % hosts.length];
String hostToConnect = hosts[_hostCounter % hosts.length];
_hostCounter++;
return hostToConnect;
}
@ -143,11 +143,10 @@ public class AgentShell implements IAgentShell, Daemon {
}
@Override
public void updateConnectedHost() {
connectedHost = hostToConnect;
public void updateConnectedHost(String connectedHost) {
this.connectedHost = connectedHost;
}
@Override
public void resetHostCounter() {
_hostCounter = 0;
@ -166,6 +165,16 @@ public class AgentShell implements IAgentShell, Daemon {
}
}
@Override
public void setAvoidHosts(List<String> avoidHosts) {
_avoidHosts = avoidHosts;
}
@Override
public List<String> getAvoidHosts() {
return _avoidHosts;
}
@Override
public String getPrivateIp() {
return _privateIp;

View File

@ -16,6 +16,7 @@
// under the License.
package com.cloud.agent;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@ -63,9 +64,13 @@ public interface IAgentShell {
String[] getHosts();
void setAvoidHosts(List<String> hosts);
List<String> getAvoidHosts();
long getLbCheckerInterval(Long receivedLbInterval);
void updateConnectedHost();
void updateConnectedHost(String connectedHost);
String getConnectedHost();

View File

@ -816,7 +816,17 @@ public class AgentProperties{
* Data type: Integer.<br>
* Default value: <code>null</code>
*/
public static final Property<Integer> SSL_HANDSHAKE_TIMEOUT = new Property<>("ssl.handshake.timeout", null, Integer.class);
public static final Property<Integer> SSL_HANDSHAKE_TIMEOUT = new Property<>("ssl.handshake.timeout", 30, Integer.class);
/**
* Timeout (in seconds) to wait for the incremental snapshot to complete.
* */
public static final Property<Integer> INCREMENTAL_SNAPSHOT_TIMEOUT = new Property<>("incremental.snapshot.timeout", 10800);
/**
* Timeout (in seconds) to wait for the snapshot reversion to complete.
* */
public static final Property<Integer> REVERT_SNAPSHOT_TIMEOUT = new Property<>("revert.snapshot.timeout", 10800);
public static class Property <T>{
private String name;

View File

@ -358,7 +358,7 @@ public class AgentShellTest {
AgentShell shell = new AgentShell();
shell.setHosts("test");
shell.getNextHost();
shell.updateConnectedHost();
shell.updateConnectedHost("test");
Assert.assertEquals(expected, shell.getConnectedHost());
}

View File

@ -35,6 +35,23 @@ public abstract class Command {
Continue, Stop
}
public enum State {
CREATED, // Command is created by management server
STARTED, // Command is started by agent
PROCESSING, // Processing by agent
PROCESSING_IN_BACKEND, // Processing in backend by agent
COMPLETED, // Operation succeeds by agent or management server
FAILED, // Operation fails by agent
RECONCILE_RETRY, // Ready for retry of reconciliation
RECONCILING, // Being reconciled by management server
RECONCILED, // Reconciled by management server
RECONCILE_SKIPPED, // Skip the reconciliation as the resource state is inconsistent with the command
RECONCILE_FAILED, // Fail to reconcile by management server
TIMED_OUT, // Timed out on management server or agent
INTERRUPTED, // Interrupted by management server or agent (for example agent is restarted),
DANGLED_IN_BACKEND // Backend process which cannot be processed normally (for example agent is restarted)
}
public static final String HYPERVISOR_TYPE = "hypervisorType";
// allow command to carry over hypervisor or other environment related context info
@ -42,6 +59,7 @@ public abstract class Command {
protected Map<String, String> contextMap = new HashMap<String, String>();
private int wait; //in second
private boolean bypassHostMaintenance = false;
private transient long requestSequence = 0L;
protected Command() {
this.wait = 0;
@ -82,6 +100,10 @@ public abstract class Command {
return contextMap.get(name);
}
public Map<String, String> getContextMap() {
return contextMap;
}
public boolean allowCaching() {
return true;
}
@ -94,6 +116,18 @@ public abstract class Command {
this.bypassHostMaintenance = bypassHostMaintenance;
}
public boolean isReconcile() {
return false;
}
public long getRequestSequence() {
return requestSequence;
}
public void setRequestSequence(long requestSequence) {
this.requestSequence = requestSequence;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View File

@ -46,7 +46,7 @@ public class DiskTO {
private Long diskSeq;
private String path;
private Volume.Type type;
private Map<String, String> _details;
private Map<String, String> details;
public DiskTO() {
@ -92,10 +92,10 @@ public class DiskTO {
}
public void setDetails(Map<String, String> details) {
_details = details;
this.details = details;
}
public Map<String, String> getDetails() {
return _details;
return details;
}
}

View File

@ -36,7 +36,7 @@ public class NetworkTO {
protected TrafficType type;
protected URI broadcastUri;
protected URI isolationUri;
protected boolean isSecurityGroupEnabled;
protected boolean securityGroupEnabled;
protected String name;
protected String ip6address;
protected String ip6gateway;
@ -112,7 +112,7 @@ public class NetworkTO {
}
public void setSecurityGroupEnabled(boolean enabled) {
this.isSecurityGroupEnabled = enabled;
this.securityGroupEnabled = enabled;
}
/**
@ -221,7 +221,7 @@ public class NetworkTO {
}
public boolean isSecurityGroupEnabled() {
return this.isSecurityGroupEnabled;
return this.securityGroupEnabled;
}
public void setIp6Dns1(String ip6Dns1) {

View File

@ -86,6 +86,14 @@ public class NicTO extends NetworkTO {
this.nicUuid = uuid;
}
public String getNicUuid() {
return nicUuid;
}
public void setNicUuid(String nicUuid) {
this.nicUuid = nicUuid;
}
@Override
public String toString() {
return new StringBuilder("[Nic:").append(type).append("-").append(ip).append("-").append(broadcastUri).append("]").toString();

View File

@ -61,7 +61,7 @@ public class VirtualMachineTO {
@LogLevel(LogLevel.Log4jLevel.Off)
String vncPassword;
String vncAddr;
Map<String, String> params;
Map<String, String> details;
String uuid;
String bootType;
String bootMode;
@ -191,7 +191,11 @@ public class VirtualMachineTO {
return maxSpeed;
}
public boolean getLimitCpuUse() {
public boolean isEnableHA() {
return enableHA;
}
public boolean isLimitCpuUse() {
return limitCpuUse;
}
@ -289,11 +293,11 @@ public class VirtualMachineTO {
}
public Map<String, String> getDetails() {
return params;
return details;
}
public void setDetails(Map<String, String> params) {
this.params = params;
this.details = params;
}
public String getUuid() {

View File

@ -201,11 +201,12 @@ public interface ConfigurationService {
* TODO
* @param allocationState
* TODO
* @param storageAccessGroups
* @return the new pod if successful, null otherwise
* @throws
* @throws
*/
Pod createPod(long zoneId, String name, String startIp, String endIp, String gateway, String netmask, String allocationState);
Pod createPod(long zoneId, String name, String startIp, String endIp, String gateway, String netmask, String allocationState, List<String> storageAccessGroups);
/**
* Creates a mutual exclusive IP range in the pod with same gateway, netmask.

View File

@ -16,52 +16,55 @@
// under the License.
package com.cloud.cpu;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.lang3.StringUtils;
import java.util.LinkedHashMap;
import java.util.Map;
public class CPU {
public enum CPUArch {
x86("i686", 32),
amd64("x86_64", 64),
arm64("aarch64", 64);
public static final String archX86Identifier = "i686";
public static final String archX86_64Identifier = "x86_64";
public static final String archARM64Identifier = "aarch64";
private final String type;
private final int bits;
public static class CPUArch {
private static final Map<String, CPUArch> cpuArchMap = new LinkedHashMap<>();
public static final CPUArch archX86 = new CPUArch(archX86Identifier, 32);
public static final CPUArch amd64 = new CPUArch(archX86_64Identifier, 64);
public static final CPUArch arm64 = new CPUArch(archARM64Identifier, 64);
private String type;
private int bits;
public CPUArch(String type, int bits) {
CPUArch(String type, int bits) {
this.type = type;
this.bits = bits;
cpuArchMap.put(type, this);
}
public static CPUArch getDefault() {
return amd64;
}
public String getType() {
return this.type;
return type;
}
public int getBits() {
return this.bits;
return bits;
}
public static CPUArch fromType(String type) {
if (StringUtils.isBlank(type)) {
return amd64;
return getDefault();
}
switch (type) {
case archX86Identifier: return archX86;
case archX86_64Identifier: return amd64;
case archARM64Identifier: return arm64;
default: throw new CloudRuntimeException(String.format("Unsupported arch type: %s", type));
for (CPUArch arch : values()) {
if (arch.type.equals(type)) {
return arch;
}
}
throw new IllegalArgumentException("Unsupported arch type: " + type);
}
public static String getTypesAsCSV() {
StringBuilder sb = new StringBuilder();
for (CPUArch arch : values()) {
sb.append(arch.getType()).append(",");
}
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}
}
}

View File

@ -43,4 +43,6 @@ public interface Pod extends InfrastructureEntity, Grouping, Identity, InternalI
AllocationState getAllocationState();
boolean getExternalDhcp();
String getStorageAccessGroups();
}

View File

@ -62,7 +62,7 @@ public interface DeploymentClusterPlanner extends DeploymentPlanner {
"vm.allocation.algorithm",
"Advanced",
"random",
"Order in which hosts within a cluster will be considered for VM/volume allocation. The value can be 'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit', or 'firstfitleastconsumed'.",
"Order in which hosts within a cluster will be considered for VM allocation. The value can be 'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit', or 'firstfitleastconsumed'.",
true,
ConfigKey.Scope.Global, null, null, null, null, null,
ConfigKey.Kind.Select,

View File

@ -465,6 +465,7 @@ public class EventTypes {
public static final String EVENT_ENABLE_PRIMARY_STORAGE = "ENABLE.PS";
public static final String EVENT_DISABLE_PRIMARY_STORAGE = "DISABLE.PS";
public static final String EVENT_SYNC_STORAGE_POOL = "SYNC.STORAGE.POOL";
public static final String EVENT_CONFIGURE_STORAGE_ACCESS = "CONFIGURE.STORAGE.ACCESS";
public static final String EVENT_CHANGE_STORAGE_POOL_SCOPE = "CHANGE.STORAGE.POOL.SCOPE";
// VPN
@ -739,6 +740,13 @@ public class EventTypes {
//Purge resources
public static final String EVENT_PURGE_EXPUNGED_RESOURCES = "PURGE.EXPUNGED.RESOURCES";
// Management Server
public static final String EVENT_MS_MAINTENANCE_PREPARE = "MS.MAINTENANCE.PREPARE";
public static final String EVENT_MS_MAINTENANCE_CANCEL = "MS.MAINTENANCE.CANCEL";
public static final String EVENT_MS_SHUTDOWN_PREPARE = "MS.SHUTDOWN.PREPARE";
public static final String EVENT_MS_SHUTDOWN_CANCEL = "MS.SHUTDOWN.CANCEL";
public static final String EVENT_MS_SHUTDOWN = "MS.SHUTDOWN";
// OBJECT STORE
public static final String EVENT_OBJECT_STORE_CREATE = "OBJECT.STORE.CREATE";
public static final String EVENT_OBJECT_STORE_DELETE = "OBJECT.STORE.DELETE";
@ -788,6 +796,11 @@ public class EventTypes {
// Resource Limit
public static final String EVENT_RESOURCE_LIMIT_UPDATE = "RESOURCE.LIMIT.UPDATE";
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";
public static final String VM_LEASE_EXPIRING = "VM.LEASE.EXPIRING";
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@ -1233,6 +1246,12 @@ public class EventTypes {
entityEventDetails.put(EVENT_UPDATE_IMAGE_STORE_ACCESS_STATE, ImageStore.class);
entityEventDetails.put(EVENT_LIVE_PATCH_SYSTEMVM, "SystemVMs");
entityEventDetails.put(EVENT_MS_MAINTENANCE_PREPARE, "ManagementServer");
entityEventDetails.put(EVENT_MS_MAINTENANCE_CANCEL, "ManagementServer");
entityEventDetails.put(EVENT_MS_SHUTDOWN_PREPARE, "ManagementServer");
entityEventDetails.put(EVENT_MS_SHUTDOWN_CANCEL, "ManagementServer");
entityEventDetails.put(EVENT_MS_SHUTDOWN, "ManagementServer");
//Object Store
entityEventDetails.put(EVENT_OBJECT_STORE_CREATE, ObjectStore.class);
entityEventDetails.put(EVENT_OBJECT_STORE_UPDATE, ObjectStore.class);
@ -1276,6 +1295,12 @@ public class EventTypes {
entityEventDetails.put(EVENT_SHAREDFS_DESTROY, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_EXPUNGE, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_RECOVER, SharedFS.class);
// VM Lease
entityEventDetails.put(VM_LEASE_EXPIRED, VirtualMachine.class);
entityEventDetails.put(VM_LEASE_EXPIRING, VirtualMachine.class);
entityEventDetails.put(VM_LEASE_DISABLED, VirtualMachine.class);
entityEventDetails.put(VM_LEASE_CANCELLED, VirtualMachine.class);
}
public static boolean isNetworkEvent(String eventType) {

View File

@ -213,4 +213,6 @@ public interface Host extends StateObject<Status>, Identity, Partition, HAResour
ResourceState getResourceState();
CPU.CPUArch getArch();
String getStorageAccessGroups();
}

View File

@ -18,6 +18,7 @@ package com.cloud.kubernetes.cluster;
import org.apache.cloudstack.acl.ControlledEntity;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Adapter;
@ -26,4 +27,5 @@ public interface KubernetesServiceHelper extends Adapter {
ControlledEntity findByUuid(String uuid);
ControlledEntity findByVmId(long vmId);
void checkVmCanBeDestroyed(UserVm userVm);
void cleanupForAccount(Account account);
}

View File

@ -41,4 +41,6 @@ public interface Cluster extends Grouping, Partition {
ManagedState getManagedState();
CPU.CPUArch getArch();
String getStorageAccessGroups();
}

View File

@ -95,4 +95,11 @@ public interface ResourceService {
boolean releaseHostReservation(Long hostId);
void updatePodStorageAccessGroups(long podId, List<String> newStorageAccessGroups);
void updateZoneStorageAccessGroups(long zoneId, List<String> newStorageAccessGroups);
void updateClusterStorageAccessGroups(Long clusterId, List<String> newStorageAccessGroups);
void updateHostStorageAccessGroups(Long hostId, List<String> newStorageAccessGroups);
}

View File

@ -24,6 +24,7 @@ public class MigrationOptions implements Serializable {
private String srcPoolUuid;
private Storage.StoragePoolType srcPoolType;
private Long srcPoolClusterId;
private Type type;
private ScopeType scopeType;
private String srcBackingFilePath;
@ -38,21 +39,23 @@ public class MigrationOptions implements Serializable {
public MigrationOptions() {
}
public MigrationOptions(String srcPoolUuid, Storage.StoragePoolType srcPoolType, String srcBackingFilePath, boolean copySrcTemplate, ScopeType scopeType) {
public MigrationOptions(String srcPoolUuid, Storage.StoragePoolType srcPoolType, String srcBackingFilePath, boolean copySrcTemplate, ScopeType scopeType, Long srcPoolClusterId) {
this.srcPoolUuid = srcPoolUuid;
this.srcPoolType = srcPoolType;
this.type = Type.LinkedClone;
this.scopeType = scopeType;
this.srcBackingFilePath = srcBackingFilePath;
this.copySrcTemplate = copySrcTemplate;
this.srcPoolClusterId = srcPoolClusterId;
}
public MigrationOptions(String srcPoolUuid, Storage.StoragePoolType srcPoolType, String srcVolumeUuid, ScopeType scopeType) {
public MigrationOptions(String srcPoolUuid, Storage.StoragePoolType srcPoolType, String srcVolumeUuid, ScopeType scopeType, Long srcPoolClusterId) {
this.srcPoolUuid = srcPoolUuid;
this.srcPoolType = srcPoolType;
this.type = Type.FullClone;
this.scopeType = scopeType;
this.srcVolumeUuid = srcVolumeUuid;
this.srcPoolClusterId = srcPoolClusterId;
}
public String getSrcPoolUuid() {
@ -63,6 +66,10 @@ public class MigrationOptions implements Serializable {
return srcPoolType;
}
public Long getSrcPoolClusterId() {
return srcPoolClusterId;
}
public ScopeType getScopeType() { return scopeType; }
public String getSrcBackingFilePath() {

View File

@ -48,7 +48,7 @@ public interface Snapshot extends ControlledEntity, Identity, InternalIdentity,
}
public enum State {
Allocated, Creating, CreatedOnPrimary, BackingUp, BackedUp, Copying, Destroying, Destroyed,
Allocated, Creating, CreatedOnPrimary, BackingUp, BackedUp, Copying, Destroying, Destroyed, Hidden,
//it's a state, user can't see the snapshot from ui, while the snapshot may still exist on the storage
Error;

View File

@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd;
import org.apache.cloudstack.api.command.admin.storage.ChangeStoragePoolScopeCmd;
import org.apache.cloudstack.api.command.admin.storage.ConfigureStorageAccessCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd;
@ -99,6 +100,8 @@ public interface StorageService {
StoragePool disablePrimaryStoragePool(Long id);
boolean configureStorageAccess(ConfigureStorageAccessCmd cmd);
StoragePool getStoragePool(long id);
boolean deleteImageStore(DeleteImageStoreCmd cmd);

View File

@ -17,6 +17,7 @@
package com.cloud.storage;
import java.util.Date;
import java.util.List;
import org.apache.cloudstack.api.InternalIdentity;
@ -25,6 +26,8 @@ public interface VMTemplateStorageResourceAssoc extends InternalIdentity {
UNKNOWN, DOWNLOAD_ERROR, NOT_DOWNLOADED, DOWNLOAD_IN_PROGRESS, DOWNLOADED, ABANDONED, UPLOADED, NOT_UPLOADED, UPLOAD_ERROR, UPLOAD_IN_PROGRESS, CREATING, CREATED, BYPASSED
}
List<Status> PENDING_DOWNLOAD_STATES = List.of(Status.NOT_DOWNLOADED, Status.DOWNLOAD_IN_PROGRESS);
String getInstallPath();
long getTemplateId();

View File

@ -71,6 +71,7 @@ public interface Account extends ControlledEntity, InternalIdentity, Identity {
}
public static final long ACCOUNT_ID_SYSTEM = 1;
public static final long ACCOUNT_ID_ADMIN = 2;
public String getAccountName();

View File

@ -101,4 +101,17 @@ public interface VmDetailConstants {
String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX);
String VMWARE_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX);
String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", VMWARE_TO_KVM_PREFIX);
// TPM
String VIRTUAL_TPM_ENABLED = "virtual.tpm.enabled";
String VIRTUAL_TPM_MODEL = "virtual.tpm.model";
String VIRTUAL_TPM_VERSION = "virtual.tpm.version";
// CPU mode and model, ADMIN only
String GUEST_CPU_MODE = "guest.cpu.mode";
String GUEST_CPU_MODEL = "guest.cpu.model";
String INSTANCE_LEASE_EXPIRY_DATE = "leaseexpirydate";
String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction";
String INSTANCE_LEASE_EXECUTION = "leaseactionexecution";
}

View File

@ -269,7 +269,10 @@ public class ApiConstants {
public static final String INTERNAL_DNS2 = "internaldns2";
public static final String INTERNET_PROTOCOL = "internetprotocol";
public static final String INTERVAL_TYPE = "intervaltype";
public static final String LOCATION_TYPE = "locationtype";
public static final String INSTANCE_LEASE_DURATION = "leaseduration";
public static final String INSTANCE_LEASE_ENABLED = "instanceleaseenabled";
public static final String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction";
public static final String INSTANCE_LEASE_EXPIRY_DATE= "leaseexpirydate";
public static final String IOPS_READ_RATE = "iopsreadrate";
public static final String IOPS_READ_RATE_MAX = "iopsreadratemax";
public static final String IOPS_READ_RATE_MAX_LENGTH = "iopsreadratemaxlength";
@ -317,11 +320,13 @@ public class ApiConstants {
public static final String LAST_BOOT = "lastboottime";
public static final String LAST_SERVER_START = "lastserverstart";
public static final String LAST_SERVER_STOP = "lastserverstop";
public static final String LEASED = "leased";
public static final String LEVEL = "level";
public static final String LENGTH = "length";
public static final String LIMIT = "limit";
public static final String LIMIT_CPU_USE = "limitcpuuse";
public static final String LIST_HOSTS = "listhosts";
public static final String LOCATION_TYPE = "locationtype";
public static final String LOCK = "lock";
public static final String LUN = "lun";
public static final String LBID = "lbruleid";
@ -456,6 +461,7 @@ public class ApiConstants {
public static final String SENT = "sent";
public static final String SENT_BYTES = "sentbytes";
public static final String SERIAL = "serial";
public static final String SERVICE_IP = "serviceip";
public static final String SERVICE_OFFERING_ID = "serviceofferingid";
public static final String SESSIONKEY = "sessionkey";
public static final String SHOW_CAPACITIES = "showcapacities";
@ -485,18 +491,22 @@ public class ApiConstants {
public static final String STATE = "state";
public static final String STATS = "stats";
public static final String STATUS = "status";
public static final String STORAGE_TYPE = "storagetype";
public static final String STORAGE_POLICY = "storagepolicy";
public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled";
public static final String STORAGE_CAPABILITIES = "storagecapabilities";
public static final String STORAGE_CUSTOM_STATS = "storagecustomstats";
public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled";
public static final String STORAGE_POLICY = "storagepolicy";
public static final String STORAGE_POOL = "storagepool";
public static final String STORAGE_TYPE = "storagetype";
public static final String SUBNET = "subnet";
public static final String OWNER = "owner";
public static final String SWAP_OWNER = "swapowner";
public static final String SYSTEM_VM_TYPE = "systemvmtype";
public static final String TAGS = "tags";
public static final String STORAGE_TAGS = "storagetags";
public static final String STORAGE_ACCESS_GROUPS = "storageaccessgroups";
public static final String STORAGE_ACCESS_GROUP = "storageaccessgroup";
public static final String CLUSTER_STORAGE_ACCESS_GROUPS = "clusterstorageaccessgroups";
public static final String POD_STORAGE_ACCESS_GROUPS = "podstorageaccessgroups";
public static final String ZONE_STORAGE_ACCESS_GROUPS = "zonestorageaccessgroups";
public static final String SUCCESS = "success";
public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine";
public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot";
@ -1150,6 +1160,7 @@ public class ApiConstants {
public static final String PENDING_JOBS_COUNT = "pendingjobscount";
public static final String AGENTS_COUNT = "agentscount";
public static final String AGENTS = "agents";
public static final String LAST_AGENTS = "lastagents";
public static final String PUBLIC_MTU = "publicmtu";
public static final String PRIVATE_MTU = "privatemtu";

View File

@ -30,6 +30,7 @@ public enum ApiErrorCode {
UNSUPPORTED_ACTION_ERROR(432),
API_LIMIT_EXCEED(429),
SERVICE_UNAVAILABLE(503),
INTERNAL_ERROR(530),
ACCOUNT_ERROR(531),
ACCOUNT_RESOURCE_LIMIT_ERROR(532),

View File

@ -310,6 +310,8 @@ public interface ResponseGenerator {
PodResponse createPodResponse(Pod pod, Boolean showCapacities);
PodResponse createMinimalPodResponse(Pod pod);
ZoneResponse createZoneResponse(ResponseView view, DataCenter dataCenter, Boolean showCapacities, Boolean showResourceIcon);
DataCenterGuestIpv6PrefixResponse createDataCenterGuestIpv6PrefixResponse(DataCenterGuestIpv6Prefix prefix);
@ -324,6 +326,8 @@ public interface ResponseGenerator {
ClusterResponse createClusterResponse(Cluster cluster, Boolean showCapacities);
ClusterResponse createMinimalClusterResponse(Cluster cluster);
FirewallRuleResponse createPortForwardingRuleResponse(PortForwardingRule fwRule);
IpForwardingRuleResponse createIpForwardingRuleResponse(StaticNatRule fwRule);

View File

@ -118,6 +118,12 @@ public class AddClusterCmd extends BaseCmd {
private String ovm3cluster;
@Parameter(name = ApiConstants.OVM3_VIP, type = CommandType.STRING, required = false, description = "Ovm3 vip to use for pool (and cluster)")
private String ovm3vip;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS,
type = CommandType.LIST, collectionType = CommandType.STRING,
description = "comma separated list of storage access groups for the hosts in the cluster",
since = "4.21.0")
private List<String> storageAccessGroups;
public String getOvm3Pool() {
return ovm3pool;
}
@ -192,6 +198,10 @@ public class AddClusterCmd extends BaseCmd {
this.clusterType = type;
}
public List<String> getStorageAccessGroups() {
return storageAccessGroups;
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;

View File

@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.cluster;
import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
@ -28,7 +27,9 @@ import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.org.Cluster;
import com.cloud.utils.Pair;
@ -68,6 +69,16 @@ public class ListClustersCmd extends BaseListCmd {
@Parameter(name = ApiConstants.SHOW_CAPACITIES, type = CommandType.BOOLEAN, description = "flag to display the capacity of the clusters")
private Boolean showCapacities;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "CPU arch of the clusters",
since = "4.20.1")
private String arch;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUP, type = CommandType.STRING,
description = "the name of the storage access group",
since = "4.21.0")
private String storageAccessGroup;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -112,6 +123,22 @@ public class ListClustersCmd extends BaseListCmd {
return showCapacities;
}
public CPU.CPUArch getArch() {
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
}
public String getStorageAccessGroup() {
return storageAccessGroup;
}
public ListClustersCmd() {
}
public ListClustersCmd(String storageAccessGroup) {
this.storageAccessGroup = storageAccessGroup;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -130,7 +130,7 @@ public class UpdateClusterCmd extends BaseCmd {
}
Cluster result = _resourceService.updateCluster(this);
if (result != null) {
ClusterResponse clusterResponse = _responseGenerator.createClusterResponse(cluster, false);
ClusterResponse clusterResponse = _responseGenerator.createClusterResponse(result, false);
clusterResponse.setResponseName(getCommandName());
this.setResponseObject(clusterResponse);
} else {

View File

@ -75,6 +75,12 @@ public class AddHostCmd extends BaseCmd {
@Parameter(name = ApiConstants.HOST_TAGS, type = CommandType.LIST, collectionType = CommandType.STRING, description = "list of tags to be added to the host")
private List<String> hostTags;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS,
type = CommandType.LIST, collectionType = CommandType.STRING,
description = "comma separated list of storage access groups for the host",
since = "4.21.0")
private List<String> storageAccessGroups;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -115,6 +121,10 @@ public class AddHostCmd extends BaseCmd {
return hostTags;
}
public List<String> getStorageAccessGroups() {
return storageAccessGroups;
}
public String getAllocationState() {
return allocationState;
}

View File

@ -21,7 +21,6 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@ -35,7 +34,9 @@ import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@ -109,6 +110,14 @@ public class ListHostsCmd extends BaseListCmd {
@Parameter(name = ApiConstants.MANAGEMENT_SERVER_ID, type = CommandType.UUID, entityType = ManagementServerResponse.class, description = "the id of the management server", since="4.21.0")
private Long managementServerId;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING, description = "CPU Arch of the host", since = "4.20.1")
private String arch;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUP, type = CommandType.STRING,
description = "the name of the storage access group",
since = "4.21.0")
private String storageAccessGroup;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -197,6 +206,22 @@ public class ListHostsCmd extends BaseListCmd {
return managementServerId;
}
public CPU.CPUArch getArch() {
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
}
public String getStorageAccessGroup() {
return storageAccessGroup;
}
public ListHostsCmd() {
}
public ListHostsCmd(String storageAccessGroup) {
this.storageAccessGroup = storageAccessGroup;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -34,7 +34,9 @@ import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.VsphereStoragePoliciesResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.vm.lease.VMLeaseManager;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.collections.CollectionUtils;
@ -251,7 +253,15 @@ public class CreateServiceOfferingCmd extends BaseCmd {
since="4.20")
private Boolean purgeResources;
@Parameter(name = ApiConstants.INSTANCE_LEASE_DURATION,
type = CommandType.INTEGER,
description = "Number of days instance is leased for.",
since = "4.21.0")
private Integer leaseDuration;
@Parameter(name = ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION, type = CommandType.STRING, since = "4.21.0",
description = "Lease expiry action, valid values are STOP and DESTROY")
private String leaseExpiryAction;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -487,6 +497,22 @@ public class CreateServiceOfferingCmd extends BaseCmd {
return false;
}
public VMLeaseManager.ExpiryAction getLeaseExpiryAction() {
if (StringUtils.isBlank(leaseExpiryAction)) {
return null;
}
VMLeaseManager.ExpiryAction action = EnumUtils.getEnumIgnoreCase(VMLeaseManager.ExpiryAction.class, leaseExpiryAction);
if (action == null) {
throw new InvalidParameterValueException("Invalid value configured for leaseexpiryaction, valid values are: " +
com.cloud.utils.EnumUtils.listValues(VMLeaseManager.ExpiryAction.values()));
}
return action;
}
public Integer getLeaseDuration() {
return leaseDuration;
}
public boolean isPurgeResources() {
return Boolean.TRUE.equals(purgeResources);
}

View File

@ -30,6 +30,8 @@ import org.apache.cloudstack.api.response.ZoneResponse;
import com.cloud.dc.Pod;
import com.cloud.user.Account;
import java.util.List;
@APICommand(name = "createPod", description = "Creates a new Pod.", responseObject = PodResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class CreatePodCmd extends BaseCmd {
@ -63,6 +65,12 @@ public class CreatePodCmd extends BaseCmd {
@Parameter(name = ApiConstants.ALLOCATION_STATE, type = CommandType.STRING, description = "Allocation state of this Pod for allocation of new resources")
private String allocationState;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS,
type = CommandType.LIST, collectionType = CommandType.STRING,
description = "comma separated list of storage access groups for the hosts in the pod",
since = "4.21.0")
private List<String> storageAccessGroups;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -95,6 +103,10 @@ public class CreatePodCmd extends BaseCmd {
return allocationState;
}
public List<String> getStorageAccessGroups() {
return storageAccessGroups;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -111,7 +123,7 @@ public class CreatePodCmd extends BaseCmd {
@Override
public void execute() {
Pod result = _configService.createPod(getZoneId(), getPodName(), getStartIp(), getEndIp(), getGateway(), getNetmask(), getAllocationState());
Pod result = _configService.createPod(getZoneId(), getPodName(), getStartIp(), getEndIp(), getGateway(), getNetmask(), getAllocationState(), getStorageAccessGroups());
if (result != null) {
PodResponse response = _responseGenerator.createPodResponse(result, false);
response.setResponseName(getCommandName());

View File

@ -55,6 +55,11 @@ public class ListPodsByCmd extends BaseListCmd {
@Parameter(name = ApiConstants.SHOW_CAPACITIES, type = CommandType.BOOLEAN, description = "flag to display the capacity of the pods")
private Boolean showCapacities;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUP, type = CommandType.STRING,
description = "the name of the storage access group",
since = "4.21.0")
private String storageAccessGroup;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -79,6 +84,18 @@ public class ListPodsByCmd extends BaseListCmd {
return showCapacities;
}
public String getStorageAccessGroup() {
return storageAccessGroup;
}
public ListPodsByCmd() {
}
public ListPodsByCmd(String storageAccessGroup) {
this.storageAccessGroup = storageAccessGroup;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -16,8 +16,6 @@
// under the License.
package org.apache.cloudstack.api.command.admin.router;
import org.apache.commons.lang.BooleanUtils;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@ -32,7 +30,10 @@ import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VpcResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.network.router.VirtualRouter.Role;
import com.cloud.vm.VirtualMachine;
@ -86,6 +87,11 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd {
description = "if true is passed for this parameter, also fetch last executed health check results for the router. Default is false")
private Boolean fetchHealthCheckResults;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "CPU arch of the router",
since = "4.20.1")
private String arch;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -146,6 +152,10 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd {
return BooleanUtils.isTrue(fetchHealthCheckResults);
}
public CPU.CPUArch getArch() {
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////

View File

@ -0,0 +1,135 @@
// 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.storage;
import java.util.List;
import com.cloud.event.EventTypes;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import com.cloud.user.Account;
@APICommand(name = "configureStorageAccess", description = "Configure the storage access groups on zone/pod/cluster/host and storage, accordingly connections to the storage pools", responseObject = SuccessResponse.class, since = "4.21.0",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ConfigureStorageAccessCmd extends BaseAsyncCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, description = "UUID of the zone")
private Long zoneId;
@Parameter(name = ApiConstants.POD_ID, type = CommandType.UUID, entityType = PodResponse.class, description = "UUID of the pod")
private Long podId;
@Parameter(name = ApiConstants.CLUSTER_ID, type = CommandType.UUID, entityType = ClusterResponse.class, description = "UUID of the cluster")
private Long clusterId;
@Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, description = "UUID of the host")
private Long hostId;
@Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, description = "UUID of the Storage Pool")
private Long storageId;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS, type = CommandType.LIST, collectionType = CommandType.STRING,
description = "comma separated list of storage access groups for connecting the storage pools and the hosts",
since = "4.21.0")
private List<String> storageAccessGroups;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getZoneId() {
return zoneId;
}
public Long getPodId() {
return podId;
}
public Long getClusterId() {
return clusterId;
}
public Long getHostId() {
return hostId;
}
public Long getStorageId() {
return storageId;
}
public List<String> getStorageAccessGroups() {
return storageAccessGroups;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.StoragePool;
}
@Override
public void execute() {
try {
boolean result = _storageService.configureStorageAccess(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to configure storage access");
}
} catch (Exception e) {
logger.debug("Failed to configure storage access ", e);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to configure storage access, " + e.getMessage());
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_CONFIGURE_STORAGE_ACCESS;
}
@Override
public String getEventDescription() {
return "configuring storage access groups";
}
}

View File

@ -61,6 +61,10 @@ public class CreateStoragePoolCmd extends BaseCmd {
@Parameter(name = ApiConstants.TAGS, type = CommandType.STRING, description = "the tags for the storage pool")
private String tags;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS, type = CommandType.STRING,
description = "comma separated list of storage access groups for connecting to hosts having those specific groups", since = "4.21.0")
private String storageAccessGroups;
@Parameter(name = ApiConstants.URL, type = CommandType.STRING, required = true, description = "the URL of the storage pool")
private String url;
@ -115,6 +119,10 @@ public class CreateStoragePoolCmd extends BaseCmd {
return tags;
}
public String getStorageAccessGroups() {
return storageAccessGroups;
}
public String getUrl() {
return url;
}

View File

@ -0,0 +1,65 @@
/*
* 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.storage;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.StorageAccessGroupResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.response.ListResponse;
@APICommand(name = "listStorageAccessGroups", description = "Lists storage access groups", responseObject = StorageAccessGroupResponse.class, since = "4.21.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListStorageAccessGroupsCmd extends BaseListCmd {
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.NAME, type = BaseCmd.CommandType.STRING, description = "Name of the Storage access group")
private String name;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public String getName() {
return name;
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.StoragePool;
}
@Override
public void execute() {
ListResponse<StorageAccessGroupResponse> response = _queryService.searchForStorageAccessGroups(this);
response.setResponseName(getCommandName());
setResponseObject(response);
}
}

View File

@ -41,7 +41,7 @@ public class ListStoragePoolsCmd extends BaseListCmd {
@Parameter(name = ApiConstants.CLUSTER_ID,
type = CommandType.UUID,
entityType = ClusterResponse.class,
description = "list storage pools belongig to the specific cluster")
description = "list storage pools belonging to the specific cluster")
private Long clusterId;
@Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, description = "the IP address for the storage pool")
@ -74,6 +74,10 @@ public class ListStoragePoolsCmd extends BaseListCmd {
@Parameter(name = ApiConstants.STORAGE_CUSTOM_STATS, type = CommandType.BOOLEAN, description = "If true, lists the custom stats of the storage pool", since = "4.18.1")
private Boolean customStats;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUP, type = CommandType.STRING, description = "the name of the storage access group", since = "4.21.0")
private String storageAccessGroup;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -134,6 +138,17 @@ public class ListStoragePoolsCmd extends BaseListCmd {
return customStats != null && customStats;
}
public String getStorageAccessGroup() {
return storageAccessGroup;
}
public ListStoragePoolsCmd() {
}
public ListStoragePoolsCmd(String storageAccessGroup) {
this.storageAccessGroup = storageAccessGroup;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.systemvm;
import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@ -31,7 +30,9 @@ import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.SystemVmResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.utils.Pair;
import com.cloud.vm.VirtualMachine;
@ -74,6 +75,11 @@ public class ListSystemVMsCmd extends BaseListCmd {
since = "3.0.1")
private Long storageId;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "CPU arch of the system VM",
since = "4.20.1")
private String arch;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -110,6 +116,10 @@ public class ListSystemVMsCmd extends BaseListCmd {
return storageId;
}
public CPU.CPUArch getArch() {
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -31,6 +31,8 @@ import org.apache.cloudstack.context.CallContext;
import com.cloud.dc.DataCenter;
import com.cloud.user.Account;
import java.util.List;
@APICommand(name = "createZone", description = "Creates a Zone.", responseObject = ZoneResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class CreateZoneCmd extends BaseCmd {
@ -88,6 +90,11 @@ public class CreateZoneCmd extends BaseCmd {
@Parameter(name = ApiConstants.IS_EDGE, type = CommandType.BOOLEAN, description = "true if the zone is an edge zone, false otherwise", since = "4.18.0")
private Boolean isEdge;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS,
type = CommandType.LIST, collectionType = CommandType.STRING,
description = "comma separated list of storage access groups for the hosts in the zone",
since = "4.21.0")
private List<String> storageAccessGroups;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -162,6 +169,10 @@ public class CreateZoneCmd extends BaseCmd {
return isEdge;
}
public List<String> getStorageAccessGroups() {
return storageAccessGroups;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
@Override

View File

@ -26,6 +26,7 @@ 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.BackupScheduleResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.backup.BackupManager;
@ -54,10 +55,16 @@ public class DeleteBackupScheduleCmd extends BaseCmd {
@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID,
type = CommandType.UUID,
entityType = UserVmResponse.class,
required = true,
description = "ID of the VM")
private Long vmId;
@Parameter(name = ApiConstants.ID,
type = CommandType.UUID,
entityType = BackupScheduleResponse.class,
description = "ID of the schedule",
since = "4.20.1")
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -66,6 +73,9 @@ public class DeleteBackupScheduleCmd extends BaseCmd {
return vmId;
}
public Long getId() { return id; }
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -73,7 +83,7 @@ public class DeleteBackupScheduleCmd extends BaseCmd {
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
try {
boolean result = backupManager.deleteBackupSchedule(getVmId());
boolean result = backupManager.deleteBackupSchedule(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
response.setResponseName(getCommandName());

View File

@ -72,6 +72,7 @@ public class ListCapabilitiesCmd extends BaseCmd {
response.setInstancesDisksStatsRetentionTime((Integer) capabilities.get(ApiConstants.INSTANCES_DISKS_STATS_RETENTION_TIME));
response.setSharedFsVmMinCpuCount((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_CPU_COUNT));
response.setSharedFsVmMinRamSize((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE));
response.setInstanceLeaseEnabled((Boolean) capabilities.get(ApiConstants.INSTANCE_LEASE_ENABLED));
response.setObjectName("capability");
response.setResponseName(getCommandName());
this.setResponseObject(response);

View File

@ -17,6 +17,7 @@
package org.apache.cloudstack.api.command.user.iso;
import com.cloud.dc.DataCenter;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@ -101,7 +102,15 @@ public class ExtractIsoCmd extends BaseAsyncCmd {
@Override
public String getEventDescription() {
return "extracting ISO: " + getId() + " from zone: " + getZoneId();
String isoId = this._uuidMgr.getUuid(VirtualMachineTemplate.class, getId());
String baseDescription = String.format("Extracting ISO: %s", isoId);
Long zoneId = getZoneId();
if (zoneId == null) {
return baseDescription;
}
return String.format("%s from zone: %s", baseDescription, this._uuidMgr.getUuid(DataCenter.class, zoneId));
}
@Override

View File

@ -101,7 +101,15 @@ public class ExtractTemplateCmd extends BaseAsyncCmd {
@Override
public String getEventDescription() {
return "extracting template: " + this._uuidMgr.getUuid(VirtualMachineTemplate.class, getId()) + ((getZoneId() != null) ? " from zone: " + this._uuidMgr.getUuid(DataCenter.class, getZoneId()) : "");
String templateId = this._uuidMgr.getUuid(VirtualMachineTemplate.class, getId());
String baseDescription = String.format("Extracting template: %s", templateId);
Long zoneId = getZoneId();
if (zoneId == null) {
return baseDescription;
}
return String.format("%s from zone: %s", baseDescription, this._uuidMgr.getUuid(DataCenter.class, zoneId));
}
@Override

View File

@ -16,17 +16,24 @@
// under the License.
package org.apache.cloudstack.api.command.user.vm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import com.cloud.agent.api.LogLevel;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.Network.IpAddresses;
import com.cloud.offering.DiskOffering;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.uservm.UserVm;
import com.cloud.utils.net.Dhcp;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VmDetailConstants;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ACL;
@ -53,29 +60,22 @@ import org.apache.cloudstack.api.response.UserDataResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.vm.lease.VMLeaseManager;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.agent.api.LogLevel;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.Network.IpAddresses;
import com.cloud.offering.DiskOffering;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.uservm.UserVm;
import com.cloud.utils.net.Dhcp;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VmDetailConstants;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@APICommand(name = "deployVirtualMachine", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
@ -278,6 +278,14 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
description = "Enable packed virtqueues or not.")
private Boolean nicPackedVirtQueues;
@Parameter(name = ApiConstants.INSTANCE_LEASE_DURATION, type = CommandType.INTEGER, since = "4.21.0",
description = "Number of days instance is leased for.")
private Integer leaseDuration;
@Parameter(name = ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION, type = CommandType.STRING, since = "4.21.0",
description = "Lease expiry action, valid values are STOP and DESTROY")
private String leaseExpiryAction;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -475,6 +483,22 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
return password;
}
public Integer getLeaseDuration() {
return leaseDuration;
}
public VMLeaseManager.ExpiryAction getLeaseExpiryAction() {
if (StringUtils.isBlank(leaseExpiryAction)) {
return null;
}
VMLeaseManager.ExpiryAction action = EnumUtils.getEnumIgnoreCase(VMLeaseManager.ExpiryAction.class, leaseExpiryAction);
if (action == null) {
throw new InvalidParameterValueException("Invalid value configured for leaseexpiryaction, valid values are: " +
com.cloud.utils.EnumUtils.listValues(VMLeaseManager.ExpiryAction.values()));
}
return action;
}
public List<Long> getNetworkIds() {
if (MapUtils.isNotEmpty(vAppNetworks)) {
if (CollectionUtils.isNotEmpty(networkIds) || ipAddress != null || getIp6Address() != null || MapUtils.isNotEmpty(ipToNetworkList)) {

View File

@ -41,13 +41,16 @@ import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.TemplateResponse;
import org.apache.cloudstack.api.response.UserDataResponse;
import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VpcResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag;
@ -149,6 +152,19 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.BOOLEAN, description = "Whether to return the VMs' user data or not. By default, user data will not be returned.", since = "4.18.0.0")
private Boolean showUserData;
@Parameter(name = ApiConstants.USER_DATA_ID, type = CommandType.UUID, entityType = UserDataResponse.class, required = false, description = "the instances by userdata", since = "4.20.1")
private Long userdataId;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "CPU arch of the VM",
since = "4.20.1")
private String arch;
@Parameter(name = ApiConstants.LEASED, type = CommandType.BOOLEAN,
description = "Whether to return only leased instances",
since = "4.21.0")
private Boolean onlyLeasedInstances = false;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -243,6 +259,10 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements
return CollectionUtils.isEmpty(viewDetails);
}
public Long getUserdataId() {
return userdataId;
}
public EnumSet<VMDetails> getDetails() throws InvalidParameterValueException {
if (isViewDetailsEmpty()) {
if (_queryService.ReturnVmStatsOnVmList.value()) {
@ -284,6 +304,14 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements
return isVnf;
}
public CPU.CPUArch getArch() {
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
}
public boolean getOnlyLeasedInstances() {
return BooleanUtils.toBoolean(onlyLeasedInstances);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -16,20 +16,19 @@
// under the License.
package org.apache.cloudstack.api.command.user.vm;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.ApiArgValidator;
import org.apache.cloudstack.api.response.UserDataResponse;
import com.cloud.utils.net.Dhcp;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiArgValidator;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
@ -40,15 +39,17 @@ import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.GuestOSResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.UserDataResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.vm.lease.VMLeaseManager;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import com.cloud.utils.net.Dhcp;
import com.cloud.vm.VirtualMachine;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@APICommand(name = "updateVirtualMachine", description="Updates properties of a virtual machine. The VM has to be stopped and restarted for the " +
"new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. " +
@ -154,6 +155,14 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction,
" autoscaling groups or CKS, delete protection will be ignored.")
private Boolean deleteProtection;
@Parameter(name = ApiConstants.INSTANCE_LEASE_DURATION, type = CommandType.INTEGER, since = "4.21.0",
description = "Number of days to lease the instance from now onward. Use -1 to remove the existing lease")
private Integer leaseDuration;
@Parameter(name = ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION, type = CommandType.STRING, since = "4.21.0",
description = "Lease expiry action, valid values are STOP and DESTROY")
private String leaseExpiryAction;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -324,4 +333,21 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction,
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.VirtualMachine;
}
public Integer getLeaseDuration() {
return leaseDuration;
}
public VMLeaseManager.ExpiryAction getLeaseExpiryAction() {
if (StringUtils.isBlank(leaseExpiryAction)) {
return null;
}
VMLeaseManager.ExpiryAction action = EnumUtils.getEnumIgnoreCase(VMLeaseManager.ExpiryAction.class, leaseExpiryAction);
if (action == null) {
throw new InvalidParameterValueException("Invalid value configured for leaseexpiryaction, valid values are: " +
com.cloud.utils.EnumUtils.listValues(VMLeaseManager.ExpiryAction.values()));
}
return action;
}
}

View File

@ -17,6 +17,7 @@
package org.apache.cloudstack.api.command.user.volume;
import com.cloud.dc.DataCenter;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
@ -114,12 +115,15 @@ public class ExtractVolumeCmd extends BaseAsyncCmd {
@Override
public String getEventDescription() {
return "Extraction job";
String volumeId = this._uuidMgr.getUuid(Volume.class, getId());
String zoneId = this._uuidMgr.getUuid(DataCenter.class, getZoneId());
return String.format("Extracting volume: %s from zone: %s", volumeId, zoneId);
}
@Override
public void execute() {
CallContext.current().setEventDetails("Volume Id: " + this._uuidMgr.getUuid(Volume.class, getId()));
CallContext.current().setEventDetails(getEventDescription());
String uploadUrl = _volumeService.extractVolume(this);
if (uploadUrl != null) {
ExtractResponse response = _responseGenerator.createVolumeExtractResponse(id, zoneId, getEntityOwnerId(), mode, uploadUrl);

View File

@ -69,6 +69,11 @@ public class ListZonesCmd extends BaseListCmd implements UserCmd {
@Parameter(name = ApiConstants.SHOW_RESOURCE_ICON, type = CommandType.BOOLEAN, description = "flag to display the resource image for the zones")
private Boolean showIcon;
@Parameter(name = ApiConstants.STORAGE_ACCESS_GROUP, type = CommandType.STRING,
description = "the name of the storage access group",
since = "4.21.0")
private String storageAccessGroup;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -109,6 +114,18 @@ public class ListZonesCmd extends BaseListCmd implements UserCmd {
return showIcon != null ? showIcon : false;
}
public String getStorageAccessGroup() {
return storageAccessGroup;
}
public ListZonesCmd() {
}
public ListZonesCmd(String storageAccessGroup) {
this.storageAccessGroup = storageAccessGroup;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -57,10 +57,6 @@ public class BackupRepositoryResponse extends BaseResponse {
@Param(description = "backup type")
private String type;
@SerializedName(ApiConstants.MOUNT_OPTIONS)
@Param(description = "mount options for the backup repository")
private String mountOptions;
@SerializedName(ApiConstants.CAPACITY_BYTES)
@Param(description = "capacity of the backup repository")
private Long capacityBytes;
@ -112,14 +108,6 @@ public class BackupRepositoryResponse extends BaseResponse {
this.address = address;
}
public String getMountOptions() {
return mountOptions;
}
public void setMountOptions(String mountOptions) {
this.mountOptions = mountOptions;
}
public String getProviderName() {
return providerName;
}

View File

@ -136,6 +136,10 @@ public class CapabilitiesResponse extends BaseResponse {
@Param(description = "the min Ram size for the service offering used by the shared filesystem instance", since = "4.20.0")
private Integer sharedFsVmMinRamSize;
@SerializedName(ApiConstants.INSTANCE_LEASE_ENABLED)
@Param(description = "true if instance lease feature is enabled", since = "4.21.0")
private Boolean instanceLeaseEnabled;
public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) {
this.securityGroupsEnabled = securityGroupsEnabled;
}
@ -247,4 +251,8 @@ public class CapabilitiesResponse extends BaseResponse {
public void setSharedFsVmMinRamSize(Integer sharedFsVmMinRamSize) {
this.sharedFsVmMinRamSize = sharedFsVmMinRamSize;
}
public void setInstanceLeaseEnabled(Boolean instanceLeaseEnabled) {
this.instanceLeaseEnabled = instanceLeaseEnabled;
}
}

View File

@ -95,6 +95,18 @@ public class ClusterResponse extends BaseResponseWithAnnotations {
@Param(description = "CPU Arch of the hosts in the cluster", since = "4.20")
private String arch;
@SerializedName(ApiConstants.STORAGE_ACCESS_GROUPS)
@Param(description = "comma-separated list of storage access groups for the host", since = "4.21.0")
private String storageAccessGroups;
@SerializedName(ApiConstants.POD_STORAGE_ACCESS_GROUPS)
@Param(description = "comma-separated list of storage access groups on the pod", since = "4.21.0")
private String podStorageAccessGroups;
@SerializedName(ApiConstants.ZONE_STORAGE_ACCESS_GROUPS)
@Param(description = "comma-separated list of storage access groups on the zone", since = "4.21.0")
private String zoneStorageAccessGroups;
public String getId() {
return id;
}
@ -259,4 +271,28 @@ public class ClusterResponse extends BaseResponseWithAnnotations {
public String getArch() {
return arch;
}
public String getStorageAccessGroups() {
return storageAccessGroups;
}
public void setStorageAccessGroups(String storageAccessGroups) {
this.storageAccessGroups = storageAccessGroups;
}
public String getPodStorageAccessGroups() {
return podStorageAccessGroups;
}
public void setPodStorageAccessGroups(String podStorageAccessGroups) {
this.podStorageAccessGroups = podStorageAccessGroups;
}
public String getZoneStorageAccessGroups() {
return zoneStorageAccessGroups;
}
public void setZoneStorageAccessGroups(String zoneStorageAccessGroups) {
this.zoneStorageAccessGroups = zoneStorageAccessGroups;
}
}

View File

@ -245,6 +245,10 @@ public class DomainRouterResponse extends BaseResponseWithAnnotations implements
@Param(description = "the version of the code / software in the router")
private String softwareVersion;
@SerializedName(ApiConstants.ARCH)
@Param(description = "CPU arch of the router", since = "4.20.1")
private String arch;
public DomainRouterResponse() {
nics = new LinkedHashSet<NicResponse>();
}
@ -518,4 +522,8 @@ public class DomainRouterResponse extends BaseResponseWithAnnotations implements
public void setSoftwareVersion(String softwareVersion) {
this.softwareVersion = softwareVersion;
}
public void setArch(String arch) {
this.arch = arch;
}
}

View File

@ -152,7 +152,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
@Deprecated
@SerializedName("memoryallocated")
@Param(description = "the amount of the host's memory currently allocated")
private Long memoryAllocated;
private long memoryAllocated;
@SerializedName("memoryallocatedpercentage")
@Param(description = "the amount of the host's memory currently allocated in percentage")
@ -302,6 +302,22 @@ public class HostResponse extends BaseResponseWithAnnotations {
@Param(description = "CPU Arch of the host", since = "4.20")
private String arch;
@SerializedName(ApiConstants.STORAGE_ACCESS_GROUPS)
@Param(description = "comma-separated list of storage access groups for the host", since = "4.21.0")
private String storageAccessGroups;
@SerializedName(ApiConstants.CLUSTER_STORAGE_ACCESS_GROUPS)
@Param(description = "comma-separated list of storage access groups on the cluster", since = "4.21.0")
private String clusterStorageAccessGroups;
@SerializedName(ApiConstants.POD_STORAGE_ACCESS_GROUPS)
@Param(description = "comma-separated list of storage access groups on the pod", since = "4.21.0")
private String podStorageAccessGroups;
@SerializedName(ApiConstants.ZONE_STORAGE_ACCESS_GROUPS)
@Param(description = "comma-separated list of storage access groups on the zone", since = "4.21.0")
private String zoneStorageAccessGroups;
@Override
public String getObjectId() {
return this.getId();
@ -415,7 +431,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
this.memWithOverprovisioning=memWithOverprovisioning;
}
public void setMemoryAllocated(Long memoryAllocated) {
public void setMemoryAllocated(long memoryAllocated) {
this.memoryAllocated = memoryAllocated;
}
@ -491,6 +507,38 @@ public class HostResponse extends BaseResponseWithAnnotations {
this.hostTags = hostTags;
}
public String getStorageAccessGroups() {
return storageAccessGroups;
}
public void setStorageAccessGroups(String storageAccessGroups) {
this.storageAccessGroups = storageAccessGroups;
}
public String getClusterStorageAccessGroups() {
return clusterStorageAccessGroups;
}
public void setClusterStorageAccessGroups(String clusterStorageAccessGroups) {
this.clusterStorageAccessGroups = clusterStorageAccessGroups;
}
public String getPodStorageAccessGroups() {
return podStorageAccessGroups;
}
public void setPodStorageAccessGroups(String podStorageAccessGroups) {
this.podStorageAccessGroups = podStorageAccessGroups;
}
public String getZoneStorageAccessGroups() {
return zoneStorageAccessGroups;
}
public void setZoneStorageAccessGroups(String zoneStorageAccessGroups) {
this.zoneStorageAccessGroups = zoneStorageAccessGroups;
}
public String getExplicitHostTags() {
return explicitHostTags;
}
@ -703,8 +751,8 @@ public class HostResponse extends BaseResponseWithAnnotations {
return memoryTotal;
}
public Long getMemoryAllocated() {
return memoryAllocated == null ? 0 : memoryAllocated;
public long getMemoryAllocated() {
return memoryAllocated;
}
public void setMemoryAllocatedPercentage(String memoryAllocatedPercentage) {

View File

@ -74,6 +74,11 @@ public class ManagementServerResponse extends BaseResponse {
@Param(description = "the running OS kernel version for this Management Server")
private String kernelVersion;
@Deprecated
@SerializedName(ApiConstants.SERVICE_IP)
@Param(description = "the IP Address for this Management Server. This is deprecated, please use 'ipaddress' instead.")
private String serviceIp;
@SerializedName(ApiConstants.IP_ADDRESS)
@Param(description = "the IP Address for this Management Server")
private String ipAddress;
@ -82,6 +87,14 @@ public class ManagementServerResponse extends BaseResponse {
@Param(description = "the Management Server Peers")
private List<PeerManagementServerNodeResponse> peers;
@SerializedName(ApiConstants.LAST_AGENTS)
@Param(description = "the last agents this Management Server is responsible for, before shutdown or preparing for maintenance", since = "4.21.0.0")
private List<String> lastAgents;
@SerializedName(ApiConstants.AGENTS)
@Param(description = "the agents this Management Server is responsible for", since = "4.21.0.0")
private List<String> agents;
@SerializedName(ApiConstants.AGENTS_COUNT)
@Param(description = "the number of host agents this Management Server is responsible for", since = "4.21.0.0")
private Long agentsCount;
@ -130,10 +143,22 @@ public class ManagementServerResponse extends BaseResponse {
return lastBoot;
}
public String getServiceIp() {
return serviceIp;
}
public String getIpAddress() {
return ipAddress;
}
public List<String> getLastAgents() {
return lastAgents;
}
public List<String> getAgents() {
return agents;
}
public Long getAgentsCount() {
return this.agentsCount;
}
@ -186,10 +211,22 @@ public class ManagementServerResponse extends BaseResponse {
this.kernelVersion = kernelVersion;
}
public void setServiceIp(String serviceIp) {
this.serviceIp = serviceIp;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public void setLastAgents(List<String> lastAgents) {
this.lastAgents = lastAgents;
}
public void setAgents(List<String> agents) {
this.agents = agents;
}
public void setAgentsCount(Long agentsCount) {
this.agentsCount = agentsCount;
}

View File

@ -28,12 +28,11 @@ import org.apache.cloudstack.api.BaseResponseWithAssociatedNetwork;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.network.Network;
import com.cloud.projects.ProjectAccount;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
@EntityReference(value = {Network.class, ProjectAccount.class})
@EntityReference(value = {Network.class})
public class NetworkResponse extends BaseResponseWithAssociatedNetwork implements ControlledEntityResponse, SetResourceIconResponse {
@SerializedName(ApiConstants.ID)

View File

@ -85,6 +85,14 @@ public class PodResponse extends BaseResponseWithAnnotations {
@Param(description = "the capacity of the Pod", responseObject = CapacityResponse.class)
private List<CapacityResponse> capacities;
@SerializedName(ApiConstants.STORAGE_ACCESS_GROUPS)
@Param(description = "comma-separated list of storage access groups for the pod", since = "4.21.0")
private String storageAccessGroups;
@SerializedName(ApiConstants.ZONE_STORAGE_ACCESS_GROUPS)
@Param(description = "comma-separated list of storage access groups on the zone", since = "4.21.0")
private String zoneStorageAccessGroups;
public String getId() {
return id;
}
@ -184,4 +192,20 @@ public class PodResponse extends BaseResponseWithAnnotations {
public void setCapacities(List<CapacityResponse> capacities) {
this.capacities = capacities;
}
public String getStorageAccessGroups() {
return storageAccessGroups;
}
public void setStorageAccessGroups(String storageAccessGroups) {
this.storageAccessGroups = storageAccessGroups;
}
public String getZoneStorageAccessGroups() {
return zoneStorageAccessGroups;
}
public void setZoneStorageAccessGroups(String zoneStorageAccessGroups) {
this.zoneStorageAccessGroups = zoneStorageAccessGroups;
}
}

View File

@ -80,7 +80,7 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations {
@Param(description = "true if the vm needs to be volatile, i.e., on every reboot of vm from API root disk is discarded and creates a new root disk")
private Boolean isVolatile;
@SerializedName("storagetags")
@SerializedName(ApiConstants.STORAGE_TAGS)
@Param(description = "the tags for the service offering")
private String tags;
@ -238,6 +238,14 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations {
@Param(description = "Whether to cleanup VM and its associated resource upon expunge", since = "4.20")
private Boolean purgeResources;
@SerializedName(ApiConstants.INSTANCE_LEASE_DURATION)
@Param(description = "Instance lease duration (in days) for service offering", since = "4.21.0")
private Integer leaseDuration;
@SerializedName(ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION)
@Param(description = "Action to be taken once lease is over", since = "4.21.0")
private String leaseExpiryAction;
public ServiceOfferingResponse() {
}
@ -505,6 +513,22 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations {
this.cacheMode = cacheMode;
}
public Integer getLeaseDuration() {
return leaseDuration;
}
public void setLeaseDuration(Integer leaseDuration) {
this.leaseDuration = leaseDuration;
}
public String getLeaseExpiryAction() {
return leaseExpiryAction;
}
public void setLeaseExpiryAction(String leaseExpiryAction) {
this.leaseExpiryAction = leaseExpiryAction;
}
public String getVsphereStoragePolicy() {
return vsphereStoragePolicy;
}

View File

@ -0,0 +1,108 @@
// 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.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param;
public class StorageAccessGroupResponse extends BaseResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the ID of the storage access group")
private String id;
@SerializedName(ApiConstants.NAME)
@Param(description = "the name of the storage access group")
private String name;
@SerializedName("hosts")
@Param(description = "List of Hosts in the Storage Access Group")
private ListResponse<HostResponse> hostResponseList;
@SerializedName("clusters")
@Param(description = "List of Clusters in the Storage Access Group")
private ListResponse<ClusterResponse> clusterResponseList;
@SerializedName("pods")
@Param(description = "List of Pods in the Storage Access Group")
private ListResponse<PodResponse> podResponseList;
@SerializedName("zones")
@Param(description = "List of Zones in the Storage Access Group")
private ListResponse<ZoneResponse> zoneResponseList;
@SerializedName("storagepools")
@Param(description = "List of Storage Pools in the Storage Access Group")
private ListResponse<StoragePoolResponse> storagePoolResponseList;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ListResponse<HostResponse> getHostResponseList() {
return hostResponseList;
}
public void setHostResponseList(ListResponse<HostResponse> hostResponseList) {
this.hostResponseList = hostResponseList;
}
public ListResponse<ClusterResponse> getClusterResponseList() {
return clusterResponseList;
}
public void setClusterResponseList(ListResponse<ClusterResponse> clusterResponseList) {
this.clusterResponseList = clusterResponseList;
}
public ListResponse<PodResponse> getPodResponseList() {
return podResponseList;
}
public void setPodResponseList(ListResponse<PodResponse> podResponseList) {
this.podResponseList = podResponseList;
}
public ListResponse<ZoneResponse> getZoneResponseList() {
return zoneResponseList;
}
public void setZoneResponseList(ListResponse<ZoneResponse> zoneResponseList) {
this.zoneResponseList = zoneResponseList;
}
public ListResponse<StoragePoolResponse> getStoragePoolResponseList() {
return storagePoolResponseList;
}
public void setStoragePoolResponseList(ListResponse<StoragePoolResponse> storagePoolResponseList) {
this.storagePoolResponseList = storagePoolResponseList;
}
}

View File

@ -109,6 +109,10 @@ public class StoragePoolResponse extends BaseResponseWithAnnotations {
@Param(description = "the tags for the storage pool")
private String tags;
@SerializedName(ApiConstants.STORAGE_ACCESS_GROUPS)
@Param(description = "the storage access groups for the storage pool", since = "4.21.0")
private String storageAccessGroups;
@SerializedName(ApiConstants.NFS_MOUNT_OPTIONS)
@Param(description = "the nfs mount options for the storage pool", since = "4.19.1")
private String nfsMountOpts;
@ -149,6 +153,10 @@ public class StoragePoolResponse extends BaseResponseWithAnnotations {
@Param(description = "whether this pool is managed or not")
private Boolean managed;
@SerializedName(ApiConstants.DETAILS)
@Param(description = "the storage pool details")
private Map<String, String> details;
public Map<String, String> getCaps() {
return caps;
}
@ -340,6 +348,14 @@ public class StoragePoolResponse extends BaseResponseWithAnnotations {
this.tags = tags;
}
public String getStorageAccessGroups() {
return storageAccessGroups;
}
public void setStorageAccessGroups(String storageAccessGroups) {
this.storageAccessGroups = storageAccessGroups;
}
public Boolean getIsTagARule() {
return isTagARule;
}
@ -407,4 +423,12 @@ public class StoragePoolResponse extends BaseResponseWithAnnotations {
public void setManaged(Boolean managed) {
this.managed = managed;
}
public Map<String, String> getDetails() {
return details;
}
public void setDetails(Map<String, String> details) {
this.details = details;
}
}

View File

@ -186,6 +186,10 @@ public class SystemVmResponse extends BaseResponseWithAnnotations {
@Param(description = "the name of the service offering of the system virtual machine.")
private String serviceOfferingName;
@SerializedName(ApiConstants.ARCH)
@Param(description = "CPU arch of the system VM", since = "4.20.1")
private String arch;
@Override
public String getObjectId() {
return this.getId();
@ -490,4 +494,8 @@ public class SystemVmResponse extends BaseResponseWithAnnotations {
public void setServiceOfferingName(String serviceOfferingName) {
this.serviceOfferingName = serviceOfferingName;
}
public void setArch(String arch) {
this.arch = arch;
}
}

View File

@ -79,6 +79,14 @@ public class UnmanagedInstanceResponse extends BaseResponse {
@Param(description = "the operating system of the virtual machine")
private String operatingSystem;
@SerializedName(ApiConstants.BOOT_MODE)
@Param(description = "indicates the boot mode")
private String bootMode;
@SerializedName(ApiConstants.BOOT_TYPE)
@Param(description = "indicates the boot type")
private String bootType;
@SerializedName(ApiConstants.DISK)
@Param(description = "the list of disks associated with the virtual machine", responseObject = UnmanagedInstanceDiskResponse.class)
private Set<UnmanagedInstanceDiskResponse> disks;
@ -211,4 +219,20 @@ public class UnmanagedInstanceResponse extends BaseResponse {
public void addNic(NicResponse nic) {
this.nics.add(nic);
}
public String getBootMode() {
return bootMode;
}
public void setBootMode(String bootMode) {
this.bootMode = bootMode;
}
public String getBootType() {
return bootType;
}
public void setBootType(String bootType) {
this.bootType = bootType;
}
}

View File

@ -31,13 +31,13 @@ import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponseWithTagInformation;
import org.apache.cloudstack.api.EntityReference;
import org.apache.commons.collections.CollectionUtils;
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.commons.collections.CollectionUtils;
@SuppressWarnings("unused")
@EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class})
@ -392,10 +392,26 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
@Param(description = "VNF details", since = "4.19.0")
private Map<String, String> vnfDetails;
@SerializedName((ApiConstants.VM_TYPE))
@SerializedName(ApiConstants.VM_TYPE)
@Param(description = "User VM type", since = "4.20.0")
private String vmType;
@SerializedName(ApiConstants.ARCH)
@Param(description = "CPU arch of the VM", since = "4.20.1")
private String arch;
@SerializedName(ApiConstants.INSTANCE_LEASE_DURATION)
@Param(description = "Instance lease duration in days", since = "4.21.0")
private Integer leaseDuration;
@SerializedName(ApiConstants.INSTANCE_LEASE_EXPIRY_DATE)
@Param(description = "Instance lease expiry date", since = "4.21.0")
private Date leaseExpiryDate;
@SerializedName(ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION)
@Param(description = "Instance lease expiry action", since = "4.21.0")
private String leaseExpiryAction;
public UserVmResponse() {
securityGroupList = new LinkedHashSet<>();
nics = new TreeSet<>(Comparator.comparingInt(x -> Integer.parseInt(x.getDeviceId())));
@ -1169,4 +1185,37 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getArch() {
return arch;
}
public void setArch(String arch) {
this.arch = arch;
}
public Integer getLeaseDuration() {
return leaseDuration;
}
public void setLeaseDuration(Integer leaseDuration) {
this.leaseDuration = leaseDuration;
}
public String getLeaseExpiryAction() {
return leaseExpiryAction;
}
public void setLeaseExpiryAction(String leaseExpiryAction) {
this.leaseExpiryAction = leaseExpiryAction;
}
public Date getLeaseExpiryDate() {
return leaseExpiryDate;
}
public void setLeaseExpiryDate(Date leaseExpiryDate) {
this.leaseExpiryDate = leaseExpiryDate;
}
}

View File

@ -95,7 +95,7 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso
@SerializedName("securitygroupsenabled")
@Param(description = "true if security groups support is enabled, false otherwise")
private boolean securityGroupsEnabled;
private Boolean securityGroupsEnabled;
@SerializedName("allocationstate")
@Param(description = "the allocation state of the cluster")
@ -115,7 +115,7 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso
@SerializedName(ApiConstants.LOCAL_STORAGE_ENABLED)
@Param(description = "true if local storage offering enabled, false otherwise")
private boolean localStorageEnabled;
private Boolean localStorageEnabled;
@SerializedName(ApiConstants.TAGS)
@Param(description = "the list of resource tags associated with zone.", responseObject = ResourceTagResponse.class, since = "4.3")
@ -161,11 +161,19 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso
@Param(description = "true, if routed network/vpc is enabled", since = "4.20.1")
private boolean routedModeEnabled = false;
@SerializedName(ApiConstants.STORAGE_ACCESS_GROUPS)
@Param(description = "comma-separated list of storage access groups for the zone", since = "4.21.0")
private String storageAccessGroups;
public ZoneResponse() {
tags = new LinkedHashSet<ResourceTagResponse>();
}
public ZoneResponse(Set<ResourceTagResponse> tags) {
this.tags = tags;
}
public void setId(String id) {
this.id = id;
}
@ -402,6 +410,14 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso
return type;
}
public String getStorageAccessGroups() {
return storageAccessGroups;
}
public void setStorageAccessGroups(String storageAccessGroups) {
this.storageAccessGroups = storageAccessGroups;
}
public void setNsxEnabled(boolean nsxEnabled) {
this.nsxEnabled = nsxEnabled;
}

View File

@ -23,6 +23,7 @@ import com.cloud.exception.ResourceAllocationException;
import org.apache.cloudstack.api.command.admin.backup.ImportBackupOfferingCmd;
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
import org.apache.cloudstack.api.command.user.backup.ListBackupOfferingsCmd;
import org.apache.cloudstack.api.command.user.backup.ListBackupsCmd;
import org.apache.cloudstack.framework.config.ConfigKey;
@ -192,10 +193,10 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
/**
* Deletes VM backup schedule for a VM
* @param vmId
* @param cmd
* @return
*/
boolean deleteBackupSchedule(Long vmId);
boolean deleteBackupSchedule(DeleteBackupScheduleCmd cmd);
/**
* Creates backup of a VM

View File

@ -0,0 +1,65 @@
// 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.command;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.hypervisor.Hypervisor;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.framework.config.ConfigKey;
import java.util.Arrays;
import java.util.List;
public interface ReconcileCommandService {
ConfigKey<Boolean> ReconcileCommandsEnabled = new ConfigKey<>("Advanced", Boolean.class,
"reconcile.commands.enabled", "false",
"Indicates whether the background task to reconcile the commands is enabled or not",
false);
ConfigKey<Integer> ReconcileCommandsInterval = new ConfigKey<>("Advanced", Integer.class,
"reconcile.commands.interval", "60",
"Interval (in seconds) for the background task to reconcile the commands",
false);
ConfigKey<Integer> ReconcileCommandsMaxAttempts = new ConfigKey<>("Advanced", Integer.class,
"reconcile.commands.max.attempts", "30",
"The maximum number of attempts to reconcile the commands",
true);
ConfigKey<Integer> ReconcileCommandsWorkers = new ConfigKey<>("Advanced", Integer.class,
"reconcile.commands.workers", "100",
"The Number of worker threads to reconcile the commands",
false);
List<Hypervisor.HypervisorType> SupportedHypervisorTypes = Arrays.asList(Hypervisor.HypervisorType.KVM);
void persistReconcileCommands(Long hostId, Long requestSequence, Command[] cmd);
boolean updateReconcileCommand(long requestSeq, Command command, Answer answer, Command.State newStateByManagement, Command.State newStateByAgent);
void processCommand(Command pingCommand, Answer pingAnswer);
void processAnswers(long requestSeq, Command[] commands, Answer[] answers);
void updateReconcileCommandToInterruptedByManagementServerId(long managementServerId);
void updateReconcileCommandToInterruptedByHostId(long hostId);
boolean isReconcileResourceNeeded(long resourceId, ApiCommandResourceType resourceType);
}

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.query;
import java.util.Arrays;
import java.util.List;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
@ -31,6 +32,7 @@ import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
import org.apache.cloudstack.api.command.admin.storage.ListImageStoresCmd;
import org.apache.cloudstack.api.command.admin.storage.ListObjectStoragePoolsCmd;
import org.apache.cloudstack.api.command.admin.storage.ListSecondaryStagingStoresCmd;
import org.apache.cloudstack.api.command.admin.storage.ListStorageAccessGroupsCmd;
import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd;
import org.apache.cloudstack.api.command.admin.storage.ListStorageTagsCmd;
import org.apache.cloudstack.api.command.admin.storage.heuristics.ListSecondaryStorageSelectorsCmd;
@ -86,6 +88,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.SnapshotResponse;
import org.apache.cloudstack.api.response.StorageAccessGroupResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.StorageTagResponse;
import org.apache.cloudstack.api.response.TemplateResponse;
@ -97,6 +100,7 @@ import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.vm.VmDetailConstants;
/**
* Service used for list api query.
@ -104,6 +108,8 @@ import com.cloud.exception.PermissionDeniedException;
*/
public interface QueryService {
List<String> RootAdminOnlyVmSettings = Arrays.asList(VmDetailConstants.GUEST_CPU_MODE, VmDetailConstants.GUEST_CPU_MODEL);
// Config keys
ConfigKey<Boolean> AllowUserViewDestroyedVM = new ConfigKey<>("Advanced", Boolean.class, "allow.user.view.destroyed.vm", "false",
"Determines whether users can view their destroyed or expunging vm ", true, ConfigKey.Scope.Account);
@ -193,6 +199,8 @@ public interface QueryService {
ListResponse<StorageTagResponse> searchForStorageTags(ListStorageTagsCmd cmd);
ListResponse<StorageAccessGroupResponse> searchForStorageAccessGroups(ListStorageAccessGroupsCmd cmd);
ListResponse<HostTagResponse> searchForHostTags(ListHostTagsCmd cmd);
ListResponse<ManagementServerResponse> listManagementServers(ListMgmtsCmd cmd);

View File

@ -61,6 +61,9 @@ public class UnmanagedInstanceTO {
private String vncPassword;
private String bootType;
private String bootMode;
public String getName() {
return name;
}
@ -196,6 +199,22 @@ public class UnmanagedInstanceTO {
this, "name", "internalCSName", "hostName", "clusterName"));
}
public String getBootType() {
return bootType;
}
public void setBootType(String bootType) {
this.bootType = bootType;
}
public String getBootMode() {
return bootMode;
}
public void setBootMode(String bootMode) {
this.bootMode = bootMode;
}
public static class Disk {
private String diskId;

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.vm.lease;
import com.cloud.utils.component.Manager;
import org.apache.cloudstack.framework.config.ConfigKey;
import java.util.List;
public interface VMLeaseManager extends Manager {
int MAX_LEASE_DURATION_DAYS = 365_00; // 100 years
enum ExpiryAction {
STOP,
DESTROY
}
enum LeaseActionExecution {
PENDING,
DISABLED,
DONE,
CANCELLED
}
ConfigKey<Boolean> InstanceLeaseEnabled = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Boolean.class,
"instance.lease.enabled", "false", "Indicates whether to enable the Instance lease," +
" will be applicable only on instances created after lease is enabled. Disabling the feature cancels lease on existing instances with lease." +
" Re-enabling feature will not cause lease expiry actions on grandfathered instances",
true, List.of(ConfigKey.Scope.Global));
ConfigKey<Integer> InstanceLeaseSchedulerInterval = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Integer.class,
"instance.lease.scheduler.interval", "3600", "VM Lease Scheduler interval in seconds",
false, List.of(ConfigKey.Scope.Global));
ConfigKey<Integer> InstanceLeaseExpiryEventSchedulerInterval = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Integer.class,
"instance.lease.eventscheduler.interval", "86400", "Lease expiry event Scheduler interval in seconds",
false, List.of(ConfigKey.Scope.Global));
ConfigKey<Integer> InstanceLeaseExpiryEventDaysBefore = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Integer.class,
"instance.lease.expiryevent.daysbefore", "7", "Indicates how many days in advance, expiry events will be created before expiry.",
true, List.of(ConfigKey.Scope.Global));
void onLeaseFeatureToggle();
}

View File

@ -0,0 +1,67 @@
// 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.cpu;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class CPUTest {
@Test
public void testCPUArchGetType() {
assertEquals("i686", CPU.CPUArch.x86.getType());
assertEquals("x86_64", CPU.CPUArch.amd64.getType());
assertEquals("aarch64", CPU.CPUArch.arm64.getType());
}
@Test
public void testCPUArchGetBits() {
assertEquals(32, CPU.CPUArch.x86.getBits());
assertEquals(64, CPU.CPUArch.amd64.getBits());
assertEquals(64, CPU.CPUArch.arm64.getBits());
}
@Test
public void testCPUArchFromTypeWithValidValues() {
assertEquals(CPU.CPUArch.x86, CPU.CPUArch.fromType("i686"));
assertEquals(CPU.CPUArch.amd64, CPU.CPUArch.fromType("x86_64"));
assertEquals(CPU.CPUArch.arm64, CPU.CPUArch.fromType("aarch64"));
}
@Test
public void testCPUArchFromTypeWithDefaultForBlankOrNull() {
assertEquals(CPU.CPUArch.amd64, CPU.CPUArch.fromType(""));
assertEquals(CPU.CPUArch.amd64, CPU.CPUArch.fromType(" "));
assertEquals(CPU.CPUArch.amd64, CPU.CPUArch.fromType(null));
}
@Test
public void testCPUArchFromTypeWithInvalidValue() {
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
CPU.CPUArch.fromType("unsupported");
});
assertTrue(exception.getMessage().contains("Unsupported arch type: unsupported"));
}
@Test
public void testCPUArchGetTypesAsCSV() {
String expectedCSV = "i686,x86_64,aarch64";
assertEquals(expectedCSV, CPU.CPUArch.getTypesAsCSV());
}
}

View File

@ -17,6 +17,8 @@
package org.apache.cloudstack.api.command.admin.offering;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.vm.lease.VMLeaseManager;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -55,4 +57,25 @@ public class CreateServiceOfferingCmdTest {
ReflectionTestUtils.setField(createServiceOfferingCmd, "purgeResources", true);
Assert.assertTrue(createServiceOfferingCmd.isPurgeResources());
}
@Test
public void testGetLeaseDuration() {
ReflectionTestUtils.setField(createServiceOfferingCmd, "leaseDuration", 10);
Assert.assertEquals(10, createServiceOfferingCmd.getLeaseDuration().longValue());
}
@Test
public void testGetLeaseExpiryAction() {
ReflectionTestUtils.setField(createServiceOfferingCmd, "leaseExpiryAction", "stop");
Assert.assertEquals(VMLeaseManager.ExpiryAction.STOP, createServiceOfferingCmd.getLeaseExpiryAction());
ReflectionTestUtils.setField(createServiceOfferingCmd, "leaseExpiryAction", "DESTROY");
Assert.assertEquals(VMLeaseManager.ExpiryAction.DESTROY, createServiceOfferingCmd.getLeaseExpiryAction());
}
@Test(expected = InvalidParameterValueException.class)
public void testGetLeaseExpiryActionInvalidValue() {
ReflectionTestUtils.setField(createServiceOfferingCmd, "leaseExpiryAction", "Unknown");
Assert.assertEquals(null, createServiceOfferingCmd.getLeaseExpiryAction());
}
}

View File

@ -44,7 +44,7 @@ public class PurgeExpungedResourcesCmdTest {
@Spy
@InjectMocks
PurgeExpungedResourcesCmd spyCmd = Mockito.spy(new PurgeExpungedResourcesCmd());
PurgeExpungedResourcesCmd spyCmd;
@Test
public void testGetResourceType() {

View File

@ -20,14 +20,11 @@ package org.apache.cloudstack.api.command.admin.storage;
import com.cloud.utils.Pair;
import org.apache.cloudstack.api.response.ExtractResponse;
import org.apache.cloudstack.storage.browser.StorageBrowser;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@ -48,18 +45,6 @@ public class DownloadImageStoreObjectCmdTest {
@Spy
private DownloadImageStoreObjectCmd cmd;
private AutoCloseable closeable;
@Before
public void setUp() {
closeable = MockitoAnnotations.openMocks(this);
}
@After
public void tearDown() throws Exception {
closeable.close();
}
@Test
public void testExecute() throws Exception {
ReflectionTestUtils.setField(cmd, "storeId", 1L);

View File

@ -68,6 +68,12 @@ public class MigrateVirtualMachineWithVolumeCmdTest {
@Mock
Host hostMock;
@Mock
private Object job;
@Mock
private Object _responseObject;
@Spy
@InjectMocks
MigrateVirtualMachineWithVolumeCmd cmdSpy;

View File

@ -20,7 +20,6 @@ package org.apache.cloudstack.api.command.admin.vpc;
import com.cloud.network.vpc.VpcService;
import com.cloud.user.AccountService;
import com.cloud.utils.db.EntityManager;
import junit.framework.TestCase;
import org.apache.cloudstack.api.ResponseGenerator;
import org.junit.Assert;
import org.junit.Test;
@ -34,7 +33,7 @@ import org.springframework.test.util.ReflectionTestUtils;
import java.util.List;
@RunWith(MockitoJUnitRunner.class)
public class CreateVPCCmdByAdminTest extends TestCase {
public class CreateVPCCmdByAdminTest {
@Mock
public VpcService _vpcService;
@ -43,8 +42,10 @@ public class CreateVPCCmdByAdminTest extends TestCase {
@Mock
public AccountService _accountService;
private ResponseGenerator responseGenerator;
@Mock
public Object job;
@InjectMocks
CreateVPCCmdByAdmin cmd = new CreateVPCCmdByAdmin();
CreateVPCCmdByAdmin cmd;
@Test
public void testBgpPeerIds() {

View File

@ -41,7 +41,10 @@ public class UpdateNetworkCmdTest {
NetworkService networkService;
@Mock
public EntityManager _entityMgr;
private ResponseGenerator responseGenerator;
@Mock
private ResponseGenerator _responseGenerator;
@Mock
private Object job;
@InjectMocks
UpdateNetworkCmd cmd = new UpdateNetworkCmd();
@ -176,15 +179,13 @@ public class UpdateNetworkCmdTest {
ReflectionTestUtils.setField(cmd, "id", networkId);
ReflectionTestUtils.setField(cmd, "publicMtu", publicmtu);
Network network = Mockito.mock(Network.class);
responseGenerator = Mockito.mock(ResponseGenerator.class);
NetworkResponse response = Mockito.mock(NetworkResponse.class);
response.setPublicMtu(publicmtu);
Mockito.when(networkService.getNetwork(networkId)).thenReturn(network);
Mockito.when(networkService.updateGuestNetwork(cmd)).thenReturn(network);
cmd._responseGenerator = responseGenerator;
Mockito.when(responseGenerator.createNetworkResponse(ResponseObject.ResponseView.Restricted, network)).thenReturn(response);
Mockito.when(_responseGenerator.createNetworkResponse(ResponseObject.ResponseView.Restricted, network)).thenReturn(response);
cmd.execute();
Mockito.verify(responseGenerator).createNetworkResponse(Mockito.any(ResponseObject.ResponseView.class), Mockito.any(Network.class));
Mockito.verify(_responseGenerator).createNetworkResponse(Mockito.any(ResponseObject.ResponseView.class), Mockito.any(Network.class));
NetworkResponse actualResponse = (NetworkResponse) cmd.getResponseObject();
Assert.assertEquals(response, actualResponse);

View File

@ -25,7 +25,6 @@ import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcService;
import com.cloud.user.AccountService;
import com.cloud.utils.db.EntityManager;
import junit.framework.TestCase;
import org.apache.cloudstack.api.ResponseGenerator;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.response.VpcResponse;
@ -39,7 +38,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class CreateVPCCmdTest extends TestCase {
public class CreateVPCCmdTest {
@Mock
public VpcService _vpcService;
@ -47,9 +46,13 @@ public class CreateVPCCmdTest extends TestCase {
public EntityManager _entityMgr;
@Mock
public AccountService _accountService;
private ResponseGenerator responseGenerator;
@Mock
private ResponseGenerator _responseGenerator;
@Mock
private Object job;
@InjectMocks
CreateVPCCmd cmd = new CreateVPCCmd();
CreateVPCCmd cmd;
@Test
public void testGetAccountName() {
@ -185,11 +188,9 @@ public class CreateVPCCmdTest extends TestCase {
VpcResponse response = Mockito.mock(VpcResponse.class);
ReflectionTestUtils.setField(cmd, "id", 1L);
responseGenerator = Mockito.mock(ResponseGenerator.class);
Mockito.doNothing().when(_vpcService).startVpc(cmd);
Mockito.when(_entityMgr.findById(Mockito.eq(Vpc.class), Mockito.any(Long.class))).thenReturn(vpc);
cmd._responseGenerator = responseGenerator;
Mockito.when(responseGenerator.createVpcResponse(ResponseObject.ResponseView.Restricted, vpc)).thenReturn(response);
Mockito.when(_responseGenerator.createVpcResponse(ResponseObject.ResponseView.Restricted, vpc)).thenReturn(response);
cmd.execute();
Mockito.verify(_vpcService, Mockito.times(1)).startVpc(cmd);
}

View File

@ -16,13 +16,27 @@
# specific language governing permissions and limitations
# under the License.
import os
import sys
# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
# ---- We do this so cloud_utils can be looked up in the following order:
# ---- 1) Sources directory
# ---- 2) waf configured PYTHONDIR
# ---- 3) System Python path
for pythonpath in (
"@PYTHONDIR@",
os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
):
if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
# ---- End snippet of code ----
from cloudutils.syscfg import sysConfigFactory
from cloudutils.utilities import initLoging, UnknownSystemException
from cloudutils.cloudException import CloudRuntimeException, CloudInternalException
from cloudutils.globalEnv import globalEnv
from cloudutils.serviceConfigServer import cloudManagementConfig
from optparse import OptionParser
if __name__ == '__main__':
initLoging("@MSLOGDIR@/setupManagement.log")
glbEnv = globalEnv()

View File

@ -642,6 +642,11 @@
<artifactId>cloud-plugin-storage-object-ceph</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-storage-object-cloudian</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-storage-object-simulator</artifactId>

View File

@ -0,0 +1,36 @@
/*
* 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 org.apache.cloudstack.storage.to.SnapshotObjectTO;
public class ConvertSnapshotAnswer extends Answer {
private SnapshotObjectTO snapshotObjectTO;
public ConvertSnapshotAnswer(SnapshotObjectTO snapshotObjectTO) {
super(null);
this.snapshotObjectTO = snapshotObjectTO;
}
public SnapshotObjectTO getSnapshotObjectTO() {
return snapshotObjectTO;
}
}

View File

@ -0,0 +1,42 @@
/*
* 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 org.apache.cloudstack.storage.to.SnapshotObjectTO;
public class ConvertSnapshotCommand extends Command {
public static final String TEMP_SNAPSHOT_NAME = "_temp";
SnapshotObjectTO snapshotObjectTO;
public SnapshotObjectTO getSnapshotObjectTO() {
return snapshotObjectTO;
}
public ConvertSnapshotCommand(SnapshotObjectTO snapshotObjectTO) {
this.snapshotObjectTO = snapshotObjectTO;
}
@Override
public boolean executeInSequence() {
return true;
}
}

View File

@ -24,11 +24,13 @@ public class GetVmIpAddressCommand extends Command {
String vmName;
String vmNetworkCidr;
boolean windows = false;
String macAddress;
public GetVmIpAddressCommand(String vmName, String vmNetworkCidr, boolean windows) {
public GetVmIpAddressCommand(String vmName, String vmNetworkCidr, boolean windows, String macAddress) {
this.vmName = vmName;
this.windows = windows;
this.vmNetworkCidr = vmNetworkCidr;
this.macAddress = macAddress;
}
@Override
@ -47,4 +49,8 @@ public class GetVmIpAddressCommand extends Command {
public String getVmNetworkCidr() {
return vmNetworkCidr;
}
public String getMacAddress() {
return macAddress;
}
}

View File

@ -29,14 +29,14 @@ import com.cloud.agent.api.to.VirtualMachineTO;
public class MigrateCommand extends Command {
private String vmName;
private String destIp;
private String destinationIp;
private Map<String, MigrateDiskInfo> migrateStorage;
private boolean migrateStorageManaged;
private boolean migrateNonSharedInc;
private boolean autoConvergence;
private String hostGuid;
private boolean isWindows;
private VirtualMachineTO vmTO;
private boolean windows;
private VirtualMachineTO virtualMachine;
private boolean executeInSequence = false;
private List<MigrateDiskInfo> migrateDiskInfoList = new ArrayList<>();
private Map<String, DpdkTO> dpdkInterfaceMapping = new HashMap<>();
@ -64,11 +64,11 @@ public class MigrateCommand extends Command {
protected MigrateCommand() {
}
public MigrateCommand(String vmName, String destIp, boolean isWindows, VirtualMachineTO vmTO, boolean executeInSequence) {
public MigrateCommand(String vmName, String destinationIp, boolean windows, VirtualMachineTO virtualMachine, boolean executeInSequence) {
this.vmName = vmName;
this.destIp = destIp;
this.isWindows = isWindows;
this.vmTO = vmTO;
this.destinationIp = destinationIp;
this.windows = windows;
this.virtualMachine = virtualMachine;
this.executeInSequence = executeInSequence;
}
@ -105,15 +105,15 @@ public class MigrateCommand extends Command {
}
public boolean isWindows() {
return isWindows;
return windows;
}
public VirtualMachineTO getVirtualMachine() {
return vmTO;
return virtualMachine;
}
public String getDestinationIp() {
return destIp;
return destinationIp;
}
public String getVmName() {
@ -233,4 +233,9 @@ public class MigrateCommand extends Command {
this.isSourceDiskOnStorageFileSystem = isDiskOnFileSystemStorage;
}
}
@Override
public boolean isReconcile() {
return true;
}
}

View File

@ -46,6 +46,10 @@ public class ModifyStoragePoolAnswer extends Answer {
templateInfo = tInfo;
}
public ModifyStoragePoolAnswer(ModifyStoragePoolCommand cmd, boolean success, String details) {
super(cmd, success, details);
}
public void setPoolInfo(StoragePoolInfo poolInfo) {
this.poolInfo = poolInfo;
}

View File

@ -19,18 +19,25 @@
package com.cloud.agent.api;
import java.util.ArrayList;
import java.util.List;
public class PingAnswer extends Answer {
private PingCommand _command = null;
private boolean sendStartup = false;
private List<String> avoidMsList;
private List<String> reconcileCommands = new ArrayList<>();
protected PingAnswer() {
}
public PingAnswer(PingCommand cmd, boolean sendStartup) {
public PingAnswer(PingCommand cmd, List<String> avoidMsList, boolean sendStartup) {
super(cmd);
_command = cmd;
this.sendStartup = sendStartup;
this.avoidMsList = avoidMsList;
}
public PingCommand getCommand() {
@ -44,4 +51,20 @@ public class PingAnswer extends Answer {
public void setSendStartup(boolean sendStartup) {
this.sendStartup = sendStartup;
}
public List<String> getReconcileCommands() {
return reconcileCommands;
}
public void setReconcileCommands(List<String> reconcileCommands) {
this.reconcileCommands = reconcileCommands;
}
public void addReconcileCommand(String reconcileCommand) {
this.reconcileCommands.add(reconcileCommand);
}
public List<String> getAvoidMsList() {
return avoidMsList;
}
}

View File

@ -20,11 +20,14 @@
package com.cloud.agent.api;
import com.cloud.host.Host;
import org.apache.cloudstack.command.CommandInfo;
public class PingCommand extends Command {
Host.Type hostType;
long hostId;
boolean outOfBand;
@LogLevel(LogLevel.Log4jLevel.Trace)
private CommandInfo[] commandInfos = new CommandInfo[] {};
protected PingCommand() {
}
@ -78,4 +81,12 @@ public class PingCommand extends Command {
result = 31 * result + (int) (hostId ^ (hostId >>> 32));
return result;
}
public CommandInfo[] getCommandInfos() {
return commandInfos;
}
public void setCommandInfos(CommandInfo[] commandInfos) {
this.commandInfos = commandInfos;
}
}

View File

@ -35,6 +35,7 @@ public class ReadyCommand extends Command {
private String hostUuid;
private String hostName;
private List<String> msHostList;
private List<String> avoidMsHostList;
private String lbAlgorithm;
private Long lbCheckInterval;
private Boolean enableHumanReadableSizes;
@ -90,6 +91,14 @@ public class ReadyCommand extends Command {
this.msHostList = msHostList;
}
public List<String> getAvoidMsHostList() {
return avoidMsHostList;
}
public void setAvoidMsHostList(List<String> msHostList) {
this.avoidMsHostList = avoidMsHostList;
}
public String getLbAlgorithm() {
return lbAlgorithm;
}

View File

@ -1,3 +1,4 @@
//
// 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
@ -14,25 +15,35 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
package org.apache.cloudstack.api.command.admin.zone;
package com.cloud.agent.api;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
public class VmwareRequestResponse<T extends ResponseObject> extends ListResponse<T> {
@SerializedName(ApiConstants.TOKEN)
@Param(description = "The Vmware API token to use for retrieving further responses with")
private String token;
import java.util.List;
public String getToken() {
return token;
public class RecreateCheckpointsCommand extends Command {
private List<VolumeObjectTO> volumes;
private String vmName;
public RecreateCheckpointsCommand(List<VolumeObjectTO> volumes, String vmName) {
this.volumes = volumes;
this.vmName = vmName;
}
public void setToken(String token) {
this.token = token;
public List<VolumeObjectTO> getDisks() {
return volumes;
}
public String getVmName() {
return vmName;
}
@Override
public boolean executeInSequence() {
return true;
}
}

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