startupTask = new AtomicReference<>();
+ private static final long DEFAULT_STARTUP_WAIT = 180;
+ long startupWait = DEFAULT_STARTUP_WAIT;
+ boolean reconnectAllowed = true;
- Thread _shutdownThread = new ShutdownThread(this);
+ //For time sensitive task, e.g. PingTask
+ ThreadPoolExecutor outRequestHandler;
+ ExecutorService requestHandler;
- private String _keystoreSetupPath;
- private String _keystoreCertImportPath;
+ Thread shutdownThread = new ShutdownThread(this);
- // for simulator use only
+ private String keystoreSetupSetupPath;
+ private String keystoreCertImportScriptPath;
+
+ private String hostname;
+
+ protected String getLinkLog(final Link link) {
+ if (link == null) {
+ return "";
+ }
+ StringBuilder str = new StringBuilder();
+ if (logger.isTraceEnabled()) {
+ str.append(System.identityHashCode(link)).append("-");
+ }
+ str.append(link.getSocketAddress());
+ return str.toString();
+ }
+
+ protected String getAgentName() {
+ return (serverResource != null && serverResource.isAppendAgentNameToLogs() &&
+ StringUtils.isNotBlank(serverResource.getName())) ?
+ serverResource.getName() :
+ "Agent";
+ }
+
+ protected void setupShutdownHookAndInitExecutors() {
+ logger.trace("Adding shutdown hook");
+ Runtime.getRuntime().addShutdownHook(shutdownThread);
+ selfTaskExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Agent-SelfTask"));
+ outRequestHandler = new ThreadPoolExecutor(shell.getPingRetries(), 2 * shell.getPingRetries(), 10, TimeUnit.MINUTES,
+ new SynchronousQueue<>(), new NamedThreadFactory("AgentOutRequest-Handler"));
+ requestHandler = new ThreadPoolExecutor(shell.getWorkers(), 5 * shell.getWorkers(), 1, TimeUnit.DAYS,
+ new LinkedBlockingQueue<>(), new NamedThreadFactory("AgentRequest-Handler"));
+ }
+
+ /**
+ * Constructor for the {@code Agent} class, intended for simulator use only.
+ *
+ * This constructor initializes the agent with a provided {@link IAgentShell}.
+ * It sets up the necessary NIO client connection, establishes a shutdown hook,
+ * and initializes the thread executors.
+ *
+ * @param shell the {@link IAgentShell} instance that provides agent configuration and runtime information.
+ */
public Agent(final IAgentShell shell) {
- _shell = shell;
- _link = null;
-
- _connection = new NioClient("Agent", _shell.getNextHost(), _shell.getPort(), _shell.getWorkers(), this);
-
- Runtime.getRuntime().addShutdownHook(_shutdownThread);
-
- _ugentTaskPool =
- new ThreadPoolExecutor(shell.getPingRetries(), 2 * shell.getPingRetries(), 10, TimeUnit.MINUTES, new SynchronousQueue(), new NamedThreadFactory(
- "UgentTask"));
-
- _executor =
- new ThreadPoolExecutor(_shell.getWorkers(), 5 * _shell.getWorkers(), 1, TimeUnit.DAYS, new LinkedBlockingQueue(), new NamedThreadFactory(
- "agentRequest-Handler"));
+ this.shell = shell;
+ this.link = null;
+ this.connection = new NioClient(
+ getAgentName(),
+ this.shell.getNextHost(),
+ this.shell.getPort(),
+ this.shell.getWorkers(),
+ this.shell.getSslHandshakeTimeout(),
+ this
+ );
+ setupShutdownHookAndInitExecutors();
}
public Agent(final IAgentShell shell, final int localAgentId, final ServerResource resource) throws ConfigurationException {
- _shell = shell;
- _resource = resource;
- _link = null;
-
+ this.shell = shell;
+ serverResource = resource;
+ link = null;
resource.setAgentControl(this);
-
- final String value = _shell.getPersistentProperty(getResourceName(), "id");
- _id = value != null ? Long.parseLong(value) : null;
- s_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());
-
- s_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"));
-
- s_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();
}
/**
@@ -253,189 +292,211 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
* agent instances and its inner objects.
*/
private void scavengeOldAgentObjects() {
- _executor.submit(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(2000L);
- } catch (final InterruptedException ignored) {
- } finally {
- System.gc();
- }
+ requestHandler.submit(() -> {
+ try {
+ Thread.sleep(2000L);
+ } catch (final InterruptedException ignored) {
+ } finally {
+ System.gc();
}
});
}
public void start() {
- if (!_resource.start()) {
- s_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) {
- s_logger.warn("NIO Connection Exception " + e);
- s_logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...");
+ logger.warn("Attempt to connect to server generated NIO Connection Exception {}, trying again", e.getLocalizedMessage());
}
- while (!_connection.isStartup()) {
- final String host = _shell.getNextHost();
- _shell.getBackoffAlgorithm().waitBeforeRetry();
- _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this);
- s_logger.info("Connecting to host:" + host);
+ while (!connection.isStartup()) {
+ final String host = shell.getNextHost();
+ shell.getBackoffAlgorithm().waitBeforeRetry();
+ connection = new NioClient(getAgentName(), host, shell.getPort(), shell.getWorkers(),
+ shell.getSslHandshakeTimeout(), this);
+ logger.info("Connecting to host: {}", host);
try {
- _connection.start();
+ connection.start();
} catch (final NioConnectionException e) {
- _connection.stop();
- try {
- _connection.cleanUp();
- } catch (final IOException ex) {
- s_logger.warn("Fail to clean up old connection. " + ex);
- }
- s_logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...", e);
+ stopAndCleanupConnection(false);
+ logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...", e);
}
}
- _shell.updateConnectedHost();
+ shell.updateConnectedHost();
scavengeOldAgentObjects();
}
public void stop(final String reason, final String detail) {
- s_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) {
- s_logger.warn("Unable to send: " + cmd.toString());
+ logger.warn("Unable to send: {}", cmd.toString());
} catch (final Exception e) {
- s_logger.warn("Unable to send: " + cmd.toString() + " due to exception: ", e);
+ logger.warn("Unable to send: {} due to exception: {}", cmd.toString(), e);
}
- s_logger.debug("Sending shutdown to management server");
+ logger.debug("Sending shutdown to management server");
try {
Thread.sleep(1000);
} catch (final InterruptedException e) {
- s_logger.debug("Who the heck interrupted me here?");
+ 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) {
- s_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));
}
- private synchronized void scheduleServicesRestartTask() {
- if (certTimer != null) {
- certTimer.cancel();
- certTimer.purge();
+ public String getUuid() {
+ return _uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this._uuid = uuid;
+ shell.setPersistentProperty(getResourceName(), "uuid", uuid);
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public void setName(String name) {
+ this._name = name;
+ shell.setPersistentProperty(getResourceName(), "name", name);
+ }
+
+ private void scheduleCertificateRenewalTask() {
+ String name = "CertificateRenewalTask";
+ if (certExecutor != null && !certExecutor.isShutdown()) {
+ certExecutor.shutdown();
+ try {
+ if (!certExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
+ certExecutor.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ logger.debug("Forcing {} shutdown as it did not shutdown in the desired time due to: {}",
+ name, e.getMessage());
+ certExecutor.shutdownNow();
+ }
}
- certTimer = new Timer("Certificate Renewal Timer");
- certTimer.schedule(new PostCertificateRenewalTask(this), 5000L);
+ certExecutor = Executors.newSingleThreadScheduledExecutor((new NamedThreadFactory(name)));
+ certExecutor.schedule(new PostCertificateRenewalTask(this), 5, TimeUnit.SECONDS);
}
- private synchronized void scheduleHostLBCheckerTask(final long checkInterval) {
- if (hostLBTimer != null) {
- hostLBTimer.cancel();
+ private void scheduleHostLBCheckerTask(final long checkInterval) {
+ String name = "HostLBCheckerTask";
+ if (hostLbCheckExecutor != null && !hostLbCheckExecutor.isShutdown()) {
+ hostLbCheckExecutor.shutdown();
+ try {
+ if (!hostLbCheckExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
+ hostLbCheckExecutor.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ logger.debug("Forcing {} shutdown as it did not shutdown in the desired time due to: {}",
+ name, e.getMessage());
+ hostLbCheckExecutor.shutdownNow();
+ }
}
if (checkInterval > 0L) {
- s_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);
+ logger.info("Scheduling preferred host 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 (s_logger.isDebugEnabled()) {
- s_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);
- s_logger.debug("Sending out of band ping");
-
- final Request request = new Request(_id, -1, command, false);
+ logger.debug("Sending out of band ping");
+ 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) {
- s_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 (s_logger.isDebugEnabled()) {
- s_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();
}
/**
@@ -446,61 +507,85 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
* when host is added back
*/
protected void cleanupAgentZoneProperties() {
- _shell.setPersistentProperty(null, "zone", "");
- _shell.setPersistentProperty(null, "cluster", "");
- _shell.setPersistentProperty(null, "pod", "");
+ shell.setPersistentProperty(null, "zone", "");
+ shell.setPersistentProperty(null, "cluster", "");
+ shell.setPersistentProperty(null, "pod", "");
}
- public synchronized void lockStartupTask(final Link link) {
- _startup = new StartupTask(link);
- _timer.schedule(_startup, _startupWait);
+ public void lockStartupTask(final Link link) {
+ logger.debug("Creating startup task for link: {}", () -> getLinkLog(link));
+ StartupTask currentTask = startupTask.get();
+ if (currentTask != null) {
+ logger.warn("A Startup task is already locked or in progress, cannot create for link {}",
+ getLinkLog(link));
+ return;
+ }
+ currentTask = new StartupTask(link);
+ if (startupTask.compareAndSet(null, currentTask)) {
+ selfTaskExecutor.schedule(currentTask, startupWait, TimeUnit.SECONDS);
+ return;
+ }
+ logger.warn("Failed to lock a StartupTask for link: {}", getLinkLog(link));
+ }
+
+ protected boolean cancelStartupTask() {
+ StartupTask task = startupTask.getAndSet(null);
+ if (task != null) {
+ task.cancel();
+ return true;
+ }
+ return false;
}
public void sendStartup(final Link link) {
- final StartupCommand[] startup = _resource.initialize();
+ 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);
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 (s_logger.isDebugEnabled()) {
- s_logger.debug("Sending Startup: " + request.toString());
- }
+ logger.debug("Sending Startup: {}", request.toString());
lockStartupTask(link);
try {
link.send(request.toBytes());
} catch (final ClosedChannelException e) {
- s_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) {
- s_logger.warn("unknown host? ", e);
+ logger.warn("unknown host? ", e);
throw new CloudRuntimeException("Cannot get local IP address");
}
+ }
- final Script command = new Script("hostname", 500, s_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());
@@ -508,6 +593,13 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
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
@@ -515,93 +607,94 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
return new ServerHandler(type, link, data);
}
- protected void reconnect(final Link link) {
- if (!_reconnectAllowed) {
+ protected void closeAndTerminateLink(final Link link) {
+ if (link == null) {
return;
}
- synchronized (this) {
- if (_startup != null) {
- _startup.cancel();
- _startup = null;
- }
- }
+ link.close();
+ link.terminated();
+ }
- if (link != null) {
- link.close();
- link.terminated();
+ protected void stopAndCleanupConnection(boolean waitForStop) {
+ if (connection == null) {
+ return;
}
+ connection.stop();
+ try {
+ connection.cleanUp();
+ } catch (final IOException e) {
+ logger.warn("Fail to clean up old connection. {}", e);
+ }
+ if (!waitForStop) {
+ return;
+ }
+ do {
+ shell.getBackoffAlgorithm().waitBeforeRetry();
+ } while (connection.isStartup());
+ }
+ protected void reconnect(final Link link) {
+ if (!reconnectAllowed) {
+ logger.debug("Reconnect requested but it is not allowed {}", () -> getLinkLog(link));
+ return;
+ }
+ cancelStartupTask();
+ closeAndTerminateLink(link);
+ closeAndTerminateLink(this.link);
setLink(null);
cancelTasks();
-
- _resource.disconnected();
-
- s_logger.info("Lost connection to host: " + _shell.getConnectedHost() + ". Attempting reconnection while we still have " + _inProgress.get() + " commands in progress.");
-
- _connection.stop();
-
- try {
- _connection.cleanUp();
- } catch (final IOException e) {
- s_logger.warn("Fail to clean up old connection. " + e);
- }
-
- while (_connection.isStartup()) {
- _shell.getBackoffAlgorithm().waitBeforeRetry();
- }
-
+ serverResource.disconnected();
+ logger.info("Lost connection to host: {}. Attempting reconnection while we still have {} commands in progress.", shell.getConnectedHost(), commandsInProgress.get());
+ stopAndCleanupConnection(true);
do {
- final String host = _shell.getNextHost();
- _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this);
- s_logger.info("Reconnecting to host:" + host);
+ final String host = shell.getNextHost();
+ connection = new NioClient(getAgentName(), host, shell.getPort(), shell.getWorkers(), shell.getSslHandshakeTimeout(), this);
+ logger.info("Reconnecting to host: {}", host);
try {
- _connection.start();
+ connection.start();
} catch (final NioConnectionException e) {
- s_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) {
- s_logger.warn("Fail to clean up old connection. " + ex);
- }
+ logger.info("Attempted to re-connect to the server, but received an unexpected exception, trying again...", e);
+ stopAndCleanupConnection(false);
}
- _shell.getBackoffAlgorithm().waitBeforeRetry();
- } while (!_connection.isStartup());
- _shell.updateConnectedHost();
- s_logger.info("Connected to the host: " + _shell.getConnectedHost());
+ shell.getBackoffAlgorithm().waitBeforeRetry();
+ } while (!connection.isStartup());
+ shell.updateConnectedHost();
+ logger.info("Connected to the host: {}", shell.getConnectedHost());
}
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()) {
- s_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) {
- s_logger.warn("Threw away a startup answer because we're reconnecting.");
+ if (!answerValid) {
+ logger.warn("Threw away a startup answer because we're reconnecting.");
return;
}
- s_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);
- s_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) {
@@ -615,62 +708,64 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
final Command cmd = cmds[i];
Answer answer;
try {
- if (cmd.getContextParam("logid") != null) {
- MDC.put("logcontextid", cmd.getContextParam("logid"));
- }
- if (s_logger.isDebugEnabled()) {
+ if (logger.isDebugEnabled()) {
if (!requestLogged) // ensures request is logged only once per method call
{
final String requestMsg = request.toString();
if (requestMsg != null) {
- s_logger.debug("Request:" + requestMsg);
+ logger.debug("Request:{}",requestMsg);
}
requestLogged = true;
}
- s_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;
- s_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) {
- s_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) {
- s_logger.debug("Received maintainCommand, do not cancel current tasks");
+ logger.debug("Received maintainCommand, do not cancel current tasks");
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) {
- s_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);
@@ -678,19 +773,19 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
if (cmd instanceof ReadyCommand) {
processReadyCommand(cmd);
}
- _inProgress.incrementAndGet();
+ commandsInProgress.incrementAndGet();
try {
- answer = _resource.executeRequest(cmd);
+ answer = serverResource.executeRequest(cmd);
} finally {
- _inProgress.decrementAndGet();
+ commandsInProgress.decrementAndGet();
}
if (answer == null) {
- s_logger.debug("Response: unsupported command" + cmd.toString());
+ logger.debug("Response: unsupported command {}", cmd.toString());
answer = Answer.createUnsupportedCommandAnswer(cmd);
}
}
} catch (final Throwable th) {
- s_logger.warn("Caught: ", th);
+ logger.warn("Caught: ", th);
final StringWriter writer = new StringWriter();
th.printStackTrace(new PrintWriter(writer));
answer = new Answer(cmd, false, writer.toString());
@@ -706,10 +801,10 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
response = new Response(request, answers);
} finally {
- if (s_logger.isDebugEnabled()) {
+ if (logger.isDebugEnabled()) {
final String responseMsg = response.toString();
if (responseMsg != null) {
- s_logger.debug(response.toString());
+ logger.debug(response.toString());
}
}
@@ -717,7 +812,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
try {
link.send(response.toBytes());
} catch (final ClosedChannelException e) {
- s_logger.warn("Unable to send response: " + response.toString());
+ logger.warn("Unable to send response: {}", response.toString());
}
}
}
@@ -727,7 +822,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
final String keyStorePassword = cmd.getKeystorePassword();
final long validityDays = cmd.getValidityDays();
- s_logger.debug("Setting up agent keystore file and generating CSR");
+ logger.debug("Setting up agent keystore file and generating CSR");
final File agentFile = PropertiesUtil.findConfigFile("agent.properties");
if (agentFile == null) {
@@ -736,13 +831,13 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
final String keyStoreFile = agentFile.getParent() + "/" + KeyStoreUtils.KS_FILENAME;
final String csrFile = agentFile.getParent() + "/" + KeyStoreUtils.CSR_FILENAME;
- String storedPassword = _shell.getPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY);
+ String storedPassword = shell.getPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY);
if (StringUtils.isEmpty(storedPassword)) {
storedPassword = keyStorePassword;
- _shell.setPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY, storedPassword);
+ shell.setPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY, storedPassword);
}
- Script script = new Script(_keystoreSetupPath, 300000, s_logger);
+ Script script = new Script(keystoreSetupSetupPath, 300000, logger);
script.add(agentFile.getAbsolutePath());
script.add(keyStoreFile);
script.add(storedPassword);
@@ -767,7 +862,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
final String privateKey = cmd.getPrivateKey();
final String caCertificates = cmd.getCaCertificates();
- s_logger.debug("Importing received certificate to agent's keystore");
+ logger.debug("Importing received certificate to agent's keystore");
final File agentFile = PropertiesUtil.findConfigFile("agent.properties");
if (agentFile == null) {
@@ -781,13 +876,13 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
try {
FileUtils.writeStringToFile(new File(certFile), certificate, Charset.defaultCharset());
FileUtils.writeStringToFile(new File(caCertFile), caCertificates, Charset.defaultCharset());
- s_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, s_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);
@@ -809,10 +904,10 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
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();
- s_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);
}
@@ -820,7 +915,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
if ("shuffle".equals(lbAlgorithm)) {
scheduleHostLBCheckerTask(0);
} else {
- scheduleHostLBCheckerTask(_shell.getLbCheckerInterval(lbCheckInterval));
+ scheduleHostLBCheckerTask(shell.getLbCheckerInterval(lbCheckInterval));
}
}
@@ -831,23 +926,19 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
public void processResponse(final Response response, final Link link) {
final Answer answer = response.getAnswer();
- if (s_logger.isDebugEnabled()) {
- s_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) {
- s_logger.info("Management server requested startup command to reinitialize the agent");
+ } else if (answer instanceof PingAnswer && (((PingAnswer) answer).isSendStartup()) && reconnectAllowed) {
+ logger.info("Management server requested startup command to reinitialize the agent");
sendStartup(link);
} else {
- setLastPingResponseTime();
+ updateLastPingResponseTime();
}
}
@@ -859,98 +950,102 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
NumbersUtil.enableHumanReadableSizes = humanReadable;
}
- s_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());
}
+ verifyAgentArch(ready.getArch());
processManagementServerList(ready.getMsHostList(), ready.getLbAlgorithm(), ready.getLbCheckInterval());
- s_logger.info("Ready command is processed for agent id = " + getId());
+ logger.info("Ready command is processed for agent [id: {}, uuid: {}, name: {}]", getId(), getUuid(), getName());
+ }
+
+ private void verifyAgentArch(String arch) {
+ if (StringUtils.isNotBlank(arch)) {
+ String agentArch = getAgentArch();
+ if (!arch.equals(agentArch)) {
+ logger.error("Unexpected arch {}, expected {}", agentArch, arch);
+ }
+ }
}
public void processOtherTask(final Task task) {
final Object obj = task.get();
if (obj instanceof Response) {
- if (System.currentTimeMillis() - _lastPingResponseTime > _pingInterval * _shell.getPingRetries()) {
- s_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 (s_logger.isDebugEnabled()) {
- s_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) {
- s_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) {
final Request req = (Request)obj;
final Command command = req.getCommand();
if (command.getContextParam("logid") != null) {
- MDC.put("logcontextid", command.getContextParam("logid"));
+ ThreadContext.put("logcontextid", command.getContextParam("logid"));
}
Answer answer = null;
- _inProgress.incrementAndGet();
+ commandsInProgress.incrementAndGet();
try {
- answer = _resource.executeRequest(command);
+ answer = serverResource.executeRequest(command);
} finally {
- _inProgress.decrementAndGet();
+ commandsInProgress.decrementAndGet();
}
if (answer != null) {
final Response response = new Response(req, answer);
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Watch Sent: " + response.toString());
- }
+ logger.debug("Watch Sent: {}", response.toString());
try {
task.getLink().send(response.toBytes());
} catch (final ClosedChannelException e) {
- s_logger.warn("Unable to send response: " + response.toString());
+ logger.warn("Unable to send response: {}", response.toString());
}
}
} else {
- s_logger.warn("Ignoring an unknown task");
+ logger.warn("Ignoring an unknown 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);
@@ -958,10 +1053,9 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
try {
listener.wait(timeoutInMilliseconds);
} catch (final InterruptedException e) {
- s_logger.warn("sendRequest is interrupted, exit waiting");
+ logger.warn("sendRequest is interrupted, exit waiting");
}
}
-
return listener.getAnswer();
} finally {
unregisterControlListener(listener);
@@ -976,11 +1070,11 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
private void postRequest(final Request request) throws AgentControlChannelException {
- if (_link != null) {
+ if (link != null) {
try {
- _link.send(request.toBytes());
+ link.send(request.toBytes());
} catch (final ClosedChannelException e) {
- s_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 {
@@ -1030,7 +1124,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
}
- public class WatchTask extends ManagedContextTimerTask {
+ public class WatchTask implements Runnable {
protected Request _request;
protected Agent _agent;
protected Link _link;
@@ -1043,52 +1137,45 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
@Override
- protected void runInContext() {
- if (s_logger.isTraceEnabled()) {
- s_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));
}
} catch (final ClosedChannelException e) {
- s_logger.warn("Unable to schedule task because channel is closed");
+ logger.warn("Unable to schedule task because channel is closed");
}
}
}
- public class StartupTask extends ManagedContextTimerTask {
+ public class StartupTask implements Runnable {
protected Link _link;
- protected volatile boolean cancelled = false;
+ private final AtomicBoolean cancelled = new AtomicBoolean(false);
public StartupTask(final Link link) {
- s_logger.debug("Startup task created");
+ logger.debug("Startup task created");
_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;
- s_logger.debug("Startup task cancelled");
- return super.cancel();
+ if (cancelled.compareAndSet(false, true)) {
+ startupWait = DEFAULT_STARTUP_WAIT;
+ logger.debug("Startup task cancelled");
}
return true;
}
@Override
- protected synchronized void runInContext() {
- if (!cancelled) {
- if (s_logger.isInfoEnabled()) {
- s_logger.info("The startup command is now cancelled");
- }
- cancelled = true;
- _startup = null;
- _startupWait = _startupWaitDefault * 2;
+ 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);
}
}
@@ -1120,7 +1207,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
@Override
public void doTask(final Task task) throws TaskExecutionException {
if (task.getType() == Task.Type.CONNECT) {
- _shell.getBackoffAlgorithm().reset();
+ shell.getBackoffAlgorithm().reset();
setLink(task.getLink());
sendStartup(task.getLink());
} else if (task.getType() == Task.Type.DATA) {
@@ -1133,22 +1220,23 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
} else {
//put the requests from mgt server into another thread pool, as the request may take a longer time to finish. Don't block the NIO main thread pool
//processRequest(request, task.getLink());
- _executor.submit(new AgentRequestHandler(getType(), getLink(), request));
+ requestHandler.submit(new AgentRequestHandler(getType(), getLink(), request));
}
} catch (final ClassNotFoundException e) {
- s_logger.error("Unable to find this request ");
+ logger.error("Unable to find this request ");
} catch (final Exception e) {
- s_logger.error("Error parsing task", e);
+ logger.error("Error parsing task", e);
}
} else if (task.getType() == Task.Type.DISCONNECT) {
try {
- // an issue has been found if reconnect immediately after disconnecting. please refer to https://github.com/apache/cloudstack/issues/8517
+ // 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) {
}
+ logger.debug("Executing disconnect task - {} and reconnecting", () -> getLinkLog(task.getLink()));
reconnect(task.getLink());
- return;
} else if (task.getType() == Task.Type.OTHER) {
processOtherTask(task);
}
@@ -1171,38 +1259,36 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
protected void runInContext() {
while (true) {
try {
- if (_inProgress.get() == 0) {
- s_logger.debug("Running post certificate renewal task to restart services.");
+ 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 (s_logger.isTraceEnabled()) {
- s_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) {
- s_logger.warn("Failed to execute post certificate renewal command:", e);
+ logger.warn("Failed to execute post certificate renewal command:", e);
break;
}
}
@@ -1214,38 +1300,34 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
@Override
protected void runInContext() {
try {
- final String[] msList = _shell.getHosts();
+ final String[] msList = shell.getHosts();
if (msList == null || msList.length < 1) {
return;
}
final String preferredHost = msList[0];
- final String connectedHost = _shell.getConnectedHost();
- if (s_logger.isTraceEnabled()) {
- s_logger.trace("Running preferred host checker task, connected host=" + connectedHost + ", preferred host=" + preferredHost);
+ final String connectedHost = shell.getConnectedHost();
+ logger.debug("Running preferred host checker task, connected host={}, preferred host={}",
+ connectedHost, preferredHost);
+ if (preferredHost == null || preferredHost.equals(connectedHost) || link == null) {
+ 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 (s_logger.isTraceEnabled()) {
- s_logger.trace("Host: " + preferredHost + " is not reachable");
- }
- }
- if (isHostUp && _link != null && _inProgress.get() == 0) {
- if (s_logger.isDebugEnabled()) {
- s_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(preferredHost, shell.getPort()), 5000);
+ isHostUp = true;
+ } catch (final IOException e) {
+ logger.debug("Host: {} is not reachable", preferredHost);
+ }
+ if (isHostUp && link != null && commandsInProgress.get() == 0) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Preferred host {} is found to be reachable, trying to reconnect", preferredHost);
}
+ shell.resetHostCounter();
+ reconnect(link);
}
} catch (Throwable t) {
- s_logger.error("Error caught while attempting to connect to preferred host", 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 ef042496a37..c5257b95b7c 100644
--- a/agent/src/main/java/com/cloud/agent/AgentShell.java
+++ b/agent/src/main/java/com/cloud/agent/AgentShell.java
@@ -16,28 +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.log4j.Logger;
-import org.apache.log4j.xml.DOMConfigurator;
-
-import javax.naming.ConfigurationException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -52,8 +30,33 @@ import java.util.Map;
import java.util.Properties;
import java.util.UUID;
+import javax.naming.ConfigurationException;
+
+import org.apache.commons.daemon.Daemon;
+import org.apache.commons.daemon.DaemonContext;
+import org.apache.commons.daemon.DaemonInitException;
+import org.apache.commons.lang.math.NumberUtils;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.config.Configurator;
+
+import com.cloud.agent.Agent.ExitStatus;
+import com.cloud.agent.dao.StorageComponent;
+import com.cloud.agent.dao.impl.PropertiesStorage;
+import com.cloud.agent.properties.AgentProperties;
+import com.cloud.agent.properties.AgentPropertiesFileHandler;
+import com.cloud.resource.ServerResource;
+import com.cloud.utils.LogUtils;
+import com.cloud.utils.ProcessUtil;
+import com.cloud.utils.PropertiesUtil;
+import com.cloud.utils.backoff.BackoffAlgorithm;
+import com.cloud.utils.backoff.impl.ConstantTimeBackoff;
+import com.cloud.utils.exception.CloudRuntimeException;
+
public class AgentShell implements IAgentShell, Daemon {
- private static final Logger s_logger = Logger.getLogger(AgentShell.class.getName());
+ protected static Logger LOGGER = LogManager.getLogger(AgentShell.class);
private final Properties _properties = new Properties();
private final Map _cmdLineProperties = new HashMap();
@@ -221,7 +224,7 @@ public class AgentShell implements IAgentShell, Daemon {
throw new ConfigurationException("Unable to find agent.properties.");
}
- s_logger.info("agent.properties found at " + file.getAbsolutePath());
+ LOGGER.info("agent.properties found at {}", file.getAbsolutePath());
try {
PropertiesUtil.loadFromFile(_properties, file);
@@ -349,7 +352,7 @@ public class AgentShell implements IAgentShell, Daemon {
@Override
public void init(DaemonContext dc) throws DaemonInitException {
- s_logger.debug("Initializing AgentShell from JSVC");
+ LOGGER.debug("Initializing AgentShell from JSVC");
try {
init(dc.getArguments());
} catch (ConfigurationException ex) {
@@ -369,11 +372,11 @@ public class AgentShell implements IAgentShell, Daemon {
}
if (null != file) {
- DOMConfigurator.configureAndWatch(file.getAbsolutePath());
+ Configurator.initialize(null, file.getAbsolutePath());
- s_logger.info("Agent started");
+ LOGGER.info("Agent started");
} else {
- s_logger.error("Could not start the Agent because the absolute path of the \"log4j-cloud.xml\" file cannot be determined.");
+ LOGGER.error("Could not start the Agent because the absolute path of the \"log4j-cloud.xml\" file cannot be determined.");
}
final Class> c = this.getClass();
@@ -381,19 +384,19 @@ public class AgentShell implements IAgentShell, Daemon {
if (_version == null) {
throw new CloudRuntimeException("Unable to find the implementation version of this agent");
}
- s_logger.info("Implementation Version is " + _version);
+ LOGGER.info("Implementation Version is {}", _version);
loadProperties();
parseCommand(args);
- if (s_logger.isDebugEnabled()) {
+ if (LOGGER.isDebugEnabled()) {
List properties = Collections.list((Enumeration)_properties.propertyNames());
for (String property : properties) {
- s_logger.debug("Found property: " + property);
+ LOGGER.debug("Found property: {}", property);
}
}
- s_logger.info("Defaulting to using properties file for storage");
+ LOGGER.info("Defaulting to using properties file for storage");
_storage = new PropertiesStorage();
_storage.configure("Storage", new HashMap());
@@ -403,14 +406,16 @@ public class AgentShell implements IAgentShell, Daemon {
_properties.put(cmdLineProp.getKey(), cmdLineProp.getValue());
}
- s_logger.info("Defaulting to the constant time backoff algorithm");
+ 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);
- s_logger.trace("resource=" + resourceClassNames);
+ LOGGER.trace("resource={}", resourceClassNames);
if (resourceClassNames != null) {
launchAgentFromClassInfo(resourceClassNames);
return;
@@ -440,10 +445,10 @@ public class AgentShell implements IAgentShell, Daemon {
private void launchAgentFromTypeInfo() throws ConfigurationException {
String typeInfo = getProperty(null, "type");
if (typeInfo == null) {
- s_logger.error("Unable to retrieve the type");
+ LOGGER.error("Unable to retrieve the type");
throw new ConfigurationException("Unable to retrieve the type of this agent.");
}
- s_logger.trace("Launching agent based on type=" + typeInfo);
+ LOGGER.trace("Launching agent based on type={}", typeInfo);
}
public void launchNewAgent(ServerResource resource) throws ConfigurationException {
@@ -454,6 +459,11 @@ public class AgentShell implements IAgentShell, Daemon {
agent.start();
}
+ @Override
+ public Integer getSslHandshakeTimeout() {
+ return AgentPropertiesFileHandler.getPropertyValue(AgentProperties.SSL_HANDSHAKE_TIMEOUT);
+ }
+
public synchronized int getNextAgentId() {
return _nextAgentId++;
}
@@ -477,17 +487,17 @@ public class AgentShell implements IAgentShell, Daemon {
}
if (ipv6disabled) {
- s_logger.info("Preferring IPv4 address family for agent connection");
+ LOGGER.info("Preferring IPv4 address family for agent connection");
System.setProperty("java.net.preferIPv4Stack", "true");
if (ipv6prefer) {
- s_logger.info("ipv6prefer is set to true, but ipv6disabled is false. Not preferring IPv6 for agent connection");
+ LOGGER.info("ipv6prefer is set to true, but ipv6disabled is false. Not preferring IPv6 for agent connection");
}
} else {
if (ipv6prefer) {
- s_logger.info("Preferring IPv6 address family for agent connection");
+ LOGGER.info("Preferring IPv6 address family for agent connection");
System.setProperty("java.net.preferIPv6Addresses", "true");
} else {
- s_logger.info("Using default Java settings for IPv6 preference for agent connection");
+ LOGGER.info("Using default Java settings for IPv6 preference for agent connection");
}
}
@@ -505,7 +515,7 @@ public class AgentShell implements IAgentShell, Daemon {
String pidDir = getProperty(null, "piddir");
final String run = "agent." + instance + "pid";
- s_logger.debug("Checking to see if " + run + " exists.");
+ LOGGER.debug("Checking to see if {} exists.", run);
ProcessUtil.pidCheck(pidDir, run);
launchAgent();
@@ -514,11 +524,11 @@ public class AgentShell implements IAgentShell, Daemon {
while (!_exit)
Thread.sleep(1000);
} catch (InterruptedException e) {
- s_logger.debug("[ignored] AgentShell was interrupted.");
+ LOGGER.debug("[ignored] AgentShell was interrupted.");
}
} catch (final Exception e) {
- s_logger.error("Unable to start agent: ", e);
+ LOGGER.error("Unable to start agent: ", e);
System.exit(ExitStatus.Error.value());
}
}
@@ -535,7 +545,7 @@ public class AgentShell implements IAgentShell, Daemon {
public static void main(String[] args) {
try {
- s_logger.debug("Initializing AgentShell from main");
+ LOGGER.debug("Initializing AgentShell from main");
AgentShell shell = new AgentShell();
shell.init(args);
shell.start();
diff --git a/agent/src/main/java/com/cloud/agent/IAgentShell.java b/agent/src/main/java/com/cloud/agent/IAgentShell.java
index 2dd08fffd45..7f04048795d 100644
--- a/agent/src/main/java/com/cloud/agent/IAgentShell.java
+++ b/agent/src/main/java/com/cloud/agent/IAgentShell.java
@@ -70,4 +70,6 @@ public interface IAgentShell {
String getConnectedHost();
void launchNewAgent(ServerResource resource) throws ConfigurationException;
+
+ 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 87610c29f34..17e0ceeeede 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
@@ -24,7 +24,8 @@ import java.util.Map;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
import com.cloud.agent.dao.StorageComponent;
import com.cloud.utils.PropertiesUtil;
@@ -36,7 +37,7 @@ import com.cloud.utils.PropertiesUtil;
* path to the properties _file | String | db/db.properties || * }
**/
public class PropertiesStorage implements StorageComponent {
- private static final Logger s_logger = Logger.getLogger(PropertiesStorage.class);
+ protected Logger logger = LogManager.getLogger(getClass());
Properties _properties = new Properties();
File _file;
String _name;
@@ -49,7 +50,7 @@ public class PropertiesStorage implements StorageComponent {
@Override
public synchronized void persist(String key, String value) {
if (!loadFromFile(_file)) {
- s_logger.error("Failed to load changes and then write to them");
+ logger.error("Failed to load changes and then write to them");
}
_properties.setProperty(key, value);
FileOutputStream output = null;
@@ -59,7 +60,7 @@ public class PropertiesStorage implements StorageComponent {
output.flush();
output.close();
} catch (IOException e) {
- s_logger.error("Uh-oh: ", e);
+ logger.error("Uh-oh: ", e);
} finally {
IOUtils.closeQuietly(output);
}
@@ -70,10 +71,10 @@ public class PropertiesStorage implements StorageComponent {
PropertiesUtil.loadFromFile(_properties, file);
_file = file;
} catch (FileNotFoundException e) {
- s_logger.error("How did we get here? ", e);
+ logger.error("How did we get here? ", e);
return false;
} catch (IOException e) {
- s_logger.error("IOException: ", e);
+ logger.error("IOException: ", e);
return false;
}
return true;
@@ -92,14 +93,12 @@ public class PropertiesStorage implements StorageComponent {
file = new File(path);
try {
if (!file.createNewFile()) {
- s_logger.error(String.format("Unable to create _file: %s", file.getAbsolutePath()));
+ logger.error("Unable to create _file: {}", file.getAbsolutePath());
return false;
}
} catch (IOException e) {
- s_logger.error(String.format("Unable to create file: %s", file.getAbsolutePath()));
- if (s_logger.isDebugEnabled()) {
- s_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/dhcp/DhcpProtocolParserServer.java b/agent/src/main/java/com/cloud/agent/dhcp/DhcpProtocolParserServer.java
index 0ee9fd6860d..00488f94382 100644
--- a/agent/src/main/java/com/cloud/agent/dhcp/DhcpProtocolParserServer.java
+++ b/agent/src/main/java/com/cloud/agent/dhcp/DhcpProtocolParserServer.java
@@ -25,12 +25,13 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import org.apache.log4j.Logger;
import com.cloud.utils.concurrency.NamedThreadFactory;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
public class DhcpProtocolParserServer extends Thread {
- private static final Logger s_logger = Logger.getLogger(DhcpProtocolParserServer.class);;
+ protected Logger logger = LogManager.getLogger(DhcpProtocolParserServer.class);;
protected ExecutorService _executor;
private int dhcpServerPort = 67;
private int bufferSize = 300;
@@ -54,7 +55,7 @@ public class DhcpProtocolParserServer extends Thread {
dhcpSocket.receive(dgp);
}
} catch (IOException e) {
- s_logger.debug(e.getMessage());
+ logger.debug(e.getMessage());
}
}
}
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 b155cb725b1..54fdde3d3d2 100644
--- a/agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java
+++ b/agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java
@@ -22,14 +22,15 @@ import java.util.Map;
import java.util.Random;
import java.util.Set;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VirtualMachine.State;
public class MockVmMgr implements VmMgr {
- private static final Logger s_logger = Logger.getLogger(MockVmMgr.class);
+ protected Logger logger = LogManager.getLogger(getClass());
private static final int DEFAULT_DOM0_MEM_MB = 128;
private static final Random randSeed = new Random();
@@ -56,14 +57,14 @@ public class MockVmMgr implements VmMgr {
public String startVM(String vmName, String vnetId, String gateway, String dns, String privateIP, String privateMac, String privateMask, String publicIP,
String publicMac, String publicMask, int cpuCount, int cpuUtilization, long ramSize, String localPath, String vncPassword) {
- if (s_logger.isInfoEnabled()) {
+ if (logger.isInfoEnabled()) {
StringBuffer sb = new StringBuffer();
sb.append("Start VM. name: " + vmName + ", vnet: " + vnetId + ", dns: " + dns);
sb.append(", privateIP: " + privateIP + ", privateMac: " + privateMac + ", privateMask: " + privateMask);
sb.append(", publicIP: " + publicIP + ", publicMac: " + publicMac + ", publicMask: " + publicMask);
sb.append(", cpu count: " + cpuCount + ", cpuUtilization: " + cpuUtilization + ", ram : " + ramSize);
sb.append(", localPath: " + localPath);
- s_logger.info(sb.toString());
+ logger.info(sb.toString());
}
synchronized (this) {
@@ -86,8 +87,7 @@ public class MockVmMgr implements VmMgr {
@Override
public String stopVM(String vmName, boolean force) {
- if (s_logger.isInfoEnabled())
- s_logger.info("Stop VM. name: " + vmName);
+ logger.info("Stop VM. name: {}", vmName);
synchronized (this) {
MockVm vm = vms.get(vmName);
@@ -102,8 +102,7 @@ public class MockVmMgr implements VmMgr {
@Override
public String rebootVM(String vmName) {
- if (s_logger.isInfoEnabled())
- s_logger.info("Reboot VM. name: " + vmName);
+ logger.info("Reboot VM. name: {}", vmName);
synchronized (this) {
MockVm vm = vms.get(vmName);
@@ -115,8 +114,7 @@ public class MockVmMgr implements VmMgr {
@Override
public boolean migrate(String vmName, String params) {
- if (s_logger.isInfoEnabled())
- s_logger.info("Migrate VM. name: " + vmName);
+ logger.info("Migrate VM. name: {}", vmName);
synchronized (this) {
MockVm vm = vms.get(vmName);
@@ -258,13 +256,13 @@ public class MockVmMgr implements VmMgr {
vm = vms.get(vmName);
if (vm == null) {
if (ramSize > getHostFreeMemory()) {
- s_logger.debug("host is out of memory");
+ logger.debug("host is out of memory");
throw new CloudRuntimeException("Host is out of Memory");
}
int vncPort = allocVncPort();
if (vncPort < 0) {
- s_logger.debug("Unable to allocate VNC port");
+ logger.debug("Unable to allocate VNC port");
throw new CloudRuntimeException("Unable to allocate vnc port");
}
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 cc0acfd18d3..c781c07c227 100644
--- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
+++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
@@ -516,6 +516,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
*/
@@ -803,12 +804,26 @@ public class AgentProperties{
*/
public static final Property KEYSTORE_PASSPHRASE = new Property<>(KeyStoreUtils.KS_PASSPHRASE_PROPERTY, null, String.class);
+ /**
+ * Implicit host tags
+ * Data type: String.
+ * Default value: null
+ */
+ public static final Property HOST_TAGS = new Property<>("host.tags", null, String.class);
+
+ /**
+ * Timeout for SSL handshake in seconds
+ * Data type: Integer.
+ * Default value: null
+ */
+ public static final Property SSL_HANDSHAKE_TIMEOUT = new Property<>("ssl.handshake.timeout", null, Integer.class);
+
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 602aa1efcb0..b28018fcd94 100644
--- a/agent/src/main/java/com/cloud/agent/properties/AgentPropertiesFileHandler.java
+++ b/agent/src/main/java/com/cloud/agent/properties/AgentPropertiesFileHandler.java
@@ -22,7 +22,8 @@ import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.IntegerConverter;
import org.apache.commons.beanutils.converters.LongConverter;
import org.apache.commons.lang3.StringUtils;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
/**
* This class provides a facility to read the agent's properties file and get
@@ -31,7 +32,7 @@ import org.apache.log4j.Logger;
*/
public class AgentPropertiesFileHandler {
- private static final Logger logger = Logger.getLogger(AgentPropertiesFileHandler.class);
+ protected static Logger LOGGER = LogManager.getLogger(AgentPropertiesFileHandler.class);
/**
* This method reads the property in the agent.properties file.
@@ -47,7 +48,7 @@ public class AgentPropertiesFileHandler {
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;
}
@@ -55,7 +56,7 @@ public class AgentPropertiesFileHandler {
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;
}
@@ -67,11 +68,11 @@ public class AgentPropertiesFileHandler {
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/consoleproxy/ConsoleProxyResource.java b/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java
index 5412c347012..ccd0d976e58 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
@@ -34,7 +34,6 @@ import javax.naming.ConfigurationException;
import com.cloud.agent.api.proxy.AllowConsoleAccessCommand;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
-import org.apache.log4j.Logger;
import com.cloud.agent.Agent.ExitStatus;
import com.cloud.agent.api.AgentControlAnswer;
@@ -81,7 +80,6 @@ import com.google.gson.Gson;
*
*/
public class ConsoleProxyResource extends ServerResourceBase implements ServerResource {
- static final Logger s_logger = Logger.getLogger(ConsoleProxyResource.class);
private final Properties properties = new Properties();
private Thread consoleProxyMain = null;
@@ -101,7 +99,7 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
} else if (cmd instanceof WatchConsoleProxyLoadCommand) {
return execute((WatchConsoleProxyLoadCommand)cmd);
} else if (cmd instanceof ReadyCommand) {
- s_logger.info("Receive ReadyCommand, response with ReadyAnswer");
+ logger.info("Receive ReadyCommand, response with ReadyAnswer");
return new ReadyAnswer((ReadyCommand)cmd);
} else if (cmd instanceof CheckHealthCommand) {
return new CheckHealthAnswer((CheckHealthCommand)cmd, true);
@@ -123,13 +121,13 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
return new Answer(cmd);
} catch (SecurityException | NoSuchMethodException | ClassNotFoundException | InvocationTargetException | IllegalAccessException e) {
String errorMsg = "Unable to add allowed session due to: " + e.getMessage();
- s_logger.error(errorMsg, e);
+ logger.error(errorMsg, e);
return new Answer(cmd, false, errorMsg);
}
}
private Answer execute(StartConsoleProxyAgentHttpHandlerCommand cmd) {
- s_logger.info("Invoke launchConsoleProxy() in responding to StartConsoleProxyAgentHttpHandlerCommand");
+ logger.info("Invoke launchConsoleProxy() in responding to StartConsoleProxyAgentHttpHandlerCommand");
launchConsoleProxy(cmd.getKeystoreBits(), cmd.getKeystorePassword(), cmd.getEncryptorPassword(), cmd.isSourceIpCheckEnabled());
return new Answer(cmd);
}
@@ -140,7 +138,7 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
{
out.write("0");
} catch (IOException e) {
- s_logger.warn("Unable to disable rp_filter");
+ logger.warn("Unable to disable rp_filter");
}
}
@@ -177,12 +175,12 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
try {
is.close();
} catch (final IOException e) {
- s_logger.warn("Exception when closing , console proxy address : " + proxyManagementIp);
+ logger.warn("Exception when closing , console proxy address : {}", proxyManagementIp);
success = false;
}
}
} catch (final IOException e) {
- s_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;
}
@@ -227,14 +225,14 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
if (eth1Ip != null) {
params.put("private.network.device", "eth1");
} else {
- s_logger.info("eth1ip parameter has not been configured, assuming that we are not inside a system vm");
+ logger.info("eth1ip parameter has not been configured, assuming that we are not inside a system vm");
}
String eth2ip = (String)params.get("eth2ip");
if (eth2ip != null) {
params.put("public.network.device", "eth2");
} else {
- s_logger.info("eth2ip parameter is not found, assuming that we are not inside a system vm");
+ logger.info("eth2ip parameter is not found, assuming that we are not inside a system vm");
}
super.configure(name, params);
@@ -262,7 +260,7 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
}
String internalDns1 = (String) params.get("internaldns1");
if (internalDns1 == null) {
- s_logger.warn("No DNS entry found during configuration of ConsoleProxy");
+ logger.warn("No DNS entry found during configuration of ConsoleProxy");
} else {
addRouteToInternalIpOrCidr(localGateway, eth1Ip, eth1Mask, internalDns1);
}
@@ -280,20 +278,19 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
disableRpFilter();
}
- if (s_logger.isInfoEnabled())
- s_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) {
- s_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) {
- s_logger.debug("addRouteToInternalIp: destIp is null");
+ logger.debug("addRouteToInternalIp: destIp is null");
return;
}
if (!NetUtils.isValidIp4(destIpOrCidr) && !NetUtils.isValidIp4Cidr(destIpOrCidr)) {
- s_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;
@@ -301,27 +298,27 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
if (eth1ip != null && eth1mask != null) {
inSameSubnet = NetUtils.sameSubnet(eth1ip, destIpOrCidr, eth1mask);
} else {
- s_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) {
- s_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", s_logger);
+ Script command = new Script("/bin/bash", logger);
command.add("-c");
command.add("ip route delete " + destIpOrCidr);
command.execute();
- command = new Script("/bin/bash", s_logger);
+ command = new Script("/bin/bash", logger);
command.add("-c");
command.add("ip route add " + destIpOrCidr + " via " + localgw);
String result = command.execute();
if (result != null) {
- s_logger.warn("Error in configuring route to internal ip err=" + result);
+ logger.warn("Error in configuring route to internal ip err={}", result);
} else {
- s_logger.debug("addRouteToInternalIp: added route to internal ip=" + destIpOrCidr + " via " + localgw);
+ logger.debug("addRouteToInternalIp: added route to internal ip={} via {}", destIpOrCidr, localgw);
}
}
@@ -332,36 +329,36 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
private void launchConsoleProxy(final byte[] ksBits, final String ksPassword, final String encryptorPassword, final Boolean isSourceIpCheckEnabled) {
final Object resource = this;
- s_logger.info("Building class loader for com.cloud.consoleproxy.ConsoleProxy");
+ logger.info("Building class loader for com.cloud.consoleproxy.ConsoleProxy");
if (consoleProxyMain == null) {
- s_logger.info("Running com.cloud.consoleproxy.ConsoleProxy with encryptor password=" + encryptorPassword);
+ logger.info("Running com.cloud.consoleproxy.ConsoleProxy with encryptor password={}", encryptorPassword);
consoleProxyMain = new Thread(new ManagedContextRunnable() {
@Override
protected void runInContext() {
try {
Class> consoleProxyClazz = Class.forName("com.cloud.consoleproxy.ConsoleProxy");
try {
- s_logger.info("Invoke startWithContext()");
+ logger.info("Invoke startWithContext()");
Method method = consoleProxyClazz.getMethod("startWithContext", Properties.class, Object.class, byte[].class, String.class, String.class, Boolean.class);
method.invoke(null, properties, resource, ksBits, ksPassword, encryptorPassword, isSourceIpCheckEnabled);
} catch (SecurityException e) {
- s_logger.error("Unable to launch console proxy due to SecurityException", e);
+ logger.error("Unable to launch console proxy due to SecurityException", e);
System.exit(ExitStatus.Error.value());
} catch (NoSuchMethodException e) {
- s_logger.error("Unable to launch console proxy due to NoSuchMethodException", e);
+ logger.error("Unable to launch console proxy due to NoSuchMethodException", e);
System.exit(ExitStatus.Error.value());
} catch (IllegalArgumentException e) {
- s_logger.error("Unable to launch console proxy due to IllegalArgumentException", e);
+ logger.error("Unable to launch console proxy due to IllegalArgumentException", e);
System.exit(ExitStatus.Error.value());
} catch (IllegalAccessException e) {
- s_logger.error("Unable to launch console proxy due to IllegalAccessException", e);
+ logger.error("Unable to launch console proxy due to IllegalAccessException", e);
System.exit(ExitStatus.Error.value());
} catch (InvocationTargetException e) {
- s_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) {
- s_logger.error("Unable to launch console proxy due to ClassNotFoundException");
+ logger.error("Unable to launch console proxy due to ClassNotFoundException");
System.exit(ExitStatus.Error.value());
}
}
@@ -369,7 +366,7 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
consoleProxyMain.setDaemon(true);
consoleProxyMain.start();
} else {
- s_logger.info("com.cloud.consoleproxy.ConsoleProxy is already running");
+ logger.info("com.cloud.consoleproxy.ConsoleProxy is already running");
try {
Class> consoleProxyClazz = Class.forName("com.cloud.consoleproxy.ConsoleProxy");
@@ -378,22 +375,22 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
methodSetup = consoleProxyClazz.getMethod("setIsSourceIpCheckEnabled", Boolean.class);
methodSetup.invoke(null, isSourceIpCheckEnabled);
} catch (SecurityException e) {
- s_logger.error("Unable to launch console proxy due to SecurityException", e);
+ logger.error("Unable to launch console proxy due to SecurityException", e);
System.exit(ExitStatus.Error.value());
} catch (NoSuchMethodException e) {
- s_logger.error("Unable to launch console proxy due to NoSuchMethodException", e);
+ logger.error("Unable to launch console proxy due to NoSuchMethodException", e);
System.exit(ExitStatus.Error.value());
} catch (IllegalArgumentException e) {
- s_logger.error("Unable to launch console proxy due to IllegalArgumentException", e);
+ logger.error("Unable to launch console proxy due to IllegalArgumentException", e);
System.exit(ExitStatus.Error.value());
} catch (IllegalAccessException e) {
- s_logger.error("Unable to launch console proxy due to IllegalAccessException", e);
+ logger.error("Unable to launch console proxy due to IllegalAccessException", e);
System.exit(ExitStatus.Error.value());
} catch (InvocationTargetException e) {
- s_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) {
- s_logger.error("Unable to launch console proxy due to ClassNotFoundException", e);
+ logger.error("Unable to launch console proxy due to ClassNotFoundException", e);
System.exit(ExitStatus.Error.value());
}
}
@@ -420,10 +417,10 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
result.setTunnelUrl(authAnswer.getTunnelUrl());
result.setTunnelSession(authAnswer.getTunnelSession());
} else {
- s_logger.error("Authentication failed for vm: " + vmId + " with sid: " + sid);
+ logger.error("Authentication failed for vm: {} with sid: {}", vmId, sid);
}
} catch (AgentControlChannelException e) {
- s_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);
@@ -433,18 +430,15 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
ConsoleProxyLoadReportCommand cmd = new ConsoleProxyLoadReportCommand(proxyVmId, gsonLoadInfo);
try {
getAgentControl().postRequest(cmd);
-
- if (s_logger.isDebugEnabled())
- s_logger.debug("Report proxy load info, proxy : " + proxyVmId + ", load: " + gsonLoadInfo);
+ logger.debug("Report proxy load info, proxy : {}, load: {}", proxyVmId, gsonLoadInfo);
} catch (AgentControlChannelException e) {
- s_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 (s_logger.isDebugEnabled())
- s_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
@@ -452,7 +446,7 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
try {
addRouteToInternalIpOrCidr(localGateway, eth1Ip, eth1Mask, address);
} catch (Throwable e) {
- s_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 f7151779f58..6d9758cc3dc 100644
--- a/agent/src/test/java/com/cloud/agent/AgentShellTest.java
+++ b/agent/src/test/java/com/cloud/agent/AgentShellTest.java
@@ -350,4 +350,23 @@ public class AgentShellTest {
Mockito.verify(agentShellSpy).setHosts(expected);
}
+
+ @Test
+ public void updateAndGetConnectedHost() {
+ String expected = "test";
+
+ AgentShell shell = new AgentShell();
+ shell.setHosts("test");
+ shell.getNextHost();
+ shell.updateConnectedHost();
+
+ Assert.assertEquals(expected, shell.getConnectedHost());
+ }
+
+ @Test
+ public void testGetSslHandshakeTimeout() {
+ Integer expected = 1;
+ agentPropertiesFileHandlerMocked.when(() -> AgentPropertiesFileHandler.getPropertyValue(Mockito.eq(AgentProperties.SSL_HANDSHAKE_TIMEOUT))).thenReturn(expected);
+ Assert.assertEquals(expected, agentShellSpy.getSslHandshakeTimeout());
+ }
}
diff --git a/agent/src/test/java/com/cloud/agent/AgentTest.java b/agent/src/test/java/com/cloud/agent/AgentTest.java
new file mode 100644
index 00000000000..65dc030ebd7
--- /dev/null
+++ b/agent/src/test/java/com/cloud/agent/AgentTest.java
@@ -0,0 +1,257 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.logging.log4j.Logger;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import com.cloud.resource.ServerResource;
+import com.cloud.utils.backoff.impl.ConstantTimeBackoff;
+import com.cloud.utils.nio.Link;
+import com.cloud.utils.nio.NioConnection;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AgentTest {
+ Agent agent;
+ private AgentShell shell;
+ private ServerResource serverResource;
+ private Logger logger;
+
+ @Before
+ public void setUp() throws ConfigurationException {
+ shell = mock(AgentShell.class);
+ serverResource = mock(ServerResource.class);
+ doReturn(true).when(serverResource).configure(any(), any());
+ doReturn(1).when(shell).getWorkers();
+ doReturn(1).when(shell).getPingRetries();
+ agent = new Agent(shell, 1, serverResource);
+ logger = mock(Logger.class);
+ ReflectionTestUtils.setField(agent, "logger", logger);
+ }
+
+ @Test
+ public void testGetLinkLogNullLinkReturnsEmptyString() {
+ Link link = null;
+ String result = agent.getLinkLog(link);
+ assertEquals("", result);
+ }
+
+ @Test
+ public void testGetLinkLogLinkWithTraceEnabledReturnsLinkLogWithHashCode() {
+ Link link = mock(Link.class);
+ InetSocketAddress socketAddress = new InetSocketAddress("192.168.1.100", 1111);
+ when(link.getSocketAddress()).thenReturn(socketAddress);
+ when(logger.isTraceEnabled()).thenReturn(true);
+
+ String result = agent.getLinkLog(link);
+ System.out.println(result);
+ assertTrue(result.startsWith(System.identityHashCode(link) + "-"));
+ assertTrue(result.contains("192.168.1.100"));
+ }
+
+ @Test
+ public void testGetAgentNameWhenServerResourceIsNull() {
+ ReflectionTestUtils.setField(agent, "serverResource", null);
+ assertEquals("Agent", agent.getAgentName());
+ }
+
+ @Test
+ public void testGetAgentNameWhenAppendAgentNameIsTrue() {
+ when(serverResource.isAppendAgentNameToLogs()).thenReturn(true);
+ when(serverResource.getName()).thenReturn("TestAgent");
+
+ String agentName = agent.getAgentName();
+ assertEquals("TestAgent", agentName);
+ }
+
+ @Test
+ public void testGetAgentNameWhenAppendAgentNameIsFalse() {
+ when(serverResource.isAppendAgentNameToLogs()).thenReturn(false);
+
+ String agentName = agent.getAgentName();
+ assertEquals("Agent", agentName);
+ }
+
+ @Test
+ public void testAgentInitialization() {
+ Runtime.getRuntime().removeShutdownHook(agent.shutdownThread);
+ when(shell.getPingRetries()).thenReturn(3);
+ when(shell.getWorkers()).thenReturn(5);
+ agent.setupShutdownHookAndInitExecutors();
+ assertNotNull(agent.selfTaskExecutor);
+ assertNotNull(agent.outRequestHandler);
+ assertNotNull(agent.requestHandler);
+ }
+
+ @Test
+ public void testAgentShutdownHookAdded() {
+ Runtime.getRuntime().removeShutdownHook(agent.shutdownThread);
+ agent.setupShutdownHookAndInitExecutors();
+ verify(logger).trace("Adding shutdown hook");
+ }
+
+ @Test
+ public void testGetResourceGuidValidGuidAndResourceName() {
+ when(shell.getGuid()).thenReturn("12345");
+ String result = agent.getResourceGuid();
+ assertTrue(result.startsWith("12345-" + ServerResource.class.getSimpleName()));
+ }
+
+ @Test
+ public void testGetZoneReturnsValidZone() {
+ when(shell.getZone()).thenReturn("ZoneA");
+ String result = agent.getZone();
+ assertEquals("ZoneA", result);
+ }
+
+ @Test
+ public void testGetPodReturnsValidPod() {
+ when(shell.getPod()).thenReturn("PodA");
+ String result = agent.getPod();
+ assertEquals("PodA", result);
+ }
+
+ @Test
+ public void testSetLinkAssignsLink() {
+ Link mockLink = mock(Link.class);
+ agent.setLink(mockLink);
+ assertEquals(mockLink, agent.link);
+ }
+
+ @Test
+ public void testGetResourceReturnsServerResource() {
+ ServerResource mockResource = mock(ServerResource.class);
+ ReflectionTestUtils.setField(agent, "serverResource", mockResource);
+ ServerResource result = agent.getResource();
+ assertSame(mockResource, result);
+ }
+
+ @Test
+ public void testGetResourceName() {
+ String result = agent.getResourceName();
+ assertTrue(result.startsWith(ServerResource.class.getSimpleName()));
+ }
+
+ @Test
+ public void testUpdateLastPingResponseTimeUpdatesCurrentTime() {
+ long beforeUpdate = System.currentTimeMillis();
+ agent.updateLastPingResponseTime();
+ long updatedTime = agent.lastPingResponseTime.get();
+ assertTrue(updatedTime >= beforeUpdate);
+ assertTrue(updatedTime <= System.currentTimeMillis());
+ }
+
+ @Test
+ public void testGetNextSequenceIncrementsSequence() {
+ long initialSequence = agent.getNextSequence();
+ long nextSequence = agent.getNextSequence();
+ assertEquals(initialSequence + 1, nextSequence);
+ long thirdSequence = agent.getNextSequence();
+ assertEquals(nextSequence + 1, thirdSequence);
+ }
+
+ @Test
+ public void testRegisterControlListenerAddsListener() {
+ IAgentControlListener listener = mock(IAgentControlListener.class);
+ agent.registerControlListener(listener);
+ assertTrue(agent.controlListeners.contains(listener));
+ }
+
+ @Test
+ public void testUnregisterControlListenerRemovesListener() {
+ IAgentControlListener listener = mock(IAgentControlListener.class);
+ agent.registerControlListener(listener);
+ assertTrue(agent.controlListeners.contains(listener));
+ agent.unregisterControlListener(listener);
+ assertFalse(agent.controlListeners.contains(listener));
+ }
+
+ @Test
+ public void testCloseAndTerminateLinkLinkIsNullDoesNothing() {
+ agent.closeAndTerminateLink(null);
+ }
+
+ @Test
+ public void testCloseAndTerminateLinkValidLinkCallsCloseAndTerminate() {
+ Link mockLink = mock(Link.class);
+ agent.closeAndTerminateLink(mockLink);
+ verify(mockLink).close();
+ verify(mockLink).terminated();
+ }
+
+ @Test
+ public void testStopAndCleanupConnectionConnectionIsNullDoesNothing() {
+ agent.connection = null;
+ agent.stopAndCleanupConnection(false);
+ }
+
+ @Test
+ public void testStopAndCleanupConnectionValidConnectionNoWaitStopsAndCleansUp() throws IOException {
+ NioConnection mockConnection = mock(NioConnection.class);
+ agent.connection = mockConnection;
+ agent.stopAndCleanupConnection(false);
+ verify(mockConnection).stop();
+ verify(mockConnection).cleanUp();
+ }
+
+ @Test
+ public void testStopAndCleanupConnectionCleanupThrowsIOExceptionLogsWarning() throws IOException {
+ NioConnection mockConnection = mock(NioConnection.class);
+ agent.connection = mockConnection;
+ doThrow(new IOException("Cleanup failed")).when(mockConnection).cleanUp();
+ agent.stopAndCleanupConnection(false);
+ verify(mockConnection).stop();
+ verify(logger).warn(eq("Fail to clean up old connection. {}"), any(IOException.class));
+ }
+
+ @Test
+ public void testStopAndCleanupConnectionValidConnectionWaitForStopWaitsForStartupToStop() throws IOException {
+ NioConnection mockConnection = mock(NioConnection.class);
+ ConstantTimeBackoff mockBackoff = mock(ConstantTimeBackoff.class);
+ mockBackoff.setTimeToWait(0);
+ agent.connection = mockConnection;
+ when(shell.getBackoffAlgorithm()).thenReturn(mockBackoff);
+ when(mockConnection.isStartup()).thenReturn(true, true, false);
+ agent.stopAndCleanupConnection(true);
+ verify(mockConnection).stop();
+ verify(mockConnection).cleanUp();
+ verify(mockBackoff, times(3)).waitBeforeRetry();
+ }
+}
diff --git a/agent/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/agent/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
deleted file mode 100644
index 1f0955d450f..00000000000
--- a/agent/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
+++ /dev/null
@@ -1 +0,0 @@
-mock-maker-inline
diff --git a/api/pom.xml b/api/pom.xml
index 737f5768799..377b6e6e341 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -24,7 +24,7 @@
org.apache.cloudstack
cloudstack
- 4.19.4.0-SNAPSHOT
+ 4.20.3.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 c873139099c..eb979c0060b 100644
--- a/api/src/main/java/com/cloud/agent/api/Command.java
+++ b/api/src/main/java/com/cloud/agent/api/Command.java
@@ -20,6 +20,8 @@ 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;
/**
* implemented by classes that extends the Command class. Command specifies
@@ -27,6 +29,8 @@ import com.cloud.agent.api.LogLevel.Log4jLevel;
*/
public abstract class Command {
+ protected transient Logger logger = LogManager.getLogger(getClass());
+
public static enum OnError {
Continue, Stop
}
diff --git a/api/src/main/java/com/cloud/agent/api/LogLevel.java b/api/src/main/java/com/cloud/agent/api/LogLevel.java
index a8da272f39f..136cb6d7228 100644
--- a/api/src/main/java/com/cloud/agent/api/LogLevel.java
+++ b/api/src/main/java/com/cloud/agent/api/LogLevel.java
@@ -23,8 +23,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Logger;
/**
*/
@@ -41,7 +41,7 @@ public @interface LogLevel {
}
public boolean enabled(Logger logger) {
- return _level != Level.OFF && logger.isEnabledFor(_level);
+ return _level != Level.OFF && logger.isEnabled(_level);
}
}
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 d4daf0e4270..6396e3deb72 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
@@ -39,7 +39,8 @@ import org.apache.cloudstack.utils.security.ParserUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -63,7 +64,7 @@ import com.cloud.utils.compression.CompressionUtil;
import com.cloud.utils.exception.CloudRuntimeException;
public class OVFHelper {
- private static final Logger s_logger = Logger.getLogger(OVFHelper.class);
+ protected Logger logger = LogManager.getLogger(getClass());
private final OVFParser ovfParser;
@@ -118,7 +119,7 @@ public class OVFHelper {
boolean password = StringUtils.isNotBlank(passStr) && passStr.equalsIgnoreCase("true");
String label = ovfParser.getChildNodeValue(node, "Label");
String description = ovfParser.getChildNodeValue(node, "Description");
- s_logger.debug("Creating OVF property index " + index + (category == null ? "" : " for category " + category)
+ logger.debug("Creating OVF property index " + index + (category == null ? "" : " for category " + category)
+ " with key = " + key);
return new OVFPropertyTO(key, type, value, qualifiers, userConfigurable,
label, description, password, index, category);
@@ -151,7 +152,7 @@ public class OVFHelper {
if (child.getNodeName().equalsIgnoreCase("Category") ||
child.getNodeName().endsWith(":Category")) {
lastCategoryFound = child.getTextContent();
- s_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);
@@ -249,13 +250,13 @@ public class OVFHelper {
int diskNumber = 0;
for (OVFVirtualHardwareItemTO diskItem : diskHardwareItems) {
if (StringUtils.isBlank(diskItem.getHostResource())) {
- s_logger.error("Missing disk information for hardware item " + diskItem.getElementName() + " " + diskItem.getInstanceId());
+ logger.error("Missing disk information for hardware item " + diskItem.getElementName() + " " + diskItem.getInstanceId());
continue;
}
String diskId = extractDiskIdFromDiskHostResource(diskItem.getHostResource());
OVFDisk diskDefinition = getDiskDefinitionFromDiskId(diskId, disks);
if (diskDefinition == null) {
- s_logger.error("Missing disk definition for disk ID " + diskId);
+ logger.error("Missing disk definition for disk ID " + diskId);
}
OVFFile fileDefinition = getFileDefinitionFromDiskDefinition(diskDefinition._fileRef, files);
DatadiskTO datadiskTO = generateDiskTO(fileDefinition, diskDefinition, ovfParentPath, diskNumber, diskItem);
@@ -277,7 +278,7 @@ public class OVFHelper {
if (StringUtils.isNotBlank(path)) {
File f = new File(path);
if (!f.exists() || f.isDirectory()) {
- s_logger.error("One of the attached disk or iso does not exists " + path);
+ logger.error("One of the attached disk or iso does not exists " + path);
throw new InternalErrorException("One of the attached disk or iso as stated on OVF does not exists " + path);
}
}
@@ -333,8 +334,8 @@ public class OVFHelper {
od._controller = getControllerType(items, od._diskId);
vd.add(od);
}
- if (s_logger.isTraceEnabled()) {
- s_logger.trace(String.format("found %d disk definitions",vd.size()));
+ if (logger.isTraceEnabled()) {
+ logger.trace(String.format("found %d disk definitions",vd.size()));
}
return vd;
}
@@ -365,8 +366,8 @@ public class OVFHelper {
vf.add(of);
}
}
- if (s_logger.isTraceEnabled()) {
- s_logger.trace(String.format("found %d file definitions in %s",vf.size(), ovfFile.getPath()));
+ if (logger.isTraceEnabled()) {
+ logger.trace(String.format("found %d file definitions in %s",vf.size(), ovfFile.getPath()));
}
return vf;
}
@@ -461,7 +462,7 @@ public class OVFHelper {
Element disk = (Element)disks.item(i);
String fileRef = ovfParser.getNodeAttribute(disk, "fileRef");
if (keepfile == null) {
- s_logger.info("FATAL: OVA format error");
+ logger.info("FATAL: OVA format error");
} else if (keepfile.equals(fileRef)) {
keepdisk = ovfParser.getNodeAttribute(disk, "diskId");
} else {
@@ -505,7 +506,7 @@ public class OVFHelper {
outfile.write(writer.toString());
outfile.close();
} catch (IOException | TransformerException e) {
- s_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);
}
}
@@ -521,8 +522,8 @@ public class OVFHelper {
public List getNetPrerequisitesFromDocument(Document doc) throws InternalErrorException {
if (doc == null) {
- if (s_logger.isTraceEnabled()) {
- s_logger.trace("no document to parse; returning no prerequisite networks");
+ if (logger.isTraceEnabled()) {
+ logger.trace("no document to parse; returning no prerequisite networks");
}
return Collections.emptyList();
}
@@ -539,8 +540,8 @@ public class OVFHelper {
private void matchNicsToNets(Map nets, Node systemElement) {
final DocumentTraversal traversal = (DocumentTraversal) systemElement;
final NodeIterator iterator = traversal.createNodeIterator(systemElement, NodeFilter.SHOW_ELEMENT, null, true);
- if (s_logger.isTraceEnabled()) {
- s_logger.trace(String.format("starting out with %d network-prerequisites, parsing hardware",nets.size()));
+ if (logger.isTraceEnabled()) {
+ logger.trace(String.format("starting out with %d network-prerequisites, parsing hardware",nets.size()));
}
int nicCount = 0;
for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
@@ -549,8 +550,8 @@ public class OVFHelper {
nicCount++;
String name = e.getTextContent(); // should be in our nets
if(nets.get(name) == null) {
- if(s_logger.isInfoEnabled()) {
- s_logger.info(String.format("found a nic definition without a network definition byname %s, adding it to the list.", name));
+ if(logger.isInfoEnabled()) {
+ logger.info(String.format("found a nic definition without a network definition byname %s, adding it to the list.", name));
}
nets.put(name, new OVFNetworkTO());
}
@@ -560,8 +561,8 @@ public class OVFHelper {
}
}
}
- if (s_logger.isTraceEnabled()) {
- s_logger.trace(String.format("ending up with %d network-prerequisites, parsed %d nics", nets.size(), nicCount));
+ if (logger.isTraceEnabled()) {
+ logger.trace(String.format("ending up with %d network-prerequisites, parsed %d nics", nets.size(), nicCount));
}
}
@@ -584,7 +585,7 @@ public class OVFHelper {
int addressOnParent = Integer.parseInt(addressOnParentStr);
nic.setAddressOnParent(addressOnParent);
} catch (NumberFormatException e) {
- s_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);
@@ -596,7 +597,7 @@ public class OVFHelper {
int instanceId = Integer.parseInt(instanceIdStr);
nic.setInstanceID(instanceId);
} catch (NumberFormatException e) {
- s_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);
@@ -608,7 +609,7 @@ public class OVFHelper {
NodeList systemElements = ovfParser.getElementsFromOVFDocument(doc, "VirtualSystem");
if (systemElements.getLength() != 1) {
String msg = "found " + systemElements.getLength() + " system definitions in OVA, can only handle exactly one.";
- s_logger.warn(msg);
+ logger.warn(msg);
throw new InternalErrorException(msg);
}
}
@@ -629,8 +630,8 @@ public class OVFHelper {
nets.put(networkName,network);
}
- if (s_logger.isTraceEnabled()) {
- s_logger.trace(String.format("found %d networks in template", nets.size()));
+ if (logger.isTraceEnabled()) {
+ logger.trace(String.format("found %d networks in template", nets.size()));
}
return nets;
}
@@ -770,7 +771,7 @@ public class OVFHelper {
try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
- s_logger.debug("Could not parse the value: " + value + ", ignoring it");
+ logger.debug("Could not parse the value: " + value + ", ignoring it");
}
}
return null;
@@ -781,7 +782,7 @@ public class OVFHelper {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
- s_logger.debug("Could not parse the value: " + value + ", ignoring it");
+ logger.debug("Could not parse the value: " + value + ", ignoring it");
}
}
return null;
@@ -819,7 +820,7 @@ public class OVFHelper {
try {
compressedLicense = compressOVFEula(eulaLicense);
} catch (IOException e) {
- s_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 b66fbe418d7..38f478d63cf 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
@@ -27,7 +27,8 @@ import javax.xml.parsers.ParserConfigurationException;
import org.apache.cloudstack.utils.security.ParserUtils;
import org.apache.commons.lang3.StringUtils;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -36,7 +37,7 @@ import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class OVFParser {
- private static final Logger s_logger = Logger.getLogger(OVFParser.class);
+ protected Logger logger = LogManager.getLogger(getClass());
private static final String DEFAULT_OVF_SCHEMA = "http://schemas.dmtf.org/ovf/envelope/1";
private static final String VMW_SCHEMA = "http://www.vmware.com/schema/ovf";
@@ -53,7 +54,7 @@ public class OVFParser {
documentBuilderFactory.setNamespaceAware(true);
documentBuilder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
- s_logger.error("Cannot start the OVF parser: " + e.getMessage(), e);
+ logger.error("Cannot start the OVF parser: " + e.getMessage(), e);
}
}
@@ -69,7 +70,7 @@ public class OVFParser {
try {
return documentBuilder.parse(new File(ovfFilePath));
} catch (SAXException | IOException e) {
- s_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 00000000000..f7e4bfea80f
--- /dev/null
+++ b/api/src/main/java/com/cloud/agent/api/to/BucketTO.java
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent.api.to;
+
+import org.apache.cloudstack.storage.object.Bucket;
+
+public final class BucketTO {
+
+ private String name;
+
+ private String accessKey;
+
+ private String secretKey;
+
+ public BucketTO(Bucket bucket) {
+ this.name = bucket.getName();
+ this.accessKey = bucket.getAccessKey();
+ this.secretKey = bucket.getSecretKey();
+ }
+
+ public BucketTO(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getAccessKey() {
+ return this.accessKey;
+ }
+
+ public String getSecretKey() {
+ return this.secretKey;
+ }
+}
diff --git a/api/src/main/java/com/cloud/agent/api/to/FirewallRuleTO.java b/api/src/main/java/com/cloud/agent/api/to/FirewallRuleTO.java
index d08884d1cbe..25c75001a3c 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
@@ -155,9 +155,7 @@ public class FirewallRuleTO implements InternalIdentity {
rule.getIcmpType(),
rule.getIcmpCode());
this.trafficType = trafficType;
- if (FirewallRule.Purpose.Ipv6Firewall.equals(purpose)) {
- this.destCidrList = rule.getDestinationCidrList();
- }
+ this.destCidrList = rule.getDestinationCidrList();
}
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, FirewallRule.Purpose purpose, FirewallRule.TrafficType trafficType,
diff --git a/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java b/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java
index 966d24886fe..f395f26aeed 100644
--- a/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java
@@ -374,13 +374,15 @@ public class LoadBalancerTO {
public static class CounterTO implements Serializable {
private static final long serialVersionUID = 2L;
private final Long id;
+ private final String uuid;
private final String name;
private final Counter.Source source;
private final String value;
private final String provider;
- public CounterTO(Long id, String name, Counter.Source source, String value, String provider) {
+ public CounterTO(Long id, String uuid, String name, Counter.Source source, String value, String provider) {
this.id = id;
+ this.uuid = uuid;
this.name = name;
this.source = source;
this.value = value;
@@ -391,6 +393,10 @@ public class LoadBalancerTO {
return id;
}
+ public String getUuid() {
+ return uuid;
+ }
+
public String getName() {
return name;
}
@@ -411,12 +417,14 @@ public class LoadBalancerTO {
public static class ConditionTO implements Serializable {
private static final long serialVersionUID = 2L;
private final Long id;
+ private final String uuid;
private final long threshold;
private final Condition.Operator relationalOperator;
private final CounterTO counter;
- public ConditionTO(Long id, long threshold, Condition.Operator relationalOperator, CounterTO counter) {
+ public ConditionTO(Long id, String uuid, long threshold, Condition.Operator relationalOperator, CounterTO counter) {
this.id = id;
+ this.uuid = uuid;
this.threshold = threshold;
this.relationalOperator = relationalOperator;
this.counter = counter;
@@ -426,6 +434,10 @@ public class LoadBalancerTO {
return id;
}
+ public String getUuid() {
+ return uuid;
+ }
+
public long getThreshold() {
return threshold;
}
@@ -442,6 +454,7 @@ public class LoadBalancerTO {
public static class AutoScalePolicyTO implements Serializable {
private static final long serialVersionUID = 2L;
private final long id;
+ private final String uuid;
private final int duration;
private final int quietTime;
private final Date lastQuietTime;
@@ -449,8 +462,9 @@ public class LoadBalancerTO {
boolean revoked;
private final List conditions;
- public AutoScalePolicyTO(long id, int duration, int quietTime, Date lastQuietTime, AutoScalePolicy.Action action, List conditions, boolean revoked) {
+ public AutoScalePolicyTO(long id, String uuid, int duration, int quietTime, Date lastQuietTime, AutoScalePolicy.Action action, List conditions, boolean revoked) {
this.id = id;
+ this.uuid = uuid;
this.duration = duration;
this.quietTime = quietTime;
this.lastQuietTime = lastQuietTime;
@@ -463,6 +477,10 @@ public class LoadBalancerTO {
return id;
}
+ public String getUuid() {
+ return uuid;
+ }
+
public int getDuration() {
return duration;
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/NfsTO.java b/api/src/main/java/com/cloud/agent/api/to/NfsTO.java
index 0f6511e8311..eeddbf649a7 100644
--- a/api/src/main/java/com/cloud/agent/api/to/NfsTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/NfsTO.java
@@ -17,6 +17,7 @@
package com.cloud.agent.api.to;
import com.cloud.storage.DataStoreRole;
+import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
public class NfsTO implements DataStoreTO {
@@ -41,6 +42,13 @@ public class NfsTO implements DataStoreTO {
}
+ @Override
+ public String toString() {
+ return String.format("NfsTO %s",
+ ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
+ this, "uuid", "_url", "_role", "nfsVersion"));
+ }
+
@Override
public String getUrl() {
return _url;
diff --git a/api/src/main/java/com/cloud/agent/api/to/NicTO.java b/api/src/main/java/com/cloud/agent/api/to/NicTO.java
index 3a616170d7e..573363c04fb 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,9 @@ public class NicTO extends NetworkTO {
Map details;
boolean dpdkEnabled;
Integer mtu;
+ Long networkId;
+
+ String networkSegmentName;
public NicTO() {
super();
@@ -127,4 +130,20 @@ public class NicTO extends NetworkTO {
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;
+ }
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/S3TO.java b/api/src/main/java/com/cloud/agent/api/to/S3TO.java
index 233238cf793..936f8168b1e 100644
--- a/api/src/main/java/com/cloud/agent/api/to/S3TO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/S3TO.java
@@ -22,6 +22,7 @@ import com.cloud.agent.api.LogLevel;
import com.cloud.agent.api.LogLevel.Log4jLevel;
import com.cloud.storage.DataStoreRole;
import com.cloud.utils.storage.S3.ClientOptions;
+import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
public final class S3TO implements ClientOptions, DataStoreTO {
@@ -68,6 +69,13 @@ public final class S3TO implements ClientOptions, DataStoreTO {
}
+ @Override
+ public String toString() {
+ return String.format("S3TO %s",
+ ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
+ this, "id", "uuid", "bucketName"));
+ }
+
public Long getId() {
return this.id;
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/StorageFilerTO.java b/api/src/main/java/com/cloud/agent/api/to/StorageFilerTO.java
index e361e7a141f..cbdb7922eb4 100644
--- a/api/src/main/java/com/cloud/agent/api/to/StorageFilerTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/StorageFilerTO.java
@@ -19,6 +19,7 @@ package com.cloud.agent.api.to;
import com.cloud.agent.api.LogLevel;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StoragePool;
+import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
public class StorageFilerTO {
long id;
@@ -73,6 +74,6 @@ public class StorageFilerTO {
@Override
public String toString() {
- return new StringBuilder("Pool[").append(id).append("|").append(host).append(":").append(port).append("|").append(path).append("]").toString();
+ return String.format("Pool %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "uuid", "host", "port", "path"));
}
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/SwiftTO.java b/api/src/main/java/com/cloud/agent/api/to/SwiftTO.java
index b89dfea40e0..14038566fbd 100644
--- a/api/src/main/java/com/cloud/agent/api/to/SwiftTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/SwiftTO.java
@@ -18,6 +18,7 @@ package com.cloud.agent.api.to;
import com.cloud.storage.DataStoreRole;
import com.cloud.utils.SwiftUtil;
+import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
public class SwiftTO implements DataStoreTO, SwiftUtil.SwiftClientCfg {
Long id;
@@ -41,6 +42,13 @@ public class SwiftTO implements DataStoreTO, SwiftUtil.SwiftClientCfg {
this.storagePolicy = storagePolicy;
}
+ @Override
+ public String toString() {
+ return String.format("SwiftTO %s",
+ ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
+ this, "id", "account", "userName"));
+ }
+
public Long getId() {
return id;
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
index db6cba77548..6f24b1cd6ca 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
@@ -82,7 +82,10 @@ public class VirtualMachineTO {
Map guestOsDetails = new HashMap();
Map extraConfig = new HashMap<>();
+ Map networkIdToNetworkNameMap = new HashMap<>();
DeployAsIsInfoTO deployAsIsInfo;
+ String metadataManufacturer;
+ String metadataProductName;
public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader,
String os, boolean enableHA, boolean limitCpuUse, String vncPassword) {
@@ -392,6 +395,14 @@ public class VirtualMachineTO {
return extraConfig;
}
+ public Map getNetworkIdToNetworkNameMap() {
+ return networkIdToNetworkNameMap;
+ }
+
+ public void setNetworkIdToNetworkNameMap(Map networkIdToNetworkNameMap) {
+ this.networkIdToNetworkNameMap = networkIdToNetworkNameMap;
+ }
+
public String getBootType() {
return bootType;
}
@@ -420,6 +431,22 @@ public class VirtualMachineTO {
this.deployAsIsInfo = deployAsIsInfo;
}
+ public String getMetadataManufacturer() {
+ return metadataManufacturer;
+ }
+
+ public void setMetadataManufacturer(String metadataManufacturer) {
+ this.metadataManufacturer = metadataManufacturer;
+ }
+
+ public String getMetadataProductName() {
+ return metadataProductName;
+ }
+
+ public void setMetadataProductName(String metadataProductName) {
+ this.metadataProductName = metadataProductName;
+ }
+
@Override
public String toString() {
return String.format("VM {id: \"%s\", name: \"%s\", uuid: \"%s\", type: \"%s\"}", id, name, uuid, type);
diff --git a/api/src/main/java/com/cloud/bgp/ASNumber.java b/api/src/main/java/com/cloud/bgp/ASNumber.java
new file mode 100644
index 00000000000..b0e5394df75
--- /dev/null
+++ b/api/src/main/java/com/cloud/bgp/ASNumber.java
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.bgp;
+
+import org.apache.cloudstack.acl.InfrastructureEntity;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+import java.util.Date;
+
+public interface ASNumber extends InfrastructureEntity, InternalIdentity, Identity {
+
+ Long getAccountId();
+ Long getDomainId();
+ long getAsNumber();
+ long getAsNumberRangeId();
+ long getDataCenterId();
+ Date getAllocatedTime();
+ boolean isAllocated();
+ Long getNetworkId();
+ Long getVpcId();
+ Date getCreated();
+ Date getRemoved();
+}
diff --git a/api/src/main/java/com/cloud/bgp/ASNumberRange.java b/api/src/main/java/com/cloud/bgp/ASNumberRange.java
new file mode 100644
index 00000000000..ae877ee60db
--- /dev/null
+++ b/api/src/main/java/com/cloud/bgp/ASNumberRange.java
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.bgp;
+
+import org.apache.cloudstack.acl.InfrastructureEntity;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+import java.util.Date;
+
+public interface ASNumberRange extends InfrastructureEntity, InternalIdentity, Identity {
+
+ long getStartASNumber();
+ long getEndASNumber();
+ long getDataCenterId();
+ Date getCreated();
+}
diff --git a/api/src/main/java/com/cloud/bgp/BGPService.java b/api/src/main/java/com/cloud/bgp/BGPService.java
new file mode 100644
index 00000000000..61d149f2847
--- /dev/null
+++ b/api/src/main/java/com/cloud/bgp/BGPService.java
@@ -0,0 +1,44 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.bgp;
+
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.Network;
+import com.cloud.network.vpc.Vpc;
+import com.cloud.utils.Pair;
+import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
+import org.apache.cloudstack.network.BgpPeer;
+
+import java.util.List;
+
+public interface BGPService {
+
+ ASNumberRange createASNumberRange(long zoneId, long startASNumber, long endASNumber);
+ List listASNumberRanges(Long zoneId);
+ Pair, Integer> listASNumbers(ListASNumbersCmd cmd);
+ boolean allocateASNumber(long zoneId, Long asNumber, Long networkId, Long vpcId);
+ Pair releaseASNumber(long zoneId, long asNumber, boolean isReleaseNetworkDestroy);
+ boolean deleteASRange(long id);
+
+ boolean applyBgpPeers(Network network, boolean continueOnError) throws ResourceUnavailableException;
+
+ boolean applyBgpPeers(Vpc vpc, boolean continueOnError) throws ResourceUnavailableException;
+
+ List extends BgpPeer> getBgpPeersForNetwork(Network network);
+
+ List extends BgpPeer> getBgpPeersForVpc(Vpc vpc);
+}
diff --git a/api/src/main/java/com/cloud/capacity/Capacity.java b/api/src/main/java/com/cloud/capacity/Capacity.java
index 684490a605c..a4e2c2a7f05 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;
@@ -35,6 +37,11 @@ public interface Capacity extends InternalIdentity, Identity {
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);
+
public Long getHostOrPoolId();
public Long getDataCenterId();
@@ -54,4 +61,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/Resource.java b/api/src/main/java/com/cloud/configuration/Resource.java
index 32db2fcafea..bf8fca9d905 100644
--- a/api/src/main/java/com/cloud/configuration/Resource.java
+++ b/api/src/main/java/com/cloud/configuration/Resource.java
@@ -85,5 +85,6 @@ public interface Resource {
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 00000000000..3016e542db6
--- /dev/null
+++ b/api/src/main/java/com/cloud/cpu/CPU.java
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.cpu;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class CPU {
+ public enum CPUArch {
+ x86("i686", 32),
+ amd64("x86_64", 64),
+ arm64("aarch64", 64);
+
+ private final String type;
+ private final int bits;
+
+ CPUArch(String type, int bits) {
+ this.type = type;
+ this.bits = bits;
+ }
+
+ public static CPUArch getDefault() {
+ return amd64;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public int getBits() {
+ return bits;
+ }
+
+ public static CPUArch fromType(String type) {
+ if (StringUtils.isBlank(type)) {
+ return getDefault();
+ }
+ for (CPUArch arch : values()) {
+ if (arch.type.equals(type)) {
+ return arch;
+ }
+ }
+ throw new IllegalArgumentException("Unsupported arch type: " + type);
+ }
+
+ public static String getTypesAsCSV() {
+ StringBuilder sb = new StringBuilder();
+ for (CPUArch arch : values()) {
+ sb.append(arch.getType()).append(",");
+ }
+ if (sb.length() > 0) {
+ sb.setLength(sb.length() - 1);
+ }
+ return sb.toString();
+ }
+ }
+}
diff --git a/api/src/main/java/com/cloud/dc/DedicatedResources.java b/api/src/main/java/com/cloud/dc/DedicatedResources.java
index 63188ca0b0e..23e6cc88a1e 100644
--- a/api/src/main/java/com/cloud/dc/DedicatedResources.java
+++ b/api/src/main/java/com/cloud/dc/DedicatedResources.java
@@ -21,6 +21,10 @@ import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
public interface DedicatedResources extends InfrastructureEntity, InternalIdentity, Identity {
+ enum Type {
+ Zone, Pod, Cluster, Host
+ }
+
@Override
long getId();
diff --git a/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java b/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java
index a668b79187d..2697311d2b9 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/volume allocation. The value can be 'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit', or 'firstfitleastconsumed'.",
+ true,
+ ConfigKey.Scope.Global, null, null, null, null, null,
+ ConfigKey.Kind.Select,
+ "random,firstfit,userdispersing,userconcentratedpod_random,userconcentratedpod_firstfit,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 e9f706ac1ce..354f9cfaac5 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.Collection;
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;
@@ -75,7 +79,7 @@ public interface DeploymentPlanner extends Adapter {
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 interface DeploymentPlanner extends Adapter {
}
}
+ 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 interface DeploymentPlanner extends Adapter {
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 496d9f5b689..81ed185dae5 100644
--- a/api/src/main/java/com/cloud/event/EventTypes.java
+++ b/api/src/main/java/com/cloud/event/EventTypes.java
@@ -28,8 +28,12 @@ import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.config.Configuration;
+import org.apache.cloudstack.datacenter.DataCenterIpv4GuestSubnet;
import org.apache.cloudstack.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.sharedfs.SharedFS;
import org.apache.cloudstack.storage.object.Bucket;
import org.apache.cloudstack.storage.object.ObjectStore;
import org.apache.cloudstack.usage.Usage;
@@ -242,6 +246,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";
@@ -286,6 +292,7 @@ public class EventTypes {
//register for user API and secret keys
public static final String EVENT_REGISTER_FOR_SECRET_API_KEY = "REGISTER.USER.KEY";
+ public static final String API_KEY_ACCESS_UPDATE = "API.KEY.ACCESS.UPDATE";
// Template Events
public static final String EVENT_TEMPLATE_CREATE = "TEMPLATE.CREATE";
@@ -333,6 +340,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";
@@ -390,6 +398,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";
@@ -448,6 +461,7 @@ 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";
@@ -722,6 +736,8 @@ 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";
// OBJECT STORE
public static final String EVENT_OBJECT_STORE_CREATE = "OBJECT.STORE.CREATE";
@@ -738,6 +754,37 @@ public class EventTypes {
public static final String EVENT_QUOTA_TARIFF_DELETE = "QUOTA.TARIFF.DELETE";
public static final String EVENT_QUOTA_TARIFF_UPDATE = "QUOTA.TARIFF.UPDATE";
+ // Routing
+ public static final String EVENT_ZONE_IP4_SUBNET_CREATE = "ZONE.IP4.SUBNET.CREATE";
+ public static final String EVENT_ZONE_IP4_SUBNET_UPDATE = "ZONE.IP4.SUBNET.UPDATE";
+ public static final String EVENT_ZONE_IP4_SUBNET_DELETE = "ZONE.IP4.SUBNET.DELETE";
+ public static final String EVENT_ZONE_IP4_SUBNET_DEDICATE = "ZONE.IP4.SUBNET.DEDICATE";
+ public static final String EVENT_ZONE_IP4_SUBNET_RELEASE = "ZONE.IP4.SUBNET.RELEASE";
+ public static final String EVENT_IP4_GUEST_SUBNET_CREATE = "IP4.GUEST.SUBNET.CREATE";
+ public static final String EVENT_IP4_GUEST_SUBNET_DELETE = "IP4.GUEST.SUBNET.DELETE";
+ public static final String EVENT_ROUTING_IPV4_FIREWALL_RULE_CREATE = "ROUTING.IPV4.FIREWALL.RULE.CREATE";
+ public static final String EVENT_ROUTING_IPV4_FIREWALL_RULE_UPDATE = "ROUTING.IPV4.FIREWALL.RULE.UPDATE";
+ public static final String EVENT_ROUTING_IPV4_FIREWALL_RULE_DELETE = "ROUTING.IPV4.FIREWALL.RULE.DELETE";
+ public static final String EVENT_BGP_PEER_CREATE = "BGP.PEER.CREATE";
+ public static final String EVENT_BGP_PEER_UPDATE = "BGP.PEER.UPDATE";
+ public static final String EVENT_BGP_PEER_DELETE = "BGP.PEER.DELETE";
+ public static final String EVENT_BGP_PEER_DEDICATE = "BGP.PEER.DEDICATE";
+ public static final String EVENT_BGP_PEER_RELEASE = "BGP.PEER.RELEASE";
+ public static final String EVENT_NETWORK_BGP_PEER_UPDATE = "NETWORK.BGP.PEER.UPDATE";
+ public static final String EVENT_VPC_BGP_PEER_UPDATE = "VPC.BGP.PEER.UPDATE";
+
+ // SharedFS
+ public static final String EVENT_SHAREDFS_CREATE = "SHAREDFS.CREATE";
+ public static final String EVENT_SHAREDFS_START = "SHAREDFS.START";
+ public static final String EVENT_SHAREDFS_UPDATE = "SHAREDFS.UPDATE";
+ public static final String EVENT_SHAREDFS_CHANGE_SERVICE_OFFERING = "SHAREDFS.CHANGE.SERVICE.OFFERING";
+ public static final String EVENT_SHAREDFS_CHANGE_DISK_OFFERING = "SHAREDFS.CHANGE.DISK.OFFERING";
+ public static final String EVENT_SHAREDFS_STOP = "SHAREDFS.STOP";
+ public static final String EVENT_SHAREDFS_RESTART = "SHAREDFS.RESTART";
+ public static final String EVENT_SHAREDFS_DESTROY = "SHAREDFS.DESTROY";
+ public static final String EVENT_SHAREDFS_EXPUNGE = "SHAREDFS.EXPUNGE";
+ public static final String EVENT_SHAREDFS_RECOVER = "SHAREDFS.RECOVER";
+
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -839,6 +886,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);
@@ -895,6 +944,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);
@@ -999,6 +1049,7 @@ 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);
@@ -1193,6 +1244,35 @@ public class EventTypes {
entityEventDetails.put(EVENT_QUOTA_TARIFF_CREATE, QuotaTariff.class);
entityEventDetails.put(EVENT_QUOTA_TARIFF_DELETE, QuotaTariff.class);
entityEventDetails.put(EVENT_QUOTA_TARIFF_UPDATE, QuotaTariff.class);
+
+ // Routing
+ entityEventDetails.put(EVENT_ZONE_IP4_SUBNET_CREATE, DataCenterIpv4GuestSubnet.class);
+ entityEventDetails.put(EVENT_ZONE_IP4_SUBNET_UPDATE, DataCenterIpv4GuestSubnet.class);
+ entityEventDetails.put(EVENT_ZONE_IP4_SUBNET_DELETE, DataCenterIpv4GuestSubnet.class);
+ entityEventDetails.put(EVENT_ZONE_IP4_SUBNET_DEDICATE, DataCenterIpv4GuestSubnet.class);
+ entityEventDetails.put(EVENT_ZONE_IP4_SUBNET_RELEASE, DataCenterIpv4GuestSubnet.class);
+ entityEventDetails.put(EVENT_IP4_GUEST_SUBNET_CREATE, Ipv4GuestSubnetNetworkMap.class);
+ entityEventDetails.put(EVENT_IP4_GUEST_SUBNET_DELETE, Ipv4GuestSubnetNetworkMap.class);
+ entityEventDetails.put(EVENT_ROUTING_IPV4_FIREWALL_RULE_CREATE, FirewallRule.class);
+ entityEventDetails.put(EVENT_ROUTING_IPV4_FIREWALL_RULE_UPDATE, FirewallRule.class);
+ entityEventDetails.put(EVENT_ROUTING_IPV4_FIREWALL_RULE_DELETE, FirewallRule.class);
+ entityEventDetails.put(EVENT_BGP_PEER_CREATE, BgpPeer.class);
+ entityEventDetails.put(EVENT_BGP_PEER_UPDATE, BgpPeer.class);
+ entityEventDetails.put(EVENT_BGP_PEER_DELETE, BgpPeer.class);
+ entityEventDetails.put(EVENT_BGP_PEER_DEDICATE, BgpPeer.class);
+ entityEventDetails.put(EVENT_BGP_PEER_RELEASE, BgpPeer.class);
+
+ // SharedFS
+ entityEventDetails.put(EVENT_SHAREDFS_CREATE, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_START, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_STOP, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_UPDATE, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_CHANGE_SERVICE_OFFERING, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_CHANGE_DISK_OFFERING, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_RESTART, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_DESTROY, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_EXPUNGE, SharedFS.class);
+ entityEventDetails.put(EVENT_SHAREDFS_RECOVER, SharedFS.class);
}
public static boolean isNetworkEvent(String eventType) {
diff --git a/api/src/main/java/com/cloud/host/Host.java b/api/src/main/java/com/cloud/host/Host.java
index 4a3b914364f..a3b6ccadc01 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,9 +53,12 @@ public interface Host extends StateObject, Identity, Partition, HAResour
return strs;
}
}
- public static final String HOST_UEFI_ENABLE = "host.uefi.enable";
- public static final String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
- public static final String HOST_INSTANCE_CONVERSION = "host.instance.conversion";
+
+ String HOST_UEFI_ENABLE = "host.uefi.enable";
+ String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
+ String HOST_INSTANCE_CONVERSION = "host.instance.conversion";
+ String HOST_OVFTOOL_VERSION = "host.ovftool.version";
+ String HOST_VIRTV2V_VERSION = "host.virtv2v.version";
/**
* @return name of the machine.
@@ -208,4 +212,6 @@ public interface Host extends StateObject, Identity, Partition, HAResour
boolean isDisabled();
ResourceState getResourceState();
+
+ CPU.CPUArch getArch();
}
diff --git a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
index 2f0cc736af3..5739daf98f7 100644
--- a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
+++ b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
@@ -17,55 +17,67 @@
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
+ }
- static Map hypervisorTypeMap;
- static Map supportedImageFormatMap;
+ 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 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 enum HypervisorType {
- None, //for storage hosts
- XenServer,
- KVM,
- VMware,
- Hyperv,
- VirtualBox,
- Parralels,
- BareMetal,
- Simulator,
- Ovm,
- Ovm3,
- LXC,
- Custom,
+ public HypervisorType(String name) {
+ this(name, null, EnumSet.noneOf(Functionality.class));
+ }
- Any; /*If you don't care about the hypervisor type*/
+ public HypervisorType(String name, ImageFormat imageFormat) {
+ this(name, imageFormat, EnumSet.noneOf(Functionality.class));
+ }
- 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 +87,77 @@ public class 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/kubernetes/cluster/KubernetesServiceHelper.java b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java
index 924dbf37f67..84e898528b5 100644
--- a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java
+++ b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java
@@ -25,6 +25,7 @@ import com.cloud.utils.component.Adapter;
public interface KubernetesServiceHelper extends Adapter {
ControlledEntity findByUuid(String uuid);
+ ControlledEntity findByVmId(long vmId);
void checkVmCanBeDestroyed(UserVm userVm);
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 cf2e2f82db9..ae1af450577 100644
--- a/api/src/main/java/com/cloud/network/IpAddress.java
+++ b/api/src/main/java/com/cloud/network/IpAddress.java
@@ -97,4 +97,6 @@ public interface IpAddress extends ControlledEntity, Identity, InternalIdentity,
void setRuleState(State ruleState);
+ boolean isForSystemVms();
+
}
diff --git a/api/src/main/java/com/cloud/network/Ipv6Service.java b/api/src/main/java/com/cloud/network/Ipv6Service.java
index 2b4dff01086..4ef5f98c38d 100644
--- a/api/src/main/java/com/cloud/network/Ipv6Service.java
+++ b/api/src/main/java/com/cloud/network/Ipv6Service.java
@@ -58,7 +58,7 @@ public interface Ipv6Service extends PluggableService, Configurable {
Pair getUsedTotalIpv6SubnetForZone(long zoneId);
- Pair preAllocateIpv6SubnetForNetwork(long zoneId) throws ResourceAllocationException;
+ Pair preAllocateIpv6SubnetForNetwork(DataCenter zone) throws ResourceAllocationException;
void assignIpv6SubnetToNetwork(String subnet, long networkId);
diff --git a/api/src/main/java/com/cloud/network/Network.java b/api/src/main/java/com/cloud/network/Network.java
index 458169c80aa..d3bc5005cb7 100644
--- a/api/src/main/java/com/cloud/network/Network.java
+++ b/api/src/main/java/com/cloud/network/Network.java
@@ -103,7 +103,7 @@ public interface Network extends ControlledEntity, StateObject, I
public static final Service Vpn = new Service("Vpn", Capability.SupportedVpnProtocols, Capability.VpnTypes);
public static final Service Dhcp = new Service("Dhcp", Capability.ExtraDhcpOptions);
public static final Service Dns = new Service("Dns", Capability.AllowDnsSuffixModification);
- public static final Service Gateway = new Service("Gateway");
+ public static final Service Gateway = new Service("Gateway", Capability.RedundantRouter);
public static final Service Firewall = new Service("Firewall", Capability.SupportedProtocols, Capability.MultipleIps, Capability.TrafficStatistics,
Capability.SupportedTrafficDirection, Capability.SupportedEgressProtocols);
public static final Service Lb = new Service("Lb", Capability.SupportedLBAlgorithms, Capability.SupportedLBIsolation, Capability.SupportedProtocols,
@@ -205,6 +205,8 @@ public interface Network extends ControlledEntity, StateObject, I
//Add Tungsten Fabric provider
public static final Provider Tungsten = new Provider("Tungsten", false);
+ public static final Provider Nsx = new Provider("Nsx", false);
+
private final String name;
private final boolean isExternal;
@@ -410,12 +412,16 @@ public interface Network extends ControlledEntity, StateObject, I
String getGateway();
+ void setGateway(String gateway);
+
// "cidr" is the Cloudstack managed address space, all CloudStack managed vms get IP address from "cidr",
// In general "cidr" also serves as the network CIDR
// But in case IP reservation is configured for a Guest network, "networkcidr" is the Effective network CIDR for that network,
// "cidr" will still continue to be the effective address space for CloudStack managed vms in that Guest network
String getCidr();
+ void setCidr(String cidr);
+
// "networkcidr" is the network CIDR of the guest network which uses IP reservation.
// It is the summation of "cidr" and the reservedIPrange(the address space used for non CloudStack purposes).
// For networks not configured with IP reservation, "networkcidr" is always null
@@ -427,6 +433,8 @@ public interface Network extends ControlledEntity, StateObject, I
long getDataCenterId();
+ long getAccountId();
+
long getNetworkOfferingId();
@Override
@@ -499,4 +507,6 @@ public interface Network extends ControlledEntity, StateObject, I
Integer getPublicMtu();
Integer getPrivateMtu();
+
+ Integer getNetworkCidrSize();
}
diff --git a/api/src/main/java/com/cloud/network/NetworkModel.java b/api/src/main/java/com/cloud/network/NetworkModel.java
index ed3506c0da1..a4cd87af008 100644
--- a/api/src/main/java/com/cloud/network/NetworkModel.java
+++ b/api/src/main/java/com/cloud/network/NetworkModel.java
@@ -173,6 +173,8 @@ public interface NetworkModel {
boolean isProviderSupportServiceInNetwork(long networkId, Service service, Provider provider);
+ boolean isAnyServiceSupportedInNetwork(long networkId, Provider provider, Service... services);
+
boolean isProviderEnabledInPhysicalNetwork(long physicalNetowrkId, String providerName);
String getNetworkTag(HypervisorType hType, Network network);
@@ -356,4 +358,8 @@ public interface NetworkModel {
void verifyIp6DnsPair(final String ip6Dns1, final String ip6Dns2);
+ boolean isSecurityGroupSupportedForZone(Long zoneId);
+
+ boolean checkSecurityGroupSupportForNetwork(Account account, DataCenter zone, List networkIds,
+ List securityGroupsIds);
}
diff --git a/api/src/main/java/com/cloud/network/NetworkProfile.java b/api/src/main/java/com/cloud/network/NetworkProfile.java
index 44853069575..2e8efb48930 100644
--- a/api/src/main/java/com/cloud/network/NetworkProfile.java
+++ b/api/src/main/java/com/cloud/network/NetworkProfile.java
@@ -22,10 +22,9 @@ import java.util.Date;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.Mode;
import com.cloud.network.Networks.TrafficType;
-import org.apache.log4j.Logger;
+import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
public class NetworkProfile implements Network {
- static final Logger s_logger = Logger.getLogger(NetworkProfile.class);
private final long id;
private final String uuid;
private final long dataCenterId;
@@ -43,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;
@@ -64,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();
@@ -100,6 +100,7 @@ public class NetworkProfile implements Network {
isRedundant = network.isRedundant();
isRollingRestart = network.isRollingRestart();
externalId = network.getExternalId();
+ networkCidrSize = network.getNetworkCidrSize();
}
@Override
@@ -212,11 +213,21 @@ public class NetworkProfile implements Network {
return gateway;
}
+ @Override
+ public void setGateway(String gateway) {
+ this.gateway = gateway;
+ }
+
@Override
public String getCidr() {
return cidr;
}
+ @Override
+ public void setCidr(String cidr) {
+ this.cidr = cidr;
+ }
+
@Override
public String getNetworkCidr() {
return networkCidr;
@@ -369,4 +380,16 @@ public class NetworkProfile implements Network {
return null;
}
+ @Override
+ public Integer getNetworkCidrSize() {
+ return networkCidrSize;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("NetworkProfile %s",
+ ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
+ this, "id", "uuid", "name", "networkOfferingId"));
+ }
+
}
diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java
index c562a54a048..b8dd464b365 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 @@ package com.cloud.network;
import java.util.List;
import java.util.Map;
+import com.cloud.dc.DataCenter;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
@@ -56,6 +57,7 @@ import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.Nic;
import com.cloud.vm.NicSecondaryIp;
+import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
/**
* The NetworkService interface is the "public" api to entities that make requests to the orchestration engine
@@ -88,6 +90,8 @@ public interface NetworkService {
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;
@@ -259,4 +263,9 @@ public interface NetworkService {
PublicIpQuarantine updatePublicIpAddressInQuarantine(UpdateQuarantinedIpCmd cmd);
void removePublicIpAddressFromQuarantine(RemoveQuarantinedIpCmd cmd);
+
+ InternalLoadBalancerElementService getInternalLoadBalancerElementByType(VirtualRouterProvider.Type type);
+ InternalLoadBalancerElementService getInternalLoadBalancerElementByNetworkServiceProviderId(long networkProviderId);
+ InternalLoadBalancerElementService getInternalLoadBalancerElementById(long providerId);
+ List getInternalLoadBalancerElements();
}
diff --git a/api/src/main/java/com/cloud/network/Networks.java b/api/src/main/java/com/cloud/network/Networks.java
index aeed5d4aec6..8e7399bb21d 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 class Networks {
}
@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 class Networks {
*/
@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,8 @@ public class Networks {
},
UnDecided(null, null),
OpenDaylight("opendaylight", String.class),
- TUNGSTEN("tf", String.class);
+ TUNGSTEN("tf", String.class),
+ NSX("nsx", String.class);
private final String scheme;
private final Class> type;
@@ -175,7 +176,7 @@ public class Networks {
* @return the scheme as BroadcastDomainType
*/
public static BroadcastDomainType getSchemeValue(URI uri) {
- return toEnumValue(uri.getScheme());
+ return toEnumValue(uri == null ? null : uri.getScheme());
}
/**
@@ -189,7 +190,7 @@ public class Networks {
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 +219,7 @@ public class Networks {
* @return the host part as String
*/
public String getValueFrom(URI uri) {
- return uri.getHost();
+ return uri == null ? null : uri.getHost();
}
/**
@@ -241,7 +242,7 @@ public class Networks {
* @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/VirtualRouterProvider.java b/api/src/main/java/com/cloud/network/VirtualRouterProvider.java
index aca526b1832..98410ca09f8 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 @@ import org.apache.cloudstack.api.InternalIdentity;
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/element/BgpServiceProvider.java b/api/src/main/java/com/cloud/network/element/BgpServiceProvider.java
new file mode 100644
index 00000000000..ee919cb1af7
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/element/BgpServiceProvider.java
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network.element;
+
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.Network;
+import com.cloud.network.vpc.Vpc;
+
+import org.apache.cloudstack.network.BgpPeer;
+
+import java.util.List;
+
+public interface BgpServiceProvider extends NetworkElement {
+
+ boolean applyBgpPeers(Vpc vpc, Network network, List extends BgpPeer> bgpPeers) throws ResourceUnavailableException;
+
+}
diff --git a/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java b/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java
index 1bb37be970d..dc0f60f4519 100644
--- a/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java
+++ b/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java
@@ -48,4 +48,7 @@ public interface LoadBalancingServiceProvider extends NetworkElement, IpDeployin
List updateHealthChecks(Network network, List lbrules);
boolean handlesOnlyRulesInTransitionState();
+
+ default void expungeLbVmRefs(List vmIds, Long batchSize) {
+ }
}
diff --git a/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java b/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java
index 8c3243c99f4..852a650cfcd 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 java.util.List;
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/VpcProvider.java b/api/src/main/java/com/cloud/network/element/VpcProvider.java
index 14e86195a70..6debd1fbc2d 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.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.IpAddress;
import com.cloud.network.vpc.NetworkACLItem;
import com.cloud.network.vpc.PrivateGateway;
import com.cloud.network.vpc.StaticRouteProfile;
@@ -52,4 +53,6 @@ public interface VpcProvider extends NetworkElement {
boolean applyStaticRoutes(Vpc vpc, List routes) throws ResourceUnavailableException;
boolean applyACLItemsToPrivateGw(PrivateGateway gateway, List extends NetworkACLItem> rules) throws ResourceUnavailableException;
+
+ boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address);
}
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 c4f2beba63e..7b81c75ed84 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,
diff --git a/api/src/main/java/com/cloud/network/lb/LoadBalancingRule.java b/api/src/main/java/com/cloud/network/lb/LoadBalancingRule.java
index 64b2aeedf12..e4cf4ec526f 100644
--- a/api/src/main/java/com/cloud/network/lb/LoadBalancingRule.java
+++ b/api/src/main/java/com/cloud/network/lb/LoadBalancingRule.java
@@ -63,6 +63,10 @@ public class LoadBalancingRule {
return lb.getId();
}
+ public LoadBalancer getLb() {
+ return lb;
+ }
+
public String getName() {
return lb.getName();
}
diff --git a/api/src/main/java/com/cloud/network/nsx/NsxProvider.java b/api/src/main/java/com/cloud/network/nsx/NsxProvider.java
new file mode 100644
index 00000000000..19cb3b4b939
--- /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 00000000000..bc4e6aafbfe
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/nsx/NsxService.java
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.network.nsx;
+
+import com.cloud.network.IpAddress;
+import com.cloud.network.vpc.Vpc;
+import org.apache.cloudstack.framework.config.ConfigKey;
+
+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);
+}
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 b4df8e38dba..38263f59667 100644
--- a/api/src/main/java/com/cloud/network/vpc/VpcOffering.java
+++ b/api/src/main/java/com/cloud/network/vpc/VpcOffering.java
@@ -18,6 +18,7 @@ package com.cloud.network.vpc;
import java.util.Date;
+import com.cloud.offering.NetworkOffering;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@@ -29,6 +30,8 @@ public interface VpcOffering extends InternalIdentity, Identity {
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";
/**
*
@@ -53,6 +56,10 @@ public interface VpcOffering extends InternalIdentity, Identity {
*/
boolean isDefault();
+ boolean isForNsx();
+
+ NetworkOffering.NetworkMode getNetworkMode();
+
/**
* @return service offering id used by VPC virtual router
*/
@@ -73,4 +80,8 @@ public interface VpcOffering extends InternalIdentity, Identity {
Date getRemoved();
Date getCreated();
+
+ NetworkOffering.RoutingMode getRoutingMode();
+
+ Boolean isSpecifyAsNumber();
}
diff --git a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
index 5cccd6c5a82..10f1ddcc12d 100644
--- a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
+++ b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
@@ -24,6 +24,7 @@ import org.apache.cloudstack.api.command.admin.vpc.CreateVPCOfferingCmd;
import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCOfferingCmd;
import org.apache.cloudstack.api.command.user.vpc.ListVPCOfferingsCmd;
+import com.cloud.offering.NetworkOffering;
import com.cloud.utils.Pair;
import com.cloud.utils.net.NetUtils;
@@ -36,7 +37,10 @@ public interface VpcProvisioningService {
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, Boolean forNsx, NetworkOffering.NetworkMode networkMode,
+ List domainIds, List zoneIds, VpcOffering.State state,
+ NetworkOffering.RoutingMode routingMode, boolean specifyAsNumber);
+
Pair,Integer> listVpcOfferings(ListVPCOfferingsCmd cmd);
diff --git a/api/src/main/java/com/cloud/network/vpc/VpcService.java b/api/src/main/java/com/cloud/network/vpc/VpcService.java
index 0f0d29f4082..af2a9847a62 100644
--- a/api/src/main/java/com/cloud/network/vpc/VpcService.java
+++ b/api/src/main/java/com/cloud/network/vpc/VpcService.java
@@ -56,7 +56,8 @@ public interface VpcService {
* @throws ResourceAllocationException TODO
*/
Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName, String displayText, String cidr, String networkDomain,
- String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Boolean displayVpc, Integer publicMtu)
+ String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Boolean displayVpc, Integer publicMtu, Integer cidrSize,
+ Long asNumber, List bgpPeerIds)
throws ResourceAllocationException;
/**
diff --git a/api/src/main/java/com/cloud/network/vpn/RemoteAccessVpnService.java b/api/src/main/java/com/cloud/network/vpn/RemoteAccessVpnService.java
index bbb9771d27a..ffa8af4576d 100644
--- a/api/src/main/java/com/cloud/network/vpn/RemoteAccessVpnService.java
+++ b/api/src/main/java/com/cloud/network/vpn/RemoteAccessVpnService.java
@@ -39,7 +39,7 @@ public interface RemoteAccessVpnService {
VpnUser addVpnUser(long vpnOwnerId, String userName, String password);
- boolean removeVpnUser(long vpnOwnerId, String userName, Account caller);
+ boolean removeVpnUser(Account vpnOwner, String userName, Account caller);
List extends VpnUser> listVpnUsers(long vpnOwnerId, String userName);
diff --git a/api/src/main/java/com/cloud/offering/NetworkOffering.java b/api/src/main/java/com/cloud/offering/NetworkOffering.java
index 207880ea28c..7011aea679e 100644
--- a/api/src/main/java/com/cloud/offering/NetworkOffering.java
+++ b/api/src/main/java/com/cloud/offering/NetworkOffering.java
@@ -43,6 +43,15 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, MacLearning, RelatedNetworkOffering, domainid, zoneid, pvlanType, internetProtocol
}
+ public enum NetworkMode {
+ NATTED,
+ ROUTED
+ }
+
+ enum RoutingMode {
+ Static, Dynamic
+ }
+
public final static String SystemPublicNetwork = "System-Public-Network";
public final static String SystemControlNetwork = "System-Control-Network";
public final static String SystemManagementNetwork = "System-Management-Network";
@@ -52,6 +61,11 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
public final static String DefaultSharedNetworkOfferingWithSGService = "DefaultSharedNetworkOfferingWithSGService";
public static final String DEFAULT_TUNGSTEN_SHARED_NETWORK_OFFERING_WITH_SGSERVICE = "DefaultTungstenSharedNetworkOfferingWithSGService";
+ public static final String DEFAULT_NAT_NSX_OFFERING_FOR_VPC = "DefaultNATNSXNetworkOfferingForVpc";
+ public static final String DEFAULT_NAT_NSX_OFFERING_FOR_VPC_WITH_ILB = "DefaultNATNSXNetworkOfferingForVpcWithInternalLB";
+ public static final String DEFAULT_ROUTED_NSX_OFFERING_FOR_VPC = "DefaultRoutedNSXNetworkOfferingForVpc";
+ public static final String DEFAULT_NAT_NSX_OFFERING = "DefaultNATNSXNetworkOffering";
+ public static final String DEFAULT_ROUTED_NSX_OFFERING = "DefaultRoutedNSXNetworkOffering";
public final static String QuickCloudNoServices = "QuickCloudNoServices";
public final static String DefaultIsolatedNetworkOfferingWithSourceNatService = "DefaultIsolatedNetworkOfferingWithSourceNatService";
public final static String OvsIsolatedNetworkOfferingWithSourceNatService = "OvsIsolatedNetworkOfferingWithSourceNatService";
@@ -90,6 +104,10 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
boolean isForTungsten();
+ boolean isForNsx();
+
+ NetworkMode getNetworkMode();
+
TrafficType getTrafficType();
boolean isSpecifyVlan();
@@ -151,4 +169,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
String getServicePackage();
Date getCreated();
+
+ RoutingMode getRoutingMode();
+
+ Boolean isSpecifyAsNumber();
}
diff --git a/api/src/main/java/com/cloud/offering/ServiceOffering.java b/api/src/main/java/com/cloud/offering/ServiceOffering.java
index 58c7b0dbaf9..acb7a9f1cf9 100644
--- a/api/src/main/java/com/cloud/offering/ServiceOffering.java
+++ b/api/src/main/java/com/cloud/offering/ServiceOffering.java
@@ -33,6 +33,9 @@ public interface ServiceOffering extends InfrastructureEntity, InternalIdentity,
static final String internalLbVmDefaultOffUniqueName = "Cloud.Com-InternalLBVm";
// leaving cloud.com references as these are identifyers and no real world addresses (check against DB)
+
+ static final String PURGE_DB_ENTITIES_KEY = "purge.db.entities";
+
enum State {
Inactive, Active,
}
diff --git a/api/src/main/java/com/cloud/org/Cluster.java b/api/src/main/java/com/cloud/org/Cluster.java
index 4079c88dfde..5124168084c 100644
--- a/api/src/main/java/com/cloud/org/Cluster.java
+++ b/api/src/main/java/com/cloud/org/Cluster.java
@@ -16,6 +16,7 @@
// under the License.
package com.cloud.org;
+import com.cloud.cpu.CPU;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.org.Managed.ManagedState;
import org.apache.cloudstack.kernel.Partition;
@@ -38,4 +39,6 @@ public interface Cluster extends Grouping, Partition {
AllocationState getAllocationState();
ManagedState getManagedState();
+
+ CPU.CPUArch getArch();
}
diff --git a/api/src/main/java/com/cloud/region/ha/GlobalLoadBalancingRulesService.java b/api/src/main/java/com/cloud/region/ha/GlobalLoadBalancingRulesService.java
index ab6e6fb6c5a..3b61367e3b4 100644
--- a/api/src/main/java/com/cloud/region/ha/GlobalLoadBalancingRulesService.java
+++ b/api/src/main/java/com/cloud/region/ha/GlobalLoadBalancingRulesService.java
@@ -19,6 +19,7 @@ package com.cloud.region.ha;
import java.util.List;
+import com.cloud.user.Account;
import org.apache.cloudstack.api.command.user.region.ha.gslb.AssignToGlobalLoadBalancerRuleCmd;
import org.apache.cloudstack.api.command.user.region.ha.gslb.CreateGlobalLoadBalancerRuleCmd;
import org.apache.cloudstack.api.command.user.region.ha.gslb.DeleteGlobalLoadBalancerRuleCmd;
@@ -39,7 +40,7 @@ public interface GlobalLoadBalancingRulesService {
GlobalLoadBalancerRule updateGlobalLoadBalancerRule(UpdateGlobalLoadBalancerRuleCmd updateGslbCmd);
- boolean revokeAllGslbRulesForAccount(com.cloud.user.Account caller, long accountId) throws com.cloud.exception.ResourceUnavailableException;
+ boolean revokeAllGslbRulesForAccount(com.cloud.user.Account caller, Account account) throws com.cloud.exception.ResourceUnavailableException;
/*
* methods for managing sites participating in global load balancing
diff --git a/api/src/main/java/com/cloud/server/ManagementServerHostStats.java b/api/src/main/java/com/cloud/server/ManagementServerHostStats.java
index 1f201d7689f..1eea7addba3 100644
--- a/api/src/main/java/com/cloud/server/ManagementServerHostStats.java
+++ b/api/src/main/java/com/cloud/server/ManagementServerHostStats.java
@@ -32,6 +32,8 @@ public interface ManagementServerHostStats {
String getManagementServerHostUuid();
+ long getManagementServerRunId();
+
long getSessions();
double getCpuUtilization();
diff --git a/api/src/main/java/com/cloud/server/ManagementService.java b/api/src/main/java/com/cloud/server/ManagementService.java
index 18f3e901cd9..d6d7f7a59c6 100644
--- a/api/src/main/java/com/cloud/server/ManagementService.java
+++ b/api/src/main/java/com/cloud/server/ManagementService.java
@@ -20,7 +20,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import com.cloud.user.UserData;
import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
import org.apache.cloudstack.api.command.admin.config.ListCfgGroupsByCmd;
import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
@@ -66,6 +65,7 @@ import org.apache.cloudstack.api.command.user.vm.GetVMPasswordCmd;
import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
import org.apache.cloudstack.config.Configuration;
import org.apache.cloudstack.config.ConfigurationGroup;
+import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.alert.Alert;
import com.cloud.capacity.Capacity;
@@ -85,6 +85,7 @@ import com.cloud.storage.GuestOSHypervisor;
import com.cloud.storage.GuestOsCategory;
import com.cloud.storage.StoragePool;
import com.cloud.user.SSHKeyPair;
+import com.cloud.user.UserData;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.vm.InstanceGroup;
@@ -98,6 +99,14 @@ import com.cloud.vm.VirtualMachine.Type;
public interface ManagementService {
static final String Name = "management-server";
+ ConfigKey JsInterpretationEnabled = new ConfigKey<>("Hidden"
+ , Boolean.class
+ , "js.interpretation.enabled"
+ , "false"
+ , "Enable/Disable all JavaScript interpretation related functionalities to create or update Javascript rules."
+ , false
+ , ConfigKey.Scope.Global);
+
/**
* returns the a map of the names/values in the configuration table
*
@@ -481,4 +490,6 @@ public interface ManagementService {
Pair patchSystemVM(PatchSystemVMCmd cmd);
+ void checkJsInterpretationAllowedIfNeededForParameterValue(String paramName, boolean paramValue);
+
}
diff --git a/api/src/main/java/com/cloud/server/ResourceManagerUtil.java b/api/src/main/java/com/cloud/server/ResourceManagerUtil.java
index 9a3b51a70d5..f5081cbe307 100644
--- a/api/src/main/java/com/cloud/server/ResourceManagerUtil.java
+++ b/api/src/main/java/com/cloud/server/ResourceManagerUtil.java
@@ -18,6 +18,7 @@ package com.cloud.server;
public interface ResourceManagerUtil {
long getResourceId(String resourceId, ResourceTag.ResourceObjectType resourceType);
+ long getResourceId(String resourceId, ResourceTag.ResourceObjectType resourceType, boolean checkAccess);
String getUuid(String resourceId, ResourceTag.ResourceObjectType resourceType);
ResourceTag.ResourceObjectType getResourceType(String resourceTypeStr);
void checkResourceAccessible(Long accountId, Long domainId, String exceptionMessage);
diff --git a/api/src/main/java/com/cloud/storage/DataStoreRole.java b/api/src/main/java/com/cloud/storage/DataStoreRole.java
index 185e370159c..d9af495ab00 100644
--- a/api/src/main/java/com/cloud/storage/DataStoreRole.java
+++ b/api/src/main/java/com/cloud/storage/DataStoreRole.java
@@ -20,6 +20,7 @@ package com.cloud.storage;
import com.cloud.utils.exception.CloudRuntimeException;
+
public enum DataStoreRole {
Primary("primary"), Image("image"), ImageCache("imagecache"), Backup("backup"), Object("object");
diff --git a/api/src/main/java/com/cloud/storage/Storage.java b/api/src/main/java/com/cloud/storage/Storage.java
index 0d7a3ed90c0..05b8b3ab7a8 100644
--- a/api/src/main/java/com/cloud/storage/Storage.java
+++ b/api/src/main/java/com/cloud/storage/Storage.java
@@ -150,6 +150,17 @@ public class Storage {
Storage
}
+ /**
+ * StoragePoolTypes carry some details about the format and capabilities of a storage pool. While not necessarily a
+ * 1:1 with PrimaryDataStoreDriver (and for KVM agent, KVMStoragePool and StorageAdaptor) implementations, it is
+ * often used to decide which storage plugin or storage command to call, so it may be necessary for new storage
+ * plugins to add a StoragePoolType. This can be done by adding it below, or by creating a new public static final
+ * instance of StoragePoolType in the plugin itself, which registers it with the map.
+ *
+ * Note that if the StoragePoolType is for KVM and defined in plugin code rather than below, care must be taken to
+ * ensure this is available on the agent side as well. This is best done by defining the StoragePoolType in a common
+ * package available on both management server and agent plugin jars.
+ */
public static enum StoragePoolType {
Filesystem(false, true, EncryptionSupport.Hypervisor), // local directory
NetworkFilesystem(true, true, EncryptionSupport.Hypervisor), // NFS
diff --git a/api/src/main/java/com/cloud/storage/StorageService.java b/api/src/main/java/com/cloud/storage/StorageService.java
index 1ce335b0115..b8df75cd3e4 100644
--- a/api/src/main/java/com/cloud/storage/StorageService.java
+++ b/api/src/main/java/com/cloud/storage/StorageService.java
@@ -95,6 +95,10 @@ public interface StorageService {
StoragePool updateStoragePool(UpdateStoragePoolCmd cmd) throws IllegalArgumentException;
+ StoragePool enablePrimaryStoragePool(Long id);
+
+ StoragePool disablePrimaryStoragePool(Long id);
+
StoragePool getStoragePool(long id);
boolean deleteImageStore(DeleteImageStoreCmd cmd);
diff --git a/api/src/main/java/com/cloud/storage/StorageStats.java b/api/src/main/java/com/cloud/storage/StorageStats.java
index a474b23489c..502e2aaae40 100644
--- a/api/src/main/java/com/cloud/storage/StorageStats.java
+++ b/api/src/main/java/com/cloud/storage/StorageStats.java
@@ -26,4 +26,7 @@ public interface StorageStats {
* @return bytes capacity of the storage server
*/
public long getCapacityBytes();
+
+ Long getCapacityIops();
+ Long getUsedIops();
}
diff --git a/api/src/main/java/com/cloud/storage/Upload.java b/api/src/main/java/com/cloud/storage/Upload.java
index 59d203ac73a..4e696e877cc 100644
--- a/api/src/main/java/com/cloud/storage/Upload.java
+++ b/api/src/main/java/com/cloud/storage/Upload.java
@@ -40,7 +40,7 @@ public interface Upload extends InternalIdentity, Identity {
}
public static enum Type {
- VOLUME, TEMPLATE, ISO
+ VOLUME, SNAPSHOT, TEMPLATE, ISO
}
public static enum Mode {
diff --git a/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java b/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java
index f43d5331222..db702a61f2b 100644
--- a/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java
+++ b/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java
@@ -17,6 +17,7 @@
package com.cloud.storage;
import java.util.Date;
+import java.util.List;
import org.apache.cloudstack.api.InternalIdentity;
@@ -25,6 +26,8 @@ public interface VMTemplateStorageResourceAssoc extends InternalIdentity {
UNKNOWN, DOWNLOAD_ERROR, NOT_DOWNLOADED, DOWNLOAD_IN_PROGRESS, DOWNLOADED, ABANDONED, UPLOADED, NOT_UPLOADED, UPLOAD_ERROR, UPLOAD_IN_PROGRESS, CREATING, CREATED, BYPASSED
}
+ List PENDING_DOWNLOAD_STATES = List.of(Status.NOT_DOWNLOADED, Status.DOWNLOAD_IN_PROGRESS);
+
String getInstallPath();
long getTemplateId();
diff --git a/api/src/main/java/com/cloud/storage/Volume.java b/api/src/main/java/com/cloud/storage/Volume.java
index 308ed2544ed..c7fbdb0a544 100644
--- a/api/src/main/java/com/cloud/storage/Volume.java
+++ b/api/src/main/java/com/cloud/storage/Volume.java
@@ -30,6 +30,8 @@ import com.cloud.utils.fsm.StateObject;
public interface Volume extends ControlledEntity, Identity, InternalIdentity, BasedOn, StateObject, Displayable {
+ static final long DISK_OFFERING_SUITABILITY_CHECK_VOLUME_ID = -1;
+
// Managed storage volume parameters (specified in the compute/disk offering for PowerFlex)
String BANDWIDTH_LIMIT_IN_MBPS = "bandwidthLimitInMbps";
String IOPS_LIMIT = "iopsLimit";
@@ -269,11 +271,13 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba
void setExternalUuid(String externalUuid);
- public Long getPassphraseId();
+ Long getPassphraseId();
- public void setPassphraseId(Long id);
+ void setPassphraseId(Long id);
- public String getEncryptFormat();
+ String getEncryptFormat();
- public void setEncryptFormat(String encryptFormat);
+ void setEncryptFormat(String encryptFormat);
+
+ boolean isDeleteProtection();
}
diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java
index 833ba442888..4182728c204 100644
--- a/api/src/main/java/com/cloud/storage/VolumeApiService.java
+++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java
@@ -22,7 +22,12 @@ import java.net.MalformedURLException;
import java.util.List;
import java.util.Map;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.offering.DiskOffering;
+import com.cloud.user.Account;
import com.cloud.utils.Pair;
+import com.cloud.utils.fsm.NoTransitionException;
+
import org.apache.cloudstack.api.command.user.volume.AssignVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.ChangeOfferingForVolumeCmd;
@@ -37,13 +42,9 @@ import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
import org.apache.cloudstack.api.response.GetUploadParamsResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.user.Account;
-import com.cloud.utils.fsm.NoTransitionException;
-
public interface VolumeApiService {
- ConfigKey ConcurrentMigrationsThresholdPerDatastore = new ConfigKey("Advanced"
+ ConfigKey ConcurrentMigrationsThresholdPerDatastore = new ConfigKey<>("Advanced"
, Long.class
, "concurrent.migrations.per.target.datastore"
, "0"
@@ -51,7 +52,7 @@ public interface VolumeApiService {
, true // not sure if this is to be dynamic
, ConfigKey.Scope.Global);
- ConfigKey UseHttpsToUpload = new ConfigKey("Advanced",
+ ConfigKey UseHttpsToUpload = new ConfigKey<>("Advanced",
Boolean.class,
"use.https.to.upload",
"true",
@@ -85,7 +86,7 @@ public interface VolumeApiService {
* @param cmd
* the API command wrapping the criteria
* @return the volume object
- * @throws ResourceAllocationException
+ * @throws ResourceAllocationException no capacity to allocate the new volume size
*/
Volume resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationException;
@@ -102,8 +103,12 @@ public interface VolumeApiService {
boolean deleteVolume(long volumeId, Account caller);
+ Volume changeDiskOfferingForVolumeInternal(Long volumeId, Long newDiskOfferingId, Long newSize, Long newMinIops, Long newMaxIops, boolean autoMigrateVolume, boolean shrinkOk) throws ResourceAllocationException;
+
Volume attachVolumeToVM(AttachVolumeCmd command);
+ Volume attachVolumeToVM(Long vmId, Long volumeId, Long deviceId, Boolean allowAttachForSharedFS);
+
Volume detachVolumeViaDestroyVM(long vmId, long volumeId);
Volume detachVolumeFromVM(DetachVolumeCmd cmd);
@@ -113,7 +118,9 @@ public interface VolumeApiService {
Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, List zoneIds) throws ResourceAllocationException;
- Volume updateVolume(long volumeId, String path, String state, Long storageId, Boolean displayVolume, String customId, long owner, String chainInfo, String name);
+ Volume updateVolume(long volumeId, String path, String state, Long storageId,
+ Boolean displayVolume, Boolean deleteProtection,
+ String customId, long owner, String chainInfo, String name);
/**
* Extracts the volume to a particular location.
@@ -163,6 +170,14 @@ public interface VolumeApiService {
*