Make charm OVN specific

This commit is contained in:
Liam Young 2022-01-31 12:52:25 +00:00
parent 24e43843e9
commit 16e16e3f5a
10 changed files with 368 additions and 5 deletions

View File

@ -12,3 +12,8 @@ parts:
charm:
build-packages:
- git
- libffi-dev
- libssl-dev
charm-python-packages:
- setuptools < 58
- cryptography < 3.4

View File

@ -0,0 +1,202 @@
"""TODO: Add a proper docstring here.
This is a placeholder docstring for this charm library. Docstrings are
presented on Charmhub and updated whenever you push a new version of the
library.
Complete documentation about creating and documenting libraries can be found
in the SDK docs at https://juju.is/docs/sdk/libraries.
See `charmcraft publish-lib` and `charmcraft fetch-lib` for details of how to
share and consume charm libraries. They serve to enhance collaboration
between charmers. Use a charmer's libraries for classes that handle
integration with their charm.
Bear in mind that new revisions of the different major API versions (v0, v1,
v2 etc) are maintained independently. You can continue to update v0 and v1
after you have pushed v3.
Markdown is supported, following the CommonMark specification.
"""
import logging
import typing
from ops.framework import (
StoredState,
EventBase,
ObjectEvents,
EventSource,
Object,
)
# The unique Charmhub library identifier, never change it
LIBID = "19e5a5857acd4a94a4a759d173d18232"
# Increment this major API version when introducing breaking changes
LIBAPI = 0
# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 1
# TODO: add your code here! Happy coding!
class OVSDBCMSConnectedEvent(EventBase):
"""OVSDBCMS connected Event."""
pass
class OVSDBCMSReadyEvent(EventBase):
"""OVSDBCMS ready for use Event."""
pass
class OVSDBCMSGoneAwayEvent(EventBase):
"""OVSDBCMS relation has gone-away Event"""
pass
class OVSDBCMSServerEvents(ObjectEvents):
"""Events class for `on`"""
connected = EventSource(OVSDBCMSConnectedEvent)
ready = EventSource(OVSDBCMSReadyEvent)
goneaway = EventSource(OVSDBCMSGoneAwayEvent)
class OVSDBCMSRequires(Object):
"""
OVSDBCMSRequires class
"""
on = OVSDBCMSServerEvents()
_stored = StoredState()
def __init__(self, charm, relation_name: str):
super().__init__(charm, relation_name)
self.charm = charm
self.relation_name = relation_name
self.framework.observe(
self.charm.on[relation_name].relation_joined,
self._on_ovsdb_cms_relation_joined,
)
self.framework.observe(
self.charm.on[relation_name].relation_changed,
self._on_ovsdb_cms_relation_changed,
)
self.framework.observe(
self.charm.on[relation_name].relation_departed,
self._on_ovsdb_cms_relation_changed,
)
self.framework.observe(
self.charm.on[relation_name].relation_broken,
self._on_ovsdb_cms_relation_broken,
)
def _on_ovsdb_cms_relation_joined(self, event):
"""OVSDBCMS relation joined."""
logging.debug("OVSDBCMSRequires on_joined")
self.on.connected.emit()
def bound_addresses(self):
return self.get_all_unit_values("bound-address")
def remote_ready(self):
return all(self.bound_addresses())
def _on_ovsdb_cms_relation_changed(self, event):
"""OVSDBCMS relation changed."""
logging.debug("OVSDBCMSRequires on_changed")
if self.remote_ready():
self.on.ready.emit()
def _on_ovsdb_cms_relation_broken(self, event):
"""OVSDBCMS relation broken."""
logging.debug("OVSDBCMSRequires on_broken")
self.on.goneaway.emit()
def get_all_unit_values(self, key: str) -> typing.List[str]:
"""Retrieve value for key from all related units."""
values = []
relation = self.framework.model.get_relation(self.relation_name)
for unit in relation.units:
values.append(relation.data[unit].get(key))
return values
class OVSDBCMSClientConnectedEvent(EventBase):
"""OVSDBCMS connected Event."""
pass
class OVSDBCMSClientReadyEvent(EventBase):
"""OVSDBCMS ready for use Event."""
pass
class OVSDBCMSClientGoneAwayEvent(EventBase):
"""OVSDBCMS relation has gone-away Event"""
pass
class OVSDBCMSClientEvents(ObjectEvents):
"""Events class for `on`"""
connected = EventSource(OVSDBCMSClientConnectedEvent)
ready = EventSource(OVSDBCMSClientReadyEvent)
goneaway = EventSource(OVSDBCMSClientGoneAwayEvent)
class OVSDBCMSProvides(Object):
"""
OVSDBCMSProvides class
"""
on = OVSDBCMSClientEvents()
_stored = StoredState()
def __init__(self, charm, relation_name):
super().__init__(charm, relation_name)
self.charm = charm
self.relation_name = relation_name
self.framework.observe(
self.charm.on[relation_name].relation_joined,
self._on_ovsdb_cms_relation_joined,
)
self.framework.observe(
self.charm.on[relation_name].relation_changed,
self._on_ovsdb_cms_relation_changed,
)
self.framework.observe(
self.charm.on[relation_name].relation_broken,
self._on_ovsdb_cms_relation_broken,
)
def _on_ovsdb_cms_relation_joined(self, event):
"""Handle ovsdb-cms joined."""
logging.debug("OVSDBCMSProvides on_joined")
self.on.connected.emit()
def _on_ovsdb_cms_relation_changed(self, event):
"""Handle ovsdb-cms changed."""
logging.debug("OVSDBCMSProvides on_changed")
self.on.ready.emit()
def _on_ovsdb_cms_relation_broken(self, event):
"""Handle ovsdb-cms broken."""
logging.debug("OVSDBCMSProvides on_departed")
self.on.goneaway.emit()
def set_unit_data(self, settings: typing.Dict[str, str]) -> None:
"""Publish settings on the peer unit data bag."""
relation = self.framework.model.get_relation(self.relation_name)
for k, v in settings.items():
relation.data[self.model.unit][k] = v

