← Back to team overview

curtin-dev team mailing list archive

[Merge] ~mwhudson/curtin:FR-2659-add-device-action into curtin:master

 

Michael Hudson-Doyle has proposed merging ~mwhudson/curtin:FR-2659-add-device-action into curtin:master.

Commit message:
block_meta: add 'device' action to directly refer to a block device



Requested reviews:
  curtin developers (curtin-dev)

For more details, see:
https://code.launchpad.net/~mwhudson/curtin/+git/curtin/+merge/429603
-- 
Your team curtin developers is requested to review the proposed merge of ~mwhudson/curtin:FR-2659-add-device-action into curtin:master.
diff --git a/curtin/commands/block_meta.py b/curtin/commands/block_meta.py
index d01333e..cef0e49 100644
--- a/curtin/commands/block_meta.py
+++ b/curtin/commands/block_meta.py
@@ -535,6 +535,9 @@ def get_path_to_storage_volume(volume, storage_config):
     elif vol.get('type') == 'image':
         volume_path = vol['dev']
 
+    elif vol.get('type') == 'device':
+        volume_path = vol['path']
+
     else:
         raise NotImplementedError("cannot determine the path to storage \
             volume '%s' with type '%s'" % (volume, vol.get('type')))
@@ -584,6 +587,11 @@ def image_handler(info, storage_config, context):
     context.handlers['disk'](info, storage_config, context)
 
 
+def device_handler(info, storage_config, context):
+    context.id_to_device[info['id']] = info['path']
+    context.handlers['disk'](info, storage_config, context)
+
+
 def dasd_handler(info, storage_config, context):
     """ Prepare the specified dasd device per configuration
 
@@ -2036,6 +2044,7 @@ def meta_custom(args):
 
     command_handlers = {
         'dasd': dasd_handler,
+        'device': device_handler,
         'disk': disk_handler,
         'partition': partition_handler,
         'format': format_handler,
@@ -2096,7 +2105,7 @@ def meta_custom(args):
         with open(device_map_path, 'w') as fp:
             json.dump(context.id_to_device, fp)
 
-    if args.testmode:
+    if args.testmode and DEVS:
         util.subp(['losetup', '--detach'] + list(DEVS))
 
     if args.umount:
diff --git a/doc/topics/storage.rst b/doc/topics/storage.rst
index 1225ee0..8eb738e 100644
--- a/doc/topics/storage.rst
+++ b/doc/topics/storage.rst
@@ -71,6 +71,7 @@ commands include:
 - Bcache Command (``bcache``)
 - Zpool Command (``zpool``) **Experimental**
 - ZFS Command (``zfs``)) **Experimental**
+- Device "Command" (``device``)
 
 Any action that refers to a block device (so things like ``partition``
 and ``dm_crypt`` but not ``lvm_volgroup`` or ``mount``, for example)
@@ -1175,6 +1176,22 @@ passed to the ZFS dataset creation command.
      canmount: noauto
      mountpoint: /
 
+Device "Command"
+~~~~~~~~~~~~~~~~
+
+This is a special command that can be used to refer to an arbitrary
+block device. It can be useful when you want to refer to a device that
+has been set up outside curtin for some reason -- partitioning or
+formatting or including in a RAID array or LVM volume group, for example.
+
+**path**: *path to device node*
+
+Path or symlink to the device node in /dev.
+
+The device action also supports the **ptable** attribute, to allow an
+arbitrary device node to be partitioned.
+
+
 
 Additional Examples
 -------------------
diff --git a/tests/integration/test_block_meta.py b/tests/integration/test_block_meta.py
index fb14a03..f753a39 100644
--- a/tests/integration/test_block_meta.py
+++ b/tests/integration/test_block_meta.py
@@ -157,7 +157,7 @@ class StorageConfigBuilder:
             }
 
     def _add(self, *, type, **kw):
-        if type != 'image' and self.cur_image is None:
+        if type not in ['image', 'device'] and self.cur_image is None:
             raise Exception("no current image")
         action = {'id': 'id' + str(len(self.config))}
         action.update(type=type, **kw)
@@ -172,6 +172,11 @@ class StorageConfigBuilder:
         self.cur_image = action['id']
         return action
 
+    def add_device(self, *, path, **kw):
+        action = self._add(type='device', path=path, **kw)
+        self.cur_image = action['id']
+        return action
+
     def add_part(self, *, size, **kw):
         fstype = kw.pop('fstype', None)
         part = self._add(type='partition', device=self.cur_image, size=size,
@@ -1188,3 +1193,15 @@ table-length: 256'''.encode()
             sfdisk_info = block.sfdisk_info(dev)
             # default is 128
             self.assertEqual(256, int(sfdisk_info['table-length']))
+
+    def test_device_action(self):
+        self.img = self.tmp_path('image.img')
+        with open(self.img, 'w') as fp:
+            fp.truncate(10 << 20)
+        with loop_dev(self.img) as dev:
+            config = StorageConfigBuilder(version=2)
+            config.add_device(path=dev, ptable='gpt')
+            config.add_part(number=1, offset=1 << 20, size=1 << 20)
+            self.run_bm(config.render())
+        self.assertPartitions(
+            PartData(number=1, offset=1 << 20, size=1 << 20))

Follow ups