def get_error_msg(self):
        # We got an error, lets go fetch the error message
        self._write_cmd('lastlog\n')

        # read everything from the STDOUT to the next prompt
        stdout, report, stderr = self._read_until_prompt()

        try:
            log = json.loads(report)

            if 'log' in log:
                error_msg = ""
                # Walk the entire log array and build an error string
                for log_entry in log['log']:
                    if log_entry['log_type'] == "error":
                        if error_msg:
                            error_msg += ', ' + log_entry['log_message']
                        else:
                            error_msg = log_entry['log_message']

                return error_msg

            return 'No error reason provided! (missing "log" section)'
        except ValueError:
            log_error("Invalid JSON returned from LVM")
            log_error("BEGIN>>\n%s\n<<END" % report)
            return "Invalid JSON returned from LVM when retrieving exit code"
Beispiel #2
0
def _shell_cfg():
	global _t_call
	# noinspection PyBroadException
	try:
		lvm_shell = LVMShellProxy()
		_t_call = lvm_shell.call_lvm
		cfg.SHELL_IN_USE = lvm_shell
		return True
	except Exception:
		_t_call = call_lvm
		cfg.SHELL_IN_USE = None
		log_error(traceback.format_exc())
		log_error("Unable to utilize lvm shell, dropping back to fork & exec")
		return False
Beispiel #3
0
def _shell_cfg():
	global _t_call
	# noinspection PyBroadException
	try:
		lvm_shell = LVMShellProxy()
		_t_call = lvm_shell.call_lvm
		cfg.SHELL_IN_USE = lvm_shell
		return True
	except Exception:
		_t_call = call_lvm
		cfg.SHELL_IN_USE = None
		log_error(traceback.format_exc())
		log_error("Unable to utilize lvm shell, dropping back to fork & exec")
		return False
 def fetch_lvs(self, lv_names):
     try:
         if not lv_names:
             return self.lvs.values()
         else:
             rc = []
             for s in lv_names:
                 rc.append(self.lvs[self.lv_full_name_to_uuid[s]])
             return rc
     except KeyError as ke:
         log_error("Key %s not found!" % (str(lv_names)))
         log_error("lv name to uuid lookup")
         for keys in sorted(self.lv_full_name_to_uuid.keys()):
             log_error("%s" % (keys))
         log_error("lvs entries by uuid")
         for keys in sorted(self.lvs.keys()):
             log_error("%s" % (keys))
         raise ke
Beispiel #5
0
	def dump(self):
		with cmd_lock:
			if len(self.queue):
				log_error("LVM dbus flight recorder START")
				for c in self.queue:
					log_error(str(c))
				log_error("LVM dbus flight recorder END")
    def call_lvm(self, argv, debug=False):
        rc = 1
        error_msg = ""
        json_result = ""

        # create the command string
        cmd = " ".join(_quote_arg(arg) for arg in argv)
        cmd += "\n"

        # run the command by writing it to the shell's STDIN
        self._write_cmd(cmd)

        # read everything from the STDOUT to the next prompt
        stdout, report, stderr = self._read_until_prompt()

        # Parse the report to see what happened
        if report and len(report):
            json_result = json.loads(report)
            if 'log' in json_result:
                if json_result['log'][-1:][0]['log_ret_code'] == '1':
                    rc = 0
                else:
                    error_msg = self.get_error_msg()

        if debug or rc != 0:
            log_error(('CMD: %s' % cmd))
            log_error(("EC = %d" % rc))
            log_error(("ERROR_MSG=\n %s\n" % error_msg))

        return rc, json_result, error_msg
Beispiel #7
0
	def dump(self):
		with cmd_lock:
			if len(self.queue):
				log_error("LVM dbus flight recorder START")
				for c in reversed(self.queue):
					log_error(str(c))
				log_error("LVM dbus flight recorder END")
