def get_info(host, *, users=None, connection=None): log.debug("Getting info about '{}'".format(host)) user, host = connection.ssh_user, connection.ssh_host data = OrderedDict() data["ssh_user"] = user data["ssh_host"] = host data["ssh"] = "{}@{}".format(user, host) data["whoami"] = ssh_cmd(connection, "whoami") data["uname"] = ssh_cmd(connection, "uname") data["arch"] = ssh_cmd(connection, "uname -m") data["os_release"] = os_release(ssh_cmd(connection, "cat /etc/os-release")) data["agent_location"] = ssh_cmd(connection, "which cf-agent") data["policy_server"] = ssh_cmd(connection, "cat /var/cfengine/policy_server.dat") agent_version = ssh_cmd(connection, "cf-agent --version") if agent_version: # 'CFEngine Core 3.12.1 \n CFEngine Enterprise 3.12.1' # ^ split and use this part for version number agent_version = agent_version.split()[2] data["agent_version"] = agent_version data["bin"] = {} for bin in ["dpkg", "rpm", "yum", "apt", "pkg"]: path = ssh_cmd(connection, "which {}".format(bin)) if path: data["bin"][bin] = path log.debug("JSON data from host info: \n" + pretty(data)) return data
def get_info(host, *, users=None, connection=None): log.debug("Getting info about '{}'".format(host)) user, host = connection.ssh_user, connection.ssh_host data = OrderedDict() data["ssh_user"] = user data["ssh_host"] = host data["ssh"] = "{}@{}".format(user, host) data["whoami"] = ssh_cmd(connection, "whoami") systeminfo = ssh_cmd(connection, "systeminfo") if systeminfo: data["os"] = "windows" data["systeminfo"] = parse_systeminfo(systeminfo) data["package_tags"] = ["x86_64", "msi"] data["arch"] = "x86_64" agent = r'& "C:\Program Files\Cfengine\bin\cf-agent.exe"' data["agent"] = agent data["agent_version"] = parse_version( ssh_cmd(connection, '{} -V'.format(agent))) else: data["os"] = "unix" data["uname"] = ssh_cmd(connection, "uname") data["arch"] = ssh_cmd(connection, "uname -m") data["os_release"] = os_release( ssh_cmd(connection, "cat /etc/os-release")) data["agent_location"] = ssh_cmd(connection, "which cf-agent") data["policy_server"] = ssh_cmd(connection, "cat /var/cfengine/policy_server.dat") agent = r'/var/cfengine/bin/cf-agent' data["agent"] = agent data["agent_version"] = parse_version( ssh_cmd(connection, "{} --version".format(agent))) data["bin"] = {} for bin in ["dpkg", "rpm", "yum", "apt", "pkg"]: path = ssh_cmd(connection, "which {}".format(bin)) if path: data["bin"][bin] = path log.debug("JSON data from host info: \n" + pretty(data)) return data
def install_package(host, pkg, data, *, connection=None): print("Installing: '{}' on '{}'".format(pkg, host)) if ".deb" in pkg: output = ssh_sudo(connection, "dpkg -i {}".format(pkg), True) elif ".msi" in pkg: output = ssh_cmd(connection, r".\{}".format(pkg), True) time.sleep(8) else: output = ssh_sudo(connection, "rpm -i {}".format(pkg), True) if output is None: sys.exit("Installation failed on '{}'".format(host))
def deploy_masterfiles(host, tarball, *, connection=None): data = get_info(host, connection=connection) print_info(data) if not data["agent_version"]: log.error( f"Cannot deploy masterfiles on {host} - CFEngine not installed") return 1 scp(tarball, host, connection=connection) ssh_cmd(connection, f"tar -xzf masterfiles.tgz") commands = [ "systemctl stop cfengine3", "rm -rf /var/cfengine/masterfiles", "mv masterfiles /var/cfengine/masterfiles", "systemctl start cfengine3", "cf-agent -Kf update.cf", "cf-agent -K", ] combined = " && ".join(commands) print(f"Running: '{combined}'") ssh_sudo(connection, combined) return 0
def bootstrap_host(host_data, policy_server, *, connection=None): host = host_data["ssh_host"] agent = host_data["agent"] print("Bootstrapping: '{}' -> '{}'".format(host, policy_server)) command = "{} --bootstrap {}".format(agent, policy_server) if host_data["os"] == "windows": output = ssh_cmd(connection, command) else: output = ssh_sudo(connection, command) if output is None: sys.exit("Bootstrap failed on '{}'".format(host)) if output and "completed successfully" in output: print("Bootstrap successful: '{}' -> '{}'".format(host, policy_server)) else: user_error("Something went wrong while bootstrapping")
def install_package(host, pkg, data, *, connection=None): print("Installing: '{}' on '{}'".format(pkg, host)) if ".deb" in pkg: output = ssh_sudo(connection, "dpkg -i {}".format(pkg), True) elif ".msi" in pkg: # Windows is crazy, be careful if you decide to change this; # This needs to work in both powershell and cmd, and in # Windows 2012 Server, 2016, and so on... # sleep is powershell specific, # timeout doesn't work over ssh. output = ssh_cmd(connection, powershell(r'.\{} ; sleep 10'.format(pkg)), True) else: output = ssh_sudo(connection, "rpm -i {}".format(pkg), True) if output is None: sys.exit("Installation failed on '{}'".format(host))
def bootstrap_host(host_data, policy_server, *, connection=None, trust_server=True): host = host_data["ssh_host"] agent = host_data["agent"] print("Bootstrapping: '{}' -> '{}'".format(host, policy_server)) command = "{} --bootstrap {}".format(agent, policy_server) if not trust_server: command += " --trust-server=no" if host_data["os"] == "windows": output = ssh_cmd(connection, powershell(command)) else: output = ssh_sudo(connection, command) if output is None: sys.exit("Bootstrap failed on '{}'".format(host)) if output and "completed successfully" in output: print("Bootstrap successful: '{}' -> '{}'".format(host, policy_server)) return True else: log.error("Something went wrong while bootstrapping") return False
def run_command(host, command, *, users=None, connection=None, sudo=False): if sudo: return ssh_sudo(connection, command, errors=True) return ssh_cmd(connection, command, errors=True)
def get_info(host, *, users=None, connection=None): log.debug("Getting info about '{}'".format(host)) user, host = connection.ssh_user, connection.ssh_host data = OrderedDict() data["ssh_user"] = user data["ssh_host"] = host data["ssh"] = "{}@{}".format(user, host) data["whoami"] = ssh_cmd(connection, "whoami") systeminfo = ssh_cmd(connection, "systeminfo") if systeminfo: data["os"] = "windows" data["systeminfo"] = parse_systeminfo(systeminfo) data["package_tags"] = ["x86_64", "msi"] data["arch"] = "x86_64" agent = r"& 'C:\Program Files\Cfengine\bin\cf-agent.exe'" data["agent"] = agent version_cmd = powershell('{} -V'.format(agent)) data["agent_version"] = parse_version(ssh_cmd(connection, version_cmd)) else: data["os"] = "unix" data["uname"] = ssh_cmd(connection, "uname") data["arch"] = ssh_cmd(connection, "uname -m") data["os_release"] = os_release( ssh_cmd(connection, "cat /etc/os-release")) tags = [] if data["os_release"]: distro = data["os_release"]["ID"] major = data["os_release"]["VERSION_ID"].split(".")[0] platform_tag = distro + major # Add tags with version number first, to filter by them first: tags.append(platform_tag) # Example: ubuntu16 if distro == "centos": tags.append("el" + major) # Then add more generic tags (lower priority): tags.append(distro) # Example: ubuntu if distro == "centos": tags.append("rhel") tags.append("el") else: redhat_release = ssh_cmd(connection, "cat /etc/redhat-release") if redhat_release: # Examples: # CentOS release 6.10 (Final) # Red Hat Enterprise Linux release 8.0 (Ootpa) before, after = redhat_release.split(" release ") distro = "rhel" if before.lower().startswith("centos"): distro = "centos" major = after.split(".")[0] tags.append(distro + major) tags.append("el" + major) if "rhel" not in tags: tags.append("rhel" + major) tags.append(distro) if "rhel" not in tags: tags.append("rhel") tags.append("el") data["package_tags"] = tags data["agent_location"] = ssh_cmd(connection, "which cf-agent") data["policy_server"] = ssh_cmd(connection, "cat /var/cfengine/policy_server.dat") agent = r'/var/cfengine/bin/cf-agent' data["agent"] = agent data["agent_version"] = parse_version( ssh_cmd(connection, "{} --version".format(agent))) data["bin"] = {} for bin in ["dpkg", "rpm", "yum", "apt", "pkg"]: path = ssh_cmd(connection, "which {}".format(bin)) if path: data["bin"][bin] = path log.debug("JSON data from host info: \n" + pretty(data)) return data
def install_host(host, *, hub=False, packages=None, bootstrap=None, version=None, demo=False, call_collect=False, connection=None, edition=None, show_info=True, remote_download=False, trust_keys=None): data = get_info(host, connection=connection) if show_info: print_info(data) package = None if packages and type(packages) is str: package = packages elif packages and len(packages) == 1: package = packages[0] if not package: tags = [] if edition == "enterprise": tags.append("hub" if hub else "agent") tags.append("64" if data["arch"] in ["x86_64", "amd64"] else data["arch"]) if data["arch"] in ["i386", "i486", "i586", "i686"]: tags.append("32") extension = None if "package_tags" in data and "msi" in data["package_tags"]: extension = ".msi" data["package_tags"].remove("msi") elif "dpkg" in data["bin"]: extension = ".deb" elif "rpm" in data["bin"]: extension = ".rpm" if "package_tags" in data and data["package_tags"]: tags.extend(data["package_tags"]) if packages is None: # No commandd line argument given package = _package_from_releases(tags, extension, version, edition, remote_download) else: package = _package_from_list(tags, extension, packages) if not package: log.error("Installation failed - no package found!") return 1 if remote_download: print(f"Downloading '{package}' on '{host}' using curl") r = ssh_cmd(cmd="curl --fail -O {}".format(package), connection=connection, errors=True) if r is None: return 1 else: scp(package, host, connection=connection) package = basename(package) install_package(host, package, data, connection=connection) data = get_info(host, connection=connection) if data["agent_version"] and len(data["agent_version"]) > 0: print("CFEngine {} was successfully installed on '{}'".format( data["agent_version"], host)) else: log.error("Installation failed!") return 1 if trust_keys: for key in trust_keys: scp(key, host, connection=connection) run_command(host, "mv %s /var/cfengine/ppkeys/" % basename(key), connection=connection, sudo=True) if bootstrap: ret = bootstrap_host(data, policy_server=bootstrap, connection=connection, trust_server=(not trust_keys)) if not ret: return 1 if demo: if hub: demo_lib.install_def_json(host, connection=connection, call_collect=call_collect) demo_lib.agent_run(data, connection=connection) demo_lib.disable_password_dialog(host) demo_lib.agent_run(data, connection=connection) return 0