Пример #1
0
 def setup_term(self, system, my_term, ssh_obj=None, block=0):
     # Login and/or setup any terminal
     # my_term needs to be the opexpect object
     # This will behave correctly even if already logged in
     # Petitboot Menu is special case to NOT participate in this setup, conditionally checks if system state is PETITBOOT and skips
     # CANNOT CALL GET_CONSOLE OR CONNECT from here since get_console and connect call into setup_term
     if block == 1:
       return
     if ssh_obj is not None:
       track_obj = ssh_obj
       term_obj = ssh_obj
       system_obj = ssh_obj.system
     else:
       track_obj = system
       term_obj = system.console
       system_obj = system
     my_term.sendline()
     rc = my_term.expect(['login: $', ".*#$", ".*# $", ".*\$", 'Petitboot', pexpect.TIMEOUT, pexpect.EOF], timeout=10)
     if rc == 0:
       track_obj.PS1_set, track_obj.LOGIN_set = self.get_login(system_obj.cv_HOST, term_obj, my_term, self.build_prompt(system_obj.prompt))
       track_obj.PS1_set, track_obj.SUDO_set = self.get_sudo(system_obj.cv_HOST, term_obj, my_term, self.build_prompt(system_obj.prompt))
       return
     if rc in [1,2,3]:
       track_obj.PS1_set = self.set_PS1(term_obj, my_term, self.build_prompt(system_obj.prompt))
       track_obj.LOGIN_set = 1 # ssh port 22 can get in which uses sshpass or Petitboot, do this after set_PS1 to make sure we have something
       track_obj.PS1_set, track_obj.SUDO_set = self.get_sudo(system_obj.cv_HOST, term_obj, my_term, self.build_prompt(system_obj.prompt))
       return
     if rc == 4:
       return # Petitboot so nothing to do
     if rc == 6: # EOF
       term_obj.close() # mark as bad
       raise ConsoleSettings(before=my_term.before, after=my_term.after,
               msg="Getting login and sudo not successful, probably connection or credential issue, retry")
     # now just timeout
     my_term.sendline()
     rc = my_term.expect(['login: $', ".*#$", ".*# $", ".*\$", 'Petitboot', pexpect.TIMEOUT, pexpect.EOF], timeout=10)
     if rc == 0:
       track_obj.PS1_set, track_obj.LOGIN_set = self.get_login(system_obj.cv_HOST, term_obj, my_term, self.build_prompt(system_obj.prompt))
       track_obj.PS1_set, track_obj.SUDO_set = self.get_sudo(system_obj.cv_HOST, term_obj, my_term, self.build_prompt(system_obj.prompt))
       return
     if rc in [1,2,3]:
       track_obj.LOGIN_set = track_obj.PS1_set = self.set_PS1(term_obj, my_term, self.build_prompt(system_obj.prompt))
       track_obj.PS1_set, track_obj.SUDO_set = self.get_sudo(system_obj.cv_HOST, term_obj, my_term, self.build_prompt(system_obj.prompt))
       return
     if rc == 4:
       return # Petitboot do nothing
     else:
       if term_obj.setup_term_quiet == 0:
         term_obj.close() # mark as bad
         raise ConsoleSettings(before=my_term.before, after=my_term.after,
                 msg="Getting login and sudo not successful, probably connection issue, retry")
       else:
         # this case happens when detect_target sets the quiet flag and we are timing out
         print "OpTestSystem detected something, checking if your system is powered off, will retry"
Пример #2
0
    def retry_password(self, term_obj, my_term, command):
        retry_list_output = []
        a = 0
        while a < 3:
          a += 1
          my_term.sendline(term_obj.system.cv_HOST.password())
          rc = my_term.expect([".*#", "try again.", pexpect.TIMEOUT, pexpect.EOF])
          if (rc == 0) or (rc == 1):
            combo_io = my_term.before + my_term.after
            retry_list_output += combo_io.splitlines()
            matching = [xs for xs in sudo_responses if any(xs in xa for xa in my_term.after.splitlines())]
            if len(matching):
              echo_rc = 1
              rc = -1 # use to flag the failure next
          if rc == 0:
            retry_list_output += self.set_env(term_obj, my_term)
            echo_rc = 0
            break
          elif a == 2:
            echo_rc = 1
            break
          elif (rc == 2):
            raise CommandFailed(command, 'Retry Password TIMEOUT ' + ''.join(retry_list_output), -1)
          elif (rc == 3):
            term_obj.close()
            raise ConsoleSettings(before=my_term.before, after=my_term.after,
                    msg='SSH session/console issue, probably connection issue, retry')

        return retry_list_output, echo_rc
