summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tantsur <divius.inside@gmail.com>2019-04-11 17:02:58 +0200
committerDmitry Tantsur <divius.inside@gmail.com>2019-05-23 17:11:50 +0200
commitc36a01a43994f7f4a8cb0f44bd0859d41cea83cd (patch)
tree8088b7000936535ec9f1e4d339236b94d3ec5911
parent82c853530f28043efc9ca5d93246ed4d5989fa02 (diff)
downloadironic-c36a01a43994f7f4a8cb0f44bd0859d41cea83cd.tar.gz
Publish baremetal endpoint via mdns
This change adds an option to publish the endpoint via mDNS on start up and clean it up on tear down. Story: #2005393 Task: #30383 Change-Id: I55d2e7718a23cde111eaac4e431588184cb16bda
-rw-r--r--ironic/conductor/base_manager.py20
-rw-r--r--ironic/conf/conductor.py3
-rw-r--r--ironic/tests/unit/conductor/test_base_manager.py36
-rw-r--r--lower-constraints.txt2
-rw-r--r--releasenotes/notes/mdns-a5f4034257139e31.yaml6
-rw-r--r--requirements.txt2
-rw-r--r--tools/config/ironic-config-generator.conf1
7 files changed, 68 insertions, 2 deletions
diff --git a/ironic/conductor/base_manager.py b/ironic/conductor/base_manager.py
index c08c8702b..31d947192 100644
--- a/ironic/conductor/base_manager.py
+++ b/ironic/conductor/base_manager.py
@@ -19,6 +19,7 @@ import eventlet
import futurist
from futurist import periodics
from futurist import rejection
+from ironic_lib import mdns
from oslo_db import exception as db_exception
from oslo_log import log
from oslo_utils import excutils
@@ -39,6 +40,7 @@ from ironic.conductor import task_manager
from ironic.conf import CONF
from ironic.db import api as dbapi
from ironic.drivers import base as driver_base
+from ironic.drivers.modules import deploy_utils
from ironic import objects
from ironic.objects import fields as obj_fields
@@ -78,6 +80,7 @@ class BaseConductorManager(object):
self.sensors_notifier = rpc.get_sensors_notifier()
self._started = False
self._shutdown = None
+ self._zeroconf = None
def init_host(self, admin_context=None):
"""Initialize the conductor host.
@@ -212,6 +215,9 @@ class BaseConductorManager(object):
except exception.NoFreeConductorWorker:
LOG.warning('Failed to start worker for resuming allocations.')
+ if CONF.conductor.enable_mdns:
+ self._publish_endpoint()
+
self._started = True
def _use_groups(self):
@@ -316,6 +322,11 @@ class BaseConductorManager(object):
self._periodic_tasks.stop()
self._periodic_tasks.wait()
self._executor.shutdown(wait=True)
+
+ if self._zeroconf is not None:
+ self._zeroconf.close()
+ self._zeroconf = None
+
self._started = False
def _register_and_validate_hardware_interfaces(self, hardware_types):
@@ -564,3 +575,12 @@ class BaseConductorManager(object):
for allocation in objects.Allocation.list(context, filters=filters):
LOG.debug('Resuming unfinished allocation %s', allocation.uuid)
allocations.do_allocate(context, allocation)
+
+ def _publish_endpoint(self):
+ params = {}
+ if CONF.debug:
+ params['ipa_debug'] = True
+ self._zeroconf = mdns.Zeroconf()
+ self._zeroconf.register_service('baremetal',
+ deploy_utils.get_ironic_api_url(),
+ params=params)
diff --git a/ironic/conf/conductor.py b/ironic/conf/conductor.py
index 039574e4e..05ecd2066 100644
--- a/ironic/conf/conductor.py
+++ b/ironic/conf/conductor.py
@@ -221,6 +221,9 @@ opts = [
mutable=True,
help=_('Allow deleting nodes which are in state '
'\'available\'. Defaults to True.')),
+ cfg.BoolOpt('enable_mdns', default=False,
+ help=_('Whether to enable publishing the ironic-inspector API '
+ 'endpoint via multicast DNS.')),
]
diff --git a/ironic/tests/unit/conductor/test_base_manager.py b/ironic/tests/unit/conductor/test_base_manager.py
index 0c619d912..02bd171f9 100644
--- a/ironic/tests/unit/conductor/test_base_manager.py
+++ b/ironic/tests/unit/conductor/test_base_manager.py
@@ -18,6 +18,7 @@ import uuid
import eventlet
import futurist
from futurist import periodics
+from ironic_lib import mdns
import mock
from oslo_config import cfg
from oslo_db import exception as db_exception
@@ -32,6 +33,7 @@ from ironic.conductor import notification_utils
from ironic.conductor import task_manager
from ironic.drivers import fake_hardware
from ironic.drivers import generic
+from ironic.drivers.modules import deploy_utils
from ironic.drivers.modules import fake
from ironic import objects
from ironic.objects import fields
@@ -247,6 +249,40 @@ class StartStopTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
self.service.del_host()
self.assertTrue(self.service._shutdown)
+ @mock.patch.object(deploy_utils, 'get_ironic_api_url', autospec=True)
+ @mock.patch.object(mdns, 'Zeroconf', autospec=True)
+ def test_start_with_mdns(self, mock_zc, mock_api_url):
+ CONF.set_override('debug', False)
+ CONF.set_override('enable_mdns', True, 'conductor')
+ self._start_service()
+ res = objects.Conductor.get_by_hostname(self.context, self.hostname)
+ self.assertEqual(self.hostname, res['hostname'])
+ mock_zc.return_value.register_service.assert_called_once_with(
+ 'baremetal',
+ mock_api_url.return_value,
+ params={})
+
+ @mock.patch.object(deploy_utils, 'get_ironic_api_url', autospec=True)
+ @mock.patch.object(mdns, 'Zeroconf', autospec=True)
+ def test_start_with_mdns_and_debug(self, mock_zc, mock_api_url):
+ CONF.set_override('debug', True)
+ CONF.set_override('enable_mdns', True, 'conductor')
+ self._start_service()
+ res = objects.Conductor.get_by_hostname(self.context, self.hostname)
+ self.assertEqual(self.hostname, res['hostname'])
+ mock_zc.return_value.register_service.assert_called_once_with(
+ 'baremetal',
+ mock_api_url.return_value,
+ params={'ipa_debug': True})
+
+ def test_del_host_with_mdns(self):
+ mock_zc = mock.Mock(spec=mdns.Zeroconf)
+ self.service._zeroconf = mock_zc
+ self._start_service()
+ self.service.del_host()
+ mock_zc.close.assert_called_once_with()
+ self.assertIsNone(self.service._zeroconf)
+
class CheckInterfacesTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
def test__check_enabled_interfaces_success(self):
diff --git a/lower-constraints.txt b/lower-constraints.txt
index 3676081f1..859c21044 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -38,7 +38,7 @@ greenlet==0.4.13
hacking==1.0.0
idna==2.6
imagesize==1.0.0
-ironic-lib==2.15.0
+ironic-lib==2.17.0
iso8601==0.1.11
Jinja2==2.10
jmespath==0.9.3
diff --git a/releasenotes/notes/mdns-a5f4034257139e31.yaml b/releasenotes/notes/mdns-a5f4034257139e31.yaml
new file mode 100644
index 000000000..8bb4327e7
--- /dev/null
+++ b/releasenotes/notes/mdns-a5f4034257139e31.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ A new option ``enable_mdns`` allows to enable publishing the baremetal
+ API endpoint via mDNS as specified in the `API SIG guideline
+ <http://specs.openstack.org/openstack/api-sig/guidelines/dns-sd.html>`_.
diff --git a/requirements.txt b/requirements.txt
index ab973569d..be3c0992b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,7 +11,7 @@ python-cinderclient>=3.3.0 # Apache-2.0
python-neutronclient>=6.7.0 # Apache-2.0
python-glanceclient>=2.8.0 # Apache-2.0
keystoneauth1>=3.4.0 # Apache-2.0
-ironic-lib>=2.15.0 # Apache-2.0
+ironic-lib>=2.17.0 # Apache-2.0
python-swiftclient>=3.2.0 # Apache-2.0
pytz>=2013.6 # MIT
stevedore>=1.20.0 # Apache-2.0
diff --git a/tools/config/ironic-config-generator.conf b/tools/config/ironic-config-generator.conf
index 5412c9159..806bf7a03 100644
--- a/tools/config/ironic-config-generator.conf
+++ b/tools/config/ironic-config-generator.conf
@@ -4,6 +4,7 @@ wrap_width = 62
namespace = ironic
namespace = ironic_lib.disk_utils
namespace = ironic_lib.disk_partitioner
+namespace = ironic_lib.mdns
namespace = ironic_lib.metrics
namespace = ironic_lib.metrics_statsd
namespace = ironic_lib.utils