Esempio n. 1
0
def supports_vdo():
	cmd = ['segtypes']
	rc, out, err = call(cmd)
	if rc == 0:
		if "vdo" in out:
			log_debug("We have VDO support")
			return True
	return False
    def refresh(self, log=True):
        """
		Go out and query lvm for the latest data in as few trips as possible
		:param log  Add debug log entry/exit messages
		:return: None
		"""
        self.num_refreshes += 1
        if log:
            log_debug("lvmdb - refresh entry")

        # Grab everything first then parse it
        if self.json:
            # Do a single lvm retrieve for everything in json
            a = cmdhandler.lvm_full_report_json()

            _pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs_json(a)
            _vgs, _vgs_lookup = self._parse_vgs_json(a)
            _lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs_json(
                a)

        else:
            _raw_pvs = cmdhandler.pv_retrieve_with_segs()
            _raw_vgs = cmdhandler.vg_retrieve(None)
            _raw_lvs = cmdhandler.lv_retrieve_with_segments()

            _pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs(_raw_pvs)
            _vgs, _vgs_lookup = self._parse_vgs(_raw_vgs)
            _lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs(
                _raw_lvs)

        # Set all
        self.pvs = _pvs
        self.pv_path_to_uuid = _pvs_lookup
        self.vg_name_to_uuid = _vgs_lookup
        self.lv_full_name_to_uuid = _lvs_lookup

        self.vgs = _vgs
        self.lvs = _lvs
        self.lvs_in_vgs = _lvs_in_vgs
        self.pvs_in_vgs = _pvs_in_vgs
        self.lvs_hidden = _lvs_hidden

        # Create lookup table for which LV and segments are on each PV
        self.pv_lvs, self.lv_pvs = self._parse_pv_in_lvs()

        if log:
            log_debug("lvmdb - refresh exit")
    def _read_until_prompt(self):
        stdout = ""
        report = ""
        stderr = ""

        # Try reading from all FDs to prevent one from filling up and causing
        # a hang.  We are also assuming that we won't get the lvm prompt back
        # until we have already received all the output from stderr and the
        # report descriptor too.
        while not stdout.endswith(SHELL_PROMPT):
            try:
                rd_fd = [
                    self.lvm_shell.stdout.fileno(), self.report_r,
                    self.lvm_shell.stderr.fileno()
                ]
                ready = select.select(rd_fd, [], [], 2)

                for r in ready[0]:
                    if r == self.lvm_shell.stdout.fileno():
                        while True:
                            tmp = self.lvm_shell.stdout.read()
                            if tmp:
                                stdout += tmp.decode("utf-8")
                            else:
                                break

                    elif r == self.report_r:
                        while True:
                            tmp = os.read(self.report_r, 16384)
                            if tmp:
                                report += tmp.decode("utf-8")
                                if len(tmp) != 16384:
                                    break

                    elif r == self.lvm_shell.stderr.fileno():
                        while True:
                            tmp = self.lvm_shell.stderr.read()
                            if tmp:
                                stderr += tmp.decode("utf-8")
                            else:
                                break

            except IOError as ioe:
                log_debug(str(ioe))
                pass

        return stdout, report, stderr
Esempio n. 4
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
Esempio n. 5
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
Esempio n. 6
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
	def _read_until_prompt(self, no_output=False):
		stdout = ""
		report = ""
		stderr = ""
		keep_reading = True
		extra_passes = 3
		report_json = {}
		prev_report_len = 0

		# Try reading from all FDs to prevent one from filling up and causing
		# a hang.  Keep reading until we get the prompt back and the report
		# FD does not contain valid JSON
		while keep_reading:
			try:
				rd_fd = [
					self.lvm_shell.stdout.fileno(),
					self.report_stream.fileno(),
					self.lvm_shell.stderr.fileno()]
				ready = select.select(rd_fd, [], [], 2)

				for r in ready[0]:
					if r == self.lvm_shell.stdout.fileno():
						stdout += LVMShellProxy._read(self.lvm_shell.stdout)
					elif r == self.report_stream.fileno():
						report += LVMShellProxy._read(self.report_stream)
					elif r == self.lvm_shell.stderr.fileno():
						stderr += LVMShellProxy._read(self.lvm_shell.stderr)

				# Check to see if the lvm process died on us
				if self.lvm_shell.poll():
					raise Exception(self.lvm_shell.returncode, "%s" % stderr)

				if stdout.endswith(SHELL_PROMPT):
					if no_output:
						keep_reading = False
					else:
						cur_report_len = len(report)
						if cur_report_len != 0:
							# Only bother to parse if we have more data
							if prev_report_len != cur_report_len:
								prev_report_len = cur_report_len
								# Parse the JSON if it's good we are done,
								# if not we will try to read some more.
								try:
									report_json = json.loads(report)
									keep_reading = False
								except ValueError:
									pass

						if keep_reading:
							extra_passes -= 1
							if extra_passes <= 0:
								if len(report):
									raise ValueError("Invalid json: %s" %
														report)
								else:
									raise ValueError(
										"lvm returned no JSON output!")

			except IOError as ioe:
				log_debug(str(ioe))
				pass

		return stdout, report_json, stderr