Пример #3
0
 def get_sudo(self, host, term_obj, my_term, prompt):
     # prompt comes in as the string desired, needs to be pre-built
     # must have PS1 expect_prompt already set
     # must be already logged in
     if term_obj.setup_term_disable == 1:
       return -1, -1
     my_term.sendline()
     expect_prompt = prompt + "$"
     my_user = host.username()
     my_pwd = host.password()
     my_term.sendline("which sudo && sudo -s")
     rc = my_term.expect([r"[Pp]assword for", "#", pexpect.TIMEOUT, pexpect.EOF], timeout=10)
     if rc == 0:
       my_term.sendline(my_pwd)
       time.sleep(0.5) # delays for next call
       my_PS1_set = self.set_PS1(term_obj, my_term, prompt)
       self.check_root(my_term, prompt)
       my_SUDO_set = 1
       return my_PS1_set, my_SUDO_set # caller needs to save state
     elif rc in [1,2]: # we must have been root, we first filter out password prompt above
       my_PS1_set = self.set_PS1(term_obj, my_term, prompt)
       self.check_root(my_term, prompt)
       my_SUDO_set = 1
       return my_PS1_set, my_SUDO_set # caller needs to save state
     else:
       if term_obj.setup_term_quiet == 0:
         print ("OpTestSystem Unable to setup root access, probably a connection issue,"
                 " raised Exception ConsoleSettings but continuing")
         raise ConsoleSettings(before=my_term.before, after=my_term.after,
                 msg='Unable to setup root access, probably a connection issue, retry')
       else:
         term_obj.setup_term_disable = 1
         return -1, -1
Пример #4
0
 def check_root(self, my_term, prompt):
     # we do the best we can to verify, but if not oh well
     expect_prompt = prompt + "$"
     my_term.sendline("date") # buffer kicker needed
     my_term.sendline("which whoami && whoami")
     time.sleep(1)
     rc = my_term.expect([expect_prompt, pexpect.TIMEOUT, pexpect.EOF], timeout=10)
     if rc == 0:
       try:
         whoami = my_term.before.splitlines()[-1]
       except Exception as e:
         pass
       my_term.sendline("echo $?")
       time.sleep(1)
       rc = my_term.expect([expect_prompt, pexpect.TIMEOUT, pexpect.EOF], timeout=10)
       if rc == 0:
         try:
           echo_rc = int(my_term.before.splitlines()[-1])
         except Exception as e:
           echo_rc = -1
         if echo_rc == 0:
           if whoami in "root":
             print "OpTestSystem now running as root"
           else:
             raise ConsoleSettings(before=my_term.before, after=my_term.after,
                     msg="Unable to confirm root access setting up terminal, check that you provided"
                     " root credentials or a properly enabled sudo user, retry")
         else:
             print "OpTestSystem should be running as root, unable to verify"
Пример #5
0
 def set_env(self, term_obj, my_term):
     set_env_list = []
     my_term.sendline("which bash && exec bash --norc --noprofile")
     expect_prompt = self.build_prompt(term_obj.prompt) + "$"
     my_term.sendline('PS1=' + self.build_prompt(term_obj.prompt))
     rc = my_term.expect([expect_prompt, pexpect.TIMEOUT, pexpect.EOF], timeout=10)
     if rc == 0:
       combo_io = (my_term.before + my_term.after).lstrip()
       set_env_list += combo_io.splitlines()
       # remove the expect prompt since matched generic #
       del set_env_list[-1]
       return set_env_list
     else:
       raise ConsoleSettings(before=my_term.before, after=my_term.after,
               msg="Setting environment for sudo command not successful, probably connection issue, retry")
