Merge ~minagalic/cloud-init:fix/fbsd-resizefs into cloud-init:master

Proposed by Mina Galić
Status: Merged
Approved by: Chad Smith
Approved revision: 7a42186003638aa69821ca6e9b30f736aee1632f
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~minagalic/cloud-init:fix/fbsd-resizefs
Merge into: cloud-init:master
Diff against target: 108 lines (+47/-8)
2 files modified
cloudinit/config/cc_resizefs.py (+7/-0)
tests/unittests/test_handler/test_handler_resizefs.py (+40/-8)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Mina Galić (community) Needs Resubmitting
Chad Smith Needs Fixing
Review via email: mp+357723@code.launchpad.net

Commit message

resizefs: Prefix discovered devpath with '/dev/' when path does not exist

In some environments, like FreeBSD, gpart can return the device basename
instead of the full path. If this discovered devpath does not exist and
is missing the '/dev/' prefix, add that prefix in an attempt to find the
device.

Description of the change

If the device name doesn't start with `/dev/` check there for its existence!

To post a comment you must log in.
Revision history for this message
Scott Moser (smoser) wrote :

Hi,
Thank you for contributing to cloud-init.

To contribute, you must sign the Canonical Contributor License Agreement (CLA) [1].

If you have already signed it as an individual, your Launchpad user will be listed in the contributor-agreement-canonical launchpad group [2]. Unfortunately there is no easy way to check if an organization or company you are doing work for has signed. If you are unsure or have questions, email <email address hidden> or ping smoser in #cloud-init channel via freenode.

For information on how to sign, please see the HACKING document [3].

Thanks again, and please feel free to reach out with any questions.


[1] http://www.canonical.com/contributors
[2] https://launchpad.net/~contributor-agreement-canonical/+members
[3] http://cloudinit.readthedocs.io/en/latest/topics/hacking.html

Revision history for this message
Mina Galić (minagalic) wrote :

> Hi,
> Thank you for contributing to cloud-init.
>
> To contribute, you must sign the Canonical Contributor License Agreement (CLA)

done… i think!

Revision history for this message
Mina Galić (minagalic) wrote :

> > Hi,
> > Thank you for contributing to cloud-init.
> >
> > To contribute, you must sign the Canonical Contributor License Agreement
> (CLA)
>
> done… i think!

https://launchpad.net/%7Econtributor-agreement-canonical/+members?active_batch=75&active_memo=300&active_start=300

indeed!

Revision history for this message
Chad Smith (chad.smith) wrote :

Thank you Igor,

To me it feels like this should be a fallback option only if the provided devpath doesn't exist.

I've added a comment inline and set this to "Work in progress" to let you know it is off our radar until you have a chance to respond to the review comments and would like us to re-review this branch.

Please set this branch top-level 'status' back to 'Needs review' when you have had a chance to respond to the comments or fixes.

thanks again!

review: Needs Fixing
Revision history for this message
Mina Galić (minagalic) wrote :

Thanks for the review Chad. I've now fixed up the code as per your suggestions, but the test i added is failing for reasons i cannot quite explain yet.

review: Needs Resubmitting
Revision history for this message
Chad Smith (chad.smith) wrote :

thanks for adding the unit test. I added a patch on top to fixup the unit test and account for my inline comments.
hopefully that works and passes tox for us.

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

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

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

review: Needs Fixing (continuous-integration)
7a42186... by =?utf-8?q?Igor_Gali=C4=87?= <email address hidden>

Fix style

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

