def _check_requires(self, element, cluster_data=None): """ Validate a requires element, raising excError if the requirement is not met. """ if element is None: return if element == "impossible": raise ex.excContinueAction("skip impossible requirement") if element.count("(") == 1: rid, states = element.rstrip(")").split("(") states = states.split(",") else: rid = element states = ["up", "stdby up"] if rid not in self.svc.resources_by_id: self.log.warning("ignore requires on %s: resource not found", rid) return if cluster_data: try: current_state = cluster_data[rcEnv.nodename]["services"][ "status"][self.svc.path]["resources"][rid]["status"] except KeyError: current_state = "undef" else: resource = self.svc.resources_by_id[rid] current_state = rcStatus.Status(resource.status()) if current_state not in states: msg = "requires on resource %s in state %s, current state %s" % \ (rid, " or ".join(states), current_state) if self.svc.options.cron: raise ex.excContinueAction(msg) else: raise ex.excError(msg)
def load_status_last(self, refresh=False): """ Fetch the resource status from the on-disk cache. """ try: with open(self.fpath_status_last, 'r') as ofile: data = json.load(ofile) except ValueError: return rcStatus.UNDEF except (OSError, IOError) as exc: if exc.errno != 2: # not EEXISTS self.log.debug(exc) return rcStatus.UNDEF try: status = rcStatus.Status(data["status"]) except (IndexError, AttributeError, ValueError) as exc: self.log.debug(exc) return rcStatus.UNDEF if not refresh and hasattr(self, "set_label"): if hasattr(self, "_lazy_label"): attr = "_lazy_label" else: attr = "label" try: setattr(self, attr, data["label"]) except (IndexError, AttributeError, ValueError) as exc: pass self.status_logs = data.get("log", []) return status
def write_status_history(self): """ Log a change to the resource status history file. """ fpath = self.fpath_status_history try: with open(fpath, 'r') as ofile: lines = ofile.readlines() last = lines[-1].split(" | ")[-1].strip("\n") except: last = None current = rcStatus.Status(self.rstatus) if current == last: return log = logging.getLogger("status_history") logformatter = logging.Formatter("%(asctime)s | %(message)s") logfilehandler = logging.handlers.RotatingFileHandler( fpath, maxBytes=512000, backupCount=1, ) logfilehandler.setFormatter(logformatter) log.addHandler(logfilehandler) log.error(current) logfilehandler.close() log.removeHandler(logfilehandler)
def _status(self, verbose=False): self.data_status() if not self.volsvc.exists(): self.status_log("volume %s does not exist" % self.volname, "info") return rcStatus.DOWN status = rcStatus.Status(self.volsvc.print_status_data()["avail"]) if not self.flag_installed(): self.status_log("%s is %s" % (self.volsvc.path, status), "info") return rcStatus.DOWN return status
def status(self, **kwargs): """ Resource status evaluation method wrapper. Handles caching, nostatus tag and disabled flag. """ verbose = kwargs.get("verbose", False) refresh = kwargs.get("refresh", False) ignore_nostatus = kwargs.get("ignore_nostatus", False) if self.is_disabled(): return rcStatus.NA if not ignore_nostatus and "nostatus" in self.tags: self.status_log("nostatus tag", "info") return rcStatus.NA if self.rstatus is not None and not refresh: return self.rstatus last_status = self.load_status_last(refresh) if refresh: self.purge_status_last() else: self.rstatus = last_status # now the rstatus can no longer be None if self.rstatus == rcStatus.UNDEF or refresh: self.status_logs = [] self.rstatus = self.try_status(verbose) self.rstatus = self.status_stdby(self.rstatus) self.log.debug("refresh status: %s => %s", rcStatus.Status(last_status), rcStatus.Status(self.rstatus)) self.write_status() if self.rstatus in (rcStatus.UP, rcStatus.STDBY_UP) and \ self.is_provisioned_flag() is False: self.write_is_provisioned_flag(True) return self.rstatus
def write_status_last(self): """ Write the in-memory resource status to the on-disk cache. """ data = { "status": str(rcStatus.Status(self.rstatus)), "label": self.label, "log": self.status_logs, } dpath = os.path.dirname(self.fpath_status_last) if not os.path.exists(dpath): os.makedirs(dpath, 0o0755) with open(self.fpath_status_last, 'w') as ofile: json.dump(data, ofile) ofile.flush()
def checkreserv(self): self.log.debug("starting checkreserv. prkey %s"%self.hostid) if self.ack_all_unit_attention() != 0: return rcStatus.WARN r = rcStatus.Status() for d in self.devs: try: key = self.get_reservation_key(d) # pylint: disable=assignment-from-none if key is None: self.log.debug("disk %s is not reserved" % d) r += rcStatus.DOWN elif key != self.hostid: self.log.debug("disk %s is reserved by another host whose key is %s" % (d, key)) r += rcStatus.DOWN else: self.log.debug("disk %s is correctly reserved" % d) r += rcStatus.UP except ex.excScsiPrNotsupported as exc: self.log.warning(str(exc)) continue return r.status
def status(self, **kwargs): """ Return the aggregate status a ResourceSet. """ agg_status = rcStatus.Status() for resource in self.resources: if resource.is_disabled(): continue if not self.svc.encap and resource.encap: # don't evaluate encap service resources continue try: status = resource.status(**kwargs) except: import traceback exc = sys.exc_info() print(exc[0], exc[1], traceback.print_tb(exc[2])) status = rcStatus.NA agg_status += status return agg_status.status
def docker_start(self, verbose=True): """ Start the docker daemon if in private mode and not already running. """ if not self.docker_daemon_private: return if self.docker_cmd is None: raise ex.excError("docker executable not found") import lock lockfile = os.path.join(self.svc.var_d, "lock.docker_start") try: lockfd = lock.lock(timeout=15, delay=1, lockfile=lockfile) except lock.LOCK_EXCEPTIONS as exc: self.svc.log.error("dockerd start lock acquire failed: %s", str(exc)) return # Sanity checks before deciding to start the daemon if self.docker_running(): lock.unlock(lockfd) return if self.container_data_dir is None: lock.unlock(lockfd) return resource = self._container_data_dir_resource() if resource is not None: state = resource._status() if state not in (rcStatus.UP, rcStatus.STDBY_UP): self.svc.log.warning( "the docker daemon data dir is handled by the %s " "resource in %s state. can't start the docker " "daemon", resource.rid, rcStatus.Status(state)) lock.unlock(lockfd) return if os.path.exists(self.docker_pid_file): self.svc.log.warning("removing leftover pid file %s", self.docker_pid_file) os.unlink(self.docker_pid_file) # Now we can start the daemon, creating its data dir if necessary cmd = self.dockerd_cmd if verbose: self.svc.log.info("starting docker daemon") self.svc.log.info(" ".join(cmd)) import subprocess subprocess.Popen( ["nohup"] + cmd, stdout=open("/dev/null", "w"), stderr=open("/dev/null", "a"), preexec_fn=os.setpgrp, close_fds=True, ) import time try: for _ in range(self.max_wait_for_dockerd): if self._docker_working(): self.clear_daemon_caches() return time.sleep(1) finally: lock.unlock(lockfd)