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

Proposed by Michael Hudson-Doyle
Status: Merged
Approved by: Michael Hudson-Doyle
Approved revision: c6180379e7cd339de763b5dc4c6cb5a2d9c2d7a0
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~mwhudson/curtin:FR-2659-add-device-action
Merge into: curtin:master
Diff against target: 119 lines (+45/-2)
3 files modified
curtin/commands/block_meta.py (+10/-1)
doc/topics/storage.rst (+17/-0)
tests/integration/test_block_meta.py (+18/-1)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Dan Bungert Approve
Review via email: mp+429603@code.launchpad.net

Commit message

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

To post a comment you must log in.
Revision history for this message
Dan Bungert (dbungert) :
review: Approve
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

Thanks for the fast turnaround :)

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/curtin/commands/block_meta.py b/curtin/commands/block_meta.py
2index d01333e..cef0e49 100644
3--- a/curtin/commands/block_meta.py
4+++ b/curtin/commands/block_meta.py
5@@ -535,6 +535,9 @@ def get_path_to_storage_volume(volume, storage_config):
6 elif vol.get('type') == 'image':
7 volume_path = vol['dev']
8
9+ elif vol.get('type') == 'device':
10+ volume_path = vol['path']
11+
12 else:
13 raise NotImplementedError("cannot determine the path to storage \
14 volume '%s' with type '%s'" % (volume, vol.get('type')))
15@@ -584,6 +587,11 @@ def image_handler(info, storage_config, context):
16 context.handlers['disk'](info, storage_config, context)
17
18
19+def device_handler(info, storage_config, context):
20+ context.id_to_device[info['id']] = info['path']
21+ context.handlers['disk'](info, storage_config, context)
22+
23+
24 def dasd_handler(info, storage_config, context):
25 """ Prepare the specified dasd device per configuration
26
27@@ -2036,6 +2044,7 @@ def meta_custom(args):
28
29 command_handlers = {
30 'dasd': dasd_handler,
31+ 'device': device_handler,
32 'disk': disk_handler,
33 'partition': partition_handler,
34 'format': format_handler,
35@@ -2096,7 +2105,7 @@ def meta_custom(args):
36 with open(device_map_path, 'w') as fp:
37 json.dump(context.id_to_device, fp)
38
39- if args.testmode:
40+ if args.testmode and DEVS:
41 util.subp(['losetup', '--detach'] + list(DEVS))
42
43 if args.umount:
44diff --git a/doc/topics/storage.rst b/doc/topics/storage.rst
45index 1225ee0..8eb738e 100644
46--- a/doc/topics/storage.rst
47+++ b/doc/topics/storage.rst
48@@ -71,6 +71,7 @@ commands include:
49 - Bcache Command (``bcache``)
50 - Zpool Command (``zpool``) **Experimental**
51 - ZFS Command (``zfs``)) **Experimental**
52+- Device "Command" (``device``)
53
54 Any action that refers to a block device (so things like ``partition``
55 and ``dm_crypt`` but not ``lvm_volgroup`` or ``mount``, for example)
56@@ -1175,6 +1176,22 @@ passed to the ZFS dataset creation command.
57 canmount: noauto
58 mountpoint: /
59
60+Device "Command"
61+~~~~~~~~~~~~~~~~
62+
63+This is a special command that can be used to refer to an arbitrary
64+block device. It can be useful when you want to refer to a device that
65+has been set up outside curtin for some reason -- partitioning or
66+formatting or including in a RAID array or LVM volume group, for example.
67+
68+**path**: *path to device node*
69+
70+Path or symlink to the device node in /dev.
71+
72+The device action also supports the **ptable** attribute, to allow an
73+arbitrary device node to be partitioned.
74+
75+
76
77 Additional Examples
78 -------------------
79diff --git a/tests/integration/test_block_meta.py b/tests/integration/test_block_meta.py
80index fb14a03..f753a39 100644
81--- a/tests/integration/test_block_meta.py
82+++ b/tests/integration/test_block_meta.py
83@@ -157,7 +157,7 @@ class StorageConfigBuilder:
84 }
85
86 def _add(self, *, type, **kw):
87- if type != 'image' and self.cur_image is None:
88+ if type not in ['image', 'device'] and self.cur_image is None:
89 raise Exception("no current image")
90 action = {'id': 'id' + str(len(self.config))}
91 action.update(type=type, **kw)
92@@ -172,6 +172,11 @@ class StorageConfigBuilder:
93 self.cur_image = action['id']
94 return action
95
96+ def add_device(self, *, path, **kw):
97+ action = self._add(type='device', path=path, **kw)
98+ self.cur_image = action['id']
99+ return action
100+
101 def add_part(self, *, size, **kw):
102 fstype = kw.pop('fstype', None)
103 part = self._add(type='partition', device=self.cur_image, size=size,
104@@ -1188,3 +1193,15 @@ table-length: 256'''.encode()
105 sfdisk_info = block.sfdisk_info(dev)
106 # default is 128
107 self.assertEqual(256, int(sfdisk_info['table-length']))
108+
109+ def test_device_action(self):
110+ self.img = self.tmp_path('image.img')
111+ with open(self.img, 'w') as fp:
112+ fp.truncate(10 << 20)
113+ with loop_dev(self.img) as dev:
114+ config = StorageConfigBuilder(version=2)
115+ config.add_device(path=dev, ptable='gpt')
116+ config.add_part(number=1, offset=1 << 20, size=1 << 20)
117+ self.run_bm(config.render())
118+ self.assertPartitions(
119+ PartData(number=1, offset=1 << 20, size=1 << 20))

Subscribers

People subscribed via source and target branches