Beispiel #1
0
def get_client(context):
    """Get a cinder client connection.

    :param context: request context,
                    instance of ironic.common.context.RequestContext
    :returns: A cinder client.
    """
    service_auth = keystone.get_auth('cinder')
    session = _get_cinder_session()

    # TODO(pas-ha) remove in Rocky
    adapter_opts = {}
    # NOTE(pas-ha) new option must always win if set
    if CONF.cinder.url and not CONF.cinder.endpoint_override:
        adapter_opts['endpoint_override'] = CONF.cinder.url

    adapter = keystone.get_adapter('cinder', session=session,
                                   auth=service_auth, **adapter_opts)
    # TODO(pas-ha) use versioned endpoint data to select required
    # cinder api version
    cinder_url = adapter.get_endpoint()
    # TODO(pas-ha) investigate possibility of passing a user context here,
    # similar to what neutron/glance-related code does
    # NOTE(pas-ha) cinderclient has both 'connect_retries' (passed to
    # ksa.Adapter) and 'retries' (used in its subclass of ksa.Adapter) options.
    # The first governs retries on establishing the HTTP connection,
    # the second governs retries on OverLimit exceptions from API.
    # The description of [cinder]/retries fits the first,
    # so this is what we pass.
    return client.Client(session=session, auth=service_auth,
                         endpoint_override=cinder_url,
                         connect_retries=CONF.cinder.retries,
                         global_request_id=context.global_id)
Beispiel #2
0
def get_client(token=None, context=None):
    if not context:
        context = ironic_context.RequestContext(auth_token=token)
    # NOTE(pas-ha) neutronclient supports passing both session
    # and the auth to client separately, makes things easier
    session = _get_neutron_session()
    service_auth = keystone.get_auth('neutron')

    # TODO(pas-ha) remove in Rocky, always simply load from config
    # 'noauth' then would correspond to 'auth_type=none' and
    # 'endpoint_override'
    adapter_params = {}
    if (CONF.neutron.auth_strategy == 'noauth'
            and CONF.neutron.auth_type is None):
        CONF.set_override('auth_type', 'none', group='neutron')
        if not CONF.neutron.endpoint_override:
            adapter_params['endpoint_override'] = (CONF.neutron.url
                                                   or DEFAULT_NEUTRON_URL)
    else:
        if CONF.neutron.url and not CONF.neutron.endpoint_override:
            adapter_params['endpoint_override'] = CONF.neutron.url
    adapter = keystone.get_adapter('neutron', session=session,
                                   auth=service_auth, **adapter_params)
    endpoint = adapter.get_endpoint()

    user_auth = None
    if CONF.neutron.auth_type != 'none' and context.auth_token:
        user_auth = keystone.get_service_auth(context, endpoint, service_auth)
    return clientv20.Client(session=session,
                            auth=user_auth or service_auth,
                            endpoint_override=endpoint,
                            retries=CONF.neutron.retries,
                            global_request_id=context.global_id,
                            timeout=CONF.neutron.request_timeout)
Beispiel #3
0
def _get_session():
    global _SESSION

    if _SESSION is None:
        auth_strategy = json_rpc.auth_strategy()
        if auth_strategy == 'keystone':
            auth = keystone.get_auth('json_rpc')
        else:
            auth = None

        session = keystone.get_session('json_rpc', auth=auth)
        headers = {'Content-Type': 'application/json'}
        if auth_strategy == 'http_basic':
            token = '{}:{}'.format(
                CONF.json_rpc.http_basic_username,
                CONF.json_rpc.http_basic_password).encode('utf-8')
            encoded = base64.b64encode(token).decode('utf-8')
            headers['Authorization'] = 'Basic {}'.format(encoded)

        # Adds options like connect_retries
        _SESSION = keystone.get_adapter('json_rpc',
                                        session=session,
                                        additional_headers=headers)

    return _SESSION
