diff --git a/README.md b/README.md index 66c35250b..f2b430929 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +**The [2017 NetBox User Survey](https://goo.gl/forms/75HnNS2iE0Y1hVFH3) is open!** Please consider taking a moment to respond. Your feedback helps shape the pace and focus of NetBox development. The survey will remain open until 2017-03-31. Results will be published on the mailing list. + +--- + ![NetBox](docs/netbox_logo.png "NetBox logo") NetBox is an IP address management (IPAM) and data center infrastructure management (DCIM) tool. Initially conceived by the network engineering team at [DigitalOcean](https://www.digitalocean.com/), NetBox was developed specifically to address the needs of network and infrastructure engineers. diff --git a/docs/data-model/extras.md b/docs/data-model/extras.md index 58da76cee..ec424fec2 100644 --- a/docs/data-model/extras.md +++ b/docs/data-model/extras.md @@ -90,6 +90,22 @@ NetBox does not have the ability to generate graphs natively, but this feature a * **Source URL:** The source of the image to be embedded. The associated object will be available as a template variable named `obj`. * **Link URL (optional):** A URL to which the graph will be linked. The associated object will be available as a template variable named `obj`. +## Examples + +You only need to define one graph object for each graph you want to include when viewing an object. For example, if you want to include a graph of traffic through an interface over the past five minutes, your graph source might looks like this: + +``` +https://my.nms.local/graphs/?node={{ obj.device.name }}&interface={{ obj.name }}&duration=5m +``` + +You can define several graphs to provide multiple contexts when viewing an object. For example: + +``` +https://my.nms.local/graphs/?type=throughput&node={{ obj.device.name }}&interface={{ obj.name }}&duration=60m +https://my.nms.local/graphs/?type=throughput&node={{ obj.device.name }}&interface={{ obj.name }}&duration=24h +https://my.nms.local/graphs/?type=errors&node={{ obj.device.name }}&interface={{ obj.name }}&duration=60m +``` + # Topology Maps NetBox can generate simple topology maps from the physical network connections recorded in its database. First, you'll need to create a topology map definition under the admin UI at Extras > Topology Maps. diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index cb307324e..246fe06f0 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -90,7 +90,12 @@ class ComponentCreateView(View): self.parent_field: parent.pk, 'name': name, } - component_data.update(data) + # Replace objects with their primary key to keep component_form.clean() happy + for k, v in data.items(): + if hasattr(v, 'pk'): + component_data[k] = v.pk + else: + component_data[k] = v component_form = self.model_form(component_data) if component_form.is_valid(): new_components.append(component_form.save(commit=False)) diff --git a/netbox/utilities/forms.py b/netbox/utilities/forms.py index 76ce1796c..dd6235f45 100644 --- a/netbox/utilities/forms.py +++ b/netbox/utilities/forms.py @@ -57,7 +57,7 @@ def parse_numeric_range(string, base=10): begin, end = dash_range.split('-') except ValueError: begin, end = dash_range, dash_range - begin, end = int(begin.strip()), int(end.strip(), base=base) + 1 + begin, end = int(begin.strip(), base=base), int(end.strip(), base=base) + 1 values.extend(range(begin, end)) return list(set(values)) diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index 4d6ec3332..f38d9a0ab 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -434,7 +434,7 @@ class BulkEditView(View): # Are we editing *all* objects in the queryset or just a selected subset? if request.POST.get('_all') and self.filter is not None: - pk_list = [obj.pk for obj in self.filter(request.GET, self.cls.objects.only('pk'))] + pk_list = [obj.pk for obj in self.filter(request.GET, self.cls.objects.only('pk')).qs] else: pk_list = [int(pk) for pk in request.POST.getlist('pk')] @@ -572,7 +572,7 @@ class BulkDeleteView(View): # Are we deleting *all* objects in the queryset or just a selected subset? if request.POST.get('_all') and self.filter is not None: - pk_list = [obj.pk for obj in self.filter(request.GET, self.cls.objects.only('pk'))] + pk_list = [obj.pk for obj in self.filter(request.GET, self.cls.objects.only('pk')).qs] else: pk_list = [int(pk) for pk in request.POST.getlist('pk')]