"Boards in a fleet"

Now a board can join a fleet

Change-Id: I5f553421929e72dd1871cce1783043e5e38865f1
This commit is contained in:
Fabio Verboso 2018-09-21 14:41:13 +02:00
parent a081c594b2
commit 3c351e80ce
6 changed files with 72 additions and 45 deletions

View File

@ -30,7 +30,8 @@ from oslo_log import log as logging
LOG = logging.getLogger(__name__)
_DEFAULT_RETURN_FIELDS = ('name', 'code', 'status', 'uuid', 'session', 'type')
_DEFAULT_RETURN_FIELDS = ('name', 'code', 'status', 'uuid', 'session', 'type',
'fleet')
class Board(base.APIBase):
@ -45,6 +46,7 @@ class Board(base.APIBase):
owner = types.uuid
session = wsme.wsattr(wtypes.text)
project = types.uuid
fleet = types.uuid
mobile = types.boolean
links = wsme.wsattr([link.Link], readonly=True)
location = wsme.wsattr([loc.Location])

View File

@ -13,6 +13,7 @@
from iotronic.api.controllers import base
from iotronic.api.controllers import link
from iotronic.api.controllers.v1.board import BoardCollection
from iotronic.api.controllers.v1 import collection
from iotronic.api.controllers.v1 import types
from iotronic.api.controllers.v1 import utils as api_utils
@ -29,6 +30,9 @@ from wsme import types as wtypes
_DEFAULT_RETURN_FIELDS = (
'name', 'uuid', 'project', 'description', 'extra')
_DEFAULT_BOARDS_RETURN_FIELDS = ('name', 'code', 'status', 'uuid', 'session',
'type', 'fleet')
class Fleet(base.APIBase):
"""API representation of a fleet.
@ -94,48 +98,16 @@ class FleetCollection(collection.Collection):
return collection
class PublicFleetsController(rest.RestController):
"""REST controller for Public Fleets."""
class FleetBoardsController(rest.RestController):
def __init__(self, fleet_ident):
self.fleet_ident = fleet_ident
invalid_sort_key_list = ['extra']
def _get_fleets_collection(self, marker, limit,
sort_key, sort_dir,
fields=None):
limit = api_utils.validate_limit(limit)
sort_dir = api_utils.validate_sort_dir(sort_dir)
marker_obj = None
if marker:
marker_obj = objects.Fleet.get_by_uuid(pecan.request.context,
marker)
if sort_key in self.invalid_sort_key_list:
raise exception.InvalidParameterValue(
("The sort_key value %(key)s is an invalid field for "
"sorting") % {'key': sort_key})
filters = {}
filters['public'] = True
fleets = objects.Fleet.list(pecan.request.context, limit,
marker_obj,
sort_key=sort_key, sort_dir=sort_dir,
filters=filters)
parameters = {'sort_key': sort_key, 'sort_dir': sort_dir}
return FleetCollection.convert_with_links(fleets, limit,
fields=fields,
**parameters)
@expose.expose(FleetCollection, types.uuid, int, wtypes.text,
wtypes.text, types.listtype, types.boolean, types.boolean)
@expose.expose(BoardCollection, types.uuid, int, wtypes.text,
wtypes.text, types.listtype)
def get_all(self, marker=None,
limit=None, sort_key='id', sort_dir='asc',
fields=None):
"""Retrieve a list of fleets.
"""Retrieve a list of boards.
:param marker: pagination marker for large data sets.
:param limit: maximum number of resources to return in a single result.
@ -148,19 +120,31 @@ class PublicFleetsController(rest.RestController):
of the resource to be returned.
"""
cdict = pecan.request.context.to_policy_values()
policy.authorize('iot:fleet:get', cdict, cdict)
policy.authorize('iot:board:get', cdict, cdict)
if fields is None:
fields = _DEFAULT_RETURN_FIELDS
return self._get_fleets_collection(marker,
limit, sort_key, sort_dir,
fields=fields)
fields = _DEFAULT_BOARDS_RETURN_FIELDS
filters = {}
filters['fleet'] = self.fleet_ident
boards = objects.Board.list(pecan.request.context, limit, marker,
sort_key=sort_key, sort_dir=sort_dir,
filters=filters)
parameters = {'sort_key': sort_key, 'sort_dir': sort_dir}
return BoardCollection.convert_with_links(boards, limit,
fields=fields,
**parameters)
class FleetsController(rest.RestController):
"""REST controller for Fleets."""
public = PublicFleetsController()
_subcontroller_map = {
'boards': FleetBoardsController,
}
invalid_sort_key_list = ['extra', ]
@ -168,6 +152,19 @@ class FleetsController(rest.RestController):
'detail': ['GET'],
}
@pecan.expose()
def _lookup(self, ident, *remainder):
try:
ident = types.uuid_or_name.validate(ident)
except exception.InvalidUuidOrName as e:
pecan.abort('400', e.args[0])
if not remainder:
return
subcontroller = self._subcontroller_map.get(remainder[0])
if subcontroller:
return subcontroller(fleet_ident=ident), remainder[1:]
def _get_fleets_collection(self, marker, limit,
sort_key, sort_dir,
fields=None):

View File

@ -0,0 +1,24 @@
# 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.
# revision identifiers, used by Alembic.
revision = '9c5c34dfd9f1'
down_revision = '44e74b9170d1'
from alembic import op
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_foreign_key(None, 'boards', 'fleets', ['fleet'], ['uuid'])
# ### end Alembic commands ###

View File

@ -131,6 +131,8 @@ class Connection(api.Connection):
query = query.filter(models.Board.project == filters['project_id'])
if 'status' in filters:
query = query.filter(models.Board.status == filters['status'])
if 'fleet' in filters:
query = query.filter(models.Board.fleet == filters['fleet'])
return query

View File

@ -154,6 +154,7 @@ class Board(Base):
agent = Column(String(255), nullable=True)
owner = Column(String(36))
project = Column(String(36))
fleet = Column(String(36), ForeignKey('fleets.uuid'), nullable=True)
mobile = Column(Boolean, default=False)
config = Column(JSONEncodedDict)
extra = Column(JSONEncodedDict)

View File

@ -39,6 +39,7 @@ class Board(base.IotronicObject):
'agent': obj_utils.str_or_none,
'owner': obj_utils.str_or_none,
'project': obj_utils.str_or_none,
'fleet': obj_utils.str_or_none,
'mobile': bool,
'config': obj_utils.dict_or_none,
'extra': obj_utils.dict_or_none,