예제 #1
0
    def __init__(self, dev_instance, *args, **kwargs):
        if not dev_instance.ip_address:
            raise DeviceImplementationError(gettext("Ip address required"))
        dev_ip_addr = dev_instance.ip_address

        if not dev_instance.man_passw:
            raise DeviceImplementationError(
                gettext(
                    "For fetch additional device info, snmp community required"
                ))
        super().__init__(dev_instance=dev_instance,
                         host=dev_ip_addr,
                         snmp_community=str(dev_instance.man_passw))
예제 #2
0
 def parse_eltex_vlan_map(bitmap: bytes,
                          table: int = 0) -> Generator[int, None, None]:
     """
     https://eltexsl.ru/wp-content/uploads/2016/05/monitoring-i-upravlenie-ethernet-kommutatorami-mes-po-snmp.pdf
     :param bitmap: str bit map vlan representation by Eltex version
     :param table: Value from 0 to 3. In which table can find vlan id list
     :return: VID, vlan id
     >>> bitmap = (\
             '\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\
             '\\x00\\x02\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\
             '\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\
             '\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\
             '\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\
             '\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\
             '\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\
             '\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\
         )
     >>> tuple(EltexSwitch.parse_eltex_vlan_map(bitmap))
     (5, 143, 152)
     """
     assert isinstance(bitmap, bytes)
     if table < 0 or table > 3:
         raise DeviceImplementationError("table must be in range 1-3")
     r = (bin_num == "1" for octet_num in bitmap
          for bin_num in f"{octet_num:08b}")
     return ((numer + 1) + (table * 1024) for numer, bit in enumerate(r)
             if bit)
예제 #3
0
    def get_ports(self) -> tuple:
        # interfaces count
        # yield safe_int(self.get_item('.1.3.6.1.2.1.17.1.2.0'))

        interfaces_ids = self.get_list(".1.3.6.1.2.1.17.1.4.1.2")
        if interfaces_ids is None:
            raise DeviceImplementationError("Switch returned null")
        interfaces_ids = tuple(
            next(interfaces_ids) for _ in range(self.ports_len))

        def build_port(i: int, n: int):
            speed = self.get_item(".1.3.6.1.2.1.2.2.1.5.%d" % n)
            oper_status = safe_int(self.get_item(".1.3.6.1.2.1.2.2.1.7.%d" %
                                                 n)) == 1
            link_status = safe_int(self.get_item(".1.3.6.1.2.1.2.2.1.8.%d" %
                                                 n)) == 1
            ep = EltexPort(
                dev_interface=self,
                num=i + 1,
                snmp_num=n,
                name=self.get_item(".1.3.6.1.2.1.2.2.1.2.%d" % n),  # name
                status=oper_status,  # status
                mac=
                b"",  # self.get_item('.1.3.6.1.2.1.2.2.1.6.%d' % n),    # mac
                speed=0 if not link_status else safe_int(speed),  # speed
                uptime=self.get_item(".1.3.6.1.2.1.2.2.1.9.%d" % n),  # UpTime
            )
            return ep

        return tuple(
            build_port(i, int(n)) for i, n in enumerate(interfaces_ids))
예제 #4
0
    def _toggle_vlan_on_port(self, vlan: Vlan, port: int, member: bool):
        if port > self.ports_len or port < 1:
            raise DeviceImplementationError("Port must be in range 1-%d" %
                                            self.ports_len)

        # if vlan does not exsists on device, then create it
        self._add_vlan_if_not_exists(vlan)

        port_member_tagged = self.get_item(".1.3.6.1.2.1.17.7.1.4.3.1.2.%d" %
                                           vlan.vid)
        port_member_untag = self.get_item(".1.3.6.1.2.1.17.7.1.4.3.1.4.%d" %
                                          vlan.vid)
        if not port_member_tagged or not port_member_untag:
            return False

        port_member_tagged_map = self._make_ports_map(port_member_tagged)
        port_member_untag_map = self._make_ports_map(port_member_untag)
        if member:
            port_member_untag_map[port - 1] = vlan.native
            port_member_tagged_map[port - 1] = True
        else:
            port_member_untag_map[port - 1] = False
            port_member_tagged_map[port - 1] = False

        port_member_tagged = self._make_buf_from_ports_map(
            port_member_tagged_map)
        port_member_untag = self._make_buf_from_ports_map(
            port_member_untag_map)

        return self.set_multiple(oid_values=[
            (".1.3.6.1.2.1.17.7.1.4.3.1.2.%d" % vlan.vid, port_member_tagged,
             "OCTETSTR"),
            (".1.3.6.1.2.1.17.7.1.4.3.1.4.%d" % vlan.vid, port_member_untag,
             "OCTETSTR"),
        ])
