Merged v2.3.6

This commit is contained in:
Jeremy Stretch 2018-07-16 12:03:32 -04:00
commit d7e40de9da
11 changed files with 51 additions and 11 deletions

View File

@ -206,3 +206,28 @@ The maximum number of objects that can be returned is limited by the [`MAX_PAGE_
!!! warning
Disabling the page size limit introduces a potential for very resource-intensive requests, since one API request can effectively retrieve an entire table from the database.
# Filtering
A list of objects retrieved via the API can be filtered by passing one or more query parameters. The same parameters used by the web UI work for the API as well. For example, to return only prefixes with a status of "Active" (`1`):
```
GET /api/ipam/prefixes/?status=1
```
The same filter can be incldued multiple times. These will effect a logical OR and return objects matching any of the given values. For example, the following will return all active and reserved prefixes:
```
GET /api/ipam/prefixes/?status=1&status=2
```
## Custom Fields
To filter on a custom field, prepend `cf_` to the field name. For example, the following query will return only sites where a custom field named `foo` is equal to 123:
```
GET /api/dcim/sites/?cf_foo=123
```
!!! note
Full versus partial matching when filtering is configurable per custom field. Filtering can be toggled (or disabled) for a custom field in the admin UI.

View File

@ -42,6 +42,8 @@ A device type represents a particular hardware model that exists in the real wor
Device types are instantiated as devices installed within racks. For example, you might define a device type to represent a Juniper EX4300-48T network switch with 48 Ethernet interfaces. You can then create multiple devices of this type named "switch1," "switch2," and so on. Each device will inherit the components (such as interfaces) of its device type.
A device type can be a parent, child, or neither. Parent devices house child devices in device bays. This relationship is used to model things like blade servers, where child devices function independently but share physical resources like rack space and power. Note that this is **not** intended to model chassis-based devices, wherein child members share a common control plane.
### Manufacturers
Each device type belongs to one manufacturer; e.g. Cisco, Opengear, or APC. The model number of a device type must be unique to its manufacturer.

View File

@ -81,7 +81,7 @@ AUTH_LDAP_USER_ATTR_MAP = {
# User Groups for Permissions
!!! info
When using Microsoft Active Directory, support for nested groups can be activated by using `NestedGroupOfNamesType()` instead of `GroupOfNamesType()` for `AUTH_LDAP_GROUP_TYPE`.
When using Microsoft Active Directory, support for nested groups can be activated by using `NestedGroupOfNamesType()` instead of `GroupOfNamesType()` for `AUTH_LDAP_GROUP_TYPE`. You will also need to modify the import line to use `NestedGroupOfNamesType` instead of `GroupOfNamesType` .
```python
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType

View File

@ -32,7 +32,7 @@ class DeviceIPsReport(Report):
Within each report class, we'll create a number of test methods to execute our report's logic. In DeviceConnectionsReport, for instance, we want to ensure that every live device has a console connection, an out-of-band management connection, and two power connections.
```
from dcim.constants import CONNECTION_STATUS_PLANNED, STATUS_ACTIVE
from dcim.constants import CONNECTION_STATUS_PLANNED, DEVICE_STATUS_ACTIVE
from dcim.models import ConsolePort, Device, PowerPort
from extras.reports import Report
@ -43,7 +43,7 @@ class DeviceConnectionsReport(Report):
def test_console_connection(self):
# Check that every console port for every active device has a connection defined.
for console_port in ConsolePort.objects.select_related('device').filter(device__status=STATUS_ACTIVE):
for console_port in ConsolePort.objects.select_related('device').filter(device__status=DEVICE_STATUS_ACTIVE):
if console_port.cs_port is None:
self.log_failure(
console_port.device,
@ -60,7 +60,7 @@ class DeviceConnectionsReport(Report):
def test_power_connections(self):
# Check that every active device has at least two connected power supplies.
for device in Device.objects.filter(status=STATUS_ACTIVE):
for device in Device.objects.filter(status=DEVICE_STATUS_ACTIVE):
connected_ports = 0
for power_port in PowerPort.objects.filter(device=device):
if power_port.power_outlet is not None:

View File

@ -1812,8 +1812,9 @@ class InterfaceAssignVLANsForm(BootstrapMixin, forms.ModelForm):
if parent is not None:
# Add site VLANs
site_vlans = VLAN.objects.filter(site=parent.site, group=None).exclude(pk__in=assigned_vlans)
vlan_choices.append((parent.site.name, [(vlan.pk, vlan) for vlan in site_vlans]))
if parent.site:
site_vlans = VLAN.objects.filter(site=parent.site, group=None).exclude(pk__in=assigned_vlans)
vlan_choices.append((parent.site.name, [(vlan.pk, vlan) for vlan in site_vlans]))
# Add grouped site VLANs
for group in VLANGroup.objects.filter(site=parent.site):

View File

@ -2101,7 +2101,7 @@ class InventoryItemBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
#
class VirtualChassisListView(ObjectListView):
queryset = VirtualChassis.objects.annotate(member_count=Count('members'))
queryset = VirtualChassis.objects.select_related('master').annotate(member_count=Count('members'))
table = tables.VirtualChassisTable
filter = filters.VirtualChassisFilter
filter_form = forms.VirtualChassisFilterForm

View File

@ -15,6 +15,7 @@ OBJ_TYPE_CHOICES = (
('rack', 'Racks'),
('devicetype', 'Device types'),
('device', 'Devices'),
('virtualchassis', 'Virtual Chassis'),
)),
('IPAM', (
('vrf', 'VRFs'),

View File

@ -12,9 +12,9 @@ from rest_framework.views import APIView
from circuits.filters import CircuitFilter, ProviderFilter
from circuits.models import Circuit, Provider
from circuits.tables import CircuitTable, ProviderTable
from dcim.filters import DeviceFilter, DeviceTypeFilter, RackFilter, SiteFilter
from dcim.models import ConsolePort, Device, DeviceType, InterfaceConnection, PowerPort, Rack, Site
from dcim.tables import DeviceDetailTable, DeviceTypeTable, RackTable, SiteTable
from dcim.filters import DeviceFilter, DeviceTypeFilter, RackFilter, SiteFilter, VirtualChassisFilter
from dcim.models import ConsolePort, Device, DeviceType, InterfaceConnection, PowerPort, Rack, Site, VirtualChassis
from dcim.tables import DeviceDetailTable, DeviceTypeTable, RackTable, SiteTable, VirtualChassisTable
from extras.models import ObjectChange, ReportResult, TopologyMap
from ipam.filters import AggregateFilter, IPAddressFilter, PrefixFilter, VLANFilter, VRFFilter
from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF
@ -72,6 +72,12 @@ SEARCH_TYPES = OrderedDict((
'table': DeviceDetailTable,
'url': 'dcim:device_list',
}),
('virtualchassis', {
'queryset': VirtualChassis.objects.select_related('master').annotate(member_count=Count('members')),
'filter': VirtualChassisFilter,
'table': VirtualChassisTable,
'url': 'dcim:virtualchassis_list',
}),
# IPAM
('vrf', {
'queryset': VRF.objects.select_related('tenant'),

View File

@ -459,6 +459,7 @@
<th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
{% endif %}
<th>Name</th>
<th>Status</th>
<th colspan="2">Installed Device</th>
<th></th>
</tr>

View File

@ -8,6 +8,9 @@
<i class="fa fa-fw fa-{% if devicebay.installed_device %}dot-circle-o{% else %}circle-o{% endif %}"></i> {{ devicebay.name }}
</td>
{% if devicebay.installed_device %}
<td>
<span class="label label-{{ devicebay.installed_device.get_status_class }}">{{ devicebay.installed_device.get_status_display }}</span>
</td>
<td>
<a href="{% url 'dcim:device' pk=devicebay.installed_device.pk %}">{{ devicebay.installed_device }}</a>
</td>
@ -15,6 +18,7 @@
<span>{{ devicebay.installed_device.device_type.full_name }}</span>
</td>
{% else %}
<td></td>
<td colspan="2">
<span class="text-muted">Vacant</span>
</td>

View File

@ -1,7 +1,7 @@
Django>=1.11
django-cors-headers>=2.1.0
django-debug-toolbar>=1.9.0
django-filter>=1.1.0
django-filter==1.1.0
django-mptt>=0.9.0
django-tables2>=1.19.0
django-taggit>=0.22.2