Exemple #1
0
def _lsn_port_configure_action(cluster, lsn_id, lsn_port_id, action, is_enabled, obj):
    nsxlib.do_request(
        HTTP_PUT,
        nsxlib._build_uri_path(LSERVICESNODE_RESOURCE, resource_id=lsn_id, extra_action=action),
        jsonutils.dumps({"enabled": is_enabled}),
        cluster=cluster,
    )
    nsxlib.do_request(
        HTTP_PUT,
        nsxlib._build_uri_path(
            LSERVICESNODEPORT_RESOURCE, parent_resource_id=lsn_id, resource_id=lsn_port_id, extra_action=action
        ),
        jsonutils.dumps(obj),
        cluster=cluster,
    )
Exemple #2
0
def create_lport(cluster, lswitch_uuid, tenant_id, neutron_port_id,
                 display_name, device_id, admin_status_enabled,
                 mac_address=None, fixed_ips=None, port_security_enabled=None,
                 security_profiles=None, queue_id=None,
                 mac_learning_enabled=None, allowed_address_pairs=None):
    """Creates a logical port on the assigned logical switch."""
    display_name = utils.check_and_truncate(display_name)
    lport_obj = dict(
        admin_status_enabled=admin_status_enabled,
        display_name=display_name,
        tags=utils.get_tags(os_tid=tenant_id,
                            q_port_id=neutron_port_id,
                            vm_id=utils.device_id_to_vm_id(device_id))
    )

    _configure_extensions(lport_obj, mac_address, fixed_ips,
                          port_security_enabled, security_profiles,
                          queue_id, mac_learning_enabled,
                          allowed_address_pairs)

    path = nsxlib._build_uri_path(LSWITCHPORT_RESOURCE,
                                  parent_resource_id=lswitch_uuid)
    result = nsxlib.do_request(HTTP_POST, path, jsonutils.dumps(lport_obj),
                               cluster=cluster)

    LOG.debug("Created logical port %(result)s on logical switch %(uuid)s",
              {'result': result['uuid'], 'uuid': lswitch_uuid})
    return result
Exemple #3
0
 def test_cluster_method_not_implemented(self):
     self.assertRaises(api_exc.NsxApiException,
                       nsxlib.do_request,
                       nsxlib.HTTP_GET,
                       nsxlib._build_uri_path('MY_FAKE_RESOURCE',
                                              resource_id='foo'),
                       cluster=self.fake_cluster)
Exemple #4
0
def create_lqueue(cluster, queue_data):
    params = {
        'name': 'display_name',
        'qos_marking': 'qos_marking',
        'min': 'min_bandwidth_rate',
        'max': 'max_bandwidth_rate',
        'dscp': 'dscp'
    }
    queue_obj = dict(
        (nsx_name, queue_data.get(api_name))
        for api_name, nsx_name in params.iteritems()
        if attr.is_attr_set(queue_data.get(api_name))
    )
    if 'display_name' in queue_obj:
        queue_obj['display_name'] = utils.check_and_truncate(
            queue_obj['display_name'])

    queue_obj['tags'] = utils.get_tags()
    try:
        return nsxlib.do_request(HTTP_POST,
                                 nsxlib._build_uri_path(LQUEUE_RESOURCE),
                                 jsonutils.dumps(queue_obj),
                                 cluster=cluster)['uuid']
    except api_exc.NsxApiException:
        # FIXME(salv-orlando): This should not raise NeutronException
        with excutils.save_and_reraise_exception():
            raise exception.NeutronException()
Exemple #5
0
 def test_build_uri_path_with_filters(self):
     filters = {"tag": 'foo', "tag_scope": "scope_foo"}
     result = nsxlib._build_uri_path('RESOURCE', filters=filters)
     expected = (
         "%s/%s?tag_scope=scope_foo&tag=foo" %
         (nsxlib.URI_PREFIX, 'RESOURCE'))
     self.assertEqual(expected, result)
Exemple #6
0
def update_security_profile(cluster, spid, name):
    return do_request(HTTP_PUT,
                      _build_uri_path(SECPROF_RESOURCE, resource_id=spid),
                      json.dumps({
                          "display_name": utils.check_and_truncate(name)
                      }),
                      cluster=cluster)
Exemple #7
0
def plug_interface(cluster, lswitch_id, lport_id, att_obj):
    return nsxlib.do_request(HTTP_PUT,
                             nsxlib._build_uri_path(LSWITCHPORT_RESOURCE,
                                                    lport_id, lswitch_id,
                                                    is_attachment=True),
                             jsonutils.dumps(att_obj),
                             cluster=cluster)
Exemple #8
0
def create_l2_gw_service(cluster, tenant_id, display_name, devices):
    """Create a NSX Layer-2 Network Gateway Service.

        :param cluster: The target NSX cluster
        :param tenant_id: Identifier of the Openstack tenant for which
        the gateway service.
        :param display_name: Descriptive name of this gateway service
        :param devices: List of transport node uuids (and network
        interfaces on them) to use for the network gateway service
        :raise NsxApiException: if there is a problem while communicating
        with the NSX controller
    """
    # NOTE(salvatore-orlando): This is a little confusing, but device_id in
    # NSX is actually the identifier a physical interface on the gateway
    # device, which in the Neutron API is referred as interface_name
    gateways = [{"transport_node_uuid": device['id'],
                 "device_id": device['interface_name'],
                 "type": "L2Gateway"} for device in devices]
    gwservice_obj = {
        "display_name": utils.check_and_truncate(display_name),
        "tags": utils.get_tags(os_tid=tenant_id),
        "gateways": gateways,
        "type": "L2GatewayServiceConfig"
    }
    return do_request(
        "POST", _build_uri_path(GWSERVICE_RESOURCE),
        json.dumps(gwservice_obj), cluster=cluster)
Exemple #9
0
def query_lrouter_lports(cluster, lr_uuid, fields="*",
                         filters=None, relations=None):
    uri = nsxlib._build_uri_path(LROUTERPORT_RESOURCE,
                                 parent_resource_id=lr_uuid,
                                 fields=fields, filters=filters,
                                 relations=relations)
    return nsxlib.do_request(HTTP_GET, uri, cluster=cluster)['results']
Exemple #10
0
def get_port_by_neutron_tag(cluster, lswitch_uuid, neutron_port_id):
    """Get port by neutron tag.

    Returns the NSX UUID of the logical port with tag q_port_id equal to
    neutron_port_id or None if the port is not Found.
    """
    uri = nsxlib._build_uri_path(LSWITCHPORT_RESOURCE,
                                 parent_resource_id=lswitch_uuid,
                                 fields='uuid',
                                 filters={'tag': neutron_port_id,
                                          'tag_scope': 'q_port_id'})
    LOG.debug("Looking for port with q_port_id tag '%(neutron_port_id)s' "
              "on: '%(lswitch_uuid)s'",
              {'neutron_port_id': neutron_port_id,
               'lswitch_uuid': lswitch_uuid})
    res = nsxlib.do_request(HTTP_GET, uri, cluster=cluster)
    num_results = len(res["results"])
    if num_results >= 1:
        if num_results > 1:
            LOG.warn(_LW("Found '%(num_ports)d' ports with "
                         "q_port_id tag: '%(neutron_port_id)s'. "
                         "Only 1 was expected."),
                     {'num_ports': num_results,
                      'neutron_port_id': neutron_port_id})
        return res["results"][0]