예제 #5
0
    def read_port_vlan_info(self, port: int) -> Vlans:
        def _calc_ret(vlan_untagged_egress_oid, vlan_egress_bitmap,
                      table_no) -> Vlans:
            vlan_untagged_egress = self.get_item(vlan_untagged_egress_oid)
            vlan_untagged_egress = list(
                self.parse_eltex_vlan_map(vlan_untagged_egress,
                                          table=table_no))
            is_native = next(
                (v == 1
                 for i, v in enumerate(vlan_untagged_egress, 1) if i >= port),
                False)
            return (Vlan(vid=vid,
                         title=self._get_vid_name(vid=vid),
                         native=is_native)
                    for vid in self.parse_eltex_vlan_map(vlan_egress_bitmap,
                                                         table=table_no))

        if port > self.ports_len or port < 1:
            raise DeviceImplementationError("Port must be in range 1-%d" %
                                            self.ports_len)
        port = port + 48

        # rldot1qPortVlanStaticEgressList1to1024
        vlan_egress = self.get_item("1.3.6.1.4.1.89.48.68.1.1.%d" % port)
        if vlan_egress:
            return _calc_ret(
                # rldot1qPortVlanStaticUntaggedEgressList1to1024
                vlan_untagged_egress_oid="1.3.6.1.4.1.89.48.68.1.5.%d" % port,
                vlan_egress_bitmap=vlan_egress,
                table_no=0,
            )

        # rldot1qPortVlanStaticEgressList1025to2048
        vlan_egress = self.get_item("1.3.6.1.4.1.89.48.68.1.2.%d" % port)
        if vlan_egress:
            return _calc_ret(
                # rldot1qPortVlanStaticUntaggedEgressList1025to2048
                vlan_untagged_egress_oid="1.3.6.1.4.1.89.48.68.1.6.%d" % port,
                vlan_egress_bitmap=vlan_egress,
                table_no=1,
            )
        # rldot1qPortVlanStaticEgressList2049to3072
        vlan_egress = self.get_item("1.3.6.1.4.1.89.48.68.1.3.%d" % port)
        if vlan_egress:
            return _calc_ret(
                # rldot1qPortVlanStaticUntaggedEgressList2049to3072
                vlan_untagged_egress_oid="1.3.6.1.4.1.89.48.68.1.7.%d" % port,
                vlan_egress_bitmap=vlan_egress,
                table_no=2,
            )
        # rldot1qPortVlanStaticEgressList3073to4094
        vlan_egress = self.get_item("1.3.6.1.4.1.89.48.68.1.4.%d" % port)
        if vlan_egress:
            return _calc_ret(
                # rldot1qPortVlanStaticUntaggedEgressList3073to4094
                vlan_untagged_egress_oid="1.3.6.1.4.1.89.48.68.1.8.%d" % port,
                vlan_egress_bitmap=vlan_egress,
                table_no=3,
            )
예제 #6
0
 def scan_ports(self, request, pk=None):
     device = self.get_object()
     manager = device.get_manager_object_switch()
     if not issubclass(manager.__class__, BaseSwitchInterface):
         raise DeviceImplementationError(
             "Expected BaseSwitchInterface subclass")
     ports = manager.get_ports()
     return Response(data=tuple(p.to_dict() for p in ports))
예제 #7
0
    def apply_vlan_config(self, serializer):
        device = self.device
        if not device:
            raise DeviceImplementationError("device could not found")
        port_num = serializer.data.get("port_num")
        if not port_num:
            raise DeviceImplementationError("port_num field required")

        mng = device.get_manager_object_switch()

        vlans_data = serializer.data.get("vlans")
        if not vlans_data:
            raise DeviceImplementationError("vlans field required")

        vlans_gen = (Vlan(**v) for v in vlans_data)

        mng.attach_vlans_to_port(vlan_list=vlans_gen, port_num=port_num)
예제 #8
0
    def attach_vlans_to_port(self, vlan_list: Vlans, port_num: int) -> tuple:
        if port_num > self.ports_len or port_num < 1:
            raise DeviceImplementationError("Port must be in range 1-%d" %
                                            self.ports_len)

        results = tuple(
            self._toggle_vlan_on_port(vlan=v, port=port_num, member=True)
            for v in vlan_list)
        return results
예제 #9
0
 def _make_ports_map(data: AnyStr) -> List[bool]:
     if isinstance(data, bytes):
         data = data[:4]
     else:
         raise DeviceImplementationError(
             "data must be instance of bytes, %s got instead" %
             data.__class__)
     i = int.from_bytes(data, "big")
     return list(v == "1" for v in f"{i:032b}")
