コード例 #1
0
    def __init__ (self, args, scope) :
        if len (args) > 0 :
            fn = args [0]
            if fn.startswith ('http') :
                f = urllib2.urlopen (fn)
            else :
                f = open (fn)
        else :
            f = sys.stdin

        self.et    = ETree (ElementTree.parse (f))
        self.stati = {}
        self.attrs = {}
        self.scope = scope
        self.links = {} # list of linked interfaces by link id
        self.ffm   = self.scope.FFM
        PAP        = self.scope.PAP
        self.owner = PAP.Person (first_name = "guifi", last_name = "net")
        self.modes = dict \
            ( client = 'Client'
            , ap     = 'AP'
            , ad_hoc = 'Ad_Hoc'
            )
        self.modes [None] = None

        #print self.et.pretty (with_text = 1)
        #print self.et.pretty ()

        self.networks = []
        # Umm: our test data uses lots of addresses in the 178.18.8.0/22
        # range which according to whois belongs to some russion entity.
        # We add this for now.
        # Then there is one address from 178.26.0.0/30 from a range of
        # some german cable provider which we simply ignore.
        for n in ('10.0.0.0/8', '172.16.0.0/12', '178.18.8.0/22') :
            n = self.ffm.IP4_Network (n, owner = self.owner)
            self.networks.append (n)

        self.et.walk (self.insert)
