Skip to content

Commit

Permalink
Glance cache updates to support Keystone Essex.
Browse files Browse the repository at this point in the history
Glance caching updates to support keystone service tenants:

 * Update glance-cache-manage so that it supports the same style OS_
  environment variables and CLI options for auth that bin/glance does.

 * Updates registry/client so that it supports Keystone KSL style
  service tenants. As services no longer use admin_tokens this is
  a requirement to be able to use caching w/ KSL.

Fixes LP Bug #949486.

Change-Id: I8d0e56a9ec0d20ef56ed2ce8b860d987ae159e01
  • Loading branch information
dprince committed Mar 9, 2012
1 parent b43b676 commit 4d41027
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 67 deletions.
47 changes: 10 additions & 37 deletions bin/glance
Expand Up @@ -41,10 +41,10 @@ if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):

gettext.install('glance', unicode=1)

from glance import version
from glance import client as glance_client
from glance.common import exception
from glance.common import utils
from glance import version


SUCCESS = 0
Expand Down Expand Up @@ -784,43 +784,16 @@ def get_client(options):
specified by the --host and --port options
supplied to the CLI
"""

if options.auth_url or os.getenv('OS_AUTH_URL'):
force_strategy = 'keystone'
else:
force_strategy = None

creds = dict(username=options.username or \
os.getenv('OS_AUTH_USER', os.getenv('OS_USERNAME')),
password=options.password or \
os.getenv('OS_AUTH_KEY', os.getenv('OS_PASSWORD')),
tenant=options.tenant or \
os.getenv('OS_AUTH_TENANT',
os.getenv('OS_TENANT_NAME')),
auth_url=options.auth_url or os.getenv('OS_AUTH_URL'),
strategy=force_strategy or options.auth_strategy or \
os.getenv('OS_AUTH_STRATEGY', 'noauth'),
region=options.region or os.getenv('OS_REGION_NAME'),
)

if creds['strategy'] == 'keystone' and not creds['auth_url']:
msg = ("--auth_url option or OS_AUTH_URL environment variable "
"required when keystone authentication strategy is enabled\n")
raise exception.ClientConfigurationError(msg)

use_ssl = (options.use_ssl or (
creds['auth_url'] is not None and
creds['auth_url'].find('https') != -1))

client = (glance_client.ProgressClient if not options.is_silent_upload
else glance_client.Client)

return client(host=options.host,
return glance_client.get_client(host=options.host,
port=options.port,
use_ssl=use_ssl,
auth_tok=options.auth_token or
os.getenv('OS_TOKEN'),
creds=creds,
username=options.username,
password=options.password,
tenant=options.tenant,
auth_url=options.auth_url,
auth_strategy=options.auth_strategy,
auth_token=options.auth_token,
region=options.region,
is_silent_upload=options.is_silent_upload,
insecure=options.insecure)


Expand Down
53 changes: 39 additions & 14 deletions bin/glance-cache-manage
Expand Up @@ -38,9 +38,9 @@ if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
gettext.install('glance', unicode=1)

from glance import client as glance_client
from glance import version
from glance.common import exception
from glance.common import utils
from glance import version


SUCCESS = 0
Expand Down Expand Up @@ -259,19 +259,16 @@ def get_client(options):
specified by the --host and --port options
supplied to the CLI
"""
creds = dict(username=os.getenv('OS_AUTH_USER'),
password=os.getenv('OS_AUTH_KEY'),
tenant=os.getenv('OS_AUTH_TENANT'),
auth_url=os.getenv('OS_AUTH_URL'),
strategy=os.getenv('OS_AUTH_STRATEGY', 'noauth'))

use_ssl = (options.host.find('https') != -1 or (
creds['auth_url'] is not None and
creds['auth_url'].find('https') != -1))

return glance_client.Client(host=options.host, port=options.port,
use_ssl=use_ssl, auth_tok=options.auth_token,
creds=creds)
return glance_client.get_client(host=options.host,
port=options.port,
username=options.username,
password=options.password,
tenant=options.tenant,
auth_url=options.auth_url,
auth_strategy=options.auth_strategy,
auth_token=options.auth_token,
region=options.region,
insecure=options.insecure)