Beispiel #8
0
def pv_retrieve_with_segs(device=None):
    d = []
    err = ""
    out = ""
    rc = 0

    columns = [
        'pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free', 'pv_used',
        'dev_size', 'pv_mda_size', 'pv_mda_free', 'pv_ba_start', 'pv_ba_size',
        'pe_start', 'pv_pe_count', 'pv_pe_alloc_count', 'pv_attr', 'pv_tags',
        'vg_name', 'vg_uuid', 'pvseg_start', 'pvseg_size', 'segtype',
        'pv_missing'
    ]

    # Lvm has some issues where it returns failure when querying pvs when other
    # operations are in process, see:
    # https://bugzilla.redhat.com/show_bug.cgi?id=1274085
    for i in range(0, 10):
        cmd = _dc('pvs', ['-o', ','.join(columns)])

        if device:
            cmd.extend(device)

        rc, out, err = call(cmd)

        if rc == 0:
            d = parse_column_names(out, columns)
            break
        else:
            time.sleep(0.2)
            log_debug("LVM Bug workaround, retrying pvs command...")

    if rc != 0:
        msg = "We were unable to get pvs to return without error after " \
         "trying 10 times, RC=%d, STDERR=(%s), STDOUT=(%s)" % \
         (rc, err, out)
        log_error(msg)
        raise RuntimeError(msg)

    return d
	def call_lvm(self, argv, debug=False):
		rc = 1
		error_msg = ""

		if self.lvm_shell.poll():
			raise Exception(
				self.lvm_shell.returncode,
				"Underlying lvm shell process is not present!")

		argv = add_no_notify(argv)

		# create the command string
		cmd = " ".join(_quote_arg(arg) for arg in argv)
		cmd += "\n"

		# run the command by writing it to the shell's STDIN
		self._write_cmd(cmd)

		# read everything from the STDOUT to the next prompt
		stdout, report_json, stderr = self._read_until_prompt()

		# Parse the report to see what happened
		if 'log' in report_json:
			if report_json['log'][-1:][0]['log_ret_code'] == '1':
				rc = 0
			else:
				error_msg = self.get_error_msg()

		if debug or rc != 0:
			log_error(('CMD: %s' % cmd))
			log_error(("EC = %d" % rc))
			log_error(("ERROR_MSG=\n %s\n" % error_msg))

		return rc, report_json, error_msg
Beispiel #10
0
def pv_retrieve_with_segs(device=None):
	d = []
	err = ""
	out = ""
	rc = 0

	columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
				'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
				'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
				'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
				'vg_uuid', 'pvseg_start', 'pvseg_size', 'segtype', 'pv_missing']

	# Lvm has some issues where it returns failure when querying pvs when other
	# operations are in process, see:
	# https://bugzilla.redhat.com/show_bug.cgi?id=1274085
	for i in range(0, 10):
		cmd = _dc('pvs', ['-o', ','.join(columns)])

		if device:
			cmd.extend(device)

		rc, out, err = call(cmd)

		if rc == 0:
			d = parse_column_names(out, columns)
			break
		else:
			time.sleep(0.2)
			log_debug("LVM Bug workaround, retrying pvs command...")

	if rc != 0:
		msg = "We were unable to get pvs to return without error after " \
			"trying 10 times, RC=%d, STDERR=(%s), STDOUT=(%s)" % \
			(rc, err, out)
		log_error(msg)
		raise RuntimeError(msg)

	return d
Beispiel #11
0
def _debug_c(cmd, exit_code, out):
	log_error('CMD= %s' % ' '.join(cmd))
	log_error(("EC= %d" % exit_code))
	log_error(("STDOUT=\n %s\n" % out[0]))
	log_error(("STDERR=\n %s\n" % out[1]))
Beispiel #12
0
def call_lvm(command, debug=False, line_cb=None,
			 cb_data=None):
	"""
	Call an executable and return a tuple of exitcode, stdout, stderr
	:param command: Command to execute
	:param debug:   Dump debug to stdout
	:param line_cb:	Call the supplied function for each line read from
					stdin, CALL MUST EXECUTE QUICKLY and not *block*
					otherwise call_lvm function will fail to read
					stdin/stdout.  Return value of call back is ignored
	:param cb_data: Supplied to callback to allow caller access to
								its own data

	# Callback signature
	def my_callback(my_context, line_read_stdin)
		pass
	"""
	# Prepend the full lvm executable so that we can run different versions
	# in different locations on the same box
	command.insert(0, cfg.LVM_CMD)
	command = add_no_notify(command)

	process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
					env=os.environ)

	stdout_text = ""
	stderr_text = ""
	stdout_index = 0
	make_non_block(process.stdout)
	make_non_block(process.stderr)

	while True:
		try:
			rd_fd = [process.stdout.fileno(), process.stderr.fileno()]
			ready = select.select(rd_fd, [], [], 2)

			for r in ready[0]:
				if r == process.stdout.fileno():
					stdout_text += read_decoded(process.stdout)
				elif r == process.stderr.fileno():
					stderr_text += read_decoded(process.stderr)

			if line_cb is not None:
				# Process the callback for each line read!
				while True:
					i = stdout_text.find("\n", stdout_index)
					if i != -1:
						try:
							line_cb(cb_data, stdout_text[stdout_index:i])
						except:
							st = traceback.format_exc()
							log_error("call_lvm: line_cb exception: \n %s" % st)
						stdout_index = i + 1
					else:
						break

			# Check to see if process has terminated, None when running
			if process.poll() is not None:
				break
		except IOError as ioe:
			log_debug("call_lvm:" + str(ioe))
			pass

	if debug or process.returncode != 0:
		_debug_c(command, process.returncode, (stdout_text, stderr_text))

	return process.returncode, stdout_text, stderr_text
