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}))
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'])
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'])
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))
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))
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 }))