package org.zstack.compute.vm;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.db.*;
import org.zstack.core.db.SimpleQuery.Op;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.header.allocator.HostCapacityVO;
import org.zstack.header.allocator.HostCapacityVO_;
import org.zstack.header.apimediator.ApiMessageInterceptionException;
import org.zstack.header.apimediator.ApiMessageInterceptor;
import org.zstack.header.apimediator.StopRoutingException;
import org.zstack.header.cluster.ClusterState;
import org.zstack.header.cluster.ClusterVO;
import org.zstack.header.cluster.ClusterVO_;
import org.zstack.header.configuration.*;
import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.header.host.HostState;
import org.zstack.header.host.HostStatus;
import org.zstack.header.host.HostVO;
import org.zstack.header.host.HostVO_;
import org.zstack.header.image.ImageConstant.ImageMediaType;
import org.zstack.header.image.ImagePlatform;
import org.zstack.header.image.ImageState;
import org.zstack.header.image.ImageVO;
import org.zstack.header.image.ImageVO_;
import org.zstack.header.message.APIMessage;
import org.zstack.header.network.l3.*;
import org.zstack.header.vm.*;
import org.zstack.header.zone.ZoneState;
import org.zstack.header.zone.ZoneVO;
import org.zstack.header.zone.ZoneVO_;
import org.zstack.utils.SizeUtils;
import org.zstack.utils.data.SizeUnit;
import org.zstack.utils.network.NetworkUtils;
import static org.zstack.core.Platform.argerr;
import static org.zstack.core.Platform.operr;
import static org.zstack.utils.CollectionDSL.list;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import java.util.*;
/**
* Created with IntelliJ IDEA.
* User: frank
* Time: 9:55 PM
* To change this template use File | Settings | File Templates.
*/
public class VmInstanceApiInterceptor implements ApiMessageInterceptor {
@Autowired
private CloudBus bus;
@Autowired
private DatabaseFacade dbf;
@Autowired
private ErrorFacade errf;
private void setServiceId(APIMessage msg) {
if (msg instanceof VmInstanceMessage) {
VmInstanceMessage vmsg = (VmInstanceMessage) msg;
bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, vmsg.getVmInstanceUuid());
}
}
@Override
public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionException {
if (msg instanceof APIDestroyVmInstanceMsg) {
validate((APIDestroyVmInstanceMsg) msg);
} else if (msg instanceof APICreateVmInstanceMsg) {
validate((APICreateVmInstanceMsg) msg);
} else if (msg instanceof APIGetVmAttachableDataVolumeMsg) {
validate((APIGetVmAttachableDataVolumeMsg) msg);
} else if (msg instanceof APIDetachL3NetworkFromVmMsg) {
validate((APIDetachL3NetworkFromVmMsg) msg);
} else if (msg instanceof APIAttachL3NetworkToVmMsg) {
validate((APIAttachL3NetworkToVmMsg) msg);
} else if (msg instanceof APIAttachIsoToVmInstanceMsg) {
validate((APIAttachIsoToVmInstanceMsg) msg);
} else if (msg instanceof APISetVmBootOrderMsg) {
validate((APISetVmBootOrderMsg) msg);
} else if (msg instanceof APIDeleteVmStaticIpMsg) {
validate((APIDeleteVmStaticIpMsg) msg);
} else if (msg instanceof APISetVmStaticIpMsg) {
validate((APISetVmStaticIpMsg) msg);
} else if (msg instanceof APIStartVmInstanceMsg) {
validate((APIStartVmInstanceMsg) msg);
} else if (msg instanceof APICreateStartVmInstanceSchedulerMsg) {
validate((APICreateStartVmInstanceSchedulerMsg) msg);
} else if (msg instanceof APICreateStopVmInstanceSchedulerMsg) {
validate((APICreateStopVmInstanceSchedulerMsg) msg);
} else if (msg instanceof APICreateRebootVmInstanceSchedulerMsg) {
validate((APICreateRebootVmInstanceSchedulerMsg) msg);
} else if (msg instanceof APIGetInterdependentL3NetworksImagesMsg) {
validate((APIGetInterdependentL3NetworksImagesMsg) msg);
} else if (msg instanceof APIUpdateVmInstanceMsg) {
validate((APIUpdateVmInstanceMsg) msg);
} else if (msg instanceof APISetVmConsolePasswordMsg) {
validate((APISetVmConsolePasswordMsg) msg);
} else if (msg instanceof APIChangeInstanceOfferingMsg) {
validate((APIChangeInstanceOfferingMsg) msg);
}
setServiceId(msg);
return msg;
}
private void validate(APIChangeInstanceOfferingMsg msg) {
new SQLBatch() {
@Override
protected void scripts() {
VmInstanceVO vo = Q.New(VmInstanceVO.class).eq(VmInstanceVO_.uuid, msg.getVmInstanceUuid()).find();
InstanceOfferingVO instanceOfferingVO = Q.New(InstanceOfferingVO.class).eq(InstanceOfferingVO_.uuid, msg.getInstanceOfferingUuid()).find();
if (!VmGlobalConfig.NUMA.value(Boolean.class) && !VmInstanceState.Stopped.equals(vo.getState())) {
throw new ApiMessageInterceptionException(argerr(
"the VM cannot do online cpu/memory update because it is not of NUMA architecture. Please stop the VM then do the cpu/memory update again"
));
}
if (!VmInstanceState.Stopped.equals(vo.getState()) && !VmInstanceState.Running.equals(vo.getState())) {
throw new OperationFailureException(operr("The state of vm[uuid:%s] is %s. Only these state[%s] is allowed to update cpu or memory.",
vo.getUuid(), vo.getState(),
StringUtils.join(list(VmInstanceState.Running, VmInstanceState.Stopped), ",")));
}
if (VmInstanceState.Stopped.equals(vo.getState())) {
return;
}
if (instanceOfferingVO.getCpuNum() < vo.getCpuNum() || instanceOfferingVO.getMemorySize() < vo.getMemorySize()) {
throw new ApiMessageInterceptionException(argerr(
"can't not decrease capacity when vm[:uuid] is running", vo.getUuid()
));
}
}
}.execute();
}
private void validate(APIUpdateVmInstanceMsg msg) {
new SQLBatch() {
@Override
protected void scripts() {
VmInstanceVO vo = Q.New(VmInstanceVO.class).eq(VmInstanceVO_.uuid, msg.getVmInstanceUuid()).find();
Integer cpuSum = msg.getCpuNum();
Long memorySize = msg.getMemorySize();
if ((cpuSum == null && memorySize == null)) {
return;
}
VmInstanceState vmState = Q.New(VmInstanceVO.class).select(VmInstanceVO_.state).eq(VmInstanceVO_.uuid, msg.getVmInstanceUuid()).findValue();
if (!VmGlobalConfig.NUMA.value(Boolean.class) && !VmInstanceState.Stopped.equals(vmState)) {
throw new ApiMessageInterceptionException(argerr(
"the VM cannot do online cpu/memory update because it is not of NUMA architecture. Please stop the VM then do the cpu/memory update again"
));
}
if (!VmInstanceState.Stopped.equals(vo.getState()) && !VmInstanceState.Running.equals(vo.getState())) {
throw new OperationFailureException(operr("The state of vm[uuid:%s] is %s. Only these state[%s] is allowed to update cpu or memory.",
vo.getUuid(), vo.getState(),
StringUtils.join(list(VmInstanceState.Running, VmInstanceState.Stopped), ",")));
}
if (VmInstanceState.Stopped.equals(vmState)) {
return;
}
if (msg.getCpuNum() != null && msg.getCpuNum() < vo.getCpuNum()) {
throw new ApiMessageInterceptionException(argerr(
"can't not decrease cpu of vm[:uuid] when it is running", vo.getUuid()
));
}
if (msg.getMemorySize() != null && msg.getMemorySize() < vo.getMemorySize()) {
throw new ApiMessageInterceptionException(argerr(
"can't not decrease memory size of vm[:uuid] when it is running", vo.getUuid()
));
}
}
}.execute();
}
private void validate(APIGetInterdependentL3NetworksImagesMsg msg) {
if (msg.getL3NetworkUuids() == null && msg.getImageUuid() == null) {
throw new ApiMessageInterceptionException(argerr(
"either l3NetworkUuids or imageUuid must be set"
));
}
}
private void validate(APIStartVmInstanceMsg msg) {
// host uuid overrides cluster uuid
if (msg.getHostUuid() != null) {
msg.setClusterUuid(null);
}
}
private void validate(APICreateStartVmInstanceSchedulerMsg msg) {
// host uuid overrides cluster uuid
if (msg.getHostUuid() != null) {
msg.setClusterUuid(null);
}
SimpleQuery<VmInstanceVO> q = dbf.createQuery(VmInstanceVO.class);
q.select(VmInstanceVO_.state);
q.add(VmInstanceVO_.uuid, Op.EQ, msg.getVmInstanceUuid());
VmInstanceState state = q.findValue();
if (state == VmInstanceState.Destroyed) {
throw new ApiMessageInterceptionException(operr("vm[uuid:%s] can only create scheduler when state is not Destroyed", msg.getVmInstanceUuid()));
}
}
private void validate(APICreateStopVmInstanceSchedulerMsg msg) {
SimpleQuery<VmInstanceVO> q = dbf.createQuery(VmInstanceVO.class);
q.select(VmInstanceVO_.state);
q.add(VmInstanceVO_.uuid, Op.EQ, msg.getVmInstanceUuid());
VmInstanceState state = q.findValue();
if (state == VmInstanceState.Destroyed) {
throw new ApiMessageInterceptionException(operr("vm[uuid:%s] can only create scheduler when state is not Destroyed", msg.getVmInstanceUuid()));
}
}
private void validate(APICreateRebootVmInstanceSchedulerMsg msg) {
SimpleQuery<VmInstanceVO> q = dbf.createQuery(VmInstanceVO.class);
q.select(VmInstanceVO_.state);
q.add(VmInstanceVO_.uuid, Op.EQ, msg.getVmInstanceUuid());
VmInstanceState state = q.findValue();
if (state == VmInstanceState.Destroyed) {
throw new ApiMessageInterceptionException(operr("vm[uuid:%s] can only create scheduler when state is not Destroyed", msg.getVmInstanceUuid()));
}
}
private void validate(APISetVmStaticIpMsg msg) {
if (!NetworkUtils.isIpv4Address(msg.getIp())) {
throw new ApiMessageInterceptionException(argerr("%s is not a valid IPv4 address", msg.getIp()));
}
SimpleQuery<VmNicVO> q = dbf.createQuery(VmNicVO.class);
q.add(VmNicVO_.vmInstanceUuid, Op.EQ, msg.getVmInstanceUuid());
q.add(VmNicVO_.l3NetworkUuid, Op.EQ, msg.getL3NetworkUuid());
if (!q.isExists()) {
throw new ApiMessageInterceptionException(argerr("the VM[uuid:%s] has no nic on the L3 network[uuid:%s]", msg.getVmInstanceUuid(),
msg.getL3NetworkUuid()));
}
}
private void validate(APIDeleteVmStaticIpMsg msg) {
SimpleQuery<VmNicVO> q = dbf.createQuery(VmNicVO.class);
q.add(VmNicVO_.vmInstanceUuid, Op.EQ, msg.getVmInstanceUuid());
q.add(VmNicVO_.l3NetworkUuid, Op.EQ, msg.getL3NetworkUuid());
if (!q.isExists()) {
throw new ApiMessageInterceptionException(argerr("the VM[uuid:%s] has no nic on the L3 network[uuid:%s]", msg.getVmInstanceUuid(),
msg.getL3NetworkUuid()));
}
}
private void validate(APISetVmBootOrderMsg msg) {
if (msg.getBootOrder() != null) {
for (String o : msg.getBootOrder()) {
try {
VmBootDevice.valueOf(o);
} catch (IllegalArgumentException e) {
throw new ApiMessageInterceptionException(argerr("invalid boot device[%s] in boot order%s", o, msg.getBootOrder()));
}
}
}
}
private void validate(APIAttachIsoToVmInstanceMsg msg) {
String isoUuid = new IsoOperator().getIsoUuidByVmUuid(msg.getVmInstanceUuid());
if (isoUuid != null) {
throw new ApiMessageInterceptionException(operr("VM[uuid:%s] already has an ISO[uuid:%s] attached", msg.getVmInstanceUuid(), isoUuid));
}
}
private void validate(APIAttachL3NetworkToVmMsg msg) {
SimpleQuery<VmInstanceVO> q = dbf.createQuery(VmInstanceVO.class);
q.select(VmInstanceVO_.type, VmInstanceVO_.state);
q.add(VmInstanceVO_.uuid, Op.EQ, msg.getVmInstanceUuid());
Tuple t = q.findTuple();
String type = t.get(0, String.class);
VmInstanceState state = t.get(1, VmInstanceState.class);
if (!VmInstanceConstant.USER_VM_TYPE.equals(type)) {
throw new ApiMessageInterceptionException(operr("unable to attach a L3 network. The vm[uuid: %s] is not a user vm", type));
}
if (!VmInstanceState.Running.equals(state) && !VmInstanceState.Stopped.equals(state)) {
throw new ApiMessageInterceptionException(operr("unable to detach a L3 network. The vm[uuid: %s] is not Running or Stopped; the current state is %s",
msg.getVmInstanceUuid(), state));
}
SimpleQuery<VmNicVO> nq = dbf.createQuery(VmNicVO.class);
nq.add(VmNicVO_.l3NetworkUuid, Op.EQ, msg.getL3NetworkUuid());
nq.add(VmNicVO_.vmInstanceUuid, Op.EQ, msg.getVmInstanceUuid());
if (nq.isExists()) {
throw new ApiMessageInterceptionException(operr("unable to attach a L3 network. The L3 network[uuid:%s] is already attached to the vm[uuid: %s]",
msg.getL3NetworkUuid(), msg.getVmInstanceUuid()));
}
SimpleQuery<L3NetworkVO> l3q = dbf.createQuery(L3NetworkVO.class);
l3q.select(L3NetworkVO_.state, L3NetworkVO_.system);
l3q.add(L3NetworkVO_.uuid, Op.EQ, msg.getL3NetworkUuid());
t = l3q.findTuple();
L3NetworkState l3state = t.get(0, L3NetworkState.class);
boolean system = t.get(1, Boolean.class);
if (l3state == L3NetworkState.Disabled) {
throw new ApiMessageInterceptionException(operr("unable to attach a L3 network. The L3 network[uuid:%s] is disabled", msg.getL3NetworkUuid()));
}
if (system) {
throw new ApiMessageInterceptionException(operr("unable to attach a L3 network. The L3 network[uuid:%s] is a system network", msg.getL3NetworkUuid()));
}
if (msg.getStaticIp() != null) {
SimpleQuery<IpRangeVO> iprq = dbf.createQuery(IpRangeVO.class);
iprq.add(IpRangeVO_.l3NetworkUuid, Op.EQ, msg.getL3NetworkUuid());
List<IpRangeVO> iprs = iprq.list();
boolean found = false;
for (IpRangeVO ipr : iprs) {
if (NetworkUtils.isIpv4InRange(msg.getStaticIp(), ipr.getStartIp(), ipr.getEndIp())) {
found = true;
break;
}
}
if (!found) {
throw new ApiMessageInterceptionException(argerr("the static IP[%s] is not in any IP range of the L3 network[uuid:%s]", msg.getStaticIp(), msg.getL3NetworkUuid()));
}
SimpleQuery<UsedIpVO> uq = dbf.createQuery(UsedIpVO.class);
uq.add(UsedIpVO_.l3NetworkUuid, Op.EQ, msg.getL3NetworkUuid());
uq.add(UsedIpVO_.ip, Op.EQ, msg.getStaticIp());
if (uq.isExists()) {
throw new ApiMessageInterceptionException(operr("the static IP[%s] has been occupied on the L3 network[uuid:%s]", msg.getStaticIp(), msg.getL3NetworkUuid()));
}
}
}
@Transactional(readOnly = true)
private void validate(APIDetachL3NetworkFromVmMsg msg) {
String sql = "select vm.uuid, vm.type, vm.state from VmInstanceVO vm, VmNicVO nic where vm.uuid = nic.vmInstanceUuid and nic.uuid = :uuid";
TypedQuery<Tuple> q = dbf.getEntityManager().createQuery(sql, Tuple.class);
q.setParameter("uuid", msg.getVmNicUuid());
Tuple t = q.getSingleResult();
String vmUuid = t.get(0, String.class);
String vmType = t.get(1, String.class);
VmInstanceState state = t.get(2, VmInstanceState.class);
if (!VmInstanceConstant.USER_VM_TYPE.equals(vmType)) {
throw new ApiMessageInterceptionException(operr("unable to detach a L3 network. The vm[uuid: %s] is not a user vm", msg.getVmInstanceUuid()));
}
if (!VmInstanceState.Running.equals(state) && !VmInstanceState.Stopped.equals(state)) {
throw new ApiMessageInterceptionException(operr("unable to detach a L3 network. The vm[uuid: %s] is not Running or Stopped; the current state is %s",
msg.getVmInstanceUuid(), state));
}
msg.setVmInstanceUuid(vmUuid);
}
private static <T> List<T> getDuplicateElements(List<T> list) {
List<T> result = new ArrayList<T>();
Set<T> set = new HashSet<T>();
for (T e : list) {
if (!set.add(e)) {
result.add(e);
}
}
return result;
}
private void validate(APIGetVmAttachableDataVolumeMsg msg) {
SimpleQuery<VmInstanceVO> q = dbf.createQuery(VmInstanceVO.class);
q.select(VmInstanceVO_.state);
q.add(VmInstanceVO_.uuid, Op.EQ, msg.getVmInstanceUuid());
VmInstanceState state = q.findValue();
if (state != VmInstanceState.Stopped && state != VmInstanceState.Running) {
throw new ApiMessageInterceptionException(operr("vm[uuid:%s] can only attach volume when state is Running or Stopped, current state is %s", msg.getVmInstanceUuid(), state));
}
}
private void validate(APICreateVmInstanceMsg msg) {
SimpleQuery<InstanceOfferingVO> iq = dbf.createQuery(InstanceOfferingVO.class);
iq.select(InstanceOfferingVO_.state);
iq.add(InstanceOfferingVO_.uuid, Op.EQ, msg.getInstanceOfferingUuid());
InstanceOfferingState istate = iq.findValue();
if (istate == InstanceOfferingState.Disabled) {
throw new ApiMessageInterceptionException(operr("instance offering[uuid:%s] is Disabled, can't create vm from it", msg.getInstanceOfferingUuid()));
}
SimpleQuery<ImageVO> imgq = dbf.createQuery(ImageVO.class);
imgq.select(ImageVO_.state, ImageVO_.system, ImageVO_.mediaType);
imgq.add(ImageVO_.uuid, Op.EQ, msg.getImageUuid());
Tuple imgt = imgq.findTuple();
ImageState imgState = imgt.get(0, ImageState.class);
if (imgState == ImageState.Disabled) {
throw new ApiMessageInterceptionException(operr("image[uuid:%s] is Disabled, can't create vm from it", msg.getImageUuid()));
}
ImageMediaType imgFormat = imgt.get(2, ImageMediaType.class);
if (imgFormat != ImageMediaType.RootVolumeTemplate && imgFormat != ImageMediaType.ISO) {
throw new ApiMessageInterceptionException(argerr("image[uuid:%s] is of mediaType: %s, only RootVolumeTemplate and ISO can be used to create vm", msg.getImageUuid(), imgFormat));
}
if (imgFormat == ImageMediaType.ISO && msg.getRootDiskOfferingUuid() == null) {
throw new ApiMessageInterceptionException(argerr("rootDiskOfferingUuid cannot be null when image mediaType is ISO"));
}
boolean isSystemImage = imgt.get(1, Boolean.class);
if (isSystemImage && (msg.getType() == null || VmInstanceConstant.USER_VM_TYPE.equals(msg.getType()))) {
throw new ApiMessageInterceptionException(argerr("image[uuid:%s] is system image, can't be used to create user vm", msg.getImageUuid()));
}
List<String> allDiskOfferingUuids = new ArrayList<String>();
if (msg.getRootDiskOfferingUuid() != null) {
allDiskOfferingUuids.add(msg.getRootDiskOfferingUuid());
}
if (msg.getDataDiskOfferingUuids() != null) {
allDiskOfferingUuids.addAll(msg.getDataDiskOfferingUuids());
}
if (!allDiskOfferingUuids.isEmpty()) {
SimpleQuery<DiskOfferingVO> dq = dbf.createQuery(DiskOfferingVO.class);
dq.select(DiskOfferingVO_.uuid);
dq.add(DiskOfferingVO_.state, Op.EQ, DiskOfferingState.Disabled);
dq.add(DiskOfferingVO_.uuid, Op.IN, allDiskOfferingUuids);
List<String> diskUuids = dq.listValue();
if (!diskUuids.isEmpty()) {
throw new ApiMessageInterceptionException(operr("disk offerings[uuids:%s] are Disabled, can not create vm from it", diskUuids));
}
}
SimpleQuery<L3NetworkVO> l3q = dbf.createQuery(L3NetworkVO.class);
l3q.select(L3NetworkVO_.uuid, L3NetworkVO_.system, L3NetworkVO_.state);
List<String> uuids = new ArrayList<>(msg.getL3NetworkUuids());
List<String> duplicateElements = getDuplicateElements(uuids);
if (duplicateElements.size() > 0) {
throw new ApiMessageInterceptionException(operr("Can't add same uuid in the l3Network,uuid: %s", duplicateElements.get(0)));
}
l3q.add(L3NetworkVO_.uuid, Op.IN, msg.getL3NetworkUuids());
List<Tuple> l3ts = l3q.listTuple();
for (Tuple t : l3ts) {
String l3Uuid = t.get(0, String.class);
Boolean system = t.get(1, Boolean.class);
L3NetworkState state = t.get(2, L3NetworkState.class);
if (state != L3NetworkState.Enabled) {
throw new ApiMessageInterceptionException(operr("l3Network[uuid:%s] is Disabled, can not create vm on it", l3Uuid));
}
if (system && (msg.getType() == null || VmInstanceConstant.USER_VM_TYPE.equals(msg.getType()))) {
throw new ApiMessageInterceptionException(operr("l3Network[uuid:%s] is system network, can not create user vm on it", l3Uuid));
}
}
// smaller taking precedence
if (msg.getHostUuid() != null) {
msg.setClusterUuid(null);
msg.setZoneUuid(null);
} else if (msg.getClusterUuid() != null) {
msg.setZoneUuid(null);
}
if (msg.getZoneUuid() != null) {
SimpleQuery<ZoneVO> zq = dbf.createQuery(ZoneVO.class);
zq.select(ZoneVO_.state);
zq.add(ZoneVO_.uuid, Op.EQ, msg.getZoneUuid());
ZoneState zoneState = zq.findValue();
if (zoneState == ZoneState.Disabled) {
throw new ApiMessageInterceptionException(operr("zone[uuid:%s] is specified but it's Disabled, can not create vm from it", msg.getZoneUuid()));
}
}
if (msg.getClusterUuid() != null) {
SimpleQuery<ClusterVO> cq = dbf.createQuery(ClusterVO.class);
cq.select(ClusterVO_.state);
cq.add(ClusterVO_.uuid, Op.EQ, msg.getClusterUuid());
ClusterState clusterState = cq.findValue();
if (clusterState == ClusterState.Disabled) {
throw new ApiMessageInterceptionException(operr("cluster[uuid:%s] is specified but it's Disabled, can not create vm from it", msg.getClusterUuid()));
}
}
if (msg.getHostUuid() != null) {
SimpleQuery<HostVO> hq = dbf.createQuery(HostVO.class);
hq.select(HostVO_.state, HostVO_.status);
hq.add(HostVO_.uuid, Op.EQ, msg.getHostUuid());
Tuple t = hq.findTuple();
HostState hostState = t.get(0, HostState.class);
if (hostState == HostState.Disabled) {
throw new ApiMessageInterceptionException(operr("host[uuid:%s] is specified but it's Disabled, can not create vm from it", msg.getHostUuid()));
}
HostStatus connectionState = t.get(1, HostStatus.class);
if (connectionState != HostStatus.Connected) {
throw new ApiMessageInterceptionException(operr("host[uuid:%s] is specified but it's connection status is %s, can not create vm from it", msg.getHostUuid(), connectionState));
}
}
if (msg.getType() == null) {
msg.setType(VmInstanceConstant.USER_VM_TYPE);
}
if (VmInstanceConstant.USER_VM_TYPE.equals(msg.getType())) {
if (msg.getDefaultL3NetworkUuid() == null && msg.getL3NetworkUuids().size() != 1) {
throw new ApiMessageInterceptionException(argerr("there are more than one L3 network specified in l3NetworkUuids, but defaultL3NetworkUuid is null"));
} else if (msg.getDefaultL3NetworkUuid() == null && msg.getL3NetworkUuids().size() == 1) {
msg.setDefaultL3NetworkUuid(msg.getL3NetworkUuids().get(0));
} else if (msg.getDefaultL3NetworkUuid() != null && !msg.getL3NetworkUuids().contains(msg.getDefaultL3NetworkUuid())) {
throw new ApiMessageInterceptionException(argerr("defaultL3NetworkUuid[uuid:%s] is not in l3NetworkUuids%s", msg.getDefaultL3NetworkUuid(), msg.getL3NetworkUuids()));
}
}
}
private void validate(APIDestroyVmInstanceMsg msg) {
if (!dbf.isExist(msg.getUuid(), VmInstanceVO.class)) {
APIDestroyVmInstanceEvent evt = new APIDestroyVmInstanceEvent(msg.getId());
bus.publish(evt);
throw new StopRoutingException();
}
}
private void validate(APISetVmConsolePasswordMsg msg) {
String pwd = msg.getConsolePassword();
if (pwd.startsWith("password")){
throw new ApiMessageInterceptionException(argerr("The console password cannot start with 'password' which may trigger a VNC security issue"));
}
}
}