Exemple #11
0
def get_lrouter(cluster, lrouter_id):
    return nsxlib.do_request(HTTP_GET,
                             nsxlib._build_uri_path(
                                 LROUTER_RESOURCE,
                                 resource_id=lrouter_id,
                                 relations='LogicalRouterStatus'),
                             cluster=cluster)
Exemple #12
0
def query_lrouters(cluster, fields=None, filters=None):
    return nsxlib.get_all_query_pages(
        nsxlib._build_uri_path(LROUTER_RESOURCE,
                               fields=fields,
                               relations='LogicalRouterStatus',
                               filters=filters),
        cluster)
Exemple #13
0
def create_gateway_device(
    cluster, tenant_id, display_name, neutron_id, tz_uuid, connector_type, connector_ip, client_certificate
):
    body = _build_gateway_device_body(
        tenant_id, display_name, neutron_id, connector_type, connector_ip, client_certificate, tz_uuid
    )
    return do_request(HTTP_POST, _build_uri_path(TRANSPORTNODE_RESOURCE), json.dumps(body), cluster=cluster)
Exemple #14
0
def create_router_lport(cluster, lrouter_uuid, tenant_id, neutron_port_id,
                        display_name, admin_status_enabled, ip_addresses,
                        mac_address=None):
    """Creates a logical port on the assigned logical router."""
    lport_obj = dict(
        admin_status_enabled=admin_status_enabled,
        display_name=display_name,
        tags=utils.get_tags(os_tid=tenant_id, q_port_id=neutron_port_id),
        ip_addresses=ip_addresses,
        type="LogicalRouterPortConfig"
    )
    # Only add the mac_address to lport_obj if present. This is because
    # when creating the fake_ext_gw there is no mac_address present.
    if mac_address:
        lport_obj['mac_address'] = mac_address
    path = nsxlib._build_uri_path(LROUTERPORT_RESOURCE,
                                  parent_resource_id=lrouter_uuid)
    result = nsxlib.do_request(HTTP_POST, path, jsonutils.dumps(lport_obj),
                               cluster=cluster)

    LOG.debug("Created logical port %(lport_uuid)s on "
              "logical router %(lrouter_uuid)s",
              {'lport_uuid': result['uuid'],
               'lrouter_uuid': lrouter_uuid})
    return result
Exemple #15
0
def get_lswitches(cluster, neutron_net_id):

    def lookup_switches_by_tag():
        # Fetch extra logical switches
        lswitch_query_path = nsxlib._build_uri_path(
            LSWITCH_RESOURCE,
            fields="uuid,display_name,tags,lport_count",
            relations="LogicalSwitchStatus",
            filters={'tag': neutron_net_id,
                     'tag_scope': 'quantum_net_id'})
        return nsxlib.get_all_query_pages(lswitch_query_path, cluster)

    lswitch_uri_path = nsxlib._build_uri_path(LSWITCH_RESOURCE, neutron_net_id,
                                              relations="LogicalSwitchStatus")
    results = []
    try:
        ls = nsxlib.do_request(HTTP_GET, lswitch_uri_path, cluster=cluster)
        results.append(ls)
        for tag in ls['tags']:
            if (tag['scope'] == "multi_lswitch" and
                tag['tag'] == "True"):
                results.extend(lookup_switches_by_tag())
    except exception.NotFound:
        # This is legit if the neutron network was created using
        # a post-Havana version of the plugin
        results.extend(lookup_switches_by_tag())
    if results:
        return results
    else:
        raise exception.NetworkNotFound(net_id=neutron_net_id)
Exemple #16
0
def update_router_lport(cluster, lrouter_uuid, lrouter_port_uuid,
                        tenant_id, neutron_port_id, display_name,
                        admin_status_enabled, ip_addresses):
    """Updates a logical port on the assigned logical router."""
    lport_obj = dict(
        admin_status_enabled=admin_status_enabled,
        display_name=display_name,
        tags=utils.get_tags(os_tid=tenant_id, q_port_id=neutron_port_id),
        ip_addresses=ip_addresses,
        type="LogicalRouterPortConfig"
    )
    # Do not pass null items to NSX
    for key in lport_obj.keys():
        if lport_obj[key] is None:
            del lport_obj[key]
    path = nsxlib._build_uri_path(LROUTERPORT_RESOURCE,
                                  lrouter_port_uuid,
                                  parent_resource_id=lrouter_uuid)
    result = nsxlib.do_request(HTTP_PUT, path,
                               jsonutils.dumps(lport_obj),
                               cluster=cluster)
    LOG.debug("Updated logical port %(lport_uuid)s on "
              "logical router %(lrouter_uuid)s",
              {'lport_uuid': lrouter_port_uuid, 'lrouter_uuid': lrouter_uuid})
    return result
Exemple #17
0
def plug_router_port_attachment(cluster, router_id, port_id,
                                attachment_uuid, nsx_attachment_type,
                                attachment_vlan=None):
    """Attach a router port to the given attachment.

    Current attachment types:
       - PatchAttachment [-> logical switch port uuid]
       - L3GatewayAttachment [-> L3GatewayService uuid]
    For the latter attachment type a VLAN ID can be specified as well.
    """
    uri = nsxlib._build_uri_path(LROUTERPORT_RESOURCE, port_id, router_id,
                                 is_attachment=True)
    attach_obj = {}
    attach_obj["type"] = nsx_attachment_type
    if nsx_attachment_type == "PatchAttachment":
        attach_obj["peer_port_uuid"] = attachment_uuid
    elif nsx_attachment_type == "L3GatewayAttachment":
        attach_obj["l3_gateway_service_uuid"] = attachment_uuid
        if attachment_vlan:
            attach_obj['vlan_id'] = attachment_vlan
    else:
        raise nsx_exc.InvalidAttachmentType(
            attachment_type=nsx_attachment_type)
    return nsxlib.do_request(
        HTTP_PUT, uri, jsonutils.dumps(attach_obj), cluster=cluster)
Exemple #18
0
def update_lrouter_port_ips(cluster, lrouter_id, lport_id,
                            ips_to_add, ips_to_remove):
    uri = nsxlib._build_uri_path(LROUTERPORT_RESOURCE, lport_id, lrouter_id)
    try:
        port = nsxlib.do_request(HTTP_GET, uri, cluster=cluster)
        # TODO(salvatore-orlando): Enforce ips_to_add intersection with
        # ips_to_remove is empty
        ip_address_set = set(port['ip_addresses'])
        ip_address_set = ip_address_set - set(ips_to_remove)
        ip_address_set = ip_address_set | set(ips_to_add)
        # Set is not JSON serializable - convert to list
        port['ip_addresses'] = list(ip_address_set)
        nsxlib.do_request(HTTP_PUT, uri, jsonutils.dumps(port),
                          cluster=cluster)
    except exception.NotFound:
        # FIXME(salv-orlando):avoid raising different exception
        data = {'lport_id': lport_id, 'lrouter_id': lrouter_id}
        msg = (_("Router Port %(lport_id)s not found on router "
                 "%(lrouter_id)s") % data)
        LOG.exception(msg)
        raise nsx_exc.NsxPluginException(err_msg=msg)
    except api_exc.NsxApiException as e:
        msg = _("An exception occurred while updating IP addresses on a "
                "router logical port:%s") % str(e)
        LOG.exception(msg)
        raise nsx_exc.NsxPluginException(err_msg=msg)
