Remote peer relation and misc fixes

This commit is contained in:
Liam Young 2023-04-03 15:02:56 +00:00
parent e4e34102ac
commit 44478c829a
5 changed files with 50 additions and 39 deletions

View File

@ -18,7 +18,7 @@ options:
default: "br-ex" default: "br-ex"
type: string type: string
external-bridge-address: external-bridge-address:
default: default: "10.20.20.1/24"
type: string type: string
ip-address: ip-address:
default: default:

View File

@ -97,7 +97,7 @@ LIBAPI = 1
# Increment this PATCH version before using `charmcraft publish-lib` or reset # Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version # to 0 if you are raising the major API version
LIBPATCH = 0 LIBPATCH = 1
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -286,6 +286,16 @@ class CloudCredentialsRequires(Object):
"""Return the region for the auth urls.""" """Return the region for the auth urls."""
return self.get_remote_app_data('region') return self.get_remote_app_data('region')
@property
def internal_endpoint(self) -> str:
"""Return the region for the internal auth url."""
return self.get_remote_app_data('internal-endpoint')
@property
def public_endpoint(self) -> str:
"""Return the region for the public auth url."""
return self.get_remote_app_data('public-endpoint')
def request_credentials(self) -> None: def request_credentials(self) -> None:
"""Request credentials from the CloudCredentials server.""" """Request credentials from the CloudCredentials server."""
if self.model.unit.is_leader(): if self.model.unit.is_leader():
@ -437,3 +447,5 @@ class CloudCredentialsProvides(Object):
app_data["project-domain-name"] = project_domain_name app_data["project-domain-name"] = project_domain_name
app_data["project-domain-id"] = project_domain_id app_data["project-domain-id"] = project_domain_id
app_data["region"] = region app_data["region"] = region
app_data["internal-endpoint"] = self.charm.internal_endpoint
app_data["public-endpoint"] = self.charm.public_endpoint

View File

@ -17,6 +17,6 @@ requires:
certificates: certificates:
interface: tls-certificates interface: tls-certificates
optional: true optional: true
peers:
peers: # This charm has no peer relation by design. This charm needs to scale to
interface: hypervisor-peer # hundreds of units and this is limited by the peer relation.

View File

@ -5,8 +5,7 @@ netifaces
jsonschema jsonschema
jinja2 jinja2
#git+https://opendev.org/openstack/charm-ops-sunbeam#egg=ops_sunbeam #git+https://opendev.org/openstack/charm-ops-sunbeam#egg=ops_sunbeam
#git+https://github.com/gnuoy/charm-ops-sunbeam@support-machine-charms#egg=ops_sunbeam git+https://github.com/gnuoy/charm-ops-sunbeam@allin#egg=ops_sunbeam
git+https://github.com/gnuoy/charm-ops-sunbeam@hypervisor-wip2#egg=ops_sunbeam
# This charm does not use lightkube* but ops_sunbeam requires it atm # This charm does not use lightkube* but ops_sunbeam requires it atm
lightkube lightkube

View File

