Versioned object - SoftwareDeployment

Prototype implementation of oslo.versionedobjects.
This patch adds SoftwareDeployment object.

Partially implements bp versioned-objects

Co-Authored-By: ShaoHe Feng <shaohe.feng@intel.com>
Co-Authored-By: He Jie Xu <hejie.xu@intel.com>

Change-Id: I3666a8b2552d8c0c9dcf05efd9c423ff5252f77d
This commit is contained in:
He Jie Xu 2015-02-03 16:29:19 +08:00 committed by Grzegorz Grasza (xek)
parent dfc3847f10
commit ce3d872e23
3 changed files with 125 additions and 19 deletions

View File

@ -23,6 +23,7 @@ from heat.common.i18n import _LI
from heat.db import api as db_api
from heat.engine import api
from heat.objects import software_config as software_config_object
from heat.objects import software_deployment as software_deployment_object
from heat.openstack.common import service
from heat.rpc import api as rpc_api
@ -54,14 +55,16 @@ class SoftwareConfigService(service.Service):
software_config_object.SoftwareConfig.delete(cnxt, config_id)
def list_software_deployments(self, cnxt, server_id):
all_sd = db_api.software_deployment_get_all(cnxt, server_id)
all_sd = software_deployment_object.SoftwareDeployment.get_all(
cnxt, server_id)
result = [api.format_software_deployment(sd) for sd in all_sd]
return result
def metadata_software_deployments(self, cnxt, server_id):
if not server_id:
raise ValueError(_('server_id must be specified'))
all_sd = db_api.software_deployment_get_all(cnxt, server_id)
all_sd = software_deployment_object.SoftwareDeployment.get_all(
cnxt, server_id)
# sort the configs by config name, to give the list of metadata a
# deterministic and controllable order.
all_sd_s = sorted(all_sd, key=lambda sd: sd.config.name)
@ -129,10 +132,12 @@ class SoftwareConfigService(service.Service):
cnxt, sd.id, jsonutils.loads(obj),
timeutils.strtime(last_modified))
return db_api.software_deployment_get(cnxt, sd.id)
return software_deployment_object.SoftwareDeployment.get_by_id(
cnxt, sd.id)
def show_software_deployment(self, cnxt, deployment_id):
sd = db_api.software_deployment_get(cnxt, deployment_id)
sd = software_deployment_object.SoftwareDeployment.get_by_id(
cnxt, deployment_id)
if sd.status == rpc_api.SOFTWARE_DEPLOYMENT_IN_PROGRESS:
c = sd.config.config
input_values = dict((i['name'], i['value']) for i in c['inputs'])
@ -146,7 +151,7 @@ class SoftwareConfigService(service.Service):
input_values, action, status,
status_reason, stack_user_project_id):
sd = db_api.software_deployment_create(cnxt, {
sd = software_deployment_object.SoftwareDeployment.create(cnxt, {
'config_id': config_id,
'server_id': server_id,
'input_values': input_values,
@ -164,7 +169,8 @@ class SoftwareConfigService(service.Service):
if not deployment_id:
raise ValueError(_('deployment_id must be specified'))
sd = db_api.software_deployment_get(cnxt, deployment_id)
sd = software_deployment_object.SoftwareDeployment.get_by_id(
cnxt, deployment_id)
status = sd.status
if not status == rpc_api.SOFTWARE_DEPLOYMENT_IN_PROGRESS:
@ -239,8 +245,8 @@ class SoftwareConfigService(service.Service):
else:
update_data['updated_at'] = timeutils.utcnow()
sd = db_api.software_deployment_update(cnxt,
deployment_id, update_data)
sd = software_deployment_object.SoftwareDeployment.update_by_id(
cnxt, deployment_id, update_data)
# only push metadata if this update resulted in the config_id
# changing, since metadata is just a list of configs
@ -250,4 +256,5 @@ class SoftwareConfigService(service.Service):
return api.format_software_deployment(sd)
def delete_software_deployment(self, cnxt, deployment_id):
db_api.software_deployment_delete(cnxt, deployment_id)
software_deployment_object.SoftwareDeployment.delete(
cnxt, deployment_id)

View File

@ -0,0 +1,90 @@
# Copyright 2014 Intel Corp.
#
# 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.
"""
SoftwareDeployment object
"""
from oslo_versionedobjects import base
from oslo_versionedobjects import fields
from heat.db import api as db_api
from heat.objects import fields as heat_fields
from heat.objects import software_config
class SoftwareDeployment(base.VersionedObject,
base.VersionedObjectDictCompat,
base.ComparableVersionedObject):
fields = {
'id': fields.StringField(nullable=False),
'config_id': fields.StringField(nullable=False),
'server_id': fields.StringField(nullable=False),
'input_values': heat_fields.JsonField(nullable=True),
'output_values': heat_fields.JsonField(nullable=True),
'tenant': fields.StringField(nullable=False),
'stack_user_project_id': fields.StringField(nullable=True),
'action': fields.StringField(nullable=True),
'status': fields.StringField(nullable=True),
'status_reason': fields.StringField(nullable=True),
'config': fields.ObjectField('SoftwareConfig'),
'created_at': fields.DateTimeField(read_only=True),
'updated_at': fields.DateTimeField(nullable=True),
}
@staticmethod
def _from_db_object(context, deployment, db_deployment):
for field in deployment.fields:
if field == 'status_reason':
deployment[field] = db_deployment['_status_reason']
elif field == 'config':
deployment[field] = (
software_config.SoftwareConfig._from_db_object(
context, software_config.SoftwareConfig(),
db_deployment['config'])
)
else:
deployment[field] = db_deployment[field]
deployment._context = context
deployment.obj_reset_changes()
return deployment
@classmethod
def create(cls, context, values):
return cls._from_db_object(
context, cls(), db_api.software_deployment_create(context, values))
@classmethod
def get_by_id(cls, context, deployment_id):
return cls._from_db_object(
context, cls(),
db_api.software_deployment_get(context, deployment_id))
@classmethod
def get_all(cls, context, server_id=None):
return [cls._from_db_object(context, cls(), db_deployment)
for db_deployment in db_api.software_deployment_get_all(
context, server_id)]
@classmethod
def update_by_id(cls, context, deployment_id, values):
return cls._from_db_object(
context, cls(),
db_api.software_deployment_update(context, deployment_id, values))
@classmethod
def delete(cls, context, deployment_id):
db_api.software_deployment_delete(context, deployment_id)

View File

@ -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 software_deployment as software_deployment_object
from heat.objects import stack as stack_object
from heat.openstack.common import threadgroup
from heat.rpc import api as rpc_api
@ -3683,7 +3684,8 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
'deployment succeeded',
self.engine.signal_software_deployment(
self.ctx, deployment_id, {}, None))
sd = db_api.software_deployment_get(self.ctx, deployment_id)
sd = software_deployment_object.SoftwareDeployment.get_by_id(
self.ctx, deployment_id)
self.assertEqual('COMPLETE', sd.status)
self.assertEqual('Outputs received', sd.status_reason)
self.assertEqual({
@ -3704,7 +3706,8 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
{'foo': 'bar', 'deploy_status_code': 0},
None)
self.assertEqual('deployment succeeded', result)
sd = db_api.software_deployment_get(self.ctx, deployment_id)
sd = software_deployment_object.SoftwareDeployment.get_by_id(
self.ctx, deployment_id)
self.assertEqual('COMPLETE', sd.status)
self.assertEqual('Outputs received', sd.status_reason)
self.assertEqual({
@ -3731,7 +3734,8 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
},
None)
self.assertEqual('deployment failed (-1)', result)
sd = db_api.software_deployment_get(self.ctx, deployment_id)
sd = software_deployment_object.SoftwareDeployment.get_by_id(
self.ctx, deployment_id)
self.assertEqual('FAILED', sd.status)
self.assertEqual(
('deploy_status_code : Deployment exited with non-zero '
@ -3761,7 +3765,8 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
},
None)
self.assertEqual('deployment failed', result)
sd = db_api.software_deployment_get(self.ctx, deployment_id)
sd = software_deployment_object.SoftwareDeployment.get_by_id(
self.ctx, deployment_id)
self.assertEqual('FAILED', sd.status)
self.assertEqual(
('foo : bar, deploy_status_code : Deployment exited with '
@ -3822,7 +3827,8 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
status='IN_PROGRESS', config_id=config['id'])
deployment_id = deployment['id']
sd = db_api.software_deployment_get(self.ctx, deployment_id)
sd = software_deployment_object.SoftwareDeployment.get_by_id(
self.ctx, deployment_id)
_refresh_software_deployment.return_value = sd
self.assertEqual(
deployment,
@ -4037,7 +4043,8 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
status='IN_PROGRESS', config_id=config['id'])
deployment_id = six.text_type(deployment['id'])
sd = db_api.software_deployment_get(self.ctx, deployment_id)
sd = software_deployment_object.SoftwareDeployment.get_by_id(
self.ctx, deployment_id)
# poll with missing object
swift_exc = swift.SwiftClientPlugin.exceptions_module
@ -4077,9 +4084,10 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
timeutils.strtime(then))
# second poll updated_at populated with first poll last-modified
db_api.software_deployment_update(
software_deployment_object.SoftwareDeployment.update_by_id(
self.ctx, deployment_id, {'updated_at': then})
sd = db_api.software_deployment_get(self.ctx, deployment_id)
sd = software_deployment_object.SoftwareDeployment.get_by_id(
self.ctx, deployment_id)
self.assertEqual(then, sd.updated_at)
self.engine.software_config._refresh_software_deployment(
self.ctx, sd, temp_url)
@ -4101,9 +4109,10 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
timeutils.strtime(now))
# four polls result in only two signals, for then and now
db_api.software_deployment_update(
software_deployment_object.SoftwareDeployment.update_by_id(
self.ctx, deployment_id, {'updated_at': now})
sd = db_api.software_deployment_get(self.ctx, deployment_id)
sd = software_deployment_object.SoftwareDeployment.get_by_id(
self.ctx, deployment_id)
self.engine.software_config._refresh_software_deployment(
self.ctx, sd, temp_url)
self.assertEqual(2, len(ssd.mock_calls))