Exemple #19
0
def delete_router_lport(cluster, lrouter_uuid, lport_uuid):
    """Creates a logical port on the assigned logical router."""
    path = nsxlib._build_uri_path(LROUTERPORT_RESOURCE, lport_uuid, lrouter_uuid)
    nsxlib.do_request(HTTP_DELETE, path, cluster=cluster)
    LOG.debug(
        "Delete logical router port %(lport_uuid)s on " "logical router %(lrouter_uuid)s",
        {"lport_uuid": lport_uuid, "lrouter_uuid": lrouter_uuid},
    )
Exemple #20
0
def create_explicit_routing_lrouter(cluster, neutron_router_id, tenant_id, display_name, nexthop, distributed=None):
    lrouter_obj = _prepare_lrouter_body(
        display_name, neutron_router_id, tenant_id, "RoutingTableRoutingConfig", distributed=distributed
    )
    router = do_request(HTTP_POST, _build_uri_path(LROUTER_RESOURCE), jsonutils.dumps(lrouter_obj), cluster=cluster)
    default_gw = {"prefix": "0.0.0.0/0", "next_hop_ip": nexthop}
    create_explicit_route_lrouter(cluster, router["uuid"], default_gw)
    return router
Exemple #21
0
def lsn_for_network_create(cluster, network_id):
    lsn_obj = {
        "edge_cluster_uuid": cluster.default_service_cluster_uuid,
        "tags": utils.get_tags(n_network_id=network_id),
    }
    return nsxlib.do_request(
        HTTP_POST, nsxlib._build_uri_path(LSERVICESNODE_RESOURCE), jsonutils.dumps(lsn_obj), cluster=cluster
    )["uuid"]
Exemple #22
0
def delete_router_lport(cluster, lrouter_uuid, lport_uuid):
    """Creates a logical port on the assigned logical router."""
    path = _build_uri_path(LROUTERPORT_RESOURCE, lport_uuid, lrouter_uuid)
    do_request(HTTP_DELETE, path, cluster=cluster)
    LOG.debug(_("Delete logical router port %(lport_uuid)s on "
                "logical router %(lrouter_uuid)s"),
              {'lport_uuid': lport_uuid,
               'lrouter_uuid': lrouter_uuid})
Exemple #23
0
def get_gateway_device_status(cluster, device_uuid):
    status_res = do_request(HTTP_GET,
                            _build_uri_path(TRANSPORTNODE_RESOURCE,
                                            device_uuid,
                                            extra_action='status'),
                            cluster=cluster)
    # Returns the connection status
    return status_res['connection']['connected']
Exemple #24
0
def get_default_route_explicit_routing_lrouter_v33(cluster, router_id):
    static_filter = {"protocol": "static", "prefix": "0.0.0.0/0"}
    default_route = nsxlib.do_request(
        HTTP_GET,
        nsxlib._build_uri_path(LROUTERRIB_RESOURCE, filters=static_filter, fields="*", parent_resource_id=router_id),
        cluster=cluster,
    )["results"][0]
    return default_route
Exemple #25
0
def get_explicit_routes_lrouter(cluster, router_id, protocol_type="static"):
    static_filter = {"protocol": protocol_type}
    existing_routes = nsxlib.do_request(
        HTTP_GET,
        nsxlib._build_uri_path(LROUTERRIB_RESOURCE, filters=static_filter, fields="*", parent_resource_id=router_id),
        cluster=cluster,
    )["results"]
    return existing_routes
Exemple #26
0
def lsn_for_network_get(cluster, network_id):
    filters = {"tag": network_id, "tag_scope": "n_network_id"}
    results = nsxlib.do_request(
        HTTP_GET, nsxlib._build_uri_path(LSERVICESNODE_RESOURCE, fields="uuid", filters=filters), cluster=cluster
    )["results"]
    if not results:
        raise exception.NotFound()
    elif len(results) == 1:
        return results[0]["uuid"]
Exemple #27
0
def get_lswitch_by_id(cluster, lswitch_id):
    try:
        lswitch_uri_path = nsxlib._build_uri_path(
            LSWITCH_RESOURCE, lswitch_id,
            relations="LogicalSwitchStatus")
        return nsxlib.do_request(HTTP_GET, lswitch_uri_path, cluster=cluster)
    except exception.NotFound:
        # FIXME(salv-orlando): this should not raise a neutron exception
        raise exception.NetworkNotFound(net_id=lswitch_id)
Exemple #28
0
def _lsn_configure_action(cluster, lsn_id, action, is_enabled, obj):
    lsn_obj = {"enabled": is_enabled}
    lsn_obj.update(obj)
    nsxlib.do_request(
        HTTP_PUT,
        nsxlib._build_uri_path(LSERVICESNODE_RESOURCE, resource_id=lsn_id, extra_action=action),
        jsonutils.dumps(lsn_obj),
        cluster=cluster,
    )
Exemple #29
0
def query_lswitch_lports(cluster, ls_uuid, fields="*",
                         filters=None, relations=None):
    # Fix filter for attachments
    if filters and "attachment" in filters:
        filters['attachment_vif_uuid'] = filters["attachment"]
        del filters['attachment']
    uri = _build_uri_path(LSWITCHPORT_RESOURCE, parent_resource_id=ls_uuid,
                          fields=fields, filters=filters, relations=relations)
    return do_request(HTTP_GET, uri, cluster=cluster)['results']
Exemple #30
0
 def lookup_switches_by_tag():
     # Fetch extra logical switches
     lswitch_query_path = nsxlib._build_uri_path(
         LSWITCH_RESOURCE,
         fields="uuid,display_name,tags,lport_count",
         relations="LogicalSwitchStatus",
         filters={'tag': neutron_net_id,
                  'tag_scope': 'quantum_net_id'})
     return nsxlib.get_all_query_pages(lswitch_query_path, cluster)
Exemple #31
0
def update_gateway_device(cluster, gateway_id, tenant_id, display_name,
                          neutron_id, tz_uuid, connector_type, connector_ip,
                          client_certificate):
    body = _build_gateway_device_body(tenant_id, display_name, neutron_id,
                                      connector_type, connector_ip,
                                      client_certificate, tz_uuid)
    try:
        return nsxlib.do_request(HTTP_PUT,
                                 nsxlib._build_uri_path(
                                     TRANSPORTNODE_RESOURCE,
                                     resource_id=gateway_id),
                                 jsonutils.dumps(body, sort_keys=True),
                                 cluster=cluster)
    except api_exc.InvalidSecurityCertificate:
        raise nsx_exc.InvalidSecurityCertificate()
Exemple #32
0
def update_default_gw_explicit_routing_lrouter(cluster, router_id, next_hop):
    default_route = get_default_route_explicit_routing_lrouter(cluster,
                                                               router_id)
    if next_hop != default_route["next_hop_ip"]:
        new_default_route = {"action": "accept",
                             "next_hop_ip": next_hop,
                             "prefix": "0.0.0.0/0",
                             "protocol": "static"}
        nsxlib.do_request(HTTP_PUT,
                          nsxlib._build_uri_path(
                              LROUTERRIB_RESOURCE,
                              resource_id=default_route['uuid'],
                              parent_resource_id=router_id),
                          jsonutils.dumps(new_default_route),
                          cluster=cluster)
