def _vm_update_access_metadata(self, dom, params): users = groups = None if "users" in params: users = params["users"] invalid_users = set(users) - set(self.users.get_list()) if len(invalid_users) != 0: raise InvalidParameter("KCHVM0027E", {'users': ", ".join(invalid_users)}) if "groups" in params: groups = params["groups"] invalid_groups = set(groups) - set(self.groups.get_list()) if len(invalid_groups) != 0: raise InvalidParameter("KCHVM0028E", {'groups': ", ".join(invalid_groups)}) if users is None and groups is None: return access_xml = (get_metadata_node(dom, "access") or """<access></access>""") old_users = xpath_get_text(access_xml, "/access/user") old_groups = xpath_get_text(access_xml, "/access/group") users = old_users if users is None else users groups = old_groups if groups is None else groups node = self._build_access_elem(users, groups) set_metadata_node(dom, node)
def test_ip_xml(self): """ Test network ip xml """ dhcp_range = {"start": "192.168.122.100", "end": "192.168.122.254"} params = {} xml = nxml._get_dhcp_xml(**params) self.assertEquals("", xml) params["net"] = "192.168.122.0/255.255.255.0" params["dhcp"] = {'range': dhcp_range} xml = nxml._get_ip_xml(**params) start = xpath_get_text(xml, "/ip/dhcp/range/@start")[0] end = xpath_get_text(xml, "/ip/dhcp/range/@end")[0] self.assertEquals(dhcp_range['start'], start) self.assertEquals(dhcp_range['end'], end) address = xpath_get_text(xml, "/ip/@address")[0] netmask = xpath_get_text(xml, "/ip/@netmask")[0] self.assertEquals(address, params["net"].split("/")[0]) self.assertEquals(netmask, params["net"].split("/")[1]) # test _get_ip_xml can accepts strings: '192.168.122.0/24', # which is same as "192.168.122.0/255.255.255.0" params["net"] = "192.168.122.0/24" xml = nxml._get_ip_xml(**params) netmask = xpath_get_text(xml, "/ip/@netmask")[0] self.assertEquals(netmask, str(ipaddr.IPNetwork(params["net"]).netmask))
def _vm_update_access_metadata(self, dom, params): users = groups = None if "users" in params: users = params["users"] invalid_users = set(users) - set(self.users.get_list()) if len(invalid_users) != 0: raise InvalidParameter("KCHVM0027E", {'users': ", ".join(invalid_users)}) if "groups" in params: groups = params["groups"] invalid_groups = set(groups) - set(self.groups.get_list()) if len(invalid_groups) != 0: raise InvalidParameter("KCHVM0028E", {'groups': ", ".join(invalid_groups)}) if users is None and groups is None: return access_xml = (get_metadata_node(dom, "access") or """<access></access>""") old_users = xpath_get_text(access_xml, "/access/user") old_groups = xpath_get_text(access_xml, "/access/group") users = old_users if users is None else users groups = old_groups if groups is None else groups node = self._build_access_elem(users, groups) set_metadata_node(dom, node)
def test_dhcp_xml(self): """ Test network dhcp xml """ dhcp_range = {"start": "192.168.122.100", "end": "192.168.122.254"} host1 = { "mac": "00:16:3e:77:e2:ed", "name": "foo.example.com", "ip": "192.168.122.10" } host2 = { "mac": "00:16:3e:3e:a9:1a", "name": "bar.example.com", "ip": "192.168.122.11" } params = {} xml = nxml._get_dhcp_xml(**params) self.assertEquals("", xml) params["range"] = dhcp_range xml = nxml._get_dhcp_xml(**params) start = xpath_get_text(xml, "/dhcp/range/@start") end = xpath_get_text(xml, "/dhcp/range/@end") self.assertEquals(dhcp_range['start'], start[0]) self.assertEquals(dhcp_range['end'], end[0]) params["hosts"] = [host1, host2] xml = nxml._get_dhcp_xml(**params) ip = xpath_get_text(xml, "/dhcp/host/@ip") self.assertEquals(ip, [host1['ip'], host2['ip']])
def lookup(self, name): pool = self.get_storagepool(name, self.conn) info = pool.info() nr_volumes = self._get_storagepool_vols_num(pool) autostart = True if pool.autostart() else False xml = pool.XMLDesc(0) path = xmlutils.xpath_get_text(xml, "/pool/target/path")[0] pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] source = self._get_storage_source(pool_type, xml) res = {'state': POOL_STATE_MAP[info[0]], 'path': path, 'source': source, 'type': pool_type, 'autostart': autostart, 'capacity': info[1], 'allocated': info[2], 'available': info[3], 'nr_volumes': nr_volumes} if not pool.isPersistent(): # Deal with deep scan generated pool try: with self.objstore as session: task_id = session.get('scanning', name) res['task_id'] = str(task_id) res['type'] = 'kimchi-iso' except NotFoundError: # User created normal pool pass return res
def _vm_get_graphics(self, name): dom = self.get_vm(name, self.conn) xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE) expr = "/domain/devices/graphics/@type" res = xmlutils.xpath_get_text(xml, expr) graphics_type = res[0] if res else None expr = "/domain/devices/graphics/@listen" res = xmlutils.xpath_get_text(xml, expr) graphics_listen = res[0] if res else None graphics_port = graphics_passwd = graphics_passwdValidTo = None if graphics_type: expr = "/domain/devices/graphics[@type='%s']/@port" res = xmlutils.xpath_get_text(xml, expr % graphics_type) graphics_port = int(res[0]) if res else None expr = "/domain/devices/graphics[@type='%s']/@passwd" res = xmlutils.xpath_get_text(xml, expr % graphics_type) graphics_passwd = res[0] if res else None expr = "/domain/devices/graphics[@type='%s']/@passwdValidTo" res = xmlutils.xpath_get_text(xml, expr % graphics_type) if res: to = time.mktime(time.strptime(res[0], '%Y-%m-%dT%H:%M:%S')) graphics_passwdValidTo = to - time.mktime(time.gmtime()) return (graphics_type, graphics_listen, graphics_port, graphics_passwd, graphics_passwdValidTo)
def test_dhcp_xml(self): """ Test network dhcp xml """ dhcp_range = {"start": "192.168.122.100", "end": "192.168.122.254"} host1 = {"mac": "00:16:3e:77:e2:ed", "name": "foo.example.com", "ip": "192.168.122.10"} host2 = {"mac": "00:16:3e:3e:a9:1a", "name": "bar.example.com", "ip": "192.168.122.11"} params = {} xml = nxml._get_dhcp_xml(**params) self.assertEquals("", xml) params["range"] = dhcp_range xml = nxml._get_dhcp_xml(**params) start = xpath_get_text(xml, "/dhcp/range/@start") end = xpath_get_text(xml, "/dhcp/range/@end") self.assertEquals(dhcp_range['start'], start[0]) self.assertEquals(dhcp_range['end'], end[0]) params["hosts"] = [host1, host2] xml = nxml._get_dhcp_xml(**params) ip = xpath_get_text(xml, "/dhcp/host/@ip") self.assertEquals(ip, [host1['ip'], host2['ip']])
def test_ip_xml(self): """ Test network ip xml """ dhcp_range = {"start": "192.168.122.100", "end": "192.168.122.254"} params = {} xml = nxml._get_dhcp_xml(**params) self.assertEquals("", xml) params["net"] = "192.168.122.0/255.255.255.0" params["dhcp"] = {'range': dhcp_range} xml = nxml._get_ip_xml(**params) start = xpath_get_text(xml, "/ip/dhcp/range/@start")[0] end = xpath_get_text(xml, "/ip/dhcp/range/@end")[0] self.assertEquals(dhcp_range['start'], start) self.assertEquals(dhcp_range['end'], end) address = xpath_get_text(xml, "/ip/@address")[0] netmask = xpath_get_text(xml, "/ip/@netmask")[0] self.assertEquals(address, params["net"].split("/")[0]) self.assertEquals(netmask, params["net"].split("/")[1]) # test _get_ip_xml can accepts strings: '192.168.122.0/24', # which is same as "192.168.122.0/255.255.255.0" params["net"] = "192.168.122.0/24" xml = nxml._get_ip_xml(**params) netmask = xpath_get_text(xml, "/ip/@netmask")[0] self.assertEquals(netmask, str(ipaddr.IPNetwork(params["net"]).netmask))
def test_to_xml(self): t = VMTemplate({'name': 'test-template'}) xml = t.to_vm_xml('test-vm', '/tmp') self.assertEquals('test-vm', xpath_get_text(xml, "/domain/name")[0]) expr = "/domain/devices/disk[@device='disk']/source/@file" self.assertEquals('/tmp/test-vm-0.img', xpath_get_text(xml, expr)[0]) expr = "/domain/devices/disk[@device='disk']/target/@dev" self.assertEquals('hda', xpath_get_text(xml, expr)[0])
def lookup(self, name): dom = self.get_vm(name, self.conn) info = dom.info() state = DOM_STATE_MAP[info[0]] screenshot = None # (type, listen, port, passwd, passwdValidTo) graphics = self._vm_get_graphics(name) graphics_port = graphics[2] graphics_port = graphics_port if state == 'running' else None try: if state == 'running' and self._has_video(dom): screenshot = self.vmscreenshot.lookup(name) elif state == 'shutoff': # reset vm stats when it is powered off to avoid sending # incorrect (old) data stats[dom.UUIDString()] = {} except NotFoundError: pass with self.objstore as session: try: extra_info = session.get('vm', dom.UUIDString()) except NotFoundError: extra_info = {} icon = extra_info.get('icon') vm_stats = stats.get(dom.UUIDString(), {}) res = {} res['cpu_utilization'] = vm_stats.get('cpu', 0) res['net_throughput'] = vm_stats.get('net_io', 0) res['net_throughput_peak'] = vm_stats.get('max_net_io', 100) res['io_throughput'] = vm_stats.get('disk_io', 0) res['io_throughput_peak'] = vm_stats.get('max_disk_io', 100) access_xml = (get_metadata_node(dom, "access") or """<access></access>""") users = xpath_get_text(access_xml, "/access/user") groups = xpath_get_text(access_xml, "/access/group") return {'name': name, 'state': state, 'stats': res, 'uuid': dom.UUIDString(), 'memory': info[2] >> 10, 'cpus': info[3], 'screenshot': screenshot, 'icon': icon, # (type, listen, port, passwd, passwdValidTo) 'graphics': {"type": graphics[0], "listen": graphics[1], "port": graphics_port, "passwd": graphics[3], "passwdValidTo": graphics[4]}, 'users': users, 'groups': groups, 'access': 'full', 'persistent': True if dom.isPersistent() else False }
def lookup(self, name): dom = self.get_vm(name, self.conn) info = dom.info() state = DOM_STATE_MAP[info[0]] screenshot = None graphics = self._vm_get_graphics(name) graphics_type, graphics_listen, graphics_port = graphics graphics_port = graphics_port if state == 'running' else None try: if state == 'running' and self._has_video(dom): screenshot = self.vmscreenshot.lookup(name) elif state == 'shutoff': # reset vm stats when it is powered off to avoid sending # incorrect (old) data stats[dom.UUIDString()] = {} except NotFoundError: pass with self.objstore as session: try: extra_info = session.get('vm', dom.UUIDString()) except NotFoundError: extra_info = {} icon = extra_info.get('icon') vm_stats = stats.get(dom.UUIDString(), {}) res = {} res['cpu_utilization'] = vm_stats.get('cpu', 0) res['net_throughput'] = vm_stats.get('net_io', 0) res['net_throughput_peak'] = vm_stats.get('max_net_io', 100) res['io_throughput'] = vm_stats.get('disk_io', 0) res['io_throughput_peak'] = vm_stats.get('max_disk_io', 100) access_xml = (get_metadata_node(dom, "access") or """<access></access>""") users = xpath_get_text(access_xml, "/access/user") groups = xpath_get_text(access_xml, "/access/group") return { 'name': name, 'state': state, 'stats': res, 'uuid': dom.UUIDString(), 'memory': info[2] >> 10, 'cpus': info[3], 'screenshot': screenshot, 'icon': icon, 'graphics': { "type": graphics_type, "listen": graphics_listen, "port": graphics_port }, 'users': users, 'groups': groups }
def test_to_xml(self): graphics = {'type': 'spice', 'listen': '0.0.0.0'} vm_uuid = str(uuid.uuid4()).replace('-', '') t = VMTemplate({'name': 'test-template'}) xml = t.to_vm_xml('test-vm', vm_uuid, graphics=graphics) self.assertEquals(vm_uuid, xpath_get_text(xml, "/domain/uuid")[0]) self.assertEquals('test-vm', xpath_get_text(xml, "/domain/name")[0]) expr = "/domain/devices/graphics/@type" self.assertEquals(graphics['type'], xpath_get_text(xml, expr)[0]) expr = "/domain/devices/graphics/@listen" self.assertEquals(graphics['listen'], xpath_get_text(xml, expr)[0])
def test_to_xml(self): graphics = {'type': 'spice', 'listen': '0.0.0.0'} vm_uuid = str(uuid.uuid4()).replace('-', '') t = VMTemplate({'name': 'test-template'}) xml = t.to_vm_xml('test-vm', vm_uuid, graphics=graphics) self.assertEquals(vm_uuid, xpath_get_text(xml, "/domain/uuid")[0]) self.assertEquals('test-vm', xpath_get_text(xml, "/domain/name")[0]) expr = "/domain/devices/graphics/@type" self.assertEquals(graphics['type'], xpath_get_text(xml, expr)[0]) expr = "/domain/devices/graphics/@listen" self.assertEquals(graphics['listen'], xpath_get_text(xml, expr)[0])
def test_to_xml(self): vm_uuid = str(uuid.uuid4()).replace('-', '') t = VMTemplate({'name': 'test-template'}) xml = t.to_vm_xml('test-vm', vm_uuid, '/tmp') self.assertEquals(vm_uuid, xpath_get_text(xml, "/domain/uuid")[0]) self.assertEquals('test-vm', xpath_get_text(xml, "/domain/name")[0]) expr = "/domain/devices/disk[@device='disk']/source/@file" img_path = '/tmp/%s-0.img' % vm_uuid self.assertEquals(img_path, xpath_get_text(xml, expr)[0]) expr = "/domain/devices/disk[@device='disk']/target/@dev" self.assertEquals('hda', xpath_get_text(xml, expr)[0])
def get_network_from_xml(xml): address = xmlutils.xpath_get_text(xml, "/network/ip/@address") address = address and address[0] or '' netmask = xmlutils.xpath_get_text(xml, "/network/ip/@netmask") netmask = netmask and netmask[0] or '' net = address and netmask and "/".join([address, netmask]) or '' dhcp_start = xmlutils.xpath_get_text(xml, "/network/ip/dhcp/range/@start") dhcp_start = dhcp_start and dhcp_start[0] or '' dhcp_end = xmlutils.xpath_get_text(xml, "/network/ip/dhcp/range/@end") dhcp_end = dhcp_end and dhcp_end[0] or '' dhcp = {'start': dhcp_start, 'end': dhcp_end} forward_mode = xmlutils.xpath_get_text(xml, "/network/forward/@mode") forward_mode = forward_mode and forward_mode[0] or '' forward_if = xmlutils.xpath_get_text(xml, "/network/forward/interface/@dev") forward_pf = xmlutils.xpath_get_text(xml, "/network/forward/pf/@dev") bridge = xmlutils.xpath_get_text(xml, "/network/bridge/@name") bridge = bridge and bridge[0] or '' return {'subnet': net, 'dhcp': dhcp, 'bridge': bridge, 'forward': {'mode': forward_mode, 'interface': forward_if, 'pf': forward_pf}}
def get_network_from_xml(xml): address = xmlutils.xpath_get_text(xml, "/network/ip/@address") address = address and address[0] or '' netmask = xmlutils.xpath_get_text(xml, "/network/ip/@netmask") netmask = netmask and netmask[0] or '' net = address and netmask and "/".join([address, netmask]) or '' dhcp_start = xmlutils.xpath_get_text(xml, "/network/ip/dhcp/range/@start") dhcp_start = dhcp_start and dhcp_start[0] or '' dhcp_end = xmlutils.xpath_get_text(xml, "/network/ip/dhcp/range/@end") dhcp_end = dhcp_end and dhcp_end[0] or '' dhcp = {'start': dhcp_start, 'end': dhcp_end} forward_mode = xmlutils.xpath_get_text(xml, "/network/forward/@mode") forward_mode = forward_mode and forward_mode[0] or '' forward_if = xmlutils.xpath_get_text(xml, "/network/forward/interface/@dev") forward_pf = xmlutils.xpath_get_text(xml, "/network/forward/pf/@dev") bridge = xmlutils.xpath_get_text(xml, "/network/bridge/@name") bridge = bridge and bridge[0] or '' return {'subnet': net, 'dhcp': dhcp, 'bridge': bridge, 'forward': {'mode': forward_mode, 'interface': forward_if, 'pf': forward_pf}}
def _vm_get_graphics(self, name): dom = self.get_vm(name, self.conn) xml = dom.XMLDesc(0) expr = "/domain/devices/graphics/@type" res = xmlutils.xpath_get_text(xml, expr) graphics_type = res[0] if res else None expr = "/domain/devices/graphics/@listen" res = xmlutils.xpath_get_text(xml, expr) graphics_listen = res[0] if res else None graphics_port = None if graphics_type: expr = "/domain/devices/graphics[@type='%s']/@port" % graphics_type res = xmlutils.xpath_get_text(xml, expr) graphics_port = int(res[0]) if res else None return graphics_type, graphics_listen, graphics_port
def lookup(self, nodedev_name): conn = self.conn.get() try: dev_xml = conn.nodeDeviceLookupByName(nodedev_name).XMLDesc(0) except: raise NotFoundError("KCHHOST0003E", {"name": nodedev_name}) cap_type = xmlutils.xpath_get_text(dev_xml, "/device/capability/capability/@type") wwnn = xmlutils.xpath_get_text(dev_xml, "/device/capability/capability/wwnn") wwpn = xmlutils.xpath_get_text(dev_xml, "/device/capability/capability/wwpn") return { "name": nodedev_name, "adapter_type": cap_type[0] if len(cap_type) >= 1 else "", "wwnn": wwnn[0] if len(wwnn) == 1 else "", "wwpn": wwpn[0] if len(wwpn) == 1 else "", }
def _vm_get_graphics(self, name): dom = self.get_vm(name, self.conn) xml = dom.XMLDesc(0) expr = "/domain/devices/graphics/@type" res = xmlutils.xpath_get_text(xml, expr) graphics_type = res[0] if res else None expr = "/domain/devices/graphics/@listen" res = xmlutils.xpath_get_text(xml, expr) graphics_listen = res[0] if res else None graphics_port = None if graphics_type: expr = "/domain/devices/graphics[@type='%s']/@port" % graphics_type res = xmlutils.xpath_get_text(xml, expr) graphics_port = int(res[0]) if res else None return graphics_type, graphics_listen, graphics_port
def test_forward_xml(self): """ Test network forward xml """ params = {"mode": None} xml = nxml._get_forward_xml(**params) self.assertEquals("", xml) params["mode"] = 'nat' params["dev"] = 'eth0' xml = nxml._get_forward_xml(**params) mode = xpath_get_text(xml, "/forward/@mode")[0] dev = xpath_get_text(xml, "/forward/@dev")[0] self.assertEquals(params['mode'], mode) self.assertEquals(params['dev'], dev)
def test_forward_xml(self): """ Test network forward xml """ params = {"mode": None} xml = nxml._get_forward_xml(**params) self.assertEquals("", xml) params["mode"] = 'nat' params["dev"] = 'eth0' xml = nxml._get_forward_xml(**params) mode = xpath_get_text(xml, "/forward/@mode")[0] dev = xpath_get_text(xml, "/forward/@dev")[0] self.assertEquals(params['mode'], mode) self.assertEquals(params['dev'], dev)
def delete(self, name): conn = self.conn.get() dom = self.get_vm(name, self.conn) self._vmscreenshot_delete(dom.UUIDString()) paths = self._vm_get_disk_paths(dom) info = self.lookup(name) if info['state'] == 'running': self.poweroff(name) try: dom.undefine() except libvirt.libvirtError as e: raise OperationFailed("KCHVM0021E", { 'name': name, 'err': e.get_error_message() }) for path in paths: vol = conn.storageVolLookupByPath(path) pool = vol.storagePoolLookupByVolume() xml = pool.XMLDesc(0) pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] if pool_type not in READONLY_POOL_TYPE: vol.delete(0) try: with self.objstore as session: session.delete('vm', dom.UUIDString(), ignore_missing=True) except Exception as e: # It is possible to delete vm without delete its database info kimchi_log.error( 'Error deleting vm information from database: ' '%s', e.message) vnc.remove_proxy_token(name)
def deactivate(self, name): if self._pool_used_by_template(name): raise InvalidOperation('KCHPOOL0034E', {'name': name}) pool = self.get_storagepool(name, self.conn) #FIXME: nfs workaround - do not try to deactivate a NFS pool # if the NFS server is not reachable. xml = pool.XMLDesc(0) pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] if pool_type == 'netfs' and not self._nfs_status_online(pool): # block the user from dactivating the pool. source = self._get_storage_source(pool_type, xml) raise OperationFailed("KCHPOOL0033E", {'name': name, 'server': source['addr']}) return try: persistent = pool.isPersistent() pool.destroy() except libvirt.libvirtError as e: raise OperationFailed("KCHPOOL0010E", {'name': name, 'err': e.get_error_message()}) # If pool was not persistent, then it was erased by destroy() and # must return nothing here, to trigger _redirect() and avoid errors if not persistent: return ""
def deactivate(self, name): if self._pool_used_by_template(name): raise InvalidOperation('KCHPOOL0034E', {'name': name}) pool = self.get_storagepool(name, self.conn) # FIXME: nfs workaround - do not try to deactivate a NFS pool # if the NFS server is not reachable. xml = pool.XMLDesc(0) pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] if pool_type == 'netfs' and not self._nfs_status_online(pool): # block the user from dactivating the pool. source = self._get_storage_source(pool_type, xml) raise OperationFailed("KCHPOOL0033E", {'name': name, 'server': source['addr']}) return try: persistent = pool.isPersistent() pool.destroy() except libvirt.libvirtError as e: raise OperationFailed("KCHPOOL0010E", {'name': name, 'err': e.get_error_message()}) # If pool was not persistent, then it was erased by destroy() and # must return nothing here, to trigger _redirect() and avoid errors if not persistent: return ""
def delete(self, name): conn = self.conn.get() dom = self.get_vm(name, self.conn) self._vmscreenshot_delete(dom.UUIDString()) paths = self._vm_get_disk_paths(dom) info = self.lookup(name) if info['state'] == 'running': self.stop(name) try: dom.undefine() except libvirt.libvirtError as e: raise OperationFailed("KCHVM0021E", {'name': name, 'err': e.get_error_message()}) for path in paths: vol = conn.storageVolLookupByPath(path) pool = vol.storagePoolLookupByVolume() xml = pool.XMLDesc(0) pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] if pool_type not in READONLY_POOL_TYPE: vol.delete(0) with self.objstore as session: session.delete('vm', dom.UUIDString(), ignore_missing=True) vnc.remove_proxy_token(name)
def lookup(self, pool, name): vol = self._get_storagevolume(pool, name) path = vol.path() info = vol.info() xml = vol.XMLDesc(0) fmt = xmlutils.xpath_get_text(xml, "/volume/target/format/@type")[0] res = dict(type=VOLUME_TYPE_MAP[info[0]], capacity=info[1], allocation=info[2], path=path, format=fmt) if fmt == 'iso': if os.path.islink(path): path = os.path.join(os.path.dirname(path), os.readlink(path)) os_distro = os_version = 'unknown' try: iso_img = IsoImage(path) os_distro, os_version = iso_img.probe() bootable = True except IsoFormatError: bootable = False res.update( dict(os_distro=os_distro, os_version=os_version, path=path, bootable=bootable)) return res
def lookup(self, pool, name): vol = self._get_storagevolume(pool, name) path = vol.path() info = vol.info() xml = vol.XMLDesc(0) fmt = xmlutils.xpath_get_text(xml, "/volume/target/format/@type")[0] res = dict(type=VOLUME_TYPE_MAP[info[0]], capacity=info[1], allocation=info[2], path=path, format=fmt) if fmt == 'iso': if os.path.islink(path): path = os.path.join(os.path.dirname(path), os.readlink(path)) os_distro = os_version = 'unknown' try: iso_img = IsoImage(path) os_distro, os_version = iso_img.probe() bootable = True except IsoFormatError: bootable = False res.update( dict(os_distro=os_distro, os_version=os_version, path=path, bootable=bootable)) return res
def lookup(self, pool, name): vol = self._get_storagevolume(pool, name) path = vol.path() info = vol.info() xml = vol.XMLDesc(0) try: fmt = xmlutils.xpath_get_text( xml, "/volume/target/format/@type")[0] except IndexError: # Not all types of libvirt storage can provide volume format # infomation. When there is no format information, we assume # it's 'raw'. fmt = 'raw' ref_cnt = self._get_ref_cnt(pool, name, path) res = dict(type=VOLUME_TYPE_MAP[info[0]], capacity=info[1], allocation=info[2], path=path, ref_cnt=ref_cnt, format=fmt) if fmt == 'iso': if os.path.islink(path): path = os.path.join(os.path.dirname(path), os.readlink(path)) os_distro = os_version = 'unknown' try: iso_img = IsoImage(path) os_distro, os_version = iso_img.probe() bootable = True except IsoFormatError: bootable = False res.update( dict(os_distro=os_distro, os_version=os_version, path=path, bootable=bootable)) return res
def lookup(self, nodedev_name): conn = self.conn.get() try: dev_xml = conn.nodeDeviceLookupByName(nodedev_name).XMLDesc(0) except: raise NotFoundError('KCHHOST0003E', {'name': nodedev_name}) cap_type = xmlutils.xpath_get_text( dev_xml, '/device/capability/capability/@type') wwnn = xmlutils.xpath_get_text( dev_xml, '/device/capability/capability/wwnn') wwpn = xmlutils.xpath_get_text( dev_xml, '/device/capability/capability/wwpn') return { 'name': nodedev_name, 'adapter_type': cap_type[0] if len(cap_type) >= 1 else '', 'wwnn': wwnn[0] if len(wwnn) == 1 else '', 'wwpn': wwpn[0] if len(wwpn) == 1 else ''}
def lookup(self, nodedev_name): conn = self.conn.get() try: dev_xml = conn.nodeDeviceLookupByName(nodedev_name).XMLDesc(0) except: raise NotFoundError('KCHHOST0003E', {'name': nodedev_name}) cap_type = xmlutils.xpath_get_text( dev_xml, '/device/capability/capability/@type') wwnn = xmlutils.xpath_get_text( dev_xml, '/device/capability/capability/wwnn') wwpn = xmlutils.xpath_get_text( dev_xml, '/device/capability/capability/wwpn') return { 'name': nodedev_name, 'adapter_type': cap_type[0] if len(cap_type) >= 1 else '', 'wwnn': wwnn[0] if len(wwnn) == 1 else '', 'wwpn': wwpn[0] if len(wwpn) == 1 else ''}
def lookup(self, name): pool = self.get_storagepool(name, self.conn) info = pool.info() autostart = True if pool.autostart() else False persistent = True if pool.isPersistent() else False xml = pool.XMLDesc(0) path = xmlutils.xpath_get_text(xml, "/pool/target/path")[0] pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] source = self._get_storage_source(pool_type, xml) # FIXME: nfs workaround - prevent any libvirt operation # for a nfs if the corresponding NFS server is down. if pool_type == 'netfs' and not self._nfs_status_online(pool): kimchi_log.debug("NFS pool %s is offline, reason: NFS " "server %s is unreachable.", name, source['addr']) # Mark state as '4' => inaccessible. info[0] = 4 # skip calculating volumes nr_volumes = 0 else: nr_volumes = self._get_storagepool_vols_num(pool) res = {'state': POOL_STATE_MAP[info[0]], 'path': path, 'source': source, 'type': pool_type, 'autostart': autostart, 'capacity': info[1], 'allocated': info[2], 'available': info[3], 'nr_volumes': nr_volumes, 'persistent': persistent} if not pool.isPersistent(): # Deal with deep scan generated pool try: with self.objstore as session: task_id = session.get('scanning', name) res['task_id'] = str(task_id) res['type'] = 'kimchi-iso' except NotFoundError: # User created normal pool pass return res
def lookup(self, name): pool = self.get_storagepool(name, self.conn) info = pool.info() autostart = True if pool.autostart() else False xml = pool.XMLDesc(0) path = xmlutils.xpath_get_text(xml, "/pool/target/path")[0] pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] source = self._get_storage_source(pool_type, xml) #FIXME: nfs workaround - prevent any libvirt operation # for a nfs if the corresponding NFS server is down. if pool_type == 'netfs' and not self._nfs_status_online(pool): kimchi_log.debug( "NFS pool %s is offline, reason: NFS " "server %s is unreachable.", name, source['addr']) # Mark state as '4' => inaccessible. info[0] = 4 # skip calculating volumes nr_volumes = 0 else: nr_volumes = self._get_storagepool_vols_num(pool) res = { 'state': POOL_STATE_MAP[info[0]], 'path': path, 'source': source, 'type': pool_type, 'autostart': autostart, 'capacity': info[1], 'allocated': info[2], 'available': info[3], 'nr_volumes': nr_volumes } if not pool.isPersistent(): # Deal with deep scan generated pool try: with self.objstore as session: task_id = session.get('scanning', name) res['task_id'] = str(task_id) res['type'] = 'kimchi-iso' except NotFoundError: # User created normal pool pass return res
def _get_storage_source(self, pool_type, pool_xml): source = {} if pool_type not in STORAGE_SOURCES: return source for key, val in STORAGE_SOURCES[pool_type].items(): res = xmlutils.xpath_get_text(pool_xml, val) source[key] = res[0] if len(res) == 1 else res return source
def start(self, name): # make sure the ISO file has read permission dom = self.get_vm(name, self.conn) xml = dom.XMLDesc(0) xpath = "/domain/devices/disk[@device='cdrom']/source/@file" isofiles = xmlutils.xpath_get_text(xml, xpath) for iso in isofiles: run_setfacl_set_attr(iso) dom = self.get_vm(name, self.conn) dom.create()
def _get_devices_fc_host(self): conn = self.conn.get() # Libvirt < 1.0.5 does not support fc_host capability if not CapabilitiesModel().fc_host_support: ret = [] scsi_hosts = conn.listDevices('scsi_host', 0) for host in scsi_hosts: xml = conn.nodeDeviceLookupByName(host).XMLDesc(0) path = '/device/capability/capability/@type' if 'fc_host' in xmlutils.xpath_get_text(xml, path): ret.append(host) return ret return conn.listDevices('fc_host', 0)
def _get_devices_fc_host(self): conn = self.conn.get() # Libvirt < 1.0.5 does not support fc_host capability if not CapabilitiesModel().fc_host_support: ret = [] scsi_hosts = conn.listDevices('scsi_host', 0) for host in scsi_hosts: xml = conn.nodeDeviceLookupByName(host).XMLDesc(0) path = '/device/capability/capability/@type' if 'fc_host' in xmlutils.xpath_get_text(xml, path): ret.append(host) return ret return conn.listDevices('fc_host', 0)
def _get_storage_source(self, pool_type, pool_xml): source = {} if pool_type not in STORAGE_SOURCES: return source for key, val in STORAGE_SOURCES[pool_type].items(): res = xmlutils.xpath_get_text(pool_xml, val) if len(res) == 1: source[key] = res[0] elif len(res) == 0: source[key] = "" else: source[key] = res return source
def start(self, name): # make sure the ISO file has read permission dom = self.get_vm(name, self.conn) xml = dom.XMLDesc(0) xpath = "/domain/devices/disk[@device='cdrom']/source/@file" isofiles = xmlutils.xpath_get_text(xml, xpath) for iso in isofiles: run_setfacl_set_attr(iso) dom = self.get_vm(name, self.conn) try: dom.create() except libvirt.libvirtError as e: raise OperationFailed("KCHVM0019E", {'name': name, 'err': e.get_error_message()})
def start(self, name): # make sure the ISO file has read permission dom = self.get_vm(name, self.conn) xml = dom.XMLDesc(0) xpath = "/domain/devices/disk[@device='cdrom']/source/@file" isofiles = xmlutils.xpath_get_text(xml, xpath) for iso in isofiles: run_setfacl_set_attr(iso) dom = self.get_vm(name, self.conn) try: dom.create() except libvirt.libvirtError as e: raise OperationFailed("KCHVM0019E", {'name': name, 'err': e.get_error_message()})
def update(self, name, params): pool = self.get_storagepool(name, self.conn) if 'autostart' in params: if params['autostart']: pool.setAutostart(1) else: pool.setAutostart(0) if 'disks' in params: # check if pool is type 'logical' xml = pool.XMLDesc(0) pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] if pool_type != 'logical': raise InvalidOperation('KCHPOOL0029E') self._update_lvm_disks(name, params['disks']) ident = pool.name() return ident
def update(self, name, params): pool = self.get_storagepool(name, self.conn) if 'autostart' in params: if params['autostart']: pool.setAutostart(1) else: pool.setAutostart(0) if 'disks' in params: # check if pool is type 'logical' xml = pool.XMLDesc(0) pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] if pool_type != 'logical': raise InvalidOperation('KCHPOOL0029E') self._update_lvm_disks(name, params['disks']) ident = pool.name() return ident
def activate(self, name): pool = self.get_storagepool(name, self.conn) # FIXME: nfs workaround - do not activate a NFS pool # if the NFS server is not reachable. xml = pool.XMLDesc(0) pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] if pool_type == 'netfs' and not self._nfs_status_online(pool): # block the user from activating the pool. source = self._get_storage_source(pool_type, xml) raise OperationFailed("KCHPOOL0032E", {'name': name, 'server': source['addr']}) return try: pool.create(0) except libvirt.libvirtError as e: raise OperationFailed("KCHPOOL0009E", {'name': name, 'err': e.get_error_message()})
def _nfs_status_online(self, pool, poolArgs=None): if not poolArgs: xml = pool.XMLDesc(0) pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] source = self._get_storage_source(pool_type, xml) poolArgs = {} poolArgs['name'] = pool.name() poolArgs['type'] = pool_type poolArgs['source'] = {'path': source['path'], 'host': source['addr']} conn = self.conn.get() poolDef = StoragePoolDef.create(poolArgs) try: poolDef.prepare(conn) return True except Exception: return False
def activate(self, name): pool = self.get_storagepool(name, self.conn) #FIXME: nfs workaround - do not activate a NFS pool # if the NFS server is not reachable. xml = pool.XMLDesc(0) pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] if pool_type == 'netfs' and not self._nfs_status_online(pool): # block the user from activating the pool. source = self._get_storage_source(pool_type, xml) raise OperationFailed("KCHPOOL0032E", {'name': name, 'server': source['addr']}) return try: pool.create(0) except libvirt.libvirtError as e: raise OperationFailed("KCHPOOL0009E", {'name': name, 'err': e.get_error_message()})
def _nfs_status_online(self, pool, poolArgs=None): if not poolArgs: xml = pool.XMLDesc(0) pool_type = xmlutils.xpath_get_text(xml, "/pool/@type")[0] source = self._get_storage_source(pool_type, xml) poolArgs = {} poolArgs['name'] = pool.name() poolArgs['type'] = pool_type poolArgs['source'] = {'path': source['path'], 'host': source['addr']} conn = self.conn.get() poolDef = StoragePoolDef.create(poolArgs) try: poolDef.prepare(conn) return True except Exception: return False
def _get_devices_fc_host(self): conn = self.conn.get() # Libvirt < 1.0.5 does not support fc_host capability if not CapabilitiesModel().fc_host_support: ret = [] scsi_hosts = self._get_devices_with_capability('scsi_host') for host in scsi_hosts: xml = conn.nodeDeviceLookupByName(host).XMLDesc(0) path = '/device/capability/capability/@type' if 'fc_host' in xmlutils.xpath_get_text(xml, path): ret.append(host) return ret # Double verification to catch the case where the libvirt # supports fc_host but does not, for some reason, recognize # the libvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_FC_HOST # attribute. if not self.cap_map['fc_host']: return conn.listDevices('fc_host', 0) return self._get_devices_with_capability('fc_host')
def template_volume_validate(self, tmp_volumes, pool): kwargs = {'conn': self.conn, 'objstore': self.objstore} pool_type = xmlutils.xpath_get_text(pool.XMLDesc(0), "/pool/@type")[0] pool_name = pool.name() # as we discussion, we do not mix disks from 2 different types of # storage pools, for instance: we do not create a template with 2 # disks, where one comes from a SCSI pool and other is a .img in # a DIR pool. if pool_type in ['iscsi', 'scsi']: if not tmp_volumes: raise InvalidParameter("KCHTMPL0018E") storagevolumes = __import__("kimchi.model.storagevolumes", fromlist=['']) pool_volumes = storagevolumes.StorageVolumesModel( **kwargs).get_list(pool_name) vols = set(tmp_volumes) - set(pool_volumes) if vols: raise InvalidParameter("KCHTMPL0019E", {'pool': pool_name, 'volume': vols})
def template_volume_validate(self, tmp_volumes, pool): kwargs = {'conn': self.conn, 'objstore': self.objstore} pool_type = xmlutils.xpath_get_text(pool.XMLDesc(0), "/pool/@type")[0] pool_name = pool.name() # as we discussion, we do not mix disks from 2 different types of # storage pools, for instance: we do not create a template with 2 # disks, where one comes from a SCSI pool and other is a .img in # a DIR pool. if pool_type in ['iscsi', 'scsi']: if not tmp_volumes: raise InvalidParameter("KCHTMPL0018E") storagevolumes = __import__("kimchi.model.storagevolumes", fromlist=['']) pool_volumes = storagevolumes.StorageVolumesModel( **kwargs).get_list(pool_name) vols = set(tmp_volumes) - set(pool_volumes) if vols: raise InvalidParameter("KCHTMPL0019E", { 'pool': pool_name, 'volume': vols })
def lookup(self, pool, name): vol = self._get_storagevolume(pool, name) path = vol.path() info = vol.info() xml = vol.XMLDesc(0) try: fmt = xmlutils.xpath_get_text(xml, "/volume/target/format/@type")[0] except IndexError: # Not all types of libvirt storage can provide volume format # infomation. When there is no format information, we assume # it's 'raw'. fmt = 'raw' ref_cnt = self._get_ref_cnt(pool, name, path) res = dict(type=VOLUME_TYPE_MAP[info[0]], capacity=info[1], allocation=info[2], path=path, ref_cnt=ref_cnt, format=fmt) if fmt == 'iso': if os.path.islink(path): path = os.path.join(os.path.dirname(path), os.readlink(path)) os_distro = os_version = 'unknown' try: iso_img = IsoImage(path) os_distro, os_version = iso_img.probe() bootable = True except IsoFormatError: bootable = False res.update( dict(os_distro=os_distro, os_version=os_version, path=path, bootable=bootable)) return res
def _get_storage_type(self): pool = self._storage_validate() xml = pool.XMLDesc(0) return xmlutils.xpath_get_text(xml, "/pool/@type")[0]
def test_network_xml(self): """ Test network xml """ params = {"name": "test", "forward": {"mode": "nat", "dev": ""}, "net": "192.168.0.0/255.255.255.0"} xml = nxml.to_network_xml(**params) name = xpath_get_text(xml, "/network/name")[0] self.assertEquals(name, params['name']) forward_mode = xpath_get_text(xml, "/network/forward/@mode")[0] self.assertEquals(forward_mode, params['forward']['mode']) forward_dev = xpath_get_text(xml, "/network/forward/@dev")[0] self.assertEquals(forward_dev, '') address = xpath_get_text(xml, "/network/ip/@address")[0] self.assertEquals(address, params["net"].split("/")[0]) netmask = xpath_get_text(xml, "/network/ip/@netmask")[0] self.assertEquals(netmask, params["net"].split("/")[1]) dhcp_start = xpath_get_text(xml, "/network/ip/dhcp/range/@start") self.assertEquals(dhcp_start, []) dhcp_end = xpath_get_text(xml, "/network/ip/dhcp/range/@end") self.assertEquals(dhcp_end, []) # test optional params params['forward']['dev'] = "eth0" params['dhcp'] = {"range": {'start': '192.168.0.1', 'end': '192.168.0.254'}} xml = nxml.to_network_xml(**params) forward_dev = xpath_get_text(xml, "/network/forward/@dev")[0] self.assertEquals(forward_dev, params['forward']['dev']) dhcp_start = xpath_get_text(xml, "/network/ip/dhcp/range/@start")[0] self.assertEquals(dhcp_start, params['dhcp']['range']['start']) dhcp_end = xpath_get_text(xml, "/network/ip/dhcp/range/@end")[0] self.assertEquals(dhcp_end, params['dhcp']['range']['end']) # test _get_ip_xml can accepts strings: '192.168.122.0/24', # which is same as "192.168.122.0/255.255.255.0" params["net"] = "192.168.0.0/24" xml = nxml.to_network_xml(**params) netmask = xpath_get_text(xml, "/network/ip/@netmask")[0] self.assertEquals(netmask, str(ipaddr.IPNetwork(params["net"]).netmask))
def _vm_get_disk_paths(self, dom): xml = dom.XMLDesc(0) xpath = "/domain/devices/disk[@device='disk']/source/@file" return xmlutils.xpath_get_text(xml, xpath)
def _get_storage_path(self): pool = self._storage_validate() xml = pool.XMLDesc(0) return xmlutils.xpath_get_text(xml, "/pool/target/path")[0]
def test_network_xml(self): """ Test network xml """ params = { "name": "test", "forward": { "mode": "nat", "dev": "" }, "net": "192.168.0.0/255.255.255.0" } xml = nxml.to_network_xml(**params) name = xpath_get_text(xml, "/network/name")[0] self.assertEquals(name, params['name']) forward_mode = xpath_get_text(xml, "/network/forward/@mode")[0] self.assertEquals(forward_mode, params['forward']['mode']) forward_dev = xpath_get_text(xml, "/network/forward/@dev")[0] self.assertEquals(forward_dev, '') address = xpath_get_text(xml, "/network/ip/@address")[0] self.assertEquals(address, params["net"].split("/")[0]) netmask = xpath_get_text(xml, "/network/ip/@netmask")[0] self.assertEquals(netmask, params["net"].split("/")[1]) dhcp_start = xpath_get_text(xml, "/network/ip/dhcp/range/@start") self.assertEquals(dhcp_start, []) dhcp_end = xpath_get_text(xml, "/network/ip/dhcp/range/@end") self.assertEquals(dhcp_end, []) # test optional params params['forward']['dev'] = "eth0" params['dhcp'] = { "range": { 'start': '192.168.0.1', 'end': '192.168.0.254' } } xml = nxml.to_network_xml(**params) forward_dev = xpath_get_text(xml, "/network/forward/@dev")[0] self.assertEquals(forward_dev, params['forward']['dev']) dhcp_start = xpath_get_text(xml, "/network/ip/dhcp/range/@start")[0] self.assertEquals(dhcp_start, params['dhcp']['range']['start']) dhcp_end = xpath_get_text(xml, "/network/ip/dhcp/range/@end")[0] self.assertEquals(dhcp_end, params['dhcp']['range']['end']) # test _get_ip_xml can accepts strings: '192.168.122.0/24', # which is same as "192.168.122.0/255.255.255.0" params["net"] = "192.168.0.0/24" xml = nxml.to_network_xml(**params) netmask = xpath_get_text(xml, "/network/ip/@netmask")[0] self.assertEquals(netmask, str(ipaddr.IPNetwork(params["net"]).netmask))
def _vm_get_networks(self, dom): xml = dom.XMLDesc(0) xpath = "/domain/devices/interface[@type='network']/source/@network" return xmlutils.xpath_get_text(xml, xpath)
def _vm_get_networks(self, dom): xml = dom.XMLDesc(0) xpath = "/domain/devices/interface[@type='network']/source/@network" return xmlutils.xpath_get_text(xml, xpath)