| // 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.ejb.Local; |
| 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.UsageEventVO; |
| import com.cloud.exception.ConcurrentOperationException; |
| import com.cloud.exception.InsufficientCapacityException; |
| import com.cloud.exception.InvalidParameterValueException; |
| import com.cloud.exception.PermissionDeniedException; |
| import com.cloud.exception.ResourceAllocationException; |
| import com.cloud.exception.ResourceUnavailableException; |
| import com.cloud.exception.StorageUnavailableException; |
| 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.NetworkVO; |
| import com.cloud.network.Networks.TrafficType; |
| 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.VMTemplateVO; |
| import com.cloud.storage.Volume; |
| import com.cloud.template.TemplateAdapter; |
| import com.cloud.template.TemplateAdapter.TemplateAdapterType; |
| import com.cloud.template.TemplateProfile; |
| 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.uservm.UserVm; |
| import com.cloud.utils.NumbersUtil; |
| import com.cloud.utils.Pair; |
| import com.cloud.utils.component.Adapters; |
| import com.cloud.utils.component.ComponentLocator; |
| import com.cloud.utils.component.Inject; |
| 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.BareMetalVmService; |
| import com.cloud.vm.NicProfile; |
| import com.cloud.vm.NicVO; |
| import com.cloud.vm.ReservationContext; |
| import com.cloud.vm.UserVmManagerImpl; |
| import com.cloud.vm.UserVmVO; |
| import com.cloud.vm.VirtualMachine; |
| import com.cloud.vm.VirtualMachine.Event; |
| import com.cloud.vm.VirtualMachine.State; |
| import com.cloud.vm.VirtualMachine.Type; |
| import com.cloud.vm.VirtualMachineName; |
| import com.cloud.vm.VirtualMachineProfile; |
| import com.cloud.vm.VirtualMachineProfile.Param; |
| |
| @Local(value={BareMetalVmManager.class, BareMetalVmService.class}) |
| public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMetalVmManager, BareMetalVmService, Manager, |
| StateListener<State, VirtualMachine.Event, VirtualMachine> { |
| private static final Logger s_logger = Logger.getLogger(BareMetalVmManagerImpl.class); |
| private ConfigurationDao _configDao; |
| @Inject PxeServerManager _pxeMgr; |
| @Inject ResourceManager _resourceMgr; |
| |
| @Inject (adapter=TemplateAdapter.class) |
| protected Adapters<TemplateAdapter> _adapters; |
| |
| @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 = _adapters.get(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); |
| } |
| |
| // check if account/domain is with in resource limits to create a new vm |
| _resourceLimitMgr.checkResourceLimit(owner, ResourceType.user_vm); |
| |
| ServiceOfferingVO offering = _serviceOfferingDao.findById(cmd.getServiceOfferingId()); |
| if (offering == null || offering.getRemoved() != null) { |
| throw new InvalidParameterValueException("Unable to find service offering: " + cmd.getServiceOfferingId()); |
| } |
| |
| 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 = _networkMgr.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); |
| |
| 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()); |
| UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_CREATE, accountId, cmd.getZoneId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), HypervisorType.BareMetal.toString()); |
| _usageEventDao.persist(usageEvent); |
| |
| _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm); |
| |
| // 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.getDataCenterIdToDeployIn()); |
| 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.getDataCenterIdToDeployIn()); |
| 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; |
| |
| ComponentLocator locator = ComponentLocator.getCurrentLocator(); |
| _configDao = locator.getDao(ConfigurationDao.class); |
| if (_configDao == null) { |
| throw new ConfigurationException("Unable to get the configuration dao."); |
| } |
| |
| 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; |
| } |
| } |