Add the Object Capsule and database table
Part of blueprint introduce-compose Change-Id: I8ed3711d14e8cda92b5bb5cf2874980cbd66cad0 Signed-off-by: Kevin Zhao <kevin.zhao@arm.com>
This commit is contained in:
parent
080f4fb00f
commit
0b4c53e363
@ -177,3 +177,26 @@ class ResourceClass(Base):
|
||||
@classmethod
|
||||
def fields(cls):
|
||||
return cls._fields
|
||||
|
||||
|
||||
class Capsule(Base):
|
||||
"""Represents a capsule."""
|
||||
|
||||
_path = '/capsules'
|
||||
|
||||
_fields = objects.Capsule.fields.keys()
|
||||
|
||||
def __init__(self, capsule_data):
|
||||
self.path = Capsule.path()
|
||||
for f in Capsule.fields():
|
||||
setattr(self, f, None)
|
||||
self.id = 1
|
||||
self.update(capsule_data)
|
||||
|
||||
@classmethod
|
||||
def path(cls):
|
||||
return cls._path
|
||||
|
||||
@classmethod
|
||||
def fields(cls):
|
||||
return cls._fields
|
||||
|
@ -0,0 +1,58 @@
|
||||
# Copyright 2017 ARM Holdings
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""create capsule table
|
||||
|
||||
Revision ID: a251f1f61217
|
||||
Revises: 75315e219cfb
|
||||
Create Date: 2017-06-20 17:12:56.105277
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'a251f1f61217'
|
||||
down_revision = '75315e219cfb'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
from zun.db.sqlalchemy import models
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table(
|
||||
'capsule',
|
||||
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('capsule_version', sa.String(length=255), nullable=True),
|
||||
sa.Column('kind', sa.String(length=36), nullable=True),
|
||||
sa.Column('project_id', sa.String(length=255), nullable=True),
|
||||
sa.Column('user_id', sa.String(length=255), nullable=True),
|
||||
sa.Column('restart_policy', sa.String(length=255), nullable=True),
|
||||
sa.Column('host_selector', sa.String(length=255), nullable=True),
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('uuid', sa.String(length=36), nullable=False),
|
||||
sa.Column('status', sa.String(length=255), nullable=True),
|
||||
sa.Column('status_reason', sa.Text(), nullable=True),
|
||||
sa.Column('message', models.JSONEncodedDict(), nullable=True),
|
||||
sa.Column('spec', models.JSONEncodedDict(), nullable=True),
|
||||
sa.Column('cpu', sa.Float(), nullable=True),
|
||||
sa.Column('memory', sa.String(length=255), nullable=True),
|
||||
sa.Column('meta_name', sa.String(length=255), nullable=True),
|
||||
sa.Column('meta_labels', models.JSONEncodedList(), nullable=True),
|
||||
sa.Column('containers_uuids', models.JSONEncodedList(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
)
|
@ -288,3 +288,30 @@ class ComputeNode(Base):
|
||||
os = Column(String(64), nullable=True)
|
||||
kernel_version = Column(String(128), nullable=True)
|
||||
labels = Column(JSONEncodedDict)
|
||||
|
||||
|
||||
class Capsule(Base):
|
||||
"""Represents a capsule."""
|
||||
|
||||
__tablename__ = 'capsule'
|
||||
__table_args__ = (
|
||||
schema.UniqueConstraint('uuid', name='uniq_capsule0uuid'),
|
||||
table_args()
|
||||
)
|
||||
uuid = Column(String(36), nullable=False)
|
||||
id = Column(Integer, primary_key=True, nullable=False)
|
||||
host_selector = Column(String(255))
|
||||
capsule_version = Column(String(255))
|
||||
kind = Column(String(255))
|
||||
restart_policy = Column(JSONEncodedDict)
|
||||
project_id = Column(String(255))
|
||||
user_id = Column(String(255))
|
||||
|
||||
status = Column(String(20))
|
||||
status_reason = Column(Text, nullable=True)
|
||||
meta_labels = Column(JSONEncodedList)
|
||||
meta_name = Column(String(255))
|
||||
spec = Column(JSONEncodedDict)
|
||||
containers_uuids = Column(JSONEncodedList)
|
||||
cpu = Column(Float)
|
||||
memory = Column(String(255))
|
||||
|
@ -10,6 +10,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from zun.objects import capsule
|
||||
from zun.objects import compute_node
|
||||
from zun.objects import container
|
||||
from zun.objects import image
|
||||
@ -26,6 +27,7 @@ NUMATopology = numa.NUMATopology
|
||||
ResourceProvider = resource_provider.ResourceProvider
|
||||
ResourceClass = resource_class.ResourceClass
|
||||
ComputeNode = compute_node.ComputeNode
|
||||
Capsule = capsule.Capsule
|
||||
|
||||
__all__ = (
|
||||
Container,
|
||||
@ -36,4 +38,5 @@ __all__ = (
|
||||
NUMANode,
|
||||
NUMATopology,
|
||||
ComputeNode,
|
||||
Capsule,
|
||||
)
|
||||
|
152
zun/objects/capsule.py
Normal file
152
zun/objects/capsule.py
Normal file
@ -0,0 +1,152 @@
|
||||
# Copyright 2017 ARM Holdings.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from zun.db import api as dbapi
|
||||
from zun.objects import base
|
||||
from zun.objects import fields as z_fields
|
||||
|
||||
|
||||
@base.ZunObjectRegistry.register
|
||||
class Capsule(base.ZunPersistentObject, base.ZunObject):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'capsule_version': fields.StringField(nullable=True),
|
||||
'kind': fields.StringField(nullable=True),
|
||||
'restart_policy': fields.DictOfStringsField(nullable=True),
|
||||
'host_selector': fields.StringField(nullable=True),
|
||||
# uuid is the infra-container id
|
||||
'id': fields.IntegerField(),
|
||||
'uuid': fields.UUIDField(nullable=True),
|
||||
'project_id': fields.StringField(nullable=True),
|
||||
'user_id': fields.StringField(nullable=True),
|
||||
|
||||
'status': z_fields.ContainerStatusField(nullable=True),
|
||||
'status_reason': fields.StringField(nullable=True),
|
||||
'cpu': fields.FloatField(nullable=True),
|
||||
'memory': fields.StringField(nullable=True),
|
||||
|
||||
# conclude the readable message
|
||||
# 'key': 'value'--> 'time':'message'
|
||||
# wait until zun notify is finished
|
||||
# 'message': fields.DictOfStringsField(nullable=True),
|
||||
|
||||
'spec': z_fields.JsonField(nullable=True),
|
||||
'meta_name': fields.StringField(nullable=True),
|
||||
'meta_labels': z_fields.JsonField(nullable=True),
|
||||
'containers': fields.ListOfObjectsField('Container', nullable=True),
|
||||
'containers_uuids': fields.ListOfStringsField(nullable=True),
|
||||
# add volumes after Cinder integration is ready
|
||||
# 'volumes': fields.ListOfObjectsField(nullable=True),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _from_db_object(capsule, db_capsule):
|
||||
"""Converts a database entity to a formal object."""
|
||||
for field in capsule.fields:
|
||||
if field != 'containers':
|
||||
setattr(capsule, field, db_capsule[field])
|
||||
capsule.obj_reset_changes()
|
||||
return capsule
|
||||
|
||||
@staticmethod
|
||||
def _from_db_object_list(db_objects, cls, context):
|
||||
"""Converts a list of database entities to a list of formal objects."""
|
||||
return [Capsule._from_db_object(cls(context), obj)
|
||||
for obj in db_objects]
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_uuid(cls, context, uuid):
|
||||
"""Find a container based on uuid and return a :class:`Container` object.
|
||||
|
||||
:param uuid: the uuid of a container.
|
||||
:param context: Security context
|
||||
:returns: a :class:`Container` object.
|
||||
"""
|
||||
db_capsule = dbapi.get_capsule_by_uuid(context, uuid)
|
||||
capsule = Capsule._from_db_object(cls(context), db_capsule)
|
||||
return capsule
|
||||
|
||||
@base.remotable_classmethod
|
||||
def list(cls, context, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None, filters=None):
|
||||
"""Return a list of Container objects.
|
||||
|
||||
:param context: Security context.
|
||||
:param limit: maximum number of resources to return in a single result.
|
||||
:param marker: pagination marker for large data sets.
|
||||
:param sort_key: column to sort results by.
|
||||
:param sort_dir: direction to sort. "asc" or "desc".
|
||||
:param filters: filters when list containers, the filter name could be
|
||||
'name', 'image', 'project_id', 'user_id', 'memory'.
|
||||
For example, filters={'image': 'nginx'}
|
||||
:returns: a list of :class:`Container` object.
|
||||
|
||||
"""
|
||||
db_capsules = dbapi.list_capsules(
|
||||
context, limit=limit, marker=marker, sort_key=sort_key,
|
||||
sort_dir=sort_dir, filters=filters)
|
||||
return Capsule._from_db_object_list(db_capsules, cls, context)
|
||||
|
||||
@base.remotable
|
||||
def create(self, context):
|
||||
"""Create a Container record in the DB.
|
||||
|
||||
:param context: Security context. NOTE: This should only
|
||||
be used internally by the indirection_api.
|
||||
Unfortunately, RPC requires context as the first
|
||||
argument, even though we don't use it.
|
||||
A context should be set when instantiating the
|
||||
object, e.g.: Container(context)
|
||||
|
||||
"""
|
||||
values = self.obj_get_changes()
|
||||
db_capsule = dbapi.create_capsule(context, values)
|
||||
self._from_db_object(self, db_capsule)
|
||||
|
||||
@base.remotable
|
||||
def destroy(self, context=None):
|
||||
"""Delete the Container from the DB.
|
||||
|
||||
:param context: Security context. NOTE: This should only
|
||||
be used internally by the indirection_api.
|
||||
Unfortunately, RPC requires context as the first
|
||||
argument, even though we don't use it.
|
||||
A context should be set when instantiating the
|
||||
object, e.g.: Container(context)
|
||||
"""
|
||||
dbapi.destroy_capsule(context, self.uuid)
|
||||
self.obj_reset_changes()
|
||||
|
||||
@base.remotable
|
||||
def save(self, context=None):
|
||||
"""Save updates to this Container.
|
||||
|
||||
Updates will be made column by column based on the result
|
||||
of self.what_changed().
|
||||
|
||||
:param context: Security context. NOTE: This should only
|
||||
be used internally by the indirection_api.
|
||||
Unfortunately, RPC requires context as the first
|
||||
argument, even though we don't use it.
|
||||
A context should be set when instantiating the
|
||||
object, e.g.: Container(context)
|
||||
"""
|
||||
updates = self.obj_get_changes()
|
||||
dbapi.update_capsule(context, self.uuid, updates)
|
||||
|
||||
self.obj_reset_changes()
|
@ -353,6 +353,7 @@ object_data = {
|
||||
'ResourceProvider': '1.0-92b427359d5a4cf9ec6c72cbe630ee24',
|
||||
'ZunService': '1.1-b1549134bfd5271daec417ca8cabc77e',
|
||||
'ComputeNode': '1.6-33a173b969781644a95ea2925eb5cca2',
|
||||
'Capsule': '1.0-0dce1bd569773c35193d75c285226e75',
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright 2017 Linaro Limited
|
||||
# Copyright 2017 ARM Holdings.
|
||||
#
|
||||
# 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
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2017 Linaro Limited
|
||||
# Copyright 2017 ARM Holdings.
|
||||
#
|
||||
# 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user