Exemple #33
0
def create_explicit_route_lrouter(cluster, router_id, route):
    next_hop_ip = route.get("nexthop") or route.get("next_hop_ip")
    prefix = route.get("destination") or route.get("prefix")
    uuid = nsxlib.do_request(
        HTTP_POST,
        nsxlib._build_uri_path(LROUTERRIB_RESOURCE,
                               parent_resource_id=router_id),
        jsonutils.dumps({
            "action": "accept",
            "next_hop_ip": next_hop_ip,
            "prefix": prefix,
            "protocol": "static"
        }),
        cluster=cluster)['uuid']
    return uuid
Exemple #34
0
def _create_implicit_routing_lrouter(cluster, neutron_router_id, tenant_id,
                                     display_name, nexthop, distributed=None):
    implicit_routing_config = {
        "default_route_next_hop": {
            "gateway_ip_address": nexthop,
            "type": "RouterNextHop"
        },
    }
    lrouter_obj = _prepare_lrouter_body(
        display_name, neutron_router_id, tenant_id,
        "SingleDefaultRouteImplicitRoutingConfig",
        distributed=distributed,
        **implicit_routing_config)
    return nsxlib.do_request(HTTP_POST,
                             nsxlib._build_uri_path(LROUTER_RESOURCE),
                             jsonutils.dumps(lrouter_obj), cluster=cluster)
Exemple #35
0
def update_implicit_routing_lrouter(cluster, r_id, display_name, nexthop):
    lrouter_obj = get_lrouter(cluster, r_id)
    if not display_name and not nexthop:
        # Nothing to update
        return lrouter_obj
    # It seems that this is faster than the doing an if on display_name
    lrouter_obj["display_name"] = (utils.check_and_truncate(display_name) or
                                   lrouter_obj["display_name"])
    if nexthop:
        nh_element = lrouter_obj["routing_config"].get(
            "default_route_next_hop")
        if nh_element:
            nh_element["gateway_ip_address"] = nexthop
    return do_request(HTTP_PUT, _build_uri_path(LROUTER_RESOURCE,
                                                resource_id=r_id),
                      jsonutils.dumps(lrouter_obj),
                      cluster=cluster)
Exemple #36
0
def lsn_port_create(cluster, lsn_id, port_data):
    port_obj = {
        "ip_address":
        port_data["ip_address"],
        "mac_address":
        port_data["mac_address"],
        "tags":
        utils.get_tags(n_mac_address=port_data["mac_address"],
                       n_subnet_id=port_data["subnet_id"]),
        "type":
        "LogicalServicesNodePortConfig",
    }
    return do_request(HTTP_POST,
                      _build_uri_path(LSERVICESNODEPORT_RESOURCE,
                                      parent_resource_id=lsn_id),
                      json.dumps(port_obj),
                      cluster=cluster)["uuid"]
Exemple #37
0
def create_explicit_routing_lrouter(cluster,
                                    neutron_router_id,
                                    tenant_id,
                                    display_name,
                                    nexthop,
                                    distributed=None):
    lrouter_obj = _prepare_lrouter_body(display_name,
                                        neutron_router_id,
                                        tenant_id,
                                        "RoutingTableRoutingConfig",
                                        distributed=distributed)
    router = nsxlib.do_request(HTTP_POST,
                               nsxlib._build_uri_path(LROUTER_RESOURCE),
                               jsonutils.dumps(lrouter_obj),
                               cluster=cluster)
    default_gw = {'prefix': '0.0.0.0/0', 'next_hop_ip': nexthop}
    create_explicit_route_lrouter(cluster, router['uuid'], default_gw)
    return router
Exemple #38
0
def update_lswitch(cluster, lswitch_id, display_name,
                   tenant_id=None, **kwargs):
    uri = nsxlib._build_uri_path(LSWITCH_RESOURCE, resource_id=lswitch_id)
    lswitch_obj = {"display_name": utils.check_and_truncate(display_name)}
    # NOTE: tag update will not 'merge' existing tags with new ones.
    tags = []
    if tenant_id:
        tags = utils.get_tags(os_tid=tenant_id)
    # The 'tags' kwarg might existing and be None
    tags.extend(kwargs.get('tags') or [])
    if tags:
        lswitch_obj['tags'] = tags
    try:
        return nsxlib.do_request(HTTP_PUT, uri, jsonutils.dumps(lswitch_obj),
                                 cluster=cluster)
    except exception.NotFound as e:
        LOG.error(_LE("Network not found, Error: %s"), str(e))
        raise exception.NetworkNotFound(net_id=lswitch_id)
Exemple #39
0
def lsn_port_plug_network(cluster, lsn_id, lsn_port_id, lswitch_port_id):
    patch_obj = {"type": "PatchAttachment", "peer_port_uuid": lswitch_port_id}
    try:
        do_request(HTTP_PUT,
                   _build_uri_path(LSERVICESNODEPORT_RESOURCE,
                                   parent_resource_id=lsn_id,
                                   resource_id=lsn_port_id,
                                   is_attachment=True),
                   json.dumps(patch_obj),
                   cluster=cluster)
    except api_exc.Conflict:
        # This restriction might be lifted at some point
        msg = (_("Attempt to plug Logical Services Node %(lsn)s into "
                 "network with port %(port)s failed. PatchAttachment "
                 "already exists with another port") % {
                     'lsn': lsn_id,
                     'port': lswitch_port_id
                 })
        LOG.exception(msg)
        raise nsx_exc.LsnConfigurationConflict(lsn_id=lsn_id)
Exemple #40
0
def update_lswitch(cluster,
                   lswitch_id,
                   display_name,
                   tenant_id=None,
                   **kwargs):
    uri = _build_uri_path(LSWITCH_RESOURCE, resource_id=lswitch_id)
    lswitch_obj = {
        "display_name": utils.check_and_truncate(display_name),
        "tags": utils.get_tags(os_tid=tenant_id)
    }
    if "tags" in kwargs:
        lswitch_obj["tags"].extend(kwargs["tags"])
    try:
        return do_request(HTTP_PUT,
                          uri,
                          json.dumps(lswitch_obj),
                          cluster=cluster)
    except exception.NotFound as e:
        LOG.error(_("Network not found, Error: %s"), str(e))
        raise exception.NetworkNotFound(net_id=lswitch_id)
 def _test_create_lrouter_dnat_rule(self, version):
     with mock.patch.object(self.fake_cluster.api_client,
                            'get_version',
                            new=lambda: Version(version)):
         tenant_id = 'pippo'
         lrouter = routerlib.create_lrouter(self.fake_cluster,
                                            uuidutils.generate_uuid(),
                                            tenant_id, 'fake_router',
                                            '192.168.0.1')
         nat_rule = routerlib.create_lrouter_dnat_rule(
             self.fake_cluster,
             lrouter['uuid'],
             '10.0.0.99',
             match_criteria={'destination_ip_addresses': '192.168.0.5'})
         uri = nsxlib._build_uri_path(routerlib.LROUTERNAT_RESOURCE,
                                      nat_rule['uuid'], lrouter['uuid'])
         resp_obj = nsxlib.do_request("GET", uri, cluster=self.fake_cluster)
         self.assertEqual('DestinationNatRule', resp_obj['type'])
         self.assertEqual('192.168.0.5',
                          resp_obj['match']['destination_ip_addresses'])
