'devices',
metavar='DEVICES',
nargs='*',
- type=arg_validators.ValidDevice(),
+ type=arg_validators.ValidBatchDevice(),
default=[],
help='Devices to provision OSDs',
)
parser.add_argument(
'--db-devices',
nargs='*',
- type=arg_validators.ValidDevice(),
+ type=arg_validators.ValidBatchDevice(),
default=[],
help='Devices to provision OSDs db volumes',
)
parser.add_argument(
'--wal-devices',
nargs='*',
- type=arg_validators.ValidDevice(),
+ type=arg_validators.ValidBatchDevice(),
default=[],
help='Devices to provision OSDs wal volumes',
)
parser.add_argument(
'--journal-devices',
nargs='*',
- type=arg_validators.ValidDevice(),
+ type=arg_validators.ValidBatchDevice(),
default=[],
help='Devices to provision OSDs journal volumes',
)
import pytest
import json
import random
+
+from argparse import ArgumentError
+from mock import MagicMock, patch
+
from ceph_volume.devices.lvm import batch
+from ceph_volume.util import arg_validators
class TestBatch(object):
batch.ensure_disjoint_device_lists(devices, db_devices)
assert 'Device lists are not disjoint' in str(disjoint_ex.value)
+ @patch('ceph_volume.util.arg_validators.Device')
+ def test_reject_partition(self, mocked_device):
+ mocked_device.return_value = MagicMock(
+ is_partition=True,
+ has_gpt_headers=False,
+ )
+ with pytest.raises(ArgumentError):
+ arg_validators.ValidBatchDevice()('foo')
+
@pytest.mark.parametrize('format_', ['pretty', 'json', 'json-pretty'])
def test_report(self, format_, factory, conf_ceph_stub, mock_device_generator):
# just ensure reporting works
self.as_string = as_string
self.gpt_ok = gpt_ok
- def __call__(self, string):
- device = Device(string)
+ def __call__(self, dev_path):
+ device = self._is_valid_device(dev_path)
+ return self._format_device(device)
+
+ def _format_device(self, device):
+ if self.as_string:
+ if device.is_lv:
+ # all codepaths expect an lv path to be returned in this format
+ return "{}/{}".format(device.vg_name, device.lv_name)
+ return device.path
+ return device
+
+ def _is_valid_device(self, dev_path):
+ device = Device(dev_path)
error = None
if not device.exists:
- error = "Unable to proceed with non-existing device: %s" % string
+ error = "Unable to proceed with non-existing device: %s" % dev_path
# FIXME this is not a nice API, this validator was meant to catch any
# non-existing devices upfront, not check for gpt headers. Now this
# needs to optionally skip checking gpt headers which is beyond
# configure this with a list of checks that can be excluded/included on
# __init__
elif device.has_gpt_headers and not self.gpt_ok:
- error = "GPT headers found, they must be removed on: %s" % string
+ error = "GPT headers found, they must be removed on: %s" % dev_path
if error:
raise argparse.ArgumentError(None, error)
- if self.as_string:
- if device.is_lv:
- # all codepaths expect an lv path to be returned in this format
- return "{}/{}".format(device.vg_name, device.lv_name)
- return string
return device
+class ValidBatchDevice(ValidDevice):
+
+ def __call__(self, dev_path):
+ dev = self._is_valid_device(dev_path)
+ if dev.is_partition:
+ raise argparse.ArgumentError(
+ None,
+ '{} is a partition, please pass '
+ 'LVs or raw block devices'.format(dev_path))
+ return self._format_device(dev)
+
+
class OSDPath(object):
"""
Validate path exists and it looks like an OSD directory.