Add checkpoint_records table of db

Also include the definition of table and the operation interface.

Partial Implements: blueprint checkpoint-scheduled-clean
Change-Id: Ia191d4a45cf12de3197e01f8e8e36d1117870bba
This commit is contained in:
xiangxinyong 2016-09-12 15:31:37 +08:00
parent a7db2f7d3b
commit 59e13c7ba4
6 changed files with 263 additions and 2 deletions

View File

@ -560,3 +560,43 @@ def operation_log_get_all_by_project(context, project_id, marker, limit,
sort_dirs=sort_dirs,
filters=filters,
offset=offset)
###################
def checkpoint_record_get(context, checkpoint_record_id):
"""Get a checkpoint record or raise if it does not exist."""
return IMPL.checkpoint_record_get(context, checkpoint_record_id)
def checkpoint_record_create(context, values):
"""Create a checkpoint record from the values dictionary."""
return IMPL.checkpoint_record_create(context, values)
def checkpoint_record_update(context, checkpoint_record_id, values):
"""Set the given properties on a checkpoint record and update it.
Raises NotFound if checkpoint record does not exist.
"""
return IMPL.checkpoint_record_update(context, checkpoint_record_id, values)
def checkpoint_record_destroy(context, checkpoint_record_id):
"""Destroy the checkpoint record or raise if it does not exist."""
return IMPL.checkpoint_record_destroy(context, checkpoint_record_id)
def checkpoint_record_get_all_by_filters_sort(
context, filters, limit=None,
marker=None, sort_keys=None, sort_dirs=None):
"""Get all checkpoint records that match all filters sorted
by multiple keys. sort_keys and sort_dirs must be a list of strings.
"""
return IMPL.checkpoint_record_get_all_by_filters_sort(
context, filters, limit=limit, marker=marker,
sort_keys=sort_keys, sort_dirs=sort_dirs)

View File

@ -1313,6 +1313,95 @@ def _process_operation_log_filters(query, filters):
###############################
@require_context
def checkpoint_record_create(context, values):
checkpoint_record_ref = models.CheckpointRecord()
if not values.get('id'):
values['id'] = str(uuid.uuid4())
checkpoint_record_ref.update(values)
session = get_session()
with session.begin():
checkpoint_record_ref.save(session)
return checkpoint_record_ref
@require_context
def checkpoint_record_get(context, checkpoint_record_id):
return _checkpoint_record_get(context, checkpoint_record_id)
@require_context
def _checkpoint_record_get(context, checkpoint_record_id, session=None):
result = model_query(
context,
models.CheckpointRecord,
session=session).filter_by(
id=checkpoint_record_id).first()
if not result:
raise exception.CheckpointRecordNotFound(id=checkpoint_record_id)
return result
@require_context
def checkpoint_record_update(context, checkpoint_record_id, values):
session = get_session()
with session.begin():
checkpoint_record_ref = _checkpoint_record_get(context,
checkpoint_record_id,
session=session)
checkpoint_record_ref.update(values)
return checkpoint_record_ref
@require_context
@_retry_on_deadlock
def checkpoint_record_destroy(context, checkpoint_record_id):
session = get_session()
with session.begin():
checkpoint_record_ref = _checkpoint_record_get(context,
checkpoint_record_id,
session=session)
checkpoint_record_ref.delete(session=session)
def _checkpoint_record_list_query(context, session, **kwargs):
return model_query(context, models.CheckpointRecord, session=session)
def _checkpoint_record_list_process_filters(query, filters):
exact_match_filter_names = ['project_id', 'id',
'checkpoint_id', 'checkpoint_status',
'plan_id', 'provider_id', 'operation_id']
query = _list_common_process_exact_filter(
models.CheckpointRecord, query, filters,
exact_match_filter_names)
regex_match_filter_names = ['create_by']
query = _list_common_process_regex_filter(
models.CheckpointRecord, query, filters,
regex_match_filter_names)
return query
def checkpoint_record_get_all_by_filters_sort(
context, filters, limit=None, marker=None,
sort_keys=None, sort_dirs=None):
session = get_session()
with session.begin():
query = _generate_paginate_query(
context, session, marker, limit,
sort_keys, sort_dirs, filters,
paginate_type=models.CheckpointRecord,
use_model=True)
return query.all() if query else []
###############################
@require_context
def _list_common_get_query(context, model, session=None):
return model_query(context, model, session=session)
@ -1415,6 +1504,11 @@ PAGINATION_HELPERS = {
_scheduled_operation_log_list_query,
_scheduled_operation_log_list_process_filters,
_scheduled_operation_log_get),
models.CheckpointRecord: (
_checkpoint_record_list_query,
_checkpoint_record_list_process_filters,
_checkpoint_record_get),
}

View File

@ -173,6 +173,25 @@ def define_tables(meta):
mysql_engine='InnoDB'
)
checkpoint_records = Table(
'checkpoint_records',
meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('deleted_at', DateTime),
Column('deleted', Boolean, nullable=False),
Column('id', String(length=36), primary_key=True, nullable=False),
Column('project_id', String(length=36), nullable=False),
Column('checkpoint_id', String(length=36), nullable=False),
Column('checkpoint_status', String(length=36), nullable=False),
Column('provider_id', String(length=36), nullable=False),
Column('plan_id', String(length=36), nullable=False),
Column('operation_id', String(length=36)),
Column('create_by', String(length=36)),
Column('extend_info', Text),
mysql_engine='InnoDB'
)
return [services,
plans,
resources,
@ -181,7 +200,8 @@ def define_tables(meta):
triggers,
scheduled_operations,
scheduled_operation_states,
scheduled_operation_logs]
scheduled_operation_logs,
checkpoint_records]
def upgrade(migrate_engine):

