Exemple #1
0
    def get_neighbors_enos(self):
        """Dump `lldp remote-device` table.

        Example output:

        ```
        LLDP Remote Devices Information
        Legend(possible values in DMAC column) :
        NB   - Nearest Bridge          - 01-80-C2-00-00-0E
        NnTB - Nearest non-TPMR Bridge - 01-80-C2-00-00-03
        NCB  - Nearest Customer Bridge - 01-80-C2-00-00-00
        Total number of current entries: 2
        LocalPort | Index | Remote Chassis ID         | Remote Port          | Remote System Name            | DMAC
        ----------|-------|---------------------------|----------------------|-------------------------------|---------
        2         | 2     | a4 8c db 34 d9 00         | MGT                  |                               | NB
        XGE4      | 1     | a4 8c db 34 d7 00         | 48                   |
        LCTC-R2U37-SW                 | NB
        ```

        Returns:
          tuple: (myport, remote_port, remote_interface)
        """
        tmp = self._dump_info("show lldp remote-device", "LocalPort")
        records = []  # [(myport, remote_interface, remote_port),]
        entries = filter(lambda x: "|" in x, tmp.split("\n"))[2:]
        for e in entries:
            tmp = map(lambda x: x.strip(), e.split("|"))

            remote_port = self._cleanse_port(tmp[3])
            if not remote_port:
                continue

            my_port = self._cleanse_port(tmp[0])
            if not my_port:
                continue

            # remote device
            remote_switch_name = tmp[4].lstrip("\x00").strip()
            existing_devices = Device.objects.filter(name=remote_switch_name)
            if not existing_devices:
                # we haven't seen this device yet,
                # wait for next scan
                continue
            remote_device = existing_devices[0]

            # remote interface
            existing_interfaces = Interface.objects.filter(
                name=remote_port, device=remote_device)
            if existing_interfaces:
                remote_interface = existing_interfaces[0]
            else:
                remote_interface = Interface(name=remote_port,
                                             device=remote_device)
            remote_interface.mac_address = self._cleanse_mac(tmp[2])
            remote_interface.save()

            records.append((my_port, remote_port, remote_interface))

        return records
Exemple #2
0
def syncInterfaces(device, connection, iface_regex):
    ''' Get interfaces from device and add|update it on netbox
    '''
    interfaces = connection.get_interfaces()

    print("Connection complete, number of interfaces {}".format(
        len(interfaces)))

    for if_name in interfaces.keys():
        # Cheking is interface matching regex
        if re.match(iface_regex, if_name):
            if_type = getInterfaceType(if_name)
            # and state (up/down)
            state = (interfaces[if_name]['is_enabled']
                     and interfaces[if_name]['is_up'])

            intf = device.interfaces.filter(name=if_name)

            # I cannot found now a way how to do it without two code block =\
            if intf.count() == 0:
                # if no interface present in device, create new
                print("Create new interface {}".format(if_name))
                iface = Interface(name=if_name)
                iface.description = interfaces[if_name]['description']
                iface.mac_address = interfaces[if_name]['mac_address']
                iface.enabled = state
                iface.form_factor = if_type
                iface.device = device
                iface.save()
                # Try to connect interface by description
                connect_interface(iface)
            else:
                # or get current iface and update them
                print("Update interface {}".format(if_name))
                iface = intf[0]
                iface.description = interfaces[if_name]['description']
                iface.mac_address = interfaces[if_name]['mac_address']
                iface.enabled = state
                #iface.form_factor = if_type
                iface.save()
                # Try to connect interface by description
                connect_interface(iface)
        else:
            pass
Exemple #3
0
    def get_system_info(self, switch):
        # dump switch system info
        mac, serial, part_no, mtm = {
            "cnos": self.get_system_info_cnos,
            "enos": self.get_system_info_enos
        }[self.mode]()

        # update switch:
        # 1. serial
        # 2. switch device's device type part number
        switch.serial = serial
        switch.save()

        switch.device_type.part_number = part_no
        switch.device_type.save()

        # From mac we create/update Interface
        existings = Interface.objects.filter(mac_address=mac)
        if existings:
            if existings.filter(device=switch):
                pass
            else:
                existings.update(device=switch)
            interface = existings[0]
        else:
            existing_mgmt = Interface.objects.filter(device=switch,
                                                     name="mgmt0")
            if existing_mgmt:
                interface = existing_mgmt[0]
            else:
                interface = Interface(
                    name="mgmt0",  # used on CNOS switch at least.
                    device=switch)
        interface.device = switch
        interface.mac_address = mac
        interface.type = INTERFACE_TYPE_MANAGEMENT
        interface.save()

        # link interface to secret & ip
        switch.primary_ip.interface = interface
        switch.primary_ip.save()

        ip, secret = switch.management_access
        secret.interface = interface
