diff --git a/heat/engine/service.py b/heat/engine/service.py index 66e381ca7b..b04af73df7 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -53,6 +53,7 @@ from heat.engine import watchrule from heat.engine import worker from heat.objects import event as event_object from heat.objects import resource as resource_objects +from heat.objects import service as service_objects from heat.objects import snapshot as snapshot_object from heat.objects import stack as stack_object from heat.openstack.common import service @@ -383,7 +384,7 @@ class EngineService(service.Service): self.manage_thread_grp.stop() ctxt = context.get_admin_context() - db_api.service_delete(ctxt, self.service_id) + service_objects.Service.delete(ctxt, self.service_id) LOG.info(_LI('Service %s is deleted'), self.service_id) # Terminate the engine process @@ -1503,7 +1504,7 @@ class EngineService(service.Service): @context.request_context def list_services(self, cnxt): result = [service_utils.format_service(srv) - for srv in db_api.service_get_all(cnxt)] + for srv in service_objects.Service.get_all(cnxt)] return result def service_manage_report(self): @@ -1511,16 +1512,17 @@ class EngineService(service.Service): if self.service_id is not None: # Service is already running - db_api.service_update( + service_objects.Service.update_by_id( cnxt, self.service_id, dict()) LOG.info(_LI('Service %s is updated'), self.service_id) else: - service_refs = db_api.service_get_all_by_args(cnxt, - self.host, - self.binary, - self.hostname) + service_refs = service_objects.Service.get_all_by_args( + cnxt, + self.host, + self.binary, + self.hostname) if len(service_refs) == 1: # Service was aborted or stopped service_ref = service_refs[0] @@ -1528,7 +1530,7 @@ class EngineService(service.Service): if service_ref['deleted_at'] is None: LOG.info(_LI('Service %s was aborted'), self.service_id) - service_ref = db_api.service_update( + service_ref = service_objects.Service.update_by_id( cnxt, service_ref['id'], dict(engine_id=self.engine_id, @@ -1538,7 +1540,7 @@ class EngineService(service.Service): LOG.info(_LI('Service %s is restarted'), self.service_id) elif len(service_refs) == 0: # Service is started now - service_ref = db_api.service_create( + service_ref = service_objects.Service.create( cnxt, dict(host=self.host, hostname=self.hostname, diff --git a/heat/objects/service.py b/heat/objects/service.py new file mode 100644 index 0000000000..097518d0a4 --- /dev/null +++ b/heat/objects/service.py @@ -0,0 +1,92 @@ +# +# 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. + + +""" +Service object +""" + +from oslo_versionedobjects import base +from oslo_versionedobjects import fields + +from heat.db import api as db_api + + +class Service(base.VersionedObject, + base.VersionedObjectDictCompat, + base.ComparableVersionedObject): + fields = { + 'id': fields.StringField(), + 'engine_id': fields.StringField(), + 'host': fields.StringField(), + 'hostname': fields.StringField(), + 'binary': fields.StringField(), + 'topic': fields.StringField(), + 'report_interval': fields.IntegerField(), + 'created_at': fields.DateTimeField(read_only=True), + 'updated_at': fields.DateTimeField(nullable=True), + 'deleted_at': fields.DateTimeField(nullable=True) + } + + @staticmethod + def _from_db_object(context, service, db_service): + for field in service.fields: + service[field] = db_service[field] + service._context = context + service.obj_reset_changes() + return service + + @classmethod + def _from_db_objects(cls, context, list_obj): + return map(lambda obj: cls._from_db_object(context, + cls(context), + obj), + list_obj) + + @classmethod + def get_by_id(cls, context, service_id): + service_db = db_api.service_get(context, service_id) + service = cls._from_db_object(context, cls(), service_db) + return service + + @classmethod + def create(cls, context, values): + return cls._from_db_object( + context, + cls(), + db_api.service_create(context, values)) + + @classmethod + def update_by_id(cls, context, service_id, values): + return cls._from_db_object( + context, + cls(), + db_api.service_update(context, service_id, values)) + + @classmethod + def delete(cls, context, service_id, soft_delete=True): + return db_api.service_delete(context, service_id, soft_delete) + + @classmethod + def get_all(cls, context): + return cls._from_db_objects(context, + db_api.service_get_all(context)) + + @classmethod + def get_all_by_args(cls, context, host, binary, hostname): + return cls._from_db_objects( + context, + db_api.service_get_all_by_args(context, + host, + binary, + hostname)) diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py index 71993afea3..50f3d2ea74 100644 --- a/heat/tests/test_engine_service.py +++ b/heat/tests/test_engine_service.py @@ -49,6 +49,7 @@ from heat.engine import template as templatem from heat.engine import watchrule from heat.engine import worker from heat.objects import resource as resource_objects +from heat.objects import service as service_objects from heat.objects import software_deployment as software_deployment_object from heat.objects import stack as stack_object from heat.openstack.common import threadgroup @@ -3136,17 +3137,17 @@ class StackServiceTest(common.HeatTestCase): self.eng._validate_new_stack, self.ctx, 'test_existing_stack', parsed_template) - @mock.patch.object(service.db_api, 'service_get_all') + @mock.patch.object(service_objects.Service, 'get_all') @mock.patch.object(service_utils, 'format_service') def test_service_get_all(self, mock_format_service, mock_get_all): mock_get_all.return_value = [mock.Mock()] mock_format_service.return_value = mock.Mock() self.assertEqual(1, len(self.eng.list_services(self.ctx))) - self.assertTrue(service.db_api.service_get_all.called) + self.assertTrue(mock_get_all.called) mock_format_service.assert_called_once_with(mock.ANY) - @mock.patch.object(service.db_api, 'service_get_all_by_args') - @mock.patch.object(service.db_api, 'service_create') + @mock.patch.object(service_objects.Service, 'get_all_by_args') + @mock.patch.object(service_objects.Service, 'create') @mock.patch.object(context, 'get_admin_context') def test_service_manage_report_start(self, mock_admin_context, @@ -3174,8 +3175,8 @@ class StackServiceTest(common.HeatTestCase): self.assertEqual(self.eng.service_id, srv['id']) - @mock.patch.object(service.db_api, 'service_get_all_by_args') - @mock.patch.object(service.db_api, 'service_update') + @mock.patch.object(service_objects.Service, 'get_all_by_args') + @mock.patch.object(service_objects.Service, 'update_by_id') @mock.patch.object(context, 'get_admin_context') def test_service_manage_report_restart( self, @@ -3202,7 +3203,7 @@ class StackServiceTest(common.HeatTestCase): self.assertEqual(self.eng.service_id, srv['id']) - @mock.patch.object(service.db_api, 'service_update') + @mock.patch.object(service_objects.Service, 'update_by_id') @mock.patch.object(context, 'get_admin_context') def test_service_manage_report_update( self, @@ -3422,7 +3423,7 @@ class StackServiceTest(common.HeatTestCase): 'stop') @mock.patch('heat.common.context.get_admin_context', return_value=mock.Mock()) - @mock.patch('heat.db.api.service_delete', + @mock.patch('heat.objects.service.Service.delete', return_value=mock.Mock()) def test_engine_service_stop_in_convergence_mode( self, @@ -3446,7 +3447,7 @@ class StackServiceTest(common.HeatTestCase): 'stop') @mock.patch('heat.common.context.get_admin_context', return_value=mock.Mock()) - @mock.patch('heat.db.api.service_delete', + @mock.patch('heat.objects.service.Service.delete', return_value=mock.Mock()) def test_engine_service_stop_in_non_convergence_mode( self,