コード例 #2
0
class Convert (object) :

    # this is only for parsing: don't know what legacy is and
    # WiMAX is surely not 802.11n, will have to model this separately if
    # needed.
    protocol_translate = {'legacy' : '802.11b', 'WiMAX' : '802.11n'}

    def __init__ (self, args, scope) :
        if len (args) > 0 :
            fn = args [0]
            if fn.startswith ('http') :
                f = urllib2.urlopen (fn)
            else :
                f = open (fn)
        else :
            f = sys.stdin

        self.et    = ETree (ElementTree.parse (f))
        self.stati = {}
        self.attrs = {}
        self.scope = scope
        self.links = {} # list of linked interfaces by link id
        self.ffm   = self.scope.FFM
        PAP        = self.scope.PAP
        self.owner = PAP.Person (first_name = "guifi", last_name = "net")
        self.modes = dict \
            ( client = 'Client'
            , ap     = 'AP'
            , ad_hoc = 'Ad_Hoc'
            )
        self.modes [None] = None

        #print self.et.pretty (with_text = 1)
        #print self.et.pretty ()

        self.networks = []
        # Umm: our test data uses lots of addresses in the 178.18.8.0/22
        # range which according to whois belongs to some russion entity.
        # We add this for now.
        # Then there is one address from 178.26.0.0/30 from a range of
        # some german cable provider which we simply ignore.
        for n in ('10.0.0.0/8', '172.16.0.0/12', '178.18.8.0/22') :
            n = self.ffm.IP4_Network (n, owner = self.owner)
            self.networks.append (n)

        self.et.walk (self.insert)
        #self.et.walk (self.record_attributes)
    # end def __init__

    def record_status (self, parent, child) :
        """ Callback routine for walk to record existing status or
            link_status fields.
        """
        s = child.get ('status')
        if not s :
            s = child.get ('link_status')
        if s :
            self.stati [s] = 1
    # end def record_status

    def record_attributes (self, parent, child) :
        """ Callback routine for walk to record attributes (with tag).
        """
        for n in child.attrib :
            self.attrs ['.'.join ((child.tag, n))] = 1
    # end def record_attributes

    def insert_node (self, element) :
        """ Insert a node.
        """
        name = '-'.join ((element.get ('title'), element.get ('id')))
        pos  = dict (lat = element.get ('lat'), lon = element.get ('lon'))
        node = self.ffm.Node \
            (name = name, position = pos, manager = self.owner, raw = True)
        for n in element :
            if n.tag == 'device' :
                self.insert_device (node, n)
            else :
                raise ValueError, "Unknown tag in node: %s" % n.tag
        MOM = self.scope.MOM
        url = 'https://guifi.net/node/%s/' % element.get ('id')
        dsc = 'Link to guifi.net node database'
        MOM.Document (node, url = url, type = 'NodeDB', desc = dsc)
        self.scope.commit ()
    # end insert_node

    def insert_device (self, node, element) :
        """ Insert a device (aka Net_Device)
            Note: guifi.net seems to use the 'name' attribute as the
            device_type (names repeat for devices while the title
            seems to be stable). For now use the name as the name
            of the Net_Device_Type.
        """
        devname = element.get ('name')
        name    = element.get ('title')
        if not devname :
            t = self.ffm.Net_Device_Type.instance (name = "Generic", raw = True)
        else :
            t = self.ffm.Net_Device_Type.instance_or_new \
                (name = devname, raw = True)
        dev = self.ffm.Net_Device \
            (left = t, node = node, name = name, raw = True)
        for nif in element :
            if nif.tag == 'radio' :
                self.insert_radio (dev, nif)
            elif nif.tag == 'interface' :
                self.insert_wired_interface (dev, nif)
            elif nif.tag == 'service' :
                pass # FIXME
            else :
                raise ValueError, "Unknown tag in device: %s" % nif.tag
    # end def insert_device

    def insert_links (self, interface, element) :
        """ Links between interfaces.
        """
        for n in element :
            if n.tag == 'link' :
                # linked_interface_id is bogus in guifi cnml, seems to
                # contain the node id, not the id of the other linked
                # interface
                #r_id  = n.get ('linked_interface_id')
                name  = n.get ('id')
                if name in self.links :
                    assert (len (self.links [name]) == 1)
                    r_id = self.links [name][0]
                    self.links [name].append (element.get ('id'))
                    left  = interface
                    right = self.ffm.Net_Interface.query (name = r_id).one ()
                    self.ffm.Net_Link (left, right)
                else :
                    self.links [name] = [element.get ('id')]
            else :
                raise ValueError, "Unknown node type in interface %s" % n.tag
    # end def insert_links

    def insert_ip_network (self, interface, ip, mask) :
        net = IP4_Address (ip, mask)
        adr = IP4_Address (ip)
        assert (adr in net)
        netadr = self.ffm.IP4_Network.instance (adr)
        if netadr and not netadr.is_free :
            ni = self.ffm.Net_Interface_in_IP4_Network.instance \
                (interface, netadr, mask_len = net.mask)
            assert (ni)
        else :
            n = [x for x in self.networks if net in x.net_address]
            if len (n) < 1 :
                print >> sys.stderr, 'Warning: ignoring address %s' % net
                return
            assert len (n) == 1
            n = n [0]
            try :
                network = n.reserve (net, self.owner)
            except FFM.Error.Address_Already_Used :
                network = self.ffm.IP4_Network.instance (net)
            netadr  = n.reserve (adr, self.owner)
            try :
               self.ffm.Net_Interface_in_IP4_Network \
                   (interface, netadr, mask_len = net.mask)
            except Exception as exc :
                print >> sys.stderr, "Warning: broken IP triggers: %s" % exc
    # end def insert_ip_network

    def insert_wired_interface (self, device, element) :
        mac  = fix_mac (element.get ('mac'))
        name = element.get ('id')
        wif  = self.ffm._Wireless_Interface_.instance \
            ( left        = device
            , name        = name
            , mac_address = mac
            , raw         = True
            )
        if wif :
            # CNML seems to have interfaces that are child of a radio
            # and are repeated on the device-level. Fortunately they seem
            # to always be in the right order (radio parent first).
            # Since there is no good way to distinguish wired from
            # wirelesse interfaces we're using the ones that have a
            # radio as parent for the wireless interfaces.
            assert (wif.mac_address == mac)
            return
        nif  = self.ffm.Wired_Interface.instance \
            ( left        = device
            , name        = name
            , mac_address = mac
            , raw         = True
            )
        if nif :
            assert (nif.mac_address == mac)
        else :
            nif  = self.ffm.Wired_Interface \
                ( left        = device
                , name        = name
                , mac_address = mac
                , raw         = True
                )
            assert (nif.mac_address == mac)
        self.insert_links (nif, element)
        ipv4 = element.get ('ipv4')
        mask = element.get ('mask')
        if ipv4 and mask :
            self.insert_ip_network (nif, ipv4, mask)
        return nif
    # end def insert_wired_interface

    def insert_wireless_interface \
            (self, device, radio, element, antenna, master) :
        mac  = fix_mac (element.get ('mac'))
        ssid = radio.get ('ssid')
        if ssid and len (ssid) > 32 :
            print >> sys.stderr, 'Warning ssid "%s" too long, shortened' % ssid
            ssid = ssid [:32]
        # an interface may have more than one IP address and occur
        # multiple times in the XML
        name  = element.get ('id')
        mode  = element.get ('mode')
        prot  = radio.get ('protocol')
        if prot :
            prot = self.protocol_translate.get (prot, prot)
        std   = self.ffm.Wireless_Standard.instance (prot, raw = True)
        param = dict \
            ( left        = device
            , name        = name
            , essid       = ssid
            , mac_address = mac
            , mode        = self.modes [mode]
            , raw         = True
            )
        wif = self.ffm.Wireless_Interface.instance (** param)
        if master and wif is None :
            wif = self.ffm.Virtual_Wireless_Interface.instance \
                (hardware = master, ** param)
        if wif :
            assert (wif.essid                 == ssid)
            assert (wif.mac_address           == mac)
        else :
            if master :
                wif = self.ffm.Virtual_Wireless_Interface \
                    (hardware = master, ** param)
            else :
                wif = self.ffm.Wireless_Interface (standard = std, ** param)
                self.ffm.Wireless_Interface_uses_Antenna.instance_or_new \
                    (wif, antenna, raw = True)
            assert (wif.mac_address == mac)
        self.insert_links (wif, element)
        ipv4 = element.get ('ipv4')
        mask = element.get ('mask')
        if ipv4 and mask :
            self.insert_ip_network (wif, ipv4, mask)
        return wif
    # end def insert_wireless_interface

    def insert_radio (self, device, element) :
        """ Insert a radio.
            guifi.net lumps all antenna and antenna_type parameters
            into the radio. No reuse of antenna types and antenna (!)
            we create an antenna_type name from the antenna
            parameters, create an antenna and create a network
            interface.
        """
        id   = element.get ('id')
        gn   = element.get ('antenna_gain') or '0'
        p    = dict \
            ( name        = gn
            , gain        = gn
            , raw         = True
            )
        antt = self.ffm.Antenna_Type.instance (** p)
        if not antt :
            antt = self.ffm.Antenna_Type (** p)
            band = self.ffm.Antenna_Band \
                ( antt
                , band = dict (lower = "1 Hz", upper = "1 THz")
                , raw = True
                )
        angle = element.get ('antenna_angle')
        elev  = None
        if angle :
            elev = str (90 - (int (angle) % 360))
        ant  = self.ffm.Antenna.instance_or_new \
            ( left            = antt
            , name            = '.'.join ((id, element.get ('device_id')))
            , azimuth         = element.get ('antenna_azimuth') or '0'
            # orientation     = element.get ('antenna_angle') FIXME: polarisation?
            , elevation_angle = elev
            , raw             = True
            )
        # FIXME: First check if there are multiple (wireless)
        # interfaces. If yes, we want one wireless interface with
        # several virtual interfaces
        wif = None
        for n in element :
            if n.tag == 'interface' :
                w = self.insert_wireless_interface \
                    (device, element, n, ant, wif)
                if not wif :
                    wif = w
            else :
                raise ValueError, "Unknown node type in radio: %s" % n.tag
    # end def insert_radio

    def insert (self, parent, child) :
        """ Insert given node into the database """
        if child.tag in ('network', 'zone') :
            return
        if child.tag == 'node' :
            self.insert_node (child)