View File

@ -38,6 +38,10 @@ requires:
interface: rabbitmq
identity-service:
interface: keystone
ovsdb-cms:
interface: ovsdb-cms
certificates:
interface: tls-certificates
peers:
peers:

View File

@ -4,7 +4,7 @@ git+https://github.com/canonical/operator@2875e73e#egg=ops
git+https://opendev.org/openstack/charm-ops-openstack#egg=ops_openstack
git+https://github.com/openstack-charmers/advanced-sunbeam-openstack#egg=advanced_sunbeam_openstack
lightkube
# These are only needeed if the charm relates to ceph
git+https://github.com/openstack/charm-ops-interface-ceph-client#egg=interface_ceph_client
cryptography < 3.4
git+https://opendev.org/openstack/charm-ops-interface-tls-certificates#egg=interface_tls_certificates
# Charmhelpers is only present as interface_ceph_client uses it.
git+https://github.com/juju/charm-helpers.git#egg=charmhelpers

View File

@ -121,11 +121,103 @@ class NeutronOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
return "/etc/neutron/neutron.conf"
class NeutronWallabyOperatorCharm(NeutronOperatorCharm):
# Neutron OVN Specific Code
class OVNContext(sunbeam_ctxts.ConfigContext):
def context(self) -> dict:
return {
'extension_drivers': 'port_security',
'type_drivers': 'geneve,gre,vlan,flat,local',
'tenant_network_types': 'geneve,gre,vlan,flat,local',
'mechanism_drivers': 'ovn',
'path_mtu': '1500',
'tunnel_id_ranges': '1:1000',
'vni_ranges': '1001:2000',
'network_vlan_ranges': 'physnet1:1000:2000',
'flat_networks': 'physnet1',
'enable_tunneling': 'True',
'local_ip': '127.0.0.1',
'tunnel_types': 'gre',
'enable_security_group': 'True',
'vni_ranges': '1001:2000',
'max_header_size': '38',
'ovn_l3_scheduler': 'leastloaded',
'ovn_metadata_enabled': 'True',
'enable_distributed_floating_ip': 'False',
'dns_servers': '',
'dhcp_default_lease_time': '43200',
'dns_servers': '',
'ovn_dhcp4_global_options': '',
'ovn_dhcp6_global_options': '',
'vhost_sock_dir': '/run/libvirt-vhost-user',
'ovn_key': '/etc/neutron/plugins/ml2/key_host',
'ovn_cert': '/etc/neutron/plugins/ml2/cert_host',
'ovn_ca_cert': '/etc/neutron/plugins/ml2/neutron-ovn.crt'}
class NeutronServerOVNPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
def default_container_configs(self):
return [
sunbeam_core.ContainerConfigFile(
[self.container_name],
'/etc/neutron/neutron.conf',
'neutron',
'neutron'),
sunbeam_core.ContainerConfigFile(
[self.container_name],
'/etc/neutron/plugins/ml2/key_host',
'root',
'root'),
sunbeam_core.ContainerConfigFile(
[self.container_name],
'/etc/neutron/plugins/ml2/cert_host',
'root',
'root'),
sunbeam_core.ContainerConfigFile(
[self.container_name],
'/etc/neutron/plugins/ml2/neutron-ovn.crt',
'root',
'root'),
sunbeam_core.ContainerConfigFile(
[self.container_name],
'/etc/neutron/plugins/ml2/ml2_conf.ini',
'root',
'root')]
class NeutronOVNOperatorCharm(NeutronOperatorCharm):
@property
def config_contexts(self) -> List[sunbeam_ctxts.ConfigContext]:
"""Configuration contexts for the operator."""
contexts = super().config_contexts
contexts.append(
OVNContext(self, "ovn"))
return contexts
def get_pebble_handlers(self) -> List[sunbeam_chandlers.PebbleHandler]:
"""Pebble handlers for the service."""
return [
NeutronServerOVNPebbleHandler(
self,
'neutron-server',
self.service_name,
self.container_configs,
self.template_dir,
self.openstack_release,
self.configure_charm,
)
]
class NeutronOVNWallabyOperatorCharm(NeutronOVNOperatorCharm):
openstack_release = 'wallaby'
if __name__ == "__main__":
# Note: use_juju_for_storage=True required per
# https://github.com/canonical/operator/issues/506
main(NeutronWallabyOperatorCharm, use_juju_for_storage=True)
main(NeutronOVNWallabyOperatorCharm, use_juju_for_storage=True)

