PXE validate() to fail if no Ironic API URL

As part of the deploy process the conductor should pass the URL of the
Ironic API to the deploy ramdisk so that it can talk back to the Ironic
API, but if the URL is not present in the Ironic configuration file or
in the keystone catalog the deploy process will fail in the middle. This
patch adds a verification to the validate() method to make sure the URL
is present before the deploy starts.

Related-Bug: #1290482
Change-Id: I95472660deff0e23a19d0b744f711bbe3acc2191
This commit is contained in:
Lucas Alvares Gomes 2014-03-11 10:52:34 +00:00
parent 1f8b8d7e54
commit 9a4ce89730
2 changed files with 49 additions and 0 deletions

View File

@ -544,6 +544,17 @@ class PXEDeploy(base.DeployInterface):
"any port associated with it.") % node.uuid)
_parse_driver_info(node)
# Try to get the URL of the Ironic API
try:
# TODO(lucasagomes): Validate the format of the URL
CONF.conductor.api_url or keystone.get_service_url()
except (exception.CatalogFailure,
exception.CatalogNotFound,
exception.CatalogUnauthorized):
raise exception.InvalidParameterValue(_(
"Couldn't get the URL of the Ironic API service from the "
"configuration file or keystone catalog."))
@task_manager.require_exclusive_lock
def deploy(self, task, node):
"""Perform start deployment a node.

View File

@ -30,6 +30,7 @@ from ironic.common import exception
from ironic.common.glance_service import base_image_service
from ironic.common.glance_service import service_utils
from ironic.common import images
from ironic.common import keystone
from ironic.common import neutron
from ironic.common import states
from ironic.common import utils
@ -614,6 +615,7 @@ class PXEDriverTestCase(db_base.DbTestCase):
self.node = self.dbapi.create_node(n)
self.port = self.dbapi.create_port(db_utils.get_test_port(
node_id=self.node.id))
self.config(group='conductor', api_url='http://127.0.0.1:1234/')
def _create_token_file(self):
token_path = pxe._get_token_file_path(self.node['uuid'])
@ -645,6 +647,42 @@ class PXEDriverTestCase(db_base.DbTestCase):
task.resources[0].driver.deploy.validate,
task, new_node)
@mock.patch.object(keystone, 'get_service_url')
def test_validate_good_api_url_from_config_file(self, mock_ks):
# not present in the keystone catalog
mock_ks.side_effect = exception.CatalogFailure
with task_manager.acquire(self.context, [self.node.uuid],
shared=True) as task:
task.resources[0].driver.deploy.validate(task, self.node)
self.assertFalse(mock_ks.called)
@mock.patch.object(keystone, 'get_service_url')
def test_validate_good_api_url_from_keystone(self, mock_ks):
# present in the keystone catalog
mock_ks.return_value = 'http://127.0.0.1:1234'
# not present in the config file
self.config(group='conductor', api_url=None)
with task_manager.acquire(self.context, [self.node.uuid],
shared=True) as task:
task.resources[0].driver.deploy.validate(task, self.node)
mock_ks.assert_called_once_with()
@mock.patch.object(keystone, 'get_service_url')
def test_validate_fail_no_api_url(self, mock_ks):
# not present in the keystone catalog
mock_ks.side_effect = exception.CatalogFailure
# not present in the config file
self.config(group='conductor', api_url=None)
with task_manager.acquire(self.context, [self.node.uuid],
shared=True) as task:
self.assertRaises(exception.InvalidParameterValue,
task.resources[0].driver.deploy.validate,
task, self.node)
mock_ks.assert_called_once_with()
def test__get_nodes_mac_addresses(self):
ports = []
ports.append(self.port)