def customize_shell(): app.print_verbose("Customize shell") app.print_verbose(" Add Date And Time To History Output") scOpen("/etc/bashrc").replace_add( "^export HISTTIMEFORMAT=.*$", "export HISTTIMEFORMAT=\"%h/%d - %H:%M:%S \"") app.print_verbose(" Add Color To Grep") root = scOpen("/root/.bash_profile") root.replace_add("^export GREP_COLOR=.*$", "export GREP_COLOR='1;32'") root.replace_add("^export GREP_OPTIONS=.*$", "export GREP_OPTIONS=--color=auto") skel = scOpen("/etc/skel/.bash_profile") skel.replace_add("^export GREP_COLOR=.*$", "export GREP_COLOR='1;32'") skel.replace_add("^export GREP_OPTIONS=.*$", "export GREP_OPTIONS=--color=auto") app.print_verbose(" Enable SSH key forwarding to work with sudo su") tmp_sudo_file = get_install_dir() + "sudoers" x("cp /etc/sudoers " + tmp_sudo_file) sudoers = scOpen(tmp_sudo_file) sudoers.remove("Defaults env_keep += \"SSH_AUTH_SOCK\"") sudoers.add("Defaults env_keep += \"SSH_AUTH_SOCK\"") xRes = x("visudo -c -f " + tmp_sudo_file) if tmp_sudo_file + ": parsed OK" in xRes: x("mv " + tmp_sudo_file + " /etc/sudoers") else: app.print_error("Temporary sudoers file corrupt, not updating")
def handle_subprocess(p, output): stdout="" stderr="" while (True): for txt in p.stdout: # Only write caption once. if (output == X_OUTPUT_ALL): if (stdout==""): app.print_verbose("---- Result ----", 2) app.print_verbose(txt, 2, new_line=False) stdout+=txt for txt in p.stderr: stderr += txt if (p.poll() != None): break if (stderr and output == X_OUTPUT_ALL): app.print_error(stderr.strip()) # # Error messages is enough to print. A failure doesn't always mean a failure. # For example [ -f '/etc/cron.allow' ] && chmod og-rwx /etc/cron.allow # will return returncode 1, when the file doesn't exist. # if (p.returncode and output == X_OUTPUT_ALL): # app.print_error("Invalid returncode %d" % p.returncode) # An extra line break for the looks. if ((stdout or stderr) and app.options.verbose >=2 and output == X_OUTPUT_ALL): print("\n"), return stdout + str(stderr)
def main(): ''' Used to control the command line options, and the execution of the script. First function called when using the script. ''' # Module variables cmd_list = Commands() usage = "usage: %prog [options] command\n\n" usage += "Commands:\n" usage += cmd_list.get_help() app.parser = OptionParser(usage=usage, version="System Console " + app.version, add_help_option=True) app.parser.add_option("-v", "--verbose", action="store_const", const=2, dest="verbose", default=1, help="Show more output.") app.parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose", help="Show no output.") app.parser.add_option("-f", "--force", action="store_const", const=1, dest="force", default=0, help="Ignore version.cfg.") (app.options, args) = app.parser.parse_args() app.print_verbose(app.parser.get_version()) if len(args) < 1 and 2 > len(args): app.parser.print_help() else: try: cmd_list.execute(args) except version.VersionException, e: app.print_error(repr(e.args))
def _install_host(self, hostname): ''' Execute the commands on the remote host. Create one process for each remote host. ''' try: server = config.host(hostname).get_back_ip() app.print_verbose("Try to install " + hostname + " (" + server + ")", 2) obj = ssh.Ssh(server, app.get_root_password()) self._validate_alive(obj, hostname) app.print_verbose("========================================================================================") app.print_verbose("=== Update " + hostname + " (" + server + ")") app.print_verbose("========================================================================================") obj.install_ssh_key() self._install_syco_on_remote_host(obj) self._execute_commands(obj, hostname) except pexpect.EOF, e: app.print_error(e, 2) # Remove progress state. if hostname in self.installed: del(self.installed[hostname])
def _install_host(self, hostname): ''' Execute the commands on the remote host. Create one process for each remote host. ''' try: server = config.host(hostname).get_front_ip() app.print_verbose("Try to install " + hostname + " (" + server + ")", 2) obj = ssh.Ssh(server, app.get_root_password()) self._validate_alive(obj, hostname) app.print_verbose("========================================================================================") app.print_verbose("=== Update " + hostname + " (" + server + ")") app.print_verbose("========================================================================================") obj.install_ssh_key() self._install_syco_on_remote_host(obj) self._execute_commands(obj, hostname) except pexpect.EOF, e: app.print_error(e, 2) # Remove progress state. if hostname in self._installed: del(self._installed[hostname])
def main(): """ Used to control the command line options, and the execution of the script. First function called when using the script. """ # Module variables cmd_list = Commands() usage = "usage: %prog [options] command\n\n" usage += "Commands:\n" usage += cmd_list.get_help() app.parser = OptionParser(usage=usage, version="System Console " + app.version, add_help_option=True) app.parser.add_option("-v", "--verbose", action="store_const", const=2, dest="verbose", default=1, help="Show more output.") app.parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose", help="Show no output.") app.parser.add_option("-f", "--force", action="store_const", const=1, dest="force", default=0, help="Ignore version.cfg.") (app.options, args) = app.parser.parse_args() app.print_verbose(app.parser.get_version()) if len(args) < 1 and 2 > len(args): app.parser.print_help() else: try: cmd_list.execute(args) except version.VersionException, e: app.print_error(repr(e.args))
def customize_shell(): app.print_verbose("Customize shell") app.print_verbose(" Add Date And Time To History Output") scOpen("/etc/bashrc").replace_add( "^export HISTTIMEFORMAT=.*$", "export HISTTIMEFORMAT=\"%h/%d - %H:%M:%S \"" ) app.print_verbose(" Add Color To Grep") root = scOpen("/root/.bash_profile") root.replace_add("^export GREP_COLOR=.*$", "export GREP_COLOR='1;32'") root.replace_add("^export GREP_OPTIONS=.*$", "export GREP_OPTIONS=--color=auto") skel = scOpen("/etc/skel/.bash_profile") skel.replace_add("^export GREP_COLOR=.*$", "export GREP_COLOR='1;32'") skel.replace_add("^export GREP_OPTIONS=.*$", "export GREP_OPTIONS=--color=auto") app.print_verbose(" Enable SSH key forwarding to work with sudo su") tmp_sudo_file = get_install_dir() + "sudoers" x("cp /etc/sudoers " + tmp_sudo_file) sudoers = scOpen(tmp_sudo_file) sudoers.remove("Defaults env_keep += \"SSH_AUTH_SOCK\"") sudoers.add("Defaults env_keep += \"SSH_AUTH_SOCK\"") xRes = x("visudo -c -f " + tmp_sudo_file) if tmp_sudo_file + ": parsed OK" in xRes: x("mv " + tmp_sudo_file + " /etc/sudoers") else: app.print_error("Temporary sudoers file corrupt, not updating")
def handle_subprocess(p, output): stdout = "" stderr = "" while (True): for txt in p.stdout: # Only write caption once. if (output == X_OUTPUT_ALL): if (stdout == ""): app.print_verbose("---- Result ----", 2) app.print_verbose(txt, 2, new_line=False) stdout += txt for txt in p.stderr: stderr += txt if (p.poll() != None): break if (stderr and output == X_OUTPUT_ALL): app.print_error(stderr.strip()) # # Error messages is enough to print. A failure doesn't always mean a failure. # For example [ -f '/etc/cron.allow' ] && chmod og-rwx /etc/cron.allow # will return returncode 1, when the file doesn't exist. # if (p.returncode and output == X_OUTPUT_ALL): # app.print_error("Invalid returncode %d" % p.returncode) # An extra line break for the looks. if ((stdout or stderr) and app.options.verbose >= 2 and output == X_OUTPUT_ALL): print("\n"), return stdout + str(stderr)
def install_ossec_client(args): ''' Install OSSEC Client on the server ''' if os.path.exists('/var/ossec/bin/manage_agents'): app.print_error("Not insalling OSSEC client since OSSEC server detected") return app.print_verbose("Install ossec client.") version_obj = version.Version("InstallOssec", SCRIPT_VERSION) version_obj.check_executed() # Initialize all passwords used by the script app.init_mysql_passwords() build_ossec('preloaded-vars-client.conf') _setup_conf() _setup_keys() # Enabling syslog logging x('/var/ossec/bin/ossec-control enable client-syslog') # Adding iptables rules iptables.add_ossec_chain() iptables.save() # Restaring OSSEC server x("service ossec restart") x('yum remove gcc perl-Time-HiRes -y') version_obj.mark_executed()
def ssh_exec(self, command, events = {}, silent=False): ''' Execute the ssh command. Connect to the remote host, execute the command and closes the conneciton. ''' try: self._ssh_exec(command, events, silent) except pexpect.TIMEOUT, e: app.print_error("Got a timeout from ssh_exec, retry to execute command: " + command + str(e)) self.ssh_exec(command, events)
def _execute_commands(self, obj, hostname): commands = config.host(hostname).get_commands(app.options.verbose >= 2) while(len(commands) != 0): try: obj.ssh_exec(commands[0]) commands.pop(0) except ssh.SSHTerminatedException, e: app.print_error("SSHTerminatedException on host " + hostname + " with command " + commands[0]) obj.wait_until_alive() except pexpect.EOF, e: app.print_error("pexpect.EOF on host " + hostname + " with command " + commands[0])
def main(): """ Used to control the command line options, and the execution of the script. First function called when using the script. """ # Module variables cmd_list = Commands() usage = "usage: %prog [options] command\n\n" usage += "Commands:\n" usage += cmd_list.get_help() info = "System Console {0}, syco(git {1})".format( app.version, get_last_git_commit('/opt/syco')) for plugin_path in app.get_syco_plugin_paths(): info += ", {0}(git {1})".format(os.path.basename(plugin_path), get_last_git_commit(plugin_path)) app.parser = OptionParser(usage=usage, version=info, add_help_option=True) app.parser.add_option("-v", "--verbose", action="store_const", const=2, dest="verbose", default=1, help="Show more output.") app.parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose", help="Show no output.") app.parser.add_option("-f", "--force", action="store_const", const=1, dest="force", default=0, help="Ignore version.cfg.") (app.options, args) = app.parser.parse_args() app.print_verbose(app.parser.get_version()) if len(args) < 1 and 2 > len(args): app.parser.print_help() else: try: cmd_list.execute(args) except version.VersionException, e: app.print_error(repr(e.args))
def __init__(self): """ Read command directories (public and private) and add commands. """ self.current_type = "public" for obj in self._get_modules(app.SYCO_PUBLIC_PATH): try: obj.build_commands(self) except AttributeError, e: app.print_error(" Problem with obj, error:: " + repr(e.args)) except NameError, e: app.print_error(" Problem with " + repr(obj) + ", error: " + repr(e.args))
def ssh_exec(self, command, events={}, silent=False): ''' Execute the ssh command. Connect to the remote host, execute the command and closes the conneciton. ''' try: self._ssh_exec(command, events, silent) except pexpect.TIMEOUT, e: app.print_error( "Got a timeout from ssh_exec, retry to execute command: " + command + str(e)) self.ssh_exec(command, events)
def uninstall_ossec_client(args): ''' Remove OSSECD Client from the server @todo: Will uninstall the server aswell. ''' if os.path.exists('/var/ossec/bin/manage_agents'): app.print_error("Not uninsalling OSSEC client since OSSEC server detected") return # Stoping OSSEC client x('/var/ossec/bin/ossec-control stop') # Remove folders x('rm -rf /var/ossec')
def _execute_commands(self, obj, hostname): commands = config.host(hostname).get_commands(app.options.verbose >= 2) while (len(commands) != 0): try: obj.ssh_exec(commands[0]) commands.pop(0) except ssh.SSHTerminatedException, e: app.print_error("SSHTerminatedException on host " + hostname + " with command " + commands[0]) obj.wait_until_alive() except pexpect.EOF, e: app.print_error("pexpect.EOF on host " + hostname + " with command " + commands[0])
def get_game(self, gameid, with_opening=True): """ Fetch data for a game based on a gameid. :param gameid: Lichess gameId. :param with_opening: Whether to get opening data for the game. :return: API data of a game, json loaded into dict. """ if gameid: path = 'game/{}?with_opening={}'.format(gameid, '1' if with_opening else '0') try: return self.request.send(path) except URLError: print_error('Unable to get gamedata: ' + path) return
def enable_selinux(): ''' All machines should have selinux on by default. For more info: http://www.crypt.gen.nz/selinux/disable_selinux.html ''' app.print_verbose("Enable SELinux") enforcing = grep("/etc/selinux/config", "SELINUX=enforcing") permissive = grep("/etc/selinux/config", "SELINUX=permissive") if (enforcing or permissive): config = scOpen("/etc/selinux/config") config.replace('^SELINUX=.*$', "SELINUX=enforcing") config.replace('^SELINUXTYPE=.*$', "SELINUXTYPE=targeted") else: app.print_error("SELinux is disabled, more need to be done, read " + "http://www.crypt.gen.nz/selinux/disable_selinux.html")
def vir_list(args): old_verbose = app.options.verbose app.options.verbose = 2 try: for hostname in config.get_hosts(): server = config.host(hostname).get_front_ip() obj = ssh.Ssh(server, app.get_root_password()) app.print_verbose("List KVM guests on host " + hostname + " (" + server + ")") if (obj.is_alive()): obj.install_ssh_key() obj.ssh_exec("virsh list --all") else: app.print_verbose(" Not online.") except SettingsError, e: app.print_error(e, 2)
def vir_list(args): old_verbose = app.options.verbose app.options.verbose = 2 try: for hostname in config.get_hosts(): server = config.host(hostname).get_back_ip() obj = ssh.Ssh(server, app.get_root_password()) app.print_verbose("List KVM guests on host " + hostname + " (" + server + ")") if (obj.is_alive()): obj.install_ssh_key() obj.ssh_exec("virsh list --all") else: app.print_verbose(" Not online.") except SettingsError, e: app.print_error(e, 2)
def remote_install_syco(self, hostname): ''' Execute the commands on the remote host. Create one process for each remote host. ''' try: server = config.host(hostname).get_back_ip() app.print_verbose("Install syco on " + hostname + " (" + server + ")", 2) obj = ssh.Ssh(server, app.get_root_password()) self._validate_alive(obj, hostname) obj.install_ssh_key() self._install_syco_on_remote_host(obj) except pexpect.EOF, e: app.print_error(e, 2)
def enable_selinux(): ''' All machines should have selinux on by default. For more info: http://www.crypt.gen.nz/selinux/disable_selinux.html ''' app.print_verbose("Enable SELinux") enforcing = grep("/etc/selinux/config", "SELINUX=enforcing") permissive = grep("/etc/selinux/config", "SELINUX=permissive") if (enforcing or permissive): config = scOpen("/etc/selinux/config") config.replace('^SELINUX=.*$', "SELINUX=enforcing") config.replace('^SELINUXTYPE=.*$', "SELINUXTYPE=targeted") else: app.print_error( "SELinux is disabled, more need to be done, read " + "http://www.crypt.gen.nz/selinux/disable_selinux.html" )
def send(self, path): """Send request to path on the API. :param path: A relative path added to lichess.org/api/ :return: API response, json loaded into dict. """ req = Request(LICHESS_API_URL + path, headers={'Accept': 'application/json'}) try: with urlopen(req) as response: response_data = response.read() except URLError: raise URLError if response.status == 429: print_error('Response 429 - waiting 61 seconds.') # Wait a full minute before resuming API usage as lichess suggests. time.sleep(61) return return json.loads(response_data)
def __init__(self): netmasks = {} #Add localhost IP/netmask local_ip = "127.0.0.1" self.server_ips.append(local_ip) netmasks[local_ip] = "255.0.0.0" #Add IPs for front/back net if they exist. front_ip = config.host(net.get_hostname()).get_front_ip() if front_ip: self.server_ips.append(front_ip) netmasks[front_ip] = config.general.get_front_netmask() back_ip = config.host(net.get_hostname()).get_back_ip() if config.general.is_back_enabled() and back_ip: self.server_ips.append(back_ip) netmasks[back_ip] = config.general.get_back_netmask() if len(self.server_ips) < 2: app.print_error( "Didn't find any valid IP addresses from front or back net. Exiting" ) sys.exit(1) for ip in self.server_ips: self.server_networks.append(net.get_network_cidr(ip, netmasks[ip])) self.virtual_alias_domains = config.general.get_option( "mailrelay.virtual_alias_domains", "") for alias_row in config.general.get_option("mailrelay.virtual_aliases", "").split(";"): if len(alias_row.strip()) == 0: #Don't process empty rows break split_row = alias_row.split(" ", 1) if len(split_row) != 2: app.print_error( "Expected mailrelay.virtual_alias to be two words separated by space, several entries " "separated by semicolon. Found \"%s\"" % alias_row) sys.exit(1) self.virtual_aliases[split_row[0]] = split_row[1]
def remote_install_syco(self, hostname): ''' Execute the commands on the remote host. Create one process for each remote host. ''' try: server = config.host(hostname).get_back_ip() app.print_verbose( "Install syco on " + hostname + " (" + server + ")", 2) obj = ssh.Ssh(server, app.get_root_password()) self._validate_alive(obj, hostname) obj.install_ssh_key() self._install_syco_on_remote_host(obj) except pexpect.EOF, e: app.print_error(e, 2)
def __init__(self): ''' Read command directories (public and private) and add commands. ''' try: self.current_type = "public" for obj in self._get_modules(app.SYCO_PUBLIC_PATH): obj.build_commands(self) self.current_type = "private" if (os.access(app.SYCO_USR_PATH, os.F_OK)): for plugin in os.listdir(app.SYCO_USR_PATH): plugin_path = os.path.abspath(app.SYCO_USR_PATH + "/" + plugin + "/bin/") for obj in self._get_modules(plugin_path): obj.build_commands(self) except AttributeError, e: app.print_error(" Problem with obj, error:: " + repr(e.args))
class RemoteInstall: ''' Run commands defined in install.cfg on remote hosts through SSH. If the remote host is not yet installed/started/available, the script will retry to connect every 30 second until it answers. ''' servers = [] # All hosts that are alive. alive = {} # All hosts config status invalid_config = {} # All hosts that has been installed. installed = {} # Abort error abort_error = {} def run(self, hostname=""): ''' Start the installation ''' self._set_servers(hostname) self._validate_install_config() self._start_all_threads() self._wait_for_all_threads_to_finish() def remote_install_syco(self, hostname): ''' Execute the commands on the remote host. Create one process for each remote host. ''' try: server = config.host(hostname).get_back_ip() app.print_verbose( "Install syco on " + hostname + " (" + server + ")", 2) obj = ssh.Ssh(server, app.get_root_password()) self._validate_alive(obj, hostname) obj.install_ssh_key() self._install_syco_on_remote_host(obj) except pexpect.EOF, e: app.print_error(e, 2) except SettingsError, e: app.print_error(e, 2)
def _setup_backup_for_all_servers(): servers = config.get_servers() total_servers = len(servers) checked_servers = 0 while (len(servers)): checked_servers += 1 hostname = servers.pop() ip = config.host(hostname).get_back_ip() remote_server = ssh.Ssh(ip, app.get_root_password()) if (remote_server.is_alive()): remote_server.install_ssh_key() _configure_backup_pathes(remote_server, ip, hostname) else: servers.insert(0, hostname) app.print_error("Server " + hostname + " is not alive.") if (checked_servers > total_servers): total_servers = len(servers) checked_servers = 0 time.sleep(60)
def _setup_backup_for_all_servers(): servers = config.get_servers() total_servers = len(servers) checked_servers = 0 while(len(servers)): checked_servers += 1 hostname = servers.pop() ip = config.host(hostname).get_back_ip() remote_server = ssh.Ssh(ip, app.get_root_password()) if (remote_server.is_alive()): remote_server.install_ssh_key() _configure_backup_pathes(remote_server, ip, hostname) else: servers.insert(0, hostname) app.print_error("Server " + hostname + " is not alive.") if (checked_servers > total_servers): total_servers = len(servers) checked_servers = 0 time.sleep(60)
def install_glassfish(args): ''' The main installation function. ''' app.print_verbose("Install %s script-version: %d" % (GLASSFISH_VERSION, SCRIPT_VERSION)) version_obj = version.Version("Install" + GLASSFISH_VERSION, SCRIPT_VERSION) version_obj.check_executed() try: initialize_passwords() general.create_install_dir() _set_env_vars() _install_software() iptables.add_glassfish_chain() iptables.save() for domain_name, port_base in [["domain1", "6000"], ["domain2", "7000"]]: admin_port = str(int(port_base) + 48) _create_domains(domain_name, port_base) _set_domain_passwords(domain_name, admin_port) _set_domain_configs(admin_port) _set_jvm_options(admin_port) _install_domains_plugins(domain_name) # Restart to get all options take affect. x("/etc/init.d/" + GLASSFISH_VERSION + " stop -an") x("/etc/init.d/" + GLASSFISH_VERSION + " start -an") version_obj.mark_executed() except Exception, error_text: app.print_error("Failed to install glassfish") app.print_error(error_text) traceback.print_exc(file=sys.stdout)
def __init__(self): netmasks = {} # Add localhost IP/netmask local_ip = "127.0.0.1" self.server_ips.append(local_ip) netmasks[local_ip] = "255.0.0.0" # Add IPs for front/back net if they exist. front_ip = config.host(net.get_hostname()).get_front_ip() if front_ip: self.server_ips.append(front_ip) netmasks[front_ip] = config.general.get_front_netmask() back_ip = config.host(net.get_hostname()).get_back_ip() if config.general.is_back_enabled() and back_ip: self.server_ips.append(back_ip) netmasks[back_ip] = config.general.get_back_netmask() if len(self.server_ips) < 2: app.print_error("Didn't find any valid IP addresses from front or back net. Exiting") sys.exit(1) for ip in self.server_ips: self.server_networks.append(net.get_network_cidr(ip, netmasks[ip])) self.virtual_alias_domains = config.general.get_option("mailrelay.virtual_alias_domains", "") for alias_row in config.general.get_option("mailrelay.virtual_aliases", "").split(";"): if len(alias_row.strip()) == 0: # Don't process empty rows break split_row = alias_row.split(" ", 1) if len(split_row) != 2: app.print_error( "Expected mailrelay.virtual_alias to be two words separated by space, several entries " 'separated by semicolon. Found "%s"' % alias_row ) sys.exit(1) self.virtual_aliases[split_row[0]] = split_row[1]
def main(): """ Used to control the command line options, and the execution of the script. First function called when using the script. """ # Module variables cmd_list = Commands() usage = "usage: %prog [options] command\n\n" usage += "Commands:\n" usage += cmd_list.get_help() info = "System Console {0}, syco(git {1})".format( app.version, get_last_git_commit('/opt/syco') ) for plugin_path in app.get_syco_plugin_paths(): info += ", {0}(git {1})".format( os.path.basename(plugin_path), get_last_git_commit(plugin_path) ) app.parser = OptionParser(usage=usage, version=info , add_help_option=True) app.parser.add_option("-v", "--verbose", action="store_const", const=2, dest="verbose", default=1, help="Show more output.") app.parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose", help="Show no output.") app.parser.add_option("-f", "--force", action="store_const", const=1, dest="force", default=0, help="Ignore version.cfg.") (app.options, args) = app.parser.parse_args() app.print_verbose(app.parser.get_version()) if len(args) < 1 and 2 > len(args): app.parser.print_help() else: try: cmd_list.execute(args) except version.VersionException, e: app.print_error(repr(e.args))
def install_glassfish(arg): """Install glassfish""" app.print_verbose("Install glassfish 5 script-version: %d" % SCRIPT_VERSION) version_obj = version.Version("install-glassfish5", SCRIPT_VERSION) version_obj.check_executed() try: initialize_passwords() general.create_install_dir() x("yum install unzip -y") if not _is_glassfish_user_installed(): # Add a new group for glassfish administration. # This can be used for all users that should be able to # adminitrate glassfish. x("groupadd glassfish5 -g 205") # Give glassfish it's own user. x("adduser -m -r --shell /bin/bash -u205 -g205 glassfish5") _check_java_installed() _install_glassfish() _setup_glassfish() _install_mariadb_connect() _install_guice() _install_icinga_ulimit_check() _set_domain_passwords() # Restart to get all options take affect. x("/etc/init.d/glassfish5 stop -n") x("/etc/init.d/glassfish5 start -n") version_obj.mark_executed() except Exception, error_text: app.print_error("Failed to install glassfish") app.print_error(error_text) traceback.print_exc(file=sys.stdout)
def install_local(args): ''' Run all commands on the localhost. ''' # Ask the user for all passwords that might be used in the remote install # so the installation can go on headless. app.init_all_passwords() hostname = "" if len(args) > 1: hostname = args[1] if hostname == "": hostname = socket.gethostname() app.print_verbose("Install all commands defined in install.cfg for host " + hostname + ".") commands = config.host(hostname).get_commands(app.options.verbose >= 2) if len(commands) > 0: for command in commands: general.shell_exec(command) else: app.print_error("No commands for this host.")
def install_glassfish(arg): """Install glassfish4""" app.print_verbose("Install glassfish 4 script-version: %d" % SCRIPT_VERSION) version_obj = version.Version("install-glassfish-4", SCRIPT_VERSION) version_obj.check_executed() try: initialize_passwords() general.create_install_dir() x("yum install unzip -y") if not _is_glassfish_user_installed(): # Add a new group for glassfish administration. # This can be used for all users that should be able to # adminitrate glassfish. x("groupadd glassfish -g 200") # Give glassfish it's own user. x("adduser -m -r --shell /bin/bash -u200 -g200 glassfish") _check_java_installed() _install_glassfish() _setup_glassfish4() _install_mysql_connect() _install_guice() _install_icinga_ulimit_check() _set_domain_passwords() # Restart to get all options take affect. x("/etc/init.d/glassfish-4 stop -n") x("/etc/init.d/glassfish-4 start -n") version_obj.mark_executed() except Exception, error_text: app.print_error("Failed to install glassfish") app.print_error(error_text) traceback.print_exc(file=sys.stdout)
def _execute_commands(self, obj, hostname): if self._enable_commands: commands = config.host(hostname).get_commands(app.options.verbose >= 2) while(len(commands) != 0): try: obj.ssh_exec(commands[0]) commands.pop(0) except ssh.SSHTerminatedException, e: app.print_error("SSHTerminatedException on host " + hostname + " with command " + commands[0]) obj.wait_until_alive() except pexpect.EOF, e: app.print_error("pexpect.EOF on host " + hostname + " with command " + commands[0]) except pxssh.ExceptionPxssh, e: app.print_error("pxssh.ExceptionPxssh on host " + hostname + " with command " + commands[0] + ", might be because the remote host rebooted.")
def shell_exec(command, user="", cwd=None, events=None, output=True): ''' Execute a shell command using pexpect, and writing verbose affected output. ''' # Build command to execute args = [] if (user): args.append(user) args.append('-c ' + command) if (output): app.print_verbose(BOLD + "Command: su " + RESET + user + " -c '" + command + "'") # Setting default events if events is None: events = {} events["Verify the SYCO master password:"******"su", args, cwd=cwd) if (not output): out.disable_output() if (output): app.print_verbose("---- Result ----", 2) stdout = "" index = 0 while (index < num_of_events + 1): index = out.expect(keys, timeout=3600) stdout += out.before if index >= 0 and index < num_of_events: if (inspect.isfunction(value[index])): out.send(str(value[index]()) + "\n") else: out.send(value[index]) elif index == num_of_events: app.print_error( "Catched a timeout from pexpect.expect, lets try again.") if (out.exitstatus and output): app.print_error("Invalid exitstatus %d" % out.exitstatus) if (out.signalstatus and output): app.print_error("Invalid signalstatus %d - %s" % out.signalstatus, out.status) # An extra line break for the looks. if (output and stdout and app.options.verbose >= 2): print("\n"), out.close() return stdout
class RemoteInstall: ''' Run commands defined in install.cfg on remote hosts through SSH. If the remote host is not yet installed/started/available, the script will retry to connect every 30 second until it answers. ''' _servers = None # All hosts that are alive. _alive = None # All hosts config status _invalid_config = None # All hosts that has been installed. _installed = None # Abort error _abort_error = None # Execute commands on each host when enabled. _enable_commands = None def __init__(self): self._servers = [] self._alive = {} self._invalid_config = {} self._installed = {} self._abort_error = {} self._enable_commands = None def run(self, hostname, enable_commands = True): ''' Start the installation ''' self._enable_commands = enable_commands self._set_servers(hostname) self._validate_install_config() self._prompt_for_passwords() self._start_all_threads(self._install_host) self._wait_for_all_threads_to_finish() def _set_servers(self, hostname): ''' Set servers/hosts to perform the remote install on. ''' if (hostname): self._servers.append(hostname) if (config.host(hostname).is_host()): self._servers += config.host(hostname).get_guests() else: self._servers = config.get_servers() sorted(self._servers) def _validate_install_config(self): ''' Validate all host options in install.cfg. Print error messages in verbose mode. ''' for hostname in self._servers: if (not config.host(hostname).get_front_ip()): self._invalid_config[hostname] = "No" app.print_verbose("In install.cfg, cant find ip for " + hostname) else: self._invalid_config[hostname] = "Yes" def _prompt_for_passwords(self): #Reference to syco.py commands global _commands_obj_reference for hostname in self._servers: commands = config.host(hostname).get_commands() for command in commands: #Assume second word is the command name split_commands = command.split(" ") if len(split_commands) < 1: app.print_verbose("Did not understand command: %s, skipping" % command) continue elif split_commands[0].lower() == "syco": if len(split_commands) < 2: app.print_verbose("Did not understand syco command: %s, skipping" % command) continue else: #This is not a syco command, ignoring it. continue #else, this is a syco command and arg[1] should be the name of the command syco_command = split_commands[1] #Find the passwords for command passwords = _commands_obj_reference.get_command_passwords(syco_command) if len(passwords) > 0: app.print_verbose("Retrieving passwords for command %s" % command) for password_combo in passwords: app.get_custom_password(password_combo[0], password_combo[1]) def _start_all_threads(self, function_to_run): while(not self._is_all_servers_installed()): self._print_install_stat() for hostname in self._servers: if (not self._is_installation_in_progress(hostname) and not self.has_abort_errors(hostname)): self._installed[hostname] = "Progress" t = threading.Thread(target=function_to_run, args=[hostname]) t.start() # End script if all threads are done, otherwise sleep for 30 for i in range(30): time.sleep(1) if(self._is_all_servers_installed()): return def _wait_for_all_threads_to_finish(self): ''' Wait for all threads to finish ''' for t in threading.enumerate(): if (threading.currentThread() != t): t.join() def _is_all_servers_installed(self): return len(self._servers) == self._installed_servers() def _installed_servers(self): installed = 0 for status in self._installed.values(): if (status == "Yes"): installed += 1 return installed def _servers_left_to_install(self): return len(self._servers) - self._installed_servers() def _is_installation_in_progress(self, hostname): if (hostname in self._installed and self._installed[hostname] != "No"): return True else: return False def has_abort_errors(self, hostname): return (hostname in self._abort_error) def _install_host(self, hostname): ''' Execute the commands on the remote host. Create one process for each remote host. ''' try: server = config.host(hostname).get_front_ip() app.print_verbose("Try to install " + hostname + " (" + server + ")", 2) obj = ssh.Ssh(server, app.get_root_password()) self._validate_alive(obj, hostname) app.print_verbose("========================================================================================") app.print_verbose("=== Update " + hostname + " (" + server + ")") app.print_verbose("========================================================================================") obj.install_ssh_key() self._install_syco_on_remote_host(obj) self._execute_commands(obj, hostname) except pexpect.EOF, e: app.print_error(e, 2) # Remove progress state. if hostname in self._installed: del(self._installed[hostname]) except SettingsError, e: app.print_error(e, 2) # Remove progress state. if hostname in self._installed: del(self._installed[hostname])
app.print_verbose("=== Update " + hostname + " (" + server + ")") app.print_verbose("========================================================================================") obj.install_ssh_key() self._install_syco_on_remote_host(obj) self._execute_commands(obj, hostname) except pexpect.EOF, e: app.print_error(e, 2) # Remove progress state. if hostname in self.installed: del(self.installed[hostname]) except SettingsError, e: app.print_error(e, 2) # Remove progress state. if hostname in self.installed: del(self.installed[hostname]) def _install_syco_on_remote_host(self, ssh): ''' Rsync syco to remote server, and install it ''' app.print_verbose("Install syco on remote host") ssh.rsync(app.SYCO_PATH, app.SYCO_PATH, "--exclude version.cfg") ssh.ssh_exec(app.SYCO_PATH + "bin/syco.py install-syco") def _execute_commands(self, obj, hostname):
class Commands: ''' Control which command line commands that can be executed. ''' class CommandList: ''' Stores added commands for a specific type [public|private} ''' name_list = {} func_list = {} arguments_list = {} help_list = {} def __init__(self): self.name_list = {} self.func_list = {} self.arguments_list = {} self.help_list = {} # Lists of all public and private commands commands = {"public":CommandList(), "private":CommandList} # The command type add() will add to. current_type = "public" # The maximum char length of name + argument name_length = 0 def add(self, name, func, arguments="", help=""): ''' Add a command that are able to be executed from the syco command line. This is a callback function used by the modules. ''' self.commands[self.current_type].name_list[name] = name.lower() self.commands[self.current_type].func_list[name] = func self.commands[self.current_type].arguments_list[name] = arguments.strip("[]") if (self.commands[self.current_type].arguments_list[name]): self.commands[self.current_type].arguments_list[name] = "{" + self.commands[self.current_type].arguments_list[name] + "}" self.commands[self.current_type].help_list[name] = help.rstrip(".") + "." self.name_length = max(self.name_length, len(name)) def execute(self, args): ''' Execute a command in a module. ''' command = args[0].lower(); if command in self.commands["public"].name_list: self.commands["public"].func_list[command](args) elif command in self.commands["private"].name_list: self.commands["private"].func_list[command](args) else: app.parser.error('Unknown command %s' % command) def get_help(self): ''' Get the full help text for all commands. ''' help = "" help += "Public commands\n" help += self._get_help_for_command_type("public") help += "\nUser commands:\n" help += self._get_help_for_command_type("private") return help def _get_help_for_command_type(self, type): ''' Build help string for one command type (public or private) ''' help = "" name_list = sorted(self.commands[type].name_list) for name in name_list: help += self.commands[type].name_list[name].ljust(self.name_length) + " - " help += self.commands[type].help_list[name] + " " + self.commands[type].arguments_list[name] + "\n" return help def __init__(self): ''' Read command directories (public and private) and add commands. ''' try: self.current_type = "public" for obj in self._get_modules(app.SYCO_PUBLIC_PATH): obj.build_commands(self) self.current_type = "private" if (os.access(app.SYCO_USR_PATH, os.F_OK)): for plugin in os.listdir(app.SYCO_USR_PATH): plugin_path = os.path.abspath(app.SYCO_USR_PATH + "/" + plugin + "/bin/") for obj in self._get_modules(plugin_path): obj.build_commands(self) except AttributeError, e: app.print_error(" Problem with obj, error:: " + repr(e.args)) except NameError, e: app.print_error(" Problem with " + repr(obj) + ", error: " + repr(e.args))
def _ssh_exec(self, command, events=None, silent=False): if not silent: app.print_verbose("SSH Command on " + self.server + ": " + command) # Setting default events if events is None: events = {} events["Verify the SYCO master password:"******"\n" keys = events.keys() value = events.values() # Timeout for ssh.expect timeout_event = len(keys) keys.append(pexpect.TIMEOUT) # The ssh session was terminated before the command had finished it's # execution. keys.append("Connection to .* closed by remote host") terminate_event = len(keys) keys.append("Terminated") # When the ssh command are executed, and back to the command prompt. pexpect_event = len(keys) keys.append("\[PEXPECT\]?") # When ssh.expect reaches the end of file. Probably never # does, is probably reaching [PEXPECT]# first. keys.append(pexpect.EOF) # Disable verbose output for SSH login process. # This outputs a lot of ugly useless text. ssh = expect.sshspawn(timeout=120) ssh.disable_output() ssh.login(self.server, username=self.user, password=self.password) ssh.enable_output() app.print_verbose("---- SSH Result - Start ----", 2) ssh.sendline(command) # First output from ssh.expect doesn't print the caption text before # the output commes. This is for the executed command. app.print_verbose("", 2, new_line=False, enable_caption=True) index = 0 while (index <= terminate_event): # Check for strings in keys in the output from the SSH command, # also uses print_verbose on all output from the result. index = ssh.expect(keys, timeout=3600) if 0 <= index and index < timeout_event: ssh.sendline(value[index]) elif index == timeout_event: app.print_error( "Caught a timeout from ssh.expect, lets try again.") elif timeout_event < index and index <= terminate_event: raise SSHTerminatedException() # Print new line when finding the PEXPECT prompt. if (app.options.verbose >= 2): if index == pexpect_event: print "" # An extra line break for the looks. if (app.options.verbose >= 2): app.print_verbose("---- SSH Result - End-------\n", 2) # Disable verbose output for SSH logout process. # This because our CENTOS installation outputs a lot of newlines # and a "clear screen" command, that makes the output look ugly. ssh.disable_output() ssh.logout() ssh.enable_output()
def install_kvmhost(args): """ The actual installation of the kvm host. """ app.print_verbose("Install kvm host version: %d" % SCRIPT_VERSION) version_obj = version.Version("InstallKvmHost", SCRIPT_VERSION) version_obj.check_executed() if not general.grep("/proc/cpuinfo", "vmx|svm"): app.print_error("CPU don't support virtualization.") _abort_kvm_host_installation() if not general.grep("/proc/cpuinfo", "constant_tsc"): app.print_error("CPU don't have a constant Time Stamp Counter.") _abort_kvm_host_installation() # Install the kvm packages install.package("qemu-kvm") install.package("libvirt") install.package("libguestfs-tools") install.package("avahi") # Provides the virt-install command for creating virtual machines. install.package("python-virtinst") # Before libvirtd starts, create a snapshot partion for qemu. _create_kvm_snapshot_partition() # Start services libvirtd depends on. x("service messagebus restart") x("service avahi-daemon start") x("chkconfig avahi-daemon on") # Start virsh x("service libvirtd start") _enable_ksm() # Looks like we need to wait for the libvirtd to start, otherwise # the virsh nodeinfo below doesn't work. time.sleep(1) # Set selinux x("setenforce 1") # Is virsh started? result = x("virsh nodeinfo") if "CPU model:" not in result: app.print_error("virsh not installed.") _abort_kvm_host_installation() result = x("virsh -c qemu:///system list") if "Id" not in result and "Name" not in result: app.print_error("virsh not installed.") _abort_kvm_host_installation() _remove_kvm_virt_networking() iptables.add_kvm_chain() iptables.save() version_obj.mark_executed() # Set selinux x("reboot") # Wait for the reboot to be executed, so the script # doesn't proceed to next command in install.cfg time.sleep(1000)
self.current_type = "public" for obj in self._get_modules(app.SYCO_PUBLIC_PATH): try: obj.build_commands(self) except AttributeError, e: app.print_error(" Problem with obj, error:: " + repr(e.args)) except NameError, e: app.print_error(" Problem with " + repr(obj) + ", error: " + repr(e.args)) self.current_type = "private" for plugin_path in app.get_syco_plugin_paths("/bin/"): for obj in self._get_modules(plugin_path): try: obj.build_commands(self) except AttributeError, e: app.print_error(" Problem with obj, error:: " + repr(e.args)) except NameError, e: app.print_error(" Problem with " + repr(obj) + ", error: " + repr(e.args)) def _get_modules(self, commands_path): """ Return a list of objects representing all available syco modules in specified folder. """ modules = [] if os.path.isdir(commands_path): for module in os.listdir(commands_path): if (module == '__init__.py' or module[-4:] == '.pyc' or module[-3:] == '.sh' or module[-3:] == 'led'):
def _setup_network_interfaces(): """ Setup bonded network interfaces and bridges. Read more. http://serverfault.com/questions/316623/what-is-the-correct-way-to-setup-a-bonded-bridge-on-centos-6-for-kvm-guests http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge http://www.cyberciti.biz/faq/rhel-linux-kvm-virtualization-bridged-networking-with-libvirt/ http://www.linux-kvm.org/page/HOWTO_BONDING https://fedorahosted.org/cobbler/wiki/VirtNetworkingSetupForUseWithKoan http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Virtualization/sect-Virtualization-Network_Configuration-Bridged_networking_with_libvirt.html http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/s1-networkscripts-interfaces.html http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/sec-Using_Channel_Bonding.html """ # Remove the virbr0, "NAT-interface". # http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Virtualization/chap-Virtualization-Network_Configuration.html x("virsh net-destroy default") x("virsh net-undefine default") x("service libvirtd restart") # Install network bridge install.package("bridge-utils") general.set_config_property2("/etc/modprobe.d/syco.conf", "alias bond0 bonding") num_of_if = net.num_of_eth_interfaces() front_gw = config.general.get_front_gateway_ip() front_resolver = config.general.get_front_resolver_ip() front_netmask = config.general.get_front_netmask() front_ip = config.host(net.get_hostname()).get_front_ip() back_gw = config.general.get_back_gateway_ip() back_resolver = config.general.get_back_resolver_ip() back_netmask = config.general.get_back_netmask() back_ip = config.host(net.get_hostname()).get_back_ip() if (num_of_if >= 4): # Setup back-net _setup_bridge("br0", back_ip, back_netmask, back_gw, back_resolver) _setup_bond("bond0", "br0") _setup_eth("eth0", "bond0") _setup_eth("eth1", "bond0") # _setup front-net _setup_bridge("br1", front_ip, front_netmask, front_gw, front_resolver) _setup_bond("bond1", "br1") _setup_eth("eth2", "bond1") _setup_eth("eth3", "bond1") elif (num_of_if == 2): # Setup back-net _setup_bridge("br0", back_ip, back_netmask, back_gw, back_resolver) _setup_bond("bond0", "br0") _setup_eth("eth0", "bond0") # _setup front-net _setup_bridge("br1", front_ip, front_netmask, front_gw, front_resolver) _setup_bond("bond1", "br1") _setup_eth("eth1", "bond1") else: app.print_error("To few network interfaces: " + str(num_of_if)) _abort_kvm_host_installation()
def install_kvmhost(args): ''' The actual installation of the kvm host. ''' app.print_verbose("Install kvm host version: %d" % SCRIPT_VERSION) version_obj = version.Version("InstallKvmHost", SCRIPT_VERSION) version_obj.check_executed() if (not general.grep("/proc/cpuinfo", "vmx|svm")): app.print_error("CPU doesn't support virtualization.") _abort_kvm_host_installation() if (not general.grep("/proc/cpuinfo", "constant_tsc")): app.print_error("CPU doesn't have a constant Time Stamp Counter.") _abort_kvm_host_installation() # Install the kvm packages install.package("qemu-kvm") install.package("libvirt") install.package("libguestfs-tools") install.package("avahi") # Provides the virt-install command for creating virtual machines. install.package("python-virtinst") # Before libvirtd starts, create a snapshot partion for qemu. _create_kvm_snapshot_partition() # Start services libvirtd depends on. x("service messagebus restart") x("service avahi-daemon start") x("chkconfig avahi-daemon on") # Start virsh x("service libvirtd start") _enable_ksm() # Looks like we need to wait for the libvirtd to start, otherwise # the virsh nodeinfo below doesn't work. time.sleep(1) # Set selinux x("setenforce 1") # Is virsh started? result = x("virsh nodeinfo") if "CPU model:" not in result: app.print_error("virsh not installed.") _abort_kvm_host_installation() result = x("virsh -c qemu:///system list") if "Id" not in result and "Name" not in result: app.print_error("virsh not installed.") _abort_kvm_host_installation() _remove_kvm_virt_networking() iptables.add_kvm_chain() iptables.save() _libvirt_init_config() version_obj.mark_executed() # Set selinux x("reboot") # Wait for the reboot to be executed, so the script # doesn't proceed to next command in install.cfg time.sleep(1000)
def net_setup_bond_br(args): """ Setup bonded network interfaces and bridges. This must work together with a virtual host using KVM. Read more. http://serverfault.com/questions/316623/what-is-the-correct-way-to-setup-a-bonded-bridge-on-centos-6-for-kvm-guests http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge http://www.cyberciti.biz/faq/rhel-linux-kvm-virtualization-bridged-networking-with-libvirt/ http://www.linux-kvm.org/page/HOWTO_BONDING https://fedorahosted.org/cobbler/wiki/VirtNetworkingSetupForUseWithKoan http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Virtualization/sect-Virtualization-Network_Configuration-Bridged_networking_with_libvirt.html http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/s1-networkscripts-interfaces.html http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/sec-Using_Channel_Bonding.html """ app.print_verbose("Install bonded bridges host version: %d" % SCRIPT_VERSION) version_obj = version.Version("NetSetupBondBr", SCRIPT_VERSION) version_obj.check_executed() # app.print_verbose( "Install yum package with all tools that is required to setup bridges." ) install.package("bridge-utils") # print_verbose( "Setup modprobe alias for bonding, don't know exactly why we need to " + "do that. Maybe because the ifcfg files referars to bond0 instead of " + "bonding, or because it loads the module bonding at the same time as " + "the alias is created." ) sycoConf = scOpen("/etc/modprobe.d/syco.conf") sycoConf.remove("alias bond.*") sycoConf.add("alias bond0 bonding") # Get all parameters from syco config. num_of_if = net.num_of_eth_interfaces() front_ip = config.host(net.get_hostname()).get_front_ip() front_netmask = config.general.get_front_netmask() front_gw = config.general.get_front_gateway_ip() front_resolver = config.general.get_front_resolver_ip() back_ip = config.host(net.get_hostname()).get_back_ip() back_netmask = config.general.get_back_netmask() back_gw = config.general.get_back_gateway_ip() back_resolver = config.general.get_back_resolver_ip() if (num_of_if >= 4): app.print_verbose( "{0} network interfaces was found, and 2 eth interfaces per bond " + "will be configured." ) # Setup back-net setup_bridge("br0", back_ip, back_netmask, back_gw, back_resolver) setup_bond("bond0", "br0") setup_eth("eth0", "bond0") setup_eth("eth1", "bond0") # _setup front-net setup_bridge("br1", front_ip, front_netmask, front_gw, front_resolver) setup_bond("bond1", "br1") setup_eth("eth2", "bond1") setup_eth("eth3", "bond1") elif (num_of_if == 2): app.print_verbose( "2 network interfaces was found, and 1 eth interfaces per bond " + "will be configured. There is no point in bonding in this case, " + "except that we have the same kind of configuration on all hosts. " ) # Setup back-net setup_bridge("br0", back_ip, back_netmask, back_gw, back_resolver) setup_bond("bond0", "br0") setup_eth("eth0", "bond0") # _setup front-net setup_bridge("br1", front_ip, front_netmask, front_gw, front_resolver) setup_bond("bond1", "br1") setup_eth("eth1", "bond1") else: app.print_error("To few network interfaces: " + str(num_of_if)) raise Exception("To few network interfaces: " + str(num_of_if)) # app.print_verbose( "Restart the network service so all changes will be applied." ) x("service network restart") # version_obj.mark_executed()
for obj in self._get_modules(app.SYCO_PUBLIC_PATH): try: obj.build_commands(self) except AttributeError, e: app.print_error(" Problem with obj, error:: " + repr(e.args)) except NameError, e: app.print_error(" Problem with " + repr(obj) + ", error: " + repr(e.args)) self.current_type = "private" for plugin_path in app.get_syco_plugin_paths("/bin/"): for obj in self._get_modules(plugin_path): try: obj.build_commands(self) except AttributeError, e: app.print_error(" Problem with obj, error:: " + repr(e.args)) except NameError, e: app.print_error(" Problem with " + repr(obj) + ", error: " + repr(e.args)) def _get_modules(self, commands_path): """ Return a list of objects representing all available syco modules in specified folder. """ modules = [] if os.path.isdir(commands_path): for module in os.listdir(commands_path): if (module == '__init__.py' or module[-4:] == '.pyc' or module[-3:] == '.sh' or module[-3:] == 'led'): continue
def _ssh_exec(self, command, events=None, silent=False): if not silent: app.print_verbose("SSH Command on " + self.server + ": " + command) # Setting default events if events is None: events = {} events["Verify the SYCO master password:"******"\n" keys = events.keys() value = events.values() # Timeout for ssh.expect timeout_event = len(keys) keys.append(pexpect.TIMEOUT) # The ssh session was terminated before the command had finished it's # execution. keys.append("Connection to .* closed by remote host") terminate_event = len(keys) keys.append("Terminated") # When the ssh command are executed, and back to the command prompt. pexpect_event = len(keys) keys.append("\[PEXPECT\]?") # When ssh.expect reaches the end of file. Probably never # does, is probably reaching [PEXPECT]# first. keys.append(pexpect.EOF) # Disable verbose output for SSH login process. # This outputs a lot of ugly useless text. ssh = expect.sshspawn(timeout=120) ssh.disable_output() ssh.login(self.server, username=self.user, password=self.password) ssh.enable_output() app.print_verbose("---- SSH Result - Start ----", 2) ssh.sendline(command) # First output from ssh.expect doesn't print the caption text before # the output commes. This is for the executed command. app.print_verbose("", 2, new_line=False, enable_caption=True) index=0 while (index <= terminate_event): # Check for strings in keys in the output from the SSH command, # also uses print_verbose on all output from the result. index = ssh.expect(keys, timeout=3600) if 0 <= index and index < timeout_event: ssh.sendline(value[index]) elif index == timeout_event: app.print_error("Caught a timeout from ssh.expect, lets try again.") elif timeout_event < index and index <= terminate_event: raise SSHTerminatedException() # Print new line when finding the PEXPECT prompt. if (app.options.verbose >= 2): if index == pexpect_event: print "" # An extra line break for the looks. if (app.options.verbose >= 2): app.print_verbose("---- SSH Result - End-------\n", 2) # Disable verbose output for SSH logout process. # This because our CENTOS installation outputs a lot of newlines # and a "clear screen" command, that makes the output look ugly. ssh.disable_output() ssh.logout() ssh.enable_output()
def shell_exec(command, user="", cwd=None, events=None, output=True): ''' Execute a shell command using pexpect, and writing verbose affected output. ''' # Build command to execute args=[] if (user): args.append(user) args.append('-c ' + command) if (output): app.print_verbose(BOLD +"Command: su " + RESET + user + " -c '" + command + "'") # Setting default events if events is None: events = {} events["Verify the SYCO master password:"******"su", args, cwd=cwd) if (not output): out.disable_output() if (output): app.print_verbose("---- Result ----", 2) stdout = "" index = 0 while (index < num_of_events+1): index = out.expect(keys, timeout=3600) stdout += out.before if index >= 0 and index < num_of_events: if (inspect.isfunction(value[index])): out.send(str(value[index]()) + "\n") else: out.send(value[index]) elif index == num_of_events: app.print_error("Catched a timeout from pexpect.expect, lets try again.") if (out.exitstatus and output): app.print_error("Invalid exitstatus %d" % out.exitstatus) if (out.signalstatus and output): app.print_error("Invalid signalstatus %d - %s" % out.signalstatus, out.status) # An extra line break for the looks. if (output and stdout and app.options.verbose >= 2): print("\n"), out.close() return stdout