A bit of cleanup

This commit is contained in:
Adam Gandelman 2011-12-23 17:34:15 -08:00
parent b279694482
commit b535ef9e54
3 changed files with 52 additions and 29 deletions

View File

@ -8,6 +8,8 @@ packages = "keystone python-mysqldb pwgen"
service = "keystone" service = "keystone"
# used to verify joined services are valid openstack components. # used to verify joined services are valid openstack components.
# this should reflect the current "core" components of openstack
# and be expanded as we add support for them as a distro
valid_services = { valid_services = {
"nova": { "nova": {
"type": "compute", "type": "compute",
@ -21,13 +23,12 @@ valid_services = {
"type": "storage", "type": "storage",
"desc": "Swift Object Storage Service" "desc": "Swift Object Storage Service"
} }
} }
def install_hook(): def install_hook():
if config["keystone-release"] != "distro": if config["keystone-release"] != "distro":
setup_ppa(config["keystone-release"]) setup_ppa(config["keystone-release"])
execute("apt-get update", die=True)
execute("apt-get -y install %s" % packages, die=True, echo=True) execute("apt-get -y install %s" % packages, die=True, echo=True)
keystone_conf_update("keystone-admin-role", keystone_conf_update("keystone-admin-role",
config["keystone-admin-role"]) config["keystone-admin-role"])
@ -74,10 +75,10 @@ def identity_changed():
juju_log("Missing relation data. Peer not ready, exit 0") juju_log("Missing relation data. Peer not ready, exit 0")
exit(0) exit(0)
# we do not support the service advertised on the other end of relation # If we do not support the service advertised on the other end of relation
# return a token of -1 if it is not supported # return a token of -1
if relation_data["service"] not in valid_services.keys(): if relation_data["service"] not in valid_services.keys():
juju_log("Invalid service requested: '%s'" % relation_data["service"]) juju_log("WARN: Invalid service requested: '%s'" % relation_data["service"])
realtion_set({ "admin_token": -1 }) realtion_set({ "admin_token": -1 })
return return
import manager import manager
@ -90,6 +91,7 @@ def identity_changed():
relation_data["admin_url"], relation_data["admin_url"],
relation_data["internal_url"]) relation_data["internal_url"])
token = generate_admin_token(manager, config) token = generate_admin_token(manager, config)
# we return a token and information about our API endpoints
relation_data = { relation_data = {
"admin_token": token, "admin_token": token,
"service_host": config["hostname"], "service_host": config["hostname"],
@ -100,13 +102,18 @@ def identity_changed():
relation_set(relation_data) relation_set(relation_data)
def keystone_joined(): def keystone_joined():
""" the keystone relations are here specifically for horizon since it """
provide an API endpoint like other services but requires a valid The keystone-service relations exist specifically for horizon. Instead of
role and token to exist in keystone. it also needs to be informed a token and entry in the service catalog (like other services), it requires
of *our* api endpoints (admin and auth) """ a token and a role. It doesn't expose any endpoint that keystone needs to
care about, thus it relates to this unit via its own service relation.
"""
pass pass
def keystone_changed(): def keystone_changed():
""" Horizon will request a default role, we create it and return a
token
"""
import manager import manager
options = ["role"] options = ["role"]
relation_data = relation_get(options) relation_data = relation_get(options)
@ -116,6 +123,8 @@ def keystone_changed():
# create the requested admin role # create the requested admin role
create_role(manager, relation_data["role"], config["admin-user"]) create_role(manager, relation_data["role"], config["admin-user"])
token = generate_admin_token(manager, config) token = generate_admin_token(manager, config)
# Return token and API ports. Let horizon find our hostname via
# 'relation-get private-address'
relation_data = { relation_data = {
"service_port": config["service-port"], "service_port": config["service-port"],
"auth_port": config["admin-port"], "auth_port": config["admin-port"],
@ -133,9 +142,9 @@ hooks = {
"keystone-service-relation-changed": keystone_changed "keystone-service-relation-changed": keystone_changed
} }
# keystone-hooks gets called by symlink corresponding to the requested relation
# hook.
arg0 = sys.argv[0].split("/").pop() arg0 = sys.argv[0].split("/").pop()
if arg0 not in hooks.keys(): if arg0 not in hooks.keys():
error_out("Unsupported hook: %s" % arg0) error_out("Unsupported hook: %s" % arg0)
hooks[arg0]() hooks[arg0]()

View File

@ -1,5 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
#
# Bootstraps the keystone API so we can utilize its managment API natively
import keystone.manage import keystone.manage
import keystone.backends as db import keystone.backends as db
from keystone import version from keystone import version
@ -12,4 +13,3 @@ parser = RaisingOptionParser("", version='%%prog %s'
(options, args) = config.parse_options(parser) (options, args) = config.parse_options(parser)
_config_file, conf = config.load_paste_config('admin', options, args) _config_file, conf = config.load_paste_config('admin', options, args)
db.configure_backends(conf.global_conf) db.configure_backends(conf.global_conf)

View File

@ -10,9 +10,11 @@ stored_passwd = "/var/lib/keystone/keystone.passwd"
def execute(cmd, die=False, echo=False): def execute(cmd, die=False, echo=False):
""" Executes a command """ Executes a command
if die=True, script will exit(1) if command does not return 0
if echo=True, output of command will be printed to stdout if die=True, script will exit(1) if command does not return 0
returns a tuple: (stdout, stderr, return code) if echo=True, output of command will be printed to stdout
returns a tuple: (stdout, stderr, return code)
""" """
p = subprocess.Popen(cmd.split(" "), p = subprocess.Popen(cmd.split(" "),
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
@ -49,7 +51,12 @@ def error_out(msg):
exit(1) exit(1)
def setup_ppa(rel): def setup_ppa(rel):
""" currently the keystone-core team only publishes a trunk PPA """ """ Configure a PPA prior to installing.
Currently, keystone-core only maintains a trunk PPA (unlike other
subprojects that maintain one for milestone + milestone-proposed)
Currently, supported options are 'trunk' or a custom PPA passed to config
as 'ppa:someproject/someppa'
"""
if rel == "trunk": if rel == "trunk":
ppa = "ppa:keystone-core/trunk" ppa = "ppa:keystone-core/trunk"
elif rel[:4] == "ppa:": elif rel[:4] == "ppa:":
@ -59,8 +66,11 @@ def setup_ppa(rel):
execute(("add-apt-repository -y %s" % ppa), die=True, echo=True) execute(("add-apt-repository -y %s" % ppa), die=True, echo=True)
def config_get(): def config_get():
""" return a dict representing the output of config-get """ Obtain the units config via 'config-get'
private-address and IP of the unit is also tacked on """ Returns a dict representing current config.
private-address and IP of the unit is also tacked on for
convienence
"""
output = execute("config-get --format json")[0] output = execute("config-get --format json")[0]
config = json.loads(output) config = json.loads(output)
# make sure no config element is blank after config-get # make sure no config element is blank after config-get
@ -80,11 +90,13 @@ def relation_set(relation_data):
execute("relation-set %s=%s" % (k, relation_data[k]), die=True) execute("relation-set %s=%s" % (k, relation_data[k]), die=True)
def relation_get(relation_data): def relation_get(relation_data):
""" takes a list of options to query from the relation """ Obtain all current relation data
returns a k,v dict of the results. relation_data is a list of options to query from the relation
leave empty responses out of the results as they haven't yet been Returns a k,v dict of the results.
set on the other end. caller expects Leave empty responses out of the results as they haven't yet been
len(results.keys()) == len(relation_data) set on the other end.
Caller can then "len(results.keys()) == len(relation_data)" to find out if
all relation values have been set on the other side
""" """
results = {} results = {}
for r in relation_data: for r in relation_data:
@ -94,10 +106,10 @@ def relation_get(relation_data):
return results return results
def keystone_conf_update(opt, val): def keystone_conf_update(opt, val):
""" updates keystone.conf values """ Updates keystone.conf values
if option exists, it is reset to new value If option exists, it is reset to new value
if it does not, it added to the top of the config file If it does not, it added to the top of the config file after the [DEFAULT]
after the [DEFAULT] heading heading to keep it out of the paste deploy config
""" """
f = open(keystone_conf, "r+") f = open(keystone_conf, "r+")
orig = f.readlines() orig = f.readlines()
@ -178,7 +190,7 @@ def create_role(manager, name, user):
juju_log("Created new role '%s'" % name) juju_log("Created new role '%s'" % name)
else: else:
juju_log("A role named '%s' already exists" % name) juju_log("A role named '%s' already exists" % name)
# TODO Doesn't seem to be anyway of querying current role assignments? # NOTE: There does not seem to be any way of querying current role asignment
manager.api.grant_role(name, user) manager.api.grant_role(name, user)
juju_log("Granted role '%s' to '%s'" % (name, user)) juju_log("Granted role '%s' to '%s'" % (name, user))
@ -196,6 +208,8 @@ def ensure_initial_admin(config):
run during install as well as during db-changed. This will maintain run during install as well as during db-changed. This will maintain
the admin tenant, user, role, service entry and endpoint across every the admin tenant, user, role, service entry and endpoint across every
datastore we might use. datastore we might use.
TODO: Possibly migrate data from one backend to another after it
changes?
""" """
import manager import manager
create_tenant(manager, "admin") create_tenant(manager, "admin")