Exemple #4
0
    def dump_port_mac(self, switch):
        port_table = {
            "cnos": self.dump_port_mac_cnos,
            "enos": self.dump_port_mac_enos
        }[self.mode]()

        for port_number, mac, enabled in port_table:
            existing = Interface.objects.filter(device=switch,
                                                name=port_number)
            if existing:
                i = existing[0]
            else:
                i = Interface(
                    device=switch,
                    name=port_number,
                )
            i.mac_address = mac
            i.type = INTERFACE_TYPE_SWITCH_PORT
            i.enabled = enabled
            i.save()
Exemple #5
0
def server_bmc_get(device_id):
    """To group all `get_` calls.

    It turned out that BMC only allows **1** SSH session
    at a time. The consequetive SSH call will return an error

    ```
    X11 forwarding request failed on channel 0
    Connection to 10.240.41.254 closed.
    ```

    Args:
      device_id: host server id. This device should have a property `bmc_access`
        which has BMC (ip, secret). We are **ASSUMING** that a device has ONE BMC.
    """
    server = Device.objects.get(id=device_id)
    the_bmc = server.bmc_controllers[0]

    ip, secret = server.bmc_access
    print "reading server %s BMC name" % ip

    cli = BmcByCli(ip, secret.name, secret.password)

    if not cli.connect():
        print "Access to BMC %s has failed. abort." % ip
        the_bmc.status = DEVICE_STATUS_OFFLINE
        server.save()
        the_bmc.save()
        return
    else:
        the_bmc.status = DEVICE_STATUS_ACTIVE

    # server name
    # Example output:
    #
    # ```
    # SystemName: brain4-3
    # ContactPerson:
    # Location:
    # FullPostalAddress:
    # RoomID:
    # RackID:
    # LowestU: 0
    # HeightU: 2
    # ```
    #
    # This is the name by BMC, not FQDN or hostname that OS represents.
    name = filter(lambda x: "SystemName" in x, cli.get_name().split("\n"))
    name = re.search("SystemName:(?P<name>.+)", name[0]).group("name").strip()
    if not server.name:
        server.name = name

    the_bmc.name = "%s BMC" % name

    # eth0 mac
    # Example output:
    #
    # ```
    # -b      :  08:94:ef:48:13:3d
    # ```
    mac = cli.get_eth0_mac()
    mac = re.search("b\s+:(?P<mac>.*)", mac).group("mac").strip().upper()
    existings = Interface.objects.filter(mac_address=mac)
    if existings:
        i = existings[0]
    else:
        i = Interface(device=server)

    i.device = the_bmc
    i.name = "eth0"
    i.type = INTERFACE_TYPE_MANAGEMENT
    i.mgmt_only = True
    i.mac_address = mac
    i.save()

    # link Interface to its primary IP
    the_bmc.primary_ip4.interface = i
    the_bmc.primary_ip4.save()

    # vpd sys
    # To get serial number, uuid of this device.
    #
    # Example output:
    # ```
    # Machine Type-Model             Serial Number                  UUID
    # --------------                 ---------                      ----
    # 8871AC1                        J11PGTT                        60CD7A22827E11E79D09089    # ```
    tmp = re.split("-+", cli.get_vpd_sys())
    sys_info = re.split("\s+", tmp[-1].strip())[:3]

    the_bmc.serial = ""
    the_bmc.asset_tag = ""
    the_bmc.save()

    server.serial = sys_info[1]
    if server.asset_tag != sys_info[2]:
        if Device.objects.filter(asset_tag=sys_info[2]):
            # wow we have someone who already owned this tag!
            # Create a random uuid one.
            server.asset_tag = "Generated %s" % str(uuid.uuid4())
        else:
            server.asset_tag = sys_info[2]
    server.save()

    server.device_type.part_number = sys_info[0]
    server.device_type.save()

    # get server's power state
    power = filter(lambda x: "power" in x, cli.get_name().split("\n"))
    for p in power:
        state = re.search("power\s(?P<state>.+)", power).group("state").strip()
        if state == "off":
            server.status = DEVICE_STATUS_POWERED_OFF
        elif state == "on":
            # Note: server BMC indicates `power on`, but OS may still
            # be in off state.
            pass
    server.save()

    # dump raid controllers inside server
    for c in cli.get_storage_controllers():
        # manufacturer
        m, whatever = Manufacturer.objects.get_or_create(
            name=c["manufacturer"].strip(),
            slug=c["manufacturer"].lower().strip())

        # device type
        model = c["model"]
        existing = DeviceType.objects.filter(slug=slugify(model))
        if existing:
            dt = existing[0]
        else:
            dt, whatever = DeviceType.objects.get_or_create(
                manufacturer=m,
                model=model,
                slug=slugify(model),
                part_number=c["part_id"].strip(),
                u_height=0,  # TODO: hardcoded special value!
                is_network_device=False,
                subdevice_role=SUBDEVICE_ROLE_CHILD)

        # items
        asset_tag = c["asset_tag"].strip()
        serial = c["serial"].strip()
        if not asset_tag:
            existing = InventoryItem.objects.filter(asset_tag=asset_tag)
        else:
            existing = InventoryItem.objects.filter(serial=serial)

        if existing:
            item = existing[0]
        else:  # inventory item
            item = InventoryItem(
                device=server,
                manufacturer=m,
                discovered=True,
                asset_tag=c["asset_tag"].strip(),
            )

        item.device_type = dt
        item.name = c["target"]
        item.part_id = c["part_id"].strip()
        item.serial = c["serial"].strip()
        item.description = convert_to_html_table(c["description"], ":")
        item.save()

    # dump disks inside server
    for c in cli.get_storage_drives():
        # manufacturer
        m, whatever = Manufacturer.objects.get_or_create(
            name=c["manufacturer"].strip(),
            slug=c["manufacturer"].lower().strip())

        # device type
        model = "/".join(
            filter(lambda x: x, [c["name"], c["disk_type"], c["media_type"]]))
        existing = DeviceType.objects.filter(slug=slugify(model))
        if existing:
            dt = existing[0]
        else:
            dt, whatever = DeviceType.objects.get_or_create(
                manufacturer=m,
                model=model,
                slug=slugify(model),
                part_number=c["part_id"].strip(),
                u_height=0,  # TODO: hardcoded special value!
                is_network_device=False,
                subdevice_role=SUBDEVICE_ROLE_CHILD)

        # inventory item
        item, whatever = InventoryItem.objects.get_or_create(
            device=server,
            manufacturer=m,
            device_type=dt,
            discovered=True,
            name=c["target"],
            part_id=c["part_id"].strip(),
            serial=c["serial"].strip(),
        )
        item.description = convert_to_html_table(c["description"], ":")
        item.save()

    # dump fw
    tmp = cli.get_firmware_status()
    tmp = re.sub("-", "", tmp)
    item, whatever = InventoryItem.objects.get_or_create(
        device=server,
        name="firmware",
        discovered=True,
    )
    item.description = convert_to_html_table(tmp)
    item.save()
Exemple #6
0
def sync_interfaces(device, interfaces):
    """ Syncing interfaces

        :param device: object NetBox Device
        :param interfaces: list of lists

        interfaces:
            interface['NAME'] - Name of interface
            interface['MAC'] - Mac-Address
            interface['IP'] - List of IP-address
            interface['MTU'] - MTU
            interface['DESCR'] - Description of interfaces
            interface['TYPE'] - Physical type of interface (Default 1G-cooper - cannot get from linux)
            interface['STATE'] - UP|DOWN

        :return: status: bool, message: string
    """
    # Updated interface counter
    count = 0

    # Init interfaces filter
    iface_filter = device.cf().get('Interfaces filter')
    try:
        iface_regex = re.compile(iface_filter)
    except Exception as e:
        logger.warning("Cannot parse regex for interface filter: {}".format(e))
        iface_regex = re.compile('.*')

    for interface in interfaces:
        name = interface.get('NAME')
        mac = interface.get('MAC')
        ips = interface.get('IP')
        mtu = interface.get('MTU')
        description = interface.get('DESCR')
        iface_type = interface.get('TYPE')
        iface_state = interface.get('STATE')
        # TODO: add a bonding support
        iface_master = interface.get('BOND')

        # Check interface filter
        if not iface_regex.match(name):
            logger.debug("Iface {} not match with regex".format(name))
            continue

        # Get interface from device - for check if exist
        ifaces = device.interfaces.filter(name=name)
        if ifaces:
            logger.info(
                "Interface {} is exist on device {}, will update".format(
                    name, device.name))
            # TODO: I think, that only one item will be in filter, but need to add check for it
            iface = ifaces[0]
        else:
            logger.info(
                "Interface {} is not exist on device {}, will create new".
                format(name, device.name))
            iface = Interface(name=name)
            iface.device = device

        logger.info(
            "Will be save next parameters: Name:{name}, MAC: {mac}, MTU: {mtu}, Descr: {description}"
            .format(name=name, mac=mac, mtu=mtu, description=description))
        if description:
            iface.description = description
        else:
            iface.description = ''
        iface.mac_address = mac

        # MTU should be less 32767
        if int(mtu) < MAX_MTU:
            iface.mtu = mtu

        logger.info("Interface state is {}".format(iface_state))
        iface.enabled = 'up' in iface_state.lower()
        iface.form_factor = _get_interface_type(name)

        try:
            iface.save()
        except Exception as e:
            logger.error("Cannot save interface, error is {}".format(e))
        else:
            count += 1
            logger.info("Interface {} was succesfully saved".format(
                name, device.name))

        try:
            _connect_interface(iface)
        except:
            logger.error("Problem with connection function")

        # IP syncing
        if len(ips) > 0:
            for address in ips:
                addr = IPAddress()
                addr.interface = iface
                logger.info("Address is: {}".format(addr))
                # TODO: Need a test ipv6 addresses
                try:
                    # tries to determine is this address exist
                    if iface.ip_addresses.filter(address=address):
                        continue
                    addr.address = IPNetwork(address)
                    addr.save()
                except:
                    logger.warning(
                        "Cannot set address {} on interface".format(address))

    if count == 0:
        return False, "Can't update any interface, see a log for details"
    return True, "Successfully updated {} interfaces".format(count)