Merge ~goneri/cloud-init:freebsd_growfs into cloud-init:master

Proposed by Gonéri Le Bouder
Status: Merged
Approved by: Ryan Harper
Approved revision: a88924bf0b6a6414094539ca3787d5ce4c771558
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~goneri/cloud-init:freebsd_growfs
Merge into: cloud-init:master
Diff against target: 186 lines (+64/-38)
6 files modified
cloudinit/config/cc_growpart.py (+2/-1)
cloudinit/config/cc_resizefs.py (+3/-3)
cloudinit/util.py (+13/-9)
tests/unittests/test_datasource/test_azure.py (+0/-24)
tests/unittests/test_distros/test_freebsd.py (+45/-0)
tests/unittests/test_handler/test_handler_resizefs.py (+1/-1)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Ryan Harper Approve
Review via email: mp+366313@code.launchpad.net

This proposal supersedes a proposal from 2019-04-14.

Commit message

freebsd: ability to grow root file system

- UFS file system support
- GPT partition table support
- add support for newfs's -L parameter (label)
- move freebsd specific test from Azure to freebsd

To post a comment you must log in.
~goneri/cloud-init:freebsd_growfs updated
a88924b... by Gonéri Le Bouder

freebsd: pass the mountpoint to growfs

growfs behaviour depends on the partition naming, if we use the
/dev/vtbd0p4 format, we can end-up with a "operation not permitted"
error. The good news is that growfs can also accept a mount point
as an argument.

See: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=237392

Revision history for this message
Gonéri Le Bouder (goneri) wrote :
Revision history for this message
Ryan Harper (raharper) wrote :

This looks fine. Can you set the commit message on the MP (+ Set commit message).
74 char limit. Please include a summary and single line capturing all of the
changes you've made.

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

FAILED: Continuous integration, rev:e0c7a82b7cba04ff289e65c306778e7f451d91e4
https://jenkins.ubuntu.com/server/job/cloud-init-ci/712/
Executed test runs:
    SUCCESS: Checkout
    FAILED: Unit & Style Tests

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/712/rebuild

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

PASSED: Continuous integration, rev:e0c7a82b7cba04ff289e65c306778e7f451d91e4
https://jenkins.ubuntu.com/server/job/cloud-init-ci/713/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/713/rebuild

review: Approve (continuous-integration)
Revision history for this message
Ryan Harper (raharper) :
review: Needs Information
Revision history for this message
Gonéri Le Bouder (goneri) wrote :

Do you need anything else to merge this PR?

Revision history for this message
Gonéri Le Bouder (goneri) wrote :