Beispiel #4
0
def get_client(token=None, context=None):
    if not context:
        context = ironic_context.RequestContext(auth_token=token)
    # NOTE(pas-ha) neutronclient supports passing both session
    # and the auth to client separately, makes things easier
    session = _get_neutron_session()
    service_auth = keystone.get_auth('neutron')

    # TODO(pas-ha) remove in Rocky, always simply load from config
    # 'noauth' then would correspond to 'auth_type=none' and
    # 'endpoint_override'
    adapter_params = {}
    if (CONF.neutron.auth_strategy == 'noauth'
            and CONF.neutron.auth_type is None):
        CONF.set_override('auth_type', 'none', group='neutron')
        if not CONF.neutron.endpoint_override:
            adapter_params['endpoint_override'] = (CONF.neutron.url
                                                   or DEFAULT_NEUTRON_URL)
    else:
        if CONF.neutron.url and not CONF.neutron.endpoint_override:
            adapter_params['endpoint_override'] = CONF.neutron.url
    adapter = keystone.get_adapter('neutron', session=session,
                                   auth=service_auth, **adapter_params)
    endpoint = adapter.get_endpoint()

    user_auth = None
    if CONF.neutron.auth_type != 'none' and context.auth_token:
        user_auth = keystone.get_service_auth(context, endpoint, service_auth)
    return clientv20.Client(session=session,
                            auth=user_auth or service_auth,
                            endpoint_override=endpoint,
                            retries=CONF.neutron.retries,
                            global_request_id=context.global_id)
Beispiel #5
0
def _get_session():
    global _SESSION

    if _SESSION is None:
        kwargs = {}
        auth_strategy = json_rpc.auth_strategy()
        if auth_strategy != 'keystone':
            auth_type = 'none' if auth_strategy == 'noauth' else auth_strategy
            CONF.set_default('auth_type', auth_type, group='json_rpc')

            # Deprecated, remove in W
            if auth_strategy == 'http_basic':
                if CONF.json_rpc.http_basic_username:
                    kwargs['username'] = CONF.json_rpc.http_basic_username
                if CONF.json_rpc.http_basic_password:
                    kwargs['password'] = CONF.json_rpc.http_basic_password

        auth = keystone.get_auth('json_rpc', **kwargs)

        session = keystone.get_session('json_rpc', auth=auth)
        headers = {'Content-Type': 'application/json'}

        # Adds options like connect_retries
        _SESSION = keystone.get_adapter('json_rpc',
                                        session=session,
                                        additional_headers=headers)

    return _SESSION
Beispiel #6
0
def get_client(context):
    """Get a cinder client connection.

    :param context: request context,
                    instance of ironic.common.context.RequestContext
    :returns: A cinder client.
    """
    service_auth = keystone.get_auth('cinder')
    session = _get_cinder_session()

    # TODO(pas-ha) remove in Rocky
    adapter_opts = {}
    # NOTE(pas-ha) new option must always win if set
    if CONF.cinder.url and not CONF.cinder.endpoint_override:
        adapter_opts['endpoint_override'] = CONF.cinder.url
    if CONF.keystone.region_name and not CONF.cinder.region_name:
        adapter_opts['region_name'] = CONF.keystone.region_name

    adapter = keystone.get_adapter('cinder', session=session,
                                   auth=service_auth, **adapter_opts)
    # TODO(pas-ha) use versioned endpoint data to select required
    # cinder api version
    cinder_url = adapter.get_endpoint()
    # TODO(pas-ha) investigate possibility of passing a user context here,
    # similar to what neutron/glance-related code does
    # NOTE(pas-ha) cinderclient has both 'connect_retries' (passed to
    # ksa.Adapter) and 'retries' (used in its subclass of ksa.Adapter) options.
    # The first governs retries on establishing the HTTP connection,
    # the second governs retries on OverLimit exceptions from API.
    # The description of [cinder]/retries fits the first,
    # so this is what we pass.
    return client.Client(session=session, auth=service_auth,
                         endpoint_override=cinder_url,
                         connect_retries=CONF.cinder.retries,
                         global_request_id=context.global_id)