예제 #10
0
def remove_from_olt(ip_addr: str, telnet_login: str, telnet_passw: str, telnet_prompt: str, int_name: str):
    if not re.match(expect_util.IP4_ADDR_REGEX, ip_addr):
        raise expect_util.ExpectValidationError("ip address for OLT not valid")

    # Split "EPON0/1:17" for fiber_num - 1, and onu_num - 17
    try:
        fiber_num, onu_num = int_name.split("/")[1].split(":")
        fiber_num, onu_num = safe_int(fiber_num), safe_int(onu_num)
    except (IndexError, ValueError):
        raise DeviceImplementationError("Device interface unexpected")

    if onu_num < 1 or onu_num > 64:
        raise DeviceImplementationError("Onu num must be in range 1-64")

    # Enter
    ch = expect_util.MySpawn("telnet %s" % ip_addr)
    ch.timeout = 15
    ch.expect_exact("Username: "******"Password: "******"Authentication failed!", "%s>" % telnet_prompt])
    if choice == 0:
        raise DeviceConsoleError(gettext("Wrong login or password for telnet access"))

    # enable privileges
    ch.do_cmd("enable", "%s#" % telnet_prompt)

    # enter to config
    ch.do_cmd("config", "%s_config#" % telnet_prompt)

    fiber_prompt = "%s_config_epon0/%d#" % (telnet_prompt, fiber_num)

    # enter to fiber
    ch.do_cmd("int EPON0/%d" % fiber_num, fiber_prompt)

    # unbind onu
    ch.do_cmd("no epon bind-onu sequence %d" % onu_num, fiber_prompt)

    # end removing
    ch.close()
    return True
예제 #11
0
 def scan_units_unregistered(self, request, pk=None):
     device = self.get_object()
     manager = device.get_manager_object_olt()
     if hasattr(manager, "get_fibers"):
         unregistered = []
         for fb in manager.get_fibers():
             for unr in manager.get_units_unregistered(int(
                     fb.get("fb_id"))):
                 unregistered.append(unr)
         return Response(unregistered)
     return DeviceImplementationError(
         "Manager has not get_fibers attribute")
예제 #12
0
 def _set_vlans_on_port(self, vlan_list: Vlans, port_num: int):
     if port_num > self.ports_len or port_num < 1:
         raise DeviceImplementationError("Port must be in range 1-%d" %
                                         self.ports_len)
     port_num = port_num + 48
     vids = (v.vid for v in vlan_list)
     bit_maps = self.make_eltex_map_vlan(vids=vids)
     oids = []
     for tbl_num, bitmap in bit_maps.items():
         oids.append(("1.3.6.1.4.1.89.48.68.1.%d.%d" % (tbl_num, port_num),
                      bitmap, "x"))
     return self.set_multiple(oids)
예제 #13
0
 def read_mac_address_vlan(self, vid: int) -> Macs:
     vid = safe_int(vid)
     if vid > 4095 or vid < 1:
         raise DeviceImplementationError("VID must be in range 1-%d" % 4095)
     fdb = self.get_list_with_oid(".1.3.6.1.2.1.17.7.1.2.2.1.2.%d" % vid)
     vid_name = self._get_vid_name(vid)
     for port_num, oid in fdb:
         fdb_mac = ":".join("%.2x" % int(i) for i in oid[-6:])
         yield MacItem(vid=vid,
                       name=vid_name,
                       mac=fdb_mac,
                       port=safe_int(port_num))
예제 #14
0
 def __init__(self, dev_instance, *args, **kwargs):
     dev_ip_addr = None
     if dev_instance.ip_address:
         dev_ip_addr = dev_instance.ip_address
     else:
         parent_device = dev_instance.parent_dev
         if parent_device is not None and parent_device.ip_address:
             dev_ip_addr = parent_device.ip_address
     if dev_ip_addr is None:
         raise DeviceImplementationError(
             gettext(
                 "Ip address or parent device with ip address required for ONU device"
             ))
     if not dev_instance.man_passw:
         raise DeviceImplementationError(
             gettext(
                 "For fetch additional device info, snmp community required"
             ))
     super().__init__(dev_instance=dev_instance,
                      host=dev_ip_addr,
                      snmp_community=str(dev_instance.man_passw),
                      *args,
                      **kwargs)
예제 #15
0
 def read_mac_address_port(self, port_num: int) -> Macs:
     if port_num > self.ports_len or port_num < 1:
         raise DeviceImplementationError("Port must be in range 1-%d" %
                                         self.ports_len)
     fdb = self.get_list_with_oid(".1.3.6.1.2.1.17.7.1.2.2.1.2")
     for fdb_port, oid in fdb:
         if port_num != int(fdb_port):
             continue
         vid = safe_int(oid[-7:-6][0])
         fdb_mac = ":".join("%.2x" % int(i) for i in oid[-6:])
         vid_name = self._get_vid_name(vid)
         yield MacItem(vid=vid,
                       name=vid_name,
                       mac=fdb_mac,
                       port=safe_int(port_num))
예제 #16
0
    def scan_onu_list(self, request, pk=None):
        device = self.get_object()
        manager = device.get_manager_object_olt()
        if not issubclass(manager.__class__, BasePONInterface):
            raise DeviceImplementationError(
                "Expected BasePONInterface subclass")

        def chunk_cook(chunk: dict) -> bytes:
            chunk_json = json_dumps(chunk,
                                    ensure_ascii=False,
                                    cls=JSONBytesEncoder)
            chunk_json = "%s\n" % chunk_json
            format_string = "{:%ds}" % chunk_max_len
            dat = format_string.format(chunk_json)
            return dat.encode()[:chunk_max_len]

        try:
            onu_list = manager.scan_onu_list()
            item_size = next(onu_list)
            chunk_max_len = next(onu_list)
            r = StreamingHttpResponse(streaming_content=(chunk_cook({
                "number":
                p.num,
                "title":
                p.name,
                "status":
                p.status,
                "mac_addr":
                p.mac,
                "signal":
                p.signal,
                "uptime":
                str(RuTimedelta(seconds=p.uptime / 100)) if p.uptime else None,
                "fiberid":
                p.fiberid,
            }) for p in onu_list))
            r["Content-Length"] = item_size * chunk_max_len
            r["Cache-Control"] = "no-store"
            r["Content-Type"] = "application/octet-stream"
            return r
        except StopIteration:
            pass
        return Response("No all fetched")
예제 #17
0
 def make_eltex_map_vlan(vids: Iterable[int]) -> Dict[int, bytes]:
     """
     https://eltexsl.ru/wp-content/uploads/2016/05/monitoring-i-upravlenie-ethernet-kommutatorami-mes-po-snmp.pdf
     :param vids: Vlan id iterable collection
     :return: bytes bit map vlan representation by Eltex version
              with index of table in dict key
     >>> EltexSwitch.make_eltex_map_vlan([3100])
     {3: b'\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'}
     >>> EltexSwitch.make_eltex_map_vlan([5, 6, 143, 152])
     {0: b'\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02
     \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
     \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'}
     """
     vids = list(vids)
     vids.sort()
     res = {}
     for vid in vids:
         if vid > 4095 or vid < 1:
             raise DeviceImplementationError("VID must be in range 1-%d" %
                                             4095)
         table_no = int(math.floor(vid / 1024))
         vid -= int(math.floor(vid / 1024)) * 1024
         if res.get(table_no) is None:
             res[table_no] = 0
         res[table_no] |= 1 << (1024 - vid)
     for k in res.keys():
         res[k] = res[k].to_bytes(128, "big")
     return res
예제 #18
0
 def read_port_vlan_info(self, port: int) -> Vlans:
     if port > self.ports_len or port < 1:
         raise DeviceImplementationError("Port must be in range 1-%d" %
                                         self.ports_len)
     vid = 1
     while True:
         member_ports, vid = self.get_next_keyval(
             ".1.3.6.1.2.1.17.7.1.4.3.1.2.%d" % vid)
         if not member_ports:
             break
         if isinstance(member_ports, str):
             member_ports = member_ports.encode()
         vid = safe_int(vid)
         if vid in (0, 1):
             break
         member_ports = self._make_ports_map(member_ports[:4])
         if not member_ports[port - 1]:
             continue
         untagged_members = self.get_item("1.3.6.1.2.1.17.7.1.4.3.1.4.%d" %
                                          vid)
         untagged_members = self._make_ports_map(untagged_members[:4])
         name = self._get_vid_name(vid)
         yield Vlan(vid=vid, title=name, native=untagged_members[port - 1])
예제 #19
0
 def read_mac_address_port(self, port_num: int) -> Macs:
     if port_num > self.ports_len or port_num < 1:
         raise DeviceImplementationError("Port must be in range 1-%d" %
                                         self.ports_len)
     try:
         ports_map = {
             int(i): n + 1
             for n, i in enumerate(self.get_list(".1.3.6.1.2.1.2.2.1.1"))
             if int(i) > 0
         }
     except ValueError:
         return
     for fdb_port, oid in self.get_list_with_oid(
             ".1.3.6.1.2.1.17.7.1.2.2.1.2"):
         real_fdb_port_num = ports_map.get(int(fdb_port))
         if port_num != real_fdb_port_num:
             continue
         vid = safe_int(oid[-7:-6][0])
         fdb_mac = ":".join("%.2x" % int(i) for i in oid[-6:])
         vid_name = self._get_vid_name(vid)
         yield MacItem(vid=vid,
                       name=vid_name,
                       mac=fdb_mac,
                       port=real_fdb_port_num)