def get_routes_directiveformat(self, routecfg_path): """ This method reads from routes file and contructs key,value information. for the below format. :param :route file path which has info in network directives format :return: dictionary consisting of route information read from file Ex: ADDRESS0=10.10.10.13 NETMASK0=255.255.255.254 GATEWAY0=10.10.10.15 METRIC0=1 """ with open(routecfg_path, "r") as routecfg_file: line = routecfg_file.read() cfgroutes_info = {} route_input = line.split() for elem in route_input: try: cfgroutes_info[elem.split('=')[0]] = elem.split('=')[1] except Exception, e: raise OperationFailed("GINNET0030E", {'err': e.message})
def change_dasdpart_type(part, type): """ Change the type of the dasd partition :param part: name of the dasd partition e.g. dasd1 :param type: partition type to be changed to e.g 4 (Linux LVM type) :return: """ partnum = ''.join(filter(lambda x: x.isdigit(), part)) typ_str = '\nt\n' + partnum + '\n' + type + '\n' + 'w\n' devname = ''.join(i for i in part if not i.isdigit()) devname = '/dev/' + devname p1_out = subprocess.Popen(["echo", "-e", "\'", typ_str, "\'"], stdout=subprocess.PIPE) p2_out = subprocess.Popen(["fdasd", devname], stdin=p1_out.stdout, stderr=subprocess.PIPE, stdout=subprocess.PIPE) p1_out.stdout.close() out, err = p2_out.communicate() if p2_out.returncode != 0: raise OperationFailed("GINDASDPAR0014E", {'err': err}) return
def getPackageInfo(self, pkg_name): """ Get package information. The return is a dictionary containg the information about a package, in the format: package = {'package_name': <string>, 'version': <string>, 'arch': <string>, 'repository': <string> } """ self.wait_pkg_manager_available() package = {} try: self._apt_cache.open() self._apt_cache.upgrade() pkgs = self._apt_cache.get_changes() self._apt_cache.close() except Exception, e: raise OperationFailed('GGBPKGUPD0006E', {'err': e.message})
def create(self, vmid, params): dev_name = params['name'] self._passthrough_device_validate(dev_name) dev_info = DeviceModel(conn=self.conn).lookup(dev_name) with RollbackContext() as rollback: try: dev = self.conn.get().nodeDeviceLookupByName(dev_name) dev.dettach() except Exception: raise OperationFailed('KCHVMHDEV0005E', {'name': dev_name}) else: rollback.prependDefer(dev.reAttach) attach_device = getattr( self, '_attach_%s_device' % dev_info['device_type']) info = attach_device(vmid, dev_info) rollback.commitAll() return info
def _refreshUpdateList(self): """ Update the list of packages to be updated in the system. """ self._pkgs = [] cmd = ["zypper", "list-updates"] (stdout, stderr, returncode) = run_command(cmd) if len(stderr) > 0: raise OperationFailed('GGBPKGUPD0003E', {'err': stderr}) for line in stdout.split('\n'): if line.find('v |') >= 0: info = line.split(' | ') package = { 'package_name': info[2], 'version': info[4], 'arch': info[5], 'repository': info[1] } self._pkgs.append(package)
def fork_vm_storage(self, vm_uuid): # Provision storages: disk_and_vol_list = self.to_volume_list(vm_uuid) try: for v in disk_and_vol_list: if v['pool'] is not None: pool = self._get_storage_pool(v['pool']) # outgoing text to libvirt, decode('utf-8') pool.createXML(v['xml'].decode('utf-8'), 0) else: capacity = v['capacity'] format_type = v['format'] path = v['path'] create_disk_image(format_type=format_type, path=path, capacity=capacity) except libvirt.libvirtError as e: raise OperationFailed('KCHVMSTOR0008E', {'error': str(e)}) return disk_and_vol_list
def getPackagesList(self): """ Return a list of package's dictionaries. Each dictionary contains the information about a package, in the format: package = {'package_name': <string>, 'version': <string>, 'arch': <string>, 'repository': <string>} """ if self.isRunning(): raise OperationFailed('GGBPKGUPD0005E') self._refreshUpdateList() pkg_list = [] for pkg in self._pkgs: package = { 'package_name': pkg.name, 'version': pkg.version, 'arch': pkg.arch, 'repository': pkg.ui_from_repo } pkg_list.append(package) return pkg_list
def getPackagesList(self): """ Return a list of packages eligible to be updated by Zypper. """ self.wait_pkg_manager_available() packages = [] cmd = ["zypper", "list-updates"] (stdout, stderr, returncode) = run_command(cmd) if len(stderr) > 0: raise OperationFailed('GGBPKGUPD0003E', {'err': stderr}) for line in stdout.split('\n'): if line.startswith('v |'): line = line.split(' | ') pkg = {'package_name': line[2].strip(), 'version': line[4].strip(), 'arch': line[5].strip(), 'repository': line[1].strip()} packages.append(pkg) return packages
def create_disk_image(format_type, path, capacity): """ Create a disk image for the Guest Args: format: Format of the storage. e.g. qcow2 path: Path where the virtual disk will be created capacity: Capacity of the virtual disk in GBs Returns: """ out, err, rc = run_command([ "/usr/bin/qemu-img", "create", "-f", format_type, "-o", "preallocation=metadata", path, encode_value(capacity) + "G" ]) if rc != 0: raise OperationFailed("KCHTMPL0041E", {'err': err}) return
def _get_storagepool_vols_num(self, pool): try: if pool.isActive(): pool.refresh(0) return pool.numOfVolumes() else: return 0 except libvirt.libvirtError as e: # If something (say a busy pool) prevents the refresh, # throwing an Exception here would prevent all pools from # displaying information -- so return None for busy wok_log.error("ERROR: Storage Pool get vol count: %s " % e.get_error_message()) wok_log.error("ERROR: Storage Pool get vol count error no: %s " % e.get_error_code()) return 0 except Exception as e: raise OperationFailed("KCHPOOL0008E", { 'name': pool.name(), 'err': e.get_error_message() })
def construct_rules(self, params): """ Creates file system, system call rule and control rules. :param params: dict with rules params :return: the rule """ try: rule = '' if params["type"] == "File System Rule": rule = '-w' rule = self.construct_fs_rule(rule, params) elif params["type"] == "System Call Rule": rule = '-a' rule = self.construct_sc_rule(rule, params) elif params["type"] == "Control Rule": rule = self.construct_control_rule(params) return rule except MissingParameter: raise except Exception as e: raise OperationFailed("GINAUD0003E", {'error': e.message})
def delete(self, name): if self._pool_used_by_template(name): raise InvalidOperation('KCHPOOL0035E', {'name': name}) pool = self.get_storagepool(name, self.conn) if pool.isActive(): raise InvalidOperation("KCHPOOL0005E", {'name': name}) vms = self._get_vms_attach_to_storagepool(name) if len(vms) > 0: raise InvalidOperation('KCHPOOL0039E', { 'name': name, 'vms': ",".join(vms) }) try: pool.undefine() except libvirt.libvirtError as e: raise OperationFailed("KCHPOOL0011E", { 'name': name, 'err': e.get_error_message() })
def run_systemd_command(command): """Function that runs systemd commands. Runs a systemd command specified in the argument, throwing a specific error if something goes wrong. Args: command (List[str]): the systemd command to be executed. Returns: str: Output of the command. Raises: OperationFailed if the return code of the command is not 0. """ output, err, rcode = run_command(command) if rcode != 0: cmd_str = ' '.join(command) raise OperationFailed('GINSERV00001E', {'cmd': cmd_str, 'err': err}) return output
def delete(self, pool, name): pool_info = StoragePoolModel(conn=self.conn, objstore=self.objstore).lookup(pool) if pool_info['type'] in READONLY_POOL_TYPE: raise InvalidParameter("KCHVOL0012E", {'type': pool_info['type']}) volume = StorageVolumeModel.get_storagevolume(pool, name, self.conn) vol_path = volume.path() try: volume.delete(0) except libvirt.libvirtError as e: raise OperationFailed("KCHVOL0010E", { 'name': name, 'err': e.get_error_message() }) try: os.remove(vol_path) except OSError, e: wok_log.error("Unable to delete storage volume file: %s." "Details: %s" % (pool_info['path'], e.message))
def create(self, vmid, params): dev_name = params['name'] dev_info = self.dev_model.lookup(dev_name) if dev_info['device_type'] == 'pci': taskid = AsyncTask( u'/plugins/kimchi/vms/%s/hostdevs/' % VMModel.get_vm(vmid, self.conn).name(), self._attach_pci_device, { 'vmid': vmid, 'dev_info': dev_info, 'lock': threading.RLock() }, ).id return self.task.lookup(taskid) with RollbackContext() as rollback: try: dev = self.conn.get().nodeDeviceLookupByName(dev_name) dev.dettach() except Exception: raise OperationFailed('KCHVMHDEV0005E', {'name': dev_name}) else: rollback.prependDefer(dev.reAttach) rollback.commitAll() taskid = AsyncTask( u'/plugins/kimchi/vms/%s/hostdevs/' % VMModel.get_vm(vmid, self.conn).name(), '_attach_%s_device' % dev_info['device_type'], { 'vmid': vmid, 'dev_info': dev_info, 'lock': threading.RLock() }, ).id return self.task.lookup(taskid)
def upgrade_objectstore_template_disks(libv_conn): """ Upgrade the value of a given JSON's item of all Templates. Removes 'storagepool' entry and adds 'pool: { name: ..., type: ... }' """ total = 0 try: conn = sqlite3.connect(config.get_object_store(), timeout=10) cursor = conn.cursor() sql = "SELECT id, json FROM objects WHERE type='template'" cursor.execute(sql) for row in cursor.fetchall(): template = json.loads(row[1]) # Get pool info pool_uri = template['storagepool'] pool_name = pool_name_from_uri(pool_uri) pool = libv_conn.get().storagePoolLookupByName( pool_name.encode("utf-8")) pool_type = xpath_get_text(pool.XMLDesc(0), "/pool/@type")[0] # Update json new_disks = [] for disk in template['disks']: disk['pool'] = {'name': pool_uri, 'type': pool_type} new_disks.append(disk) template['disks'] = new_disks del template['storagepool'] sql = "UPDATE objects SET json=? WHERE id=?" cursor.execute(sql, (json.dumps(template), row[0])) conn.commit() total += 1 except sqlite3.Error, e: if conn: conn.rollback() wok_log.error("Error while upgrading objectstore data: %s", e.args[0]) raise OperationFailed("KCHUTILS0006E")
def update(self, vm_name, dev_name, params): old_disk_used_by = None new_disk_used_by = None dom = VMModel.get_vm(vm_name, self.conn) dev_info = self.lookup(vm_name, dev_name) if dev_info['type'] != 'cdrom': raise InvalidOperation('KCHVMSTOR0006E') params['path'] = params.get('path', '') old_disk_path = dev_info['path'] new_disk_path = params['path'] if new_disk_path != old_disk_path: # An empty path means a CD-ROM was empty or ejected: if old_disk_path != '': old_disk_used_by = get_disk_used_by(self.conn, old_disk_path) if new_disk_path != '': new_disk_used_by = get_disk_used_by(self.conn, new_disk_path) dev_info.update(params) dev, xml = get_disk_xml(dev_info) try: # FIXME: when updating from local file to remote file (http) # libvirt adds a new device with same name instead of replacing # the existing one dom.updateDeviceFlags(xml, get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed('KCHVMSTOR0009E', {'error': str(e)}) try: if old_disk_used_by is not None and vm_name in old_disk_used_by: old_disk_used_by.remove(vm_name) if new_disk_used_by is not None: new_disk_used_by.append(vm_name) except Exception as e: wok_log.error('Unable to update dev used_by on update due to' ' %s:' % str(e)) return dev
def get_sudoers(admin_check=True): """ method to get user and groups mentioned in /etc/sudoers file if admin_check is True - return users and groups with admin privilege if False, return users and groups is mentioned in /etc/sudoers file :param admin_check: True/False (to check admin/just part of sudoers file) :return: list of users and groups """ sudoers = [] try: parser = augeas.Augeas() parser.load() users = parser.match(SUDOERS_CHECK) # sample ouput with augeas: # parser.match('etc/sudoers/spec/user') # [u'/files/etc/sudoers/spec[1]/user', # u'/files/etc/sudoers/spec[2]/user', # u'/files/etc/sudoers/spec[3]/user'] # indicates /etc/sudoers file has 3 users/groups for user in users: name = parser.get(user) if isinstance(name, str): # augeas returns in unicode format name = name.encode('utf-8') if admin_check: user = user.rstrip('user') + 'host_group' # to check for commands and host # parser.get('etc/sudoers/spec[1]/host_group/host') # u'ALL' # parser.get('etc/sudoers/spec[1]/host_group/command') # Out[35]: u'ALL' if 'ALL' == parser.get(user + '/command') and\ 'ALL' == parser.get(user + '/host'): sudoers.append(name) else: sudoers.append(name) except Exception as e: raise OperationFailed('GINUSER0019E', {'error': e.__str__()}) return sudoers
def get_iscsi_session_id(iqn): """ Get the session ID of the given logged in target :param iqn: iSCSI Qualified Name :return: Session ID of the target """ iscsi_session_id = None try: current_sessions = os.listdir('/sys/class/iscsi_session') for session in current_sessions: target_name = open( '/sys/class/iscsi_session/' + session + "/targetname").readline().rstrip() if iqn == target_name: iscsi_session_id = _parse_session_dir_name(session) break except Exception as e: raise OperationFailed("GINISCSI014E", {'err': e.message, 'iqn': iqn}) return iscsi_session_id
def get_discovered_iscsi_qns(): """ List the already discovered iSCSI targets on the system Returns: Dictionary of discovered IQNs """ discovered_iqns = {} iqn_list = [] try: iscsiadm_db_path = '/etc/iscsi/nodes' if not os.path.exists(iscsiadm_db_path): iscsiadm_db_path = '/var/lib/iscsi/nodes' discovered_iqns_list = os.listdir(iscsiadm_db_path) for discovered_iqn in discovered_iqns_list: discovered_iqns[discovered_iqn] = False current_sessions = os.listdir('/sys/class/iscsi_session') # Iterate over all sessions once for efficiency instead of # calling is_target_logged_in function below for every iqn for session in current_sessions: target_name = open('/sys/class/iscsi_session/' + session + '/targetname').readline().rstrip() discovered_iqns[target_name] = True for iqn, status in discovered_iqns.iteritems(): iqn_list.append({ 'iqn': iqn, 'status': status, 'targets': get_iscsi_iqn_auth_info(iqn) }) except Exception as e: raise OperationFailed("GINISCSI005E", {'err': e.message}) return iqn_list
def iscsiadm_update_db(iqn, db_key, db_key_value): """ Method to update the iscsiadm db Args: iqn: iSCSI Qualified Name db_key: DB Key db_key_value: New Value for the DB Key Returns: None """ out, err, rc = run_command([ "iscsiadm", "--m", "node", "--targetname", iqn, "--op=update", "--name", db_key, "--value=" + db_key_value ]) if rc != 0: raise OperationFailed("GINISCSI011E", { 'err': err, 'iqn': iqn, 'db_key': db_key })
def parse_tape_list(lstape_out): """ Parse the output of the command lstape :param lstape_out : Output obtained by 'lstape' command """ try: final_list = [] input_list = lstape_out.splitlines() scsi_keys = input_list[0].split() for input_device in input_list[1:]: device_params = {} device_params_list = input_device.split() for scsi_key, device_param in zip(scsi_keys, device_params_list): device_params[scsi_key] = device_param final_list.append(device_params) except Exception as e: wok_log.error("Unable to parse output of lstape") raise OperationFailed("GS390XSTG00016", {'err': e.message}) return final_list
def get_list_of_loaded_control_rules(): control_rules = [] control_rules_dict = { 'backlog_limit': '-b', 'enabled': '-e', 'failure': '-f', 'flag': '-f', 'rate_limit': '-r' } cmd_cntl = ['auditctl', '-s'] out, err, returncode = run_command(cmd_cntl) if returncode == 0: audit_status = out.split('\n') for each_line in audit_status: if each_line.split(' ')[0] in control_rules_dict: audit_control_rule = control_rules_dict[ each_line.split(' ')[0]] + \ " " + each_line.split(' ')[1] control_rules.append(audit_control_rule) return control_rules else: raise OperationFailed('GINAUD0002E', {'name': ' '.join(cmd_cntl)})
def _get_fs_info(mnt_pt): """ Fetches information about the given filesystem :param mnt_pt: mount point of the filesystem :return: dictionary containing filesystem info """ fs_info = {} try: fs_search_list = _get_df_output() for i in fs_search_list: if mnt_pt == i['mounted_on']: fs_info['filesystem'] = i['filesystem'] fs_info['type'] = i['type'] fs_info['size'] = i['size'] fs_info['used'] = i['used'] fs_info['avail'] = i['avail'] fs_info['use%'] = i['use%'] fs_info['mounted_on'] = i['mounted_on'] except: wok_log.error("Fetching fs %s info failed", mnt_pt) raise OperationFailed("GINFS00005E", {'device': mnt_pt}) return fs_info
def getPackagesList(self): """ Return a list of package's dictionaries. Each dictionary contains the information about a package, in the format package = {'package_name': <string>, 'version': <string>, 'arch': <string>, 'repository': <string>} """ if self.isRunning(): raise OperationFailed('GGBPKGUPD0005E') gingerBaseLock.acquire() self._refreshUpdateList() gingerBaseLock.release() pkg_list = [] for pkg in self._pkgs: package = {'package_name': pkg.shortname, 'version': pkg.candidate.version, 'arch': pkg._pkg.architecture, 'repository': pkg.candidate.origins[0].label} pkg_list.append(package) return pkg_list
def update(self, name, params): if params.get('name') or params.get('ipaddr'): raise InvalidParameter("GINSE00009E") if not params.get('password'): raise MissingParameter("GINSE00008E") serverData = get_config(name) ipaddr = serverData['ipaddr'] serverData['salt'] = ''.join( random.choice(ALPHABET) for i in range(16)) serverData['password'] = encrypt(params['password'], serverData['salt']) if params.get('username'): serverData['username'] = params['username'] serverData = get_server_status(serverData) if not serverData: raise OperationFailed('GINSE00003E', { 'name': name, 'ipaddr': ipaddr }) else: update_config(serverData) return serverData['name']
def _set_network_subnet(self, params): netaddr = params.get('subnet', '') # lookup a free network address for nat and isolated automatically if not netaddr: netaddr = self._get_available_address() if not netaddr: raise OperationFailed("KCHNET0009E", {'name': params['name']}) try: ip = ipaddr.IPNetwork(netaddr) except ValueError: raise InvalidParameter("KCHNET0003E", {'subent': netaddr, 'network': params['name']}) if ip.ip == ip.network: ip.ip = ip.ip + 1 dhcp_start = str(ip.ip + ip.numhosts / 2) dhcp_end = str(ip.ip + ip.numhosts - 2) params.update({'net': str(ip), 'dhcp': {'range': {'start': dhcp_start, 'end': dhcp_end}}})
def getPackageInfo(self, pkg_name): """ Get package information. The return is a dictionary containg the information about a package, in the format: package = {'package_name': <string>, 'version': <string>, 'arch': <string>, 'repository': <string> } """ self.wait_pkg_manager_available() cmd = ["zypper", "info", pkg_name] (stdout, stderr, returncode) = run_command(cmd) if len(stderr) > 0: raise OperationFailed('GGBPKGUPD0006E', {'err': stderr}) # Zypper returns returncode == 0 and stderr <= 0, even if package is # not found in it's base. Need check the output of the command to parse # correctly. message = '\'%s\' not found' % pkg_name if message in stdout: raise NotFoundError('GGBPKGUPD0006E', {'err': message}) package = {} stdout = stdout.split('\n') for (key, token) in (('repository', 'Repository:'), ('version', 'Version:'), ('arch', 'Arch:'), ('package_name', 'Name:')): for line in stdout: if line.startswith(token): package[key] = line.split(': ')[1].strip() break return package
def _create_archive(self, params): error = None try: params['file'] = _tar_create_archive( self._archive_dir, params['identity'], params['include'], params['exclude']) params['checksum'] = {'algorithm': 'sha256', 'value': _sha256sum(params['file'])} with self._objstore as session: session.store(self._objstore_type, params['identity'], params) except TimeoutExpired as e: error = e reason = 'GINHBK0010E' except Exception as e: error = e reason = 'GINHBK0009E' if error is not None: msg = 'Error creating archive %s: %s' % (params['identity'], error) wok_log.error(msg) try: with self._objstore as session: session.delete(self._objstore_type, params['identity'], ignore_missing=True) except Exception as e_session: wok_log.error('Error cleaning archive meta data %s. ' 'Error: %s', params['identity'], e_session) if params['file'] != '': try: os.unlink(params['file']) except Exception as e_file: wok_log.error('Error cleaning archive file %s. ' 'Error: %s', params['file'], e_file) raise OperationFailed(reason, {'identity': params['identity']})
def create(self, params): if utils.is_lun_scan_enabled()['current']: wok_log.error( "Lun scan is enabled. Cannot add/remove LUNs manually.") raise InvalidOperation("GS390XSTG00009") if 'hbaId' not in params: wok_log.error("hbaId is required for adding a LUN") raise MissingParameter("GS390XSTG00010") hbaId = params['hbaId'] utils.validate_hba_id(hbaId) if 'remoteWwpn' not in params: wok_log.error("remoteWwpn is required for adding a LUN") raise MissingParameter("GS390XSTG00011") wwpn = params['remoteWwpn'] utils.validate_wwpn_or_lun(wwpn) if 'lunId' not in params: wok_log.error("lunId is required for adding a LUN") raise MissingParameter("GS390XSTG00012") lunId = params['lunId'] utils.validate_wwpn_or_lun(lunId) try: fc_lock.acquire() utils.add_lun(hbaId, wwpn, lunId) except OperationFailed as e: wok_log.error("Adding LUN failed") raise OperationFailed("GS390XSTG00003", {'err': e}) finally: fc_lock.release() lun_path = hbaId + ":" + wwpn + ":" + lunId return lun_path