Beispiel #7
0
    def wrapper(self, *args, **kwargs):
        """Wrapper around methods calls.

        :param image_href: href that describes the location of an image
        """

        if self.client:
            return func(self, *args, **kwargs)

        # TODO(pas-ha) remove in Rocky
        session_params = {}
        if CONF.glance.glance_api_insecure and not CONF.glance.insecure:
            session_params['insecure'] = CONF.glance.glance_api_insecure
        if CONF.glance.glance_cafile and not CONF.glance.cafile:
            session_params['cacert'] = CONF.glance.glance_cafile
        # NOTE(pas-ha) glanceclient uses Adapter-based SessionClient,
        # so we can pass session and auth separately, makes things easier
        session = _get_glance_session(**session_params)

        # TODO(pas-ha) remove in Rocky
        # NOTE(pas-ha) new option must win if configured
        if (CONF.glance.glance_api_servers
                and not CONF.glance.endpoint_override):
            # NOTE(pas-ha) all the 2 methods have image_href as the first
            #              positional arg, but check in kwargs too
            image_href = args[0] if args else kwargs.get('image_href')
            url = service_utils.get_glance_api_server(image_href)
            CONF.set_override('endpoint_override', url, group='glance')

        # TODO(pas-ha) remove in Rocky
        if CONF.glance.auth_strategy == 'noauth':
            CONF.set_override('auth_type', 'none', group='glance')

        service_auth = keystone.get_auth('glance')

        # TODO(pas-ha) remove in Rocky
        adapter_params = {}
        if CONF.keystone.region_name and not CONF.glance.region_name:
            adapter_params['region_name'] = CONF.keystone.region_name

        adapter = keystone.get_adapter('glance',
                                       session=session,
                                       auth=service_auth,
                                       **adapter_params)
        self.endpoint = adapter.get_endpoint()

        user_auth = None
        # NOTE(pas-ha) our ContextHook removes context.auth_token in noauth
        # case, so when ironic is in noauth but glance is not, we will not
        # enter the next if-block and use auth from [glance] config section
        if self.context.auth_token:
            user_auth = keystone.get_service_auth(self.context, self.endpoint,
                                                  service_auth)
        self.client = client.Client(self.version,
                                    session=session,
                                    auth=user_auth or service_auth,
                                    endpoint_override=self.endpoint,
                                    global_request_id=self.context.global_id)
        return func(self, *args, **kwargs)
 def test_get_adapter_from_config(self):
     self.config(valid_interfaces=['internal', 'public'],
                 group=self.test_group)
     session = keystone.get_session(self.test_group)
     adapter = keystone.get_adapter(self.test_group, session=session,
                                    interface='admin')
     self.assertEqual('admin', adapter.interface)
     self.assertEqual(session, adapter.session)
Beispiel #9
0
 def test_get_adapter_from_config(self):
     self.config(valid_interfaces=['internal', 'public'],
                 group=self.test_group)
     session = keystone.get_session(self.test_group)
     adapter = keystone.get_adapter(self.test_group,
                                    session=session,
                                    interface='admin')
     self.assertEqual('admin', adapter.interface)
     self.assertEqual(session, adapter.session)
Beispiel #10
0
def _get_nova_adapter():
    global _NOVA_ADAPTER
    if not _NOVA_ADAPTER:
        _NOVA_ADAPTER = keystone.get_adapter(
            'nova',
            session=keystone.get_session('nova'),
            auth=keystone.get_auth('nova'),
            version=NOVA_API_VERSION)
    return _NOVA_ADAPTER
    def wrapper(self, *args, **kwargs):
        """Wrapper around methods calls.

        :param image_href: href that describes the location of an image
        """

        if self.client:
            return func(self, *args, **kwargs)

        # TODO(pas-ha) remove in Rocky
        session_params = {}
        if CONF.glance.glance_api_insecure and not CONF.glance.insecure:
            session_params['insecure'] = CONF.glance.glance_api_insecure
        if CONF.glance.glance_cafile and not CONF.glance.cafile:
            session_params['cacert'] = CONF.glance.glance_cafile
        # NOTE(pas-ha) glanceclient uses Adapter-based SessionClient,
        # so we can pass session and auth separately, makes things easier
        session = _get_glance_session(**session_params)

        # TODO(pas-ha) remove in Rocky
        # NOTE(pas-ha) new option must win if configured
        if (CONF.glance.glance_api_servers
                and not CONF.glance.endpoint_override):
            # NOTE(pas-ha) all the 2 methods have image_href as the first
            #              positional arg, but check in kwargs too
            image_href = args[0] if args else kwargs.get('image_href')
            url = service_utils.get_glance_api_server(image_href)
            CONF.set_override('endpoint_override', url, group='glance')

        # TODO(pas-ha) remove in Rocky
        if CONF.glance.auth_strategy == 'noauth':
            CONF.set_override('auth_type', 'none', group='glance')

        service_auth = keystone.get_auth('glance')

        adapter_params = {}
        adapter = keystone.get_adapter('glance', session=session,
                                       auth=service_auth, **adapter_params)
        self.endpoint = adapter.get_endpoint()

        user_auth = None
        # NOTE(pas-ha) our ContextHook removes context.auth_token in noauth
        # case, so when ironic is in noauth but glance is not, we will not
        # enter the next if-block and use auth from [glance] config section
        if self.context.auth_token:
            user_auth = keystone.get_service_auth(self.context, self.endpoint,
                                                  service_auth)
        self.client = client.Client(2, session=session,
                                    auth=user_auth or service_auth,
                                    endpoint_override=self.endpoint,
                                    global_request_id=self.context.global_id)
        return func(self, *args, **kwargs)
