Exemplo n.º 1
0
        def process_bridge(buuid, uo):
            try:
                nv = uo['new']
                if 'datapath_id' in nv:
                    if ovsdb.getoptional(nv['datapath_id']) is None:
                        # This bridge is not initialized. Wait for the bridge to be initialized.
                        for m in callAPI(
                                self.apiroutine, 'ovsdbmanager', 'waitbridge',
                            {
                                'connection': connection,
                                'name': nv['name'],
                                'timeout': 5
                            }):
                            yield m
                        datapath_id = self.apiroutine.retvalue
                    else:
                        datapath_id = int(nv['datapath_id'], 16)
                    self.bridge_datapathid[buuid] = datapath_id
                elif buuid in self.bridge_datapathid:
                    datapath_id = self.bridge_datapathid[buuid]
                else:
                    # This should not happen, but just in case...
                    for m in callAPI(self.apiroutine, 'ovsdbmanager',
                                     'waitbridge', {
                                         'connection': connection,
                                         'name': nv['name'],
                                         'timeout': 5
                                     }):
                        yield m
                    datapath_id = self.apiroutine.retvalue
                    self.bridge_datapathid[buuid] = datapath_id
                if 'ports' in nv:
                    nset = set((p for _, p in ovsdb.getlist(nv['ports'])))
                else:
                    nset = set()
                if 'old' in uo:
                    ov = uo['old']
                    if 'ports' in ov:
                        oset = set((p for _, p in ovsdb.getlist(ov['ports'])))
                    else:
                        # new ports are not really added; it is only sent because datapath_id is modified
                        nset = set()
                        oset = set()
                    if 'datapath_id' in ov and ovsdb.getoptional(
                            ov['datapath_id']) is not None:
                        old_datapathid = int(ov['datapath_id'], 16)
                    else:
                        old_datapathid = datapath_id
                else:
                    oset = set()
                    old_datapathid = datapath_id
                # For every deleted port, remove the interfaces with this port _uuid
                remove = []
                add_routine = []
                for puuid in oset - nset:
                    remove += self._remove_all_interface(
                        connection, protocol, old_datapathid, puuid, buuid)
                # For every port not changed, check if the interfaces are modified;
                for puuid in oset.intersection(nset):
                    if puuid in port_update:
                        # The port is modified, there should be an 'old' set and 'new' set
                        pu = port_update[puuid]
                        if 'old' in pu:
                            poset = set((p for _, p in ovsdb.getlist(
                                pu['old']['interfaces'])))
                        else:
                            poset = set()
                        if 'new' in pu:
                            pnset = set((p for _, p in ovsdb.getlist(
                                pu['new']['interfaces'])))
                        else:
                            pnset = set()
                        # Remove old interfaces
                        remove += [
                            r for r in (self._remove_interface(
                                connection, protocol, datapath_id, iuuid,
                                puuid) for iuuid in (poset - pnset))
                            if r is not None
                        ]
                        # Prepare to add new interfaces
                        add_routine += [
                            self._get_interface_info(connection, protocol,
                                                     buuid, iuuid, puuid)
                            for iuuid in (pnset - poset)
                        ]
                # For every port added, add the interfaces
                def add_port_interfaces(puuid):
                    # If the uuid does not appear in update info, we have no choice but to query interfaces with select
                    # we cannot use data from other bridges; the port may be moved from a bridge which is not tracked
                    try:
                        method, params = ovsdb.transact(
                            'Open_vSwitch',
                            ovsdb.select('Port',
                                         [["_uuid", "==",
                                           ovsdb.uuid(puuid)]],
                                         ["interfaces"]))
                        for m in protocol.querywithreply(
                                method, params, connection, self.apiroutine):
                            yield m
                        r = self.apiroutine.jsonrpc_result[0]
                        if 'error' in r:
                            raise JsonRPCErrorResultException(
                                'Error when query interfaces from port ' +
                                repr(puuid) + ': ' + r['error'])
                        if r['rows']:
                            interfaces = ovsdb.getlist(
                                r['rows'][0]['interfaces'])
                            with closing(
                                    self.apiroutine.executeAll([
                                        self._get_interface_info(
                                            connection, protocol, buuid, iuuid,
                                            puuid) for _, iuuid in interfaces
                                    ])) as g:
                                for m in g:
                                    yield m
                            self.apiroutine.retvalue = list(
                                itertools.chain(
                                    r[0] for r in self.apiroutine.retvalue))
                        else:
                            self.apiroutine.retvalue = []
                    except JsonRPCProtocolException:
                        self.apiroutine.retvalue = []
                    except ConnectionResetException:
                        self.apiroutine.retvalue = []

                for puuid in nset - oset:
                    self.ports_uuids[puuid] = buuid
                    if puuid in port_update and 'new' in port_update[puuid] \
                            and 'old' not in port_update[puuid]:
                        # Add all the interfaces in 'new'
                        interfaces = ovsdb.getlist(
                            port_update[puuid]['new']['interfaces'])
                        add_routine += [
                            self._get_interface_info(connection, protocol,
                                                     buuid, iuuid, puuid)
                            for _, iuuid in interfaces
                        ]
                    else:
                        add_routine.append(add_port_interfaces(puuid))
                # Execute the add_routine
                try:
                    with closing(self.apiroutine.executeAll(add_routine)) as g:
                        for m in g:
                            yield m
                except:
                    add = []
                    raise
                else:
                    add = list(
                        itertools.chain(r[0]
                                        for r in self.apiroutine.retvalue))
                finally:
                    if update:
                        self.scheduler.emergesend(
                            ModuleNotification(self.getServiceName(),
                                               'update',
                                               datapathid=datapath_id,
                                               connection=connection,
                                               vhost=protocol.vhost,
                                               add=add,
                                               remove=remove,
                                               reason='bridgemodify'
                                               if 'old' in uo else 'bridgeup'))
            except JsonRPCProtocolException:
                pass
            except ConnectionResetException:
                pass
            except OVSDBBridgeNotAppearException:
                pass
