Пример #1
0
    def powerState(self):
        """
        Get the power state for all slots
        """
        walkAttr = 'remoteControlBladePowerState'
        oid = 'BLADE-MIB::%s' % walkAttr

        # Start async snmpwalk. This call returns immediately
        # and spawns a background thread to perform the SNMPWalk
        snmpWalk = SNMPWalk.withConfigFile(self.host, oid)

        state = []

        # While the snmpwalk is running
        while not snmpWalk.eof:
            # Get snmp oid/value pairs off the queue
            while not snmpWalk.queue.empty():
                (oid, value) = snmpWalk.queue.get()
                (mibName, attr, lastOctet) = snmpWalk.extractOidParts(oid)

                if attr == walkAttr:
                    if value == 'on(1)':
                        state.append(1)
                    else:
                        state.append(0)
        snmpWalk.join()
        Log.debug(100, 'ch %03d power state: %s' % (self.num, state))
        return state
Пример #2
0
    def walk(self, oid):
        """
        Perform an SNMP walk

        Params
        -----
        oid : string
              The starting OID
        """
        version = '-v1'
        if self.version == 2:
            version = '-v2'

        args = [
            snmpwalk_cmd, '-t', '120', version, '-c', self.readCommunity,
            self.host, oid
        ]
        Log.debug(100, ' '.join(args))
        (output, exitcode) = Command.run(args)

        values = None
        if exitcode == 0 and output:
            values = []
            for line in output:
                line.rstrip('\n')
                if len(line) > 0:
                    values.append(self.parseSNMPLine(line))

        return values
Пример #3
0
    def powerState(self):
        """
        Get the power state for all slots
        """
        walkAttr = 'remoteControlBladePowerState'
        oid = 'BLADE-MIB::%s' % walkAttr

        # Start async snmpwalk. This call returns immediately
        # and spawns a background thread to perform the SNMPWalk
        snmpWalk = SNMPWalk.withConfigFile(self.host, oid)

        state = []

        # While the snmpwalk is running
        while not snmpWalk.eof:
            # Get snmp oid/value pairs off the queue
            while not snmpWalk.queue.empty():
                (oid, value) = snmpWalk.queue.get()
                (mibName, attr, lastOctet) = snmpWalk.extractOidParts(oid)

                if attr == walkAttr:
                    if value == 'on(1)':
                        state.append(1)
                    else:
                        state.append(0)
        snmpWalk.join()
        Log.debug(100, 'ch %03d power state: %s' % (self.num, state))
        return state
Пример #4
0
    def putDocument(self, docId, params):
        """
        PUT a document on the CouchDB server. If the document
        already exists, you will need to pass in a _rev param
        with the revision you would like to update. The
        saveDocument() method handles this for you, if all
        you want to do is save a document, regardless of whether
        or not it already exists.

        Params
        ------
        docId  : string
                 The unique ID of the document
        params : dictionary
                 A dictionary of parameters that define the document
        """
        path = '/%s/%s' % (self.db, docId.replace(' ', '+'))
        Log.debug(100, 'Putting %s' % path)
        connection = httplib.HTTPConnection(self.host, self.port)
        connection.connect()
        params['updatedAt'] = CouchDB.now()
        connection.request('PUT', path,
                           json.dumps(params),
                           {
                               'Content-Type': 'application/json'
                           })

        result = json.loads(connection.getresponse().read())

        if result.has_key(u'error'):
            Log.error('PUT %s: %s' % (path, result))

        return result
Пример #5
0
    def retrieveWithMac(cls, couch, mac):
        """
        Find a slot that matches the specified mac address

        Params
        ------
        couch:  object
                couch database connection
        mac:    string
                The mac address for which to search

        Returns
        -------
        Dictionary of key/value pairs for the slot that matches the specified mac address
        """
        if mac == 'not available' or mac == 'not installed':
            return None

        output = couch.getView('slot', 'mac_to_slot', mac)
        Log.debug(200, output)
        if output and len(output) > 0:
            key, value = output.popitem()
            if value:
                return value

        return None