Пример #6
0
 def get_sudo(self, host, term_obj, my_term, prompt):
     # prompt comes in as the string desired, needs to be pre-built
     # must have PS1 expect_prompt already set
     # must be already logged in
     if term_obj.setup_term_disable == 1:
         return -1, -1
     my_term.sendline()
     expect_prompt = prompt + "$"
     my_user = host.username()
     my_pwd = host.password()
     my_term.sendline("which sudo && sudo -s")
     rc = my_term.expect([r"[Pp]assword for", pexpect.TIMEOUT, pexpect.EOF],
                         timeout=5)
     # we must not add # prompt to the expect, we get false hit when complicated user login prompt and control chars,
     # we need to cleanly ignore everything but password and then we blindly next do PS1 setup, ignoring who knows what
     if rc == 0:
         my_term.sendline(my_pwd)
         time.sleep(0.5)  # delays for next call
         my_PS1_set = self.set_PS1(term_obj, my_term, prompt)
         self.check_root(my_term, prompt)
         my_SUDO_set = 1
         return my_PS1_set, my_SUDO_set  # caller needs to save state
     elif rc == 1:  # we must have been root, we first filter out password prompt above
         my_PS1_set = self.set_PS1(term_obj, my_term, prompt)
         self.check_root(my_term, prompt)
         my_SUDO_set = 1
         return my_PS1_set, my_SUDO_set  # caller needs to save state
     else:
         if term_obj.setup_term_quiet == 0:
             log.warning(
                 "OpTestSystem Unable to setup root access, probably a connection issue,"
                 " raised Exception ConsoleSettings but continuing")
             raise ConsoleSettings(
                 before=my_term.before,
                 after=my_term.after,
                 msg=
                 'Unable to setup root access, probably a connection issue, retry'
             )
         else:
             term_obj.setup_term_disable = 1
             return -1, -1
Пример #7
0
 def get_login(self, host, term_obj, my_term, prompt):
     # prompt comes in as the string desired, needs to be pre-built
     if term_obj.setup_term_disable == 1:
         return -1, -1
     my_user = host.username()
     my_pwd = host.password()
     my_term.sendline()
     rc = my_term.expect(['login: '******'login: $', ".*#$", ".*# $", ".*\$", 'Petitboot',
                 pexpect.TIMEOUT, pexpect.EOF
             ],
                                 timeout=10)
             if rc not in [1, 2, 3]:
                 if term_obj.setup_term_quiet == 0:
                     log.warning(
                         "OpTestSystem Problem with the login and/or password prompt,"
                         " raised Exception ConsoleSettings but continuing")
                     raise ConsoleSettings(
                         before=my_term.before,
                         after=my_term.after,
                         msg=
                         "Problem with the login and/or password prompt, probably a connection or credential issue, retry"
                     )
                 else:
                     term_obj.setup_term_disable = 1
                     return -1, -1
         else:
             if term_obj.setup_term_quiet == 0:
                 log.warning(
                     "OpTestSystem Problem with the login and/or password prompt, raised Exception ConsoleSettings but continuing"
                 )
                 raise ConsoleSettings(
                     before=my_term.before,
                     after=my_term.after,
                     msg=
                     "Problem with the login and/or password prompt, probably a connection or credential issue, retry"
                 )
             else:
                 term_obj.setup_term_disable = 1
                 return -1, -1
         my_PS1_set = self.set_PS1(term_obj, my_term, prompt)
         my_LOGIN_set = 1
     else:  # timeout eof
         my_term.sendline()
         rc = my_term.expect(['login: '******'login: $', ".*#$", ".*# $", ".*\$", 'Petitboot',
                     pexpect.TIMEOUT, pexpect.EOF
                 ],
                                     timeout=10)
                 if rc not in [1, 2, 3]:
                     if term_obj.setup_term_quiet == 0:
                         log.warning(
                             "OpTestSystem Problem with the login and/or password prompt,"
                             " raised Exception ConsoleSettings but continuing"
                         )
                         raise ConsoleSettings(
                             before=my_term.before,
                             after=my_term.after,
                             msg=
                             "Problem with the login and/or password prompt, probably a connection or credential issue, retry"
                         )
                     else:
                         term_obj.setup_term_disable = 1
                         return -1, -1
             else:
                 if term_obj.setup_term_quiet == 0:
                     log.warning(
                         "OpTestSystem Problem with the login and/or password prompt after a secondary connection issue,"
                         " raised Exception ConsoleSettings but continuing")
                     raise ConsoleSettings(
                         before=my_term.before,
                         after=my_term.after,
                         msg=
                         "Problem with the login and/or password prompt after a secondary connection or credential issue, retry"
                     )
                 else:
                     term_obj.setup_term_disable = 1
                     return -1, -1
             my_PS1_set = self.set_PS1(term_obj, my_term, prompt)
             my_LOGIN_set = 1
         else:  # timeout eof
             if term_obj.setup_term_quiet == 0:
                 log.warning(
                     "OpTestSystem Problem with the login and/or password prompt after a previous connection issue,"
                     " raised Exception ConsoleSettings but continuing")
                 raise ConsoleSettings(
                     before=my_term.before,
                     after=my_term.after,
                     msg=
                     "Problem with the login and/or password prompt last try, probably a connection or credential issue, retry"
                 )
             else:
                 term_obj.setup_term_disable = 1
                 return -1, -1
     return my_PS1_set, my_LOGIN_set  # caller needs to save state