Exemplo n.º 2
0
 def _get_interface_info(self, connection, protocol, buuid, interface_uuid,
                         port_uuid):
     try:
         method, params = ovsdb.transact(
             'Open_vSwitch',
             ovsdb.wait(
                 'Interface',
                 [["_uuid", "==", ovsdb.uuid(interface_uuid)]], ["ofport"],
                 [{
                     "ofport": ovsdb.oset()
                 }], False, 5000),
             ovsdb.wait(
                 'Interface',
                 [["_uuid", "==", ovsdb.uuid(interface_uuid)]], ["ofport"],
                 [{
                     "ofport": -1
                 }], False, 0),
             ovsdb.wait(
                 'Interface',
                 [["_uuid", "==", ovsdb.uuid(interface_uuid)]], ["ifindex"],
                 [{
                     "ifindex": ovsdb.oset()
                 }], False, 5000),
             ovsdb.select(
                 'Interface',
                 [["_uuid", "==", ovsdb.uuid(interface_uuid)]], [
                     "_uuid", "name", "ifindex", "ofport", "type",
                     "external_ids"
                 ]))
         for m in protocol.querywithreply(method, params, connection,
                                          self.apiroutine):
             yield m
         r = self.apiroutine.jsonrpc_result[0]
         if 'error' in r:
             raise JsonRPCErrorResultException(
                 'Error while acquiring interface: ' + repr(r['error']))
         r = self.apiroutine.jsonrpc_result[1]
         if 'error' in r:
             raise JsonRPCErrorResultException(
                 'Error while acquiring interface: ' + repr(r['error']))
         r = self.apiroutine.jsonrpc_result[2]
         if 'error' in r:
             # Ignore this port because it is in an error state
             self.apiroutine.retvalue = []
             return
         r = self.apiroutine.jsonrpc_result[3]
         if 'error' in r:
             raise JsonRPCErrorResultException(
                 'Error while acquiring interface: ' + repr(r['error']))
         if not r['rows']:
             self.apiroutine.retvalue = []
             return
         r0 = r['rows'][0]
         if r0['ofport'] < 0:
             # Ignore this port because it is in an error state
             self.apiroutine.retvalue = []
             return
         r0['_uuid'] = r0['_uuid'][1]
         r0['ifindex'] = ovsdb.getoptional(r0['ifindex'])
         r0['external_ids'] = ovsdb.getdict(r0['external_ids'])
         if buuid not in self.bridge_datapathid:
             self.apiroutine.retvalue = []
             return
         else:
             datapath_id = self.bridge_datapathid[buuid]
         if 'iface-id' in r0['external_ids']:
             eid = r0['external_ids']['iface-id']
             r0['id'] = eid
             id_ports = self.managed_ids.setdefault((protocol.vhost, eid),
                                                    [])
             id_ports.append((datapath_id, r0))
         else:
             r0['id'] = None
         self.managed_ports.setdefault((protocol.vhost, datapath_id),
                                       []).append((port_uuid, r0))
         notify = False
         if (protocol.vhost, datapath_id,
                 r0['ofport']) in self.wait_portnos:
             notify = True
             del self.wait_portnos[(protocol.vhost, datapath_id,
                                    r0['ofport'])]
         if (protocol.vhost, datapath_id, r0['name']) in self.wait_names:
             notify = True
             del self.wait_names[(protocol.vhost, datapath_id, r0['name'])]
         if (protocol.vhost, r0['id']) in self.wait_ids:
             notify = True
             del self.wait_ids[(protocol.vhost, r0['id'])]
         if notify:
             for m in self.apiroutine.waitForSend(
                     OVSDBPortUpNotification(connection,
                                             r0['name'],
                                             r0['ofport'],
                                             r0['id'],
                                             protocol.vhost,
                                             datapath_id,
                                             port=r0)):
                 yield m
         self.apiroutine.retvalue = [r0]
     except JsonRPCProtocolException:
         self.apiroutine.retvalue = []
