import subprocess import os import uuid import base64 import apt_pkg as apt from lib.utils import ( juju_log as log, configure_source, config_get ) OVS = "ovs" OVS_PLUGIN = \ "quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPluginV2" CORE_PLUGIN = { OVS: OVS_PLUGIN, } OVS_PLUGIN_CONF = \ "/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini" PLUGIN_CONF = { OVS: OVS_PLUGIN_CONF, } GATEWAY_PKGS = { OVS: [ "quantum-plugin-openvswitch-agent", "quantum-l3-agent", "quantum-dhcp-agent", 'python-mysqldb', "nova-api-metadata" ], } GATEWAY_AGENTS = { OVS: [ "quantum-plugin-openvswitch-agent", "quantum-l3-agent", "quantum-dhcp-agent", "nova-api-metadata" ], } EXT_PORT_CONF = '/etc/init/ext-port.conf' def get_os_version(package=None): apt.init() cache = apt.Cache() pkg = cache[package or 'quantum-common'] if pkg.current_ver: return apt.upstream_version(pkg.current_ver.ver_str) else: return None if get_os_version('quantum-common') >= "2013.1": for plugin in GATEWAY_AGENTS: GATEWAY_AGENTS[plugin].append("quantum-metadata-agent") DB_USER = "quantum" QUANTUM_DB = "quantum" KEYSTONE_SERVICE = "quantum" NOVA_DB_USER = "nova" NOVA_DB = "nova" QUANTUM_CONF = "/etc/quantum/quantum.conf" L3_AGENT_CONF = "/etc/quantum/l3_agent.ini" DHCP_AGENT_CONF = "/etc/quantum/dhcp_agent.ini" METADATA_AGENT_CONF = "/etc/quantum/metadata_agent.ini" NOVA_CONF = "/etc/nova/nova.conf" RESTART_MAP = { QUANTUM_CONF: [ 'quantum-l3-agent', 'quantum-dhcp-agent', 'quantum-metadata-agent', 'quantum-plugin-openvswitch-agent' ], DHCP_AGENT_CONF: [ 'quantum-dhcp-agent' ], L3_AGENT_CONF: [ 'quantum-l3-agent' ], METADATA_AGENT_CONF: [ 'quantum-metadata-agent' ], OVS_PLUGIN_CONF: [ 'quantum-plugin-openvswitch-agent' ], NOVA_CONF: [ 'nova-api-metadata' ] } RABBIT_USER = "nova" RABBIT_VHOST = "nova" INT_BRIDGE = "br-int" EXT_BRIDGE = "br-ex" def add_bridge(name): status = subprocess.check_output(["ovs-vsctl", "show"]) if "Bridge {}".format(name) not in status: log('INFO', 'Creating bridge {}'.format(name)) subprocess.check_call(["ovs-vsctl", "add-br", name]) def del_bridge(name): status = subprocess.check_output(["ovs-vsctl", "show"]) if "Bridge {}".format(name) in status: log('INFO', 'Deleting bridge {}'.format(name)) subprocess.check_call(["ovs-vsctl", "del-br", name]) def add_bridge_port(name, port): status = subprocess.check_output(["ovs-vsctl", "show"]) if ("Bridge {}".format(name) in status and "Interface \"{}\"".format(port) not in status): log('INFO', 'Adding port {} to bridge {}'.format(port, name)) subprocess.check_call(["ovs-vsctl", "add-port", name, port]) subprocess.check_call(["ip", "link", "set", port, "up"]) def del_bridge_port(name, port): status = subprocess.check_output(["ovs-vsctl", "show"]) if ("Bridge {}".format(name) in status and "Interface \"{}\"".format(port) in status): log('INFO', 'Deleting port {} from bridge {}'.format(port, name)) subprocess.check_call(["ovs-vsctl", "del-port", name, port]) subprocess.check_call(["ip", "link", "set", port, "down"]) SHARED_SECRET = "/etc/quantum/secret.txt" def get_shared_secret(): secret = None if not os.path.exists(SHARED_SECRET): secret = str(uuid.uuid4()) with open(SHARED_SECRET, 'w') as secret_file: secret_file.write(secret) else: with open(SHARED_SECRET, 'r') as secret_file: secret = secret_file.read().strip() return secret def flush_local_configuration(): if os.path.exists('/usr/bin/quantum-netns-cleanup'): cmd = [ "quantum-netns-cleanup", "--config-file=/etc/quantum/quantum.conf" ] for agent_conf in ['l3_agent.ini', 'dhcp_agent.ini']: agent_cmd = list(cmd) agent_cmd.append('--config-file=/etc/quantum/{}'\ .format(agent_conf)) subprocess.call(agent_cmd) def install_ca(ca_cert): with open('/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt', 'w') as crt: crt.write(base64.b64decode(ca_cert)) subprocess.check_call(['update-ca-certificates', '--fresh']) DHCP_AGENT = "DHCP Agent" L3_AGENT = "L3 Agent" def reassign_agent_resources(env): ''' Use agent scheduler API to detect down agents and re-schedule ''' from quantumclient.v2_0 import client # TODO: Fixup for https keystone auth_url = 'http://%(keystone_host)s:%(auth_port)s/v2.0' % env quantum = client.Client(username=env['service_username'], password=env['service_password'], tenant_name=env['service_tenant'], auth_url=auth_url, region_name=env['region']) agents = quantum.list_agents(agent_type=DHCP_AGENT) dhcp_agents = [] l3_agents = [] networks = {} for agent in agents['agents']: if not agent['alive']: log('INFO', 'DHCP Agent %s down' % agent['id']) for network in \ quantum.list_networks_on_dhcp_agent(agent['id'])['networks']: networks[network['id']] = agent['id'] else: dhcp_agents.append(agent['id']) agents = quantum.list_agents(agent_type=L3_AGENT) routers = {} for agent in agents['agents']: if not agent['alive']: log('INFO', 'L3 Agent %s down' % agent['id']) for router in \ quantum.list_routers_on_l3_agent(agent['id'])['routers']: routers[router['id']] = agent['id'] else: l3_agents.append(agent['id']) index = 0 for router_id in routers: agent = index % len(l3_agents) log('INFO', 'Moving router %s from %s to %s' % \ (router_id, routers[router_id], l3_agents[agent])) quantum.remove_router_from_l3_agent(l3_agent=routers[router_id], router_id=router_id) quantum.add_router_to_l3_agent(l3_agent=l3_agents[agent], body={'router_id': router_id}) index += 1 index = 0 for network_id in networks: agent = index % len(dhcp_agents) log('INFO', 'Moving network %s from %s to %s' % \ (network_id, networks[network_id], dhcp_agents[agent])) quantum.remove_network_from_dhcp_agent(dhcp_agent=networks[network_id], network_id=network_id) quantum.add_network_to_dhcp_agent(dhcp_agent=dhcp_agents[agent], body={'network_id': network_id}) index += 1 def do_openstack_upgrade(): configure_source() plugin = config_get('plugin') pkgs = [] if plugin in GATEWAY_PKGS.keys(): pkgs += GATEWAY_PKGS[plugin] if plugin == OVS: pkgs.append('openvswitch-datapath-dkms') cmd = ['apt-get', '--option', 'Dpkg::Options::=--force-confnew', '-y', 'install'] + pkgs subprocess.check_call(cmd)