Пример #6
0
    def getViewDict(self, design, view, params = {}):
        """
        Get a view, return the results as a dictionary of key => values.
        If the particular key occurs multiple times, then the value will 
        be an array of values for that key

        Params
        ------
        design:  string
                 The design document name
        view:    string
                 The view name
        params:  dictv
                 Dictionary of parameters:
                   key: The key to which results will be limited
                   start: The starting key for the range to which results will be
                             limited
                   end:   The ending key for the range to which results will be limited
                   includeDocs: Set this to anything, and the entire document will
                                be returned as the value

        Returns
        -------
        A dictionary of view key/value pairs. If no results were returned, then
        None is returned
        """
        path = self.getViewPath(design, view, params)
        Log.debug(10, 'Getting view path %s' % path)
        output = self.getDocument(path)
        results = {}

        if output.has_key(u'total_rows'):
            Log.debug(10, '%s returned %s rows' % (path, output[u'total_rows']))

        if output.has_key(u'rows'):
            for row in output[u'rows']:
                key   = row[u'key']
                value = row.get(u'value', None)
                if params.has_key('includeDocs'):
                    value = row.get(u'doc', None)

                # If this key is already in the results, then append this value
                # to the list
                if results.has_key(key):
                    storedValue = results[key]

                    # If the stored value is a dict, change to an array of dicts
                    if isinstance(storedValue, (frozenset, list, set, tuple)):
                        storedValue.append(value)
                        value = storedValue
                    else:
                        value = [storedValue, value]

                results[key] = value

        # If no results, then return a None object
        if len(results) <= 0:
            results = {}

        return results
Пример #7
0
    def walk(self, oid):
        """
        Perform an SNMP walk

        Params
        -----
        oid : string
              The starting OID
        """
        version = '-v1'
        if self.version == 2:
            version = '-v2'

        args = [snmpwalk_cmd, '-t', '120', version, '-c', self.readCommunity, self.host, oid]
        Log.debug(100, ' '.join(args))
        (output, exitcode) = Command.run(args)

        values = None
        if exitcode == 0 and output:
            values = []
            for line in output:
                line.rstrip('\n')
                if len(line) > 0:
                    values.append(self.parseSNMPLine(line))

        return values
Пример #8
0
    def retrieveWithMac(cls, couch, mac):
        """
        Find a slot that matches the specified mac address

        Params
        ------
        couch:  object
                couch database connection
        mac:    string
                The mac address for which to search

        Returns
        -------
        Dictionary of key/value pairs for the slot that matches the specified mac address
        """
        if mac == 'not available' or mac == 'not installed':
            return None

        output = couch.getView('slot', 'mac_to_slot', mac)
        Log.debug(200, output)
        if output and len(output) > 0:
            key, value = output.popitem()
            if value:
                return value

        return None
Пример #9
0
 def collectChassisInfo(self, snmp):
     """
     Retrieve chassis information
     """ 
     for (attr, oid) in self.chassisOidDict.items():
         values = snmp.walk(oid)
         if values:
             Log.debug(10, '%s: %s' % (attr, values[0][1]))
             setattr(self, attr, values[0][1])
Пример #10
0
 def collectChassisInfo(self, snmp):
     """
     Retrieve chassis information
     """
     for (attr, oid) in self.chassisOidDict.items():
         values = snmp.walk(oid)
         if values:
             Log.debug(10, '%s: %s' % (attr, values[0][1]))
             setattr(self, attr, values[0][1])
Пример #11
0
    def run(cls, args):
        output = None
        exitCode = 0
        try:
            Log.debug(100, ' '.join(args))
            proc = Popen(args, stdout=PIPE)
            output = proc.communicate()[0].split('\n')
            exitCode = proc.returncode
        except (OSError) as e:
            Log.error(str(e))

        return (output, exitCode)
Пример #12
0
    def run(cls, args):
        output = None
        exitCode = 0
        try:
            Log.debug(100, " ".join(args))
            proc = Popen(args, stdout=PIPE)
            output = proc.communicate()[0].split("\n")
            exitCode = proc.returncode
        except (OSError) as e:
            Log.error(str(e))

        return (output, exitCode)
Пример #13
0
    def getView(self, design, view, key = None):
        """
        Get a view

        Params
        ------
        design:  string
                 The design document name
        view:    string
                 The view name
        key:     string (optional)
                 a key to select

        Returns
        -------
        A dictionary of view key/value pairs. If no results were returned, then
        None is returned
        """
        path = '_design/%s/_view/%s' % (design, view)

        if key:
            path = '%s?key="%s"' % (path, key)

        output = self.getDocument(path)
        results = {}

        if output.has_key(u'total_rows'):
            Log.debug(10, '%s returned %s rows' % (path, output[u'total_rows']))

        if output.has_key(u'rows'):
            for row in output[u'rows']:
                value = row[u'value']
                key   = row[u'key']

                if results.has_key(key):
                    storedValue = results[key]

                    # If the stored value is a dict, change to an array of dicts
                    if isinstance(storedValue, (frozenset, list, set, tuple)):
                        storedValue.append(value)
                        value = storedValue
                    else:
                        value = [storedValue, value]

                results[key] = value

        # If no results, then return a None object
        if len(results) <= 0:
            results = {}

        return results