Beispiel #13
0
def lvm_full_report_json():
	pv_columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
					'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
					'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
					'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
					'vg_uuid', 'pv_missing']

	pv_seg_columns = ['pvseg_start', 'pvseg_size', 'segtype',
						'pv_uuid', 'lv_uuid', 'pv_name']

	vg_columns = ['vg_name', 'vg_uuid', 'vg_fmt', 'vg_size', 'vg_free',
					'vg_sysid', 'vg_extent_size', 'vg_extent_count',
					'vg_free_count', 'vg_profile', 'max_lv', 'max_pv',
					'pv_count', 'lv_count', 'snap_count', 'vg_seqno',
					'vg_mda_count', 'vg_mda_free', 'vg_mda_size',
					'vg_mda_used_count', 'vg_attr', 'vg_tags']

	lv_columns = ['lv_uuid', 'lv_name', 'lv_path', 'lv_size',
				'vg_name', 'pool_lv_uuid', 'pool_lv', 'origin_uuid',
				'origin', 'data_percent',
				'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
				'metadata_lv', 'lv_parent', 'lv_role', 'lv_layout',
				'snap_percent', 'metadata_percent', 'copy_percent',
				'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']

	lv_seg_columns = ['seg_pe_ranges', 'segtype', 'lv_uuid']

	if cfg.vdo_support:
		lv_columns.extend(
			['vdo_operating_mode', 'vdo_compression_state', 'vdo_index_state',
				'vdo_used_size', 'vdo_saving_percent']
		)

		lv_seg_columns.extend(
			['vdo_compression', 'vdo_deduplication',
				'vdo_use_metadata_hints', 'vdo_minimum_io_size',
				'vdo_block_map_cache_size', 'vdo_block_map_era_length',
				'vdo_use_sparse_index', 'vdo_index_memory_size',
				'vdo_slab_size', 'vdo_ack_threads', 'vdo_bio_threads',
				'vdo_bio_rotation', 'vdo_cpu_threads', 'vdo_hash_zone_threads',
				'vdo_logical_threads', 'vdo_physical_threads',
				'vdo_max_discard', 'vdo_write_policy', 'vdo_header_size'])

	cmd = _dc('fullreport', [
		'-a',		# Need hidden too
		'--configreport', 'pv', '-o', ','.join(pv_columns),
		'--configreport', 'vg', '-o', ','.join(vg_columns),
		'--configreport', 'lv', '-o', ','.join(lv_columns),
		'--configreport', 'seg', '-o', ','.join(lv_seg_columns),
		'--configreport', 'pvseg', '-o', ','.join(pv_seg_columns),
		'--reportformat', 'json'
	])

	rc, out, err = call(cmd)
	# When we have an exported vg the exit code of lvs or fullreport will be 5
	if rc == 0 or rc == 5:
		# With the current implementation, if we are using the shell then we
		# are using JSON and JSON is returned back to us as it was parsed to
		# figure out if we completed OK or not
		if cfg.SHELL_IN_USE:
			assert(type(out) == dict)
			return out
		else:
			try:
				return json.loads(out)
			except json.decoder.JSONDecodeError as joe:
				log_error("JSONDecodeError %s, \n JSON=\n%s\n" %
							(str(joe), out))
				raise joe

	return None
 def exit_shell(self):
     try:
         self._write_cmd('exit\n')
     except Exception as e:
         log_error(str(e))
Beispiel #15
0
def _debug_c(cmd, exit_code, out):
	log_error('CMD= %s' % ' '.join(cmd))
	log_error(("EC= %d" % exit_code))
	log_error(("STDOUT=\n %s\n" % out[0]))
	log_error(("STDERR=\n %s\n" % out[1]))