Loading magma/hackfest_gateway_vnfd/charms/vyos-config/actions.yaml +0 −12 Original line number Diff line number Diff line Loading @@ -9,18 +9,6 @@ configure-remote: required: - magmaIP # Standard OSM functions start: description: "Stop the service on the VNF." stop: description: "Stop the service on the VNF." restart: description: "Stop the service on the VNF." reboot: description: "Reboot the VNF virtual machine." upgrade: description: "Upgrade the software on the VNF." # Required by charms.osm.sshproxy run: description: "Run an arbitrary command" Loading magma/hackfest_gateway_vnfd/charms/vyos-config/src/charm.py +13 −209 Original line number Diff line number Diff line Loading @@ -30,145 +30,48 @@ from ops.model import ( import os import subprocess import traceback from proxy_cluster import ProxyCluster from charms.osm.sshproxy import SSHProxy from charms.osm.sshproxy import SSHProxyCharm from charms.osm import libansible class SSHKeysInitialized(EventBase): def __init__(self, handle, ssh_public_key, ssh_private_key): super().__init__(handle) self.ssh_public_key = ssh_public_key self.ssh_private_key = ssh_private_key def snapshot(self): return { "ssh_public_key": self.ssh_public_key, "ssh_private_key": self.ssh_private_key, } def restore(self, snapshot): self.ssh_public_key = snapshot["ssh_public_key"] self.ssh_private_key = snapshot["ssh_private_key"] class ProxyClusterEvents(CharmEvents): ssh_keys_initialized = EventSource(SSHKeysInitialized) class SimpleHAProxyCharm(CharmBase): state = StoredState() on = ProxyClusterEvents() class VyosCharm(SSHProxyCharm): def __init__(self, framework, key): super().__init__(framework, key) # An example of setting charm state # that's persistent across events self.state.set_default(is_started=False) self.peers = ProxyCluster(self, "proxypeer") if not self.state.is_started: self.state.is_started = True # Register all of the events we want to observe self.framework.observe(self.on.config_changed, self.on_config_changed) self.framework.observe(self.on.install, self.on_install) self.framework.observe(self.on.start, self.on_start) self.framework.observe(self.on.upgrade_charm, self.on_upgrade_charm) # Charm actions (primitives) self.framework.observe(self.on.configure_remote_action, self.on_configure_remote_action) # OSM actions (primitives) self.framework.observe(self.on.start_action, self.on_start_action) self.framework.observe(self.on.stop_action, self.on_stop_action) self.framework.observe(self.on.restart_action, self.on_restart_action) self.framework.observe(self.on.reboot_action, self.on_reboot_action) self.framework.observe(self.on.upgrade_action, self.on_upgrade_action) # SSH Proxy actions (primitives) self.framework.observe(self.on.generate_ssh_key_action, self.on_generate_ssh_key_action) self.framework.observe(self.on.get_ssh_public_key_action, self.on_get_ssh_public_key_action) self.framework.observe(self.on.run_action, self.on_run_action) self.framework.observe(self.on.verify_ssh_credentials_action, self.on_verify_ssh_credentials_action) self.framework.observe(self.on.proxypeer_relation_changed, self.on_proxypeer_relation_changed) def get_ssh_proxy(self): """Get the SSHProxy instance""" proxy = SSHProxy( hostname=self.model.config["ssh-hostname"], username=self.model.config["ssh-username"], password=self.model.config["ssh-password"], self.framework.observe( self.on.configure_remote_action, self.on_configure_remote_action ) return proxy def on_proxypeer_relation_changed(self, event): if self.peers.is_cluster_initialized: pubkey = self.peers.ssh_public_key privkey = self.peers.ssh_private_key SSHProxy.write_ssh_keys(public=pubkey, private=privkey) self.on_config_changed(event) else: event.defer() def on_config_changed(self, event): """Handle changes in configuration""" unit = self.model.unit # Unit should go into a waiting state until verify_ssh_credentials is successful unit.status = WaitingStatus("Waiting for SSH credentials") proxy = self.get_ssh_proxy() verified = proxy.verify_credentials() if verified: unit.status = ActiveStatus() else: unit.status = BlockedStatus("Invalid SSH credentials.") super().on_config_changed(event) def on_install(self, event): unit = self.model.unit unit.status = MaintenanceStatus("Installing Ansible") """Called when the charm is being installed""" super().on_install(event) self.unit.status = MaintenanceStatus("Installing Ansible") libansible.install_ansible_support() unit.status = ActiveStatus() self.unit.status = ActiveStatus() def on_start(self, event): """Called when the charm is being installed""" if not self.peers.is_joined: event.defer() return unit = self.model.unit if not SSHProxy.has_ssh_key(): unit.status = MaintenanceStatus("Generating SSH keys...") pubkey = None privkey = None if self.is_leader: if self.peers.is_cluster_initialized: SSHProxy.write_ssh_keys( public=self.peers.ssh_public_key, private=self.peers.ssh_private_key, ) else: SSHProxy.generate_ssh_key() self.on.ssh_keys_initialized.emit( SSHProxy.get_ssh_public_key(), SSHProxy.get_ssh_private_key() ) unit.status = ActiveStatus() else: unit.status = WaitingStatus("Waiting for leader to populate the keys") """Called when the charm is being started""" super().on_start(event) def on_configure_remote_action(self, event): """Configure remote.""" if self.is_leader: if self.unit.is_leader(): try: config = self.model.config magmaIP = event.params["magmaIP"] dict_vars = {"MAGMA_AGW_IP": magmaIP} proxy = self.get_ssh_proxy() result = libansible.execute_playbook( "configure-remote.yaml", config["ssh-hostname"], Loading @@ -188,106 +91,7 @@ class SimpleHAProxyCharm(CharmBase): def on_upgrade_charm(self, event): """Upgrade the charm.""" unit = self.model.unit # Mark the unit as under Maintenance. unit.status = MaintenanceStatus("Upgrading charm") self.on_install(event) # When maintenance is done, return to an Active state unit.status = ActiveStatus() ############### # OSM methods # ############### def on_start_action(self, event): """Start the VNF service on the VM.""" pass def on_stop_action(self, event): """Stop the VNF service on the VM.""" pass def on_restart_action(self, event): """Restart the VNF service on the VM.""" pass def on_reboot_action(self, event): """Reboot the VM.""" if self.is_leader: proxy = self.get_ssh_proxy() stdout, stderr = proxy.run("sudo reboot") if len(stderr): event.fail(stderr) else: event.fail("Unit is not leader") return def on_upgrade_action(self, event): """Upgrade the VNF service on the VM.""" pass ##################### # SSH Proxy methods # ##################### def on_generate_ssh_key_action(self, event): """Generate a new SSH keypair for this unit.""" if self.is_leader: if not SSHProxy.generate_ssh_key(): event.fail("Unable to generate ssh key") else: event.fail("Unit is not leader") return def on_get_ssh_public_key_action(self, event): """Get the SSH public key for this unit.""" if self.is_leader: pubkey = SSHProxy.get_ssh_public_key() event.set_results({"pubkey": SSHProxy.get_ssh_public_key()}) else: event.fail("Unit is not leader") return def on_run_action(self, event): """Run an arbitrary command on the remote host.""" if self.is_leader: cmd = event.params["command"] proxy = self.get_ssh_proxy() stdout, stderr = proxy.run(cmd) event.set_results({"output": stdout}) if len(stderr): event.fail(stderr) else: event.fail("Unit is not leader") return def on_verify_ssh_credentials_action(self, event): """Verify the SSH credentials for this unit.""" if self.is_leader: proxy = self.get_ssh_proxy() verified = proxy.verify_credentials() if verified: print("Verified!") event.set_results({"verified": True}) else: print("Verification failed!") event.set_results({"verified": False}) else: event.fail("Unit is not leader") return @property def is_leader(self): # update the framework to include self.unit.is_leader() return self.model.unit.is_leader() class LeadershipError(ModelError): def __init__(self): super().__init__("not leader") if __name__ == "__main__": main(SimpleHAProxyCharm) main(VyosCharm) magma/hackfest_gateway_vnfd/charms/vyos-config/src/proxy_cluster.pydeleted 100644 → 0 +0 −71 Original line number Diff line number Diff line # Copyright 2020 Canonical Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from ops.framework import Object, StoredState class ProxyCluster(Object): state = StoredState() def __init__(self, charm, relation_name): super().__init__(charm, relation_name) self._relation_name = relation_name self._relation = self.framework.model.get_relation(self._relation_name) self.framework.observe(charm.on.ssh_keys_initialized, self.on_ssh_keys_initialized) self.state.set_default(ssh_public_key=None) self.state.set_default(ssh_private_key=None) def on_ssh_keys_initialized(self, event): if not self.framework.model.unit.is_leader(): raise RuntimeError("The initial unit of a cluster must also be a leader.") self.state.ssh_public_key = event.ssh_public_key self.state.ssh_private_key = event.ssh_private_key if not self.is_joined: event.defer() return self._relation.data[self.model.app][ "ssh_public_key" ] = self.state.ssh_public_key self._relation.data[self.model.app][ "ssh_private_key" ] = self.state.ssh_private_key @property def is_joined(self): return self._relation is not None @property def ssh_public_key(self): if self.is_joined: return self._relation.data[self.model.app].get("ssh_public_key") @property def ssh_private_key(self): if self.is_joined: return self._relation.data[self.model.app].get("ssh_private_key") @property def is_cluster_initialized(self): return ( True if self.is_joined and self._relation.data[self.model.app].get("ssh_public_key") and self._relation.data[self.model.app].get("ssh_private_key") else False ) magma/hackfest_magma-agw-enb_vnfd/charms/magmagw/actions.yaml +0 −12 Original line number Diff line number Diff line Loading @@ -67,18 +67,6 @@ add-test-subscriber: type: "string" default: "" # Standard OSM functions start: description: "Stop the service on the VNF." stop: description: "Stop the service on the VNF." restart: description: "Stop the service on the VNF." reboot: description: "Reboot the VNF virtual machine." upgrade: description: "Upgrade the software on the VNF." # Required by charms.osm.sshproxy run: description: "Run an arbitrary command" Loading magma/hackfest_magma-agw-enb_vnfd/charms/magmagw/src/charm.py +10 −1 Original line number Diff line number Diff line Loading @@ -146,7 +146,16 @@ class MagmaAGWProxyCharm(SSHProxyCharm): """Resets the hardware ID""" if self.unit.is_leader(): proxy = self.get_ssh_proxy() attempt = 0 while attempt < 50: try: stdout, stderr = proxy.run("sudo snowflake --force-new-key") break except subprocess.CalledProcessError: attempt += 1 import time time.sleep(5) event.set_results({"output": stdout, "stderr": stderr}) else: event.fail("Unit is not leader") Loading Loading
magma/hackfest_gateway_vnfd/charms/vyos-config/actions.yaml +0 −12 Original line number Diff line number Diff line Loading @@ -9,18 +9,6 @@ configure-remote: required: - magmaIP # Standard OSM functions start: description: "Stop the service on the VNF." stop: description: "Stop the service on the VNF." restart: description: "Stop the service on the VNF." reboot: description: "Reboot the VNF virtual machine." upgrade: description: "Upgrade the software on the VNF." # Required by charms.osm.sshproxy run: description: "Run an arbitrary command" Loading
magma/hackfest_gateway_vnfd/charms/vyos-config/src/charm.py +13 −209 Original line number Diff line number Diff line Loading @@ -30,145 +30,48 @@ from ops.model import ( import os import subprocess import traceback from proxy_cluster import ProxyCluster from charms.osm.sshproxy import SSHProxy from charms.osm.sshproxy import SSHProxyCharm from charms.osm import libansible class SSHKeysInitialized(EventBase): def __init__(self, handle, ssh_public_key, ssh_private_key): super().__init__(handle) self.ssh_public_key = ssh_public_key self.ssh_private_key = ssh_private_key def snapshot(self): return { "ssh_public_key": self.ssh_public_key, "ssh_private_key": self.ssh_private_key, } def restore(self, snapshot): self.ssh_public_key = snapshot["ssh_public_key"] self.ssh_private_key = snapshot["ssh_private_key"] class ProxyClusterEvents(CharmEvents): ssh_keys_initialized = EventSource(SSHKeysInitialized) class SimpleHAProxyCharm(CharmBase): state = StoredState() on = ProxyClusterEvents() class VyosCharm(SSHProxyCharm): def __init__(self, framework, key): super().__init__(framework, key) # An example of setting charm state # that's persistent across events self.state.set_default(is_started=False) self.peers = ProxyCluster(self, "proxypeer") if not self.state.is_started: self.state.is_started = True # Register all of the events we want to observe self.framework.observe(self.on.config_changed, self.on_config_changed) self.framework.observe(self.on.install, self.on_install) self.framework.observe(self.on.start, self.on_start) self.framework.observe(self.on.upgrade_charm, self.on_upgrade_charm) # Charm actions (primitives) self.framework.observe(self.on.configure_remote_action, self.on_configure_remote_action) # OSM actions (primitives) self.framework.observe(self.on.start_action, self.on_start_action) self.framework.observe(self.on.stop_action, self.on_stop_action) self.framework.observe(self.on.restart_action, self.on_restart_action) self.framework.observe(self.on.reboot_action, self.on_reboot_action) self.framework.observe(self.on.upgrade_action, self.on_upgrade_action) # SSH Proxy actions (primitives) self.framework.observe(self.on.generate_ssh_key_action, self.on_generate_ssh_key_action) self.framework.observe(self.on.get_ssh_public_key_action, self.on_get_ssh_public_key_action) self.framework.observe(self.on.run_action, self.on_run_action) self.framework.observe(self.on.verify_ssh_credentials_action, self.on_verify_ssh_credentials_action) self.framework.observe(self.on.proxypeer_relation_changed, self.on_proxypeer_relation_changed) def get_ssh_proxy(self): """Get the SSHProxy instance""" proxy = SSHProxy( hostname=self.model.config["ssh-hostname"], username=self.model.config["ssh-username"], password=self.model.config["ssh-password"], self.framework.observe( self.on.configure_remote_action, self.on_configure_remote_action ) return proxy def on_proxypeer_relation_changed(self, event): if self.peers.is_cluster_initialized: pubkey = self.peers.ssh_public_key privkey = self.peers.ssh_private_key SSHProxy.write_ssh_keys(public=pubkey, private=privkey) self.on_config_changed(event) else: event.defer() def on_config_changed(self, event): """Handle changes in configuration""" unit = self.model.unit # Unit should go into a waiting state until verify_ssh_credentials is successful unit.status = WaitingStatus("Waiting for SSH credentials") proxy = self.get_ssh_proxy() verified = proxy.verify_credentials() if verified: unit.status = ActiveStatus() else: unit.status = BlockedStatus("Invalid SSH credentials.") super().on_config_changed(event) def on_install(self, event): unit = self.model.unit unit.status = MaintenanceStatus("Installing Ansible") """Called when the charm is being installed""" super().on_install(event) self.unit.status = MaintenanceStatus("Installing Ansible") libansible.install_ansible_support() unit.status = ActiveStatus() self.unit.status = ActiveStatus() def on_start(self, event): """Called when the charm is being installed""" if not self.peers.is_joined: event.defer() return unit = self.model.unit if not SSHProxy.has_ssh_key(): unit.status = MaintenanceStatus("Generating SSH keys...") pubkey = None privkey = None if self.is_leader: if self.peers.is_cluster_initialized: SSHProxy.write_ssh_keys( public=self.peers.ssh_public_key, private=self.peers.ssh_private_key, ) else: SSHProxy.generate_ssh_key() self.on.ssh_keys_initialized.emit( SSHProxy.get_ssh_public_key(), SSHProxy.get_ssh_private_key() ) unit.status = ActiveStatus() else: unit.status = WaitingStatus("Waiting for leader to populate the keys") """Called when the charm is being started""" super().on_start(event) def on_configure_remote_action(self, event): """Configure remote.""" if self.is_leader: if self.unit.is_leader(): try: config = self.model.config magmaIP = event.params["magmaIP"] dict_vars = {"MAGMA_AGW_IP": magmaIP} proxy = self.get_ssh_proxy() result = libansible.execute_playbook( "configure-remote.yaml", config["ssh-hostname"], Loading @@ -188,106 +91,7 @@ class SimpleHAProxyCharm(CharmBase): def on_upgrade_charm(self, event): """Upgrade the charm.""" unit = self.model.unit # Mark the unit as under Maintenance. unit.status = MaintenanceStatus("Upgrading charm") self.on_install(event) # When maintenance is done, return to an Active state unit.status = ActiveStatus() ############### # OSM methods # ############### def on_start_action(self, event): """Start the VNF service on the VM.""" pass def on_stop_action(self, event): """Stop the VNF service on the VM.""" pass def on_restart_action(self, event): """Restart the VNF service on the VM.""" pass def on_reboot_action(self, event): """Reboot the VM.""" if self.is_leader: proxy = self.get_ssh_proxy() stdout, stderr = proxy.run("sudo reboot") if len(stderr): event.fail(stderr) else: event.fail("Unit is not leader") return def on_upgrade_action(self, event): """Upgrade the VNF service on the VM.""" pass ##################### # SSH Proxy methods # ##################### def on_generate_ssh_key_action(self, event): """Generate a new SSH keypair for this unit.""" if self.is_leader: if not SSHProxy.generate_ssh_key(): event.fail("Unable to generate ssh key") else: event.fail("Unit is not leader") return def on_get_ssh_public_key_action(self, event): """Get the SSH public key for this unit.""" if self.is_leader: pubkey = SSHProxy.get_ssh_public_key() event.set_results({"pubkey": SSHProxy.get_ssh_public_key()}) else: event.fail("Unit is not leader") return def on_run_action(self, event): """Run an arbitrary command on the remote host.""" if self.is_leader: cmd = event.params["command"] proxy = self.get_ssh_proxy() stdout, stderr = proxy.run(cmd) event.set_results({"output": stdout}) if len(stderr): event.fail(stderr) else: event.fail("Unit is not leader") return def on_verify_ssh_credentials_action(self, event): """Verify the SSH credentials for this unit.""" if self.is_leader: proxy = self.get_ssh_proxy() verified = proxy.verify_credentials() if verified: print("Verified!") event.set_results({"verified": True}) else: print("Verification failed!") event.set_results({"verified": False}) else: event.fail("Unit is not leader") return @property def is_leader(self): # update the framework to include self.unit.is_leader() return self.model.unit.is_leader() class LeadershipError(ModelError): def __init__(self): super().__init__("not leader") if __name__ == "__main__": main(SimpleHAProxyCharm) main(VyosCharm)
magma/hackfest_gateway_vnfd/charms/vyos-config/src/proxy_cluster.pydeleted 100644 → 0 +0 −71 Original line number Diff line number Diff line # Copyright 2020 Canonical Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from ops.framework import Object, StoredState class ProxyCluster(Object): state = StoredState() def __init__(self, charm, relation_name): super().__init__(charm, relation_name) self._relation_name = relation_name self._relation = self.framework.model.get_relation(self._relation_name) self.framework.observe(charm.on.ssh_keys_initialized, self.on_ssh_keys_initialized) self.state.set_default(ssh_public_key=None) self.state.set_default(ssh_private_key=None) def on_ssh_keys_initialized(self, event): if not self.framework.model.unit.is_leader(): raise RuntimeError("The initial unit of a cluster must also be a leader.") self.state.ssh_public_key = event.ssh_public_key self.state.ssh_private_key = event.ssh_private_key if not self.is_joined: event.defer() return self._relation.data[self.model.app][ "ssh_public_key" ] = self.state.ssh_public_key self._relation.data[self.model.app][ "ssh_private_key" ] = self.state.ssh_private_key @property def is_joined(self): return self._relation is not None @property def ssh_public_key(self): if self.is_joined: return self._relation.data[self.model.app].get("ssh_public_key") @property def ssh_private_key(self): if self.is_joined: return self._relation.data[self.model.app].get("ssh_private_key") @property def is_cluster_initialized(self): return ( True if self.is_joined and self._relation.data[self.model.app].get("ssh_public_key") and self._relation.data[self.model.app].get("ssh_private_key") else False )
magma/hackfest_magma-agw-enb_vnfd/charms/magmagw/actions.yaml +0 −12 Original line number Diff line number Diff line Loading @@ -67,18 +67,6 @@ add-test-subscriber: type: "string" default: "" # Standard OSM functions start: description: "Stop the service on the VNF." stop: description: "Stop the service on the VNF." restart: description: "Stop the service on the VNF." reboot: description: "Reboot the VNF virtual machine." upgrade: description: "Upgrade the software on the VNF." # Required by charms.osm.sshproxy run: description: "Run an arbitrary command" Loading
magma/hackfest_magma-agw-enb_vnfd/charms/magmagw/src/charm.py +10 −1 Original line number Diff line number Diff line Loading @@ -146,7 +146,16 @@ class MagmaAGWProxyCharm(SSHProxyCharm): """Resets the hardware ID""" if self.unit.is_leader(): proxy = self.get_ssh_proxy() attempt = 0 while attempt < 50: try: stdout, stderr = proxy.run("sudo snowflake --force-new-key") break except subprocess.CalledProcessError: attempt += 1 import time time.sleep(5) event.set_results({"output": stdout, "stderr": stderr}) else: event.fail("Unit is not leader") Loading