Merge remote-tracking branch 'origin/4.19'

This commit is contained in:
Rohit Yadav 2024-02-05 14:22:09 +05:30
commit 25009bfb76
21 changed files with 470 additions and 73 deletions

View File

@ -400,6 +400,7 @@ public class EventTypes {
public static final String EVENT_IMAGE_STORE_DATA_MIGRATE = "IMAGE.STORE.MIGRATE.DATA"; public static final String EVENT_IMAGE_STORE_DATA_MIGRATE = "IMAGE.STORE.MIGRATE.DATA";
public static final String EVENT_IMAGE_STORE_RESOURCES_MIGRATE = "IMAGE.STORE.MIGRATE.RESOURCES"; public static final String EVENT_IMAGE_STORE_RESOURCES_MIGRATE = "IMAGE.STORE.MIGRATE.RESOURCES";
public static final String EVENT_IMAGE_STORE_OBJECT_DOWNLOAD = "IMAGE.STORE.OBJECT.DOWNLOAD"; public static final String EVENT_IMAGE_STORE_OBJECT_DOWNLOAD = "IMAGE.STORE.OBJECT.DOWNLOAD";
public static final String EVENT_UPDATE_IMAGE_STORE_ACCESS_STATE = "IMAGE.STORE.ACCESS.UPDATED";
// Configuration Table // Configuration Table
public static final String EVENT_CONFIGURATION_VALUE_EDIT = "CONFIGURATION.VALUE.EDIT"; public static final String EVENT_CONFIGURATION_VALUE_EDIT = "CONFIGURATION.VALUE.EDIT";
@ -1164,6 +1165,7 @@ public class EventTypes {
entityEventDetails.put(EVENT_IMAGE_STORE_DATA_MIGRATE, ImageStore.class); entityEventDetails.put(EVENT_IMAGE_STORE_DATA_MIGRATE, ImageStore.class);
entityEventDetails.put(EVENT_IMAGE_STORE_OBJECT_DOWNLOAD, ImageStore.class); entityEventDetails.put(EVENT_IMAGE_STORE_OBJECT_DOWNLOAD, ImageStore.class);
entityEventDetails.put(EVENT_UPDATE_IMAGE_STORE_ACCESS_STATE, ImageStore.class);
entityEventDetails.put(EVENT_LIVE_PATCH_SYSTEMVM, "SystemVMs"); entityEventDetails.put(EVENT_LIVE_PATCH_SYSTEMVM, "SystemVMs");
//Object Store //Object Store

View File

@ -52,7 +52,7 @@ public interface AlertService {
public static final AlertType ALERT_TYPE_ROUTING = new AlertType((short)11, "ALERT.NETWORK.ROUTING", true); public static final AlertType ALERT_TYPE_ROUTING = new AlertType((short)11, "ALERT.NETWORK.ROUTING", true);
public static final AlertType ALERT_TYPE_STORAGE_MISC = new AlertType((short)12, "ALERT.STORAGE.MISC", true); public static final AlertType ALERT_TYPE_STORAGE_MISC = new AlertType((short)12, "ALERT.STORAGE.MISC", true);
public static final AlertType ALERT_TYPE_USAGE_SERVER = new AlertType((short)13, "ALERT.USAGE", true); public static final AlertType ALERT_TYPE_USAGE_SERVER = new AlertType((short)13, "ALERT.USAGE", true);
public static final AlertType ALERT_TYPE_MANAGMENT_NODE = new AlertType((short)14, "ALERT.MANAGEMENT", true); public static final AlertType ALERT_TYPE_MANAGEMENT_NODE = new AlertType((short)14, "ALERT.MANAGEMENT", true);
public static final AlertType ALERT_TYPE_DOMAIN_ROUTER_MIGRATE = new AlertType((short)15, "ALERT.NETWORK.DOMAINROUTERMIGRATE", true); public static final AlertType ALERT_TYPE_DOMAIN_ROUTER_MIGRATE = new AlertType((short)15, "ALERT.NETWORK.DOMAINROUTERMIGRATE", true);
public static final AlertType ALERT_TYPE_CONSOLE_PROXY_MIGRATE = new AlertType((short)16, "ALERT.SERVICE.CONSOLEPROXYMIGRATE", true); public static final AlertType ALERT_TYPE_CONSOLE_PROXY_MIGRATE = new AlertType((short)16, "ALERT.SERVICE.CONSOLEPROXYMIGRATE", true);
public static final AlertType ALERT_TYPE_USERVM_MIGRATE = new AlertType((short)17, "ALERT.USERVM.MIGRATE", true); public static final AlertType ALERT_TYPE_USERVM_MIGRATE = new AlertType((short)17, "ALERT.USERVM.MIGRATE", true);

View File

@ -39,7 +39,7 @@ import com.cloud.user.User;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
@APICommand(name = "moveUser", @APICommand(name = "moveUser",
description = "Moves a user to another account", description = "Moves a user to another account in the same domain.",
responseObject = SuccessResponse.class, responseObject = SuccessResponse.class,
requestHasSensitiveInfo = false, requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false, responseHasSensitiveInfo = false,
@ -56,18 +56,18 @@ public class MoveUserCmd extends BaseCmd {
type = CommandType.UUID, type = CommandType.UUID,
entityType = UserResponse.class, entityType = UserResponse.class,
required = true, required = true,
description = "id of the user to be deleted") description = "id of the user to be moved.")
private Long id; private Long id;
@Parameter(name = ApiConstants.ACCOUNT, @Parameter(name = ApiConstants.ACCOUNT,
type = CommandType.STRING, type = CommandType.STRING,
description = "Creates the user under the specified account. If no account is specified, the username will be used as the account name.") description = "Moves the user under the specified account. If no account name is specified, it is necessary to provide an account id.")
private String accountName; private String accountName;
@Parameter(name = ApiConstants.ACCOUNT_ID, @Parameter(name = ApiConstants.ACCOUNT_ID,
type = CommandType.UUID, type = CommandType.UUID,
entityType = AccountResponse.class, entityType = AccountResponse.class,
description = "Creates the user under the specified domain. Has to be accompanied with the account parameter") description = "Moves the user under the specified account. If no account id is specified, it is necessary to provide an account name.")
private Long accountId; private Long accountId;
@Inject @Inject

View File

@ -17,9 +17,21 @@
package com.cloud.vm; package com.cloud.vm;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.serializer.GsonHelper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
public class VmWork implements Serializable { public class VmWork implements Serializable {
private static final long serialVersionUID = -6946320465729853589L; private static final long serialVersionUID = -6946320465729853589L;
private static final Gson gsonLogger = GsonHelper.getGsonLogger();
long userId; long userId;
long accountId; long accountId;
@ -56,4 +68,31 @@ public class VmWork implements Serializable {
public String getHandlerName() { public String getHandlerName() {
return handlerName; return handlerName;
} }
@Override
public String toString() {
return gsonLogger.toJson(this);
}
protected String toStringAfterRemoveParams(String paramsObjName, List<String> params) {
String ObjJsonStr = gsonLogger.toJson(this);
if (StringUtils.isBlank(ObjJsonStr) || StringUtils.isBlank(paramsObjName) || CollectionUtils.isEmpty(params)) {
return ObjJsonStr;
}
try {
Map<String, Object> ObjMap = new ObjectMapper().readValue(ObjJsonStr, HashMap.class);
if (ObjMap != null && ObjMap.containsKey(paramsObjName)) {
for (String param : params) {
((Map<String, String>)ObjMap.get(paramsObjName)).remove(param);
}
String resultJson = new ObjectMapper().writeValueAsString(ObjMap);
return resultJson;
}
} catch (final JsonProcessingException e) {
// Ignore json exception
}
return ObjJsonStr;
}
} }

View File

@ -21,15 +21,13 @@ import java.lang.reflect.Method;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.log4j.Logger;
import com.google.gson.Gson;
import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper; import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
import org.apache.cloudstack.jobs.JobInfo; import org.apache.cloudstack.jobs.JobInfo;
import org.apache.log4j.Logger;
import com.cloud.serializer.GsonHelper; import com.cloud.serializer.GsonHelper;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
import com.google.gson.Gson;
/** /**
* VmWorkJobHandlerProxy can not be used as standalone due to run-time * VmWorkJobHandlerProxy can not be used as standalone due to run-time
@ -102,12 +100,12 @@ public class VmWorkJobHandlerProxy implements VmWorkJobHandler {
try { try {
if (s_logger.isDebugEnabled()) if (s_logger.isDebugEnabled())
s_logger.debug("Execute VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work)); s_logger.debug("Execute VM work job: " + work.getClass().getName() + work);
Object obj = method.invoke(_target, work); Object obj = method.invoke(_target, work);
if (s_logger.isDebugEnabled()) if (s_logger.isDebugEnabled())
s_logger.debug("Done executing VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work)); s_logger.debug("Done executing VM work job: " + work.getClass().getName() + work);
assert (obj instanceof Pair); assert (obj instanceof Pair);
return (Pair<JobInfo.Status, String>)obj; return (Pair<JobInfo.Status, String>)obj;

View File

@ -17,7 +17,9 @@
package com.cloud.vm; package com.cloud.vm;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper; import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
@ -62,4 +64,11 @@ public class VmWorkReboot extends VmWork {
} }
} }
} }
@Override
public String toString() {
List<String> params = new ArrayList<>();
params.add(VirtualMachineProfile.Param.VmPassword.getName());
return super.toStringAfterRemoveParams("rawParams", params);
}
} }

View File

@ -18,7 +18,9 @@
package com.cloud.vm; package com.cloud.vm;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.context.CallContext;
@ -135,4 +137,11 @@ public class VmWorkStart extends VmWork {
} }
} }
} }
@Override
public String toString() {
List<String> params = new ArrayList<>();
params.add(VirtualMachineProfile.Param.VmPassword.getName());
return super.toStringAfterRemoveParams("rawParams", params);
}
} }

View File

@ -0,0 +1,42 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.vm;
import java.util.HashMap;
import java.util.Map;
import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
import org.junit.Assert;
import org.junit.Test;
public class VmWorkRebootTest {
@Test
public void testToString() {
VmWork vmWork = new VmWork(1l, 1l, 1l, "testhandler");
Map<VirtualMachineProfile.Param, Object> params = new HashMap<>();
String lastHost = "rO0ABXQABHRydWU";
String lastHostSerialized = JobSerializerHelper.toObjectSerializedString(lastHost);
params.put(VirtualMachineProfile.Param.ConsiderLastHost, lastHost);
params.put(VirtualMachineProfile.Param.VmPassword, "rO0ABXQADnNhdmVkX3Bhc3N3b3Jk");
VmWorkReboot workInfo = new VmWorkReboot(vmWork, params);
String expectedVmWorkRebootStr = "{\"accountId\":1,\"vmId\":1,\"handlerName\":\"testhandler\",\"userId\":1,\"rawParams\":{\"ConsiderLastHost\":\"" + lastHostSerialized + "\"}}";
String vmWorkRebootStr = workInfo.toString();
Assert.assertEquals(expectedVmWorkRebootStr, vmWorkRebootStr);
}
}

View File

@ -0,0 +1,57 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.vm;
import java.util.HashMap;
import java.util.Map;
import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
import org.junit.Assert;
import org.junit.Test;
public class VmWorkStartTest {
@Test
public void testToStringWithParams() {
VmWork vmWork = new VmWork(1l, 1l, 1l, "testhandler");
VmWorkStart workInfo = new VmWorkStart(vmWork);
Map<VirtualMachineProfile.Param, Object> params = new HashMap<>();
String lastHost = "rO0ABXQABHRydWU";
String lastHostSerialized = JobSerializerHelper.toObjectSerializedString(lastHost);
params.put(VirtualMachineProfile.Param.ConsiderLastHost, lastHost);
params.put(VirtualMachineProfile.Param.VmPassword, "rO0ABXQADnNhdmVkX3Bhc3N3b3Jk");
workInfo.setParams(params);
String expectedVmWorkStartStr = "{\"accountId\":1,\"dcId\":0,\"vmId\":1,\"handlerName\":\"testhandler\",\"userId\":1,\"rawParams\":{\"ConsiderLastHost\":\"" + lastHostSerialized + "\"}}";
String vmWorkStartStr = workInfo.toString();
Assert.assertEquals(expectedVmWorkStartStr, vmWorkStartStr);
}
@Test
public void testToStringWithRawParams() {
VmWork vmWork = new VmWork(1l, 1l, 1l, "testhandler");
VmWorkStart workInfo = new VmWorkStart(vmWork);
Map<String, String> rawParams = new HashMap<>();
rawParams.put(VirtualMachineProfile.Param.ConsiderLastHost.getName(), "rO0ABXQABHRydWU");
rawParams.put(VirtualMachineProfile.Param.VmPassword.getName(), "rO0ABXQADnNhdmVkX3Bhc3N3b3Jk");
workInfo.setRawParams(rawParams);
String expectedVmWorkStartStr = "{\"accountId\":1,\"dcId\":0,\"vmId\":1,\"handlerName\":\"testhandler\",\"userId\":1,\"rawParams\":{\"ConsiderLastHost\":\"rO0ABXQABHRydWU\"}}";
String vmWorkStartStr = workInfo.toString();
Assert.assertEquals(expectedVmWorkStartStr, vmWorkStartStr);
}
}

View File

@ -85,7 +85,6 @@ import org.libvirt.DomainInfo;
import org.libvirt.DomainInfo.DomainState; import org.libvirt.DomainInfo.DomainState;
import org.libvirt.DomainInterfaceStats; import org.libvirt.DomainInterfaceStats;
import org.libvirt.DomainSnapshot; import org.libvirt.DomainSnapshot;
import org.libvirt.Library;
import org.libvirt.LibvirtException; import org.libvirt.LibvirtException;
import org.libvirt.MemoryStatistic; import org.libvirt.MemoryStatistic;
import org.libvirt.Network; import org.libvirt.Network;
@ -3694,20 +3693,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
} }
private void setupLibvirtEventListener() { private void setupLibvirtEventListener() {
final Thread libvirtListenerThread = new Thread(() -> {
try {
Library.runEventLoop();
} catch (LibvirtException e) {
s_logger.error("LibvirtException was thrown in event loop: ", e);
} catch (InterruptedException e) {
s_logger.error("Libvirt event loop was interrupted: ", e);
}
});
try { try {
libvirtListenerThread.setDaemon(true);
libvirtListenerThread.start();
Connect conn = LibvirtConnection.getConnection(); Connect conn = LibvirtConnection.getConnection();
conn.addLifecycleListener(this::onDomainLifecycleChange); conn.addLifecycleListener(this::onDomainLifecycleChange);
@ -3727,7 +3713,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
* Checking for this helps us differentiate between events where cloudstack or admin stopped the VM vs guest * Checking for this helps us differentiate between events where cloudstack or admin stopped the VM vs guest
* initiated, and avoid pushing extra updates for actions we are initiating without a need for extra tracking */ * initiated, and avoid pushing extra updates for actions we are initiating without a need for extra tracking */
DomainEventDetail detail = domainEvent.getDetail(); DomainEventDetail detail = domainEvent.getDetail();
if (StoppedDetail.SHUTDOWN.equals(detail) || StoppedDetail.CRASHED.equals(detail)) { if (StoppedDetail.SHUTDOWN.equals(detail) || StoppedDetail.CRASHED.equals(detail) || StoppedDetail.FAILED.equals(detail)) {
s_logger.info("Triggering out of band status update due to completed self-shutdown or crash of VM"); s_logger.info("Triggering out of band status update due to completed self-shutdown or crash of VM");
_agentStatusUpdater.triggerUpdate(); _agentStatusUpdater.triggerUpdate();
} else { } else {

View File

@ -23,6 +23,7 @@ import com.cloud.agent.properties.AgentProperties;
import com.cloud.agent.properties.AgentPropertiesFileHandler; import com.cloud.agent.properties.AgentPropertiesFileHandler;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.libvirt.Connect; import org.libvirt.Connect;
import org.libvirt.Library;
import org.libvirt.LibvirtException; import org.libvirt.LibvirtException;
import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor;
@ -34,6 +35,7 @@ public class LibvirtConnection {
static private Connect s_connection; static private Connect s_connection;
static private String s_hypervisorURI; static private String s_hypervisorURI;
static private Thread libvirtEventThread;
static public Connect getConnection() throws LibvirtException { static public Connect getConnection() throws LibvirtException {
return getConnection(s_hypervisorURI); return getConnection(s_hypervisorURI);
@ -45,6 +47,8 @@ public class LibvirtConnection {
if (conn == null) { if (conn == null) {
s_logger.info("No existing libvirtd connection found. Opening a new one"); s_logger.info("No existing libvirtd connection found. Opening a new one");
setupEventListener();
conn = new Connect(hypervisorURI, false); conn = new Connect(hypervisorURI, false);
s_logger.debug("Successfully connected to libvirt at: " + hypervisorURI); s_logger.debug("Successfully connected to libvirt at: " + hypervisorURI);
s_connections.put(hypervisorURI, conn); s_connections.put(hypervisorURI, conn);
@ -53,7 +57,15 @@ public class LibvirtConnection {
conn.getVersion(); conn.getVersion();
} catch (LibvirtException e) { } catch (LibvirtException e) {
s_logger.error("Connection with libvirtd is broken: " + e.getMessage()); s_logger.error("Connection with libvirtd is broken: " + e.getMessage());
try {
conn.close();
} catch (LibvirtException closeEx) {
s_logger.debug("Ignoring error while trying to close broken connection:" + closeEx.getMessage());
}
s_logger.debug("Opening a new libvirtd connection to: " + hypervisorURI); s_logger.debug("Opening a new libvirtd connection to: " + hypervisorURI);
setupEventListener();
conn = new Connect(hypervisorURI, false); conn = new Connect(hypervisorURI, false);
s_connections.put(hypervisorURI, conn); s_connections.put(hypervisorURI, conn);
} }
@ -101,4 +113,33 @@ public class LibvirtConnection {
return "qemu:///system"; return "qemu:///system";
} }
/**
* Set up Libvirt event handling and polling. This is not specific to a connection object instance, but needs
* to be done prior to creating connections. See the Libvirt documentation for virEventRegisterDefaultImpl and
* virEventRunDefaultImpl or the libvirt-java Library Javadoc for more information.
* @throws LibvirtException
*/
private static synchronized void setupEventListener() throws LibvirtException {
if (libvirtEventThread == null || !libvirtEventThread.isAlive()) {
// Registers a default event loop, must be called before connecting to hypervisor
Library.initEventLoop();
libvirtEventThread = new Thread(() -> {
while (true) {
try {
// This blocking call contains a loop of its own that will process events until the event loop is stopped or exception is thrown.
Library.runEventLoop();
} catch (LibvirtException e) {
s_logger.error("LibvirtException was thrown in event loop: ", e);
} catch (InterruptedException e) {
s_logger.error("Libvirt event loop was interrupted: ", e);
}
}
});
// Process events in separate thread. Failure to run event loop regularly will cause connections to close due to keepalive timeout.
libvirtEventThread.setDaemon(true);
libvirtEventThread.start();
}
}
} }

View File

@ -117,6 +117,8 @@ SP_API_HTTP - address of StorPool Api
SP_AUTH_TOKEN - StorPool's token SP_AUTH_TOKEN - StorPool's token
SP_TEMPLATE - name of StorPool's template SP_TEMPLATE - name of StorPool's template
> **NOTE:** You can use the alternative format option for the URL - storpool://{SP_AUTH_TOKEN}@{SP_API_HTTP}:{SP_API_HTTP_PORT}/{SP_TEMPLATE}
Storage Tags: If left blank, the StorPool storage plugin will use the pool name to create a corresponding storage tag. Storage Tags: If left blank, the StorPool storage plugin will use the pool name to create a corresponding storage tag.
This storage tag may be used later, when defining service or disk offerings. This storage tag may be used later, when defining service or disk offerings.

View File

@ -172,6 +172,12 @@ public class StorPoolUtil {
private String templateName; private String templateName;
public SpConnectionDesc(String url) { public SpConnectionDesc(String url) {
try {
extractUriParams(url);
return;
} catch (URISyntaxException e) {
log.debug("[ignore] the uri is not valid");
}
String[] urlSplit = url.split(";"); String[] urlSplit = url.split(";");
if (urlSplit.length == 1 && !urlSplit[0].contains("=")) { if (urlSplit.length == 1 && !urlSplit[0].contains("=")) {
this.templateName = url; this.templateName = url;
@ -240,6 +246,16 @@ public class StorPoolUtil {
} }
} }
private void extractUriParams(String url) throws URISyntaxException {
URI uri = new URI(url);
if (!StringUtils.equalsIgnoreCase(uri.getScheme(), "storpool")) {
throw new CloudRuntimeException("The scheme is invalid. The URL should be with a format storpool://{SP_AUTH_TOKEN}@{SP_API_HTTP}:{SP_API_HTTP_PORT}/{SP_TEMPLATE}");
}
hostPort = uri.getHost() + ":" + uri.getPort();
authToken = uri.getUserInfo();
templateName = uri.getPath().replace("/", "");
}
public SpConnectionDesc(String host, String authToken2, String templateName2) { public SpConnectionDesc(String host, String authToken2, String templateName2) {
this.hostPort = host; this.hostPort = host;
this.authToken = authToken2; this.authToken = authToken2;

View File

@ -727,7 +727,7 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi
if ((alertType != AlertManager.AlertType.ALERT_TYPE_HOST) && (alertType != AlertManager.AlertType.ALERT_TYPE_USERVM) if ((alertType != AlertManager.AlertType.ALERT_TYPE_HOST) && (alertType != AlertManager.AlertType.ALERT_TYPE_USERVM)
&& (alertType != AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER) && (alertType != AlertManager.AlertType.ALERT_TYPE_CONSOLE_PROXY) && (alertType != AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER) && (alertType != AlertManager.AlertType.ALERT_TYPE_CONSOLE_PROXY)
&& (alertType != AlertManager.AlertType.ALERT_TYPE_SSVM) && (alertType != AlertManager.AlertType.ALERT_TYPE_STORAGE_MISC) && (alertType != AlertManager.AlertType.ALERT_TYPE_SSVM) && (alertType != AlertManager.AlertType.ALERT_TYPE_STORAGE_MISC)
&& (alertType != AlertManager.AlertType.ALERT_TYPE_MANAGMENT_NODE) && (alertType != AlertManager.AlertType.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED) && (alertType != AlertManager.AlertType.ALERT_TYPE_MANAGEMENT_NODE) && (alertType != AlertManager.AlertType.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED)
&& (alertType != AlertManager.AlertType.ALERT_TYPE_UPLOAD_FAILED) && (alertType != AlertManager.AlertType.ALERT_TYPE_OOBM_AUTH_ERROR) && (alertType != AlertManager.AlertType.ALERT_TYPE_UPLOAD_FAILED) && (alertType != AlertManager.AlertType.ALERT_TYPE_OOBM_AUTH_ERROR)
&& (alertType != AlertManager.AlertType.ALERT_TYPE_HA_ACTION) && (alertType != AlertManager.AlertType.ALERT_TYPE_CA_CERT)) { && (alertType != AlertManager.AlertType.ALERT_TYPE_HA_ACTION) && (alertType != AlertManager.AlertType.ALERT_TYPE_CA_CERT)) {
alert = _alertDao.getLastAlert(alertType.getType(), dataCenterId, podId, clusterId); alert = _alertDao.getLastAlert(alertType.getType(), dataCenterId, podId, clusterId);

View File

@ -70,7 +70,7 @@ public class ClusterAlertAdapter extends AdapterBase implements AlertAdapter {
s_logger.debug("Management server node " + mshost.getServiceIP() + " is up, send alert"); s_logger.debug("Management server node " + mshost.getServiceIP() + " is up, send alert");
} }
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_MANAGMENT_NODE, 0, new Long(0), "Management server node " + mshost.getServiceIP() + " is up", ""); _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_MANAGEMENT_NODE, 0, new Long(0), "Management server node " + mshost.getServiceIP() + " is up", "");
break; break;
} }
} }
@ -90,7 +90,7 @@ public class ClusterAlertAdapter extends AdapterBase implements AlertAdapter {
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
s_logger.debug("Detected management server node " + mshost.getServiceIP() + " is down, send alert"); s_logger.debug("Detected management server node " + mshost.getServiceIP() + " is down, send alert");
} }
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_MANAGMENT_NODE, 0, new Long(0), "Management server node " + mshost.getServiceIP() + " is down", _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_MANAGEMENT_NODE, 0, new Long(0), "Management server node " + mshost.getServiceIP() + " is down",
""); "");
} else { } else {
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {

View File

@ -651,12 +651,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
if (localCidrs != null && localCidrs.length > 0) { if (localCidrs != null && localCidrs.length > 0) {
s_logger.warn("Management network CIDR is not configured originally. Set it default to " + localCidrs[0]); s_logger.warn("Management network CIDR is not configured originally. Set it default to " + localCidrs[0]);
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_MANAGMENT_NODE, 0, new Long(0), "Management network CIDR is not configured originally. Set it default to " _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_MANAGEMENT_NODE, 0, new Long(0), "Management network CIDR is not configured originally. Set it default to "
+ localCidrs[0], ""); + localCidrs[0], "");
_configDao.update(Config.ManagementNetwork.key(), Config.ManagementNetwork.getCategory(), localCidrs[0]); _configDao.update(Config.ManagementNetwork.key(), Config.ManagementNetwork.getCategory(), localCidrs[0]);
} else { } else {
s_logger.warn("Management network CIDR is not properly configured and we are not able to find a default setting"); s_logger.warn("Management network CIDR is not properly configured and we are not able to find a default setting");
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_MANAGMENT_NODE, 0, new Long(0), _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_MANAGEMENT_NODE, 0, new Long(0),
"Management network CIDR is not properly configured and we are not able to find a default setting", ""); "Management network CIDR is not properly configured and we are not able to find a default setting", "");
} }
} }

