Stabilized API, update README
This commit is contained in:
parent
de3f143781
commit
d8bd1a78c3
28
README.rst
28
README.rst
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue