Esempio n. 1
0
def bulk_gather_vlan_pools(request):
    vlan_name = request.GET.get('vlan_name', None)
    vlan_number = request.GET.get('vlan_number', None)
    site_name = request.GET.get('site_name', None)
    ip_type = request.GET.get('ip_type', None)

    if not site_name:
        return HttpResponse(dumps({'errors': 'Site name was not provided'}))

    if not ip_type:
        return HttpResponse(dumps({'errors': 'IP type is required here.'}))

    if vlan_name and vlan_number:
        s = 'site=:{site_name} AND vlan=:{vlan_name},{vlan_number}'.format(
            site_name=site_name, vlan_name=vlan_name, vlan_number=vlan_number)
    elif vlan_name:
        s = 'site=:{site_name} AND vlan=:{vlan_name}'.format(
            site_name=site_name, vlan_name=vlan_name)
    elif vlan_number:
        s = 'site=:{site_name} AND vlan=:{vlan_number}'.format(
            site_name=site_name, vlan_number=vlan_number)
    else:
        return HttpResponse(
            dumps({'errors': 'Not enough vlan information was provided'}))

    q_map, errors = compile_to_q(s)

    if errors:
        return None, errors

    networks = Network.objects.filter(q_map['NET']).filter(ip_type=ip_type)
    if networks.count() > 1:
        return HttpResponse(
            dumps({
                'errors':
                "Using the search '{s}', too many networks were "
                "found. Please be more specific and specify a range.".format(
                    s=s)
            }))
    if not networks.count():
        return HttpResponse(
            dumps({
                'errors':
                "Using the search '{s}', no networks were "
                "found.".format(s=s)
            }))

    ranges = integrate_real_ranges(networks[0],
                                   calc_template_ranges(networks[0]))
    free_ranges = []
    for r in ranges:
        if r['rtype'] == 'special purpose':
            continue
        free_ranges += range_usage(r['start'], r['end'],
                                   ip_type)['free_ranges']

    return HttpResponse(dumps({'free_ranges': free_ranges}))
Esempio n. 2
0
    def test_contained_in_template(self):
        # 1 to 15 is templated to be special purpose
        r1 = Range.objects.create(
            start_str='10.8.0.2', end_str='10.8.0.14', network=self.n1
        )
        trs = calc_template_ranges(self.n1)
        rs = integrate_real_ranges(self.n1, trs)
        self.assertEqual(len(rs), len(trs))
        rs = sorted(rs, key=lambda r: int(ipaddr.IPv4Address(r['start'])))

        self.assertEqual(r1.start_str, rs[0]['start'])
        self.assertEqual(r1.end_str, rs[0]['end'])
        self.assertEqual(r1.pk, rs[0]['pk'])
Esempio n. 3
0
    def test_overlaps_two_ranges(self):
        # 1 to 15 is templated to be special purpose
        # 16 to 127 is templated to be multi-host pools
        r1 = Range.objects.create(
            start_str='10.8.0.10', end_str='10.8.0.100', network=self.n1
        )

        trs = calc_template_ranges(self.n1)
        n_trs = len(trs)
        rs = integrate_real_ranges(self.n1, trs)
        # We should have lost one range
        self.assertEqual(n_trs - 1, len(rs))
        rs = sorted(rs, key=lambda r: int(ipaddr.IPv4Address(r['start'])))

        self.assertEqual(r1.start_str, rs[0]['start'])
        self.assertEqual(r1.end_str, rs[0]['end'])
        self.assertEqual(r1.pk, rs[0]['pk'])
Esempio n. 4
0
    def test_not_in_template(self):
        # 1 to 15 is templated to be special purpose
        r1 = Range.objects.create(
            start_str='10.8.0.2', end_str='10.8.0.14', network=self.n1
        )
        trs = calc_template_ranges(self.n1)
        trs = sorted(trs, key=lambda r: int(ipaddr.IPv4Address(r['start'])))

        # remove the first range that would have conflicted
        trs.pop(0)

        rs = integrate_real_ranges(self.n1, trs)
        rs = sorted(rs, key=lambda r: int(ipaddr.IPv4Address(r['start'])))

        self.assertEqual(r1.start_str, rs[0]['start'])
        self.assertEqual(r1.end_str, rs[0]['end'])
        self.assertEqual(r1.pk, rs[0]['pk'])
def find_related(request):
    """
    Given a list of site, vlan, and network primary keys, help a user make
    choices about where to put an IP address

    A user can select from choices:
        Networks
        Vlans
        Sites

    The goal of the UI is to help a user choose a range -- which for this
    function can be seen as filtering down to exactly 1 network.

    When a user selects a site, this can limit which networks and in turn which
    vlans are displayed.

    When a user selects a vlan, this can limit which networks are displayed
    which in turn can limit which sites are displayed

    When a user selects a network, this will limit both networks, vlans, and
    sites to at most one object per each type.

    input::
        {
            'choice': [<type>, <pk>],
            'sites': [1, ...],
            'vlans': [1, ...],
            'networks': [1, ...],
        }

    The value of '<type>' is a string that is either 'site', 'vlan', or
    'network'. The value of '<pk>' is a number.

    output:
        Same as input but with things filtered plus a new list of 'range'
        information. E.x.:
        {
            'sites': [<pks>],
            'vlans': [<pks>],
            'networks': [<pks>],
            'range': [
                {'name': ...
                 'ip_start': ...
                 'ip_end': ...
                 'reserved': ...
                },
                ...
                ...
                ...
                {'name': ...
                 'ip_start': ...
                 'ip_end': ...
                 'reserved': ...
                }
            ]
        }

    This function will key off of 'choice' to determine how to slim down a
    users choice of objects.
    """
    state = json.loads(request.raw_post_data)

    if not state:
        raise Exception("No state?")

    if 'choice' not in state:
        raise Exception("No choice?")

    try:
        choice_type, choice_pk = state['choice']
    except ValueError:
        raise Exception("Choice was '{0}'. This is wrong".format(
            state['choice']))

    filter_network, filter_site, filter_vlan = calculate_filters(
        choice_type, choice_pk)
    format_network, format_site, format_vlan = label_value_maker()

    new_state = {
        'sites': format_site(filter_site(state['sites'])),
        'vlans': format_vlan(filter_vlan(state['vlans'])),
    }

    # Network are special. If there is only one, we need to add some range
    # info. If there are zero or more than one, don't add any range objects
    networks = filter_network(state['networks'])
    if len(networks) == 1:
        new_state['ranges'] = integrate_real_ranges(
            networks[0], calc_template_ranges(networks[0]))
    new_state['networks'] = format_network(networks)

    return HttpResponse(json.dumps(new_state))
