mirror of https://github.com/apache/cloudstack.git
552 lines
23 KiB
Java
Executable File
552 lines
23 KiB
Java
Executable File
// 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.baremetal;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.concurrent.Executors;
|
|
|
|
import javax.annotation.PostConstruct;
|
|
import javax.ejb.Local;
|
|
import javax.inject.Inject;
|
|
import javax.naming.ConfigurationException;
|
|
|
|
import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd;
|
|
import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
|
|
import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
|
|
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
|
|
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
|
|
import org.apache.log4j.Logger;
|
|
|
|
import com.cloud.agent.api.Answer;
|
|
import com.cloud.agent.api.StopAnswer;
|
|
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
|
|
import com.cloud.agent.api.baremetal.IpmiBootorResetCommand;
|
|
import com.cloud.agent.manager.Commands;
|
|
import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
|
|
|
|
import com.cloud.baremetal.PxeServerManager.PxeServerType;
|
|
import com.cloud.configuration.Resource.ResourceType;
|
|
import com.cloud.configuration.dao.ConfigurationDao;
|
|
import com.cloud.dc.DataCenter.NetworkType;
|
|
import com.cloud.dc.DataCenterVO;
|
|
import com.cloud.deploy.DataCenterDeployment;
|
|
import com.cloud.deploy.DeployDestination;
|
|
import com.cloud.domain.DomainVO;
|
|
import com.cloud.event.EventTypes;
|
|
import com.cloud.event.UsageEventUtils;
|
|
import com.cloud.exception.*;
|
|
import com.cloud.host.Host;
|
|
import com.cloud.host.HostVO;
|
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
|
import com.cloud.network.Network;
|
|
import com.cloud.network.Networks.TrafficType;
|
|
import com.cloud.network.dao.NetworkVO;
|
|
import com.cloud.org.Grouping;
|
|
import com.cloud.resource.ResourceManager;
|
|
import com.cloud.service.ServiceOfferingVO;
|
|
import com.cloud.storage.Storage;
|
|
import com.cloud.storage.Storage.TemplateType;
|
|
import com.cloud.storage.TemplateProfile;
|
|
import com.cloud.storage.VMTemplateVO;
|
|
import com.cloud.storage.Volume;
|
|
import com.cloud.template.TemplateAdapter;
|
|
import com.cloud.template.TemplateAdapter.TemplateAdapterType;
|
|
import com.cloud.user.Account;
|
|
import com.cloud.user.AccountVO;
|
|
import com.cloud.user.SSHKeyPair;
|
|
import com.cloud.user.User;
|
|
import com.cloud.user.UserContext;
|
|
import com.cloud.user.*;
|
|
import com.cloud.uservm.UserVm;
|
|
import com.cloud.utils.NumbersUtil;
|
|
import com.cloud.utils.Pair;
|
|
import com.cloud.utils.component.AdapterBase;
|
|
import com.cloud.utils.component.Manager;
|
|
import com.cloud.utils.concurrency.NamedThreadFactory;
|
|
import com.cloud.utils.db.DB;
|
|
import com.cloud.utils.exception.CloudRuntimeException;
|
|
import com.cloud.utils.fsm.StateListener;
|
|
import com.cloud.utils.net.NetUtils;
|
|
import com.cloud.vm.*;
|
|
import com.cloud.vm.VirtualMachine.Event;
|
|
import com.cloud.vm.VirtualMachine.State;
|
|
import com.cloud.vm.VirtualMachine.Type;
|
|
import com.cloud.vm.VirtualMachineProfile.Param;
|
|
|
|
@Local(value={BareMetalVmManager.class, BareMetalVmService.class})
|
|
public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMetalVmManager, BareMetalVmService,
|
|
StateListener<State, VirtualMachine.Event, VirtualMachine> {
|
|
private static final Logger s_logger = Logger.getLogger(BareMetalVmManagerImpl.class);
|
|
@Inject ConfigurationDao _configDao;
|
|
@Inject PxeServerManager _pxeMgr;
|
|
@Inject ResourceManager _resourceMgr;
|
|
|
|
@Inject protected List<TemplateAdapter> _adapters;
|
|
|
|
@PostConstruct
|
|
public void init() {
|
|
}
|
|
|
|
@Override
|
|
public boolean attachISOToVM(long vmId, long isoId, boolean attach) {
|
|
s_logger.warn("attachISOToVM is not supported by Bare Metal, just fake a true");
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public Volume attachVolumeToVM(AttachVolumeCmd command) {
|
|
s_logger.warn("attachVolumeToVM is not supported by Bare Metal, return null");
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Volume detachVolumeFromVM(DetachVolumeCmd cmd) {
|
|
s_logger.warn("detachVolumeFromVM is not supported by Bare Metal, return null");
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) {
|
|
s_logger.warn("upgradeVirtualMachine is not supported by Bare Metal, return null");
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException {
|
|
/*Baremetal creates record after host rebooting for imaging, in createPrivateTemplate*/
|
|
return null;
|
|
}
|
|
|
|
@Override @DB
|
|
public VMTemplateVO createPrivateTemplate(CreateTemplateCmd cmd) throws CloudRuntimeException {
|
|
Long vmId = cmd.getVmId();
|
|
if (vmId == null) {
|
|
throw new InvalidParameterValueException("VM ID is null");
|
|
}
|
|
|
|
UserVmVO vm = _vmDao.findById(vmId);
|
|
if (vm == null) {
|
|
throw new InvalidParameterValueException("Cannot find VM for ID " + vmId);
|
|
}
|
|
|
|
Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
|
|
HostVO host = _hostDao.findById(hostId);
|
|
if (host == null) {
|
|
throw new InvalidParameterValueException("Cannot find host with id " + hostId);
|
|
}
|
|
|
|
List<HostVO> pxes = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, host.getPodId(), host.getDataCenterId());
|
|
if (pxes.size() == 0) {
|
|
throw new CloudRuntimeException("Please add PXE server in Pod before taking image");
|
|
}
|
|
|
|
if (pxes.size() > 1) {
|
|
CloudRuntimeException ex = new CloudRuntimeException("Multiple PXE servers found in Pod " + host.getPodId() + " in Zone with specified id");
|
|
ex.addProxyObject("data_center", host.getDataCenterId(), "zoneId");
|
|
throw ex;
|
|
}
|
|
|
|
HostVO pxe = pxes.get(0);
|
|
/*
|
|
* prepare() will check if current account has right for creating
|
|
* template
|
|
*/
|
|
TemplateAdapter adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.BareMetal.getName());
|
|
Long userId = UserContext.current().getCallerUserId();
|
|
userId = (userId == null ? User.UID_SYSTEM : userId);
|
|
AccountVO account = _accountDao.findById(vm.getAccountId());
|
|
|
|
try {
|
|
TemplateProfile tmplProfile;
|
|
tmplProfile = adapter.prepare(false, userId, cmd.getTemplateName(), cmd.getDisplayText(), cmd.getBits(), false, false, cmd.getUrl(), cmd.isPublic(), cmd.isFeatured(), false,
|
|
"BareMetal", cmd.getOsTypeId(), pxe.getDataCenterId(), HypervisorType.BareMetal, account.getAccountName(), account.getDomainId(), "0", true, cmd.getDetails());
|
|
|
|
if (!_pxeMgr.prepareCreateTemplate(_pxeMgr.getPxeServerType(pxe), pxe.getId(), vm, cmd.getUrl())) {
|
|
throw new Exception("Prepare PXE boot file for host " + hostId + " failed");
|
|
}
|
|
|
|
IpmISetBootDevCommand setBootDev = new IpmISetBootDevCommand(IpmISetBootDevCommand.BootDev.pxe);
|
|
Answer ans = _agentMgr.send(hostId, setBootDev);
|
|
if (!ans.getResult()) {
|
|
throw new Exception("Set host " + hostId + " to PXE boot failed");
|
|
}
|
|
|
|
IpmiBootorResetCommand boot = new IpmiBootorResetCommand();
|
|
ans = _agentMgr.send(hostId, boot);
|
|
if (!ans.getResult()) {
|
|
throw new Exception("Boot/Reboot host " + hostId + " failed");
|
|
}
|
|
|
|
VMTemplateVO tmpl = adapter.create(tmplProfile);
|
|
s_logger.debug("Create baremetal template for host " + hostId + " successfully, template id:" + tmpl.getId());
|
|
return tmpl;
|
|
} catch (Exception e) {
|
|
s_logger.debug("Create baremetal tempalte for host " + hostId + " failed", e);
|
|
throw new CloudRuntimeException(e.getMessage());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException,
|
|
StorageUnavailableException, ResourceAllocationException {
|
|
Account caller = UserContext.current().getCaller();
|
|
|
|
String accountName = cmd.getAccountName();
|
|
Long domainId = cmd.getDomainId();
|
|
List<Long> networkList = cmd.getNetworkIds();
|
|
String group = cmd.getGroup();
|
|
|
|
Account owner = _accountDao.findActiveAccount(accountName, domainId);
|
|
if (owner == null) {
|
|
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
|
|
}
|
|
|
|
_accountMgr.checkAccess(caller, null, true, owner);
|
|
long accountId = owner.getId();
|
|
|
|
DataCenterVO dc = _dcDao.findById(cmd.getZoneId());
|
|
if (dc == null) {
|
|
throw new InvalidParameterValueException("Unable to find zone: " + cmd.getZoneId());
|
|
}
|
|
|
|
if(Grouping.AllocationState.Disabled == dc.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())){
|
|
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: "+ cmd.getZoneId() );
|
|
}
|
|
|
|
if (dc.getDomainId() != null) {
|
|
DomainVO domain = _domainDao.findById(dc.getDomainId());
|
|
if (domain == null) {
|
|
throw new CloudRuntimeException("Unable to find the domain " + dc.getDomainId() + " for the zone: " + dc);
|
|
}
|
|
_configMgr.checkZoneAccess(caller, dc);
|
|
_configMgr.checkZoneAccess(owner, dc);
|
|
}
|
|
|
|
ServiceOfferingVO offering = _serviceOfferingDao.findById(cmd.getServiceOfferingId());
|
|
if (offering == null || offering.getRemoved() != null) {
|
|
throw new InvalidParameterValueException("Unable to find service offering: " + cmd.getServiceOfferingId());
|
|
}
|
|
|
|
// check if account/domain is with in resource limits to create a new vm
|
|
resourceLimitCheck(owner, new Long(offering.getCpu()), new Long(offering.getRamSize()));
|
|
|
|
VMTemplateVO template = _templateDao.findById(cmd.getTemplateId());
|
|
// Make sure a valid template ID was specified
|
|
if (template == null || template.getRemoved() != null) {
|
|
throw new InvalidParameterValueException("Unable to use template " + cmd.getTemplateId());
|
|
}
|
|
|
|
if (template.getTemplateType().equals(TemplateType.SYSTEM)) {
|
|
throw new InvalidParameterValueException("Unable to use system template " + cmd.getTemplateId()+" to deploy a user vm");
|
|
}
|
|
|
|
if (template.getFormat() != Storage.ImageFormat.BAREMETAL) {
|
|
throw new InvalidParameterValueException("Unable to use non Bare Metal template" + cmd.getTemplateId() +" to deploy a bare metal vm");
|
|
}
|
|
|
|
String userData = cmd.getUserData();
|
|
byte [] decodedUserData = null;
|
|
if (userData != null) {
|
|
if (userData.length() >= 2 * MAX_USER_DATA_LENGTH_BYTES) {
|
|
throw new InvalidParameterValueException("User data is too long");
|
|
}
|
|
decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
|
|
if (decodedUserData.length > MAX_USER_DATA_LENGTH_BYTES){
|
|
throw new InvalidParameterValueException("User data is too long");
|
|
}
|
|
if (decodedUserData.length < 1) {
|
|
throw new InvalidParameterValueException("User data is too short");
|
|
}
|
|
}
|
|
|
|
// Find an SSH public key corresponding to the key pair name, if one is given
|
|
String sshPublicKey = null;
|
|
if (cmd.getSSHKeyPairName() != null && !cmd.getSSHKeyPairName().equals("")) {
|
|
Account account = UserContext.current().getCaller();
|
|
SSHKeyPair pair = _sshKeyPairDao.findByName(account.getAccountId(), account.getDomainId(), cmd.getSSHKeyPairName());
|
|
if (pair == null) {
|
|
throw new InvalidParameterValueException("A key pair with name '" + cmd.getSSHKeyPairName() + "' was not found.");
|
|
}
|
|
|
|
sshPublicKey = pair.getPublicKey();
|
|
}
|
|
|
|
_accountMgr.checkAccess(caller, null, true, template);
|
|
|
|
DataCenterDeployment plan = new DataCenterDeployment(dc.getId());
|
|
|
|
s_logger.debug("Allocating in the DB for bare metal vm");
|
|
|
|
if (dc.getNetworkType() != NetworkType.Basic || networkList != null) {
|
|
s_logger.warn("Bare Metal only supports basical network mode now, switch to baisc network automatically");
|
|
}
|
|
|
|
Network defaultNetwork = _networkModel.getExclusiveGuestNetwork(dc.getId());
|
|
if (defaultNetwork == null) {
|
|
throw new InvalidParameterValueException("Unable to find a default network to start a vm");
|
|
}
|
|
|
|
|
|
networkList = new ArrayList<Long>();
|
|
networkList.add(defaultNetwork.getId());
|
|
|
|
List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>();
|
|
for (Long networkId : networkList) {
|
|
NetworkVO network = _networkDao.findById(networkId);
|
|
if (network == null) {
|
|
throw new InvalidParameterValueException("Unable to find network by id " + networkId);
|
|
} else {
|
|
if (network.getGuestType() != Network.GuestType.Shared) {
|
|
//Check account permissions
|
|
List<NetworkVO> networkMap = _networkDao.listBy(accountId, networkId);
|
|
if (networkMap == null || networkMap.isEmpty()) {
|
|
throw new PermissionDeniedException("Unable to create a vm using network with id " + networkId + ", permission denied");
|
|
}
|
|
}
|
|
networks.add(new Pair<NetworkVO, NicProfile>(network, null));
|
|
}
|
|
}
|
|
|
|
long id = _vmDao.getNextInSequence(Long.class, "id");
|
|
|
|
String hostName = cmd.getName();
|
|
String instanceName = VirtualMachineName.getVmName(id, owner.getId(), _instance);
|
|
if (hostName == null) {
|
|
hostName = instanceName;
|
|
} else {
|
|
//verify hostName (hostname doesn't have to be unique)
|
|
if (!NetUtils.verifyDomainNameLabel(hostName, true)) {
|
|
throw new InvalidParameterValueException("Invalid name. Vm name can contain ASCII letters 'a' through 'z', the digits '0' through '9', " +
|
|
"and the hyphen ('-'), must be between 1 and 63 characters long, and can't start or end with \"-\" and can't start with digit");
|
|
}
|
|
}
|
|
|
|
UserVmVO vm = new UserVmVO(id, instanceName, cmd.getDisplayName(), template.getId(), HypervisorType.BareMetal,
|
|
template.getGuestOSId(), offering.getOfferHA(), false, domainId, owner.getId(), offering.getId(), userData, hostName, null);
|
|
|
|
if (sshPublicKey != null) {
|
|
vm.setDetail("SSH.PublicKey", sshPublicKey);
|
|
}
|
|
|
|
if (_itMgr.allocate(vm, template, offering, null, null, networks, null, plan, cmd.getHypervisor(), owner) == null) {
|
|
return null;
|
|
}
|
|
|
|
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Successfully allocated DB entry for " + vm);
|
|
}
|
|
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Successfully allocated DB entry for " + vm);
|
|
}
|
|
UserContext.current().setEventDetails("Vm Id: " + vm.getId());
|
|
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, cmd.getZoneId(), vm.getId(),
|
|
vm.getHostName(), offering.getId(), template.getId(), HypervisorType.BareMetal.toString(),
|
|
VirtualMachine.class.getName(), vm.getUuid());
|
|
|
|
resourceCountIncrement(accountId, new Long(offering.getCpu()), new Long(offering.getRamSize()));
|
|
|
|
// Assign instance to the group
|
|
try {
|
|
if (group != null) {
|
|
boolean addToGroup = addInstanceToGroup(Long.valueOf(id), group);
|
|
if (!addToGroup) {
|
|
throw new CloudRuntimeException("Unable to assign Vm to the group " + group);
|
|
}
|
|
}
|
|
} catch (Exception ex) {
|
|
throw new CloudRuntimeException("Unable to assign Vm to the group " + group);
|
|
}
|
|
|
|
return vm;
|
|
}
|
|
|
|
public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
|
|
UserVmVO vm = _vmDao.findById(cmd.getInstanceId());
|
|
|
|
List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.PxeServer, vm.getDataCenterId());
|
|
if (servers.size() == 0) {
|
|
throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
|
|
}
|
|
HostVO pxeServer = servers.get(0);
|
|
|
|
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
|
|
if (template == null || template.getFormat() != Storage.ImageFormat.BAREMETAL) {
|
|
throw new InvalidParameterValueException("Invalid template with id = " + vm.getTemplateId());
|
|
}
|
|
|
|
Map<VirtualMachineProfile.Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>();
|
|
params.put(Param.PxeSeverType, _pxeMgr.getPxeServerType(pxeServer));
|
|
|
|
return startVirtualMachine(cmd, params);
|
|
}
|
|
|
|
|
|
public UserVm startVirtualMachine(StartVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
|
|
UserVmVO vm = _vmDao.findById(cmd.getInstanceId());
|
|
|
|
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
|
|
if (template == null || template.getFormat() != Storage.ImageFormat.BAREMETAL) {
|
|
throw new InvalidParameterValueException("Invalid template with id = " + vm.getTemplateId());
|
|
}
|
|
|
|
Map<VirtualMachineProfile.Param, Object> params = null;
|
|
if (vm.isUpdateParameters()) {
|
|
List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.PxeServer, vm.getDataCenterId());
|
|
if (servers.size() == 0) {
|
|
throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
|
|
}
|
|
HostVO pxeServer = servers.get(0);
|
|
params = new HashMap<VirtualMachineProfile.Param, Object>();
|
|
params.put(Param.PxeSeverType, _pxeMgr.getPxeServerType(pxeServer));
|
|
}
|
|
|
|
Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmDetailsPair = super.startVirtualMachine(vm.getId(), cmd.getHostId(), params);
|
|
return vmDetailsPair.first();
|
|
}
|
|
|
|
@Override
|
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
|
_name = name;
|
|
|
|
Map<String, String> configs = _configDao.getConfiguration("AgentManager", params);
|
|
|
|
_instance = configs.get("instance.name");
|
|
if (_instance == null) {
|
|
_instance = "DEFAULT";
|
|
}
|
|
|
|
String workers = configs.get("expunge.workers");
|
|
int wrks = NumbersUtil.parseInt(workers, 10);
|
|
|
|
String time = configs.get("expunge.interval");
|
|
_expungeInterval = NumbersUtil.parseInt(time, 86400);
|
|
|
|
time = configs.get("expunge.delay");
|
|
_expungeDelay = NumbersUtil.parseInt(time, _expungeInterval);
|
|
|
|
_executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("UserVm-Scavenger"));
|
|
|
|
_itMgr.registerGuru(Type.UserBareMetal, this);
|
|
VirtualMachine.State.getStateMachine().registerListener(this);
|
|
|
|
s_logger.info("User VM Manager is configured.");
|
|
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean finalizeVirtualMachineProfile(VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context) {
|
|
UserVmVO vm = profile.getVirtualMachine();
|
|
Account owner = _accountDao.findById(vm.getAccountId());
|
|
|
|
if (owner == null || owner.getState() == Account.State.disabled) {
|
|
throw new PermissionDeniedException("The owner of " + vm + " either does not exist or is disabled: " + vm.getAccountId());
|
|
}
|
|
|
|
PxeServerType pxeType = (PxeServerType) profile.getParameter(Param.PxeSeverType);
|
|
if (pxeType == null) {
|
|
s_logger.debug("This is a normal IPMI start, skip prepartion of PXE server");
|
|
return true;
|
|
}
|
|
s_logger.debug("This is a PXE start, prepare PXE server first");
|
|
|
|
List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, dest.getPod().getId(), dest.getDataCenter().getId());
|
|
if (servers.size() == 0) {
|
|
throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
|
|
}
|
|
if (servers.size() > 1) {
|
|
throw new CloudRuntimeException("Find more than one PXE server, please make sure there is only one PXE server per zone in pod " + dest.getPod().getId() + " zone " + dest.getDataCenter().getId());
|
|
}
|
|
HostVO pxeServer = servers.get(0);
|
|
|
|
if (!_pxeMgr.prepare(pxeType, profile, dest, context, pxeServer.getId())) {
|
|
throw new CloudRuntimeException("Pepare PXE server failed");
|
|
}
|
|
|
|
profile.addBootArgs("PxeBoot");
|
|
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context) {
|
|
UserVmVO userVm = profile.getVirtualMachine();
|
|
List<NicVO> nics = _nicDao.listByVmId(userVm.getId());
|
|
for (NicVO nic : nics) {
|
|
NetworkVO network = _networkDao.findById(nic.getNetworkId());
|
|
if (network.getTrafficType() == TrafficType.Guest) {
|
|
userVm.setPrivateIpAddress(nic.getIp4Address());
|
|
userVm.setPrivateMacAddress(nic.getMacAddress());
|
|
}
|
|
}
|
|
_vmDao.update(userVm.getId(), userVm);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void finalizeStop(VirtualMachineProfile<UserVmVO> profile, StopAnswer answer) {
|
|
super.finalizeStop(profile, answer);
|
|
}
|
|
|
|
@Override
|
|
public UserVm destroyVm(long vmId) throws ResourceUnavailableException, ConcurrentOperationException {
|
|
return super.destroyVm(vmId);
|
|
}
|
|
|
|
@Override
|
|
public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
|
|
if (newState != State.Starting && newState != State.Error && newState != State.Expunging) {
|
|
return true;
|
|
}
|
|
|
|
if (vo.getHypervisorType() != HypervisorType.BareMetal) {
|
|
return true;
|
|
}
|
|
|
|
HostVO host = _hostDao.findById(vo.getHostId());
|
|
if (host == null) {
|
|
s_logger.debug("Skip oldState " + oldState + " to " + "newState " + newState + " transimtion");
|
|
return true;
|
|
}
|
|
_hostDao.loadDetails(host);
|
|
|
|
if (newState == State.Starting) {
|
|
host.setDetail("vmName", vo.getInstanceName());
|
|
s_logger.debug("Add vmName " + host.getDetail("vmName") + " to host " + host.getId() + " details");
|
|
} else {
|
|
if (host.getDetail("vmName") != null && host.getDetail("vmName").equalsIgnoreCase(vo.getInstanceName())) {
|
|
s_logger.debug("Remove vmName " + host.getDetail("vmName") + " from host " + host.getId() + " details");
|
|
host.getDetails().remove("vmName");
|
|
}
|
|
}
|
|
_hostDao.saveDetails(host);
|
|
|
|
|
|
return true;
|
|
}
|
|
}
|