Refactoring to use openstack charm helpers

This commit is contained in:
James Page 2013-03-18 12:56:57 +00:00
parent b22142ee63
commit 7ce1bb2dd7
16 changed files with 296 additions and 343 deletions

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1,19 +1,53 @@
#!/usr/bin/python #!/usr/bin/python
import sys import os
import time import time
import urlparse import urlparse
from base64 import b64encode from base64 import b64encode
from utils import * from keystone_utils import (
config_get,
execute,
update_config_block,
set_admin_token,
ensure_initial_admin,
relation_get_dict,
create_service_entry,
create_endpoint_template,
create_role,
get_admin_token,
get_service_password,
create_user,
grant_role,
get_ca,
synchronize_service_credentials,
do_openstack_upgrade,
configure_pki_tokens,
SSH_USER,
SSL_DIR,
CLUSTER_RES
)
from lib.openstack_common import * from lib.openstack_common import (
configure_installation_source,
get_os_codename_install_source,
get_os_codename_package,
get_os_version_codename,
get_os_version_package,
save_script_rc
)
import lib.unison as unison import lib.unison as unison
import lib.utils as utils
import lib.cluster_utils as cluster
import lib.haproxy_utils as haproxy
config = config_get() config = config_get()
packages = "keystone python-mysqldb pwgen haproxy python-jinja2 openssl unison" packages = [
"keystone", "python-mysqldb", "pwgen",
"haproxy", "python-jinja2", "openssl", "unison"
]
service = "keystone" service = "keystone"
# used to verify joined services are valid openstack components. # used to verify joined services are valid openstack components.
@ -62,13 +96,15 @@ valid_services = {
} }
} }
def install_hook(): def install_hook():
if config["openstack-origin"] != "distro": if config["openstack-origin"] != "distro":
configure_installation_source(config["openstack-origin"]) configure_installation_source(config["openstack-origin"])
execute("apt-get update", die=True) utils.install(packages)
execute("apt-get -y install %s" % packages, die=True, echo=True) update_config_block('DEFAULT',
update_config_block('DEFAULT', public_port=config["service-port"]) public_port=cluster.determine_api_port(config["service-port"]))
update_config_block('DEFAULT', admin_port=config["admin-port"]) update_config_block('DEFAULT',
admin_port=cluster.determine_api_port(config["admin-port"]))
set_admin_token(config['admin-token']) set_admin_token(config['admin-token'])
# set all backends to use sql+sqlite, if they are not already by default # set all backends to use sql+sqlite, if they are not already by default
@ -83,9 +119,9 @@ def install_hook():
update_config_block('ec2', update_config_block('ec2',
driver='keystone.contrib.ec2.backends.sql.Ec2') driver='keystone.contrib.ec2.backends.sql.Ec2')
execute("service keystone stop", echo=True) utils.stop('keystone')
execute("keystone-manage db_sync") execute("keystone-manage db_sync")
execute("service keystone start", echo=True) utils.start('keystone')
# ensure /var/lib/keystone is g+wrx for peer relations that # ensure /var/lib/keystone is g+wrx for peer relations that
# may be syncing data there via SSH_USER. # may be syncing data there via SSH_USER.
@ -96,17 +132,21 @@ def install_hook():
def db_joined(): def db_joined():
relation_data = { "database": config["database"], relation_data = {
"username": config["database-user"], "database": config["database"],
"hostname": config["hostname"] } "username": config["database-user"],
relation_set(relation_data) "hostname": config["hostname"]
}
utils.relation_set(**relation_data)
def db_changed(): def db_changed():
relation_data = relation_get_dict() relation_data = relation_get_dict()
if ('password' not in relation_data or if ('password' not in relation_data or
'db_host' not in relation_data): 'db_host' not in relation_data):
juju_log("db_host or password not set. Peer not ready, exit 0") utils.juju_log('INFO',
exit(0) "db_host or password not set. Peer not ready, exit 0")
return
update_config_block('sql', connection="mysql://%s:%s@%s/%s" % update_config_block('sql', connection="mysql://%s:%s@%s/%s" %
(config["database-user"], (config["database-user"],
@ -114,15 +154,13 @@ def db_changed():
relation_data["db_host"], relation_data["db_host"],
config["database"])) config["database"]))
execute("service keystone stop", echo=True) utils.stop('keystone')
if cluster.eligible_leader(CLUSTER_RES):
utils.juju_log('INFO',
'Cluster leader, performing db-sync')
execute("keystone-manage db_sync", echo=True)
utils.start('keystone')
if not eligible_leader():
juju_log('Deferring DB initialization to service leader.')
execute("service keystone start")
return
execute("keystone-manage db_sync", echo=True)
execute("service keystone start")
time.sleep(5) time.sleep(5)
ensure_initial_admin(config) ensure_initial_admin(config)
@ -130,54 +168,46 @@ def db_changed():
# are existing identity-service relations,, service entries need to be # are existing identity-service relations,, service entries need to be
# recreated in the new database. Re-executing identity-service-changed # recreated in the new database. Re-executing identity-service-changed
# will do this. # will do this.
for id in relation_ids(relation_name='identity-service'): for rid in utils.relation_ids('identity-service'):
for unit in relation_list(relation_id=id): for unit in utils.relation_list(rid=rid):
juju_log("Re-exec'ing identity-service-changed for: %s - %s" % utils.juju_log('INFO',
(id, unit)) "Re-exec'ing identity-service-changed"
identity_changed(relation_id=id, remote_unit=unit) " for: %s - %s" % (rid, unit))
identity_changed(relation_id=rid, remote_unit=unit)
def ensure_valid_service(service): def ensure_valid_service(service):
if service not in valid_services.keys(): if service not in valid_services.keys():
juju_log("WARN: Invalid service requested: '%s'" % service) utils.juju_log('WARNING',
realtion_set({ "admin_token": -1 }) "Invalid service requested: '%s'" % service)
utils.relation_set(admin_token=-1)
return return
def add_endpoint(region, service, public_url, admin_url, internal_url):
def add_endpoint(region, service, publicurl, adminurl, internalurl):
desc = valid_services[service]["desc"] desc = valid_services[service]["desc"]
service_type = valid_services[service]["type"] service_type = valid_services[service]["type"]
create_service_entry(service, service_type, desc) create_service_entry(service, service_type, desc)
create_endpoint_template(region=region, service=service, create_endpoint_template(region=region, service=service,
public_url=public_url, publicurl=publicurl,
admin_url=admin_url, adminurl=adminurl,
internal_url=internal_url) internalurl=internalurl)
def identity_joined(): def identity_joined():
""" Do nothing until we get information about requested service """ """ Do nothing until we get information about requested service """
pass pass
def identity_changed(relation_id=None, remote_unit=None): def identity_changed(relation_id=None, remote_unit=None):
""" A service has advertised its API endpoints, create an entry in the """ A service has advertised its API endpoints, create an entry in the
service catalog. service catalog.
Optionally allow this hook to be re-fired for an existing Optionally allow this hook to be re-fired for an existing
relation+unit, for context see see db_changed(). relation+unit, for context see see db_changed().
""" """
def ensure_valid_service(service): if not cluster.eligible_leader(CLUSTER_RES):
if service not in valid_services.keys(): utils.juju_log('INFO',
juju_log("WARN: Invalid service requested: '%s'" % service) 'Deferring identity_changed() to service leader.')
realtion_set({ "admin_token": -1 })
return
def add_endpoint(region, service, publicurl, adminurl, internalurl):
desc = valid_services[service]["desc"]
service_type = valid_services[service]["type"]
create_service_entry(service, service_type, desc)
create_endpoint_template(region=region, service=service,
publicurl=publicurl,
adminurl=adminurl,
internalurl=internalurl)
if not eligible_leader():
juju_log('Deferring identity_changed() to service leader.')
return return
settings = relation_get_dict(relation_id=relation_id, settings = relation_get_dict(relation_id=relation_id,
@ -187,7 +217,8 @@ def identity_changed(relation_id=None, remote_unit=None):
# Currently used by Swift. # Currently used by Swift.
if 'requested_roles' in settings and settings['requested_roles'] != 'None': if 'requested_roles' in settings and settings['requested_roles'] != 'None':
roles = settings['requested_roles'].split(',') roles = settings['requested_roles'].split(',')
juju_log("Creating requested roles: %s" % roles) utils.juju_log('INFO',
"Creating requested roles: %s" % roles)
for role in roles: for role in roles:
create_role(role, user=config['admin-user'], tenant='admin') create_role(role, user=config['admin-user'], tenant='admin')
@ -196,25 +227,22 @@ def identity_changed(relation_id=None, remote_unit=None):
'internal_url']) 'internal_url'])
if single.issubset(settings): if single.issubset(settings):
# other end of relation advertised only one endpoint # other end of relation advertised only one endpoint
if 'None' in [v for k,v in settings.iteritems()]: if 'None' in [v for k, v in settings.iteritems()]:
# Some backend services advertise no endpoint but require a # Some backend services advertise no endpoint but require a
# hook execution to update auth strategy. # hook execution to update auth strategy.
relation_data = {} relation_data = {}
# Check if clustered and use vip + haproxy ports if so # Check if clustered and use vip + haproxy ports if so
if is_clustered(): if cluster.is_clustered():
relation_data["auth_host"] = config['vip'] relation_data["auth_host"] = config['vip']
relation_data["auth_port"] = SERVICE_PORTS['keystone_admin']
relation_data["service_host"] = config['vip'] relation_data["service_host"] = config['vip']
relation_data["service_port"] = SERVICE_PORTS['keystone_service']
else: else:
relation_data["auth_host"] = config['hostname'] relation_data["auth_host"] = config['hostname']
relation_data["auth_port"] = config['admin-port']
relation_data["service_host"] = config['hostname'] relation_data["service_host"] = config['hostname']
relation_data["service_port"] = config['service-port'] relation_data["auth_port"] = config['admin-port']
relation_set(relation_data) relation_data["service_port"] = config['service-port']
utils.relation_set(**relation_data)
return return
ensure_valid_service(settings['service']) ensure_valid_service(settings['service'])
add_endpoint(region=settings['region'], service=settings['service'], add_endpoint(region=settings['region'], service=settings['service'],
@ -242,7 +270,7 @@ def identity_changed(relation_id=None, remote_unit=None):
# } # }
# } # }
endpoints = {} endpoints = {}
for k,v in settings.iteritems(): for k, v in settings.iteritems():
ep = k.split('_')[0] ep = k.split('_')[0]
x = '_'.join(k.split('_')[1:]) x = '_'.join(k.split('_')[1:])
if ep not in endpoints: if ep not in endpoints:
@ -267,18 +295,20 @@ def identity_changed(relation_id=None, remote_unit=None):
https_cn = https_cn.hostname https_cn = https_cn.hostname
service_username = '_'.join(services) service_username = '_'.join(services)
if 'None' in [v for k,v in settings.iteritems()]: if 'None' in [v for k, v in settings.iteritems()]:
return return
if not service_username: if not service_username:
return return
token = get_admin_token() token = get_admin_token()
juju_log("Creating service credentials for '%s'" % service_username) utils.juju_log('INFO',
"Creating service credentials for '%s'" % service_username)
service_password = get_service_password(service_username) service_password = get_service_password(service_username)
create_user(service_username, service_password, config['service-tenant']) create_user(service_username, service_password, config['service-tenant'])
grant_role(service_username, config['admin-role'], config['service-tenant']) grant_role(service_username, config['admin-role'],
config['service-tenant'])
# As of https://review.openstack.org/#change,4675, all nodes hosting # As of https://review.openstack.org/#change,4675, all nodes hosting
# an endpoint(s) needs a service username and password assigned to # an endpoint(s) needs a service username and password assigned to
@ -305,27 +335,25 @@ def identity_changed(relation_id=None, remote_unit=None):
relation_data['rid'] = relation_id relation_data['rid'] = relation_id
# Check if clustered and use vip + haproxy ports if so # Check if clustered and use vip + haproxy ports if so
if is_clustered(): if cluster.is_clustered():
relation_data["auth_host"] = config['vip'] relation_data["auth_host"] = config['vip']
relation_data["auth_port"] = SERVICE_PORTS['keystone_admin']
relation_data["service_host"] = config['vip'] relation_data["service_host"] = config['vip']
relation_data["service_port"] = SERVICE_PORTS['keystone_service']
# generate or get a new cert/key for service if set to manage certs. # generate or get a new cert/key for service if set to manage certs.
if config['https-service-endpoints'] in ['True', 'true']: if config['https-service-endpoints'] in ['True', 'true']:
ca = get_ca(user=SSH_USER) ca = get_ca(user=SSH_USER)
service = os.getenv('JUJU_REMOTE_UNIT').split('/')[0]
cert, key = ca.get_cert_and_key(common_name=https_cn) cert, key = ca.get_cert_and_key(common_name=https_cn)
ca_bundle= ca.get_ca_bundle() ca_bundle = ca.get_ca_bundle()
relation_data['ssl_cert'] = b64encode(cert) relation_data['ssl_cert'] = b64encode(cert)
relation_data['ssl_key'] = b64encode(key) relation_data['ssl_key'] = b64encode(key)
relation_data['ca_cert'] = b64encode(ca_bundle) relation_data['ca_cert'] = b64encode(ca_bundle)
relation_data['https_keystone'] = 'True' relation_data['https_keystone'] = 'True'
unison.sync_to_peers(peer_interface='cluster', unison.sync_to_peers(peer_interface='cluster',
paths=[SSL_DIR], user=SSH_USER, verbose=True) paths=[SSL_DIR], user=SSH_USER, verbose=True)
relation_set_2(**relation_data) utils.relation_set(**relation_data)
synchronize_service_credentials() synchronize_service_credentials()
def config_changed(): def config_changed():
# Determine whether or not we should do an upgrade, based on the # Determine whether or not we should do an upgrade, based on the
@ -334,7 +362,8 @@ def config_changed():
installed = get_os_codename_package('keystone') installed = get_os_codename_package('keystone')
if (available and if (available and
get_os_version_codename(available) > get_os_version_codename(installed)): get_os_version_codename(available) > \
get_os_version_codename(installed)):
do_openstack_upgrade(config['openstack-origin'], packages) do_openstack_upgrade(config['openstack-origin'], packages)
env_vars = {'OPENSTACK_SERVICE_KEYSTONE': 'keystone', env_vars = {'OPENSTACK_SERVICE_KEYSTONE': 'keystone',
@ -344,8 +373,10 @@ def config_changed():
set_admin_token(config['admin-token']) set_admin_token(config['admin-token'])
if eligible_leader(): if cluster.eligible_leader(CLUSTER_RES):
juju_log('Cluster leader - ensuring endpoint configuration is up to date') utils.juju_log('INFO',
'Cluster leader - ensuring endpoint configuration'
' is up to date')
ensure_initial_admin(config) ensure_initial_admin(config)
update_config_block('logger_root', level=config['log-level'], update_config_block('logger_root', level=config['log-level'],
@ -354,69 +385,68 @@ def config_changed():
# PKI introduced in Grizzly # PKI introduced in Grizzly
configure_pki_tokens(config) configure_pki_tokens(config)
execute("service keystone restart", echo=True) utils.restart('keystone')
cluster_changed() cluster_changed()
def upgrade_charm(): def upgrade_charm():
cluster_changed() cluster_changed()
if eligible_leader(): if cluster.eligible_leader(CLUSTER_RES):
juju_log('Cluster leader - ensuring endpoint configuration is up to date') utils.juju_log('INFO',
'Cluster leader - ensuring endpoint configuration'
' is up to date')
ensure_initial_admin(config) ensure_initial_admin(config)
SERVICE_PORTS = {
"keystone_admin": int(config['admin-port']) + 1,
"keystone_service": int(config['service-port']) + 1
}
def cluster_joined(): def cluster_joined():
unison.ssh_authorized_peers(user=SSH_USER, unison.ssh_authorized_peers(user=SSH_USER,
group='keystone', group='keystone',
peer_interface='cluster', peer_interface='cluster',
ensure_user=True) ensure_user=True)
update_config_block('DEFAULT',
public_port=cluster.determine_api_port(config["service-port"]))
update_config_block('DEFAULT',
admin_port=cluster.determine_api_port(config["admin-port"]))
utils.restart('keystone')
service_ports = {
"keystone_admin": \
cluster.determine_haproxy_port(config['admin-port']),
"keystone_service": \
cluster.determine_haproxy_port(config['service-port'])
}
haproxy.configure_haproxy(service_ports)
def cluster_changed(): def cluster_changed():
unison.ssh_authorized_peers(user=SSH_USER, unison.ssh_authorized_peers(user=SSH_USER,
group='keystone', group='keystone',
peer_interface='cluster', peer_interface='cluster',
ensure_user=True) ensure_user=True)
cluster_hosts = {}
cluster_hosts['self'] = config['hostname']
for r_id in relation_ids('cluster'):
for unit in relation_list(r_id):
# trigger identity-changed to reconfigure HTTPS
# as necessary.
identity_changed(relation_id=r_id, remote_unit=unit)
cluster_hosts[unit.replace('/','-')] = \
relation_get_dict(relation_id=r_id,
remote_unit=unit)['private-address']
configure_haproxy(cluster_hosts,
SERVICE_PORTS)
synchronize_service_credentials() synchronize_service_credentials()
service_ports = {
"keystone_admin": \
cluster.determine_haproxy_port(config['admin-port']),
"keystone_service": \
cluster.determine_haproxy_port(config['service-port'])
}
haproxy.configure_haproxy(service_ports)
for r_id in relation_ids('identity-service'):
for unit in relation_list(r_id):
# trigger identity-changed to reconfigure HTTPS as necessary
identity_changed(relation_id=r_id, remote_unit=unit)
def ha_relation_changed(): def ha_relation_changed():
relation_data = relation_get_dict() relation_data = relation_get_dict()
if ('clustered' in relation_data and if ('clustered' in relation_data and
is_leader()): cluster.is_leader(CLUSTER_RES)):
juju_log('Cluster configured, notifying other services and updating' utils.juju_log('INFO',
'keystone endpoint configuration') 'Cluster configured, notifying other services'
' and updating keystone endpoint configuration')
# Update keystone endpoint to point at VIP # Update keystone endpoint to point at VIP
ensure_initial_admin(config) ensure_initial_admin(config)
# Tell all related services to start using # Tell all related services to start using
# the VIP and haproxy ports instead # the VIP and haproxy ports instead
for r_id in relation_ids('identity-service'): for r_id in utils.relation_ids('identity-service'):
relation_set_2(rid=r_id, utils.relation_set(rid=r_id,
auth_host=config['vip'], auth_host=config['vip'],
service_host=config['vip'], service_host=config['vip'])
service_port=SERVICE_PORTS['keystone_service'],
auth_port=SERVICE_PORTS['keystone_admin'])
def ha_relation_joined(): def ha_relation_joined():
@ -424,41 +454,33 @@ def ha_relation_joined():
# include multicast port and interface to bind to. # include multicast port and interface to bind to.
corosync_bindiface = config['ha-bindiface'] corosync_bindiface = config['ha-bindiface']
corosync_mcastport = config['ha-mcastport'] corosync_mcastport = config['ha-mcastport']
vip = config['vip']
vip_cidr = config['vip_cidr']
vip_iface = config['vip_iface']
# Obtain resources # Obtain resources
resources = { resources = {
'res_ks_vip':'ocf:heartbeat:IPaddr2', 'res_ks_vip': 'ocf:heartbeat:IPaddr2',
'res_ks_haproxy':'lsb:haproxy' 'res_ks_haproxy': 'lsb:haproxy'
} }
# TODO: Obtain netmask and nic where to place VIP.
resource_params = { resource_params = {
'res_ks_vip':'params ip="%s" cidr_netmask="%s" nic="%s"' % (config['vip'], 'res_ks_vip': 'params ip="%s" cidr_netmask="%s" nic="%s"' % \
config['vip_cidr'], config['vip_iface']), (vip, vip_cidr, vip_iface),
'res_ks_haproxy':'op monitor interval="5s"' 'res_ks_haproxy': 'op monitor interval="5s"'
} }
init_services = { init_services = {
'res_ks_haproxy':'haproxy' 'res_ks_haproxy': 'haproxy'
} }
groups = { clones = {
'grp_ks_haproxy':'res_ks_vip res_ks_haproxy' 'gl_ks_haproxy': 'res_ks_haproxy'
} }
#clones = {
# 'cln_ks_haproxy':'res_ks_haproxy meta globally-unique="false" interleave="true"'
# }
#orders = { utils.relation_set(init_services=init_services,
# 'ord_vip_before_haproxy':'inf: res_ks_vip res_ks_haproxy' corosync_bindiface=corosync_bindiface,
# } corosync_mcastport=corosync_mcastport,
#colocations = { resources=resources,
# 'col_vip_on_haproxy':'inf: res_ks_haproxy res_ks_vip' resource_params=resource_params,
# } clones=clones)
relation_set_2(init_services=init_services,
corosync_bindiface=corosync_bindiface,
corosync_mcastport=corosync_mcastport,
resources=resources,
resource_params=resource_params,
groups=groups)
hooks = { hooks = {
@ -476,9 +498,4 @@ hooks = {
"upgrade-charm": upgrade_charm "upgrade-charm": upgrade_charm
} }
# keystone-hooks gets called by symlink corresponding to the requested relation utils.do_hooks(hooks)
# hook.
hook = os.path.basename(sys.argv[0])
if hook not in hooks.keys():
error_out("Unsupported hook: %s" % hook)
hooks[hook]()

View File

@ -1,17 +1,23 @@
#!/usr/bin/python #!/usr/bin/python
import ConfigParser import ConfigParser
import subprocess
import sys import sys
import json import json
import os
import tarfile
import tempfile
import time import time
import subprocess
import os
from lib.openstack_common import * from lib.openstack_common import(
get_os_codename_install_source,
get_os_codename_package,
error_out,
configure_installation_source
)
import keystone_ssl as ssl import keystone_ssl as ssl
import lib.unison as unison import lib.unison as unison
import lib.utils as utils
import lib.cluster_utils as cluster
keystone_conf = "/etc/keystone/keystone.conf" keystone_conf = "/etc/keystone/keystone.conf"
stored_passwd = "/var/lib/keystone/keystone.passwd" stored_passwd = "/var/lib/keystone/keystone.passwd"
@ -20,8 +26,9 @@ SERVICE_PASSWD_PATH = '/var/lib/keystone/services.passwd'
SSL_DIR = '/var/lib/keystone/juju_ssl/' SSL_DIR = '/var/lib/keystone/juju_ssl/'
SSL_CA_NAME = 'Ubuntu Cloud' SSL_CA_NAME = 'Ubuntu Cloud'
CLUSTER_RES = 'res_ks_vip'
SSH_USER = 'juju_keystone'
SSH_USER='juju_keystone'
def execute(cmd, die=False, echo=False): def execute(cmd, die=False, echo=False):
""" Executes a command """ Executes a command
@ -35,8 +42,8 @@ def execute(cmd, die=False, echo=False):
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
stderr=subprocess.PIPE) stderr=subprocess.PIPE)
stdout="" stdout = ""
stderr="" stderr = ""
def print_line(l): def print_line(l):
if echo: if echo:
@ -59,7 +66,7 @@ def execute(cmd, die=False, echo=False):
def config_get(): def config_get():
""" Obtain the units config via 'config-get' """ Obtain the units config via 'config-get'
Returns a dict representing current config. Returns a dict representing current config.
private-address and IP of the unit is also tacked on for private-address and IP of the unit is also tacked on for
convienence convienence
@ -68,71 +75,12 @@ def config_get():
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
for c in config.keys(): for c in config.keys():
if not config[c]: if not config[c]:
error_out("ERROR: Config option has no paramter: %s" % c) error_out("ERROR: Config option has no paramter: %s" % c)
# tack on our private address and ip # tack on our private address and ip
hostname = execute("unit-get private-address")[0].strip() config["hostname"] = utils.unit_get('private-address')
config["hostname"] = execute("unit-get private-address")[0].strip()
return config return config
def relation_ids(relation_name=None):
j = execute('relation-ids --format=json %s' % relation_name)[0]
return json.loads(j)
def relation_list(relation_id=None):
cmd = 'relation-list --format=json'
if relation_id:
cmd += ' -r %s' % relation_id
j = execute(cmd)[0]
return json.loads(j)
def relation_set(relation_data):
""" calls relation-set for all key=values in dict """
for k in relation_data:
execute("relation-set %s=%s" % (k, relation_data[k]), die=True)
def relation_set_2(**kwargs):
cmd = [
'relation-set'
]
args = []
for k, v in kwargs.items():
if k == 'rid':
cmd.append('-r')
cmd.append(v)
else:
args.append('{}={}'.format(k, v))
cmd += args
subprocess.check_call(cmd)
def unit_get(attribute):
cmd = [
'unit-get',
attribute
]
value = subprocess.check_output(cmd).strip() # IGNORE:E1103
if value == "":
return None
else:
return value
def relation_get(relation_data):
""" Obtain all current relation data
relation_data is a list of options to query from the relation
Returns a k,v dict of the results.
Leave empty responses out of the results as they haven't yet been
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 = {}
for r in relation_data:
result = execute("relation-get %s" % r, die=True)[0].strip('\n')
if result != "":
results[r] = result
return results
def relation_get_dict(relation_id=None, remote_unit=None): def relation_get_dict(relation_id=None, remote_unit=None):
"""Obtain all relation data as dict by way of JSON""" """Obtain all relation data as dict by way of JSON"""
@ -152,18 +100,23 @@ def relation_get_dict(relation_id=None, remote_unit=None):
settings[str(k)] = str(v) settings[str(k)] = str(v)
return settings return settings
def set_admin_token(admin_token): def set_admin_token(admin_token):
"""Set admin token according to deployment config or use a randomly """Set admin token according to deployment config or use a randomly
generated token if none is specified (default). generated token if none is specified (default).
""" """
if admin_token != 'None': if admin_token != 'None':
juju_log('Configuring Keystone to use a pre-configured admin token.') utils.juju_log('INFO',
'Configuring Keystone to use'
' a pre-configured admin token.')
token = admin_token token = admin_token
else: else:
juju_log('Configuring Keystone to use a random admin token.') utils.juju_log('INFO',
'Configuring Keystone to use a random admin token.')
if os.path.isfile(stored_token): if os.path.isfile(stored_token):
msg = 'Loading a previously generated admin token from %s' % stored_token msg = 'Loading a previously generated' \
juju_log(msg) ' admin token from %s' % stored_token
utils.juju_log('INFO', msg)
f = open(stored_token, 'r') f = open(stored_token, 'r')
token = f.read().strip() token = f.read().strip()
f.close() f.close()
@ -174,6 +127,7 @@ def set_admin_token(admin_token):
out.close() out.close()
update_config_block('DEFAULT', admin_token=token) update_config_block('DEFAULT', admin_token=token)
def get_admin_token(): def get_admin_token():
"""Temporary utility to grab the admin token as configured in """Temporary utility to grab the admin token as configured in
keystone.conf keystone.conf
@ -188,6 +142,7 @@ def get_admin_token():
keystone_conf) keystone_conf)
error_out('Could not find admin_token line in %s' % keystone_conf) error_out('Could not find admin_token line in %s' % keystone_conf)
def update_config_block(section, **kwargs): def update_config_block(section, **kwargs):
""" Updates keystone.conf blocks given kwargs. """ Updates keystone.conf blocks given kwargs.
Update a config setting in a specific setting of a config Update a config setting in a specific setting of a config
@ -209,6 +164,7 @@ def update_config_block(section, **kwargs):
with open(conf_file, 'wb') as out: with open(conf_file, 'wb') as out:
config.write(out) config.write(out)
def create_service_entry(service_name, service_type, service_desc, owner=None): def create_service_entry(service_name, service_type, service_desc, owner=None):
""" Add a new service entry to keystone if one does not already exist """ """ Add a new service entry to keystone if one does not already exist """
import manager import manager
@ -216,12 +172,15 @@ def create_service_entry(service_name, service_type, service_desc, owner=None):
token=get_admin_token()) token=get_admin_token())
for service in [s._info for s in manager.api.services.list()]: for service in [s._info for s in manager.api.services.list()]:
if service['name'] == service_name: if service['name'] == service_name:
juju_log("Service entry for '%s' already exists." % service_name) utils.juju_log('INFO',
"Service entry for '%s' already exists." % \
service_name)
return return
manager.api.services.create(name=service_name, manager.api.services.create(name=service_name,
service_type=service_type, service_type=service_type,
description=service_desc) description=service_desc)
juju_log("Created new service entry '%s'" % service_name) utils.juju_log('INFO', "Created new service entry '%s'" % service_name)
def create_endpoint_template(region, service, publicurl, adminurl, def create_endpoint_template(region, service, publicurl, adminurl,
internalurl): internalurl):
@ -233,8 +192,9 @@ def create_endpoint_template(region, service, publicurl, adminurl,
service_id = manager.resolve_service_id(service) service_id = manager.resolve_service_id(service)
for ep in [e._info for e in manager.api.endpoints.list()]: for ep in [e._info for e in manager.api.endpoints.list()]:
if ep['service_id'] == service_id and ep['region'] == region: if ep['service_id'] == service_id and ep['region'] == region:
juju_log("Endpoint template already exists for '%s' in '%s'" utils.juju_log('INFO',
% (service, region)) "Endpoint template already exists for '%s' in '%s'"
% (service, region))
up_to_date = True up_to_date = True
for k in ['publicurl', 'adminurl', 'internalurl']: for k in ['publicurl', 'adminurl', 'internalurl']:
@ -245,7 +205,9 @@ def create_endpoint_template(region, service, publicurl, adminurl,
return return
else: else:
# delete endpoint and recreate if endpoint urls need updating. # delete endpoint and recreate if endpoint urls need updating.
juju_log("Updating endpoint template with new endpoint urls.") utils.juju_log('INFO',
"Updating endpoint template with"
" new endpoint urls.")
manager.api.endpoints.delete(ep['id']) manager.api.endpoints.delete(ep['id'])
manager.api.endpoints.create(region=region, manager.api.endpoints.create(region=region,
@ -253,8 +215,9 @@ def create_endpoint_template(region, service, publicurl, adminurl,
publicurl=publicurl, publicurl=publicurl,
adminurl=adminurl, adminurl=adminurl,
internalurl=internalurl) internalurl=internalurl)
juju_log("Created new endpoint template for '%s' in '%s'" % utils.juju_log('INFO', "Created new endpoint template for '%s' in '%s'" %
(region, service)) (region, service))
def create_tenant(name): def create_tenant(name):
""" creates a tenant if it does not already exist """ """ creates a tenant if it does not already exist """
@ -265,9 +228,10 @@ def create_tenant(name):
if not tenants or name not in [t['name'] for t in tenants]: if not tenants or name not in [t['name'] for t in tenants]:
manager.api.tenants.create(tenant_name=name, manager.api.tenants.create(tenant_name=name,
description='Created by Juju') description='Created by Juju')
juju_log("Created new tenant: %s" % name) utils.juju_log('INFO', "Created new tenant: %s" % name)
return return
juju_log("Tenant '%s' already exists." % name) utils.juju_log('INFO', "Tenant '%s' already exists." % name)
def create_user(name, password, tenant): def create_user(name, password, tenant):
""" creates a user if it doesn't already exist, as a member of tenant """ """ creates a user if it doesn't already exist, as a member of tenant """
@ -283,9 +247,11 @@ def create_user(name, password, tenant):
password=password, password=password,
email='juju@localhost', email='juju@localhost',
tenant_id=tenant_id) tenant_id=tenant_id)
juju_log("Created new user '%s' tenant: %s" % (name, tenant_id)) utils.juju_log('INFO', "Created new user '%s' tenant: %s" % \
(name, tenant_id))
return return
juju_log("A user named '%s' already exists" % name) utils.juju_log('INFO', "A user named '%s' already exists" % name)
def create_role(name, user=None, tenant=None): def create_role(name, user=None, tenant=None):
""" creates a role if it doesn't already exist. grants role to user """ """ creates a role if it doesn't already exist. grants role to user """
@ -295,9 +261,9 @@ def create_role(name, user=None, tenant=None):
roles = [r._info for r in manager.api.roles.list()] roles = [r._info for r in manager.api.roles.list()]
if not roles or name not in [r['name'] for r in roles]: if not roles or name not in [r['name'] for r in roles]:
manager.api.roles.create(name=name) manager.api.roles.create(name=name)
juju_log("Created new role '%s'" % name) utils.juju_log('INFO', "Created new role '%s'" % name)
else: else:
juju_log("A role named '%s' already exists" % name) utils.juju_log('INFO', "A role named '%s' already exists" % name)
if not user and not tenant: if not user and not tenant:
return return
@ -308,32 +274,35 @@ def create_role(name, user=None, tenant=None):
tenant_id = manager.resolve_tenant_id(tenant) tenant_id = manager.resolve_tenant_id(tenant)
if None in [user_id, role_id, tenant_id]: if None in [user_id, role_id, tenant_id]:
error_out("Could not resolve [user_id, role_id, tenant_id]" % error_out("Could not resolve [%s, %s, %s]" %
[user_id, role_id, tenant_id]) (user_id, role_id, tenant_id))
grant_role(user, name, tenant) grant_role(user, name, tenant)
def grant_role(user, role, tenant): def grant_role(user, role, tenant):
"""grant user+tenant a specific role""" """grant user+tenant a specific role"""
import manager import manager
manager = manager.KeystoneManager(endpoint='http://localhost:35357/v2.0/', manager = manager.KeystoneManager(endpoint='http://localhost:35357/v2.0/',
token=get_admin_token()) token=get_admin_token())
juju_log("Granting user '%s' role '%s' on tenant '%s'" %\ utils.juju_log('INFO', "Granting user '%s' role '%s' on tenant '%s'" % \
(user, role, tenant)) (user, role, tenant))
user_id = manager.resolve_user_id(user) user_id = manager.resolve_user_id(user)
role_id = manager.resolve_role_id(role) role_id = manager.resolve_role_id(role)
tenant_id = manager.resolve_tenant_id(tenant) tenant_id = manager.resolve_tenant_id(tenant)
cur_roles = manager.api.roles.roles_for_user(user_id, tenant_id) cur_roles = manager.api.roles.roles_for_user(user_id, tenant_id)
if not cur_roles or role_id not in [r.id for r in cur_roles]: if not cur_roles or role_id not in [r.id for r in cur_roles]:
manager.api.roles.add_user_role(user=user_id, manager.api.roles.add_user_role(user=user_id,
role=role_id, role=role_id,
tenant=tenant_id) tenant=tenant_id)
juju_log("Granted user '%s' role '%s' on tenant '%s'" %\ utils.juju_log('INFO', "Granted user '%s' role '%s' on tenant '%s'" % \
(user, role, tenant)) (user, role, tenant))
else: else:
juju_log("User '%s' already has role '%s' on tenant '%s'" %\ utils.juju_log('INFO',
(user, role, tenant)) "User '%s' already has role '%s' on tenant '%s'" % \
(user, role, tenant))
def generate_admin_token(config): def generate_admin_token(config):
""" generate and add an admin token """ """ generate and add an admin token """
@ -345,12 +314,15 @@ def generate_admin_token(config):
token = random.randrange(1000000000000, 9999999999999) token = random.randrange(1000000000000, 9999999999999)
else: else:
return config["admin-token"] return config["admin-token"]
manager.api.add_token(token, config["admin-user"], "admin", config["token-expiry"]) manager.api.add_token(token, config["admin-user"],
juju_log("Generated and added new random admin token.") "admin", config["token-expiry"])
utils.juju_log('INFO', "Generated and added new random admin token.")
return token return token
def ensure_initial_admin(config): def ensure_initial_admin(config):
""" Ensures the minimum admin stuff exists in whatever database we're using. """ Ensures the minimum admin stuff exists in whatever database we're
using.
This and the helper functions it calls are meant to be idempotent and This and the helper functions it calls are meant to be idempotent and
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
@ -365,10 +337,11 @@ def ensure_initial_admin(config):
if config["admin-password"] != "None": if config["admin-password"] != "None":
passwd = config["admin-password"] passwd = config["admin-password"]
elif os.path.isfile(stored_passwd): elif os.path.isfile(stored_passwd):
juju_log("Loading stored passwd from %s" % stored_passwd) utils.juju_log('INFO', "Loading stored passwd from %s" % stored_passwd)
passwd = open(stored_passwd, 'r').readline().strip('\n') passwd = open(stored_passwd, 'r').readline().strip('\n')
if passwd == "": if passwd == "":
juju_log("Generating new passwd for user: %s" % config["admin-user"]) utils.juju_log('INFO', "Generating new passwd for user: %s" % \
config["admin-user"])
passwd = execute("pwgen -c 16 1", die=True)[0] passwd = execute("pwgen -c 16 1", die=True)[0]
open(stored_passwd, 'w+').writelines("%s\n" % passwd) open(stored_passwd, 'w+').writelines("%s\n" % passwd)
@ -380,22 +353,13 @@ def ensure_initial_admin(config):
create_role("KeystoneServiceAdmin", config["admin-user"], 'admin') create_role("KeystoneServiceAdmin", config["admin-user"], 'admin')
create_service_entry("keystone", "identity", "Keystone Identity Service") create_service_entry("keystone", "identity", "Keystone Identity Service")
if is_clustered(): utils.juju_log('INFO', "Creating standard endpoint")
juju_log("Creating endpoint for clustered configuration") for region in config['region'].split():
for region in config['region'].split(): create_keystone_endpoint(service_host=config["hostname"],
create_keystone_endpoint(service_host=config["vip"], service_port=config["service-port"],
service_port=int(config["service-port"]) + 1, auth_host=config["hostname"],
auth_host=config["vip"], auth_port=config["admin-port"],
auth_port=int(config["admin-port"]) + 1, region=region)
region=region)
else:
juju_log("Creating standard endpoint")
for region in config['region'].split():
create_keystone_endpoint(service_host=config["hostname"],
service_port=config["service-port"],
auth_host=config["hostname"],
auth_port=config["admin-port"],
region=region)
def create_keystone_endpoint(service_host, service_port, def create_keystone_endpoint(service_host, service_port,
@ -411,14 +375,16 @@ def update_user_password(username, password):
import manager import manager
manager = manager.KeystoneManager(endpoint='http://localhost:35357/v2.0/', manager = manager.KeystoneManager(endpoint='http://localhost:35357/v2.0/',
token=get_admin_token()) token=get_admin_token())
juju_log("Updating password for user '%s'" % username) utils.juju_log('INFO', "Updating password for user '%s'" % username)
user_id = manager.resolve_user_id(username) user_id = manager.resolve_user_id(username)
if user_id is None: if user_id is None:
error_out("Could not resolve user id for '%s'" % username) error_out("Could not resolve user id for '%s'" % username)
manager.api.users.update_password(user=user_id, password=password) manager.api.users.update_password(user=user_id, password=password)
juju_log("Successfully updated password for user '%s'" % username) utils.juju_log('INFO', "Successfully updated password for user '%s'" % \
username)
def load_stored_passwords(path=SERVICE_PASSWD_PATH): def load_stored_passwords(path=SERVICE_PASSWD_PATH):
creds = {} creds = {}
@ -431,10 +397,12 @@ def load_stored_passwords(path=SERVICE_PASSWD_PATH):
creds[user] = passwd creds[user] = passwd
return creds return creds
def save_stored_passwords(path=SERVICE_PASSWD_PATH, **creds): def save_stored_passwords(path=SERVICE_PASSWD_PATH, **creds):
with open(path, 'wb') as stored_passwd: with open(path, 'wb') as stored_passwd:
[stored_passwd.write('%s:%s\n' % (u, p)) for u, p in creds.iteritems()] [stored_passwd.write('%s:%s\n' % (u, p)) for u, p in creds.iteritems()]
def get_service_password(service_username): def get_service_password(service_username):
creds = load_stored_passwords() creds = load_stored_passwords()
if service_username in creds: if service_username in creds:
@ -446,12 +414,13 @@ def get_service_password(service_username):
return passwd return passwd
def configure_pki_tokens(config): def configure_pki_tokens(config):
'''Configure PKI token signing, if enabled.''' '''Configure PKI token signing, if enabled.'''
if config['enable-pki'] not in ['True', 'true']: if config['enable-pki'] not in ['True', 'true']:
update_config_block('signing', token_format='UUID') update_config_block('signing', token_format='UUID')
else: else:
juju_log('TODO: PKI Support, setting to UUID for now.') utils.juju_log('INFO', 'TODO: PKI Support, setting to UUID for now.')
update_config_block('signing', token_format='UUID') update_config_block('signing', token_format='UUID')
@ -462,10 +431,12 @@ def do_openstack_upgrade(install_src, packages):
old_vers = get_os_codename_package('keystone') old_vers = get_os_codename_package('keystone')
new_vers = get_os_codename_install_source(install_src) new_vers = get_os_codename_install_source(install_src)
juju_log("Beginning Keystone upgrade: %s -> %s" % (old_vers, new_vers)) utils.juju_log('INFO',
"Beginning Keystone upgrade: %s -> %s" % \
(old_vers, new_vers))
# Backup previous config. # Backup previous config.
juju_log("Backing up contents of /etc/keystone.") utils.juju_log('INFO', "Backing up contents of /etc/keystone.")
stamp = time.strftime('%Y%m%d%H%M') stamp = time.strftime('%Y%m%d%H%M')
cmd = 'tar -pcf /var/lib/juju/keystone-backup-%s.tar /etc/keystone' % stamp cmd = 'tar -pcf /var/lib/juju/keystone-backup-%s.tar /etc/keystone' % stamp
execute(cmd, die=True, echo=True) execute(cmd, die=True, echo=True)
@ -482,14 +453,16 @@ def do_openstack_upgrade(install_src, packages):
set_admin_token(config['admin-token']) set_admin_token(config['admin-token'])
# set the sql connection string if a shared-db relation is found. # set the sql connection string if a shared-db relation is found.
ids = relation_ids(relation_name='shared-db') ids = utils.relation_ids('shared-db')
if ids: if ids:
for id in ids: for rid in ids:
for unit in relation_list(id): for unit in utils.relation_list(rid):
juju_log('Configuring new keystone.conf for datbase access '\ utils.juju_log('INFO',
'on existing database relation to %s' % unit) 'Configuring new keystone.conf for '
relation_data = relation_get_dict(relation_id=id, 'database access on existing database'
' relation to %s' % unit)
relation_data = relation_get_dict(relation_id=rid,
remote_unit=unit) remote_unit=unit)
update_config_block('sql', connection="mysql://%s:%s@%s/%s" % update_config_block('sql', connection="mysql://%s:%s@%s/%s" %
@ -498,66 +471,21 @@ def do_openstack_upgrade(install_src, packages):
relation_data["private-address"], relation_data["private-address"],
config["database"])) config["database"]))
execute('service keystone stop', echo=True) utils.stop('keystone')
if ((is_clustered() and is_leader()) or if (cluster.eligible_leader(CLUSTER_RES)):
not is_clustered()): utils.juju_log('INFO',
juju_log('Running database migrations for %s' % new_vers) 'Running database migrations for %s' % new_vers)
execute('keystone-manage db_sync', echo=True, die=True) execute('keystone-manage db_sync', echo=True, die=True)
else: else:
juju_log('Not cluster leader; snoozing whilst leader upgrades DB') utils.juju_log('INFO',
'Not cluster leader; snoozing whilst'
' leader upgrades DB')
time.sleep(10) time.sleep(10)
execute('service keystone start', echo=True) utils.start('keystone')
time.sleep(5) time.sleep(5)
juju_log('Completed Keystone upgrade: %s -> %s' % (old_vers, new_vers)) utils.juju_log('INFO',
'Completed Keystone upgrade: '
'%s -> %s' % (old_vers, new_vers))
def is_clustered():
for r_id in (relation_ids('ha') or []):
for unit in (relation_list(r_id) or []):
relation_data = \
relation_get_dict(relation_id=r_id,
remote_unit=unit)
if 'clustered' in relation_data:
return True
return False
def is_leader():
status = execute('crm resource show res_ks_vip', echo=True)[0].strip()
hostname = execute('hostname', echo=True)[0].strip()
if hostname in status:
return True
else:
return False
def peer_units():
peers = []
for r_id in (relation_ids('cluster') or []):
for unit in (relation_list(r_id) or []):
peers.append(unit)
return peers
def oldest_peer(peers):
local_unit_no = os.getenv('JUJU_UNIT_NAME').split('/')[1]
for peer in peers:
remote_unit_no = peer.split('/')[1]
if remote_unit_no < local_unit_no:
return False
return True
def eligible_leader():
if is_clustered():
if not is_leader():
juju_log('Deferring action to CRM leader.')
return False
else:
peers = peer_units()
if peers and not oldest_peer(peers):
juju_log('Deferring action to oldest service unit.')
return False
return True
def synchronize_service_credentials(): def synchronize_service_credentials():
@ -565,15 +493,17 @@ def synchronize_service_credentials():
Broadcast service credentials to peers or consume those that have been Broadcast service credentials to peers or consume those that have been
broadcasted by peer, depending on hook context. broadcasted by peer, depending on hook context.
''' '''
if (not eligible_leader() or if (not cluster.eligible_leader(CLUSTER_RES) or
not os.path.isfile(SERVICE_PASSWD_PATH)): not os.path.isfile(SERVICE_PASSWD_PATH)):
return return
juju_log('Synchronizing service passwords to all peers.') utils.juju_log('INFO', 'Synchronizing service passwords to all peers.')
unison.sync_to_peers(peer_interface='cluster', unison.sync_to_peers(peer_interface='cluster',
paths=[SERVICE_PASSWD_PATH], user=SSH_USER, paths=[SERVICE_PASSWD_PATH], user=SSH_USER,
verbose=True) verbose=True)
CA = [] CA = []
def get_ca(user='keystone', group='keystone'): def get_ca(user='keystone', group='keystone'):
""" """
Initialize a new CA object if one hasn't already been loaded. Initialize a new CA object if one hasn't already been loaded.

View File

@ -13,7 +13,7 @@ ubuntu_openstack_release = {
'oneiric': 'diablo', 'oneiric': 'diablo',
'precise': 'essex', 'precise': 'essex',
'quantal': 'folsom', 'quantal': 'folsom',
'raring' : 'grizzly', 'raring': 'grizzly',
} }
@ -34,6 +34,7 @@ swift_codenames = {
'1.7.7': 'grizzly', '1.7.7': 'grizzly',
} }
def juju_log(msg): def juju_log(msg):
subprocess.check_call(['juju-log', msg]) subprocess.check_call(['juju-log', msg])
@ -78,6 +79,7 @@ def get_os_codename_install_source(src):
if v in src: if v in src:
return v return v
def get_os_codename_version(vers): def get_os_codename_version(vers):
'''Determine OpenStack codename from version number.''' '''Determine OpenStack codename from version number.'''
try: try:
@ -136,6 +138,7 @@ def get_os_version_package(pkg):
e = "Could not determine OpenStack version for package: %s" % pkg e = "Could not determine OpenStack version for package: %s" % pkg
error_out(e) error_out(e)
def configure_installation_source(rel): def configure_installation_source(rel):
'''Configure apt installation source.''' '''Configure apt installation source.'''
@ -154,7 +157,7 @@ def configure_installation_source(rel):
subprocess.check_call(["add-apt-repository", "-y", src]) subprocess.check_call(["add-apt-repository", "-y", src])
elif rel[:3] == "deb": elif rel[:3] == "deb":
l = len(rel.split('|')) l = len(rel.split('|'))
if l == 2: if l == 2:
src, key = rel.split('|') src, key = rel.split('|')
juju_log("Importing PPA key from keyserver for %s" % src) juju_log("Importing PPA key from keyserver for %s" % src)
_import_key(key) _import_key(key)
@ -211,6 +214,7 @@ def configure_installation_source(rel):
HAPROXY_CONF = '/etc/haproxy/haproxy.cfg' HAPROXY_CONF = '/etc/haproxy/haproxy.cfg'
HAPROXY_DEFAULT = '/etc/default/haproxy' HAPROXY_DEFAULT = '/etc/default/haproxy'
def configure_haproxy(units, service_ports, template_dir=None): def configure_haproxy(units, service_ports, template_dir=None):
template_dir = template_dir or 'templates' template_dir = template_dir or 'templates'
import jinja2 import jinja2
@ -229,6 +233,7 @@ def configure_haproxy(units, service_ports, template_dir=None):
with open(HAPROXY_DEFAULT, 'w') as f: with open(HAPROXY_DEFAULT, 'w') as f:
f.write('ENABLED=1') f.write('ENABLED=1')
def save_script_rc(script_path="scripts/scriptrc", **env_vars): def save_script_rc(script_path="scripts/scriptrc", **env_vars):
""" """
Write an rc file in the charm-delivered directory containing Write an rc file in the charm-delivered directory containing
@ -238,7 +243,7 @@ def save_script_rc(script_path="scripts/scriptrc", **env_vars):
service changes. service changes.
""" """
unit_name = os.getenv('JUJU_UNIT_NAME').replace('/', '-') unit_name = os.getenv('JUJU_UNIT_NAME').replace('/', '-')
juju_rc_path="/var/lib/juju/units/%s/charm/%s" % (unit_name, script_path) juju_rc_path = "/var/lib/juju/units/%s/charm/%s" % (unit_name, script_path)
with open(juju_rc_path, 'wb') as rc_script: with open(juju_rc_path, 'wb') as rc_script:
rc_script.write( rc_script.write(
"#!/bin/bash\n") "#!/bin/bash\n")

View File

@ -1,6 +1,7 @@
#!/usr/bin/python #!/usr/bin/python
from keystoneclient.v2_0 import client from keystoneclient.v2_0 import client
class KeystoneManager(object): class KeystoneManager(object):
def __init__(self, endpoint, token): def __init__(self, endpoint, token):
self.api = client.Client(endpoint=endpoint, token=token) self.api = client.Client(endpoint=endpoint, token=token)

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py

View File

@ -1 +1 @@
keystone-hooks keystone_hooks.py