def test_get_service_url_versionless_v3(self, mock_ks): mock_ks.return_value = FakeClient() self.config(group="keystone_authtoken", auth_version="v3.0", auth_uri="http://127.0.0.1") expected_url = "http://127.0.0.1/v3" keystone.get_service_url() mock_ks.assert_called_once_with( username="******", password="******", tenant_name="fake", region_name="fake", auth_url=expected_url )
def test_get_service_url_versionless_v2(self, mock_ks): mock_ks.return_value = FakeClient() self.config(group='keystone_authtoken', auth_uri='http://127.0.0.1') expected_url = 'http://127.0.0.1/v2.0' keystone.get_service_url() mock_ks.assert_called_once_with(username='******', password='******', tenant_name='fake', auth_url=expected_url)
def test_get_region_name_v2(self, mock_ks): mock_ks.return_value = FakeClient() self.config(group="keystone", region_name="fake_region") expected_url = "http://127.0.0.1:9898/v2.0" expected_region = "fake_region" keystone.get_service_url() mock_ks.assert_called_once_with( username="******", password="******", tenant_name="fake", region_name=expected_region, auth_url=expected_url )
def test_get_region_name_v2(self, mock_ks): mock_ks.return_value = FakeClient() self.config(group='keystone', region_name='fake_region') expected_url = 'http://127.0.0.1:9898/v2.0' expected_region = 'fake_region' keystone.get_service_url() mock_ks.assert_called_once_with(username='******', password='******', tenant_name='fake', region_name=expected_region, auth_url=expected_url)
def test_get_region_name_v3(self, mock_ks): mock_ks.return_value = FakeClient() self.config(group='keystone', region_name='fake_region') self.config(group='keystone_authtoken', auth_version='v3.0') expected_url = 'http://127.0.0.1:9898/v3' expected_region = 'fake_region' keystone.get_service_url() mock_ks.assert_called_once_with(username='******', password='******', tenant_name='fake', region_name=expected_region, auth_url=expected_url)
def validate(task): """Validates the pre-requisites for iSCSI deploy. Validates whether node in the task provided has some ports enrolled. This method validates whether conductor url is available either from CONF file or from keystone. :param task: a TaskManager instance containing the node to act on. :raises: InvalidParameterValue if the URL of the Ironic API service is not configured in config file and is not accessible via Keystone catalog. :raises: MissingParameterValue if no ports are enrolled for the given node. """ try: # TODO(lucasagomes): Validate the format of the URL CONF.conductor.api_url or keystone.get_service_url() except (exception.KeystoneFailure, exception.CatalogNotFound, exception.KeystoneUnauthorized) as e: raise exception.InvalidParameterValue(_( "Couldn't get the URL of the Ironic API service from the " "configuration file or keystone catalog. Keystone error: %s") % e) # Validate the root device hints deploy_utils.parse_root_device_hints(task.node) parse_instance_info(task.node)
def _get_api_server_iterator(): """Return iterator over shuffled API servers. Shuffle a list of CONF.glance.glance_api_servers and return an iterator that will cycle through the list, looping around to the beginning if necessary. If CONF.glance.glance_api_servers isn't set, fetch the endpoint from the service catalog. :returns: iterator that cycles (indefinitely) over shuffled glance API servers. """ api_servers = [] if not CONF.glance.glance_api_servers: session = keystone.get_session('glance', auth=keystone.get_auth('glance')) api_servers = [ keystone.get_service_url(session, service_type='image', endpoint_type='public') ] else: api_servers = random.sample(CONF.glance.glance_api_servers, len(CONF.glance.glance_api_servers)) return itertools.cycle(api_servers)
def _get_api_server_iterator(): """Return iterator over shuffled API servers. Shuffle a list of CONF.glance.glance_api_servers and return an iterator that will cycle through the list, looping around to the beginning if necessary. If CONF.glance.glance_api_servers isn't set, we fall back to using this as the server: CONF.glance.glance_host:CONF.glance.glance_port. If CONF.glance.glance_host is also not set, fetch the endpoint from the service catalog. :returns: iterator that cycles (indefinitely) over shuffled glance API servers. """ api_servers = [] if not CONF.glance.glance_api_servers and not CONF.glance.glance_host: session = keystone.get_session('glance', auth=keystone.get_auth('glance')) api_servers = [keystone.get_service_url(session, service_type='image', endpoint_type='public')] else: configured_servers = (CONF.glance.glance_api_servers or ['%s:%s' % (CONF.glance.glance_host, CONF.glance.glance_port)]) for api_server in configured_servers: if '//' not in api_server: api_server = '%s://%s' % (CONF.glance.glance_protocol, api_server) api_servers.append(api_server) random.shuffle(api_servers) return itertools.cycle(api_servers)
def __init__(self, context): self.context = context self.client = None params = { 'timeout': CONF.neutron.url_timeout, 'insecure': CONF.keystone_authtoken.insecure, 'ca_cert': CONF.keystone_authtoken.certfile, } if CONF.neutron.auth_strategy not in ['noauth', 'keystone']: raise exception.ConfigInvalid(_('Neutron auth_strategy should be ' 'either "noauth" or "keystone".')) if CONF.neutron.auth_strategy == 'noauth': params['endpoint_url'] = CONF.neutron.url params['auth_strategy'] = 'noauth' elif (CONF.neutron.auth_strategy == 'keystone' and context.auth_token is None): params['endpoint_url'] = (CONF.neutron.url or keystone.get_service_url('neutron')) params['username'] = CONF.keystone_authtoken.admin_user params['tenant_name'] = CONF.keystone_authtoken.admin_tenant_name params['password'] = CONF.keystone_authtoken.admin_password params['auth_url'] = (CONF.keystone_authtoken.auth_uri or '') else: params['token'] = context.auth_token params['endpoint_url'] = CONF.neutron.url params['auth_strategy'] = None self.client = clientv20.Client(**params)
def validate(self, task): """Validate the deployment information for the task's node. :param task: a TaskManager instance containing the node to act on. :raises: InvalidParameterValue. """ node = task.node if not driver_utils.get_node_mac_addresses(task): raise exception.InvalidParameterValue(_("Node %s does not have " "any port associated with it.") % node.uuid) d_info = _parse_deploy_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.")) _validate_glance_image(task.context, d_info)
def test_get_service_url_internal(self): session = mock.Mock() session.get_endpoint.return_value = 'spam' params = {'ham': 'eggs'} self.assertEqual('spam', keystone.get_service_url(session, **params)) session.get_endpoint.assert_called_once_with(interface='internal', **params)
def _build_client(token=None): """Utility function to create Neutron client.""" params = { "timeout": CONF.neutron.url_timeout, "retries": CONF.neutron.retries, "insecure": CONF.keystone_authtoken.insecure, "ca_cert": CONF.keystone_authtoken.certfile, } if CONF.neutron.auth_strategy not in ["noauth", "keystone"]: raise exception.ConfigInvalid(_("Neutron auth_strategy should be " 'either "noauth" or "keystone".')) if CONF.neutron.auth_strategy == "noauth": params["endpoint_url"] = CONF.neutron.url params["auth_strategy"] = "noauth" elif CONF.neutron.auth_strategy == "keystone" and token is None: params["endpoint_url"] = CONF.neutron.url or keystone.get_service_url("neutron") params["username"] = CONF.keystone_authtoken.admin_user params["tenant_name"] = CONF.keystone_authtoken.admin_tenant_name params["password"] = CONF.keystone_authtoken.admin_password params["auth_url"] = CONF.keystone_authtoken.auth_uri or "" if CONF.keystone.region_name: params["region_name"] = CONF.keystone.region_name else: params["token"] = token params["endpoint_url"] = CONF.neutron.url params["auth_strategy"] = None return clientv20.Client(**params)
def validate(task): """Validates the pre-requisites for iSCSI deploy. Validates whether node in the task provided has some ports enrolled. This method validates whether conductor url is available either from CONF file or from keystone. :param task: a TaskManager instance containing the node to act on. :raises: InvalidParameterValue if the URL of the Ironic API service is not configured in config file and is not accessible via Keystone catalog. :raises: MissingParameterValue if no ports are enrolled for the given node. """ try: # TODO(lucasagomes): Validate the format of the URL CONF.conductor.api_url or keystone.get_service_url() except (exception.KeystoneFailure, exception.CatalogNotFound, exception.KeystoneUnauthorized) as e: raise exception.InvalidParameterValue( _( "Couldn't get the URL of the Ironic API service from the " "configuration file or keystone catalog. Keystone error: %s" ) % e ) # Validate the root device hints deploy_utils.parse_root_device_hints(task.node) parse_instance_info(task.node)
def _build_pxe_config_options(self, task, pxe_info, live_boot): """Builds the pxe config options for booting agent. This method builds the config options to be replaced on the agent pxe config template. :param task: a TaskManager instance :param pxe_info: A dict containing the 'deploy_kernel' and 'deploy_ramdisk' for the agent pxe config template. :returns: a dict containing the options to be applied on the agent pxe config template. """ ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') agent_config_opts = { 'deployment_aki_path': pxe_info['deploy_kernel'][1], 'deployment_ari_path': pxe_info['deploy_ramdisk'][1], 'bareon_pxe_append_params': CONF.bareon.bareon_pxe_append_params, 'deployment_id': task.node.uuid, 'api-url': ironic_api, } if live_boot: agent_config_opts['rootfs-url'] = _create_rootfs_link(task) return agent_config_opts
def _build_client(token=None): """Utility function to create Neutron client.""" params = { 'timeout': CONF.neutron.url_timeout, 'retries': CONF.neutron.retries, 'insecure': CONF.keystone_authtoken.insecure, 'ca_cert': CONF.keystone_authtoken.certfile, } if CONF.neutron.auth_strategy not in ['noauth', 'keystone']: raise exception.ConfigInvalid(_('Neutron auth_strategy should be ' 'either "noauth" or "keystone".')) if CONF.neutron.auth_strategy == 'noauth': params['endpoint_url'] = CONF.neutron.url params['auth_strategy'] = 'noauth' elif (CONF.neutron.auth_strategy == 'keystone' and token is None): params['endpoint_url'] = (CONF.neutron.url or keystone.get_service_url('neutron')) params['username'] = CONF.keystone_authtoken.admin_user params['tenant_name'] = CONF.keystone_authtoken.admin_tenant_name params['password'] = CONF.keystone_authtoken.admin_password params['auth_url'] = (CONF.keystone_authtoken.auth_uri or '') if CONF.keystone.region_name: params['region_name'] = CONF.keystone.region_name else: params['token'] = token params['endpoint_url'] = CONF.neutron.url params['auth_strategy'] = None return clientv20.Client(**params)
def validate(self, task): """Validate the deployment information for the task's node. :param task: a TaskManager instance containing the node to act on. :raises: InvalidParameterValue. """ node = task.node if not driver_utils.get_node_mac_addresses(task): raise exception.InvalidParameterValue( _("Node %s does not have " "any port associated with it.") % node.uuid) d_info = _parse_deploy_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.")) _validate_glance_image(task.context, d_info)
def _build_client(token=None): """Utility function to create Neutron client.""" params = { 'timeout': CONF.neutron.url_timeout, 'retries': CONF.neutron.retries, 'insecure': CONF.keystone_authtoken.insecure, 'ca_cert': CONF.keystone_authtoken.certfile, } if CONF.neutron.auth_strategy == 'noauth': params['endpoint_url'] = CONF.neutron.url params['auth_strategy'] = 'noauth' else: params['endpoint_url'] = ( CONF.neutron.url or keystone.get_service_url(service_type='network')) params['username'] = CONF.keystone_authtoken.admin_user params['tenant_name'] = CONF.keystone_authtoken.admin_tenant_name params['password'] = CONF.keystone_authtoken.admin_password params['auth_url'] = (CONF.keystone_authtoken.auth_uri or '') if CONF.keystone.region_name: params['region_name'] = CONF.keystone.region_name params['token'] = token return clientv20.Client(**params)
def build_deploy_ramdisk_options(node): """Build the ramdisk config options for a node This method builds the ramdisk options for a node, given all the required parameters for doing iscsi deploy. :param node: a single Node. :returns: A dictionary of options to be passed to ramdisk for performing the deploy. """ # NOTE: we should strip '/' from the end because this is intended for # hardcoded ramdisk script ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') deploy_key = utils.random_alnum(32) i_info = node.instance_info i_info['deploy_key'] = deploy_key node.instance_info = i_info node.save() deploy_options = { 'deployment_id': node['uuid'], 'deployment_key': deploy_key, 'iscsi_target_iqn': "iqn-%s" % node.uuid, 'ironic_api_url': ironic_api, 'disk': CONF.pxe.disk_devices, } return deploy_options
def get_client(token=None): params = {'retries': CONF.neutron.retries} url = CONF.neutron.url if CONF.neutron.auth_strategy == 'noauth': params['endpoint_url'] = url or DEFAULT_NEUTRON_URL params['auth_strategy'] = 'noauth' params.update({ 'timeout': CONF.neutron.url_timeout or CONF.neutron.timeout, 'insecure': CONF.neutron.insecure, 'ca_cert': CONF.neutron.cafile}) else: session = _get_neutron_session() if token is None: params['session'] = session # NOTE(pas-ha) endpoint_override==None will auto-discover # endpoint from Keystone catalog. # Region is needed only in this case. # SSL related options are ignored as they are already embedded # in keystoneauth Session object if url: params['endpoint_override'] = url else: params['region_name'] = CONF.keystone.region_name else: params['token'] = token params['endpoint_url'] = url or keystone.get_service_url( session, service_type='network', region_name=CONF.keystone.region_name) params.update({ 'timeout': CONF.neutron.url_timeout or CONF.neutron.timeout, 'insecure': CONF.neutron.insecure, 'ca_cert': CONF.neutron.cafile}) return clientv20.Client(**params)
def get_client(token=None): params = {'retries': CONF.neutron.retries} url = CONF.neutron.url if CONF.neutron.auth_strategy == 'noauth': params['endpoint_url'] = url or DEFAULT_NEUTRON_URL params['auth_strategy'] = 'noauth' params.update({ 'timeout': CONF.neutron.url_timeout or CONF.neutron.timeout, 'insecure': CONF.neutron.insecure, 'ca_cert': CONF.neutron.cafile}) else: session = _get_neutron_session() if token is None: params['session'] = session # NOTE(pas-ha) endpoint_override==None will auto-discover # endpoint from Keystone catalog. # Region is needed only in this case. # SSL related options are ignored as they are already embedded # in keystoneauth Session object if url: params['endpoint_override'] = url else: params['region_name'] = CONF.keystone.region_name else: params['token'] = token params['endpoint_url'] = url or keystone.get_service_url( session, service_type='network') params.update({ 'timeout': CONF.neutron.url_timeout or CONF.neutron.timeout, 'insecure': CONF.neutron.insecure, 'ca_cert': CONF.neutron.cafile}) return clientv20.Client(**params)
def __init__(self, **kwargs): token = kwargs.get('token', None) self.client = None params = { 'timeout': CONF.neutron.url_timeout, 'insecure': CONF.keystone_authtoken.insecure, 'ca_cert': CONF.keystone_authtoken.certfile, } if CONF.neutron.auth_strategy not in ['noauth', 'keystone']: raise exception.ConfigInvalid(_('Neutron auth_strategy should be ' 'either "noauth" or "keystone".')) if CONF.neutron.auth_strategy == 'noauth': params['endpoint_url'] = CONF.neutron.url params['auth_strategy'] = 'noauth' elif (CONF.neutron.auth_strategy == 'keystone' and token is None): params['endpoint_url'] = (CONF.neutron.url or keystone.get_service_url('neutron')) params['username'] = CONF.keystone_authtoken.admin_user params['tenant_name'] = CONF.keystone_authtoken.admin_tenant_name params['password'] = CONF.keystone_authtoken.admin_password params['auth_url'] = (CONF.keystone_authtoken.auth_uri or '') else: params['token'] = token params['endpoint_url'] = CONF.neutron.url params['auth_strategy'] = None self.client = clientv20.Client(**params)
def test_get_url(self): fake_url = 'http://127.0.0.1:6385' mock_sess = mock.Mock() mock_sess.get_endpoint.return_value = fake_url res = keystone.get_service_url(mock_sess) mock_sess.get_endpoint.assert_called_with( interface='internal', region='fake_region', service_type='baremetal') self.assertEqual(fake_url, res)
def build_agent_options(node): """Build the options to be passed to the agent ramdisk. :param node: an ironic node object :returns: a dictionary containing the parameters to be passed to agent ramdisk. """ ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip("/") return {"ipa-api-url": ironic_api, "ipa-driver-name": node.driver}
def _build_pxe_config_options(pxe_info): ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') return { 'deployment_aki_path': pxe_info['deploy_kernel'][1], 'deployment_ari_path': pxe_info['deploy_ramdisk'][1], 'pxe_append_params': CONF.agent.agent_pxe_append_params, 'ipa_api_url': ironic_api, }
def test_get_url(self): fake_url = 'http://127.0.0.1:6385' mock_sess = mock.Mock() mock_sess.get_endpoint.return_value = fake_url res = keystone.get_service_url(mock_sess) mock_sess.get_endpoint.assert_called_with( interface='internal', region_name='fake_region', service_type='baremetal') self.assertEqual(fake_url, res)
def test_get_service_url_internal_fail(self): session = mock.Mock() session.get_endpoint.side_effect = [ksexception.EndpointNotFound(), 'spam'] params = {'ham': 'eggs'} self.assertEqual('spam', keystone.get_service_url(session, **params)) session.get_endpoint.assert_has_calls([ mock.call(interface='internal', **params), mock.call(interface='public', **params)])
def build_agent_options(node): """Build the options to be passed to the agent ramdisk. :param node: an ironic node object :returns: a dictionary containing the parameters to be passed to agent ramdisk. """ ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') return {'ipa-api-url': ironic_api, 'ipa-driver-name': node.driver}
def build_agent_options(): """Build the options to be passed to the agent ramdisk. :returns: a dictionary containing the parameters to be passed to agent ramdisk. """ ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') return { 'ipa-api-url': ironic_api, }
def build_deploy_ramdisk_options(node): """Build the ramdisk config options for a node This method builds the ramdisk options for a node, given all the required parameters for doing iscsi deploy. :param node: a single Node. :returns: A dictionary of options to be passed to ramdisk for performing the deploy. """ # NOTE: we should strip '/' from the end because this is intended for # hardcoded ramdisk script ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') deploy_key = utils.random_alnum(32) i_info = node.instance_info i_info['deploy_key'] = deploy_key node.instance_info = i_info node.save() # XXX(jroll) DIB relies on boot_option=local to decide whether or not to # lay down a bootloader. Hack this for now; fix it for real in Liberty. # See also bug #1441556. boot_option = deploy_utils.get_boot_option(node) if node.driver_internal_info.get('is_whole_disk_image'): boot_option = 'netboot' deploy_options = { 'deployment_id': node['uuid'], 'deployment_key': deploy_key, 'iscsi_target_iqn': 'iqn.2008-10.org.openstack:%s' % node.uuid, 'iscsi_portal_port': CONF.iscsi.portal_port, 'ironic_api_url': ironic_api, 'disk': CONF.pxe.disk_devices, 'boot_option': boot_option, 'boot_mode': _get_boot_mode(node), # NOTE: The below entry is a temporary workaround for bug/1433812 'coreos.configdrive': 0, } root_device = deploy_utils.parse_root_device_hints(node) if root_device: deploy_options['root_device'] = root_device return deploy_options
def build_deploy_ramdisk_options(node): """Build the ramdisk config options for a node This method builds the ramdisk options for a node, given all the required parameters for doing iscsi deploy. :param node: a single Node. :returns: A dictionary of options to be passed to ramdisk for performing the deploy. """ # NOTE: we should strip '/' from the end because this is intended for # hardcoded ramdisk script ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip("/") deploy_key = utils.random_alnum(32) i_info = node.instance_info i_info["deploy_key"] = deploy_key node.instance_info = i_info node.save() # XXX(jroll) DIB relies on boot_option=local to decide whether or not to # lay down a bootloader. Hack this for now; fix it for real in Liberty. # See also bug #1441556. boot_option = get_boot_option(node) if node.driver_internal_info.get("is_whole_disk_image"): boot_option = "netboot" deploy_options = { "deployment_id": node["uuid"], "deployment_key": deploy_key, "iscsi_target_iqn": "iqn-%s" % node.uuid, "ironic_api_url": ironic_api, "disk": CONF.pxe.disk_devices, "boot_option": boot_option, "boot_mode": _get_boot_mode(node), # NOTE: The below entry is a temporary workaround for bug/1433812 "coreos.configdrive": 0, } root_device = deploy_utils.parse_root_device_hints(node) if root_device: deploy_options["root_device"] = root_device return deploy_options
def _build_pxe_config(node, pxe_info): """Build the PXE config file for a node This method builds the PXE boot configuration file for a node, given all the required parameters. The resulting file has both a "deploy" and "boot" label, which correspond to the two phases of booting. This may be extended later. :param pxe_options: A dict of values to set on the configuarion file :returns: A formated string with the file content. """ LOG.debug(_("Building PXE config for deployment %s.") % node['id']) # NOTE: we should strip '/' from the end because this is intended for # hardcoded ramdisk script ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') deploy_key = utils.random_alnum(32) ctx = context.get_admin_context() driver_info = node['driver_info'] driver_info['pxe_deploy_key'] = deploy_key node['driver_info'] = driver_info node.save(ctx) pxe_options = { 'deployment_id': node['uuid'], 'deployment_key': deploy_key, 'deployment_iscsi_iqn': "iqn-%s" % node['instance_uuid'], 'deployment_aki_path': pxe_info['deploy_kernel'][1], 'deployment_ari_path': pxe_info['deploy_ramdisk'][1], 'aki_path': pxe_info['kernel'][1], 'ari_path': pxe_info['ramdisk'][1], 'ironic_api_url': ironic_api, 'pxe_append_params': CONF.pxe.pxe_append_params, } tmpl_path, tmpl_file = os.path.split(CONF.pxe.pxe_config_template) env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path)) template = env.get_template(tmpl_file) return template.render({'pxe_options': pxe_options, 'ROOT': '{{ ROOT }}'})
def build_agent_options(node): """Build the options to be passed to the agent ramdisk. :param node: an ironic node object :returns: a dictionary containing the parameters to be passed to agent ramdisk. """ ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip("/") agent_config_opts = { "ipa-api-url": ironic_api, "ipa-driver-name": node.driver, # NOTE: The below entry is a temporary workaround for bug/1433812 "coreos.configdrive": 0, } root_device = parse_root_device_hints(node) if root_device: agent_config_opts["root_device"] = root_device return agent_config_opts
def get_ironic_api_url(): """Resolve Ironic API endpoint either from config of from Keystone catalog. """ ironic_api = CONF.conductor.api_url if not ironic_api: try: ironic_session = _get_ironic_session() ironic_api = keystone.get_service_url(ironic_session) except (exception.KeystoneFailure, exception.CatalogNotFound, exception.KeystoneUnauthorized) as e: raise exception.InvalidParameterValue( _("Couldn't get the URL of the Ironic API service from the " "configuration file or keystone catalog. Keystone error: " "%s") % six.text_type(e)) # NOTE: we should strip '/' from the end because it might be used in # hardcoded ramdisk script ironic_api = ironic_api.rstrip('/') return ironic_api
def test_get_url(self): fake_url = 'http://127.0.0.1:6385' class _fake_catalog: def url_for(self, **kwargs): return fake_url class _fake_client: def __init__(self, **kwargs): self.service_catalog = _fake_catalog() def has_service_catalog(self): return True self.useFixture( fixtures.MonkeyPatch('keystoneclient.v2_0.client.Client', _fake_client)) res = keystone.get_service_url() self.assertEqual(res, fake_url)
def test_get_url(self): fake_url = 'http://127.0.0.1:6385' class _fake_catalog: def url_for(self, **kwargs): return fake_url class _fake_client: def __init__(self, **kwargs): self.service_catalog = _fake_catalog() def has_service_catalog(self): return True self.useFixture(fixtures.MonkeyPatch( 'keystoneclient.v2_0.client.Client', _fake_client)) res = keystone.get_service_url() self.assertEqual(fake_url, res)
def build_agent_options(node): """Build the options to be passed to the agent ramdisk. :param node: an ironic node object :returns: a dictionary containing the parameters to be passed to agent ramdisk. """ ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') agent_config_opts = { 'ipa-api-url': ironic_api, 'ipa-driver-name': node.driver, # NOTE: The below entry is a temporary workaround for bug/1433812 'coreos.configdrive': 0, } root_device = parse_root_device_hints(node) if root_device: agent_config_opts['root_device'] = root_device return agent_config_opts
def _build_pxe_config(node, pxe_info, ctx): """Build the PXE config file for a node This method builds the PXE boot configuration file for a node, given all the required parameters. The resulting file has both a "deploy" and "boot" label, which correspond to the two phases of booting. This may be extended later. :param pxe_options: A dict of values to set on the configuarion file :returns: A formated string with the file content. """ LOG.debug("Building PXE config for deployment %s." % node.uuid) # NOTE: we should strip '/' from the end because this is intended for # hardcoded ramdisk script ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') deploy_key = utils.random_alnum(32) driver_info = node['driver_info'] driver_info['pxe_deploy_key'] = deploy_key node['driver_info'] = driver_info node.save(ctx) pxe_options = { 'deployment_id': node['uuid'], 'deployment_key': deploy_key, 'deployment_iscsi_iqn': "iqn-%s" % node.uuid, 'deployment_aki_path': pxe_info['deploy_kernel'][1], 'deployment_ari_path': pxe_info['deploy_ramdisk'][1], 'aki_path': pxe_info['kernel'][1], 'ari_path': pxe_info['ramdisk'][1], 'ironic_api_url': ironic_api, 'pxe_append_params': CONF.pxe.pxe_append_params, } tmpl_path, tmpl_file = os.path.split(CONF.pxe.pxe_config_template) env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path)) template = env.get_template(tmpl_file) return template.render({'pxe_options': pxe_options, 'ROOT': '{{ ROOT }}'})
def get_ironic_api_url(): """Resolve Ironic API endpoint either from config of from Keystone catalog. """ ironic_api = CONF.conductor.api_url if not ironic_api: try: ironic_session = _get_ironic_session() ironic_api = keystone.get_service_url(ironic_session) except (exception.KeystoneFailure, exception.CatalogNotFound, exception.KeystoneUnauthorized) as e: raise exception.InvalidParameterValue(_( "Couldn't get the URL of the Ironic API service from the " "configuration file or keystone catalog. Keystone error: " "%s") % six.text_type(e)) # NOTE: we should strip '/' from the end because it might be used in # hardcoded ramdisk script ironic_api = ironic_api.rstrip('/') return ironic_api
def __init__(self): # TODO(pas-ha): swiftclient does not support keystone sessions ATM. # Must be reworked when LP bug #1518938 is fixed. session = _get_swift_session() params = { 'retries': CONF.swift.swift_max_retries, 'preauthurl': keystone.get_service_url( session, service_type='object-store'), 'preauthtoken': keystone.get_admin_auth_token(session) } # NOTE(pas-ha):session.verify is for HTTPS urls and can be # - False (do not verify) # - True (verify but try to locate system CA certificates) # - Path (verify using specific CA certificate) verify = session.verify params['insecure'] = not verify if verify and isinstance(verify, six.string_types): params['cacert'] = verify self.connection = swift_client.Connection(**params)
def build_agent_options(node): """Build the options to be passed to the agent ramdisk. :param node: an ironic node object :returns: a dictionary containing the parameters to be passed to agent ramdisk. """ ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') agent_config_opts = { 'ipa-api-url': ironic_api, 'ipa-driver-name': node.driver, # NOTE: The below entry is a temporary workaround for bug/1433812 'coreos.configdrive': 0, } # TODO(dtantsur): deprecate in favor of reading root hints directly from a # node record. root_device = parse_root_device_hints(node) if root_device: agent_config_opts['root_device'] = root_device return agent_config_opts
def validate(self, task, node): """Validate the driver-specific Node deployment info. :param task: a task from TaskManager. :param node: a single Node to validate. :returns: InvalidParameterValue. """ if not driver_utils.get_node_mac_addresses(task, node): raise exception.InvalidParameterValue(_("Node %s does not have " "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."))
def validate(self, task, node): """Validate the driver-specific Node deployment info. :param task: a task from TaskManager. :param node: a single Node to validate. :returns: InvalidParameterValue. """ if not _get_node_mac_addresses(task, node): raise exception.InvalidParameterValue( _("Node %s does not have " "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."))
def __init__(self): # TODO(pas-ha): swiftclient does not support keystone sessions ATM. # Must be reworked when LP bug #1518938 is fixed. session = _get_swift_session() params = { 'retries': CONF.swift.swift_max_retries, 'preauthurl': keystone.get_service_url(session, service_type='object-store'), 'preauthtoken': keystone.get_admin_auth_token(session) } # NOTE(pas-ha):session.verify is for HTTPS urls and can be # - False (do not verify) # - True (verify but try to locate system CA certificates) # - Path (verify using specific CA certificate) verify = session.verify params['insecure'] = not verify if verify and isinstance(verify, six.string_types): params['cacert'] = verify self.connection = swift_client.Connection(**params)
def __init__(self, context): self.context = context self.client = None params = { 'timeout': CONF.neutron.url_timeout, 'insecure': CONF.keystone_authtoken.insecure, 'ca_cert': CONF.keystone_authtoken.certfile, } if context.auth_token is None: params['endpoint_url'] = (CONF.neutron.url or keystone.get_service_url('neutron')) params['username'] = CONF.keystone_authtoken.admin_user params['tenant_name'] = CONF.keystone_authtoken.admin_tenant_name params['password'] = CONF.keystone_authtoken.admin_password params['auth_url'] = (CONF.keystone_authtoken.auth_uri or '') else: params['token'] = context.auth_token params['endpoint_url'] = CONF.neutron.url params['auth_strategy'] = None self.client = clientv20.Client(**params)
def build_deploy_ramdisk_options(node): """Build the ramdisk config options for a node This method builds the ramdisk options for a node, given all the required parameters for doing iscsi deploy. :param node: a single Node. :returns: A dictionary of options to be passed to ramdisk for performing the deploy. """ # NOTE: we should strip '/' from the end because this is intended for # hardcoded ramdisk script ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') deploy_key = utils.random_alnum(32) i_info = node.instance_info i_info['deploy_key'] = deploy_key node.instance_info = i_info node.save() deploy_options = { 'deployment_id': node['uuid'], 'deployment_key': deploy_key, 'iscsi_target_iqn': "iqn-%s" % node.uuid, 'ironic_api_url': ironic_api, 'disk': CONF.pxe.disk_devices, 'boot_option': get_boot_option(node), 'boot_mode': _get_boot_mode(node), # NOTE: The below entry is a temporary workaround for bug/1433812 'coreos.configdrive': 0, } root_device = deploy_utils.parse_root_device_hints(node) if root_device: deploy_options['root_device'] = root_device return deploy_options
def _build_pxe_config_options(node, pxe_info, ctx): """Build the PXE config options for a node This method builds the PXE boot options for a node, given all the required parameters. The options should then be passed to pxe_utils.create_pxe_config to create the actual config files. :param node: a single Node. :param pxe_info: a dict of values to set on the configuration file :param ctx: security context :returns: A dictionary of pxe options to be used in the pxe bootfile template. """ # NOTE: we should strip '/' from the end because this is intended for # hardcoded ramdisk script ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') deploy_key = utils.random_alnum(32) i_info = node.instance_info i_info['deploy_key'] = deploy_key node.instance_info = i_info node.save(ctx) pxe_options = { 'deployment_id': node['uuid'], 'deployment_key': deploy_key, 'deployment_iscsi_iqn': "iqn-%s" % node.uuid, 'deployment_aki_path': pxe_info['deploy_kernel'][1], 'deployment_ari_path': pxe_info['deploy_ramdisk'][1], 'aki_path': pxe_info.get('kernel', ['', ''])[1], 'ari_path': pxe_info.get('ramdisk', ['', ''])[1], 'ironic_api_url': ironic_api, 'pxe_append_params': CONF.pxe.pxe_append_params, } return pxe_options
def _build_pxe_config_options(task, pxe_info): """Builds the pxe config options for booting agent. This method builds the config options to be replaced on the agent pxe config template. :param task: a TaskManager instance :param pxe_info: A dict containing the 'deploy_kernel' and 'deploy_ramdisk' for the agent pxe config template. :returns: a dict containing the options to be applied on the agent pxe config template. """ ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip('/') agent_config_opts = { 'deployment_aki_path': pxe_info['deploy_kernel'][1], 'deployment_ari_path': pxe_info['deploy_ramdisk'][1], 'rootfs-url': _create_rootfs_link(task), 'deployment_id': task.node.uuid, 'api-url': ironic_api, } return agent_config_opts
def validate(task): """Validates the pre-requisites for iSCSI deploy. Validates whether node in the task provided has some ports enrolled. This method validates whether conductor url is available either from CONF file or from keystone. :param task: a TaskManager instance containing the node to act on. :raises: InvalidParameterValue if no ports are enrolled for the given node. """ node = task.node if not driver_utils.get_node_mac_addresses(task): raise exception.InvalidParameterValue(_("Node %s does not have " "any port associated with it.") % node.uuid) try: # TODO(lucasagomes): Validate the format of the URL CONF.conductor.api_url or keystone.get_service_url() except (exception.KeystoneFailure, exception.CatalogNotFound, exception.KeystoneUnauthorized): raise exception.InvalidParameterValue(_( "Couldn't get the URL of the Ironic API service from the " "configuration file or keystone catalog."))
def test_get_url(self, mock_ks, mock_uf): fake_url = 'http://127.0.0.1:6385' mock_uf.return_value = fake_url mock_ks.return_value = FakeClient() res = keystone.get_service_url() self.assertEqual(fake_url, res)