Initial baseline

This commit is contained in:
James Page 2012-11-05 11:59:27 +00:00
parent 89a83cd8df
commit ae86ade9cb
17 changed files with 229 additions and 336 deletions

1
hooks/amqp-relation-changed Symbolic link
View File

@ -0,0 +1 @@
hooks.py

1
hooks/amqp-relation-joined Symbolic link
View File

@ -0,0 +1 @@
hooks.py

View File

@ -3,6 +3,7 @@
import utils
import sys
import quantum_utils
import os
PLUGIN_PKGS = {
@ -26,7 +27,9 @@ def install():
# Install OVS DKMS first to ensure that the ovs module
# loaded supports GRE tunnels
utils.install('openvswitch-datapath-dkms')
utils.install(['quantum-server'].extend(PLUGIN_PKGS[plugin]))
utils.install('quantum-server',
'python-mysqldb',
*PLUGIN_PKGS[plugin])
else:
utils.juju_log('ERROR', 'Please provide a valid plugin config')
sys.exit(1)
@ -35,22 +38,66 @@ def install():
def config_changed():
plugin = utils.config_get('plugin')
if plugin in PLUGIN_PKGS.keys():
render_api_paste_conf()
render_quantum_conf()
render_plugin_conf()
if plugin == "ovs":
# TODO: Defaults to Quantum Provider Router
quantum_utils.add_bridge('br-int')
quantum_utils.add_bridge('br-ext')
quantum_utils.add_bridge('br-ex')
ext_port = utils.config_get('ext-port')
if ext_port:
quantum_utils.add_bridge_port('br-ex', ext_port)
quantum_utils.configure_core_plugin(plugin)
quantum_utils.configure_local_ip(plugin,
utils.unit_get('private-address'))
render_l3_agent_conf()
utils.restart('quantum-l3-agent',
'quantum-plugin-openvswitch-agent',
'quantum-dhcp-agent')
utils.restart('quantum-server')
else:
utils.juju_log('ERROR',
'Please provide a valid plugin config')
sys.exit(1)
def upgrade_charm():
install()
config_changed()
def render_l3_agent_conf():
context = get_keystone_conf()
if context:
with open(quantum_utils.L3_AGENT_CONF, "w") as conf:
conf.write(utils.render_template("l3_agent.ini", context))
def render_api_paste_conf():
context = get_keystone_conf()
if context:
with open(quantum_utils.QUANTUM_API_CONF, "w") as conf:
conf.write(utils.render_template("api-paste.ini", context))
def render_quantum_conf():
context = get_rabbit_conf()
if context:
context['core_plugin'] = \
quantum_utils.CORE_PLUGIN[utils.config_get('plugin')]
with open(quantum_utils.QUANTUM_CONF, "w") as conf:
conf.write(utils.render_template("quantum.conf", context))
def render_plugin_conf():
context = get_db_conf()
if context:
context['local_ip'] = utils.unit_get('private-address')
plugin = utils.config_get('plugin')
conf_file = quantum_utils.PLUGIN_CONF[plugin]
with open(conf_file, "w") as conf:
conf.write(utils.render_template(os.path.basename(conf_file),
context))
def keystone_joined():
url = "http://{}:9696/".format(utils.unit_get('private-address'))
utils.relation_set(service="quantum",
@ -61,34 +108,36 @@ def keystone_joined():
def keystone_changed():
token = utils.relation_get('admin_token')
service_port = utils.relation_get('service_port')
auth_port = utils.relation_get('auth_port')
service_username = utils.relation_get('service_username')
service_password = utils.relation_get('service_password')
service_tenant = utils.relation_get('service_tenant')
if not (token and
service_port and
auth_port and
service_username and
service_password and
service_tenant):
utils.juju_log('INFO',
'keystone peer not ready yet')
return
if token == "-1":
utils.juju_log('ERROR',
'Admin token error')
sys.exit(1)
keystone_host = utils.relation_get('private-address')
utils.juju_log('INFO', 'Configuring quantum for keystone authentication')
quantum_utils.configure_keystone(keystone_host,
token,
service_port,
auth_port,
service_username,
service_password,
service_tenant)
if os.path.exists(quantum_utils.L3_AGENT_CONF):
render_l3_agent_conf() # Restart quantum_l3_agent
utils.restart('quantum-l3-agent')
render_api_paste_conf() # Restart quantum server
utils.restart('quantum-server')
if os.path.exists(quantum_utils.DHCP_AGENT_CONF):
utils.restart('quantum-dhcp-agent')
notify_agents()
def get_keystone_conf():
for relid in utils.relation_ids('identity-service'):
for unit in utils.relation_list(relid):
conf = {
"keystone_host": utils.relation_get('private-address',
unit, relid),
"token": utils.relation_get('admin_token', unit, relid),
"service_port": utils.relation_get('service_port',
unit, relid),
"auth_port": utils.relation_get('auth_port', unit, relid),
"service_username": utils.relation_get('service_username',
unit, relid),
"service_password": utils.relation_get('service_password',
unit, relid),
"service_tenant": utils.relation_get('service_tenant',
unit, relid)
}
if None not in conf.itervalues():
return conf
return None
def db_joined():
@ -98,32 +147,83 @@ def db_joined():
def db_changed():
host = utils.relation_get('private-address')
password = utils.relation_get('password')
if not (host and password):
return
else:
quantum_utils.configure_db_connection(utils.config_get('plugin'),
host, password)
render_plugin_conf()
utils.restart('quantum-server')
if utils.config_get('plugin') == 'ovs':
utils.restart('quantum-plugin-openvswitch-agent')
def get_db_conf():
for relid in utils.relation_ids('shared-db'):
for unit in utils.relation_list(relid):
conf = {
"host": utils.relation_get('private-address',
unit, relid),
"user": quantum_utils.DB_USER,
"password": utils.relation_get('password',
unit, relid),
"db": quantum_utils.QUANTUM_DB
}
if None not in conf.itervalues():
return conf
return None
def amqp_joined():
pass
utils.relation_set(username=quantum_utils.RABBIT_USER,
vhost=quantum_utils.RABBIT_VHOST)
def amqp_changed():
pass
render_quantum_conf()
utils.restart('quantum-server', 'quantum-dhcp-agent')
if utils.config_get('plugin') == 'ovs':
utils.restart('quantum-plugin-openvswitch-agent')
def get_rabbit_conf():
for relid in utils.relation_ids('amqp'):
for unit in utils.relation_list(relid):
conf = {
"rabbit_host": utils.relation_get('private-address',
unit, relid),
"rabbit_virtual_host": quantum_utils.RABBIT_VHOST,
"rabbit_userid": quantum_utils.RABBIT_USER,
"rabbit_password": utils.relation_get('password',
unit, relid)
}
if None not in conf.itervalues():
return conf
return None
def nm_joined():
keystone_conf = get_keystone_conf()
if keystone_conf:
utils.relation_set(**keystone_conf) # IGNORE:W0142
utils.relation_set(plugin=utils.config_get('plugin'))
def notify_agents():
keystone_conf = get_keystone_conf()
if keystone_conf:
for relid in utils.relation_ids('network-manager'):
utils.relation_set(relid=relid,
plugin=utils.config_get('plugin'),
**keystone_conf)
utils.do_hooks({
"install": install,
"config-changed": config_changed,
"upgrade-charm": upgrade_charm,
"identity-service-relation-joined": keystone_joined,
"identity-service-relation-changed": keystone_changed,
"shared-db-relation-joined": db_joined,
"shared-db-relation-changed": db_changed,
"amqp-relation-joined": amqp_joined,
"amqp-relation-changed": amqp_changed
"amqp-relation-changed": amqp_changed,
"network-manager-relation-joined": nm_joined,
})
sys.exit(0)

View File

@ -0,0 +1 @@
hooks.py

View File

@ -0,0 +1 @@
hooks.py

View File

@ -1,47 +0,0 @@
Quantum Server
==============
quantum-server
# OVS
quantum-plugin-openvswitch quantum-plugin-openvswitch-agent
# Configure connection to the database
-> store in sql_connection in plugins.
# OVS
/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini
enable_tunneling=True
tenant_network_type=gre
tunnel_id_ranges=1:1000
# only if node is running the agent
local_ip=$(unit-get private-address) # data network
service quantum-server restart
# Add internal bridge
ovs-vsctl add-br br-int
# restart openvswitch plugin
# Same everywhere
quantum-dhcp-agent
quantum-l3-agent
ovs-vsctl add-br br-ex
ovs-vsctl add-port br-ex $(config-get external-port)
# Keystone - need to review keystone charm to see how this works.
keystone service-create --name quantum --type network --description 'OpenStack Networking Service'
keystone endpoint-create --region $REGION --service-id $ID --publicurl \
'http://$IP:9696/' --adminurl 'http://$IP:9696/' --internalurl 'http://$IP:9696/'
keystone user-create --name=quantum --pass=$SERVICE_PASSWORD --tenant-id service
keystone user-role-add --user_id 45e9461fa61e48f99de1adcd0b38eae7 --role_id e45af7cf33be4dac8070aa8310144ce3 \
--tenant_id 950fe8e5ed5f4659a8556ac836e8943d

View File

@ -1,131 +0,0 @@
#!/bin/bash -e
# vim: set ts=2:set et:
[ -f hooks/openstack-common ] && . hooks/openstack-common
ARG0=${0##*/}
PLUGIN=$(config-get plugin)
EXT_PORT=$(config-get ext-port)
PRIVATE_ADDRESS=$(unit-get private-address)
DB_USER=quantum
QUANTUM_DB=quantum
OVS_PLUGIN_CONF="/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini"
NVP_PLUGIN_CONF="/etc/quantum/plugins/nicira/nvp.ini"
case $PLUGIN in
"ovs") PLUGIN_CONF=$OVS_PLUGIN_CONF ;;
"nvp") PLUGIN_CONF=$NVP_PLUGIN_CONF ;;
esac
function install_hook() {
case $PLUGIN in
"ovs")
PLUGIN_PKGS="quantum-plugin-openvswitch quantum-plugin-openvswitch-agent"
;;
"nvp")
# XXX implement nvp
;;
*)
juju-log "Unsupported plugin specified"
exit 1
;;
esac
apt-get install quantum-server $PLUGIN_PKGS \
quantum-dhcp-agent \
quantum-l3-agent \
openvswitch-datapath-dkms
ovs-vsctl add-br br-int
ovs-vsctl add-br br-ex
}
function config_changed_hook() {
ovs-vsctl add-br br-int
ovs-vsctl add-br br-ex
if [ -n "$EXT_PORT" ]; then
juju-log "Adding $EXT_PORT to external bridge for external access"
ovs-vsctl add-port br-ex $EXT_PORT
fi
case $PLUGIN in
"ovs")
CORE_PLUGIN="quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPluginV2"
;;
"nvp")
CORE_PLUGIN="quantum.plugins.nicira.nicira_nvp_plugin.QuantumPlugin.NvpPluginV2"
;;
esac
juju-log "Configuring quantum with core_plugin: $CORE_PLUGIN"
set_or_update core_plugin $CORE_PLUGIN /etc/quantum/quantum.conf
}
function start() {
}
function stop() {
}
function keystone_joined {
# advertise our API endpoint to keystone
url="http://$(unit-get private-address):9696/v1"
public_url="http://$(unit-get public-address):9696/v1"
relation-set service="quantum" \
region="RegionOne" public_url=$public_url admin_url=$url internal_url=$url
}
function keystone_changed {
# we hopefully get a token in return. configure middleware accordingly
token=$(relation-get admin_token)
service_port=$(relation-get service_port)
auth_port=$(relation-get auth_port)
service_username=$(relation-get service_username)
service_password=$(relation-get service_password)
service_tenant=$(relation-get service_tenant)
[[ -z "$token" ]] || [[ -z "$service_port" ]] || [[ -z "$auth_port" ]] ||
[[ -z "$service_username" ]] || [[ -z "$service_password" ]] ||
[[ -z "$service_tenant" ]] && juju-log "Peer not ready" &&
exit 0
[[ "$token" == "-1" ]] &&
juju-log "admin token error" && exit 1
juju-log "Acquired admin. token"
keystone_host=$(relation-get private-address)
}
function db_joined {
juju-log "Requesting access to $QUANTUM_DB for $DB_USER@$PRIVATE_ADDRESS"
relation-set database=$QUANTUM_DB username=$DB_USER hostname=$PRIVATE_ADDRESS
}
function db_changed {
DB_HOST=$(relation-get private-address)
DB_PASSWORD=$(relation-get password)
if [ -z "$DB_HOST" ] || [ -z "$DB_PASSWORD" ] ; then
echo "DB_HOST || DB_PASSWORD not yet set. Exit 0 and retry"
exit 0
else
echo "Received password from $DB_HOST"
fi
juju-log "Configuring registry for access to $QUANTUM_DB@$DB_HOST"
set_or_update sql_connection \
"mysql://$DB_USER:$DB_PASSWORD@$DB_HOST/$QUANTUM_DB?charset=utf8" \
$PLUGIN_CONF
}
case $ARG0 in
"install") install_hook ;;
"config-changed") config_changed_hook ;;
"identity-service-relation-joined") keystone_joined ;;
"identity-service-relation-changed") keystone_changed ;;
"shared-db-relation-joined") db_joined ;;
"shared-db-relation-changed") db_changed;;
esac
# TODO: Add hooks for rabbitmq integration - dhcpagent seems to require:
# /etc/quantum/quantum.conf:
# rabbit_password = openstack
# rabbit_host = 100.1.1.10

