startupTask = new AtomicReference<>();
+ private static final long DEFAULT_STARTUP_WAIT = 180;
+ long startupWait = DEFAULT_STARTUP_WAIT;
+ boolean reconnectAllowed = true;
- Thread _shutdownThread = new ShutdownThread(this);
+ //For time sensitive task, e.g. PingTask
+ ThreadPoolExecutor outRequestHandler;
+ ExecutorService requestHandler;
- private String _keystoreSetupPath;
- private String _keystoreCertImportPath;
+ Thread shutdownThread = new ShutdownThread(this);
- // for simulator use only
+ private String keystoreSetupSetupPath;
+ private String keystoreCertImportScriptPath;
+
+ private String hostname;
+
+ protected String getLinkLog(final Link link) {
+ if (link == null) {
+ return "";
+ }
+ StringBuilder str = new StringBuilder();
+ if (logger.isTraceEnabled()) {
+ str.append(System.identityHashCode(link)).append("-");
+ }
+ str.append(link.getSocketAddress());
+ return str.toString();
+ }
+
+ protected String getAgentName() {
+ return (serverResource != null && serverResource.isAppendAgentNameToLogs() &&
+ StringUtils.isNotBlank(serverResource.getName())) ?
+ serverResource.getName() :
+ "Agent";
+ }
+
+ protected void setupShutdownHookAndInitExecutors() {
+ logger.trace("Adding shutdown hook");
+ Runtime.getRuntime().addShutdownHook(shutdownThread);
+ selfTaskExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Agent-SelfTask"));
+ outRequestHandler = new ThreadPoolExecutor(shell.getPingRetries(), 2 * shell.getPingRetries(), 10, TimeUnit.MINUTES,
+ new SynchronousQueue<>(), new NamedThreadFactory("AgentOutRequest-Handler"));
+ requestHandler = new ThreadPoolExecutor(shell.getWorkers(), 5 * shell.getWorkers(), 1, TimeUnit.DAYS,
+ new LinkedBlockingQueue<>(), new NamedThreadFactory("AgentRequest-Handler"));
+ }
+
+ /**
+ * Constructor for the {@code Agent} class, intended for simulator use only.
+ *
+ * This constructor initializes the agent with a provided {@link IAgentShell}.
+ * It sets up the necessary NIO client connection, establishes a shutdown hook,
+ * and initializes the thread executors.
+ *
+ * @param shell the {@link IAgentShell} instance that provides agent configuration and runtime information.
+ */
public Agent(final IAgentShell shell) {
- _shell = shell;
- _link = null;
-
- _connection = new NioClient("Agent", _shell.getNextHost(), _shell.getPort(), _shell.getWorkers(), this);
-
- Runtime.getRuntime().addShutdownHook(_shutdownThread);
-
- _ugentTaskPool =
- new ThreadPoolExecutor(shell.getPingRetries(), 2 * shell.getPingRetries(), 10, TimeUnit.MINUTES, new SynchronousQueue(), new NamedThreadFactory(
- "UgentTask"));
-
- _executor =
- new ThreadPoolExecutor(_shell.getWorkers(), 5 * _shell.getWorkers(), 1, TimeUnit.DAYS, new LinkedBlockingQueue(), new NamedThreadFactory(
- "agentRequest-Handler"));
+ this.shell = shell;
+ this.link = null;
+ this.connection = new NioClient(
+ getAgentName(),
+ this.shell.getNextHost(),
+ this.shell.getPort(),
+ this.shell.getWorkers(),
+ this.shell.getSslHandshakeTimeout(),
+ this
+ );
+ setupShutdownHookAndInitExecutors();
}
public Agent(final IAgentShell shell, final int localAgentId, final ServerResource resource) throws ConfigurationException {
- _shell = shell;
- _resource = resource;
- _link = null;
-
+ this.shell = shell;
+ serverResource = resource;
+ link = null;
resource.setAgentControl(this);
-
- final String value = _shell.getPersistentProperty(getResourceName(), "id");
- _id = value != null ? Long.parseLong(value) : null;
- logger.info("id is {}", ObjectUtils.defaultIfNull(_id, ""));
+ final String value = shell.getPersistentProperty(getResourceName(), "id");
+ _uuid = shell.getPersistentProperty(getResourceName(), "uuid");
+ _name = shell.getPersistentProperty(getResourceName(), "name");
+ id = value != null ? Long.parseLong(value) : null;
+ logger.info("Initialising agent [id: {}, uuid: {}, name: {}]", ObjectUtils.defaultIfNull(id, ""), _uuid, _name);
final Map params = new HashMap<>();
-
// merge with properties from command line to let resource access command line parameters
- for (final Map.Entry cmdLineProp : _shell.getCmdLineProperties().entrySet()) {
+ for (final Map.Entry cmdLineProp : this.shell.getCmdLineProperties().entrySet()) {
params.put(cmdLineProp.getKey(), cmdLineProp.getValue());
}
-
- if (!_resource.configure(getResourceName(), params)) {
- throw new ConfigurationException("Unable to configure " + _resource.getName());
+ if (!serverResource.configure(getResourceName(), params)) {
+ throw new ConfigurationException("Unable to configure " + serverResource.getName());
}
+ ThreadContext.put("agentname", getAgentName());
+ final String host = this.shell.getNextHost();
+ connection = new NioClient(getAgentName(), host, this.shell.getPort(), this.shell.getWorkers(),
+ this.shell.getSslHandshakeTimeout(), this);
+ setupShutdownHookAndInitExecutors();
+ logger.info("{} with host = {}, local id = {}", this, host, localAgentId);
+ }
- final String host = _shell.getNextHost();
- _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this);
- // ((NioClient)_connection).setBindAddress(_shell.getPrivateIp());
-
- logger.debug("Adding shutdown hook");
- Runtime.getRuntime().addShutdownHook(_shutdownThread);
-
- _ugentTaskPool =
- new ThreadPoolExecutor(shell.getPingRetries(), 2 * shell.getPingRetries(), 10, TimeUnit.MINUTES, new SynchronousQueue(), new NamedThreadFactory(
- "UgentTask"));
-
- _executor =
- new ThreadPoolExecutor(_shell.getWorkers(), 5 * _shell.getWorkers(), 1, TimeUnit.DAYS, new LinkedBlockingQueue(), new NamedThreadFactory(
- "agentRequest-Handler"));
-
- logger.info("Agent [id = {} : type = {} : zone = {} : pod = {} : workers = {} : host = {} : port = {}", ObjectUtils.defaultIfNull(_id, "new"), getResourceName(),
- _shell.getZone(), _shell.getPod(), _shell.getWorkers(), host, _shell.getPort());
+ @Override
+ public String toString() {
+ return String.format("Agent [id = %s, uuid = %s, name = %s, type = %s, zone = %s, pod = %s, workers = %d, port = %d]",
+ ObjectUtils.defaultIfNull(id, "new"),
+ _uuid,
+ _name,
+ getResourceName(),
+ this.shell.getZone(),
+ this.shell.getPod(),
+ this.shell.getWorkers(),
+ this.shell.getPort());
}
public String getVersion() {
- return _shell.getVersion();
+ return shell.getVersion();
}
public String getResourceGuid() {
- final String guid = _shell.getGuid();
+ final String guid = shell.getGuid();
return guid + "-" + getResourceName();
}
public String getZone() {
- return _shell.getZone();
+ return shell.getZone();
}
public String getPod() {
- return _shell.getPod();
+ return shell.getPod();
}
protected void setLink(final Link link) {
- _link = link;
+ this.link = link;
}
public ServerResource getResource() {
- return _resource;
- }
-
- public BackoffAlgorithm getBackoffAlgorithm() {
- return _shell.getBackoffAlgorithm();
+ return serverResource;
}
public String getResourceName() {
- return _resource.getClass().getSimpleName();
+ return serverResource.getClass().getSimpleName();
}
/**
@@ -255,71 +297,64 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
* agent instances and its inner objects.
*/
private void scavengeOldAgentObjects() {
- _executor.submit(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(2000L);
- } catch (final InterruptedException ignored) {
- } finally {
- System.gc();
- }
+ requestHandler.submit(() -> {
+ try {
+ Thread.sleep(2000L);
+ } catch (final InterruptedException ignored) {
+ } finally {
+ System.gc();
}
});
}
public void start() {
- if (!_resource.start()) {
- logger.error("Unable to start the resource: {}", _resource.getName());
- throw new CloudRuntimeException("Unable to start the resource: " + _resource.getName());
+ if (!serverResource.start()) {
+ String msg = String.format("Unable to start the resource: %s", serverResource.getName());
+ logger.error(msg);
+ throw new CloudRuntimeException(msg);
}
- _keystoreSetupPath = Script.findScript("scripts/util/", KeyStoreUtils.KS_SETUP_SCRIPT);
- if (_keystoreSetupPath == null) {
+ keystoreSetupSetupPath = Script.findScript("scripts/util/", KeyStoreUtils.KS_SETUP_SCRIPT);
+ if (keystoreSetupSetupPath == null) {
throw new CloudRuntimeException(String.format("Unable to find the '%s' script", KeyStoreUtils.KS_SETUP_SCRIPT));
}
- _keystoreCertImportPath = Script.findScript("scripts/util/", KeyStoreUtils.KS_IMPORT_SCRIPT);
- if (_keystoreCertImportPath == null) {
+ keystoreCertImportScriptPath = Script.findScript("scripts/util/", KeyStoreUtils.KS_IMPORT_SCRIPT);
+ if (keystoreCertImportScriptPath == null) {
throw new CloudRuntimeException(String.format("Unable to find the '%s' script", KeyStoreUtils.KS_IMPORT_SCRIPT));
}
try {
- _connection.start();
+ connection.start();
} catch (final NioConnectionException e) {
logger.warn("Attempt to connect to server generated NIO Connection Exception {}, trying again", e.getLocalizedMessage());
}
- while (!_connection.isStartup()) {
- final String host = _shell.getNextHost();
- _shell.getBackoffAlgorithm().waitBeforeRetry();
- _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this);
- logger.info("Connecting to host:{}", host);
+ while (!connection.isStartup()) {
+ final String host = shell.getNextHost();
+ shell.getBackoffAlgorithm().waitBeforeRetry();
+ connection = new NioClient(getAgentName(), host, shell.getPort(), shell.getWorkers(),
+ shell.getSslHandshakeTimeout(), this);
+ logger.info("Connecting to host: {}", host);
try {
- _connection.start();
+ connection.start();
} catch (final NioConnectionException e) {
- _connection.stop();
- try {
- _connection.cleanUp();
- } catch (final IOException ex) {
- logger.warn("Fail to clean up old connection. {}", ex);
- }
+ stopAndCleanupConnection(false);
logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...", e);
}
}
- _shell.updateConnectedHost();
+ shell.updateConnectedHost(((NioClient)connection).getHost());
scavengeOldAgentObjects();
-
}
public void stop(final String reason, final String detail) {
- logger.info("Stopping the agent: Reason = {} {}", reason, ": Detail = " + ObjectUtils.defaultIfNull(detail, ""));
- _reconnectAllowed = false;
- if (_connection != null) {
+ logger.info("Stopping the agent: Reason = {}{}", reason, (detail != null ? ": Detail = " + detail : ""));
+ reconnectAllowed = false;
+ if (connection != null) {
final ShutdownCommand cmd = new ShutdownCommand(reason, detail);
try {
- if (_link != null) {
- final Request req = new Request(_id != null ? _id : -1, -1, cmd, false);
- _link.send(req.toBytes());
+ if (link != null) {
+ final Request req = new Request(id != null ? id : -1, -1, cmd, false);
+ link.send(req.toBytes());
}
} catch (final ClosedChannelException e) {
logger.warn("Unable to send: {}", cmd.toString());
@@ -332,108 +367,148 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
} catch (final InterruptedException e) {
logger.debug("Who the heck interrupted me here?");
}
- _connection.stop();
- _connection = null;
- _link = null;
+ connection.stop();
+ connection = null;
+ link = null;
}
- if (_resource != null) {
- _resource.stop();
- _resource = null;
+ if (serverResource != null) {
+ serverResource.stop();
+ serverResource = null;
}
- if (_startup != null) {
- _startup = null;
+ if (startupTask.get() != null) {
+ startupTask.set(null);
}
- if (_ugentTaskPool != null) {
- _ugentTaskPool.shutdownNow();
- _ugentTaskPool = null;
+ if (outRequestHandler != null) {
+ outRequestHandler.shutdownNow();
+ outRequestHandler = null;
}
- if (_executor != null) {
- _executor.shutdown();
- _executor = null;
+ if (requestHandler != null) {
+ requestHandler.shutdown();
+ requestHandler = null;
}
- if (_timer != null) {
- _timer.cancel();
- _timer = null;
+ if (selfTaskExecutor != null) {
+ selfTaskExecutor.shutdown();
+ selfTaskExecutor = null;
}
- if (hostLBTimer != null) {
- hostLBTimer.cancel();
- hostLBTimer = null;
+ if (hostLbCheckExecutor != null) {
+ hostLbCheckExecutor.shutdown();
+ hostLbCheckExecutor = null;
}
- if (certTimer != null) {
- certTimer.cancel();
- certTimer = null;
+ if (certExecutor != null) {
+ certExecutor.shutdown();
+ certExecutor = null;
}
}
public Long getId() {
- return _id;
+ return id;
}
public void setId(final Long id) {
logger.debug("Set agent id {}", id);
- _id = id;
- _shell.setPersistentProperty(getResourceName(), "id", Long.toString(id));
+ this.id = id;
+ shell.setPersistentProperty(getResourceName(), "id", Long.toString(id));
}
- private synchronized void scheduleServicesRestartTask() {
- if (certTimer != null) {
- certTimer.cancel();
- certTimer.purge();
+ public String getUuid() {
+ return _uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this._uuid = uuid;
+ shell.setPersistentProperty(getResourceName(), "uuid", uuid);
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public void setName(String name) {
+ this._name = name;
+ shell.setPersistentProperty(getResourceName(), "name", name);
+ }
+
+ private void scheduleCertificateRenewalTask() {
+ String name = "CertificateRenewalTask";
+ if (certExecutor != null && !certExecutor.isShutdown()) {
+ certExecutor.shutdown();
+ try {
+ if (!certExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
+ certExecutor.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ logger.debug("Forcing {} shutdown as it did not shutdown in the desired time due to: {}",
+ name, e.getMessage());
+ certExecutor.shutdownNow();
+ }
}
- certTimer = new Timer("Certificate Renewal Timer");
- certTimer.schedule(new PostCertificateRenewalTask(this), 5000L);
+ certExecutor = Executors.newSingleThreadScheduledExecutor((new NamedThreadFactory(name)));
+ certExecutor.schedule(new PostCertificateRenewalTask(this), 5, TimeUnit.SECONDS);
}
- private synchronized void scheduleHostLBCheckerTask(final long checkInterval) {
- if (hostLBTimer != null) {
- hostLBTimer.cancel();
+ private void scheduleHostLBCheckerTask(final String lbAlgorithm, final long checkInterval) {
+ String name = "HostLBCheckerTask";
+ if (hostLbCheckExecutor != null && !hostLbCheckExecutor.isShutdown()) {
+ logger.info("Shutting down the preferred host checker task {}", name);
+ hostLbCheckExecutor.shutdown();
+ try {
+ if (!hostLbCheckExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
+ hostLbCheckExecutor.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ logger.debug("Forcing the preferred host checker task {} shutdown as it did not shutdown in the desired time due to: {}",
+ name, e.getMessage());
+ hostLbCheckExecutor.shutdownNow();
+ }
}
if (checkInterval > 0L) {
- logger.info("Scheduling preferred host timer task with host.lb.interval={}ms", checkInterval);
- hostLBTimer = new Timer("Host LB Timer");
- hostLBTimer.scheduleAtFixedRate(new PreferredHostCheckerTask(), checkInterval, checkInterval);
+ if ("shuffle".equalsIgnoreCase(lbAlgorithm)) {
+ logger.info("Scheduling the preferred host checker task to trigger once (to apply lb algorithm '{}') after host.lb.interval={} ms", lbAlgorithm, checkInterval);
+ hostLbCheckExecutor = Executors.newSingleThreadScheduledExecutor((new NamedThreadFactory(name)));
+ hostLbCheckExecutor.schedule(new PreferredHostCheckerTask(), checkInterval, TimeUnit.MILLISECONDS);
+ return;
+ }
+
+ logger.info("Scheduling a recurring preferred host checker task with lb algorithm '{}' and host.lb.interval={} ms", lbAlgorithm, checkInterval);
+ hostLbCheckExecutor = Executors.newSingleThreadScheduledExecutor((new NamedThreadFactory(name)));
+ hostLbCheckExecutor.scheduleAtFixedRate(new PreferredHostCheckerTask(), checkInterval, checkInterval,
+ TimeUnit.MILLISECONDS);
}
}
public void scheduleWatch(final Link link, final Request request, final long delay, final long period) {
- synchronized (_watchList) {
- logger.debug("Adding task with request: {} to watch list", request.toString());
-
- final WatchTask task = new WatchTask(link, request, this);
- _timer.schedule(task, 0, period);
- _watchList.add(task);
- }
+ logger.debug("Adding a watch list");
+ final WatchTask task = new WatchTask(link, request, this);
+ final ScheduledFuture> future = selfTaskExecutor.scheduleAtFixedRate(task, delay, period, TimeUnit.MILLISECONDS);
+ watchList.add(future);
}
public void triggerUpdate() {
- PingCommand command = _resource.getCurrentStatus(getId());
+ PingCommand command = serverResource.getCurrentStatus(getId());
command.setOutOfBand(true);
logger.debug("Sending out of band ping");
-
- final Request request = new Request(_id, -1, command, false);
+ final Request request = new Request(id, -1, command, false);
request.setSequence(getNextSequence());
try {
- _link.send(request.toBytes());
+ link.send(request.toBytes());
} catch (final ClosedChannelException e) {
logger.warn("Unable to send ping update: {}", request.toString());
}
}
protected void cancelTasks() {
- synchronized (_watchList) {
- for (final WatchTask task : _watchList) {
- task.cancel();
- }
- logger.debug("Clearing {} tasks of watch list", _watchList.size());
- _watchList.clear();
+ for (final ScheduledFuture> task : watchList) {
+ task.cancel(true);
}
+ logger.debug("Clearing watch list: {}", () -> watchList.size());
+ watchList.clear();
}
/**
@@ -444,27 +519,52 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
* when host is added back
*/
protected void cleanupAgentZoneProperties() {
- _shell.setPersistentProperty(null, "zone", "");
- _shell.setPersistentProperty(null, "cluster", "");
- _shell.setPersistentProperty(null, "pod", "");
+ shell.setPersistentProperty(null, "zone", "");
+ shell.setPersistentProperty(null, "cluster", "");
+ shell.setPersistentProperty(null, "pod", "");
}
- public synchronized void lockStartupTask(final Link link) {
- _startup = new StartupTask(link);
- _timer.schedule(_startup, _startupWait);
+ public void lockStartupTask(final Link link) {
+ logger.debug("Creating startup task for link: {}", () -> getLinkLog(link));
+ StartupTask currentTask = startupTask.get();
+ if (currentTask != null) {
+ logger.warn("A Startup task is already locked or in progress, cannot create for link {}",
+ getLinkLog(link));
+ return;
+ }
+ currentTask = new StartupTask(link);
+ if (startupTask.compareAndSet(null, currentTask)) {
+ selfTaskExecutor.schedule(currentTask, startupWait, TimeUnit.SECONDS);
+ return;
+ }
+ logger.warn("Failed to lock a StartupTask for link: {}", getLinkLog(link));
+ }
+
+ protected boolean cancelStartupTask() {
+ StartupTask task = startupTask.getAndSet(null);
+ if (task != null) {
+ task.cancel();
+ return true;
+ }
+ return false;
}
public void sendStartup(final Link link) {
- final StartupCommand[] startup = _resource.initialize();
+ sendStartup(link, false);
+ }
+
+ public void sendStartup(final Link link, boolean transfer) {
+ final StartupCommand[] startup = serverResource.initialize();
if (startup != null) {
- final String msHostList = _shell.getPersistentProperty(null, "host");
+ final String msHostList = shell.getPersistentProperty(null, "host");
final Command[] commands = new Command[startup.length];
for (int i = 0; i < startup.length; i++) {
setupStartupCommand(startup[i]);
startup[i].setMSHostList(msHostList);
+ startup[i].setConnectionTransferred(transfer);
commands[i] = startup[i];
}
- final Request request = new Request(_id != null ? _id : -1, -1, commands, false, false);
+ final Request request = new Request(id != null ? id : -1, -1, commands, false, false);
request.setSequence(getNextSequence());
logger.debug("Sending Startup: {}", request.toString());
@@ -472,31 +572,37 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
try {
link.send(request.toBytes());
} catch (final ClosedChannelException e) {
- logger.warn("Unable to send request: {}", request.toString());
+ logger.warn("Unable to send request to {} due to '{}', request: {}",
+ getLinkLog(link), e.getMessage(), request);
}
- if (_resource instanceof ResourceStatusUpdater) {
- ((ResourceStatusUpdater) _resource).registerStatusUpdater(this);
+ if (serverResource instanceof ResourceStatusUpdater) {
+ ((ResourceStatusUpdater) serverResource).registerStatusUpdater(this);
}
}
}
- protected void setupStartupCommand(final StartupCommand startup) {
- InetAddress addr;
+ protected String retrieveHostname() {
+ logger.trace("Retrieving hostname with resource={}", () -> serverResource.getClass().getSimpleName());
+ final String result = Script.runSimpleBashScript(Script.getExecutableAbsolutePath("hostname"), 500);
+ if (StringUtils.isNotBlank(result)) {
+ return result;
+ }
try {
- addr = InetAddress.getLocalHost();
+ InetAddress address = InetAddress.getLocalHost();
+ return address.toString();
} catch (final UnknownHostException e) {
logger.warn("unknown host? ", e);
throw new CloudRuntimeException("Cannot get local IP address");
}
+ }
- final Script command = new Script("hostname", 500, logger);
- final OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser();
- final String result = command.execute(parser);
- final String hostname = result == null ? parser.getLine() : addr.toString();
-
+ protected void setupStartupCommand(final StartupCommand startup) {
startup.setId(getId());
- if (startup.getName() == null) {
+ if (StringUtils.isBlank(startup.getName())) {
+ if (StringUtils.isBlank(hostname)) {
+ hostname = retrieveHostname();
+ }
startup.setName(hostname);
}
startup.setDataCenter(getZone());
@@ -504,6 +610,13 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
startup.setGuid(getResourceGuid());
startup.setResourceName(getResourceName());
startup.setVersion(getVersion());
+ startup.setArch(getAgentArch());
+ }
+
+ protected String getAgentArch() {
+ final Script command = new Script("/usr/bin/arch", 500, logger);
+ final OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser();
+ return command.execute(parser);
}
@Override
@@ -512,92 +625,104 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
protected void reconnect(final Link link) {
- if (!_reconnectAllowed) {
+ reconnect(link, null, false);
+ }
+
+ protected void reconnect(final Link link, String preferredMSHost, boolean forTransfer) {
+ if (!(forTransfer || reconnectAllowed)) {
+ logger.debug("Reconnect requested but it is not allowed {}", () -> getLinkLog(link));
return;
}
- synchronized (this) {
- if (_startup != null) {
- _startup.cancel();
- _startup = null;
- }
- }
-
- if (link != null) {
- link.close();
- link.terminated();
- }
-
+ cancelStartupTask();
+ closeAndTerminateLink(link);
+ closeAndTerminateLink(this.link);
setLink(null);
cancelTasks();
+ 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 avoidMSHostList = shell.getAvoidHosts();
+ do {
+ 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(((NioClient)connection).getHost());
+ logger.info("Connected to the host: {}", shell.getConnectedHost());
+ }
- _resource.disconnected();
-
- logger.info("Lost connection to host: {}. Attempting reconnection while we still have {} commands in progress.", _shell.getConnectedHost(), _inProgress.get());
-
- _connection.stop();
+ protected void closeAndTerminateLink(final Link link) {
+ if (link == null) {
+ return;
+ }
+ link.close();
+ link.terminated();
+ }
+ protected void stopAndCleanupConnection(boolean waitForStop) {
+ if (connection == null) {
+ return;
+ }
+ connection.stop();
try {
- _connection.cleanUp();
+ connection.cleanUp();
} catch (final IOException e) {
logger.warn("Fail to clean up old connection. {}", e);
}
-
- while (_connection.isStartup()) {
- _shell.getBackoffAlgorithm().waitBeforeRetry();
+ if (!waitForStop) {
+ return;
}
-
do {
- final String host = _shell.getNextHost();
- _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), 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);
- _connection.stop();
- try {
- _connection.cleanUp();
- } catch (final IOException ex) {
- logger.warn("Fail to clean up old connection. {}", ex);
- }
- }
- _shell.getBackoffAlgorithm().waitBeforeRetry();
- } while (!_connection.isStartup());
- _shell.updateConnectedHost();
- logger.info("Connected to the host: {}", _shell.getConnectedHost());
+ shell.getBackoffAlgorithm().waitBeforeRetry();
+ } while (connection.isStartup());
}
public void processStartupAnswer(final Answer answer, final Response response, final Link link) {
- boolean cancelled = false;
- synchronized (this) {
- if (_startup != null) {
- _startup.cancel();
- _startup = null;
- } else {
- cancelled = true;
- }
- }
+ boolean answerValid = cancelStartupTask();
final StartupAnswer startup = (StartupAnswer)answer;
if (!startup.getResult()) {
logger.error("Not allowed to connect to the server: {}", answer.getDetails());
+ if (serverResource != null && !serverResource.isExitOnFailures()) {
+ logger.trace("{} does not allow exit on failure, reconnecting",
+ serverResource.getClass().getSimpleName());
+ reconnect(link);
+ return;
+ }
System.exit(1);
}
- if (cancelled) {
+ if (!answerValid) {
logger.warn("Threw away a startup answer because we're reconnecting.");
return;
}
- logger.info("Process agent startup answer, agent id = {}", startup.getHostId());
+ logger.info("Process agent startup answer, agent [id: {}, uuid: {}, name: {}] connected to the server",
+ startup.getHostId(), startup.getHostUuid(), startup.getHostName());
setId(startup.getHostId());
- _pingInterval = (long)startup.getPingInterval() * 1000; // change to ms.
+ setUuid(startup.getHostUuid());
+ setName(startup.getHostName());
+ pingInterval = startup.getPingInterval() * 1000L; // change to ms.
- setLastPingResponseTime();
- scheduleWatch(link, response, _pingInterval, _pingInterval);
+ updateLastPingResponseTime();
+ scheduleWatch(link, response, pingInterval, pingInterval);
- _ugentTaskPool.setKeepAliveTime(2 * _pingInterval, TimeUnit.MILLISECONDS);
+ outRequestHandler.setKeepAliveTime(2 * pingInterval, TimeUnit.MILLISECONDS);
- logger.info("Startup Response Received: agent id = {}", getId());
+ logger.info("Startup Response Received: agent [id: {}, uuid: {}, name: {}]",
+ startup.getHostId(), startup.getHostUuid(), startup.getHostName());
}
protected void processRequest(final Request request, final Link link) {
@@ -628,7 +753,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
if (cmd instanceof CronCommand) {
final CronCommand watch = (CronCommand)cmd;
- scheduleWatch(link, request, (long)watch.getInterval() * 1000, watch.getInterval() * 1000);
+ scheduleWatch(link, request, watch.getInterval() * 1000L, watch.getInterval() * 1000L);
answer = new Answer(cmd, true, null);
} else if (cmd instanceof ShutdownCommand) {
final ShutdownCommand shutdown = (ShutdownCommand)cmd;
@@ -637,10 +762,17 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
if (shutdown.isRemoveHost()) {
cleanupAgentZoneProperties();
}
- _reconnectAllowed = false;
+ reconnectAllowed = false;
answer = new Answer(cmd, true, null);
} else if (cmd instanceof ReadyCommand && ((ReadyCommand)cmd).getDetails() != null) {
+
logger.debug("Not ready to connect to mgt server: {}", ((ReadyCommand)cmd).getDetails());
+ if (serverResource != null && !serverResource.isExitOnFailures()) {
+ logger.trace("{} does not allow exit on failure, reconnecting",
+ serverResource.getClass().getSimpleName());
+ reconnect(link);
+ return;
+ }
System.exit(1);
return;
} else if (cmd instanceof MaintainCommand) {
@@ -648,12 +780,10 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
answer = new MaintainAnswer((MaintainCommand)cmd);
} else if (cmd instanceof AgentControlCommand) {
answer = null;
- synchronized (_controlListeners) {
- for (final IAgentControlListener listener : _controlListeners) {
- answer = listener.processControlRequest(request, (AgentControlCommand)cmd);
- if (answer != null) {
- break;
- }
+ for (final IAgentControlListener listener : controlListeners) {
+ answer = listener.processControlRequest(request, (AgentControlCommand)cmd);
+ if (answer != null) {
+ break;
}
}
@@ -665,20 +795,25 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
answer = setupAgentKeystore((SetupKeyStoreCommand) cmd);
} else if (cmd instanceof SetupCertificateCommand && ((SetupCertificateCommand) cmd).isHandleByAgent()) {
answer = setupAgentCertificate((SetupCertificateCommand) cmd);
- if (Host.Type.Routing.equals(_resource.getType())) {
- scheduleServicesRestartTask();
+ if (Host.Type.Routing.equals(serverResource.getType())) {
+ scheduleCertificateRenewalTask();
}
} else if (cmd instanceof SetupMSListCommand) {
answer = setupManagementServerList((SetupMSListCommand) cmd);
+ } else if (cmd instanceof MigrateAgentConnectionCommand) {
+ answer = migrateAgentToOtherMS((MigrateAgentConnectionCommand) cmd);
} else {
if (cmd instanceof ReadyCommand) {
processReadyCommand(cmd);
}
- _inProgress.incrementAndGet();
+ commandsInProgress.incrementAndGet();
try {
- answer = _resource.executeRequest(cmd);
+ if (cmd.isReconcile()) {
+ cmd.setRequestSequence(request.getSequence());
+ }
+ answer = serverResource.executeRequest(cmd);
} finally {
- _inProgress.decrementAndGet();
+ commandsInProgress.decrementAndGet();
}
if (answer == null) {
logger.debug("Response: unsupported command {}", cmd.toString());
@@ -732,13 +867,13 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
final String keyStoreFile = agentFile.getParent() + "/" + KeyStoreUtils.KS_FILENAME;
final String csrFile = agentFile.getParent() + "/" + KeyStoreUtils.CSR_FILENAME;
- String storedPassword = _shell.getPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY);
+ String storedPassword = shell.getPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY);
if (StringUtils.isEmpty(storedPassword)) {
storedPassword = keyStorePassword;
- _shell.setPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY, storedPassword);
+ shell.setPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY, storedPassword);
}
- Script script = new Script(_keystoreSetupPath, 300000, logger);
+ Script script = new Script(keystoreSetupSetupPath, 300000, logger);
script.add(agentFile.getAbsolutePath());
script.add(keyStoreFile);
script.add(storedPassword);
@@ -782,8 +917,8 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
throw new CloudRuntimeException("Unable to save received agent client and ca certificates", e);
}
- String ksPassphrase = _shell.getPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY);
- Script script = new Script(_keystoreCertImportPath, 300000, logger);
+ String ksPassphrase = shell.getPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY);
+ Script script = new Script(keystoreCertImportScriptPath, 300000, logger);
script.add(agentFile.getAbsolutePath());
script.add(ksPassphrase);
script.add(keyStoreFile);
@@ -801,30 +936,85 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
return new SetupCertificateAnswer(true);
}
- private void processManagementServerList(final List msList, final String lbAlgorithm, final Long lbCheckInterval) {
+ private void processManagementServerList(final List msList, final List avoidMsList, final String lbAlgorithm, final Long lbCheckInterval, final boolean triggerHostLB) {
if (CollectionUtils.isNotEmpty(msList) && StringUtils.isNotEmpty(lbAlgorithm)) {
try {
final String newMSHosts = String.format("%s%s%s", com.cloud.utils.StringUtils.toCSVList(msList), IAgentShell.hostLbAlgorithmSeparator, lbAlgorithm);
- _shell.setPersistentProperty(null, "host", newMSHosts);
- _shell.setHosts(newMSHosts);
- _shell.resetHostCounter();
+ shell.setPersistentProperty(null, "host", newMSHosts);
+ shell.setHosts(newMSHosts);
+ shell.resetHostCounter();
logger.info("Processed new management server list: {}", newMSHosts);
} catch (final Exception e) {
throw new CloudRuntimeException("Could not persist received management servers list", e);
}
}
- if ("shuffle".equals(lbAlgorithm)) {
- scheduleHostLBCheckerTask(0);
- } else {
- scheduleHostLBCheckerTask(_shell.getLbCheckerInterval(lbCheckInterval));
+ shell.setAvoidHosts(avoidMsList);
+ if (triggerHostLB) {
+ logger.info("Triggering the preferred host checker task now");
+ ScheduledExecutorService hostLbExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("HostLB-Executor"));
+ hostLbExecutor.schedule(new PreferredHostCheckerTask(), 0, TimeUnit.MILLISECONDS);
+ hostLbExecutor.shutdown();
}
+ scheduleHostLBCheckerTask(lbAlgorithm, shell.getLbCheckerInterval(lbCheckInterval));
}
private Answer setupManagementServerList(final SetupMSListCommand cmd) {
- processManagementServerList(cmd.getMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval());
+ processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval(), cmd.getTriggerHostLb());
return new SetupMSListAnswer(true);
}
+ private Answer migrateAgentToOtherMS(final MigrateAgentConnectionCommand cmd) {
+ try {
+ if (CollectionUtils.isNotEmpty(cmd.getMsList())) {
+ processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval(), false);
+ }
+ ScheduledExecutorService migrateAgentConnectionService = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("MigrateAgentConnection-Job"));
+ migrateAgentConnectionService.schedule(() -> {
+ migrateAgentConnection(cmd.getAvoidMsList());
+ }, 3, TimeUnit.SECONDS);
+ migrateAgentConnectionService.shutdown();
+ } catch (Exception e) {
+ String errMsg = "Migrate agent connection failed, due to " + e.getMessage();
+ logger.debug(errMsg, e);
+ return new MigrateAgentConnectionAnswer(errMsg);
+ }
+ return new MigrateAgentConnectionAnswer(true);
+ }
+
+ private void migrateAgentConnection(List avoidMsList) {
+ final String[] msHosts = shell.getHosts();
+ if (msHosts == null || msHosts.length < 1) {
+ throw new CloudRuntimeException("Management Server hosts empty, not properly configured in agent");
+ }
+
+ List msHostsList = new ArrayList<>(Arrays.asList(msHosts));
+ msHostsList.removeAll(avoidMsList);
+ if (msHostsList.isEmpty() || StringUtils.isEmpty(msHostsList.get(0))) {
+ throw new CloudRuntimeException("No other Management Server hosts to migrate");
+ }
+
+ String preferredMSHost = null;
+ for (String msHost : msHostsList) {
+ try (final Socket socket = new Socket()) {
+ socket.connect(new InetSocketAddress(msHost, shell.getPort()), 5000);
+ preferredMSHost = msHost;
+ break;
+ } catch (final IOException e) {
+ throw new CloudRuntimeException("Management server host: " + msHost + " is not reachable, to migrate connection");
+ }
+ }
+
+ if (preferredMSHost == null) {
+ throw new CloudRuntimeException("Management server host(s) are not reachable, to migrate connection");
+ }
+
+ logger.debug("Management server host " + preferredMSHost + " is found to be reachable, trying to reconnect");
+ shell.resetHostCounter();
+ shell.setAvoidHosts(avoidMsList);
+ shell.setConnectionTransfer(true);
+ reconnect(link, preferredMSHost, true);
+ }
+
public void processResponse(final Response response, final Link link) {
final Answer answer = response.getAnswer();
logger.debug("Received response: {}", response.toString());
@@ -832,17 +1022,24 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
processStartupAnswer(answer, response, link);
} else if (answer instanceof AgentControlAnswer) {
// Notice, we are doing callback while holding a lock!
- synchronized (_controlListeners) {
- for (final IAgentControlListener listener : _controlListeners) {
- listener.processControlResponse(response, (AgentControlAnswer)answer);
- }
+ for (final IAgentControlListener listener : controlListeners) {
+ listener.processControlResponse(response, (AgentControlAnswer)answer);
}
- } else if (answer instanceof PingAnswer && (((PingAnswer) answer).isSendStartup()) && _reconnectAllowed) {
+ } 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 {
- setLastPingResponseTime();
+ serverResource.processPingAnswer((PingAnswer) answer);
}
+ shell.setAvoidHosts(answer.getAvoidMsList());
}
public void processReadyCommand(final Command cmd) {
@@ -853,35 +1050,49 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
NumbersUtil.enableHumanReadableSizes = humanReadable;
}
- logger.info("Processing agent ready command, agent id = {}", ready.getHostId());
+ logger.info("Processing agent ready command, agent id = {}, uuid = {}, name = {}", ready.getHostId(), ready.getHostUuid(), ready.getHostName());
if (ready.getHostId() != null) {
setId(ready.getHostId());
+ setUuid(ready.getHostUuid());
+ setName(ready.getHostName());
}
- processManagementServerList(ready.getMsHostList(), ready.getLbAlgorithm(), ready.getLbCheckInterval());
+ verifyAgentArch(ready.getArch());
+ processManagementServerList(ready.getMsHostList(), ready.getAvoidMsHostList(), ready.getLbAlgorithm(), ready.getLbCheckInterval(), false);
- logger.info("Ready command is processed for agent id = {}", getId());
+ logger.info("Ready command is processed for agent [id: {}, uuid: {}, name: {}]", getId(), getUuid(), getName());
+ }
+
+ private void verifyAgentArch(String arch) {
+ if (StringUtils.isNotBlank(arch)) {
+ String agentArch = getAgentArch();
+ if (!arch.equals(agentArch)) {
+ logger.error("Unexpected arch {}, expected {}", agentArch, arch);
+ }
+ }
}
public void processOtherTask(final Task task) {
final Object obj = task.get();
if (obj instanceof Response) {
- if (System.currentTimeMillis() - _lastPingResponseTime > _pingInterval * _shell.getPingRetries()) {
- logger.error("Ping Interval has gone past {}. Won't reconnect to mgt server, as connection is still alive", _pingInterval * _shell.getPingRetries());
+ if (System.currentTimeMillis() - lastPingResponseTime.get() > pingInterval * shell.getPingRetries()) {
+ logger.error("Ping Interval has gone past {}. Won't reconnect to mgt server, as connection is still alive",
+ pingInterval * shell.getPingRetries());
return;
}
- final PingCommand ping = _resource.getCurrentStatus(getId());
- final Request request = new Request(_id, -1, ping, false);
+ final PingCommand ping = serverResource.getCurrentStatus(getId());
+ final Request request = new Request(id, -1, ping, false);
request.setSequence(getNextSequence());
logger.debug("Sending ping: {}", request.toString());
try {
task.getLink().send(request.toBytes());
//if i can send pingcommand out, means the link is ok
- setLastPingResponseTime();
+ updateLastPingResponseTime();
} catch (final ClosedChannelException e) {
- logger.warn("Unable to send request: {}", request.toString());
+ logger.warn("Unable to send request to {} due to '{}', request: {}",
+ getLinkLog(task.getLink()), e.getMessage(), request);
}
} else if (obj instanceof Request) {
@@ -891,11 +1102,14 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
ThreadContext.put("logcontextid", command.getContextParam("logid"));
}
Answer answer = null;
- _inProgress.incrementAndGet();
+ commandsInProgress.incrementAndGet();
try {
- answer = _resource.executeRequest(command);
+ if (command.isReconcile()) {
+ command.setRequestSequence(req.getSequence());
+ }
+ answer = serverResource.executeRequest(command);
} finally {
- _inProgress.decrementAndGet();
+ commandsInProgress.decrementAndGet();
}
if (answer != null) {
final Response response = new Response(req, answer);
@@ -912,35 +1126,29 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
}
- public synchronized void setLastPingResponseTime() {
- _lastPingResponseTime = System.currentTimeMillis();
+ public void updateLastPingResponseTime() {
+ lastPingResponseTime.set(System.currentTimeMillis());
}
- protected synchronized long getNextSequence() {
- return _sequence++;
+ protected long getNextSequence() {
+ return sequence.getAndIncrement();
}
@Override
public void registerControlListener(final IAgentControlListener listener) {
- synchronized (_controlListeners) {
- _controlListeners.add(listener);
- }
+ controlListeners.add(listener);
}
@Override
public void unregisterControlListener(final IAgentControlListener listener) {
- synchronized (_controlListeners) {
- _controlListeners.remove(listener);
- }
+ controlListeners.remove(listener);
}
@Override
public AgentControlAnswer sendRequest(final AgentControlCommand cmd, final int timeoutInMilliseconds) throws AgentControlChannelException {
final Request request = new Request(getId(), -1, new Command[] {cmd}, true, false);
request.setSequence(getNextSequence());
-
final AgentControlListener listener = new AgentControlListener(request);
-
registerControlListener(listener);
try {
postRequest(request);
@@ -951,7 +1159,6 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
logger.warn("sendRequest is interrupted, exit waiting");
}
}
-
return listener.getAnswer();
} finally {
unregisterControlListener(listener);
@@ -966,9 +1173,9 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
private void postRequest(final Request request) throws AgentControlChannelException {
- if (_link != null) {
+ if (link != null) {
try {
- _link.send(request.toBytes());
+ link.send(request.toBytes());
} catch (final ClosedChannelException e) {
logger.warn("Unable to post agent control request: {}", request.toString());
throw new AgentControlChannelException("Unable to post agent control request due to " + e.getMessage());
@@ -1020,26 +1227,26 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
}
- public class WatchTask extends ManagedContextTimerTask {
+ public class WatchTask implements Runnable {
protected Request _request;
protected Agent _agent;
- protected Link _link;
+ protected Link link;
public WatchTask(final Link link, final Request request, final Agent agent) {
super();
_request = request;
- _link = link;
+ this.link = link;
_agent = agent;
}
@Override
- protected void runInContext() {
+ public void run() {
logger.trace("Scheduling {}", (_request instanceof Response ? "Ping" : "Watch Task"));
try {
if (_request instanceof Response) {
- _ugentTaskPool.submit(new ServerHandler(Task.Type.OTHER, _link, _request));
+ outRequestHandler.submit(new ServerHandler(Task.Type.OTHER, link, _request));
} else {
- _link.schedule(new ServerHandler(Task.Type.OTHER, _link, _request));
+ link.schedule(new ServerHandler(Task.Type.OTHER, link, _request));
}
} catch (final ClosedChannelException e) {
logger.warn("Unable to schedule task because channel is closed");
@@ -1047,35 +1254,32 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
}
- public class StartupTask extends ManagedContextTimerTask {
- protected Link _link;
- protected volatile boolean cancelled = false;
+ public class StartupTask implements Runnable {
+ protected Link link;
+ private final AtomicBoolean cancelled = new AtomicBoolean(false);
public StartupTask(final Link link) {
logger.debug("Startup task created");
- _link = link;
+ this.link = link;
}
- @Override
- public synchronized boolean cancel() {
+ public boolean cancel() {
// TimerTask.cancel may fail depends on the calling context
- if (!cancelled) {
- cancelled = true;
- _startupWait = _startupWaitDefault;
+ if (cancelled.compareAndSet(false, true)) {
+ startupWait = DEFAULT_STARTUP_WAIT;
logger.debug("Startup task cancelled");
- return super.cancel();
}
return true;
}
@Override
- protected synchronized void runInContext() {
- if (!cancelled) {
- logger.info("The startup command is now cancelled");
- cancelled = true;
- _startup = null;
- _startupWait = _startupWaitDefault * 2;
- reconnect(_link);
+ public void run() {
+ if (cancelled.compareAndSet(false, true)) {
+ logger.info("The running startup command is now invalid. Attempting reconnect");
+ startupTask.set(null);
+ startupWait = DEFAULT_STARTUP_WAIT * 2;
+ logger.debug("Executing reconnect from task - {}", () -> getLinkLog(link));
+ reconnect(link);
}
}
}
@@ -1106,9 +1310,10 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
@Override
public void doTask(final Task task) throws TaskExecutionException {
if (task.getType() == Task.Type.CONNECT) {
- _shell.getBackoffAlgorithm().reset();
+ shell.getBackoffAlgorithm().reset();
setLink(task.getLink());
- sendStartup(task.getLink());
+ sendStartup(task.getLink(), shell.isConnectionTransfer());
+ shell.setConnectionTransfer(false);
} else if (task.getType() == Task.Type.DATA) {
Request request;
try {
@@ -1119,7 +1324,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
} else {
//put the requests from mgt server into another thread pool, as the request may take a longer time to finish. Don't block the NIO main thread pool
//processRequest(request, task.getLink());
- _executor.submit(new AgentRequestHandler(getType(), getLink(), request));
+ requestHandler.submit(new AgentRequestHandler(getType(), getLink(), request));
}
} catch (final ClassNotFoundException e) {
logger.error("Unable to find this request ");
@@ -1127,8 +1332,15 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
logger.error("Error parsing task", e);
}
} else if (task.getType() == Task.Type.DISCONNECT) {
+ try {
+ // an issue has been found if reconnect immediately after disconnecting. please refer to https://github.com/apache/cloudstack/issues/8517
+ // wait 5 seconds before reconnecting
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ }
+ shell.setConnectionTransfer(false);
+ logger.debug("Executing disconnect task - {}", () -> getLinkLog(task.getLink()));
reconnect(task.getLink());
- return;
} else if (task.getType() == Task.Type.OTHER) {
processOtherTask(task);
}
@@ -1151,26 +1363,26 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
protected void runInContext() {
while (true) {
try {
- if (_inProgress.get() == 0) {
+ if (commandsInProgress.get() == 0) {
logger.debug("Running post certificate renewal task to restart services.");
// Let the resource perform any post certificate renewal cleanups
- _resource.executeRequest(new PostCertificateRenewalCommand());
+ serverResource.executeRequest(new PostCertificateRenewalCommand());
- IAgentShell shell = agent._shell;
- ServerResource resource = agent._resource.getClass().newInstance();
+ IAgentShell shell = agent.shell;
+ ServerResource resource = agent.serverResource.getClass().getDeclaredConstructor().newInstance();
// Stop current agent
agent.cancelTasks();
- agent._reconnectAllowed = false;
- Runtime.getRuntime().removeShutdownHook(agent._shutdownThread);
+ agent.reconnectAllowed = false;
+ Runtime.getRuntime().removeShutdownHook(agent.shutdownThread);
agent.stop(ShutdownCommand.Requested, "Restarting due to new X509 certificates");
// Nullify references for GC
- agent._shell = null;
- agent._watchList = null;
- agent._shutdownThread = null;
- agent._controlListeners = null;
+ agent.shell = null;
+ agent.watchList = null;
+ agent.shutdownThread = null;
+ agent.controlListeners = null;
agent = null;
// Start a new agent instance
@@ -1178,7 +1390,6 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
return;
}
logger.debug("Other tasks are in progress, will retry post certificate renewal command after few seconds");
-
Thread.sleep(5000);
} catch (final Exception e) {
logger.warn("Failed to execute post certificate renewal command:", e);
@@ -1193,35 +1404,34 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
@Override
protected void runInContext() {
try {
- final String[] msList = _shell.getHosts();
+ final String[] msList = shell.getHosts();
if (msList == null || msList.length < 1) {
return;
}
- final String preferredHost = msList[0];
- final String connectedHost = _shell.getConnectedHost();
- logger.trace("Running preferred host checker task, connected host={}, preferred host={}", connectedHost, preferredHost);
-
- if (preferredHost != null && !preferredHost.equals(connectedHost) && _link != null) {
- boolean isHostUp = true;
- try (final Socket socket = new Socket()) {
- socket.connect(new InetSocketAddress(preferredHost, _shell.getPort()), 5000);
- } catch (final IOException e) {
- isHostUp = false;
- logger.trace("Host: {} is not reachable", preferredHost);
-
- }
- if (isHostUp && _link != null && _inProgress.get() == 0) {
- logger.debug("Preferred host {} is found to be reachable, trying to reconnect", preferredHost);
-
- _shell.resetHostCounter();
- reconnect(_link);
+ final String preferredMSHost = msList[0];
+ final String connectedHost = shell.getConnectedHost();
+ logger.debug("Running preferred host checker task, connected host={}, preferred host={}",
+ connectedHost, preferredMSHost);
+ if (preferredMSHost == null || preferredMSHost.equals(connectedHost) || link == null) {
+ return;
+ }
+ boolean isHostUp = false;
+ try (final Socket socket = new Socket()) {
+ socket.connect(new InetSocketAddress(preferredMSHost, shell.getPort()), 5000);
+ isHostUp = true;
+ } catch (final IOException e) {
+ 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", preferredMSHost);
}
+ shell.resetHostCounter();
+ reconnect(link, preferredMSHost, false);
}
} catch (Throwable t) {
logger.error("Error caught while attempting to connect to preferred host", t);
}
}
-
}
-
}
diff --git a/agent/src/main/java/com/cloud/agent/AgentShell.java b/agent/src/main/java/com/cloud/agent/AgentShell.java
index 0699e00250b..4862e7e001e 100644
--- a/agent/src/main/java/com/cloud/agent/AgentShell.java
+++ b/agent/src/main/java/com/cloud/agent/AgentShell.java
@@ -16,29 +16,6 @@
// under the License.
package com.cloud.agent;
-import com.cloud.agent.Agent.ExitStatus;
-import com.cloud.agent.dao.StorageComponent;
-import com.cloud.agent.dao.impl.PropertiesStorage;
-import com.cloud.agent.properties.AgentProperties;
-import com.cloud.agent.properties.AgentPropertiesFileHandler;
-import com.cloud.resource.ServerResource;
-import com.cloud.utils.LogUtils;
-import com.cloud.utils.ProcessUtil;
-import com.cloud.utils.PropertiesUtil;
-import com.cloud.utils.backoff.BackoffAlgorithm;
-import com.cloud.utils.backoff.impl.ConstantTimeBackoff;
-import com.cloud.utils.exception.CloudRuntimeException;
-import org.apache.commons.daemon.Daemon;
-import org.apache.commons.daemon.DaemonContext;
-import org.apache.commons.daemon.DaemonInitException;
-import org.apache.commons.lang.math.NumberUtils;
-import org.apache.commons.lang3.BooleanUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.core.config.Configurator;
-
-import javax.naming.ConfigurationException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -53,6 +30,31 @@ import java.util.Map;
import java.util.Properties;
import java.util.UUID;
+import javax.naming.ConfigurationException;
+
+import org.apache.commons.daemon.Daemon;
+import org.apache.commons.daemon.DaemonContext;
+import org.apache.commons.daemon.DaemonInitException;
+import org.apache.commons.lang.math.NumberUtils;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.config.Configurator;
+
+import com.cloud.agent.Agent.ExitStatus;
+import com.cloud.agent.dao.StorageComponent;
+import com.cloud.agent.dao.impl.PropertiesStorage;
+import com.cloud.agent.properties.AgentProperties;
+import com.cloud.agent.properties.AgentPropertiesFileHandler;
+import com.cloud.resource.ServerResource;
+import com.cloud.utils.LogUtils;
+import com.cloud.utils.ProcessUtil;
+import com.cloud.utils.PropertiesUtil;
+import com.cloud.utils.backoff.BackoffAlgorithm;
+import com.cloud.utils.backoff.impl.ConstantTimeBackoff;
+import com.cloud.utils.exception.CloudRuntimeException;
+
public class AgentShell implements IAgentShell, Daemon {
protected static Logger LOGGER = LogManager.getLogger(AgentShell.class);
@@ -64,6 +66,7 @@ public class AgentShell implements IAgentShell, Daemon {
private String _zone;
private String _pod;
private String _host;
+ private List _avoidHosts;
private String _privateIp;
private int _port;
private int _proxyPort;
@@ -74,9 +77,9 @@ public class AgentShell implements IAgentShell, Daemon {
private volatile boolean _exit = false;
private int _pingRetries;
private final List _agents = new ArrayList();
- private String hostToConnect;
private String connectedHost;
private Long preferredHostCheckInterval;
+ private boolean connectionTransfer = false;
protected AgentProperties agentProperties = new AgentProperties();
public AgentShell() {
@@ -118,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;
}
@@ -140,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;
@@ -163,6 +165,16 @@ public class AgentShell implements IAgentShell, Daemon {
}
}
+ @Override
+ public void setAvoidHosts(List avoidHosts) {
+ _avoidHosts = avoidHosts;
+ }
+
+ @Override
+ public List getAvoidHosts() {
+ return _avoidHosts;
+ }
+
@Override
public String getPrivateIp() {
return _privateIp;
@@ -215,6 +227,14 @@ public class AgentShell implements IAgentShell, Daemon {
_storage.persist(name, value);
}
+ public boolean isConnectionTransfer() {
+ return connectionTransfer;
+ }
+
+ public void setConnectionTransfer(boolean connectionTransfer) {
+ this.connectionTransfer = connectionTransfer;
+ }
+
void loadProperties() throws ConfigurationException {
final File file = PropertiesUtil.findConfigFile("agent.properties");
@@ -406,7 +426,9 @@ public class AgentShell implements IAgentShell, Daemon {
LOGGER.info("Defaulting to the constant time backoff algorithm");
_backoff = new ConstantTimeBackoff();
- _backoff.configure("ConstantTimeBackoff", new HashMap());
+ Map map = new HashMap<>();
+ map.put("seconds", _properties.getProperty("backoff.seconds"));
+ _backoff.configure("ConstantTimeBackoff", map);
}
private void launchAgent() throws ConfigurationException {
@@ -455,6 +477,11 @@ public class AgentShell implements IAgentShell, Daemon {
agent.start();
}
+ @Override
+ public Integer getSslHandshakeTimeout() {
+ return AgentPropertiesFileHandler.getPropertyValue(AgentProperties.SSL_HANDSHAKE_TIMEOUT);
+ }
+
public synchronized int getNextAgentId() {
return _nextAgentId++;
}
diff --git a/agent/src/main/java/com/cloud/agent/IAgentShell.java b/agent/src/main/java/com/cloud/agent/IAgentShell.java
index 2dd08fffd45..9eefa6d2eee 100644
--- a/agent/src/main/java/com/cloud/agent/IAgentShell.java
+++ b/agent/src/main/java/com/cloud/agent/IAgentShell.java
@@ -16,6 +16,7 @@
// under the License.
package com.cloud.agent;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -63,11 +64,21 @@ public interface IAgentShell {
String[] getHosts();
+ void setAvoidHosts(List hosts);
+
+ List getAvoidHosts();
+
long getLbCheckerInterval(Long receivedLbInterval);
- void updateConnectedHost();
+ void updateConnectedHost(String connectedHost);
String getConnectedHost();
void launchNewAgent(ServerResource resource) throws ConfigurationException;
+
+ boolean isConnectionTransfer();
+
+ void setConnectionTransfer(boolean connectionTransfer);
+
+ Integer getSslHandshakeTimeout();
}
diff --git a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
index 24a09ae2ac1..847d1bb2396 100644
--- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
+++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
@@ -155,6 +155,14 @@ public class AgentProperties{
*/
public static final Property CMDS_TIMEOUT = new Property<>("cmds.timeout", 7200);
+ /**
+ * The timeout (in seconds) for the snapshot merge operation, mainly used for classic volume snapshots and disk-only VM snapshots on file-based storage.
+ * This configuration is only considered if libvirt.events.enabled is also true.
+ * Data type: Integer.
+ * Default value: 259200
+ */
+ public static final Property QCOW2_DELTA_MERGE_TIMEOUT = new Property<>("qcow2.delta.merge.timeout", 60 * 60 * 72);
+
/**
* This parameter sets the VM migration speed (in mbps). The default value is -1,
* which means that the agent will try to guess the speed of the guest network and consume all possible bandwidth.
@@ -213,6 +221,15 @@ public class AgentProperties{
*/
public static final Property AGENT_HOOKS_LIBVIRT_VM_XML_TRANSFORMER_SCRIPT = new Property<>("agent.hooks.libvirt_vm_xml_transformer.script", "libvirt-vm-xml-transformer.groovy");
+ /**
+ * This property is used with the agent.hooks.basedir property to define the Libvirt VM XML transformer shell script.
+ * The shell script is used to execute the Libvirt VM XML transformer script.
+ * For more information see the agent.properties file.
+ * Data type: String.
+ * Default value: libvirt-vm-xml-transformer.sh
+ */
+ public static final Property AGENT_HOOKS_LIBVIRT_VM_XML_TRANSFORMER_SHELL_SCRIPT = new Property<>("agent.hooks.libvirt_vm_xml_transformer.shell_script", "libvirt-vm-xml-transformer.sh");
+
/**
* This property is used with the agent.hooks.basedir and agent.hooks.libvirt_vm_xml_transformer.script properties to define the Libvirt VM XML transformer method.
* Libvirt XML transformer hook does XML-to-XML transformation.
@@ -233,6 +250,15 @@ public class AgentProperties{
*/
public static final Property AGENT_HOOKS_LIBVIRT_VM_ON_START_SCRIPT = new Property<>("agent.hooks.libvirt_vm_on_start.script", "libvirt-vm-state-change.groovy");
+ /**
+ * This property is used with the agent.hooks.basedir property to define the Libvirt VM on start shell script.
+ * The shell script is used to execute the Libvirt VM on start script.
+ * For more information see the agent.properties file.
+ * Data type: String.
+ * Default value: libvirt-vm-state-change.sh
+ */
+ public static final Property AGENT_HOOKS_LIBVIRT_VM_ON_START_SHELL_SCRIPT = new Property<>("agent.hooks.libvirt_vm_on_start.shell_script", "libvirt-vm-state-change.sh");
+
/**
* This property is used with the agent.hooks.basedir and agent.hooks.libvirt_vm_on_start.script properties to define the Libvirt VM on start method.
* The hook is called right after Libvirt successfully launched the VM.
@@ -252,6 +278,15 @@ public class AgentProperties{
*/
public static final Property AGENT_HOOKS_LIBVIRT_VM_ON_STOP_SCRIPT = new Property<>("agent.hooks.libvirt_vm_on_stop.script", "libvirt-vm-state-change.groovy");
+ /**
+ * This property is used with the agent.hooks.basedir property to define the Libvirt VM on stop shell script.
+ * The shell script is used to execute the Libvirt VM on stop script.
+ * For more information see the agent.properties file.
+ * Data type: String.
+ * Default value: libvirt-vm-state-change.sh
+ */
+ public static final Property AGENT_HOOKS_LIBVIRT_VM_ON_STOP_SHELL_SCRIPT = new Property<>("agent.hooks.libvirt_vm_on_stop.shell_script", "libvirt-vm-state-change.sh");
+
/**
* This property is used with the agent.hooks.basedir and agent.hooks.libvirt_vm_on_stop.script properties to define the Libvirt VM on stop method.
* The hook is called right after libvirt successfully stopped the VM.
@@ -383,7 +418,7 @@ public class AgentProperties{
/**
* This param will set the CPU architecture for the domain to override what the management server would send.
* In case of arm64 (aarch64), this will change the machine type to 'virt' and add a SCSI and a USB controller in the domain XML.
- * Possible values: x86_64 | aarch64
+ * Possible values: x86_64 | aarch64 | s390x
* Data type: String.
* Default value: null (will set use the architecture of the VM's OS).
*/
@@ -516,6 +551,7 @@ public class AgentProperties{
/**
* The model of Watchdog timer to present to the Guest.
* For all models refer to the libvirt documentation.
+ * PLEASE NOTE: to disable the watchdogs definitions, use value: none
* Data type: String.
* Default value: i6300esb
*/
@@ -751,7 +787,7 @@ public class AgentProperties{
public static final Property IOTHREADS = new Property<>("iothreads", 1);
/**
- * Enable verbose mode for virt-v2v Instance Conversion from Vmware to KVM
+ * Enable verbose mode for virt-v2v Instance Conversion from VMware to KVM
* Data type: Boolean.
* Default value: false
*/
@@ -803,12 +839,44 @@ public class AgentProperties{
*/
public static final Property KEYSTORE_PASSPHRASE = new Property<>(KeyStoreUtils.KS_PASSPHRASE_PROPERTY, null, String.class);
+ /**
+ * Implicit host tags
+ * Data type: String.
+ * Default value: null
+ */
+ public static final Property HOST_TAGS = new Property<>("host.tags", null, String.class);
+
+ /**
+ * Timeout for SSL handshake in seconds
+ * Data type: Integer.
+ * Default value: null
+ */
+ public static final Property 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 INCREMENTAL_SNAPSHOT_TIMEOUT = new Property<>("incremental.snapshot.timeout", 10800);
+
+ /**
+ * Timeout (in seconds) to wait for the snapshot reversion to complete.
+ * */
+ public static final Property REVERT_SNAPSHOT_TIMEOUT = new Property<>("revert.snapshot.timeout", 10800);
+
+ /**
+ * If set to true, creates VMs as full clones of their templates on KVM hypervisor. Creates as linked clones otherwise.
+ * Data type: Boolean.
+ * Default value: false
+ */
+ public static final Property CREATE_FULL_CLONE = new Property<>("create.full.clone", false);
+
+
public static class Property {
private String name;
private T defaultValue;
private Class typeClass;
- Property(String name, T value) {
+ public Property(String name, T value) {
init(name, value);
}
diff --git a/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java b/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java
index ccd0d976e58..26f9d4b3d73 100644
--- a/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java
+++ b/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java
@@ -397,9 +397,8 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
}
public String authenticateConsoleAccess(String host, String port, String vmId, String sid, String ticket,
- Boolean isReauthentication, String sessionToken) {
-
- ConsoleAccessAuthenticationCommand cmd = new ConsoleAccessAuthenticationCommand(host, port, vmId, sid, ticket, sessionToken);
+ Boolean isReauthentication, String sessionToken, String clientAddress) {
+ ConsoleAccessAuthenticationCommand cmd = new ConsoleAccessAuthenticationCommand(host, port, vmId, sid, ticket, sessionToken, clientAddress);
cmd.setReauthenticating(isReauthentication);
ConsoleProxyAuthenticationResult result = new ConsoleProxyAuthenticationResult();
diff --git a/agent/src/test/java/com/cloud/agent/AgentShellTest.java b/agent/src/test/java/com/cloud/agent/AgentShellTest.java
index f7151779f58..d8def24a603 100644
--- a/agent/src/test/java/com/cloud/agent/AgentShellTest.java
+++ b/agent/src/test/java/com/cloud/agent/AgentShellTest.java
@@ -350,4 +350,23 @@ public class AgentShellTest {
Mockito.verify(agentShellSpy).setHosts(expected);
}
+
+ @Test
+ public void updateAndGetConnectedHost() {
+ String expected = "test";
+
+ AgentShell shell = new AgentShell();
+ shell.setHosts("test");
+ shell.getNextHost();
+ shell.updateConnectedHost("test");
+
+ Assert.assertEquals(expected, shell.getConnectedHost());
+ }
+
+ @Test
+ public void testGetSslHandshakeTimeout() {
+ Integer expected = 1;
+ agentPropertiesFileHandlerMocked.when(() -> AgentPropertiesFileHandler.getPropertyValue(Mockito.eq(AgentProperties.SSL_HANDSHAKE_TIMEOUT))).thenReturn(expected);
+ Assert.assertEquals(expected, agentShellSpy.getSslHandshakeTimeout());
+ }
}
diff --git a/agent/src/test/java/com/cloud/agent/AgentTest.java b/agent/src/test/java/com/cloud/agent/AgentTest.java
new file mode 100644
index 00000000000..65dc030ebd7
--- /dev/null
+++ b/agent/src/test/java/com/cloud/agent/AgentTest.java
@@ -0,0 +1,257 @@
+// 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.logging.log4j.Logger;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import com.cloud.resource.ServerResource;
+import com.cloud.utils.backoff.impl.ConstantTimeBackoff;
+import com.cloud.utils.nio.Link;
+import com.cloud.utils.nio.NioConnection;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AgentTest {
+ Agent agent;
+ private AgentShell shell;
+ private ServerResource serverResource;
+ private Logger logger;
+
+ @Before
+ public void setUp() throws ConfigurationException {
+ shell = mock(AgentShell.class);
+ serverResource = mock(ServerResource.class);
+ doReturn(true).when(serverResource).configure(any(), any());
+ doReturn(1).when(shell).getWorkers();
+ doReturn(1).when(shell).getPingRetries();
+ agent = new Agent(shell, 1, serverResource);
+ logger = mock(Logger.class);
+ ReflectionTestUtils.setField(agent, "logger", logger);
+ }
+
+ @Test
+ public void testGetLinkLogNullLinkReturnsEmptyString() {
+ Link link = null;
+ String result = agent.getLinkLog(link);
+ assertEquals("", result);
+ }
+
+ @Test
+ public void testGetLinkLogLinkWithTraceEnabledReturnsLinkLogWithHashCode() {
+ Link link = mock(Link.class);
+ InetSocketAddress socketAddress = new InetSocketAddress("192.168.1.100", 1111);
+ when(link.getSocketAddress()).thenReturn(socketAddress);
+ when(logger.isTraceEnabled()).thenReturn(true);
+
+ String result = agent.getLinkLog(link);
+ System.out.println(result);
+ assertTrue(result.startsWith(System.identityHashCode(link) + "-"));
+ assertTrue(result.contains("192.168.1.100"));
+ }
+
+ @Test
+ public void testGetAgentNameWhenServerResourceIsNull() {
+ ReflectionTestUtils.setField(agent, "serverResource", null);
+ assertEquals("Agent", agent.getAgentName());
+ }
+
+ @Test
+ public void testGetAgentNameWhenAppendAgentNameIsTrue() {
+ when(serverResource.isAppendAgentNameToLogs()).thenReturn(true);
+ when(serverResource.getName()).thenReturn("TestAgent");
+
+ String agentName = agent.getAgentName();
+ assertEquals("TestAgent", agentName);
+ }
+
+ @Test
+ public void testGetAgentNameWhenAppendAgentNameIsFalse() {
+ when(serverResource.isAppendAgentNameToLogs()).thenReturn(false);
+
+ String agentName = agent.getAgentName();
+ assertEquals("Agent", agentName);
+ }
+
+ @Test
+ public void testAgentInitialization() {
+ Runtime.getRuntime().removeShutdownHook(agent.shutdownThread);
+ when(shell.getPingRetries()).thenReturn(3);
+ when(shell.getWorkers()).thenReturn(5);
+ agent.setupShutdownHookAndInitExecutors();
+ assertNotNull(agent.selfTaskExecutor);
+ assertNotNull(agent.outRequestHandler);
+ assertNotNull(agent.requestHandler);
+ }
+
+ @Test
+ public void testAgentShutdownHookAdded() {
+ Runtime.getRuntime().removeShutdownHook(agent.shutdownThread);
+ agent.setupShutdownHookAndInitExecutors();
+ verify(logger).trace("Adding shutdown hook");
+ }
+
+ @Test
+ public void testGetResourceGuidValidGuidAndResourceName() {
+ when(shell.getGuid()).thenReturn("12345");
+ String result = agent.getResourceGuid();
+ assertTrue(result.startsWith("12345-" + ServerResource.class.getSimpleName()));
+ }
+
+ @Test
+ public void testGetZoneReturnsValidZone() {
+ when(shell.getZone()).thenReturn("ZoneA");
+ String result = agent.getZone();
+ assertEquals("ZoneA", result);
+ }
+
+ @Test
+ public void testGetPodReturnsValidPod() {
+ when(shell.getPod()).thenReturn("PodA");
+ String result = agent.getPod();
+ assertEquals("PodA", result);
+ }
+
+ @Test
+ public void testSetLinkAssignsLink() {
+ Link mockLink = mock(Link.class);
+ agent.setLink(mockLink);
+ assertEquals(mockLink, agent.link);
+ }
+
+ @Test
+ public void testGetResourceReturnsServerResource() {
+ ServerResource mockResource = mock(ServerResource.class);
+ ReflectionTestUtils.setField(agent, "serverResource", mockResource);
+ ServerResource result = agent.getResource();
+ assertSame(mockResource, result);
+ }
+
+ @Test
+ public void testGetResourceName() {
+ String result = agent.getResourceName();
+ assertTrue(result.startsWith(ServerResource.class.getSimpleName()));
+ }
+
+ @Test
+ public void testUpdateLastPingResponseTimeUpdatesCurrentTime() {
+ long beforeUpdate = System.currentTimeMillis();
+ agent.updateLastPingResponseTime();
+ long updatedTime = agent.lastPingResponseTime.get();
+ assertTrue(updatedTime >= beforeUpdate);
+ assertTrue(updatedTime <= System.currentTimeMillis());
+ }
+
+ @Test
+ public void testGetNextSequenceIncrementsSequence() {
+ long initialSequence = agent.getNextSequence();
+ long nextSequence = agent.getNextSequence();
+ assertEquals(initialSequence + 1, nextSequence);
+ long thirdSequence = agent.getNextSequence();
+ assertEquals(nextSequence + 1, thirdSequence);
+ }
+
+ @Test
+ public void testRegisterControlListenerAddsListener() {
+ IAgentControlListener listener = mock(IAgentControlListener.class);
+ agent.registerControlListener(listener);
+ assertTrue(agent.controlListeners.contains(listener));
+ }
+
+ @Test
+ public void testUnregisterControlListenerRemovesListener() {
+ IAgentControlListener listener = mock(IAgentControlListener.class);
+ agent.registerControlListener(listener);
+ assertTrue(agent.controlListeners.contains(listener));
+ agent.unregisterControlListener(listener);
+ assertFalse(agent.controlListeners.contains(listener));
+ }
+
+ @Test
+ public void testCloseAndTerminateLinkLinkIsNullDoesNothing() {
+ agent.closeAndTerminateLink(null);
+ }
+
+ @Test
+ public void testCloseAndTerminateLinkValidLinkCallsCloseAndTerminate() {
+ Link mockLink = mock(Link.class);
+ agent.closeAndTerminateLink(mockLink);
+ verify(mockLink).close();
+ verify(mockLink).terminated();
+ }
+
+ @Test
+ public void testStopAndCleanupConnectionConnectionIsNullDoesNothing() {
+ agent.connection = null;
+ agent.stopAndCleanupConnection(false);
+ }
+
+ @Test
+ public void testStopAndCleanupConnectionValidConnectionNoWaitStopsAndCleansUp() throws IOException {
+ NioConnection mockConnection = mock(NioConnection.class);
+ agent.connection = mockConnection;
+ agent.stopAndCleanupConnection(false);
+ verify(mockConnection).stop();
+ verify(mockConnection).cleanUp();
+ }
+
+ @Test
+ public void testStopAndCleanupConnectionCleanupThrowsIOExceptionLogsWarning() throws IOException {
+ NioConnection mockConnection = mock(NioConnection.class);
+ agent.connection = mockConnection;
+ doThrow(new IOException("Cleanup failed")).when(mockConnection).cleanUp();
+ agent.stopAndCleanupConnection(false);
+ verify(mockConnection).stop();
+ verify(logger).warn(eq("Fail to clean up old connection. {}"), any(IOException.class));
+ }
+
+ @Test
+ public void testStopAndCleanupConnectionValidConnectionWaitForStopWaitsForStartupToStop() throws IOException {
+ NioConnection mockConnection = mock(NioConnection.class);
+ ConstantTimeBackoff mockBackoff = mock(ConstantTimeBackoff.class);
+ mockBackoff.setTimeToWait(0);
+ agent.connection = mockConnection;
+ when(shell.getBackoffAlgorithm()).thenReturn(mockBackoff);
+ when(mockConnection.isStartup()).thenReturn(true, true, false);
+ agent.stopAndCleanupConnection(true);
+ verify(mockConnection).stop();
+ verify(mockConnection).cleanUp();
+ verify(mockBackoff, times(3)).waitBeforeRetry();
+ }
+}
diff --git a/api/pom.xml b/api/pom.xml
index 32897725e0c..ec68e24c7e5 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -24,7 +24,7 @@
org.apache.cloudstack
cloudstack
- 4.20.0.0-SNAPSHOT
+ 4.21.0.0-SNAPSHOT
diff --git a/api/src/main/java/com/cloud/agent/api/Command.java b/api/src/main/java/com/cloud/agent/api/Command.java
index eb979c0060b..c4e99cb4170 100644
--- a/api/src/main/java/com/cloud/agent/api/Command.java
+++ b/api/src/main/java/com/cloud/agent/api/Command.java
@@ -19,9 +19,10 @@ package com.cloud.agent.api;
import java.util.HashMap;
import java.util.Map;
-import com.cloud.agent.api.LogLevel.Log4jLevel;
-import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import com.cloud.agent.api.LogLevel.Log4jLevel;
/**
* implemented by classes that extends the Command class. Command specifies
@@ -35,6 +36,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 +60,8 @@ public abstract class Command {
protected Map contextMap = new HashMap();
private int wait; //in second
private boolean bypassHostMaintenance = false;
+ private transient long requestSequence = 0L;
+ protected Map> externalDetails;
protected Command() {
this.wait = 0;
@@ -82,6 +102,10 @@ public abstract class Command {
return contextMap.get(name);
}
+ public Map getContextMap() {
+ return contextMap;
+ }
+
public boolean allowCaching() {
return true;
}
@@ -94,6 +118,26 @@ 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;
+ }
+
+ public void setExternalDetails(Map> externalDetails) {
+ this.externalDetails = externalDetails;
+ }
+
+ public Map> getExternalDetails() {
+ return externalDetails;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/api/src/main/java/com/cloud/agent/api/VgpuTypesInfo.java b/api/src/main/java/com/cloud/agent/api/VgpuTypesInfo.java
index 85ffc189820..5515a9c48bc 100644
--- a/api/src/main/java/com/cloud/agent/api/VgpuTypesInfo.java
+++ b/api/src/main/java/com/cloud/agent/api/VgpuTypesInfo.java
@@ -15,10 +15,24 @@
// specific language governing permissions and limitations
// under the License.
package com.cloud.agent.api;
+
+import org.apache.cloudstack.gpu.GpuDevice;
+
public class VgpuTypesInfo {
+ private boolean passthroughEnabled = true;
+ private GpuDevice.DeviceType deviceType;
+ private String parentBusAddress;
+ private String busAddress;
+ private String numaNode;
+ private String pciRoot;
+ private String deviceId;
+ private String deviceName;
+ private String vendorId;
+ private String vendorName;
private String modelName;
private String groupName;
+ private String vmName;
private Long maxHeads;
private Long videoRam;
private Long maxResolutionX;
@@ -26,6 +40,7 @@ public class VgpuTypesInfo {
private Long maxVgpuPerGpu;
private Long remainingCapacity;
private Long maxCapacity;
+ private boolean display = false;
public String getModelName() {
return modelName;
@@ -39,22 +54,42 @@ public class VgpuTypesInfo {
return videoRam;
}
+ public void setVideoRam(Long videoRam) {
+ this.videoRam = videoRam;
+ }
+
public Long getMaxHeads() {
return maxHeads;
}
+ public void setMaxHeads(Long maxHeads) {
+ this.maxHeads = maxHeads;
+ }
+
public Long getMaxResolutionX() {
return maxResolutionX;
}
+ public void setMaxResolutionX(Long maxResolutionX) {
+ this.maxResolutionX = maxResolutionX;
+ }
+
public Long getMaxResolutionY() {
return maxResolutionY;
}
+ public void setMaxResolutionY(Long maxResolutionY) {
+ this.maxResolutionY = maxResolutionY;
+ }
+
public Long getMaxVpuPerGpu() {
return maxVgpuPerGpu;
}
+ public void setMaxVgpuPerGpu(Long maxVgpuPerGpu) {
+ this.maxVgpuPerGpu = maxVgpuPerGpu;
+ }
+
public Long getRemainingCapacity() {
return remainingCapacity;
}
@@ -71,8 +106,133 @@ public class VgpuTypesInfo {
this.maxCapacity = maxCapacity;
}
- public VgpuTypesInfo(String groupName, String modelName, Long videoRam, Long maxHeads, Long maxResolutionX, Long maxResolutionY, Long maxVgpuPerGpu,
- Long remainingCapacity, Long maxCapacity) {
+ public boolean isPassthroughEnabled() {
+ return passthroughEnabled;
+ }
+
+ public void setPassthroughEnabled(boolean passthroughEnabled) {
+ this.passthroughEnabled = passthroughEnabled;
+ }
+
+ public GpuDevice.DeviceType getDeviceType() {
+ return deviceType;
+ }
+
+ public void setDeviceType(GpuDevice.DeviceType deviceType) {
+ this.deviceType = deviceType;
+ }
+
+ public String getParentBusAddress() {
+ return parentBusAddress;
+ }
+
+ public void setParentBusAddress(String parentBusAddress) {
+ this.parentBusAddress = parentBusAddress;
+ }
+
+ public String getBusAddress() {
+ return busAddress;
+ }
+
+ public void setBusAddress(String busAddress) {
+ this.busAddress = busAddress;
+ }
+
+ public String getNumaNode() {
+ return numaNode;
+ }
+
+ public void setNumaNode(String numaNode) {
+ this.numaNode = numaNode;
+ }
+
+ public String getPciRoot() {
+ return pciRoot;
+ }
+
+ public void setPciRoot(String pciRoot) {
+ this.pciRoot = pciRoot;
+ }
+
+ public String getDeviceId() {
+ return deviceId;
+ }
+
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ public String getDeviceName() {
+ return deviceName;
+ }
+
+ public void setDeviceName(String deviceName) {
+ this.deviceName = deviceName;
+ }
+
+ public String getVendorId() {
+ return vendorId;
+ }
+
+ public void setVendorId(String vendorId) {
+ this.vendorId = vendorId;
+ }
+
+ public String getVendorName() {
+ return vendorName;
+ }
+
+ public void setVendorName(String vendorName) {
+ this.vendorName = vendorName;
+ }
+
+ public String getVmName() {
+ return vmName;
+ }
+
+ public void setVmName(String vmName) {
+ this.vmName = vmName;
+ }
+
+ public boolean isDisplay() {
+ return display;
+ }
+
+ public void setDisplay(boolean display) {
+ this.display = display;
+ }
+
+ public VgpuTypesInfo(GpuDevice.DeviceType deviceType, String groupName, String modelName, String busAddress,
+ String vendorId, String vendorName, String deviceId, String deviceName, String numaNode, String pciRoot
+ ) {
+ this.deviceType = deviceType;
+ this.groupName = groupName;
+ this.modelName = modelName;
+ this.busAddress = busAddress;
+ this.deviceId = deviceId;
+ this.deviceName = deviceName;
+ this.vendorId = vendorId;
+ this.vendorName = vendorName;
+ this.numaNode = numaNode;
+ this.pciRoot = pciRoot;
+ }
+
+ public VgpuTypesInfo(GpuDevice.DeviceType deviceType, String groupName, String modelName, String busAddress,
+ String vendorId, String vendorName, String deviceId, String deviceName
+ ) {
+ this.deviceType = deviceType;
+ this.groupName = groupName;
+ this.modelName = modelName;
+ this.busAddress = busAddress;
+ this.deviceId = deviceId;
+ this.deviceName = deviceName;
+ this.vendorId = vendorId;
+ this.vendorName = vendorName;
+ }
+
+ public VgpuTypesInfo(String groupName, String modelName, Long videoRam, Long maxHeads, Long maxResolutionX,
+ Long maxResolutionY, Long maxVgpuPerGpu, Long remainingCapacity, Long maxCapacity
+ ) {
this.groupName = groupName;
this.modelName = modelName;
this.videoRam = videoRam;
diff --git a/api/src/main/java/com/cloud/agent/api/to/BucketTO.java b/api/src/main/java/com/cloud/agent/api/to/BucketTO.java
new file mode 100644
index 00000000000..f7e4bfea80f
--- /dev/null
+++ b/api/src/main/java/com/cloud/agent/api/to/BucketTO.java
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent.api.to;
+
+import org.apache.cloudstack.storage.object.Bucket;
+
+public final class BucketTO {
+
+ private String name;
+
+ private String accessKey;
+
+ private String secretKey;
+
+ public BucketTO(Bucket bucket) {
+ this.name = bucket.getName();
+ this.accessKey = bucket.getAccessKey();
+ this.secretKey = bucket.getSecretKey();
+ }
+
+ public BucketTO(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getAccessKey() {
+ return this.accessKey;
+ }
+
+ public String getSecretKey() {
+ return this.secretKey;
+ }
+}
diff --git a/api/src/main/java/com/cloud/agent/api/to/DiskTO.java b/api/src/main/java/com/cloud/agent/api/to/DiskTO.java
index d22df2df172..5664de79091 100644
--- a/api/src/main/java/com/cloud/agent/api/to/DiskTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/DiskTO.java
@@ -46,7 +46,7 @@ public class DiskTO {
private Long diskSeq;
private String path;
private Volume.Type type;
- private Map _details;
+ private Map details;
public DiskTO() {
@@ -92,10 +92,10 @@ public class DiskTO {
}
public void setDetails(Map details) {
- _details = details;
+ this.details = details;
}
public Map getDetails() {
- return _details;
+ return details;
}
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/FirewallRuleTO.java b/api/src/main/java/com/cloud/agent/api/to/FirewallRuleTO.java
index d08884d1cbe..69350815be3 100644
--- a/api/src/main/java/com/cloud/agent/api/to/FirewallRuleTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/FirewallRuleTO.java
@@ -47,7 +47,7 @@ public class FirewallRuleTO implements InternalIdentity {
int[] srcPortRange;
boolean revoked;
boolean alreadyAdded;
- private List sourceCidrList;
+ protected List sourceCidrList;
private List destCidrList;
FirewallRule.Purpose purpose;
private Integer icmpType;
@@ -155,9 +155,7 @@ public class FirewallRuleTO implements InternalIdentity {
rule.getIcmpType(),
rule.getIcmpCode());
this.trafficType = trafficType;
- if (FirewallRule.Purpose.Ipv6Firewall.equals(purpose)) {
- this.destCidrList = rule.getDestinationCidrList();
- }
+ this.destCidrList = rule.getDestinationCidrList();
}
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, FirewallRule.Purpose purpose, FirewallRule.TrafficType trafficType,
diff --git a/api/src/main/java/com/cloud/agent/api/to/GPUDeviceTO.java b/api/src/main/java/com/cloud/agent/api/to/GPUDeviceTO.java
index 4afe080477b..6e9cee06dd3 100644
--- a/api/src/main/java/com/cloud/agent/api/to/GPUDeviceTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/GPUDeviceTO.java
@@ -16,7 +16,9 @@
// under the License.
package com.cloud.agent.api.to;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import com.cloud.agent.api.VgpuTypesInfo;
@@ -24,9 +26,23 @@ public class GPUDeviceTO {
private String gpuGroup;
private String vgpuType;
+ private int gpuCount;
private HashMap> groupDetails = new HashMap>();
+ private List gpuDevices = new ArrayList<>();
- public GPUDeviceTO( String gpuGroup, String vgpuType, HashMap> groupDetails) {
+ public GPUDeviceTO(String gpuGroup, String vgpuType, int gpuCount,
+ HashMap> groupDetails,
+ List gpuDevices) {
+ this.gpuGroup = gpuGroup;
+ this.vgpuType = vgpuType;
+ this.groupDetails = groupDetails;
+ this.gpuCount = gpuCount;
+ this.gpuDevices = gpuDevices;
+
+ }
+
+ public GPUDeviceTO(String gpuGroup, String vgpuType,
+ HashMap> groupDetails) {
this.gpuGroup = gpuGroup;
this.vgpuType = vgpuType;
this.groupDetails = groupDetails;
@@ -48,6 +64,14 @@ public class GPUDeviceTO {
this.vgpuType = vgpuType;
}
+ public int getGpuCount() {
+ return gpuCount;
+ }
+
+ public void setGpuCount(int gpuCount) {
+ this.gpuCount = gpuCount;
+ }
+
public HashMap> getGroupDetails() {
return groupDetails;
}
@@ -56,4 +80,11 @@ public class GPUDeviceTO {
this.groupDetails = groupDetails;
}
+ public List getGpuDevices() {
+ return gpuDevices;
+ }
+
+ public void setGpuDevices(List gpuDevices) {
+ this.gpuDevices = gpuDevices;
+ }
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java b/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java
index 966d24886fe..f395f26aeed 100644
--- a/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java
@@ -374,13 +374,15 @@ public class LoadBalancerTO {
public static class CounterTO implements Serializable {
private static final long serialVersionUID = 2L;
private final Long id;
+ private final String uuid;
private final String name;
private final Counter.Source source;
private final String value;
private final String provider;
- public CounterTO(Long id, String name, Counter.Source source, String value, String provider) {
+ public CounterTO(Long id, String uuid, String name, Counter.Source source, String value, String provider) {
this.id = id;
+ this.uuid = uuid;
this.name = name;
this.source = source;
this.value = value;
@@ -391,6 +393,10 @@ public class LoadBalancerTO {
return id;
}
+ public String getUuid() {
+ return uuid;
+ }
+
public String getName() {
return name;
}
@@ -411,12 +417,14 @@ public class LoadBalancerTO {
public static class ConditionTO implements Serializable {
private static final long serialVersionUID = 2L;
private final Long id;
+ private final String uuid;
private final long threshold;
private final Condition.Operator relationalOperator;
private final CounterTO counter;
- public ConditionTO(Long id, long threshold, Condition.Operator relationalOperator, CounterTO counter) {
+ public ConditionTO(Long id, String uuid, long threshold, Condition.Operator relationalOperator, CounterTO counter) {
this.id = id;
+ this.uuid = uuid;
this.threshold = threshold;
this.relationalOperator = relationalOperator;
this.counter = counter;
@@ -426,6 +434,10 @@ public class LoadBalancerTO {
return id;
}
+ public String getUuid() {
+ return uuid;
+ }
+
public long getThreshold() {
return threshold;
}
@@ -442,6 +454,7 @@ public class LoadBalancerTO {
public static class AutoScalePolicyTO implements Serializable {
private static final long serialVersionUID = 2L;
private final long id;
+ private final String uuid;
private final int duration;
private final int quietTime;
private final Date lastQuietTime;
@@ -449,8 +462,9 @@ public class LoadBalancerTO {
boolean revoked;
private final List conditions;
- public AutoScalePolicyTO(long id, int duration, int quietTime, Date lastQuietTime, AutoScalePolicy.Action action, List conditions, boolean revoked) {
+ public AutoScalePolicyTO(long id, String uuid, int duration, int quietTime, Date lastQuietTime, AutoScalePolicy.Action action, List conditions, boolean revoked) {
this.id = id;
+ this.uuid = uuid;
this.duration = duration;
this.quietTime = quietTime;
this.lastQuietTime = lastQuietTime;
@@ -463,6 +477,10 @@ public class LoadBalancerTO {
return id;
}
+ public String getUuid() {
+ return uuid;
+ }
+
public int getDuration() {
return duration;
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/NetworkTO.java b/api/src/main/java/com/cloud/agent/api/to/NetworkTO.java
index bd08ce81101..d65ec0e3daa 100644
--- a/api/src/main/java/com/cloud/agent/api/to/NetworkTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/NetworkTO.java
@@ -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) {
diff --git a/api/src/main/java/com/cloud/agent/api/to/NfsTO.java b/api/src/main/java/com/cloud/agent/api/to/NfsTO.java
index 0f6511e8311..eeddbf649a7 100644
--- a/api/src/main/java/com/cloud/agent/api/to/NfsTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/NfsTO.java
@@ -17,6 +17,7 @@
package com.cloud.agent.api.to;
import com.cloud.storage.DataStoreRole;
+import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
public class NfsTO implements DataStoreTO {
@@ -41,6 +42,13 @@ public class NfsTO implements DataStoreTO {
}
+ @Override
+ public String toString() {
+ return String.format("NfsTO %s",
+ ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
+ this, "uuid", "_url", "_role", "nfsVersion"));
+ }
+
@Override
public String getUrl() {
return _url;
diff --git a/api/src/main/java/com/cloud/agent/api/to/NicTO.java b/api/src/main/java/com/cloud/agent/api/to/NicTO.java
index 573363c04fb..ca95fcfd679 100644
--- a/api/src/main/java/com/cloud/agent/api/to/NicTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/NicTO.java
@@ -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();
diff --git a/api/src/main/java/com/cloud/agent/api/to/PortForwardingRuleTO.java b/api/src/main/java/com/cloud/agent/api/to/PortForwardingRuleTO.java
index 76d6d952814..91f337c5f55 100644
--- a/api/src/main/java/com/cloud/agent/api/to/PortForwardingRuleTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/PortForwardingRuleTO.java
@@ -19,6 +19,7 @@ package com.cloud.agent.api.to;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.utils.net.NetUtils;
+import org.apache.commons.lang3.StringUtils;
/**
* PortForwardingRuleTO specifies one port forwarding rule.
@@ -37,6 +38,7 @@ public class PortForwardingRuleTO extends FirewallRuleTO {
super(rule, srcVlanTag, srcIp);
this.dstIp = rule.getDestinationIpAddress().addr();
this.dstPortRange = new int[] {rule.getDestinationPortStart(), rule.getDestinationPortEnd()};
+ this.sourceCidrList = rule.getSourceCidrList();
}
public PortForwardingRuleTO(long id, String srcIp, int srcPortStart, int srcPortEnd, String dstIp, int dstPortStart, int dstPortEnd, String protocol,
@@ -58,4 +60,11 @@ public class PortForwardingRuleTO extends FirewallRuleTO {
return NetUtils.portRangeToString(dstPortRange);
}
+ public String getSourceCidrListAsString() {
+ if (sourceCidrList != null) {
+ return StringUtils.join(sourceCidrList, ",");
+ }
+ return null;
+ }
+
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java
index 6e7aa8b21e2..18737c584b3 100644
--- a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java
@@ -18,40 +18,41 @@
*/
package com.cloud.agent.api.to;
+import java.io.Serializable;
+
import com.cloud.agent.api.LogLevel;
import com.cloud.hypervisor.Hypervisor;
-import java.io.Serializable;
-
public class RemoteInstanceTO implements Serializable {
private Hypervisor.HypervisorType hypervisorType;
- private String hostName;
private String instanceName;
+ private String instancePath;
- // Vmware Remote Instances parameters
+ // VMware Remote Instances parameters (required for exporting OVA through ovftool)
// TODO: cloud.agent.transport.Request#getCommands() cannot handle gsoc decode for polymorphic classes
private String vcenterUsername;
@LogLevel(LogLevel.Log4jLevel.Off)
private String vcenterPassword;
private String vcenterHost;
private String datacenterName;
- private String clusterName;
public RemoteInstanceTO() {
}
- public RemoteInstanceTO(String hostName, String instanceName, String vcenterHost,
- String datacenterName, String clusterName,
- String vcenterUsername, String vcenterPassword) {
+ public RemoteInstanceTO(String instanceName) {
this.hypervisorType = Hypervisor.HypervisorType.VMware;
- this.hostName = hostName;
this.instanceName = instanceName;
+ }
+
+ public RemoteInstanceTO(String instanceName, String instancePath, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) {
+ this.hypervisorType = Hypervisor.HypervisorType.VMware;
+ this.instanceName = instanceName;
+ this.instancePath = instancePath;
this.vcenterHost = vcenterHost;
- this.datacenterName = datacenterName;
- this.clusterName = clusterName;
this.vcenterUsername = vcenterUsername;
this.vcenterPassword = vcenterPassword;
+ this.datacenterName = datacenterName;
}
public Hypervisor.HypervisorType getHypervisorType() {
@@ -62,8 +63,8 @@ public class RemoteInstanceTO implements Serializable {
return this.instanceName;
}
- public String getHostName() {
- return this.hostName;
+ public String getInstancePath() {
+ return this.instancePath;
}
public String getVcenterUsername() {
@@ -81,8 +82,4 @@ public class RemoteInstanceTO implements Serializable {
public String getDatacenterName() {
return datacenterName;
}
-
- public String getClusterName() {
- return clusterName;
- }
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/S3TO.java b/api/src/main/java/com/cloud/agent/api/to/S3TO.java
index 233238cf793..936f8168b1e 100644
--- a/api/src/main/java/com/cloud/agent/api/to/S3TO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/S3TO.java
@@ -22,6 +22,7 @@ import com.cloud.agent.api.LogLevel;
import com.cloud.agent.api.LogLevel.Log4jLevel;
import com.cloud.storage.DataStoreRole;
import com.cloud.utils.storage.S3.ClientOptions;
+import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
public final class S3TO implements ClientOptions, DataStoreTO {
@@ -68,6 +69,13 @@ public final class S3TO implements ClientOptions, DataStoreTO {
}
+ @Override
+ public String toString() {
+ return String.format("S3TO %s",
+ ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
+ this, "id", "uuid", "bucketName"));
+ }
+
public Long getId() {
return this.id;
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/StorageFilerTO.java b/api/src/main/java/com/cloud/agent/api/to/StorageFilerTO.java
index e361e7a141f..cbdb7922eb4 100644
--- a/api/src/main/java/com/cloud/agent/api/to/StorageFilerTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/StorageFilerTO.java
@@ -19,6 +19,7 @@ package com.cloud.agent.api.to;
import com.cloud.agent.api.LogLevel;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StoragePool;
+import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
public class StorageFilerTO {
long id;
@@ -73,6 +74,6 @@ public class StorageFilerTO {
@Override
public String toString() {
- return new StringBuilder("Pool[").append(id).append("|").append(host).append(":").append(port).append("|").append(path).append("]").toString();
+ return String.format("Pool %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "uuid", "host", "port", "path"));
}
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/SwiftTO.java b/api/src/main/java/com/cloud/agent/api/to/SwiftTO.java
index b89dfea40e0..14038566fbd 100644
--- a/api/src/main/java/com/cloud/agent/api/to/SwiftTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/SwiftTO.java
@@ -18,6 +18,7 @@ package com.cloud.agent.api.to;
import com.cloud.storage.DataStoreRole;
import com.cloud.utils.SwiftUtil;
+import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
public class SwiftTO implements DataStoreTO, SwiftUtil.SwiftClientCfg {
Long id;
@@ -41,6 +42,13 @@ public class SwiftTO implements DataStoreTO, SwiftUtil.SwiftClientCfg {
this.storagePolicy = storagePolicy;
}
+ @Override
+ public String toString() {
+ return String.format("SwiftTO %s",
+ ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
+ this, "id", "account", "userName"));
+ }
+
public Long getId() {
return id;
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
index b4f4619be9a..cffb9874080 100644
--- a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
@@ -19,20 +19,22 @@ package com.cloud.agent.api.to;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
+import java.util.stream.Collectors;
import com.cloud.agent.api.LogLevel;
import com.cloud.network.element.NetworkElement;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
+import com.cloud.vm.VmDetailConstants;
public class VirtualMachineTO {
private long id;
private String name;
private BootloaderType bootloader;
private VirtualMachine.State state;
- Type type;
- int cpus;
+ private Type type;
+ private int cpus;
/**
'speed' is still here since 4.0.X/4.1.X management servers do not support
@@ -43,47 +45,50 @@ public class VirtualMachineTO {
So this is here for backwards compatibility with 4.0.X/4.1.X management servers
and newer agents.
*/
- Integer speed;
- Integer minSpeed;
- Integer maxSpeed;
+ private Integer speed;
+ private Integer minSpeed;
+ private Integer maxSpeed;
- long minRam;
- long maxRam;
- String hostName;
- String arch;
- String os;
- String platformEmulator;
- String bootArgs;
- String[] bootupScripts;
- boolean enableHA;
- boolean limitCpuUse;
- boolean enableDynamicallyScaleVm;
+ private long minRam;
+ private long maxRam;
+ private String hostName;
+ private String arch;
+ private String os;
+ private String platformEmulator;
+ private String bootArgs;
+ private String[] bootupScripts;
+ private boolean enableHA;
+ private boolean limitCpuUse;
+ private boolean enableDynamicallyScaleVm;
@LogLevel(LogLevel.Log4jLevel.Off)
- String vncPassword;
- String vncAddr;
- Map params;
- String uuid;
- String bootType;
- String bootMode;
- boolean enterHardwareSetup;
+ private String vncPassword;
+ private String vncAddr;
+ private Map details;
+ private Map params;
+ private String uuid;
+ private String bootType;
+ private String bootMode;
+ private boolean enterHardwareSetup;
- DiskTO[] disks;
- NicTO[] nics;
- GPUDeviceTO gpuDevice;
- Integer vcpuMaxLimit;
- List vmData = null;
+ private DiskTO[] disks;
+ private NicTO[] nics;
+ private GPUDeviceTO gpuDevice;
+ private Integer vcpuMaxLimit;
+ private List vmData = null;
- String configDriveLabel = null;
- String configDriveIsoRootFolder = null;
- String configDriveIsoFile = null;
- NetworkElement.Location configDriveLocation = NetworkElement.Location.SECONDARY;
+ private String configDriveLabel = null;
+ private String configDriveIsoRootFolder = null;
+ private String configDriveIsoFile = null;
+ private NetworkElement.Location configDriveLocation = NetworkElement.Location.SECONDARY;
- Double cpuQuotaPercentage = null;
+ private Double cpuQuotaPercentage = null;
- Map guestOsDetails = new HashMap();
- Map extraConfig = new HashMap<>();
- Map networkIdToNetworkNameMap = new HashMap<>();
- DeployAsIsInfoTO deployAsIsInfo;
+ private Map guestOsDetails = new HashMap();
+ private Map extraConfig = new HashMap<>();
+ private Map networkIdToNetworkNameMap = new HashMap<>();
+ private DeployAsIsInfoTO deployAsIsInfo;
+ private String metadataManufacturer;
+ private String metadataProductName;
public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader,
String os, boolean enableHA, boolean limitCpuUse, String vncPassword) {
@@ -189,7 +194,11 @@ public class VirtualMachineTO {
return maxSpeed;
}
- public boolean getLimitCpuUse() {
+ public boolean isEnableHA() {
+ return enableHA;
+ }
+
+ public boolean isLimitCpuUse() {
return limitCpuUse;
}
@@ -254,6 +263,10 @@ public class VirtualMachineTO {
this.bootupScripts = bootupScripts;
}
+ public void setEnableHA(boolean enableHA) {
+ this.enableHA = enableHA;
+ }
+
public DiskTO[] getDisks() {
return disks;
}
@@ -287,11 +300,11 @@ public class VirtualMachineTO {
}
public Map getDetails() {
- return params;
+ return details;
}
public void setDetails(Map params) {
- this.params = params;
+ this.details = params;
}
public String getUuid() {
@@ -429,8 +442,72 @@ public class VirtualMachineTO {
this.deployAsIsInfo = deployAsIsInfo;
}
+ public void setSpeed(Integer speed) {
+ this.speed = speed;
+ }
+
+ public void setMinSpeed(Integer minSpeed) {
+ this.minSpeed = minSpeed;
+ }
+
+ public void setMaxSpeed(Integer maxSpeed) {
+ this.maxSpeed = maxSpeed;
+ }
+
+ public void setMinRam(long minRam) {
+ this.minRam = minRam;
+ }
+
+ public void setMaxRam(long maxRam) {
+ this.maxRam = maxRam;
+ }
+
+ public void setLimitCpuUse(boolean limitCpuUse) {
+ this.limitCpuUse = limitCpuUse;
+ }
+
+ public Map getParams() {
+ return params;
+ }
+
+ public void setParams(Map params) {
+ this.params = params;
+ }
+
+ public void setExtraConfig(Map extraConfig) {
+ this.extraConfig = extraConfig;
+ }
+
+ public String getMetadataManufacturer() {
+ return metadataManufacturer;
+ }
+
+ public void setMetadataManufacturer(String metadataManufacturer) {
+ this.metadataManufacturer = metadataManufacturer;
+ }
+
+ public String getMetadataProductName() {
+ return metadataProductName;
+ }
+
+ public void setMetadataProductName(String metadataProductName) {
+ this.metadataProductName = metadataProductName;
+ }
+
@Override
public String toString() {
return String.format("VM {id: \"%s\", name: \"%s\", uuid: \"%s\", type: \"%s\"}", id, name, uuid, type);
}
+
+ public Map getExternalDetails() {
+ if (details == null) {
+ return new HashMap<>();
+ }
+ return details.entrySet().stream()
+ .filter(entry -> entry.getKey().startsWith(VmDetailConstants.EXTERNAL_DETAIL_PREFIX))
+ .collect(Collectors.toMap(
+ entry -> entry.getKey().substring(VmDetailConstants.EXTERNAL_DETAIL_PREFIX.length()),
+ Map.Entry::getValue
+ ));
+ }
}
diff --git a/api/src/main/java/com/cloud/bgp/ASNumber.java b/api/src/main/java/com/cloud/bgp/ASNumber.java
new file mode 100644
index 00000000000..b0e5394df75
--- /dev/null
+++ b/api/src/main/java/com/cloud/bgp/ASNumber.java
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.bgp;
+
+import org.apache.cloudstack.acl.InfrastructureEntity;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+import java.util.Date;
+
+public interface ASNumber extends InfrastructureEntity, InternalIdentity, Identity {
+
+ Long getAccountId();
+ Long getDomainId();
+ long getAsNumber();
+ long getAsNumberRangeId();
+ long getDataCenterId();
+ Date getAllocatedTime();
+ boolean isAllocated();
+ Long getNetworkId();
+ Long getVpcId();
+ Date getCreated();
+ Date getRemoved();
+}
diff --git a/api/src/main/java/com/cloud/bgp/ASNumberRange.java b/api/src/main/java/com/cloud/bgp/ASNumberRange.java
new file mode 100644
index 00000000000..ae877ee60db
--- /dev/null
+++ b/api/src/main/java/com/cloud/bgp/ASNumberRange.java
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.bgp;
+
+import org.apache.cloudstack.acl.InfrastructureEntity;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+import java.util.Date;
+
+public interface ASNumberRange extends InfrastructureEntity, InternalIdentity, Identity {
+
+ long getStartASNumber();
+ long getEndASNumber();
+ long getDataCenterId();
+ Date getCreated();
+}
diff --git a/api/src/main/java/com/cloud/bgp/BGPService.java b/api/src/main/java/com/cloud/bgp/BGPService.java
new file mode 100644
index 00000000000..61d149f2847
--- /dev/null
+++ b/api/src/main/java/com/cloud/bgp/BGPService.java
@@ -0,0 +1,44 @@
+// 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.bgp;
+
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.Network;
+import com.cloud.network.vpc.Vpc;
+import com.cloud.utils.Pair;
+import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
+import org.apache.cloudstack.network.BgpPeer;
+
+import java.util.List;
+
+public interface BGPService {
+
+ ASNumberRange createASNumberRange(long zoneId, long startASNumber, long endASNumber);
+ List listASNumberRanges(Long zoneId);
+ Pair, Integer> listASNumbers(ListASNumbersCmd cmd);
+ boolean allocateASNumber(long zoneId, Long asNumber, Long networkId, Long vpcId);
+ Pair releaseASNumber(long zoneId, long asNumber, boolean isReleaseNetworkDestroy);
+ boolean deleteASRange(long id);
+
+ boolean applyBgpPeers(Network network, boolean continueOnError) throws ResourceUnavailableException;
+
+ boolean applyBgpPeers(Vpc vpc, boolean continueOnError) throws ResourceUnavailableException;
+
+ List extends BgpPeer> getBgpPeersForNetwork(Network network);
+
+ List extends BgpPeer> getBgpPeersForVpc(Vpc vpc);
+}
diff --git a/api/src/main/java/com/cloud/capacity/Capacity.java b/api/src/main/java/com/cloud/capacity/Capacity.java
index a4e2c2a7f05..4e584b18fee 100644
--- a/api/src/main/java/com/cloud/capacity/Capacity.java
+++ b/api/src/main/java/com/cloud/capacity/Capacity.java
@@ -34,13 +34,17 @@ public interface Capacity extends InternalIdentity, Identity {
public static final short CAPACITY_TYPE_LOCAL_STORAGE = 9;
public static final short CAPACITY_TYPE_VIRTUAL_NETWORK_IPV6_SUBNET = 10;
public static final short CAPACITY_TYPE_GPU = 19;
+ public static final short CAPACITY_TYPE_OBJECT_STORAGE = 20;
+ public static final short CAPACITY_TYPE_BACKUP_STORAGE = 21;
public static final short CAPACITY_TYPE_CPU_CORE = 90;
public static final List STORAGE_CAPACITY_TYPES = List.of(CAPACITY_TYPE_STORAGE,
CAPACITY_TYPE_STORAGE_ALLOCATED,
CAPACITY_TYPE_SECONDARY_STORAGE,
- CAPACITY_TYPE_LOCAL_STORAGE);
+ CAPACITY_TYPE_LOCAL_STORAGE,
+ CAPACITY_TYPE_BACKUP_STORAGE,
+ CAPACITY_TYPE_OBJECT_STORAGE);
public Long getHostOrPoolId();
diff --git a/api/src/main/java/com/cloud/configuration/ConfigurationService.java b/api/src/main/java/com/cloud/configuration/ConfigurationService.java
index 97d4b42974b..32e31519ea7 100644
--- a/api/src/main/java/com/cloud/configuration/ConfigurationService.java
+++ b/api/src/main/java/com/cloud/configuration/ConfigurationService.java
@@ -17,7 +17,11 @@
package com.cloud.configuration;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import com.cloud.network.Network;
+import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd;
import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
import org.apache.cloudstack.api.command.admin.network.CreateGuestNetworkIpv6PrefixCmd;
@@ -201,11 +205,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 storageAccessGroups);
/**
* Creates a mutual exclusive IP range in the pod with same gateway, netmask.
@@ -372,4 +377,16 @@ public interface ConfigurationService {
List extends PortableIp> listPortableIps(long id);
Boolean isAccountAllowedToCreateOfferingsWithTags(IsAccountAllowedToCreateOfferingsWithTagsCmd cmd);
+
+ public static final Map ProviderDetailKeyMap = Map.of(
+ Network.Provider.Nsx.getName(), ApiConstants.NSX_DETAIL_KEY,
+ Network.Provider.Netris.getName(), ApiConstants.NETRIS_DETAIL_KEY
+ );
+
+ public static boolean IsIpRangeForProvider(Network.Provider provider) {
+ if (Objects.isNull(provider)) {
+ return false;
+ }
+ return ProviderDetailKeyMap.containsKey(provider.getName());
+ }
}
diff --git a/api/src/main/java/com/cloud/configuration/Resource.java b/api/src/main/java/com/cloud/configuration/Resource.java
index bf8fca9d905..97be7f9d64c 100644
--- a/api/src/main/java/com/cloud/configuration/Resource.java
+++ b/api/src/main/java/com/cloud/configuration/Resource.java
@@ -21,7 +21,7 @@ public interface Resource {
short RESOURCE_UNLIMITED = -1;
String UNLIMITED = "Unlimited";
- enum ResourceType { // Primary and Secondary storage are allocated_storage and not the physical storage.
+ enum ResourceType { // All storage type resources are allocated_storage and not the physical storage.
user_vm("user_vm", 0),
public_ip("public_ip", 1),
volume("volume", 2),
@@ -33,7 +33,12 @@ public interface Resource {
cpu("cpu", 8),
memory("memory", 9),
primary_storage("primary_storage", 10),
- secondary_storage("secondary_storage", 11);
+ secondary_storage("secondary_storage", 11),
+ backup("backup", 12),
+ backup_storage("backup_storage", 13),
+ bucket("bucket", 14),
+ object_storage("object_storage", 15),
+ gpu("gpu", 16);
private String name;
private int ordinal;
@@ -62,6 +67,10 @@ public interface Resource {
}
return null;
}
+
+ public static Boolean isStorageType(ResourceType type) {
+ return (type == primary_storage || type == secondary_storage || type == backup_storage || type == object_storage);
+ }
}
public static class ResourceOwnerType {
diff --git a/api/src/main/java/com/cloud/cpu/CPU.java b/api/src/main/java/com/cloud/cpu/CPU.java
new file mode 100644
index 00000000000..3016e542db6
--- /dev/null
+++ b/api/src/main/java/com/cloud/cpu/CPU.java
@@ -0,0 +1,70 @@
+// 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 org.apache.commons.lang3.StringUtils;
+
+public class CPU {
+ public enum CPUArch {
+ x86("i686", 32),
+ amd64("x86_64", 64),
+ arm64("aarch64", 64);
+
+ private final String type;
+ private final int bits;
+
+ CPUArch(String type, int bits) {
+ this.type = type;
+ this.bits = bits;
+ }
+
+ public static CPUArch getDefault() {
+ return amd64;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public int getBits() {
+ return bits;
+ }
+
+ public static CPUArch fromType(String type) {
+ if (StringUtils.isBlank(type)) {
+ return getDefault();
+ }
+ 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();
+ }
+ }
+}
diff --git a/api/src/main/java/com/cloud/dc/DedicatedResources.java b/api/src/main/java/com/cloud/dc/DedicatedResources.java
index 63188ca0b0e..23e6cc88a1e 100644
--- a/api/src/main/java/com/cloud/dc/DedicatedResources.java
+++ b/api/src/main/java/com/cloud/dc/DedicatedResources.java
@@ -21,6 +21,10 @@ import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
public interface DedicatedResources extends InfrastructureEntity, InternalIdentity, Identity {
+ enum Type {
+ Zone, Pod, Cluster, Host
+ }
+
@Override
long getId();
diff --git a/api/src/main/java/com/cloud/dc/Pod.java b/api/src/main/java/com/cloud/dc/Pod.java
index 1cbab36f3bd..17c5b615d4b 100644
--- a/api/src/main/java/com/cloud/dc/Pod.java
+++ b/api/src/main/java/com/cloud/dc/Pod.java
@@ -43,4 +43,6 @@ public interface Pod extends InfrastructureEntity, Grouping, Identity, InternalI
AllocationState getAllocationState();
boolean getExternalDhcp();
+
+ String getStorageAccessGroups();
}
diff --git a/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java b/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java
index 2697311d2b9..d127e4bdd66 100644
--- a/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java
+++ b/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java
@@ -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,
diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java
index d385fa9ed07..be21f13267b 100644
--- a/api/src/main/java/com/cloud/event/EventTypes.java
+++ b/api/src/main/java/com/cloud/event/EventTypes.java
@@ -28,10 +28,19 @@ import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.config.Configuration;
+import org.apache.cloudstack.datacenter.DataCenterIpv4GuestSubnet;
+import org.apache.cloudstack.extension.Extension;
+import org.apache.cloudstack.extension.ExtensionCustomAction;
+import org.apache.cloudstack.gpu.GpuCard;
+import org.apache.cloudstack.gpu.GpuDevice;
+import org.apache.cloudstack.gpu.VgpuProfile;
import org.apache.cloudstack.ha.HAConfig;
+import org.apache.cloudstack.network.BgpPeer;
+import org.apache.cloudstack.network.Ipv4GuestSubnetNetworkMap;
+import org.apache.cloudstack.quota.QuotaTariff;
import org.apache.cloudstack.storage.object.Bucket;
import org.apache.cloudstack.storage.object.ObjectStore;
-import org.apache.cloudstack.quota.QuotaTariff;
+import org.apache.cloudstack.storage.sharedfs.SharedFS;
import org.apache.cloudstack.usage.Usage;
import org.apache.cloudstack.vm.schedule.VMSchedule;
@@ -242,6 +251,8 @@ public class EventTypes {
public static final String EVENT_ROLE_UPDATE = "ROLE.UPDATE";
public static final String EVENT_ROLE_DELETE = "ROLE.DELETE";
public static final String EVENT_ROLE_IMPORT = "ROLE.IMPORT";
+ public static final String EVENT_ROLE_ENABLE = "ROLE.ENABLE";
+ public static final String EVENT_ROLE_DISABLE = "ROLE.DISABLE";
public static final String EVENT_ROLE_PERMISSION_CREATE = "ROLE.PERMISSION.CREATE";
public static final String EVENT_ROLE_PERMISSION_UPDATE = "ROLE.PERMISSION.UPDATE";
public static final String EVENT_ROLE_PERMISSION_DELETE = "ROLE.PERMISSION.DELETE";
@@ -283,9 +294,12 @@ public class EventTypes {
//registering userdata events
public static final String EVENT_REGISTER_USER_DATA = "REGISTER.USER.DATA";
+ public static final String EVENT_REGISTER_CNI_CONFIG = "REGISTER.CNI.CONFIG";
+ public static final String EVENT_DELETE_CNI_CONFIG = "DELETE.CNI.CONFIG";
//register for user API and secret keys
public static final String EVENT_REGISTER_FOR_SECRET_API_KEY = "REGISTER.USER.KEY";
+ public static final String API_KEY_ACCESS_UPDATE = "API.KEY.ACCESS.UPDATE";
// Template Events
public static final String EVENT_TEMPLATE_CREATE = "TEMPLATE.CREATE";
@@ -316,6 +330,8 @@ public class EventTypes {
public static final String EVENT_VOLUME_UPDATE = "VOLUME.UPDATE";
public static final String EVENT_VOLUME_DESTROY = "VOLUME.DESTROY";
public static final String EVENT_VOLUME_RECOVER = "VOLUME.RECOVER";
+ public static final String EVENT_VOLUME_IMPORT = "VOLUME.IMPORT";
+ public static final String EVENT_VOLUME_UNMANAGE = "VOLUME.UNMANAGE";
public static final String EVENT_VOLUME_CHANGE_DISK_OFFERING = "VOLUME.CHANGE.DISK.OFFERING";
// Domains
@@ -331,6 +347,7 @@ public class EventTypes {
public static final String EVENT_SNAPSHOT_OFF_PRIMARY = "SNAPSHOT.OFF_PRIMARY";
public static final String EVENT_SNAPSHOT_DELETE = "SNAPSHOT.DELETE";
public static final String EVENT_SNAPSHOT_REVERT = "SNAPSHOT.REVERT";
+ public static final String EVENT_SNAPSHOT_EXTRACT = "SNAPSHOT.EXTRACT";
public static final String EVENT_SNAPSHOT_POLICY_CREATE = "SNAPSHOTPOLICY.CREATE";
public static final String EVENT_SNAPSHOT_POLICY_UPDATE = "SNAPSHOTPOLICY.UPDATE";
public static final String EVENT_SNAPSHOT_POLICY_DELETE = "SNAPSHOTPOLICY.DELETE";
@@ -364,6 +381,21 @@ public class EventTypes {
public static final String EVENT_DISK_OFFERING_EDIT = "DISK.OFFERING.EDIT";
public static final String EVENT_DISK_OFFERING_DELETE = "DISK.OFFERING.DELETE";
+ // GPU Cards
+ public static final String EVENT_GPU_CARD_CREATE = "GPU.CARD.CREATE";
+ public static final String EVENT_GPU_CARD_EDIT = "GPU.CARD.EDIT";
+ public static final String EVENT_GPU_CARD_DELETE = "GPU.CARD.DELETE";
+
+ // vGPU Profile
+ public static final String EVENT_VGPU_PROFILE_CREATE = "VGPU.PROFILE.CREATE";
+ public static final String EVENT_VGPU_PROFILE_EDIT = "VGPU.PROFILE.EDIT";
+ public static final String EVENT_VGPU_PROFILE_DELETE = "VGPU.PROFILE.DELETE";
+
+ // GPU Devices
+ public static final String EVENT_GPU_DEVICE_CREATE = "GPU.DEVICE.CREATE";
+ public static final String EVENT_GPU_DEVICE_EDIT = "GPU.DEVICE.EDIT";
+ public static final String EVENT_GPU_DEVICE_DELETE = "GPU.DEVICE.DELETE";
+
// Network offerings
public static final String EVENT_NETWORK_OFFERING_CREATE = "NETWORK.OFFERING.CREATE";
public static final String EVENT_NETWORK_OFFERING_ASSIGN = "NETWORK.OFFERING.ASSIGN";
@@ -388,6 +420,11 @@ public class EventTypes {
public static final String EVENT_VLAN_IP_RANGE_RELEASE = "VLAN.IP.RANGE.RELEASE";
public static final String EVENT_VLAN_IP_RANGE_UPDATE = "VLAN.IP.RANGE.UPDATE";
+ // AS Number
+ public static final String EVENT_AS_RANGE_CREATE = "AS.RANGE.CREATE";
+ public static final String EVENT_AS_RANGE_DELETE = "AS.RANGE.DELETE";
+ public static final String EVENT_AS_NUMBER_RELEASE = "AS.NUMBER.RELEASE";
+
public static final String EVENT_MANAGEMENT_IP_RANGE_CREATE = "MANAGEMENT.IP.RANGE.CREATE";
public static final String EVENT_MANAGEMENT_IP_RANGE_DELETE = "MANAGEMENT.IP.RANGE.DELETE";
public static final String EVENT_MANAGEMENT_IP_RANGE_UPDATE = "MANAGEMENT.IP.RANGE.UPDATE";
@@ -446,9 +483,12 @@ public class EventTypes {
public static final String EVENT_MAINTENANCE_PREPARE_PRIMARY_STORAGE = "MAINT.PREPARE.PS";
// Primary storage pool
+ public static final String EVENT_UPDATE_PRIMARY_STORAGE = "UPDATE.PS";
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
public static final String EVENT_REMOTE_ACCESS_VPN_CREATE = "VPN.REMOTE.ACCESS.CREATE";
@@ -479,6 +519,8 @@ public class EventTypes {
public static final String EVENT_ZONE_VLAN_ASSIGN = "ZONE.VLAN.ASSIGN";
public static final String EVENT_ZONE_VLAN_RELEASE = "ZONE.VLAN.RELEASE";
+ public static final String EVENT_ZONE_VXLAN_ASSIGN = "ZONE.VXLAN.ASSIGN";
+ public static final String EVENT_ZONE_VXLAN_RELEASE = "ZONE.VXLAN.RELEASE";
// Projects
public static final String EVENT_PROJECT_CREATE = "PROJECT.CREATE";
@@ -590,11 +632,13 @@ public class EventTypes {
public static final String EVENT_VM_BACKUP_CREATE = "BACKUP.CREATE";
public static final String EVENT_VM_BACKUP_RESTORE = "BACKUP.RESTORE";
public static final String EVENT_VM_BACKUP_DELETE = "BACKUP.DELETE";
+ public static final String EVENT_VM_BACKUP_OFFERING_REMOVED_AND_BACKUPS_DELETED = "BACKUP.OFFERING.BACKUPS.DEL";
public static final String EVENT_VM_BACKUP_RESTORE_VOLUME_TO_VM = "BACKUP.RESTORE.VOLUME.TO.VM";
public static final String EVENT_VM_BACKUP_SCHEDULE_CONFIGURE = "BACKUP.SCHEDULE.CONFIGURE";
public static final String EVENT_VM_BACKUP_SCHEDULE_DELETE = "BACKUP.SCHEDULE.DELETE";
public static final String EVENT_VM_BACKUP_USAGE_METRIC = "BACKUP.USAGE.METRIC";
public static final String EVENT_VM_BACKUP_EDIT = "BACKUP.OFFERING.EDIT";
+ public static final String EVENT_VM_CREATE_FROM_BACKUP = "VM.CREATE.FROM.BACKUP";
// external network device events
public static final String EVENT_EXTERNAL_NVP_CONTROLLER_ADD = "PHYSICAL.NVPCONTROLLER.ADD";
@@ -670,6 +714,9 @@ public class EventTypes {
public static final String EVENT_EXTERNAL_OPENDAYLIGHT_CONFIGURE_CONTROLLER = "PHYSICAL.ODLCONTROLLER.CONFIGURE";
//Guest OS related events
+ public static final String EVENT_GUEST_OS_CATEGORY_ADD = "GUEST.OS.CATEGORY.ADD";
+ public static final String EVENT_GUEST_OS_CATEGORY_DELETE = "GUEST.OS.CATEGORY.DELETE";
+ public static final String EVENT_GUEST_OS_CATEGORY_UPDATE = "GUEST.OS.CATEGORY.UPDATE";
public static final String EVENT_GUEST_OS_ADD = "GUEST.OS.ADD";
public static final String EVENT_GUEST_OS_REMOVE = "GUEST.OS.REMOVE";
public static final String EVENT_GUEST_OS_UPDATE = "GUEST.OS.UPDATE";
@@ -719,6 +766,15 @@ public class EventTypes {
// SystemVM
public static final String EVENT_LIVE_PATCH_SYSTEMVM = "LIVE.PATCH.SYSTEM.VM";
+ //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";
@@ -735,6 +791,67 @@ public class EventTypes {
public static final String EVENT_QUOTA_TARIFF_DELETE = "QUOTA.TARIFF.DELETE";
public static final String EVENT_QUOTA_TARIFF_UPDATE = "QUOTA.TARIFF.UPDATE";
+ // Routing
+ public static final String EVENT_ZONE_IP4_SUBNET_CREATE = "ZONE.IP4.SUBNET.CREATE";
+ public static final String EVENT_ZONE_IP4_SUBNET_UPDATE = "ZONE.IP4.SUBNET.UPDATE";
+ public static final String EVENT_ZONE_IP4_SUBNET_DELETE = "ZONE.IP4.SUBNET.DELETE";
+ public static final String EVENT_ZONE_IP4_SUBNET_DEDICATE = "ZONE.IP4.SUBNET.DEDICATE";
+ public static final String EVENT_ZONE_IP4_SUBNET_RELEASE = "ZONE.IP4.SUBNET.RELEASE";
+ public static final String EVENT_IP4_GUEST_SUBNET_CREATE = "IP4.GUEST.SUBNET.CREATE";
+ public static final String EVENT_IP4_GUEST_SUBNET_DELETE = "IP4.GUEST.SUBNET.DELETE";
+ public static final String EVENT_ROUTING_IPV4_FIREWALL_RULE_CREATE = "ROUTING.IPV4.FIREWALL.RULE.CREATE";
+ public static final String EVENT_ROUTING_IPV4_FIREWALL_RULE_UPDATE = "ROUTING.IPV4.FIREWALL.RULE.UPDATE";
+ public static final String EVENT_ROUTING_IPV4_FIREWALL_RULE_DELETE = "ROUTING.IPV4.FIREWALL.RULE.DELETE";
+ public static final String EVENT_BGP_PEER_CREATE = "BGP.PEER.CREATE";
+ public static final String EVENT_BGP_PEER_UPDATE = "BGP.PEER.UPDATE";
+ public static final String EVENT_BGP_PEER_DELETE = "BGP.PEER.DELETE";
+ public static final String EVENT_BGP_PEER_DEDICATE = "BGP.PEER.DEDICATE";
+ public static final String EVENT_BGP_PEER_RELEASE = "BGP.PEER.RELEASE";
+ public static final String EVENT_NETWORK_BGP_PEER_UPDATE = "NETWORK.BGP.PEER.UPDATE";
+ public static final String EVENT_VPC_BGP_PEER_UPDATE = "VPC.BGP.PEER.UPDATE";
+
+ // SharedFS
+ public static final String EVENT_SHAREDFS_CREATE = "SHAREDFS.CREATE";
+ public static final String EVENT_SHAREDFS_START = "SHAREDFS.START";
+ public static final String EVENT_SHAREDFS_UPDATE = "SHAREDFS.UPDATE";
+ public static final String EVENT_SHAREDFS_CHANGE_SERVICE_OFFERING = "SHAREDFS.CHANGE.SERVICE.OFFERING";
+ public static final String EVENT_SHAREDFS_CHANGE_DISK_OFFERING = "SHAREDFS.CHANGE.DISK.OFFERING";
+ public static final String EVENT_SHAREDFS_STOP = "SHAREDFS.STOP";
+ public static final String EVENT_SHAREDFS_RESTART = "SHAREDFS.RESTART";
+ public static final String EVENT_SHAREDFS_DESTROY = "SHAREDFS.DESTROY";
+ public static final String EVENT_SHAREDFS_EXPUNGE = "SHAREDFS.EXPUNGE";
+ public static final String EVENT_SHAREDFS_RECOVER = "SHAREDFS.RECOVER";
+
+ // Resource Limit
+ public static final String EVENT_RESOURCE_LIMIT_UPDATE = "RESOURCE.LIMIT.UPDATE";
+
+ // Management Server
+ public static final String EVENT_MANAGEMENT_SERVER_REMOVE = "MANAGEMENT.SERVER.REMOVE";
+
+ // VM Lease
+ 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";
+
+ // GUI Theme
+ public static final String EVENT_GUI_THEME_CREATE = "GUI.THEME.CREATE";
+ public static final String EVENT_GUI_THEME_REMOVE = "GUI.THEME.REMOVE";
+ public static final String EVENT_GUI_THEME_UPDATE = "GUI.THEME.UPDATE";
+
+ // Extension
+ public static final String EVENT_EXTENSION_CREATE = "EXTENSION.CREATE";
+ public static final String EVENT_EXTENSION_UPDATE = "EXTENSION.UPDATE";
+ public static final String EVENT_EXTENSION_DELETE = "EXTENSION.DELETE";
+ public static final String EVENT_EXTENSION_RESOURCE_REGISTER = "EXTENSION.RESOURCE.REGISTER";
+ public static final String EVENT_EXTENSION_RESOURCE_UNREGISTER = "EXTENSION.RESOURCE.UNREGISTER";
+ public static final String EVENT_EXTENSION_CUSTOM_ACTION_ADD = "EXTENSION.CUSTOM.ACTION.ADD";
+ public static final String EVENT_EXTENSION_CUSTOM_ACTION_UPDATE = "EXTENSION.CUSTOM.ACTION.UPDATE";
+ public static final String EVENT_EXTENSION_CUSTOM_ACTION_DELETE = "EXTENSION.CUSTOM.ACTION.DELETE";
+
+ // Custom Action
+ public static final String EVENT_CUSTOM_ACTION = "CUSTOM.ACTION";
+
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -836,6 +953,8 @@ public class EventTypes {
entityEventDetails.put(EVENT_ROLE_UPDATE, Role.class);
entityEventDetails.put(EVENT_ROLE_DELETE, Role.class);
entityEventDetails.put(EVENT_ROLE_IMPORT, Role.class);
+ entityEventDetails.put(EVENT_ROLE_ENABLE, Role.class);
+ entityEventDetails.put(EVENT_ROLE_DISABLE, Role.class);
entityEventDetails.put(EVENT_ROLE_PERMISSION_CREATE, RolePermission.class);
entityEventDetails.put(EVENT_ROLE_PERMISSION_UPDATE, RolePermission.class);
entityEventDetails.put(EVENT_ROLE_PERMISSION_DELETE, RolePermission.class);
@@ -892,6 +1011,7 @@ public class EventTypes {
// Snapshots
entityEventDetails.put(EVENT_SNAPSHOT_CREATE, Snapshot.class);
entityEventDetails.put(EVENT_SNAPSHOT_DELETE, Snapshot.class);
+ entityEventDetails.put(EVENT_SNAPSHOT_EXTRACT, Snapshot.class);
entityEventDetails.put(EVENT_SNAPSHOT_ON_PRIMARY, Snapshot.class);
entityEventDetails.put(EVENT_SNAPSHOT_OFF_PRIMARY, Snapshot.class);
entityEventDetails.put(EVENT_SNAPSHOT_POLICY_CREATE, SnapshotPolicy.class);
@@ -926,6 +1046,21 @@ public class EventTypes {
entityEventDetails.put(EVENT_DISK_OFFERING_EDIT, DiskOffering.class);
entityEventDetails.put(EVENT_DISK_OFFERING_DELETE, DiskOffering.class);
+ // GPU Cards
+ entityEventDetails.put(EVENT_GPU_CARD_CREATE, GpuCard.class);
+ entityEventDetails.put(EVENT_GPU_CARD_EDIT, GpuCard.class);
+ entityEventDetails.put(EVENT_GPU_CARD_DELETE, GpuCard.class);
+
+ // vGPU Profiles
+ entityEventDetails.put(EVENT_VGPU_PROFILE_CREATE, VgpuProfile.class);
+ entityEventDetails.put(EVENT_VGPU_PROFILE_EDIT, VgpuProfile.class);
+ entityEventDetails.put(EVENT_VGPU_PROFILE_DELETE, VgpuProfile.class);
+
+ // GPU Devices
+ entityEventDetails.put(EVENT_GPU_DEVICE_CREATE, GpuDevice.class);
+ entityEventDetails.put(EVENT_GPU_DEVICE_EDIT, GpuDevice.class);
+ entityEventDetails.put(EVENT_GPU_DEVICE_DELETE, GpuDevice.class);
+
// Network offerings
entityEventDetails.put(EVENT_NETWORK_OFFERING_CREATE, NetworkOffering.class);
entityEventDetails.put(EVENT_NETWORK_OFFERING_ASSIGN, NetworkOffering.class);
@@ -996,8 +1131,10 @@ public class EventTypes {
entityEventDetails.put(EVENT_MAINTENANCE_PREPARE_PRIMARY_STORAGE, Host.class);
// Primary storage pool
+ entityEventDetails.put(EVENT_UPDATE_PRIMARY_STORAGE, StoragePool.class);
entityEventDetails.put(EVENT_ENABLE_PRIMARY_STORAGE, StoragePool.class);
entityEventDetails.put(EVENT_DISABLE_PRIMARY_STORAGE, StoragePool.class);
+ entityEventDetails.put(EVENT_CHANGE_STORAGE_POOL_SCOPE, StoragePool.class);
// VPN
entityEventDetails.put(EVENT_REMOTE_ACCESS_VPN_CREATE, RemoteAccessVpn.class);
@@ -1175,6 +1312,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);
@@ -1189,8 +1332,65 @@ public class EventTypes {
entityEventDetails.put(EVENT_QUOTA_TARIFF_CREATE, QuotaTariff.class);
entityEventDetails.put(EVENT_QUOTA_TARIFF_DELETE, QuotaTariff.class);
entityEventDetails.put(EVENT_QUOTA_TARIFF_UPDATE, QuotaTariff.class);
+
+ // Routing
+ entityEventDetails.put(EVENT_ZONE_IP4_SUBNET_CREATE, DataCenterIpv4GuestSubnet.class);
+ entityEventDetails.put(EVENT_ZONE_IP4_SUBNET_UPDATE, DataCenterIpv4GuestSubnet.class);
+ entityEventDetails.put(EVENT_ZONE_IP4_SUBNET_DELETE, DataCenterIpv4GuestSubnet.class);
+ entityEventDetails.put(EVENT_ZONE_IP4_SUBNET_DEDICATE, DataCenterIpv4GuestSubnet.class);
+ entityEventDetails.put(EVENT_ZONE_IP4_SUBNET_RELEASE, DataCenterIpv4GuestSubnet.class);
+ entityEventDetails.put(EVENT_IP4_GUEST_SUBNET_CREATE, Ipv4GuestSubnetNetworkMap.class);
+ entityEventDetails.put(EVENT_IP4_GUEST_SUBNET_DELETE, Ipv4GuestSubnetNetworkMap.class);
+ entityEventDetails.put(EVENT_ROUTING_IPV4_FIREWALL_RULE_CREATE, FirewallRule.class);
+ entityEventDetails.put(EVENT_ROUTING_IPV4_FIREWALL_RULE_UPDATE, FirewallRule.class);
+ entityEventDetails.put(EVENT_ROUTING_IPV4_FIREWALL_RULE_DELETE, FirewallRule.class);
+ entityEventDetails.put(EVENT_BGP_PEER_CREATE, BgpPeer.class);
+ entityEventDetails.put(EVENT_BGP_PEER_UPDATE, BgpPeer.class);
+ entityEventDetails.put(EVENT_BGP_PEER_DELETE, BgpPeer.class);
+ entityEventDetails.put(EVENT_BGP_PEER_DEDICATE, BgpPeer.class);
+ entityEventDetails.put(EVENT_BGP_PEER_RELEASE, BgpPeer.class);
+
+ // SharedFS
+ entityEventDetails.put(EVENT_SHAREDFS_CREATE, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_START, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_STOP, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_UPDATE, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_CHANGE_SERVICE_OFFERING, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_CHANGE_DISK_OFFERING, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_RESTART, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_DESTROY, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_EXPUNGE, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_RECOVER, SharedFS.class);
+
+ // Management Server
+ entityEventDetails.put(EVENT_MANAGEMENT_SERVER_REMOVE, "ManagementServer");
+
+ // VM Lease
+ entityEventDetails.put(VM_LEASE_EXPIRED, VirtualMachine.class);
+ entityEventDetails.put(VM_LEASE_EXPIRING, VirtualMachine.class);
+ entityEventDetails.put(VM_LEASE_DISABLED, VirtualMachine.class);
+ entityEventDetails.put(VM_LEASE_CANCELLED, VirtualMachine.class);
+
+ // GUI theme
+ entityEventDetails.put(EVENT_GUI_THEME_CREATE, "GuiTheme");
+ entityEventDetails.put(EVENT_GUI_THEME_REMOVE, "GuiTheme");
+ entityEventDetails.put(EVENT_GUI_THEME_UPDATE, "GuiTheme");
+
+ // Extension
+ entityEventDetails.put(EVENT_EXTENSION_CREATE, Extension.class);
+ entityEventDetails.put(EVENT_EXTENSION_UPDATE, Extension.class);
+ entityEventDetails.put(EVENT_EXTENSION_DELETE, Extension.class);
+ entityEventDetails.put(EVENT_EXTENSION_RESOURCE_REGISTER, Extension.class);
+ entityEventDetails.put(EVENT_EXTENSION_RESOURCE_UNREGISTER, Extension.class);
+ entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_ADD, ExtensionCustomAction.class);
+ entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_UPDATE, ExtensionCustomAction.class);
+ entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_DELETE, ExtensionCustomAction.class);
}
+ public static boolean isNetworkEvent(String eventType) {
+ return EVENT_NETWORK_CREATE.equals(eventType) || EVENT_NETWORK_DELETE.equals(eventType) ||
+ EVENT_NETWORK_UPDATE.equals(eventType);
+ }
public static String getEntityForEvent(String eventName) {
Object entityClass = entityEventDetails.get(eventName);
if (entityClass == null) {
@@ -1219,4 +1419,12 @@ public class EventTypes {
return null;
}
+
+ public static boolean isVpcEvent(String eventType) {
+ return EventTypes.EVENT_VPC_CREATE.equals(eventType) || EventTypes.EVENT_VPC_DELETE.equals(eventType);
+ }
+
+ public static void addEntityEventDetail(String event, Class> clazz) {
+ entityEventDetails.put(event, clazz);
+ }
}
diff --git a/api/src/main/java/com/cloud/exception/OperationTimedoutException.java b/api/src/main/java/com/cloud/exception/OperationTimedoutException.java
index fe27408eb4e..66b607100d9 100644
--- a/api/src/main/java/com/cloud/exception/OperationTimedoutException.java
+++ b/api/src/main/java/com/cloud/exception/OperationTimedoutException.java
@@ -40,7 +40,7 @@ public class OperationTimedoutException extends CloudException {
boolean _isActive;
public OperationTimedoutException(Command[] cmds, long agentId, long seqId, int time, boolean isActive) {
- super("Commands " + seqId + " to Host " + agentId + " timed out after " + time);
+ super("Commands " + seqId + " to Host " + agentId + " timed out after " + time + " secs");
_agentId = agentId;
_seqId = seqId;
_time = time;
diff --git a/api/src/main/java/com/cloud/exception/StorageAccessException.java b/api/src/main/java/com/cloud/exception/StorageAccessException.java
index eefbcf5518a..d54d77d66f1 100644
--- a/api/src/main/java/com/cloud/exception/StorageAccessException.java
+++ b/api/src/main/java/com/cloud/exception/StorageAccessException.java
@@ -26,7 +26,7 @@ import com.cloud.utils.SerialVersionUID;
public class StorageAccessException extends RuntimeException {
private static final long serialVersionUID = SerialVersionUID.StorageAccessException;
- public StorageAccessException(String message) {
- super(message);
+ public StorageAccessException(String message, Exception causer) {
+ super(message, causer);
}
}
diff --git a/api/src/main/java/com/cloud/host/Host.java b/api/src/main/java/com/cloud/host/Host.java
index 7563bc3b742..07a0dfce041 100644
--- a/api/src/main/java/com/cloud/host/Host.java
+++ b/api/src/main/java/com/cloud/host/Host.java
@@ -16,6 +16,7 @@
// under the License.
package com.cloud.host;
+import com.cloud.cpu.CPU;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ResourceState;
import com.cloud.utils.fsm.StateObject;
@@ -52,8 +53,12 @@ public interface Host extends StateObject, Identity, Partition, HAResour
return strs;
}
}
- public static final String HOST_UEFI_ENABLE = "host.uefi.enable";
- public static final String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
+
+ String HOST_UEFI_ENABLE = "host.uefi.enable";
+ String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
+ String HOST_INSTANCE_CONVERSION = "host.instance.conversion";
+ String HOST_OVFTOOL_VERSION = "host.ovftool.version";
+ String HOST_VIRTV2V_VERSION = "host.virtv2v.version";
/**
* @return name of the machine.
@@ -175,6 +180,8 @@ public interface Host extends StateObject, Identity, Partition, HAResour
*/
Long getManagementServerId();
+ Long getLastManagementServerId();
+
/*
*@return removal date
*/
@@ -207,4 +214,8 @@ public interface Host extends StateObject, Identity, Partition, HAResour
boolean isDisabled();
ResourceState getResourceState();
+
+ CPU.CPUArch getArch();
+
+ String getStorageAccessGroups();
}
diff --git a/api/src/main/java/com/cloud/host/Status.java b/api/src/main/java/com/cloud/host/Status.java
index 5dc82bbfaef..af6af82e973 100644
--- a/api/src/main/java/com/cloud/host/Status.java
+++ b/api/src/main/java/com/cloud/host/Status.java
@@ -127,6 +127,7 @@ public enum Status {
s_fsm.addTransition(Status.Connecting, Event.HostDown, Status.Down);
s_fsm.addTransition(Status.Connecting, Event.Ping, Status.Connecting);
s_fsm.addTransition(Status.Connecting, Event.ManagementServerDown, Status.Disconnected);
+ s_fsm.addTransition(Status.Connecting, Event.StartAgentRebalance, Status.Rebalancing);
s_fsm.addTransition(Status.Connecting, Event.AgentDisconnected, Status.Alert);
s_fsm.addTransition(Status.Up, Event.PingTimeout, Status.Alert);
s_fsm.addTransition(Status.Up, Event.AgentDisconnected, Status.Alert);
diff --git a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
index e1108b34a83..5baac484772 100644
--- a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
+++ b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
@@ -20,37 +20,58 @@ import com.cloud.storage.Storage.ImageFormat;
import org.apache.commons.lang3.StringUtils;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.stream.Collectors;
+
+import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.DirectDownloadTemplate;
+import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.RootDiskSizeOverride;
+import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.VmStorageMigration;
public class Hypervisor {
public static class HypervisorType {
+ public enum Functionality {
+ DirectDownloadTemplate,
+ RootDiskSizeOverride,
+ VmStorageMigration
+ }
+
private static final Map hypervisorTypeMap = new LinkedHashMap<>();
public static final HypervisorType None = new HypervisorType("None"); //for storage hosts
- public static final HypervisorType XenServer = new HypervisorType("XenServer", ImageFormat.VHD);
- public static final HypervisorType KVM = new HypervisorType("KVM", ImageFormat.QCOW2);
- public static final HypervisorType VMware = new HypervisorType("VMware", ImageFormat.OVA);
+ public static final HypervisorType XenServer = new HypervisorType("XenServer", ImageFormat.VHD, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
+ public static final HypervisorType KVM = new HypervisorType("KVM", ImageFormat.QCOW2, EnumSet.of(DirectDownloadTemplate, RootDiskSizeOverride, VmStorageMigration));
+ public static final HypervisorType VMware = new HypervisorType("VMware", ImageFormat.OVA, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
public static final HypervisorType Hyperv = new HypervisorType("Hyperv");
public static final HypervisorType VirtualBox = new HypervisorType("VirtualBox");
public static final HypervisorType Parralels = new HypervisorType("Parralels");
public static final HypervisorType BareMetal = new HypervisorType("BareMetal");
- public static final HypervisorType Simulator = new HypervisorType("Simulator");
+ public static final HypervisorType Simulator = new HypervisorType("Simulator", null, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
public static final HypervisorType Ovm = new HypervisorType("Ovm", ImageFormat.RAW);
public static final HypervisorType Ovm3 = new HypervisorType("Ovm3", ImageFormat.RAW);
public static final HypervisorType LXC = new HypervisorType("LXC");
- public static final HypervisorType Custom = new HypervisorType("Custom");
+ public static final HypervisorType Custom = new HypervisorType("Custom", null, EnumSet.of(RootDiskSizeOverride));
+ public static final HypervisorType External = new HypervisorType("External", null, EnumSet.of(RootDiskSizeOverride));
public static final HypervisorType Any = new HypervisorType("Any"); /*If you don't care about the hypervisor type*/
private final String name;
private final ImageFormat imageFormat;
+ private final Set supportedFunctionalities;
public HypervisorType(String name) {
- this(name, null);
+ this(name, null, EnumSet.noneOf(Functionality.class));
}
public HypervisorType(String name, ImageFormat imageFormat) {
+ this(name, imageFormat, EnumSet.noneOf(Functionality.class));
+ }
+
+ public HypervisorType(String name, ImageFormat imageFormat, Set supportedFunctionalities) {
this.name = name;
this.imageFormat = imageFormat;
+ this.supportedFunctionalities = supportedFunctionalities;
if (name.equals("Parralels")){ // typo in the original code
hypervisorTypeMap.put("parallels", this);
} else {
@@ -81,6 +102,12 @@ public class Hypervisor {
return hypervisorType;
}
+ public static List getListOfHypervisorsSupportingFunctionality(Functionality functionality) {
+ return hypervisorTypeMap.values().stream()
+ .filter(hypervisor -> hypervisor.supportedFunctionalities.contains(functionality))
+ .collect(Collectors.toList());
+ }
+
/**
* Returns the display name of a hypervisor type in case the custom hypervisor is used,
* using the 'hypervisor.custom.display.name' setting. Otherwise, returns hypervisor name
@@ -102,6 +129,15 @@ public class Hypervisor {
return name;
}
+ /**
+ * Make this method to be part of the properties of the hypervisor type itself.
+ *
+ * @return true if the hypervisor plugin support the specified functionality
+ */
+ public boolean isFunctionalitySupported(Functionality functionality) {
+ return supportedFunctionalities.contains(functionality);
+ }
+
@Override
public int hashCode() {
return Objects.hash(name);
diff --git a/api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java b/api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java
index 3c7dbac6442..0c821b4e36c 100644
--- a/api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java
+++ b/api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java
@@ -23,6 +23,7 @@ import org.apache.cloudstack.backup.Backup;
import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -101,21 +102,20 @@ public interface HypervisorGuru extends Adapter {
* Will generate commands to migrate a vm to a pool. For now this will only work for stopped VMs on Vmware.
*
* @param vm the stopped vm to migrate
- * @param destination the primary storage pool to migrate to
+ * @param volumeToPool the primary storage pools to migrate to
* @return a list of commands to perform for a successful migration
*/
List finalizeMigrate(VirtualMachine vm, Map volumeToPool);
/**
- * Will perform a clone of a VM on an external host (if the guru can handle)
+ * Will return the hypervisor VM (clone VM for PowerOn VMs), performs a clone of a VM if required on an external host (if the guru can handle)
* @param hostIp VM's source host IP
- * @param vmName name of the source VM to clone from
+ * @param vmName name of the source VM (clone VM name if cloned)
* @param params hypervisor specific additional parameters
- * @return a reference to the cloned VM
+ * @return a reference to the hypervisor or cloned VM, and cloned flag
*/
- UnmanagedInstanceTO cloneHypervisorVMOutOfBand(String hostIp, String vmName,
- Map params);
+ Pair getHypervisorVMOutOfBandAndCloneIfRequired(String hostIp, String vmName, Map params);
/**
* Removes a VM created as a clone of a VM on an external host
@@ -124,6 +124,23 @@ public interface HypervisorGuru extends Adapter {
* @param params hypervisor specific additional parameters
* @return true if the operation succeeds, false if not
*/
- boolean removeClonedHypervisorVMOutOfBand(String hostIp, String vmName,
- Map params);
+ boolean removeClonedHypervisorVMOutOfBand(String hostIp, String vmName, Map params);
+
+ /**
+ * Create an OVA/OVF template of a VM on an external host (if the guru can handle)
+ * @param hostIp VM's source host IP
+ * @param vmName name of the source VM to create template from
+ * @param params hypervisor specific additional parameters
+ * @param templateLocation datastore to create the template file
+ * @return the created template dir/name
+ */
+ String createVMTemplateOutOfBand(String hostIp, String vmName, Map params, DataStoreTO templateLocation, int threadsCountToExportOvf);
+
+ /**
+ * Removes the template on the location
+ * @param templateLocation datastore to remove the template file
+ * @param templateDir the template dir to remove from datastore
+ * @return true if the operation succeeds, false if not
+ */
+ boolean removeVMTemplateOutOfBand(DataStoreTO templateLocation, String templateDir);
}
diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java
similarity index 82%
rename from plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java
rename to api/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java
index 591da077aec..8b5551d6a8e 100644
--- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java
+++ b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java
@@ -44,6 +44,8 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
AutoscaleRequested,
ScaleUpRequested,
ScaleDownRequested,
+ AddNodeRequested,
+ RemoveNodeRequested,
UpgradeRequested,
OperationSucceeded,
OperationFailed,
@@ -59,6 +61,8 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
Stopped("All resources for the Kubernetes cluster are destroyed, Kubernetes cluster may still have ephemeral resource like persistent volumes provisioned"),
Scaling("Transient state in which resources are either getting scaled up/down"),
Upgrading("Transient state in which cluster is getting upgraded"),
+ Importing("Transient state in which additional nodes are added as worker nodes to a cluster"),
+ RemovingNodes("Transient state in which additional nodes are removed from a cluster"),
Alert("State to represent Kubernetes clusters which are not in expected desired state (operationally in active control place, stopped cluster VM's etc)."),
Recovering("State in which Kubernetes cluster is recovering from alert state"),
Destroyed("End state of Kubernetes cluster in which all resources are destroyed, cluster will not be usable further"),
@@ -96,6 +100,17 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
s_fsm.addTransition(State.Upgrading, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Upgrading, Event.OperationFailed, State.Alert);
+ s_fsm.addTransition(State.Running, Event.AddNodeRequested, State.Importing);
+ s_fsm.addTransition(State.Alert, Event.AddNodeRequested, State.Importing);
+ s_fsm.addTransition(State.Importing, Event.OperationSucceeded, State.Running);
+ s_fsm.addTransition(State.Importing, Event.OperationFailed, State.Running);
+ s_fsm.addTransition(State.Alert, Event.OperationSucceeded, State.Running);
+
+ s_fsm.addTransition(State.Running, Event.RemoveNodeRequested, State.RemovingNodes);
+ s_fsm.addTransition(State.Alert, Event.RemoveNodeRequested, State.RemovingNodes);
+ s_fsm.addTransition(State.RemovingNodes, Event.OperationSucceeded, State.Running);
+ s_fsm.addTransition(State.RemovingNodes, Event.OperationFailed, State.Running);
+
s_fsm.addTransition(State.Alert, Event.RecoveryRequested, State.Recovering);
s_fsm.addTransition(State.Recovering, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Recovering, Event.OperationFailed, State.Alert);
@@ -142,4 +157,13 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
Long getMaxSize();
Long getSecurityGroupId();
ClusterType getClusterType();
+ Long getControlNodeServiceOfferingId();
+ Long getWorkerNodeServiceOfferingId();
+ Long getEtcdNodeServiceOfferingId();
+ Long getControlNodeTemplateId();
+ Long getWorkerNodeTemplateId();
+ Long getEtcdNodeTemplateId();
+ Long getEtcdNodeCount();
+ Long getCniConfigId();
+ String getCniConfigDetails();
}
diff --git a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java
new file mode 100644
index 00000000000..37b8907b454
--- /dev/null
+++ b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java
@@ -0,0 +1,40 @@
+// 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.kubernetes.cluster;
+
+import org.apache.cloudstack.acl.ControlledEntity;
+
+import java.util.Map;
+
+import com.cloud.user.Account;
+import com.cloud.uservm.UserVm;
+import com.cloud.utils.component.Adapter;
+
+public interface KubernetesServiceHelper extends Adapter {
+
+ enum KubernetesClusterNodeType {
+ CONTROL, WORKER, ETCD, DEFAULT
+ }
+
+ ControlledEntity findByUuid(String uuid);
+ ControlledEntity findByVmId(long vmId);
+ void checkVmCanBeDestroyed(UserVm userVm);
+ boolean isValidNodeType(String nodeType);
+ Map getServiceOfferingNodeTypeMap(Map> serviceOfferingNodeTypeMap);
+ Map getTemplateNodeTypeMap(Map> templateNodeTypeMap);
+ void cleanupForAccount(Account account);
+}
diff --git a/api/src/main/java/com/cloud/network/IpAddress.java b/api/src/main/java/com/cloud/network/IpAddress.java
index ae1af450577..70d652b54e9 100644
--- a/api/src/main/java/com/cloud/network/IpAddress.java
+++ b/api/src/main/java/com/cloud/network/IpAddress.java
@@ -99,4 +99,5 @@ public interface IpAddress extends ControlledEntity, Identity, InternalIdentity,
boolean isForSystemVms();
+ boolean isForRouter();
}
diff --git a/api/src/main/java/com/cloud/network/Ipv6Service.java b/api/src/main/java/com/cloud/network/Ipv6Service.java
index 2b4dff01086..4ef5f98c38d 100644
--- a/api/src/main/java/com/cloud/network/Ipv6Service.java
+++ b/api/src/main/java/com/cloud/network/Ipv6Service.java
@@ -58,7 +58,7 @@ public interface Ipv6Service extends PluggableService, Configurable {
Pair getUsedTotalIpv6SubnetForZone(long zoneId);
- Pair preAllocateIpv6SubnetForNetwork(long zoneId) throws ResourceAllocationException;
+ Pair preAllocateIpv6SubnetForNetwork(DataCenter zone) throws ResourceAllocationException;
void assignIpv6SubnetToNetwork(String subnet, long networkId);
diff --git a/api/src/main/java/com/cloud/network/Network.java b/api/src/main/java/com/cloud/network/Network.java
index 3b13ef7bd9c..dc94932e31f 100644
--- a/api/src/main/java/com/cloud/network/Network.java
+++ b/api/src/main/java/com/cloud/network/Network.java
@@ -103,7 +103,7 @@ public interface Network extends ControlledEntity, StateObject, I
public static final Service Vpn = new Service("Vpn", Capability.SupportedVpnProtocols, Capability.VpnTypes);
public static final Service Dhcp = new Service("Dhcp", Capability.ExtraDhcpOptions);
public static final Service Dns = new Service("Dns", Capability.AllowDnsSuffixModification);
- public static final Service Gateway = new Service("Gateway");
+ public static final Service Gateway = new Service("Gateway", Capability.RedundantRouter);
public static final Service Firewall = new Service("Firewall", Capability.SupportedProtocols, Capability.MultipleIps, Capability.TrafficStatistics,
Capability.SupportedTrafficDirection, Capability.SupportedEgressProtocols);
public static final Service Lb = new Service("Lb", Capability.SupportedLBAlgorithms, Capability.SupportedLBIsolation, Capability.SupportedProtocols,
@@ -206,6 +206,7 @@ public interface Network extends ControlledEntity, StateObject, I
public static final Provider Tungsten = new Provider("Tungsten", false);
public static final Provider Nsx = new Provider("Nsx", false);
+ public static final Provider Netris = new Provider("Netris", false);
private final String name;
private final boolean isExternal;
@@ -412,12 +413,16 @@ public interface Network extends ControlledEntity, StateObject, I
String getGateway();
+ void setGateway(String gateway);
+
// "cidr" is the Cloudstack managed address space, all CloudStack managed vms get IP address from "cidr",
// In general "cidr" also serves as the network CIDR
// But in case IP reservation is configured for a Guest network, "networkcidr" is the Effective network CIDR for that network,
// "cidr" will still continue to be the effective address space for CloudStack managed vms in that Guest network
String getCidr();
+ void setCidr(String cidr);
+
// "networkcidr" is the network CIDR of the guest network which uses IP reservation.
// It is the summation of "cidr" and the reservedIPrange(the address space used for non CloudStack purposes).
// For networks not configured with IP reservation, "networkcidr" is always null
@@ -503,4 +508,6 @@ public interface Network extends ControlledEntity, StateObject, I
Integer getPublicMtu();
Integer getPrivateMtu();
+
+ Integer getNetworkCidrSize();
}
diff --git a/api/src/main/java/com/cloud/network/NetworkModel.java b/api/src/main/java/com/cloud/network/NetworkModel.java
index 53ac735cf05..eb496ac4e0b 100644
--- a/api/src/main/java/com/cloud/network/NetworkModel.java
+++ b/api/src/main/java/com/cloud/network/NetworkModel.java
@@ -149,7 +149,7 @@ public interface NetworkModel {
boolean areServicesSupportedByNetworkOffering(long networkOfferingId, Service... services);
- Network getNetworkWithSGWithFreeIPs(Long zoneId);
+ Network getNetworkWithSGWithFreeIPs(Account account, Long zoneId);
Network getNetworkWithSecurityGroupEnabled(Long zoneId);
@@ -173,6 +173,8 @@ public interface NetworkModel {
boolean isProviderSupportServiceInNetwork(long networkId, Service service, Provider provider);
+ boolean isAnyServiceSupportedInNetwork(long networkId, Provider provider, Service... services);
+
boolean isProviderEnabledInPhysicalNetwork(long physicalNetowrkId, String providerName);
String getNetworkTag(HypervisorType hType, Network network);
@@ -303,6 +305,8 @@ public interface NetworkModel {
NicProfile getNicProfile(VirtualMachine vm, long networkId, String broadcastUri);
+ NicProfile getNicProfile(VirtualMachine vm, Nic nic, DataCenter dataCenter);
+
Set getAvailableIps(Network network, String requestedIp);
String getDomainNetworkDomain(long domainId, long zoneId);
@@ -317,6 +321,8 @@ public interface NetworkModel {
void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gateway, String ip6Cidr) throws InvalidParameterValueException;
+ void checkIp6CidrSizeEqualTo64(String ip6Cidr) throws InvalidParameterValueException;
+
void checkRequestedIpAddresses(long networkId, IpAddresses ips) throws InvalidParameterValueException;
String getStartIpv6Address(long id);
@@ -354,4 +360,8 @@ public interface NetworkModel {
void verifyIp6DnsPair(final String ip6Dns1, final String ip6Dns2);
+ boolean isSecurityGroupSupportedForZone(Long zoneId);
+
+ boolean checkSecurityGroupSupportForNetwork(Account account, DataCenter zone, List networkIds,
+ List securityGroupsIds);
}
diff --git a/api/src/main/java/com/cloud/network/NetworkProfile.java b/api/src/main/java/com/cloud/network/NetworkProfile.java
index 1a5c80ea871..2e8efb48930 100644
--- a/api/src/main/java/com/cloud/network/NetworkProfile.java
+++ b/api/src/main/java/com/cloud/network/NetworkProfile.java
@@ -22,6 +22,7 @@ import java.util.Date;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.Mode;
import com.cloud.network.Networks.TrafficType;
+import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
public class NetworkProfile implements Network {
private final long id;
@@ -41,8 +42,8 @@ public class NetworkProfile implements Network {
private final Mode mode;
private final BroadcastDomainType broadcastDomainType;
private TrafficType trafficType;
- private final String gateway;
- private final String cidr;
+ private String gateway;
+ private String cidr;
private final String networkCidr;
private final String ip6Gateway;
private final String ip6Cidr;
@@ -62,6 +63,7 @@ public class NetworkProfile implements Network {
private final String guruName;
private boolean strechedL2Subnet;
private String externalId;
+ private Integer networkCidrSize;
public NetworkProfile(Network network) {
id = network.getId();
@@ -98,6 +100,7 @@ public class NetworkProfile implements Network {
isRedundant = network.isRedundant();
isRollingRestart = network.isRollingRestart();
externalId = network.getExternalId();
+ networkCidrSize = network.getNetworkCidrSize();
}
@Override
@@ -210,11 +213,21 @@ public class NetworkProfile implements Network {
return gateway;
}
+ @Override
+ public void setGateway(String gateway) {
+ this.gateway = gateway;
+ }
+
@Override
public String getCidr() {
return cidr;
}
+ @Override
+ public void setCidr(String cidr) {
+ this.cidr = cidr;
+ }
+
@Override
public String getNetworkCidr() {
return networkCidr;
@@ -367,4 +380,16 @@ public class NetworkProfile implements Network {
return null;
}
+ @Override
+ public Integer getNetworkCidrSize() {
+ return networkCidrSize;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("NetworkProfile %s",
+ ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
+ this, "id", "uuid", "name", "networkOfferingId"));
+ }
+
}
diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java
index 51799e25cda..196e1f9aab8 100644
--- a/api/src/main/java/com/cloud/network/NetworkService.java
+++ b/api/src/main/java/com/cloud/network/NetworkService.java
@@ -19,7 +19,7 @@ package com.cloud.network;
import java.util.List;
import java.util.Map;
-import com.cloud.dc.DataCenter;
+import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
@@ -38,13 +38,16 @@ import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
+import com.cloud.agent.api.to.NicTO;
+import com.cloud.dc.DataCenter;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
@@ -56,7 +59,6 @@ import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.Nic;
import com.cloud.vm.NicSecondaryIp;
-import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
/**
* The NetworkService interface is the "public" api to entities that make requests to the orchestration engine
@@ -102,6 +104,10 @@ public interface NetworkService {
Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException;
+ Network createGuestNetwork(long networkOfferingId, String name, String displayText, Account owner,
+ PhysicalNetwork physicalNetwork, long zoneId, ControlledEntity.ACLType aclType) throws
+ InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException;
+
Pair, Integer> searchForNetworks(ListNetworksCmd cmd);
boolean deleteNetwork(long networkId, boolean forced);
@@ -263,4 +269,10 @@ public interface NetworkService {
InternalLoadBalancerElementService getInternalLoadBalancerElementByNetworkServiceProviderId(long networkProviderId);
InternalLoadBalancerElementService getInternalLoadBalancerElementById(long providerId);
List getInternalLoadBalancerElements();
+
+ boolean handleCksIsoOnNetworkVirtualRouter(Long virtualRouterId, boolean mount) throws ResourceUnavailableException;
+
+ IpAddresses getIpAddressesFromIps(String ipAddress, String ip6Address, String macAddress);
+
+ String getNicVlanValueForExternalVm(NicTO nic);
}
diff --git a/api/src/main/java/com/cloud/network/Networks.java b/api/src/main/java/com/cloud/network/Networks.java
index dfa0ddb84ca..9f06a044111 100644
--- a/api/src/main/java/com/cloud/network/Networks.java
+++ b/api/src/main/java/com/cloud/network/Networks.java
@@ -129,7 +129,8 @@ public class Networks {
UnDecided(null, null),
OpenDaylight("opendaylight", String.class),
TUNGSTEN("tf", String.class),
- NSX("nsx", String.class);
+ NSX("nsx", String.class),
+ Netris("netris", String.class);
private final String scheme;
private final Class> type;
diff --git a/api/src/main/java/com/cloud/network/SDNProviderNetworkRule.java b/api/src/main/java/com/cloud/network/SDNProviderNetworkRule.java
new file mode 100644
index 00000000000..a22db4287dc
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/SDNProviderNetworkRule.java
@@ -0,0 +1,358 @@
+// 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.network;
+
+import java.util.List;
+
+public class SDNProviderNetworkRule {
+
+ protected long domainId;
+ protected long accountId;
+ protected long zoneId;
+ protected Long networkResourceId;
+ protected String networkResourceName;
+ protected boolean isVpcResource;
+ protected long vmId;
+ protected long ruleId;
+ protected String publicIp;
+ protected String vmIp;
+ protected String publicPort;
+ protected String privatePort;
+ protected String protocol;
+ protected String algorithm;
+ protected List sourceCidrList;
+ protected List destinationCidrList;
+ protected Integer icmpCode;
+
+ protected Integer icmpType;
+ protected String trafficType;
+ protected Network.Service service;
+
+ public long getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(long domainId) {
+ this.domainId = domainId;
+ }
+
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(long accountId) {
+ this.accountId = accountId;
+ }
+
+ public long getZoneId() {
+ return zoneId;
+ }
+
+ public void setZoneId(long zoneId) {
+ this.zoneId = zoneId;
+ }
+
+ public Long getNetworkResourceId() {
+ return networkResourceId;
+ }
+
+ public void setNetworkResourceId(Long networkResourceId) {
+ this.networkResourceId = networkResourceId;
+ }
+
+ public String getNetworkResourceName() {
+ return networkResourceName;
+ }
+
+ public void setNetworkResourceName(String networkResourceName) {
+ this.networkResourceName = networkResourceName;
+ }
+
+ public boolean isVpcResource() {
+ return isVpcResource;
+ }
+
+ public void setVpcResource(boolean vpcResource) {
+ isVpcResource = vpcResource;
+ }
+
+ public long getVmId() {
+ return vmId;
+ }
+
+ public void setVmId(long vmId) {
+ this.vmId = vmId;
+ }
+
+ public long getRuleId() {
+ return ruleId;
+ }
+
+ public void setRuleId(long ruleId) {
+ this.ruleId = ruleId;
+ }
+
+ public String getPublicIp() {
+ return publicIp;
+ }
+
+ public void setPublicIp(String publicIp) {
+ this.publicIp = publicIp;
+ }
+
+ public String getVmIp() {
+ return vmIp;
+ }
+
+ public void setVmIp(String vmIp) {
+ this.vmIp = vmIp;
+ }
+
+ public String getPublicPort() {
+ return publicPort;
+ }
+
+ public void setPublicPort(String publicPort) {
+ this.publicPort = publicPort;
+ }
+
+ public String getPrivatePort() {
+ return privatePort;
+ }
+
+ public void setPrivatePort(String privatePort) {
+ this.privatePort = privatePort;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public void setAlgorithm(String algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ public Network.Service getService() {
+ return service;
+ }
+
+ public void setService(Network.Service service) {
+ this.service = service;
+ }
+
+ public Integer getIcmpCode() {
+ return icmpCode;
+ }
+
+ public void setIcmpCode(Integer icmpCode) {
+ this.icmpCode = icmpCode;
+ }
+
+ public Integer getIcmpType() {
+ return icmpType;
+ }
+
+ public void setIcmpType(Integer icmpType) {
+ this.icmpType = icmpType;
+ }
+
+ public List getSourceCidrList() {
+ return sourceCidrList;
+ }
+
+ public void setSourceCidrList(List sourceCidrList) {
+ this.sourceCidrList = sourceCidrList;
+ }
+
+ public List getDestinationCidrList() {
+ return destinationCidrList;
+ }
+
+ public void setDestinationCidrList(List destinationCidrList) {
+ this.destinationCidrList = destinationCidrList;
+ }
+
+ public String getTrafficType() {
+ return trafficType;
+ }
+
+ public void setTrafficType(String trafficType) {
+ this.trafficType = trafficType;
+ }
+
+ public static class Builder {
+ public long domainId;
+ public long accountId;
+ public long zoneId;
+ public Long networkResourceId;
+ public String networkResourceName;
+ public boolean isVpcResource;
+ public long vmId;
+
+ public long ruleId;
+ public String publicIp;
+ public String vmIp;
+ public String publicPort;
+ public String privatePort;
+ public String protocol;
+ public String algorithm;
+ public List sourceCidrList;
+ public List destinationCidrList;
+ public String trafficType;
+ public Integer icmpType;
+ public Integer icmpCode;
+ public Network.Service service;
+
+ public Builder() {
+ // Default constructor
+ }
+
+ public Builder setDomainId(long domainId) {
+ this.domainId = domainId;
+ return this;
+ }
+
+ public Builder setAccountId(long accountId) {
+ this.accountId = accountId;
+ return this;
+ }
+
+ public Builder setZoneId(long zoneId) {
+ this.zoneId = zoneId;
+ return this;
+ }
+
+ public Builder setNetworkResourceId(Long networkResourceId) {
+ this.networkResourceId = networkResourceId;
+ return this;
+ }
+
+ public Builder setNetworkResourceName(String networkResourceName) {
+ this.networkResourceName = networkResourceName;
+ return this;
+ }
+
+ public Builder setVpcResource(boolean isVpcResource) {
+ this.isVpcResource = isVpcResource;
+ return this;
+ }
+
+
+ public Builder setVmId(long vmId) {
+ this.vmId = vmId;
+ return this;
+ }
+
+ public Builder setRuleId(long ruleId) {
+ this.ruleId = ruleId;
+ return this;
+ }
+
+ public Builder setPublicIp(String publicIp) {
+ this.publicIp = publicIp;
+ return this;
+ }
+
+ public Builder setVmIp(String vmIp) {
+ this.vmIp = vmIp;
+ return this;
+ }
+
+ public Builder setPublicPort(String publicPort) {
+ this.publicPort = publicPort;
+ return this;
+ }
+
+ public Builder setPrivatePort(String privatePort) {
+ this.privatePort = privatePort;
+ return this;
+ }
+
+ public Builder setProtocol(String protocol) {
+ this.protocol = protocol;
+ return this;
+ }
+
+ public Builder setAlgorithm(String algorithm) {
+ this.algorithm = algorithm;
+ return this;
+ }
+
+ public Builder setTrafficType(String trafficType) {
+ this.trafficType = trafficType;
+ return this;
+ }
+
+ public Builder setIcmpType(Integer icmpType) {
+ this.icmpType = icmpType;
+ return this;
+ }
+
+ public Builder setIcmpCode(Integer icmpCode) {
+ this.icmpCode = icmpCode;
+ return this;
+ }
+
+ public Builder setSourceCidrList(List sourceCidrList) {
+ this.sourceCidrList = sourceCidrList;
+ return this;
+ }
+
+ public Builder setDestinationCidrList(List destinationCidrList) {
+ this.destinationCidrList = destinationCidrList;
+ return this;
+ }
+
+ public Builder setService(Network.Service service) {
+ this.service = service;
+ return this;
+ }
+
+ public SDNProviderNetworkRule build() {
+ SDNProviderNetworkRule rule = new SDNProviderNetworkRule();
+ rule.setDomainId(this.domainId);
+ rule.setAccountId(this.accountId);
+ rule.setZoneId(this.zoneId);
+ rule.setNetworkResourceId(this.networkResourceId);
+ rule.setNetworkResourceName(this.networkResourceName);
+ rule.setVpcResource(this.isVpcResource);
+ rule.setVmId(this.vmId);
+ rule.setVmIp(this.vmIp);
+ rule.setPublicIp(this.publicIp);
+ rule.setPublicPort(this.publicPort);
+ rule.setPrivatePort(this.privatePort);
+ rule.setProtocol(this.protocol);
+ rule.setRuleId(this.ruleId);
+ rule.setAlgorithm(this.algorithm);
+ rule.setIcmpType(this.icmpType);
+ rule.setIcmpCode(this.icmpCode);
+ rule.setSourceCidrList(this.sourceCidrList);
+ rule.setDestinationCidrList(this.destinationCidrList);
+ rule.setTrafficType(this.trafficType);
+ rule.setService(service);
+ return rule;
+ }
+ }
+}
diff --git a/api/src/main/java/com/cloud/network/Site2SiteVpnConnection.java b/api/src/main/java/com/cloud/network/Site2SiteVpnConnection.java
index 994df875f7d..51036abe060 100644
--- a/api/src/main/java/com/cloud/network/Site2SiteVpnConnection.java
+++ b/api/src/main/java/com/cloud/network/Site2SiteVpnConnection.java
@@ -24,7 +24,7 @@ import org.apache.cloudstack.api.InternalIdentity;
public interface Site2SiteVpnConnection extends ControlledEntity, InternalIdentity, Displayable {
enum State {
- Pending, Connecting, Connected, Disconnected, Error,
+ Pending, Connecting, Connected, Disconnected, Error, Removed
}
@Override
diff --git a/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java b/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java
index c47500c7849..cb92739d283 100644
--- a/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java
+++ b/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java
@@ -17,17 +17,22 @@
package com.cloud.network;
import java.util.List;
+import java.util.Map;
import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd;
import org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd;
+import com.cloud.deploy.DeploymentPlanner;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.router.VirtualRouter;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.vm.Nic;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
public interface VirtualNetworkApplianceService {
/**
@@ -62,6 +67,10 @@ public interface VirtualNetworkApplianceService {
VirtualRouter startRouter(long id) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException;
+ void startRouterForHA(VirtualMachine vm, Map params, DeploymentPlanner planner)
+ throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException,
+ OperationTimedoutException;
+
VirtualRouter destroyRouter(long routerId, Account caller, Long callerUserId) throws ResourceUnavailableException, ConcurrentOperationException;
VirtualRouter findRouter(long routerId);
diff --git a/api/src/main/java/com/cloud/network/VpcVirtualNetworkApplianceService.java b/api/src/main/java/com/cloud/network/VpcVirtualNetworkApplianceService.java
index 5c3ee3f1032..cd04db802ca 100644
--- a/api/src/main/java/com/cloud/network/VpcVirtualNetworkApplianceService.java
+++ b/api/src/main/java/com/cloud/network/VpcVirtualNetworkApplianceService.java
@@ -29,7 +29,6 @@ public interface VpcVirtualNetworkApplianceService extends VirtualNetworkApplian
/**
* @param router
* @param network
- * @param isRedundant
* @param params TODO
* @return
* @throws ConcurrentOperationException
@@ -42,11 +41,30 @@ public interface VpcVirtualNetworkApplianceService extends VirtualNetworkApplian
/**
* @param router
* @param network
- * @param isRedundant
* @return
* @throws ConcurrentOperationException
* @throws ResourceUnavailableException
*/
boolean removeVpcRouterFromGuestNetwork(VirtualRouter router, Network network) throws ConcurrentOperationException, ResourceUnavailableException;
+
+ /**
+ * @param router
+ * @param network
+ * @return
+ * @throws ConcurrentOperationException
+ * @throws ResourceUnavailableException
+ */
+ boolean stopKeepAlivedOnRouter(VirtualRouter router, Network network) throws ConcurrentOperationException, ResourceUnavailableException;
+
+
+ /**
+ * @param router
+ * @param network
+ * @return
+ * @throws ConcurrentOperationException
+ * @throws ResourceUnavailableException
+ */
+ boolean startKeepAlivedOnRouter(VirtualRouter router, Network network) throws ConcurrentOperationException, ResourceUnavailableException;
+
}
diff --git a/api/src/main/java/com/cloud/network/element/BgpServiceProvider.java b/api/src/main/java/com/cloud/network/element/BgpServiceProvider.java
new file mode 100644
index 00000000000..ee919cb1af7
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/element/BgpServiceProvider.java
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network.element;
+
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.Network;
+import com.cloud.network.vpc.Vpc;
+
+import org.apache.cloudstack.network.BgpPeer;
+
+import java.util.List;
+
+public interface BgpServiceProvider extends NetworkElement {
+
+ boolean applyBgpPeers(Vpc vpc, Network network, List extends BgpPeer> bgpPeers) throws ResourceUnavailableException;
+
+}
diff --git a/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java b/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java
index 1bb37be970d..dc0f60f4519 100644
--- a/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java
+++ b/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java
@@ -48,4 +48,7 @@ public interface LoadBalancingServiceProvider extends NetworkElement, IpDeployin
List updateHealthChecks(Network network, List lbrules);
boolean handlesOnlyRulesInTransitionState();
+
+ default void expungeLbVmRefs(List vmIds, Long batchSize) {
+ }
}
diff --git a/api/src/main/java/com/cloud/network/element/NetworkElement.java b/api/src/main/java/com/cloud/network/element/NetworkElement.java
index fa67575edd3..cb0fc2fca98 100644
--- a/api/src/main/java/com/cloud/network/element/NetworkElement.java
+++ b/api/src/main/java/com/cloud/network/element/NetworkElement.java
@@ -23,6 +23,7 @@ import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
@@ -87,6 +88,14 @@ public interface NetworkElement extends Adapter {
boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException;
+ /**
+ * Release IP from the network provider if reserved
+ * @param ipAddress
+ */
+ default boolean releaseIp(IpAddress ipAddress) {
+ return true;
+ }
+
/**
* The network is being shutdown.
* @param network
diff --git a/api/src/main/java/com/cloud/network/element/PortForwardingServiceProvider.java b/api/src/main/java/com/cloud/network/element/PortForwardingServiceProvider.java
index e99bc2fd416..8dcc8b6d0a4 100644
--- a/api/src/main/java/com/cloud/network/element/PortForwardingServiceProvider.java
+++ b/api/src/main/java/com/cloud/network/element/PortForwardingServiceProvider.java
@@ -17,12 +17,40 @@
package com.cloud.network.element;
import java.util.List;
+import java.util.Objects;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
+import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.PortForwardingRule;
+import com.cloud.network.vpc.NetworkACLItem;
public interface PortForwardingServiceProvider extends NetworkElement, IpDeployingRequester {
+
+ static String getPublicPortRange(PortForwardingRule rule) {
+ return Objects.equals(rule.getSourcePortStart(), rule.getSourcePortEnd()) ?
+ String.valueOf(rule.getSourcePortStart()) :
+ String.valueOf(rule.getSourcePortStart()).concat("-").concat(String.valueOf(rule.getSourcePortEnd()));
+ }
+
+ static String getPrivatePFPortRange(PortForwardingRule rule) {
+ return rule.getDestinationPortStart() == rule.getDestinationPortEnd() ?
+ String.valueOf(rule.getDestinationPortStart()) :
+ String.valueOf(rule.getDestinationPortStart()).concat("-").concat(String.valueOf(rule.getDestinationPortEnd()));
+ }
+
+ static String getPrivatePortRange(FirewallRule rule) {
+ return Objects.equals(rule.getSourcePortStart(), rule.getSourcePortEnd()) ?
+ String.valueOf(rule.getSourcePortStart()) :
+ String.valueOf(rule.getSourcePortStart()).concat("-").concat(String.valueOf(rule.getSourcePortEnd()));
+ }
+
+ static String getPrivatePortRangeForACLRule(NetworkACLItem rule) {
+ return Objects.equals(rule.getSourcePortStart(), rule.getSourcePortEnd()) ?
+ String.valueOf(rule.getSourcePortStart()) :
+ String.valueOf(rule.getSourcePortStart()).concat("-").concat(String.valueOf(rule.getSourcePortEnd()));
+ }
+
/**
* Apply rules
* @param network
diff --git a/api/src/main/java/com/cloud/network/element/VpcProvider.java b/api/src/main/java/com/cloud/network/element/VpcProvider.java
index 6debd1fbc2d..fe8c8f8612f 100644
--- a/api/src/main/java/com/cloud/network/element/VpcProvider.java
+++ b/api/src/main/java/com/cloud/network/element/VpcProvider.java
@@ -55,4 +55,8 @@ public interface VpcProvider extends NetworkElement {
boolean applyACLItemsToPrivateGw(PrivateGateway gateway, List extends NetworkACLItem> rules) throws ResourceUnavailableException;
boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address);
+
+ default boolean updateVpc(Vpc vpc, String previousVpcName) {
+ return true;
+ }
}
diff --git a/api/src/main/java/com/cloud/network/guru/NetworkGuru.java b/api/src/main/java/com/cloud/network/guru/NetworkGuru.java
index cbadbb18a8f..ced664e54a9 100644
--- a/api/src/main/java/com/cloud/network/guru/NetworkGuru.java
+++ b/api/src/main/java/com/cloud/network/guru/NetworkGuru.java
@@ -212,4 +212,11 @@ public interface NetworkGuru extends Adapter {
boolean isMyTrafficType(TrafficType type);
+ default boolean isSlaacV6Only() {
+ return true;
+ }
+
+ default boolean update(Network network, String prevNetworkName) {
+ return true;
+ }
}
diff --git a/api/src/main/java/com/cloud/network/lb/LoadBalancingRule.java b/api/src/main/java/com/cloud/network/lb/LoadBalancingRule.java
index 64b2aeedf12..e4cf4ec526f 100644
--- a/api/src/main/java/com/cloud/network/lb/LoadBalancingRule.java
+++ b/api/src/main/java/com/cloud/network/lb/LoadBalancingRule.java
@@ -63,6 +63,10 @@ public class LoadBalancingRule {
return lb.getId();
}
+ public LoadBalancer getLb() {
+ return lb;
+ }
+
public String getName() {
return lb.getName();
}
diff --git a/api/src/main/java/com/cloud/network/netris/NetrisLbBackend.java b/api/src/main/java/com/cloud/network/netris/NetrisLbBackend.java
new file mode 100644
index 00000000000..afc21f7f511
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/netris/NetrisLbBackend.java
@@ -0,0 +1,41 @@
+// 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.network.netris;
+
+public class NetrisLbBackend {
+ private long vmId;
+ private String vmIp;
+ private int port;
+
+ public NetrisLbBackend(long vmId, String vmIp, int port) {
+ this.vmId = vmId;
+ this.vmIp = vmIp;
+ this.port = port;
+ }
+
+ public long getVmId() {
+ return vmId;
+ }
+
+ public String getVmIp() {
+ return vmIp;
+ }
+
+ public int getPort() {
+ return port;
+ }
+}
diff --git a/api/src/main/java/com/cloud/network/netris/NetrisNetworkRule.java b/api/src/main/java/com/cloud/network/netris/NetrisNetworkRule.java
new file mode 100644
index 00000000000..211517ead49
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/netris/NetrisNetworkRule.java
@@ -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 com.cloud.network.netris;
+
+import com.cloud.network.SDNProviderNetworkRule;
+
+
+import java.util.List;
+
+public class NetrisNetworkRule {
+ public enum NetrisRuleAction {
+ PERMIT, DENY
+ }
+
+ private SDNProviderNetworkRule baseRule;
+ private NetrisRuleAction aclAction;
+ private List lbBackends;
+ private String lbRuleName;
+ private String lbCidrList;
+ private String reason;
+
+ public NetrisNetworkRule(Builder builder) {
+ this.baseRule = builder.baseRule;
+ this.aclAction = builder.aclAction;
+ this.lbBackends = builder.lbBackends;
+ this.reason = builder.reason;
+ this.lbCidrList = builder.lbCidrList;
+ this.lbRuleName = builder.lbRuleName;
+ }
+
+ public NetrisRuleAction getAclAction() {
+ return aclAction;
+ }
+
+ public List getLbBackends() {
+ return lbBackends;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public String getLbCidrList() {return lbCidrList; }
+
+ public String getLbRuleName() { return lbRuleName; }
+
+ public SDNProviderNetworkRule getBaseRule() {
+ return baseRule;
+ }
+
+ // Builder class extending the parent builder
+ public static class Builder {
+ private SDNProviderNetworkRule baseRule;
+ private NetrisRuleAction aclAction;
+ private List lbBackends;
+ private String reason;
+ private String lbCidrList;
+ private String lbRuleName;
+
+ public Builder baseRule(SDNProviderNetworkRule baseRule) {
+ this.baseRule = baseRule;
+ return this;
+ }
+
+ public Builder aclAction(NetrisRuleAction aclAction) {
+ this.aclAction = aclAction;
+ return this;
+ }
+
+ public Builder lbBackends(List lbBackends) {
+ this.lbBackends = lbBackends;
+ return this;
+ }
+
+ public Builder reason(String reason) {
+ this.reason = reason;
+ return this;
+ }
+
+ public Builder lbCidrList(String lbCidrList) {
+ this.lbCidrList = lbCidrList;
+ return this;
+ }
+
+ public Builder lbRuleName(String lbRuleName) {
+ this.lbRuleName = lbRuleName;
+ return this;
+ }
+
+ public NetrisNetworkRule build() {
+ return new NetrisNetworkRule(this);
+ }
+ }
+}
diff --git a/api/src/main/java/com/cloud/network/netris/NetrisProvider.java b/api/src/main/java/com/cloud/network/netris/NetrisProvider.java
new file mode 100644
index 00000000000..fccf2930e97
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/netris/NetrisProvider.java
@@ -0,0 +1,30 @@
+// 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.network.netris;
+
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface NetrisProvider extends InternalIdentity, Identity {
+ long getZoneId();
+ String getName();
+ String getUrl();
+ String getUsername();
+ String getSiteName();
+ String getTenantName();
+ String getNetrisTag();
+}
diff --git a/api/src/main/java/com/cloud/network/netris/NetrisService.java b/api/src/main/java/com/cloud/network/netris/NetrisService.java
new file mode 100644
index 00000000000..110e9f07105
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/netris/NetrisService.java
@@ -0,0 +1,310 @@
+// 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.network.netris;
+
+import com.cloud.network.IpAddress;
+import com.cloud.network.Network;
+import com.cloud.network.SDNProviderNetworkRule;
+import com.cloud.network.vpc.StaticRoute;
+import com.cloud.network.vpc.Vpc;
+
+import java.util.List;
+
+/**
+ * Interface for Netris Services that provides methods to manage VPCs, networks,
+ * NAT rules, network rules, and static routes in an SDN (Software Defined Networking) environment.
+ */
+
+public interface NetrisService {
+
+ /**
+ * Creates IPAM (IP Address Management) allocations for zone-level public ranges.
+ *
+ * @param zoneId the ID of the zone
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createIPAMAllocationsForZoneLevelPublicRanges(long zoneId);
+
+ /**
+ * Creates a VPC (Virtual Private Cloud) resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcId the ID of the VPC
+ * @param vpcName the name of the VPC
+ * @param sourceNatEnabled true if source NAT is enabled
+ * @param cidr the CIDR of the VPC
+ * @param isVpcNetwork true if it is a VPC network
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createVpcResource(long zoneId, long accountId, long domainId, Long vpcId, String vpcName, boolean sourceNatEnabled, String cidr, boolean isVpcNetwork);
+
+ /**
+ * Updates an existing VPC resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcId the ID of the VPC
+ * @param vpcName the new name of the VPC
+ * @param previousVpcName the previous name of the VPC
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean updateVpcResource(long zoneId, long accountId, long domainId, Long vpcId, String vpcName, String previousVpcName);
+
+ /**
+ * Deletes a VPC resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpc the VPC to delete
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteVpcResource(long zoneId, long accountId, long domainId, Vpc vpc);
+
+ /**
+ * Creates a virtual network (vNet) resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the name of the network
+ * @param networkId the ID of the network
+ * @param cidr the CIDR of the network
+ * @param globalRouting true if global routing is enabled
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr, Boolean globalRouting);
+
+ /**
+ * Updates an existing vNet resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the new name of the network
+ * @param networkId the ID of the network
+ * @param prevNetworkName the previous name of the network
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean updateVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String prevNetworkName);
+
+ /**
+ * Deletes an existing vNet resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the name of the network
+ * @param networkId the ID of the network
+ * @param cidr the CIDR of the network
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteVnetResource(long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr);
+
+ /**
+ * Creates a source NAT rule for a VPC or network.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the name of the network
+ * @param networkId the ID of the network
+ * @param isForVpc true if the rule applies to a VPC
+ * @param vpcCidr the VPC CIDR
+ * @param sourceNatIp the source NAT IP
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createSnatRule(long zoneId, long accountId, long domainId, String vpcName, long vpcId, String networkName, long networkId, boolean isForVpc, String vpcCidr, String sourceNatIp);
+
+ /**
+ * Creates a port forwarding rule for a VPC or network.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the name of the network
+ * @param networkId the ID of the network
+ * @param isForVpc true if the rule applies to a VPC
+ * @param vpcCidr the VPC CIDR
+ * @param networkRule the network rule to forward
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createPortForwardingRule(long zoneId, long accountId, long domainId, String vpcName, long vpcId, String networkName, Long networkId, boolean isForVpc, String vpcCidr, SDNProviderNetworkRule networkRule);
+
+ /**
+ * Deletes a port forwarding rule for a VPC or network.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the name of the network
+ * @param networkId the ID of the network
+ * @param isForVpc true if the rule applies to a VPC
+ * @param vpcCidr the VPC CIDR
+ * @param networkRule the network rule to remove
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deletePortForwardingRule(long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, boolean isForVpc, String vpcCidr, SDNProviderNetworkRule networkRule);
+
+ /**
+ * Updates the source NAT IP for a specified VPC.
+ *
+ * @param vpc the VPC to updates
+ * @param address the new source NAT IP address
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address);
+
+ /**
+ * Creates a static NAT rule for a specific VM.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param networkResourceName the name of the network resource
+ * @param networkResourceId the ID of the network resource
+ * @param isForVpc true if the rule applies to a VPC
+ * @param vpcCidr the VPC CIDR
+ * @param staticNatIp the static NAT IP
+ * @param vmIp the VM's IP address
+ * @param vmId the ID of the VM
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createStaticNatRule(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String vpcCidr, String staticNatIp, String vmIp, long vmId);
+
+ /**
+ * Deletes a static NAT rule for a specific VM.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param networkResourceName the name of the network resource
+ * @param networkResourceId the ID of the network resource
+ * @param isForVpc true if the rule applies to a VPC
+ * @param staticNatIp the static NAT IP
+ * @param vmId the ID of the VM
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteStaticNatRule(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String staticNatIp, long vmId);
+
+ /**
+ * Adds firewall rules to a specific network.
+ *
+ * @param network the target network
+ * @param firewallRules the list of firewall rules to add
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean addFirewallRules(Network network, List firewallRules);
+
+ /**
+ * Deletes firewall rules from a specific network.
+ *
+ * @param network the target network
+ * @param firewallRules the list of firewall rules to delete
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteFirewallRules(Network network, List firewallRules);
+
+ /**
+ * Adds or updates a static route for a specific network or VPC.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param networkResourceName the name of the network resource
+ * @param networkResourceId the ID of the network resource
+ * @param isForVpc true if it is for a VPC
+ * @param prefix the IP prefix of the route
+ * @param nextHop the next hop address
+ * @param routeId the ID of the route
+ * @param updateRoute true if the route should be updated
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean addOrUpdateStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId, boolean updateRoute);
+
+ /**
+ * Deletes a specific static route for a network or VPC.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param networkResourceName the name of the network resource
+ * @param networkResourceId the ID of the network resource
+ * @param isForVpc true if it is for a VPC
+ * @param prefix the IP prefix of the route
+ * @param nextHop the next hop address
+ * @param routeId the ID of the route
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId);
+
+ /**
+ * Lists static routes for a specific network or VPC.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param networkResourceName the name of the network resource
+ * @param networkResourceId the ID of the network resource
+ * @param isForVpc true if it is for a VPC
+ * @param prefix the IP prefix of the route
+ * @param nextHop the next hop address
+ * @param routeId the ID of the route
+ * @return a list of static routes
+ */
+ List listStaticRoutes(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId);
+
+ /**
+ * Releases a NAT IP address.
+ *
+ * @param zoneId the ID of the zone
+ * @param publicIp the public NAT IP to release
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean releaseNatIp(long zoneId, String publicIp);
+
+ /**
+ * Creates or updates a load balancer (LB) rule.
+ *
+ * @param rule the network rule for the load balancer
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createOrUpdateLbRule(NetrisNetworkRule rule);
+
+ /**
+ * Deletes a load balancer (LB) rule.
+ *
+ * @param rule the network rule to delete
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteLbRule(NetrisNetworkRule rule);
+}
diff --git a/api/src/main/java/com/cloud/network/nsx/NsxService.java b/api/src/main/java/com/cloud/network/nsx/NsxService.java
index 79ad9547c73..1adb7461cc0 100644
--- a/api/src/main/java/com/cloud/network/nsx/NsxService.java
+++ b/api/src/main/java/com/cloud/network/nsx/NsxService.java
@@ -16,11 +16,23 @@
// under the License.
package com.cloud.network.nsx;
+import org.apache.cloudstack.framework.config.ConfigKey;
+
import com.cloud.network.IpAddress;
import com.cloud.network.vpc.Vpc;
public interface NsxService {
+ ConfigKey NSX_API_FAILURE_RETRIES = new ConfigKey<>("Advanced", Integer.class,
+ "nsx.api.failure.retries", "30",
+ "Number of retries for NSX API operations in case of failures",
+ true, ConfigKey.Scope.Zone);
+ ConfigKey NSX_API_FAILURE_INTERVAL = new ConfigKey<>("Advanced", Integer.class,
+ "nsx.api.failure.interval", "60",
+ "Waiting time (in seconds) before retrying an NSX API operation in case of failure",
+ true, ConfigKey.Scope.Zone);
+
boolean createVpcNetwork(Long zoneId, long accountId, long domainId, Long vpcId, String vpcName, boolean sourceNatEnabled);
boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address);
+ String getSegmentId(long domainId, long accountId, long zoneId, Long vpcId, long networkId);
}
diff --git a/api/src/main/java/com/cloud/network/rules/RulesService.java b/api/src/main/java/com/cloud/network/rules/RulesService.java
index 0b4afeef945..547d4ab51e0 100644
--- a/api/src/main/java/com/cloud/network/rules/RulesService.java
+++ b/api/src/main/java/com/cloud/network/rules/RulesService.java
@@ -26,6 +26,7 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.utils.net.Ip;
+import org.apache.cloudstack.api.command.user.firewall.UpdatePortForwardingRuleCmd;
public interface RulesService {
Pair, Integer> searchStaticNatRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId,
@@ -81,6 +82,8 @@ public interface RulesService {
boolean disableStaticNat(long ipId) throws ResourceUnavailableException, NetworkRuleConflictException, InsufficientAddressCapacityException;
- PortForwardingRule updatePortForwardingRule(long id, Integer privatePort, Integer privateEndPort, Long virtualMachineId, Ip vmGuestIp, String customId, Boolean forDisplay);
+ PortForwardingRule updatePortForwardingRule(UpdatePortForwardingRuleCmd cmd);
+
+ void validatePortForwardingSourceCidrList(List sourceCidrList);
}
diff --git a/api/src/main/java/com/cloud/network/vpc/StaticRoute.java b/api/src/main/java/com/cloud/network/vpc/StaticRoute.java
index 5707ca14024..739fca328b8 100644
--- a/api/src/main/java/com/cloud/network/vpc/StaticRoute.java
+++ b/api/src/main/java/com/cloud/network/vpc/StaticRoute.java
@@ -25,6 +25,7 @@ public interface StaticRoute extends ControlledEntity, Identity, InternalIdentit
Staged, // route been created but has never got through network rule conflict detection. Routes in this state can not be sent to VPC virtual router.
Add, // Add means the route has been created and has gone through network rule conflict detection.
Active, // Route has been sent to the VPC router and reported to be active.
+ Update,
Revoke, // Revoke means this route has been revoked. If this route has been sent to the VPC router, the route will be deleted from database.
Deleting // rule has been revoked and is scheduled for deletion
}
@@ -32,7 +33,9 @@ public interface StaticRoute extends ControlledEntity, Identity, InternalIdentit
/**
* @return
*/
- long getVpcGatewayId();
+ Long getVpcGatewayId();
+
+ String getNextHop();
/**
* @return
diff --git a/api/src/main/java/com/cloud/network/vpc/StaticRouteProfile.java b/api/src/main/java/com/cloud/network/vpc/StaticRouteProfile.java
index cb4849f1f7b..c8fc073911f 100644
--- a/api/src/main/java/com/cloud/network/vpc/StaticRouteProfile.java
+++ b/api/src/main/java/com/cloud/network/vpc/StaticRouteProfile.java
@@ -23,7 +23,8 @@ public class StaticRouteProfile implements StaticRoute {
private String targetCidr;
private long accountId;
private long domainId;
- private long gatewayId;
+ private Long gatewayId;
+ private String nextHop;
private StaticRoute.State state;
private long vpcId;
String vlanTag;
@@ -46,6 +47,18 @@ public class StaticRouteProfile implements StaticRoute {
ipAddress = gateway.getIp4Address();
}
+ public StaticRouteProfile(StaticRoute staticRoute) {
+ id = staticRoute.getId();
+ uuid = staticRoute.getUuid();
+ targetCidr = staticRoute.getCidr();
+ accountId = staticRoute.getAccountId();
+ domainId = staticRoute.getDomainId();
+ gatewayId = staticRoute.getVpcGatewayId();
+ state = staticRoute.getState();
+ vpcId = staticRoute.getVpcId();
+ gateway = staticRoute.getNextHop();
+ }
+
@Override
public long getAccountId() {
return accountId;
@@ -57,10 +70,15 @@ public class StaticRouteProfile implements StaticRoute {
}
@Override
- public long getVpcGatewayId() {
+ public Long getVpcGatewayId() {
return gatewayId;
}
+ @Override
+ public String getNextHop() {
+ return nextHop;
+ }
+
@Override
public String getCidr() {
return targetCidr;
diff --git a/api/src/main/java/com/cloud/network/vpc/Vpc.java b/api/src/main/java/com/cloud/network/vpc/Vpc.java
index e9a831c9d83..b94089d2d43 100644
--- a/api/src/main/java/com/cloud/network/vpc/Vpc.java
+++ b/api/src/main/java/com/cloud/network/vpc/Vpc.java
@@ -105,4 +105,6 @@ public interface Vpc extends ControlledEntity, Identity, InternalIdentity {
String getIp6Dns1();
String getIp6Dns2();
+
+ boolean useRouterIpAsResolver();
}
diff --git a/api/src/main/java/com/cloud/network/vpc/VpcOffering.java b/api/src/main/java/com/cloud/network/vpc/VpcOffering.java
index 3aab57d5d3d..17f49bb3652 100644
--- a/api/src/main/java/com/cloud/network/vpc/VpcOffering.java
+++ b/api/src/main/java/com/cloud/network/vpc/VpcOffering.java
@@ -18,6 +18,7 @@ package com.cloud.network.vpc;
import java.util.Date;
+import com.cloud.offering.NetworkOffering;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@@ -31,6 +32,8 @@ public interface VpcOffering extends InternalIdentity, Identity {
public static final String redundantVPCOfferingName = "Redundant VPC offering";
public static final String DEFAULT_VPC_NAT_NSX_OFFERING_NAME = "VPC offering with NSX - NAT Mode";
public static final String DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME = "VPC offering with NSX - Route Mode";
+ public static final String DEFAULT_VPC_ROUTE_NETRIS_OFFERING_NAME = "VPC offering with Netris - Route Mode";
+ public static final String DEFAULT_VPC_NAT_NETRIS_OFFERING_NAME = "VPC offering with Netris - NAT Mode";
/**
*
@@ -55,9 +58,7 @@ public interface VpcOffering extends InternalIdentity, Identity {
*/
boolean isDefault();
- boolean isForNsx();
-
- String getNsxMode();
+ NetworkOffering.NetworkMode getNetworkMode();
/**
* @return service offering id used by VPC virtual router
@@ -79,4 +80,8 @@ public interface VpcOffering extends InternalIdentity, Identity {
Date getRemoved();
Date getCreated();
+
+ NetworkOffering.RoutingMode getRoutingMode();
+
+ Boolean isSpecifyAsNumber();
}
diff --git a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
index 1ce3cf8ab0e..97b95339ecf 100644
--- a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
+++ b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
@@ -24,6 +24,7 @@ import org.apache.cloudstack.api.command.admin.vpc.CreateVPCOfferingCmd;
import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCOfferingCmd;
import org.apache.cloudstack.api.command.user.vpc.ListVPCOfferingsCmd;
+import com.cloud.offering.NetworkOffering;
import com.cloud.utils.Pair;
import com.cloud.utils.net.NetUtils;
@@ -36,8 +37,10 @@ public interface VpcProvisioningService {
VpcOffering createVpcOffering(String name, String displayText, List supportedServices,
Map> serviceProviders,
Map serviceCapabilitystList, NetUtils.InternetProtocol internetProtocol,
- Long serviceOfferingId, Boolean forNsx, String mode,
- List domainIds, List zoneIds, VpcOffering.State state);
+ Long serviceOfferingId, String externalProvider, NetworkOffering.NetworkMode networkMode,
+ List domainIds, List zoneIds, VpcOffering.State state,
+ NetworkOffering.RoutingMode routingMode, boolean specifyAsNumber);
+
Pair,Integer> listVpcOfferings(ListVPCOfferingsCmd cmd);
diff --git a/api/src/main/java/com/cloud/network/vpc/VpcService.java b/api/src/main/java/com/cloud/network/vpc/VpcService.java
index 2cdc034a16e..c1546609d2b 100644
--- a/api/src/main/java/com/cloud/network/vpc/VpcService.java
+++ b/api/src/main/java/com/cloud/network/vpc/VpcService.java
@@ -48,16 +48,17 @@ public interface VpcService {
* @param vpcName
* @param displayText
* @param cidr
- * @param networkDomain TODO
+ * @param networkDomain TODO
* @param ip4Dns1
* @param ip4Dns2
- * @param displayVpc TODO
+ * @param displayVpc TODO
+ * @param useVrIpResolver
* @return
* @throws ResourceAllocationException TODO
*/
Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName, String displayText, String cidr, String networkDomain,
- String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Boolean displayVpc, Integer publicMtu)
- throws ResourceAllocationException;
+ String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Boolean displayVpc, Integer publicMtu, Integer cidrSize,
+ Long asNumber, List bgpPeerIds, Boolean useVrIpResolver) throws ResourceAllocationException;
/**
* Persists VPC record in the database
@@ -132,6 +133,8 @@ public interface VpcService {
*/
boolean startVpc(long vpcId, boolean destroyOnFailure) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException;
+ void startVpc(CreateVPCCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException;
+
/**
* Shuts down the VPC which includes shutting down all VPC provider and rules cleanup on the backend
*
@@ -235,7 +238,7 @@ public interface VpcService {
* @param cidr
* @return
*/
- StaticRoute createStaticRoute(long gatewayId, String cidr) throws NetworkRuleConflictException;
+ StaticRoute createStaticRoute(Long gatewayId, Long vpcId, String nextHop, String cidr) throws NetworkRuleConflictException;
/**
* Lists static routes based on parameters passed to the call
diff --git a/api/src/main/java/com/cloud/network/vpn/RemoteAccessVpnService.java b/api/src/main/java/com/cloud/network/vpn/RemoteAccessVpnService.java
index bbb9771d27a..ffa8af4576d 100644
--- a/api/src/main/java/com/cloud/network/vpn/RemoteAccessVpnService.java
+++ b/api/src/main/java/com/cloud/network/vpn/RemoteAccessVpnService.java
@@ -39,7 +39,7 @@ public interface RemoteAccessVpnService {
VpnUser addVpnUser(long vpnOwnerId, String userName, String password);
- boolean removeVpnUser(long vpnOwnerId, String userName, Account caller);
+ boolean removeVpnUser(Account vpnOwner, String userName, Account caller);
List extends VpnUser> listVpnUsers(long vpnOwnerId, String userName);
diff --git a/api/src/main/java/com/cloud/offering/DiskOfferingInfo.java b/api/src/main/java/com/cloud/offering/DiskOfferingInfo.java
index d83039e15c2..12dcf423e34 100644
--- a/api/src/main/java/com/cloud/offering/DiskOfferingInfo.java
+++ b/api/src/main/java/com/cloud/offering/DiskOfferingInfo.java
@@ -31,6 +31,13 @@ public class DiskOfferingInfo {
_diskOffering = diskOffering;
}
+ public DiskOfferingInfo(DiskOffering diskOffering, Long size, Long minIops, Long maxIops) {
+ _diskOffering = diskOffering;
+ _size = size;
+ _minIops = minIops;
+ _maxIops = maxIops;
+ }
+
public void setDiskOffering(DiskOffering diskOffering) {
_diskOffering = diskOffering;
}
diff --git a/api/src/main/java/com/cloud/offering/NetworkOffering.java b/api/src/main/java/com/cloud/offering/NetworkOffering.java
index cf01fbf30e2..5000a4f8c62 100644
--- a/api/src/main/java/com/cloud/offering/NetworkOffering.java
+++ b/api/src/main/java/com/cloud/offering/NetworkOffering.java
@@ -43,11 +43,15 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, MacLearning, RelatedNetworkOffering, domainid, zoneid, pvlanType, internetProtocol
}
- public enum NsxMode {
+ public enum NetworkMode {
NATTED,
ROUTED
}
+ enum RoutingMode {
+ Static, Dynamic
+ }
+
public final static String SystemPublicNetwork = "System-Public-Network";
public final static String SystemControlNetwork = "System-Control-Network";
public final static String SystemManagementNetwork = "System-Management-Network";
@@ -60,6 +64,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
public static final String DEFAULT_NAT_NSX_OFFERING_FOR_VPC = "DefaultNATNSXNetworkOfferingForVpc";
public static final String DEFAULT_NAT_NSX_OFFERING_FOR_VPC_WITH_ILB = "DefaultNATNSXNetworkOfferingForVpcWithInternalLB";
public static final String DEFAULT_ROUTED_NSX_OFFERING_FOR_VPC = "DefaultRoutedNSXNetworkOfferingForVpc";
+ public static final String DEFAULT_ROUTED_NETRIS_OFFERING_FOR_VPC = "DefaultRoutedNetrisNetworkOfferingForVpc";
+ public static final String DEFAULT_NAT_NETRIS_OFFERING_FOR_VPC = "DefaultNATNetrisNetworkOfferingForVpc";
public static final String DEFAULT_NAT_NSX_OFFERING = "DefaultNATNSXNetworkOffering";
public static final String DEFAULT_ROUTED_NSX_OFFERING = "DefaultRoutedNSXNetworkOffering";
public final static String QuickCloudNoServices = "QuickCloudNoServices";
@@ -98,11 +104,7 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
boolean isForVpc();
- boolean isForTungsten();
-
- boolean isForNsx();
-
- String getNsxMode();
+ NetworkMode getNetworkMode();
TrafficType getTrafficType();
@@ -165,4 +167,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
String getServicePackage();
Date getCreated();
+
+ RoutingMode getRoutingMode();
+
+ Boolean isSpecifyAsNumber();
}
diff --git a/api/src/main/java/com/cloud/offering/ServiceOffering.java b/api/src/main/java/com/cloud/offering/ServiceOffering.java
index 58c7b0dbaf9..532123e4373 100644
--- a/api/src/main/java/com/cloud/offering/ServiceOffering.java
+++ b/api/src/main/java/com/cloud/offering/ServiceOffering.java
@@ -33,6 +33,9 @@ public interface ServiceOffering extends InfrastructureEntity, InternalIdentity,
static final String internalLbVmDefaultOffUniqueName = "Cloud.Com-InternalLBVm";
// leaving cloud.com references as these are identifyers and no real world addresses (check against DB)
+
+ static final String PURGE_DB_ENTITIES_KEY = "purge.db.entities";
+
enum State {
Inactive, Active,
}
@@ -139,4 +142,8 @@ public interface ServiceOffering extends InfrastructureEntity, InternalIdentity,
Boolean getDiskOfferingStrictness();
void setDiskOfferingStrictness(boolean diskOfferingStrictness);
+
+ Long getVgpuProfileId();
+
+ Integer getGpuCount();
}
diff --git a/api/src/main/java/com/cloud/org/Cluster.java b/api/src/main/java/com/cloud/org/Cluster.java
index 4079c88dfde..b0aa6bb04cf 100644
--- a/api/src/main/java/com/cloud/org/Cluster.java
+++ b/api/src/main/java/com/cloud/org/Cluster.java
@@ -16,6 +16,7 @@
// under the License.
package com.cloud.org;
+import com.cloud.cpu.CPU;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.org.Managed.ManagedState;
import org.apache.cloudstack.kernel.Partition;
@@ -38,4 +39,8 @@ public interface Cluster extends Grouping, Partition {
AllocationState getAllocationState();
ManagedState getManagedState();
+
+ CPU.CPUArch getArch();
+
+ String getStorageAccessGroups();
}
diff --git a/api/src/main/java/com/cloud/region/ha/GlobalLoadBalancingRulesService.java b/api/src/main/java/com/cloud/region/ha/GlobalLoadBalancingRulesService.java
index ab6e6fb6c5a..3b61367e3b4 100644
--- a/api/src/main/java/com/cloud/region/ha/GlobalLoadBalancingRulesService.java
+++ b/api/src/main/java/com/cloud/region/ha/GlobalLoadBalancingRulesService.java
@@ -19,6 +19,7 @@ package com.cloud.region.ha;
import java.util.List;
+import com.cloud.user.Account;
import org.apache.cloudstack.api.command.user.region.ha.gslb.AssignToGlobalLoadBalancerRuleCmd;
import org.apache.cloudstack.api.command.user.region.ha.gslb.CreateGlobalLoadBalancerRuleCmd;
import org.apache.cloudstack.api.command.user.region.ha.gslb.DeleteGlobalLoadBalancerRuleCmd;
@@ -39,7 +40,7 @@ public interface GlobalLoadBalancingRulesService {
GlobalLoadBalancerRule updateGlobalLoadBalancerRule(UpdateGlobalLoadBalancerRuleCmd updateGslbCmd);
- boolean revokeAllGslbRulesForAccount(com.cloud.user.Account caller, long accountId) throws com.cloud.exception.ResourceUnavailableException;
+ boolean revokeAllGslbRulesForAccount(com.cloud.user.Account caller, Account account) throws com.cloud.exception.ResourceUnavailableException;
/*
* methods for managing sites participating in global load balancing
diff --git a/api/src/main/java/com/cloud/resource/ResourceService.java b/api/src/main/java/com/cloud/resource/ResourceService.java
index 2757c918ed6..3cdf8fc64e9 100644
--- a/api/src/main/java/com/cloud/resource/ResourceService.java
+++ b/api/src/main/java/com/cloud/resource/ResourceService.java
@@ -23,11 +23,11 @@ import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd;
import org.apache.cloudstack.api.command.admin.cluster.UpdateClusterCmd;
import org.apache.cloudstack.api.command.admin.host.AddHostCmd;
import org.apache.cloudstack.api.command.admin.host.AddSecondaryStorageCmd;
-import org.apache.cloudstack.api.command.admin.host.CancelMaintenanceCmd;
+import org.apache.cloudstack.api.command.admin.host.CancelHostMaintenanceCmd;
import org.apache.cloudstack.api.command.admin.host.ReconnectHostCmd;
import org.apache.cloudstack.api.command.admin.host.UpdateHostCmd;
import org.apache.cloudstack.api.command.admin.host.UpdateHostPasswordCmd;
-import org.apache.cloudstack.api.command.admin.host.PrepareForMaintenanceCmd;
+import org.apache.cloudstack.api.command.admin.host.PrepareForHostMaintenanceCmd;
import org.apache.cloudstack.api.command.admin.host.DeclareHostAsDegradedCmd;
import org.apache.cloudstack.api.command.admin.host.CancelHostAsDegradedCmd;
@@ -51,7 +51,7 @@ public interface ResourceService {
Host autoUpdateHostAllocationState(Long hostId, ResourceState.Event resourceEvent) throws NoTransitionException;
- Host cancelMaintenance(CancelMaintenanceCmd cmd);
+ Host cancelMaintenance(CancelHostMaintenanceCmd cmd);
Host reconnectHost(ReconnectHostCmd cmd) throws AgentUnavailableException;
@@ -69,7 +69,7 @@ public interface ResourceService {
List extends Host> discoverHosts(AddSecondaryStorageCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
- Host maintain(PrepareForMaintenanceCmd cmd);
+ Host maintain(PrepareForHostMaintenanceCmd cmd);
Host declareHostAsDegraded(DeclareHostAsDegradedCmd cmd) throws NoTransitionException;
@@ -95,4 +95,11 @@ public interface ResourceService {
boolean releaseHostReservation(Long hostId);
+ void updatePodStorageAccessGroups(long podId, List newStorageAccessGroups);
+
+ void updateZoneStorageAccessGroups(long zoneId, List newStorageAccessGroups);
+
+ void updateClusterStorageAccessGroups(Long clusterId, List newStorageAccessGroups);
+
+ void updateHostStorageAccessGroups(Long hostId, List newStorageAccessGroups);
}
diff --git a/api/src/main/java/com/cloud/resource/ResourceState.java b/api/src/main/java/com/cloud/resource/ResourceState.java
index 70738c7921b..e91cf820b08 100644
--- a/api/src/main/java/com/cloud/resource/ResourceState.java
+++ b/api/src/main/java/com/cloud/resource/ResourceState.java
@@ -76,6 +76,10 @@ public enum ResourceState {
}
}
+ public static List s_maintenanceStates = List.of(ResourceState.Maintenance,
+ ResourceState.ErrorInMaintenance, ResourceState.PrepareForMaintenance,
+ ResourceState.ErrorInPrepareForMaintenance);
+
public ResourceState getNextState(Event a) {
return s_fsm.getNextState(this, a);
}
@@ -98,8 +102,7 @@ public enum ResourceState {
}
public static boolean isMaintenanceState(ResourceState state) {
- return Arrays.asList(ResourceState.Maintenance, ResourceState.ErrorInMaintenance,
- ResourceState.PrepareForMaintenance, ResourceState.ErrorInPrepareForMaintenance).contains(state);
+ return s_maintenanceStates.contains(state);
}
public static boolean canAttemptMaintenance(ResourceState state) {
diff --git a/api/src/main/java/com/cloud/server/ManagementServerHostStats.java b/api/src/main/java/com/cloud/server/ManagementServerHostStats.java
index 1f201d7689f..6eb275031e8 100644
--- a/api/src/main/java/com/cloud/server/ManagementServerHostStats.java
+++ b/api/src/main/java/com/cloud/server/ManagementServerHostStats.java
@@ -19,6 +19,7 @@
package com.cloud.server;
import java.util.Date;
+import java.util.List;
/**
* management server related stats
@@ -32,6 +33,8 @@ public interface ManagementServerHostStats {
String getManagementServerHostUuid();
+ long getManagementServerRunId();
+
long getSessions();
double getCpuUtilization();
@@ -68,6 +71,10 @@ public interface ManagementServerHostStats {
String getOsDistribution();
+ List getLastAgents();
+
+ List getAgents();
+
int getAgentCount();
long getHeapMemoryUsed();
diff --git a/api/src/main/java/com/cloud/server/ManagementService.java b/api/src/main/java/com/cloud/server/ManagementService.java
index 18f3e901cd9..f7b2456ce5c 100644
--- a/api/src/main/java/com/cloud/server/ManagementService.java
+++ b/api/src/main/java/com/cloud/server/ManagementService.java
@@ -25,16 +25,20 @@ import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
import org.apache.cloudstack.api.command.admin.config.ListCfgGroupsByCmd;
import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd;
+import org.apache.cloudstack.api.command.admin.guest.AddGuestOsCategoryCmd;
import org.apache.cloudstack.api.command.admin.guest.AddGuestOsCmd;
import org.apache.cloudstack.api.command.admin.guest.AddGuestOsMappingCmd;
+import org.apache.cloudstack.api.command.admin.guest.DeleteGuestOsCategoryCmd;
import org.apache.cloudstack.api.command.admin.guest.GetHypervisorGuestOsNamesCmd;
import org.apache.cloudstack.api.command.admin.guest.ListGuestOsMappingCmd;
import org.apache.cloudstack.api.command.admin.guest.RemoveGuestOsCmd;
import org.apache.cloudstack.api.command.admin.guest.RemoveGuestOsMappingCmd;
+import org.apache.cloudstack.api.command.admin.guest.UpdateGuestOsCategoryCmd;
import org.apache.cloudstack.api.command.admin.guest.UpdateGuestOsCmd;
import org.apache.cloudstack.api.command.admin.guest.UpdateGuestOsMappingCmd;
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
import org.apache.cloudstack.api.command.admin.host.UpdateHostPasswordCmd;
+import org.apache.cloudstack.api.command.admin.management.RemoveManagementServerCmd;
import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd;
import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd;
import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd;
@@ -59,8 +63,10 @@ import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd;
import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd;
+import org.apache.cloudstack.api.command.user.userdata.DeleteCniConfigurationCmd;
import org.apache.cloudstack.api.command.user.userdata.DeleteUserDataCmd;
import org.apache.cloudstack.api.command.user.userdata.ListUserDataCmd;
+import org.apache.cloudstack.api.command.user.userdata.RegisterCniConfigurationCmd;
import org.apache.cloudstack.api.command.user.userdata.RegisterUserDataCmd;
import org.apache.cloudstack.api.command.user.vm.GetVMPasswordCmd;
import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
@@ -168,6 +174,12 @@ public interface ManagementService {
*/
Pair, Integer> listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd);
+ GuestOsCategory addGuestOsCategory(AddGuestOsCategoryCmd cmd);
+
+ GuestOsCategory updateGuestOsCategory(UpdateGuestOsCategoryCmd cmd);
+
+ boolean deleteGuestOsCategory(DeleteGuestOsCategoryCmd cmd);
+
/**
* Obtains a list of all guest OS mappings
*
@@ -360,17 +372,23 @@ public interface ManagementService {
* The api command class.
* @return The list of userdatas found.
*/
- Pair, Integer> listUserDatas(ListUserDataCmd cmd);
+ Pair, Integer> listUserDatas(ListUserDataCmd cmd, boolean forCks);
+
+ /**
+ * Registers a cni configuration.
+ *
+ * @param cmd The api command class.
+ * @return A VO with the registered user data.
+ */
+ UserData registerCniConfiguration(RegisterCniConfigurationCmd cmd);
/**
* Registers a userdata.
*
- * @param cmd
- * The api command class.
+ * @param cmd The api command class.
* @return A VO with the registered userdata.
*/
UserData registerUserData(RegisterUserDataCmd cmd);
-
/**
* Deletes a userdata.
*
@@ -380,6 +398,14 @@ public interface ManagementService {
*/
boolean deleteUserData(DeleteUserDataCmd cmd);
+ /**
+ * Deletes user data.
+ *
+ * @param cmd
+ * The api command class.
+ * @return True on success. False otherwise.
+ */
+ boolean deleteCniConfiguration(DeleteCniConfigurationCmd cmd);
/**
* Search registered key pairs for the logged in user.
*
@@ -481,4 +507,6 @@ public interface ManagementService {
Pair patchSystemVM(PatchSystemVMCmd cmd);
+ boolean removeManagementServer(RemoveManagementServerCmd cmd);
+
}
diff --git a/api/src/main/java/com/cloud/server/ResourceIconManager.java b/api/src/main/java/com/cloud/server/ResourceIconManager.java
index e5111d9160b..d10b3eb0cd5 100644
--- a/api/src/main/java/com/cloud/server/ResourceIconManager.java
+++ b/api/src/main/java/com/cloud/server/ResourceIconManager.java
@@ -16,7 +16,9 @@
// under the License.
package com.cloud.server;
+import java.util.Collection;
import java.util.List;
+import java.util.Map;
public interface ResourceIconManager {
@@ -25,4 +27,8 @@ public interface ResourceIconManager {
boolean deleteResourceIcon(List resourceIds, ResourceTag.ResourceObjectType resourceType);
ResourceIcon getByResourceTypeAndUuid(ResourceTag.ResourceObjectType type, String resourceId);
+
+ Map getByResourceTypeAndIds(ResourceTag.ResourceObjectType type, Collection resourceIds);
+
+ Map getByResourceTypeAndUuids(ResourceTag.ResourceObjectType type, Collection resourceUuids);
}
diff --git a/api/src/main/java/com/cloud/server/ResourceTag.java b/api/src/main/java/com/cloud/server/ResourceTag.java
index 9bbb5d43eae..b3026deceff 100644
--- a/api/src/main/java/com/cloud/server/ResourceTag.java
+++ b/api/src/main/java/com/cloud/server/ResourceTag.java
@@ -66,6 +66,7 @@ public interface ResourceTag extends ControlledEntity, Identity, InternalIdentit
LBStickinessPolicy(false, true),
LBHealthCheckPolicy(false, true),
SnapshotPolicy(true, true),
+ GuestOsCategory(false, false, true),
GuestOs(false, true),
NetworkOffering(false, true),
VpcOffering(true, false),
diff --git a/api/src/main/java/com/cloud/storage/GuestOsCategory.java b/api/src/main/java/com/cloud/storage/GuestOsCategory.java
index b46418d5c8f..e1ee4489158 100644
--- a/api/src/main/java/com/cloud/storage/GuestOsCategory.java
+++ b/api/src/main/java/com/cloud/storage/GuestOsCategory.java
@@ -16,6 +16,8 @@
// under the License.
package com.cloud.storage;
+import java.util.Date;
+
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@@ -27,4 +29,7 @@ public interface GuestOsCategory extends Identity, InternalIdentity {
void setName(String name);
+ boolean isFeatured();
+
+ Date getCreated();
}
diff --git a/api/src/main/java/com/cloud/storage/MigrationOptions.java b/api/src/main/java/com/cloud/storage/MigrationOptions.java
index a39a2a7c827..8b642d09e29 100644
--- a/api/src/main/java/com/cloud/storage/MigrationOptions.java
+++ b/api/src/main/java/com/cloud/storage/MigrationOptions.java
@@ -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() {
diff --git a/api/src/main/java/com/cloud/storage/Snapshot.java b/api/src/main/java/com/cloud/storage/Snapshot.java
index fc919e442b2..c0a7b812ed9 100644
--- a/api/src/main/java/com/cloud/storage/Snapshot.java
+++ b/api/src/main/java/com/cloud/storage/Snapshot.java
@@ -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;
diff --git a/api/src/main/java/com/cloud/storage/Storage.java b/api/src/main/java/com/cloud/storage/Storage.java
index c997f5e1dbf..1ad3731b9ea 100644
--- a/api/src/main/java/com/cloud/storage/Storage.java
+++ b/api/src/main/java/com/cloud/storage/Storage.java
@@ -16,14 +16,10 @@
// under the License.
package com.cloud.storage;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
import org.apache.commons.lang.NotImplementedException;
-import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
public class Storage {
public static enum ImageFormat {
@@ -34,6 +30,7 @@ public class Storage {
OVA(true, true, true, "ova"),
VHDX(true, true, true, "vhdx"),
BAREMETAL(false, false, false, "BAREMETAL"),
+ EXTERNAL(false, false, false, "EXTERNAL"),
VMDK(true, true, false, "vmdk"),
VDI(true, true, false, "vdi"),
TAR(false, false, false, "tar"),
@@ -139,6 +136,21 @@ public class Storage {
ISODISK /* Template corresponding to a iso (non root disk) present in an OVA */
}
+ public enum EncryptionSupport {
+ /**
+ * Encryption not supported.
+ */
+ Unsupported,
+ /**
+ * Will use hypervisor encryption driver (qemu -> luks)
+ */
+ Hypervisor,
+ /**
+ * Storage pool handles encryption and just provides an encrypted volume
+ */
+ Storage
+ }
+
/**
* StoragePoolTypes carry some details about the format and capabilities of a storage pool. While not necessarily a
* 1:1 with PrimaryDataStoreDriver (and for KVM agent, KVMStoragePool and StorageAdaptor) implementations, it is
@@ -150,61 +162,37 @@ public class Storage {
* ensure this is available on the agent side as well. This is best done by defining the StoragePoolType in a common
* package available on both management server and agent plugin jars.
*/
- public static class StoragePoolType {
- private static final Map map = new LinkedHashMap<>();
+ public static enum StoragePoolType {
+ Filesystem(false, true, EncryptionSupport.Hypervisor), // local directory
+ NetworkFilesystem(true, true, EncryptionSupport.Hypervisor), // NFS
+ IscsiLUN(true, false, EncryptionSupport.Unsupported), // shared LUN, with a clusterfs overlay
+ Iscsi(true, false, EncryptionSupport.Unsupported), // for e.g., ZFS Comstar
+ ISO(false, false, EncryptionSupport.Unsupported), // for iso image
+ LVM(false, false, EncryptionSupport.Unsupported), // XenServer local LVM SR
+ CLVM(true, false, EncryptionSupport.Unsupported),
+ RBD(true, true, EncryptionSupport.Unsupported), // http://libvirt.org/storage.html#StorageBackendRBD
+ SharedMountPoint(true, true, EncryptionSupport.Hypervisor),
+ VMFS(true, true, EncryptionSupport.Unsupported), // VMware VMFS storage
+ PreSetup(true, true, EncryptionSupport.Unsupported), // for XenServer, Storage Pool is set up by customers.
+ EXT(false, true, EncryptionSupport.Unsupported), // XenServer local EXT SR
+ OCFS2(true, false, EncryptionSupport.Unsupported),
+ SMB(true, false, EncryptionSupport.Unsupported),
+ Gluster(true, false, EncryptionSupport.Unsupported),
+ PowerFlex(true, true, EncryptionSupport.Hypervisor), // Dell EMC PowerFlex/ScaleIO (formerly VxFlexOS)
+ ManagedNFS(true, false, EncryptionSupport.Unsupported),
+ Linstor(true, true, EncryptionSupport.Storage),
+ DatastoreCluster(true, true, EncryptionSupport.Unsupported), // for VMware, to abstract pool of clusters
+ StorPool(true, true, EncryptionSupport.Hypervisor),
+ FiberChannel(true, true, EncryptionSupport.Unsupported); // Fiber Channel Pool for KVM hypervisors is used to find the volume by WWN value (/dev/disk/by-id/wwn-)
- public static final StoragePoolType Filesystem = new StoragePoolType("Filesystem", false, true, true);
- public static final StoragePoolType NetworkFilesystem = new StoragePoolType("NetworkFilesystem", true, true, true);
- public static final StoragePoolType IscsiLUN = new StoragePoolType("IscsiLUN", true, false, false);
- public static final StoragePoolType Iscsi = new StoragePoolType("Iscsi", true, false, false);
- public static final StoragePoolType ISO = new StoragePoolType("ISO", false, false, false);
- public static final StoragePoolType LVM = new StoragePoolType("LVM", false, false, false);
- public static final StoragePoolType CLVM = new StoragePoolType("CLVM", true, false, false);
- public static final StoragePoolType RBD = new StoragePoolType("RBD", true, true, false);
- public static final StoragePoolType SharedMountPoint = new StoragePoolType("SharedMountPoint", true, true, true);
- public static final StoragePoolType VMFS = new StoragePoolType("VMFS", true, true, false);
- public static final StoragePoolType PreSetup = new StoragePoolType("PreSetup", true, true, false);
- public static final StoragePoolType EXT = new StoragePoolType("EXT", false, true, false);
- public static final StoragePoolType OCFS2 = new StoragePoolType("OCFS2", true, false, false);
- public static final StoragePoolType SMB = new StoragePoolType("SMB", true, false, false);
- public static final StoragePoolType Gluster = new StoragePoolType("Gluster", true, false, false);
- public static final StoragePoolType PowerFlex = new StoragePoolType("PowerFlex", true, true, true);
- public static final StoragePoolType ManagedNFS = new StoragePoolType("ManagedNFS", true, false, false);
- public static final StoragePoolType Linstor = new StoragePoolType("Linstor", true, true, false);
- public static final StoragePoolType DatastoreCluster = new StoragePoolType("DatastoreCluster", true, true, false);
- public static final StoragePoolType StorPool = new StoragePoolType("StorPool", true,true,true);
- public static final StoragePoolType FiberChannel = new StoragePoolType("FiberChannel", true,true,false);
-
-
- private final String name;
private final boolean shared;
private final boolean overProvisioning;
- private final boolean encryption;
+ private final EncryptionSupport encryption;
- /**
- * New StoragePoolType, set the name to check with it in Dao (Note: Do not register it into the map of pool types).
- * @param name name of the StoragePoolType.
- */
- public StoragePoolType(String name) {
- this.name = name;
- this.shared = false;
- this.overProvisioning = false;
- this.encryption = false;
- }
-
- /**
- * Define a new StoragePoolType, and register it into the map of pool types known to the management server.
- * @param name Simple unique name of the StoragePoolType.
- * @param shared Storage pool is shared/accessible to multiple hypervisors
- * @param overProvisioning Storage pool supports overProvisioning
- * @param encryption Storage pool supports encrypted volumes
- */
- public StoragePoolType(String name, boolean shared, boolean overProvisioning, boolean encryption) {
- this.name = name;
+ StoragePoolType(boolean shared, boolean overProvisioning, EncryptionSupport encryption) {
this.shared = shared;
this.overProvisioning = overProvisioning;
this.encryption = encryption;
- addStoragePoolType(this);
}
public boolean isShared() {
@@ -216,50 +204,12 @@ public class Storage {
}
public boolean supportsEncryption() {
+ return encryption == EncryptionSupport.Hypervisor || encryption == EncryptionSupport.Storage;
+ }
+
+ public EncryptionSupport encryptionSupportMode() {
return encryption;
}
-
- private static void addStoragePoolType(StoragePoolType storagePoolType) {
- map.putIfAbsent(storagePoolType.name, storagePoolType);
- }
-
- public static StoragePoolType[] values() {
- return map.values().toArray(StoragePoolType[]::new).clone();
- }
-
- public static StoragePoolType valueOf(String name) {
- if (StringUtils.isBlank(name)) {
- return null;
- }
-
- StoragePoolType storage = map.get(name);
- if (storage == null) {
- throw new IllegalArgumentException("StoragePoolType '" + name + "' not found");
- }
- return storage;
- }
-
- @Override
- public String toString() {
- return name;
- }
-
- public String name() {
- return name;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- StoragePoolType that = (StoragePoolType) o;
- return Objects.equals(name, that.name);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(name);
- }
}
public static List getNonSharedStoragePoolTypes() {
diff --git a/api/src/main/java/com/cloud/storage/StorageService.java b/api/src/main/java/com/cloud/storage/StorageService.java
index c3609cfd8ee..a29c8f6aece 100644
--- a/api/src/main/java/com/cloud/storage/StorageService.java
+++ b/api/src/main/java/com/cloud/storage/StorageService.java
@@ -21,6 +21,8 @@ import java.net.UnknownHostException;
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;
@@ -29,11 +31,13 @@ import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.DeleteSecondaryStagingStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.SyncStoragePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.UpdateObjectStoragePoolCmd;
+import org.apache.cloudstack.api.command.admin.storage.UpdateImageStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd;
import com.cloud.exception.DiscoveryException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.exception.ResourceUnavailableException;
import org.apache.cloudstack.api.command.admin.storage.heuristics.CreateSecondaryStorageSelectorCmd;
@@ -92,6 +96,12 @@ public interface StorageService {
StoragePool updateStoragePool(UpdateStoragePoolCmd cmd) throws IllegalArgumentException;
+ StoragePool enablePrimaryStoragePool(Long id);
+
+ StoragePool disablePrimaryStoragePool(Long id);
+
+ boolean configureStorageAccess(ConfigureStorageAccessCmd cmd);
+
StoragePool getStoragePool(long id);
boolean deleteImageStore(DeleteImageStoreCmd cmd);
@@ -110,6 +120,8 @@ public interface StorageService {
*/
ImageStore migrateToObjectStore(String name, String url, String providerName, Map details) throws DiscoveryException;
+ ImageStore updateImageStore(UpdateImageStoreCmd cmd);
+
ImageStore updateImageStoreStatus(Long id, Boolean readonly);
void updateStorageCapabilities(Long poolId, boolean failOnChecks);
@@ -122,9 +134,11 @@ public interface StorageService {
void removeSecondaryStorageHeuristic(RemoveSecondaryStorageSelectorCmd cmd);
- ObjectStore discoverObjectStore(String name, String url, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
+ ObjectStore discoverObjectStore(String name, String url, Long size, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
boolean deleteObjectStore(DeleteObjectStoragePoolCmd cmd);
ObjectStore updateObjectStore(Long id, UpdateObjectStoragePoolCmd cmd);
+
+ void changeStoragePoolScope(ChangeStoragePoolScopeCmd cmd) throws IllegalArgumentException, InvalidParameterValueException, PermissionDeniedException;
}
diff --git a/api/src/main/java/com/cloud/storage/StorageStats.java b/api/src/main/java/com/cloud/storage/StorageStats.java
index a474b23489c..502e2aaae40 100644
--- a/api/src/main/java/com/cloud/storage/StorageStats.java
+++ b/api/src/main/java/com/cloud/storage/StorageStats.java
@@ -26,4 +26,7 @@ public interface StorageStats {
* @return bytes capacity of the storage server
*/
public long getCapacityBytes();
+
+ Long getCapacityIops();
+ Long getUsedIops();
}
diff --git a/api/src/main/java/com/cloud/storage/Upload.java b/api/src/main/java/com/cloud/storage/Upload.java
index 59d203ac73a..4e696e877cc 100644
--- a/api/src/main/java/com/cloud/storage/Upload.java
+++ b/api/src/main/java/com/cloud/storage/Upload.java
@@ -40,7 +40,7 @@ public interface Upload extends InternalIdentity, Identity {
}
public static enum Type {
- VOLUME, TEMPLATE, ISO
+ VOLUME, SNAPSHOT, TEMPLATE, ISO
}
public static enum Mode {
diff --git a/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java b/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java
index f43d5331222..db702a61f2b 100644
--- a/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java
+++ b/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java
@@ -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 PENDING_DOWNLOAD_STATES = List.of(Status.NOT_DOWNLOADED, Status.DOWNLOAD_IN_PROGRESS);
+
String getInstallPath();
long getTemplateId();
diff --git a/api/src/main/java/com/cloud/storage/Volume.java b/api/src/main/java/com/cloud/storage/Volume.java
index 40c5660b2df..c7fbdb0a544 100644
--- a/api/src/main/java/com/cloud/storage/Volume.java
+++ b/api/src/main/java/com/cloud/storage/Volume.java
@@ -271,11 +271,13 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba
void setExternalUuid(String externalUuid);
- public Long getPassphraseId();
+ Long getPassphraseId();
- public void setPassphraseId(Long id);
+ void setPassphraseId(Long id);
- public String getEncryptFormat();
+ String getEncryptFormat();
- public void setEncryptFormat(String encryptFormat);
+ void setEncryptFormat(String encryptFormat);
+
+ boolean isDeleteProtection();
}
diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java
index 4f09702b7db..dd7341da1b5 100644
--- a/api/src/main/java/com/cloud/storage/VolumeApiService.java
+++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java
@@ -22,7 +22,12 @@ import java.net.MalformedURLException;
import java.util.List;
import java.util.Map;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.offering.DiskOffering;
+import com.cloud.user.Account;
import com.cloud.utils.Pair;
+import com.cloud.utils.fsm.NoTransitionException;
+
import org.apache.cloudstack.api.command.user.volume.AssignVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.ChangeOfferingForVolumeCmd;
@@ -37,13 +42,9 @@ import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
import org.apache.cloudstack.api.response.GetUploadParamsResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.user.Account;
-import com.cloud.utils.fsm.NoTransitionException;
-
public interface VolumeApiService {
- ConfigKey ConcurrentMigrationsThresholdPerDatastore = new ConfigKey("Advanced"
+ ConfigKey ConcurrentMigrationsThresholdPerDatastore = new ConfigKey<>("Advanced"
, Long.class
, "concurrent.migrations.per.target.datastore"
, "0"
@@ -51,7 +52,7 @@ public interface VolumeApiService {
, true // not sure if this is to be dynamic
, ConfigKey.Scope.Global);
- ConfigKey UseHttpsToUpload = new ConfigKey("Advanced",
+ ConfigKey UseHttpsToUpload = new ConfigKey<>("Advanced",
Boolean.class,
"use.https.to.upload",
"true",
@@ -85,7 +86,7 @@ public interface VolumeApiService {
* @param cmd
* the API command wrapping the criteria
* @return the volume object
- * @throws ResourceAllocationException
+ * @throws ResourceAllocationException no capacity to allocate the new volume size
*/
Volume resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationException;
@@ -102,8 +103,12 @@ public interface VolumeApiService {
boolean deleteVolume(long volumeId, Account caller);
+ Volume changeDiskOfferingForVolumeInternal(Long volumeId, Long newDiskOfferingId, Long newSize, Long newMinIops, Long newMaxIops, boolean autoMigrateVolume, boolean shrinkOk) throws ResourceAllocationException;
+
Volume attachVolumeToVM(AttachVolumeCmd command);
+ Volume attachVolumeToVM(Long vmId, Long volumeId, Long deviceId, Boolean allowAttachForSharedFS);
+
Volume detachVolumeViaDestroyVM(long vmId, long volumeId);
Volume detachVolumeFromVM(DetachVolumeCmd cmd);
@@ -113,7 +118,9 @@ public interface VolumeApiService {
Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, List zoneIds) throws ResourceAllocationException;
- Volume updateVolume(long volumeId, String path, String state, Long storageId, Boolean displayVolume, String customId, long owner, String chainInfo, String name);
+ Volume updateVolume(long volumeId, String path, String state, Long storageId,
+ Boolean displayVolume, Boolean deleteProtection,
+ String customId, long owner, String chainInfo, String name);
/**
* Extracts the volume to a particular location.
@@ -130,16 +137,16 @@ public interface VolumeApiService {
void updateDisplay(Volume volume, Boolean displayVolume);
- Snapshot allocSnapshotForVm(Long vmId, Long volumeId, String snapshotName) throws ResourceAllocationException;
+ Snapshot allocSnapshotForVm(Long vmId, Long volumeId, String snapshotName, Long vmSnapshotId) throws ResourceAllocationException;
/**
- * Checks if the target storage supports the disk offering.
+ * Checks if the storage pool supports the disk offering tags.
* This validation is consistent with the mechanism used to select a storage pool to deploy a volume when a virtual machine is deployed or when a data disk is allocated.
*
* The scenarios when this method returns true or false is presented in the following table.
*
*
- * | # | Disk offering tags | Storage tags | Does the storage support the disk offering? |
+ * # | Disk offering diskOfferingTags | Storage diskOfferingTags | Does the storage support the disk offering? |
*
*
*
@@ -163,7 +170,15 @@ public interface VolumeApiService {
*
*
*/
- boolean doesTargetStorageSupportDiskOffering(StoragePool destPool, String diskOfferingTags);
+ boolean doesStoragePoolSupportDiskOffering(StoragePool destPool, DiskOffering diskOffering);
+
+ /**
+ * Checks if the storage pool supports the required disk offering tags
+ * destPool the storage pool to check the disk offering tags
+ * diskOfferingTags the tags that should be supported
+ * return whether the tags are supported in the storage pool
+ */
+ boolean doesStoragePoolSupportDiskOfferingTags(StoragePool destPool, String diskOfferingTags);
Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge);
@@ -184,4 +199,6 @@ public interface VolumeApiService {
boolean stateTransitTo(Volume vol, Volume.Event event) throws NoTransitionException;
Pair checkAndRepairVolume(CheckAndRepairVolumeCmd cmd) throws ResourceAllocationException;
+
+ Long getVolumePhysicalSize(Storage.ImageFormat format, String path, String chainInfo);
}
diff --git a/api/src/main/java/com/cloud/storage/snapshot/SnapshotApiService.java b/api/src/main/java/com/cloud/storage/snapshot/SnapshotApiService.java
index 0893f337ce2..67afd6aa4e2 100644
--- a/api/src/main/java/com/cloud/storage/snapshot/SnapshotApiService.java
+++ b/api/src/main/java/com/cloud/storage/snapshot/SnapshotApiService.java
@@ -21,6 +21,7 @@ import java.util.List;
import org.apache.cloudstack.api.command.user.snapshot.CopySnapshotCmd;
import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotPolicyCmd;
import org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotPoliciesCmd;
+import org.apache.cloudstack.api.command.user.snapshot.ExtractSnapshotCmd;
import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotPoliciesCmd;
import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd;
import org.apache.cloudstack.api.command.user.snapshot.UpdateSnapshotPolicyCmd;
@@ -106,6 +107,16 @@ public interface SnapshotApiService {
*/
Snapshot createSnapshot(Long volumeId, Long policyId, Long snapshotId, Account snapshotOwner);
+ /**
+ * Extracts the snapshot to a particular location.
+ *
+ * @param cmd
+ * the command specifying url (where the snapshot needs to be extracted to), zoneId (zone where the snapshot exists) and
+ * id (the id of the snapshot)
+ *
+ */
+ String extractSnapshot(ExtractSnapshotCmd cmd);
+
/**
* Archives a snapshot from primary storage to secondary storage.
* @param id Snapshot ID
diff --git a/api/src/main/java/com/cloud/template/TemplateApiService.java b/api/src/main/java/com/cloud/template/TemplateApiService.java
index 5b494c308c3..6138f24c92b 100644
--- a/api/src/main/java/com/cloud/template/TemplateApiService.java
+++ b/api/src/main/java/com/cloud/template/TemplateApiService.java
@@ -58,10 +58,23 @@ public interface TemplateApiService {
VirtualMachineTemplate prepareTemplate(long templateId, long zoneId, Long storageId);
+ /**
+ * Detach ISO from VM
+ * @param vmId id of the VM
+ * @param isoId id of the ISO (when passed). If it is not passed, it will get it from user_vm table
+ * @param extraParams forced, isVirtualRouter
+ * @return true when operation succeeds, false if not
+ */
+ boolean detachIso(long vmId, Long isoId, Boolean... extraParams);
- boolean detachIso(long vmId, boolean forced);
-
- boolean attachIso(long isoId, long vmId, boolean forced);
+ /**
+ * Attach ISO to a VM
+ * @param isoId id of the ISO to attach
+ * @param vmId id of the VM to attach the ISO to
+ * @param extraParams: forced, isVirtualRouter
+ * @return true when operation succeeds, false if not
+ */
+ boolean attachIso(long isoId, long vmId, Boolean... extraParams);
/**
* Deletes a template
diff --git a/api/src/main/java/com/cloud/template/VirtualMachineTemplate.java b/api/src/main/java/com/cloud/template/VirtualMachineTemplate.java
index 1f8cef0365b..b8c646048b9 100644
--- a/api/src/main/java/com/cloud/template/VirtualMachineTemplate.java
+++ b/api/src/main/java/com/cloud/template/VirtualMachineTemplate.java
@@ -19,6 +19,7 @@ package com.cloud.template;
import java.util.Date;
import java.util.Map;
+import com.cloud.cpu.CPU;
import com.cloud.user.UserData;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.Identity;
@@ -144,8 +145,14 @@ public interface VirtualMachineTemplate extends ControlledEntity, Identity, Inte
boolean isDeployAsIs();
+ boolean isForCks();
+
Long getUserDataId();
UserData.UserDataOverridePolicy getUserDataOverridePolicy();
+ CPU.CPUArch getArch();
+
+ Long getExtensionId();
+
}
diff --git a/api/src/main/java/com/cloud/user/Account.java b/api/src/main/java/com/cloud/user/Account.java
index bb9838f137a..1cc5eae64a6 100644
--- a/api/src/main/java/com/cloud/user/Account.java
+++ b/api/src/main/java/com/cloud/user/Account.java
@@ -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();
@@ -93,4 +94,8 @@ public interface Account extends ControlledEntity, InternalIdentity, Identity {
boolean isDefault();
+ public void setApiKeyAccess(Boolean apiKeyAccess);
+
+ public Boolean getApiKeyAccess();
+
}
diff --git a/api/src/main/java/com/cloud/user/AccountService.java b/api/src/main/java/com/cloud/user/AccountService.java
index 63f5455cfd0..c0ebcf09f59 100644
--- a/api/src/main/java/com/cloud/user/AccountService.java
+++ b/api/src/main/java/com/cloud/user/AccountService.java
@@ -19,6 +19,7 @@ package com.cloud.user;
import java.util.List;
import java.util.Map;
+import com.cloud.utils.Pair;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@@ -86,6 +87,8 @@ public interface AccountService {
boolean isDomainAdmin(Long accountId);
+ boolean isResourceDomainAdmin(Long accountId);
+
boolean isNormalUser(long accountId);
User getActiveUserByRegistrationToken(String registrationToken);
@@ -116,6 +119,8 @@ public interface AccountService {
void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) throws PermissionDeniedException;
+ void validateAccountHasAccessToResource(Account account, AccessType accessType, Object resource);
+
Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly);
/**
@@ -125,9 +130,9 @@ public interface AccountService {
*/
UserAccount getUserAccountById(Long userId);
- public Map getKeys(GetUserKeysCmd cmd);
+ public Pair> getKeys(GetUserKeysCmd cmd);
- public Map getKeys(Long userId);
+ public Pair> getKeys(Long userId);
/**
* Lists user two-factor authentication provider plugins
diff --git a/api/src/main/java/com/cloud/user/ResourceLimitService.java b/api/src/main/java/com/cloud/user/ResourceLimitService.java
index 04560df428f..49b20fe2fef 100644
--- a/api/src/main/java/com/cloud/user/ResourceLimitService.java
+++ b/api/src/main/java/com/cloud/user/ResourceLimitService.java
@@ -38,13 +38,26 @@ public interface ResourceLimitService {
static final ConfigKey MaxProjectSecondaryStorage = new ConfigKey<>("Project Defaults", Long.class, "max.project.secondary.storage", "400",
"The default maximum secondary storage space (in GiB) that can be used for a project", false);
static final ConfigKey ResourceCountCheckInterval = new ConfigKey<>("Advanced", Long.class, "resourcecount.check.interval", "300",
- "Time (in seconds) to wait before running resource recalculation and fixing task. Default is 300 seconds, Setting this to 0 disables execution of the task", true);
+ "Time (in seconds) to wait before running resource recalculation and fixing tasks like stale resource reservation cleanup" +
+ ". Default is 300 seconds, Setting this to 0 disables execution of the task", true);
+ static final ConfigKey ResourceReservationCleanupDelay = new ConfigKey<>("Advanced", Long.class, "resource.reservation.cleanup.delay", "3600",
+ "Time (in seconds) after which a resource reservation gets deleted. Default is 3600 seconds, Setting this to 0 disables execution of the task", true);
static final ConfigKey ResourceLimitHostTags = new ConfigKey<>("Advanced", String.class, "resource.limit.host.tags", "",
"A comma-separated list of tags for host resource limits", true);
static final ConfigKey ResourceLimitStorageTags = new ConfigKey<>("Advanced", String.class, "resource.limit.storage.tags", "",
"A comma-separated list of tags for storage resource limits", true);
+ static final ConfigKey DefaultMaxAccountProjects = new ConfigKey<>("Account Defaults",Long.class,"max.account.projects","10",
+ "The default maximum number of projects that can be created for an account",false);
+ static final ConfigKey DefaultMaxDomainProjects = new ConfigKey<>("Domain Defaults",Long.class,"max.domain.projects","50",
+ "The default maximum number of projects that can be created for a domain",false);
+ static final ConfigKey DefaultMaxAccountGpus = new ConfigKey<>("Account Defaults",Long.class,"max.account.gpus","20",
+ "The default maximum number of GPU devices that can be used for an account", false);
+ static final ConfigKey DefaultMaxDomainGpus = new ConfigKey<>("Domain Defaults",Long.class,"max.domain.gpus","20",
+ "The default maximum number of GPU devices that can be used for a domain", false);
+ static final ConfigKey DefaultMaxProjectGpus = new ConfigKey<>("Project Defaults",Long.class,"max.project.gpus","20",
+ "The default maximum number of GPU devices that can be used for a project", false);
- static final List HostTagsSupportingTypes = List.of(ResourceType.user_vm, ResourceType.cpu, ResourceType.memory);
+ static final List HostTagsSupportingTypes = List.of(ResourceType.user_vm, ResourceType.cpu, ResourceType.memory, ResourceType.gpu);
static final List StorageTagsSupportingTypes = List.of(ResourceType.volume, ResourceType.primary_storage);
/**
@@ -239,13 +252,37 @@ public interface ResourceLimitService {
void updateTaggedResourceLimitsAndCountsForAccounts(List responses, String tag);
void updateTaggedResourceLimitsAndCountsForDomains(List responses, String tag);
void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException;
+
+ void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize,
+ DiskOffering currentOffering, DiskOffering newOffering) throws ResourceAllocationException;
+
+ void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException;
+
void incrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
void decrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
+
+ void updateVmResourceCountForTemplateChange(long accountId, Boolean display, ServiceOffering offering, VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate);
+
+ void updateVmResourceCountForServiceOfferingChange(long accountId, Boolean display, Long currentCpu, Long newCpu, Long currentMemory,
+ Long newMemory,
+ ServiceOffering currentOffering, ServiceOffering newOffering,
+ VirtualMachineTemplate template);
+
+ void updateVolumeResourceCountForDiskOfferingChange(long accountId, Boolean display, Long currentSize, Long newSize,
+ DiskOffering currentDiskOffering, DiskOffering newDiskOffering);
+
void incrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
void decrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template) throws ResourceAllocationException;
void incrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
void decrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
+
+ void checkVmResourceLimitsForServiceOfferingChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
+ Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template) throws ResourceAllocationException;
+
+ void checkVmResourceLimitsForTemplateChange(Account owner, Boolean display, ServiceOffering offering,
+ VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate) throws ResourceAllocationException;
+
void checkVmCpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu) throws ResourceAllocationException;
void incrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu);
void decrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu);
@@ -253,4 +290,8 @@ public interface ResourceLimitService {
void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
void decrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
+ void checkVmGpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu) throws ResourceAllocationException;
+ void incrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu);
+ void decrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu);
+
}
diff --git a/api/src/main/java/com/cloud/user/User.java b/api/src/main/java/com/cloud/user/User.java
index 422e264f10b..041b39ad272 100644
--- a/api/src/main/java/com/cloud/user/User.java
+++ b/api/src/main/java/com/cloud/user/User.java
@@ -94,4 +94,9 @@ public interface User extends OwnedBy, InternalIdentity {
public boolean isUser2faEnabled();
public String getKeyFor2fa();
+
+ public void setApiKeyAccess(Boolean apiKeyAccess);
+
+ public Boolean getApiKeyAccess();
+
}
diff --git a/api/src/main/java/com/cloud/user/UserData.java b/api/src/main/java/com/cloud/user/UserData.java
index fa0c50473c0..13a3c74f367 100644
--- a/api/src/main/java/com/cloud/user/UserData.java
+++ b/api/src/main/java/com/cloud/user/UserData.java
@@ -29,4 +29,5 @@ public interface UserData extends ControlledEntity, InternalIdentity, Identity {
String getUserData();
String getParams();
+ boolean isForCks();
}
diff --git a/api/src/main/java/com/cloud/uservm/UserVm.java b/api/src/main/java/com/cloud/uservm/UserVm.java
index e30f5e03054..9035d2903c9 100644
--- a/api/src/main/java/com/cloud/uservm/UserVm.java
+++ b/api/src/main/java/com/cloud/uservm/UserVm.java
@@ -48,4 +48,6 @@ public interface UserVm extends VirtualMachine, ControlledEntity {
void setAccountId(long accountId);
public boolean isDisplayVm();
+
+ String getUserVmType();
}
diff --git a/api/src/main/java/com/cloud/vm/NicProfile.java b/api/src/main/java/com/cloud/vm/NicProfile.java
index d3c1daa1f5d..a0c80ceb1bf 100644
--- a/api/src/main/java/com/cloud/vm/NicProfile.java
+++ b/api/src/main/java/com/cloud/vm/NicProfile.java
@@ -62,6 +62,7 @@ public class NicProfile implements InternalIdentity, Serializable {
String iPv4Dns1;
String iPv4Dns2;
String requestedIPv4;
+ boolean ipv4AllocationRaceCheck;
// IPv6
String iPv6Address;
@@ -405,6 +406,13 @@ public class NicProfile implements InternalIdentity, Serializable {
this.mtu = mtu;
}
+ public boolean getIpv4AllocationRaceCheck() {
+ return this.ipv4AllocationRaceCheck;
+ }
+
+ public void setIpv4AllocationRaceCheck(boolean ipv4AllocationRaceCheck) {
+ this.ipv4AllocationRaceCheck = ipv4AllocationRaceCheck;
+ }
//
// OTHER METHODS
@@ -442,6 +450,9 @@ public class NicProfile implements InternalIdentity, Serializable {
@Override
public String toString() {
- return String.format("NicProfile %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "vmId", "deviceId", "broadcastUri", "reservationId", "iPv4Address"));
+ return String.format("NicProfile %s",
+ ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
+ this, "id", "uuid", "vmId", "deviceId",
+ "broadcastUri", "reservationId", "iPv4Address"));
}
}
diff --git a/api/src/main/java/com/cloud/vm/UserVmService.java b/api/src/main/java/com/cloud/vm/UserVmService.java
index 787ed7bde37..6f1aba4613d 100644
--- a/api/src/main/java/com/cloud/vm/UserVmService.java
+++ b/api/src/main/java/com/cloud/vm/UserVmService.java
@@ -16,14 +16,18 @@
// under the License.
package com.cloud.vm;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.Volume;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import com.cloud.deploy.DeploymentPlan;
import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd;
import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd;
import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd;
+import org.apache.cloudstack.api.command.user.vm.CreateVMFromBackupCmd;
import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd;
import org.apache.cloudstack.api.command.user.vm.RebootVMCmd;
@@ -42,9 +46,11 @@ import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
import com.cloud.dc.DataCenter;
+import com.cloud.deploy.DeploymentPlanner;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ManagementServerException;
+import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.StorageUnavailableException;
@@ -66,10 +72,7 @@ public interface UserVmService {
/**
* Destroys one virtual machine
*
- * @param userId
- * the id of the user performing the action
- * @param vmId
- * the id of the virtual machine.
+ * @param cmd the API Command Object containg the parameters to use for this service action
* @throws ConcurrentOperationException
* @throws ResourceUnavailableException
*/
@@ -110,7 +113,13 @@ public interface UserVmService {
UserVm startVirtualMachine(StartVMCmd cmd) throws StorageUnavailableException, ExecutionException, ConcurrentOperationException, ResourceUnavailableException,
InsufficientCapacityException, ResourceAllocationException;
- UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException;
+ UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ResourceAllocationException;
+
+ void startVirtualMachine(UserVm vm, DeploymentPlan plan) throws OperationTimedoutException, ResourceUnavailableException, InsufficientCapacityException;
+
+ void startVirtualMachineForHA(VirtualMachine vm, Map params,
+ DeploymentPlanner planner) throws InsufficientCapacityException, ResourceUnavailableException,
+ ConcurrentOperationException, OperationTimedoutException;
UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException;
@@ -148,14 +157,6 @@ public interface UserVmService {
* Creates a Basic Zone User VM in the database and returns the VM to the
* caller.
*
- *
- *
- * @param sshKeyPair
- * - name of the ssh key pair used to login to the virtual
- * machine
- * @param cpuSpeed
- * @param memory
- * @param cpuNumber
* @param zone
* - availability zone for the virtual machine
* @param serviceOffering
@@ -220,20 +221,17 @@ public interface UserVmService {
* available.
*/
UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List securityGroupIdList,
- Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
+ Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, List dataDiskInfoList, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
String userData, Long userDataId, String userDataDetails, List sshKeyPairs, Map requestedIps, IpAddresses defaultIp, Boolean displayVm, String keyboard,
List affinityGroupIdList, Map customParameter, String customId, Map> dhcpOptionMap,
Map dataDiskTemplateToDiskOfferingMap,
- Map userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId) throws InsufficientCapacityException,
+ Map userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId, Volume volume, Snapshot snapshot) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
/**
* Creates a User VM in Advanced Zone (Security Group feature is enabled) in
* the database and returns the VM to the caller.
*
- *
- *
- * @param type
* @param zone
* - availability zone for the virtual machine
* @param serviceOffering
@@ -300,23 +298,15 @@ public interface UserVmService {
* available.
*/
UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList,
- List securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
+ List securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, List dataDiskInfoList, String group, HypervisorType hypervisor,
HTTPMethod httpmethod, String userData, Long userDataId, String userDataDetails, List sshKeyPairs, Map requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard,
List affinityGroupIdList, Map customParameters, String customId, Map> dhcpOptionMap,
- Map dataDiskTemplateToDiskOfferingMap, Map userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId, String vmType) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
+ Map dataDiskTemplateToDiskOfferingMap, Map userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId, String vmType, Volume volume, Snapshot snapshot) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
/**
* Creates a User VM in Advanced Zone (Security Group feature is disabled)
* in the database and returns the VM to the caller.
*
- *
- *
- * @param sshKeyPair
- * - name of the ssh key pair used to login to the virtual
- * machine
- * @param cpuSpeed
- * @param memory
- * @param cpuNumber
* @param zone
* - availability zone for the virtual machine
* @param serviceOffering
@@ -380,10 +370,10 @@ public interface UserVmService {
* available.
*/
UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, Account owner,
- String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData,
+ String hostName, String displayName, Long diskOfferingId, Long diskSize, List dataDiskInfoList, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData,
Long userDataId, String userDataDetails, List sshKeyPairs, Map requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, List affinityGroupIdList,
Map customParameters, String customId, Map> dhcpOptionMap, Map dataDiskTemplateToDiskOfferingMap,
- Map templateOvfPropertiesMap, boolean dynamicScalingEnabled, String vmType, Long overrideDiskOfferingId)
+ Map templateOvfPropertiesMap, boolean dynamicScalingEnabled, String vmType, Long overrideDiskOfferingId, Volume volume, Snapshot snapshot)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
@@ -483,14 +473,14 @@ public interface UserVmService {
VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost, Map volumeToPool) throws ResourceUnavailableException,
ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException;
- UserVm moveVMToUser(AssignVMCmd moveUserVMCmd) throws ResourceAllocationException, ConcurrentOperationException, ResourceUnavailableException,
+ UserVm moveVmToUser(AssignVMCmd moveUserVMCmd) throws ResourceAllocationException, ConcurrentOperationException, ResourceUnavailableException,
InsufficientCapacityException;
VirtualMachine vmStorageMigration(Long vmId, StoragePool destPool);
VirtualMachine vmStorageMigration(Long vmId, Map volumeToPool);
- UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException;
+ UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ResourceAllocationException;
UserVm restoreVirtualMachine(Account caller, long vmId, Long newTemplateId, Long rootDiskOfferingId, boolean expunge, Map details) throws InsufficientCapacityException, ResourceUnavailableException;
@@ -527,4 +517,8 @@ public interface UserVmService {
* @return true if the VM is successfully unmanaged, false if not.
*/
boolean unmanageUserVM(Long vmId);
+
+ UserVm allocateVMFromBackup(CreateVMFromBackupCmd cmd) throws InsufficientCapacityException, ResourceAllocationException, ResourceUnavailableException;
+
+ UserVm restoreVMFromBackup(CreateVMFromBackupCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException;
}
diff --git a/api/src/main/java/com/cloud/vm/VirtualMachine.java b/api/src/main/java/com/cloud/vm/VirtualMachine.java
index e7c5efb773b..d244de7115e 100644
--- a/api/src/main/java/com/cloud/vm/VirtualMachine.java
+++ b/api/src/main/java/com/cloud/vm/VirtualMachine.java
@@ -128,7 +128,6 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Partition,
s_fsm.addTransition(new Transition(State.Error, VirtualMachine.Event.DestroyRequested, State.Expunging, null));
s_fsm.addTransition(new Transition(State.Error, VirtualMachine.Event.ExpungeOperation, State.Expunging, null));
s_fsm.addTransition(new Transition(State.Stopped, Event.RestoringRequested, State.Restoring, null));
- s_fsm.addTransition(new Transition