Manage existing BMs: Part-1
This patch introduce a new API: 'GET: /manageable_servers' to list the adoptable nodes from drivers to operators. As a reference, now we implement api in the Ironic driver. APIImpact Implements: bp manage-existing-bms Change-Id: I56340ce534c3b8d4e855a4c753ecf90a07147d29
This commit is contained in:
parent
77d19eceb7
commit
d577c88d4a
40
api-ref/source/v1/manageable_servers.inc
Normal file
40
api-ref/source/v1/manageable_servers.inc
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
.. -*- rst -*-
|
||||||
|
|
||||||
|
===================
|
||||||
|
Manageable Servers
|
||||||
|
===================
|
||||||
|
|
||||||
|
Lists manageable servers.
|
||||||
|
|
||||||
|
List manageable servers information
|
||||||
|
===================================
|
||||||
|
|
||||||
|
.. rest_method:: GET /manageable_servers
|
||||||
|
|
||||||
|
Lists manageable servers information.
|
||||||
|
|
||||||
|
Normal response codes: 200
|
||||||
|
|
||||||
|
Error response codes: unauthorized(401), forbidden(403)
|
||||||
|
|
||||||
|
Response
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- manageable_servers: manageable_servers
|
||||||
|
- uuid: manageable_servers_uuid
|
||||||
|
- name: manageable_servers_name
|
||||||
|
- resource_class: manageable_servers_resource_class
|
||||||
|
- power_state: manageable_servers_power_state
|
||||||
|
- provision_state: manageable_servers_provision_state
|
||||||
|
- ports: manageable_servers_ports
|
||||||
|
- portgroups: manageable_servers_portgroups
|
||||||
|
- image_source: manageable_servers_image_source
|
||||||
|
|
||||||
|
|
|
||||||
|
|
||||||
|
**Example List manageable servers information**
|
||||||
|
|
||||||
|
.. literalinclude:: samples/manageable_servers/manageable-servers-list-resp.json
|
||||||
|
:language: javascript
|
@ -425,6 +425,60 @@ lock_state:
|
|||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
type: boolean
|
type: boolean
|
||||||
|
manageable_servers:
|
||||||
|
description: |
|
||||||
|
An array of manageable servers information.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: array
|
||||||
|
manageable_servers_image_source:
|
||||||
|
description: |
|
||||||
|
Image source uuid of manageable server.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
manageable_servers_name:
|
||||||
|
description: |
|
||||||
|
Name of manageable server.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
manageable_servers_portgroups:
|
||||||
|
description: |
|
||||||
|
The portgroups of manageable server.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: array
|
||||||
|
manageable_servers_ports:
|
||||||
|
description: |
|
||||||
|
The ports of manageable server.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: array
|
||||||
|
manageable_servers_power_state:
|
||||||
|
description: |
|
||||||
|
The power state of manageable server.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
manageable_servers_provision_state:
|
||||||
|
description: |
|
||||||
|
The provision state of manageable server.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
manageable_servers_resource_class:
|
||||||
|
description: |
|
||||||
|
Resource class of manageable server.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
manageable_servers_uuid:
|
||||||
|
description: |
|
||||||
|
UUID of manageable server.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
max_count_body:
|
max_count_body:
|
||||||
description: |
|
description: |
|
||||||
The max number of servers to be created. Defaults to the value of ``min_count``.
|
The max number of servers to be created. Defaults to the value of ``min_count``.
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"manageable_servers": [
|
||||||
|
{
|
||||||
|
"uuid": "7de2859d-ec6d-42c7-bb86-9d630ba5ac94",
|
||||||
|
"name": "test_node",
|
||||||
|
"resource_class": "gold",
|
||||||
|
"power_state": "power on",
|
||||||
|
"provision_state": "active",
|
||||||
|
"ports": [
|
||||||
|
{
|
||||||
|
"address": "a4:dc:be:0e:82:a5",
|
||||||
|
"uuid": "1ec01153-685a-49b5-a6d3-45a4e7dddf53",
|
||||||
|
"neutron_port_id": "a9b94592-1d8e-46bb-836b-c7ba935b0136"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"portgroups": [
|
||||||
|
{
|
||||||
|
"address": "a4:dc:be:0e:82:a6",
|
||||||
|
"uuid": "1ec01153-685a-49b5-a6d3-45a4e7dddf54",
|
||||||
|
"neutron_port_id": "a9b94592-1d8e-46bb-836b-c7ba935b0137"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"image_source": "03239419-e588-42b6-a70f-94f23ed0c9e2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -29,6 +29,7 @@ from mogan.api.controllers.v1 import aggregates
|
|||||||
from mogan.api.controllers.v1 import availability_zones
|
from mogan.api.controllers.v1 import availability_zones
|
||||||
from mogan.api.controllers.v1 import flavors
|
from mogan.api.controllers.v1 import flavors
|
||||||
from mogan.api.controllers.v1 import keypairs
|
from mogan.api.controllers.v1 import keypairs
|
||||||
|
from mogan.api.controllers.v1 import manageable_servers
|
||||||
from mogan.api.controllers.v1 import nodes
|
from mogan.api.controllers.v1 import nodes
|
||||||
from mogan.api.controllers.v1 import server_groups
|
from mogan.api.controllers.v1 import server_groups
|
||||||
from mogan.api.controllers.v1 import servers
|
from mogan.api.controllers.v1 import servers
|
||||||
@ -62,6 +63,9 @@ class V1(base.APIBase):
|
|||||||
server_groups = [link.Link]
|
server_groups = [link.Link]
|
||||||
"""Links to the server groups resource"""
|
"""Links to the server groups resource"""
|
||||||
|
|
||||||
|
manageable_servers = [link.Link]
|
||||||
|
"""Links to the manageable servers resource"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def convert():
|
def convert():
|
||||||
v1 = V1()
|
v1 = V1()
|
||||||
@ -120,6 +124,14 @@ class V1(base.APIBase):
|
|||||||
'server_groups', '',
|
'server_groups', '',
|
||||||
bookmark=True)
|
bookmark=True)
|
||||||
]
|
]
|
||||||
|
v1.manageable_servers = [link.Link.make_link('self',
|
||||||
|
pecan.request.public_url,
|
||||||
|
'manageable_servers', ''),
|
||||||
|
link.Link.make_link('bookmark',
|
||||||
|
pecan.request.public_url,
|
||||||
|
'manageable_servers', '',
|
||||||
|
bookmark=True)
|
||||||
|
]
|
||||||
return v1
|
return v1
|
||||||
|
|
||||||
|
|
||||||
@ -133,6 +145,7 @@ class Controller(rest.RestController):
|
|||||||
aggregates = aggregates.AggregateController()
|
aggregates = aggregates.AggregateController()
|
||||||
nodes = nodes.NodeController()
|
nodes = nodes.NodeController()
|
||||||
server_groups = server_groups.ServerGroupController()
|
server_groups = server_groups.ServerGroupController()
|
||||||
|
manageable_servers = manageable_servers.ManageableServersController()
|
||||||
|
|
||||||
@expose.expose(V1)
|
@expose.expose(V1)
|
||||||
def get(self):
|
def get(self):
|
||||||
|
86
mogan/api/controllers/v1/manageable_servers.py
Normal file
86
mogan/api/controllers/v1/manageable_servers.py
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
# Copyright 2017 Fiberhome Integration 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
|
||||||
|
|
||||||
|
|
||||||
|
class ManageableServer(base.APIBase):
|
||||||
|
"""API representation of manageable server."""
|
||||||
|
|
||||||
|
uuid = types.uuid
|
||||||
|
"""The UUID of the manageable server"""
|
||||||
|
|
||||||
|
name = wtypes.text
|
||||||
|
"""The name of the manageable server"""
|
||||||
|
|
||||||
|
resource_class = wtypes.text
|
||||||
|
"""The resource_class of the manageable server"""
|
||||||
|
|
||||||
|
power_state = wtypes.text
|
||||||
|
"""The power_state of the manageable server"""
|
||||||
|
|
||||||
|
provision_state = wtypes.text
|
||||||
|
"""The provision_state of the manageable server"""
|
||||||
|
|
||||||
|
ports = types.jsontype
|
||||||
|
"""The ports of the manageable server"""
|
||||||
|
|
||||||
|
portgroups = types.jsontype
|
||||||
|
"""The portgroups of the manageable server"""
|
||||||
|
|
||||||
|
image_source = types.uuid
|
||||||
|
"""The UUID of the image id which manageable server use"""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(ManageableServer, self).__init__(**kwargs)
|
||||||
|
self.fields = []
|
||||||
|
for field in kwargs.keys():
|
||||||
|
if not hasattr(self, field):
|
||||||
|
continue
|
||||||
|
self.fields.append(field)
|
||||||
|
setattr(self, field, kwargs.get(field, wtypes.Unset))
|
||||||
|
|
||||||
|
|
||||||
|
class ManageableServerCollection(base.APIBase):
|
||||||
|
"""API representation of a collection of manageable server."""
|
||||||
|
|
||||||
|
manageable_servers = [ManageableServer]
|
||||||
|
"""A list containing manageable server objects"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def convert_with_list_of_dicts(manageable_servers):
|
||||||
|
collection = ManageableServerCollection()
|
||||||
|
collection.manageable_servers = [ManageableServer(**mserver)
|
||||||
|
for mserver in manageable_servers]
|
||||||
|
return collection
|
||||||
|
|
||||||
|
|
||||||
|
class ManageableServersController(rest.RestController):
|
||||||
|
"""REST controller for manage existing servers."""
|
||||||
|
|
||||||
|
@policy.authorize_wsgi("mogan:manageable_servers", "get_all", False)
|
||||||
|
@expose.expose(ManageableServerCollection)
|
||||||
|
def get_all(self):
|
||||||
|
"""List manageable servers from driver."""
|
||||||
|
nodes = pecan.request.engine_api.get_manageable_servers(
|
||||||
|
pecan.request.context)
|
||||||
|
return ManageableServerCollection.convert_with_list_of_dicts(nodes)
|
@ -137,6 +137,13 @@ class BaseEngineDriver(object):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_manageable_nodes(self):
|
||||||
|
"""Retrieve all manageable nodes information.
|
||||||
|
|
||||||
|
:returns:A list of describing manageable nodes
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
def load_engine_driver(engine_driver):
|
def load_engine_driver(engine_driver):
|
||||||
"""Load a engine driver module.
|
"""Load a engine driver module.
|
||||||
|
@ -44,6 +44,10 @@ _NODE_FIELDS = ('uuid', 'power_state', 'target_power_state', 'provision_state',
|
|||||||
'target_provision_state', 'last_error', 'maintenance',
|
'target_provision_state', 'last_error', 'maintenance',
|
||||||
'properties', 'instance_uuid')
|
'properties', 'instance_uuid')
|
||||||
|
|
||||||
|
TENANT_VIF_KEY = 'tenant_vif_port_id'
|
||||||
|
|
||||||
|
VIF_KEY = 'vif_port_id'
|
||||||
|
|
||||||
|
|
||||||
def map_power_state(state):
|
def map_power_state(state):
|
||||||
try:
|
try:
|
||||||
@ -99,6 +103,37 @@ class IronicDriver(base_driver.BaseEngineDriver):
|
|||||||
except ironic_exc.NotFound:
|
except ironic_exc.NotFound:
|
||||||
raise exception.ServerNotFound(server=server.uuid)
|
raise exception.ServerNotFound(server=server.uuid)
|
||||||
|
|
||||||
|
def _node_resource(self, node):
|
||||||
|
"""Helper method to create resource dict from node stats."""
|
||||||
|
|
||||||
|
dic = {
|
||||||
|
'resource_class': str(node.resource_class),
|
||||||
|
'ports': node.ports,
|
||||||
|
'portgroups': node.portgroups,
|
||||||
|
'name': node.name,
|
||||||
|
'power_state': node.power_state,
|
||||||
|
'provision_state': node.provision_state,
|
||||||
|
'image_source': node.instance_info.get('image_source'),
|
||||||
|
}
|
||||||
|
|
||||||
|
return dic
|
||||||
|
|
||||||
|
def _port_or_group_resource(self, port_or_pg):
|
||||||
|
"""Helper method to create resource dict from port or portgroup
|
||||||
|
|
||||||
|
stats.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
neutron_port_id = (port_or_pg.internal_info.get(TENANT_VIF_KEY) or
|
||||||
|
port_or_pg.extra.get(VIF_KEY))
|
||||||
|
dic = {
|
||||||
|
'address': port_or_pg.address,
|
||||||
|
'uuid': port_or_pg.uuid,
|
||||||
|
'neutron_port_id': neutron_port_id,
|
||||||
|
}
|
||||||
|
return dic
|
||||||
|
|
||||||
def _add_server_info_to_node(self, node, server):
|
def _add_server_info_to_node(self, node, server):
|
||||||
patch = list()
|
patch = list()
|
||||||
# Associate the node with a server
|
# Associate the node with a server
|
||||||
@ -356,6 +391,67 @@ class IronicDriver(base_driver.BaseEngineDriver):
|
|||||||
LOG.info('Successfully unprovisioned Ironic node %s',
|
LOG.info('Successfully unprovisioned Ironic node %s',
|
||||||
node.uuid, server=server)
|
node.uuid, server=server)
|
||||||
|
|
||||||
|
def _get_manageable_nodes(self):
|
||||||
|
"""Helper function to return the list of manageable nodes.
|
||||||
|
|
||||||
|
If unable to connect ironic server, an empty list is returned.
|
||||||
|
|
||||||
|
:returns: a list of raw node from ironic
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Retrieve nodes
|
||||||
|
params = {
|
||||||
|
'maintenance': False,
|
||||||
|
'detail': True,
|
||||||
|
'provision_state': ironic_states.ACTIVE,
|
||||||
|
'associated': False,
|
||||||
|
'limit': 0
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
node_list = self.ironicclient.call("node.list", **params)
|
||||||
|
except client_e.ClientException as e:
|
||||||
|
LOG.exception("Could not get nodes from ironic. Reason: "
|
||||||
|
"%(detail)s", {'detail': six.text_type(e)})
|
||||||
|
raise e
|
||||||
|
|
||||||
|
# Retrive ports
|
||||||
|
params = {
|
||||||
|
'limit': 0,
|
||||||
|
'fields': ('uuid', 'node_uuid', 'extra', 'address',
|
||||||
|
'internal_info')
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
port_list = self.ironicclient.call("port.list", **params)
|
||||||
|
except client_e.ClientException as e:
|
||||||
|
LOG.exception("Could not get ports from ironic. Reason: "
|
||||||
|
"%(detail)s", {'detail': six.text_type(e)})
|
||||||
|
port_list = []
|
||||||
|
|
||||||
|
# Retrive portgroups
|
||||||
|
try:
|
||||||
|
portgroup_list = self.ironicclient.call("portgroup.list", **params)
|
||||||
|
except client_e.ClientException as e:
|
||||||
|
LOG.exception("Could not get portgroups from ironic. Reason: "
|
||||||
|
"%(detail)s", {'detail': six.text_type(e)})
|
||||||
|
portgroup_list = []
|
||||||
|
|
||||||
|
node_resources = {}
|
||||||
|
for node in node_list:
|
||||||
|
if node.resource_class is None:
|
||||||
|
continue
|
||||||
|
# Add ports to the associated node
|
||||||
|
node.ports = [self._port_or_group_resource(port)
|
||||||
|
for port in port_list
|
||||||
|
if node.uuid == port.node_uuid]
|
||||||
|
# Add portgroups to the associated node
|
||||||
|
node.portgroups = [self._port_or_group_resource(portgroup)
|
||||||
|
for portgroup in portgroup_list
|
||||||
|
if node.uuid == portgroup.node_uuid]
|
||||||
|
node_resources[node.uuid] = self._node_resource(node)
|
||||||
|
return node_resources
|
||||||
|
|
||||||
def get_maintenance_node_list(self):
|
def get_maintenance_node_list(self):
|
||||||
"""Helper function to return the list of maintenance nodes.
|
"""Helper function to return the list of maintenance nodes.
|
||||||
|
|
||||||
@ -602,3 +698,18 @@ class IronicDriver(base_driver.BaseEngineDriver):
|
|||||||
"""
|
"""
|
||||||
return (not node.instance_uuid and node.provision_state ==
|
return (not node.instance_uuid and node.provision_state ==
|
||||||
ironic_states.AVAILABLE)
|
ironic_states.AVAILABLE)
|
||||||
|
|
||||||
|
def get_manageable_nodes(self):
|
||||||
|
nodes = self._get_manageable_nodes()
|
||||||
|
manageable_nodes = []
|
||||||
|
for node_uuid, node in nodes.items():
|
||||||
|
manageable_nodes.append(
|
||||||
|
{'uuid': node_uuid,
|
||||||
|
'name': node.get('name'),
|
||||||
|
'resource_class': node.get('resource_class'),
|
||||||
|
'power_state': node.get('power_state'),
|
||||||
|
'provision_state': node.get('provision_state'),
|
||||||
|
'ports': node.get('ports'),
|
||||||
|
'portgroups': node.get('portgroups'),
|
||||||
|
'image_source': node.get('image_source')})
|
||||||
|
return manageable_nodes
|
||||||
|
@ -464,4 +464,8 @@ class ServerGroupNotFound(NotFound):
|
|||||||
class ServerGroupExists(Conflict):
|
class ServerGroupExists(Conflict):
|
||||||
_msg_fmt = _("Sever group %(group_uuid)s already exists.")
|
_msg_fmt = _("Sever group %(group_uuid)s already exists.")
|
||||||
|
|
||||||
|
|
||||||
|
class GetManageableServersFailed(MoganException):
|
||||||
|
_msg_fmt = _("Failed to get manageable servers from driver: %(reason)s")
|
||||||
|
|
||||||
ObjectActionError = obj_exc.ObjectActionError
|
ObjectActionError = obj_exc.ObjectActionError
|
||||||
|
@ -183,6 +183,9 @@ server_policies = [
|
|||||||
policy.RuleDefault('mogan:server_group:delete',
|
policy.RuleDefault('mogan:server_group:delete',
|
||||||
'rule:default',
|
'rule:default',
|
||||||
description='Delete a server group'),
|
description='Delete a server group'),
|
||||||
|
policy.RuleDefault('mogan:manageable_servers:get_all',
|
||||||
|
'rule:admin_api',
|
||||||
|
description='Get manageable nodes from driver'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -588,3 +588,12 @@ class API(object):
|
|||||||
def list_node_aggregates(self, context, node):
|
def list_node_aggregates(self, context, node):
|
||||||
"""Get the node aggregates list."""
|
"""Get the node aggregates list."""
|
||||||
return self.engine_rpcapi.list_node_aggregates(context, node)
|
return self.engine_rpcapi.list_node_aggregates(context, node)
|
||||||
|
|
||||||
|
def get_manageable_servers(self, context):
|
||||||
|
"""Get manageable servers list"""
|
||||||
|
mservers = []
|
||||||
|
try:
|
||||||
|
mservers = self.engine_rpcapi.get_manageable_servers(context)
|
||||||
|
except Exception as e:
|
||||||
|
raise exception.GetManageableServersFailed(reason=e)
|
||||||
|
return mservers
|
||||||
|
@ -605,3 +605,6 @@ class EngineManager(base_manager.BaseEngineManager):
|
|||||||
aggregates = self.scheduler_client.reportclient \
|
aggregates = self.scheduler_client.reportclient \
|
||||||
.get_aggregates_from_node(node)
|
.get_aggregates_from_node(node)
|
||||||
return aggregates
|
return aggregates
|
||||||
|
|
||||||
|
def get_manageable_servers(self, context):
|
||||||
|
return self.driver.get_manageable_nodes()
|
||||||
|
@ -120,3 +120,7 @@ class EngineAPI(object):
|
|||||||
def list_node_aggregates(self, context, node):
|
def list_node_aggregates(self, context, node):
|
||||||
cctxt = self.client.prepare(topic=self.topic, server=CONF.host)
|
cctxt = self.client.prepare(topic=self.topic, server=CONF.host)
|
||||||
return cctxt.call(context, 'list_node_aggregates', node=node)
|
return cctxt.call(context, 'list_node_aggregates', node=node)
|
||||||
|
|
||||||
|
def get_manageable_servers(self, context):
|
||||||
|
cctxt = self.client.prepare(topic=self.topic, server=CONF.host)
|
||||||
|
return cctxt.call(context, 'get_manageable_servers')
|
||||||
|
48
mogan/tests/unit/api/v1/test_manageable_servers.py
Normal file
48
mogan/tests/unit/api/v1/test_manageable_servers.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2017 Fiberhome
|
||||||
|
#
|
||||||
|
# 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 mock
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from mogan.tests.functional.api import v1 as v1_test
|
||||||
|
|
||||||
|
|
||||||
|
class TestManageableServers(v1_test.APITestV1):
|
||||||
|
|
||||||
|
DENY_MESSAGE = "Access was denied to the following resource: mogan:%s"
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestManageableServers, self).setUp()
|
||||||
|
self.project_id = "0abcdef1-2345-6789-abcd-ef123456abc1"
|
||||||
|
# evil_project is an wicked tenant, is used for unauthorization test.
|
||||||
|
self.evil_project = "0abcdef1-2345-6789-abcd-ef123456abc9"
|
||||||
|
|
||||||
|
def test_server_get_manageable_servers_with_invalid_rule(self):
|
||||||
|
self.context.tenant = self.evil_project
|
||||||
|
headers = self.gen_headers(self.context, roles="no-admin")
|
||||||
|
resp = self.get_json('/manageable_servers', True, headers=headers)
|
||||||
|
error = self.parser_error_body(resp)
|
||||||
|
self.assertEqual(self.DENY_MESSAGE % 'manageable_servers:get_all',
|
||||||
|
error['faultstring'])
|
||||||
|
|
||||||
|
@mock.patch('mogan.engine.api.API.get_manageable_servers')
|
||||||
|
def test_server_get_manageable_servers(self, mock_get):
|
||||||
|
mock_get.return_value = [{'uuid': uuidutils.generate_uuid(),
|
||||||
|
'name': "test_node",
|
||||||
|
'resource_class': "gold"}]
|
||||||
|
self.context.tenant = self.project_id
|
||||||
|
headers = self.gen_headers(self.context, roles="admin")
|
||||||
|
resp = self.get_json('/manageable_servers', headers=headers)
|
||||||
|
self.assertIn("uuid", resp['manageable_servers'][0])
|
@ -202,3 +202,21 @@ class ManageServerTestCase(mgr_utils.ServiceSetUpMixin,
|
|||||||
manager.EngineManager, self.context, server=server)
|
manager.EngineManager, self.context, server=server)
|
||||||
|
|
||||||
self.assertFalse(called['fault_added'])
|
self.assertFalse(called['fault_added'])
|
||||||
|
|
||||||
|
@mock.patch.object(IronicDriver, 'get_manageable_nodes')
|
||||||
|
def test_get_manageable_servers_failed(self, get_manageable_mock):
|
||||||
|
get_manageable_mock.side_effect = exception.MoganException()
|
||||||
|
self._start_service()
|
||||||
|
self.assertRaises(exception.MoganException,
|
||||||
|
self.service.get_manageable_servers,
|
||||||
|
self.context)
|
||||||
|
self._stop_service()
|
||||||
|
get_manageable_mock.assert_called_once()
|
||||||
|
|
||||||
|
@mock.patch.object(IronicDriver, 'get_manageable_nodes')
|
||||||
|
def test_get_manageable_servers(self, get_manageable_mock):
|
||||||
|
get_manageable_mock.return_value = {}
|
||||||
|
self._start_service()
|
||||||
|
self.service.get_manageable_servers(self.context)
|
||||||
|
self._stop_service()
|
||||||
|
get_manageable_mock.assert_called_once()
|
||||||
|
Loading…
Reference in New Issue
Block a user