Beispiel #1
0
 def login(self):
     logger = logging.getLogger("protocols")
     try:
         match = self.terminal.expect([
             'The authenticity of host .* can\'t be established',
             '[Pp]assword:', self.prompt
         ])
     except pexpect.TIMEOUT:
         raise exceptions.NetworkException(
             "Time-out (>%d sec) while connecting to host ('ssh %s@%s')" %
             (self.timeout, self.username, self.hostname))
     if match == 0:  # 'The authenticity of host .* can\'t be established'
         try:
             self.terminal.expect(
                 'Are you sure you want to continue connecting')
             self.terminal.sendline('yes')
         except pexpect.TIMEOUT, pexpect.EOF:
             raise exceptions.MalformedIO(
                 "Authenticity of host %s can't be established. Expected question, but got time-out"
                 % (self.hostname))
         try:
             match = 1 + self.terminal.expect(['[Pp]assword:', self.prompt])
         except pexpect.TIMEOUT, pexpect.EOF:
             raise exceptions.MalformedIO(
                 "Unexpected time-out (>%d sec) while waiting for prompt from %s"
                 % (self.timeout, self.hostname))
Beispiel #2
0
def ParseCLILines(lines,
                  skipStartLines=0,
                  lastSkipLineRe=None,
                  skipEndLines=0):
    """Delete first few and last few lines in an array"""
    if skipStartLines > 0:
        if lastSkipLineRe != None:
            # sanity check. Make sure last line to skip matches the given regexp
            if None == re.match(lastSkipLineRe, lines[(skipStartLines - 1)]):
                raise exceptions.MalformedIO(
                    "Expected '%s' at line %d of result, but found '%s'." %
                    (lastSkipLineRe, skipStartLines,
                     lines[(skipStartLines - 1)].strip()))
        if len(lines) < skipStartLines:
            raise exceptions.MalformedIO(
                "Can't skip first %d lines of result %s. It only contains %d lines."
                % (skipStartLines, repr(lines), len(lines)))
        del lines[0:skipStartLines]
    if skipEndLines > 0:
        if len(lines) < skipEndLines:
            raise exceptions.MalformedIO(
                "Can't skip last %d lines of result %s. It only contains %d lines."
                % (skipEndLines, repr(lines), len(lines)))
        del lines[-skipEndLines:]
    return lines
Beispiel #3
0
 def login(self):
     logger = logging.getLogger("protocols")
     try:
         match = self.terminal.expect(
             ['[Ll]ogin:', '[Pp]assword:', self.prompt])
     except pexpect.TIMEOUT:
         raise exceptions.NetworkException(
             "Time-out while connecting to host ('telnet %s %d')" %
             (self.hostname, self.port))
     if match == 0:  # Login prompt
         try:
             self.terminal.sendline(self.username)
             match = 1 + self.terminal.expect(['[Pp]assword:', self.prompt])
         except pexpect.TIMEOUT:
             raise exceptions.MalformedIO(
                 "Unexpected time-out while waiting for prompt from %s" %
                 (self.hostname))
     if match == 1:  # Password prompt
         try:
             self.terminal.sendline(self.password)
             match = 1 + self.terminal.expect(
                 ['Permission denied', self.prompt])
             if match == 1:  # permission denied
                 if self.password:
                     raise exceptions.NetworkException(
                         "Password failed when connecting to %s@%s" %
                         (self.username, self.hostname))
                 else:
                     raise exceptions.NetworkException(
                         "No password given for %s@%s. Unable to connect" %
                         (self.username, self.hostname))
         except pexpect.TIMEOUT, pexpect.EOF:
             raise exceptions.MalformedIO(
                 "Unexpected time-out (>%d sec) while authenticating to %s"
                 % (self.timeout, self.hostname))
Beispiel #4
0
 def readmessage(self, timeout):
     """Reads text from the terminal up to the next delimiter. Does return the string as-is, 
     without checking validity. The result MUST be an UTF-8 encoded string.
     Should raise an TimeOut in case more then timeout seconds have been passed."""
     logger = logging.getLogger("protocols")
     try:
         self.terminal.expect(self.delimiter, timeout=timeout)
         # Store the result in a variable
         resultString = self.terminal.before
     except pexpect.TIMEOUT:
         raise exceptions.MalformedIO(
             "No delimiter %s after in data %s from %s" %
             (repr(self.delimiter), self.terminal.before, self.hostname))
     instring = resultString + self.delimiter
     self.writetolog(instring.replace("\r\n", "\n"), output=True)
     logger.debug("Received %d bytes of data" % len(resultString))
     return resultString
