Add snap optimisations
Add optimisations to only install snap if it is absent and to only update snap settings if they have changed. Depends-On: If8086efcf7df4dcbe02be7454578dbbfb2d7945a Change-Id: Icf2e9834cca6330eec92239aa5a5b76503c7c0f1
This commit is contained in:
parent
744491d03b
commit
123b9af8f2
File diff suppressed because it is too large
Load Diff
@ -27,9 +27,9 @@ import os
|
|||||||
import secrets
|
import secrets
|
||||||
import socket
|
import socket
|
||||||
import string
|
import string
|
||||||
import subprocess
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
import charms.operator_libs_linux.v1.snap as snap
|
||||||
import ops.framework
|
import ops.framework
|
||||||
import ops_sunbeam.charm as sunbeam_charm
|
import ops_sunbeam.charm as sunbeam_charm
|
||||||
import ops_sunbeam.guard as sunbeam_guard
|
import ops_sunbeam.guard as sunbeam_guard
|
||||||
@ -121,20 +121,47 @@ class HypervisorOperatorCharm(sunbeam_charm.OSBaseOperatorCharm):
|
|||||||
self._state.metadata_secret = secret
|
self._state.metadata_secret = secret
|
||||||
return secret
|
return secret
|
||||||
|
|
||||||
|
def set_snap_data(self, snap_data):
|
||||||
|
"""Set snap setting if needed.
|
||||||
|
|
||||||
|
Update the snap with any settings that have changed.
|
||||||
|
"""
|
||||||
|
cache = snap.SnapCache()
|
||||||
|
hypervisor = cache["openstack-hypervisor"]
|
||||||
|
new_settings = {}
|
||||||
|
for k in sorted(snap_data.keys()):
|
||||||
|
try:
|
||||||
|
if snap_data[k] != hypervisor.get(k):
|
||||||
|
new_settings[k] = snap_data[k]
|
||||||
|
except snap.SnapError:
|
||||||
|
# Trying to retrieve an unset parameter results in a snapError
|
||||||
|
# so assume the snap.SnapError means there is missing config
|
||||||
|
# that needs setting.
|
||||||
|
new_settings[k] = snap_data[k]
|
||||||
|
if new_settings:
|
||||||
|
logger.debug(f"Applying new snap settings {new_settings}")
|
||||||
|
hypervisor.set(new_settings)
|
||||||
|
else:
|
||||||
|
logger.debug("Snap settings do not need updating")
|
||||||
|
|
||||||
|
def ensure_snap_present(self):
|
||||||
|
"""Install snap if it is not already present."""
|
||||||
|
config = self.model.config.get
|
||||||
|
try:
|
||||||
|
cache = snap.SnapCache()
|
||||||
|
hypervisor = cache["openstack-hypervisor"]
|
||||||
|
|
||||||
|
if not hypervisor.present:
|
||||||
|
hypervisor.ensure(snap.SnapState.Latest, channel=config("snap-channel"))
|
||||||
|
except snap.SnapError as e:
|
||||||
|
logger.error("An exception occurred when installing charmcraft. Reason: %s", e.message)
|
||||||
|
|
||||||
def configure_unit(self, event) -> None:
|
def configure_unit(self, event) -> None:
|
||||||
"""Run configuration on this unit."""
|
"""Run configuration on this unit."""
|
||||||
self.check_leader_ready()
|
self.check_leader_ready()
|
||||||
self.check_relation_handlers_ready()
|
self.check_relation_handlers_ready()
|
||||||
config = self.model.config.get
|
config = self.model.config.get
|
||||||
subprocess.check_call(
|
self.ensure_snap_present()
|
||||||
[
|
|
||||||
"snap",
|
|
||||||
"install",
|
|
||||||
"openstack-hypervisor",
|
|
||||||
"--channel",
|
|
||||||
config("snap-channel"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
local_ip = _get_local_ip_by_default_route()
|
local_ip = _get_local_ip_by_default_route()
|
||||||
try:
|
try:
|
||||||
contexts = self.contexts()
|
contexts = self.contexts()
|
||||||
@ -174,10 +201,7 @@ class HypervisorOperatorCharm(sunbeam_charm.OSBaseOperatorCharm):
|
|||||||
}
|
}
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
raise sunbeam_guard.WaitingExceptionError("Data missing: {}".format(e.name))
|
raise sunbeam_guard.WaitingExceptionError("Data missing: {}".format(e.name))
|
||||||
cmd = ["snap", "set", "openstack-hypervisor"]
|
self.set_snap_data(snap_data)
|
||||||
for k in sorted(snap_data.keys()):
|
|
||||||
cmd.append(f"{k}={snap_data[k]}")
|
|
||||||
subprocess.check_call(cmd)
|
|
||||||
self.ensure_services_running()
|
self.ensure_services_running()
|
||||||
self._state.unit_bootstrapped = True
|
self._state.unit_bootstrapped = True
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
import ops_sunbeam.test_utils as test_utils
|
import ops_sunbeam.test_utils as test_utils
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ class _HypervisorOperatorCharm(charm.HypervisorOperatorCharm):
|
|||||||
|
|
||||||
|
|
||||||
class TestCharm(test_utils.CharmTestCase):
|
class TestCharm(test_utils.CharmTestCase):
|
||||||
PATCHES = ["subprocess", "socket"]
|
PATCHES = ["socket", "snap"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup OpenStack Hypervisor tests."""
|
"""Setup OpenStack Hypervisor tests."""
|
||||||
@ -78,12 +79,14 @@ class TestCharm(test_utils.CharmTestCase):
|
|||||||
|
|
||||||
def test_all_relations(self):
|
def test_all_relations(self):
|
||||||
"""Test all the charms relations."""
|
"""Test all the charms relations."""
|
||||||
|
hypervisor_snap_mock = mock.MagicMock()
|
||||||
|
hypervisor_snap_mock.present = False
|
||||||
|
self.snap.SnapState.Latest = "latest"
|
||||||
|
self.snap.SnapCache.return_value = {"openstack-hypervisor": hypervisor_snap_mock}
|
||||||
self.socket.getfqdn.return_value = "test.local"
|
self.socket.getfqdn.return_value = "test.local"
|
||||||
self.initial_setup()
|
self.initial_setup()
|
||||||
self.harness.set_leader()
|
self.harness.set_leader()
|
||||||
self.subprocess.check_call.assert_any_call(
|
hypervisor_snap_mock.ensure.assert_any_call("latest", channel="essex/stable")
|
||||||
["snap", "install", "openstack-hypervisor", "--channel", "essex/stable"]
|
|
||||||
)
|
|
||||||
test_utils.add_complete_amqp_relation(self.harness)
|
test_utils.add_complete_amqp_relation(self.harness)
|
||||||
test_utils.add_complete_identity_credentials_relation(self.harness)
|
test_utils.add_complete_identity_credentials_relation(self.harness)
|
||||||
metadata = self.harness.charm.metadata_secret()
|
metadata = self.harness.charm.metadata_secret()
|
||||||
@ -93,34 +96,32 @@ class TestCharm(test_utils.CharmTestCase):
|
|||||||
self.harness.charm.contexts().certificates.key.encode()
|
self.harness.charm.contexts().certificates.key.encode()
|
||||||
).decode()
|
).decode()
|
||||||
certificate = base64.b64encode(test_utils.TEST_SERVER_CERT.encode()).decode()
|
certificate = base64.b64encode(test_utils.TEST_SERVER_CERT.encode()).decode()
|
||||||
expect_settings = [
|
expect_settings = {
|
||||||
"compute.cpu-mode=host-model",
|
"compute.cpu-mode": "host-model",
|
||||||
"compute.spice-proxy-address=10.0.0.10",
|
"compute.spice-proxy-address": "10.0.0.10",
|
||||||
"compute.virt-type=kvm",
|
"compute.virt-type": "kvm",
|
||||||
f"credentials.ovn-metadata-proxy-shared-secret={metadata}",
|
"credentials.ovn-metadata-proxy-shared-secret": metadata,
|
||||||
"identity.auth-url=None",
|
"identity.auth-url": "http://10.20.21.11:80/openstack-keystone",
|
||||||
"identity.password=user-password",
|
"identity.password": "user-password",
|
||||||
"identity.project-domain-name=pdomain_-ame",
|
"identity.project-domain-name": "pdomain_-ame",
|
||||||
"identity.project-name=user-project",
|
"identity.project-name": "user-project",
|
||||||
"identity.region-name=region12",
|
"identity.region-name": "region12",
|
||||||
"identity.user-domain-name=udomain-name",
|
"identity.user-domain-name": "udomain-name",
|
||||||
"identity.username=username",
|
"identity.username": "username",
|
||||||
"logging.debug=false",
|
"logging.debug": "false",
|
||||||
"network.dns-domain=openstack.local",
|
"network.dns-domain": "openstack.local",
|
||||||
"network.dns-servers=8.8.8.8",
|
"network.dns-servers": "8.8.8.8",
|
||||||
"network.enable-gateway=false",
|
"network.enable-gateway": "false",
|
||||||
"network.external-bridge=br-ex",
|
"network.external-bridge": "br-ex",
|
||||||
"network.external-bridge-address=10.20.20.1/24",
|
"network.external-bridge-address": "10.20.20.1/24",
|
||||||
"network.ip-address=10.0.0.10",
|
"network.ip-address": "10.0.0.10",
|
||||||
f"network.ovn-cacert={ovn_cacert}",
|
"network.ovn-cacert": ovn_cacert,
|
||||||
f"network.ovn-cert={certificate}",
|
"network.ovn-cert": certificate,
|
||||||
f"network.ovn-key={private_key}",
|
"network.ovn-key": private_key,
|
||||||
"network.ovn-sb-connection=ssl:10.20.21.10:6642",
|
"network.ovn-sb-connection": "ssl:10.20.21.10:6642",
|
||||||
"network.physnet-name=physnet1",
|
"network.physnet-name": "physnet1",
|
||||||
"node.fqdn=test.local",
|
"node.fqdn": "test.local",
|
||||||
"node.ip-address=10.0.0.10",
|
"node.ip-address": "10.0.0.10",
|
||||||
"rabbitmq.url=rabbit://hypervisor:rabbit.pass@10.0.0.13:5672/openstack",
|
"rabbitmq.url": "rabbit://hypervisor:rabbit.pass@10.0.0.13:5672/openstack",
|
||||||
]
|
}
|
||||||
expect_set_cmd = ["snap", "set", "openstack-hypervisor"]
|
hypervisor_snap_mock.set.assert_any_call(expect_settings)
|
||||||
expect_set_cmd.extend(expect_settings)
|
|
||||||
self.subprocess.check_call.assert_any_call(expect_set_cmd)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user