View File

@ -199,6 +199,22 @@ class OperationLog(BASE, KarborBase):
entries = Column(Text)
class CheckpointRecord(BASE, KarborBase):
"""Represents a checkpoint record."""
__tablename__ = 'checkpoint_records'
id = Column(String(36), primary_key=True, nullable=False)
project_id = Column(String(36), nullable=False)
checkpoint_id = Column(String(36), nullable=False)
checkpoint_status = Column(String(36), nullable=False)
provider_id = Column(String(36), nullable=False)
plan_id = Column(String(36), nullable=False)
operation_id = Column(String(36))
create_by = Column(String(36))
extend_info = Column(Text)
def register_models():
"""Register Models and create metadata.
@ -214,7 +230,8 @@ def register_models():
ScheduledOperation,
ScheduledOperationState,
ScheduledOperationLog,
Restore)
Restore,
CheckpointRecord)
engine = create_engine(CONF.database.connection, echo=False)
for model in models:
model.metadata.create_all(engine)

View File

@ -267,6 +267,10 @@ class ProviderNotFound(NotFound):
" not be found.")
class CheckpointRecordNotFound(NotFound):
message = _("CheckpointRecord %(id)s could not be found.")
class CreateBackupFailed(KarborException):
message = _("Create Backup failed: %(reason)s, id=%(resource_id)s,"
" type=%(resource_type)s")

View File

@ -627,3 +627,89 @@ class OperationLogTestCase(base.TestCase):
self.assertRaises(exception.OperationLogNotFound,
db.operation_log_update,
self.ctxt, 42, {})
class CheckpointRecordTestCase(base.TestCase):
"""Unit tests for karbor.db.api.checkpoint_record_*."""
fake_checkpoint_record = {
"id": "36ea41b2-c358-48a7-9117-70cb7617410a",
"project_id": "586cc6ce-e286-40bd-b2b5-dd32694d9944",
"checkpoint_id": "2220f8b1-975d-4621-a872-fa9afb43cb6c",
"checkpoint_status": "available",
"provider_id": "39bb894794b741e982bd26144d2949f6",
"plan_id": "efc6a88b-9096-4bb6-8634-cda182a6e12b",
"operation_id": "64e51e85-4f31-441f-9a5d-6e93e3196628",
"create_by": "operation-engine",
"extend_info": "[{"
"'id': '0354ca9d-dcd0-46b6-9334-0d78759fd275',"
"'type': 'OS::Nova::Server',"
"'name': 'vm1'"
"}]"
}
def _dict_from_object(self, obj, ignored_keys):
if ignored_keys is None:
ignored_keys = []
if isinstance(obj, dict):
items = obj.items()
else:
items = obj.iteritems()
return {k: v for k, v in items
if k not in ignored_keys}
def _assertEqualObjects(self, obj1, obj2, ignored_keys=None):
obj1 = self._dict_from_object(obj1, ignored_keys)
obj2 = self._dict_from_object(obj2, ignored_keys)
self.assertEqual(
len(obj1), len(obj2),
"Keys mismatch: %s" % six.text_type(
set(obj1.keys()) ^ set(obj2.keys())))
for key, value in obj1.items():
self.assertEqual(value, obj2[key])
def setUp(self):
super(CheckpointRecordTestCase, self).setUp()
self.ctxt = context.get_admin_context()
def test_checkpoint_record_create(self):
checkpoint_record = db.checkpoint_record_create(
self.ctxt,
self.fake_checkpoint_record)
self.assertTrue(uuidutils.is_uuid_like(checkpoint_record['id']))
self.assertEqual('available', checkpoint_record.checkpoint_status)
def test_checkpoint_record_get(self):
checkpoint_record = db.checkpoint_record_create(
self.ctxt,
self.fake_checkpoint_record)
self._assertEqualObjects(checkpoint_record, db.checkpoint_record_get(
self.ctxt, checkpoint_record['id']))
def test_checkpoint_record_destroy(self):
checkpoint_record = db.checkpoint_record_create(
self.ctxt,
self.fake_checkpoint_record)
db.checkpoint_record_destroy(self.ctxt, checkpoint_record['id'])
self.assertRaises(exception.CheckpointRecordNotFound,
db.checkpoint_record_get,
self.ctxt, checkpoint_record['id'])
def test_checkpoint_record_update(self):
checkpoint_record = db.checkpoint_record_create(
self.ctxt,
self.fake_checkpoint_record)
db.checkpoint_record_update(self.ctxt,
checkpoint_record['id'],
{'checkpoint_status': 'error'})
checkpoint_record = db.checkpoint_record_get(
self.ctxt,
checkpoint_record['id'])
self.assertEqual('error', checkpoint_record['checkpoint_status'])
def test_checkpoint_record_update_nonexistent(self):
self.assertRaises(exception.CheckpointRecordNotFound,
db.checkpoint_record_update,
self.ctxt, 42, {})