Closes #191: Support for racks numbered top-to-bottom

This commit is contained in:
Jeremy Stretch 2016-10-28 11:30:40 -04:00
parent f8f5d6876b
commit 2db50dd4a7
10 changed files with 49 additions and 13 deletions

View File

@ -79,7 +79,7 @@ class RackSerializer(CustomFieldSerializer, serializers.ModelSerializer):
class Meta:
model = Rack
fields = ['id', 'name', 'facility_id', 'display_name', 'site', 'group', 'tenant', 'role', 'type', 'width',
'u_height', 'comments', 'custom_fields']
'u_height', 'desc_units', 'comments', 'custom_fields']
class RackNestedSerializer(RackSerializer):
@ -94,7 +94,7 @@ class RackDetailSerializer(RackSerializer):
class Meta(RackSerializer.Meta):
fields = ['id', 'name', 'facility_id', 'display_name', 'site', 'group', 'tenant', 'role', 'type', 'width',
'u_height', 'comments', 'custom_fields', 'front_units', 'rear_units']
'u_height', 'desc_units', 'comments', 'custom_fields', 'front_units', 'rear_units']
def get_front_units(self, obj):
units = obj.get_rack_units(face=RACK_FACE_FRONT)

View File

@ -142,7 +142,8 @@ class RackForm(BootstrapMixin, CustomFieldForm):
class Meta:
model = Rack
fields = ['site', 'group', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height', 'comments']
fields = ['site', 'group', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height', 'desc_units',
'comments']
help_texts = {
'site': "The site at which the rack exists",
'name': "Organizational rack name",
@ -178,7 +179,8 @@ class RackFromCSVForm(forms.ModelForm):
class Meta:
model = Rack
fields = ['site', 'group_name', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height']
fields = ['site', 'group_name', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height',
'desc_units']
def clean(self):
@ -368,7 +370,7 @@ class DeviceForm(BootstrapMixin, CustomFieldForm):
attrs={'filter-for': 'position'}
))
position = forms.TypedChoiceField(required=False, empty_value=None,
help_text="For multi-U devices, this is the lowest occupied rack unit.",
help_text="The lowest-numbered unit occupied by the device",
widget=APISelect(api_url='/api/dcim/racks/{{rack}}/rack-units/?face={{face}}',
disabled_indicator='device'))
manufacturer = forms.ModelChoiceField(queryset=Manufacturer.objects.all(),

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-10-28 15:01
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dcim', '0019_new_iface_form_factors'),
]
operations = [
migrations.AddField(
model_name='rack',
name='desc_units',
field=models.BooleanField(default=False, help_text=b'Units are numbered top-to-bottom', verbose_name=b'Descending units'),
),
]

View File

@ -375,6 +375,8 @@ class Rack(CreatedUpdatedModel, CustomFieldModel):
help_text='Rail-to-rail width')
u_height = models.PositiveSmallIntegerField(default=42, verbose_name='Height (U)',
validators=[MinValueValidator(1), MaxValueValidator(100)])
desc_units = models.BooleanField(default=False, verbose_name='Descending units',
help_text='Units are numbered top-to-bottom')
comments = models.TextField(blank=True)
custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
@ -422,7 +424,10 @@ class Rack(CreatedUpdatedModel, CustomFieldModel):
@property
def units(self):
return reversed(range(1, self.u_height + 1))
if self.desc_units:
return range(1, self.u_height + 1)
else:
return reversed(range(1, self.u_height + 1))
@property
def display_name(self):
@ -441,7 +446,7 @@ class Rack(CreatedUpdatedModel, CustomFieldModel):
"""
elevation = OrderedDict()
for u in reversed(range(1, self.u_height + 1)):
for u in self.units:
elevation[u] = {'id': u, 'name': 'U{}'.format(u), 'face': face, 'device': None}
# Add devices to rack units list
@ -815,7 +820,7 @@ class Device(CreatedUpdatedModel, CustomFieldModel):
rack = models.ForeignKey('Rack', related_name='devices', on_delete=models.PROTECT)
position = models.PositiveSmallIntegerField(blank=True, null=True, validators=[MinValueValidator(1)],
verbose_name='Position (U)',
help_text='Number of the lowest U position occupied by the device')
help_text='The lowest-numbered unit occupied by the device')
face = models.PositiveSmallIntegerField(blank=True, null=True, choices=RACK_FACE_CHOICES, verbose_name='Rack face')
status = models.BooleanField(choices=STATUS_CHOICES, default=STATUS_ACTIVE, verbose_name='Status')
primary_ip4 = models.OneToOneField('ipam.IPAddress', related_name='primary_ip4_for', on_delete=models.SET_NULL,

View File

@ -49,6 +49,7 @@ class SiteTest(APITestCase):
'type',
'width',
'u_height',
'desc_units',
'comments',
'custom_fields',
]
@ -129,6 +130,7 @@ class RackTest(APITestCase):
'type',
'width',
'u_height',
'desc_units',
'comments',
'custom_fields',
]
@ -145,6 +147,7 @@ class RackTest(APITestCase):
'type',
'width',
'u_height',
'desc_units',
'comments',
'custom_fields',
'front_units',

View File

@ -78,7 +78,7 @@
</tr>
<tr>
<td>Position (U)</td>
<td>Lowest rack unit occupied by the device (optional)</td>
<td>Lowest-numbered rack unit occupied by the device (optional)</td>
<td>21</td>
</tr>
<tr>

View File

@ -122,7 +122,7 @@
</tr>
<tr>
<td>Height</td>
<td>{{ rack.u_height }}U</td>
<td>{{ rack.u_height }}U ({% if rack.desc_units %}descending{% else %}ascending{% endif %})</td>
</tr>
<tr>
<td>Devices</td>
@ -189,13 +189,13 @@
<div class="rack_header">
<h4>Front</h4>
</div>
{% include 'dcim/_rack_elevation.html' with primary_face=front_elevation secondary_face=rear_elevation face_id=0 %}
{% include 'dcim/inc/_rack_elevation.html' with primary_face=front_elevation secondary_face=rear_elevation face_id=0 %}
</div>
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="rack_header">
<h4>Rear</h4>
</div>
{% include 'dcim/_rack_elevation.html' with primary_face=rear_elevation secondary_face=front_elevation face_id=1 %}
{% include 'dcim/inc/_rack_elevation.html' with primary_face=rear_elevation secondary_face=front_elevation face_id=1 %}
</div>
</div>
</div>

View File

@ -14,6 +14,7 @@
{% render_field form.type %}
{% render_field form.width %}
{% render_field form.u_height %}
{% render_field form.desc_units %}
</div>
</div>
{% if form.custom_fields %}

View File

@ -73,10 +73,15 @@
<td>Height in rack units</td>
<td>42</td>
</tr>
<tr>
<td>Descending units</td>
<td>Units are numbered top-to-bottom</td>
<td>False</td>
</tr>
</tbody>
</table>
<h4>Example</h4>
<pre>DC-4,Cage 1400,R101,J12.100,Pied Piper,Compute,4-post cabinet,19,42</pre>
<pre>DC-4,Cage 1400,R101,J12.100,Pied Piper,Compute,4-post cabinet,19,42,False</pre>
</div>
</div>
{% endblock %}