@ -21,6 +21,7 @@ This charm provide hypervisor services as part of an OpenStack deployment
""" """
import base64 import base64
import json
import logging import logging
import secrets import secrets
import socket import socket
@ -33,7 +34,7 @@ import ops_sunbeam.guard as sunbeam_guard
import ops_sunbeam.ovn.relation_handlers as ovn_relation_handlers import ops_sunbeam.ovn.relation_handlers as ovn_relation_handlers
import ops_sunbeam.relation_handlers as sunbeam_rhandlers import ops_sunbeam.relation_handlers as sunbeam_rhandlers
from netifaces import AF_INET, gateways, ifaddresses from netifaces import AF_INET, gateways, ifaddresses
from ops.framework import StoredState import ops.framework
from ops.main import main from ops.main import main
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -58,11 +59,16 @@ def _get_local_ip_by_default_route() -> str:
class HypervisorOperatorCharm(sunbeam_charm.OSBaseOperatorCharm): class HypervisorOperatorCharm(sunbeam_charm.OSBaseOperatorCharm):
"""Charm the service.""" """Charm the service."""
_state = StoredState() _state = ops.framework.StoredState()
service_name = "hypervisor" service_name = "hypervisor"
METADATA_SECRET_KEY = "ovn-metadata-proxy-shared-secret" METADATA_SECRET_KEY = "ovn-metadata-proxy-shared-secret"
DEFAULT_SECRET_LENGTH = 32 DEFAULT_SECRET_LENGTH = 32
def __init__(self, framework: ops.framework.Framework) -> None:
"""Run constructor."""
super().__init__(framework)
self._state.set_default(metadata_secret='')
def get_relation_handlers( def get_relation_handlers(
self, handlers: List[sunbeam_rhandlers.RelationHandler] = None self, handlers: List[sunbeam_rhandlers.RelationHandler] = None
) -> List[sunbeam_rhandlers.RelationHandler]: ) -> List[sunbeam_rhandlers.RelationHandler]:
@ -93,19 +99,14 @@ class HypervisorOperatorCharm(sunbeam_charm.OSBaseOperatorCharm):
def metadata_secret(self) -> str: def metadata_secret(self) -> str:
"""Retrieve or set self.METADATA_SECRET_KEY.""" """Retrieve or set self.METADATA_SECRET_KEY."""
if self.leader_get(self.METADATA_SECRET_KEY): if self._state.metadata_secret:
logging.debug("Found {} in leader db".format(self.METADATA_SECRET_KEY)) logging.debug("Found metadata secret in local db")
return self.leader_get(self.METADATA_SECRET_KEY) return self._state.metadata_secret
if self.unit.is_leader():
logging.debug("Generating new {}".format(self.METADATA_SECRET_KEY))
secret = self.generate_metadata_secret()
self.leader_set({self.METADATA_SECRET_KEY: secret})
return secret
else: else:
logging.debug( logging.debug("Generating new metadata secret")
"{} is missing, need leader to generate it".format(self.METADATA_SECRET_KEY) secret = self.generate_metadata_secret()
) self._state.metadata_secret = secret
raise AttributeError return secret
def configure_unit(self, event) -> None: def configure_unit(self, event) -> None:
"""Run configuration on this unit.""" """Run configuration on this unit."""
@ -123,43 +124,42 @@ class HypervisorOperatorCharm(sunbeam_charm.OSBaseOperatorCharm):
) )
local_ip = _get_local_ip_by_default_route() local_ip = _get_local_ip_by_default_route()
try: try:
contexts = self.contexts()
snap_data = { snap_data = {
"compute.cpu-mode": "host-model", "compute.cpu-mode": "host-model",
"compute.spice-proxy-address": config("ip-address") or local_ip, "compute.spice-proxy-address": config("ip-address") or local_ip,
"compute.virt-type": "kvm", "compute.virt-type": "kvm",
"credentials.ovn-metadata-proxy-shared-secret": self.metadata_secret(), "credentials.ovn-metadata-proxy-shared-secret": self.metadata_secret(),
"identity.auth-url": "http://{}/openstack-keystone".format( "identity.auth-url": contexts.identity_credentials.public_endpoint,
self.contexts().identity_credentials.auth_host "identity.password": contexts.identity_credentials.password,
), "identity.project-domain-name": contexts.identity_credentials.project_domain_name,
"identity.password": self.contexts().identity_credentials.password, "identity.project-name": contexts.identity_credentials.project_name,
"identity.project-domain-name": self.contexts().identity_credentials.project_domain_name, "identity.region-name": contexts.identity_credentials.region,
"identity.project-name": self.contexts().identity_credentials.project_name, "identity.user-domain-name": contexts.identity_credentials.user_domain_name,
"identity.region-name": self.contexts().identity_credentials.region, "identity.username": contexts.identity_credentials.username,
"identity.user-domain-name": self.contexts().identity_credentials.user_domain_name, "logging.debug": json.dumps(config("debug")),
"identity.username": self.contexts().identity_credentials.username,
"logging.debug": config("debug"),
"network.dns-domain": config("dns-domain"), "network.dns-domain": config("dns-domain"),
"network.dns-servers": config("dns-servers"), "network.dns-servers": config("dns-servers"),
"network.enable-gateway": config("enable-gateway"), "network.enable-gateway": json.dumps(config("enable-gateway")),
"network.external-bridge": config("external-bridge"), "network.external-bridge": config("external-bridge"),
"network.external-bridge-address": config("external-bridge-address"), "network.external-bridge-address": config("external-bridge-address") or "10.20.20.1/24",
"network.ip-address": config("ip-address") or local_ip, "network.ip-address": config("ip-address") or local_ip,
"network.ovn-key": base64.b64encode( "network.ovn-key": base64.b64encode(
self.contexts().certificates.key.encode() contexts.certificates.key.encode()
).decode(), ).decode(),
"network.ovn-cert": base64.b64encode( "network.ovn-cert": base64.b64encode(
self.contexts().certificates.cert.encode() contexts.certificates.cert.encode()
).decode(), ).decode(),
"network.ovn-cacert": base64.b64encode( "network.ovn-cacert": base64.b64encode(
self.contexts().certificates.ca_cert.encode() contexts.certificates.ca_cert.encode()
).decode(), ).decode(),
"network.ovn-sb-connection": list( "network.ovn-sb-connection": list(
self.contexts().ovsdb_cms.db_public_sb_connection_strs contexts.ovsdb_cms.db_ingress_sb_connection_strs
)[0], )[0],
"network.physnet-name": config("physnet-name"), "network.physnet-name": config("physnet-name"),
"node.fqdn": config("fqdn") or socket.getfqdn, "node.fqdn": config("fqdn") or socket.getfqdn(),
"node.ip-address": config("ip-address") or local_ip, "node.ip-address": config("ip-address") or local_ip,
"rabbitmq.url": self.contexts().amqp.transport_url, "rabbitmq.url": contexts.amqp.transport_url,
} }
cmd = ["snap", "set", "openstack-hypervisor"] + [ cmd = ["snap", "set", "openstack-hypervisor"] + [