diff --git a/contrib/rackspace/rackspace/resources/cloud_server.py b/contrib/rackspace/rackspace/resources/cloud_server.py index dea61060e8..6504e3f584 100644 --- a/contrib/rackspace/rackspace/resources/cloud_server.py +++ b/contrib/rackspace/rackspace/resources/cloud_server.py @@ -11,17 +11,12 @@ # License for the specific language governing permissions and limitations # under the License. -import copy - from oslo_log import log as logging from heat.common import exception from heat.common.i18n import _ from heat.common.i18n import _LW -from heat.engine import attributes -from heat.engine import properties from heat.engine.resources import server -from heat.engine import support try: import pyrax # noqa @@ -35,11 +30,6 @@ LOG = logging.getLogger(__name__) class CloudServer(server.Server): """Resource for Rackspace Cloud Servers.""" - support_status = support.SupportStatus( - support.DEPRECATED, - _('Use OS::Nova::Server instead.'), - ) - # Managed Cloud automation statuses MC_STATUS_IN_PROGRESS = 'In Progress' MC_STATUS_COMPLETE = 'Complete' @@ -51,78 +41,11 @@ class CloudServer(server.Server): RC_STATUS_FAILED = 'FAILED' RC_STATUS_UNPROCESSABLE = 'UNPROCESSABLE' - # Admin Pass Properties - SAVE_ADMIN_PASS = 'save_admin_pass' - - properties_schema = copy.deepcopy(server.Server.properties_schema) - properties_schema.update( - { - SAVE_ADMIN_PASS: properties.Schema( - properties.Schema.BOOLEAN, - _('True if the system should remember the admin password; ' - 'False otherwise.'), - default=False - ), - } - ) - - NEW_ATTRIBUTES = ( - DISTRO, PRIVATE_IP_V4, ADMIN_PASS_ATTR, - ) = ( - 'distro', 'privateIPv4', 'admin_pass', - ) - - ATTRIBUTES = copy.deepcopy(server.Server.ATTRIBUTES) - ATTRIBUTES += NEW_ATTRIBUTES - - attributes_schema = copy.deepcopy(server.Server.attributes_schema) - attributes_schema.update( - { - DISTRO: attributes.Schema( - _('The Linux distribution on the server.') - ), - PRIVATE_IP_V4: attributes.Schema( - _('The private IPv4 address of the server.') - ), - ADMIN_PASS_ATTR: attributes.Schema( - _('The administrator password for the server.'), - cache_mode=attributes.Schema.CACHE_NONE - ), - } - ) - def __init__(self, name, json_snippet, stack): super(CloudServer, self).__init__(name, json_snippet, stack) - self._server = None - self._distro = None - self._image = None self._managed_cloud_started_event_sent = False self._rack_connect_started_event_sent = False - @property - def server(self): - """Return the Cloud Server object.""" - if self._server is None: - self._server = self.nova().servers.get(self.resource_id) - return self._server - - @property - def distro(self): - """Return the Linux distribution for this server.""" - image = self.properties.get(self.IMAGE) - if self._distro is None and image: - image_data = self.nova().images.get(self.image) - self._distro = image_data.metadata['os_distro'] - return self._distro - - @property - def image(self): - """Return the server's image ID.""" - image = self.properties.get(self.IMAGE) - if image and self._image is None: - self._image = self.client_plugin('glance').get_image_id(image) - return self._image - def _config_drive(self): user_data = self.properties.get(self.USER_DATA) config_drive = self.properties.get(self.CONFIG_DRIVE) @@ -219,51 +142,9 @@ class CloudServer(server.Server): return True - def _resolve_attribute(self, name): - if name == self.DISTRO: - return self.distro - if name == self.PRIVATE_IP_V4: - return self.client_plugin().get_ip(self.server, 'private', 4) - if name == self.ADMIN_PASS_ATTR: - return self.data().get(self.ADMIN_PASS_ATTR, '') - return super(CloudServer, self)._resolve_attribute(name) - - def handle_create(self): - server = super(CloudServer, self).handle_create() - - # Server will not have an adminPass attribute if Nova's - # "enable_instance_password" config option is turned off - if (self.properties.get(self.SAVE_ADMIN_PASS) and - hasattr(server, 'adminPass') and server.adminPass): - self.data_set(self.ADMIN_PASS, - server.adminPass, - redact=True) - - return server - - def handle_check(self): - server = self._check_server_status() - checks = [] - - if 'rack_connect' in self.context.roles: - rc_status = self._check_rack_connect_complete(server) - checks.append( - {'attr': 'rackconnect complete', 'expected': True, - 'current': rc_status} - ) - - if 'rax_managed' in self.context.roles: - mc_status = self._check_managed_cloud_complete(server) - checks.append( - {'attr': 'managed_cloud complete', 'expected': True, - 'current': mc_status} - ) - - self._verify_check_conditions(checks) - def resource_mapping(): - return {'Rackspace::Cloud::Server': CloudServer} + return {'OS::Nova::Server': CloudServer} def available_resource_mapping(): diff --git a/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py b/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py index 64fc55f4ee..5e98157851 100644 --- a/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py +++ b/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py @@ -44,7 +44,7 @@ wp_template = ''' }, "Resources" : { "WebServer": { - "Type": "Rackspace::Cloud::Server", + "Type": "OS::Nova::Server", "Properties": { "image" : "CentOS 5.2", "flavor" : "256 MB Server", @@ -75,7 +75,7 @@ class CloudServersTest(common.HeatTestCase): # Test environment may not have pyrax client library installed and if # pyrax is not installed resource class would not be registered. # So register resource provider class explicitly for unit testing. - resource._register_class("Rackspace::Cloud::Server", + resource._register_class("OS::Nova::Server", cloud_server.CloudServer) def _mock_get_image_id_success(self, imageId): @@ -325,156 +325,6 @@ class CloudServersTest(common.HeatTestCase): self.assertEqual('Error: Unknown Managed Cloud automation status: FOO', six.text_type(exc)) - def _prepare_server_check(self): - templ, stack = self._setup_test_stack('server_check') - server = self.fc.servers.list()[1] - res = stack['WebServer'] - res.nova = mock.Mock() - res.nova().servers.get = mock.Mock(return_value=server) - return res - - def test_check_rackconnect(self): - res = self._prepare_server_check() - res._check_rack_connect_complete = mock.Mock(return_value=True) - self.ctx.roles = ['rack_connect'] - - scheduler.TaskRunner(res.check)() - self.assertEqual((res.CHECK, res.COMPLETE), res.state) - - def test_check_rackconnect_failure(self): - self.ctx.roles = ['rack_connect'] - res = self._prepare_server_check() - res._check_active = mock.Mock(return_value=True) - res._check_rack_connect_complete = mock.Mock(return_value=False) - - exc = self.assertRaises(exception.ResourceFailure, - scheduler.TaskRunner(res.check)) - self.assertIn('False', six.text_type(exc)) - self.assertEqual((res.CHECK, res.FAILED), res.state) - - def test_check_managed_cloud(self): - res = self._prepare_server_check() - res._check_managed_cloud_complete = mock.Mock(return_value=True) - self.ctx.roles = ['rax_managed'] - - scheduler.TaskRunner(res.check)() - self.assertEqual((res.CHECK, res.COMPLETE), res.state) - - def test_check_managed_cloud_failure(self): - res = self._prepare_server_check() - res._check_managed_cloud_complete = mock.Mock(return_value=False) - self.ctx.roles = ['rax_managed'] - - exc = self.assertRaises(exception.ResourceFailure, - scheduler.TaskRunner(res.check)) - self.assertIn('False', six.text_type(exc)) - self.assertEqual((res.CHECK, res.FAILED), res.state) - - @mock.patch.object(resource.Resource, 'data_set') - def test_create_store_admin_pass_resource_data(self, - mock_data_set): - self._mock_metadata_os_distro() - return_server = self.fc.servers.list()[1] - return_server.adminPass = 'autogenerated' - stack_name = 'admin_pass_s' - (t, stack) = self._setup_test_stack(stack_name) - - t.t['Resources']['WebServer']['Properties']['save_admin_pass'] = True - resource_defns = t.resource_definitions(stack) - server = cloud_server.CloudServer('WebServer', - resource_defns['WebServer'], stack) - - self.fc.servers.create = mock.Mock(return_value=return_server) - self._mock_get_image_id_success('image_id') - scheduler.TaskRunner(server.create)() - expected_call = mock.call(server.ADMIN_PASS, - 'autogenerated', redact=True) - self.assertIn(expected_call, mock_data_set.call_args_list) - - @mock.patch.object(resource.Resource, 'data_set') - def test_create_save_admin_pass_is_false(self, mock_data_set): - self._mock_metadata_os_distro() - return_server = self.fc.servers.list()[1] - return_server.adminPass = 'autogenerated' - stack_name = 'admin_pass_s' - (t, stack) = self._setup_test_stack(stack_name) - - t.t['Resources']['WebServer']['Properties']['save_admin_pass'] = False - resource_defns = t.resource_definitions(stack) - server = cloud_server.CloudServer('WebServer', - resource_defns['WebServer'], stack) - - self.fc.servers.create = mock.Mock(return_value=return_server) - self._mock_get_image_id_success('image_id') - scheduler.TaskRunner(server.create)() - expected_call = mock.call(mock.ANY, server.ADMIN_PASS, - mock.ANY, mock.ANY) - self.assertNotIn(expected_call, mock_data_set.call_args_list) - - @mock.patch.object(resource.Resource, 'data_set') - def test_create_save_admin_pass_defaults_to_false(self, - mock_data_set): - self._mock_metadata_os_distro() - return_server = self.fc.servers.list()[1] - return_server.adminPass = 'autogenerated' - stack_name = 'admin_pass_s' - (t, stack) = self._setup_test_stack(stack_name) - - t.t['Resources']['WebServer']['Properties']['save_admin_pass'] = None - resource_defns = t.resource_definitions(stack) - server = cloud_server.CloudServer('WebServer', - resource_defns['WebServer'], stack) - - self.fc.servers.create = mock.Mock(return_value=return_server) - self._mock_get_image_id_success('image_id') - - scheduler.TaskRunner(server.create)() - expected_call = mock.call(mock.ANY, server.ADMIN_PASS, - mock.ANY, mock.ANY) - self.assertNotIn(expected_call, mock_data_set.call_args_list) - - @mock.patch.object(resource.Resource, 'data_set') - def test_create_without_adminPass_attribute(self, - mock_data_set): - self._mock_metadata_os_distro() - return_server = self.fc.servers.list()[1] - stack_name = 'admin_pass_s' - (tmpl, stack) = self._setup_test_stack(stack_name) - - resource_defns = tmpl.resource_definitions(stack) - server = cloud_server.CloudServer('WebServer', - resource_defns['WebServer'], stack) - - self.fc.servers.create = mock.Mock(return_value=return_server) - self._mock_get_image_id_success('image_id') - - scheduler.TaskRunner(server.create)() - expected_call = mock.call(mock.ANY, server.ADMIN_PASS, - mock.ANY, redact=mock.ANY) - self.assertNotIn(expected_call, mock_data_set.call_args_list) - - @mock.patch.object(resource.Resource, 'data') - def test_server_handles_server_without_password(self, mock_data_get): - mock_data_get.return_value = {} - stack_name = 'admin_pass_s' - (tmpl, stack) = self._setup_test_stack(stack_name) - - resource_defns = tmpl.resource_definitions(stack) - server = cloud_server.CloudServer('WebServer', - resource_defns['WebServer'], stack) - self.assertEqual('', server.FnGetAtt('admin_pass')) - - @mock.patch.object(resource.Resource, 'data') - def test_server_has_admin_pass_attribute_available(self, mock_data_get): - mock_data_get.return_value = {'admin_pass': 'foo'} - stack_name = 'admin_pass_s' - (tmpl, stack) = self._setup_test_stack(stack_name) - - resource_defns = tmpl.resource_definitions(stack) - server = cloud_server.CloudServer('WebServer', - resource_defns['WebServer'], stack) - self.assertEqual('foo', server.FnGetAtt('admin_pass')) - def _test_server_config_drive(self, user_data, config_drive, result): return_server = self.fc.servers.list()[1] stack_name = 'no_user_data'