示例#1
0
    def get_ports(self, o):
        i = 0
        ports = []
        if (o.slice.network in ["host", "bridged"]):
            pass  # no ports in host or bridged mode
        else:
            for port in o.ports.all():
                if (not port.ip):
                    # 'unmanaged' ports may have an ip, but no mac
                    # XXX: are there any ports that have a mac but no ip?
                    raise DeferredException(
                        "Port on network %s is not yet ready" %
                        port.network.name)

                pd = {}
                pd["mac"] = port.mac or ""
                pd["ip"] = port.ip or ""
                pd["xos_network_id"] = port.network.id

                if port.network.name == "wan_network":
                    if port.ip:
                        (a, b, c, d) = port.ip.split('.')
                        pd["mac"] = "02:42:%02x:%02x:%02x:%02x" % (
                            int(a), int(b), int(c), int(d))

                if o.isolation == "container":
                    # container on bare metal
                    instance_port = self.get_instance_port(port)
                    if not instance_port:
                        raise DeferredException(
                            "No instance on slice for port on network %s" %
                            port.network.name)

                    pd["snoop_instance_mac"] = instance_port.mac
                    pd["snoop_instance_id"] = instance_port.instance.instance_id
                    pd["src_device"] = ""
                    pd["bridge"] = "br-int"
                else:
                    # container in VM
                    pd["snoop_instance_mac"] = ""
                    pd["snoop_instance_id"] = ""
                    pd["parent_mac"] = self.get_parent_port_mac(o, port)
                    pd["bridge"] = ""

                for (k, v) in port.get_parameters().items():
                    pd[k] = v

                ports.append(pd)

            # for any ports that don't have a device, assign one
            used_ports = [x["device"] for x in ports if ("device" in x)]
            avail_ports = [
                "eth%d" % i for i in range(0, 64)
                if ("eth%d" % i not in used_ports)
            ]
            for port in ports:
                if not port.get("device", None):
                    port["device"] = avail_ports.pop(0)

        return ports
示例#2
0
    def map_tenant_to_route(self, address_si):
        instance = None
        # Address setup is kind of hacky right now, we'll
        # need to revisit.  The idea is:
        # * Look up the instance corresponding to the address
        # * Look up the node running the instance
        # * Get the "dataPlaneIp" tag, push to the fabric

        sub = self.get_subscriber(address_si)
        if sub:
            instance = sub.instance
        else:
            instance_id = address_si.get_attribute("tenant_for_instance_id")
            instance = Instance.objects.filter(id=instance_id)[0]

        node = instance.node
        dataPlaneIp = node.dataPlaneIp

        if not dataPlaneIp:
            raise DeferredException(
                "No IP found for node %s tenant %s -- skipping" %
                (str(node), str(address_si)))

        data = {
            PREFIX: "%s/32" % address_si.public_ip,
            NEXT_HOP: dataPlaneIp.split('/')[0]
        }

        return data
示例#3
0
    def sync_record(self, o):
        self.log.info("Sync'ing Fabric Crossconnect Service Instance",
                      service_instance=o)

        if (o.policed is None) or (o.policed < o.updated):
            raise DeferredException(
                "Waiting for model_policy to run on fcsi %s" % o.id)

        onos = self.get_fabric_onos_info(o)

        si = ServiceInstance.objects.get(id=o.id)

        if (o.s_tag is None):
            raise Exception(
                "Cannot sync FabricCrossconnectServiceInstance if s_tag is None on fcsi %s"
                % o.id)

        if (o.source_port is None):
            raise Exception(
                "Cannot sync FabricCrossconnectServiceInstance if source_port is None on fcsi %s"
                % o.id)

        if (not o.switch_datapath_id):
            raise Exception(
                "Cannot sync FabricCrossconnectServiceInstance if switch_datapath_id is unset on fcsi %s"
                % o.id)

        bng_mapping = self.find_bng(s_tag=o.s_tag)
        if not bng_mapping:
            raise Exception("Unable to determine BNG port for s_tag %s" %
                            o.s_tag)
        east_port = bng_mapping.switch_port

        data = {
            "deviceId": o.switch_datapath_id,
            "vlanId": o.s_tag,
            "ports": [int(o.source_port), int(east_port)]
        }

        url = onos['url'] + '/onos/segmentrouting/xconnect'

        self.log.info("Sending request to ONOS", url=url, body=data)

        r = requests.post(url,
                          json=data,
                          auth=HTTPBasicAuth(onos['user'], onos['pass']))

        if r.status_code != 200:
            raise Exception(
                "Failed to create fabric crossconnect in ONOS: %s" % r.text)

        # TODO(smbaker): If the o.backend_handle changed, then someone must have changed the
        #   FabricCrossconnectServiceInstance. If so, then we potentially need to clean up the old
        #   entry in ONOS. Furthermore, we might want to also save the two port numbers that we used,
        #   to detect someone changing those.

        o.backend_handle = self.make_handle(o.s_tag, o.switch_datapath_id)
        o.save(update_fields=["backend_handle"])

        self.log.info("ONOS response", res=r.text)
