]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/ceph-volume/ceph_volume/devices/lvm/prepare.py
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / ceph-volume / ceph_volume / devices / lvm / prepare.py
index d2cd3547d1d228490fc5c16cd57c635c9fadfcc8..c602a705fb921a78d7ddf0494d0fcf029b324523 100644 (file)
@@ -143,13 +143,14 @@ class Prepare(object):
         :param argument: The command-line value that will need to be split to
                          retrieve the actual lv
         """
+        #TODO is this efficient?
         try:
             vg_name, lv_name = argument.split('/')
         except (ValueError, AttributeError):
             return None
         return api.get_lv(lv_name=lv_name, vg_name=vg_name)
 
-    def setup_device(self, device_type, device_name, tags):
+    def setup_device(self, device_type, device_name, tags, size):
         """
         Check if ``device`` is an lv, if so, set the tags, making sure to
         update the tags with the lv_uuid and lv_path which the incoming tags
@@ -169,6 +170,24 @@ class Prepare(object):
             tags['ceph.%s_uuid' % device_type] = uuid
             tags['ceph.%s_device' % device_type] = path
             lv.set_tags(tags)
+        elif disk.is_device(device_name):
+            # We got a disk, create an lv
+            lv_type = "osd-{}".format(device_type)
+            uuid = system.generate_uuid()
+            tags['ceph.{}_uuid'.format(device_type)] = uuid
+            kwargs = {
+                'device': device_name,
+                'tags': tags,
+            }
+            if size != 0:
+                kwargs['size'] = disk.Size.parse(size)
+            lv = api.create_lv(
+                lv_type,
+                uuid,
+                **kwargs)
+            path = lv.lv_path
+            tags['ceph.{}_device'.format(device_type)] = path
+            lv.set_tags(tags)
         else:
             # otherwise assume this is a regular disk partition
             uuid = self.get_ptuuid(device_name)
@@ -177,7 +196,7 @@ class Prepare(object):
             tags['ceph.%s_device' % device_type] = path
         return path, uuid, tags
 
-    def prepare_device(self, arg, device_type, cluster_fsid, osd_fsid):
+    def prepare_data_device(self, device_type, osd_uuid):
         """
         Check if ``arg`` is a device or partition to create an LV out of it
         with a distinct volume group name, assigning LV tags on it and
@@ -186,24 +205,29 @@ class Prepare(object):
 
         :param arg: The value of ``--data`` when parsing args
         :param device_type: Usually, either ``data`` or ``block`` (filestore vs. bluestore)
-        :param cluster_fsid: The cluster fsid/uuid
-        :param osd_fsid: The OSD fsid/uuid
+        :param osd_uuid: The OSD uuid
         """
-        if disk.is_partition(arg) or disk.is_device(arg):
+        device = self.args.data
+        if disk.is_partition(device) or disk.is_device(device):
             # we must create a vg, and then a single lv
-            vg = api.create_vg(arg)
-            lv_name = "osd-%s-%s" % (device_type, osd_fsid)
+            lv_name_prefix = "osd-{}".format(device_type)
+            kwargs = {'device': device,
+                      'tags': {'ceph.type': device_type},
+                     }
+            logger.debug('data device size: {}'.format(self.args.data_size))
+            if self.args.data_size != 0:
+                kwargs['size'] = disk.Size.parse(self.args.data_size)
             return api.create_lv(
-                lv_name,
-                vg.name,  # the volume group
-                tags={'ceph.type': device_type})
+                lv_name_prefix,
+                osd_uuid,
+                **kwargs)
         else:
             error = [
-                'Cannot use device (%s).' % arg,
+                'Cannot use device ({}).'.format(device),
                 'A vg/lv path or an existing device is needed']
             raise RuntimeError(' '.join(error))
 
