From 2a5f6ae5d69be71daeab6c9cbe4dd642255ff3c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= Date: Tue, 24 Jul 2018 12:08:51 +0200 Subject: [PATCH] Updating running domains in virt.running So far virt.running does nothing if the corresponding domain is already defined. Use the new virt.update function to change the domain configuration. --- salt/states/virt.py | 48 ++++++++++++++++++++++++++++--- tests/unit/states/test_libvirt.py | 43 ++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/salt/states/virt.py b/salt/states/virt.py index 28eaa585de..b28ed6f16c 100644 --- a/salt/states/virt.py +++ b/salt/states/virt.py @@ -250,6 +250,7 @@ def running(name, install=True, pub_key=None, priv_key=None, + update=False, connection=None, username=None, password=None): @@ -312,6 +313,9 @@ def running(name, .. versionadded:: Fluorine :param seed_cmd: Salt command to execute to seed the image. (Default: ``'seed.apply'``) + .. versionadded:: Fluorine + :param update: set to ``True`` to update a defined module. (Default: ``False``) + .. versionadded:: Fluorine :param connection: libvirt connection URI, overriding defaults @@ -374,11 +378,47 @@ def running(name, try: __salt__['virt.vm_state'](name) if __salt__['virt.vm_state'](name) != 'running': + action_msg = 'started' + if update: + status = __salt__['virt.update'](name, + cpu=cpu, + mem=mem, + disk_profile=disk_profile, + disks=disks, + nic_profile=nic_profile, + interfaces=interfaces, + graphics=graphics, + live=False, + connection=connection, + username=username, + password=password) + if status['definition']: + action_msg = 'updated and started' __salt__['virt.start'](name) - ret['changes'][name] = 'Domain started' - ret['comment'] = 'Domain {0} started'.format(name) + ret['changes'][name] = 'Domain {0}'.format(action_msg) + ret['comment'] = 'Domain {0} {1}'.format(name, action_msg) else: - ret['comment'] = 'Domain {0} exists and is running'.format(name) + if update: + status = __salt__['virt.update'](name, + cpu=cpu, + mem=mem, + disk_profile=disk_profile, + disks=disks, + nic_profile=nic_profile, + interfaces=interfaces, + graphics=graphics, + connection=connection, + username=username, + password=password) + ret['changes'][name] = status + if status.get('errors', None): + ret['comment'] = 'Domain {0} updated, but some live update(s) failed'.format(name) + elif not status['definition']: + ret['comment'] = 'Domain {0} exists and is running'.format(name) + else: + ret['comment'] = 'Domain {0} updated, restart to fully apply the changes'.format(name) + else: + ret['comment'] = 'Domain {0} exists and is running'.format(name) except CommandExecutionError: if image: salt.utils.versions.warn_until( @@ -406,7 +446,7 @@ def running(name, ret['changes'][name] = 'Domain defined and started' ret['comment'] = 'Domain {0} defined and started'.format(name) except libvirt.libvirtError as err: - # Something bad happened when starting the VM, report it + # Something bad happened when starting / updating the VM, report it ret['comment'] = six.text_type(err) ret['result'] = False diff --git a/tests/unit/states/test_libvirt.py b/tests/unit/states/test_libvirt.py index 3cef512211..52648c9cec 100644 --- a/tests/unit/states/test_libvirt.py +++ b/tests/unit/states/test_libvirt.py @@ -234,7 +234,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin): 'comment': 'myvm is running'} with patch.dict(virt.__salt__, { # pylint: disable=no-member 'virt.vm_state': MagicMock(return_value='stopped'), - 'virt.start': MagicMock(return_value=0) + 'virt.start': MagicMock(return_value=0), }): ret.update({'changes': {'myvm': 'Domain started'}, 'comment': 'Domain myvm started'}) @@ -327,6 +327,47 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin): ret.update({'changes': {}, 'result': False, 'comment': 'libvirt error msg'}) self.assertDictEqual(virt.running('myvm'), ret) + # Working update case when running + with patch.dict(virt.__salt__, { # pylint: disable=no-member + 'virt.vm_state': MagicMock(return_value='running'), + 'virt.update': MagicMock(return_value={'definition': True, 'cpu': True}) + }): + ret.update({'changes': {'myvm': {'definition': True, 'cpu': True}}, + 'result': True, + 'comment': 'Domain myvm updated, restart to fully apply the changes'}) + self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret) + + # Working update case when stopped + with patch.dict(virt.__salt__, { # pylint: disable=no-member + 'virt.vm_state': MagicMock(return_value='stopped'), + 'virt.start': MagicMock(return_value=0), + 'virt.update': MagicMock(return_value={'definition': True}) + }): + ret.update({'changes': {'myvm': 'Domain updated and started'}, + 'result': True, + 'comment': 'Domain myvm updated and started'}) + self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret) + + # Failed live update case + with patch.dict(virt.__salt__, { # pylint: disable=no-member + 'virt.vm_state': MagicMock(return_value='running'), + 'virt.update': MagicMock(return_value={'definition': True, 'cpu': False, 'errors': ['some error']}) + }): + ret.update({'changes': {'myvm': {'definition': True, 'cpu': False, 'errors': ['some error']}}, + 'result': True, + 'comment': 'Domain myvm updated, but some live update(s) failed'}) + self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret) + + # Failed definition update case + with patch.dict(virt.__salt__, { # pylint: disable=no-member + 'virt.vm_state': MagicMock(return_value='running'), + 'virt.update': MagicMock(side_effect=[self.mock_libvirt.libvirtError('error message')]) + }): + ret.update({'changes': {}, + 'result': False, + 'comment': 'error message'}) + self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret) + def test_stopped(self): ''' stopped state test cases.