
NAME_utils.py was completely redundant and caused confusion so it was renamed to just utils/NAME.py Change-Id: Ifd9178772cca385f687ac9806e6043cfbf27813e Implements: blueprint volume-manager-refactoring
244 lines
8.0 KiB
Python
244 lines
8.0 KiB
Python
# Copyright 2014 Mirantis, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
from fuel_agent import errors
|
|
from fuel_agent.openstack.common import log as logging
|
|
from fuel_agent.utils import utils
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def pvdisplay():
|
|
# unit m means MiB (power of 2)
|
|
output = utils.execute(
|
|
'pvdisplay',
|
|
'-C',
|
|
'--noheading',
|
|
'--units', 'm',
|
|
'--options', 'pv_name,vg_name,pv_size,dev_size,pv_uuid',
|
|
'--separator', ';',
|
|
check_exit_code=[0])[0]
|
|
return pvdisplay_parse(output)
|
|
|
|
|
|
def pvdisplay_parse(output):
|
|
pvs = []
|
|
for line in output.split('\n'):
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
pv_params = line.split(';')
|
|
pvs.append({
|
|
'name': pv_params[0],
|
|
'vg': pv_params[1] or None,
|
|
'psize': utils.parse_unit(pv_params[2], 'm'),
|
|
'devsize': utils.parse_unit(pv_params[3], 'm'),
|
|
'uuid': pv_params[4]
|
|
})
|
|
LOG.debug('Found physical volumes: {0}'.format(pvs))
|
|
return pvs
|
|
|
|
|
|
def pvcreate(pvname, metadatasize=64, metadatacopies=2):
|
|
# check if pv already exists
|
|
if filter(lambda x: x['name'] == pvname, pvdisplay()):
|
|
raise errors.PVAlreadyExistsError(
|
|
'Error while creating pv: pv %s already exists' % pvname)
|
|
utils.execute('pvcreate',
|
|
'--metadatacopies', str(metadatacopies),
|
|
'--metadatasize', str(metadatasize) + 'm',
|
|
pvname, check_exit_code=[0])
|
|
|
|
|
|
def pvremove(pvname):
|
|
pv = filter(lambda x: x['name'] == pvname, pvdisplay())
|
|
|
|
# check if pv exists
|
|
if not pv:
|
|
raise errors.PVNotFoundError(
|
|
'Error while removing pv: pv %s not found' % pvname)
|
|
# check if pv is attached to some vg
|
|
if pv[0]['vg'] is not None:
|
|
raise errors.PVBelongsToVGError('Error while removing pv: '
|
|
'pv belongs to vg %s' % pv[0]['vg'])
|
|
utils.execute('pvremove', '-ff', '-y', pvname, check_exit_code=[0])
|
|
|
|
|
|
def vgdisplay():
|
|
output = utils.execute(
|
|
'vgdisplay',
|
|
'-C',
|
|
'--noheading',
|
|
'--units', 'm',
|
|
'--options', 'vg_name,vg_uuid,vg_size,vg_free',
|
|
'--separator', ';',
|
|
check_exit_code=[0])[0]
|
|
return vgdisplay_parse(output)
|
|
|
|
|
|
def vgdisplay_parse(output):
|
|
vgs = []
|
|
for line in output.split('\n'):
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
vg_params = line.split(';')
|
|
vgs.append({
|
|
'name': vg_params[0],
|
|
'uuid': vg_params[1],
|
|
'size': utils.parse_unit(vg_params[2], 'm'),
|
|
'free': utils.parse_unit(vg_params[3], 'm', ceil=False)
|
|
})
|
|
LOG.debug('Found volume groups: {0}'.format(vgs))
|
|
return vgs
|
|
|
|
|
|
def _vg_attach_validate(pvnames):
|
|
pvs = pvdisplay()
|
|
# check if all necessary pv exist
|
|
if not set(pvnames).issubset(set([pv['name'] for pv in pvs])):
|
|
raise errors.PVNotFoundError(
|
|
'Error while creating vg: at least one of pv is not found')
|
|
# check if all necessary pv are not already attached to some vg
|
|
if not set(pvnames).issubset(
|
|
set([pv['name'] for pv in pvs if pv['vg'] is None])):
|
|
raise errors.PVBelongsToVGError(
|
|
'Error while creating vg: at least one of pvs is '
|
|
'already attached to some vg')
|
|
|
|
|
|
def vgcreate(vgname, pvname, *args):
|
|
# check if vg already exists
|
|
if filter(lambda x: x['name'] == vgname, vgdisplay()):
|
|
raise errors.VGAlreadyExistsError(
|
|
'Error while creating vg: vg %s already exists' % vgname)
|
|
pvnames = [pvname] + list(args)
|
|
_vg_attach_validate(pvnames)
|
|
utils.execute('vgcreate', vgname, *pvnames, check_exit_code=[0])
|
|
|
|
|
|
def vgextend(vgname, pvname, *args):
|
|
# check if vg exists
|
|
if not filter(lambda x: x['name'] == vgname, vgdisplay()):
|
|
raise errors.VGNotFoundError(
|
|
'Error while extending vg: vg %s not found' % vgname)
|
|
pvnames = [pvname] + list(args)
|
|
_vg_attach_validate(pvnames)
|
|
utils.execute('vgextend', vgname, *pvnames, check_exit_code=[0])
|
|
|
|
|
|
def vgreduce(vgname, pvname, *args):
|
|
# check if vg exists
|
|
if not filter(lambda x: x['name'] == vgname, vgdisplay()):
|
|
raise errors.VGNotFoundError(
|
|
'Error while reducing vg: vg %s not found' % vgname)
|
|
pvnames = [pvname] + list(args)
|
|
# check if all necessary pv are attached to vg
|
|
if not set(pvnames).issubset(
|
|
set([pv['name'] for pv in pvdisplay() if pv['vg'] == vgname])):
|
|
raise errors.PVNotFoundError(
|
|
'Error while reducing vg: at least one of pv is '
|
|
'not attached to vg')
|
|
utils.execute('vgreduce', '-f', vgname, *pvnames, check_exit_code=[0])
|
|
|
|
|
|
def vgremove(vgname):
|
|
# check if vg exists
|
|
if not filter(lambda x: x['name'] == vgname, vgdisplay()):
|
|
raise errors.VGNotFoundError(
|
|
'Error while removing vg: vg %s not found' % vgname)
|
|
utils.execute('vgremove', '-f', vgname, check_exit_code=[0])
|
|
|
|
|
|
def lvdisplay():
|
|
output = utils.execute(
|
|
'lvdisplay',
|
|
'-C',
|
|
'--noheading',
|
|
'--units', 'm',
|
|
# NOTE(agordeev): lv_path had been removed from options
|
|
# since versions of lvdisplay prior 2.02.68 don't have it.
|
|
'--options', 'lv_name,lv_size,vg_name,lv_uuid',
|
|
'--separator', ';',
|
|
check_exit_code=[0])[0]
|
|
return lvdisplay_parse(output)
|
|
|
|
|
|
def lvdisplay_parse(output):
|
|
lvs = []
|
|
for line in output.split('\n'):
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
lv_params = line.split(';')
|
|
lvs.append({
|
|
'name': lv_params[0],
|
|
'size': utils.parse_unit(lv_params[1], 'm'),
|
|
'vg': lv_params[2],
|
|
'uuid': lv_params[3],
|
|
# NOTE(agordeev): simulate lv_path with '/dev/$vg_name/$lv_name'
|
|
'path': '/dev/%s/%s' % (lv_params[2], lv_params[0])
|
|
})
|
|
LOG.debug('Found logical volumes: {0}'.format(lvs))
|
|
return lvs
|
|
|
|
|
|
def lvcreate(vgname, lvname, size):
|
|
vg = filter(lambda x: x['name'] == vgname, vgdisplay())
|
|
|
|
# check if vg exists
|
|
if not vg:
|
|
raise errors.VGNotFoundError(
|
|
'Error while creating vg: vg %s not found' % vgname)
|
|
# check if enough space is available
|
|
if vg[0]['free'] < size:
|
|
raise errors.NotEnoughSpaceError(
|
|
'Error while creating lv: vg %s has only %s m of free space, '
|
|
'but at least %s m is needed' % (vgname, vg[0]['free'], size))
|
|
# check if lv already exists
|
|
if filter(lambda x: x['name'] == lvname and x['vg'] == vgname,
|
|
lvdisplay()):
|
|
raise errors.LVAlreadyExistsError(
|
|
'Error while creating lv: lv %s already exists' % lvname)
|
|
# NOTE(agordeev): by default, lvcreate is configured to wipe signature
|
|
# on allocated volume. '--yes' should be passed to avoid waiting for
|
|
# user's confirmation:
|
|
# "WARNING: <signature> signature detected on <device>. Wipe it? [y/n]"
|
|
utils.execute('lvcreate', '--yes', '-L', '%sm' % size, '-n', lvname,
|
|
vgname, check_exit_code=[0])
|
|
|
|
|
|
def lvremove(lvpath):
|
|
# check if lv exists
|
|
if not filter(lambda x: x['path'] == lvpath, lvdisplay()):
|
|
raise errors.LVNotFoundError(
|
|
'Error while removing lv: lv %s not found' % lvpath)
|
|
utils.execute('lvremove', '-f', lvpath, check_exit_code=[0])
|
|
|
|
|
|
def lvremove_all():
|
|
for lv in lvdisplay():
|
|
lvremove(lv['path'])
|
|
|
|
|
|
def vgremove_all():
|
|
for vg in vgdisplay():
|
|
vgremove(vg['name'])
|
|
|
|
|
|
def pvremove_all():
|
|
for pv in pvdisplay():
|
|
pvremove(pv['name'])
|