def main(relation_name=None): """ This is the main entry point for the reactive framework. It calls :func:`~bus.discover` to find and load all reactive handlers (e.g., :func:`@when <decorators.when>` decorated blocks), and then :func:`~bus.dispatch` to trigger hook and state handlers until the state settles out. Finally, :meth:`unitdata.kv().flush <charmhelpers.core.unitdata.Storage.flush>` is called to persist the state. :param str relation_name: Optional name of the relation which is being handled. """ hookenv.log('Reactive main running for hook %s' % hookenv.hook_name(), level=hookenv.INFO) def flush_kv(): if unitdata._KV: unitdata._KV.flush() hookenv.atexit(flush_kv) try: bus.discover() bus.dispatch() except SystemExit as x: if x.code is None or x.code == 0: hookenv._run_atexit() raise hookenv._run_atexit()
def main(relation_name=None): """ This is the main entry point for the reactive framework. It calls :func:`~bus.discover` to find and load all reactive handlers (e.g., :func:`@when <decorators.when>` decorated blocks), and then :func:`~bus.dispatch` to trigger hook and state handlers until the state settles out. Finally, :meth:`unitdata.kv().flush <charmhelpers.core.unitdata.Storage.flush>` is called to persist the state. :param str relation_name: Optional name of the relation which is being handled. """ hookenv.log('Reactive main running for hook %s' % hookenv.hook_name(), level=hookenv.INFO) # work-around for https://bugs.launchpad.net/juju-core/+bug/1503039 # ensure that external handlers can tell what hook they're running in if 'JUJU_HOOK_NAME' not in os.environ: os.environ['JUJU_HOOK_NAME'] = os.path.basename(sys.argv[0]) def flush_kv(): if unitdata._KV: unitdata._KV.flush() hookenv.atexit(flush_kv) try: bus.discover() hookenv._run_atstart() bus.dispatch() except SystemExit as x: if x.code is None or x.code == 0: hookenv._run_atexit() raise hookenv._run_atexit()
def main(args): hookenv._run_atstart() action_name = os.path.basename(args[0]) try: action = ACTIONS[action_name] except KeyError: return "Action %s undefined" % action_name else: try: action(args) except Exception as e: hookenv.action_fail(str(e)) hookenv._run_atexit()
def manage(self): """ Handle the current hook by doing The Right Thing with the registered services. """ hookenv._run_atstart() try: hook_name = hookenv.hook_name() if hook_name == 'stop': self.stop_services() else: self.reconfigure_services() self.provide_data() except SystemExit as x: if x.code is None or x.code == 0: hookenv._run_atexit() hookenv._run_atexit()
def main(relation_name=None): """ This is the main entry point for the reactive framework. It calls :func:`~bus.discover` to find and load all reactive handlers (e.g., :func:`@when <decorators.when>` decorated blocks), and then :func:`~bus.dispatch` to trigger hook and state handlers until the state settles out. Finally, :meth:`unitdata.kv().flush <charmhelpers.core.unitdata.Storage.flush>` is called to persist the state. :param str relation_name: Optional name of the relation which is being handled. """ hookenv.log('Reactive main running for hook %s' % hookenv.hook_name(), level=hookenv.INFO) # work-around for https://bugs.launchpad.net/juju-core/+bug/1503039 # ensure that external handlers can tell what hook they're running in if 'JUJU_HOOK_NAME' not in os.environ: os.environ['JUJU_HOOK_NAME'] = os.path.basename(sys.argv[0]) # update data to be backwards compatible after fix for issue 28 relations._migrate_conversations() def flush_kv(): if unitdata._KV: unitdata._KV.flush() hookenv.atexit(flush_kv) if hookenv.hook_name().endswith('-relation-departed'): def depart_conv(): rel = RelationBase.from_name(hookenv.relation_type()) rel.conversation().depart() hookenv.atexit(depart_conv) try: bus.discover() hookenv._run_atstart() bus.dispatch() except SystemExit as x: if x.code is None or x.code == 0: hookenv._run_atexit() raise hookenv._run_atexit()
def main(relation_name=None): """ This is the main entry point for the reactive framework. It calls :func:`~bus.discover` to find and load all reactive handlers (e.g., :func:`@when <decorators.when>` decorated blocks), and then :func:`~bus.dispatch` to trigger handlers until the queue settles out. Finally, :meth:`unitdata.kv().flush <charmhelpers.core.unitdata.Storage.flush>` is called to persist the flags and other data. :param str relation_name: Optional name of the relation which is being handled. """ restricted_mode = hookenv.hook_name() in [ 'meter-status-changed', 'collect-metrics' ] hookenv.log('Reactive main running for hook %s' % hookenv.hook_name(), level=hookenv.INFO) if restricted_mode: hookenv.log('Restricted mode.', level=hookenv.INFO) # work-around for https://bugs.launchpad.net/juju-core/+bug/1503039 # ensure that external handlers can tell what hook they're running in if 'JUJU_HOOK_NAME' not in os.environ: os.environ['JUJU_HOOK_NAME'] = os.path.basename(sys.argv[0]) try: bus.discover() if not restricted_mode: # limit what gets run in restricted mode hookenv._run_atstart() bus.dispatch(restricted=restricted_mode) except Exception: tb = traceback.format_exc() hookenv.log('Hook error:\n{}'.format(tb), level=hookenv.ERROR) raise except SystemExit as x: if x.code not in (None, 0): raise if not restricted_mode: # limit what gets run in restricted mode hookenv._run_atexit() unitdata._KV.flush()
def restore(): """ Implementation of easyrsa 'restore' action Backup restoration process can be summarized as following: * Selected backup is scanned and verified * Contents of the backup are unpacked into <cahrm_dir>/EasyRSA/pki * Data that are stored in the local database are updated * All units that have relation with this easyrsa unit will be notified about the certificate changes. """ pki_dir = os.path.join(easyrsa_directory, "pki") backup_name = function_get("name") if backup_name is None: raise RuntimeError("Parameter 'name' is required.") log("Restoring pki from backup file {}".format(backup_name), hookenv.INFO) backup_path = os.path.join(PKI_BACKUP, backup_name) if not os.path.isfile(backup_path): log("Backup file '{}' does not exists.".format(backup_path), hookenv.ERROR) raise RuntimeError( "Backup with name '{}' does not exist. Use action " "'list-backups' to list all available " "backups".format(backup_name) ) with tarfile.open(backup_path, "r:gz") as pki_tar: _verify_backup(pki_tar) _replace_pki(pki_tar, pki_dir) cert_dir = os.path.join(pki_dir, "issued") key_dir = os.path.join(pki_dir, "private") # Update CA and global client data stored in the local leader's database # NOTE(mkalcok): Easyrsa does not really support HA mode, so it's usually # run as a single unit/model _update_leadership_data(pki_dir, cert_dir, key_dir) ca_cert = leader_get("certificate_authority") tls = endpoint_from_name("client") log("Sending CA certificate to all related units", hookenv.INFO) tls.set_ca(ca_cert) log("Sending global client certificate and key to all related units", hookenv.INFO) tls.set_client_cert(leader_get("client_certificate"), leader_get("client_key")) for client in tls.all_requests: try: cert_file = os.path.join(cert_dir, "{}.crt".format(client.common_name)) key_file = os.path.join(key_dir, "{}.key".format(client.common_name)) with open(cert_file, "r") as file: cert = file.read() with open(key_file, "r") as file: key = file.read() log( "Sending certificate for '{}' to unit" "'{}'".format(client.common_name, client.unit_name), hookenv.INFO, ) log(cert, hookenv.DEBUG) client.set_cert(cert, key) except FileNotFoundError: log( "Certificate for '{}' not found in backup. " "Generating new one.", hookenv.INFO, ) if client.cert_type == "client": cert, key = create_client_certificate(client.common_name) elif client.cert_type == "server": cert, key = create_server_certificate( client.common_name, client.sans, client.common_name ) else: # This use case should not really happen as easyrsa charm # does not support Application type certificates raise RuntimeError( "Unrecognized certificate request type " '"{}".'.format(client.cert_type) ) log( "Sending certificate for '{}' to unit" "'{}'".format(client.common_name, client.unit_name), hookenv.INFO, ) log(cert, hookenv.DEBUG) client.set_cert(cert, key) hookenv._run_atexit()
etcd_conf.cluster_state = 'new' conf_path = os.path.join(etcd_conf.etcd_conf_dir, "etcd.conf.yml") render('etcd3.conf', conf_path, etcd_conf.__dict__, owner='root', group='root') def rebuild_cluster(): """Signal other etcd units to rejoin new cluster.""" log('Requesting peer members to rejoin cluster') rejoin_request = uuid4().hex hookenv.leader_set(force_rejoin=rejoin_request) if __name__ == '__main__': log('Performing etcd snapshot restore') preflight_check() render_backup() dismantle_cluster() service_stop(opts['etcd_daemon_process']) if is_v3_backup(): restore_v3_backup() else: unpack_resource() pid = start_etcd_forked() probe_forked_etcd() reconfigure_client_advertise() pkill_etcd(pid) service_start(opts['etcd_daemon_process']) rebuild_cluster() _run_atexit()