(), new NamedThreadFactory(
- "agentRequest-Handler"));
+ 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"));
}
- public Agent(final IAgentShell shell, final int localAgentId, final ServerResource resource) throws ConfigurationException {
- _shell = shell;
- _resource = resource;
- _link = null;
+ /**
+ * 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) {
+ 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 {
+ 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 " + (_id != null ? _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 = " + (_id != null ? _id : "new") + " : type = " + getResourceName() + " : zone = " + _shell.getZone() + " : pod = " + _shell.getPod() +
- " : workers = " + _shell.getWorkers() + " : host = " + host + " : port = " + _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();
}
/**
@@ -254,77 +296,69 @@ public String getResourceName() {
* 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("NIO Connection Exception " + e);
- logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...");
- }
- 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);
+ 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(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 != null ? ": Detail = " + 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());
+ logger.warn("Unable to send: {}", cmd.toString());
} catch (final Exception e) {
- logger.warn("Unable to send: " + cmd.toString() + " due to exception: ", e);
+ logger.warn("Unable to send: {} due to exception: {}", cmd.toString(), e);
}
logger.debug("Sending shutdown to management server");
try {
@@ -332,111 +366,148 @@ public void stop(final String reason, final String detail) {
} 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.info("Set agent id " + id);
- _id = id;
- _shell.setPersistentProperty(getResourceName(), "id", Long.toString(id));
+ logger.debug("Set agent id {}", id);
+ this.id = id;
+ shell.setPersistentProperty(getResourceName(), "id", Long.toString(id));
+ }
+
+ public String getUuid() {
+ return _uuid;
}
- private synchronized void scheduleServicesRestartTask() {
- if (certTimer != null) {
- certTimer.cancel();
- certTimer.purge();
+ 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=" + checkInterval + "ms");
- 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 host.lb.interval={} ms", 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) {
- if (logger.isDebugEnabled()) {
- logger.debug("Adding a watch list");
- }
- 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());
+ logger.warn("Unable to send ping update: {}", request.toString());
}
}
protected void cancelTasks() {
- synchronized (_watchList) {
- for (final WatchTask task : _watchList) {
- task.cancel();
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Clearing watch list: " + _watchList.size());
- }
- _watchList.clear();
+ for (final ScheduledFuture> task : watchList) {
+ task.cancel(true);
}
+ logger.debug("Clearing watch list: {}", () -> watchList.size());
+ watchList.clear();
}
/**
@@ -447,61 +518,90 @@ protected void cancelTasks() {
* 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());
- if (logger.isDebugEnabled()) {
- logger.debug("Sending Startup: " + request.toString());
- }
+ logger.debug("Sending Startup: {}", request.toString());
lockStartupTask(link);
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());
@@ -509,6 +609,13 @@ protected void setupStartupCommand(final StartupCommand startup) {
startup.setGuid(getResourceGuid());
startup.setResourceName(getResourceName());
startup.setVersion(getVersion());
+ startup.setArch(getAgentArch());
+ }
+
+ protected String getAgentArch() {
+ String arch = Script.runSimpleBashScript(Script.getExecutableAbsolutePath("arch"), 2000);
+ logger.debug("Arch for agent: {} found: {}", _name, arch);
+ return arch;
}
@Override
@@ -517,92 +624,104 @@ public Task create(final Task.Type type, final Link link, final byte[] data) {
}
protected void reconnect(final Link link) {
- if (!_reconnectAllowed) {
- return;
- }
- synchronized (this) {
- if (_startup != null) {
- _startup.cancel();
- _startup = null;
- }
- }
+ reconnect(link, null, false);
+ }
- if (link != null) {
- link.close();
- link.terminated();
+ 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;
}
-
+ 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: " + _shell.getConnectedHost() + ". Attempting reconnection while we still have " + _inProgress.get() + " commands in progress.");
-
- _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);
+ 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());
+ 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) {
@@ -624,28 +743,35 @@ protected void processRequest(final Request request, final Link link) {
{
final String requestMsg = request.toString();
if (requestMsg != null) {
- logger.debug("Request:" + requestMsg);
+ logger.debug("Request:{}",requestMsg);
}
requestLogged = true;
}
- logger.debug("Processing command: " + cmd.toString());
+ logger.debug("Processing command: {}", cmd.toString());
}
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;
- logger.debug("Received shutdownCommand, due to: " + shutdown.getReason());
+ logger.debug("Received shutdownCommand, due to: {}", shutdown.getReason());
cancelTasks();
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());
+
+ 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) {
@@ -653,40 +779,43 @@ protected void processRequest(final Request request, final Link link) {
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;
}
}
if (answer == null) {
- logger.warn("No handler found to process cmd: " + cmd.toString());
+ logger.warn("No handler found to process cmd: {}", cmd.toString());
answer = new AgentControlAnswer(cmd);
}
} else if (cmd instanceof SetupKeyStoreCommand && ((SetupKeyStoreCommand) cmd).isHandleByAgent()) {
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());
+ logger.debug("Response: unsupported command {}", cmd.toString());
answer = Answer.createUnsupportedCommandAnswer(cmd);
}
}
@@ -718,7 +847,7 @@ protected void processRequest(final Request request, final Link link) {
try {
link.send(response.toBytes());
} catch (final ClosedChannelException e) {
- logger.warn("Unable to send response: " + response.toString());
+ logger.warn("Unable to send response: {}", response.toString());
}
}
}
@@ -737,13 +866,13 @@ public Answer setupAgentKeystore(final SetupKeyStoreCommand cmd) {
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,13 +911,13 @@ private Answer setupAgentCertificate(final SetupCertificateCommand cmd) {
try {
FileUtils.writeStringToFile(new File(certFile), certificate, Charset.defaultCharset());
FileUtils.writeStringToFile(new File(caCertFile), caCertificates, Charset.defaultCharset());
- logger.debug("Saved received client certificate to: " + certFile);
+ logger.debug("Saved received client certificate to: {}", certFile);
} catch (IOException e) {
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);
@@ -806,50 +935,110 @@ private Answer setupAgentCertificate(final SetupCertificateCommand cmd) {
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();
- logger.info("Processed new management server list: " + newMSHosts);
+ 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();
- if (logger.isDebugEnabled()) {
- logger.debug("Received response: " + response.toString());
- }
+ logger.debug("Received response: {}", response.toString());
if (answer instanceof StartupAnswer) {
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) {
@@ -860,37 +1049,49 @@ public void processReadyCommand(final Command cmd) {
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: {}, uuid: {}, name: {}]", getId(), getUuid(), getName());
+ }
- logger.info("Ready command is processed for agent id = " + getId());
+ 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 " + _pingInterval * _shell.getPingRetries() + ". Won't reconnect to mgt server, as connection is still alive");
+ 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());
- if (logger.isDebugEnabled()) {
- logger.debug("Sending ping: " + request.toString());
- }
+ 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) {
@@ -900,22 +1101,23 @@ public void processOtherTask(final Task task) {
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);
- if (logger.isDebugEnabled()) {
- logger.debug("Watch Sent: " + response.toString());
- }
+ logger.debug("Watch Sent: {}", response.toString());
try {
task.getLink().send(response.toBytes());
} catch (final ClosedChannelException e) {
- logger.warn("Unable to send response: " + response.toString());
+ logger.warn("Unable to send response: {}", response.toString());
}
}
} else {
@@ -923,35 +1125,29 @@ public void processOtherTask(final Task task) {
}
}
- 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);
@@ -962,7 +1158,6 @@ public AgentControlAnswer sendRequest(final AgentControlCommand cmd, final int t
logger.warn("sendRequest is interrupted, exit waiting");
}
}
-
return listener.getAnswer();
} finally {
unregisterControlListener(listener);
@@ -977,11 +1172,11 @@ public void postRequest(final AgentControlCommand cmd) throws AgentControlChanne
}
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());
+ logger.warn("Unable to post agent control request: {}", request.toString());
throw new AgentControlChannelException("Unable to post agent control request due to " + e.getMessage());
}
} else {
@@ -1031,28 +1226,26 @@ public void run() {
}
}
- 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() {
- if (logger.isTraceEnabled()) {
- logger.trace("Scheduling " + (_request instanceof Response ? "Ping" : "Watch Task"));
- }
+ 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");
@@ -1060,37 +1253,32 @@ protected void runInContext() {
}
}
- 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) {
- if (logger.isInfoEnabled()) {
- 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);
}
}
}
@@ -1121,9 +1309,10 @@ public ServerHandler(final Task.Type type, final Link link, final Request req) {
@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 {
@@ -1133,8 +1322,7 @@ public void doTask(final Task task) throws TaskExecutionException {
processResponse((Response)request, task.getLink());
} 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 ");
@@ -1142,8 +1330,16 @@ public void doTask(final Task task) throws TaskExecutionException {
logger.error("Error parsing task", e);
}
} else if (task.getType() == Task.Type.DISCONNECT) {
+ try {
+ // an issue has been found if reconnect immediately after disconnecting.
+ // wait 5 seconds before reconnecting
+ logger.debug("Wait for 5 secs before reconnecting, disconnect task - {}", () -> getLinkLog(task.getLink()));
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ }
+ shell.setConnectionTransfer(false);
+ logger.debug("Executing disconnect task - {} and reconnecting", () -> getLinkLog(task.getLink()));
reconnect(task.getLink());
- return;
} else if (task.getType() == Task.Type.OTHER) {
processOtherTask(task);
}
@@ -1166,35 +1362,33 @@ public PostCertificateRenewalTask(final Agent agent) {
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
shell.launchNewAgent(resource);
return;
}
- if (logger.isTraceEnabled()) {
- logger.debug("Other tasks are in progress, will retry post certificate renewal command after few seconds");
- }
+ 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);
@@ -1209,38 +1403,34 @@ public class PreferredHostCheckerTask extends ManagedContextTimerTask {
@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();
- if (logger.isTraceEnabled()) {
- logger.trace("Running preferred host checker task, connected host=" + connectedHost + ", preferred host=" + preferredHost);
+ 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;
}
- 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;
- if (logger.isTraceEnabled()) {
- logger.trace("Host: " + preferredHost + " is not reachable");
- }
- }
- if (isHostUp && _link != null && _inProgress.get() == 0) {
- if (logger.isDebugEnabled()) {
- logger.debug("Preferred host " + preferredHost + " is found to be reachable, trying to reconnect");
- }
- _shell.resetHostCounter();
- reconnect(_link);
+ 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 4b2bd9a524f6..4862e7e001e3 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.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 String getNextHost() {
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 long getLbCheckerInterval(final Long receivedLbInterval) {
}
@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 void setHosts(final String host) {
}
}
+ @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 void setPersistentProperty(String prefix, String name, String value) {
_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");
@@ -222,7 +242,7 @@ void loadProperties() throws ConfigurationException {
throw new ConfigurationException("Unable to find agent.properties.");
}
- LOGGER.info("agent.properties found at " + file.getAbsolutePath());
+ LOGGER.info("agent.properties found at {}", file.getAbsolutePath());
try {
PropertiesUtil.loadFromFile(_properties, file);
@@ -382,7 +402,7 @@ public void init(String[] args) throws ConfigurationException {
if (_version == null) {
throw new CloudRuntimeException("Unable to find the implementation version of this agent");
}
- LOGGER.info("Implementation Version is " + _version);
+ LOGGER.info("Implementation Version is {}", _version);
loadProperties();
parseCommand(args);
@@ -390,7 +410,7 @@ public void init(String[] args) throws ConfigurationException {
if (LOGGER.isDebugEnabled()) {
List properties = Collections.list((Enumeration)_properties.propertyNames());
for (String property : properties) {
- LOGGER.debug("Found property: " + property);
+ LOGGER.debug("Found property: {}", property);
}
}
@@ -406,12 +426,14 @@ public void init(String[] args) throws ConfigurationException {
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 {
String resourceClassNames = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.RESOURCE);
- LOGGER.trace("resource=" + resourceClassNames);
+ LOGGER.trace("resource={}", resourceClassNames);
if (resourceClassNames != null) {
launchAgentFromClassInfo(resourceClassNames);
return;
@@ -444,7 +466,7 @@ private void launchAgentFromTypeInfo() throws ConfigurationException {
LOGGER.error("Unable to retrieve the type");
throw new ConfigurationException("Unable to retrieve the type of this agent.");
}
- LOGGER.trace("Launching agent based on type=" + typeInfo);
+ LOGGER.trace("Launching agent based on type={}", typeInfo);
}
public void launchNewAgent(ServerResource resource) throws ConfigurationException {
@@ -455,6 +477,11 @@ public void launchNewAgent(ServerResource resource) throws ConfigurationExceptio
agent.start();
}
+ @Override
+ public Integer getSslHandshakeTimeout() {
+ return AgentPropertiesFileHandler.getPropertyValue(AgentProperties.SSL_HANDSHAKE_TIMEOUT);
+ }
+
public synchronized int getNextAgentId() {
return _nextAgentId++;
}
@@ -506,7 +533,7 @@ public void start() {
String pidDir = getProperty(null, "piddir");
final String run = "agent." + instance + "pid";
- LOGGER.debug("Checking to see if " + run + " exists.");
+ LOGGER.debug("Checking to see if {} exists.", run);
ProcessUtil.pidCheck(pidDir, run);
launchAgent();
diff --git a/agent/src/main/java/com/cloud/agent/IAgentShell.java b/agent/src/main/java/com/cloud/agent/IAgentShell.java
index 2dd08fffd459..9eefa6d2eeee 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/dao/impl/PropertiesStorage.java b/agent/src/main/java/com/cloud/agent/dao/impl/PropertiesStorage.java
index b4b22fa8d168..17e0ceeeedea 100644
--- a/agent/src/main/java/com/cloud/agent/dao/impl/PropertiesStorage.java
+++ b/agent/src/main/java/com/cloud/agent/dao/impl/PropertiesStorage.java
@@ -93,14 +93,12 @@ public synchronized boolean configure(String name, Map params) {
file = new File(path);
try {
if (!file.createNewFile()) {
- logger.error(String.format("Unable to create _file: %s", file.getAbsolutePath()));
+ logger.error("Unable to create _file: {}", file.getAbsolutePath());
return false;
}
} catch (IOException e) {
- logger.error(String.format("Unable to create file: %s", file.getAbsolutePath()));
- if (logger.isDebugEnabled()) {
- logger.debug(String.format("IOException while trying to create file: %s", file.getAbsolutePath()), e);
- }
+ logger.error("Unable to create file: {}", file.getAbsolutePath());
+ logger.debug("IOException while trying to create file: {}", file.getAbsolutePath(), e);
return false;
}
}
diff --git a/agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java b/agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java
index 1e6fefa48180..54fdde3d3d28 100644
--- a/agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java
+++ b/agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java
@@ -87,8 +87,7 @@ public String startVM(String vmName, String vnetId, String gateway, String dns,
@Override
public String stopVM(String vmName, boolean force) {
- if (logger.isInfoEnabled())
- logger.info("Stop VM. name: " + vmName);
+ logger.info("Stop VM. name: {}", vmName);
synchronized (this) {
MockVm vm = vms.get(vmName);
@@ -103,8 +102,7 @@ public String stopVM(String vmName, boolean force) {
@Override
public String rebootVM(String vmName) {
- if (logger.isInfoEnabled())
- logger.info("Reboot VM. name: " + vmName);
+ logger.info("Reboot VM. name: {}", vmName);
synchronized (this) {
MockVm vm = vms.get(vmName);
@@ -116,8 +114,7 @@ public String rebootVM(String vmName) {
@Override
public boolean migrate(String vmName, String params) {
- if (logger.isInfoEnabled())
- logger.info("Migrate VM. name: " + vmName);
+ logger.info("Migrate VM. name: {}", vmName);
synchronized (this) {
MockVm vm = vms.get(vmName);
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 322a0ed2444f..18a6b6df1006 100644
--- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
+++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
@@ -117,12 +117,26 @@ public class AgentProperties{
/**
* Local storage path.
- * This property allows multiple values to be entered in a single String. The differente values must be separated by commas.
+ * This property allows multiple values to be entered in a single String. The different values must be separated by commas.
* Data type: String.
* Default value: /var/lib/libvirt/images/
*/
public static final Property LOCAL_STORAGE_PATH = new Property<>("local.storage.path", "/var/lib/libvirt/images/");
+ /**
+ * Enables TLS on the KVM image server transfer endpoint.
+ * Data type: Boolean.
+ * Default value: true
+ */
+ public static final Property IMAGE_SERVER_TLS_ENABLED = new Property<>("image.server.tls.enabled", true);
+
+ /**
+ * The IP address that the KVM image server listens on.
+ * Data type: String.
+ * Default value: null
+ */
+ public static final Property IMAGE_SERVER_LISTEN_ADDRESS = new Property<>("image.server.listen.address", null, String.class);
+
/**
* Directory where Qemu sockets are placed.
* These sockets are for the Qemu Guest Agent and SSVM provisioning.
@@ -134,7 +148,7 @@ public class AgentProperties{
/**
* MANDATORY: The UUID for the local storage pool.
- * This property allows multiple values to be entered in a single String. The differente values must be separated by commas.
+ * This property allows multiple values to be entered in a single String. The different values must be separated by commas.
* Data type: String.
* Default value: null
*/
@@ -155,6 +169,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 +235,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 +264,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 +292,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,15 +432,16 @@ 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).
*/
public static final Property GUEST_CPU_ARCH = new Property<>("guest.cpu.arch", null, String.class);
/**
- * This param will require CPU features on the CPU section.
- * The features listed in this property must be separated by a blank space (see example below).
+ * Specifies required CPU features for end-user and system VMs.
+ * These features must be present on the host CPU for VM deployment.
+ * Multiple features should be separated by whitespace (see example below).
* Possible values: vmx vme
* Data type: String.
* Default value: null
@@ -516,6 +566,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
*/
@@ -695,6 +746,13 @@ public class AgentProperties{
*/
public static final Property DEVELOPER = new Property<>("developer", false);
+ /**
+ * If set to "true", the agent will register for libvirt domain events, allowing for immediate updates on crashed or unexpectedly
+ * stopped VMs. Experimental, requires agent restart.
+ * Default value: false
+ */
+ public static final Property LIBVIRT_EVENTS_ENABLED = new Property<>("libvirt.events.enabled", false);
+
/**
* Can only be used if developer = true. This property is used to define the local bridge name and private network name.
* Data type: String.
@@ -744,12 +802,50 @@ public Property getWorkers() {
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
*/
public static final Property VIRTV2V_VERBOSE_ENABLED = new Property<>("virtv2v.verbose.enabled", false);
+ /**
+ * Set env TMPDIR var for virt-v2v Instance Conversion from VMware to KVM
+ * Data type: String.
+ * Default value: null
+ */
+ public static final Property CONVERT_ENV_TMPDIR = new Property<>("convert.instance.env.tmpdir", null, String.class);
+
+ /**
+ * Set env VIRT_V2V_TMPDIR var for virt-v2v Instance Conversion from VMware to KVM
+ * Data type: String.
+ * Default value: null
+ */
+ public static final Property CONVERT_ENV_VIRTV2V_TMPDIR = new Property<>("convert.instance.env.virtv2v.tmpdir", null, String.class);
+
+ /**
+ * Path to the VDDK library directory on the KVM conversion host, used when converting VMs from VMware to KVM via VDDK.
+ * This directory is passed to virt-v2v as -io vddk-libdir=<path>.
+ * Data type: String.
+ * Default value: null
+ */
+ public static final Property VDDK_LIB_DIR = new Property<>("vddk.lib.dir", null, String.class);
+
+ /**
+ * Ordered list of VDDK transports for virt-v2v, passed as -io vddk-transports=<value>.
+ * Example: nbd:nbdssl.
+ * Data type: String.
+ * Default value: null
+ */
+ public static final Property VDDK_TRANSPORTS = new Property<>("vddk.transports", null, String.class);
+
+ /**
+ * vCenter TLS certificate thumbprint used by virt-v2v VDDK mode, passed as -io vddk-thumbprint=<value>.
+ * If unset, the KVM host computes it at runtime from the vCenter endpoint.
+ * Data type: String.
+ * Default value: null
+ */
+ public static final Property VDDK_THUMBPRINT = new Property<>("vddk.thumbprint", null, String.class);
+
/**
* BGP controll CIDR
* Data type: String.
@@ -796,12 +892,49 @@ public Property getWorkers() {
*/
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);
+
+ /**
+ * Time, in seconds, to wait before retrying to rebase during the incremental snapshot process.
+ * */
+ public static final Property INCREMENTAL_SNAPSHOT_RETRY_REBASE_WAIT = new Property<>("incremental.snapshot.retry.rebase.wait", 60);
+
+
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/properties/AgentPropertiesFileHandler.java b/agent/src/main/java/com/cloud/agent/properties/AgentPropertiesFileHandler.java
index 614848fb96e4..b28018fcd943 100644
--- a/agent/src/main/java/com/cloud/agent/properties/AgentPropertiesFileHandler.java
+++ b/agent/src/main/java/com/cloud/agent/properties/AgentPropertiesFileHandler.java
@@ -48,7 +48,7 @@ public static T getPropertyValue(AgentProperties.Property property) {
File agentPropertiesFile = PropertiesUtil.findConfigFile(KeyStoreUtils.AGENT_PROPSFILE);
if (agentPropertiesFile == null) {
- LOGGER.debug(String.format("File [%s] was not found, we will use default defined values. Property [%s]: [%s].", KeyStoreUtils.AGENT_PROPSFILE, name, defaultValue));
+ LOGGER.debug("File [{}] was not found, we will use default defined values. Property [{}]: [{}].", KeyStoreUtils.AGENT_PROPSFILE, name, defaultValue);
return defaultValue;
}
@@ -56,7 +56,7 @@ public static T getPropertyValue(AgentProperties.Property property) {
try {
String configValue = PropertiesUtil.loadFromFile(agentPropertiesFile).getProperty(name);
if (StringUtils.isBlank(configValue)) {
- LOGGER.debug(String.format("Property [%s] has empty or null value. Using default value [%s].", name, defaultValue));
+ LOGGER.debug("Property [{}] has empty or null value. Using default value [{}].", name, defaultValue);
return defaultValue;
}
@@ -68,11 +68,11 @@ public static T getPropertyValue(AgentProperties.Property property) {
ConvertUtils.register(new LongConverter(defaultValue), Long.class);
}
- LOGGER.debug(String.format("Property [%s] was altered. Now using the value [%s].", name, configValue));
+ LOGGER.debug("Property [{}] was altered. Now using the value [{}].", name, configValue);
return (T)ConvertUtils.convert(configValue, property.getTypeClass());
} catch (IOException ex) {
- LOGGER.debug(String.format("Failed to get property [%s]. Using default value [%s].", name, defaultValue), ex);
+ LOGGER.debug("Failed to get property [{}]. Using default value [{}].", name, defaultValue, ex);
}
return defaultValue;
diff --git a/agent/src/main/java/com/cloud/agent/resource/DummyResource.java b/agent/src/main/java/com/cloud/agent/resource/DummyResource.java
index fe519ca9497f..4002e53b5858 100644
--- a/agent/src/main/java/com/cloud/agent/resource/DummyResource.java
+++ b/agent/src/main/java/com/cloud/agent/resource/DummyResource.java
@@ -20,7 +20,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.UUID;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
@@ -40,6 +39,7 @@
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.utils.StringUtils;
+import com.cloud.utils.UuidUtils;
public class DummyResource implements ServerResource {
String _name;
@@ -133,7 +133,7 @@ protected StoragePoolInfo initializeLocalStorage() {
String hostIp = getConfiguredProperty("private.ip.address", "127.0.0.1");
String localStoragePath = getConfiguredProperty("local.storage.path", "/mnt");
String lh = hostIp + localStoragePath;
- String uuid = UUID.nameUUIDFromBytes(lh.getBytes(StringUtils.getPreferredCharset())).toString();
+ String uuid = UuidUtils.nameUUIDFromBytes(lh.getBytes(StringUtils.getPreferredCharset())).toString();
String capacity = getConfiguredProperty("local.storage.capacity", "1000000000");
String available = getConfiguredProperty("local.storage.avail", "10000000");
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 f0407a129882..ef98fa532ecb 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
@@ -175,12 +175,12 @@ private Answer executeProxyLoadScan(final Command cmd, final long proxyVmId, fin
try {
is.close();
} catch (final IOException e) {
- logger.warn("Exception when closing , console proxy address : " + proxyManagementIp);
+ logger.warn("Exception when closing , console proxy address: {}", proxyManagementIp);
success = false;
}
}
} catch (final IOException e) {
- logger.warn("Unable to open console proxy command port url, console proxy address : " + proxyManagementIp);
+ logger.warn("Unable to open console proxy command port url, console proxy address: {}", proxyManagementIp);
success = false;
}
@@ -278,20 +278,19 @@ public boolean configure(String name, Map params) throws Configu
disableRpFilter();
}
- if (logger.isInfoEnabled())
- logger.info("Receive proxyVmId in ConsoleProxyResource configuration as " + proxyVmId);
+ logger.info("Receive proxyVmId in ConsoleProxyResource configuration as {}", proxyVmId);
return true;
}
private void addRouteToInternalIpOrCidr(String localgw, String eth1ip, String eth1mask, String destIpOrCidr) {
- logger.debug("addRouteToInternalIp: localgw=" + localgw + ", eth1ip=" + eth1ip + ", eth1mask=" + eth1mask + ",destIp=" + destIpOrCidr);
+ logger.debug("addRouteToInternalIp: localgw={}, eth1ip={}, eth1mask={}, destIp={}", localgw, eth1ip, eth1mask, destIpOrCidr);
if (destIpOrCidr == null) {
logger.debug("addRouteToInternalIp: destIp is null");
return;
}
if (!NetUtils.isValidIp4(destIpOrCidr) && !NetUtils.isValidIp4Cidr(destIpOrCidr)) {
- logger.warn(" destIp is not a valid ip address or cidr destIp=" + destIpOrCidr);
+ logger.warn(" destIp is not a valid ip address or cidr destIp={}", destIpOrCidr);
return;
}
boolean inSameSubnet = false;
@@ -299,13 +298,13 @@ private void addRouteToInternalIpOrCidr(String localgw, String eth1ip, String et
if (eth1ip != null && eth1mask != null) {
inSameSubnet = NetUtils.sameSubnet(eth1ip, destIpOrCidr, eth1mask);
} else {
- logger.warn("addRouteToInternalIp: unable to determine same subnet: eth1ip=" + eth1ip + ", dest ip=" + destIpOrCidr + ", eth1mask=" + eth1mask);
+ logger.warn("addRouteToInternalIp: unable to determine same subnet: eth1ip={}, dest ip={}, eth1mask={}", eth1ip, destIpOrCidr, eth1mask);
}
} else {
inSameSubnet = NetUtils.isNetworkAWithinNetworkB(destIpOrCidr, NetUtils.ipAndNetMaskToCidr(eth1ip, eth1mask));
}
if (inSameSubnet) {
- logger.debug("addRouteToInternalIp: dest ip " + destIpOrCidr + " is in the same subnet as eth1 ip " + eth1ip);
+ logger.debug("addRouteToInternalIp: dest ip {} is in the same subnet as eth1 ip {}", destIpOrCidr, eth1ip);
return;
}
Script command = new Script("/bin/bash", logger);
@@ -317,9 +316,9 @@ private void addRouteToInternalIpOrCidr(String localgw, String eth1ip, String et
command.add("ip route add " + destIpOrCidr + " via " + localgw);
String result = command.execute();
if (result != null) {
- logger.warn("Error in configuring route to internal ip err=" + result);
+ logger.warn("Error in configuring route to internal ip err={}", result);
} else {
- logger.debug("addRouteToInternalIp: added route to internal ip=" + destIpOrCidr + " via " + localgw);
+ logger.debug("addRouteToInternalIp: added route to internal ip={} via {}", destIpOrCidr, localgw);
}
}
@@ -332,7 +331,7 @@ private void launchConsoleProxy(final byte[] ksBits, final String ksPassword, fi
final Object resource = this;
logger.info("Building class loader for com.cloud.consoleproxy.ConsoleProxy");
if (consoleProxyMain == null) {
- logger.info("Running com.cloud.consoleproxy.ConsoleProxy with encryptor password=" + encryptorPassword);
+ logger.info("Running com.cloud.consoleproxy.ConsoleProxy");
consoleProxyMain = new Thread(new ManagedContextRunnable() {
@Override
protected void runInContext() {
@@ -355,7 +354,7 @@ protected void runInContext() {
logger.error("Unable to launch console proxy due to IllegalAccessException", e);
System.exit(ExitStatus.Error.value());
} catch (InvocationTargetException e) {
- logger.error("Unable to launch console proxy due to InvocationTargetException " + e.getTargetException().toString(), e);
+ logger.error("Unable to launch console proxy due to InvocationTargetException {}", e.getTargetException().toString(), e);
System.exit(ExitStatus.Error.value());
}
} catch (final ClassNotFoundException e) {
@@ -398,9 +397,8 @@ protected void runInContext() {
}
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();
@@ -418,10 +416,10 @@ public String authenticateConsoleAccess(String host, String port, String vmId, S
result.setTunnelUrl(authAnswer.getTunnelUrl());
result.setTunnelSession(authAnswer.getTunnelSession());
} else {
- logger.error("Authentication failed for vm: " + vmId + " with sid: " + sid);
+ logger.error("Authentication failed for vm: {} with sid: {}", vmId, sid);
}
} catch (AgentControlChannelException e) {
- logger.error("Unable to send out console access authentication request due to " + e.getMessage(), e);
+ logger.error("Unable to send out console access authentication request due to {}", e.getMessage(), e);
}
return new Gson().toJson(result);
@@ -431,18 +429,15 @@ public void reportLoadInfo(String gsonLoadInfo) {
ConsoleProxyLoadReportCommand cmd = new ConsoleProxyLoadReportCommand(proxyVmId, gsonLoadInfo);
try {
getAgentControl().postRequest(cmd);
-
- if (logger.isDebugEnabled())
- logger.debug("Report proxy load info, proxy : " + proxyVmId + ", load: " + gsonLoadInfo);
+ logger.debug("Report proxy load info, proxy : {}, load: {}", proxyVmId, gsonLoadInfo);
} catch (AgentControlChannelException e) {
- logger.error("Unable to send out load info due to " + e.getMessage(), e);
+ logger.error("Unable to send out load info due to {}", e.getMessage(), e);
}
}
public void ensureRoute(String address) {
if (localGateway != null) {
- if (logger.isDebugEnabled())
- logger.debug("Ensure route for " + address + " via " + localGateway);
+ logger.debug("Ensure route for {} via {}", address, localGateway);
// this method won't be called in high frequency, serialize access
// to script execution
@@ -450,7 +445,7 @@ public void ensureRoute(String address) {
try {
addRouteToInternalIpOrCidr(localGateway, eth1Ip, eth1Mask, address);
} catch (Throwable e) {
- logger.warn("Unexpected exception while adding internal route to " + address, e);
+ logger.warn("Unexpected exception while adding internal route to {}", address, e);
}
}
}
diff --git a/agent/src/test/java/com/cloud/agent/AgentShellTest.java b/agent/src/test/java/com/cloud/agent/AgentShellTest.java
index f7151779f585..d8def24a603a 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 void setHostTestValueIsNullPropertyDoesNotStartAndEndWithAtSignSetHosts()
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 000000000000..65dc030ebd76
--- /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 32897725e0c1..c80c35593451 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -24,7 +24,7 @@
org.apache.cloudstack
cloudstack
- 4.20.0.0-SNAPSHOT
+ 4.23.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 eb979c0060b9..c4e99cb41707 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 @@
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 static enum OnError {
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 static enum OnError {
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 String getContextParam(String name) {
return contextMap.get(name);
}
+ public Map getContextMap() {
+ return contextMap;
+ }
+
public boolean allowCaching() {
return true;
}
@@ -94,6 +118,26 @@ public void setBypassHostMaintenance(boolean bypassHostMaintenance) {
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 85ffc1898209..5515a9c48bcb 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 Long getVideoRam() {
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 void setMaxVmCapacity(Long maxCapacity) {
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/storage/OVFHelper.java b/api/src/main/java/com/cloud/agent/api/storage/OVFHelper.java
index 6396e3deb723..23167c5c53b0 100644
--- a/api/src/main/java/com/cloud/agent/api/storage/OVFHelper.java
+++ b/api/src/main/java/com/cloud/agent/api/storage/OVFHelper.java
@@ -119,8 +119,7 @@ protected OVFPropertyTO createOVFPropertyFromNode(Node node, int index, String c
boolean password = StringUtils.isNotBlank(passStr) && passStr.equalsIgnoreCase("true");
String label = ovfParser.getChildNodeValue(node, "Label");
String description = ovfParser.getChildNodeValue(node, "Description");
- logger.debug("Creating OVF property index " + index + (category == null ? "" : " for category " + category)
- + " with key = " + key);
+ logger.debug("Creating OVF property index {} {} with key = {}", index, (category == null ? "" : " for category " + category), key);
return new OVFPropertyTO(key, type, value, qualifiers, userConfigurable,
label, description, password, index, category);
}
@@ -152,7 +151,7 @@ public List getConfigurableOVFPropertiesFromDocument(Document doc
if (child.getNodeName().equalsIgnoreCase("Category") ||
child.getNodeName().endsWith(":Category")) {
lastCategoryFound = child.getTextContent();
- logger.info("Category found " + lastCategoryFound);
+ logger.info("Category found {}", lastCategoryFound);
} else if (child.getNodeName().equalsIgnoreCase("Property") ||
child.getNodeName().endsWith(":Property")) {
OVFPropertyTO prop = createOVFPropertyFromNode(child, propertyIndex, lastCategoryFound);
@@ -250,13 +249,13 @@ private List matchHardwareItemsToDiskAndFilesInformation(List extractDisksFromOvfDocumentTree(Document doc) {
od._controller = getControllerType(items, od._diskId);
vd.add(od);
}
- if (logger.isTraceEnabled()) {
- logger.trace(String.format("found %d disk definitions",vd.size()));
- }
+ logger.trace("Found {} disk definitions", vd.size());
return vd;
}
@@ -366,9 +363,7 @@ protected List extractFilesFromOvfDocumentTree(File ovfFile, Document d
vf.add(of);
}
}
- if (logger.isTraceEnabled()) {
- logger.trace(String.format("found %d file definitions in %s",vf.size(), ovfFile.getPath()));
- }
+ logger.trace("Found {} file definitions in {}", vf.size(), ovfFile.getPath());
return vf;
}
@@ -506,7 +501,7 @@ private void writeDocumentToFile(String newOvfFilePath, Document doc) {
outfile.write(writer.toString());
outfile.close();
} catch (IOException | TransformerException e) {
- logger.info("Unexpected exception caught while rewriting OVF:" + e.getMessage(), e);
+ logger.info("Unexpected exception caught while rewriting OVF: {}", e.getMessage(), e);
throw new CloudRuntimeException(e);
}
}
@@ -522,9 +517,7 @@ OVFFile getFileDefinitionFromDiskDefinition(String fileRef, List files)
public List getNetPrerequisitesFromDocument(Document doc) throws InternalErrorException {
if (doc == null) {
- if (logger.isTraceEnabled()) {
- logger.trace("no document to parse; returning no prerequisite networks");
- }
+ logger.trace("No document to parse; returning no prerequisite networks");
return Collections.emptyList();
}
@@ -540,9 +533,7 @@ public List getNetPrerequisitesFromDocument(Document doc) throws I
private void matchNicsToNets(Map nets, Node systemElement) {
final DocumentTraversal traversal = (DocumentTraversal) systemElement;
final NodeIterator iterator = traversal.createNodeIterator(systemElement, NodeFilter.SHOW_ELEMENT, null, true);
- if (logger.isTraceEnabled()) {
- logger.trace(String.format("starting out with %d network-prerequisites, parsing hardware",nets.size()));
- }
+ logger.trace("Starting out with {} network-prerequisites, parsing hardware", nets.size());
int nicCount = 0;
for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
final Element e = (Element) n;
@@ -550,9 +541,7 @@ private void matchNicsToNets(Map nets, Node systemElement)
nicCount++;
String name = e.getTextContent(); // should be in our nets
if(nets.get(name) == null) {
- if(logger.isInfoEnabled()) {
- logger.info(String.format("found a nic definition without a network definition byname %s, adding it to the list.", name));
- }
+ logger.info("Found a NIC definition without a Network definition by name {}, adding it to the list.", name);
nets.put(name, new OVFNetworkTO());
}
OVFNetworkTO thisNet = nets.get(name);
@@ -561,9 +550,7 @@ private void matchNicsToNets(Map nets, Node systemElement)
}
}
}
- if (logger.isTraceEnabled()) {
- logger.trace(String.format("ending up with %d network-prerequisites, parsed %d nics", nets.size(), nicCount));
- }
+ logger.trace("Ending up with {} network-prerequisites, parsed {} nics", nets.size(), nicCount);
}
/**
@@ -585,7 +572,7 @@ private void fillNicPrerequisites(OVFNetworkTO nic, Node parentNode) {
int addressOnParent = Integer.parseInt(addressOnParentStr);
nic.setAddressOnParent(addressOnParent);
} catch (NumberFormatException e) {
- logger.warn("Encountered element of type \"AddressOnParent\", that could not be parse to an integer number: " + addressOnParentStr);
+ logger.warn("Encountered element of type \"AddressOnParent\", that could not be parse to an integer number: {}", addressOnParentStr);
}
boolean automaticAllocation = StringUtils.isNotBlank(automaticAllocationStr) && Boolean.parseBoolean(automaticAllocationStr);
@@ -597,7 +584,7 @@ private void fillNicPrerequisites(OVFNetworkTO nic, Node parentNode) {
int instanceId = Integer.parseInt(instanceIdStr);
nic.setInstanceID(instanceId);
} catch (NumberFormatException e) {
- logger.warn("Encountered element of type \"InstanceID\", that could not be parse to an integer number: " + instanceIdStr);
+ logger.warn("Encountered element of type \"InstanceID\", that could not be parse to an integer number: {}", instanceIdStr);
}
nic.setResourceSubType(resourceSubType);
@@ -630,9 +617,7 @@ private Map getNetworksFromDocumentTree(Document doc) {
nets.put(networkName,network);
}
- if (logger.isTraceEnabled()) {
- logger.trace(String.format("found %d networks in template", nets.size()));
- }
+ logger.trace("Found {} Networks in Template", nets.size());
return nets;
}
@@ -771,7 +756,7 @@ private Long getLongValueFromString(String value) {
try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
- logger.debug("Could not parse the value: " + value + ", ignoring it");
+ logger.debug("Could not parse the value: {}, ignoring it", value);
}
}
return null;
@@ -782,7 +767,7 @@ private Integer getIntValueFromString(String value) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
- logger.debug("Could not parse the value: " + value + ", ignoring it");
+ logger.debug("Could not parse the value: {}, ignoring it", value);
}
}
return null;
@@ -820,7 +805,7 @@ public List getEulaSectionsFromDocument(Document doc) {
try {
compressedLicense = compressOVFEula(eulaLicense);
} catch (IOException e) {
- logger.error("Could not compress the license for info " + eulaInfo);
+ logger.error("Could not compress the license for info {}", eulaInfo);
continue;
}
OVFEulaSectionTO eula = new OVFEulaSectionTO(eulaInfo, compressedLicense, eulaIndex);
diff --git a/api/src/main/java/com/cloud/agent/api/storage/OVFParser.java b/api/src/main/java/com/cloud/agent/api/storage/OVFParser.java
index 38f478d63cf8..316ab4ea87b9 100644
--- a/api/src/main/java/com/cloud/agent/api/storage/OVFParser.java
+++ b/api/src/main/java/com/cloud/agent/api/storage/OVFParser.java
@@ -54,7 +54,7 @@ public OVFParser() {
documentBuilderFactory.setNamespaceAware(true);
documentBuilder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
- logger.error("Cannot start the OVF parser: " + e.getMessage(), e);
+ logger.error("Cannot start the OVF parser: {}", e.getMessage(), e);
}
}
@@ -70,7 +70,7 @@ public Document parseOVFFile(String ovfFilePath) {
try {
return documentBuilder.parse(new File(ovfFilePath));
} catch (SAXException | IOException e) {
- logger.error("Error parsing " + ovfFilePath + " " + e.getMessage(), e);
+ logger.error("Error parsing {} {}", ovfFilePath, e.getMessage(), e);
return null;
}
}
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 000000000000..fd8237998a74
--- /dev/null
+++ b/api/src/main/java/com/cloud/agent/api/to/BucketTO.java
@@ -0,0 +1,57 @@
+// 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;
+
+ private long accountId;
+
+ public BucketTO(Bucket bucket) {
+ this.name = bucket.getName();
+ this.accessKey = bucket.getAccessKey();
+ this.secretKey = bucket.getSecretKey();
+ this.accountId = bucket.getAccountId();
+ }
+
+ 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;
+ }
+
+ public long getAccountId() {
+ return this.accountId;
+ }
+}
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 d22df2df172e..5664de790919 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 void setType(Volume.Type type) {
}
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 d08884d1cbe0..69350815be3a 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 FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, Firewa
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 4afe080477b7..6e9cee06dd38 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 void setVgpuType(String vgpuType) {
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 void setGroupDetails(HashMap> grou
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 966d24886fef..6c4b9e607c51 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
@@ -71,7 +71,7 @@ public LoadBalancerTO(String uuid, String srcIp, int srcPort, String protocol, S
this.destinations = new DestinationTO[destinations.size()];
this.stickinessPolicies = null;
this.sslCert = null;
- this.lbProtocol = null;
+ this.lbProtocol = protocol;
int i = 0;
for (LbDestination destination : destinations) {
this.destinations[i++] = new DestinationTO(destination.getIpAddress(), destination.getDestinationPortStart(), destination.isRevoked(), false);
@@ -205,6 +205,10 @@ public LbSslCert getSslCert() {
return this.sslCert;
}
+ public void setLbSslCert(LbSslCert sslCert) {
+ this.sslCert = sslCert;
+ }
+
public String getSrcIpVlan() {
return srcIpVlan;
}
@@ -374,13 +378,15 @@ public String getMonitorState() {
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 +397,10 @@ public Long getId() {
return id;
}
+ public String getUuid() {
+ return uuid;
+ }
+
public String getName() {
return name;
}
@@ -411,12 +421,14 @@ public String getProvider() {
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 +438,10 @@ public Long getId() {
return id;
}
+ public String getUuid() {
+ return uuid;
+ }
+
public long getThreshold() {
return threshold;
}
@@ -442,6 +458,7 @@ public CounterTO getCounter() {
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 +466,9 @@ public static class AutoScalePolicyTO implements Serializable {
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 +481,10 @@ public long getId() {
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 bd08ce811013..d65ec0e3daad 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 String getName() {
}
public void setSecurityGroupEnabled(boolean enabled) {
- this.isSecurityGroupEnabled = enabled;
+ this.securityGroupEnabled = enabled;
}
/**
@@ -221,7 +221,7 @@ public void setIsolationuri(URI isolationUri) {
}
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 0f6511e83114..eeddbf649a77 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 NfsTO(String url, DataStoreRole role) {
}
+ @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 3a616170d7e0..2ed7d9f9a201 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
@@ -32,6 +32,10 @@ public class NicTO extends NetworkTO {
Map details;
boolean dpdkEnabled;
Integer mtu;
+ Long networkId;
+ boolean enabled;
+
+ String networkSegmentName;
public NicTO() {
super();
@@ -83,6 +87,14 @@ public void setUuid(String uuid) {
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();
@@ -127,4 +139,28 @@ public Integer getMtu() {
public void setMtu(Integer mtu) {
this.mtu = mtu;
}
+
+ public Long getNetworkId() {
+ return networkId;
+ }
+
+ public void setNetworkId(Long networkId) {
+ this.networkId = networkId;
+ }
+
+ public String getNetworkSegmentName() {
+ return networkSegmentName;
+ }
+
+ public void setNetworkSegmentName(String networkSegmentName) {
+ this.networkSegmentName = networkSegmentName;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
}
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 76d6d952814c..91f337c5f55b 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 @@
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 PortForwardingRuleTO(PortForwardingRule rule, String srcVlanTag, String s
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 String getStringDstPortRange() {
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 6e7aa8b21e28..7daeb9649177 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,18 +18,18 @@
*/
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)
@@ -37,21 +37,32 @@ public class RemoteInstanceTO implements Serializable {
private String vcenterHost;
private String datacenterName;
private String clusterName;
+ private String hostName;
public RemoteInstanceTO() {
}
- public RemoteInstanceTO(String hostName, String instanceName, String vcenterHost,
- String datacenterName, String clusterName,
- String vcenterUsername, String vcenterPassword) {
+ public RemoteInstanceTO(String instanceName, String clusterName, String hostName) {
this.hypervisorType = Hypervisor.HypervisorType.VMware;
+ this.instanceName = instanceName;
+ this.clusterName = clusterName;
this.hostName = hostName;
+ }
+
+ 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 RemoteInstanceTO(String instanceName, String instancePath, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName, String clusterName, String hostName) {
+ this(instanceName, instancePath, vcenterHost, vcenterUsername, vcenterPassword, datacenterName);
+ this.clusterName = clusterName;
+ this.hostName = hostName;
}
public Hypervisor.HypervisorType getHypervisorType() {
@@ -62,8 +73,8 @@ public String getInstanceName() {
return this.instanceName;
}
- public String getHostName() {
- return this.hostName;
+ public String getInstancePath() {
+ return this.instancePath;
}
public String getVcenterUsername() {
@@ -85,4 +96,8 @@ public String getDatacenterName() {
public String getClusterName() {
return clusterName;
}
+
+ public String getHostName() {
+ return hostName;
+ }
}
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 233238cf793d..936f8168b1e8 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.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 S3TO(final Long id, final String uuid, final String accessKey, final Stri
}
+ @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 e361e7a141fb..cbdb7922eb43 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 @@
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 @@ protected 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 b89dfea40e0c..14038566fbd3 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 @@
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 SwiftTO(Long id, String url, String account, String userName, String key,
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/VirtualMachineMetadataTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineMetadataTO.java
new file mode 100644
index 000000000000..5b22afdedd53
--- /dev/null
+++ b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineMetadataTO.java
@@ -0,0 +1,182 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent.api.to;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class VirtualMachineMetadataTO {
+ // VM details
+ private final String name;
+ private final String internalName;
+ private final String displayName;
+ private final String instanceUuid;
+ private final Integer cpuCores;
+ private final Integer memory;
+ private final Long created;
+ private final Long started;
+
+ // Owner details
+ private final String ownerDomainUuid;
+ private final String ownerDomainName;
+ private final String ownerAccountUuid;
+ private final String ownerAccountName;
+ private final String ownerProjectUuid;
+ private final String ownerProjectName;
+
+ // Host and service offering
+ private final String serviceOfferingName;
+ private final List serviceOfferingHostTags;
+
+ // zone, pod, and cluster details
+ private final String zoneName;
+ private final String zoneUuid;
+ private final String podName;
+ private final String podUuid;
+ private final String clusterName;
+ private final String clusterUuid;
+
+ // resource tags
+ private final Map resourceTags;
+
+ public VirtualMachineMetadataTO(
+ String name, String internalName, String displayName, String instanceUuid, Integer cpuCores, Integer memory, Long created, Long started,
+ String ownerDomainUuid, String ownerDomainName, String ownerAccountUuid, String ownerAccountName, String ownerProjectUuid, String ownerProjectName,
+ String serviceOfferingName, List serviceOfferingHostTags,
+ String zoneName, String zoneUuid, String podName, String podUuid, String clusterName, String clusterUuid, Map resourceTags) {
+ /*
+ * Something failed in the metadata shall not be a fatal error, the VM can still be started
+ * Thus, the unknown fields just get an explicit "unknown" value so it can be fixed in case
+ * there are bugs on some execution paths.
+ * */
+
+ this.name = (name != null) ? name : "unknown";
+ this.internalName = (internalName != null) ? internalName : "unknown";
+ this.displayName = (displayName != null) ? displayName : "unknown";
+ this.instanceUuid = (instanceUuid != null) ? instanceUuid : "unknown";
+ this.cpuCores = (cpuCores != null) ? cpuCores : -1;
+ this.memory = (memory != null) ? memory : -1;
+ this.created = (created != null) ? created : 0;
+ this.started = (started != null) ? started : 0;
+ this.ownerDomainUuid = (ownerDomainUuid != null) ? ownerDomainUuid : "unknown";
+ this.ownerDomainName = (ownerDomainName != null) ? ownerDomainName : "unknown";
+ this.ownerAccountUuid = (ownerAccountUuid != null) ? ownerAccountUuid : "unknown";
+ this.ownerAccountName = (ownerAccountName != null) ? ownerAccountName : "unknown";
+ this.ownerProjectUuid = (ownerProjectUuid != null) ? ownerProjectUuid : "unknown";
+ this.ownerProjectName = (ownerProjectName != null) ? ownerProjectName : "unknown";
+ this.serviceOfferingName = (serviceOfferingName != null) ? serviceOfferingName : "unknown";
+ this.serviceOfferingHostTags = (serviceOfferingHostTags != null) ? serviceOfferingHostTags : new ArrayList<>();
+ this.zoneName = (zoneName != null) ? zoneName : "unknown";
+ this.zoneUuid = (zoneUuid != null) ? zoneUuid : "unknown";
+ this.podName = (podName != null) ? podName : "unknown";
+ this.podUuid = (podUuid != null) ? podUuid : "unknown";
+ this.clusterName = (clusterName != null) ? clusterName : "unknown";
+ this.clusterUuid = (clusterUuid != null) ? clusterUuid : "unknown";
+
+ this.resourceTags = (resourceTags != null) ? resourceTags : new HashMap<>();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getInternalName() {
+ return internalName;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public String getInstanceUuid() {
+ return instanceUuid;
+ }
+
+ public Integer getCpuCores() {
+ return cpuCores;
+ }
+
+ public Integer getMemory() {
+ return memory;
+ }
+
+ public Long getCreated() { return created; }
+
+ public Long getStarted() {
+ return started;
+ }
+
+ public String getOwnerDomainUuid() {
+ return ownerDomainUuid;
+ }
+
+ public String getOwnerDomainName() {
+ return ownerDomainName;
+ }
+
+ public String getOwnerAccountUuid() {
+ return ownerAccountUuid;
+ }
+
+ public String getOwnerAccountName() {
+ return ownerAccountName;
+ }
+
+ public String getOwnerProjectUuid() {
+ return ownerProjectUuid;
+ }
+
+ public String getOwnerProjectName() {
+ return ownerProjectName;
+ }
+
+ public String getserviceOfferingName() {
+ return serviceOfferingName;
+ }
+
+ public List getserviceOfferingHostTags() {
+ return serviceOfferingHostTags;
+ }
+
+ public String getZoneName() {
+ return zoneName;
+ }
+
+ public String getZoneUuid() {
+ return zoneUuid;
+ }
+
+ public String getPodName() {
+ return podName;
+ }
+
+ public String getPodUuid() {
+ return podUuid;
+ }
+
+ public String getClusterName() {
+ return clusterName;
+ }
+
+ public String getClusterUuid() {
+ return clusterUuid;
+ }
+
+ public Map getResourceTags() { return resourceTags; }
+}
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 db6cba775483..9af6c731fd24 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 @@
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,46 +45,52 @@ 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;
-
- long minRam;
- long maxRam;
- String hostName;
- String arch;
- String os;
- String platformEmulator;
- String bootArgs;
- String[] bootupScripts;
- boolean enableHA;
- boolean limitCpuUse;
- boolean enableDynamicallyScaleVm;
+ private Integer speed;
+ private Integer minSpeed;
+ private Integer maxSpeed;
+
+ private long minRam;
+ private long maxRam;
+ private long requestedRam;
+ 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;
-
- DiskTO[] disks;
- NicTO[] nics;
- GPUDeviceTO gpuDevice;
- Integer vcpuMaxLimit;
- List vmData = null;
-
- String configDriveLabel = null;
- String configDriveIsoRootFolder = null;
- String configDriveIsoFile = null;
- NetworkElement.Location configDriveLocation = NetworkElement.Location.SECONDARY;
-
- Double cpuQuotaPercentage = null;
-
- Map guestOsDetails = new HashMap();
- Map extraConfig = new HashMap<>();
- DeployAsIsInfoTO deployAsIsInfo;
+ private String vncPassword;
+ private String vncAddr;
+ private Map details;
+ private Map params;
+ private String uuid;
+ private String bootType;
+ private String bootMode;
+ private boolean enterHardwareSetup;
+
+ private DiskTO[] disks;
+ private NicTO[] nics;
+ private GPUDeviceTO gpuDevice;
+ private Integer vcpuMaxLimit;
+ private List vmData = null;
+
+ private String configDriveLabel = null;
+ private String configDriveIsoRootFolder = null;
+ private String configDriveIsoFile = null;
+ private NetworkElement.Location configDriveLocation = NetworkElement.Location.SECONDARY;
+
+ private Double cpuQuotaPercentage = null;
+
+ private Map guestOsDetails = new HashMap();
+ private Map extraConfig = new HashMap<>();
+ private Map networkIdToNetworkNameMap = new HashMap<>();
+ private DeployAsIsInfoTO deployAsIsInfo;
+ private String metadataManufacturer;
+ private String metadataProductName;
+ private VirtualMachineMetadataTO metadata;
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) {
@@ -188,7 +196,11 @@ public Integer getMaxSpeed() {
return maxSpeed;
}
- public boolean getLimitCpuUse() {
+ public boolean isEnableHA() {
+ return enableHA;
+ }
+
+ public boolean isLimitCpuUse() {
return limitCpuUse;
}
@@ -196,15 +208,20 @@ public long getMinRam() {
return minRam;
}
- public void setRam(long minRam, long maxRam) {
+ public void setRam(long minRam, long maxRam, long requestedRam) {
this.minRam = minRam;
this.maxRam = maxRam;
+ this.requestedRam = requestedRam;
}
public long getMaxRam() {
return maxRam;
}
+ public long getRequestedRam() {
+ return requestedRam;
+ }
+
public String getHostName() {
return hostName;
}
@@ -253,6 +270,10 @@ public void setBootupScripts(String[] bootupScripts) {
this.bootupScripts = bootupScripts;
}
+ public void setEnableHA(boolean enableHA) {
+ this.enableHA = enableHA;
+ }
+
public DiskTO[] getDisks() {
return disks;
}
@@ -286,11 +307,11 @@ public void setVncAddr(String vncAddr) {
}
public Map getDetails() {
- return params;
+ return details;
}
public void setDetails(Map params) {
- this.params = params;
+ this.details = params;
}
public String getUuid() {
@@ -392,6 +413,14 @@ public Map getExtraConfig() {
return extraConfig;
}
+ public Map getNetworkIdToNetworkNameMap() {
+ return networkIdToNetworkNameMap;
+ }
+
+ public void setNetworkIdToNetworkNameMap(Map networkIdToNetworkNameMap) {
+ this.networkIdToNetworkNameMap = networkIdToNetworkNameMap;
+ }
+
public String getBootType() {
return bootType;
}
@@ -420,8 +449,80 @@ public void setDeployAsIsInfo(DeployAsIsInfoTO deployAsIsInfo) {
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;
+ }
+
+ public VirtualMachineMetadataTO getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(VirtualMachineMetadataTO metadata) {
+ this.metadata = metadata;
+ }
+
@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/agent/manager/allocator/HostAllocator.java b/api/src/main/java/com/cloud/agent/manager/allocator/HostAllocator.java
index 604720aaa290..5d028d31d5b6 100644
--- a/api/src/main/java/com/cloud/agent/manager/allocator/HostAllocator.java
+++ b/api/src/main/java/com/cloud/agent/manager/allocator/HostAllocator.java
@@ -22,19 +22,11 @@
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
-import com.cloud.offering.ServiceOffering;
import com.cloud.utils.component.Adapter;
-import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface HostAllocator extends Adapter {
- /**
- * @param UserVm vm
- * @param ServiceOffering offering
- **/
- boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering);
-
/**
* Determines which physical hosts are suitable to
* allocate the guest virtual machines on
@@ -49,31 +41,6 @@ public interface HostAllocator extends Adapter {
public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo);
- /**
- * Determines which physical hosts are suitable to allocate the guest
- * virtual machines on
- *
- * Allocators must set any other hosts not considered for allocation in the
- * ExcludeList avoid. Thus the avoid set and the list of hosts suitable,
- * together must cover the entire host set in the cluster.
- *
- * @param VirtualMachineProfile
- * vmProfile
- * @param DeploymentPlan
- * plan
- * @param GuestType
- * type
- * @param ExcludeList
- * avoid
- * @param int returnUpTo (use -1 to return all possible hosts)
- * @param boolean considerReservedCapacity (default should be true, set to
- * false if host capacity calculation should not look at reserved
- * capacity)
- * @return List List of hosts that are suitable for VM allocation
- **/
-
- public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity);
-
/**
* Determines which physical hosts are suitable to allocate the guest
* virtual machines on
diff --git a/api/src/main/java/com/cloud/api/commands/ListRecurringSnapshotScheduleCmd.java b/api/src/main/java/com/cloud/api/commands/ListRecurringSnapshotScheduleCmd.java
index d34c09c94fde..d8aa13710e23 100644
--- a/api/src/main/java/com/cloud/api/commands/ListRecurringSnapshotScheduleCmd.java
+++ b/api/src/main/java/com/cloud/api/commands/ListRecurringSnapshotScheduleCmd.java
@@ -35,10 +35,10 @@ public class ListRecurringSnapshotScheduleCmd extends BaseListCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
- @Parameter(name = ApiConstants.SNAPSHOT_POLICY_ID, type = CommandType.LONG, description = "lists recurring snapshots by snapshot policy ID")
+ @Parameter(name = ApiConstants.SNAPSHOT_POLICY_ID, type = CommandType.LONG, description = "Lists recurring Snapshots by Snapshot policy ID")
private Long snapshotPolicyId;
- @Parameter(name = ApiConstants.VOLUME_ID, type = CommandType.LONG, required = true, description = "list recurring snapshots by volume ID")
+ @Parameter(name = ApiConstants.VOLUME_ID, type = CommandType.LONG, required = true, description = "List recurring Snapshots by volume ID")
private Long volumeId;
/////////////////////////////////////////////////////
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 000000000000..b0e5394df75e
--- /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 000000000000..ae877ee60db7
--- /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 000000000000..61d149f28470
--- /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 684490a605c3..4e584b18feee 100644
--- a/api/src/main/java/com/cloud/capacity/Capacity.java
+++ b/api/src/main/java/com/cloud/capacity/Capacity.java
@@ -16,6 +16,8 @@
// under the License.
package com.cloud.capacity;
+import java.util.List;
+
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@@ -32,9 +34,18 @@ 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_BACKUP_STORAGE,
+ CAPACITY_TYPE_OBJECT_STORAGE);
+
public Long getHostOrPoolId();
public Long getDataCenterId();
@@ -54,4 +65,6 @@ public interface Capacity extends InternalIdentity, Identity {
public Float getUsedPercentage();
public Long getAllocatedCapacity();
+
+ public String getTag();
}
diff --git a/api/src/main/java/com/cloud/configuration/ConfigurationService.java b/api/src/main/java/com/cloud/configuration/ConfigurationService.java
index 97d4b42974b3..729f72b23ca2 100644
--- a/api/src/main/java/com/cloud/configuration/ConfigurationService.java
+++ b/api/src/main/java/com/cloud/configuration/ConfigurationService.java
@@ -17,18 +17,25 @@
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.CloneNetworkOfferingCmd;
import org.apache.cloudstack.api.command.admin.network.CreateGuestNetworkIpv6PrefixCmd;
import org.apache.cloudstack.api.command.admin.network.CreateManagementNetworkIpRangeCmd;
-import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd;
import org.apache.cloudstack.api.command.admin.network.DeleteGuestNetworkIpv6PrefixCmd;
import org.apache.cloudstack.api.command.admin.network.DeleteManagementNetworkIpRangeCmd;
import org.apache.cloudstack.api.command.admin.network.DeleteNetworkOfferingCmd;
import org.apache.cloudstack.api.command.admin.network.ListGuestNetworkIpv6PrefixesCmd;
+import org.apache.cloudstack.api.command.admin.network.NetworkOfferingBaseCmd;
import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd;
import org.apache.cloudstack.api.command.admin.network.UpdatePodManagementNetworkIpRangeCmd;
+import org.apache.cloudstack.api.command.admin.offering.CloneDiskOfferingCmd;
+import org.apache.cloudstack.api.command.admin.offering.CloneServiceOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd;
import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd;
@@ -101,39 +108,52 @@ public interface ConfigurationService {
*/
ServiceOffering createServiceOffering(CreateServiceOfferingCmd cmd);
+ /**
+ * Clones a service offering with optional parameter overrides
+ *
+ * @param cmd
+ * the command object that specifies the source offering ID and optional parameter overrides
+ * @return the newly created service offering cloned from source, null otherwise
+ */
+ ServiceOffering cloneServiceOffering(CloneServiceOfferingCmd cmd);
+
+ /**
+ * Clones a disk offering with optional parameter overrides
+ *
+ * @param cmd
+ * the command object that specifies the source offering ID and optional parameter overrides
+ * @return the newly created disk offering cloned from source, null otherwise
+ */
+ DiskOffering cloneDiskOffering(CloneDiskOfferingCmd cmd);
+
+ /**
+ * Clones a network offering with optional parameter overrides
+ *
+ * @param cmd
+ * the command object that specifies the source offering ID and optional parameter overrides
+ * @return the newly created network offering cloned from source, null otherwise
+ */
+ NetworkOffering cloneNetworkOffering(CloneNetworkOfferingCmd cmd);
+
/**
* Updates a service offering
*
- * @param serviceOfferingId
- * @param userId
- * @param name
- * @param displayText
- * @param offerHA
- * @param useVirtualNetwork
- * @param tags
* @return updated service offering
*/
ServiceOffering updateServiceOffering(UpdateServiceOfferingCmd cmd);
/**
* Deletes a service offering
- *
- * @param userId
- * @param serviceOfferingId
*/
boolean deleteServiceOffering(DeleteServiceOfferingCmd cmd);
/**
* Retrieve ID of domains for a service offering
- *
- * @param serviceOfferingId
*/
List getServiceOfferingDomains(Long serviceOfferingId);
/**
* Retrieve ID of domains for a service offering
- *
- * @param serviceOfferingId
*/
List getServiceOfferingZones(Long serviceOfferingId);
@@ -143,7 +163,6 @@ public interface ConfigurationService {
* @param cmd
* - the command specifying diskOfferingId, name, description, tags
* @return updated disk offering
- * @throws
*/
DiskOffering updateDiskOffering(UpdateDiskOfferingCmd cmd);
@@ -153,34 +172,22 @@ public interface ConfigurationService {
* @param cmd
* - the command specifying disk offering id
* @return true or false
- * @throws
*/
boolean deleteDiskOffering(DeleteDiskOfferingCmd cmd);
/**
* Creates a new disk offering
- *
- * @param domainId
- * @param name
- * @param description
- * @param numGibibytes
- * @param mirrored
- * @param size
* @return ID
*/
DiskOffering createDiskOffering(CreateDiskOfferingCmd cmd);
/**
* Retrieve ID of domains for a disk offering
- *
- * @param diskOfferingId
*/
List getDiskOfferingDomains(Long diskOfferingId);
/**
* Retrieve ID of domains for a disk offering
- *
- * @param diskOfferingId
*/
List getDiskOfferingZones(Long diskOfferingId);
@@ -201,11 +208,10 @@ 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.
@@ -223,8 +229,7 @@ public interface ConfigurationService {
/**
* Updates a mutually exclusive IP range in the pod.
* @param cmd - The command specifying pod ID, current Start IP, current End IP, new Start IP, new End IP.
- * @throws com.cloud.exception.ConcurrentOperationException
- * @return Success
+ * @throws com.cloud.exception.ConcurrentOperationException when this pod is already being accessed
*/
void updatePodIpRange(UpdatePodManagementNetworkIpRangeCmd cmd) throws ConcurrentOperationException;
@@ -245,9 +250,6 @@ public interface ConfigurationService {
/**
* Edits a pod in the database. Will not allow you to edit pods that are being used anywhere in the system.
- *
- * @param UpdatePodCmd
- * api command
*/
Pod editPod(UpdatePodCmd cmd);
@@ -257,17 +259,12 @@ public interface ConfigurationService {
* @param cmd
* - the command containing podId
* @return true or false
- * @throws ,
*/
boolean deletePod(DeletePodCmd cmd);
/**
* Creates a new zone
- *
- * @param cmd
* @return the zone if successful, null otherwise
- * @throws
- * @throws
*/
DataCenter createZone(CreateZoneCmd cmd);
@@ -290,22 +287,7 @@ public interface ConfigurationService {
* Adds a VLAN to the database, along with an IP address range. Can add three types of VLANs: (1) zone-wide VLANs on
* the
* virtual public network (2) pod-wide direct attached VLANs (3) account-specific direct attached VLANs
- *
- * @param userId
- * @param vlanType
- * - either "DomR" (VLAN for a virtual public network) or "DirectAttached" (VLAN for IPs that will be
- * directly
- * attached to UserVMs)
- * @param zoneId
- * @param accountId
- * @param podId
- * @param add
- * @param vlanId
- * @param gateway
- * @param startIP
- * @param endIP
* @throws ResourceAllocationException TODO
- * @throws
* @return The new Vlan object
*/
Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException,
@@ -320,9 +302,6 @@ Vlan updateVlanAndPublicIpRange(UpdateVlanIpRangeCmd cmd) throws ConcurrentOpera
/**
* Marks the account with the default zone-id.
*
- * @param accountName
- * @param domainId
- * @param defaultZoneId
* @return The new account object
*/
Account markDefaultZone(String accountName, long domainId, long defaultZoneId);
@@ -333,7 +312,7 @@ Vlan updateVlanAndPublicIpRange(UpdateVlanIpRangeCmd cmd) throws ConcurrentOpera
boolean releasePublicIpRange(ReleasePublicIpRangeCmd cmd);
- NetworkOffering createNetworkOffering(CreateNetworkOfferingCmd cmd);
+ NetworkOffering createNetworkOffering(NetworkOfferingBaseCmd cmd);
NetworkOffering updateNetworkOffering(UpdateNetworkOfferingCmd cmd);
@@ -344,14 +323,12 @@ Vlan updateVlanAndPublicIpRange(UpdateVlanIpRangeCmd cmd) throws ConcurrentOpera
/**
* Retrieve ID of domains for a network offering
*
- * @param networkOfferingId
*/
List getNetworkOfferingDomains(Long networkOfferingId);
/**
* Retrieve ID of domains for a network offering
*
- * @param networkOfferingId
*/
List getNetworkOfferingZones(Long networkOfferingId);
@@ -372,4 +349,16 @@ Vlan updateVlanAndPublicIpRange(UpdateVlanIpRangeCmd cmd) throws ConcurrentOpera
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 32db2fcafeaf..97be7f9d64c5 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 @@ enum ResourceType { // Primary and Secondary storage are allocated_storage and n
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 static ResourceType fromOrdinal(int ordinal) {
}
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 {
@@ -85,5 +94,6 @@ public String getName() {
long getOwnerId();
ResourceOwnerType getResourceOwnerType();
+ String getTag();
}
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 000000000000..11b38b73da53
--- /dev/null
+++ b/api/src/main/java/com/cloud/cpu/CPU.java
@@ -0,0 +1,71 @@
+// 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),
+ s390x("s390x", 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 63188ca0b0e9..23e6cc88a1e0 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.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 1cbab36f3bd4..17c5b615d4b6 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 a668b79187dc..9471c3d5c84c 100644
--- a/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java
+++ b/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java
@@ -57,6 +57,17 @@ public interface DeploymentClusterPlanner extends DeploymentPlanner {
false,
ConfigKey.Scope.Global);
+ static final ConfigKey VmAllocationAlgorithm = new ConfigKey<>(
+ String.class,
+ "vm.allocation.algorithm",
+ "Advanced",
+ "random",
+ "Order in which hosts within a cluster will be considered for VM allocation. The value can be 'random', 'firstfit', 'userdispersing', or 'firstfitleastconsumed'.",
+ true,
+ ConfigKey.Scope.Global, null, null, null, null, null,
+ ConfigKey.Kind.Select,
+ "random,firstfit,userdispersing,firstfitleastconsumed");
+
/**
* This is called to determine list of possible clusters where a virtual
* machine can be deployed.
diff --git a/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java b/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java
index e9f706ac1cee..22d796d4a775 100644
--- a/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java
+++ b/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java
@@ -21,8 +21,12 @@
import java.util.HashSet;
import java.util.Set;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
import com.cloud.dc.DataCenter;
import com.cloud.dc.Pod;
+import com.cloud.exception.CloudException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.ResourceUnavailableException;
@@ -66,7 +70,7 @@ public interface DeploymentPlanner extends Adapter {
boolean canHandle(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid);
public enum AllocationAlgorithm {
- random, firstfit, userdispersing, userconcentratedpod_random, userconcentratedpod_firstfit;
+ random, firstfit, userdispersing, firstfitleastconsumed;
}
public enum PlannerResourceUsage {
@@ -75,7 +79,7 @@ public enum PlannerResourceUsage {
public static class ExcludeList implements Serializable {
private static final long serialVersionUID = -482175549460148301L;
-
+ protected static Logger LOGGER = LogManager.getLogger(ExcludeList.class);
private Set _dcIds;
private Set _podIds;
private Set _clusterIds;
@@ -104,13 +108,26 @@ public ExcludeList(Set dcIds, Set podIds, Set clusterIds, Set<
}
}
+ private void logAvoid(Class> scope, CloudException e) {
+ Long id = null;
+ if (e instanceof InsufficientCapacityException) {
+ id = ((InsufficientCapacityException) e).getId();
+ } else if (e instanceof ResourceUnavailableException) {
+ id = ((ResourceUnavailableException) e).getResourceId();
+ } else {
+ LOGGER.debug("Failed to log avoided component due to unexpected exception type [{}].", e.getMessage());
+ return;
+ }
+ LOGGER.debug("Adding {} [{}] to the avoid set due to [{}].", scope.getSimpleName(), id, e.getMessage());
+ }
+
public boolean add(InsufficientCapacityException e) {
Class> scope = e.getScope();
if (scope == null) {
return false;
}
-
+ logAvoid(scope, e);
if (Host.class.isAssignableFrom(scope)) {
addHost(e.getId());
} else if (Pod.class.isAssignableFrom(scope)) {
@@ -128,13 +145,14 @@ public boolean add(InsufficientCapacityException e) {
return true;
}
+
public boolean add(ResourceUnavailableException e) {
Class> scope = e.getScope();
if (scope == null) {
return false;
}
-
+ logAvoid(scope, e);
if (Host.class.isAssignableFrom(scope)) {
addHost(e.getResourceId());
} else if (Pod.class.isAssignableFrom(scope)) {
diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java
index 5d5252290959..42395bf89992 100644
--- a/api/src/main/java/com/cloud/event/EventTypes.java
+++ b/api/src/main/java/com/cloud/event/EventTypes.java
@@ -27,10 +27,21 @@
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.backup.BackupRepositoryService;
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.storage.sharedfs.SharedFS;
import org.apache.cloudstack.usage.Usage;
import org.apache.cloudstack.vm.schedule.VMSchedule;
@@ -241,6 +252,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";
@@ -282,9 +295,13 @@ 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
+ //user API and secret keys
public static final String EVENT_REGISTER_FOR_SECRET_API_KEY = "REGISTER.USER.KEY";
+ public static final String EVENT_DELETE_SECRET_API_KEY = "DELETE.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";
@@ -303,6 +320,7 @@ public class EventTypes {
public static final String EVENT_VOLUME_CREATE = "VOLUME.CREATE";
public static final String EVENT_VOLUME_DELETE = "VOLUME.DELETE";
public static final String EVENT_VOLUME_ATTACH = "VOLUME.ATTACH";
+ public static final String EVENT_VOLUME_CHECK = "VOLUME.CHECK";
public static final String EVENT_VOLUME_DETACH = "VOLUME.DETACH";
public static final String EVENT_VOLUME_EXTRACT = "VOLUME.EXTRACT";
public static final String EVENT_VOLUME_UPLOAD = "VOLUME.UPLOAD";
@@ -314,6 +332,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
@@ -329,6 +349,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";
@@ -354,16 +375,34 @@ public class EventTypes {
// Service Offerings
public static final String EVENT_SERVICE_OFFERING_CREATE = "SERVICE.OFFERING.CREATE";
+ public static final String EVENT_SERVICE_OFFERING_CLONE = "SERVICE.OFFERING.CLONE";
public static final String EVENT_SERVICE_OFFERING_EDIT = "SERVICE.OFFERING.EDIT";
public static final String EVENT_SERVICE_OFFERING_DELETE = "SERVICE.OFFERING.DELETE";
// Disk Offerings
public static final String EVENT_DISK_OFFERING_CREATE = "DISK.OFFERING.CREATE";
+ public static final String EVENT_DISK_OFFERING_CLONE = "DISK.OFFERING.CLONE";
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_CLONE = "NETWORK.OFFERING.CLONE";
public static final String EVENT_NETWORK_OFFERING_ASSIGN = "NETWORK.OFFERING.ASSIGN";
public static final String EVENT_NETWORK_OFFERING_EDIT = "NETWORK.OFFERING.EDIT";
public static final String EVENT_NETWORK_OFFERING_REMOVE = "NETWORK.OFFERING.REMOVE";
@@ -386,6 +425,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";
@@ -444,9 +488,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";
@@ -460,6 +507,7 @@ public class EventTypes {
public static final String EVENT_S2S_VPN_CUSTOMER_GATEWAY_CREATE = "VPN.S2S.CUSTOMER.GATEWAY.CREATE";
public static final String EVENT_S2S_VPN_CUSTOMER_GATEWAY_DELETE = "VPN.S2S.CUSTOMER.GATEWAY.DELETE";
public static final String EVENT_S2S_VPN_CUSTOMER_GATEWAY_UPDATE = "VPN.S2S.CUSTOMER.GATEWAY.UPDATE";
+ public static final String EVENT_S2S_VPN_GATEWAY_OBSOLETE_PARAMS = "VPN.S2S.GATEWAY.OBSOLETE.PARAMS";
public static final String EVENT_S2S_VPN_CONNECTION_CREATE = "VPN.S2S.CONNECTION.CREATE";
public static final String EVENT_S2S_VPN_CONNECTION_DELETE = "VPN.S2S.CONNECTION.DELETE";
public static final String EVENT_S2S_VPN_CONNECTION_RESET = "VPN.S2S.CONNECTION.RESET";
@@ -477,6 +525,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";
@@ -537,6 +587,7 @@ public class EventTypes {
// Network ACL
public static final String EVENT_NETWORK_ACL_CREATE = "NETWORK.ACL.CREATE";
+ public static final String EVENT_NETWORK_ACL_IMPORT = "NETWORK.ACL.IMPORT";
public static final String EVENT_NETWORK_ACL_DELETE = "NETWORK.ACL.DELETE";
public static final String EVENT_NETWORK_ACL_REPLACE = "NETWORK.ACL.REPLACE";
public static final String EVENT_NETWORK_ACL_UPDATE = "NETWORK.ACL.UPDATE";
@@ -551,6 +602,7 @@ public class EventTypes {
// VPC offerings
public static final String EVENT_VPC_OFFERING_CREATE = "VPC.OFFERING.CREATE";
+ public static final String EVENT_VPC_OFFERING_CLONE = "VPC.OFFERING.CLONE";
public static final String EVENT_VPC_OFFERING_UPDATE = "VPC.OFFERING.UPDATE";
public static final String EVENT_VPC_OFFERING_DELETE = "VPC.OFFERING.DELETE";
@@ -583,16 +635,19 @@ public class EventTypes {
// Backup and Recovery events
public static final String EVENT_VM_BACKUP_IMPORT_OFFERING = "BACKUP.IMPORT.OFFERING";
+ public static final String EVENT_VM_BACKUP_OFFERING_CLONE = "BACKUP.OFFERING.CLONE";
public static final String EVENT_VM_BACKUP_OFFERING_ASSIGN = "BACKUP.OFFERING.ASSIGN";
public static final String EVENT_VM_BACKUP_OFFERING_REMOVE = "BACKUP.OFFERING.REMOVE";
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";
@@ -668,6 +723,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";
@@ -717,6 +775,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";
@@ -728,6 +795,76 @@ public class EventTypes {
public static final String EVENT_BUCKET_DELETE = "BUCKET.DELETE";
public static final String EVENT_BUCKET_UPDATE = "BUCKET.UPDATE";
+ // Quota
+ public static final String EVENT_QUOTA_TARIFF_CREATE = "QUOTA.TARIFF.CREATE";
+ 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";
+
+ // Backup Repository
+ public static final String EVENT_BACKUP_REPOSITORY_ADD = "BACKUP.REPOSITORY.ADD";
+ public static final String EVENT_BACKUP_REPOSITORY_UPDATE = "BACKUP.REPOSITORY.UPDATE";
+
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -829,6 +966,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);
@@ -885,6 +1024,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);
@@ -911,16 +1051,34 @@ public class EventTypes {
// Service Offerings
entityEventDetails.put(EVENT_SERVICE_OFFERING_CREATE, ServiceOffering.class);
+ entityEventDetails.put(EVENT_SERVICE_OFFERING_CLONE, ServiceOffering.class);
entityEventDetails.put(EVENT_SERVICE_OFFERING_EDIT, ServiceOffering.class);
entityEventDetails.put(EVENT_SERVICE_OFFERING_DELETE, ServiceOffering.class);
// Disk Offerings
entityEventDetails.put(EVENT_DISK_OFFERING_CREATE, DiskOffering.class);
+ entityEventDetails.put(EVENT_DISK_OFFERING_CLONE, DiskOffering.class);
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_CLONE, NetworkOffering.class);
entityEventDetails.put(EVENT_NETWORK_OFFERING_ASSIGN, NetworkOffering.class);
entityEventDetails.put(EVENT_NETWORK_OFFERING_EDIT, NetworkOffering.class);
entityEventDetails.put(EVENT_NETWORK_OFFERING_REMOVE, NetworkOffering.class);
@@ -989,8 +1147,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);
@@ -1002,6 +1162,7 @@ public class EventTypes {
entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_CREATE, Site2SiteCustomerGateway.class);
entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_DELETE, Site2SiteCustomerGateway.class);
entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_UPDATE, Site2SiteCustomerGateway.class);
+ entityEventDetails.put(EVENT_S2S_VPN_GATEWAY_OBSOLETE_PARAMS, Site2SiteCustomerGateway.class);
entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_CREATE, Site2SiteVpnConnection.class);
entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_DELETE, Site2SiteVpnConnection.class);
entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_RESET, Site2SiteVpnConnection.class);
@@ -1168,6 +1329,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);
@@ -1177,8 +1344,74 @@ public class EventTypes {
entityEventDetails.put(EVENT_BUCKET_CREATE, Bucket.class);
entityEventDetails.put(EVENT_BUCKET_UPDATE, Bucket.class);
entityEventDetails.put(EVENT_BUCKET_DELETE, Bucket.class);
+
+ // Quota
+ 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);
+
+ // Backup Repository
+ entityEventDetails.put(EVENT_BACKUP_REPOSITORY_ADD, BackupRepositoryService.class);
+ entityEventDetails.put(EVENT_BACKUP_REPOSITORY_UPDATE, BackupRepositoryService.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) {
@@ -1207,4 +1440,12 @@ public static Class getEntityClassForEvent(String eventName) {
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 fe27408eb4e3..66b607100d97 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 eefbcf5518a3..d54d77d66f1e 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 @@
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/ha/Investigator.java b/api/src/main/java/com/cloud/ha/Investigator.java
index 88d802a1ce44..00371d395f5a 100644
--- a/api/src/main/java/com/cloud/ha/Investigator.java
+++ b/api/src/main/java/com/cloud/ha/Investigator.java
@@ -26,17 +26,19 @@ public interface Investigator extends Adapter {
* Returns if the vm is still alive.
*
* @param vm to work on.
+ * @return true if vm is alive, otherwise false
*/
- public boolean isVmAlive(VirtualMachine vm, Host host) throws UnknownVM;
+ boolean isVmAlive(VirtualMachine vm, Host host) throws UnknownVM;
- public Status isAgentAlive(Host agent);
+ /**
+ * Returns the agent status of the host.
+ *
+ * @param host
+ * @return status of the host agent
+ */
+ Status getHostAgentStatus(Host host);
class UnknownVM extends Exception {
-
- /**
- *
- */
private static final long serialVersionUID = 1L;
-
};
}
diff --git a/api/src/main/java/com/cloud/host/Host.java b/api/src/main/java/com/cloud/host/Host.java
index 7563bc3b7426..8b14cfd3a390 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,20 @@ public static String[] toStrings(Host.Type... types) {
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_VDDK_SUPPORT = "host.vddk.support";
+ String HOST_VDDK_LIB_DIR = "vddk.lib.dir";
+ String HOST_VDDK_VERSION = "host.vddk.version";
+ String HOST_OVFTOOL_VERSION = "host.ovftool.version";
+ String HOST_VIRTV2V_VERSION = "host.virtv2v.version";
+ String HOST_SSH_PORT = "host.ssh.port";
+ String GUEST_OS_CATEGORY_ID = "guest.os.category.id";
+ String GUEST_OS_RULE = "guest.os.rule";
+
+ int DEFAULT_SSH_PORT = 22;
/**
* @return name of the machine.
@@ -175,6 +188,8 @@ public static String[] toStrings(Host.Type... types) {
*/
Long getManagementServerId();
+ Long getLastManagementServerId();
+
/*
*@return removal date
*/
@@ -207,4 +222,8 @@ public static String[] toStrings(Host.Type... types) {
boolean isDisabled();
ResourceState getResourceState();
+
+ CPU.CPUArch getArch();
+
+ String getStorageAccessGroups();
}
diff --git a/api/src/main/java/com/cloud/host/HostStats.java b/api/src/main/java/com/cloud/host/HostStats.java
index d14794401fa3..0e72b5f2d9d0 100644
--- a/api/src/main/java/com/cloud/host/HostStats.java
+++ b/api/src/main/java/com/cloud/host/HostStats.java
@@ -36,5 +36,4 @@ public interface HostStats {
public HostStats getHostStats();
public double getLoadAverage();
- // public double getXapiMemoryUsageKBs();
}
diff --git a/api/src/main/java/com/cloud/host/Status.java b/api/src/main/java/com/cloud/host/Status.java
index 5dc82bbfaefa..af6af82e9739 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 static String[] toStrings(Status... states) {
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 2f0cc736af3d..1f8741d3b7b2 100644
--- a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
+++ b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
@@ -17,55 +17,68 @@
package com.cloud.hypervisor;
import com.cloud.storage.Storage.ImageFormat;
+import org.apache.commons.lang3.StringUtils;
-import java.util.HashMap;
+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;
+import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.VmStorageMigrationWithSnapshots;
public class Hypervisor {
+ public static class HypervisorType {
+ public enum Functionality {
+ DirectDownloadTemplate,
+ RootDiskSizeOverride,
+ VmStorageMigration,
+ VmStorageMigrationWithSnapshots
+ }
+
+ 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, 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, VmStorageMigrationWithSnapshots));
+ 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", 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", 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, EnumSet.noneOf(Functionality.class));
+ }
+
+ public HypervisorType(String name, ImageFormat imageFormat) {
+ this(name, imageFormat, EnumSet.noneOf(Functionality.class));
+ }
- static Map hypervisorTypeMap;
- static Map supportedImageFormatMap;
-
- public enum HypervisorType {
- None, //for storage hosts
- XenServer,
- KVM,
- VMware,
- Hyperv,
- VirtualBox,
- Parralels,
- BareMetal,
- Simulator,
- Ovm,
- Ovm3,
- LXC,
- Custom,
-
- Any; /*If you don't care about the hypervisor type*/
-
- static {
- hypervisorTypeMap = new HashMap<>();
- hypervisorTypeMap.put("xenserver", HypervisorType.XenServer);
- hypervisorTypeMap.put("kvm", HypervisorType.KVM);
- hypervisorTypeMap.put("vmware", HypervisorType.VMware);
- hypervisorTypeMap.put("hyperv", HypervisorType.Hyperv);
- hypervisorTypeMap.put("virtualbox", HypervisorType.VirtualBox);
- hypervisorTypeMap.put("parallels", HypervisorType.Parralels);
- hypervisorTypeMap.put("baremetal", HypervisorType.BareMetal);
- hypervisorTypeMap.put("simulator", HypervisorType.Simulator);
- hypervisorTypeMap.put("ovm", HypervisorType.Ovm);
- hypervisorTypeMap.put("lxc", HypervisorType.LXC);
- hypervisorTypeMap.put("any", HypervisorType.Any);
- hypervisorTypeMap.put("ovm3", HypervisorType.Ovm3);
- hypervisorTypeMap.put("custom", HypervisorType.Custom);
-
- supportedImageFormatMap = new HashMap<>();
- supportedImageFormatMap.put(HypervisorType.XenServer, ImageFormat.VHD);
- supportedImageFormatMap.put(HypervisorType.KVM, ImageFormat.QCOW2);
- supportedImageFormatMap.put(HypervisorType.VMware, ImageFormat.OVA);
- supportedImageFormatMap.put(HypervisorType.Ovm, ImageFormat.RAW);
- supportedImageFormatMap.put(HypervisorType.Ovm3, ImageFormat.RAW);
+ 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 {
+ hypervisorTypeMap.putIfAbsent(name.toLowerCase(Locale.ROOT), this);
+ }
}
public static HypervisorType getType(String hypervisor) {
@@ -75,24 +88,77 @@ public static HypervisorType getType(String hypervisor) {
hypervisorTypeMap.getOrDefault(hypervisor.toLowerCase(Locale.ROOT), HypervisorType.None));
}
+ public static HypervisorType[] values() {
+ return hypervisorTypeMap.values().toArray(HypervisorType[]::new).clone();
+ }
+
+ public static HypervisorType valueOf(String name) {
+ if (StringUtils.isBlank(name)) {
+ return null;
+ }
+
+ HypervisorType hypervisorType = hypervisorTypeMap.get(name.toLowerCase(Locale.ROOT));
+ if (hypervisorType == null) {
+ throw new IllegalArgumentException("HypervisorType '" + name + "' not found");
+ }
+ 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
*/
public String getHypervisorDisplayName() {
- return !Hypervisor.HypervisorType.Custom.equals(this) ?
- this.toString() :
- HypervisorGuru.HypervisorCustomDisplayName.value();
+ return HypervisorType.Custom.equals(this) ? HypervisorGuru.HypervisorCustomDisplayName.value() : name;
}
/**
* This method really needs to be part of the properties of the hypervisor type itself.
*
- * @param hyperType
* @return
*/
- public static ImageFormat getSupportedImageFormat(HypervisorType hyperType) {
- return supportedImageFormatMap.getOrDefault(hyperType, null);
+ public ImageFormat getSupportedImageFormat() {
+ return imageFormat;
+ }
+
+ public String name() {
+ 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);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ } else if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ HypervisorType that = (HypervisorType) o;
+ return Objects.equals(name, that.name);
+ }
+
+ @Override
+ public String toString() {
+ return name;
}
}
diff --git a/api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java b/api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java
index 3c7dbac6442c..0c821b4e36c0 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.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 @@ boolean attachRestoredVolumeToVirtualMachine(long zoneId, String location, Backu
* 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 @@ UnmanagedInstanceTO cloneHypervisorVMOutOfBand(String hostIp, String vmName,
* @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 76%
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 591da077aec6..80f6a6045c72 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 @@ enum Event {
AutoscaleRequested,
ScaleUpRequested,
ScaleDownRequested,
+ AddNodeRequested,
+ RemoveNodeRequested,
UpgradeRequested,
OperationSucceeded,
OperationFailed,
@@ -58,7 +60,10 @@ enum State {
Stopping("Resources for the Kubernetes cluster are being destroyed"),
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"),
+ ScalingStoppedCluster("Transient state in which the service offerings of stopped clusters are getting scaled"),
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"),
@@ -83,19 +88,35 @@ enum State {
s_fsm.addTransition(State.Stopping, Event.OperationFailed, State.Alert);
s_fsm.addTransition(State.Stopped, Event.StartRequested, State.Starting);
+ s_fsm.addTransition(State.Stopped, Event.OperationSucceeded, State.Stopped);
+ s_fsm.addTransition(State.Running, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Running, Event.FaultsDetected, State.Alert);
s_fsm.addTransition(State.Running, Event.AutoscaleRequested, State.Scaling);
s_fsm.addTransition(State.Running, Event.ScaleUpRequested, State.Scaling);
s_fsm.addTransition(State.Running, Event.ScaleDownRequested, State.Scaling);
+ s_fsm.addTransition(State.Stopped, Event.ScaleUpRequested, State.ScalingStoppedCluster);
s_fsm.addTransition(State.Scaling, Event.OperationSucceeded, State.Running);
- s_fsm.addTransition(State.Scaling, Event.OperationFailed, State.Alert);
+ s_fsm.addTransition(State.Scaling, Event.OperationFailed, State.Running);
+ s_fsm.addTransition(State.ScalingStoppedCluster, Event.OperationSucceeded, State.Stopped);
+ s_fsm.addTransition(State.ScalingStoppedCluster, Event.OperationFailed, State.Alert);
s_fsm.addTransition(State.Running, Event.UpgradeRequested, State.Upgrading);
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 +163,14 @@ enum State {
Long getMaxSize();
Long getSecurityGroupId();
ClusterType getClusterType();
+ Long getControlNodeServiceOfferingId();
+ Long getWorkerNodeServiceOfferingId();
+ Long getEtcdNodeServiceOfferingId();
+ Long getControlNodeTemplateId();
+ Long getWorkerNodeTemplateId();
+ Long getEtcdNodeTemplateId();
+ Long getEtcdNodeCount();
+ Long getCniConfigId();
+ String getCniConfigDetails();
+ boolean isCsiEnabled();
}
diff --git a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelper.java b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelper.java
deleted file mode 100644
index e445e50f82cb..000000000000
--- a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelper.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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 com.cloud.utils.component.Adapter;
-import org.apache.cloudstack.acl.ControlledEntity;
-
-public interface KubernetesClusterHelper extends Adapter {
-
- ControlledEntity findByUuid(String uuid);
-}
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 000000000000..5a6eaa3f7b9a
--- /dev/null
+++ b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java
@@ -0,0 +1,43 @@
+// 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.List;
+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);
+ void checkVmAffinityGroupsCanBeUpdated(UserVm userVm);
+ boolean isValidNodeType(String nodeType);
+ Map getServiceOfferingNodeTypeMap(Map> serviceOfferingNodeTypeMap);
+ Map getTemplateNodeTypeMap(Map> templateNodeTypeMap);
+ Map> getAffinityGroupNodeTypeMap(Map> affinityGroupNodeTypeMap);
+ 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 cf2e2f82db9f..70d652b54e99 100644
--- a/api/src/main/java/com/cloud/network/IpAddress.java
+++ b/api/src/main/java/com/cloud/network/IpAddress.java
@@ -97,4 +97,7 @@ enum Purpose {
void setRuleState(State ruleState);
+ 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 2b4dff01086e..e6c3b9250a7a 100644
--- a/api/src/main/java/com/cloud/network/Ipv6Service.java
+++ b/api/src/main/java/com/cloud/network/Ipv6Service.java
@@ -45,7 +45,7 @@ public interface Ipv6Service extends PluggableService, Configurable {
static final ConfigKey Ipv6OfferingCreationEnabled = new ConfigKey("Advanced", Boolean.class,
"ipv6.offering.enabled",
"false",
- "Indicates whether creation of IPv6 network/VPC offering is enabled or not.",
+ "Indicates whether creation of IPv6 Network/VPC offering is enabled or not.",
true);
static final ConfigKey Ipv6PrefixSubnetCleanupInterval = new ConfigKey("Advanced", Integer.class,
@@ -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 458169c80aa3..e41eb880ffd5 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 @@ class Service {
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,
@@ -205,6 +205,9 @@ public static class Provider {
//Add Tungsten Fabric provider
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;
@@ -322,9 +325,9 @@ enum Event {
public enum State {
- Allocated("Indicates the network configuration is in allocated but not setup"), Setup("Indicates the network configuration is setup"), Implementing(
- "Indicates the network configuration is being implemented"), Implemented("Indicates the network configuration is in use"), Shutdown(
- "Indicates the network configuration is being destroyed"), Destroy("Indicates that the network is destroyed");
+ Allocated("Indicates the Network configuration is in allocated but not setup"), Setup("Indicates the Network configuration is setup"), Implementing(
+ "Indicates the Network configuration is being implemented"), Implemented("Indicates the Network configuration is in use"), Shutdown(
+ "Indicates the Network configuration is being destroyed"), Destroy("Indicates that the Network is destroyed");
protected static final StateMachine2 s_fsm = new StateMachine2();
@@ -410,12 +413,16 @@ public void setIp6Address(String ip6Address) {
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
@@ -427,6 +434,8 @@ public void setIp6Address(String ip6Address) {
long getDataCenterId();
+ long getAccountId();
+
long getNetworkOfferingId();
@Override
@@ -499,4 +508,8 @@ public void setIp6Address(String ip6Address) {
Integer getPublicMtu();
Integer getPrivateMtu();
+
+ Integer getNetworkCidrSize();
+
+ boolean getKeepMacAddressOnPublicNic();
}
diff --git a/api/src/main/java/com/cloud/network/NetworkModel.java b/api/src/main/java/com/cloud/network/NetworkModel.java
index 53ac735cf050..c212e6319eb4 100644
--- a/api/src/main/java/com/cloud/network/NetworkModel.java
+++ b/api/src/main/java/com/cloud/network/NetworkModel.java
@@ -125,6 +125,10 @@ public interface NetworkModel {
*/
String getNextAvailableMacAddressInNetwork(long networkConfigurationId) throws InsufficientAddressCapacityException;
+ String getUniqueMacAddress(long macAddress, long networkId, long datacenterId) throws InsufficientAddressCapacityException;
+
+ boolean isMACUnique(String mac, long networkId);
+
PublicIpAddress getPublicIpAddress(long ipAddressId);
List extends Vlan> listPodVlans(long podId);
@@ -149,7 +153,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 +177,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 +309,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 +325,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 +364,12 @@ List generateVmData(String userData, String userDataDetails, String se
void verifyIp6DnsPair(final String ip6Dns1, final String ip6Dns2);
+ boolean isSecurityGroupSupportedForZone(Long zoneId);
+
+ boolean checkSecurityGroupSupportForNetwork(Account account, DataCenter zone, List networkIds,
+ List securityGroupsIds);
+
+ default long getMacIdentifier(Long dataCenterId) {
+ return 0;
+ }
}
diff --git a/api/src/main/java/com/cloud/network/NetworkProfile.java b/api/src/main/java/com/cloud/network/NetworkProfile.java
index 1a5c80ea8718..d690344a0e38 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 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 NetworkProfile(Network network) {
isRedundant = network.isRedundant();
isRollingRestart = network.isRollingRestart();
externalId = network.getExternalId();
+ networkCidrSize = network.getNetworkCidrSize();
}
@Override
@@ -210,11 +213,21 @@ public String getGateway() {
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,21 @@ public Integer getPrivateMtu() {
return null;
}
+ @Override
+ public Integer getNetworkCidrSize() {
+ return networkCidrSize;
+ }
+
+ @Override
+ public boolean getKeepMacAddressOnPublicNic() {
+ return true;
+ }
+
+ @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 82d229da459d..c32bb711c0f2 100644
--- a/api/src/main/java/com/cloud/network/NetworkService.java
+++ b/api/src/main/java/com/cloud/network/NetworkService.java
@@ -19,6 +19,7 @@
import java.util.List;
import java.util.Map;
+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;
@@ -37,13 +38,16 @@
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;
@@ -77,7 +81,7 @@ public interface NetworkService {
true, ConfigKey.Scope.Zone);
public static final ConfigKey AllowUsersToSpecifyVRMtu = new ConfigKey<>("Advanced", Boolean.class,
- "allow.end.users.to.specify.vr.mtu", "false", "Allow end users to specify VR MTU",
+ "allow.end.users.to.specify.vr.mtu", "false", "Allow end Users to specify VR MTU",
true, ConfigKey.Scope.Zone);
List extends Network> getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner);
@@ -87,6 +91,8 @@ IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displ
IpAddress reserveIpAddress(Account account, Boolean displayIp, Long ipAddressId) throws ResourceAllocationException;
+ IpAddress reserveIpAddressWithVlanDetail(Account account, DataCenter zone, Boolean displayIp, String vlanDetailKey) throws ResourceAllocationException;
+
boolean releaseReservedIpAddress(long ipAddressId) throws InsufficientAddressCapacityException;
boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException;
@@ -98,6 +104,14 @@ IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long ne
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;
+
+ Network createGuestNetwork(long networkOfferingId, String name, String displayText, Account owner,
+ PhysicalNetwork physicalNetwork, long zoneId, ControlledEntity.ACLType aclType, Pair vrIfaceMTUs) throws
+ InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException;
+
Pair, Integer> searchForNetworks(ListNetworksCmd cmd);
boolean deleteNetwork(long networkId, boolean forced);
@@ -218,7 +232,7 @@ Network createPrivateNetwork(String networkName, String displayText, long physic
/**
* Requests an IP address for the guest NIC
*/
- NicSecondaryIp allocateSecondaryGuestIP(long nicId, IpAddresses requestedIpPair) throws InsufficientAddressCapacityException;
+ NicSecondaryIp allocateSecondaryGuestIP(long nicId, IpAddresses requestedIpPair, String description) throws InsufficientAddressCapacityException;
boolean releaseSecondaryIpFromNic(long ipAddressId);
@@ -254,4 +268,17 @@ Network createPrivateNetwork(String networkName, String displayText, long physic
PublicIpQuarantine updatePublicIpAddressInQuarantine(UpdateQuarantinedIpCmd cmd);
void removePublicIpAddressFromQuarantine(RemoveQuarantinedIpCmd cmd);
+
+ InternalLoadBalancerElementService getInternalLoadBalancerElementByType(VirtualRouterProvider.Type type);
+ 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);
+
+ Long getPreferredNetworkIdForPublicIpRuleAssignment(IpAddress ip, Long networkId);
}
diff --git a/api/src/main/java/com/cloud/network/Networks.java b/api/src/main/java/com/cloud/network/Networks.java
index aeed5d4aec6a..5f767686dc97 100644
--- a/api/src/main/java/com/cloud/network/Networks.java
+++ b/api/src/main/java/com/cloud/network/Networks.java
@@ -78,7 +78,7 @@ public URI toUri(T value) {
}
@Override
public String getValueFrom(URI uri) {
- return uri.getAuthority();
+ return uri == null ? null : uri.getAuthority();
}
},
Vswitch("vs", String.class), LinkLocal(null, null), Vnet("vnet", Long.class), Storage("storage", Integer.class), Lswitch("lswitch", String.class) {
@@ -96,7 +96,7 @@ public URI toUri(T value) {
*/
@Override
public String getValueFrom(URI uri) {
- return uri.getSchemeSpecificPart();
+ return uri == null ? null : uri.getSchemeSpecificPart();
}
},
Mido("mido", String.class), Pvlan("pvlan", String.class),
@@ -128,7 +128,9 @@ public URI toUri(T value) {
},
UnDecided(null, null),
OpenDaylight("opendaylight", String.class),
- TUNGSTEN("tf", String.class);
+ TUNGSTEN("tf", String.class),
+ NSX("nsx", String.class),
+ Netris("netris", String.class);
private final String scheme;
private final Class> type;
@@ -175,7 +177,7 @@ public URI toUri(T value) {
* @return the scheme as BroadcastDomainType
*/
public static BroadcastDomainType getSchemeValue(URI uri) {
- return toEnumValue(uri.getScheme());
+ return toEnumValue(uri == null ? null : uri.getScheme());
}
/**
@@ -189,7 +191,7 @@ public static BroadcastDomainType getTypeOf(String str) throws URISyntaxExceptio
if (com.cloud.dc.Vlan.UNTAGGED.equalsIgnoreCase(str)) {
return Native;
}
- return getSchemeValue(new URI(str));
+ return getSchemeValue(str == null ? null : new URI(str));
}
/**
@@ -218,7 +220,7 @@ public static BroadcastDomainType toEnumValue(String scheme) {
* @return the host part as String
*/
public String getValueFrom(URI uri) {
- return uri.getHost();
+ return uri == null ? null : uri.getHost();
}
/**
@@ -241,7 +243,7 @@ public static String getValue(URI uri) {
* @throws URISyntaxException the string is not even an uri
*/
public static String getValue(String uriString) throws URISyntaxException {
- return getValue(new URI(uriString));
+ return getValue(uriString == null ? null : new URI(uriString));
}
/**
diff --git a/api/src/main/java/com/cloud/network/PhysicalNetworkTrafficType.java b/api/src/main/java/com/cloud/network/PhysicalNetworkTrafficType.java
index 9676badb4e90..d3804cd29daf 100644
--- a/api/src/main/java/com/cloud/network/PhysicalNetworkTrafficType.java
+++ b/api/src/main/java/com/cloud/network/PhysicalNetworkTrafficType.java
@@ -41,4 +41,6 @@ public interface PhysicalNetworkTrafficType extends InternalIdentity, Identity {
String getHypervNetworkLabel();
String getOvm3NetworkLabel();
+
+ String getVlan();
}
diff --git a/api/src/main/java/com/cloud/network/RouterHealthCheckResult.java b/api/src/main/java/com/cloud/network/RouterHealthCheckResult.java
index eb65ae9088ec..22a46ce9ecdf 100644
--- a/api/src/main/java/com/cloud/network/RouterHealthCheckResult.java
+++ b/api/src/main/java/com/cloud/network/RouterHealthCheckResult.java
@@ -26,7 +26,7 @@ public interface RouterHealthCheckResult {
String getCheckType();
- boolean getCheckResult();
+ VirtualNetworkApplianceService.RouterHealthStatus getCheckResult();
Date getLastUpdateTime();
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 000000000000..a22db4287dcd
--- /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 994df875f7d3..51036abe0609 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 @@
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 c47500c78495..a60f1d49336a 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);
@@ -78,4 +87,8 @@ public interface VirtualNetworkApplianceService {
Pair performRouterHealthChecks(long routerId);
void collectNetworkStatistics(T router, Nic nic);
+
+ enum RouterHealthStatus{
+ SUCCESS, FAILED, WARNING, UNKNOWN;
+ }
}
diff --git a/api/src/main/java/com/cloud/network/VirtualRouterProvider.java b/api/src/main/java/com/cloud/network/VirtualRouterProvider.java
index aca526b1832b..98410ca09f88 100644
--- a/api/src/main/java/com/cloud/network/VirtualRouterProvider.java
+++ b/api/src/main/java/com/cloud/network/VirtualRouterProvider.java
@@ -21,7 +21,7 @@
public interface VirtualRouterProvider extends InternalIdentity, Identity {
public enum Type {
- VirtualRouter, ElasticLoadBalancerVm, VPCVirtualRouter, InternalLbVm, NetScalerVm
+ VirtualRouter, ElasticLoadBalancerVm, VPCVirtualRouter, InternalLbVm, NetScalerVm, Nsx
}
public Type getType();
diff --git a/api/src/main/java/com/cloud/network/VpcVirtualNetworkApplianceService.java b/api/src/main/java/com/cloud/network/VpcVirtualNetworkApplianceService.java
index 5c3ee3f1032a..cd04db802cac 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 @@ boolean addVpcRouterToGuestNetwork(VirtualRouter router, Network network, Map listCounters(ListCountersCmd cmd);
diff --git a/api/src/main/java/com/cloud/network/as/AutoScaleVmGroup.java b/api/src/main/java/com/cloud/network/as/AutoScaleVmGroup.java
index c265c1f36a0a..c05b3bda3db5 100644
--- a/api/src/main/java/com/cloud/network/as/AutoScaleVmGroup.java
+++ b/api/src/main/java/com/cloud/network/as/AutoScaleVmGroup.java
@@ -43,7 +43,7 @@ public static State fromValue(String state) {
} else if (state.equalsIgnoreCase("scaling")) {
return SCALING;
} else {
- throw new IllegalArgumentException("Unexpected AutoScale VM group state : " + state);
+ throw new IllegalArgumentException("Unexpected AutoScale Instance group state : " + state);
}
}
}
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 000000000000..ee919cb1af7d
--- /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 1bb37be970d3..dc0f60f45196 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/NetworkACLServiceProvider.java b/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java
index 8c3243c99f4b..852a650cfcde 100644
--- a/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java
+++ b/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java
@@ -21,6 +21,7 @@
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.vpc.NetworkACLItem;
+import com.cloud.network.vpc.Vpc;
public interface NetworkACLServiceProvider extends NetworkElement {
@@ -32,4 +33,6 @@ public interface NetworkACLServiceProvider extends NetworkElement {
*/
boolean applyNetworkACLs(Network config, List extends NetworkACLItem> rules) throws ResourceUnavailableException;
+ boolean reorderAclRules(Vpc vpc, List extends Network> networks, List extends NetworkACLItem> networkACLItems);
+
}
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 fa67575edd35..cb0fc2fca981 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.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 @@ boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, Deplo
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 e99bc2fd416b..8dcc8b6d0a47 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 14e86195a704..fe8c8f8612f7 100644
--- a/api/src/main/java/com/cloud/network/element/VpcProvider.java
+++ b/api/src/main/java/com/cloud/network/element/VpcProvider.java
@@ -22,6 +22,7 @@
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.IpAddress;
import com.cloud.network.vpc.NetworkACLItem;
import com.cloud.network.vpc.PrivateGateway;
import com.cloud.network.vpc.StaticRouteProfile;
@@ -52,4 +53,10 @@ boolean implementVpc(Vpc vpc, DeployDestination dest, ReservationContext context
boolean applyStaticRoutes(Vpc vpc, List routes) throws ResourceUnavailableException;
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 52f654007f28..ced664e54a96 100644
--- a/api/src/main/java/com/cloud/network/guru/NetworkGuru.java
+++ b/api/src/main/java/com/cloud/network/guru/NetworkGuru.java
@@ -79,20 +79,24 @@ public interface NetworkGuru extends Adapter {
* be used to make determination can be isolation methods, services
* provided on the guest network and the service provider that's on the
* guest network.
- *
+ *
* If a network is already fully substantiated with the necessary resources
* during this design phase, then the state should be set to Setup. If
* the resources are not allocated at this point, the state should be set
* to Allocated.
*
- * @param offering network offering that contains the package of services
- * the end user intends to use on that network.
- * @param plan where is this network being deployed.
+ * @param offering network offering that contains the package of services
+ * the end user intends to use on that network.
+ * @param plan where is this network being deployed.
* @param userSpecified user specified parameters for this network.
- * @param owner owner of this network.
+ * @param name
+ * @param vpcId
+ * @param owner owner of this network.
* @return Network
*/
- Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner);
+ Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, String name, Long vpcId, Account owner);
+
+ void setup(Network network, long networkId);
/**
* For guest networks that are in Allocated state after the design stage,
@@ -208,4 +212,11 @@ void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDe
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 64b2aeedf128..e4cf4ec526f0 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 long getId() {
return lb.getId();
}
+ public LoadBalancer getLb() {
+ return lb;
+ }
+
public String getName() {
return lb.getName();
}
diff --git a/api/src/main/java/com/cloud/network/lb/LoadBalancingRulesService.java b/api/src/main/java/com/cloud/network/lb/LoadBalancingRulesService.java
index 46f17237e029..b7fe3b26761c 100644
--- a/api/src/main/java/com/cloud/network/lb/LoadBalancingRulesService.java
+++ b/api/src/main/java/com/cloud/network/lb/LoadBalancingRulesService.java
@@ -41,13 +41,23 @@
public interface LoadBalancingRulesService {
/**
* Create a load balancer rule from the given ipAddress/port to the given private port
+ * @param xId an existing UUID for this rule (for instance a device generated one)
+ * @param name
+ * @param description
+ * @param srcPortStart
+ * @param srcPortEnd
+ * @param defPortStart
+ * @param defPortEnd
+ * @param ipAddrId
+ * @param protocol
+ * @param algorithm
+ * @param networkId
+ * @param lbOwnerId
* @param openFirewall
- * TODO
- * @param forDisplay TODO
- * @param cmd
- * the command specifying the ip address, public port, protocol, private port, and algorithm
- *
+ * @param lbProtocol
+ * @param forDisplay
* @return the newly created LoadBalancerVO if successful, null otherwise
+ * @throws NetworkRuleConflictException
* @throws InsufficientAddressCapacityException
*/
LoadBalancer createPublicLoadBalancerRule(String xId, String name, String description, int srcPortStart, int srcPortEnd, int defPortStart, int defPortEnd,
@@ -98,7 +108,7 @@ LoadBalancer createPublicLoadBalancerRule(String xId, String name, String descri
/**
* Assign a virtual machine or list of virtual machines, or Map of to a load balancer.
*/
- boolean assignToLoadBalancer(long lbRuleId, List vmIds, Map> vmIdIpMap, boolean isAutoScaleVM);
+ boolean assignToLoadBalancer(long lbRuleId, List vmIds, Map> vmIdIpMap, Map vmIdNetworkMap, boolean isAutoScaleVM);
boolean assignSSLCertToLoadBalancerRule(Long lbRuleId, String certName, String publicCert, String privateKey);
@@ -106,7 +116,7 @@ LoadBalancer createPublicLoadBalancerRule(String xId, String name, String descri
boolean applyLoadBalancerConfig(long lbRuleId) throws ResourceUnavailableException;
- boolean assignCertToLoadBalancer(long lbRuleId, Long certId);
+ boolean assignCertToLoadBalancer(long lbRuleId, Long certId, boolean isForced);
boolean removeCertFromLoadBalancer(long lbRuleId);
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 000000000000..afc21f7f511b
--- /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 000000000000..211517ead491
--- /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 000000000000..fccf2930e976
--- /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 000000000000..110e9f07105a
--- /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/NsxProvider.java b/api/src/main/java/com/cloud/network/nsx/NsxProvider.java
new file mode 100644
index 000000000000..19cb3b4b939e
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/nsx/NsxProvider.java
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network.nsx;
+
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface NsxProvider extends InternalIdentity, Identity {
+ String getHostname();
+
+ String getPort();
+ String getProviderName();
+ String getUsername();
+ long getZoneId();
+
+ String getTier0Gateway();
+ String getEdgeCluster();
+
+ String getTransportZone();
+}
diff --git a/api/src/main/java/com/cloud/network/nsx/NsxService.java b/api/src/main/java/com/cloud/network/nsx/NsxService.java
new file mode 100644
index 000000000000..1adb7461cc09
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/nsx/NsxService.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.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/LbStickinessMethod.java b/api/src/main/java/com/cloud/network/rules/LbStickinessMethod.java
index 56a0622a52ba..5143611ee828 100644
--- a/api/src/main/java/com/cloud/network/rules/LbStickinessMethod.java
+++ b/api/src/main/java/com/cloud/network/rules/LbStickinessMethod.java
@@ -108,8 +108,7 @@ public LbStickinessMethod(StickinessMethodType methodType, String description) {
}
public void addParam(String name, Boolean required, String description, Boolean isFlag) {
- /* FIXME : UI is breaking if the capability string length is larger , temporarily description is commented out */
- // LbStickinessMethodParam param = new LbStickinessMethodParam(name, required, description);
+ /* is this still a valid comment: FIXME : UI is breaking if the capability string length is larger , temporarily description is commented out */
LbStickinessMethodParam param = new LbStickinessMethodParam(name, required, " ", isFlag);
_paramList.add(param);
return;
@@ -133,7 +132,6 @@ public String getDescription() {
public void setDescription(String description) {
/* FIXME : UI is breaking if the capability string length is larger , temporarily description is commented out */
- //this.description = description;
this._description = " ";
}
}
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 0b4afeef9458..547d4ab51e03 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.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 @@ Pair, Integer> searchStaticNatRules(Long ipId, Long
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/NetworkACLService.java b/api/src/main/java/com/cloud/network/vpc/NetworkACLService.java
index 40aee1f08f1d..84e48d5d5b8a 100644
--- a/api/src/main/java/com/cloud/network/vpc/NetworkACLService.java
+++ b/api/src/main/java/com/cloud/network/vpc/NetworkACLService.java
@@ -19,6 +19,7 @@
import java.util.List;
import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd;
+import org.apache.cloudstack.api.command.user.network.ImportNetworkACLCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd;
import org.apache.cloudstack.api.command.user.network.MoveNetworkAclItemCmd;
@@ -98,4 +99,6 @@ public interface NetworkACLService {
NetworkACLItem moveNetworkAclRuleToNewPosition(MoveNetworkAclItemCmd moveNetworkAclItemCmd);
NetworkACLItem moveRuleToTheTopInACLList(NetworkACLItem ruleBeingMoved);
+
+ List importNetworkACLRules(ImportNetworkACLCmd cmd) throws ResourceUnavailableException;
}
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 5707ca140246..739fca328b8c 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 @@ enum State {
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 @@ enum State {
/**
* @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 cb4849f1f7b2..c8fc073911fe 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 StaticRouteProfile(StaticRoute staticRoute, VpcGateway gateway) {
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 long getDomainId() {
}
@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 e9a831c9d839..a0686e2bf7d0 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,8 @@ public enum State {
String getIp6Dns1();
String getIp6Dns2();
+
+ boolean useRouterIpAsResolver();
+
+ boolean getKeepMacAddressOnPublicNic();
}
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 b4df8e38dbac..f84602232159 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 @@
import java.util.Date;
+import com.cloud.offering.NetworkOffering;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@@ -29,6 +30,10 @@ public enum State {
public static final String defaultVPCOfferingName = "Default VPC offering";
public static final String defaultVPCNSOfferingName = "Default VPC offering with Netscaler";
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";
/**
*
@@ -53,6 +58,8 @@ public enum State {
*/
boolean isDefault();
+ NetworkOffering.NetworkMode getNetworkMode();
+
/**
* @return service offering id used by VPC virtual router
*/
@@ -73,4 +80,10 @@ public enum State {
Date getRemoved();
Date getCreated();
+
+ NetworkOffering.RoutingMode getRoutingMode();
+
+ Boolean isSpecifyAsNumber();
+
+ boolean isConserveMode();
}
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 5cccd6c5a823..891cfb02d9df 100644
--- a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
+++ b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
@@ -20,10 +20,12 @@
import java.util.List;
import java.util.Map;
+import org.apache.cloudstack.api.command.admin.vpc.CloneVPCOfferingCmd;
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;
@@ -33,10 +35,15 @@ public interface VpcProvisioningService {
VpcOffering createVpcOffering(CreateVPCOfferingCmd cmd);
+ VpcOffering cloneVPCOffering(CloneVPCOfferingCmd cmd);
+
VpcOffering createVpcOffering(String name, String displayText, List supportedServices,
Map> serviceProviders,
Map serviceCapabilitystList, NetUtils.InternetProtocol internetProtocol,
- Long serviceOfferingId, List domainIds, List zoneIds, VpcOffering.State state);
+ Long serviceOfferingId, String externalProvider, NetworkOffering.NetworkMode networkMode,
+ List domainIds, List