View File

@ -0,0 +1 @@
{{ certificates.cert }}

View File

@ -0,0 +1 @@
{{ certificates.key }}

View File

@ -0,0 +1,55 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
###############################################################################
[ml2]
extension_drivers = {{ ovn.extension_drivers }}
type_drivers = {{ ovn.type_drivers }}
tenant_network_types = {{ ovn.tenant_network_types }}
mechanism_drivers = {{ ovn.mechanism_drivers }}
path_mtu = {{ ovn.path_mtu }}
[ml2_type_gre]
tunnel_id_ranges = {{ ovn.tunnel_id_ranges }}
[ml2_type_vxlan]
vni_ranges = {{ ovn.vni_ranges }}
[ml2_type_vlan]
network_vlan_ranges = {{ ovn.network_vlan_ranges }}
[ml2_type_flat]
flat_networks = {{ ovn.flat_networks }}
[ovs]
enable_tunneling = {{ ovn.enable_tunneling }}
# local_ip = {{ ovn.local_ip }}
[agent]
tunnel_types = {{ ovn.tunnel_types }}
[securitygroup]
enable_security_group = {{ ovn.enable_security_group }}
[ovn]
ovn_nb_connection = {{ ovsdb_cms.db_nb_connection_strs }}
ovn_nb_private_key = {{ ovn.ovn_key }}
ovn_nb_certificate = {{ ovn.ovn_cert }}
ovn_nb_ca_cert = {{ ovn.ovn_ca_cert }}
ovn_sb_connection = {{ ovsdb_cms.db_sb_connection_strs }}
ovn_sb_private_key = {{ ovn.ovn_key }}
ovn_sb_certificate = {{ ovn.ovn_cert }}
ovn_sb_ca_cert = {{ ovn.ovn_ca_cert }}
ovn_l3_scheduler = {{ ovn.ovn_l3_scheduler }}
ovn_metadata_enabled = {{ ovn.ovn_metadata_enabled }}
enable_distributed_floating_ip = {{ ovn.enable_distributed_floating_ip }}
dns_servers = {{ ovn.dns_servers }}
dhcp_default_lease_time = {{ ovn.dhcp_default_lease_time }}
ovn_dhcp4_global_options = {{ ovn.ovn_dhcp4_global_options }}
ovn_dhcp6_global_options = {{ ovn.ovn_dhcp6_global_options }}
vhost_sock_dir = {{ ovn.vhost_sock_dir }}
[ml2_type_geneve]
vni_ranges = {{ ovn.vni_ranges }}
max_header_size = {{ ovn.max_header_size }}

View File

@ -0,0 +1 @@
{{ certificates.ca_cert }}

View File

@ -1,6 +1,8 @@
[DEFAULT]
core_plugin = ml2
debug = {{ options.debug }}
# debug = {{ options.debug }}
log_dir = /var/log/neutron
debug = True
#
# From neutron