Add compute node list API for admin

Admin should be able to list the compute nodes in order to divide
them into aggregate groups.

Change-Id: I33760d06607d0816c73f806b529d1729c211e793
This commit is contained in:
Zhenguo Niu 2017-06-02 15:40:29 +08:00
parent 75bfaeb0f3
commit 23871c345b
7 changed files with 182 additions and 0 deletions

View File

@ -0,0 +1,32 @@
.. -*- rst -*-
===============
Compute Nodes
===============
Lists compute nodes.
List Compute Node information
=============================
.. rest_method:: GET /nodes
Lists compute node information.
Normal response codes: 200
Error response codes: unauthorized(401), forbidden(403)
Response
--------
.. rest_parameters:: parameters.yaml
- nodes: nodes
|
**Example List compute node information**
.. literalinclude:: samples/nodes/node-list-resp.json
:language: javascript

View File

@ -353,6 +353,12 @@ nics:
in: body
required: true
type: dict
nodes:
description: |
The compute node list information.
in: body
required: true
type: dict
personality:
description: |
The file path and contents, text only, to inject into the server at launch. The

View File

@ -0,0 +1,22 @@
{
"nodes" : [
{
"node_uuid" : "99a0fdb0-d73f-471b-841d-a6e149c4a9a4",
"updated_at" : null,
"hypervisor_type" : "ironic",
"node_type" : "2288V3",
"created_at" : "2017-06-02T02:25:14+00:00",
"extra_specs" : {},
"availability_zone" : null
},
{
"extra_specs" : {},
"availability_zone" : null,
"node_type" : "2288V3",
"hypervisor_type" : "ironic",
"node_uuid" : "4f047692-fe12-4706-993e-e1b4e99f016b",
"updated_at" : null,
"created_at" : "2017-06-02T02:33:22+00:00"
}
]
}

View File

@ -28,6 +28,7 @@ from mogan.api.controllers import link
from mogan.api.controllers.v1 import availability_zone
from mogan.api.controllers.v1 import flavors
from mogan.api.controllers.v1 import keypairs
from mogan.api.controllers.v1 import nodes
from mogan.api.controllers.v1 import servers
from mogan.api import expose
@ -50,6 +51,9 @@ class V1(base.APIBase):
keypairs = [link.Link]
"""Links to the keypairs resource"""
nodes = [link.Link]
"""Links to the nodes resource"""
@staticmethod
def convert():
v1 = V1()
@ -84,6 +88,14 @@ class V1(base.APIBase):
'keypairs', '',
bookmark=True)
]
v1.nodes = [link.Link.make_link('self',
pecan.request.public_url,
'nodes', ''),
link.Link.make_link('bookmark',
pecan.request.public_url,
'nodes', '',
bookmark=True)
]
return v1
@ -94,6 +106,7 @@ class Controller(rest.RestController):
servers = servers.ServerController()
availability_zones = availability_zone.AvailabilityZoneController()
keypairs = keypairs.KeyPairController()
nodes = nodes.NodeController()
@expose.expose(V1)
def get(self):

View File

@ -0,0 +1,80 @@
# Copyright 2017 Huawei Technologies Co.,LTD.
# All Rights Reserved.
#
# 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.
import pecan
from pecan import rest
from wsme import types as wtypes
from mogan.api.controllers import base
from mogan.api.controllers.v1 import types
from mogan.api import expose
from mogan.common import policy
from mogan import objects
class Node(base.APIBase):
"""API representation of a node.
This class enforces type checking and value constraints, and converts
between the internal object model and the API representation of
a node.
"""
node_uuid = types.uuid
"""The UUID of the node"""
availability_zone = wtypes.text
"""The availability zone of the node"""
node_type = wtypes.text
"""The type of the node"""
hypervisor_type = wtypes.text
"""The hypervisor type of the node"""
extra_specs = {wtypes.text: types.jsontype}
"""The meta data of the node"""
def __init__(self, **kwargs):
super(Node, self).__init__(**kwargs)
self.fields = []
for field in objects.ComputeNode.fields:
# Skip fields we do not expose.
if not hasattr(self, field):
continue
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
class NodeCollection(base.APIBase):
"""API representation of a collection of nodes."""
nodes = [Node]
"""A list containing compute node objects"""
class NodeController(rest.RestController):
"""REST controller for Node."""
@policy.authorize_wsgi("mogan:node", "get_all",
need_target=False)
@expose.expose(NodeCollection)
def get_all(self):
"""Retrieve a list of nodes."""
nodes = objects.ComputeNodeList.get_all_available(
pecan.request.context)
nodes_data = [Node(**node.as_dict()) for node in nodes]
return NodeCollection(nodes=nodes_data)

View File

@ -150,6 +150,9 @@ server_policies = [
policy.RuleDefault('mogan:flavor_extra_specs:get_all',
'rule:allow',
description='Retrieve flavor extra specs'),
policy.RuleDefault('mogan:node:get_all',
'rule:admin_api',
description='Retrieve all compute nodes'),
]

View File

@ -0,0 +1,26 @@
# Copyright 2017 Huawei Technologies Co., Ltd.
#
# 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 mogan.tests.functional.api import v1 as v1_test
class TestNode(v1_test.APITestV1):
def setUp(self):
super(TestNode, self).setUp()
def test_node_get_all(self):
headers = self.gen_headers(self.context, roles="admin")
resp = self.get_json('/nodes', headers=headers)
self.assertItemsEqual([], resp['nodes'])