diff --git a/charm-helpers.yaml b/charm-helpers.yaml index 3000e7c5..f73b209a 100644 --- a/charm-helpers.yaml +++ b/charm-helpers.yaml @@ -8,3 +8,4 @@ include: - contrib.hahelpers: - apache - cluster + - contrib.network.ovs diff --git a/hooks/charmhelpers/contrib/network/__init__.py b/hooks/charmhelpers/contrib/network/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hooks/charmhelpers/contrib/network/ovs/__init__.py b/hooks/charmhelpers/contrib/network/ovs/__init__.py new file mode 100644 index 00000000..983074fa --- /dev/null +++ b/hooks/charmhelpers/contrib/network/ovs/__init__.py @@ -0,0 +1,72 @@ +''' Helpers for interacting with OpenvSwitch ''' +import subprocess +import os +from charmhelpers.core.hookenv import ( + log, WARNING +) +from charmhelpers.core.host import ( + service +) + + +def add_bridge(name): + ''' Add the named bridge to openvswitch ''' + log('Creating bridge {}'.format(name)) + subprocess.check_call(["ovs-vsctl", "--", "--may-exist", "add-br", name]) + + +def del_bridge(name): + ''' Delete the named bridge from openvswitch ''' + log('Deleting bridge {}'.format(name)) + subprocess.check_call(["ovs-vsctl", "--", "--if-exists", "del-br", name]) + + +def add_bridge_port(name, port): + ''' Add a port to the named openvswitch bridge ''' + log('Adding port {} to bridge {}'.format(port, name)) + subprocess.check_call(["ovs-vsctl", "--", "--may-exist", "add-port", + name, port]) + subprocess.check_call(["ip", "link", "set", port, "up"]) + + +def del_bridge_port(name, port): + ''' Delete a port from the named openvswitch bridge ''' + log('Deleting port {} from bridge {}'.format(port, name)) + subprocess.check_call(["ovs-vsctl", "--", "--if-exists", "del-port", + name, port]) + subprocess.check_call(["ip", "link", "set", port, "down"]) + + +def set_manager(manager): + ''' Set the controller for the local openvswitch ''' + log('Setting manager for local ovs to {}'.format(manager)) + subprocess.check_call(['ovs-vsctl', 'set-manager', + 'ssl:{}'.format(manager)]) + + +CERT_PATH = '/etc/openvswitch/ovsclient-cert.pem' + + +def get_certificate(): + ''' Read openvswitch certificate from disk ''' + if os.path.exists(CERT_PATH): + log('Reading ovs certificate from {}'.format(CERT_PATH)) + with open(CERT_PATH, 'r') as cert: + full_cert = cert.read() + begin_marker = "-----BEGIN CERTIFICATE-----" + end_marker = "-----END CERTIFICATE-----" + begin_index = full_cert.find(begin_marker) + end_index = full_cert.rfind(end_marker) + if end_index == -1 or begin_index == -1: + raise RuntimeError("Certificate does not contain valid begin" + " and end markers.") + full_cert = full_cert[begin_index:(end_index + len(end_marker))] + return full_cert + else: + log('Certificate not found', level=WARNING) + return None + + +def full_restart(): + ''' Full restart and reload of openvswitch ''' + service('force-reload-kmod', 'openvswitch-switch') diff --git a/hooks/charmhelpers/contrib/storage/linux/ceph.py b/hooks/charmhelpers/contrib/storage/linux/ceph.py index 10e665d4..9bb9530c 100644 --- a/hooks/charmhelpers/contrib/storage/linux/ceph.py +++ b/hooks/charmhelpers/contrib/storage/linux/ceph.py @@ -97,12 +97,13 @@ def pool_exists(service, name): return name in out -def get_osds(): +def get_osds(service): ''' Return a list of all Ceph Object Storage Daemons currently in the cluster ''' - return json.loads(check_output(['ceph', 'osd', 'ls', '--format=json'])) + return json.loads(check_output(['ceph', '--id', service, + 'osd', 'ls', '--format=json'])) def create_pool(service, name, replicas=2): @@ -113,17 +114,17 @@ def create_pool(service, name, replicas=2): return # Calculate the number of placement groups based # on upstream recommended best practices. - pgnum = (len(get_osds()) * 100 / replicas) + pgnum = (len(get_osds(service)) * 100 / replicas) cmd = [ 'ceph', '--id', service, 'osd', 'pool', 'create', - name, pgnum + name, str(pgnum) ] check_call(cmd) cmd = [ 'ceph', '--id', service, - 'osd', 'set', name, - 'size', replicas + 'osd', 'pool', 'set', name, + 'size', str(replicas) ] check_call(cmd) diff --git a/hooks/nova_compute_context.py b/hooks/nova_compute_context.py index 8bd2d25b..c2c29f6c 100644 --- a/hooks/nova_compute_context.py +++ b/hooks/nova_compute_context.py @@ -18,6 +18,7 @@ from charmhelpers.core.hookenv import ( ) from charmhelpers.contrib.openstack.utils import get_host_ip, os_release +from charmhelpers.contrib.network.ovs import add_bridge # This is just a label and it must be consistent across @@ -311,14 +312,7 @@ class NeutronComputeContext(context.NeutronContext): def _ensure_bridge(self): if not service_running('openvswitch-switch'): service_start('openvswitch-switch') - - ovs_output = check_output(['ovs-vsctl', 'show']) - for ln in ovs_output.split('\n'): - if OVS_BRIDGE in ln.strip(): - log('Found OVS bridge: %s.' % OVS_BRIDGE) - return - log('Creating new OVS bridge: %s.' % OVS_BRIDGE) - check_call(['ovs-vsctl', 'add-br', OVS_BRIDGE]) + add_bridge(OVS_BRIDGE) def ovs_ctxt(self): # In addition to generating config context, ensure the OVS service