def ip_to_range(ip): """Attempt to map an IP into a range""" ip_type = resolve_ip_type(ip) ip_upper, ip_lower = one_to_two(ip_to_int(ip, ip_type[0])) # If it's within the uppers, it's definitely within the lowers upper_q = Q( ~Q(start_upper=F('end_upper')), start_upper__lte=ip_upper, end_upper__gte=ip_upper ) # If the uppers match, look in the lowers lower_q = Q( Q(start_upper=F('end_upper')), start_lower__lte=ip_lower, end_lower__gte=ip_lower ) try: return Range.objects.get(upper_q | lower_q) except Range.DoesNotExist: pass
def integrate_real_ranges(network, template_ranges): """ Say we have a network:: 10.8.0.0 10.8.0.255 |------------------------------------------------------....--| For every network there is (or should be) a range template. This breaks up the range into reservations that the user can then select from when finding a free ip address:: 10.8.0.0 10.8.0.255 |------------------------------------------------------....--| |--template--| |------template-----| 10.8.0.1 10.8.0.10 10.8.0.50 10.8.0.100 "Template" ranges are not real objects in the database; they do not have detail pages, they do not show up in search, and they do not have primary keys. They are a simple *default* overlay onto a network's ip space. There is, however, a real version of a range that is stored in Inventory's database; it has a detail page, shows up in searches, and has a primary key. These range objects have a ``start`` and ``end`` ip address and have a foreign key back to a specific Inventory network object. They serve the same purpose as a template range except they are defined by the user via the GUI or invtool. Inventory makes sure that these real range objects are always within the bounds of their parent network and that no two ranges overlap. What happens to the template ranges when a real range is defined inside an Inventory network? For example:: 10.8.0.0 10.8.0.255 |------------------------------------------------------....--| |-- template --| |----- user defined range -----| 10.8.0.1 10.8.0.10 10.8.0.50 10.8.0.100 In this case both the template range and the user defined range is returned. Another example:: 10.8.0.0 10.8.0.255 |------------------------------------------------------....--| |----- template ------| 10.8.0.15 10.8.0.60 |-- template --| |----- user defined range ----| 10.8.0.1 10.8.0.10 10.8.0.50 10.8.0.100 In this case the overlapping template range is filtered out. This function looks at the ranges in the db and removed template ranges that overlap with real ranges. This function also injects the real ranges in with the template ranges. The return format is the same as :func:`calc_ranges`. """ real_ranges = network.range_set.all() if not real_ranges: return template_ranges name_fragment = calc_name_fragment(network) dhcp_scope = network.calc_dhcp_scope_name() filtered_ranges = [] no_ovlp_templates = [] for tr in template_ranges: ol = False for r in real_ranges: ol = overlap( (r.start_str, r.end_str), (tr['start'], tr['end']), ip_type=network.ip_type, cast_to_int=True ) if ol: break if not ol: no_ovlp_templates.append(tr) for r in real_ranges: filtered_ranges.append({ 'name': r.name, 'rtype': r.name, 'start': r.start_str, 'end': r.end_str, 'dhcp_scope': dhcp_scope, 'name_fragment': name_fragment, 'pk': r.pk }) filtered_ranges += no_ovlp_templates return sorted( filtered_ranges, key=lambda r: ip_to_int(r['start'], network.ip_type) )
def integrate_real_ranges(network, template_ranges): """ Say we have a network:: 10.8.0.0 10.8.0.255 |------------------------------------------------------....--| For every network there is (or should be) a range template. This breaks up the range into reservations that the user can then select from when finding a free ip address:: 10.8.0.0 10.8.0.255 |------------------------------------------------------....--| |--template--| |------template-----| 10.8.0.1 10.8.0.10 10.8.0.50 10.8.0.100 "Template" ranges are not real objects in the database; they do not have detail pages, they do not show up in search, and they do not have primary keys. They are a simple *default* overlay onto a network's ip space. There is, however, a real version of a range that is stored in Inventory's database; it has a detail page, shows up in searches, and has a primary key. These range objects have a ``start`` and ``end`` ip address and have a foreign key back to a specific Inventory network object. They serve the same purpose as a template range except they are defined by the user via the GUI or invtool. Inventory makes sure that these real range objects are always within the bounds of their parent network and that no two ranges overlap. What happens to the template ranges when a real range is defined inside an Inventory network? For example:: 10.8.0.0 10.8.0.255 |------------------------------------------------------....--| |-- template --| |----- user defined range -----| 10.8.0.1 10.8.0.10 10.8.0.50 10.8.0.100 In this case both the template range and the user defined range is returned. Another example:: 10.8.0.0 10.8.0.255 |------------------------------------------------------....--| |----- template ------| 10.8.0.15 10.8.0.60 |-- template --| |----- user defined range ----| 10.8.0.1 10.8.0.10 10.8.0.50 10.8.0.100 In this case the overlapping template range is filtered out. This function looks at the ranges in the db and removed template ranges that overlap with real ranges. This function also injects the real ranges in with the template ranges. The return format is the same as :func:`calc_ranges`. """ real_ranges = network.range_set.all() if not real_ranges: return template_ranges name_fragment = calc_name_fragment(network) dhcp_scope = network.calc_dhcp_scope_name() filtered_ranges = [] no_ovlp_templates = [] for tr in template_ranges: ol = False for r in real_ranges: ol = overlap((r.start_str, r.end_str), (tr['start'], tr['end']), ip_type=network.ip_type, cast_to_int=True) if ol: break if not ol: no_ovlp_templates.append(tr) for r in real_ranges: filtered_ranges.append({ 'name': r.name, 'rtype': r.name, 'start': r.start_str, 'end': r.end_str, 'dhcp_scope': dhcp_scope, 'name_fragment': name_fragment, 'pk': r.pk }) filtered_ranges += no_ovlp_templates return sorted(filtered_ranges, key=lambda r: ip_to_int(r['start'], network.ip_type))