def storagepools_create(self, params): try: name = params['name'] pool = MockStoragePool(name) pool.info['type'] = params['type'] if params['type'] == 'scsi': pool.info['path'] = '/dev/disk/by-path' pool.info['source'] = params['source'] if not pool.info['source'].get('adapter_name'): raise MissingParameter('KCHPOOL0004E', { 'item': 'adapter_name', 'name': name }) for vol in [ 'unit:0:0:1', 'unit:0:0:2', 'unit:0:0:3', 'unit:0:0:4' ]: mockvol = MockStorageVolume(name, vol, dict([('type', 'lun')])) pool._volumes[vol] = mockvol else: pool.info['path'] = params['path'] if params['type'] in ['dir', 'scsi']: pool.info['autostart'] = True else: pool.info['autostart'] = False except KeyError, item: raise MissingParameter("KCHPOOL0004E", { 'item': str(item), 'name': name })
def addRepo(self, params): """ Add a new APT repository based on <params> """ # To create a APT repository the dist is a required parameter # (in addition to baseurl, verified on controller through API.json) config = params.get('config', None) if config is None: raise MissingParameter("KCHREPOS0019E") if 'dist' not in config.keys(): raise MissingParameter("KCHREPOS0019E") uri = params['baseurl'] dist = config['dist'] comps = config.get('comps', []) validate_repo_url(uri) kimchiLock.acquire() try: repos = self._get_repos() source_entry = repos.add('deb', uri, dist, comps, file=self.filename) with self.pkg_lock(): repos.save() except Exception as e: kimchiLock.release() raise OperationFailed("KCHREPOS0026E", {'err': e.message}) kimchiLock.release() return self._get_repo_id(source_entry)
def networks_create(self, params): name = params['name'] if name in self.networks_get_list(): raise InvalidOperation("KCHNET0001E", {'name': name}) network = MockNetwork(name) connection = params['connection'] network.info['connection'] = connection if connection == "bridge": try: interface = params['interface'] network.info['interface'] = interface except KeyError: raise MissingParameter("KCHNET0004E", {'name': name}) subnet = params.get('subnet', '') if subnet: network.info['subnet'] = subnet try: net = ipaddr.IPNetwork(subnet) except ValueError: msg_args = {'subnet': subnet, 'network': name} raise InvalidParameter("KCHNET0003E", msg_args) network.info['dhcp'] = { 'start': str(net.network + net.numhosts / 2), 'stop': str(net.network + net.numhosts - 2) } self._mock_networks[name] = network return name
def create(self, params): task_id = None conn = self.conn.get() try: name = params['name'] if name == ISO_POOL_NAME: raise InvalidOperation("KCHPOOL0031E") if params['type'] == 'kimchi-iso': task_id = self._do_deep_scan(params) if params['type'] == 'scsi': adapter_name = params['source']['adapter_name'] extra_params = self.device.lookup(adapter_name) # Adds name, adapter_type, wwpn and wwnn to source information params['source'].update(extra_params) params['fc_host_support'] = self.caps.fc_host_support poolDef = StoragePoolDef.create(params) poolDef.prepare(conn) xml = poolDef.xml.encode("utf-8") except KeyError, item: raise MissingParameter("KCHPOOL0004E", { 'item': str(item), 'name': name })
def addRepo(self, params): """ Add a given repository to YumBase """ # At least one base url, or one mirror, must be given. baseurl = params.get('baseurl', '') config = params.get('config', {}) mirrorlist = config.get('mirrorlist', '') metalink = config.get('metalink', '') if not baseurl and not mirrorlist and not metalink: raise MissingParameter("KCHREPOS0013E") if baseurl: validate_repo_url(baseurl) if mirrorlist: validate_repo_url(mirrorlist) if metalink: validate_repo_url(metalink) if mirrorlist and metalink: raise InvalidOperation('KCHREPOS0030E') repo_id = params.get('repo_id', None) if repo_id is None: repo_id = "kimchi_repo_%s" % str(int(time.time() * 1000)) repos = self._get_repos('KCHREPOS0026E') if repo_id in repos.keys(): raise InvalidOperation("KCHREPOS0022E", {'repo_id': repo_id}) repo_name = config.get('repo_name', repo_id) repo = { 'baseurl': baseurl, 'mirrorlist': mirrorlist, 'name': repo_name, 'gpgcheck': 1, 'gpgkey': [], 'enabled': 1, 'metalink': metalink } # write a repo file in the system with repo{} information. parser = ConfigParser() parser.add_section(repo_id) for key, value in repo.iteritems(): if value: parser.set(repo_id, key, value) repofile = os.path.join(self._confdir, repo_id + '.repo') try: with open(repofile, 'w') as fd: parser.write(fd) except: raise OperationFailed("KCHREPOS0018E", {'repo_file': repofile}) return repo_id
def _create_volume_with_capacity(self, cb, params): pool_name = params.pop('pool') vol_xml = """ <volume> <name>%(name)s</name> <allocation unit='bytes'>%(allocation)s</allocation> <capacity unit='bytes'>%(capacity)s</capacity> <source> </source> <target> <format type='%(format)s'/> </target> </volume> """ params.setdefault('allocation', 0) params.setdefault('format', 'qcow2') name = params['name'] try: pool = StoragePoolModel.get_storagepool(pool_name, self.conn) xml = vol_xml % params except KeyError, item: raise MissingParameter("KCHVOL0004E", { 'item': str(item), 'volume': name })
def _get_os_info(self, args, scan): distro = version = 'unknown' # Identify the cdrom if present iso = args.get('cdrom', '') if len(iso) > 0: if not iso.startswith('/'): self.info.update({'iso_stream': True}) if scan: distro, version = self.get_iso_info(iso) return distro, version # CDROM is not presented: check for base image base_imgs = [] for d in args.get('disks', []): if 'base' in d.keys(): base_imgs.append(d) if scan: distro, version = imageinfo.probe_image(d['base']) if 'size' not in d.keys(): d_info = imageinfo.probe_img_info(d['base']) d['size'] = d_info['virtual-size'] if len(base_imgs) == 0: raise MissingParameter("KCHTMPL0016E") return distro, version
def login(self, *args): params = parse_request() try: username = params['username'] password = params['password'] except KeyError, item: e = MissingParameter('KCHAUTH0003E', {'item': str(item)}) raise cherrypy.HTTPError(400, e.message)
def updateRepo(self, repo_id, repo={}): """ Update a given repository in repositories.Repositories() format """ if len(repo) == 0: raise MissingParameter("KCHREPOS0013E") self.removeRepo(repo_id) self.addRepo(repo)
def vms_create(self, params): t_name = template_name_from_uri(params['template']) name = get_vm_name(params.get('name'), t_name, self._mock_vms.keys()) if name in self._mock_vms: raise InvalidOperation("KCHVM0001E", {'name': name}) vm_uuid = str(uuid.uuid4()) vm_overrides = dict() pool_uri = params.get('storagepool') if pool_uri: vm_overrides['storagepool'] = pool_uri t = self._get_template(t_name, vm_overrides) t.validate() t_info = copy.deepcopy(t.info) graphics = params.get('graphics') if graphics: t_info.update({'graphics': graphics}) vm = MockVM(vm_uuid, name, t_info) icon = t_info.get('icon') if icon: vm.info['icon'] = icon pool = t._storage_validate() if pool.info['type'] == 'scsi': vm.disk_paths = [] if not params.get('volumes'): raise MissingParameter('KCHVM0017E') for vol in params['volumes']: vm.disk_paths.append({'pool': pool.name, 'volume': vol}) else: vm.disk_paths = t.fork_vm_storage(vm_uuid) index = 0 for disk in vm.disk_paths: storagepath = self._mock_storagepools[disk['pool']].info['path'] fullpath = os.path.join(storagepath, disk['volume']) dev_name = "hd" + string.ascii_lowercase[index] params = {'dev': dev_name, 'path': fullpath, 'type': 'disk'} vm.storagedevices[dev_name] = MockVMStorageDevice(params) index += 1 cdrom = "hd" + string.ascii_lowercase[index + 1] cdrom_params = {'dev': cdrom, 'path': t_info['cdrom'], 'type': 'cdrom'} vm.storagedevices[cdrom] = MockVMStorageDevice(cdrom_params) self._mock_vms[name] = vm return name
def updateRepo(self, repo_id, params): """ Update a given repository in repositories.Repositories() format """ kimchiLock.acquire() repos = self._get_repos('KCHREPOS0011E') kimchiLock.release() if repo_id not in repos.repos.keys(): raise NotFoundError("KCHREPOS0012E", {'repo_id': repo_id}) entry = repos.getRepo(repo_id) baseurl = params.get('baseurl', None) config = params.get('config', {}) mirrorlist = config.get('mirrorlist', None) metalink = config.get('metalink', None) if baseurl is not None and len(baseurl.strip()) == 0: baseurl = None if mirrorlist is not None and len(mirrorlist.strip()) == 0: mirrorlist = None if metalink is not None and len(metalink.strip()) == 0: metalink = None if baseurl is None and mirrorlist is None and metalink is None: raise MissingParameter("KCHREPOS0013E") if baseurl is not None: validate_repo_url(baseurl) entry.baseurl = baseurl if mirrorlist is not None: validate_repo_url(mirrorlist) entry.mirrorlist = mirrorlist if metalink is not None: validate_repo_url(metalink) entry.metalink = metalink if mirrorlist and metalink: raise InvalidOperation('KCHREPOS0030E') entry.id = params.get('repo_id', repo_id) entry.name = config.get('repo_name', entry.name) entry.gpgcheck = config.get('gpgcheck', entry.gpgcheck) entry.gpgkey = config.get('gpgkey', entry.gpgkey) kimchiLock.acquire() self._conf.writeRawRepoFile(entry) kimchiLock.release() return repo_id
def create(self, vm, params): conn = self.conn.get() networks = conn.listNetworks() + conn.listDefinedNetworks() networks = map(lambda x: x.decode('utf-8'), networks) if params['type'] == 'network': network = params.get("network") if network is None: raise MissingParameter('KCHVMIF0007E') if network not in networks: raise InvalidParameter('KCHVMIF0002E', { 'name': vm, 'network': network }) macs = (iface.mac.get('address') for iface in self.get_vmifaces(vm, self.conn)) # user defined customized mac address if 'mac' in params and params['mac']: # make sure it is unique if params['mac'] in macs: raise InvalidParameter('KCHVMIF0009E', { 'name': vm, 'mac': params['mac'] }) # otherwise choose a random mac address else: while True: params['mac'] = VMIfacesModel.random_mac() if params['mac'] not in macs: break dom = VMModel.get_vm(vm, self.conn) os_data = VMModel.vm_get_os_metadata(dom, self.caps.metadata_support) os_version, os_distro = os_data xml = get_iface_xml(params, conn.getInfo()[0], os_distro, os_version) flags = 0 if dom.isPersistent(): flags |= libvirt.VIR_DOMAIN_AFFECT_CONFIG if DOM_STATE_MAP[dom.info()[0]] != "shutoff": flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE dom.attachDeviceFlags(xml, flags) return params['mac']
def storagevolumes_create(self, pool_name, params): pool = self._get_storagepool(pool_name) if pool.info['state'] == 'inactive': raise InvalidOperation("KCHVOL0003E", {'pool': pool_name, 'volume': params['name']}) try: name = params['name'] volume = MockStorageVolume(pool, name, params) volume.info['type'] = params['type'] volume.info['format'] = params['format'] volume.info['path'] = os.path.join( pool.info['path'], name) except KeyError, item: raise MissingParameter("KCHVOL0004E", {'item': str(item), 'volume': name})
def create(self, params): task_id = None conn = self.conn.get() try: name = params['name'] if name == ISO_POOL_NAME: raise InvalidOperation("KCHPOOL0031E") # The user may want to create a logical pool with the same name # used before but a volume group will already exist with this name # So check the volume group does not exist to create the pool if params['type'] == 'logical': vgdisplay_cmd = ['vgdisplay', name.encode('utf-8')] output, error, returncode = run_command(vgdisplay_cmd) # From vgdisplay error codes: # 1 error reading VGDA # 2 volume group doesn't exist # 3 not all physical volumes of volume group online # 4 volume group not found # 5 no volume groups found at all # 6 error reading VGDA from lvmtab if returncode not in [2, 4, 5]: raise InvalidOperation("KCHPOOL0036E", {'name': name}) if params['type'] == 'kimchi-iso': task_id = self._do_deep_scan(params) if params['type'] == 'scsi': adapter_name = params['source']['adapter_name'] extra_params = self.device.lookup(adapter_name) # Adds name, adapter_type, wwpn and wwnn to source information params['source'].update(extra_params) params['fc_host_support'] = self.caps.fc_host_support poolDef = StoragePoolDef.create(params) poolDef.prepare(conn) xml = poolDef.xml.encode("utf-8") except KeyError, item: raise MissingParameter("KCHPOOL0004E", { 'item': str(item), 'name': name })
def _set_network_bridge(self, params): try: iface = params['interface'] if iface in self.get_all_networks_interfaces(): msg_args = {'iface': iface, 'network': params['name']} raise InvalidParameter("KCHNET0006E", msg_args) except KeyError: raise MissingParameter("KCHNET0004E", {'name': params['name']}) self._ensure_iface_up(iface) if netinfo.is_bridge(iface): if 'vlan_id' in params: raise InvalidParameter('KCHNET0019E', {'name': iface}) params['bridge'] = iface elif netinfo.is_bare_nic(iface) or netinfo.is_bonding(iface): if params.get('vlan_id') is None: params['forward']['dev'] = iface else: params['bridge'] = \ self._create_vlan_tagged_bridge(str(iface), str(params['vlan_id'])) else: raise InvalidParameter("KCHNET0007E")
def update(self, vm, mac, params): dom = VMModel.get_vm(vm, self.conn) iface = self._get_vmiface(vm, mac) if iface is None: raise NotFoundError("KCHVMIF0001E", {'name': vm, 'iface': mac}) # cannot change mac address in a running system if DOM_STATE_MAP[dom.info()[0]] != "shutoff": raise InvalidOperation('KCHVMIF0011E') # mac address is a required parameter if 'mac' not in params: raise MissingParameter('KCHVMIF0008E') # new mac address must be unique if self._get_vmiface(vm, params['mac']) is not None: raise InvalidParameter('KCHVMIF0009E', { 'name': vm, 'mac': params['mac'] }) flags = 0 if dom.isPersistent(): flags |= libvirt.VIR_DOMAIN_AFFECT_CONFIG # remove the current nic xml = etree.tostring(iface) dom.detachDeviceFlags(xml, flags=flags) # add the nic with the desired mac address iface.mac.attrib['address'] = params['mac'] xml = etree.tostring(iface) dom.attachDeviceFlags(xml, flags=flags) return [vm, params['mac']]
def create(self, params): conn = self.conn.get() t_name = template_name_from_uri(params['template']) vm_uuid = str(uuid.uuid4()) vm_list = self.get_list() name = get_vm_name(params.get('name'), t_name, vm_list) # incoming text, from js json, is unicode, do not need decode if name in vm_list: raise InvalidOperation("KCHVM0001E", {'name': name}) vm_overrides = dict() pool_uri = params.get('storagepool') if pool_uri: vm_overrides['storagepool'] = pool_uri vm_overrides['fc_host_support'] = self.caps.fc_host_support t = TemplateModel.get_template(t_name, self.objstore, self.conn, vm_overrides) if not self.caps.qemu_stream and t.info.get('iso_stream', False): raise InvalidOperation("KCHVM0005E") t.validate() # If storagepool is SCSI, volumes will be LUNs and must be passed by # the user from UI or manually. vol_list = [] if t._get_storage_type() in READONLY_POOL_TYPE: if not params.get('volumes'): raise MissingParameter('KCHVM0017E') else: # Get system path of the LUNs pool = t.info['storagepool'].split('/')[-1] for vol in params.get('volumes'): path = self._get_volume_path(pool, vol) vol_list.append((vol, path)) else: vol_list = t.fork_vm_storage(vm_uuid) # Store the icon for displaying later icon = t.info.get('icon') if icon: with self.objstore as session: session.store('vm', vm_uuid, {'icon': icon}) libvirt_stream = False if len(self.caps.libvirt_stream_protocols) == 0: libvirt_stream = True graphics = params.get('graphics') xml = t.to_vm_xml(name, vm_uuid, libvirt_stream=libvirt_stream, qemu_stream_dns=self.caps.qemu_stream_dns, graphics=graphics, volumes=vol_list) try: conn.defineXML(xml.encode('utf-8')) except libvirt.libvirtError as e: if t._get_storage_type() not in READONLY_POOL_TYPE: for v in vol_list: vol = conn.storageVolLookupByPath(v['path']) vol.delete(0) raise OperationFailed("KCHVM0007E", {'name': name, 'err': e.get_error_message()}) return name