Пример #14
0
    def run(self):
        """
        Perform an SNMP walk
        """
        version = '-v1'
        if self.version == 2:
            version = '-v2'

        command = [
            snmpwalk_cmd, '-t', '120', version, '-c', self.readCommunity,
            self.host, self.oid
        ]
        Log.debug(100, ' '.join(command))

        # Launch the command as subprocess.
        process = subprocess.Popen(command,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)

        # Launch the asynchronous readers of the process' stdout and stderr.
        stdoutQueue = Queue.Queue()
        stdoutReader = AsynchronousFileReader(process.stdout, stdoutQueue)
        stdoutReader.start()
        stderrQueue = Queue.Queue()
        stderrReader = AsynchronousFileReader(process.stderr, stderrQueue)
        stderrReader.start()

        # Check the queues if we received some output (until there is nothing more to get).
        while not stdoutReader.eof() or not stderrReader.eof():
            # Show what we received from standard output.
            while not stdoutQueue.empty():
                line = stdoutQueue.get()
                self.queue.put(self.split(line))

            # Show what we received from standard error.
            while not stderrQueue.empty():
                line = stderrQueue.get()
                print 'Received line on standard error: ' + repr(line)

            # Sleep a bit before asking the readers again.
            time.sleep(.1)

        # Let's be tidy and join the threads we've started.
        stdoutReader.join()
        stderrReader.join()

        # Close subprocess' file descriptors.
        process.stdout.close()
        process.stderr.close()
Пример #15
0
    def delete(self, params):
        """
        Delete a document. Params must have an _id and _rev param
        """
        path = '/%s/%s?rev=%s' % (self.db, params['_id'].replace(' ', '+'), params['_rev'].replace(' ', '+'))
        Log.debug(10, 'DELETE %s' % path)
        connection = httplib.HTTPConnection(self.host, self.port)
        connection.connect()
        connection.request('DELETE', path)
        result = json.loads(connection.getresponse().read())

        if result.has_key(u'error'):
            if result[u'error'] != u'not_found':
                Log.error('GET %s: %s' % (path, result))

        return result
Пример #16
0
    def allBladesFailToNetboot(cls, couch):
        """
        Find a list of chassis where all blades failed to netboot
        
        Params
        ------
        couch:   object
                 A CouchDB object

        Returns
        -------
        A list of chassis docId
        """

        results = couch.getView('blade', 'failed_netboot')

        chassis = {}
        failedChassis = []

        for bladeDocId in results:
            slotInfo = Slot.retrieveWithMac(couch, bladeDocId)

            chassisDocId = None
            slotNum = None

            if slotInfo:
                Log.debug(200, 'slotInfo: %s' % slotInfo)
                if slotInfo.has_key(u'chassisDocId'):
                    chassisDocId = slotInfo[u'chassisDocId']

                if slotInfo.has_key(u'num'):
                    slotNum = slotInfo[u'num']

            if chassisDocId and slotInfo:
                if chassis.has_key(chassisDocId):
                    chassis[chassisDocId].append(slotNum)
                else:
                    chassis[chassisDocId] = [slotNum]

        for chassisDocId in sorted(chassis.iterkeys()):
            slots = chassis[chassisDocId]
            if len(slots) >= 14:
                failedChassis.append(chassisDocId)

        return failedChassis
