Merge ~mwhudson/curtin:partition-dasd-without-device_id into curtin:master

Proposed by Michael Hudson-Doyle
Status: Superseded
Proposed branch: ~mwhudson/curtin:partition-dasd-without-device_id
Merge into: curtin:master
Prerequisite: ~mwhudson/curtin:pare-down-dasdview-parsing
Diff against target: 221 lines (+53/-107)
3 files modified
curtin/block/dasd.py (+51/-70)
curtin/commands/block_meta.py (+2/-3)
tests/unittests/test_block_dasd.py (+0/-34)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Paride Legovini Approve
Review via email: mp+394208@code.launchpad.net

This proposal has been superseded by a proposal from 2020-12-14.

Commit message

allow adding a vtoc partition without a device id

this is needed for the "dasd passed to kvm via virtio" use case

Description of the change

pls note the prerequisite branch

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Paride Legovini (paride) wrote :

LGTM from the code perspective, but I didn't test it.

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

Hmm prerequisite branches and a bot that squash merges do not get along.

Unmerged commits

aa3b584... by Michael Hudson-Doyle

allow adding a vtoc partition without a device id

this is needed for the "dasd passed to kvm via virtio" use case

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/curtin/block/dasd.py b/curtin/block/dasd.py
2index b10651c..3423601 100644
3--- a/curtin/block/dasd.py
4+++ b/curtin/block/dasd.py
5@@ -32,6 +32,57 @@ class DasdPartitionTable:
6 def tracks_needed(self, size_in_bytes):
7 return ((size_in_bytes - 1) // self.bytes_per_track) + 1
8
9+ def _ptable_for_new_partition(self, partnumber, partsize):
10+ if partnumber > 3:
11+ raise ValueError('DASD devices only allow 3 partitions')
12+
13+ # first partition always starts at track 2
14+ # all others start after the previous partition ends
15+ if partnumber == 1:
16+ start = 2
17+ else:
18+ start = int(self.partitions[-1].end) + 1
19+ end = start + self.tracks_needed(partsize) - 1
20+
21+ return [
22+ (p.start, p.end) for p in self.partitions[:partnumber-1]
23+ ] + [(start, end)]
24+
25+ def add_partition(self, partnumber, partsize):
26+ """ Add a partition to this DasdDevice specifying partnumber and size.
27+
28+ :param partnumber: integer value of partition number (1, 2 or 3)
29+ :param partsize: partition sizes in bytes.
30+
31+ :raises: ValueError on invalid devname
32+
33+ Example fdasd command with defaults:
34+ fdasd --verbose --config=/tmp/curtin/dasd-part1.fdasd /dev/dasdb
35+ """
36+ LOG.debug(
37+ "add_partition: partnumber: %s partsize: %s",
38+ partnumber, partsize)
39+
40+ partitions = self._ptable_for_new_partition(partnumber, partsize)
41+ LOG.debug("fdasd: partitions to be created: %s", partitions)
42+ content = "\n".join([
43+ "[%s,%s]" % (part[0], part[1]) for part in partitions
44+ ])
45+ LOG.debug("fdasd: content=\n%s", content)
46+ wfp = tempfile.NamedTemporaryFile(suffix=".fdasd", delete=False)
47+ wfp.close()
48+ util.write_file(wfp.name, content)
49+ cmd = ['fdasd', '--verbose', '--config=%s' % wfp.name, self.devname]
50+ LOG.debug('Partitioning %s with %s', self.devname, cmd)
51+ try:
52+ out, err = util.subp(cmd, capture=True)
53+ except util.ProcessExecutionError as e:
54+ LOG.error("Partitioning failed: %s", e)
55+ raise
56+ finally:
57+ if os.path.exists(wfp.name):
58+ os.unlink(wfp.name)
59+
60 @classmethod
61 def from_fdasd_output(cls, devname, output):
62 line_iter = iter(output.splitlines())
63@@ -131,22 +182,6 @@ def dasd_format(devname):
64
65
66 DASD_FORMAT = r"^format\s+:.+\s+(?P<value>\w+\s\w+)$"
67-<<<<<<< curtin/block/dasd.py
68-
69-
70-def find_val(regex, content):
71- m = re.search(regex, content, re.MULTILINE)
72- if m is not None:
73- return m.group("value")
74-
75-
76-def _dasd_format(dasdview_output):
77- """ Read and return specified device "disk_layout" value.
78-
79- :returns: string: One of ['cdl', 'ldl', 'not-formatted'].
80- :raises: ValueError if dasdview result missing 'format' section.
81-
82-=======
83
84
85 def find_val(regex, content):
86@@ -161,7 +196,6 @@ def _dasd_format(dasdview_output):
87 :returns: string: One of ['cdl', 'ldl', 'not-formatted'].
88 :raises: ValueError if dasdview result missing 'format' section.
89
90->>>>>>> curtin/block/dasd.py
91 """
92 if not dasdview_output:
93 return
94@@ -243,59 +277,6 @@ class DasdDevice(CcwDevice):
95 def devname(self):
96 return '/dev/disk/by-path/ccw-%s' % self.device_id
97
98- def partition(self, partnumber, partsize, strict=True):
99- """ Add a partition to this DasdDevice specifying partnumber and size.
100-
101- :param partnumber: integer value of partition number (1, 2 or 3)
102- :param partsize: partition sizes in bytes.
103- :param strict: boolean which enforces that dasd device exists before
104- issuing fdasd command, defaults to True.
105-
106- :raises: RuntimeError if strict==True and devname does not exist.
107- :raises: ValueError on invalid devname
108-
109- Example fdasd command with defaults:
110- fdasd --verbose --config=/tmp/curtin/dasd-part1.fdasd /dev/dasdb
111- """
112- if partnumber > 3:
113- raise ValueError('DASD devices only allow 3 partitions')
114-
115- if strict and not os.path.exists(self.devname):
116- raise RuntimeError("devname '%s' does not exist" % self.devname)
117-
118- pt = DasdPartitionTable.from_fdasd(self.devname)
119- new_partitions = []
120- for partinfo in pt.partitions[0:partnumber]:
121- new_partitions.append((partinfo.start, partinfo.end))
122-
123- # first partition always starts at track 2
124- # all others start after the previous partition ends
125- if partnumber == 1:
126- start = 2
127- else:
128- start = int(pt.partitions[-1].end) + 1
129- # end is inclusive
130- end = start + pt.tracks_needed(partsize) - 1
131- new_partitions.append((start, end))
132-
133- content = "\n".join(["[%s,%s]" % (part[0], part[1])
134- for part in new_partitions])
135- LOG.debug("fdasd: partitions to be created: %s", new_partitions)
136- LOG.debug("fdasd: content=\n%s", content)
137- wfp = tempfile.NamedTemporaryFile(suffix=".fdasd", delete=False)
138- wfp.close()
139- util.write_file(wfp.name, content)
140- cmd = ['fdasd', '--verbose', '--config=%s' % wfp.name, self.devname]
141- LOG.debug('Partitioning %s with %s', self.devname, cmd)
142- try:
143- out, err = util.subp(cmd, capture=True)
144- except util.ProcessExecutionError as e:
145- LOG.error("Partitioning failed: %s", e)
146- raise
147- finally:
148- if os.path.exists(wfp.name):
149- os.unlink(wfp.name)
150-
151 def is_not_formatted(self):
152 """ Returns a boolean indicating if the specified device_id is not yet
153 formatted.
154diff --git a/curtin/commands/block_meta.py b/curtin/commands/block_meta.py
155index 66dfdb4..e29c1e4 100644
156--- a/curtin/commands/block_meta.py
157+++ b/curtin/commands/block_meta.py
158@@ -946,9 +946,8 @@ def partition_handler(info, storage_config):
159 "--typecode=%s:%s" % (partnumber, typecode), disk]
160 util.subp(cmd, capture=True)
161 elif disk_ptable == "vtoc":
162- disk_device_id = storage_config.get(device).get('device_id')
163- dasd_device = dasd.DasdDevice(disk_device_id)
164- dasd_device.partition(partnumber, length_bytes)
165+ dasd_pt = dasd.DasdPartitionTable.from_fdasd(disk)
166+ dasd_pt.add_partition(partnumber, length_bytes)
167 else:
168 raise ValueError("parent partition has invalid partition table")
169
170diff --git a/tests/unittests/test_block_dasd.py b/tests/unittests/test_block_dasd.py
171index cc545a1..2058800 100644
172--- a/tests/unittests/test_block_dasd.py
173+++ b/tests/unittests/test_block_dasd.py
174@@ -415,7 +415,6 @@ class TestDasdInfo(CiTestCase):
175
176
177 class TestDasdFormat(CiTestCase):
178-<<<<<<< tests/unittests/test_block_dasd.py
179
180 def setUp(self):
181 super(TestDasdFormat, self).setUp()
182@@ -447,39 +446,6 @@ class TestDasdFormat(CiTestCase):
183
184 class Test_DasdFormat(CiTestCase):
185
186-=======
187-
188- def setUp(self):
189- super(TestDasdFormat, self).setUp()
190- self.add_patch('curtin.block.dasd.util.subp', 'm_subp')
191- self.add_patch('curtin.block.dasd.os.path.exists', 'm_exists')
192- self.add_patch('curtin.block.dasd._dasd_format', 'm_dasd_format')
193-
194- # defaults
195- self.m_exists.return_value = True
196- self.m_subp.return_value = ('', '')
197-
198- def test_dasd_format_raise_error_on_invalid_device(self):
199- """dasdview raises error on invalid device path."""
200- devname = self.random_string()
201- self.m_exists.return_value = False
202- with self.assertRaises(ValueError):
203- dasd.dasd_format(devname)
204-
205- def test_dasd_foramt_calls__dasd_format(self):
206- """dasdview calls parser on output from dasdview command."""
207- devname = self.random_string()
208- view = self.random_string()
209- self.m_subp.return_value = (view, self.random_string())
210- dasd.dasd_format(devname)
211- self.m_subp.assert_called_with(
212- ['dasdview', '--extended', devname], capture=True)
213- self.m_dasd_format.assert_called_with(view)
214-
215-
216-class Test_DasdFormat(CiTestCase):
217-
218->>>>>>> tests/unittests/test_block_dasd.py
219 view_output_template = textwrap.dedent("""\
220
221 --- general DASD information ----------------------------------------------

Subscribers

People subscribed via source and target branches