View File

@ -1,7 +1,5 @@
import utils
import subprocess
import os
OVS_PLUGIN = \
"quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPluginV2"
@ -27,115 +25,10 @@ QUANTUM_DB = "quantum"
QUANTUM_CONF = "/etc/quantum/quantum.conf"
L3_AGENT_CONF = "/etc/quantum/l3_agent.ini"
QUANTUM_API_CONF = "/etc/quantum/api-paste.ini"
DHCP_AGENT_CONF = "/etc/quantum/dhcp_agent.ini"
MYSQL_CS = "mysql://%(user)s:%(password)s@%(host)s/%(db)s?charset=utf8"
def update_config_block(block, conf, **kwargs):
"""
Updates configuration file blocks given kwargs.
Can be used to update driver settings for a particular backend,
setting the sql connection, etc.
Parses block heading as '[block]'
If block does not exist, a new block will be created at end of file with
given kwargs
"""
f = open(conf, "r+")
orig = f.readlines()
new = []
heading = "[{}]\n".format(block)
lines = len(orig)
ln = 0
def update_block(block):
for k, v in kwargs.iteritems():
for l in block:
if l.strip().split(" ")[0] == k:
block[block.index(l)] = "{} = {}\n".format(k, v)
return
block.append('{} = {}\n'.format(k, v))
block.append('\n')
found = False
while ln < lines:
if orig[ln] != heading:
new.append(orig[ln])
ln += 1
else:
new.append(orig[ln])
ln += 1
block = []
while orig[ln].strip() != '':
block.append(orig[ln])
ln += 1
update_block(block)
new += block
found = True
if not found:
if new[(len(new) - 1)].strip() != '':
new.append('\n')
new.append('{}'.format(heading))
for k, v in kwargs.iteritems():
new.append('{} = {}\n'.format(k, v))
new.append('\n')
# backup original config
backup = open(conf + '.juju-back', 'w+')
for l in orig:
backup.write(l)
backup.close()
# update config
f.seek(0)
f.truncate()
for l in new:
f.write(l)
def configure_core_plugin(plugin):
update_config_block("DEFAULT", QUANTUM_CONF,
core_plugin=CORE_PLUGIN[plugin])
def configure_db_connection(plugin, host, password):
update_config_block(
"DATABASE", PLUGIN_CONF[plugin],
sql_connection=MYSQL_CS.format(host=host,
user=DB_USER,
password=password,
db=QUANTUM_DB)
)
def configure_local_ip(plugin, address):
update_config_block("OVS", PLUGIN_CONF[plugin], local_ip=address)
def configure_keystone(keystone_host,
token,
service_port,
auth_port,
username,
password,
tenant):
if os.path.exists(L3_AGENT_CONF): # Indicated OVS model is in use.
update_config_block("DEFAULT", L3_AGENT_CONF,
auth_url="http://{}:{}/v2.0".format(keystone_host,
auth_port),
auth_region="RegionOne",
admin_tenant_name=tenant,
admin_user=username,
admin_password=password)
update_config_block("filter:authtoken", QUANTUM_API_CONF,
auth_host=keystone_host,
auth_port=auth_port,
admin_tenant_name=tenant,
admin_user=username,
admin_password=password)
RABBIT_USER = "nova"
RABBIT_VHOST = "nova"
def add_bridge(name):
@ -152,7 +45,8 @@ def del_bridge(name):
def add_bridge_port(name, port):
status = subprocess.check_output(["ovs-vsctl", "show"])
if "Bridge {}".format(name) in status:
if ("Bridge {}".format(name) in status and
"Interface \"{}\"".format(port) not in status):
subprocess.check_call(["ovs-vsctl", "add-port", name, port])