Пример #17
0
    def allBladesFailToNetboot(cls, couch):
        """
        Find a list of chassis where all blades failed to netboot
        
        Params
        ------
        couch:   object
                 A CouchDB object

        Returns
        -------
        A list of chassis docId
        """

        results = couch.getView('blade', 'failed_netboot')

        chassis = {}
        failedChassis = []

        for bladeDocId in results:
            slotInfo = Slot.retrieveWithMac(couch, bladeDocId)

            chassisDocId = None
            slotNum = None

            if slotInfo:
                Log.debug(200, 'slotInfo: %s' % slotInfo)
                if slotInfo.has_key(u'chassisDocId'):
                    chassisDocId = slotInfo[u'chassisDocId']

                if slotInfo.has_key(u'num'):
                    slotNum = slotInfo[u'num']

            if chassisDocId and slotInfo:
                if chassis.has_key(chassisDocId):
                    chassis[chassisDocId].append(slotNum)
                else:
                    chassis[chassisDocId] = [slotNum]

        for chassisDocId in sorted(chassis.iterkeys()):
            slots = chassis[chassisDocId]
            if len(slots) >= 14:
                failedChassis.append(chassisDocId)

        return failedChassis
Пример #18
0
    def run(self):
        """
        Perform an SNMP walk
        """
        version = '-v1'
        if self.version == 2:
            version = '-v2'

        command = [snmpwalk_cmd, '-t', '120', version, '-c', self.readCommunity, self.host, self.oid]
        Log.debug(100, ' '.join(command))

        # Launch the command as subprocess.
        process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
        # Launch the asynchronous readers of the process' stdout and stderr.
        stdoutQueue = Queue.Queue()
        stdoutReader = AsynchronousFileReader(process.stdout, stdoutQueue)
        stdoutReader.start()
        stderrQueue = Queue.Queue()
        stderrReader = AsynchronousFileReader(process.stderr, stderrQueue)
        stderrReader.start()

        # Check the queues if we received some output (until there is nothing more to get).
        while not stdoutReader.eof() or not stderrReader.eof():
            # Show what we received from standard output.
            while not stdoutQueue.empty():
                line = stdoutQueue.get()
                self.queue.put(self.split(line))
 
            # Show what we received from standard error.
            while not stderrQueue.empty():
                line = stderrQueue.get()
                print 'Received line on standard error: ' + repr(line)
 
            # Sleep a bit before asking the readers again.
            time.sleep(.1)
 
        # Let's be tidy and join the threads we've started.
        stdoutReader.join()
        stderrReader.join()
 
        # Close subprocess' file descriptors.
        process.stdout.close()
        process.stderr.close()
Пример #19
0
    def getViewTuple(self, design, view, params = None):
        """
        Get a view, return a list of key/value tuples

        Params
        ------
        design:  string
                 The design document name
        view:    string
                 The view name
        key:     string (optional)
                 a key to select

        Returns
        -------
        An array of 2-tuples. The first element in the tuple is the key,
        the second element is the value. If no results were returned, then
        the array will be empty
        """
        path = self.getViewPath(design, view, params)
        Log.debug(10, 'Getting view path %s' % path)

        output = self.getDocument(path)
        results = []

        if output.has_key(u'total_rows'):
            Log.debug(10, '%s returned %s rows' % (path, output[u'total_rows']))

        if output.has_key(u'rows'):
            for row in output[u'rows']:
                key   = row[u'key']
                value = row.get(u'value', None)
                if params is not None and params.has_key('includeDocs'):
                    value = row.get(u'doc', None)
                results.append((key, value))

        return results