Beispiel #5
0
 def sendcommand(self, string):
     self.writetolog(string, input=True)
     logger = logging.getLogger("protocols")
     logger.debug("Sending command %s" % (repr(string)))
     try:
         self.terminal.sendline(string)
         if self.hasecho:
             # if the command is 'command\n', the echo is 'command\r\n'
             expectstring = string.replace("\n", "\r\n")
             self.terminal.expect(expectstring, timeout=self.timeout)
             echostring = self.terminal.before + expectstring
             self.writetolog(echostring.replace("\r\n", "\n"), output=True)
     except pexpect.TIMEOUT:
         raise exceptions.MalformedIO(
             "No echo response %s in data %s from %s" %
             (repr(echostring), repr(self.terminal.before), self.hostname))
     self.lastcommand = string.strip()
Beispiel #6
0
 def makeCommand(self, command):
     """TL1 emulation: removes the ctag. The identifier is None"""
     if command[-1] == ";":
         command = command[:-1]
     command = command.split(":")
     try:
         command[3] = ""  # set ctag to empty
     except IndexError:
         raise exceptions.MalformedIO(
             "Invalid TL1 command given. The fourth (ctag) parameter MUST be present. E.g.: ACT-USER:::ctag;"
         )
     if self.ignorecase:
         command[0] = command[0].upper()
     if self.ignorecredentials and (command[0] in ["ACT-USER", "CANC-USER"
                                                   ]):
         # e.g. "act-user::username:ctag::password"
         # if len(command) > 2:
         #     command[2] = ""     # remove username
         if len(command) > 5:
             command[5] = ""  # remove password
     command = ":".join(command) + ";"
     return (None, command + "\n")
Beispiel #7
0
 def makeCommand(self, command):
     """Takes a command, and turns it into a string read to send to the device. 
     It may add a line break (I/O specific), or identifier in the command (language-specific).
     Returns a tuple (identifier, commandstring). The identifier is the ctag."""
     self.acquireMemLock()
     ctag = self.ctag
     self.ctag += 1
     self.releaseMemLock()
     if (len(command) > 0) and (command[-1] == ";"):
         command = command[:-1]
     command = command.split(":")
     if self.ignorecase:
         command[0] = command[0].upper()
     try:
         command[3] = str(ctag)  # set ctag to empty
         command = ":".join(command) + ";"
     except IndexError:
         raise exceptions.MalformedIO(
             "Invalid TL1 command given. The fourth (ctag) parameter MUST be present. E.g.: ACT-USER:::ctag;"
         )
         command = ":".join(command) + ";"
     return (str(ctag), command + "\n")
Beispiel #8
0
 def isAutonomousType(self, identifier, status):
     """Given the identifier and status, decide if the message is autonomous,
     and if so, if it is of a certain type. For regular (non-autonomous), return None."""
     responsetype = status[0]
     # (responsetype, status, comment) = status
     if responsetype == 'M':
         return False  # regular message
     elif (responsetype[0] == "A"):
         return "auto"
         # autonomous message or no alarm
     elif (responsetype == "*C"):
         return "critical"
         # critical alarm
     elif (responsetype == "**"):
         return "major"
         # major alarm
     elif (responsetype == "*^"):
         return "minor"
         # minor alarm
     else:
         raise exceptions.MalformedIO(
             "Received an unknown message type '%s' (only understand M, A and *) with identifier %s from %s"
             % (responsetype, identifier, self.getTarget()))
