mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge remote-tracking branch 'origin/4.19'
This commit is contained in:
commit
25009bfb76
@ -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
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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 {
|
||||||
|
|||||||
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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.
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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()) {
|
||||||
|
|||||||
@ -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", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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'">
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user