diff options
| author | Conrad Hoffmann <1226676+bitfehler@users.noreply.github.com> | 2020-01-14 21:27:59 +0100 | 
|---|---|---|
| committer | Daniel Watkins <oddbloke@ubuntu.com> | 2020-01-14 15:27:59 -0500 | 
| commit | bb4131a2bd36d9e8932fdcb61432260f16159cde (patch) | |
| tree | be3501e7efbdfe21d221e4d221120f88ebdbba62 | |
| parent | 863394ba0b5f18483b350daec30af8434be8811b (diff) | |
| download | vyos-cloud-init-bb4131a2bd36d9e8932fdcb61432260f16159cde.tar.gz vyos-cloud-init-bb4131a2bd36d9e8932fdcb61432260f16159cde.zip  | |
Only use gpart if it is the BSD gpart (#131)
Currently, cloud-init will happily try to run `gpart` on Linux even
though on most distributions this a different tool [1]. Extend the
availability check to make sure the `gpart` present is really the BSD
variant, to avoid accidental execution.
Also add a pointer to the docs, so that people do not try to install
gpart on Linux in the expectation it will work with this module.
[1] https://github.com/baruch/gpart
| -rw-r--r-- | cloudinit/config/cc_growpart.py | 26 | ||||
| -rw-r--r-- | tests/unittests/test_handler/test_handler_growpart.py | 29 | 
2 files changed, 44 insertions, 11 deletions
diff --git a/cloudinit/config/cc_growpart.py b/cloudinit/config/cc_growpart.py index aa9716e7..1b512a06 100644 --- a/cloudinit/config/cc_growpart.py +++ b/cloudinit/config/cc_growpart.py @@ -22,11 +22,11 @@ mountpoint in the filesystem or a path to the block device in ``/dev``.  The utility to use for resizing can be selected using the ``mode`` config key.  If ``mode`` key is set to ``auto``, then any available utility (either -``growpart`` or ``gpart``) will be used. If neither utility is available, no -error will be raised. If ``mode`` is set to ``growpart``, then the ``growpart`` -utility will be used. If this utility is not available on the system, this will -result in an error. If ``mode`` is set to ``off`` or ``false``, then -``cc_growpart`` will take no action. +``growpart`` or BSD ``gpart``) will be used. If neither utility is available, +no error will be raised. If ``mode`` is set to ``growpart``, then the +``growpart`` utility will be used. If this utility is not available on the +system, this will result in an error. If ``mode`` is set to ``off`` or +``false``, then ``cc_growpart`` will take no action.  There is some functionality overlap between this module and the ``growroot``  functionality of ``cloud-initramfs-tools``. However, there are some situations @@ -132,7 +132,7 @@ class ResizeGrowPart(object):          try:              (out, _err) = util.subp(["growpart", "--help"], env=myenv) -            if re.search(r"--update\s+", out, re.DOTALL): +            if re.search(r"--update\s+", out):                  return True          except util.ProcessExecutionError: @@ -161,9 +161,17 @@ class ResizeGrowPart(object):  class ResizeGpart(object):      def available(self): -        if not util.which('gpart'): -            return False -        return True +        myenv = os.environ.copy() +        myenv['LANG'] = 'C' + +        try: +            (_out, err) = util.subp(["gpart", "help"], env=myenv, rcs=[0, 1]) +            if re.search(r"gpart recover ", err): +                return True + +        except util.ProcessExecutionError: +            pass +        return False      def resize(self, diskdev, partnum, partdev):          """ diff --git a/tests/unittests/test_handler/test_handler_growpart.py b/tests/unittests/test_handler/test_handler_growpart.py index a3e46351..1f39ebe7 100644 --- a/tests/unittests/test_handler/test_handler_growpart.py +++ b/tests/unittests/test_handler/test_handler_growpart.py @@ -52,6 +52,18 @@ growpart disk partition        Resize partition 1 on /dev/sda  """ +HELP_GPART = """ +usage: gpart add -t type [-a alignment] [-b start] <SNIP> geom +       gpart backup geom +       gpart bootcode [-b bootcode] [-p partcode -i index] [-f flags] geom +<SNIP> +       gpart resize -i index [-a alignment] [-s size] [-f flags] geom +       gpart restore [-lF] [-f flags] provider [...] +       gpart recover [-f flags] geom +       gpart help +<SNIP> +""" +  class TestDisabled(unittest.TestCase):      def setUp(self): @@ -97,8 +109,9 @@ class TestConfig(TestCase):              self.handle(self.name, config, self.cloud_init, self.log,                          self.args) -            mockobj.assert_called_once_with( -                ['growpart', '--help'], env={'LANG': 'C'}) +            mockobj.assert_has_calls([ +                mock.call(['growpart', '--help'], env={'LANG': 'C'}), +                mock.call(['gpart', 'help'], env={'LANG': 'C'}, rcs=[0, 1])])      @mock.patch.dict("os.environ", clear=True)      def test_no_resizers_mode_growpart_is_exception(self): @@ -124,6 +137,18 @@ class TestConfig(TestCase):              mockobj.assert_called_once_with(                  ['growpart', '--help'], env={'LANG': 'C'}) +    @mock.patch.dict("os.environ", clear=True) +    def test_mode_auto_falls_back_to_gpart(self): +        with mock.patch.object( +                util, 'subp', +                return_value=("", HELP_GPART)) as mockobj: +            ret = cc_growpart.resizer_factory(mode="auto") +            self.assertIsInstance(ret, cc_growpart.ResizeGpart) + +            mockobj.assert_has_calls([ +                mock.call(['growpart', '--help'], env={'LANG': 'C'}), +                mock.call(['gpart', 'help'], env={'LANG': 'C'}, rcs=[0, 1])]) +      def test_handle_with_no_growpart_entry(self):          # if no 'growpart' entry in config, then mode=auto should be used  | 