Esempio n. 6
0
def find_related(request):
    """
    Given a list of site, vlan, and network primary keys, help a user make
    choices about where to put an IP address

    A user can select from choices:
        Networks
        Vlans
        Sites

    The goal of the UI is to help a user choose a range -- which for this
    function can be seen as filtering down to exactly 1 network.

    When a user selects a site, this can limit which networks and in turn which
    vlans are displayed.

    When a user selects a vlan, this can limit which networks are displayed
    which in turn can limit which sites are displayed

    When a user selects a network, this will limit both networks, vlans, and
    sites to at most one object per each type.

    input::
        {
            'choice': [<type>, <pk>],
            'sites': [1, ...],
            'vlans': [1, ...],
            'networks': [1, ...],
        }

    The value of '<type>' is a string that is either 'site', 'vlan', or
    'network'. The value of '<pk>' is a number.

    output:
        Same as input but with things filtered plus a new list of 'range'
        information. E.x.:
        {
            'sites': [<pks>],
            'vlans': [<pks>],
            'networks': [<pks>],
            'range': [
                {'name': ...
                 'ip_start': ...
                 'ip_end': ...
                 'reserved': ...
                },
                ...
                ...
                ...
                {'name': ...
                 'ip_start': ...
                 'ip_end': ...
                 'reserved': ...
                }
            ]
        }

    This function will key off of 'choice' to determine how to slim down a
    users choice of objects.
    """
    state = json.loads(request.raw_post_data)

    if not state:
        raise Exception("No state?")

    if 'choice' not in state:
        raise Exception("No choice?")

    try:
        choice_type, choice_pk = state['choice']
    except ValueError:
        raise Exception(
            "Choice was '{0}'. This is wrong".format(state['choice'])
        )

    filter_network, filter_site, filter_vlan = calculate_filters(
        choice_type, choice_pk
    )
    format_network, format_site, format_vlan = label_value_maker()

    new_state = {
        'sites': format_site(filter_site(state['sites'])),
        'vlans': format_vlan(filter_vlan(state['vlans'])),
    }

    # Network are special. If there is only one, we need to add some range
    # info. If there are zero or more than one, don't add any range objects
    networks = filter_network(state['networks'])
    if len(networks) == 1:
        new_state['ranges'] = integrate_real_ranges(
            networks[0], calc_template_ranges(networks[0])
        )
    new_state['networks'] = format_network(networks)

    return HttpResponse(json.dumps(new_state))
Esempio n. 7
0
def bulk_gather_vlan_pools(request):
    vlan_name = request.GET.get('vlan_name', None)
    vlan_number = request.GET.get('vlan_number', None)
    site_name = request.GET.get('site_name', None)
    ip_type = request.GET.get('ip_type', None)

    if not site_name:
        return HttpResponse(dumps({
            'errors': 'Site name was not provided'
        }))

    if not ip_type:
        return HttpResponse(dumps({
            'errors': 'IP type is required here.'
        }))

    if vlan_name and vlan_number:
        s = 'site=:{site_name} AND vlan=:{vlan_name},{vlan_number}'.format(
            site_name=site_name, vlan_name=vlan_name, vlan_number=vlan_number
        )
    elif vlan_name:
        s = 'site=:{site_name} AND vlan=:{vlan_name}'.format(
            site_name=site_name, vlan_name=vlan_name
        )
    elif vlan_number:
        s = 'site=:{site_name} AND vlan=:{vlan_number}'.format(
            site_name=site_name, vlan_number=vlan_number
        )
    else:
        return HttpResponse(dumps({
            'errors': 'Not enough vlan information was provided'
        }))

    q_map, errors = compile_to_q(s)

    if errors:
        return None, errors

    networks = Network.objects.filter(q_map['NET']).filter(ip_type=ip_type)
    if networks.count() > 1:
        return HttpResponse(dumps({
            'errors': "Using the search '{s}', too many networks were "
            "found. Please be more specific and specify a range.".format(s=s)
        }))
    if not networks.count():
        return HttpResponse(dumps({
            'errors': "Using the search '{s}', no networks were "
            "found.".format(s=s)
        }))

    ranges = integrate_real_ranges(
        networks[0], calc_template_ranges(networks[0])
    )
    free_ranges = []
    for r in ranges:
        if r['rtype'] == 'special purpose':
            continue
        free_ranges += range_usage(
            r['start'], r['end'], ip_type
        )['free_ranges']

    return HttpResponse(dumps({
        'free_ranges': free_ranges
    }))