// Copyright 2012 Citrix Systems, Inc. Licensed under the // Apache License, Version 2.0 (the "License"); you may not use this // file except in compliance with the License. Citrix Systems, Inc. // reserves all rights not expressly granted by 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. // // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.hypervisor.guru; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.ejb.Local; import org.apache.log4j.Logger; import com.cloud.agent.api.BackupSnapshotCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.cluster.CheckPointManager; import com.cloud.cluster.ClusterManager; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDetailsDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.HypervisorGuru; import com.cloud.hypervisor.HypervisorGuruBase; import com.cloud.hypervisor.vmware.VmwareCleanupMaid; import com.cloud.hypervisor.vmware.manager.VmwareManager; import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.NetworkDao; import com.cloud.secstorage.CommandExecLogDao; import com.cloud.secstorage.CommandExecLogVO; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.utils.Pair; import com.cloud.utils.component.Inject; import com.cloud.utils.db.DB; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.ConsoleProxyVO; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; import com.cloud.vm.SecondaryStorageVmVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VmDetailConstants; @Local(value=HypervisorGuru.class) public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { private static final Logger s_logger = Logger.getLogger(VMwareGuru.class); @Inject NetworkDao _networkDao; @Inject GuestOSDao _guestOsDao; @Inject HostDao _hostDao; @Inject HostDetailsDao _hostDetailsDao; @Inject CommandExecLogDao _cmdExecLogDao; @Inject ClusterManager _clusterMgr; @Inject VmwareManager _vmwareMgr; @Inject SecondaryStorageVmManager _secStorageMgr; @Inject CheckPointManager _checkPointMgr; @Inject NetworkManager _networkMgr; protected VMwareGuru() { super(); } @Override public HypervisorType getHypervisorType() { return HypervisorType.VMware; } @Override public <T extends VirtualMachine> VirtualMachineTO implement(VirtualMachineProfile<T> vm) { VirtualMachineTO to = toVirtualMachineTO(vm); to.setBootloader(BootloaderType.HVM); Map<String, String> details = to.getDetails(); if(details == null) details = new HashMap<String, String>(); String nicDeviceType = details.get(VmDetailConstants.NIC_ADAPTER); if(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO || vm.getVirtualMachine() instanceof SecondaryStorageVmVO) { if(nicDeviceType == null) { details.put(VmDetailConstants.NIC_ADAPTER, _vmwareMgr.getSystemVMDefaultNicAdapterType()); } else { try { VirtualEthernetCardType.valueOf(nicDeviceType); } catch (Exception e) { s_logger.warn("Invalid NIC device type " + nicDeviceType + " is specified in VM details, switch to default E1000"); details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString()); } } } else { // for user-VM, use E1000 as default if(nicDeviceType == null) { details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString()); } else { try { VirtualEthernetCardType.valueOf(nicDeviceType); } catch (Exception e) { s_logger.warn("Invalid NIC device type " + nicDeviceType + " is specified in VM details, switch to default E1000"); details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString()); } } } to.setDetails(details); if(vm.getVirtualMachine() instanceof DomainRouterVO) { List<NicProfile> nicProfiles = vm.getNics(); NicProfile publicNicProfile = null; for(NicProfile nicProfile : nicProfiles) { if(nicProfile.getTrafficType() == TrafficType.Public) { publicNicProfile = nicProfile; break; } } if(publicNicProfile != null) { NicTO[] nics = to.getNics(); // reserve extra NICs NicTO[] expandedNics = new NicTO[nics.length + _vmwareMgr.getRouterExtraPublicNics()]; int i = 0; int deviceId = -1; for(i = 0; i < nics.length; i++) { expandedNics[i] = nics[i]; if(nics[i].getDeviceId() > deviceId) deviceId = nics[i].getDeviceId(); } deviceId++; long networkId = publicNicProfile.getNetworkId(); NetworkVO network = _networkDao.findById(networkId); for(; i < nics.length + _vmwareMgr.getRouterExtraPublicNics(); i++) { NicTO nicTo = new NicTO(); nicTo.setDeviceId(deviceId++); nicTo.setBroadcastType(publicNicProfile.getBroadcastType()); nicTo.setType(publicNicProfile.getTrafficType()); nicTo.setIp("0.0.0.0"); nicTo.setNetmask("255.255.255.255"); try { String mac = _networkMgr.getNextAvailableMacAddressInNetwork(networkId); nicTo.setMac(mac); } catch (InsufficientAddressCapacityException e) { throw new CloudRuntimeException("unable to allocate mac address on network: " + networkId); } nicTo.setDns1(publicNicProfile.getDns1()); nicTo.setDns2(publicNicProfile.getDns2()); if (publicNicProfile.getGateway() != null) { nicTo.setGateway(publicNicProfile.getGateway()); } else { nicTo.setGateway(network.getGateway()); } nicTo.setDefaultNic(false); nicTo.setBroadcastUri(publicNicProfile.getBroadCastUri()); nicTo.setIsolationuri(publicNicProfile.getIsolationUri()); Integer networkRate = _networkMgr.getNetworkRate(network.getId(), null); nicTo.setNetworkRateMbps(networkRate); expandedNics[i] = nicTo; } to.setNics(expandedNics); } StringBuffer sbMacSequence = new StringBuffer(); for(NicTO nicTo : sortNicsByDeviceId(to.getNics())) { sbMacSequence.append(nicTo.getMac()).append("|"); } sbMacSequence.deleteCharAt(sbMacSequence.length() - 1); String bootArgs = to.getBootArgs(); to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString()); } // Determine the VM's OS description GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId()); to.setOs(guestOS.getDisplayName()); return to; } private NicTO[] sortNicsByDeviceId(NicTO[] nics) { List<NicTO> listForSort = new ArrayList<NicTO>(); for (NicTO nic : nics) { listForSort.add(nic); } Collections.sort(listForSort, new Comparator<NicTO>() { @Override public int compare(NicTO arg0, NicTO arg1) { if (arg0.getDeviceId() < arg1.getDeviceId()) { return -1; } else if (arg0.getDeviceId() == arg1.getDeviceId()) { return 0; } return 1; } }); return listForSort.toArray(new NicTO[0]); } @Override @DB public long getCommandHostDelegation(long hostId, Command cmd) { boolean needDelegation = false; if(cmd instanceof PrimaryStorageDownloadCommand || cmd instanceof BackupSnapshotCommand || cmd instanceof CreatePrivateTemplateFromVolumeCommand || cmd instanceof CreatePrivateTemplateFromSnapshotCommand || cmd instanceof CopyVolumeCommand || cmd instanceof CreateVolumeFromSnapshotCommand) { needDelegation = true; } if(needDelegation) { HostVO host = _hostDao.findById(hostId); assert(host != null); assert(host.getHypervisorType() == HypervisorType.VMware); long dcId = host.getDataCenterId(); Pair<HostVO, SecondaryStorageVmVO> cmdTarget = _secStorageMgr.assignSecStorageVm(dcId, cmd); if(cmdTarget != null) { // TODO, we need to make sure agent is actually connected too cmd.setContextParam("hypervisor", HypervisorType.VMware.toString()); Map<String, String> hostDetails = _hostDetailsDao.findDetails(hostId); cmd.setContextParam("guid", resolveNameInGuid(hostDetails.get("guid"))); cmd.setContextParam("username", hostDetails.get("username")); cmd.setContextParam("password", hostDetails.get("password")); cmd.setContextParam("serviceconsole", _vmwareMgr.getServiceConsolePortGroupName()); cmd.setContextParam("manageportgroup", _vmwareMgr.getManagementPortGroupName()); CommandExecLogVO execLog = new CommandExecLogVO(cmdTarget.first().getId(), cmdTarget.second().getId(), cmd.getClass().getSimpleName(), 1); _cmdExecLogDao.persist(execLog); cmd.setContextParam("execid", String.valueOf(execLog.getId())); if(cmd instanceof BackupSnapshotCommand || cmd instanceof CreatePrivateTemplateFromVolumeCommand || cmd instanceof CreatePrivateTemplateFromSnapshotCommand || cmd instanceof CopyVolumeCommand || cmd instanceof CreateVolumeFromSnapshotCommand) { String workerName = _vmwareMgr.composeWorkerName(); long checkPointId = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName)); cmd.setContextParam("worker", workerName); cmd.setContextParam("checkpoint", String.valueOf(checkPointId)); // some commands use 2 workers String workerName2 = _vmwareMgr.composeWorkerName(); long checkPointId2 = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName2)); cmd.setContextParam("worker2", workerName2); cmd.setContextParam("checkpoint2", String.valueOf(checkPointId2)); } return cmdTarget.first().getId(); } } return hostId; } public boolean trackVmHostChange() { return true; } private static String resolveNameInGuid(String guid) { String tokens[] = guid.split("@"); assert(tokens.length == 2); String vCenterIp = NetUtils.resolveToIp(tokens[1]); if(vCenterIp == null) { s_logger.error("Fatal : unable to resolve vCenter address " + tokens[1] + ", please check your DNS configuration"); return guid; } if(vCenterIp.equals(tokens[1])) return guid; return tokens[0] + "@" + vCenterIp; } }