Пример #20
0
    def collectInfoAndPersist(self, couch):
        """
        Collect blade info for this chassis via SNMP, and 
        persist those blades and slots and this Chassis object
        to CouchDB when done
        """
        if not self.ping():
            Log.info('%s not pingable, not collecting SNMP info' % self.host)
        else:
            Log.debug(5, '%s is pingable' % self.host)
            self.isPingable = 1

            snmp = SNMP.withConfigFile(self.host)

            self.collectChassisInfo(snmp)
            self.collectFanPackInfo()

            bladesCommunicating = bitarray(self.bladesCommunicating)
            bladesInstalled = bitarray(self.bladesInstalled)

            oids = {
                'mac0':
                'BLADE-MIB::bladeMACAddress1Vpd',
                'mac1':
                'BLADE-MIB::bladeMACAddress2Vpd',
                'biosVersion':
                'BLADE-MIB::bladeBiosVpdRevision',
                'bmcVersion':
                'BLADE-MIB::bladeSysMgmtProcVpdRevision',
                'diagVersion':
                'BLADE-MIB::bladeDiagsVpdRevision',
                'serialNumber':
                'BLADE-MIB::bladeBiosVpdName',
                'healthState':
                'BLADE-MIB::bladeHealthState',
                'healthSummarySeverity':
                'BLADE-MIB::bladeHealthSummarySeverity',
                'healthSummaryDescription':
                'BLADE-MIB::bladeHealthSummaryDescription',
            }

            blade = {}

            for (attr, oid) in oids.items():
                values = self.bladeInfo(snmp, oid)
                if values:
                    for (slot, value) in values:
                        if not blade.has_key(slot):
                            blade[slot] = {}
                        blade[slot][attr] = value

            if len(blade) > 0:
                self.collectedSNMP = 1
                for (slotNum, params) in blade.items():
                    Log.debug(
                        10, 'chassis %d slot %s blade params: %s' %
                        (self.num, slotNum, params))
                    nodeNum = (int(slotNum) - 1) + self.firstNode
                    nodeName = self.nodeNameFormat % nodeNum

                    blade = Blade(params)

                    slotInt = int(slotNum)

                    slotParams = {
                        'num': slotInt,
                        'nodeName': nodeName,
                        'chassisDocId': self.docId,
                        'bladeDocId': blade.mac0,
                        'bladeInstalled': bladesInstalled[slotInt - 1],
                        'bladeCommunicating': bladesCommunicating[slotInt - 1],
                    }

                    slot = Slot(slotParams)

                    # This appears to be pointless. We shouldn't save any information about blades that
                    # are not available
                    #                    if blade.mac0 == 'not available':
                    #                        blade.mac0 = '%s-%s' % (blade.mac0, slot.docId)

                    slot.persist(couch)

                    if blade.validMac0:
                        blade.persist(couch)

        self.persist(couch)
Пример #21
0
    def collectInfoAndPersist(self, couch):
        """
        Collect blade info for this chassis via SNMP, and 
        persist those blades and slots and this Chassis object
        to CouchDB when done
        """
        if not self.ping():
            Log.info('%s not pingable, not collecting SNMP info' % self.host)
        else:
            Log.debug(5, '%s is pingable' % self.host)
            self.isPingable = 1

            snmp = SNMP.withConfigFile(self.host)

            self.collectChassisInfo(snmp)
            self.collectFanPackInfo()

            bladesCommunicating = bitarray(self.bladesCommunicating)
            bladesInstalled = bitarray(self.bladesInstalled)

            oids = {'mac0':                     'BLADE-MIB::bladeMACAddress1Vpd',
                    'mac1':                     'BLADE-MIB::bladeMACAddress2Vpd',
                    'biosVersion':              'BLADE-MIB::bladeBiosVpdRevision',
                    'bmcVersion':               'BLADE-MIB::bladeSysMgmtProcVpdRevision',
                    'diagVersion':              'BLADE-MIB::bladeDiagsVpdRevision',
                    'serialNumber':             'BLADE-MIB::bladeBiosVpdName',
                    'healthState':              'BLADE-MIB::bladeHealthState',
                    'healthSummarySeverity':    'BLADE-MIB::bladeHealthSummarySeverity',
                    'healthSummaryDescription': 'BLADE-MIB::bladeHealthSummaryDescription',
                }

            blade = {}
            
            for (attr, oid) in oids.items():
                values = self.bladeInfo(snmp, oid)
                if values:
                    for (slot, value) in values:
                        if not blade.has_key(slot):
                            blade[slot] = {}
                        blade[slot][attr] = value

            if len(blade) > 0:
                self.collectedSNMP = 1
                for (slotNum, params) in blade.items():
                    Log.debug(10, 'chassis %d slot %s blade params: %s' % (self.num, slotNum, params))
                    nodeNum = (int(slotNum) - 1) + self.firstNode
                    nodeName = self.nodeNameFormat % nodeNum

                    blade = Blade(params)

                    slotInt = int(slotNum)

                    slotParams = {'num':                slotInt,
                                  'nodeName':           nodeName,
                                  'chassisDocId':       self.docId,
                                  'bladeDocId':         blade.mac0,
                                  'bladeInstalled':     bladesInstalled[slotInt - 1],
                                  'bladeCommunicating': bladesCommunicating[slotInt - 1],
                              }

                    slot = Slot(slotParams)

# This appears to be pointless. We shouldn't save any information about blades that
# are not available
#                    if blade.mac0 == 'not available':
#                        blade.mac0 = '%s-%s' % (blade.mac0, slot.docId)

                    slot.persist(couch)

                    if blade.validMac0:
                        blade.persist(couch)

        self.persist(couch)