Exemple #42
0
def create_lport(cluster,
                 lswitch_uuid,
                 tenant_id,
                 neutron_port_id,
                 display_name,
                 device_id,
                 admin_status_enabled,
                 mac_address=None,
                 fixed_ips=None,
                 port_security_enabled=None,
                 security_profiles=None,
                 queue_id=None,
                 mac_learning_enabled=None,
                 allowed_address_pairs=None):
    """Creates a logical port on the assigned logical switch."""
    display_name = utils.check_and_truncate(display_name)
    lport_obj = dict(admin_status_enabled=admin_status_enabled,
                     display_name=display_name,
                     tags=utils.get_tags(
                         os_tid=tenant_id,
                         q_port_id=neutron_port_id,
                         vm_id=utils.device_id_to_vm_id(device_id)))

    _configure_extensions(lport_obj, mac_address, fixed_ips,
                          port_security_enabled, security_profiles, queue_id,
                          mac_learning_enabled, allowed_address_pairs)

    path = _build_uri_path(LSWITCHPORT_RESOURCE,
                           parent_resource_id=lswitch_uuid)
    result = do_request(HTTP_POST,
                        path,
                        json.dumps(lport_obj),
                        cluster=cluster)

    LOG.debug(_("Created logical port %(result)s on logical switch %(uuid)s"),
              {
                  'result': result['uuid'],
                  'uuid': lswitch_uuid
              })
    return result
Exemple #43
0
 def test_update_security_profile_rules(self):
     sec_prof = secgrouplib.create_security_profile(
         self.fake_cluster, _uuid(), 'pippo', {'name': 'test'})
     ingress_rule = {'ethertype': 'IPv4'}
     egress_rule = {'ethertype': 'IPv4', 'profile_uuid': 'xyz'}
     new_rules = {'logical_port_egress_rules': [egress_rule],
                  'logical_port_ingress_rules': [ingress_rule]}
     secgrouplib.update_security_group_rules(
         self.fake_cluster, sec_prof['uuid'], new_rules)
     sec_prof_res = nsxlib.do_request(
         nsxlib.HTTP_GET,
         nsxlib._build_uri_path('security-profile',
                                resource_id=sec_prof['uuid']),
         cluster=self.fake_cluster)
     self.assertEqual(sec_prof['uuid'], sec_prof_res['uuid'])
     # Check for builtin rules
     self.assertEqual(len(sec_prof_res['logical_port_egress_rules']), 2)
     self.assertIn(egress_rule,
                   sec_prof_res['logical_port_egress_rules'])
     self.assertEqual(len(sec_prof_res['logical_port_ingress_rules']), 1)
     self.assertIn(ingress_rule,
                   sec_prof_res['logical_port_ingress_rules'])
Exemple #44
0
def create_lswitch(cluster, neutron_net_id, tenant_id, display_name,
                   transport_zones_config,
                   shared=None,
                   **kwargs):
    # The tag scope adopts a slightly different naming convention for
    # historical reasons
    lswitch_obj = {"display_name": utils.check_and_truncate(display_name),
                   "transport_zones": transport_zones_config,
                   "replication_mode": cfg.CONF.NSX.replication_mode,
                   "tags": utils.get_tags(os_tid=tenant_id,
                                          quantum_net_id=neutron_net_id)}
    # TODO(salv-orlando): Now that we have async status synchronization
    # this tag is perhaps not needed anymore
    if shared:
        lswitch_obj["tags"].append({"tag": "true",
                                    "scope": "shared"})
    if "tags" in kwargs:
        lswitch_obj["tags"].extend(kwargs["tags"])
    uri = nsxlib._build_uri_path(LSWITCH_RESOURCE)
    lswitch = nsxlib.do_request(HTTP_POST, uri, jsonutils.dumps(lswitch_obj),
                                cluster=cluster)
    LOG.debug("Created logical switch: %s", lswitch['uuid'])
    return lswitch
Exemple #45
0
 def test_plug_l2_gw_port_attachment(self):
     tenant_id = 'pippo'
     node_uuid = _uuid()
     transport_zones_config = [{'zone_uuid': _uuid(),
                                'transport_type': 'stt'}]
     lswitch = switchlib.create_lswitch(
         self.fake_cluster, _uuid(), tenant_id,
         'fake-switch', transport_zones_config)
     gw_id = self._create_gw_service(node_uuid, 'fake-gw')['uuid']
     lport = switchlib.create_lport(
         self.fake_cluster, lswitch['uuid'], tenant_id, _uuid(),
         'fake-gw-port', gw_id, True)
     l2gwlib.plug_l2_gw_service(
         self.fake_cluster, lswitch['uuid'],
         lport['uuid'], gw_id)
     uri = nsxlib._build_uri_path(switchlib.LSWITCHPORT_RESOURCE,
                                  lport['uuid'],
                                  lswitch['uuid'],
                                  is_attachment=True)
     resp_obj = nsxlib.do_request("GET", uri,
                                  cluster=self.fake_cluster)
     self.assertIn('LogicalPortAttachment', resp_obj)
     self.assertEqual(resp_obj['LogicalPortAttachment']['type'],
                      'L2GatewayAttachment')
Exemple #46
0
def lsn_port_delete(cluster, lsn_id, lsn_port_id):
    return do_request(HTTP_DELETE,
                      _build_uri_path(LSERVICESNODEPORT_RESOURCE,
                                      parent_resource_id=lsn_id,
                                      resource_id=lsn_port_id),
                      cluster=cluster)
Exemple #47
0
def query_nat_rules(cluster, router_id, fields="*", filters=None):
    uri = nsxlib._build_uri_path(LROUTERNAT_RESOURCE,
                                 parent_resource_id=router_id,
                                 fields=fields, filters=filters)
    return nsxlib.get_all_query_pages(uri, cluster)
Exemple #48
0
def query_security_profiles(cluster, fields=None, filters=None):
    return nsxlib.get_all_query_pages(
        nsxlib._build_uri_path(SECPROF_RESOURCE,
                               fields=fields,
                               filters=filters),
        cluster)
Exemple #49
0
 def test_build_uri_path_plain(self):
     result = nsxlib._build_uri_path('RESOURCE')
     self.assertEqual("%s/%s" % (nsxlib.URI_PREFIX, 'RESOURCE'), result)
Exemple #50
0
def delete_l2_gw_service(cluster, gateway_id):
    nsxlib.do_request(HTTP_DELETE,
                      nsxlib._build_uri_path(GWSERVICE_RESOURCE,
                                             resource_id=gateway_id),
                      cluster=cluster)
Exemple #51
0
def get_l2_gw_service(cluster, gateway_id):
    return nsxlib.do_request(HTTP_GET,
                             nsxlib._build_uri_path(GWSERVICE_RESOURCE,
                                                    resource_id=gateway_id),
                             cluster=cluster)
Exemple #52
0
 def test_build_uri_path_with_resource_id(self):
     res = 'RESOURCE'
     res_id = 'resource_id'
     result = nsxlib._build_uri_path(res, resource_id=res_id)
     expected = "%s/%s/%s" % (nsxlib.URI_PREFIX, res, res_id)
     self.assertEqual(expected, result)