PASSED: Continuous integration, rev:7a42186003638aa69821ca6e9b30f736aee1632f
https://jenkins.ubuntu.com/server/job/cloud-init-ci/443/
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/443/rebuild

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_resizefs.py b/cloudinit/config/cc_resizefs.py
2index 2edddd0..076b9d5 100644
3--- a/cloudinit/config/cc_resizefs.py
4+++ b/cloudinit/config/cc_resizefs.py
5@@ -197,6 +197,13 @@ def maybe_get_writable_device_path(devpath, info, log):
6 if devpath.startswith('gpt/'):
7 log.debug('We have a gpt label - just go ahead')
8 return devpath
9+ # Alternatively, our device could simply be a name as returned by gpart,
10+ # such as da0p3
11+ if not devpath.startswith('/dev/') and not os.path.exists(devpath):
12+ fulldevpath = '/dev/' + devpath.lstrip('/')
13+ log.debug("'%s' doesn't appear to be a valid device path. Trying '%s'",
14+ devpath, fulldevpath)
15+ devpath = fulldevpath
16
17 try:
18 statret = os.stat(devpath)
19diff --git a/tests/unittests/test_handler/test_handler_resizefs.py b/tests/unittests/test_handler/test_handler_resizefs.py
20index feca56c..6ebacb1 100644
21--- a/tests/unittests/test_handler/test_handler_resizefs.py
22+++ b/tests/unittests/test_handler/test_handler_resizefs.py
23@@ -173,6 +173,38 @@ class TestResizefs(CiTestCase):
24
25 self.assertEqual(('zpool', 'online', '-e', 'vmzroot', disk), ret)
26
27+ @mock.patch('cloudinit.util.is_container', return_value=False)
28+ @mock.patch('cloudinit.util.get_mount_info')
29+ @mock.patch('cloudinit.util.get_device_info_from_zpool')
30+ @mock.patch('cloudinit.util.parse_mount')
31+ def test_handle_modern_zfsroot(self, mount_info, zpool_info, parse_mount,
32+ is_container):
33+ devpth = 'zroot/ROOT/default'
34+ disk = 'da0p3'
35+ fs_type = 'zfs'
36+ mount_point = '/'
37+
38+ mount_info.return_value = (devpth, fs_type, mount_point)
39+ zpool_info.return_value = disk
40+ parse_mount.return_value = (devpth, fs_type, mount_point)
41+
42+ cfg = {'resize_rootfs': True}
43+
44+ def fake_stat(devpath):
45+ if devpath == disk:
46+ raise OSError("not here")
47+ FakeStat = namedtuple(
48+ 'FakeStat', ['st_mode', 'st_size', 'st_mtime']) # minimal stat
49+ return FakeStat(25008, 0, 1) # fake char block device
50+
51+ with mock.patch('cloudinit.config.cc_resizefs.do_resize') as dresize:
52+ with mock.patch('cloudinit.config.cc_resizefs.os.stat') as m_stat:
53+ m_stat.side_effect = fake_stat
54+ handle('cc_resizefs', cfg, _cloud=None, log=LOG, args=[])
55+
56+ self.assertEqual(('zpool', 'online', '-e', 'zroot', '/dev/' + disk),
57+ dresize.call_args[0][0])
58+
59
60 class TestRootDevFromCmdline(CiTestCase):
61
62@@ -246,39 +278,39 @@ class TestMaybeGetDevicePathAsWritableBlock(CiTestCase):
63
64 def test_maybe_get_writable_device_path_does_not_exist(self):
65 """When devpath does not exist, a warning is logged."""
66- info = 'dev=/I/dont/exist mnt_point=/ path=/dev/none'
67+ info = 'dev=/dev/I/dont/exist mnt_point=/ path=/dev/none'
68 devpath = wrap_and_call(
69 'cloudinit.config.cc_resizefs.util',
70 {'is_container': {'return_value': False}},
71- maybe_get_writable_device_path, '/I/dont/exist', info, LOG)
72+ maybe_get_writable_device_path, '/dev/I/dont/exist', info, LOG)
73 self.assertIsNone(devpath)
74 self.assertIn(
75- "WARNING: Device '/I/dont/exist' did not exist."
76+ "WARNING: Device '/dev/I/dont/exist' did not exist."
77 ' cannot resize: %s' % info,
78 self.logs.getvalue())
79
80 def test_maybe_get_writable_device_path_does_not_exist_in_container(self):
81 """When devpath does not exist in a container, log a debug message."""
82- info = 'dev=/I/dont/exist mnt_point=/ path=/dev/none'
83+ info = 'dev=/dev/I/dont/exist mnt_point=/ path=/dev/none'
84 devpath = wrap_and_call(
85 'cloudinit.config.cc_resizefs.util',
86 {'is_container': {'return_value': True}},
87- maybe_get_writable_device_path, '/I/dont/exist', info, LOG)
88+ maybe_get_writable_device_path, '/dev/I/dont/exist', info, LOG)
89 self.assertIsNone(devpath)
90 self.assertIn(
91- "DEBUG: Device '/I/dont/exist' did not exist in container."
92+ "DEBUG: Device '/dev/I/dont/exist' did not exist in container."
93 ' cannot resize: %s' % info,
94 self.logs.getvalue())
95
96 def test_maybe_get_writable_device_path_raises_oserror(self):
97 """When unexpected OSError is raises by os.stat it is reraised."""
98- info = 'dev=/I/dont/exist mnt_point=/ path=/dev/none'
99+ info = 'dev=/dev/I/dont/exist mnt_point=/ path=/dev/none'
100 with self.assertRaises(OSError) as context_manager:
101 wrap_and_call(
102 'cloudinit.config.cc_resizefs',
103 {'util.is_container': {'return_value': True},
104 'os.stat': {'side_effect': OSError('Something unexpected')}},
105- maybe_get_writable_device_path, '/I/dont/exist', info, LOG)
106+ maybe_get_writable_device_path, '/dev/I/dont/exist', info, LOG)
107 self.assertEqual(
108 'Something unexpected', str(context_manager.exception))
109

Subscribers

People subscribed via source and target branches