1
hooks/upgrade-charm Symbolic link
View File

@ -0,0 +1 @@
hooks.py

View File

@ -65,7 +65,7 @@ def configure_source():
with open('/etc/apt/sources.list.d/ceph.list', 'w') as apt:
apt.write("deb " + source + "\n")
key = config_get('key')
if key != "":
if key:
cmd = [
'apt-key',
'adv', '--keyserver keyserver.ubuntu.com',
@ -183,3 +183,8 @@ def get_host_ip(hostname=unit_get('private-address')):
hostname
]
return subprocess.check_output(cmd).strip() # IGNORE:E1103
def restart(*services):
for service in services:
subprocess.check_call(['service', service, 'restart'])

View File

@ -14,8 +14,6 @@ provides:
network-manager:
interface: quantum
requires:
cloud-compute:
interface: nova-compute
shared-db:
interface: mysql-shared
amqp:

View File

@ -1 +1 @@
1
23

30
templates/api-paste.ini Normal file
View File

@ -0,0 +1,30 @@
[composite:quantum]
use = egg:Paste#urlmap
/: quantumversions
/v2.0: quantumapi_v2_0
[composite:quantumapi_v2_0]
use = call:quantum.auth:pipeline_factory
noauth = extensions quantumapiapp_v2_0
keystone = authtoken keystonecontext extensions quantumapiapp_v2_0
[filter:keystonecontext]
paste.filter_factory = quantum.auth:QuantumKeystoneContext.factory
[filter:authtoken]
paste.filter_factory = keystone.middleware.auth_token:filter_factory
auth_host = {{ keystone_host }}
auth_port = {{ auth_port }}
auth_protocol = http
admin_tenant_name = {{ service_tenant }}
admin_user = {{ service_username }}
admin_password = {{ service_password }}
[filter:extensions]
paste.filter_factory = quantum.extensions.extensions:plugin_aware_extension_middleware_factory
[app:quantumversions]
paste.app_factory = quantum.api.versions:Versions.factory
[app:quantumapiapp_v2_0]
paste.app_factory = quantum.api.v2.router:APIRouter.factory

