Parcourir la source

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

Jeremy Stretch il y a 8 ans
Parent
commit
2db50dd4a7

+ 2 - 2
netbox/dcim/api/serializers.py

@@ -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)

+ 5 - 3
netbox/dcim/forms.py

@@ -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(),

+ 20 - 0
netbox/dcim/migrations/0020_rack_desc_units.py

@@ -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'),
+        ),
+    ]

+ 8 - 3
netbox/dcim/models.py

@@ -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,

+ 3 - 0
netbox/dcim/tests/test_apis.py

@@ -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',

+ 1 - 1
netbox/templates/dcim/device_import.html

@@ -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>

netbox/templates/dcim/_rack_elevation.html → netbox/templates/dcim/inc/_rack_elevation.html


+ 3 - 3
netbox/templates/dcim/rack.html

@@ -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>

+ 1 - 0
netbox/templates/dcim/rack_edit.html

@@ -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 %}

+ 6 - 1
netbox/templates/dcim/rack_import.html

@@ -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 %}