| // 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.hypervisor.hyperv.guru; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.inject.Inject; |
| |
| import com.cloud.agent.api.to.NicTO; |
| import com.cloud.agent.api.to.VirtualMachineTO; |
| import com.cloud.exception.InsufficientAddressCapacityException; |
| import com.cloud.hypervisor.Hypervisor.HypervisorType; |
| import com.cloud.hypervisor.HypervisorGuru; |
| import com.cloud.hypervisor.HypervisorGuruBase; |
| import com.cloud.hypervisor.hyperv.manager.HypervManager; |
| import com.cloud.network.NetworkModel; |
| import com.cloud.network.Networks.BroadcastDomainType; |
| import com.cloud.network.Networks.TrafficType; |
| import com.cloud.network.dao.NetworkDao; |
| import com.cloud.network.dao.NetworkVO; |
| import com.cloud.storage.GuestOSVO; |
| import com.cloud.storage.dao.GuestOSDao; |
| import com.cloud.utils.exception.CloudRuntimeException; |
| import com.cloud.vm.NicProfile; |
| import com.cloud.vm.VirtualMachine; |
| import com.cloud.vm.VirtualMachineProfile; |
| |
| /** |
| * Implementation of Hypervisor guru for Hyper-V. |
| **/ |
| public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru { |
| |
| @Inject |
| private GuestOSDao _guestOsDao; |
| @Inject HypervManager _hypervMgr; |
| @Inject NetworkDao _networkDao; |
| @Inject NetworkModel _networkMgr; |
| int MaxNicSupported = 8; |
| @Override |
| public final HypervisorType getHypervisorType() { |
| return HypervisorType.Hyperv; |
| } |
| |
| /** |
| * Prevent direct creation. |
| */ |
| protected HypervGuru() { |
| super(); |
| } |
| |
| @Override |
| public final VirtualMachineTO implement(VirtualMachineProfile vm) { |
| VirtualMachineTO to = toVirtualMachineTO(vm); |
| List<NicProfile> nicProfiles = vm.getNics(); |
| |
| if(vm.getVirtualMachine().getType() == VirtualMachine.Type.DomainRouter) { |
| |
| NicProfile publicNicProfile = null; |
| NicProfile controlNicProfile = null; |
| NicProfile profile = null; |
| for(NicProfile nicProfile : nicProfiles) { |
| if(nicProfile.getTrafficType() == TrafficType.Public) { |
| publicNicProfile = nicProfile; |
| break; |
| } |
| else if (nicProfile.getTrafficType() == TrafficType.Control) { |
| controlNicProfile = nicProfile; |
| } |
| } |
| |
| if(publicNicProfile != null || controlNicProfile != null) { |
| NicTO[] nics = to.getNics(); |
| // reserve extra NICs |
| NicTO[] expandedNics = new NicTO[MaxNicSupported]; |
| 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 = 0; |
| if(publicNicProfile != null ) { |
| networkId= publicNicProfile.getNetworkId(); |
| profile = publicNicProfile; |
| } |
| else { |
| networkId = controlNicProfile.getNetworkId(); |
| profile = controlNicProfile; |
| } |
| |
| NetworkVO network = _networkDao.findById(networkId); |
| // for Hyperv Hot Nic plug is not supported and it will support upto 8 nics. |
| // creating the VR with extra nics (actual nics(3) + extra nics) will be 8 |
| for(; i < MaxNicSupported; i++) { |
| NicTO nicTo = new NicTO(); |
| nicTo.setDeviceId(deviceId++); |
| nicTo.setBroadcastType(BroadcastDomainType.Vlan); |
| nicTo.setType(TrafficType.Public); |
| nicTo.setIp("0.0.0.0"); |
| nicTo.setNetmask("255.255.255.255"); |
| nicTo.setName(profile.getName()); |
| |
| 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(profile.getIPv4Dns1()); |
| nicTo.setDns2(profile.getIPv4Dns2()); |
| if (publicNicProfile != null && publicNicProfile.getIPv4Gateway() != null) { |
| nicTo.setGateway(publicNicProfile.getIPv4Gateway()); |
| } else { |
| nicTo.setGateway(network.getGateway()); |
| } |
| nicTo.setDefaultNic(false); |
| nicTo.setBroadcastUri(profile.getBroadCastUri()); |
| nicTo.setIsolationuri(profile.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("|"); |
| } |
| |
| if (!sbMacSequence.toString().isEmpty()) { |
| 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 |
| public final boolean trackVmHostChange() { |
| return false; |
| } |
| |
| @Override |
| public Map<String, String> getClusterSettings(long vmId) { |
| return null; |
| } |
| |
| } |