Beispiel #12
0
def _get_session():
    global _SESSION

    if _SESSION is None:
        if json_rpc.require_authentication():
            auth = keystone.get_auth('json_rpc')
        else:
            auth = None

        session = keystone.get_session('json_rpc', auth=auth)
        session.headers = {'Content-Type': 'application/json'}

        # Adds options like connect_retries
        _SESSION = keystone.get_adapter('json_rpc', session=session)

    return _SESSION
Beispiel #13
0
    def __init__(self):
        """Initialize the connection with swift or radosgw

        :raises: ConfigInvalid if required keystone authorization credentials
         with swift are missing.
        """
        params = {'retries': CONF.swift.swift_max_retries}
        if CONF.deploy.object_store_endpoint_type == 'radosgw':
            params.update({
                'authurl': CONF.swift.auth_url,
                'user': CONF.swift.username,
                'key': CONF.swift.password
            })
        else:
            # NOTE(pas-ha) swiftclient still (as of 3.3.0) does not use
            # (adapter-based) SessionClient, and uses the passed in session
            # only to resolve endpoint and get a token,
            # but not to make further requests to Swift itself (LP 1736135).
            # Thus we need to deconstruct back all the adapter- and
            # session-related args as loaded by keystoneauth from config
            # to pass them to the client explicitly.
            # TODO(pas-ha) re-write this when swiftclient is brought on par
            # with other OS clients re auth plugins, sessions and adapters
            # support.
            # TODO(pas-ha) pass the context here and use token from context
            # with service auth
            params['session'] = session = get_swift_session()
            adapter = keystone.get_adapter('swift', session=session)
            params['os_options'] = {
                'object_storage_url': adapter.get_endpoint()
            }
            # deconstruct back session-related options
            params['timeout'] = session.timeout
            if session.verify is False:
                params['insecure'] = True
            elif isinstance(session.verify, six.string_types):
                params['cacert'] = session.verify
            if session.cert:
                # NOTE(pas-ha) although setting cert as path to single file
                # with both client cert and key is supported by Session,
                # keystoneauth loading always sets the session.cert
                # as tuple of cert and key.
                params['cert'], params['cert_key'] = session.cert

        self.connection = swift_client.Connection(**params)
Beispiel #14
0
def _get_client(context):
    """Helper to get inspector client instance."""
    # NOTE(pas-ha) remove in Rocky
    if CONF.auth_strategy != 'keystone':
        CONF.set_override('auth_type', 'none', group='inspector')
    service_auth = keystone.get_auth('inspector')
    session = _get_inspector_session(auth=service_auth)
    adapter_params = {}
    if CONF.inspector.service_url and not CONF.inspector.endpoint_override:
        adapter_params['endpoint_override'] = CONF.inspector.service_url
    adapter = keystone.get_adapter('inspector', session=session,
                                   **adapter_params)
    inspector_url = adapter.get_endpoint()
    # TODO(pas-ha) investigate possibility of passing user context here,
    # similar to what neutron/glance-related code does
    # NOTE(pas-ha) ironic-inspector-client has no Adaper-based
    # SessionClient, so we'll resolve inspector API form adapter loaded
    # form config options
    # TODO(pas-ha) rewrite when inspectorclient is based on ksa Adapter,
    #              also add global_request_id to the call
    return client.ClientV1(api_version=INSPECTOR_API_VERSION,
                           session=session,
                           inspector_url=inspector_url)
Beispiel #15
0
def _get_client(context):
    """Helper to get inspector client instance."""
    # NOTE(pas-ha) remove in Rocky
    if CONF.auth_strategy != 'keystone':
        CONF.set_override('auth_type', 'none', group='inspector')
    service_auth = keystone.get_auth('inspector')
    session = _get_inspector_session(auth=service_auth)
    adapter_params = {}
    if CONF.inspector.service_url and not CONF.inspector.endpoint_override:
        adapter_params['endpoint_override'] = CONF.inspector.service_url
    adapter = keystone.get_adapter('inspector',
                                   session=session,
                                   **adapter_params)
    inspector_url = adapter.get_endpoint()
    # TODO(pas-ha) investigate possibility of passing user context here,
    # similar to what neutron/glance-related code does
    # NOTE(pas-ha) ironic-inspector-client has no Adaper-based
    # SessionClient, so we'll resolve inspector API form adapter loaded
    # form config options
    # TODO(pas-ha) rewrite when inspectorclient is based on ksa Adapter,
    #              also add global_request_id to the call
    return client.ClientV1(api_version=INSPECTOR_API_VERSION,
                           session=session,
                           inspector_url=inspector_url)
