Merge "Allow for composition via flavor"
This commit is contained in:
commit
0db8a8e186
@ -1,4 +1,17 @@
|
||||
{
|
||||
"name": "test_node",
|
||||
"description": "node1",
|
||||
"properties": {
|
||||
"memory": {
|
||||
"capacity_mib": "8000",
|
||||
"type": "DDR2"
|
||||
},
|
||||
"processor": {
|
||||
"model": "Multi-Core Intel(R) Xeon(R) processor 7xxx Series",
|
||||
"total_cores": "2"
|
||||
},
|
||||
"remote_storage": {
|
||||
"capacity_gib": "100"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,6 +188,12 @@ node_processor_asset:
|
||||
in: body
|
||||
required: true
|
||||
type: array
|
||||
node_properties:
|
||||
description: |
|
||||
Dictionary of properties of a composed node.
|
||||
in: body
|
||||
required: false
|
||||
type: dictionary
|
||||
node_property:
|
||||
description: |
|
||||
Property of composed node including processor , memory , storage info.
|
||||
|
@ -29,6 +29,8 @@ Request
|
||||
|
||||
- name: node_request_name
|
||||
- description: node_request_description
|
||||
- flavor_id: flavor_uuid
|
||||
- properties: node_properties
|
||||
|
||||
**Example Node creation request:**
|
||||
|
||||
|
@ -24,6 +24,11 @@ def list_flavors():
|
||||
return [flavor.as_dict() for flavor in flavor_models]
|
||||
|
||||
|
||||
def get_flavor(flavorid):
|
||||
flavor = db_api.Connection.get_flavor_by_uuid(flavorid)
|
||||
return flavor.as_dict()
|
||||
|
||||
|
||||
def create_flavor(values):
|
||||
flavor = db_api.Connection.create_flavor(values)
|
||||
return flavor.as_dict()
|
||||
|
@ -15,6 +15,7 @@
|
||||
import six
|
||||
|
||||
from valence.common import utils
|
||||
from valence.controller import flavors
|
||||
from valence.db import api as db_api
|
||||
from valence.redfish import redfish
|
||||
|
||||
@ -26,6 +27,32 @@ class Node(object):
|
||||
return {key: node_info[key] for key in six.iterkeys(node_info)
|
||||
if key in ["uuid", "name", "links"]}
|
||||
|
||||
@staticmethod
|
||||
def _create_compose_request(name, description, requirements):
|
||||
request = {}
|
||||
|
||||
request["Name"] = name
|
||||
request["Description"] = description
|
||||
|
||||
memory = {}
|
||||
if "memory" in requirements:
|
||||
if "capacity_mib" in requirements["memory"]:
|
||||
memory["CapacityMiB"] = requirements["memory"]["capacity_mib"]
|
||||
if "type" in requirements["memory"]:
|
||||
memory["DimmDeviceType"] = requirements["memory"]["type"]
|
||||
request["Memory"] = [memory]
|
||||
|
||||
processor = {}
|
||||
if "processor" in requirements:
|
||||
if "model" in requirements["processor"]:
|
||||
processor["Model"] = requirements["processor"]["model"]
|
||||
if "total_cores" in requirements["processor"]:
|
||||
processor["TotalCores"] = (
|
||||
requirements["processor"]["total_cores"])
|
||||
request["Processors"] = [processor]
|
||||
|
||||
return request
|
||||
|
||||
@classmethod
|
||||
def compose_node(cls, request_body):
|
||||
"""Compose new node
|
||||
@ -34,8 +61,26 @@ class Node(object):
|
||||
return: brief info of this new composed node
|
||||
"""
|
||||
|
||||
if "flavor_id" in request_body:
|
||||
flavor = flavors.get_flavor(request_body["flavor_id"])
|
||||
requirements = flavor["properties"]
|
||||
elif "properties" in request_body:
|
||||
requirements = request_body["properties"]
|
||||
else:
|
||||
requirements = {
|
||||
"memory": {},
|
||||
"processor": {}
|
||||
}
|
||||
|
||||
name = request_body["name"]
|
||||
description = request_body["description"]
|
||||
|
||||
compose_request = cls._create_compose_request(name,
|
||||
description,
|
||||
requirements)
|
||||
|
||||
# Call redfish to compose new node
|
||||
composed_node = redfish.compose_node(request_body)
|
||||
composed_node = redfish.compose_node(compose_request)
|
||||
|
||||
composed_node["uuid"] = utils.generate_uuid()
|
||||
|
||||
|
@ -46,7 +46,7 @@ def get_test_composed_node(**kwargs):
|
||||
'vlans': [{'status': 'Enabled',
|
||||
'vlanid': 99}]}],
|
||||
'processor': [{'instruction_set': None,
|
||||
'model': None,
|
||||
'model': 'None',
|
||||
'speed_mhz': 3700,
|
||||
'total_core': 0}]})
|
||||
'total_core': 2}]})
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import mock
|
||||
from valence.controller import nodes
|
||||
from valence.tests.unit.controller import fakes
|
||||
from valence.tests.unit.db import utils as test_utils
|
||||
from valence.tests.unit.fakes import flavor_fakes
|
||||
|
||||
|
||||
class TestAPINodes(unittest.TestCase):
|
||||
@ -39,6 +40,37 @@ class TestAPINodes(unittest.TestCase):
|
||||
self.assertEqual(expected,
|
||||
nodes.Node._show_node_brief_info(node_info))
|
||||
|
||||
def test_create_compose_request(self):
|
||||
name = "test_request"
|
||||
description = "request for testing purposes"
|
||||
requirements = {
|
||||
"memory": {
|
||||
"capacity_mib": "4000",
|
||||
"type": "DDR3"
|
||||
},
|
||||
"processor": {
|
||||
"model": "Intel",
|
||||
"total_cores": "4"
|
||||
}
|
||||
}
|
||||
|
||||
expected = {
|
||||
"Name": "test_request",
|
||||
"Description": "request for testing purposes",
|
||||
"Memory": [{
|
||||
"CapacityMiB": "4000",
|
||||
"DimmDeviceType": "DDR3"
|
||||
}],
|
||||
"Processors": [{
|
||||
"Model": "Intel",
|
||||
"TotalCores": "4"
|
||||
}]
|
||||
}
|
||||
result = nodes.Node._create_compose_request(name,
|
||||
description,
|
||||
requirements)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
@mock.patch("valence.db.api.Connection.create_composed_node")
|
||||
@mock.patch("valence.common.utils.generate_uuid")
|
||||
@mock.patch("valence.redfish.redfish.compose_node")
|
||||
@ -55,12 +87,46 @@ class TestAPINodes(unittest.TestCase):
|
||||
uuid = 'ea8e2a25-2901-438d-8157-de7ffd68d051'
|
||||
mock_generate_uuid.return_value = uuid
|
||||
|
||||
result = nodes.Node.compose_node({"name": "test"})
|
||||
result = nodes.Node.compose_node(
|
||||
{"name": node_hw["name"],
|
||||
"description": node_hw["description"]})
|
||||
expected = nodes.Node._show_node_brief_info(node_hw)
|
||||
|
||||
self.assertEqual(expected, result)
|
||||
mock_db_create_composed_node.assert_called_once_with(node_db)
|
||||
|
||||
@mock.patch("valence.db.api.Connection.create_composed_node")
|
||||
@mock.patch("valence.common.utils.generate_uuid")
|
||||
@mock.patch("valence.redfish.redfish.compose_node")
|
||||
@mock.patch("valence.controller.flavors.get_flavor")
|
||||
def test_compose_node_with_flavor(self, mock_get_flavor,
|
||||
mock_redfish_compose_node,
|
||||
mock_generate_uuid,
|
||||
mock_db_create_composed_node):
|
||||
"""Test node composition using a flavor for requirements"""
|
||||
node_hw = fakes.get_test_composed_node()
|
||||
node_db = {"uuid": node_hw["uuid"],
|
||||
"index": node_hw["index"],
|
||||
"name": node_hw["name"],
|
||||
"links": node_hw["links"]}
|
||||
|
||||
mock_redfish_compose_node.return_value = node_hw
|
||||
uuid = 'ea8e2a25-2901-438d-8157-de7ffd68d051'
|
||||
mock_generate_uuid.return_value = uuid
|
||||
|
||||
flavor = flavor_fakes.fake_flavor()
|
||||
mock_get_flavor.return_value = flavor
|
||||
|
||||
result = nodes.Node.compose_node(
|
||||
{"name": node_hw["name"],
|
||||
"description": node_hw["description"],
|
||||
"flavor_id": flavor["uuid"]})
|
||||
expected = nodes.Node._show_node_brief_info(node_hw)
|
||||
|
||||
self.assertEqual(expected, result)
|
||||
mock_db_create_composed_node.assert_called_once_with(node_db)
|
||||
mock_get_flavor.assert_called_once_with(flavor["uuid"])
|
||||
|
||||
@mock.patch("valence.redfish.redfish.get_node_by_id")
|
||||
@mock.patch("valence.db.api.Connection.get_composed_node_by_uuid")
|
||||
def test_get_composed_node_by_uuid(
|
||||
|
@ -23,7 +23,7 @@ def fake_flavor():
|
||||
"type": "DDR2"
|
||||
},
|
||||
"processor": {
|
||||
"total_cores": "10",
|
||||
"total_cores": "2",
|
||||
"model": "Intel"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user