def create_options(parser):
Expand All @@ -296,6 +293,34 @@ def create_options(parser):
metavar="TOKEN", default=None,
help="Authentication token to use to identify the "
"client to the glance server")
parser.add_option('-I', '--username', dest="username",
metavar="USER", default=None,
help="User name used to acquire an authentication token")
parser.add_option('-K', '--password', dest="password",
metavar="PASSWORD", default=None,
help="Password used to acquire an authentication token")
parser.add_option('-R', '--region', dest="region",
metavar="REGION", default=None,
help="Region name. When using keystone authentication "
"version 2.0 or later this identifies the region "
"name to use when selecting the service endpoint. A "
"region name must be provided if more than one "
"region endpoint is available")
parser.add_option('-T', '--tenant', dest="tenant",
metavar="TENANT", default=None,
help="Tenant name")
parser.add_option('-N', '--auth_url', dest="auth_url",
metavar="AUTH_URL", default=None,
help="Authentication URL")
parser.add_option('-k', '--insecure', dest="insecure",
default=False, action="store_true",
help="Explicitly allow glance to perform \"insecure\" "
"SSL (https) requests. The server's certificate will "
"not be verified against any certificate authorities. "
"This option should be used with caution.")
parser.add_option('-S', '--auth_strategy', dest="auth_strategy",
metavar="STRATEGY", default=None,
help="Authentication strategy (keystone or noauth)")
parser.add_option('-f', '--force', dest="force", metavar="FORCE",
default=False, action="store_true",
help="Prevent select actions from requesting "
Expand Down
7 changes: 5 additions & 2 deletions etc/glance-cache.conf
Expand Up @@ -36,5 +36,8 @@ registry_host = 0.0.0.0
# Port the registry server is listening on
registry_port = 9191

# Admin token to use if using Keystone
# admin_token = 123
# Auth settings if using Keystone
# auth_url = http://127.0.0.1:5000/v2.0/
# admin_tenant_name = %SERVICE_TENANT_NAME%
# admin_user = %SERVICE_USER%
# admin_password = %SERVICE_PASSWORD%
48 changes: 48 additions & 0 deletions glance/client.py
Expand Up @@ -399,3 +399,51 @@ def start_animation(self, headers):
return transfer_info

Client = V1Client


def get_client(host, port=None, username=None,
password=None, tenant=None,
auth_url=None, auth_strategy=None,
auth_token=None, region=None,
is_silent_upload=False, insecure=False):
"""
Returns a new client Glance client object based on common kwargs.
If an option isn't specified falls back to common environment variable
defaults.
"""

if auth_url or os.getenv('OS_AUTH_URL'):
force_strategy = 'keystone'
else:
force_strategy = None

creds = dict(username=username or
os.getenv('OS_AUTH_USER', os.getenv('OS_USERNAME')),
password=password or
os.getenv('OS_AUTH_KEY', os.getenv('OS_PASSWORD')),
tenant=tenant or
os.getenv('OS_AUTH_TENANT',
os.getenv('OS_TENANT_NAME')),
auth_url=auth_url or os.getenv('OS_AUTH_URL'),
strategy=force_strategy or auth_strategy or
os.getenv('OS_AUTH_STRATEGY', 'noauth'),
region=region or os.getenv('OS_REGION_NAME'),
)

if creds['strategy'] == 'keystone' and not creds['auth_url']:
msg = ("--auth_url option or OS_AUTH_URL environment variable "
"required when keystone authentication strategy is enabled\n")
raise exception.ClientConfigurationError(msg)

use_ssl = (creds['auth_url'] is not None and
creds['auth_url'].find('https') != -1)

client = (ProgressClient if not is_silent_upload else Client)

return client(host=host,
port=port,
use_ssl=use_ssl,
auth_tok=auth_token or
os.getenv('OS_TOKEN'),
creds=creds,
insecure=insecure)
7 changes: 4 additions & 3 deletions glance/common/client.py
Expand Up @@ -211,7 +211,8 @@ class BaseClient(object):

def __init__(self, host, port=None, use_ssl=False, auth_tok=None,
creds=None, doc_root=None, key_file=None,
cert_file=None, ca_file=None, insecure=False):
cert_file=None, ca_file=None, insecure=False,
configure_via_auth=True):
"""
Creates a new client to some service.
Expand Down Expand Up @@ -247,6 +248,7 @@ def __init__(self, host, port=None, use_ssl=False, auth_tok=None,
self.auth_tok = auth_tok
self.creds = creds or {}
self.connection = None
self.configure_via_auth = configure_via_auth
# doc_root can be a nullstring, which is valid, and why we
# cannot simply do doc_root or self.DEFAULT_DOC_ROOT below.
self.doc_root = (doc_root if doc_root is not None
Expand Down Expand Up @@ -365,7 +367,7 @@ def _authenticate(self, force_reauth=False):
self.auth_tok = auth_plugin.auth_token

management_url = auth_plugin.management_url
if management_url:
if management_url and self.configure_via_auth:
self.configure_from_url(management_url)

@handle_unauthorized
Expand All @@ -385,7 +387,6 @@ def do_request(self, method, action, body=None, headers=None,
self._authenticate()

url = self._construct_url(action, params)

return self._do_request(method=method, url=url, body=body,
headers=headers)

Expand Down
6 changes: 4 additions & 2 deletions glance/image_cache/prefetcher.py
Expand Up @@ -26,6 +26,7 @@
from glance.common import exception
from glance.image_cache import ImageCache
from glance import registry
from glance.registry import context
import glance.store
import glance.store.filesystem
import glance.store.http
Expand All @@ -45,10 +46,11 @@ def __init__(self, conf, **local_conf):
glance.store.create_stores(conf)
self.cache = ImageCache(conf)
registry.configure_registry_client(conf)
registry.configure_registry_admin_creds(conf)

def fetch_image_into_cache(self, image_id):
ctx = registry.get_client_context(self.conf,
is_admin=True, show_deleted=True)
ctx = context.RequestContext(is_admin=True, show_deleted=True)

try:
image_meta = registry.get_image_metadata(ctx, image_id)
if image_meta['status'] != 'active':
Expand Down
5 changes: 3 additions & 2 deletions glance/image_cache/queue_image.py
Expand Up @@ -26,6 +26,7 @@
from glance.common import exception
from glance.image_cache import ImageCache
from glance import registry
from glance.registry import context


logger = logging.getLogger(__name__)
Expand All @@ -37,10 +38,10 @@ def __init__(self, conf, **local_conf):
self.conf = conf
self.cache = ImageCache(conf)
registry.configure_registry_client(conf)
registry.configure_registry_admin_creds(conf)

def queue_image(self, image_id):
ctx = \
registry.get_client_context(conf, is_admin=True, show_deleted=True)
ctx = context.RequestContext(is_admin=True, show_deleted=True)
try:
image_meta = registry.get_image_metadata(ctx, image_id)
if image_meta['status'] != 'active':
Expand Down
38 changes: 32 additions & 6 deletions glance/registry/__init__.py
Expand Up @@ -20,13 +20,15 @@
"""