-        raise RuntimeError('no data logical volume found with: %s' % arg)
+        raise RuntimeError('no data logical volume found with: {}'.format(device))
 
     def safe_prepare(self, args=None):
         """
@@ -215,6 +239,9 @@ class Prepare(object):
         """
         if args is not None:
             self.args = args
+        if api.is_ceph_device(self.get_lv(self.args.data)):
+            logger.info("device {} is already used".format(self.args.data))
+            raise RuntimeError("skipping {}, it is already prepared".format(self.args.data))
         try:
             self.prepare()
         except Exception:
@@ -265,12 +292,14 @@ class Prepare(object):
             'ceph.crush_device_class': crush_device_class,
         }
         if self.args.filestore:
+            #TODO: allow auto creation of journal on passed device, only works
+            # when physical device is passed, not LV
             if not self.args.journal:
                 raise RuntimeError('--journal is required when using --filestore')
 
             data_lv = self.get_lv(self.args.data)
             if not data_lv:
-                data_lv = self.prepare_device(self.args.data, 'data', cluster_fsid, osd_fsid)
+                data_lv = self.prepare_data_device('data', osd_fsid)
 
             tags['ceph.data_device'] = data_lv.lv_path
             tags['ceph.data_uuid'] = data_lv.lv_uuid
@@ -279,8 +308,7 @@ class Prepare(object):
             tags['ceph.vdo'] = api.is_vdo(data_lv.lv_path)
 
             journal_device, journal_uuid, tags = self.setup_device(
-                'journal', self.args.journal, tags
-            )
+                'journal', self.args.journal, tags, self.args.journal_size)
 
             tags['ceph.type'] = 'data'
             data_lv.set_tags(tags)
@@ -296,7 +324,7 @@ class Prepare(object):
         elif self.args.bluestore:
             block_lv = self.get_lv(self.args.data)
             if not block_lv:
-                block_lv = self.prepare_device(self.args.data, 'block', cluster_fsid, osd_fsid)
+                block_lv = self.prepare_data_device('block', osd_fsid)
 
             tags['ceph.block_device'] = block_lv.lv_path
             tags['ceph.block_uuid'] = block_lv.lv_uuid
@@ -304,8 +332,10 @@ class Prepare(object):
             tags['ceph.encrypted'] = encrypted
             tags['ceph.vdo'] = api.is_vdo(block_lv.lv_path)
 
-            wal_device, wal_uuid, tags = self.setup_device('wal', self.args.block_wal, tags)
-            db_device, db_uuid, tags = self.setup_device('db', self.args.block_db, tags)
+            wal_device, wal_uuid, tags = self.setup_device(
+                'wal', self.args.block_wal, tags, self.args.block_wal_size)
+            db_device, db_uuid, tags = self.setup_device(
+                'db', self.args.block_db, tags, self.args.block_db_size)
 
             tags['ceph.type'] = 'block'
             block_lv.set_tags(tags)
@@ -336,13 +366,15 @@ class Prepare(object):
 
             ceph-volume lvm prepare --data {vg/lv}
 
-        Existing block device, that will be made a group and logical volume:
+        Existing block device (a logical volume will be created):
 
             ceph-volume lvm prepare --data /path/to/device
 
-        Optionally, can consume db and wal partitions or logical volumes:
+        Optionally, can consume db and wal devices, partitions or logical
+        volumes. A device will get a logical volume, partitions and existing
+        logical volumes will be used as is:
 
-            ceph-volume lvm prepare --data {vg/lv} --block.wal {partition} --block.db {vg/lv}
+            ceph-volume lvm prepare --data {vg/lv} --block.wal {partition} --block.db {/path/to/device}
         """)
         parser = prepare_parser(
             prog='ceph-volume lvm prepare',
@@ -362,4 +394,4 @@ class Prepare(object):
         # cause both to be True
         if not self.args.bluestore and not self.args.filestore:
             self.args.bluestore = True
-        self.safe_prepare(self.args)
+        self.safe_prepare()