def diskpool_get_info(self, pool): dp_info = self._smutclient.get_diskpool_info(pool) with zvmutils.expect_invalid_resp_data(dp_info): for k in list(dp_info.keys()): s = dp_info[k].strip().upper() if s.endswith('G'): sl = s[:-1].split('.') n1, n2 = int(sl[0]), int(sl[1]) if n2 >= 5: n1 += 1 dp_info[k] = n1 elif s.endswith('M'): n_mb = int(s[:-3]) n_gb, n_ad = n_mb // 1024, n_mb % 1024 if n_ad >= 512: n_gb += 1 dp_info[k] = n_gb else: exp = "ending with a 'G' or 'M'" errmsg = ("Invalid diskpool size format: %(invalid)s; " "Expected: %(exp)s") % {'invalid': s, 'exp': exp} LOG.error(errmsg) raise exception.SDKInternalError(msg=errmsg) return dp_info
def get_info(self, userid): power_stat = self.get_power_state(userid) perf_info = self._smutclient.get_image_performance_info(userid) if perf_info: try: max_mem_kb = int(perf_info['max_memory'].split()[0]) mem_kb = int(perf_info['used_memory'].split()[0]) num_cpu = int(perf_info['guest_cpus']) cpu_time_us = int(perf_info['used_cpu_time'].split()[0]) except (ValueError, TypeError, IndexError, AttributeError, KeyError) as err: LOG.error('Parse performance_info encounter error: %s', str(perf_info)) raise exception.SDKInternalError(msg=str(err), modID='guest') return {'power_state': power_stat, 'max_mem_kb': max_mem_kb, 'mem_kb': mem_kb, 'num_cpu': num_cpu, 'cpu_time_us': cpu_time_us} else: # virtual machine in shutdown state or not exists dict_info = self._smutclient.get_user_direct(userid) return { 'power_state': power_stat, 'max_mem_kb': self._get_max_memory_from_user_dict(dict_info), 'mem_kb': 0, 'num_cpu': self._get_cpu_num_from_user_dict(dict_info), 'cpu_time_us': 0}
def get_adapters_info(self, userid): adapters_info = self._smtclient.get_adapters_info(userid) if not adapters_info: msg = 'Get network information failed on: %s' % userid LOG.error(msg) raise exception.SDKInternalError(msg=msg, modID='guest') return {'adapters': adapters_info}
def get_console_output(self, userid): def append_to_log(log_data, log_path): LOG.debug('log_data: %(log_data)r, log_path: %(log_path)r', {'log_data': log_data, 'log_path': log_path}) with open(log_path, 'a+') as fp: fp.write(log_data) return log_path LOG.info("Begin to capture console log on vm %s", userid) log_size = CONF.guest.console_log_size * 1024 console_log = self._smutclient.get_user_console_output(userid) log_path = self._pathutils.get_console_log_path(userid) # TODO: need consider shrink log file size append_to_log(console_log, log_path) log_fp = file(log_path, 'rb') try: log_data, remaining = zvmutils.last_bytes(log_fp, log_size) except Exception as err: msg = ("Failed to truncate console log, error: %s" % six.text_type(err)) LOG.error(msg) raise exception.SDKInternalError(msg) if remaining > 0: LOG.info('Truncated console log returned, %d bytes ignored' % remaining) LOG.info("Complete get console output on vm %s", userid) return log_data
def execute(cmd): """ execute command, return rc and output string. The cmd argument can be a string or a list composed of the command name and each of its argument. eg, ['/usr/bin/cp', '-r', 'src', 'dst'] """ # Parse cmd string to a list if not isinstance(cmd, list): cmd = shlex.split(cmd) # Execute command rc = 0 output = "" try: output = subprocess.check_output(cmd, close_fds=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as err: rc = err.returncode output = err.output except Exception as err: err_msg = ('Command "%s" Error: %s' % (' '.join(cmd), str(err))) raise exception.SDKInternalError(msg=err_msg) output = bytes.decode(output) return (rc, output)
def translate_response_to_dict(rawdata, dirt): """Translate SMUT response to a python dictionary. SMUT response example: keyword1: value1\n keyword2: value2\n ... keywordn: valuen\n Will return a python dictionary: {keyword1: value1, keyword2: value2, ... keywordn: valuen,} """ data_list = rawdata.split("\n") data = {} for ls in data_list: for k in list(dirt.keys()): if ls.__contains__(dirt[k]): data[k] = ls[(ls.find(dirt[k]) + len(dirt[k])):].strip() break if data == {}: msg = ("Invalid smut response data. Error: No value matched with " "keywords. Raw Data: %(raw)s; Keywords: %(kws)s" % {'raw': rawdata, 'kws': str(dirt)}) raise exception.SDKInternalError(msg=msg) return data
def update_guest_by_userid(self, userid, meta=None, net_set=None, comments=None): userid = userid if (meta is None) and (net_set is None) and (comments is None): msg = ("Update guest with userid: %s failed, no field " "specified to be updated." % userid) LOG.error(msg) raise exception.SDKInternalError(msg=msg, modID=self._module_id) # First check whether the guest exist in db table self._check_existence_by_userid(userid) # Start update sql_cmd = "UPDATE guests SET" sql_var = [] if meta is not None: sql_cmd += " metadata=?," sql_var.append(meta) if net_set is not None: sql_cmd += " net_set=?," sql_var.append(net_set) if comments is not None: sql_cmd += " comments=?," sql_var.append(comments) # remove the tailing comma sql_cmd = sql_cmd.strip(',') # Add the id filter sql_cmd += " WHERE userid=?" sql_var.append(userid) with get_guest_conn() as conn: conn.execute(sql_cmd, sql_var)
def decorated_function(*arg, **kwargs): try: return function(*arg, **kwargs) except (ValueError, TypeError, IndexError, AttributeError, KeyError) as err: msg = ('Invalid smt response data. Error: %s' % six.text_type(err)) LOG.error(msg) raise exception.SDKInternalError(msg=msg)
def expect_and_reraise_internal_error(modID='SDK'): """Catch all kinds of zvm client request failure and reraise. modID: the moduleID that the internal error happens in. """ try: yield except exception.SDKInternalError as err: msg = err.format_message() raise exception.SDKInternalError(msg, modID=modID)
def expect_invalid_resp_data(data=''): """Catch exceptions when using zvm client response data.""" try: yield except (ValueError, TypeError, IndexError, AttributeError, KeyError) as err: msg = ('Invalid smut response data: %s. Error: %s' % (data, six.text_type(err))) LOG.error(msg) raise exception.SDKInternalError(msg=msg)
def get_smut_userid(): """Get the userid of smut server""" cmd = ["sudo", "/sbin/vmcp", "query userid"] try: userid = subprocess.check_output(cmd, close_fds=True, stderr=subprocess.STDOUT).split()[0] return userid except Exception as err: msg = ("Could not find the userid of the smut server: %s") % err raise exception.SDKInternalError(msg=msg)
def check_userid_on_others(userid): try: check_userid_exist(userid) cmd = 'sudo vmcp q %s' % userid rc, output = execute(cmd) if re.search(' - SSI', output): return True return False except Exception as err: msg = ("Could not find the userid: %s") % err raise exception.SDKInternalError(msg=msg)
def _expand_fcp_list(fcp_list): """Expand fcp list string into a python list object which contains each fcp devices in the list string. A fcp list is composed of fcp device addresses, range indicator '-', and split indicator ';'. For example, if fcp_list is "0011-0013;0015;0017-0018", expand_fcp_list(fcp_list) will return [0011, 0012, 0013, 0015, 0017, 0018]. ATTENTION: To support multipath, we expect fcp_list should be like "0011-0014;0021-0024", "0011-0014" should have been on same physical WWPN which we called path0, "0021-0024" should be on another physical WWPN we called path1 which is different from "0011-0014". path0 and path1 should have same count of FCP devices in their group. When attach, we will choose one WWPN from path0 group, and choose another one from path1 group. Then we will attach this pair of WWPNs together to the guest as a way to implement multipath. """ LOG.debug("Expand FCP list %s" % fcp_list) if not fcp_list: return set() fcp_list = fcp_list.strip() fcp_list = fcp_list.replace(' ', '') range_pattern = '[0-9a-fA-F]{1,4}(-[0-9a-fA-F]{1,4})?' match_pattern = "^(%(range)s)(;%(range)s;?)*$" % \ {'range': range_pattern} if not re.match(match_pattern, fcp_list): errmsg = ("Invalid FCP address %s") % fcp_list raise exception.SDKInternalError(msg=errmsg) fcp_devices = {} path_no = 0 for _range in fcp_list.split(';'): # remove duplicate entries devices = set() if _range != '': if '-' not in _range: # single device fcp_addr = int(_range, 16) devices.add("%04x" % fcp_addr) else: # a range of address (_min, _max) = _range.split('-') _min = int(_min, 16) _max = int(_max, 16) for fcp_addr in range(_min, _max + 1): devices.add("%04x" % fcp_addr) fcp_devices[path_no] = devices path_no = path_no + 1 return fcp_devices
def convert_to_mb(s): """Convert memory size from GB to MB.""" s = s.upper() try: if s.endswith('G'): return float(s[:-1].strip()) * 1024 elif s.endswith('T'): return float(s[:-1].strip()) * 1024 * 1024 else: return float(s[:-1].strip()) except (IndexError, ValueError, KeyError, TypeError): errmsg = ("Invalid memory format: %s") % s raise exception.SDKInternalError(msg=errmsg)
def get_lpar_name(): """Get the name of the LPAR that this vm is on.""" cmd = ["sudo", "/sbin/vmcp", "query userid"] try: userid = subprocess.check_output(cmd, close_fds=True, stderr=subprocess.STDOUT) userid = bytes.decode(userid) userid = userid.split()[-1] return userid except Exception as err: msg = ("Failed to get the LPAR name for the smt server: %s") % err raise exception.SDKInternalError(msg=msg)
def get_metadata_by_userid(self, userid): """get metadata record. output should be like: "a=1,b=2,c=3" """ userid = userid with get_guest_conn() as conn: res = conn.execute("SELECT * FROM guests " "WHERE userid=?", (userid, )) guest = res.fetchall() if len(guest) == 1: return guest[0][2] elif len(guest) == 0: LOG.debug("Guest with userid: %s not found from DB!" % userid) return '' else: msg = "Guest with userid: %s have multiple records!" % userid LOG.error(msg) raise exception.SDKInternalError(msg=msg, modID=self._module_id)
def _expand_fcp_list(fcp_list): """Expand fcp list string into a python list object which contains each fcp devices in the list string. A fcp list is composed of fcp device addresses, range indicator '-', and split indicator ';'. For example, if fcp_list is "0011-0013;0015;0017-0018", expand_fcp_list(fcp_list) will return [0011, 0012, 0013, 0015, 0017, 0018]. """ LOG.debug("Expand FCP list %s" % fcp_list) if not fcp_list: return set() range_pattern = '[0-9a-fA-F]{1,4}(-[0-9a-fA-F]{1,4})?' match_pattern = "^(%(range)s)(;%(range)s)*$" % {'range': range_pattern} if not re.match(match_pattern, fcp_list): errmsg = ("Invalid FCP address %s") % fcp_list raise exception.SDKInternalError(msg=errmsg) fcp_devices = set() for _range in fcp_list.split(';'): if '-' not in _range: # single device fcp_addr = int(_range, 16) fcp_devices.add("%04x" % fcp_addr) else: # a range of address (_min, _max) = _range.split('-') _min = int(_min, 16) _max = int(_max, 16) for fcp_addr in range(_min, _max + 1): fcp_devices.add("%04x" % fcp_addr) # remove duplicate entries return fcp_devices
def get_info(self, userid): power_stat = self.get_power_state(userid) perf_info = self._smtclient.get_image_performance_info(userid) # Get the online CPU number, OS distro and kernel version try: act_cpus = self._smtclient.get_active_cpu_addrs(userid) act_cpus_num = len(act_cpus) LOG.debug('Online cpu info: %s, %d' % (act_cpus, act_cpus_num)) except exception.SDKSMTRequestFailed as err: msg = ('Failed to execute command on capture source vm %(vm)s ' 'to get online cpu number with error %(err)s' % {'vm': userid, 'err': err.results['response'][0]}) LOG.error(msg) act_cpus_num = 0 try: os_distro = self._smtclient.guest_get_os_version(userid) kernel_info = self._smtclient.guest_get_kernel_info(userid) LOG.debug('OS and kernel info: %s, %s' % (os_distro, kernel_info)) except exception.SDKSMTRequestFailed as err: msg = ('Failed to execute command on capture source vm %(vm)s ' 'to get OS distro with error %(err)s' % {'vm': userid, 'err': err.results['response'][0]}) LOG.error(msg) os_distro = '' kernel_info = '' if perf_info: try: max_mem_kb = int(perf_info['max_memory'].split()[0]) mem_kb = int(perf_info['used_memory'].split()[0]) num_cpu = int(perf_info['guest_cpus']) cpu_time_us = int(perf_info['used_cpu_time'].split()[0]) except (ValueError, TypeError, IndexError, AttributeError, KeyError) as err: LOG.error('Parse performance_info encounter error: %s', str(perf_info)) raise exception.SDKInternalError(msg=str(err), modID='guest') return {'power_state': power_stat, 'max_mem_kb': max_mem_kb, 'mem_kb': mem_kb, 'num_cpu': num_cpu, 'cpu_time_us': cpu_time_us, 'online_cpu_num': act_cpus_num, 'os_distro': os_distro, 'kernel_info': kernel_info} else: # virtual machine in shutdown state or not exists dict_info = self._smtclient.get_user_direct(userid) return { 'power_state': power_stat, 'max_mem_kb': self._get_max_memory_from_user_dict(dict_info), 'mem_kb': 0, 'num_cpu': self._get_cpu_num_from_user_dict(dict_info), 'cpu_time_us': 0, 'online_cpu_num': act_cpus_num, 'os_distro': os_distro, 'kernel_info': kernel_info}