Пример #8
0
 def set_PS1(self, term_obj, my_term, prompt):
     # prompt comes in as the string desired, needs to be pre-built
     # on success caller is returned 1, otherwise exception thrown
     # order of execution and commands are sensitive here to provide reliability
     if term_obj.setup_term_disable == 1:
         return -1
     expect_prompt = prompt + "$"
     my_term.sendline("which bash && exec bash --norc --noprofile")
     time.sleep(0.2)
     my_term.sendline('PS1=' + prompt)
     time.sleep(0.2)
     my_term.sendline(
         "which stty && stty cols 300;which stty && stty rows 30")
     time.sleep(0.2)
     my_term.sendline("export LANG=C")
     time.sleep(0.2)
     my_term.sendline()  # needed to sync buffers later on
     time.sleep(
         0.2
     )  # pause for first time setup, buffers you know, more sensitive in petitboot shell, pexpect or console buffer not sure
     rc = my_term.expect([expect_prompt, pexpect.TIMEOUT, pexpect.EOF],
                         timeout=10)
     if rc == 0:
         log.debug("Shell prompt changed")
         return 1  # caller needs to save state
     else:  # we don't seem to have anything so try to get something
         term_obj.close()
         try:
             # special case to allow calls back to connect which is where we probably came from
             self.orig_system_setup_term = term_obj.get_system_setup_term()
             self.orig_block_setup_term = term_obj.get_block_setup_term()
             term_obj.set_system_setup_term(
                 1
             )  # block so the new connect will not try to come back here
             term_obj.set_block_setup_term(
                 1
             )  # block so the new connect will not try to come back here
             self.try_recover(
                 term_obj, counter=3
             )  # if try_recover bails we leave things blocked, they'll get reset
             # if we get back here we have a new prompt and unknown console
             # in future if state can change or block flags can change this needs revisted
             my_term = term_obj.connect(
             )  # need a new my_term since we recovered
             term_obj.set_system_setup_term = self.orig_system_setup_term
             term_obj.set_block_setup_term = self.orig_block_setup_term
             my_term.sendline("which bash && exec bash --norc --noprofile")
             time.sleep(0.2)
             my_term.sendline('PS1=' + prompt)
             time.sleep(0.2)
             my_term.sendline(
                 "which stty && stty cols 300;which stty && stty rows 30")
             time.sleep(0.2)
             my_term.sendline("export LANG=C")
             time.sleep(0.2)
             my_term.sendline()  # needed to sync buffers later on
             time.sleep(
                 0.2
             )  # pause for first time setup, buffers you know, more sensitive in petitboot shell, pexpect or console buffer not sure
             rc = my_term.expect(
                 [expect_prompt, pexpect.TIMEOUT, pexpect.EOF], timeout=10)
             if rc == 0:
                 log.debug("Shell prompt changed")
                 return 1  # caller needs to save state
             else:
                 if term_obj.setup_term_quiet == 0:
                     log.warning(
                         "OpTestSystem Change of shell prompt not completed after last final retry,"
                         " probably a connection issue, raised Exception ConsoleSettings but continuing"
                     )
                     raise ConsoleSettings(
                         before=my_term.before,
                         after=my_term.after,
                         msg=
                         "Change of shell prompt not completed after last final retry, probably a connection issue, retry"
                     )
                 else:
                     term_obj.setup_term_disable = 1
                     return -1
         except RecoverFailed as e:
             if term_obj.setup_term_quiet == 0:
                 log.warning(
                     "OpTestSystem Change of shell prompt not completed after last retry,"
                     " probably a connection issue, raised Exception ConsoleSettings but continuing"
                 )
                 raise ConsoleSettings(
                     before=my_term.before,
                     after=my_term.after,
                     msg=
                     "Change of shell prompt not completed after last retry, probably a connection issue, retry"
                 )
             else:
                 term_obj.setup_term_disable = 1
                 return -1