import logging
import os

from glance.common import cfg
from glance.common import exception
from glance.registry import client

logger = logging.getLogger('glance.registry')

_CLIENT_CREDS = None
_CLIENT_HOST = None
_CLIENT_PORT = None
_CLIENT_KWARGS = {}
Expand All @@ -45,7 +47,14 @@
cfg.StrOpt('registry_client_ca_file'),
cfg.StrOpt('metadata_encryption_key'),
]
admin_token_opt = cfg.StrOpt('admin_token')
registry_client_ctx_opts = [
cfg.StrOpt('admin_user'),
cfg.StrOpt('admin_password'),
cfg.StrOpt('admin_tenant_name'),
cfg.StrOpt('auth_url'),
cfg.StrOpt('auth_strategy', default='noauth'),
cfg.StrOpt('auth_region'),
]


def get_registry_addr(conf):
Expand Down Expand Up @@ -84,16 +93,33 @@ def configure_registry_client(conf):
}


def get_client_context(conf, **kwargs):
conf.register_opt(admin_token_opt)
from glance.common import context
return context.RequestContext(auth_tok=conf.admin_token, **kwargs)
def configure_registry_admin_creds(conf):
global _CLIENT_CREDS
conf.register_opts(registry_client_ctx_opts)

if conf.auth_url or os.getenv('OS_AUTH_URL'):
strategy = 'keystone'
else:
strategy = conf.auth_strategy

_CLIENT_CREDS = {
'user': conf.admin_user,
'password': conf.admin_password,
'username': conf.admin_user,
'tenant': conf.admin_tenant_name,
'auth_url': conf.auth_url,
'strategy': strategy,
'region': conf.auth_region,
}


def get_registry_client(cxt):
global _CLIENT_KWARGS, _CLIENT_HOST, _CLIENT_PORT, _METADATA_ENCRYPTION_KEY
global _CLIENT_CREDS, _CLIENT_KWARGS, _CLIENT_HOST, _CLIENT_PORT
global _METADATA_ENCRYPTION_KEY
kwargs = _CLIENT_KWARGS.copy()
kwargs['auth_tok'] = cxt.auth_tok
if _CLIENT_CREDS:
kwargs['creds'] = _CLIENT_CREDS
return client.RegistryClient(_CLIENT_HOST, _CLIENT_PORT,
_METADATA_ENCRYPTION_KEY, **kwargs)

Expand Down
6 changes: 5 additions & 1 deletion glance/registry/client.py
Expand Up @@ -40,7 +40,11 @@ def __init__(self, host=None, port=None, metadata_encryption_key=None,
:param metadata_encryption_key: Key used to encrypt 'location' metadata
"""
self.metadata_encryption_key = metadata_encryption_key
BaseClient.__init__(self, host, port, **kwargs)
# NOTE (dprince): by default base client overwrites host and port
# settings when using keystone. configure_via_auth=False disables
# this behaviour to ensure we still send requests to the Registry API
BaseClient.__init__(self, host, port, configure_via_auth=False,
**kwargs)

def decrypt_metadata(self, image_metadata):
if (self.metadata_encryption_key is not None
Expand Down

0 comments on commit 4d41027

Please sign in to comment.