From 337edc3cd1145cf85dfa3745a8e0ab7c5d26cbf3 Mon Sep 17 00:00:00 2001 From: Alfredo Deza Date: Thu, 24 Aug 2017 19:28:12 -0400 Subject: [PATCH] ceph-volume lvm.api create the PVolume class Signed-off-by: Alfredo Deza (cherry picked from commit 1725a5f3589ba2faddc9ce633997e5563fc66a01) --- .../ceph_volume/devices/lvm/api.py | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/ceph-volume/ceph_volume/devices/lvm/api.py b/src/ceph-volume/ceph_volume/devices/lvm/api.py index bb052191be90..8b1916ac5985 100644 --- a/src/ceph-volume/ceph_volume/devices/lvm/api.py +++ b/src/ceph-volume/ceph_volume/devices/lvm/api.py @@ -108,6 +108,27 @@ def get_api_lvs(): return _output_parser(stdout, fields) +def get_api_pvs(): + """ + Return the list of physical volumes configured for lvm and available in the + system using flags to include common metadata associated with them like the uuid + + Command and delimeted output, should look like:: + + $ sudo lvs --noheadings --separator=';' -o lv_tags,lv_path,lv_name,vg_name + ;/dev/ubuntubox-vg/root;root;ubuntubox-vg + ;/dev/ubuntubox-vg/swap_1;swap_1;ubuntubox-vg + + """ + fields = 'pv_name,pv_tags,pv_uuid' + + stdout, stderr, returncode = process.call( + ['sudo', 'pvs', '--no-heading', '--separator=";"', '-o', fields] + ) + + return _output_parser(stdout, fields) + + def get_lv(lv_name=None, vg_name=None, lv_path=None, lv_tags=None): """ Return a matching lv for the current system, requiring ``lv_name``, @@ -485,3 +506,61 @@ class Volume(object): '--addtag', '%s=%s' % (key, value), self.lv_path ] ) + + +class PVolume(object): + """ + Represents a Physical Volume from LVM, with some top-level attributes like + ``pv_name`` and parsed tags as a dictionary of key/value pairs. + """ + + def __init__(self, **kw): + for k, v in kw.items(): + setattr(self, k, v) + self.pv_api = kw + self.name = kw['pv_name'] + self.tags = parse_tags(kw['pv_tags']) + + def __str__(self): + return '<%s>' % self.pv_api['pv_name'] + + def __repr__(self): + return self.__str__() + + def set_tags(self, tags): + """ + :param tags: A dictionary of tag names and values, like:: + + { + "ceph.osd_fsid": "aaa-fff-bbbb", + "ceph.osd_id": "0" + } + + At the end of all modifications, the tags are refreshed to reflect + LVM's most current view. + """ + for k, v in tags.items(): + self.set_tag(k, v) + # after setting all the tags, refresh them for the current object, use the + # pv_* identifiers to filter because those shouldn't change + pv_object = get_pv(pv_name=self.pv_name, pv_path=self.pv_path) + self.tags = pv_object.tags + + def set_tag(self, key, value): + """ + Set the key/value pair as an pvM tag. Does not "refresh" the values of + the current object for its tags. Meant to be a "fire and forget" type + of modification. + """ + # remove it first if it exists + if self.tags.get(key): + current_value = self.tags[key] + tag = "%s=%s" % (key, current_value) + process.call(['sudo', 'pvchange', '--deltag', tag, self.pv_api['pv_path']]) + + process.call( + [ + 'sudo', 'pvchange', + '--addtag', '%s=%s' % (key, value), self.pv_path + ] + ) -- 2.47.3