def ready(): """ When the StorPool block service has been installed and the OpenStack integration has been installed everywhere, set the unit's status to `active`. """ rdebug('ready to go') ensure_our_presence() spstatus.set('active', 'so far so good so what')
def update_status(): try: status = get_status() spstatus.set("active" if status["ready"] else "maintenance", status["message"]) except BaseException as e: s = "Querying the StorPool status: {e}".format(e=e) hookenv.log(s, hookenv.ERROR) spstatus.set("maintenance", s)
def sp_status(): # Yes, removing it at once, not after the fact. If something # goes wrong, the action may be reissued. reactive.remove_state("storpool-block-charm.sp-status") try: status = get_status() hookenv.action_set({"status": json.dumps(status)}) spstatus.set("active" if status["ready"] else "maintenance", status["message"]) except BaseException as e: s = "Querying the StorPool status: {e}".format(e=e) hookenv.log(s, hookenv.ERROR) hookenv.action_fail(s)
def try_to_submit(): """ Once the data has been collected and `submit_url` is set, go ahead. """ url = hookenv.config().get('submit_url', None) rdebug('trying to submit to {url}'.format(url=url)) reactive.remove_state('storpool-inventory.submitting') if url is None: rdebug('erm, how did we get here with no submit URL?') return spstatus.npset('maintenance', 'submitting the collected data') try: global datafile rdebug('about to read {df}'.format(df=datafile)) with open(datafile, mode='r', encoding='latin1') as f: contents = ''.join(f.readlines()) rdebug('read {ln} characters of data from the collect file'.format( ln=len(contents))) data = json.dumps({'filename': platform.node(), 'contents': contents}) rdebug('encoded stuff into {ln} characters of data to submit'.format( ln=len(data))) data_enc = data.encode('latin1') rdebug('submitting {ln} bytes of data to {url}'.format( ln=len(data_enc), url=url)) with urllib.request.urlopen(url, data=data_enc) as resp: rdebug('got some kind of an HTTP response') code = resp.getcode() rdebug('got response code {code}'.format(code=code)) if code is not None and code >= 200 and code < 300: rdebug('success!') reactive.set_state('storpool-inventory.submitted') spstatus.set('active', 'here, have a blob of data') except Exception as e: rdebug('could not submit the data: {e}'.format(e=e)) sputils.err('failed to submit the collected data')
def get_status(): inst = reactive.is_state("storpool-block-charm.services-started") status = { "node": sputils.get_machine_id(), "charm-config": dict(hookenv.config()), "storpool-conf": read_storpool_conf(), "installed": inst, "presence": service_hook.fetch_presence(RELATIONS), "lxd": unitdata.kv().get(kvdata.KEY_LXD_NAME), "ready": False, } for name in ( "storpool_repo_url", "storpool_version", "storpool_openstack_version", ): value = status["charm-config"].get(name) if value is None or value == "": status["message"] = "No {name} in the config".format(name=name) return status if not inst: status["message"] = "Packages not installed yet" return status spstatus.set("maintenance", "checking the StorPool configuration") rdebug("about to try to obtain our StorPool ID") try: out = subprocess.check_output(["storpool_showconf", "-ne", "SP_OURID"]) out = out.decode() out = out.split("\n") our_id = out[0] except Exception as e: status["message"] = "Could not obtain the StorPool ID: {e}".format(e=e) return status spstatus.set("maintenance", "checking the Cinder and Nova processes...") found = False status["proc"] = {} for cmd in ("cinder-volume", "nova-compute"): d = osi.check_spopenstack_processes(cmd) if d: found = True status["proc"][cmd] = d bad = sorted(filter(lambda pid: not d[pid], d.keys())) if bad: status["message"] = "No spopenstack group: {pid}".format(pid=bad) return status if found: spstatus.set("maintenance", "checking for the spool directory") dirname = pathlib.Path("/var/spool/openstack-storpool") if not dirname.is_dir(): status["message"] = "No {d} directory".format(d=dirname) return status st = dirname.stat() if not st.st_mode & 0o0020: status["message"] = "{d} not group-writable".format(d=dirname) return status spstatus.set("maintenance", "checking the StorPool services...") svcs = ("storpool_beacon", "storpool_block") rdebug("checking for services: {svcs}".format(svcs=svcs)) missing = list(filter(lambda s: not host.service_running(s), svcs)) rdebug("missing: {missing}".format(missing=missing)) if missing: status["message"] = "StorPool services not running: {missing}".format( missing=" ".join(missing)) return status spstatus.set("maintenance", "querying the StorPool API") rdebug("checking the network status of the StorPool client") try: out = subprocess.check_output(["storpool", "-jB", "service", "list"]) out = out.decode() data = json.loads(out) rdebug("got API response: {d}".format(d=data)) if "error" in data: raise Exception( "API response: {d}".format(d=data["error"]["descr"])) state = data["data"]["clients"][our_id]["status"] rdebug("got our client status {st}".format(st=state)) if state != "running": status["message"] = "StorPool client: {st}".format(st=state) return status except Exception as e: status["message"] = "Could not query the StorPool API: {e}".format(e=e) return status spstatus.set("maintenance", "querying the StorPool API for client status") rdebug("checking the status of the StorPool client") try: out = subprocess.check_output(["storpool", "-jB", "client", "status"]) out = out.decode() data = json.loads(out) rdebug("got API response: {d}".format(d=data)) if "error" in data: raise Exception( "API response: {d}".format(d=data["error"]["descr"])) int_id = int(our_id) found = list(filter(lambda e: e["id"] == int_id, data["data"])) if not found: raise Exception( "No client status reported for {our_id}".format(our_id=our_id)) state = found[0]["configStatus"] status["message"] = "StorPool client: {st}".format(st=state) if state == "ok": status["ready"] = True rdebug("get_status: calling for Cinder LXD reconfiguration") reactive.set_state("storpool-block-charm.lxd") else: status["ready"] = False return status except Exception as e: status["message"] = "Could not query the StorPool API: {e}".format(e=e) return status
def err(msg): """ Log an error message and set the unit's status. """ hookenv.log(msg, hookenv.ERROR) spstatus.set("error", msg)