Stabilized API, update README

This commit is contained in:
Dmitry Tantsur 2014-10-06 12:16:08 +02:00
parent de3f143781
commit d8bd1a78c3
4 changed files with 43 additions and 20 deletions

View File

@ -1,5 +1,5 @@
Hardware discovery for OpenStack Ironic
=======================================
Hardware properties discovery for OpenStack Ironic
==================================================
.. image:: https://travis-ci.org/Divius/ironic-discoverd.svg?branch=master
:target: https://travis-ci.org/Divius/ironic-discoverd
@ -21,3 +21,27 @@ Or you can test locally::
Of course you may want to modify *example.conf* to match your OpenStack
environment.
API
---
HTTP API consist of 2 endpoints.
``/v1/discover`` initiate hardware discovery. Request body: JSON - list of
UUID's of nodes to discover. All power management configuration for these nodes
needs to be done prior to calling the endpoint.
.. note::
Right now this endpoint is not authenticated. It will switch to
OpenStack authentication in the near future.
``/v1/continue`` intertnal endpoint for the discovery ramdisk to post back
discovered data. Should not be used fofr anything other than implementing
the ramdisk. Request body: JSON dictionary with keys:
* ``cpus`` number of CPU
* ``cpu_arch`` architecture of the CPU
* ``memory_mb`` RAM in MiB
* ``local_gb`` hard drive size in GiB
* ``macs`` list of MAC addresses for all NIC's

View File

@ -12,7 +12,7 @@ from ironic_discoverd.discoverd import (CONF, LOG, process, start,
app = Flask(__name__)
@app.route('/continue', methods=['POST'])
@app.route('/v1/continue', methods=['POST'])
def post_continue():
data = request.get_json(force=True)
LOG.debug("Got JSON %s, going into processing thread", data)
@ -20,8 +20,8 @@ def post_continue():
return "{}", 202, {"content-type": "application/json"}
@app.route('/start', methods=['POST'])
def post_start():
@app.route('/v1/discover', methods=['POST'])
def post_discover():
data = request.get_json(force=True)
LOG.debug("Got JSON %s, going into processing thread", data)
threading.Thread(target=start, args=(data,)).start()

View File

@ -97,9 +97,8 @@ def process(node_info):
'allowed')
return
if not node.maintenance:
LOG.error('Refusing to apply discovered data to node %s '
'which is not in maintenance state', node.uuid)
if not node.extra.get('on_discovery'):
LOG.error('Node is not on discovery, cannot proceed')
return
patch = [{'op': 'add', 'path': '/extra/newly_discovered', 'value': 'true'}]
@ -200,11 +199,12 @@ class Firewall(object):
cls._iptables('-E', cls.NEW_CHAIN, cls.CHAIN)
def start(uuids):
def discover(uuids):
"""Initiate discovery for given node uuids."""
ironic = get_client()
LOG.debug('Validating nodes %s', uuids)
nodes = []
patch = [{'op': 'add', 'path': '/extra/on_discovery', 'value': 'true'}]
for uuid in uuids:
try:
node = ironic.node.get(uuid)
@ -212,9 +212,7 @@ def start(uuids):
LOG.exception('Failed validation of node %s', uuid)
continue
if not node.maintenance:
LOG.error('Node %s not in maintenance - skipping', uuid)
continue
ironic.node.update(uuid, patch)
nodes.append(node)

View File

@ -12,9 +12,9 @@ from ironic_discoverd import discoverd
class TestProcess(unittest.TestCase):
def setUp(self):
self.node = Mock(driver_info={},
maintenance=True,
properties={'cpu_arch': 'i386', 'local_gb': 40},
uuid='uuid')
uuid='uuid',
extra={'on_discovery': 'true'})
self.patch = [
{'op': 'add', 'path': '/extra/newly_discovered', 'value': 'true'},
{'op': 'add', 'path': '/properties/cpus', 'value': '2'},
@ -83,13 +83,11 @@ class TestProcess(unittest.TestCase):
@patch.object(discoverd.Firewall, 'update_filters')
@patch.object(discoverd, 'get_client')
class TestStart(unittest.TestCase):
class TestDiscover(unittest.TestCase):
def setUp(self):
self.node1 = Mock(driver='pxe_ssh',
maintenance=True,
uuid='uuid1')
self.node2 = Mock(driver='pxe_ipmitool',
maintenance=True,
uuid='uuid2')
discoverd.Firewall.MACS_DISCOVERY = set()
@ -98,18 +96,21 @@ class TestStart(unittest.TestCase):
cli.node.get.side_effect = [
exceptions.NotFound(),
self.node1,
Mock(maintenance=False),
exceptions.Conflict(),
self.node2,
]
cli.node.list_ports.return_value = [Mock(address='1'),
Mock(address='2')]
discoverd.start(['uuid%d' % i for i in range(5)])
discoverd.discover(['uuid%d' % i for i in range(4)])
self.assertEqual(5, cli.node.get.call_count)
self.assertEqual(4, cli.node.get.call_count)
cli.node.list_ports.assert_called_once_with('uuid1', limit=0)
filters_mock.assert_called_once_with(cli)
self.assertEqual(set(['1', '2']), discoverd.Firewall.MACS_DISCOVERY)
self.assertEqual(2, cli.node.set_power_state.call_count)
cli.node.set_power_state.assert_called_with(ANY, 'on')
patch = [{'op': 'add', 'path': '/extra/on_discovery', 'value': 'true'}]
cli.node.update.assert_any_call('uuid1', patch)
cli.node.update.assert_any_call('uuid3', patch)
self.assertEqual(2, cli.node.update.call_count)