Beispiel #16
0
    def __init__(self):
        """Initialize the connection with swift

        :raises: ConfigInvalid if required keystone authorization credentials
         with swift are missing.
        """
        params = {'retries': CONF.swift.swift_max_retries}
        # NOTE(pas-ha) swiftclient still (as of 3.3.0) does not use
        # (adapter-based) SessionClient, and uses the passed in session
        # only to resolve endpoint and get a token,
        # but not to make further requests to Swift itself (LP 1736135).
        # Thus we need to deconstruct back all the adapter- and
        # session-related args as loaded by keystoneauth from config
        # to pass them to the client explicitly.
        # TODO(pas-ha) re-write this when swiftclient is brought on par
        # with other OS clients re auth plugins, sessions and adapters
        # support.
        # TODO(pas-ha) pass the context here and use token from context
        # with service auth
        params['session'] = session = get_swift_session()
        adapter = keystone.get_adapter('swift', session=session)
        params['os_options'] = {'object_storage_url': adapter.get_endpoint()}
        # deconstruct back session-related options
        params['timeout'] = session.timeout
        if session.verify is False:
            params['insecure'] = True
        elif isinstance(session.verify, six.string_types):
            params['cacert'] = session.verify
        if session.cert:
            # NOTE(pas-ha) although setting cert as path to single file
            # with both client cert and key is supported by Session,
            # keystoneauth loading always sets the session.cert
            # as tuple of cert and key.
            params['cert'], params['cert_key'] = session.cert

        self.connection = swift_client.Connection(**params)
Beispiel #17
0
    def swift_temp_url(self, image_info):
        """Generate a no-auth Swift temporary URL.

        This function will generate (or return the cached one if temp URL
        cache is enabled) the temporary Swift URL using the image
        id from Glance and the config options: 'swift_endpoint_url',
        'swift_api_version', 'swift_account' and 'swift_container'.
        The temporary URL will be valid for 'swift_temp_url_duration' seconds.
        This allows Ironic to download a Glance image without passing around
        an auth_token.

        :param image_info: The return from a GET request to Glance for a
            certain image_id. Should be a dictionary, with keys like 'name' and
            'checksum'. See
            https://docs.openstack.org/glance/latest/user/glanceapi.html for
            examples.
        :returns: A signed Swift URL from which an image can be downloaded,
            without authentication.

        :raises: InvalidParameterValue if Swift config options are not set
            correctly.
        :raises: MissingParameterValue if a required parameter is not set.
        :raises: ImageUnacceptable if the image info from Glance does not
            have an image ID.
        """
        self._validate_temp_url_config()

        if ('id' not in image_info
                or not uuidutils.is_uuid_like(image_info['id'])):
            raise exc.ImageUnacceptable(
                _('The given image info does not have a valid image id: %s') %
                image_info)

        image_id = image_info['id']

        url_fragments = {
            'api_version': CONF.glance.swift_api_version,
            'container': self._get_swift_container(image_id),
            'object_id': image_id
        }

        endpoint_url = CONF.glance.swift_endpoint_url
        if not endpoint_url:
            swift_session = swift.get_swift_session()
            adapter = keystone.get_adapter('swift', session=swift_session)
            endpoint_url = adapter.get_endpoint()

        if not endpoint_url:
            raise exc.MissingParameterValue(
                _('Swift temporary URLs require a Swift endpoint URL, but it '
                  'was not found in the service catalog. '
                  'You must provide "swift_endpoint_url" as a config option.'))

        # Strip /v1/AUTH_%(tenant_id)s, if present
        endpoint_url = re.sub('/v1/AUTH_[^/]+/?$', '', endpoint_url)

        key = CONF.glance.swift_temp_url_key
        if CONF.deploy.object_store_endpoint_type == 'radosgw':
            chunks = urlparse.urlsplit(CONF.glance.swift_endpoint_url)
            if not chunks.path:
                endpoint_url = urlparse.urljoin(endpoint_url, 'swift')
            elif chunks.path != '/swift':
                raise exc.InvalidParameterValue(
                    _('Swift endpoint URL should only contain scheme, '
                      'hostname, optional port and optional /swift path '
                      'without trailing slash; provided value is: %s') %
                    endpoint_url)

            template = '/{api_version}/{container}/{object_id}'
        else:
            account = CONF.glance.swift_account
            if not account:
                swift_session = swift.get_swift_session()
                auth_ref = swift_session.auth.get_auth_ref(swift_session)
                account = 'AUTH_%s' % auth_ref.project_id

            if not key:
                swift_api = swift.SwiftAPI()
                key_header = 'x-account-meta-temp-url-key'
                key = swift_api.connection.head_account().get(key_header)

            if not key:
                raise exc.MissingParameterValue(
                    _('Swift temporary URLs require a shared secret to be '
                      'created. You must provide "swift_temp_url_key" as a '
                      'config option or pre-generate the key on the project '
                      'used to access Swift.'))

            url_fragments['account'] = account
            template = '/{api_version}/{account}/{container}/{object_id}'

        url_path = template.format(**url_fragments)

        return self._generate_temp_url(
            path=url_path,
            seconds=CONF.glance.swift_temp_url_duration,
            key=key,
            method='GET',
            endpoint=endpoint_url,
            image_id=image_id)
