def run(all_hosts):
# type: (List[orchestrator.HostSpec]) -> None
- drive_group.validate([h.hostname for h in all_hosts])
+ drive_group.validate()
return self.get_hosts().then(run).then(
on_complete=orchestrator.ProgressReference(
message='create_osds',
_supported_features = [
"encrypted", "block_wal_size", "osds_per_device",
- "db_slots", "wal_slots", "block_db_size", "placement", "service_id",
+ "db_slots", "wal_slots", "block_db_size", "placement", "service_id", "service_type",
"data_devices", "db_devices", "wal_devices", "journal_devices",
"data_directories", "osds_per_device", "objectstore", "osd_id_claims",
"journal_size"
block_db_size=None, # type: Optional[int]
block_wal_size=None, # type: Optional[int]
journal_size=None, # type: Optional[int]
+ service_type=None, # type: Optional[str]
):
-
+ assert service_type is None or service_type == 'osd'
super(DriveGroupSpec, self).__init__('osd', service_id=service_id, placement=placement)
#: A :class:`ceph.deployment.drive_group.DeviceSelection`
self.osd_id_claims = osd_id_claims
@classmethod
- def from_json(cls, json_drive_group):
+ def _from_json_impl(cls, json_drive_group):
# type: (dict) -> DriveGroupSpec
"""
Initialize 'Drive group' structure
except (KeyError, TypeError) as e:
raise DriveGroupValidationError(str(e))
- def validate(self, all_hosts):
- # type: (List[str]) -> None
+ def validate(self):
+ # type: () -> None
+ super(DriveGroupSpec, self).validate()
+
if not isinstance(self.placement.host_pattern, six.string_types):
raise DriveGroupValidationError('host_pattern must be of type string')
if self.objectstore not in ('filestore', 'bluestore'):
raise DriveGroupValidationError("objectstore not in ('filestore', 'bluestore')")
- if not self.placement.pattern_matches_hosts(all_hosts):
- raise DriveGroupValidationError(
- "host_pattern '{}' does not match any hosts".format(self.placement.host_pattern))
if self.block_wal_size is not None and type(self.block_wal_size) != int:
raise DriveGroupValidationError('block_wal_size must be of type int')
self.service_type = service_type
self.service_id = service_id
- @classmethod
- def from_json(cls, json_spec: dict) -> "ServiceSpec":
+ @staticmethod
+ def from_json(json_spec):
+ # type: (dict) -> "ServiceSpec"
"""
Initialize 'ServiceSpec' object data from a json structure
:param json_spec: A valid dict with ServiceSpec
"""
- args = {} # type: Dict[str, Dict[Any, Any]]
- service_type = json_spec.get('service_type', '')
+ from ceph.deployment.drive_group import DriveGroupSpec
+
+ if 'service_type' not in json_spec:
+ raise ServiceSpecValidationError('Spec needs a "service_type" key.')
+ service_type = json_spec.get('service_type')
assert service_type
- if service_type == 'rgw':
- _cls = RGWSpec # type: ignore
- elif service_type == 'nfs':
- _cls = NFSServiceSpec # type: ignore
- else:
- _cls = ServiceSpec # type: ignore
+ _cls = {
+ 'rgw': RGWSpec,
+ 'nfs': NFSServiceSpec,
+ 'osd': DriveGroupSpec
+ }.get(service_type, ServiceSpec)
+ return _cls._from_json_impl(json_spec) # type: ignore
+
+ @classmethod
+ def _from_json_impl(cls, json_spec):
+ args = {} # type: Dict[str, Dict[Any, Any]]
for k, v in json_spec.items():
if k == 'placement':
v = PlacementSpec.from_json(v)
args.update(v)
continue
args.update({k: v})
- return _cls(**args) # type: ignore
+ return cls(**args)
def service_name(self):
n = self.service_type
c['placement'] = self.placement.to_json()
return c
+ def validate(self):
+ if not self.service_type:
+ raise ServiceSpecValidationError('Cannot add Service: type required')
+
+ if self.placement is not None:
+ self.placement.validate()
+
def __repr__(self):
return "{}({!r})".format(self.__class__.__name__, self.__dict__)
def servicespec_validate_add(self: ServiceSpec):
# This must not be a method of ServiceSpec, otherwise you'll hunt
# sub-interpreter affinity bugs.
- if not self.service_type:
- raise ServiceSpecValidationError('Cannot add Service: type required')
+ ServiceSpec.validate(self)
if self.service_type in ['mds', 'rgw', 'nfs'] and not self.service_id:
raise ServiceSpecValidationError('Cannot add Service: id required')
osds_per_device='',
disk_format='bluestore'):
raw_sample_bluestore = {
+ 'service_type': 'osd',
'placement': {'host_pattern': 'data*'},
'data_devices': {
'size': '30G:50G',
'encrypted': True,
}
raw_sample_filestore = {
+ 'service_type': 'osd',
'placement': {'host_pattern': 'data*'},
'objectstore': 'filestore',
'data_devices': {
raw_sample = raw_sample_bluestore
if empty:
- raw_sample = {'placement': {'host_pattern': 'data*'}}
+ raw_sample = {
+ 'service_type': 'osd',
+ 'placement': {'host_pattern': 'data*'}
+ }
dgo = DriveGroupSpec.from_json(raw_sample)
return dgo
from ceph.deployment import drive_selection, translate
from ceph.deployment.inventory import Device
-from ceph.deployment.service_spec import PlacementSpec
+from ceph.deployment.service_spec import PlacementSpec, ServiceSpecValidationError
from ceph.tests.utils import _mk_inventory, _mk_device
from ceph.deployment.drive_group import DriveGroupSpec, DriveGroupSpecs, \
DeviceSelection, DriveGroupValidationError
def test_DriveGroup():
dg_json = [
{
+ 'service_type': 'osd',
'service_id': 'testing_drivegroup',
'placement': {'host_pattern': 'hostname'},
'data_devices': {'paths': ['/dev/sda']}
def test_DriveGroup_fail():
- with pytest.raises(DriveGroupValidationError):
+ with pytest.raises(ServiceSpecValidationError):
DriveGroupSpec.from_json({})