logger = logging.getLogger(__name__)
+def convert_filters_to_str(filters):
+ """
+ Convert filter args from dictionary to following format -
+ filters={filter_name=filter_val,...}
+ """
+ if not filters:
+ return filters
+
+ filter_arg = ''
+ for k, v in filters.items():
+ filter_arg += k + '=' + v + ','
+ # get rid of extra comma at the end
+ filter_arg = filter_arg[:len(filter_arg) - 1]
+
+ return filter_arg
+
+
+def convert_tags_to_str(tags):
+ """
+ Convert tags from dictionary to following format -
+ tags={tag_name=tag_val,...}
+ """
+ if not tags:
+ return tags
+
+ tag_arg = 'tags={'
+ for k, v in tags.items():
+ tag_arg += k + '=' + v + ','
+ # get rid of extra comma at the end
+ tag_arg = tag_arg[:len(tag_arg) - 1] + '}'
+
+ return tag_arg
+
+
+def make_filters_lvmcmd_ready(filters, tags):
+ """
+ Convert filters (including tags) from dictionary to following format -
+ filter_name=filter_val...,tags={tag_name=tag_val,...}
+
+ The command will look as follows =
+ lvs -S filter_name=filter_val...,tags={tag_name=tag_val,...}
+ """
+ filters = convert_filters_to_str(filters)
+ tags = convert_tags_to_str(tags)
+
+ if filters and tags:
+ return filters + ',' + tags
+ if filters and not tags:
+ return filters
+ if not filters and tags:
+ return tags
+ else:
+ return ''
+
+
def _output_parser(output, fields):
"""
Newer versions of LVM allow ``--reportformat=json``, but older versions,
)
+def get_pvs(fields=PV_FIELDS, filters='', tags=None):
+ """
+ Return a list of PVs that are available on the system and match the
+ filters and tags passed. Argument filters takes a dictionary containing
+ arguments required by -S option of LVM. Passing a list of LVM tags can be
+ quite tricky to pass as a dictionary within dictionary, therefore pass
+ dictionary of tags via tags argument and tricky part will be taken care of
+ by the helper methods.
+
+ :param fields: string containing list of fields to be displayed by the
+ pvs command
+ :param sep: string containing separator to be used between two fields
+ :param filters: dictionary containing LVM filters
+ :param tags: dictionary containng LVM tags
+ :returns: list of class PVolume object representing pvs on the system
+ """
+ filters = make_filters_lvmcmd_ready(filters, tags)
+ args = ['pvs', '--no-heading', '--readonly', '--separator=";"', '-S',
+ filters, '-o', fields]
+
+ stdout, stderr, returncode = process.call(args, verbose_on_failure=False)
+ pvs_report = _output_parser(stdout, fields)
+ return [PVolume(**pv_report) for pv_report in pvs_report]
+
+
+def get_first_pv(fields=PV_FIELDS, filters=None, tags=None):
+ """
+ Wrapper of get_pv meant to be a convenience method to avoid the phrase::
+ pvs = get_pvs()
+ if len(pvs) >= 1:
+ pv = pvs[0]
+ """
+ pvs = get_pvs(fields=fields, filters=filters, tags=tags)
+ return pvs[0] if len(pvs) > 0 else []
+
+
################################
#
# Code for LVM Volume Groups
)
+def get_vgs(fields=VG_FIELDS, filters='', tags=None):
+ """
+ Return a list of VGs that are available on the system and match the
+ filters and tags passed. Argument filters takes a dictionary containing
+ arguments required by -S option of LVM. Passing a list of LVM tags can be
+ quite tricky to pass as a dictionary within dictionary, therefore pass
+ dictionary of tags via tags argument and tricky part will be taken care of
+ by the helper methods.
+
+ :param fields: string containing list of fields to be displayed by the
+ vgs command
+ :param sep: string containing separator to be used between two fields
+ :param filters: dictionary containing LVM filters
+ :param tags: dictionary containng LVM tags
+ :returns: list of class VolumeGroup object representing vgs on the system
+ """
+ filters = make_filters_lvmcmd_ready(filters, tags)
+ args = ['vgs'] + VG_CMD_OPTIONS + ['-S', filters, '-o', fields]
+
+ stdout, stderr, returncode = process.call(args, verbose_on_failure=False)
+ vgs_report =_output_parser(stdout, fields)
+ return [VolumeGroup(**vg_report) for vg_report in vgs_report]
+
+
+def get_first_vg(fields=VG_FIELDS, filters=None, tags=None):
+ """
+ Wrapper of get_vg meant to be a convenience method to avoid the phrase::
+ vgs = get_vgs()
+ if len(vgs) >= 1:
+ vg = vgs[0]
+ """
+ vgs = get_vgs(fields=fields, filters=filters, tags=tags)
+ return vgs[0] if len(vgs) > 0 else []
+
+
def get_device_vgs(device, name_prefix=''):
stdout, stderr, returncode = process.call(
['pvs'] + VG_CMD_OPTIONS + ['-o', VG_FIELDS, device],
return lv
-def remove_lv(lv):
- """
- Removes a logical volume given it's absolute path.
-
- Will return True if the lv is successfully removed or
- raises a RuntimeError if the removal fails.
-
- :param lv: A ``Volume`` object or the path for an LV
- """
- if isinstance(lv, Volume):
- path = lv.lv_path
- else:
- path = lv
-
- stdout, stderr, returncode = process.call(
- [
- 'lvremove',
- '-v', # verbose
- '-f', # force it
- path
- ],
- show_command=True,
- terminal_verbose=True,
- )
- if returncode != 0:
- raise RuntimeError("Unable to remove %s" % path)
- return True
-
-
-def get_lv_by_name(name):
- stdout, stderr, returncode = process.call(
- ['lvs', '--noheadings', '-o', LV_FIELDS, '-S',
- 'lv_name={}'.format(name)],
- verbose_on_failure=False
- )
- lvs = _output_parser(stdout, LV_FIELDS)
- return [Volume(**lv) for lv in lvs]
-
-def get_lvs_by_tag(lv_tag):
- stdout, stderr, returncode = process.call(
- ['lvs', '--noheadings', '--separator=";"', '-a', '-o', LV_FIELDS, '-S',
- 'lv_tags={{{}}}'.format(lv_tag)],
- verbose_on_failure=False
- )
- lvs = _output_parser(stdout, LV_FIELDS)
- return [Volume(**lv) for lv in lvs]
-
def create_lvs(volume_group, parts=None, size=None, name_prefix='ceph-lv'):
"""
Create multiple Logical Volumes from a Volume Group by calculating the
return lvs
-def get_device_lvs(device, name_prefix=''):
- stdout, stderr, returncode = process.call(
- ['pvs'] + LV_CMD_OPTIONS + ['-o', LV_FIELDS, device],
- verbose_on_failure=False
- )
- lvs = _output_parser(stdout, LV_FIELDS)
- return [Volume(**lv) for lv in lvs if lv['lv_name'] and
- lv['lv_name'].startswith(name_prefix)]
-
-
-#############################################################
-#
-# New methods to get PVs, LVs, and VGs.
-# Later, these can be easily merged with get_api_* methods
-#
-###########################################################
-
-def convert_filters_to_str(filters):
- """
- Convert filter args from dictionary to following format -
- filters={filter_name=filter_val,...}
- """
- if not filters:
- return filters
-
- filter_arg = ''
- for k, v in filters.items():
- filter_arg += k + '=' + v + ','
- # get rid of extra comma at the end
- filter_arg = filter_arg[:len(filter_arg) - 1]
-
- return filter_arg
-
-def convert_tags_to_str(tags):
- """
- Convert tags from dictionary to following format -
- tags={tag_name=tag_val,...}
+def remove_lv(lv):
"""
- if not tags:
- return tags
-
- tag_arg = 'tags={'
- for k, v in tags.items():
- tag_arg += k + '=' + v + ','
- # get rid of extra comma at the end
- tag_arg = tag_arg[:len(tag_arg) - 1] + '}'
-
- return tag_arg
+ Removes a logical volume given it's absolute path.
-def make_filters_lvmcmd_ready(filters, tags):
- """
- Convert filters (including tags) from dictionary to following format -
- filter_name=filter_val...,tags={tag_name=tag_val,...}
+ Will return True if the lv is successfully removed or
+ raises a RuntimeError if the removal fails.
- The command will look as follows =
- lvs -S filter_name=filter_val...,tags={tag_name=tag_val,...}
+ :param lv: A ``Volume`` object or the path for an LV
"""
- filters = convert_filters_to_str(filters)
- tags = convert_tags_to_str(tags)
-
- if filters and tags:
- return filters + ',' + tags
- if filters and not tags:
- return filters
- if not filters and tags:
- return tags
+ if isinstance(lv, Volume):
+ path = lv.lv_path
else:
- return ''
-
-def get_pvs(fields=PV_FIELDS, filters='', tags=None):
- """
- Return a list of PVs that are available on the system and match the
- filters and tags passed. Argument filters takes a dictionary containing
- arguments required by -S option of LVM. Passing a list of LVM tags can be
- quite tricky to pass as a dictionary within dictionary, therefore pass
- dictionary of tags via tags argument and tricky part will be taken care of
- by the helper methods.
-
- :param fields: string containing list of fields to be displayed by the
- pvs command
- :param sep: string containing separator to be used between two fields
- :param filters: dictionary containing LVM filters
- :param tags: dictionary containng LVM tags
- :returns: list of class PVolume object representing pvs on the system
- """
- filters = make_filters_lvmcmd_ready(filters, tags)
- args = ['pvs', '--no-heading', '--readonly', '--separator=";"', '-S',
- filters, '-o', fields]
-
- stdout, stderr, returncode = process.call(args, verbose_on_failure=False)
- pvs_report = _output_parser(stdout, fields)
- return [PVolume(**pv_report) for pv_report in pvs_report]
-
-def get_first_pv(fields=PV_FIELDS, filters=None, tags=None):
- """
- Wrapper of get_pv meant to be a convenience method to avoid the phrase::
- pvs = get_pvs()
- if len(pvs) >= 1:
- pv = pvs[0]
- """
- pvs = get_pvs(fields=fields, filters=filters, tags=tags)
- return pvs[0] if len(pvs) > 0 else []
-
-def get_vgs(fields=VG_FIELDS, filters='', tags=None):
- """
- Return a list of VGs that are available on the system and match the
- filters and tags passed. Argument filters takes a dictionary containing
- arguments required by -S option of LVM. Passing a list of LVM tags can be
- quite tricky to pass as a dictionary within dictionary, therefore pass
- dictionary of tags via tags argument and tricky part will be taken care of
- by the helper methods.
-
- :param fields: string containing list of fields to be displayed by the
- vgs command
- :param sep: string containing separator to be used between two fields
- :param filters: dictionary containing LVM filters
- :param tags: dictionary containng LVM tags
- :returns: list of class VolumeGroup object representing vgs on the system
- """
- filters = make_filters_lvmcmd_ready(filters, tags)
- args = ['vgs'] + VG_CMD_OPTIONS + ['-S', filters, '-o', fields]
+ path = lv
- stdout, stderr, returncode = process.call(args, verbose_on_failure=False)
- vgs_report =_output_parser(stdout, fields)
- return [VolumeGroup(**vg_report) for vg_report in vgs_report]
+ stdout, stderr, returncode = process.call(
+ [
+ 'lvremove',
+ '-v', # verbose
+ '-f', # force it
+ path
+ ],
+ show_command=True,
+ terminal_verbose=True,
+ )
+ if returncode != 0:
+ raise RuntimeError("Unable to remove %s" % path)
+ return True
-def get_first_vg(fields=VG_FIELDS, filters=None, tags=None):
- """
- Wrapper of get_vg meant to be a convenience method to avoid the phrase::
- vgs = get_vgs()
- if len(vgs) >= 1:
- vg = vgs[0]
- """
- vgs = get_vgs(fields=fields, filters=filters, tags=tags)
- return vgs[0] if len(vgs) > 0 else []
def get_lvs(fields=LV_FIELDS, filters='', tags=None):
"""
lvs_report = _output_parser(stdout, fields)
return [Volume(**lv_report) for lv_report in lvs_report]
+
def get_first_lv(fields=LV_FIELDS, filters=None, tags=None):
"""
Wrapper of get_lv meant to be a convenience method to avoid the phrase::
"""
lvs = get_lvs(fields=fields, filters=filters, tags=tags)
return lvs[0] if len(lvs) > 0 else []
+
+
+def get_lv_by_name(name):
+ stdout, stderr, returncode = process.call(
+ ['lvs', '--noheadings', '-o', LV_FIELDS, '-S',
+ 'lv_name={}'.format(name)],
+ verbose_on_failure=False
+ )
+ lvs = _output_parser(stdout, LV_FIELDS)
+ return [Volume(**lv) for lv in lvs]
+
+
+def get_lvs_by_tag(lv_tag):
+ stdout, stderr, returncode = process.call(
+ ['lvs', '--noheadings', '--separator=";"', '-a', '-o', LV_FIELDS, '-S',
+ 'lv_tags={{{}}}'.format(lv_tag)],
+ verbose_on_failure=False
+ )
+ lvs = _output_parser(stdout, LV_FIELDS)
+ return [Volume(**lv) for lv in lvs]
+
+
+def get_device_lvs(device, name_prefix=''):
+ stdout, stderr, returncode = process.call(
+ ['pvs'] + LV_CMD_OPTIONS + ['-o', LV_FIELDS, device],
+ verbose_on_failure=False
+ )
+ lvs = _output_parser(stdout, LV_FIELDS)
+ return [Volume(**lv) for lv in lvs if lv['lv_name'] and
+ lv['lv_name'].startswith(name_prefix)]