# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import copy from unittest import mock from senlin.common import consts from senlin.common import exception as exc from senlin.objects import node as node_obj from senlin.profiles.os.nova import server from senlin.tests.unit.common import base from senlin.tests.unit.common import utils class TestServerNameChecking(base.SenlinTestCase): scenarios = [ ('none-none', dict( old_name=None, new_name=None, result=(False, 'NODE_NAME'))), ('none-new', dict( old_name=None, new_name='NEW_NAME', result=(True, 'NEW_NAME'))), ('old-none', dict( old_name='OLD_NAME', new_name=None, result=(True, 'NODE_NAME'))), ('old-new', dict( old_name='OLD_NAME', new_name='NEW_NAME', result=(True, 'NEW_NAME'))) ] def setUp(self): super(TestServerNameChecking, self).setUp() self.old_spec = { 'type': 'os.nova.server', 'version': '1.0', 'properties': { 'flavor': 'FLAVOR', } } self.new_spec = copy.deepcopy(self.old_spec) obj = mock.Mock() obj.name = 'NODE_NAME' self.obj = obj def test_check_server_name(self): if self.old_name: self.old_spec['properties']['name'] = self.old_name if self.new_name: self.new_spec['properties']['name'] = self.new_name profile = server.ServerProfile('t', self.old_spec) new_profile = server.ServerProfile('t1', self.new_spec) res = profile._check_server_name(self.obj, new_profile) self.assertEqual(self.result, res) class TestPasswordChecking(base.SenlinTestCase): scenarios = [ ('none-none', dict( old_passwd=None, new_passwd=None, result=(False, ''))), ('none-new', dict( old_passwd=None, new_passwd='NEW_PASSWD', result=(True, 'NEW_PASSWD'))), ('old-none', dict( old_passwd='OLD_PASSWD', new_passwd=None, result=(True, ''))), ('old-new', dict( old_passwd='OLD_PASSWD', new_passwd='NEW_PASSWD', result=(True, 'NEW_PASSWD'))) ] def setUp(self): super(TestPasswordChecking, self).setUp() self.old_spec = { 'type': 'os.nova.server', 'version': '1.0', 'properties': { 'flavor': 'FLAVOR', } } self.new_spec = copy.deepcopy(self.old_spec) self.obj = mock.Mock() def test_check_password(self): if self.old_passwd: self.old_spec['properties']['admin_pass'] = self.old_passwd if self.new_passwd: self.new_spec['properties']['admin_pass'] = self.new_passwd profile = server.ServerProfile('t', self.old_spec) new_profile = server.ServerProfile('t1', self.new_spec) res = profile._check_password(self.obj, new_profile) self.assertEqual(self.result, res) class TestNovaServerUpdate(base.SenlinTestCase): def setUp(self): super(TestNovaServerUpdate, self).setUp() self.context = utils.dummy_context() self.spec = { 'type': 'os.nova.server', 'version': '1.0', 'properties': { 'context': {}, 'admin_pass': 'adminpass', 'auto_disk_config': True, 'availability_zone': 'FAKE_AZ', 'block_device_mapping': [{ 'device_name': 'FAKE_NAME', 'volume_size': 1000, }], 'config_drive': False, 'flavor': 'FLAV', 'image': 'FAKE_IMAGE', 'key_name': 'FAKE_KEYNAME', "metadata": {"meta var": "meta val"}, 'name': 'FAKE_SERVER_NAME', 'networks': [{ 'port': 'FAKE_PORT', 'fixed_ip': 'FAKE_IP', 'network': 'FAKE_NET', }], 'personality': [{ 'path': '/etc/motd', 'contents': 'foo', }], 'scheduler_hints': { 'same_host': 'HOST_ID', }, 'security_groups': ['HIGH_SECURITY_GROUP'], 'user_data': 'FAKE_USER_DATA', } } self.patchobject(node_obj.Node, 'update') def test_update_name(self): profile = server.ServerProfile('t', self.spec) cc = mock.Mock() profile._computeclient = cc obj = mock.Mock(physical_id='NOVA_ID') res = profile._update_name(obj, 'NEW_NAME') self.assertIsNone(res) cc.server_update.assert_called_once_with('NOVA_ID', name='NEW_NAME') def test_update_name_nova_failure(self): profile = server.ServerProfile('t', self.spec) cc = mock.Mock() profile._computeclient = cc cc.server_update.side_effect = exc.InternalError(message='BOOM') obj = mock.Mock(physical_id='NOVA_ID') ex = self.assertRaises(exc.EResourceUpdate, profile._update_name, obj, 'NEW_NAME') self.assertEqual("Failed in updating server 'NOVA_ID': BOOM.", str(ex)) cc.server_update.assert_called_once_with('NOVA_ID', name='NEW_NAME') def test_update_password(self): profile = server.ServerProfile('t', self.spec) cc = mock.Mock() profile._computeclient = cc obj = mock.Mock(physical_id='NOVA_ID') res = profile._update_password(obj, 'NEW_PASSWORD') self.assertIsNone(res) cc.server_change_password.assert_called_once_with( 'NOVA_ID', 'NEW_PASSWORD') def test_update_password_nova_failure(self): profile = server.ServerProfile('t', self.spec) cc = mock.Mock() profile._computeclient = cc err = exc.InternalError(message='BOOM') cc.server_change_password.side_effect = err obj = mock.Mock(physical_id='NOVA_ID') ex = self.assertRaises(exc.EResourceUpdate, profile._update_password, obj, 'NEW_PASSWORD') self.assertEqual("Failed in updating server 'NOVA_ID': BOOM.", str(ex)) cc.server_change_password.assert_called_once_with( 'NOVA_ID', 'NEW_PASSWORD') def test_update_metadata(self): obj = mock.Mock(id='NODE_ID', physical_id='NOVA_ID', cluster_id='CLUSTER_ID', index=456) cc = mock.Mock() profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['metadata'] = {'new_key': 'new_value'} new_profile = server.ServerProfile('t', new_spec) res = profile._update_metadata(obj, new_profile) self.assertIsNone(res) cc.server_metadata_update.assert_called_once_with( 'NOVA_ID', { 'new_key': 'new_value', 'cluster_node_id': 'NODE_ID', 'cluster_id': 'CLUSTER_ID', 'cluster_node_index': '456', } ) def test__update_metadata_no_change(self): obj = mock.Mock(id='NODE_ID') profile = server.ServerProfile('t', self.spec) cc = mock.Mock() profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_profile = server.ServerProfile('t', new_spec) res = profile._update_metadata(obj, new_profile) self.assertIsNone(res) self.assertEqual(0, cc.server_metadata_update.call_count) def test_update_metadata_nova_failure(self): obj = mock.Mock(id='NODE_ID', physical_id='NOVA_ID', cluster_id='') err = exc.InternalError(code=500, message='Nova Error') cc = mock.Mock() cc.server_metadata_update.side_effect = err profile = server.ServerProfile('t', self.spec) profile._computeclient = cc # new profile with new metadata new_spec = copy.deepcopy(self.spec) new_spec['properties']['metadata'] = {'fooa': 'baaar'} new_profile = server.ServerProfile('t', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile._update_metadata, obj, new_profile) self.assertEqual("Failed in updating server 'NOVA_ID': " "Nova Error.", str(ex)) cc.server_metadata_update.assert_called_once_with( 'NOVA_ID', {'fooa': 'baaar', 'cluster_node_id': 'NODE_ID'} ) def test_update_flavor(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() cc.server_get.return_value = mock.Mock(status=consts.VS_ACTIVE) profile = server.ServerProfile('t', self.spec) profile.stop_timeout = 123 profile._computeclient = cc x_flavors = [mock.Mock(id='123'), mock.Mock(id='456')] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) profile._update_flavor(obj, new_profile) mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update') ]) cc.server_resize.assert_called_once_with('NOVA_ID', '456') cc.server_resize_confirm.assert_called_once_with('NOVA_ID') cc.wait_for_server.assert_has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=profile.stop_timeout), mock.call('NOVA_ID', 'VERIFY_RESIZE'), mock.call('NOVA_ID', consts.VS_SHUTOFF)]) # update flavor on server that is already stopped def test_update_flavor_stopped_server(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() cc.server_get.return_value = mock.Mock(status=consts.VS_SHUTOFF) profile = server.ServerProfile('t', self.spec) profile._computeclient = cc x_flavors = [mock.Mock(id='123'), mock.Mock(id='456')] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) profile._update_flavor(obj, new_profile) mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update') ]) cc.server_resize.assert_called_once_with('NOVA_ID', '456') cc.server_resize_confirm.assert_called_once_with('NOVA_ID') cc.wait_for_server.assert_has_calls([ mock.call('NOVA_ID', 'VERIFY_RESIZE'), mock.call('NOVA_ID', consts.VS_SHUTOFF)]) def test_update_flavor_failed_validation(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) err = exc.EResourceUpdate(type='server', id='NOVA_ID', message='BOOM') mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=err) self.assertRaises(exc.EResourceUpdate, profile._update_flavor, obj, new_profile) mock_validate.assert_called_once_with(obj, 'FLAV', 'update') def test_update_flavor_failed_validation_2(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) result = [ mock.Mock(), exc.EResourceUpdate(type='server', id='NOVA_ID', message='BOOM') ] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=result) self.assertRaises(exc.EResourceUpdate, profile._update_flavor, obj, new_profile) mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update'), ]) def test_update_flavor_same(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_profile = server.ServerProfile('t1', new_spec) x_flavors = [mock.Mock(id=123), mock.Mock(id=123)] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) res = profile._update_flavor(obj, new_profile) self.assertFalse(res) mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'FLAV', 'update'), ]) self.assertEqual(0, cc.server_resize.call_count) def test_update_flavor_server_stop_failed(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() cc.server_get.return_value = mock.Mock(status=consts.VS_ACTIVE) cc.server_stop.side_effect = [ exc.InternalError(code=500, message='Stop failed')] profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) x_flavors = [mock.Mock(id='123'), mock.Mock(id='456')] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) ex = self.assertRaises(exc.EResourceUpdate, profile._update_flavor, obj, new_profile) mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update'), ]) cc.server_resize.assert_not_called() cc.server_resize_revert.assert_not_called() cc.wait_for_server.assert_not_called() self.assertEqual("Failed in updating server 'NOVA_ID': Stop " "failed.", str(ex)) def test_update_flavor_server_paused(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() cc.server_get.return_value = mock.Mock(status=consts.VS_PAUSED) profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) x_flavors = [mock.Mock(id='123'), mock.Mock(id='456')] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) ex = self.assertRaises(exc.EResourceUpdate, profile._update_flavor, obj, new_profile) mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update'), ]) cc.server_resize.assert_not_called() cc.server_resize_revert.assert_not_called() cc.wait_for_server.assert_not_called() self.assertEqual("Failed in updating server 'NOVA_ID': Server needs " "to be ACTIVE or STOPPED in order to update flavor.", str(ex)) def test_update_flavor_resize_failed(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() cc.server_get.side_effect = [ mock.Mock(status=consts.VS_ACTIVE), mock.Mock(status='RESIZE')] cc.server_resize.side_effect = [ exc.InternalError(code=500, message='Resize failed')] profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) x_flavors = [mock.Mock(id='123'), mock.Mock(id='456')] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) ex = self.assertRaises(exc.EResourceUpdate, profile._update_flavor, obj, new_profile) mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update'), ]) cc.server_resize.assert_called_once_with('NOVA_ID', '456') cc.server_resize_revert.assert_called_once_with('NOVA_ID') cc.wait_for_server.assert_has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=600), mock.call('NOVA_ID', consts.VS_SHUTOFF), mock.call('NOVA_ID', consts.VS_ACTIVE) ]) self.assertEqual("Failed in updating server 'NOVA_ID': Resize " "failed.", str(ex)) def test_update_flavor_first_wait_for_server_failed(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() cc.server_get.return_value = mock.Mock(status=consts.VS_ACTIVE) cc.wait_for_server.side_effect = [ exc.InternalError(code=500, message='TIMEOUT') ] profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) x_flavors = [mock.Mock(id='123'), mock.Mock(id='456')] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) # do it ex = self.assertRaises(exc.EResourceUpdate, profile._update_flavor, obj, new_profile) # assertions mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update'), ]) cc.server_resize.assert_not_called() cc.wait_for_server.has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=600)]) self.assertEqual("Failed in updating server 'NOVA_ID': " "TIMEOUT.", str(ex)) def test_update_flavor_second_wait_for_server_failed(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() cc.server_get.side_effect = [ mock.Mock(status=consts.VS_ACTIVE), mock.Mock(status='RESIZE')] cc.wait_for_server.side_effect = [ None, exc.InternalError(code=500, message='TIMEOUT'), None, None ] profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) x_flavors = [mock.Mock(id='123'), mock.Mock(id='456')] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) # do it ex = self.assertRaises(exc.EResourceUpdate, profile._update_flavor, obj, new_profile) # assertions mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update'), ]) cc.server_resize.assert_called_once_with('NOVA_ID', '456') cc.wait_for_server.has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=600), mock.call('NOVA_ID', 'VERIFY_RESIZE'), mock.call('NOVA_ID', consts.VS_SHUTOFF), mock.call('NOVA_ID', consts.VS_ACTIVE), ]) cc.server_resize_revert.assert_called_once_with('NOVA_ID') self.assertEqual("Failed in updating server 'NOVA_ID': " "TIMEOUT.", str(ex)) def test_update_flavor_resize_failed_revert_failed(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() cc.server_get.side_effect = [ mock.Mock(status=consts.VS_ACTIVE), mock.Mock(status='RESIZE')] err_resize = exc.InternalError(code=500, message='Resize') cc.server_resize.side_effect = err_resize err_revert = exc.InternalError(code=500, message='Revert') cc.server_resize_revert.side_effect = err_revert profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) x_flavors = [mock.Mock(id='123'), mock.Mock(id='456')] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) # do it ex = self.assertRaises(exc.EResourceUpdate, profile._update_flavor, obj, new_profile) # assertions mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update'), ]) cc.server_resize.assert_called_once_with('NOVA_ID', '456') cc.server_resize_revert.assert_called_once_with('NOVA_ID') cc.wait_for_server.has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=600), ]) self.assertEqual("Failed in updating server 'NOVA_ID': " "Revert.", str(ex)) def test_update_flavor_confirm_failed(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() cc.server_get.return_value = mock.Mock(status=consts.VS_ACTIVE) err_confirm = exc.InternalError(code=500, message='Confirm') cc.server_resize_confirm.side_effect = err_confirm profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) x_flavors = [mock.Mock(id='123'), mock.Mock(id='456')] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) # do it ex = self.assertRaises(exc.EResourceUpdate, profile._update_flavor, obj, new_profile) # assertions mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update'), ]) cc.server_resize.assert_called_once_with('NOVA_ID', '456') cc.server_resize_confirm.assert_called_once_with('NOVA_ID') cc.wait_for_server.has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=600), mock.call('NOVA_ID', 'VERIFY_RESIZE'), ]) self.assertEqual("Failed in updating server 'NOVA_ID': Confirm.", str(ex)) def test_update_flavor_wait_confirm_failed(self): obj = mock.Mock(physical_id='NOVA_ID') cc = mock.Mock() cc.server_get.return_value = mock.Mock(status=consts.VS_SHUTOFF) err_wait = exc.InternalError(code=500, message='Wait') cc.wait_for_server.side_effect = [None, err_wait] profile = server.ServerProfile('t', self.spec) profile._computeclient = cc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'new_flavor' new_profile = server.ServerProfile('t1', new_spec) x_flavors = [mock.Mock(id='123'), mock.Mock(id='456')] mock_validate = self.patchobject(profile, '_validate_flavor', side_effect=x_flavors) # do it ex = self.assertRaises(exc.InternalError, profile._update_flavor, obj, new_profile) # assertions mock_validate.assert_has_calls([ mock.call(obj, 'FLAV', 'update'), mock.call(obj, 'new_flavor', 'update'), ]) cc.server_resize.assert_called_once_with('NOVA_ID', '456') cc.server_resize_confirm.assert_called_once_with('NOVA_ID') cc.wait_for_server.assert_has_calls([ mock.call('NOVA_ID', 'VERIFY_RESIZE'), mock.call('NOVA_ID', consts.VS_SHUTOFF) ]) self.assertEqual("Failed in updating server 'NOVA_ID': Wait.", str(ex)) def test_update_image(self): profile = server.ServerProfile('t', self.spec) profile.stop_timeout = 123 x_image = {'id': '123'} x_server = mock.Mock(image=x_image, status=consts.VS_ACTIVE) cc = mock.Mock() cc.server_get.return_value = x_server profile._computeclient = cc x_new_image = mock.Mock(id='456') x_images = [x_new_image] mock_check = self.patchobject(profile, '_validate_image', side_effect=x_images) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) profile._update_image(obj, new_profile, 'new_name', 'new_pass') mock_check.assert_has_calls([ mock.call(obj, 'new_image', reason='update'), ]) cc.server_rebuild.assert_called_once_with( 'NOVA_ID', '456', 'new_name', 'new_pass') cc.wait_for_server.assert_has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=profile.stop_timeout), mock.call('NOVA_ID', consts.VS_SHUTOFF), ]) def test_update_image_server_stopped(self): profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image, status=consts.VS_SHUTOFF) cc = mock.Mock() cc.server_get.return_value = x_server profile._computeclient = cc x_new_image = mock.Mock(id='456') x_images = [x_new_image] mock_check = self.patchobject(profile, '_validate_image', side_effect=x_images) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) profile._update_image(obj, new_profile, 'new_name', 'new_pass') mock_check.assert_has_calls([ mock.call(obj, 'new_image', reason='update'), ]) cc.server_rebuild.assert_called_once_with( 'NOVA_ID', '456', 'new_name', 'new_pass') cc.wait_for_server.assert_has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF), ]) def test_update_image_server_paused(self): profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image, status=consts.VS_PAUSED) cc = mock.Mock() cc.server_get.return_value = x_server profile._computeclient = cc x_new_image = mock.Mock(id='456') x_images = [x_new_image] mock_check = self.patchobject(profile, '_validate_image', side_effect=x_images) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile._update_image, obj, new_profile, 'new_name', '') msg = ("Failed in updating server 'NOVA_ID': Server needs to be ACTIVE" " or STOPPED in order to update image.") self.assertEqual(msg, str(ex)) mock_check.assert_has_calls([ mock.call(obj, 'new_image', reason='update'), ]) cc.server_rebuild.assert_not_called() cc.wait_for_server.assert_not_called() def test_update_image_new_image_is_none(self): profile = server.ServerProfile('t', self.spec) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) del new_spec['properties']['image'] new_profile = server.ServerProfile('t1', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile._update_image, obj, new_profile, 'new_name', '') msg = ("Failed in updating server 'NOVA_ID': Updating Nova server" " with image set to None is not supported by Nova.") self.assertEqual(msg, str(ex)) def test_update_image_new_image_invalid(self): # NOTE: The image invalid could be caused by a non-existent image or # a compute driver failure profile = server.ServerProfile('t', self.spec) # _validate_image will always throw EResourceUpdate if driver fails err = exc.EResourceUpdate(type='server', id='NOVA_ID', message='BAD') mock_check = self.patchobject(profile, '_validate_image', side_effect=err) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile._update_image, obj, new_profile, 'new_name', 'new_pass') msg = ("Failed in updating server 'NOVA_ID': BAD.") self.assertEqual(msg, str(ex)) mock_check.assert_called_once_with(obj, 'new_image', reason='update') def test_update_image_old_image_invalid(self): # NOTE: The image invalid could be caused by a non-existent image or # a compute driver failure profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image) cc = mock.Mock() cc.server_get.return_value = x_server profile._computeclient = cc # _validate_image will always throw EResourceUpdate if driver fails results = [ exc.EResourceUpdate(type='server', id='NOVA_ID', message='BAD') ] mock_check = self.patchobject(profile, '_validate_image', side_effect=results) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile._update_image, obj, new_profile, 'new_name', 'new_pass') msg = ("Failed in updating server 'NOVA_ID': BAD.") self.assertEqual(msg, str(ex)) mock_check.assert_has_calls([ mock.call(obj, 'new_image', reason='update'), ]) def test_update_image_old_image_is_none_but_succeeded(self): old_spec = copy.deepcopy(self.spec) del old_spec['properties']['image'] profile = server.ServerProfile('t', old_spec) cc = mock.Mock() profile._computeclient = cc x_server = mock.Mock(image={'id': '123'}, status=consts.VS_ACTIVE) cc.server_get.return_value = x_server # this is the new one x_image = mock.Mock(id='456') mock_check = self.patchobject(profile, '_validate_image', return_value=x_image) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) res = profile._update_image(obj, new_profile, 'new_name', 'new_pass') self.assertTrue(res) mock_check.assert_called_once_with(obj, 'new_image', reason='update') cc.server_get.assert_called_once_with('NOVA_ID') cc.server_rebuild.assert_called_once_with( 'NOVA_ID', '456', 'new_name', 'new_pass') cc.wait_for_server.assert_has_calls([ # first wait is from active to shutoff and has custom timeout mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=600), mock.call('NOVA_ID', consts.VS_SHUTOFF), ]) def test_update_image_old_image_is_none_but_failed(self): old_spec = copy.deepcopy(self.spec) del old_spec['properties']['image'] profile = server.ServerProfile('t', old_spec) cc = mock.Mock() profile._computeclient = cc # this is about the new one x_image = mock.Mock(id='456') mock_check = self.patchobject(profile, '_validate_image', return_value=x_image) cc.server_get.side_effect = exc.InternalError(message='DRIVER') obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile._update_image, obj, new_profile, 'new_name', 'new_pass') self.assertEqual("Failed in updating server 'NOVA_ID': DRIVER.", str(ex)) mock_check.assert_called_once_with(obj, 'new_image', reason='update') cc.server_get.assert_called_once_with('NOVA_ID') def test_update_image_updating_to_same_image(self): profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image) cc = mock.Mock() cc.server_get.return_value = x_server profile._computeclient = cc x_new_image = mock.Mock(id='123') x_images = [x_new_image] mock_check = self.patchobject(profile, '_validate_image', side_effect=x_images) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) res = profile._update_image(obj, new_profile, 'new_name', 'new_pass') self.assertFalse(res) mock_check.assert_has_calls([ mock.call(obj, 'new_image', reason='update'), ]) self.assertEqual(0, cc.server_rebuild.call_count) self.assertEqual(0, cc.wait_for_server.call_count) def test_update_image_failed_stopping(self): profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image) cc = mock.Mock() cc.server_get.return_value = x_server cc.server_stop.side_effect = exc.InternalError(message='FAILED') profile._computeclient = cc x_new_image = mock.Mock(id='456') x_images = [x_new_image] mock_check = self.patchobject(profile, '_validate_image', side_effect=x_images) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile._update_image, obj, new_profile, 'new_name', 'new_pass') self.assertEqual("Failed in updating server 'NOVA_ID': Server needs to" " be ACTIVE or STOPPED in order to update image.", str(ex)) mock_check.assert_has_calls([ mock.call(obj, 'new_image', reason='update'), ]) cc.server_rebuild.assert_not_called() cc.wait_for_server.assert_not_called() def test_update_image_failed_rebuilding(self): profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image, status=consts.VS_ACTIVE) cc = mock.Mock() cc.server_get.return_value = x_server cc.server_rebuild.side_effect = exc.InternalError(message='FAILED') profile._computeclient = cc x_new_image = mock.Mock(id='456') x_images = [x_new_image] mock_check = self.patchobject(profile, '_validate_image', side_effect=x_images) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile._update_image, obj, new_profile, 'new_name', 'new_pass') self.assertEqual("Failed in updating server 'NOVA_ID': FAILED.", str(ex)) mock_check.assert_has_calls([ mock.call(obj, 'new_image', reason='update'), ]) cc.server_rebuild.assert_called_once_with( 'NOVA_ID', '456', 'new_name', 'new_pass') cc.wait_for_server.assert_has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=600), ]) def test_update_image_failed_first_waiting(self): profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image, status=consts.VS_ACTIVE) cc = mock.Mock() cc.server_get.return_value = x_server cc.wait_for_server.side_effect = exc.InternalError(message='TIMEOUT') profile._computeclient = cc x_new_image = mock.Mock(id='456') x_images = [x_new_image] mock_check = self.patchobject(profile, '_validate_image', side_effect=x_images) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile._update_image, obj, new_profile, 'new_name', 'new_pass') self.assertEqual("Failed in updating server 'NOVA_ID': TIMEOUT.", str(ex)) mock_check.assert_has_calls([ mock.call(obj, 'new_image', reason='update'), ]) cc.server_rebuild.assert_not_called() cc.wait_for_server.assert_called_once_with( 'NOVA_ID', consts.VS_SHUTOFF, timeout=600) def test_update_image_failed_second_waiting(self): profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image, status=consts.VS_ACTIVE) cc = mock.Mock() cc.server_get.return_value = x_server cc.wait_for_server.side_effect = [ None, exc.InternalError(message='TIMEOUT')] profile._computeclient = cc x_new_image = mock.Mock(id='456') x_images = [x_new_image] mock_check = self.patchobject(profile, '_validate_image', side_effect=x_images) obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'new_image' new_profile = server.ServerProfile('t1', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile._update_image, obj, new_profile, 'new_name', 'new_pass') self.assertEqual("Failed in updating server 'NOVA_ID': TIMEOUT.", str(ex)) mock_check.assert_has_calls([ mock.call(obj, 'new_image', reason='update'), ]) cc.server_rebuild.assert_called_once_with( 'NOVA_ID', '456', 'new_name', 'new_pass') cc.wait_for_server.assert_has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=600), mock.call('NOVA_ID', consts.VS_SHUTOFF)]) def test_create_interfaces(self): cc = mock.Mock() server_obj = mock.Mock() cc.server_get.return_value = server_obj profile = server.ServerProfile('t', self.spec) profile._computeclient = cc validation_results = [ {'network': 'net1_id', 'fixed_ip': 'ip2'}, {'network': 'net2_id'}, {'port': 'port4'} ] mock_validate = self.patchobject(profile, '_validate_network', side_effect=validation_results) ports_results = [ (mock.Mock( id='port1_id', network_id='net1_id', fixed_ips=[{'ip_address': 'ip2'}], security_group_ids=[]), None), (mock.Mock( id='port2_id', network_id='net2_id', fixed_ips=[{'ip_address': 'ip3'}], security_group_ids=[]), None), (mock.Mock( id='port4_id', network_id='net3_id', fixed_ips=[{'ip_address': 'ip4'}], security_group_ids=[]), None) ] mock_get_port = self.patchobject(profile, '_get_port', side_effect=ports_results) networks = [ {'network': 'net1', 'port': None, 'fixed_ip': 'ip2'}, {'network': 'net2', 'port': None, 'fixed_ip': None}, {'network': None, 'port': 'port4', 'fixed_ip': None} ] obj = mock.Mock(physical_id='NOVA_ID', data={}) res = profile._update_network_add_port(obj, networks) self.assertIsNone(res) cc.server_get.assert_called_with('NOVA_ID') validation_calls = [ mock.call(obj, {'network': 'net1', 'port': None, 'fixed_ip': 'ip2'}, 'update'), mock.call(obj, {'network': 'net2', 'port': None, 'fixed_ip': None}, 'update'), mock.call(obj, {'network': None, 'port': 'port4', 'fixed_ip': None}, 'update') ] mock_validate.assert_has_calls(validation_calls) mock_get_port.assert_called_with(obj, {'port': 'port4'}) create_calls = [ mock.call(server_obj, port_id='port1_id'), mock.call(server_obj, port_id='port2_id'), mock.call(server_obj, port_id='port4_id'), ] cc.server_interface_create.assert_has_calls(create_calls) def test_create_interfaces_failed_getting_server(self): cc = mock.Mock() cc.server_get.side_effect = exc.InternalError(message='Not valid') profile = server.ServerProfile('t', self.spec) profile._computeclient = cc self.patchobject(profile, '_create_ports_from_properties') obj = mock.Mock(physical_id='NOVA_ID') networks = [{'foo': 'bar'}] # not used ex = self.assertRaises(exc.EResourceUpdate, profile._update_network_add_port, obj, networks) self.assertEqual("Failed in updating server 'NOVA_ID': Not valid.", str(ex)) cc.server_get.assert_called_once_with('NOVA_ID') self.assertEqual(0, profile._create_ports_from_properties.call_count) def test_create_interfaces_failed_validation(self): cc = mock.Mock() server_obj = mock.Mock() cc.server_get.return_value = server_obj profile = server.ServerProfile('t', self.spec) profile._computeclient = cc err = exc.EResourceUpdate(type='server', id='NOVA_ID', message='Driver error') mock_validate = self.patchobject(profile, '_validate_network', side_effect=err) networks = [{'network': 'net1', 'port': None, 'fixed_ip': 'ip2'}] obj = mock.Mock(physical_id='NOVA_ID') ex = self.assertRaises(exc.EResourceUpdate, profile._update_network_add_port, obj, networks) self.assertEqual("Failed in updating server 'NOVA_ID': Driver error.", str(ex)) cc.server_get.assert_called_once_with('NOVA_ID') mock_validate.assert_called_once_with(obj, networks[0], 'update') self.assertEqual(0, cc.server_interface_create.call_count) def test_delete_interfaces(self): cc = mock.Mock() cc.server_get.return_value = mock.Mock(status=consts.VS_ACTIVE) nc = mock.Mock() net1 = mock.Mock(id='net1') nc.network_get.return_value = net1 nc.port_find.return_value = mock.Mock(id='port3', status='DOWN') profile = server.ServerProfile('t', self.spec) profile.stop_timeout = 232 profile._computeclient = cc profile._networkclient = nc obj = mock.Mock(physical_id='NOVA_ID', data={'internal_ports': [ {'id': 'port1', 'network_id': 'net1', 'remove': True, 'fixed_ips': [{'ip_address': 'ip1'}]}, {'id': 'port2', 'network_id': 'net1', 'remove': True, 'fixed_ips': [{'ip_address': 'ip-random2'}]}, {'id': 'port3', 'network_id': 'net1', 'remove': True, 'fixed_ips': [{'ip_address': 'ip3'}]}]}) networks = [ {'network': 'net1', 'port': None, 'fixed_ip': 'ip1'}, {'network': 'net1', 'port': None, 'fixed_ip': None}, {'network': None, 'port': 'port3', 'fixed_ip': None} ] res = profile._update_network_remove_port(obj, networks) self.assertIsNone(res) nc.network_get.assert_has_calls([ mock.call('net1'), mock.call('net1') ]) cc.wait_for_server.assert_has_calls([ mock.call('NOVA_ID', consts.VS_SHUTOFF, timeout=profile.stop_timeout), ]) cc.server_interface_delete.assert_has_calls([ mock.call('port1', 'NOVA_ID'), mock.call('port2', 'NOVA_ID'), mock.call('port3', 'NOVA_ID'), ]) nc.port_delete.assert_has_calls([ mock.call('port1', ignore_missing=True), mock.call('port2', ignore_missing=True), mock.call('port3', ignore_missing=True), ]) def test_delete_interfaces_failed_delete(self): cc = mock.Mock() profile = server.ServerProfile('t', self.spec) profile._computeclient = cc profile._networkclient = mock.Mock() candidate_ports = [ [{'id': 'port1', 'network_id': 'net1', 'fixed_ips': [{'ip_address': 'ip1'}]}], ] self.patchobject(profile, '_find_port_by_net_spec', side_effect=candidate_ports) err = exc.InternalError(message='BANG') cc.server_interface_delete.side_effect = err internal_ports = [ {'id': 'port1', 'remove': True} ] obj = mock.Mock(physical_id='NOVA_ID', data={'internal_ports': internal_ports}) networks = [ {'network': 'net1', 'port': None, 'fixed_ip': 'ip1'}, ] ex = self.assertRaises(exc.EResourceUpdate, profile._update_network_remove_port, obj, networks) self.assertEqual("Failed in updating server 'NOVA_ID': BANG.", str(ex)) cc.server_interface_delete.assert_called_once_with('port1', 'NOVA_ID') def test_update_port(self): cc = mock.Mock() cc.server_get.return_value = mock.Mock(status=consts.VS_ACTIVE) nc = mock.Mock() net1 = mock.Mock(id='net1') nc.network_get.return_value = net1 nc.port_find.return_value = mock.Mock(id='port3', status='DOWN') profile = server.ServerProfile('t', self.spec) profile.stop_timeout = 232 profile._computeclient = cc profile._networkclient = nc validation_results = [ {'network': 'net1_id', 'fixed_ip': 'ip1', 'security_groups': ['sg1_id']}, {'network': 'net1_id', 'fixed_ip': 'ip1', 'security_groups': ['sg1_id', 'sg2_id']}, {'network': 'net1_id', 'fixed_ip': 'ip1'} ] mock_validate = self.patchobject(profile, '_validate_network', side_effect=validation_results) candidate_ports = [ [{'id': 'port1_id', 'network_id': 'net1_id', 'fixed_ips': [{'ip_address': 'ip1'}]}], [{'id': 'port2_id', 'network_id': 'net1_id', 'fixed_ips': [{'ip_address': 'ip1'}]}], [{'id': 'port3_id', 'network_id': 'net1_id', 'fixed_ips': [{'ip_address': 'ip1'}]}] ] self.patchobject(profile, '_find_port_by_net_spec', side_effect=candidate_ports) obj = mock.Mock(physical_id='NOVA_ID', data={'internal_ports': [ {'id': 'port1', 'network_id': 'net1', 'fixed_ips': [{'ip_address': 'ip1'}]}, {'id': 'port2', 'network_id': 'net1', 'remove': True, 'fixed_ips': [{'ip_address': 'ip-random2'}], 'security_groups': ['default']}, {'id': 'port3', 'network_id': 'net1', 'remove': True, 'fixed_ips': [{'ip_address': 'ip3'}], 'security_groups': ['default']} ]}) networks = [ {'network': 'net1', 'port': None, 'fixed_ip': 'ip1', 'security_groups': ['default'], 'floating_network': None, 'floating_ip': None}, {'network': 'net1', 'port': None, 'fixed_ip': 'ip1', 'security_groups': ['default', 'blah'], 'floating_network': None, 'floating_ip': None}, {'network': 'net1', 'port': None, 'fixed_ip': 'ip1', 'security_groups': None, 'floating_network': None, 'floating_ip': None}, ] res = profile._update_network_update_port(obj, networks) self.assertIsNone(res) validation_calls = [ mock.call(obj, {'network': 'net1', 'port': None, 'fixed_ip': 'ip1', 'security_groups': ['default'], 'floating_network': None, 'floating_ip': None}, 'update'), mock.call(obj, {'network': 'net1', 'port': None, 'fixed_ip': 'ip1', 'security_groups': ['default', 'blah'], 'floating_network': None, 'floating_ip': None}, 'update'), mock.call(obj, {'network': 'net1', 'port': None, 'fixed_ip': 'ip1', 'security_groups': None, 'floating_network': None, 'floating_ip': None}, 'update') ] mock_validate.assert_has_calls(validation_calls) update_calls = [ mock.call('port1_id', security_groups=['sg1_id']), mock.call('port2_id', security_groups=['sg1_id', 'sg2_id']), mock.call('port3_id', security_groups=[]), ] nc.port_update.assert_has_calls(update_calls) @mock.patch.object(server.ServerProfile, '_update_network_update_port') @mock.patch.object(server.ServerProfile, '_update_network_remove_port') @mock.patch.object(server.ServerProfile, '_update_network_add_port') def test_update_network(self, mock_create, mock_delete, mock_update): obj = mock.Mock(physical_id='FAKE_ID') old_spec = copy.deepcopy(self.spec) old_spec['properties']['networks'] = [ {'network': 'net1', 'fixed_ip': 'ip1'}, {'network': 'net1'}, {'port': 'port3'}, # sg only changes: {'network': 'net3', 'fixed_ip': 'ip1'}, {'network': 'net4', 'fixed_ip': 'ip1', 'security_groups': ['blah']}, {'port': 'port5', 'security_groups': ['default']}, ] profile = server.ServerProfile('t', old_spec) new_spec = copy.deepcopy(self.spec) new_spec['properties']['networks'] = [ {'network': 'net1', 'fixed_ip': 'ip2'}, {'network': 'net2'}, {'port': 'port4'}, # sg only changes: {'network': 'net3', 'fixed_ip': 'ip1', 'security_groups': ['default']}, {'network': 'net4', 'fixed_ip': 'ip1', 'security_groups': ['default']}, {'port': 'port5', 'security_groups': ['default', 'blah']}, ] new_profile = server.ServerProfile('t1', new_spec) networks_created, networks_deleted = profile._update_network( obj, new_profile) self.assertTrue(networks_created) self.assertTrue(networks_deleted) networks_create = [ {'floating_network': None, 'network': 'net1', 'fixed_ip': 'ip2', 'floating_ip': None, 'port': None, 'vnic_type': None, 'security_groups': None}, {'floating_network': None, 'network': 'net2', 'fixed_ip': None, 'floating_ip': None, 'port': None, 'vnic_type': None, 'security_groups': None}, {'floating_network': None, 'network': None, 'fixed_ip': None, 'floating_ip': None, 'port': 'port4', 'vnic_type': None, 'security_groups': None} ] mock_create.assert_called_once_with(obj, networks_create) networks_delete = [ {'floating_network': None, 'network': 'net1', 'fixed_ip': 'ip1', 'floating_ip': None, 'port': None, 'vnic_type': None, 'security_groups': None}, {'floating_network': None, 'network': 'net1', 'fixed_ip': None, 'floating_ip': None, 'port': None, 'vnic_type': None, 'security_groups': None}, {'floating_network': None, 'network': None, 'fixed_ip': None, 'floating_ip': None, 'port': 'port3', 'vnic_type': None, 'security_groups': None} ] mock_delete.assert_called_once_with(obj, networks_delete) networks_update = [ {'network': 'net3', 'port': None, 'fixed_ip': 'ip1', 'security_groups': ['default'], 'floating_network': None, 'vnic_type': None, 'floating_ip': None}, {'network': 'net4', 'port': None, 'fixed_ip': 'ip1', 'security_groups': ['default'], 'floating_network': None, 'vnic_type': None, 'floating_ip': None}, {'network': None, 'port': 'port5', 'fixed_ip': None, 'security_groups': ['default', 'blah'], 'floating_network': None, 'vnic_type': None, 'floating_ip': None} ] mock_update.assert_called_once_with(obj, networks_update) @mock.patch.object(server.ServerProfile, '_update_password') @mock.patch.object(server.ServerProfile, '_check_password') @mock.patch.object(server.ServerProfile, '_update_name') @mock.patch.object(server.ServerProfile, '_check_server_name') @mock.patch.object(server.ServerProfile, '_update_flavor') @mock.patch.object(server.ServerProfile, '_update_metadata') @mock.patch.object(server.ServerProfile, '_update_image') @mock.patch.object(server.ServerProfile, '_update_network') def test_do_update_name_succeeded(self, mock_update_network, mock_update_image, mock_update_metadata, mock_update_flavor, mock_check_name, mock_update_name, mock_check_password, mock_update_password): mock_check_name.return_value = True, 'NEW_NAME' mock_check_password.return_value = True, 'NEW_PASSWORD' mock_update_image.return_value = False mock_update_flavor.return_value = False mock_update_network.return_value = False, False obj = mock.Mock(physical_id='FAKE_ID') profile = server.ServerProfile('t', self.spec) profile._computeclient = mock.Mock() profile._computeclient.server_get = mock.Mock() profile._computeclient.server_start = mock.Mock() new_profile = server.ServerProfile('t', self.spec) res = profile.do_update(obj, new_profile) self.assertTrue(res) mock_check_name.assert_called_once_with(obj, new_profile) mock_update_metadata.assert_called_once_with(obj, new_profile) mock_update_image.assert_called_once_with( obj, new_profile, 'NEW_NAME', 'NEW_PASSWORD') mock_update_name.assert_called_once_with(obj, 'NEW_NAME') mock_update_password.assert_called_once_with(obj, 'NEW_PASSWORD') mock_update_flavor.assert_called_once_with(obj, new_profile) mock_update_network.assert_called_once_with(obj, new_profile) @mock.patch.object(server.ServerProfile, '_update_password') @mock.patch.object(server.ServerProfile, '_check_password') @mock.patch.object(server.ServerProfile, '_update_name') @mock.patch.object(server.ServerProfile, '_check_server_name') @mock.patch.object(server.ServerProfile, '_update_flavor') @mock.patch.object(server.ServerProfile, '_update_metadata') @mock.patch.object(server.ServerProfile, '_update_image') @mock.patch.object(server.ServerProfile, '_update_network') def test_do_update_name_no_change(self, mock_update_network, mock_update_image, mock_update_metadata, mock_update_flavor, mock_check_name, mock_update_name, mock_check_password, mock_update_password): mock_check_name.return_value = False, 'NEW_NAME' mock_check_password.return_value = False, 'OLD_PASS' mock_update_network.return_value = False, False obj = mock.Mock(physical_id='NOVA_ID') profile = server.ServerProfile('t', self.spec) profile._computeclient = mock.Mock() new_profile = server.ServerProfile('t', self.spec) res = profile.do_update(obj, new_profile) self.assertTrue(res) mock_check_name.assert_called_once_with(obj, new_profile) mock_check_password.assert_called_once_with(obj, new_profile) mock_update_image.assert_called_once_with( obj, new_profile, 'NEW_NAME', 'OLD_PASS') self.assertEqual(0, mock_update_name.call_count) self.assertEqual(0, mock_update_password.call_count) mock_update_flavor.assert_called_once_with(obj, new_profile) mock_update_network.assert_called_once_with(obj, new_profile) mock_update_metadata.assert_called_once_with(obj, new_profile) @mock.patch.object(server.ServerProfile, '_update_password') @mock.patch.object(server.ServerProfile, '_check_password') @mock.patch.object(server.ServerProfile, '_update_name') @mock.patch.object(server.ServerProfile, '_check_server_name') @mock.patch.object(server.ServerProfile, '_update_flavor') @mock.patch.object(server.ServerProfile, '_update_metadata') @mock.patch.object(server.ServerProfile, '_update_image') @mock.patch.object(server.ServerProfile, '_update_network') def test_do_update_name_failed(self, mock_update_network, mock_update_image, mock_update_metadata, mock_update_flavor, mock_check_name, mock_update_name, mock_check_password, mock_update_password): mock_check_name.return_value = True, 'NEW_NAME' mock_check_password.return_value = False, 'OLD_PASS' mock_update_image.return_value = False err = exc.EResourceUpdate(type='server', id='NOVA_ID', message='BANG') mock_update_name.side_effect = err obj = mock.Mock(physical_id='NOVA_ID') profile = server.ServerProfile('t', self.spec) profile._computeclient = mock.Mock() new_profile = server.ServerProfile('t', self.spec) ex = self.assertRaises(exc.EResourceUpdate, profile.do_update, obj, new_profile) self.assertEqual("Failed in updating server 'NOVA_ID': BANG.", str(ex)) mock_check_name.assert_called_once_with(obj, new_profile) mock_check_password.assert_called_once_with(obj, new_profile) mock_update_image.assert_called_once_with( obj, new_profile, 'NEW_NAME', 'OLD_PASS') mock_update_name.assert_called_once_with(obj, 'NEW_NAME') self.assertEqual(0, mock_update_password.call_count) self.assertEqual(0, mock_update_flavor.call_count) self.assertEqual(0, mock_update_metadata.call_count) @mock.patch.object(server.ServerProfile, '_update_password') @mock.patch.object(server.ServerProfile, '_update_name') @mock.patch.object(server.ServerProfile, '_check_password') @mock.patch.object(server.ServerProfile, '_check_server_name') @mock.patch.object(server.ServerProfile, '_update_flavor') @mock.patch.object(server.ServerProfile, '_update_image') def test_do_update_image_succeeded(self, mock_update_image, mock_update_flavor, mock_check_name, mock_check_password, mock_update_name, mock_update_password): mock_check_name.return_value = False, 'OLD_NAME' mock_check_password.return_value = False, 'OLD_PASS' mock_update_image.return_value = True obj = mock.Mock() obj.physical_id = 'FAKE_ID' profile = server.ServerProfile('t', self.spec) profile._computeclient = mock.Mock() profile._computeclient.server_get = mock.Mock() profile._computeclient.server_get.return_value = mock.Mock( status=consts.VS_SHUTOFF) new_spec = copy.deepcopy(self.spec) new_spec['properties']['image'] = 'FAKE_IMAGE_NEW' new_profile = server.ServerProfile('t', new_spec) res = profile.do_update(obj, new_profile) self.assertTrue(res) mock_update_image.assert_called_with( obj, new_profile, 'OLD_NAME', 'OLD_PASS') self.assertEqual(0, mock_update_name.call_count) self.assertEqual(0, mock_update_password.call_count) profile._computeclient.server_get.assert_called_once_with( obj.physical_id) profile._computeclient.server_start.assert_called_once_with( obj.physical_id) @mock.patch.object(server.ServerProfile, '_update_flavor') @mock.patch.object(server.ServerProfile, '_update_name') @mock.patch.object(server.ServerProfile, '_update_metadata') @mock.patch.object(server.ServerProfile, '_update_image') @mock.patch.object(server.ServerProfile, '_check_password') @mock.patch.object(server.ServerProfile, '_check_server_name') def test_do_update_image_failed(self, mock_check_name, mock_check_password, mock_update_image, mock_update_meta, mock_update_name, mock_update_flavor): mock_check_name.return_value = False, 'OLD_NAME' mock_check_password.return_value = False, 'OLD_PASS' # _update_image always throw EResourceUpdate ex = exc.EResourceUpdate(type='server', id='NOVA_ID', message='Image Not Found') mock_update_image.side_effect = ex obj = mock.Mock(physical_id='NOVA_ID') profile = server.ServerProfile('t', self.spec) profile._computeclient = mock.Mock() # don't need to invent a new spec new_spec = copy.deepcopy(self.spec) new_profile = server.ServerProfile('t', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile.do_update, obj, new_profile) mock_update_image.assert_called_with( obj, new_profile, 'OLD_NAME', 'OLD_PASS') self.assertEqual("Failed in updating server 'NOVA_ID': " "Image Not Found.", str(ex)) @mock.patch.object(server.ServerProfile, '_update_flavor') def test_do_update_update_flavor_succeeded(self, mock_update_flavor): mock_update_flavor.return_value = True obj = mock.Mock(physical_id='FAKE_ID') profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image, status=consts.VS_SHUTOFF) cc = mock.Mock() cc.server_get.return_value = x_server gc = mock.Mock() profile._computeclient = cc profile._glanceclient = gc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'FAKE_FLAVOR_NEW' new_profile = server.ServerProfile('t', new_spec) res = profile.do_update(obj, new_profile) self.assertTrue(res) mock_update_flavor.assert_called_with(obj, new_profile) gc.image_find.assert_called_with('FAKE_IMAGE', False) cc.server_start.assert_called_once_with(obj.physical_id) @mock.patch.object(server.ServerProfile, '_update_flavor') def test_do_update_update_flavor_failed(self, mock_update_flavor): ex = exc.EResourceUpdate(type='server', id='NOVA_ID', message='Flavor Not Found') mock_update_flavor.side_effect = ex obj = mock.Mock(physical_id='NOVA_ID') profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image, status=consts.VS_ACTIVE) cc = mock.Mock() cc.server_get.return_value = x_server gc = mock.Mock() profile._computeclient = cc profile._glanceclient = gc new_spec = copy.deepcopy(self.spec) new_spec['properties']['flavor'] = 'FAKE_FLAVOR_NEW' new_profile = server.ServerProfile('t', new_spec) ex = self.assertRaises(exc.EResourceUpdate, profile.do_update, obj, new_profile) mock_update_flavor.assert_called_with(obj, new_profile) self.assertEqual("Failed in updating server 'NOVA_ID': " "Flavor Not Found.", str(ex)) gc.image_find.assert_called_with('FAKE_IMAGE', False) @mock.patch.object(server.ServerProfile, '_update_flavor') @mock.patch.object(server.ServerProfile, '_update_network') def test_do_update_update_network_succeeded( self, mock_update_network, mock_update_flavor): mock_update_network.return_value = True, True profile = server.ServerProfile('t', self.spec) x_image = {'id': '123'} x_server = mock.Mock(image=x_image, status=consts.VS_SHUTOFF) cc = mock.Mock() gc = mock.Mock() cc.server_get.return_value = x_server profile._computeclient = cc profile._glanceclient = gc obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_spec['properties']['networks'] = [ {'network': 'new_net', 'port': 'new_port', 'fixed_ip': 'new-ip'} ] new_profile = server.ServerProfile('t', new_spec) params = {'cluster.stop_timeout_before_update': 134} res = profile.do_update(obj, new_profile=new_profile, **params) self.assertTrue(res) gc.image_find.assert_called_with('FAKE_IMAGE', False) mock_update_network.assert_called_with(obj, new_profile) cc.server_start.assert_called_once_with(obj.physical_id) self.assertEqual(profile.stop_timeout, params['cluster.stop_timeout_before_update']) @mock.patch.object(server.ServerProfile, '_update_password') @mock.patch.object(server.ServerProfile, '_check_password') @mock.patch.object(server.ServerProfile, '_update_name') @mock.patch.object(server.ServerProfile, '_check_server_name') @mock.patch.object(server.ServerProfile, '_update_flavor') @mock.patch.object(server.ServerProfile, '_update_metadata') @mock.patch.object(server.ServerProfile, '_update_image') @mock.patch.object(server.ServerProfile, '_update_network') def test_do_update_update_network_failed( self, mock_update_network, mock_update_image, mock_update_metadata, mock_update_flavor, mock_check_name, mock_update_name, mock_check_password, mock_update_password): mock_check_name.return_value = True, 'NEW_NAME' mock_check_password.return_value = True, 'NEW_PASSWORD' mock_update_image.return_value = True err = exc.EResourceUpdate(type='server', id='NOVA_ID', message='BOOM') mock_update_network.side_effect = err profile = server.ServerProfile('t', self.spec) profile._computeclient = mock.Mock() new_network = { 'port': 'FAKE_PORT_NEW', 'fixed_ip': 'FAKE_IP_NEW', 'network': 'FAKE_NET_NEW', } new_spec = copy.deepcopy(self.spec) new_spec['properties']['networks'] = [new_network] new_profile = server.ServerProfile('t', new_spec) obj = mock.Mock(physical_id='NOVA_ID') ex = self.assertRaises(exc.EResourceUpdate, profile.do_update, obj, new_profile) self.assertEqual("Failed in updating server 'NOVA_ID': BOOM.", str(ex)) mock_check_name.assert_called_once_with(obj, new_profile) mock_check_password.assert_called_once_with(obj, new_profile) mock_update_image.assert_called_once_with( obj, new_profile, 'NEW_NAME', 'NEW_PASSWORD') self.assertEqual(0, mock_update_name.call_count) self.assertEqual(0, mock_update_password.call_count) mock_update_flavor.assert_called_once_with(obj, new_profile) mock_update_network.assert_called_with(obj, new_profile) self.assertEqual(0, mock_update_metadata.call_count) def test_do_update_without_profile(self): profile = server.ServerProfile('t', self.spec) obj = mock.Mock() obj.physical_id = 'FAKE_ID' new_profile = None res = profile.do_update(obj, new_profile) self.assertFalse(res) def test_do_update_no_physical_id(self): profile = server.ServerProfile('t', self.spec) profile._computeclient = mock.Mock() node_obj = mock.Mock(physical_id=None) new_profile = mock.Mock() # Test path where server doesn't exist res = profile.do_update(node_obj, new_profile) self.assertFalse(res) def test_do_update_invalid_stop_timeout(self): profile = server.ServerProfile('t', self.spec) profile._computeclient = mock.Mock() node_obj = mock.Mock(physical_id='NOVA_ID') new_spec = copy.deepcopy(self.spec) new_profile = server.ServerProfile('t', new_spec) params = {'cluster.stop_timeout_before_update': '123'} ex = self.assertRaises(exc.EResourceUpdate, profile.do_update, node_obj, new_profile, **params) self.assertEqual("Failed in updating server 'NOVA_ID': " "cluster.stop_timeout_before_update value must be of " "type int.", str(ex))