def get_mgmt_ip_addr(cls, vm_name, ip_network): mgmt_ip_network = netaddr.IPNetwork(ip_network) iface_list = powershell.exec_powershell( 'get-vm', name=vm_name, select_clause='networkadapters' )[0].NetworkAdapters mgmt_ip_addr_list = [] for iface in iface_list: for ip_network in iface['IPAddresses'].split(): if netaddr.IPAddress(ip_network) in mgmt_ip_network: mgmt_ip_addr_list.append(ip_network) if len(mgmt_ip_addr_list) == 1: return mgmt_ip_addr_list[0] elif len(mgmt_ip_addr_list) > 1: raise exception.ConfigException( '%s has two management IP addresses (%s) that are belong to ' 'the same subnet. This is likely a configuration error' % ( vm_name, ', '.join(mgmt_ip_addr_list))) else: raise exception.ValueException( 'No management IP addresses are discovered')
def _get_virt_network(): try: virt_network = importlib.import_module('virt.lib.%s.network' % platform.system().lower()) except ImportError: raise exception.ConfigException('Not supported OS %s' % platform.system()) return virt_network
def validate(self, vswitch_list=None): # Validate the pool template_pool = storage.Pool('template') vm_pool = storage.Pool('vm') if not template_pool.exist: raise exception.ConfigException('"template" pool not found') if not vm_pool.exist: raise exception.ConfigException('"vm" pool not found') # Validate the network if vswitch_list: for vswitch in vswitch_list: try: network.get_vswitch(name=vswitch) except exception.NotFoundException: raise exception.ConfigException('vSwitch "%s" not found' % vswitch) return True
def validate(self, vswitch_list=None): vswitch_list = vswitch_list or [] with LibvirtOpen() as conn: try: conn.storagePoolLookupByName('template') conn.storagePoolLookupByName('vm') except libvirt.libvirtError as err: if 'Storage pool not found' in err.message: raise exception.ConfigException( '"template" and/or "vm" storage pools do not exist') else: raise for vswitch in vswitch_list: try: conn.networkLookupByName(vswitch) except libvirt.libvirtError as err: if 'Network not found' in err.message: raise exception.ConfigException( '"%s" does not exist' % vswitch) else: raise
def _download(self): """Download the disk image from the URL""" if not os.access(self.template_path['dir'], 0): raise exception.ConfigException( 'Cannot find "template" pool at %s' % self.template_path['dir']) if not os.access(self.template_path['file'], 0): log.info('Downloading the template image %s ... ' % self.template_path['file']) wget.download(url=self.template_path['url'], out=self.template_path['file']) print('\n') # workaround for line overlap of wget return True
def get_mgmt_ip_addr(cls, vm_name, ip_network): """Return the management IP address of the virtual machine Due to livirtd-python does not provide APIs for guest agent yet, use shell command "virsh" to get the information. Args: vm_name (str): A name of the virtual machine ip_network (str): IP address/prefix (x.x.x.x/x) for network where the management IP address should be be long to """ mgmt_ip_addr_list = [] iface_list = cls._get_network(vm_name) for iface in iface_list: if 'ip-addresses' not in iface: log.debug('No IP addresses detected on %s (%s)' % (iface['name'], iface['hardware-address'])) continue for ip_addr in iface['ip-addresses']: if netaddr.IPAddress( ip_addr['ip-address']) in netaddr.IPNetwork( ip_network): mgmt_ip_addr_list.append(ip_addr['ip-address']) if len(mgmt_ip_addr_list) == 1: return mgmt_ip_addr_list[0] elif len(mgmt_ip_addr_list) > 1: raise exception.ConfigException( '%s has two management IP addresses (%s) that are belong to ' 'the same subnet. This is likely a configuration error' % (vm_name, ', '.join(mgmt_ip_addr_list))) else: raise exception.ValueException( 'No management IP addresses are discovered')
def __init__(self, file_ext, **kwargs): self._file_ext = file_ext storage = importlib.import_module('virt.lib.%s.storage' % platform.system().lower()) template_pool = storage.Pool(name='template') vm_pool = storage.Pool(name='vm') if not template_pool.exist or not vm_pool.exist: raise exception.ConfigException( 'template and/or vm pools do not exist') self.template_path = { 'url': self.url + '/' + self.name + '.' + template_pool.file_ext, 'dir': template_pool.path, 'file': os.path.join(template_pool.path, self.name + '.' + template_pool.file_ext) } self.vm_dir = vm_pool.path self._vm_manager = virtual_machine.get_vm_manager()
def create(self, name=None, mgmt_ip_addr=None, test_ip_addr_dict=None, cpu=1, memory=512, exist=None, test_vf_dev_dict=None): """Create a virtual machine and power it up Args: name (str): A name of the virtual machine. If not given, will use auto-generated honstame using "mgmt_ip_addr" mgmt_ip_addr (str): Management IP address. If not given, "name" must be given. test_ip_addr_dict (dict): key=vswitch (network) name, value is list of <IP addresses/prefix> test_vf_dev_dict(dict): key=pci_device_id(VF), value is list of <IP addresses/prefix> cpu (int): A number of CPUs for the VM memory (int): A size of the memory in MB exist (str): A policy to handle if a virtual machine or disk already exists. choices=[None|overwrite|reuse] """ # Download the image fromt he URL self._download() test_ip_addr_dict = test_ip_addr_dict or {} vswitch_list = list( k for k in test_ip_addr_dict.keys() if k is not None) + \ ['Management Network'] self.validate(vswitch_list=vswitch_list) # Add a management network vnic_list = [ network.get_vnic(network='Management Network', mac_addr=test_network.get_mac_addr( mgmt_ip_addr, True), mgmt_iface=True) ] # Add a test network for _network, _test_ip_addr_list in test_ip_addr_dict.items(): if _network is None: continue for _test_ip_addr in _test_ip_addr_list: vnic_list.append( network.get_vnic( network=_network, mac_addr=test_network.get_mac_addr(_test_ip_addr))) # Add a pci hostdev for _pci_id, _test_ip_addr_list in test_vf_dev_dict.items(): for _test_ip_addr in _test_ip_addr_list: vnic_list.append( network.get_pci_vnic( vnic_pci=_pci_id, mac_addr=test_network.get_mac_addr(_test_ip_addr))) # Get the disk file name and the virtual machine name disk_file = os.path.join(self.vm_dir, name) + '.' + self.file_ext name = self._get_name(mgmt_ip_addr=mgmt_ip_addr, name=name) create_vm = False if name in self.vm_manager.get_vm_list(): if exist == 'reuse': log.info('Reuse the existing VM %s.' % name) elif exist == 'overwrite': log.info('Removing the existing virtual machine ... ') self.remove(name) create_vm = True else: raise exception.ConfigException( 'Virtual machine %s already exists' % name) else: create_vm = True if create_vm: # Copy the file if os.access(disk_file, 0) and exist is None: raise exception.ConfigException( 'Disk file %s already exists. You can force to create a ' 'new virtual disk with "--exist" option' % disk_file) elif os.access(disk_file, 0) and exist == 'reuse': log.info('Reuse the existing virtual disk %s ' % disk_file) else: log.info('Cloning a virtual disk ... ') shutil.copy(self.template_path['file'], disk_file) time.sleep(10) log.info('\tCompleted') self.vm_manager.create(name=name, disk_file=disk_file, vnic_list=vnic_list, cpu=cpu, memory=memory) else: if platform.system().lower() == 'windows': self.vm_manager.update(name=name, vnic_list=vnic_list, cpu=cpu, memory=memory) log.info('Powering up the virtual machine ... ') self.vm_manager.power(name=name, oper='on') log.info('Creating the virtual machine is completed')
def factory(cls, name, mode=None, **kwargs): _network = BaseLinuxVSwitch(name=name) forward_mode = None forward_interface = None ip_addr = None br_iface = None iface_list = None virtual_port = None if not mode: # Expect to get an existing switch if _network.object is None: raise exception.NotFoundException( 'vSwitch "%s" does not exist' % name) vswitch_xml = ElementTree.fromstring(_network.object.XMLDesc()) if vswitch_xml.find('forward') is not None: forward_mode = vswitch_xml.find('forward').get('mode') forward_interface = vswitch_xml.find('forward').get('dev') if vswitch_xml.findall('forward/interface') is not None: iface_list = [ iface.get('dev') for iface in vswitch_xml.findall('forward/interface')] if vswitch_xml.find('ip') is not None: _ip_addr = vswitch_xml.find('ip').get('address') _prefix = vswitch_xml.find('ip').get('prefix') ip_addr = _ip_addr + '/' + _prefix if vswitch_xml.find('bridge') is not None: br_iface = vswitch_xml.find('bridge').get('name') if forward_mode == 'nat': # NAT return NAT(name=name, br_iface=br_iface, ip_addr=ip_addr) elif forward_mode == 'hostdev': # SR-IOV: iface = vswitch_xml.find('forward/pf').get('dev') return HostDev(name=name, iface=iface) if iface_list: # MacVTAP return MacVtap( name=name, iface_list=iface_list, macvtap_mode=forward_mode) if virtual_port: # OVS return OVS(name=name, br_iface=br_iface) if forward_interface: # routed return Route( name=name, br_iface=br_iface, iface=forward_interface) if forward_mode: return Bridge( name=name, br_iface=br_iface, ) raise exception.ValueException( 'Failed to detect the vswitch mode. XML output: %s' % _network.get_xml() ) if _network.object is not None: # vswitch exists. Compare the mode, and if they are same, return # that object otherwise raise exception # _vswitch = cls.factory(name=name, **kwargs) # if _vswitch._mode == mode: # return _vswitch raise exception.ConfigException('vSwitch %s already exists' % name) # Creating a new vswitch for subclass in BaseLinuxVSwitch._get_all_subclasses(BaseLinuxVSwitch): if subclass.get_mode() == mode: return subclass(name, **kwargs) raise exception.ValueException('Invalid mode %s' % mode)