Beispiel #9
0
    def parseMessage(self, resultString):
        """Takes a message, and parses it into a tripley (resultlines, identifier, status)
        The resultline is an array of result line (e.g. 
        ['10.1a.3:NOP,NONE,NONE:INOPTDEGR=-15.00,INOPTCRIT=-18.0']), the identifier is the 
        ctag. The status is a 3-item list [type, status, comment] with type 'M' or 'A',
        status "DENY" or "COMPLD", and comment whatever string was found between /* and */.
        May raise a ParsingError in case the output can't be parsed, but does not 
        raise an exception if the status is unsuccessful."""
        logger = logging.getLogger("protocols")

        # The result should start with a header line (2,3,4), and result lines (5,6):
        #                                                           1
        #    BeautyCees 07-03-13 14:52:28                           2
        # M  123 COMPLD                         (normal response)   3
        # A  123 REPT DBCHG EVT SECU IDVN       (automatic message) 3
        # *C  123 REPT ALM CRS                  (critical alarm)    3
        # **  123 REPT ALM ENV DBCHG EVT SECU   (major alarm)       3
        # *^  123 REPT ALM                      (minor alarm)       3
        #     PLNA                              (error code)        4
        #    /* Here is a comment. */                               5
        #    "10.3a.1-10.3a.2:SRCPORT=10.3a.1,DSTPORT=10.3a.2"      6
        #    "10.2a.7-10.3a.5:SRCPORT=10.2a.7,DSTPORT=10.3a.5"      6
        # return lines formated as:
        #     "resultstring, possible with \"quotes\"" (line type 5)
        # note that the header lines (1,2,3) can be repeated in the list of resultsline (type 5)

        identifierRE = re.compile(
            r'^\s+(\w+) (\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$')
        statusRE = re.compile(r'^([MA\*][\*C\^]?)\s+(\S+)\s([\w ]+)$')
        moreStatusRE = re.compile(r'^\s+([\w ]+)$')
        commentRE = re.compile(r'^\s+/\*(.*)\*/')
        resultRE = re.compile(r'^\s+"{0,1}([^\n]*)[,"]$')

        resultLines = resultString.split('\r\n')

        commentlines = []
        resultlines = []
        responsetype = None
        status = None
        ctag = None
        skiplines = True  # only store result and comment lines after a valid status line

        # line types
        for line in resultLines:
            statusmatch = statusRE.match(line)
            morestatusmatch = moreStatusRE.match(line)
            identifiermatch = identifierRE.match(line)
            commentmatch = commentRE.match(line)
            resultmatch = resultRE.match(line)
            if statusmatch:
                if ctag == None:
                    responsetype = statusmatch.group(1)
                    ctag = statusmatch.group(2)
                    status = statusmatch.group(
                        3
                    )  # warning: may be more then one word! (e.g. "COMPLD" or "DENY" or "REPT ALM CRS")
                    skiplines = False
                elif ctag == statusmatch.group(2):
                    skiplines = False
                else:
                    logger.warning(
                        "Ignoring TL1 output with ctag %s, since the output of ctag %s is not finished (we can only handle output one-by-one)."
                        % (statusmatch.group(2), ctag))
                    skiplines = True
            elif morestatusmatch:
                status = status + " " + morestatusmatch.group(
                    1)  # warning: may be more then one word!
            elif resultmatch:
                match = resultmatch.group(1)
                if skiplines:
                    if ctag == None:
                        logger.error(
                            "Haven't receive a valid status line yet. Thus skip TL1 result line %s"
                            % repr(match))
                    else:
                        logger.warning("Skip TL1 result line %s" % repr(match))
                else:
                    resultlines.append(match)
            elif commentmatch:
                match = commentmatch.group(1)
                if skiplines:
                    logger.warning("Skip TL1 comment line %s" % repr(match))
                else:
                    commentlines.append(match.strip())
            elif identifiermatch:
                pass
            elif line == "":  # this instruction must come before the line[0] == ">" checks
                pass
            elif line[0] == ">":
                pass
            elif line[0] == "<":
                pass
            elif line == ";":
                skiplines = True  # termination line
            else:
                logger.error("Skip uknown TL1 line %s" % repr(line))
        if ctag == None:
            raise exceptions.MalformedIO(
                "Could not find valid response header (e.g. 'M  123 COMPLD') in response %s"
                % repr(resultString))
            # NOTE: we actually like to include the associated command that was send out, but we don't have that information.
            # However, experience showed that command is often unrelated to the alarm. So we leave it as it is.
        comment = " ".join(commentlines)  # paste them together
        # The comment line typically contains the error message
        status = [responsetype, status, comment]
        logger.debug("Received %d lines of data, identifier=%s, status=%s" %
                     (len(resultlines), ctag, status))
        return (resultlines, ctag, status)