Exemplo n.º 3
0
 def _get_interface_info(self, connection, protocol, buuid, interface_uuid, port_uuid):
     try:
         method, params = ovsdb.transact('Open_vSwitch',
                                         ovsdb.wait('Interface', [["_uuid", "==", ovsdb.uuid(interface_uuid)]],
                                                    ["ofport"], [{"ofport":ovsdb.oset()}], False, 5000),
                                         ovsdb.wait('Interface', [["_uuid", "==", ovsdb.uuid(interface_uuid)]],
                                                    ["ifindex"], [{"ifindex":ovsdb.oset()}], False, 5000),
                                         ovsdb.select('Interface', [["_uuid", "==", ovsdb.uuid(interface_uuid)]],
                                                                      ["_uuid", "name", "ifindex", "ofport", "type", "external_ids"]))
         for m in protocol.querywithreply(method, params, connection, self.apiroutine):
             yield m
         r = self.apiroutine.jsonrpc_result[0]
         if 'error' in r:
             raise JsonRPCErrorResultException('Error while acquiring interface: ' + repr(r['error']))            
         r = self.apiroutine.jsonrpc_result[1]
         if 'error' in r:
             raise JsonRPCErrorResultException('Error while acquiring interface: ' + repr(r['error']))            
         r = self.apiroutine.jsonrpc_result[2]
         if 'error' in r:
             raise JsonRPCErrorResultException('Error while acquiring interface: ' + repr(r['error']))
         if not r['rows']:
             self.apiroutine.retvalue = []
             return
         r0 = r['rows'][0]
         if r0['ofport'] < 0:
             # Ignore this port because it is in an error state
             self.apiroutine.retvalue = []
             return
         r0['_uuid'] = r0['_uuid'][1]
         r0['ifindex'] = ovsdb.getoptional(r0['ifindex'])
         r0['external_ids'] = ovsdb.getdict(r0['external_ids'])
         if buuid not in self.bridge_datapathid:
             self.apiroutine.retvalue = []
             return
         else:
             datapath_id = self.bridge_datapathid[buuid]
         if 'iface-id' in r0['external_ids']:
             eid = r0['external_ids']['iface-id']
             r0['id'] = eid
             id_ports = self.managed_ids.setdefault((protocol.vhost, eid), [])
             id_ports.append((datapath_id, r0))
         else:
             r0['id'] = None
         self.managed_ports.setdefault((protocol.vhost, datapath_id),[]).append((port_uuid, r0))
         notify = False
         if (protocol.vhost, datapath_id, r0['ofport']) in self.wait_portnos:
             notify = True
             del self.wait_portnos[(protocol.vhost, datapath_id, r0['ofport'])]
         if (protocol.vhost, datapath_id, r0['name']) in self.wait_names:
             notify = True
             del self.wait_names[(protocol.vhost, datapath_id, r0['name'])]
         if (protocol.vhost, r0['id']) in self.wait_ids:
             notify = True
             del self.wait_ids[(protocol.vhost, r0['id'])]
         if notify:
             for m in self.apiroutine.waitForSend(OVSDBPortUpNotification(connection, r0['name'],
                                                                          r0['ofport'], r0['id'],
                                                                          protocol.vhost, datapath_id,
                                                                          port = r0)):
                 yield m
         self.apiroutine.retvalue = [r0]
     except JsonRPCProtocolException:
         self.apiroutine.retvalue = []