def _cleanup_zombie_vpn(self, delay=1, log_lvl=logger.DEBUG): time.sleep(delay) logger.log(log_lvl, 'Cleanup the VPN zombie processes...') SystemHelper.kill_by_process(f'{self.vpn_dir}/vpnclient execsvc', silent=True, log_lvl=logger.down_lvl(log_lvl)) self.device.ip_resolver.cleanup_zombie(f'vpn_')
def remove(self, svc_opts: UnixServiceOpts, force: bool = False): service_fqn = self.to_service_fqn(svc_opts.service_dir, svc_opts.service_name) self.stop(svc_opts.service_name) self.disable(svc_opts.service_name) if force and FileHelper.is_exists(service_fqn): logger.info(f'Remove System service [{svc_opts.service_name}]...') FileHelper.rm(service_fqn) SystemHelper.exec_command("systemctl daemon-reload", silent=True, log_lvl=logger.INFO)
def lease_ip(self, vpn_acc: str, vpn_nic: str, daemon=False, is_execute=True): logger.log(self.log_lvl, 'Lease a new VPN IP...') command = f'{self.ip_tool} {self._lease_ip_opt(vpn_acc, vpn_nic, daemon)}' if is_execute: SystemHelper.exec_command(command, silent=self.silent, log_lvl=logger.down_lvl(self.log_lvl)) return command
def pre_exec(self, silent=False, log_lvl=logger.DEBUG, **kwargs): logger.log(log_lvl, 'Start VPN Client if not yet running...') if not self.is_installed(silent, log_lvl): return if self.pid_handler.is_running(): self._prev_is_run = True return SystemHelper.exec_command(f'{self.opts.vpnclient} start', log_lvl=logger.down_lvl(log_lvl)) time.sleep(1) if not self.pid_handler.is_running(log_lvl=logger.down_lvl(log_lvl)): logger.error('Unable start VPN Client') sys.exit(ErrorCode.VPN_START_FAILED)
def post_exec(self, silent=False, log_lvl=logger.DEBUG, **kwargs): logger.log(log_lvl, 'Stop VPN Client if applicable...') if not self.is_installed(True, log_lvl): return if (self._prev_is_run or not self.adhoc_task) and not kwargs.get('_force_stop', False): return lvl = logger.down_lvl(log_lvl) if self.pid_handler.is_running(log_lvl=lvl): SystemHelper.exec_command(f'{self.opts.vpnclient} stop', silent=silent, log_lvl=lvl) self._cleanup_zombie_vpn(1, log_lvl=lvl) self.pid_handler.cleanup()
def status(self, service_name: str) -> ServiceStatus: status = SystemHelper.exec_command( f"systemctl status {service_name} | grep Active | awk '{{print $2$3}}'", shell=True, silent=True, log_lvl=logger.TRACE) return ServiceStatus.parse(status)
def factory(resource_dir: Union[str, Path], runtime_dir: Union[str, Path], log_lvl: int, silent: bool = True) -> 'IPResolver': if SystemHelper.which(IPResolverType.DHCLIENT.value): return DHCPResolver(resource_dir, runtime_dir, log_lvl, silent) return None
def create(self, svc_opts: UnixServiceOpts, replacements: dict, auto_startup: bool = False): service_fqn = self.to_service_fqn(svc_opts.service_dir, svc_opts.service_name) logger.info( f'Add new service [{svc_opts.service_name}] in [{service_fqn}]...') FileHelper.copy(self.resource_dir.joinpath(Systemd.SERVICE_FILE_TMPL), service_fqn, force=True) FileHelper.replace_in_file(service_fqn, replacements, backup='') FileHelper.chmod(service_fqn, mode=0o0644) SystemHelper.exec_command("systemctl daemon-reload", silent=True, log_lvl=logger.INFO) if auto_startup: self.enable(svc_opts.service_name)
def _check_pid(pid_file: str, log_lvl=logger.TRACE) -> int: try: logger.log(log_lvl, f'Read PID file {pid_file}') pid = FileHelper.read_file_by_line(pid_file) pid = int(pid) if pid and pid > 0 and SystemHelper.is_pid_exists(pid): return pid except Exception as _: FileHelper.rm(pid_file) return 0
def probe(self) -> 'DNSResolver': self.kind = next( (t for t in DNSResolverType.as_services() if self.service.status(t.config.identity).is_enabled()), self.kind) if self.kind.might_be_command(): self.kind = next(t for t in DNSResolverType.as_command() if SystemHelper.verify_command(t.config.identity)) if self.kind.is_unknown(): logger.warn( 'Unknown DNS resolver. DNS VPN IP might be not resolved correctly' ) if self.kind not in [DNSResolverType.DNSMASQ, DNSResolverType.UNKNOWN]: dnsmasq_name = DNSResolverType.DNSMASQ.config.identity self._is_dnsmasq = self.service.status(dnsmasq_name).is_enabled( ) or shutil.which(dnsmasq_name) is not None logger.debug( f'Current DNS resolver [{self.kind.name}], is dnsmasq available [{self._is_dnsmasq}]' ) return self
def cleanup_zombie(self, process): logger.decrease(self.log_lvl, 'Cleanup the IP lease zombie processes...') SystemHelper.kill_by_process(f'{self.ip_tool}.*{process}.*', silent=True, log_lvl=self.log_lvl)
def factory(resource_dir: Union[str, Path], runtime_dir: Union[str, Path]) -> 'UnixService': if SystemHelper.verify_command(f'pidof {UnixServiceType.PROCD.value}'): raise NotImplementedError('Not yet supported OpenWRT') return None
def install(self, package): SystemHelper.exec_command(f'{self.tool} install {package} -y', log_lvl=logger.INFO, silent=True)
def restart(self, service_name, delay: int = 1): logger.info(f"Restart System service [{service_name}]...") SystemHelper.exec_command(f"systemctl restart {service_name}", log_lvl=logger.INFO) time.sleep(delay)
def stop(self, service_name): logger.info(f"Stop System service [{service_name}]...") SystemHelper.exec_command(f"systemctl stop {service_name}", silent=True, log_lvl=logger.INFO)
def disable(self, service_name: str): logger.info(f'Disable System service [{service_name}]...', ) SystemHelper.exec_command(f"systemctl disable {service_name}", silent=True, log_lvl=logger.INFO)
def enable(self, service_name: str): logger.info(f'Enable System service [{service_name}]...', ) SystemHelper.exec_command(f"systemctl enable {service_name}", log_lvl=logger.INFO)
def pm(self) -> Optional[PackageManager]: if SystemHelper.which(AptPM().tool): return AptPM() if SystemHelper.which(YumPM().tool): return YumPM() return None
def factory(resource_dir: Union[str, Path], runtime_dir: Union[str, Path]) -> 'UnixService': if SystemHelper.verify_command( f'pidof {UnixServiceType.SYSTEMD.value}'): return Systemd(resource_dir=resource_dir, runtime_dir=runtime_dir) return None
def release_ip(self, vpn_acc: str, vpn_nic: str): logger.log(self.log_lvl, 'Release the current VPN IP...') SystemHelper.exec_command( f'{self.ip_tool} {self._release_ip_opt(vpn_acc, vpn_nic)}', silent=self.silent, log_lvl=logger.down_lvl(self.log_lvl))
def renew_all_ip(self, delay=1, silent=False): logger.log(self.log_lvl, 'Refresh all IPs...') time.sleep(delay) SystemHelper.exec_command(f'{self._refresh_all_ip_opt()}', silent=silent or self.silent, log_lvl=logger.down_lvl(self.log_lvl))