Exemple #53
0
 def test_build_uri_path_with_filters(self):
     filters = {"tag": 'foo', "tag_scope": "scope_foo"}
     result = nsxlib._build_uri_path('RESOURCE', filters=filters)
     expected = ("%s/%s?tag_scope=scope_foo&tag=foo" %
                 (nsxlib.URI_PREFIX, 'RESOURCE'))
     self.assertEqual(expected, result)
Exemple #54
0
 def test_build_uri_path_with_field(self):
     result = nsxlib._build_uri_path('RESOURCE', fields='uuid')
     expected = "%s/%s?fields=uuid" % (nsxlib.URI_PREFIX, 'RESOURCE')
     self.assertEqual(expected, result)
Exemple #55
0
def get_l2_gw_service(cluster, gateway_id):
    return do_request(
        "GET", _build_uri_path(GWSERVICE_RESOURCE,
                               resource_id=gateway_id),
        cluster=cluster)
Exemple #56
0
def delete_l2_gw_service(cluster, gateway_id):
    do_request("DELETE", _build_uri_path(GWSERVICE_RESOURCE,
                                         resource_id=gateway_id),
               cluster=cluster)
Exemple #57
0
def delete_gateway_device(cluster, device_uuid):
    return nsxlib.do_request(HTTP_DELETE,
                             nsxlib._build_uri_path(TRANSPORTNODE_RESOURCE,
                                                    device_uuid),
                             cluster=cluster)
Exemple #58
0
def update_security_profile(cluster, spid, name):
    return nsxlib.do_request(
        HTTP_PUT,
        nsxlib._build_uri_path(SECPROF_RESOURCE, resource_id=spid),
        jsonutils.dumps({"display_name": utils.check_and_truncate(name)}),
        cluster=cluster)