5
templates/dhcp_agent.ini Normal file
View File

@ -0,0 +1,5 @@
[DEFAULT]
state_path = /var/lib/quantum
interface_driver = quantum.agent.linux.interface.OVSInterfaceDriver
dhcp_driver = quantum.agent.linux.dhcp.Dnsmasq
root_helper = sudo /usr/bin/quantum-rootwrap /etc/quantum/rootwrap.conf

8
templates/l3_agent.ini Normal file
View File

@ -0,0 +1,8 @@
[DEFAULT]
interface_driver = quantum.agent.linux.interface.OVSInterfaceDriver
auth_url = http://{{ keystone_host }}:{{ service_port }}/v2.0
auth_region = RegionOne
admin_tenant_name = {{ service_tenant }}
admin_user = {{ service_username }}
admin_password = {{ service_password }}
root_helper = sudo /usr/bin/quantum-rootwrap /etc/quantum/rootwrap.conf

View File

@ -0,0 +1,11 @@
[DATABASE]
sql_connection = mysql://{{ user }}:{{ password }}@{{ host }}/{{ db }}?charset=utf8
reconnect_interval = 2
[OVS]
local_ip = {{ local_ip }}
tenant_network_type = gre
enable_tunneling = True
tunnel_id_ranges = 1:1000
[AGENT]
polling_interval = 2
root_helper = sudo /usr/bin/quantum-rootwrap /etc/quantum/rootwrap.conf

15
templates/quantum.conf Normal file
View File

@ -0,0 +1,15 @@
[DEFAULT]
verbose = True
rabbit_userid = {{ rabbit_userid }}
rabbit_virtual_host = {{ rabbit_virtual_host }}
rabbit_host = {{ rabbit_host }}
rabbit_password = {{ rabbit_password }}
debug = True
bind_host = 0.0.0.0
bind_port = 9696
core_plugin = {{ core_plugin }}
api_paste_config = /etc/quantum/api-paste.ini
control_exchange = quantum
notification_driver = quantum.openstack.common.notifier.list_notifier
list_notifier_drivers = quantum.openstack.common.notifier.rabbit_notifier
[QUOTAS]