def userdel(name: str) -> None: if user_exists(name): try: p = subprocess.Popen( # pylint:disable=consider-using-with ["userdel", "-r", name], stdin=open(os.devnull, "r"), # pylint:disable=consider-using-with stdout=open(os.devnull, "w"), # pylint:disable=consider-using-with stderr=subprocess.PIPE, close_fds=True, encoding="utf-8", ) except OSError as e: raise MKTerminate("\n" + tty.error + ": Failed to delete user '%s': %s" % (name, e)) stderr = p.communicate()[1] if p.returncode != 0: raise MKTerminate("\n" + tty.error + ": Failed to delete user '%s': %s" % (name, stderr)) # On some OSes (e.g. debian) the group is automatically removed if # it bears the same name as the user. So first check for the group. if group_exists(name): groupdel(name)
def user_confirms(site, conflict_mode, title, message, relpath, yes_choice, yes_text, no_choice, no_text): # type: (SiteContext, str, str, str, str, str, str, str, str) -> bool # Handle non-interactive mode if conflict_mode == "abort": raise MKTerminate("Update aborted.") if conflict_mode == "install": return False if conflict_mode == "keepold": return True user_path = site.dir + "/" + relpath options = [(yes_choice, yes_text), (no_choice, no_text), ("shell", "Open a shell for looking around"), ("abort", "Stop here and abort update!")] while True: choice = ask_user_choices(title, message, options) if choice == "abort": raise MKTerminate("Update aborted.") if choice == "shell": thedir = "/".join(user_path.split("/")[:-1]) sys.stdout.write("\n Starting BASH. Type CTRL-D to continue.\n\n") subprocess.Popen(["bash", "-i"], cwd=thedir).wait() else: return choice == yes_choice
def userdel(name: str) -> None: if user_exists(name): try: completed_process = subprocess.run( ["userdel", "-r", name], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, close_fds=True, encoding="utf-8", check=False, ) except OSError as e: raise MKTerminate("\n" + tty.error + ": Failed to delete user '%s': %s" % (name, e)) if completed_process.returncode: raise MKTerminate("\n" + tty.error + ": Failed to delete user '%s': %s" % (name, completed_process.stderr)) # On some OSes (e.g. debian) the group is automatically removed if # it bears the same name as the user. So first check for the group. if group_exists(name): groupdel(name)
def _config_load_hook(site: "SiteContext", hook_name: str) -> ConfigHook: hook: ConfigHook = { "name": hook_name, "deprecated": False, } if not site.hook_dir: # IMHO this should be unreachable... raise MKTerminate("Site has no version and therefore no hooks") description = "" description_active = False with Path(site.hook_dir, hook_name).open() as hook_file: for line in hook_file: if line.startswith("# Alias:"): hook["alias"] = line[8:].strip() elif line.startswith("# Menu:"): hook["menu"] = line[7:].strip() elif line.startswith("# Deprecated: yes"): hook["deprecated"] = True elif line.startswith("# Description:"): description_active = True elif line.startswith("# ") and description_active: description += line[3:].strip() + "\n" else: description_active = False hook["description"] = description def get_hook_info(info: str) -> str: return call_hook(site, hook_name, [info])[1] # The choices can either be a list of possible keys. Then # the hook outputs one live for each choice where the key and a # description are separated by a colon. Or it outputs one line # where that line is an extended regular expression matching the # possible values. choicestxt = get_hook_info("choices").split("\n") choices: ConfigHookChoices = None if len(choicestxt) == 1: regextext = choicestxt[0].strip() if regextext != "": choices = re.compile(regextext + "$") else: choices = None else: choices = [] try: for line in choicestxt: val, descr = line.split(":", 1) val = val.strip() descr = descr.strip() choices.append((val, descr)) except Exception as e: raise MKTerminate("Invalid output of hook: %s: %s" % (choicestxt, e)) hook["choices"] = choices return hook
def groupdel(groupname: str) -> None: try: p = subprocess.Popen(["groupdel", groupname], stdin=open(os.devnull, "r"), stdout=open(os.devnull, "w"), stderr=subprocess.PIPE, close_fds=True, encoding="utf-8") except OSError as e: raise MKTerminate("\n" + tty.error + ": Failed to delete group '%s': %s" % (groupname, e)) stderr = p.communicate()[1] if p.returncode != 0: raise MKTerminate("\n" + tty.error + ": Failed to delete group '%s': %s" % (groupname, stderr))
def useradd( version_info: "VersionInfo", site: "SiteContext", uid: Optional[str] = None, gid: Optional[str] = None, ) -> None: # Create user for running site 'name' _groupadd(site.name, gid) useradd_options = version_info.USERADD_OPTIONS if uid is not None: useradd_options += " -u %d" % int(uid) if (os.system( # nosec "useradd %s -r -d '%s' -c 'OMD site %s' -g %s -G omd %s -s /bin/bash" % (useradd_options, site.dir, site.name, site.name, site.name)) != 0): groupdel(site.name) raise MKTerminate("Error creating site user.") # On SLES11+ there is a standard group "trusted" that the OMD site users should be members # of to be able to access CRON. if group_exists("trusted"): _add_user_to_group(version_info, site.name, "trusted") # Add Apache to new group. It needs to be able to write in to the # command pipe and possible other stuff _add_user_to_group(version_info, version_info.APACHE_USER, site.name)
def call_hook(site: "SiteContext", hook_name: str, args: List[str]) -> ConfigHookResult: if not site.hook_dir: # IMHO this should be unreachable... raise MKTerminate("Site has no version and therefore no hooks") cmd = [site.hook_dir + hook_name] + args hook_env = os.environ.copy() hook_env.update({ "OMD_ROOT": site.dir, "OMD_SITE": site.name, }) logger.log(VERBOSE, "Calling hook: %s", subprocess.list2cmdline(cmd)) completed_process = subprocess.run( cmd, env=hook_env, close_fds=True, shell=False, stdout=subprocess.PIPE, encoding="utf-8", check=False, ) content = completed_process.stdout.strip() if completed_process.returncode and args[0] != "depends": sys.stderr.write("Error running %s: %s\n" % (subprocess.list2cmdline(cmd), content)) return completed_process.returncode, content
def _handle_sigterm(self, signum: int, frame: Optional[FrameType]) -> None: self._logger.debug("Received SIGTERM") status = self._jobstatus.get_status_from_file() if not status.get("stoppable", True): self._logger.warning("Skip termination of background job (Job ID: %s, PID: %d)", self._job_parameters["job_id"], os.getpid()) return raise MKTerminate()
def skel_permissions(self) -> Permissions: """Returns the skeleton permissions. Load either from version meta directory or from the original version skel.permissions file""" if not self._has_version_meta_data(): if self.version is None: raise MKTerminate("Failed to determine site version") return load_skel_permissions(self.version) return load_skel_permissions_from(self.version_meta_dir + "/skel.permissions")
def groupdel(groupname: str) -> None: try: completed_process = subprocess.run( ["groupdel", groupname], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, close_fds=True, encoding="utf-8", check=False, ) except OSError as e: raise MKTerminate("\n" + tty.error + ": Failed to delete group '%s': %s" % (groupname, e)) if completed_process.returncode: raise MKTerminate("\n" + tty.error + ": Failed to delete group '%s': %s" % (groupname, completed_process.stderr))
def _groupadd(groupname: str, gid: Optional[str] = None) -> None: cmd = ["groupadd"] if gid is not None: cmd += ["-g", "%d" % int(gid)] cmd.append(groupname) if subprocess.run(cmd, close_fds=True, stdin=subprocess.DEVNULL, check=False).returncode: raise MKTerminate("Cannot create group for site user.")
def groupdel(groupname: str) -> None: try: p = subprocess.Popen( # pylint:disable=consider-using-with ["groupdel", groupname], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, close_fds=True, encoding="utf-8", ) except OSError as e: raise MKTerminate("\n" + tty.error + ": Failed to delete group '%s': %s" % (groupname, e)) stderr = p.communicate()[1] if p.returncode != 0: raise MKTerminate("\n" + tty.error + ": Failed to delete group '%s': %s" % (groupname, stderr))
def _config_load_hook(site, hook_name): # type: (SiteContext, str) -> ConfigHook hook = { "name": hook_name, "deprecated": False, } # type: ConfigHook description = "" description_active = False for line in open(site.dir + "/lib/omd/hooks/" + hook_name): if line.startswith("# Alias:"): hook["alias"] = line[8:].strip() elif line.startswith("# Menu:"): hook["menu"] = line[7:].strip() elif line.startswith("# Deprecated: yes"): hook["deprecated"] = True elif line.startswith("# Description:"): description_active = True elif line.startswith("# ") and description_active: description += line[3:].strip() + "\n" else: description_active = False hook["description"] = description def get_hook_info(info): # type: (str) -> str return call_hook(site, hook_name, [info])[1] # The choices can either be a list of possible keys. Then # the hook outputs one live for each choice where the key and a # description are separated by a colon. Or it outputs one line # where that line is an extended regular expression matching the # possible values. choicestxt = get_hook_info("choices").split("\n") choices = None # type: ConfigHookChoices if len(choicestxt) == 1: regextext = choicestxt[0].strip() if regextext != "": choices = re.compile(regextext + "$") else: choices = None else: choices = [] try: for line in choicestxt: val, descr = line.split(":", 1) val = val.strip() descr = descr.strip() choices.append((val, descr)) except Exception as e: raise MKTerminate("Invalid output of hook: %s: %s" % (choicestxt, e)) hook["choices"] = choices return hook
def _groupadd(groupname: str, gid: Optional[str] = None) -> None: cmd = ["groupadd"] if gid is not None: cmd += ["-g", "%d" % int(gid)] cmd.append(groupname) if (subprocess.Popen( # pylint:disable=consider-using-with cmd, close_fds=True, stdin=open(os.devnull, "r"), # pylint:disable=consider-using-with ).wait() != 0): raise MKTerminate("Cannot create group for site user.")
def _groupadd(groupname: str, gid: Optional[str] = None) -> None: cmd = ["groupadd"] if gid is not None: cmd += ["-g", "%d" % int(gid)] cmd.append(groupname) if subprocess.Popen( cmd, close_fds=True, stdin=open(os.devnull, "r"), ).wait() != 0: raise MKTerminate("Cannot create group for site user.")
def user_verify(version_info: "VersionInfo", site: "SiteContext", allow_populated: bool = False) -> bool: name = site.name if not user_exists(name): raise MKTerminate(tty.error + ": user %s does not exist" % name) user = _user_by_id(user_id(name)) if user.pw_dir != site.dir: raise MKTerminate(tty.error + ": Wrong home directory for user %s, must be %s" % (name, site.dir)) if not os.path.exists(site.dir): raise MKTerminate(tty.error + ": home directory for user %s (%s) does not exist" % (name, site.dir)) if not allow_populated and os.path.exists(site.dir + "/version"): raise MKTerminate(tty.error + ": home directory for user %s (%s) must be empty" % (name, site.dir)) if not _file_owner_verify(site.dir, user.pw_uid, user.pw_gid): raise MKTerminate( tty.error + ": home directory (%s) is not owned by user %s and group %s" % (site.dir, name, name)) group = _group_by_id(user.pw_gid) if group is None or group.gr_name != name: raise MKTerminate(tty.error + ": primary group for siteuser must be %s" % name) if not _user_has_group(version_info.APACHE_USER, name): raise MKTerminate(tty.error + ": apache user %s must be member of group %s" % (version_info.APACHE_USER, name)) if not _user_has_group(name, "omd"): raise MKTerminate(tty.error + ": siteuser must be member of group omd") return True
def _handle_keepalive_interrupt(signum: int, frame: Optional[FrameType]) -> NoReturn: raise MKTerminate()
def _handle_keepalive_interrupt(signum, frame): raise MKTerminate()
def _handle_keepalive_interrupt(signum, frame): # type: (int, Optional[FrameType]) -> NoReturn raise MKTerminate()