View File

@ -3261,6 +3261,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
} }
@Override @Override
@ActionEvent(eventType = EventTypes.EVENT_UPDATE_IMAGE_STORE_ACCESS_STATE,
eventDescription = "image store access updated")
public ImageStore updateImageStoreStatus(Long id, Boolean readonly) { public ImageStore updateImageStoreStatus(Long id, Boolean readonly) {
// Input validation // Input validation
ImageStoreVO imageStoreVO = _imageStoreDao.findById(id); ImageStoreVO imageStoreVO = _imageStoreDao.findById(id);

View File

@ -354,6 +354,7 @@ import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction; import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallbackNoReturn; import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionCallbackWithException;
import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn; import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn;
import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.db.UUIDManager; import com.cloud.utils.db.UUIDManager;
@ -7765,49 +7766,68 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
List<Volume> newVols = new ArrayList<>(); List<Volume> newVols = new ArrayList<>();
for (VolumeVO root : rootVols) { for (VolumeVO root : rootVols) {
if ( !Volume.State.Allocated.equals(root.getState()) || newTemplateId != null ){ if ( !Volume.State.Allocated.equals(root.getState()) || newTemplateId != null ) {
Long templateId = root.getTemplateId(); final UserVmVO userVm = vm;
boolean isISO = false; Pair<UserVmVO, Volume> vmAndNewVol = Transaction.execute(new TransactionCallbackWithException<Pair<UserVmVO, Volume>, CloudRuntimeException>() {
if (templateId == null) { @Override
// Assuming that for a vm deployed using ISO, template ID is set to NULL public Pair<UserVmVO, Volume> doInTransaction(final TransactionStatus status) throws CloudRuntimeException {
isISO = true; Long templateId = root.getTemplateId();
templateId = vm.getIsoId(); boolean isISO = false;
} if (templateId == null) {
// Assuming that for a vm deployed using ISO, template ID is set to NULL
isISO = true;
templateId = userVm.getIsoId();
}
/* If new template/ISO is provided allocate a new volume from new template/ISO otherwise allocate new volume from original template/ISO */ /* If new template/ISO is provided allocate a new volume from new template/ISO otherwise allocate new volume from original template/ISO */
Volume newVol = null; Volume newVol = null;
if (newTemplateId != null) { if (newTemplateId != null) {
if (isISO) { if (isISO) {
newVol = volumeMgr.allocateDuplicateVolume(root, null); newVol = volumeMgr.allocateDuplicateVolume(root, null);
vm.setIsoId(newTemplateId); userVm.setIsoId(newTemplateId);
vm.setGuestOSId(template.getGuestOSId()); userVm.setGuestOSId(template.getGuestOSId());
vm.setTemplateId(newTemplateId); userVm.setTemplateId(newTemplateId);
} else { } else {
newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId);
vm.setGuestOSId(template.getGuestOSId()); userVm.setGuestOSId(template.getGuestOSId());
vm.setTemplateId(newTemplateId); userVm.setTemplateId(newTemplateId);
}
// check and update VM if it can be dynamically scalable with the new template
updateVMDynamicallyScalabilityUsingTemplate(userVm, newTemplateId);
} else {
newVol = volumeMgr.allocateDuplicateVolume(root, null);
}
newVols.add(newVol);
if (userVmDetailsDao.findDetail(userVm.getId(), VmDetailConstants.ROOT_DISK_SIZE) == null && !newVol.getSize().equals(template.getSize())) {
VolumeVO resizedVolume = (VolumeVO) newVol;
if (template.getSize() != null) {
resizedVolume.setSize(template.getSize());
_volsDao.update(resizedVolume.getId(), resizedVolume);
}
}
// 1. Save usage event and update resource count for user vm volumes
try {
_resourceLimitMgr.incrementResourceCount(newVol.getAccountId(), ResourceType.volume, newVol.isDisplay());
_resourceLimitMgr.incrementResourceCount(newVol.getAccountId(), ResourceType.primary_storage, newVol.isDisplay(), new Long(newVol.getSize()));
} catch (final CloudRuntimeException e) {
throw e;
} catch (final Exception e) {
s_logger.error("Unable to restore VM " + userVm.getUuid(), e);
throw new CloudRuntimeException(e);
}
// 2. Create Usage event for the newly created volume
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, newVol.getAccountId(), newVol.getDataCenterId(), newVol.getId(), newVol.getName(), newVol.getDiskOfferingId(), template.getId(), newVol.getSize());
_usageEventDao.persist(usageEvent);
return new Pair<>(userVm, newVol);
} }
// check and update VM if it can be dynamically scalable with the new template });
updateVMDynamicallyScalabilityUsingTemplate(vm, newTemplateId);
} else {
newVol = volumeMgr.allocateDuplicateVolume(root, null);
}
newVols.add(newVol);
if (userVmDetailsDao.findDetail(vm.getId(), VmDetailConstants.ROOT_DISK_SIZE) == null && !newVol.getSize().equals(template.getSize())) { vm = vmAndNewVol.first();
VolumeVO resizedVolume = (VolumeVO) newVol; Volume newVol = vmAndNewVol.second();
if (template.getSize() != null) {
resizedVolume.setSize(template.getSize());
_volsDao.update(resizedVolume.getId(), resizedVolume);
}
}
// 1. Save usage event and update resource count for user vm volumes
_resourceLimitMgr.incrementResourceCount(newVol.getAccountId(), ResourceType.volume, newVol.isDisplay());
_resourceLimitMgr.incrementResourceCount(newVol.getAccountId(), ResourceType.primary_storage, newVol.isDisplay(), new Long(newVol.getSize()));
// 2. Create Usage event for the newly created volume
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, newVol.getAccountId(), newVol.getDataCenterId(), newVol.getId(), newVol.getName(), newVol.getDiskOfferingId(), template.getId(), newVol.getSize());
_usageEventDao.persist(usageEvent);
handleManagedStorage(vm, root); handleManagedStorage(vm, root);

View File

@ -30,6 +30,7 @@ import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host; import com.cloud.host.Host;
@ -47,6 +48,8 @@ import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.GuestOSVO; import com.cloud.storage.GuestOSVO;
import com.cloud.storage.ScopeType; import com.cloud.storage.ScopeType;
import com.cloud.storage.Snapshot;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage; import com.cloud.storage.Storage;
import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume; import com.cloud.storage.Volume;
@ -54,6 +57,7 @@ import com.cloud.storage.VolumeApiService;
import com.cloud.storage.VolumeVO; import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.dao.VolumeDao;
import com.cloud.template.VirtualMachineTemplate; import com.cloud.template.VirtualMachineTemplate;
@ -66,6 +70,7 @@ import com.cloud.user.UserData;
import com.cloud.user.UserDataVO; import com.cloud.user.UserDataVO;
import com.cloud.user.UserVO; import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.user.dao.UserDataDao; import com.cloud.user.dao.UserDataDao;
import com.cloud.uservm.UserVm; import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
@ -74,10 +79,14 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
import org.apache.cloudstack.api.BaseCmd.HTTPMethod; import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
import org.apache.cloudstack.api.command.user.vm.DeployVMCmd; import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
import org.apache.cloudstack.api.command.user.vm.DeployVnfApplianceCmd; import org.apache.cloudstack.api.command.user.vm.DeployVnfApplianceCmd;
import org.apache.cloudstack.api.command.user.vm.ResetVMUserDataCmd; import org.apache.cloudstack.api.command.user.vm.ResetVMUserDataCmd;
import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd;
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd; import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.context.CallContext;
@ -191,6 +200,9 @@ public class UserVmManagerImplTest {
@Mock @Mock
private AccountDao accountDao; private AccountDao accountDao;
@Mock
private UserDao userDao;
@Mock @Mock
ResourceLimitService resourceLimitMgr; ResourceLimitService resourceLimitMgr;
@ -218,6 +230,12 @@ public class UserVmManagerImplTest {
@Mock @Mock
private VolumeDao volumeDaoMock; private VolumeDao volumeDaoMock;
@Mock
private SnapshotDao snapshotDaoMock;
@Mock
private VMSnapshotDao vmSnapshotDaoMock;
@Mock @Mock
AccountVO account; AccountVO account;
@ -1221,4 +1239,160 @@ public class UserVmManagerImplTest {
Mockito.verify(userVmVoMock).setLastHostId(2L); Mockito.verify(userVmVoMock).setLastHostId(2L);
Mockito.verify(userVmVoMock).setState(VirtualMachine.State.Running); Mockito.verify(userVmVoMock).setState(VirtualMachine.State.Running);
} }
@Test(expected = InvalidParameterValueException.class)
public void testRestoreVMNoVM() throws ResourceUnavailableException, InsufficientCapacityException {
CallContext callContextMock = Mockito.mock(CallContext.class);
Mockito.lenient().doReturn(accountMock).when(callContextMock).getCallingAccount();
RestoreVMCmd cmd = Mockito.mock(RestoreVMCmd.class);
when(cmd.getVmId()).thenReturn(vmId);
when(cmd.getTemplateId()).thenReturn(2L);
when(userVmDao.findById(vmId)).thenReturn(null);
userVmManagerImpl.restoreVM(cmd);
}
@Test(expected = CloudRuntimeException.class)
public void testRestoreVMWithVolumeSnapshots() throws ResourceUnavailableException, InsufficientCapacityException {
CallContext callContextMock = Mockito.mock(CallContext.class);
Mockito.lenient().doReturn(accountMock).when(callContextMock).getCallingAccount();
Mockito.lenient().doNothing().when(accountManager).checkAccess(accountMock, null, true, userVmVoMock);
RestoreVMCmd cmd = Mockito.mock(RestoreVMCmd.class);
when(cmd.getVmId()).thenReturn(vmId);
when(cmd.getTemplateId()).thenReturn(2L);
when(userVmDao.findById(vmId)).thenReturn(userVmVoMock);
List<VolumeVO> volumes = new ArrayList<>();
long rootVolumeId = 1l;
VolumeVO rootVolumeOfVm = Mockito.mock(VolumeVO.class);
Mockito.when(rootVolumeOfVm.getId()).thenReturn(rootVolumeId);
volumes.add(rootVolumeOfVm);
when(volumeDaoMock.findByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(volumes);
List<SnapshotVO> snapshots = new ArrayList<>();
SnapshotVO snapshot = Mockito.mock(SnapshotVO.class);
snapshots.add(snapshot);
when(snapshotDaoMock.listByStatus(rootVolumeId, Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp)).thenReturn(snapshots);
userVmManagerImpl.restoreVM(cmd);
}
@Test(expected = InvalidParameterValueException.class)
public void testRestoreVirtualMachineNoOwner() throws ResourceUnavailableException, InsufficientCapacityException {
long userId = 1l;
long accountId = 2l;
long newTemplateId = 2l;
when(accountMock.getId()).thenReturn(userId);
when(userVmDao.findById(vmId)).thenReturn(userVmVoMock);
when(userVmVoMock.getAccountId()).thenReturn(accountId);
when(accountDao.findById(accountId)).thenReturn(null);
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
}
@Test(expected = PermissionDeniedException.class)
public void testRestoreVirtualMachineOwnerDisabled() throws ResourceUnavailableException, InsufficientCapacityException {
long userId = 1l;
long accountId = 2l;
long newTemplateId = 2l;
when(accountMock.getId()).thenReturn(userId);
when(userVmDao.findById(vmId)).thenReturn(userVmVoMock);
when(userVmVoMock.getAccountId()).thenReturn(accountId);
when(accountDao.findById(accountId)).thenReturn(callerAccount);
when(callerAccount.getState()).thenReturn(Account.State.DISABLED);
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
}
@Test(expected = CloudRuntimeException.class)
public void testRestoreVirtualMachineNotInRightState() throws ResourceUnavailableException, InsufficientCapacityException {
long userId = 1l;
long accountId = 2l;
long newTemplateId = 2l;
when(accountMock.getId()).thenReturn(userId);
when(userVmDao.findById(vmId)).thenReturn(userVmVoMock);
when(userVmVoMock.getAccountId()).thenReturn(accountId);
when(userVmVoMock.getUuid()).thenReturn("a967643d-7633-4ab4-ac26-9c0b63f50cc1");
when(accountDao.findById(accountId)).thenReturn(callerAccount);
when(userVmVoMock.getState()).thenReturn(VirtualMachine.State.Starting);
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
}
@Test(expected = InvalidParameterValueException.class)
public void testRestoreVirtualMachineNoRootVolume() throws ResourceUnavailableException, InsufficientCapacityException {
long userId = 1l;
long accountId = 2l;
long currentTemplateId = 1l;
long newTemplateId = 2l;
when(accountMock.getId()).thenReturn(userId);
when(userVmDao.findById(vmId)).thenReturn(userVmVoMock);
when(userVmVoMock.getAccountId()).thenReturn(accountId);
when(userVmVoMock.getUuid()).thenReturn("a967643d-7633-4ab4-ac26-9c0b63f50cc1");
when(accountDao.findById(accountId)).thenReturn(callerAccount);
when(userVmVoMock.getState()).thenReturn(VirtualMachine.State.Running);
when(userVmVoMock.getTemplateId()).thenReturn(currentTemplateId);
VMTemplateVO currentTemplate = Mockito.mock(VMTemplateVO.class);
when(templateDao.findById(currentTemplateId)).thenReturn(currentTemplate);
when(volumeDaoMock.findByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(new ArrayList<VolumeVO>());
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
}
@Test(expected = InvalidParameterValueException.class)
public void testRestoreVirtualMachineMoreThanOneRootVolume() throws ResourceUnavailableException, InsufficientCapacityException {
long userId = 1l;
long accountId = 2l;
long currentTemplateId = 1l;
long newTemplateId = 2l;
when(accountMock.getId()).thenReturn(userId);
when(userVmDao.findById(vmId)).thenReturn(userVmVoMock);
when(userVmVoMock.getAccountId()).thenReturn(accountId);
when(userVmVoMock.getUuid()).thenReturn("a967643d-7633-4ab4-ac26-9c0b63f50cc1");
when(accountDao.findById(accountId)).thenReturn(callerAccount);
when(userVmVoMock.getState()).thenReturn(VirtualMachine.State.Running);
when(userVmVoMock.getTemplateId()).thenReturn(currentTemplateId);
VMTemplateVO currentTemplate = Mockito.mock(VMTemplateVO.class);
when(currentTemplate.isDeployAsIs()).thenReturn(false);
when(templateDao.findById(currentTemplateId)).thenReturn(currentTemplate);
List<VolumeVO> volumes = new ArrayList<>();
VolumeVO rootVolume1 = Mockito.mock(VolumeVO.class);
volumes.add(rootVolume1);
VolumeVO rootVolume2 = Mockito.mock(VolumeVO.class);
volumes.add(rootVolume2);
when(volumeDaoMock.findByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(volumes);
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
}
@Test(expected = InvalidParameterValueException.class)
public void testRestoreVirtualMachineWithVMSnapshots() throws ResourceUnavailableException, InsufficientCapacityException {
long userId = 1l;
long accountId = 2l;
long currentTemplateId = 1l;
long newTemplateId = 2l;
when(accountMock.getId()).thenReturn(userId);
when(userVmDao.findById(vmId)).thenReturn(userVmVoMock);
when(userVmVoMock.getAccountId()).thenReturn(accountId);
when(accountDao.findById(accountId)).thenReturn(callerAccount);
when(userVmVoMock.getState()).thenReturn(VirtualMachine.State.Running);
when(userVmVoMock.getTemplateId()).thenReturn(currentTemplateId);
VMTemplateVO currentTemplate = Mockito.mock(VMTemplateVO.class);
when(templateDao.findById(currentTemplateId)).thenReturn(currentTemplate);
List<VolumeVO> volumes = new ArrayList<>();
VolumeVO rootVolumeOfVm = Mockito.mock(VolumeVO.class);
volumes.add(rootVolumeOfVm);
when(volumeDaoMock.findByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(volumes);
List<VMSnapshotVO> vmSnapshots = new ArrayList<>();
VMSnapshotVO vmSnapshot = Mockito.mock(VMSnapshotVO.class);
vmSnapshots.add(vmSnapshot);
when(vmSnapshotDaoMock.findByVm(vmId)).thenReturn(vmSnapshots);
userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
}
} }

View File

@ -340,7 +340,7 @@
<template v-if="column.key === 'softwareversion'"> <template v-if="column.key === 'softwareversion'">
<span> {{ record.softwareversion ? record.softwareversion : 'N/A' }} </span> <span> {{ record.softwareversion ? record.softwareversion : 'N/A' }} </span>
</template> </template>
<template v-if="column.key === 'access'"> <template v-if="column.key === 'readonly'">
<status :text="record.readonly ? 'ReadOnly' : 'ReadWrite'" displayText /> <status :text="record.readonly ? 'ReadOnly' : 'ReadWrite'" displayText />
</template> </template>
<template v-if="column.key === 'requiresupgrade'"> <template v-if="column.key === 'requiresupgrade'">

View File

@ -83,7 +83,7 @@ public class UsageAlertManagerImpl extends ManagerBase implements AlertManager {
if ((alertType != AlertManager.AlertType.ALERT_TYPE_HOST) && (alertType != AlertManager.AlertType.ALERT_TYPE_USERVM) if ((alertType != AlertManager.AlertType.ALERT_TYPE_HOST) && (alertType != AlertManager.AlertType.ALERT_TYPE_USERVM)
&& (alertType != AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER) && (alertType != AlertManager.AlertType.ALERT_TYPE_CONSOLE_PROXY) && (alertType != AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER) && (alertType != AlertManager.AlertType.ALERT_TYPE_CONSOLE_PROXY)
&& (alertType != AlertManager.AlertType.ALERT_TYPE_SSVM) && (alertType != AlertManager.AlertType.ALERT_TYPE_STORAGE_MISC) && (alertType != AlertManager.AlertType.ALERT_TYPE_SSVM) && (alertType != AlertManager.AlertType.ALERT_TYPE_STORAGE_MISC)
&& (alertType != AlertManager.AlertType.ALERT_TYPE_MANAGMENT_NODE)) { && (alertType != AlertManager.AlertType.ALERT_TYPE_MANAGEMENT_NODE)) {
alert = _alertDao.getLastAlert(alertType.getType(), dataCenterId, podId); alert = _alertDao.getLastAlert(alertType.getType(), dataCenterId, podId);
} }
if (alert == null) { if (alert == null) {