Exemple #59
0
class NsxSynchronizer():

    LS_URI = nsxlib._build_uri_path(switchlib.LSWITCH_RESOURCE,
                                    fields='uuid,tags,fabric_status',
                                    relations='LogicalSwitchStatus')
    LR_URI = nsxlib._build_uri_path(routerlib.LROUTER_RESOURCE,
                                    fields='uuid,tags,fabric_status',
                                    relations='LogicalRouterStatus')
    LP_URI = nsxlib._build_uri_path(switchlib.LSWITCHPORT_RESOURCE,
                                    parent_resource_id='*',
                                    fields='uuid,tags,fabric_status_up',
                                    relations='LogicalPortStatus')

    def __init__(self,
                 plugin,
                 cluster,
                 state_sync_interval,
                 req_delay,
                 min_chunk_size,
                 max_rand_delay=0):
        random.seed()
        self._nsx_cache = NsxCache()
        # Store parameters as instance members
        # NOTE(salv-orlando): apologies if it looks java-ish
        self._plugin = plugin
        self._cluster = cluster
        self._req_delay = req_delay
        self._sync_interval = state_sync_interval
        self._max_rand_delay = max_rand_delay
        # Validate parameters
        if self._sync_interval < self._req_delay:
            err_msg = (_("Minimum request delay:%(req_delay)s must not "
                         "exceed synchronization interval:%(sync_interval)s") %
                       {
                           'req_delay': self._req_delay,
                           'sync_interval': self._sync_interval
                       })
            LOG.error(err_msg)
            raise nsx_exc.NsxPluginException(err_msg=err_msg)
        # Backoff time in case of failures while fetching sync data
        self._sync_backoff = 1
        # Store the looping call in an instance variable to allow unit tests
        # for controlling its lifecycle
        self._sync_looping_call = _start_loopingcall(min_chunk_size,
                                                     state_sync_interval,
                                                     self._synchronize_state)

    def _get_tag_dict(self, tags):
        return dict((tag.get('scope'), tag['tag']) for tag in tags)

    def synchronize_network(self,
                            context,
                            neutron_network_data,
                            lswitches=None):
        """Synchronize a Neutron network with its NSX counterpart.

        This routine synchronizes a set of switches when a Neutron
        network is mapped to multiple lswitches.
        """
        if not lswitches:
            # Try to get logical switches from nsx
            try:
                lswitches = nsx_utils.fetch_nsx_switches(
                    context.session, self._cluster, neutron_network_data['id'])
            except exceptions.NetworkNotFound:
                # TODO(salv-orlando): We should be catching
                # api_exc.ResourceNotFound here
                # The logical switch was not found
                LOG.warning(
                    _("Logical switch for neutron network %s not "
                      "found on NSX."), neutron_network_data['id'])
                lswitches = []
            else:
                for lswitch in lswitches:
                    self._nsx_cache.update_lswitch(lswitch)
        # By default assume things go wrong
        status = constants.NET_STATUS_ERROR
        # In most cases lswitches will contain a single element
        for ls in lswitches:
            if not ls:
                # Logical switch was deleted
                break
            ls_status = ls['_relations']['LogicalSwitchStatus']
            if not ls_status['fabric_status']:
                status = constants.NET_STATUS_DOWN
                break
        else:
            # No switch was down or missing. Set status to ACTIVE unless
            # there were no switches in the first place!
            if lswitches:
                status = constants.NET_STATUS_ACTIVE
        # Update db object
        if status == neutron_network_data['status']:
            # do nothing
            return

        with context.session.begin(subtransactions=True):
            try:
                network = self._plugin._get_network(context,
                                                    neutron_network_data['id'])
            except exc.NoResultFound:
                pass
            else:
                network.status = status
                LOG.debug(
                    _("Updating status for neutron resource %(q_id)s to:"
                      " %(status)s"), {
                          'q_id': neutron_network_data['id'],
                          'status': status
                      })

    def _synchronize_lswitches(self, ctx, ls_uuids, scan_missing=False):
        if not ls_uuids and not scan_missing:
            return
        neutron_net_ids = set()
        neutron_nsx_mappings = {}
        # TODO(salvatore-orlando): Deal with the case the tag
        # has been tampered with
        for ls_uuid in ls_uuids:
            # If the lswitch has been deleted, get backup copy of data
            lswitch = (self._nsx_cache[ls_uuid].get('data')
                       or self._nsx_cache[ls_uuid].get('data_bk'))
            tags = self._get_tag_dict(lswitch['tags'])
            neutron_id = tags.get('quantum_net_id')
            neutron_net_ids.add(neutron_id)
            neutron_nsx_mappings[neutron_id] = (
                neutron_nsx_mappings.get(neutron_id, []) +
                [self._nsx_cache[ls_uuid]])
        # Fetch neutron networks from database
        filters = {'router:external': [False]}
        if not scan_missing:
            filters['id'] = neutron_net_ids

        networks = self._plugin._get_collection(
            ctx,
            models_v2.Network,
            self._plugin._make_network_dict,
            filters=filters)

        for network in networks:
            lswitches = neutron_nsx_mappings.get(network['id'], [])
            lswitches = [lswitch.get('data') for lswitch in lswitches]
            self.synchronize_network(ctx, network, lswitches)

    def synchronize_router(self, context, neutron_router_data, lrouter=None):
        """Synchronize a neutron router with its NSX counterpart."""
        if not lrouter:
            # Try to get router from nsx
            try:
                # This query will return the logical router status too
                nsx_router_id = nsx_utils.get_nsx_router_id(
                    context.session, self._cluster, neutron_router_data['id'])
                if nsx_router_id:
                    lrouter = routerlib.get_lrouter(self._cluster,
                                                    nsx_router_id)
            except exceptions.NotFound:
                # NOTE(salv-orlando): We should be catching
                # api_exc.ResourceNotFound here
                # The logical router was not found
                LOG.warning(
                    _("Logical router for neutron router %s not "
                      "found on NSX."), neutron_router_data['id'])
            if lrouter:
                # Update the cache
                self._nsx_cache.update_lrouter(lrouter)

        # Note(salv-orlando): It might worth adding a check to verify neutron
        # resource tag in nsx entity matches a Neutron id.
        # By default assume things go wrong
        status = constants.NET_STATUS_ERROR
        if lrouter:
            lr_status = (
                lrouter['_relations']['LogicalRouterStatus']['fabric_status'])
            status = (lr_status and constants.NET_STATUS_ACTIVE
                      or constants.NET_STATUS_DOWN)
        # Update db object
        if status == neutron_router_data['status']:
            # do nothing
            return

        with context.session.begin(subtransactions=True):
            try:
                router = self._plugin._get_router(context,
                                                  neutron_router_data['id'])
            except exc.NoResultFound:
                pass
            else:
                router.status = status
                LOG.debug(
                    _("Updating status for neutron resource %(q_id)s to:"
                      " %(status)s"), {
                          'q_id': neutron_router_data['id'],
                          'status': status
                      })

    def _synchronize_lrouters(self, ctx, lr_uuids, scan_missing=False):
        if not lr_uuids and not scan_missing:
            return
        # TODO(salvatore-orlando): Deal with the case the tag
        # has been tampered with
        neutron_router_mappings = {}
        for lr_uuid in lr_uuids:
            lrouter = (self._nsx_cache[lr_uuid].get('data')
                       or self._nsx_cache[lr_uuid].get('data_bk'))
            tags = self._get_tag_dict(lrouter['tags'])
            neutron_router_id = tags.get('q_router_id')
            if neutron_router_id:
                neutron_router_mappings[neutron_router_id] = (
                    self._nsx_cache[lr_uuid])
            else:
                LOG.warn(
                    _("Unable to find Neutron router id for "
                      "NSX logical router: %s"), lr_uuid)
        # Fetch neutron routers from database
        filters = ({} if scan_missing else {
            'id': neutron_router_mappings.keys()
        })
        routers = self._plugin._get_collection(ctx,
                                               l3_db.Router,
                                               self._plugin._make_router_dict,
                                               filters=filters)
        for router in routers:
            lrouter = neutron_router_mappings.get(router['id'])
            self.synchronize_router(ctx, router, lrouter
                                    and lrouter.get('data'))

    def synchronize_port(self,
                         context,
                         neutron_port_data,
                         lswitchport=None,
                         ext_networks=None):
        """Synchronize a Neutron port with its NSX counterpart."""
        # Skip synchronization for ports on external networks
        if not ext_networks:
            ext_networks = [
                net['id']
                for net in context.session.query(models_v2.Network).join(
                    external_net_db.ExternalNetwork, (
                        models_v2.Network.id ==
                        external_net_db.ExternalNetwork.network_id))
            ]
        if neutron_port_data['network_id'] in ext_networks:
            with context.session.begin(subtransactions=True):
                neutron_port_data['status'] = constants.PORT_STATUS_ACTIVE
                return

        if not lswitchport:
            # Try to get port from nsx
            try:
                ls_uuid, lp_uuid = nsx_utils.get_nsx_switch_and_port_id(
                    context.session, self._cluster, neutron_port_data['id'])
                if lp_uuid:
                    lswitchport = switchlib.get_port(
                        self._cluster,
                        ls_uuid,
                        lp_uuid,
                        relations='LogicalPortStatus')
            except (exceptions.PortNotFoundOnNetwork):
                # NOTE(salv-orlando): We should be catching
                # api_exc.ResourceNotFound here instead
                # of PortNotFoundOnNetwork when the id exists but
                # the logical switch port was not found
                LOG.warning(
                    _("Logical switch port for neutron port %s "
                      "not found on NSX."), neutron_port_data['id'])
                lswitchport = None
            else:
                # If lswitchport is not None, update the cache.
                # It could be none if the port was deleted from the backend
                if lswitchport:
                    self._nsx_cache.update_lswitchport(lswitchport)
        # Note(salv-orlando): It might worth adding a check to verify neutron
        # resource tag in nsx entity matches Neutron id.
        # By default assume things go wrong
        status = constants.PORT_STATUS_ERROR
        if lswitchport:
            lp_status = (lswitchport['_relations']['LogicalPortStatus']
                         ['fabric_status_up'])
            status = (lp_status and constants.PORT_STATUS_ACTIVE
                      or constants.PORT_STATUS_DOWN)

        # Update db object
        if status == neutron_port_data['status']:
            # do nothing
            return

        with context.session.begin(subtransactions=True):
            try:
                port = self._plugin._get_port(context, neutron_port_data['id'])
            except exc.NoResultFound:
                pass
            else:
                port.status = status
                LOG.debug(
                    _("Updating status for neutron resource %(q_id)s to:"
                      " %(status)s"), {
                          'q_id': neutron_port_data['id'],
                          'status': status
                      })

    def _synchronize_lswitchports(self, ctx, lp_uuids, scan_missing=False):
        if not lp_uuids and not scan_missing:
            return
        # Find Neutron port id by tag - the tag is already
        # loaded in memory, no reason for doing a db query
        # TODO(salvatore-orlando): Deal with the case the tag
        # has been tampered with
        neutron_port_mappings = {}
        for lp_uuid in lp_uuids:
            lport = (self._nsx_cache[lp_uuid].get('data')
                     or self._nsx_cache[lp_uuid].get('data_bk'))
            tags = self._get_tag_dict(lport['tags'])
            neutron_port_id = tags.get('q_port_id')
            if neutron_port_id:
                neutron_port_mappings[neutron_port_id] = (
                    self._nsx_cache[lp_uuid])
        # Fetch neutron ports from database
        # At the first sync we need to fetch all ports
        filters = ({} if scan_missing else {
            'id': neutron_port_mappings.keys()
        })
        # TODO(salv-orlando): Work out a solution for avoiding
        # this query
        ext_nets = [
            net['id'] for net in ctx.session.query(models_v2.Network).join(
                external_net_db.ExternalNetwork, (
                    models_v2.Network.id ==
                    external_net_db.ExternalNetwork.network_id))
        ]
        ports = self._plugin._get_collection(ctx,
                                             models_v2.Port,
                                             self._plugin._make_port_dict,
                                             filters=filters)
        for port in ports:
            lswitchport = neutron_port_mappings.get(port['id'])
            self.synchronize_port(ctx,
                                  port,
                                  lswitchport and lswitchport.get('data'),
                                  ext_networks=ext_nets)

    def _get_chunk_size(self, sp):
        # NOTE(salv-orlando): Try to use __future__ for this routine only?
        ratio = ((float(sp.total_size) / float(sp.chunk_size)) /
                 (float(self._sync_interval) / float(self._req_delay)))
        new_size = max(1.0, ratio) * float(sp.chunk_size)
        return int(new_size) + (new_size - int(new_size) > 0)

    def _fetch_data(self, uri, cursor, page_size):
        # If not cursor there is nothing to retrieve
        if cursor:
            if cursor == 'start':
                cursor = None
            # Chunk size tuning might, in some conditions, make it larger
            # than 5,000, which is the maximum page size allowed by the NSX
            # API. In this case the request should be split in multiple
            # requests. This is not ideal, and therefore a log warning will
            # be emitted.
            num_requests = page_size / (MAX_PAGE_SIZE + 1) + 1
            if num_requests > 1:
                LOG.warn(
                    _("Requested page size is %(cur_chunk_size)d."
                      "It might be necessary to do %(num_requests)d "
                      "round-trips to NSX for fetching data. Please "
                      "tune sync parameters to ensure chunk size "
                      "is less than %(max_page_size)d"), {
                          'cur_chunk_size': page_size,
                          'num_requests': num_requests,
                          'max_page_size': MAX_PAGE_SIZE
                      })
            # Only the first request might return the total size,
            # subsequent requests will definetely not
            results, cursor, total_size = nsxlib.get_single_query_page(
                uri, self._cluster, cursor, min(page_size, MAX_PAGE_SIZE))
            for _req in range(num_requests - 1):
                # If no cursor is returned break the cycle as there is no
                # actual need to perform multiple requests (all fetched)
                # This happens when the overall size of resources exceeds
                # the maximum page size, but the number for each single
                # resource type is below this threshold
                if not cursor:
                    break
                req_results, cursor = nsxlib.get_single_query_page(
                    uri, self._cluster, cursor, min(page_size,
                                                    MAX_PAGE_SIZE))[:2]
                results.extend(req_results)
            # reset cursor before returning if we queried just to
            # know the number of entities
            return results, cursor if page_size else 'start', total_size
        return [], cursor, None

    def _fetch_nsx_data_chunk(self, sp):
        base_chunk_size = sp.chunk_size
        chunk_size = base_chunk_size + sp.extra_chunk_size
        LOG.info(_("Fetching up to %s resources "
                   "from NSX backend"), chunk_size)
        fetched = ls_count = lr_count = lp_count = 0
        lswitches = lrouters = lswitchports = []
        if sp.ls_cursor or sp.ls_cursor == 'start':
            (lswitches, sp.ls_cursor,
             ls_count) = self._fetch_data(self.LS_URI, sp.ls_cursor,
                                          chunk_size)
            fetched = len(lswitches)
        if fetched < chunk_size and sp.lr_cursor or sp.lr_cursor == 'start':
            (lrouters, sp.lr_cursor,
             lr_count) = self._fetch_data(self.LR_URI, sp.lr_cursor,
                                          max(chunk_size - fetched, 0))
        fetched += len(lrouters)
        if fetched < chunk_size and sp.lp_cursor or sp.lp_cursor == 'start':
            (lswitchports, sp.lp_cursor,
             lp_count) = self._fetch_data(self.LP_URI, sp.lp_cursor,
                                          max(chunk_size - fetched, 0))
        fetched += len(lswitchports)
        if sp.current_chunk == 0:
            # No cursors were provided. Then it must be possible to
            # calculate the total amount of data to fetch
            sp.total_size = ls_count + lr_count + lp_count
        LOG.debug(_("Total data size: %d"), sp.total_size)
        sp.chunk_size = self._get_chunk_size(sp)
        # Calculate chunk size adjustment
        sp.extra_chunk_size = sp.chunk_size - base_chunk_size
        LOG.debug(
            _("Fetched %(num_lswitches)d logical switches, "
              "%(num_lswitchports)d logical switch ports,"
              "%(num_lrouters)d logical routers"), {
                  'num_lswitches': len(lswitches),
                  'num_lswitchports': len(lswitchports),
                  'num_lrouters': len(lrouters)
              })
        return (lswitches, lrouters, lswitchports)

    def _synchronize_state(self, sp):
        # If the plugin has been destroyed, stop the LoopingCall
        if not self._plugin:
            raise loopingcall.LoopingCallDone
        start = timeutils.utcnow()
        # Reset page cursor variables if necessary
        if sp.current_chunk == 0:
            sp.ls_cursor = sp.lr_cursor = sp.lp_cursor = 'start'
        LOG.info(_("Running state synchronization task. Chunk: %s"),
                 sp.current_chunk)
        # Fetch chunk_size data from NSX
        try:
            (lswitches, lrouters,
             lswitchports) = (self._fetch_nsx_data_chunk(sp))
        except (api_exc.RequestTimeout, api_exc.NsxApiException):
            sleep_interval = self._sync_backoff
            # Cap max back off to 64 seconds
            self._sync_backoff = min(self._sync_backoff * 2, 64)
            LOG.exception(
                _("An error occurred while communicating with "
                  "NSX backend. Will retry synchronization "
                  "in %d seconds"), sleep_interval)
            return sleep_interval
        LOG.debug(_("Time elapsed querying NSX: %s"),
                  timeutils.utcnow() - start)
        if sp.total_size:
            num_chunks = ((sp.total_size / sp.chunk_size) +
                          (sp.total_size % sp.chunk_size != 0))
        else:
            num_chunks = 1
        LOG.debug(_("Number of chunks: %d"), num_chunks)
        # Find objects which have changed on NSX side and need
        # to be synchronized
        (ls_uuids, lr_uuids,
         lp_uuids) = self._nsx_cache.process_updates(lswitches, lrouters,
                                                     lswitchports)
        # Process removed objects only at the last chunk
        scan_missing = (sp.current_chunk == num_chunks - 1
                        and not sp.init_sync_performed)
        if sp.current_chunk == num_chunks - 1:
            self._nsx_cache.process_deletes()
            ls_uuids = self._nsx_cache.get_lswitches(
                changed_only=not scan_missing)
            lr_uuids = self._nsx_cache.get_lrouters(
                changed_only=not scan_missing)
            lp_uuids = self._nsx_cache.get_lswitchports(
                changed_only=not scan_missing)
        LOG.debug(_("Time elapsed hashing data: %s"),
                  timeutils.utcnow() - start)
        # Get an admin context
        ctx = context.get_admin_context()
        # Synchronize with database
        self._synchronize_lswitches(ctx, ls_uuids, scan_missing=scan_missing)
        self._synchronize_lrouters(ctx, lr_uuids, scan_missing=scan_missing)
        self._synchronize_lswitchports(ctx,
                                       lp_uuids,
                                       scan_missing=scan_missing)
        # Increase chunk counter
        LOG.info(
            _("Synchronization for chunk %(chunk_num)d of "
              "%(total_chunks)d performed"), {
                  'chunk_num': sp.current_chunk + 1,
                  'total_chunks': num_chunks
              })
        sp.current_chunk = (sp.current_chunk + 1) % num_chunks
        added_delay = 0
        if sp.current_chunk == 0:
            # Ensure init_sync_performed is True
            if not sp.init_sync_performed:
                sp.init_sync_performed = True
            # Add additional random delay
            added_delay = random.randint(0, self._max_rand_delay)
        LOG.debug(_("Time elapsed at end of sync: %s"),
                  timeutils.utcnow() - start)
        return self._sync_interval / num_chunks + added_delay
Exemple #60
0
def lsn_delete(cluster, lsn_id):
    do_request(HTTP_DELETE,
               _build_uri_path(LSERVICESNODE_RESOURCE, resource_id=lsn_id),
               cluster=cluster)