Beispiel #10
0
class TelnetInput(CLIIOInput, CLILangInput, base.BaseSyncInput):
    """Telnet input, based on the expect class. This opens a telnet subprocess, and most likely only works for UNIX."""
    port = 23

    # I/O commands

    def connect(self):
        try:
            if not self.username:
                raise AttributeError(
                    "username is not set for %s. Please call setLoginCredentials() before getSubject()."
                    % self.hostname)
            self.terminal = pexpect.spawn('telnet %s %d' %
                                          (self.hostname, self.port))
            self.terminal.timeout = int(self.timeout)
        except pexpect.ExceptionPexpect:
            raise exceptions.NetworkException(
                "Problem spawning a new process ('telnet %s %d')" %
                (self.hostname, self.port))

    def login(self):
        logger = logging.getLogger("protocols")
        try:
            match = self.terminal.expect(
                ['[Ll]ogin:', '[Pp]assword:', self.prompt])
        except pexpect.TIMEOUT:
            raise exceptions.NetworkException(
                "Time-out while connecting to host ('telnet %s %d')" %
                (self.hostname, self.port))
        if match == 0:  # Login prompt
            try:
                self.terminal.sendline(self.username)
                match = 1 + self.terminal.expect(['[Pp]assword:', self.prompt])
            except pexpect.TIMEOUT:
                raise exceptions.MalformedIO(
                    "Unexpected time-out while waiting for prompt from %s" %
                    (self.hostname))
        if match == 1:  # Password prompt
            try:
                self.terminal.sendline(self.password)
                match = 1 + self.terminal.expect(
                    ['Permission denied', self.prompt])
                if match == 1:  # permission denied
                    if self.password:
                        raise exceptions.NetworkException(
                            "Password failed when connecting to %s@%s" %
                            (self.username, self.hostname))
                    else:
                        raise exceptions.NetworkException(
                            "No password given for %s@%s. Unable to connect" %
                            (self.username, self.hostname))
            except pexpect.TIMEOUT, pexpect.EOF:
                raise exceptions.MalformedIO(
                    "Unexpected time-out (>%d sec) while authenticating to %s"
                    % (self.timeout, self.hostname))
        if match != 2:  # haven't gotten a prompt yet
            try:
                self.terminal.expect(self.prompt)
            except pexpect.TIMEOUT, pexpect.EOF:
                raise exceptions.MalformedIO(
                    "Unexpected time-out (>%d sec) while waiting for prompt from %s"
                    % (self.timeout, self.hostname))
Beispiel #11
0
            try:
                self.terminal.sendline(self.password)
                match = 1 + self.terminal.expect(
                    ['Permission denied', self.prompt])
                if match == 1:  # permission denied
                    if self.password:
                        raise exceptions.NetworkException(
                            "Password failed when connecting to %s@%s" %
                            (self.username, self.hostname))
                    else:
                        raise exceptions.NetworkException(
                            "No password given for %s@%s. Unable to connect" %
                            (self.username, self.hostname))
            except pexpect.TIMEOUT, pexpect.EOF:
                raise exceptions.MalformedIO(
                    "Unexpected time-out (>%d sec) while authenticating to %s"
                    % (self.timeout, self.hostname))
        if match != 2:  # haven't gotten a prompt yet
            try:
                self.terminal.expect(self.prompt)
            except pexpect.TIMEOUT, pexpect.EOF:
                raise exceptions.MalformedIO(
                    "Unexpected time-out (>%d sec) while waiting for prompt from %s"
                    % (self.timeout, self.hostname))
                # raise exceptions.MalformedIO("Expected 'permission denied' or '%s', but got: '%s'" % (self.prompt, self.terminal.before))
        logger.debug("Succesfully logged in to %s" % (self.hostname))


class CLIEmulatorInput(emulate.FileIOInput, CLILangInput, base.BaseSyncInput):
    """Emulates a CLI input, but in reality, reads data from a file"""
    pass