示例#4
0
    def defer_sync(self, o, reason):
        # zdw, 2017-02-18 - is raising the exception here necessary? - seems like
        # it's just logging the same thing twice
        self.log.info("defer object",
                      object=str(o),
                      reason=reason,
                      **o.tologdict())

        raise DeferredException("defer object %s due to %s" % (str(o), reason))
示例#5
0
 def get_parent_port_mac(self, instance, port):
     if not instance.parent:
         raise Exception("instance has no parent")
     for parent_port in instance.parent.ports.all():
         if parent_port.network == port.network:
             if not parent_port.mac:
                 raise DeferredException(
                     "parent port on network %s does not have mac yet" %
                     parent_port.network.name)
             return parent_port.mac
     raise Exception(
         "failed to find corresponding parent port for network %s" %
         port.network.name)
示例#6
0
    def get_onos_netcfg(self, vtn):
        privateGatewayMac = vtn.privateGatewayMac
        localManagementIp = vtn.localManagementIp
        ovsdbPort = vtn.ovsdbPort
        sshPort = vtn.sshPort
        sshUser = vtn.sshUser
        sshKeyFile = vtn.sshKeyFile
        mgmtSubnetBits = vtn.mgmtSubnetBits
        xosEndpoint = vtn.xosEndpoint
        xosUser = vtn.xosUser
        xosPassword = vtn.xosPassword

        controllerPort = vtn.controllerPort
        if ":" in controllerPort:
            (c_hostname, c_port) = controllerPort.split(":",1)
            controllerPort = socket.gethostbyname(c_hostname) + ":" + c_port
        else:
            controllerPort = ":" + controllerPort

        data = {
            "apps" : {
                "org.opencord.vtn" : {
                    "cordvtn" : {
                        "privateGatewayMac" : privateGatewayMac,
                        "localManagementIp": localManagementIp,
                        "ovsdbPort": ovsdbPort,
                        "ssh": {
                            "sshPort": sshPort,
                            "sshUser": sshUser,
                            "sshKeyFile": sshKeyFile
                        },
                        "xos": {
                            "endpoint": xosEndpoint,
                            "user": xosUser,
                            "password": xosPassword
                        },
                        "publicGateways": [],
                        "nodes" : [],
                        "controllers": [controllerPort]
                    }
                }
            }
        }

        # Generate apps->org.opencord.vtn->cordvtn->openstack
        controllers = Controller.objects.all()
        if controllers:
            controller = controllers[0]
            keystone_server = controller.auth_url
            user_name = controller.admin_user
            tenant_name = controller.admin_tenant
            password = controller.admin_password
            openstack = {
                "endpoint": keystone_server,
                "tenant": tenant_name,
                "user": user_name,
                "password": password
            }
            data["apps"]["org.opencord.vtn"]["cordvtn"]["openstack"] = openstack

        # Generate apps->org.opencord.vtn->cordvtn->nodes
        nodes = Node.objects.all()

        for node in nodes:
            try:
                nodeip = socket.gethostbyname(node.name)
            except socket.gaierror:
                log.warn("unable to resolve hostname %s: node will not be added to config"
                            % node.name)
                continue

            try:
                bridgeId = node.bridgeId
                dataPlaneIntf = node.dataPlaneIntf
                dataPlaneIp = node.dataPlaneIp
            except:
                log.error("not adding node %s to the VTN configuration" % node.name)
                continue

            node_dict = {
                "hostname": node.name,
                "hostManagementIp": "%s/%s" % (nodeip, mgmtSubnetBits),
                "bridgeId": bridgeId,
                "dataPlaneIntf": dataPlaneIntf,
                "dataPlaneIp": dataPlaneIp
            }

            # this one is optional
            try:
                node_dict["hostManagementIface"] = node.hostManagementIface
            except AttributeError:
                pass

            data["apps"]["org.opencord.vtn"]["cordvtn"]["nodes"].append(node_dict)

        if not (data["apps"]["org.opencord.vtn"]["cordvtn"]["nodes"]):
            raise DeferredException("Waiting for there to be valid nodes")

        # Generate apps->org.onosproject.cordvtn->cordvtn->publicGateways
        # Pull the gateway information from Address Pool objects
        for ap in AddressPool.objects.all():
            if (not ap.gateway_ip) or (not ap.gateway_mac):
                log.info("Gateway_ip or gateway_mac is blank for addresspool %s. Skipping." % ap)
                continue

            gateway_dict = {
                "gatewayIp": ap.gateway_ip,
                "gatewayMac": ap.gateway_mac
            }
            data["apps"]["org.opencord.vtn"]["cordvtn"]["publicGateways"].append(gateway_dict)

        if not AddressPool.objects.all().exists():
            log.info("No Address Pools present, not adding publicGateways to config")

        return json.dumps(data, indent=4, sort_keys=True)
 def defer_sync(self, o, reason):
     log.info("defer object", object=str(o), reason=reason, **o.tologdict())
     raise DeferredException("defer object %s due to %s" % (str(o), reason))