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
|
@classmethod
|
||||||
def fields(cls):
|
def fields(cls):
|
||||||
return cls._fields
|
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)
|
os = Column(String(64), nullable=True)
|
||||||
kernel_version = Column(String(128), nullable=True)
|
kernel_version = Column(String(128), nullable=True)
|
||||||
labels = Column(JSONEncodedDict)
|
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
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from zun.objects import capsule
|
||||||
from zun.objects import compute_node
|
from zun.objects import compute_node
|
||||||
from zun.objects import container
|
from zun.objects import container
|
||||||
from zun.objects import image
|
from zun.objects import image
|
||||||
@ -26,6 +27,7 @@ NUMATopology = numa.NUMATopology
|
|||||||
ResourceProvider = resource_provider.ResourceProvider
|
ResourceProvider = resource_provider.ResourceProvider
|
||||||
ResourceClass = resource_class.ResourceClass
|
ResourceClass = resource_class.ResourceClass
|
||||||
ComputeNode = compute_node.ComputeNode
|
ComputeNode = compute_node.ComputeNode
|
||||||
|
Capsule = capsule.Capsule
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
Container,
|
Container,
|
||||||
@ -36,4 +38,5 @@ __all__ = (
|
|||||||
NUMANode,
|
NUMANode,
|
||||||
NUMATopology,
|
NUMATopology,
|
||||||
ComputeNode,
|
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',
|
'ResourceProvider': '1.0-92b427359d5a4cf9ec6c72cbe630ee24',
|
||||||
'ZunService': '1.1-b1549134bfd5271daec417ca8cabc77e',
|
'ZunService': '1.1-b1549134bfd5271daec417ca8cabc77e',
|
||||||
'ComputeNode': '1.6-33a173b969781644a95ea2925eb5cca2',
|
'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
|
# 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
|
# 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
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
Loading…
x
Reference in New Issue
Block a user