I just realized my inline answers were not saved. :-(

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

PASSED: Continuous integration, rev:a88924bf0b6a6414094539ca3787d5ce4c771558
https://jenkins.ubuntu.com/server/job/cloud-init-ci/730/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/730/rebuild

review: Approve (continuous-integration)
Revision history for this message
Ryan Harper (raharper) wrote :

Thanks.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/config/cc_growpart.py b/cloudinit/config/cc_growpart.py
2index bafca9d..564f376 100644
3--- a/cloudinit/config/cc_growpart.py
4+++ b/cloudinit/config/cc_growpart.py
5@@ -215,7 +215,8 @@ def device_part_info(devpath):
6 # FreeBSD doesn't know of sysfs so just get everything we need from
7 # the device, like /dev/vtbd0p2.
8 if util.is_FreeBSD():
9- m = re.search('^(/dev/.+)p([0-9])$', devpath)
10+ freebsd_part = "/dev/" + util.find_freebsd_part(devpath)
11+ m = re.search('^(/dev/.+)p([0-9])$', freebsd_part)
12 return (m.group(1), m.group(2))
13
14 if not os.path.exists(syspath):
15diff --git a/cloudinit/config/cc_resizefs.py b/cloudinit/config/cc_resizefs.py
16index 076b9d5..afd2e06 100644
17--- a/cloudinit/config/cc_resizefs.py
18+++ b/cloudinit/config/cc_resizefs.py
19@@ -81,7 +81,7 @@ def _resize_xfs(mount_point, devpth):
20
21
22 def _resize_ufs(mount_point, devpth):
23- return ('growfs', '-y', devpth)
24+ return ('growfs', '-y', mount_point)
25
26
27 def _resize_zfs(mount_point, devpth):
28@@ -101,7 +101,7 @@ def _can_skip_resize_ufs(mount_point, devpth):
29 """
30 # dumpfs -m /
31 # newfs command for / (/dev/label/rootfs)
32- newfs -O 2 -U -a 4 -b 32768 -d 32768 -e 4096 -f 4096 -g 16384
33+ newfs -L rootf -O 2 -U -a 4 -b 32768 -d 32768 -e 4096 -f 4096 -g 16384
34 -h 64 -i 8192 -j -k 6408 -m 8 -o time -s 58719232 /dev/label/rootf
35 """
36 cur_fs_sz = None
37@@ -110,7 +110,7 @@ def _can_skip_resize_ufs(mount_point, devpth):
38 for line in dumpfs_res.splitlines():
39 if not line.startswith('#'):
40 newfs_cmd = shlex.split(line)
41- opt_value = 'O:Ua:s:b:d:e:f:g:h:i:jk:m:o:'
42+ opt_value = 'O:Ua:s:b:d:e:f:g:h:i:jk:m:o:L:'
43 optlist, _args = getopt.getopt(newfs_cmd[1:], opt_value)
44 for o, a in optlist:
45 if o == "-s":
46diff --git a/cloudinit/util.py b/cloudinit/util.py
47index ea4199c..aa23b3f 100644
48--- a/cloudinit/util.py
49+++ b/cloudinit/util.py
50@@ -2337,17 +2337,21 @@ def parse_mtab(path):
51 return None
52
53
54-def find_freebsd_part(label_part):
55- if label_part.startswith("/dev/label/"):
56- target_label = label_part[5:]
57- (label_part, _err) = subp(['glabel', 'status', '-s'])
58- for labels in label_part.split("\n"):
59+def find_freebsd_part(fs):
60+ splitted = fs.split('/')
61+ if len(splitted) == 3:
62+ return splitted[2]
63+ elif splitted[2] in ['label', 'gpt', 'ufs']:
64+ target_label = fs[5:]
65+ (part, _err) = subp(['glabel', 'status', '-s'])
66+ for labels in part.split("\n"):
67 items = labels.split()
68- if len(items) > 0 and items[0].startswith(target_label):
69- label_part = items[2]
70+ if len(items) > 0 and items[0] == target_label:
71+ part = items[2]
72 break
73- label_part = str(label_part)
74- return label_part
75+ return str(part)
76+ else:
77+ LOG.warning("Unexpected input in find_freebsd_part: %s", fs)
78
79
80 def get_path_dev_freebsd(path, mnt_list):
81diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py
82index 427ab7e..afb614e 100644
83--- a/tests/unittests/test_datasource/test_azure.py
84+++ b/tests/unittests/test_datasource/test_azure.py
85@@ -6,7 +6,6 @@ from cloudinit import url_helper
86 from cloudinit.sources import (
87 UNSET, DataSourceAzure as dsaz, InvalidMetaDataException)
88 from cloudinit.util import (b64e, decode_binary, load_file, write_file,
89- find_freebsd_part, get_path_dev_freebsd,
90 MountFailedError, json_dumps, load_json)
91 from cloudinit.version import version_string as vs
92 from cloudinit.tests.helpers import (
93@@ -391,29 +390,6 @@ scbus-1 on xpt0 bus 0
94 dev = ds.get_resource_disk_on_freebsd(1)
95 self.assertEqual("da1", dev)
96
97- @mock.patch('cloudinit.util.subp')
98- def test_find_freebsd_part_on_Azure(self, mock_subp):
99- glabel_out = '''
100-gptid/fa52d426-c337-11e6-8911-00155d4c5e47 N/A da0p1
101- label/rootfs N/A da0p2
102- label/swap N/A da0p3
103-'''
104- mock_subp.return_value = (glabel_out, "")
105- res = find_freebsd_part("/dev/label/rootfs")
106- self.assertEqual("da0p2", res)
107-
108- def test_get_path_dev_freebsd_on_Azure(self):
109- mnt_list = '''
110-/dev/label/rootfs / ufs rw 1 1
111-devfs /dev devfs rw,multilabel 0 0
112-fdescfs /dev/fd fdescfs rw 0 0
113-/dev/da1s1 /mnt/resource ufs rw 2 2
114-'''
115- with mock.patch.object(os.path, 'exists',
116- return_value=True):
117- res = get_path_dev_freebsd('/etc', mnt_list)
118- self.assertIsNotNone(res)
119-
120 @mock.patch(MOCKPATH + '_is_platform_viable')
121 def test_call_is_platform_viable_seed(self, m_is_platform_viable):
122 """Check seed_dir using _is_platform_viable and return False."""
123diff --git a/tests/unittests/test_distros/test_freebsd.py b/tests/unittests/test_distros/test_freebsd.py
124new file mode 100644
125index 0000000..8af253a
126--- /dev/null
127+++ b/tests/unittests/test_distros/test_freebsd.py
128@@ -0,0 +1,45 @@
129+# This file is part of cloud-init. See LICENSE file for license information.
130+
131+from cloudinit.util import (find_freebsd_part, get_path_dev_freebsd)
132+from cloudinit.tests.helpers import (CiTestCase, mock)
133+
134+import os
135+
136+
137+class TestDeviceLookUp(CiTestCase):
138+
139+ @mock.patch('cloudinit.util.subp')
140+ def test_find_freebsd_part_label(self, mock_subp):
141+ glabel_out = '''
142+gptid/fa52d426-c337-11e6-8911-00155d4c5e47 N/A da0p1
143+ label/rootfs N/A da0p2
144+ label/swap N/A da0p3
145+'''
146+ mock_subp.return_value = (glabel_out, "")
147+ res = find_freebsd_part("/dev/label/rootfs")
148+ self.assertEqual("da0p2", res)
149+
150+ @mock.patch('cloudinit.util.subp')
151+ def test_find_freebsd_part_gpt(self, mock_subp):
152+ glabel_out = '''
153+ gpt/bootfs N/A vtbd0p1
154+gptid/3f4cbe26-75da-11e8-a8f2-002590ec6166 N/A vtbd0p1
155+ gpt/swapfs N/A vtbd0p2
156+ gpt/rootfs N/A vtbd0p3
157+ iso9660/cidata N/A vtbd2
158+'''
159+ mock_subp.return_value = (glabel_out, "")
160+ res = find_freebsd_part("/dev/gpt/rootfs")
161+ self.assertEqual("vtbd0p3", res)
162+
163+ def test_get_path_dev_freebsd_label(self):
164+ mnt_list = '''
165+/dev/label/rootfs / ufs rw 1 1
166+devfs /dev devfs rw,multilabel 0 0
167+fdescfs /dev/fd fdescfs rw 0 0
168+/dev/da1s1 /mnt/resource ufs rw 2 2
169+'''
170+ with mock.patch.object(os.path, 'exists',
171+ return_value=True):
172+ res = get_path_dev_freebsd('/etc', mnt_list)
173+ self.assertIsNotNone(res)
174diff --git a/tests/unittests/test_handler/test_handler_resizefs.py b/tests/unittests/test_handler/test_handler_resizefs.py
175index 3518784..db9a041 100644
176--- a/tests/unittests/test_handler/test_handler_resizefs.py
177+++ b/tests/unittests/test_handler/test_handler_resizefs.py
178@@ -147,7 +147,7 @@ class TestResizefs(CiTestCase):
179 def test_resize_ufs_cmd_return(self):
180 mount_point = '/'
181 devpth = '/dev/sda2'
182- self.assertEqual(('growfs', '-y', devpth),
183+ self.assertEqual(('growfs', '-y', mount_point),
184 _resize_ufs(mount_point, devpth))
185
186 @mock.patch('cloudinit.util.is_container', return_value=False)

Subscribers

People subscribed via source and target branches