Beispiel #18
0
    def swift_temp_url(self, image_info):
        """Generate a no-auth Swift temporary URL.

        This function will generate (or return the cached one if temp URL
        cache is enabled) the temporary Swift URL using the image
        id from Glance and the config options: 'swift_endpoint_url',
        'swift_api_version', 'swift_account' and 'swift_container'.
        The temporary URL will be valid for 'swift_temp_url_duration' seconds.
        This allows Ironic to download a Glance image without passing around
        an auth_token.

        :param image_info: The return from a GET request to Glance for a
            certain image_id. Should be a dictionary, with keys like 'name' and
            'checksum'. See
            https://docs.openstack.org/glance/latest/user/glanceapi.html for
            examples.
        :returns: A signed Swift URL from which an image can be downloaded,
            without authentication.

        :raises: InvalidParameterValue if Swift config options are not set
            correctly.
        :raises: MissingParameterValue if a required parameter is not set.
        :raises: ImageUnacceptable if the image info from Glance does not
            have an image ID.
        """
        self._validate_temp_url_config()

        if ('id' not in image_info or not
                uuidutils.is_uuid_like(image_info['id'])):
            raise exc.ImageUnacceptable(_(
                'The given image info does not have a valid image id: %s')
                % image_info)

        image_id = image_info['id']

        url_fragments = {
            'api_version': CONF.glance.swift_api_version,
            'container': self._get_swift_container(image_id),
            'object_id': image_id
        }

        endpoint_url = CONF.glance.swift_endpoint_url
        if not endpoint_url:
            swift_session = swift.get_swift_session()
            adapter = keystone.get_adapter('swift', session=swift_session)
            endpoint_url = adapter.get_endpoint()

        if not endpoint_url:
            raise exc.MissingParameterValue(_(
                'Swift temporary URLs require a Swift endpoint URL, but it '
                'was not found in the service catalog. '
                'You must provide "swift_endpoint_url" as a config option.'))

        # Strip /v1/AUTH_%(tenant_id)s, if present
        endpoint_url = re.sub('/v1/AUTH_[^/]+/?$', '', endpoint_url)

        key = CONF.glance.swift_temp_url_key
        account = CONF.glance.swift_account
        if not account:
            swift_session = swift.get_swift_session()
            auth_ref = swift_session.auth.get_auth_ref(swift_session)
            account = 'AUTH_%s' % auth_ref.project_id

        if not key:
            swift_api = swift.SwiftAPI()
            key_header = 'x-account-meta-temp-url-key'
            key = swift_api.connection.head_account().get(key_header)

        if not key:
            raise exc.MissingParameterValue(_(
                'Swift temporary URLs require a shared secret to be '
                'created. You must provide "swift_temp_url_key" as a '
                'config option or pre-generate the key on the project '
                'used to access Swift.'))

        url_fragments['account'] = account
        template = '/{api_version}/{account}/{container}/{object_id}'

        url_path = template.format(**url_fragments)

        return self._generate_temp_url(
            path=url_path,
            seconds=CONF.glance.swift_temp_url_duration,
            key=key,
            method='GET',
            endpoint=endpoint_url,
            image_id=image_id
        )