Add a few fixes for the API.
This commit is contained in:
parent
e8e3b07f1a
commit
05b90de34d
@ -22,7 +22,7 @@ Should maintain feature parity with Nova Baremetal Extension.
|
||||
Specification in ironic/doc/api/v1.rst
|
||||
"""
|
||||
|
||||
|
||||
import inspect
|
||||
import pecan
|
||||
from pecan import rest
|
||||
|
||||
@ -30,27 +30,30 @@ import wsme
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
from wsme import types as wtypes
|
||||
|
||||
from ironic import db
|
||||
from ironic.openstack.common import log
|
||||
|
||||
# TODO(deva): The API shouldn't know what db IMPL is in use.
|
||||
# Import ironic.db.models instead of the sqlalchemy models
|
||||
# once that layer is written.
|
||||
from ironic.db.sqlalchemy import models
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class Base(wtypes.Base):
|
||||
# TODO: all the db bindings
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.fields = list(kwargs)
|
||||
for k, v in kwargs.iteritems():
|
||||
setattr(self, k, v)
|
||||
|
||||
@classmethod
|
||||
def from_db_model(cls, m):
|
||||
return cls(**(m.as_dict()))
|
||||
|
||||
@classmethod
|
||||
def from_db_and_links(cls, m, links):
|
||||
return cls(links=links, **(m.as_dict()))
|
||||
|
||||
def as_dict(self, db_model):
|
||||
valid_keys = inspect.getargspec(db_model.__init__)[0]
|
||||
if 'self' in valid_keys:
|
||||
valid_keys.remove('self')
|
||||
return cls(**m.as_dict())
|
||||
|
||||
def as_dict(self):
|
||||
return dict((k, getattr(self, k))
|
||||
for k in valid_keys
|
||||
for k in self.fields
|
||||
if hasattr(self, k) and
|
||||
getattr(self, k) != wsme.Unset)
|
||||
|
||||
@ -61,11 +64,6 @@ class Interface(Base):
|
||||
node_id = int
|
||||
address = wtypes.text
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.fields = list(kwargs)
|
||||
for k, v in kwargs.iteritems():
|
||||
setattr(self, k, v)
|
||||
|
||||
@classmethod
|
||||
def sample(cls):
|
||||
return cls(node_id=1,
|
||||
@ -119,11 +117,6 @@ class Node(Base):
|
||||
power_info = wtypes.text
|
||||
extra = wtypes.text
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.fields = list(kwargs)
|
||||
for k, v in kwargs.iteritems():
|
||||
setattr(self, k, v)
|
||||
|
||||
@classmethod
|
||||
def sample(cls):
|
||||
power_info = "{'driver': 'ipmi', 'user': 'fake', " \
|
||||
@ -153,12 +146,13 @@ class NodeIfaceController(rest.RestController):
|
||||
class NodesController(rest.RestController):
|
||||
"""REST controller for Nodes"""
|
||||
|
||||
@wsme_pecan.wsexpose(Node, body=Node)
|
||||
def post(self, data):
|
||||
@wsme.validate(Node)
|
||||
@wsme_pecan.wsexpose(Node, body=Node, status_code=201)
|
||||
def post(self, node):
|
||||
"""Ceate a new node."""
|
||||
try:
|
||||
r = pecan.request.dbapi.create_node(
|
||||
data.as_dict(db.models.Node))
|
||||
d = node.as_dict()
|
||||
r = pecan.request.dbapi.create_node(d)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
raise wsme.exc.ClientSideError(_("Invalid data"))
|
||||
|
@ -115,6 +115,7 @@ class Connection(api.Connection):
|
||||
node = models.Node()
|
||||
node.update(values)
|
||||
node.save()
|
||||
return node
|
||||
|
||||
def get_node(self, node):
|
||||
query = model_query(models.Node)
|
||||
@ -198,6 +199,7 @@ class Connection(api.Connection):
|
||||
iface = models.Iface()
|
||||
iface.update(values)
|
||||
iface.save()
|
||||
return iface
|
||||
|
||||
def update_iface(self, iface, values):
|
||||
session = get_session()
|
||||
|
@ -19,6 +19,7 @@
|
||||
SQLAlchemy models for baremetal data.
|
||||
"""
|
||||
|
||||
import json
|
||||
import urlparse
|
||||
|
||||
from oslo.config import cfg
|
||||
@ -26,6 +27,7 @@ from oslo.config import cfg
|
||||
from sqlalchemy import Table, Column, Index, ForeignKey
|
||||
from sqlalchemy import Boolean, DateTime, Float, Integer, String, Text
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.types import TypeDecorator, VARCHAR
|
||||
|
||||
from ironic.openstack.common.db.sqlalchemy import models
|
||||
|
||||
@ -45,10 +47,34 @@ def table_args():
|
||||
'mysql_charset': "utf8"}
|
||||
return None
|
||||
|
||||
|
||||
class JSONEncodedDict(TypeDecorator):
|
||||
"""Represents an immutable structure as a json-encoded string."""
|
||||
|
||||
impl = VARCHAR
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if value is not None:
|
||||
value = json.dumps(value)
|
||||
return value
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is not None:
|
||||
value = json.loads(value)
|
||||
return value
|
||||
|
||||
|
||||
class IronicBase(models.TimestampMixin,
|
||||
models.ModelBase):
|
||||
|
||||
metadata = None
|
||||
|
||||
def as_dict(self):
|
||||
d = {}
|
||||
for c in self.__table__.columns:
|
||||
d[c.name] = self[c.name]
|
||||
return d
|
||||
|
||||
|
||||
Base = declarative_base(cls=IronicBase)
|
||||
|
||||
@ -59,7 +85,7 @@ class Node(Base):
|
||||
__tablename__ = 'nodes'
|
||||
id = Column(Integer, primary_key=True)
|
||||
uuid = Column(String(36), unique=True)
|
||||
power_info = Column(Text)
|
||||
power_info = Column(JSONEncodedDict)
|
||||
cpu_arch = Column(String(10))
|
||||
cpu_num = Column(Integer)
|
||||
memory = Column(Integer)
|
||||
@ -68,7 +94,7 @@ class Node(Base):
|
||||
image_path = Column(String(255), nullable=True)
|
||||
instance_uuid = Column(String(36), nullable=True, unique=True)
|
||||
instance_name = Column(String(255), nullable=True)
|
||||
extra = Column(Text)
|
||||
extra = Column(JSONEncodedDict)
|
||||
|
||||
|
||||
class Iface(Base):
|
||||
@ -78,4 +104,4 @@ class Iface(Base):
|
||||
id = Column(Integer, primary_key=True)
|
||||
address = Column(String(18), unique=True)
|
||||
node_id = Column(Integer, ForeignKey('nodes.id'), nullable=True)
|
||||
extra = Column(Text)
|
||||
extra = Column(JSONEncodedDict)
|
||||
|
Loading…
x
Reference in New Issue
Block a user