1from decimal import Decimal 2 3import pytz 4import yaml 5from django.contrib.auth.models import User 6from django.contrib.contenttypes.models import ContentType 7from django.test import override_settings 8from django.urls import reverse 9from netaddr import EUI 10 11from dcim.choices import * 12from dcim.constants import * 13from dcim.models import * 14from ipam.models import VLAN 15from utilities.testing import ViewTestCases, create_tags, create_test_device 16 17 18class RegionTestCase(ViewTestCases.OrganizationalObjectViewTestCase): 19 model = Region 20 21 @classmethod 22 def setUpTestData(cls): 23 24 # Create three Regions 25 regions = ( 26 Region(name='Region 1', slug='region-1'), 27 Region(name='Region 2', slug='region-2'), 28 Region(name='Region 3', slug='region-3'), 29 ) 30 for region in regions: 31 region.save() 32 33 cls.form_data = { 34 'name': 'Region X', 35 'slug': 'region-x', 36 'parent': regions[2].pk, 37 'description': 'A new region', 38 } 39 40 cls.csv_data = ( 41 "name,slug,description", 42 "Region 4,region-4,Fourth region", 43 "Region 5,region-5,Fifth region", 44 "Region 6,region-6,Sixth region", 45 ) 46 47 cls.bulk_edit_data = { 48 'description': 'New description', 49 } 50 51 52class SiteGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase): 53 model = SiteGroup 54 55 @classmethod 56 def setUpTestData(cls): 57 58 # Create three SiteGroups 59 sitegroups = ( 60 SiteGroup(name='Site Group 1', slug='site-group-1'), 61 SiteGroup(name='Site Group 2', slug='site-group-2'), 62 SiteGroup(name='Site Group 3', slug='site-group-3'), 63 ) 64 for sitegroup in sitegroups: 65 sitegroup.save() 66 67 cls.form_data = { 68 'name': 'Site Group X', 69 'slug': 'site-group-x', 70 'parent': sitegroups[2].pk, 71 'description': 'A new site group', 72 } 73 74 cls.csv_data = ( 75 "name,slug,description", 76 "Site Group 4,site-group-4,Fourth site group", 77 "Site Group 5,site-group-5,Fifth site group", 78 "Site Group 6,site-group-6,Sixth site group", 79 ) 80 81 cls.bulk_edit_data = { 82 'description': 'New description', 83 } 84 85 86class SiteTestCase(ViewTestCases.PrimaryObjectViewTestCase): 87 model = Site 88 89 @classmethod 90 def setUpTestData(cls): 91 92 regions = ( 93 Region(name='Region 1', slug='region-1'), 94 Region(name='Region 2', slug='region-2'), 95 ) 96 for region in regions: 97 region.save() 98 99 groups = ( 100 SiteGroup(name='Site Group 1', slug='site-group-1'), 101 SiteGroup(name='Site Group 2', slug='site-group-2'), 102 ) 103 for group in groups: 104 group.save() 105 106 Site.objects.bulk_create([ 107 Site(name='Site 1', slug='site-1', region=regions[0], group=groups[1]), 108 Site(name='Site 2', slug='site-2', region=regions[0], group=groups[1]), 109 Site(name='Site 3', slug='site-3', region=regions[0], group=groups[1]), 110 ]) 111 112 tags = create_tags('Alpha', 'Bravo', 'Charlie') 113 114 cls.form_data = { 115 'name': 'Site X', 116 'slug': 'site-x', 117 'status': SiteStatusChoices.STATUS_PLANNED, 118 'region': regions[1].pk, 119 'group': groups[1].pk, 120 'tenant': None, 121 'facility': 'Facility X', 122 'asn': 65001, 123 'time_zone': pytz.UTC, 124 'description': 'Site description', 125 'physical_address': '742 Evergreen Terrace, Springfield, USA', 126 'shipping_address': '742 Evergreen Terrace, Springfield, USA', 127 'latitude': Decimal('35.780000'), 128 'longitude': Decimal('-78.642000'), 129 'contact_name': 'Hank Hill', 130 'contact_phone': '123-555-9999', 131 'contact_email': 'hank@stricklandpropane.com', 132 'comments': 'Test site', 133 'tags': [t.pk for t in tags], 134 } 135 136 cls.csv_data = ( 137 "name,slug,status", 138 "Site 4,site-4,planned", 139 "Site 5,site-5,active", 140 "Site 6,site-6,staging", 141 ) 142 143 cls.bulk_edit_data = { 144 'status': SiteStatusChoices.STATUS_PLANNED, 145 'region': regions[1].pk, 146 'group': groups[1].pk, 147 'tenant': None, 148 'asn': 65009, 149 'time_zone': pytz.timezone('US/Eastern'), 150 'description': 'New description', 151 } 152 153 154class LocationTestCase(ViewTestCases.OrganizationalObjectViewTestCase): 155 model = Location 156 157 @classmethod 158 def setUpTestData(cls): 159 160 site = Site(name='Site 1', slug='site-1') 161 site.save() 162 163 locations = ( 164 Location(name='Location 1', slug='location-1', site=site), 165 Location(name='Location 2', slug='location-2', site=site), 166 Location(name='Location 3', slug='location-3', site=site), 167 ) 168 for location in locations: 169 location.save() 170 171 cls.form_data = { 172 'name': 'Location X', 173 'slug': 'location-x', 174 'site': site.pk, 175 'description': 'A new location', 176 } 177 178 cls.csv_data = ( 179 "site,name,slug,description", 180 "Site 1,Location 4,location-4,Fourth location", 181 "Site 1,Location 5,location-5,Fifth location", 182 "Site 1,Location 6,location-6,Sixth location", 183 ) 184 185 cls.bulk_edit_data = { 186 'description': 'New description', 187 } 188 189 190class RackRoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase): 191 model = RackRole 192 193 @classmethod 194 def setUpTestData(cls): 195 196 RackRole.objects.bulk_create([ 197 RackRole(name='Rack Role 1', slug='rack-role-1'), 198 RackRole(name='Rack Role 2', slug='rack-role-2'), 199 RackRole(name='Rack Role 3', slug='rack-role-3'), 200 ]) 201 202 cls.form_data = { 203 'name': 'Rack Role X', 204 'slug': 'rack-role-x', 205 'color': 'c0c0c0', 206 'description': 'New role', 207 } 208 209 cls.csv_data = ( 210 "name,slug,color", 211 "Rack Role 4,rack-role-4,ff0000", 212 "Rack Role 5,rack-role-5,00ff00", 213 "Rack Role 6,rack-role-6,0000ff", 214 ) 215 216 cls.bulk_edit_data = { 217 'color': '00ff00', 218 'description': 'New description', 219 } 220 221 222class RackReservationTestCase(ViewTestCases.PrimaryObjectViewTestCase): 223 model = RackReservation 224 225 @classmethod 226 def setUpTestData(cls): 227 228 user2 = User.objects.create_user(username='testuser2') 229 user3 = User.objects.create_user(username='testuser3') 230 231 site = Site.objects.create(name='Site 1', slug='site-1') 232 233 location = Location(name='Location 1', slug='location-1', site=site) 234 location.save() 235 236 rack = Rack(name='Rack 1', site=site, location=location) 237 rack.save() 238 239 RackReservation.objects.bulk_create([ 240 RackReservation(rack=rack, user=user2, units=[1, 2, 3], description='Reservation 1'), 241 RackReservation(rack=rack, user=user2, units=[4, 5, 6], description='Reservation 2'), 242 RackReservation(rack=rack, user=user2, units=[7, 8, 9], description='Reservation 3'), 243 ]) 244 245 tags = create_tags('Alpha', 'Bravo', 'Charlie') 246 247 cls.form_data = { 248 'rack': rack.pk, 249 'units': "10,11,12", 250 'user': user3.pk, 251 'tenant': None, 252 'description': 'Rack reservation', 253 'tags': [t.pk for t in tags], 254 } 255 256 cls.csv_data = ( 257 'site,location,rack,units,description', 258 'Site 1,Location 1,Rack 1,"10,11,12",Reservation 1', 259 'Site 1,Location 1,Rack 1,"13,14,15",Reservation 2', 260 'Site 1,Location 1,Rack 1,"16,17,18",Reservation 3', 261 ) 262 263 cls.bulk_edit_data = { 264 'user': user3.pk, 265 'tenant': None, 266 'description': 'New description', 267 } 268 269 270class RackTestCase(ViewTestCases.PrimaryObjectViewTestCase): 271 model = Rack 272 273 @classmethod 274 def setUpTestData(cls): 275 276 sites = ( 277 Site(name='Site 1', slug='site-1'), 278 Site(name='Site 2', slug='site-2'), 279 ) 280 Site.objects.bulk_create(sites) 281 282 locations = ( 283 Location(name='Location 1', slug='location-1', site=sites[0]), 284 Location(name='Location 2', slug='location-2', site=sites[1]) 285 ) 286 for location in locations: 287 location.save() 288 289 rackroles = ( 290 RackRole(name='Rack Role 1', slug='rack-role-1'), 291 RackRole(name='Rack Role 2', slug='rack-role-2'), 292 ) 293 RackRole.objects.bulk_create(rackroles) 294 295 Rack.objects.bulk_create(( 296 Rack(name='Rack 1', site=sites[0]), 297 Rack(name='Rack 2', site=sites[0]), 298 Rack(name='Rack 3', site=sites[0]), 299 )) 300 301 tags = create_tags('Alpha', 'Bravo', 'Charlie') 302 303 cls.form_data = { 304 'name': 'Rack X', 305 'facility_id': 'Facility X', 306 'site': sites[1].pk, 307 'location': locations[1].pk, 308 'tenant': None, 309 'status': RackStatusChoices.STATUS_PLANNED, 310 'role': rackroles[1].pk, 311 'serial': '123456', 312 'asset_tag': 'ABCDEF', 313 'type': RackTypeChoices.TYPE_CABINET, 314 'width': RackWidthChoices.WIDTH_19IN, 315 'u_height': 48, 316 'desc_units': False, 317 'outer_width': 500, 318 'outer_depth': 500, 319 'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER, 320 'comments': 'Some comments', 321 'tags': [t.pk for t in tags], 322 } 323 324 cls.csv_data = ( 325 "site,location,name,status,width,u_height", 326 "Site 1,,Rack 4,active,19,42", 327 "Site 1,Location 1,Rack 5,active,19,42", 328 "Site 2,Location 2,Rack 6,active,19,42", 329 ) 330 331 cls.bulk_edit_data = { 332 'site': sites[1].pk, 333 'location': locations[1].pk, 334 'tenant': None, 335 'status': RackStatusChoices.STATUS_DEPRECATED, 336 'role': rackroles[1].pk, 337 'serial': '654321', 338 'type': RackTypeChoices.TYPE_4POST, 339 'width': RackWidthChoices.WIDTH_23IN, 340 'u_height': 49, 341 'desc_units': True, 342 'outer_width': 30, 343 'outer_depth': 30, 344 'outer_unit': RackDimensionUnitChoices.UNIT_INCH, 345 'comments': 'New comments', 346 } 347 348 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 349 def test_list_rack_elevations(self): 350 """ 351 Test viewing the list of rack elevations. 352 """ 353 response = self.client.get(reverse('dcim:rack_elevation_list')) 354 self.assertHttpStatus(response, 200) 355 356 357class ManufacturerTestCase(ViewTestCases.OrganizationalObjectViewTestCase): 358 model = Manufacturer 359 360 @classmethod 361 def setUpTestData(cls): 362 363 Manufacturer.objects.bulk_create([ 364 Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), 365 Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), 366 Manufacturer(name='Manufacturer 3', slug='manufacturer-3'), 367 ]) 368 369 cls.form_data = { 370 'name': 'Manufacturer X', 371 'slug': 'manufacturer-x', 372 'description': 'A new manufacturer', 373 } 374 375 cls.csv_data = ( 376 "name,slug,description", 377 "Manufacturer 4,manufacturer-4,Fourth manufacturer", 378 "Manufacturer 5,manufacturer-5,Fifth manufacturer", 379 "Manufacturer 6,manufacturer-6,Sixth manufacturer", 380 ) 381 382 cls.bulk_edit_data = { 383 'description': 'New description', 384 } 385 386 387# TODO: Change base class to PrimaryObjectViewTestCase 388# Blocked by absence of bulk import view for DeviceTypes 389class DeviceTypeTestCase( 390 ViewTestCases.GetObjectViewTestCase, 391 ViewTestCases.GetObjectChangelogViewTestCase, 392 ViewTestCases.CreateObjectViewTestCase, 393 ViewTestCases.EditObjectViewTestCase, 394 ViewTestCases.DeleteObjectViewTestCase, 395 ViewTestCases.ListObjectsViewTestCase, 396 ViewTestCases.BulkEditObjectsViewTestCase, 397 ViewTestCases.BulkDeleteObjectsViewTestCase 398): 399 model = DeviceType 400 401 @classmethod 402 def setUpTestData(cls): 403 404 manufacturers = ( 405 Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), 406 Manufacturer(name='Manufacturer 2', slug='manufacturer-2') 407 ) 408 Manufacturer.objects.bulk_create(manufacturers) 409 410 DeviceType.objects.bulk_create([ 411 DeviceType(model='Device Type 1', slug='device-type-1', manufacturer=manufacturers[0]), 412 DeviceType(model='Device Type 2', slug='device-type-2', manufacturer=manufacturers[0]), 413 DeviceType(model='Device Type 3', slug='device-type-3', manufacturer=manufacturers[0]), 414 ]) 415 416 tags = create_tags('Alpha', 'Bravo', 'Charlie') 417 418 cls.form_data = { 419 'manufacturer': manufacturers[1].pk, 420 'model': 'Device Type X', 421 'slug': 'device-type-x', 422 'part_number': '123ABC', 423 'u_height': 2, 424 'is_full_depth': True, 425 'subdevice_role': '', # CharField 426 'comments': 'Some comments', 427 'tags': [t.pk for t in tags], 428 } 429 430 cls.bulk_edit_data = { 431 'manufacturer': manufacturers[1].pk, 432 'u_height': 3, 433 'is_full_depth': False, 434 } 435 436 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 437 def test_import_objects(self): 438 """ 439 Custom import test for YAML-based imports (versus CSV) 440 """ 441 IMPORT_DATA = """ 442manufacturer: Generic 443model: TEST-1000 444slug: test-1000 445u_height: 2 446subdevice_role: parent 447comments: test comment 448console-ports: 449 - name: Console Port 1 450 type: de-9 451 - name: Console Port 2 452 type: de-9 453 - name: Console Port 3 454 type: de-9 455console-server-ports: 456 - name: Console Server Port 1 457 type: rj-45 458 - name: Console Server Port 2 459 type: rj-45 460 - name: Console Server Port 3 461 type: rj-45 462power-ports: 463 - name: Power Port 1 464 type: iec-60320-c14 465 - name: Power Port 2 466 type: iec-60320-c14 467 - name: Power Port 3 468 type: iec-60320-c14 469power-outlets: 470 - name: Power Outlet 1 471 type: iec-60320-c13 472 power_port: Power Port 1 473 feed_leg: A 474 - name: Power Outlet 2 475 type: iec-60320-c13 476 power_port: Power Port 1 477 feed_leg: A 478 - name: Power Outlet 3 479 type: iec-60320-c13 480 power_port: Power Port 1 481 feed_leg: A 482interfaces: 483 - name: Interface 1 484 type: 1000base-t 485 mgmt_only: true 486 - name: Interface 2 487 type: 1000base-t 488 - name: Interface 3 489 type: 1000base-t 490rear-ports: 491 - name: Rear Port 1 492 type: 8p8c 493 - name: Rear Port 2 494 type: 8p8c 495 - name: Rear Port 3 496 type: 8p8c 497front-ports: 498 - name: Front Port 1 499 type: 8p8c 500 rear_port: Rear Port 1 501 - name: Front Port 2 502 type: 8p8c 503 rear_port: Rear Port 2 504 - name: Front Port 3 505 type: 8p8c 506 rear_port: Rear Port 3 507device-bays: 508 - name: Device Bay 1 509 - name: Device Bay 2 510 - name: Device Bay 3 511""" 512 513 # Create the manufacturer 514 Manufacturer(name='Generic', slug='generic').save() 515 516 # Add all required permissions to the test user 517 self.add_permissions( 518 'dcim.view_devicetype', 519 'dcim.add_devicetype', 520 'dcim.add_consoleporttemplate', 521 'dcim.add_consoleserverporttemplate', 522 'dcim.add_powerporttemplate', 523 'dcim.add_poweroutlettemplate', 524 'dcim.add_interfacetemplate', 525 'dcim.add_frontporttemplate', 526 'dcim.add_rearporttemplate', 527 'dcim.add_devicebaytemplate', 528 ) 529 530 form_data = { 531 'data': IMPORT_DATA, 532 'format': 'yaml' 533 } 534 response = self.client.post(reverse('dcim:devicetype_import'), data=form_data, follow=True) 535 self.assertHttpStatus(response, 200) 536 537 dt = DeviceType.objects.get(model='TEST-1000') 538 self.assertEqual(dt.comments, 'test comment') 539 540 # Verify all of the components were created 541 self.assertEqual(dt.consoleporttemplates.count(), 3) 542 cp1 = ConsolePortTemplate.objects.first() 543 self.assertEqual(cp1.name, 'Console Port 1') 544 self.assertEqual(cp1.type, ConsolePortTypeChoices.TYPE_DE9) 545 546 self.assertEqual(dt.consoleserverporttemplates.count(), 3) 547 csp1 = ConsoleServerPortTemplate.objects.first() 548 self.assertEqual(csp1.name, 'Console Server Port 1') 549 self.assertEqual(csp1.type, ConsolePortTypeChoices.TYPE_RJ45) 550 551 self.assertEqual(dt.powerporttemplates.count(), 3) 552 pp1 = PowerPortTemplate.objects.first() 553 self.assertEqual(pp1.name, 'Power Port 1') 554 self.assertEqual(pp1.type, PowerPortTypeChoices.TYPE_IEC_C14) 555 556 self.assertEqual(dt.poweroutlettemplates.count(), 3) 557 po1 = PowerOutletTemplate.objects.first() 558 self.assertEqual(po1.name, 'Power Outlet 1') 559 self.assertEqual(po1.type, PowerOutletTypeChoices.TYPE_IEC_C13) 560 self.assertEqual(po1.power_port, pp1) 561 self.assertEqual(po1.feed_leg, PowerOutletFeedLegChoices.FEED_LEG_A) 562 563 self.assertEqual(dt.interfacetemplates.count(), 3) 564 iface1 = InterfaceTemplate.objects.first() 565 self.assertEqual(iface1.name, 'Interface 1') 566 self.assertEqual(iface1.type, InterfaceTypeChoices.TYPE_1GE_FIXED) 567 self.assertTrue(iface1.mgmt_only) 568 569 self.assertEqual(dt.rearporttemplates.count(), 3) 570 rp1 = RearPortTemplate.objects.first() 571 self.assertEqual(rp1.name, 'Rear Port 1') 572 573 self.assertEqual(dt.frontporttemplates.count(), 3) 574 fp1 = FrontPortTemplate.objects.first() 575 self.assertEqual(fp1.name, 'Front Port 1') 576 self.assertEqual(fp1.rear_port, rp1) 577 self.assertEqual(fp1.rear_port_position, 1) 578 579 self.assertEqual(dt.devicebaytemplates.count(), 3) 580 db1 = DeviceBayTemplate.objects.first() 581 self.assertEqual(db1.name, 'Device Bay 1') 582 583 def test_export_objects(self): 584 url = reverse('dcim:devicetype_list') 585 self.add_permissions('dcim.view_devicetype') 586 587 # Test default YAML export 588 response = self.client.get('{}?export'.format(url)) 589 self.assertEqual(response.status_code, 200) 590 data = list(yaml.load_all(response.content, Loader=yaml.SafeLoader)) 591 self.assertEqual(len(data), 3) 592 self.assertEqual(data[0]['manufacturer'], 'Manufacturer 1') 593 self.assertEqual(data[0]['model'], 'Device Type 1') 594 595 # Test table-based export 596 response = self.client.get(f'{url}?export=table') 597 self.assertHttpStatus(response, 200) 598 self.assertEqual(response.get('Content-Type'), 'text/csv; charset=utf-8') 599 600 601# 602# DeviceType components 603# 604 605class ConsolePortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase): 606 model = ConsolePortTemplate 607 608 @classmethod 609 def setUpTestData(cls): 610 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 611 devicetypes = ( 612 DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'), 613 DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'), 614 ) 615 DeviceType.objects.bulk_create(devicetypes) 616 617 ConsolePortTemplate.objects.bulk_create(( 618 ConsolePortTemplate(device_type=devicetypes[0], name='Console Port Template 1'), 619 ConsolePortTemplate(device_type=devicetypes[0], name='Console Port Template 2'), 620 ConsolePortTemplate(device_type=devicetypes[0], name='Console Port Template 3'), 621 )) 622 623 cls.form_data = { 624 'device_type': devicetypes[1].pk, 625 'name': 'Console Port Template X', 626 'type': ConsolePortTypeChoices.TYPE_RJ45, 627 } 628 629 cls.bulk_create_data = { 630 'device_type': devicetypes[1].pk, 631 'name_pattern': 'Console Port Template [4-6]', 632 'type': ConsolePortTypeChoices.TYPE_RJ45, 633 } 634 635 cls.bulk_edit_data = { 636 'type': ConsolePortTypeChoices.TYPE_RJ45, 637 } 638 639 640class ConsoleServerPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase): 641 model = ConsoleServerPortTemplate 642 643 @classmethod 644 def setUpTestData(cls): 645 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 646 devicetypes = ( 647 DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'), 648 DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'), 649 ) 650 DeviceType.objects.bulk_create(devicetypes) 651 652 ConsoleServerPortTemplate.objects.bulk_create(( 653 ConsoleServerPortTemplate(device_type=devicetypes[0], name='Console Server Port Template 1'), 654 ConsoleServerPortTemplate(device_type=devicetypes[0], name='Console Server Port Template 2'), 655 ConsoleServerPortTemplate(device_type=devicetypes[0], name='Console Server Port Template 3'), 656 )) 657 658 cls.form_data = { 659 'device_type': devicetypes[1].pk, 660 'name': 'Console Server Port Template X', 661 'type': ConsolePortTypeChoices.TYPE_RJ45, 662 } 663 664 cls.bulk_create_data = { 665 'device_type': devicetypes[1].pk, 666 'name_pattern': 'Console Server Port Template [4-6]', 667 'type': ConsolePortTypeChoices.TYPE_RJ45, 668 } 669 670 cls.bulk_edit_data = { 671 'type': ConsolePortTypeChoices.TYPE_RJ45, 672 } 673 674 675class PowerPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase): 676 model = PowerPortTemplate 677 678 @classmethod 679 def setUpTestData(cls): 680 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 681 devicetypes = ( 682 DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'), 683 DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'), 684 ) 685 DeviceType.objects.bulk_create(devicetypes) 686 687 PowerPortTemplate.objects.bulk_create(( 688 PowerPortTemplate(device_type=devicetypes[0], name='Power Port Template 1'), 689 PowerPortTemplate(device_type=devicetypes[0], name='Power Port Template 2'), 690 PowerPortTemplate(device_type=devicetypes[0], name='Power Port Template 3'), 691 )) 692 693 cls.form_data = { 694 'device_type': devicetypes[1].pk, 695 'name': 'Power Port Template X', 696 'type': PowerPortTypeChoices.TYPE_IEC_C14, 697 'maximum_draw': 100, 698 'allocated_draw': 50, 699 } 700 701 cls.bulk_create_data = { 702 'device_type': devicetypes[1].pk, 703 'name_pattern': 'Power Port Template [4-6]', 704 'type': PowerPortTypeChoices.TYPE_IEC_C14, 705 'maximum_draw': 100, 706 'allocated_draw': 50, 707 } 708 709 cls.bulk_edit_data = { 710 'type': PowerPortTypeChoices.TYPE_IEC_C14, 711 'maximum_draw': 100, 712 'allocated_draw': 50, 713 } 714 715 716class PowerOutletTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase): 717 model = PowerOutletTemplate 718 719 @classmethod 720 def setUpTestData(cls): 721 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 722 devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') 723 724 PowerOutletTemplate.objects.bulk_create(( 725 PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 1'), 726 PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 2'), 727 PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 3'), 728 )) 729 730 powerports = ( 731 PowerPortTemplate(device_type=devicetype, name='Power Port Template 1'), 732 ) 733 PowerPortTemplate.objects.bulk_create(powerports) 734 735 cls.form_data = { 736 'device_type': devicetype.pk, 737 'name': 'Power Outlet Template X', 738 'type': PowerOutletTypeChoices.TYPE_IEC_C13, 739 'power_port': powerports[0].pk, 740 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B, 741 } 742 743 cls.bulk_create_data = { 744 'device_type': devicetype.pk, 745 'name_pattern': 'Power Outlet Template [4-6]', 746 'type': PowerOutletTypeChoices.TYPE_IEC_C13, 747 'power_port': powerports[0].pk, 748 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B, 749 } 750 751 cls.bulk_edit_data = { 752 'type': PowerOutletTypeChoices.TYPE_IEC_C13, 753 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B, 754 } 755 756 757class InterfaceTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase): 758 model = InterfaceTemplate 759 760 @classmethod 761 def setUpTestData(cls): 762 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 763 devicetypes = ( 764 DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'), 765 DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'), 766 ) 767 DeviceType.objects.bulk_create(devicetypes) 768 769 InterfaceTemplate.objects.bulk_create(( 770 InterfaceTemplate(device_type=devicetypes[0], name='Interface Template 1'), 771 InterfaceTemplate(device_type=devicetypes[0], name='Interface Template 2'), 772 InterfaceTemplate(device_type=devicetypes[0], name='Interface Template 3'), 773 )) 774 775 cls.form_data = { 776 'device_type': devicetypes[1].pk, 777 'name': 'Interface Template X', 778 'type': InterfaceTypeChoices.TYPE_1GE_GBIC, 779 'mgmt_only': True, 780 } 781 782 cls.bulk_create_data = { 783 'device_type': devicetypes[1].pk, 784 'name_pattern': 'Interface Template [4-6]', 785 # Test that a label can be applied to each generated interface templates 786 'label_pattern': 'Interface Template Label [3-5]', 787 'type': InterfaceTypeChoices.TYPE_1GE_GBIC, 788 'mgmt_only': True, 789 } 790 791 cls.bulk_edit_data = { 792 'type': InterfaceTypeChoices.TYPE_1GE_GBIC, 793 'mgmt_only': True, 794 } 795 796 797class FrontPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase): 798 model = FrontPortTemplate 799 800 @classmethod 801 def setUpTestData(cls): 802 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 803 devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') 804 805 rearports = ( 806 RearPortTemplate(device_type=devicetype, name='Rear Port Template 1'), 807 RearPortTemplate(device_type=devicetype, name='Rear Port Template 2'), 808 RearPortTemplate(device_type=devicetype, name='Rear Port Template 3'), 809 RearPortTemplate(device_type=devicetype, name='Rear Port Template 4'), 810 RearPortTemplate(device_type=devicetype, name='Rear Port Template 5'), 811 RearPortTemplate(device_type=devicetype, name='Rear Port Template 6'), 812 ) 813 RearPortTemplate.objects.bulk_create(rearports) 814 815 FrontPortTemplate.objects.bulk_create(( 816 FrontPortTemplate(device_type=devicetype, name='Front Port Template 1', rear_port=rearports[0], rear_port_position=1), 817 FrontPortTemplate(device_type=devicetype, name='Front Port Template 2', rear_port=rearports[1], rear_port_position=1), 818 FrontPortTemplate(device_type=devicetype, name='Front Port Template 3', rear_port=rearports[2], rear_port_position=1), 819 )) 820 821 cls.form_data = { 822 'device_type': devicetype.pk, 823 'name': 'Front Port X', 824 'type': PortTypeChoices.TYPE_8P8C, 825 'rear_port': rearports[3].pk, 826 'rear_port_position': 1, 827 } 828 829 cls.bulk_create_data = { 830 'device_type': devicetype.pk, 831 'name_pattern': 'Front Port [4-6]', 832 'type': PortTypeChoices.TYPE_8P8C, 833 'rear_port_set': [ 834 '{}:1'.format(rp.pk) for rp in rearports[3:6] 835 ], 836 } 837 838 cls.bulk_edit_data = { 839 'type': PortTypeChoices.TYPE_8P8C, 840 } 841 842 843class RearPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase): 844 model = RearPortTemplate 845 846 @classmethod 847 def setUpTestData(cls): 848 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 849 devicetypes = ( 850 DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'), 851 DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'), 852 ) 853 DeviceType.objects.bulk_create(devicetypes) 854 855 RearPortTemplate.objects.bulk_create(( 856 RearPortTemplate(device_type=devicetypes[0], name='Rear Port Template 1'), 857 RearPortTemplate(device_type=devicetypes[0], name='Rear Port Template 2'), 858 RearPortTemplate(device_type=devicetypes[0], name='Rear Port Template 3'), 859 )) 860 861 cls.form_data = { 862 'device_type': devicetypes[1].pk, 863 'name': 'Rear Port Template X', 864 'type': PortTypeChoices.TYPE_8P8C, 865 'positions': 2, 866 } 867 868 cls.bulk_create_data = { 869 'device_type': devicetypes[1].pk, 870 'name_pattern': 'Rear Port Template [4-6]', 871 'type': PortTypeChoices.TYPE_8P8C, 872 'positions': 2, 873 } 874 875 cls.bulk_edit_data = { 876 'type': PortTypeChoices.TYPE_8P8C, 877 } 878 879 880class DeviceBayTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase): 881 model = DeviceBayTemplate 882 883 @classmethod 884 def setUpTestData(cls): 885 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 886 devicetypes = ( 887 DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1', subdevice_role=SubdeviceRoleChoices.ROLE_PARENT), 888 DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2', subdevice_role=SubdeviceRoleChoices.ROLE_PARENT), 889 ) 890 DeviceType.objects.bulk_create(devicetypes) 891 892 DeviceBayTemplate.objects.bulk_create(( 893 DeviceBayTemplate(device_type=devicetypes[0], name='Device Bay Template 1'), 894 DeviceBayTemplate(device_type=devicetypes[0], name='Device Bay Template 2'), 895 DeviceBayTemplate(device_type=devicetypes[0], name='Device Bay Template 3'), 896 )) 897 898 cls.form_data = { 899 'device_type': devicetypes[1].pk, 900 'name': 'Device Bay Template X', 901 } 902 903 cls.bulk_create_data = { 904 'device_type': devicetypes[1].pk, 905 'name_pattern': 'Device Bay Template [4-6]', 906 } 907 908 cls.bulk_edit_data = { 909 'description': 'Foo bar', 910 } 911 912 913class DeviceRoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase): 914 model = DeviceRole 915 916 @classmethod 917 def setUpTestData(cls): 918 919 DeviceRole.objects.bulk_create([ 920 DeviceRole(name='Device Role 1', slug='device-role-1'), 921 DeviceRole(name='Device Role 2', slug='device-role-2'), 922 DeviceRole(name='Device Role 3', slug='device-role-3'), 923 ]) 924 925 cls.form_data = { 926 'name': 'Devie Role X', 927 'slug': 'device-role-x', 928 'color': 'c0c0c0', 929 'vm_role': False, 930 'description': 'New device role', 931 } 932 933 cls.csv_data = ( 934 "name,slug,color", 935 "Device Role 4,device-role-4,ff0000", 936 "Device Role 5,device-role-5,00ff00", 937 "Device Role 6,device-role-6,0000ff", 938 ) 939 940 cls.bulk_edit_data = { 941 'color': '00ff00', 942 'description': 'New description', 943 } 944 945 946class PlatformTestCase(ViewTestCases.OrganizationalObjectViewTestCase): 947 model = Platform 948 949 @classmethod 950 def setUpTestData(cls): 951 952 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 953 954 Platform.objects.bulk_create([ 955 Platform(name='Platform 1', slug='platform-1', manufacturer=manufacturer), 956 Platform(name='Platform 2', slug='platform-2', manufacturer=manufacturer), 957 Platform(name='Platform 3', slug='platform-3', manufacturer=manufacturer), 958 ]) 959 960 cls.form_data = { 961 'name': 'Platform X', 962 'slug': 'platform-x', 963 'manufacturer': manufacturer.pk, 964 'napalm_driver': 'junos', 965 'napalm_args': None, 966 'description': 'A new platform', 967 } 968 969 cls.csv_data = ( 970 "name,slug,description", 971 "Platform 4,platform-4,Fourth platform", 972 "Platform 5,platform-5,Fifth platform", 973 "Platform 6,platform-6,Sixth platform", 974 ) 975 976 cls.bulk_edit_data = { 977 'napalm_driver': 'ios', 978 'description': 'New description', 979 } 980 981 982class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase): 983 model = Device 984 985 @classmethod 986 def setUpTestData(cls): 987 988 sites = ( 989 Site(name='Site 1', slug='site-1'), 990 Site(name='Site 2', slug='site-2'), 991 ) 992 Site.objects.bulk_create(sites) 993 994 location = Location(site=sites[0], name='Location 1', slug='location-1') 995 location.save() 996 997 racks = ( 998 Rack(name='Rack 1', site=sites[0], location=location), 999 Rack(name='Rack 2', site=sites[1]), 1000 ) 1001 Rack.objects.bulk_create(racks) 1002 1003 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 1004 1005 devicetypes = ( 1006 DeviceType(model='Device Type 1', slug='device-type-1', manufacturer=manufacturer), 1007 DeviceType(model='Device Type 2', slug='device-type-2', manufacturer=manufacturer), 1008 ) 1009 DeviceType.objects.bulk_create(devicetypes) 1010 1011 deviceroles = ( 1012 DeviceRole(name='Device Role 1', slug='device-role-1'), 1013 DeviceRole(name='Device Role 2', slug='device-role-2'), 1014 ) 1015 DeviceRole.objects.bulk_create(deviceroles) 1016 1017 platforms = ( 1018 Platform(name='Platform 1', slug='platform-1'), 1019 Platform(name='Platform 2', slug='platform-2'), 1020 ) 1021 Platform.objects.bulk_create(platforms) 1022 1023 Device.objects.bulk_create([ 1024 Device(name='Device 1', site=sites[0], rack=racks[0], device_type=devicetypes[0], device_role=deviceroles[0], platform=platforms[0]), 1025 Device(name='Device 2', site=sites[0], rack=racks[0], device_type=devicetypes[0], device_role=deviceroles[0], platform=platforms[0]), 1026 Device(name='Device 3', site=sites[0], rack=racks[0], device_type=devicetypes[0], device_role=deviceroles[0], platform=platforms[0]), 1027 ]) 1028 1029 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1030 1031 VirtualChassis.objects.create(name='Virtual Chassis 1') 1032 1033 cls.form_data = { 1034 'device_type': devicetypes[1].pk, 1035 'device_role': deviceroles[1].pk, 1036 'tenant': None, 1037 'platform': platforms[1].pk, 1038 'name': 'Device X', 1039 'serial': '123456', 1040 'asset_tag': 'ABCDEF', 1041 'site': sites[1].pk, 1042 'rack': racks[1].pk, 1043 'position': 1, 1044 'face': DeviceFaceChoices.FACE_FRONT, 1045 'status': DeviceStatusChoices.STATUS_PLANNED, 1046 'primary_ip4': None, 1047 'primary_ip6': None, 1048 'cluster': None, 1049 'virtual_chassis': None, 1050 'vc_position': None, 1051 'vc_priority': None, 1052 'comments': 'A new device', 1053 'tags': [t.pk for t in tags], 1054 'local_context_data': None, 1055 } 1056 1057 cls.csv_data = ( 1058 "device_role,manufacturer,device_type,status,name,site,location,rack,position,face,virtual_chassis,vc_position,vc_priority", 1059 "Device Role 1,Manufacturer 1,Device Type 1,active,Device 4,Site 1,Location 1,Rack 1,10,front,Virtual Chassis 1,1,10", 1060 "Device Role 1,Manufacturer 1,Device Type 1,active,Device 5,Site 1,Location 1,Rack 1,20,front,Virtual Chassis 1,2,20", 1061 "Device Role 1,Manufacturer 1,Device Type 1,active,Device 6,Site 1,Location 1,Rack 1,30,front,Virtual Chassis 1,3,30", 1062 ) 1063 1064 cls.bulk_edit_data = { 1065 'device_type': devicetypes[1].pk, 1066 'device_role': deviceroles[1].pk, 1067 'tenant': None, 1068 'platform': platforms[1].pk, 1069 'serial': '123456', 1070 'status': DeviceStatusChoices.STATUS_DECOMMISSIONING, 1071 } 1072 1073 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1074 def test_device_consoleports(self): 1075 device = Device.objects.first() 1076 console_ports = ( 1077 ConsolePort(device=device, name='Console Port 1'), 1078 ConsolePort(device=device, name='Console Port 2'), 1079 ConsolePort(device=device, name='Console Port 3'), 1080 ) 1081 ConsolePort.objects.bulk_create(console_ports) 1082 1083 url = reverse('dcim:device_consoleports', kwargs={'pk': device.pk}) 1084 self.assertHttpStatus(self.client.get(url), 200) 1085 1086 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1087 def test_device_consoleserverports(self): 1088 device = Device.objects.first() 1089 console_server_ports = ( 1090 ConsoleServerPort(device=device, name='Console Server Port 1'), 1091 ConsoleServerPort(device=device, name='Console Server Port 2'), 1092 ConsoleServerPort(device=device, name='Console Server Port 3'), 1093 ) 1094 ConsoleServerPort.objects.bulk_create(console_server_ports) 1095 1096 url = reverse('dcim:device_consoleserverports', kwargs={'pk': device.pk}) 1097 self.assertHttpStatus(self.client.get(url), 200) 1098 1099 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1100 def test_device_powerports(self): 1101 device = Device.objects.first() 1102 power_ports = ( 1103 PowerPort(device=device, name='Power Port 1'), 1104 PowerPort(device=device, name='Power Port 2'), 1105 PowerPort(device=device, name='Power Port 3'), 1106 ) 1107 PowerPort.objects.bulk_create(power_ports) 1108 1109 url = reverse('dcim:device_powerports', kwargs={'pk': device.pk}) 1110 self.assertHttpStatus(self.client.get(url), 200) 1111 1112 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1113 def test_device_poweroutlets(self): 1114 device = Device.objects.first() 1115 power_outlets = ( 1116 PowerOutlet(device=device, name='Power Outlet 1'), 1117 PowerOutlet(device=device, name='Power Outlet 2'), 1118 PowerOutlet(device=device, name='Power Outlet 3'), 1119 ) 1120 PowerOutlet.objects.bulk_create(power_outlets) 1121 1122 url = reverse('dcim:device_poweroutlets', kwargs={'pk': device.pk}) 1123 self.assertHttpStatus(self.client.get(url), 200) 1124 1125 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1126 def test_device_interfaces(self): 1127 device = Device.objects.first() 1128 interfaces = ( 1129 Interface(device=device, name='Interface 1'), 1130 Interface(device=device, name='Interface 2'), 1131 Interface(device=device, name='Interface 3'), 1132 ) 1133 Interface.objects.bulk_create(interfaces) 1134 1135 url = reverse('dcim:device_interfaces', kwargs={'pk': device.pk}) 1136 self.assertHttpStatus(self.client.get(url), 200) 1137 1138 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1139 def test_device_rearports(self): 1140 device = Device.objects.first() 1141 rear_ports = ( 1142 RearPort(device=device, name='Rear Port 1'), 1143 RearPort(device=device, name='Rear Port 2'), 1144 RearPort(device=device, name='Rear Port 3'), 1145 ) 1146 RearPort.objects.bulk_create(rear_ports) 1147 1148 url = reverse('dcim:device_rearports', kwargs={'pk': device.pk}) 1149 self.assertHttpStatus(self.client.get(url), 200) 1150 1151 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1152 def test_device_frontports(self): 1153 device = Device.objects.first() 1154 rear_ports = ( 1155 RearPort(device=device, name='Rear Port 1'), 1156 RearPort(device=device, name='Rear Port 2'), 1157 RearPort(device=device, name='Rear Port 3'), 1158 ) 1159 RearPort.objects.bulk_create(rear_ports) 1160 front_ports = ( 1161 FrontPort(device=device, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1), 1162 FrontPort(device=device, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1), 1163 FrontPort(device=device, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1), 1164 ) 1165 FrontPort.objects.bulk_create(front_ports) 1166 1167 url = reverse('dcim:device_frontports', kwargs={'pk': device.pk}) 1168 self.assertHttpStatus(self.client.get(url), 200) 1169 1170 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1171 def test_device_devicebays(self): 1172 device = Device.objects.first() 1173 device_bays = ( 1174 DeviceBay(device=device, name='Device Bay 1'), 1175 DeviceBay(device=device, name='Device Bay 2'), 1176 DeviceBay(device=device, name='Device Bay 3'), 1177 ) 1178 DeviceBay.objects.bulk_create(device_bays) 1179 1180 url = reverse('dcim:device_devicebays', kwargs={'pk': device.pk}) 1181 self.assertHttpStatus(self.client.get(url), 200) 1182 1183 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1184 def test_device_inventory(self): 1185 device = Device.objects.first() 1186 inventory_items = ( 1187 InventoryItem(device=device, name='Inventory Item 1'), 1188 InventoryItem(device=device, name='Inventory Item 2'), 1189 InventoryItem(device=device, name='Inventory Item 3'), 1190 ) 1191 for item in inventory_items: 1192 item.save() 1193 1194 url = reverse('dcim:device_inventory', kwargs={'pk': device.pk}) 1195 self.assertHttpStatus(self.client.get(url), 200) 1196 1197 1198class ConsolePortTestCase(ViewTestCases.DeviceComponentViewTestCase): 1199 model = ConsolePort 1200 1201 @classmethod 1202 def setUpTestData(cls): 1203 device = create_test_device('Device 1') 1204 1205 ConsolePort.objects.bulk_create([ 1206 ConsolePort(device=device, name='Console Port 1'), 1207 ConsolePort(device=device, name='Console Port 2'), 1208 ConsolePort(device=device, name='Console Port 3'), 1209 ]) 1210 1211 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1212 1213 cls.form_data = { 1214 'device': device.pk, 1215 'name': 'Console Port X', 1216 'type': ConsolePortTypeChoices.TYPE_RJ45, 1217 'description': 'A console port', 1218 'tags': sorted([t.pk for t in tags]), 1219 } 1220 1221 cls.bulk_create_data = { 1222 'device': device.pk, 1223 'name_pattern': 'Console Port [4-6]', 1224 # Test that a label can be applied to each generated console ports 1225 'label_pattern': 'Serial[3-5]', 1226 'type': ConsolePortTypeChoices.TYPE_RJ45, 1227 'description': 'A console port', 1228 'tags': sorted([t.pk for t in tags]), 1229 } 1230 1231 cls.bulk_edit_data = { 1232 'type': ConsolePortTypeChoices.TYPE_RJ45, 1233 'description': 'New description', 1234 } 1235 1236 cls.csv_data = ( 1237 "device,name", 1238 "Device 1,Console Port 4", 1239 "Device 1,Console Port 5", 1240 "Device 1,Console Port 6", 1241 ) 1242 1243 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1244 def test_trace(self): 1245 consoleport = ConsolePort.objects.first() 1246 consoleserverport = ConsoleServerPort.objects.create( 1247 device=consoleport.device, 1248 name='Console Server Port 1' 1249 ) 1250 Cable(termination_a=consoleport, termination_b=consoleserverport).save() 1251 1252 response = self.client.get(reverse('dcim:consoleport_trace', kwargs={'pk': consoleport.pk})) 1253 self.assertHttpStatus(response, 200) 1254 1255 1256class ConsoleServerPortTestCase(ViewTestCases.DeviceComponentViewTestCase): 1257 model = ConsoleServerPort 1258 1259 @classmethod 1260 def setUpTestData(cls): 1261 device = create_test_device('Device 1') 1262 1263 ConsoleServerPort.objects.bulk_create([ 1264 ConsoleServerPort(device=device, name='Console Server Port 1'), 1265 ConsoleServerPort(device=device, name='Console Server Port 2'), 1266 ConsoleServerPort(device=device, name='Console Server Port 3'), 1267 ]) 1268 1269 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1270 1271 cls.form_data = { 1272 'device': device.pk, 1273 'name': 'Console Server Port X', 1274 'type': ConsolePortTypeChoices.TYPE_RJ45, 1275 'description': 'A console server port', 1276 'tags': [t.pk for t in tags], 1277 } 1278 1279 cls.bulk_create_data = { 1280 'device': device.pk, 1281 'name_pattern': 'Console Server Port [4-6]', 1282 'type': ConsolePortTypeChoices.TYPE_RJ45, 1283 'description': 'A console server port', 1284 'tags': [t.pk for t in tags], 1285 } 1286 1287 cls.bulk_edit_data = { 1288 'type': ConsolePortTypeChoices.TYPE_RJ11, 1289 'description': 'New description', 1290 } 1291 1292 cls.csv_data = ( 1293 "device,name", 1294 "Device 1,Console Server Port 4", 1295 "Device 1,Console Server Port 5", 1296 "Device 1,Console Server Port 6", 1297 ) 1298 1299 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1300 def test_trace(self): 1301 consoleserverport = ConsoleServerPort.objects.first() 1302 consoleport = ConsolePort.objects.create( 1303 device=consoleserverport.device, 1304 name='Console Port 1' 1305 ) 1306 Cable(termination_a=consoleserverport, termination_b=consoleport).save() 1307 1308 response = self.client.get(reverse('dcim:consoleserverport_trace', kwargs={'pk': consoleserverport.pk})) 1309 self.assertHttpStatus(response, 200) 1310 1311 1312class PowerPortTestCase(ViewTestCases.DeviceComponentViewTestCase): 1313 model = PowerPort 1314 1315 @classmethod 1316 def setUpTestData(cls): 1317 device = create_test_device('Device 1') 1318 1319 PowerPort.objects.bulk_create([ 1320 PowerPort(device=device, name='Power Port 1'), 1321 PowerPort(device=device, name='Power Port 2'), 1322 PowerPort(device=device, name='Power Port 3'), 1323 ]) 1324 1325 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1326 1327 cls.form_data = { 1328 'device': device.pk, 1329 'name': 'Power Port X', 1330 'type': PowerPortTypeChoices.TYPE_IEC_C14, 1331 'maximum_draw': 100, 1332 'allocated_draw': 50, 1333 'description': 'A power port', 1334 'tags': [t.pk for t in tags], 1335 } 1336 1337 cls.bulk_create_data = { 1338 'device': device.pk, 1339 'name_pattern': 'Power Port [4-6]]', 1340 'type': PowerPortTypeChoices.TYPE_IEC_C14, 1341 'maximum_draw': 100, 1342 'allocated_draw': 50, 1343 'description': 'A power port', 1344 'tags': [t.pk for t in tags], 1345 } 1346 1347 cls.bulk_edit_data = { 1348 'type': PowerPortTypeChoices.TYPE_IEC_C14, 1349 'maximum_draw': 100, 1350 'allocated_draw': 50, 1351 'description': 'New description', 1352 } 1353 1354 cls.csv_data = ( 1355 "device,name", 1356 "Device 1,Power Port 4", 1357 "Device 1,Power Port 5", 1358 "Device 1,Power Port 6", 1359 ) 1360 1361 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1362 def test_trace(self): 1363 powerport = PowerPort.objects.first() 1364 poweroutlet = PowerOutlet.objects.create( 1365 device=powerport.device, 1366 name='Power Outlet 1' 1367 ) 1368 Cable(termination_a=powerport, termination_b=poweroutlet).save() 1369 1370 response = self.client.get(reverse('dcim:powerport_trace', kwargs={'pk': powerport.pk})) 1371 self.assertHttpStatus(response, 200) 1372 1373 1374class PowerOutletTestCase(ViewTestCases.DeviceComponentViewTestCase): 1375 model = PowerOutlet 1376 1377 @classmethod 1378 def setUpTestData(cls): 1379 device = create_test_device('Device 1') 1380 1381 powerports = ( 1382 PowerPort(device=device, name='Power Port 1'), 1383 PowerPort(device=device, name='Power Port 2'), 1384 ) 1385 PowerPort.objects.bulk_create(powerports) 1386 1387 PowerOutlet.objects.bulk_create([ 1388 PowerOutlet(device=device, name='Power Outlet 1', power_port=powerports[0]), 1389 PowerOutlet(device=device, name='Power Outlet 2', power_port=powerports[0]), 1390 PowerOutlet(device=device, name='Power Outlet 3', power_port=powerports[0]), 1391 ]) 1392 1393 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1394 1395 cls.form_data = { 1396 'device': device.pk, 1397 'name': 'Power Outlet X', 1398 'type': PowerOutletTypeChoices.TYPE_IEC_C13, 1399 'power_port': powerports[1].pk, 1400 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B, 1401 'description': 'A power outlet', 1402 'tags': [t.pk for t in tags], 1403 } 1404 1405 cls.bulk_create_data = { 1406 'device': device.pk, 1407 'name_pattern': 'Power Outlet [4-6]', 1408 'type': PowerOutletTypeChoices.TYPE_IEC_C13, 1409 'power_port': powerports[1].pk, 1410 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B, 1411 'description': 'A power outlet', 1412 'tags': [t.pk for t in tags], 1413 } 1414 1415 cls.bulk_edit_data = { 1416 'type': PowerOutletTypeChoices.TYPE_IEC_C15, 1417 'power_port': powerports[1].pk, 1418 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B, 1419 'description': 'New description', 1420 } 1421 1422 cls.csv_data = ( 1423 "device,name", 1424 "Device 1,Power Outlet 4", 1425 "Device 1,Power Outlet 5", 1426 "Device 1,Power Outlet 6", 1427 ) 1428 1429 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1430 def test_trace(self): 1431 poweroutlet = PowerOutlet.objects.first() 1432 powerport = PowerPort.objects.first() 1433 Cable(termination_a=poweroutlet, termination_b=powerport).save() 1434 1435 response = self.client.get(reverse('dcim:poweroutlet_trace', kwargs={'pk': poweroutlet.pk})) 1436 self.assertHttpStatus(response, 200) 1437 1438 1439class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase): 1440 model = Interface 1441 1442 @classmethod 1443 def setUpTestData(cls): 1444 device = create_test_device('Device 1') 1445 1446 interfaces = ( 1447 Interface(device=device, name='Interface 1'), 1448 Interface(device=device, name='Interface 2'), 1449 Interface(device=device, name='Interface 3'), 1450 Interface(device=device, name='LAG', type=InterfaceTypeChoices.TYPE_LAG), 1451 ) 1452 Interface.objects.bulk_create(interfaces) 1453 1454 vlans = ( 1455 VLAN(vid=1, name='VLAN1', site=device.site), 1456 VLAN(vid=101, name='VLAN101', site=device.site), 1457 VLAN(vid=102, name='VLAN102', site=device.site), 1458 VLAN(vid=103, name='VLAN103', site=device.site), 1459 ) 1460 VLAN.objects.bulk_create(vlans) 1461 1462 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1463 1464 cls.form_data = { 1465 'device': device.pk, 1466 'virtual_machine': None, 1467 'name': 'Interface X', 1468 'type': InterfaceTypeChoices.TYPE_1GE_GBIC, 1469 'enabled': False, 1470 'lag': interfaces[3].pk, 1471 'mac_address': EUI('01:02:03:04:05:06'), 1472 'mtu': 65000, 1473 'mgmt_only': True, 1474 'description': 'A front port', 1475 'mode': InterfaceModeChoices.MODE_TAGGED, 1476 'untagged_vlan': vlans[0].pk, 1477 'tagged_vlans': [v.pk for v in vlans[1:4]], 1478 'tags': [t.pk for t in tags], 1479 } 1480 1481 cls.bulk_create_data = { 1482 'device': device.pk, 1483 'name_pattern': 'Interface [4-6]', 1484 'type': InterfaceTypeChoices.TYPE_1GE_GBIC, 1485 'enabled': False, 1486 'lag': interfaces[3].pk, 1487 'mac_address': EUI('01:02:03:04:05:06'), 1488 'mtu': 2000, 1489 'mgmt_only': True, 1490 'description': 'A front port', 1491 'mode': InterfaceModeChoices.MODE_TAGGED, 1492 'untagged_vlan': vlans[0].pk, 1493 'tagged_vlans': [v.pk for v in vlans[1:4]], 1494 'tags': [t.pk for t in tags], 1495 } 1496 1497 cls.bulk_edit_data = { 1498 'type': InterfaceTypeChoices.TYPE_1GE_FIXED, 1499 'enabled': True, 1500 'lag': interfaces[3].pk, 1501 'mac_address': EUI('01:02:03:04:05:06'), 1502 'mtu': 2000, 1503 'mgmt_only': True, 1504 'description': 'New description', 1505 'mode': InterfaceModeChoices.MODE_TAGGED, 1506 'untagged_vlan': vlans[0].pk, 1507 'tagged_vlans': [v.pk for v in vlans[1:4]], 1508 } 1509 1510 cls.csv_data = ( 1511 "device,name,type", 1512 "Device 1,Interface 4,1000base-t", 1513 "Device 1,Interface 5,1000base-t", 1514 "Device 1,Interface 6,1000base-t", 1515 ) 1516 1517 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1518 def test_trace(self): 1519 interface1, interface2 = Interface.objects.all()[:2] 1520 Cable(termination_a=interface1, termination_b=interface2).save() 1521 1522 response = self.client.get(reverse('dcim:interface_trace', kwargs={'pk': interface1.pk})) 1523 self.assertHttpStatus(response, 200) 1524 1525 1526class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase): 1527 model = FrontPort 1528 1529 @classmethod 1530 def setUpTestData(cls): 1531 device = create_test_device('Device 1') 1532 1533 rearports = ( 1534 RearPort(device=device, name='Rear Port 1'), 1535 RearPort(device=device, name='Rear Port 2'), 1536 RearPort(device=device, name='Rear Port 3'), 1537 RearPort(device=device, name='Rear Port 4'), 1538 RearPort(device=device, name='Rear Port 5'), 1539 RearPort(device=device, name='Rear Port 6'), 1540 ) 1541 RearPort.objects.bulk_create(rearports) 1542 1543 FrontPort.objects.bulk_create([ 1544 FrontPort(device=device, name='Front Port 1', rear_port=rearports[0]), 1545 FrontPort(device=device, name='Front Port 2', rear_port=rearports[1]), 1546 FrontPort(device=device, name='Front Port 3', rear_port=rearports[2]), 1547 ]) 1548 1549 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1550 1551 cls.form_data = { 1552 'device': device.pk, 1553 'name': 'Front Port X', 1554 'type': PortTypeChoices.TYPE_8P8C, 1555 'rear_port': rearports[3].pk, 1556 'rear_port_position': 1, 1557 'description': 'New description', 1558 'tags': [t.pk for t in tags], 1559 } 1560 1561 cls.bulk_create_data = { 1562 'device': device.pk, 1563 'name_pattern': 'Front Port [4-6]', 1564 'type': PortTypeChoices.TYPE_8P8C, 1565 'rear_port_set': [ 1566 '{}:1'.format(rp.pk) for rp in rearports[3:6] 1567 ], 1568 'description': 'New description', 1569 'tags': [t.pk for t in tags], 1570 } 1571 1572 cls.bulk_edit_data = { 1573 'type': PortTypeChoices.TYPE_8P8C, 1574 'description': 'New description', 1575 } 1576 1577 cls.csv_data = ( 1578 "device,name,type,rear_port,rear_port_position", 1579 "Device 1,Front Port 4,8p8c,Rear Port 4,1", 1580 "Device 1,Front Port 5,8p8c,Rear Port 5,1", 1581 "Device 1,Front Port 6,8p8c,Rear Port 6,1", 1582 ) 1583 1584 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1585 def test_trace(self): 1586 frontport = FrontPort.objects.first() 1587 interface = Interface.objects.create( 1588 device=frontport.device, 1589 name='Interface 1' 1590 ) 1591 Cable(termination_a=frontport, termination_b=interface).save() 1592 1593 response = self.client.get(reverse('dcim:frontport_trace', kwargs={'pk': frontport.pk})) 1594 self.assertHttpStatus(response, 200) 1595 1596 1597class RearPortTestCase(ViewTestCases.DeviceComponentViewTestCase): 1598 model = RearPort 1599 1600 @classmethod 1601 def setUpTestData(cls): 1602 device = create_test_device('Device 1') 1603 1604 RearPort.objects.bulk_create([ 1605 RearPort(device=device, name='Rear Port 1'), 1606 RearPort(device=device, name='Rear Port 2'), 1607 RearPort(device=device, name='Rear Port 3'), 1608 ]) 1609 1610 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1611 1612 cls.form_data = { 1613 'device': device.pk, 1614 'name': 'Rear Port X', 1615 'type': PortTypeChoices.TYPE_8P8C, 1616 'positions': 3, 1617 'description': 'A rear port', 1618 'tags': [t.pk for t in tags], 1619 } 1620 1621 cls.bulk_create_data = { 1622 'device': device.pk, 1623 'name_pattern': 'Rear Port [4-6]', 1624 'type': PortTypeChoices.TYPE_8P8C, 1625 'positions': 3, 1626 'description': 'A rear port', 1627 'tags': [t.pk for t in tags], 1628 } 1629 1630 cls.bulk_edit_data = { 1631 'type': PortTypeChoices.TYPE_8P8C, 1632 'description': 'New description', 1633 } 1634 1635 cls.csv_data = ( 1636 "device,name,type,positions", 1637 "Device 1,Rear Port 4,8p8c,1", 1638 "Device 1,Rear Port 5,8p8c,1", 1639 "Device 1,Rear Port 6,8p8c,1", 1640 ) 1641 1642 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 1643 def test_trace(self): 1644 rearport = RearPort.objects.first() 1645 interface = Interface.objects.create( 1646 device=rearport.device, 1647 name='Interface 1' 1648 ) 1649 Cable(termination_a=rearport, termination_b=interface).save() 1650 1651 response = self.client.get(reverse('dcim:rearport_trace', kwargs={'pk': rearport.pk})) 1652 self.assertHttpStatus(response, 200) 1653 1654 1655class DeviceBayTestCase(ViewTestCases.DeviceComponentViewTestCase): 1656 model = DeviceBay 1657 1658 @classmethod 1659 def setUpTestData(cls): 1660 device = create_test_device('Device 1') 1661 1662 # Update the DeviceType subdevice role to allow adding DeviceBays 1663 DeviceType.objects.update(subdevice_role=SubdeviceRoleChoices.ROLE_PARENT) 1664 1665 DeviceBay.objects.bulk_create([ 1666 DeviceBay(device=device, name='Device Bay 1'), 1667 DeviceBay(device=device, name='Device Bay 2'), 1668 DeviceBay(device=device, name='Device Bay 3'), 1669 ]) 1670 1671 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1672 1673 cls.form_data = { 1674 'device': device.pk, 1675 'name': 'Device Bay X', 1676 'description': 'A device bay', 1677 'tags': [t.pk for t in tags], 1678 } 1679 1680 cls.bulk_create_data = { 1681 'device': device.pk, 1682 'name_pattern': 'Device Bay [4-6]', 1683 'description': 'A device bay', 1684 'tags': [t.pk for t in tags], 1685 } 1686 1687 cls.bulk_edit_data = { 1688 'description': 'New description', 1689 } 1690 1691 cls.csv_data = ( 1692 "device,name", 1693 "Device 1,Device Bay 4", 1694 "Device 1,Device Bay 5", 1695 "Device 1,Device Bay 6", 1696 ) 1697 1698 1699class InventoryItemTestCase(ViewTestCases.DeviceComponentViewTestCase): 1700 model = InventoryItem 1701 1702 @classmethod 1703 def setUpTestData(cls): 1704 device = create_test_device('Device 1') 1705 manufacturer, _ = Manufacturer.objects.get_or_create(name='Manufacturer 1', slug='manufacturer-1') 1706 1707 InventoryItem.objects.create(device=device, name='Inventory Item 1') 1708 InventoryItem.objects.create(device=device, name='Inventory Item 2') 1709 InventoryItem.objects.create(device=device, name='Inventory Item 3') 1710 1711 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1712 1713 cls.form_data = { 1714 'device': device.pk, 1715 'manufacturer': manufacturer.pk, 1716 'name': 'Inventory Item X', 1717 'parent': None, 1718 'discovered': False, 1719 'part_id': '123456', 1720 'serial': '123ABC', 1721 'asset_tag': 'ABC123', 1722 'description': 'An inventory item', 1723 'tags': [t.pk for t in tags], 1724 } 1725 1726 cls.bulk_create_data = { 1727 'device': device.pk, 1728 'name_pattern': 'Inventory Item [4-6]', 1729 'manufacturer': manufacturer.pk, 1730 'parent': None, 1731 'discovered': False, 1732 'part_id': '123456', 1733 'serial': '123ABC', 1734 'description': 'An inventory item', 1735 'tags': [t.pk for t in tags], 1736 } 1737 1738 cls.bulk_edit_data = { 1739 'part_id': '123456', 1740 'description': 'New description', 1741 } 1742 1743 cls.csv_data = ( 1744 "device,name,parent", 1745 "Device 1,Inventory Item 4,Inventory Item 1", 1746 "Device 1,Inventory Item 5,Inventory Item 2", 1747 "Device 1,Inventory Item 6,Inventory Item 3", 1748 ) 1749 1750 1751# TODO: Change base class to PrimaryObjectViewTestCase 1752# Blocked by lack of common creation view for cables (termination A must be initialized) 1753class CableTestCase( 1754 ViewTestCases.GetObjectViewTestCase, 1755 ViewTestCases.GetObjectChangelogViewTestCase, 1756 ViewTestCases.EditObjectViewTestCase, 1757 ViewTestCases.DeleteObjectViewTestCase, 1758 ViewTestCases.ListObjectsViewTestCase, 1759 ViewTestCases.BulkImportObjectsViewTestCase, 1760 ViewTestCases.BulkEditObjectsViewTestCase, 1761 ViewTestCases.BulkDeleteObjectsViewTestCase 1762): 1763 model = Cable 1764 1765 @classmethod 1766 def setUpTestData(cls): 1767 1768 site = Site.objects.create(name='Site 1', slug='site-1') 1769 manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') 1770 devicetype = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer) 1771 devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') 1772 1773 devices = ( 1774 Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole), 1775 Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole), 1776 Device(name='Device 3', site=site, device_type=devicetype, device_role=devicerole), 1777 Device(name='Device 4', site=site, device_type=devicetype, device_role=devicerole), 1778 ) 1779 Device.objects.bulk_create(devices) 1780 1781 interfaces = ( 1782 Interface(device=devices[0], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1783 Interface(device=devices[0], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1784 Interface(device=devices[0], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1785 Interface(device=devices[1], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1786 Interface(device=devices[1], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1787 Interface(device=devices[1], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1788 Interface(device=devices[2], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1789 Interface(device=devices[2], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1790 Interface(device=devices[2], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1791 Interface(device=devices[3], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1792 Interface(device=devices[3], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1793 Interface(device=devices[3], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED), 1794 ) 1795 Interface.objects.bulk_create(interfaces) 1796 1797 Cable(termination_a=interfaces[0], termination_b=interfaces[3], type=CableTypeChoices.TYPE_CAT6).save() 1798 Cable(termination_a=interfaces[1], termination_b=interfaces[4], type=CableTypeChoices.TYPE_CAT6).save() 1799 Cable(termination_a=interfaces[2], termination_b=interfaces[5], type=CableTypeChoices.TYPE_CAT6).save() 1800 1801 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1802 1803 interface_ct = ContentType.objects.get_for_model(Interface) 1804 cls.form_data = { 1805 # Changing terminations not supported when editing an existing Cable 1806 'termination_a_type': interface_ct.pk, 1807 'termination_a_id': interfaces[0].pk, 1808 'termination_b_type': interface_ct.pk, 1809 'termination_b_id': interfaces[3].pk, 1810 'type': CableTypeChoices.TYPE_CAT6, 1811 'status': CableStatusChoices.STATUS_PLANNED, 1812 'label': 'Label', 1813 'color': 'c0c0c0', 1814 'length': 100, 1815 'length_unit': CableLengthUnitChoices.UNIT_FOOT, 1816 'tags': [t.pk for t in tags], 1817 } 1818 1819 cls.csv_data = ( 1820 "side_a_device,side_a_type,side_a_name,side_b_device,side_b_type,side_b_name", 1821 "Device 3,dcim.interface,Interface 1,Device 4,dcim.interface,Interface 1", 1822 "Device 3,dcim.interface,Interface 2,Device 4,dcim.interface,Interface 2", 1823 "Device 3,dcim.interface,Interface 3,Device 4,dcim.interface,Interface 3", 1824 ) 1825 1826 cls.bulk_edit_data = { 1827 'type': CableTypeChoices.TYPE_CAT5E, 1828 'status': CableStatusChoices.STATUS_CONNECTED, 1829 'label': 'New label', 1830 'color': '00ff00', 1831 'length': 50, 1832 'length_unit': CableLengthUnitChoices.UNIT_METER, 1833 } 1834 1835 1836class VirtualChassisTestCase(ViewTestCases.PrimaryObjectViewTestCase): 1837 model = VirtualChassis 1838 1839 @classmethod 1840 def setUpTestData(cls): 1841 1842 site = Site.objects.create(name='Site 1', slug='site-1') 1843 manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer-1') 1844 device_type = DeviceType.objects.create( 1845 manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' 1846 ) 1847 device_role = DeviceRole.objects.create( 1848 name='Device Role', slug='device-role-1' 1849 ) 1850 1851 devices = ( 1852 Device(device_type=device_type, device_role=device_role, name='Device 1', site=site), 1853 Device(device_type=device_type, device_role=device_role, name='Device 2', site=site), 1854 Device(device_type=device_type, device_role=device_role, name='Device 3', site=site), 1855 Device(device_type=device_type, device_role=device_role, name='Device 4', site=site), 1856 Device(device_type=device_type, device_role=device_role, name='Device 5', site=site), 1857 Device(device_type=device_type, device_role=device_role, name='Device 6', site=site), 1858 Device(device_type=device_type, device_role=device_role, name='Device 7', site=site), 1859 Device(device_type=device_type, device_role=device_role, name='Device 8', site=site), 1860 Device(device_type=device_type, device_role=device_role, name='Device 9', site=site), 1861 Device(device_type=device_type, device_role=device_role, name='Device 10', site=site), 1862 Device(device_type=device_type, device_role=device_role, name='Device 11', site=site), 1863 Device(device_type=device_type, device_role=device_role, name='Device 12', site=site), 1864 ) 1865 Device.objects.bulk_create(devices) 1866 1867 # Create three VirtualChassis with three members each 1868 vc1 = VirtualChassis.objects.create(name='VC1', master=devices[0], domain='domain-1') 1869 Device.objects.filter(pk=devices[0].pk).update(virtual_chassis=vc1, vc_position=1) 1870 Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=vc1, vc_position=2) 1871 Device.objects.filter(pk=devices[2].pk).update(virtual_chassis=vc1, vc_position=3) 1872 vc2 = VirtualChassis.objects.create(name='VC2', master=devices[3], domain='domain-2') 1873 Device.objects.filter(pk=devices[3].pk).update(virtual_chassis=vc2, vc_position=1) 1874 Device.objects.filter(pk=devices[4].pk).update(virtual_chassis=vc2, vc_position=2) 1875 Device.objects.filter(pk=devices[5].pk).update(virtual_chassis=vc2, vc_position=3) 1876 vc3 = VirtualChassis.objects.create(name='VC3', master=devices[6], domain='domain-3') 1877 Device.objects.filter(pk=devices[6].pk).update(virtual_chassis=vc3, vc_position=1) 1878 Device.objects.filter(pk=devices[7].pk).update(virtual_chassis=vc3, vc_position=2) 1879 Device.objects.filter(pk=devices[8].pk).update(virtual_chassis=vc3, vc_position=3) 1880 1881 cls.form_data = { 1882 'name': 'VC4', 1883 'domain': 'domain-4', 1884 # Management form data for VC members 1885 'form-TOTAL_FORMS': 0, 1886 'form-INITIAL_FORMS': 3, 1887 'form-MIN_NUM_FORMS': 0, 1888 'form-MAX_NUM_FORMS': 1000, 1889 } 1890 1891 cls.csv_data = ( 1892 "name,domain,master", 1893 "VC4,Domain 4,Device 10", 1894 "VC5,Domain 5,Device 11", 1895 "VC6,Domain 6,Device 12", 1896 ) 1897 1898 cls.bulk_edit_data = { 1899 'domain': 'domain-x', 1900 } 1901 1902 1903class PowerPanelTestCase(ViewTestCases.PrimaryObjectViewTestCase): 1904 model = PowerPanel 1905 1906 @classmethod 1907 def setUpTestData(cls): 1908 1909 sites = ( 1910 Site(name='Site 1', slug='site-1'), 1911 Site(name='Site 2', slug='site-2'), 1912 ) 1913 Site.objects.bulk_create(sites) 1914 1915 locations = ( 1916 Location(name='Location 1', slug='location-1', site=sites[0]), 1917 Location(name='Location 2', slug='location-2', site=sites[1]), 1918 ) 1919 for location in locations: 1920 location.save() 1921 1922 PowerPanel.objects.bulk_create(( 1923 PowerPanel(site=sites[0], location=locations[0], name='Power Panel 1'), 1924 PowerPanel(site=sites[0], location=locations[0], name='Power Panel 2'), 1925 PowerPanel(site=sites[0], location=locations[0], name='Power Panel 3'), 1926 )) 1927 1928 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1929 1930 cls.form_data = { 1931 'site': sites[1].pk, 1932 'location': locations[1].pk, 1933 'name': 'Power Panel X', 1934 'tags': [t.pk for t in tags], 1935 } 1936 1937 cls.csv_data = ( 1938 "site,location,name", 1939 "Site 1,Location 1,Power Panel 4", 1940 "Site 1,Location 1,Power Panel 5", 1941 "Site 1,Location 1,Power Panel 6", 1942 ) 1943 1944 cls.bulk_edit_data = { 1945 'site': sites[1].pk, 1946 'location': locations[1].pk, 1947 } 1948 1949 1950class PowerFeedTestCase(ViewTestCases.PrimaryObjectViewTestCase): 1951 model = PowerFeed 1952 1953 @classmethod 1954 def setUpTestData(cls): 1955 1956 site = Site.objects.create(name='Site 1', slug='site-1') 1957 1958 powerpanels = ( 1959 PowerPanel(site=site, name='Power Panel 1'), 1960 PowerPanel(site=site, name='Power Panel 2'), 1961 ) 1962 PowerPanel.objects.bulk_create(powerpanels) 1963 1964 racks = ( 1965 Rack(site=site, name='Rack 1'), 1966 Rack(site=site, name='Rack 2'), 1967 ) 1968 Rack.objects.bulk_create(racks) 1969 1970 PowerFeed.objects.bulk_create(( 1971 PowerFeed(name='Power Feed 1', power_panel=powerpanels[0], rack=racks[0]), 1972 PowerFeed(name='Power Feed 2', power_panel=powerpanels[0], rack=racks[0]), 1973 PowerFeed(name='Power Feed 3', power_panel=powerpanels[0], rack=racks[0]), 1974 )) 1975 1976 tags = create_tags('Alpha', 'Bravo', 'Charlie') 1977 1978 cls.form_data = { 1979 'name': 'Power Feed X', 1980 'power_panel': powerpanels[1].pk, 1981 'rack': racks[1].pk, 1982 'status': PowerFeedStatusChoices.STATUS_PLANNED, 1983 'type': PowerFeedTypeChoices.TYPE_REDUNDANT, 1984 'supply': PowerFeedSupplyChoices.SUPPLY_DC, 1985 'phase': PowerFeedPhaseChoices.PHASE_3PHASE, 1986 'voltage': 100, 1987 'amperage': 100, 1988 'max_utilization': 50, 1989 'comments': 'New comments', 1990 'tags': [t.pk for t in tags], 1991 } 1992 1993 cls.csv_data = ( 1994 "site,power_panel,name,status,type,supply,phase,voltage,amperage,max_utilization", 1995 "Site 1,Power Panel 1,Power Feed 4,active,primary,ac,single-phase,120,20,80", 1996 "Site 1,Power Panel 1,Power Feed 5,active,primary,ac,single-phase,120,20,80", 1997 "Site 1,Power Panel 1,Power Feed 6,active,primary,ac,single-phase,120,20,80", 1998 ) 1999 2000 cls.bulk_edit_data = { 2001 'power_panel': powerpanels[1].pk, 2002 'rack': racks[1].pk, 2003 'status': PowerFeedStatusChoices.STATUS_PLANNED, 2004 'type': PowerFeedTypeChoices.TYPE_REDUNDANT, 2005 'supply': PowerFeedSupplyChoices.SUPPLY_DC, 2006 'phase': PowerFeedPhaseChoices.PHASE_3PHASE, 2007 'voltage': 100, 2008 'amperage': 100, 2009 'max_utilization': 50, 2010 'comments': 'New comments', 2011 } 2012 2013 @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) 2014 def test_trace(self): 2015 manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer-1') 2016 device_type = DeviceType.objects.create( 2017 manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' 2018 ) 2019 device_role = DeviceRole.objects.create( 2020 name='Device Role', slug='device-role-1' 2021 ) 2022 device = Device.objects.create( 2023 site=Site.objects.first(), device_type=device_type, device_role=device_role 2024 ) 2025 2026 powerfeed = PowerFeed.objects.first() 2027 powerport = PowerPort.objects.create( 2028 device=device, 2029 name='Power Port 1' 2030 ) 2031 Cable(termination_a=powerfeed, termination_b=powerport).save() 2032 2033 response = self.client.get(reverse('dcim:powerfeed_trace', kwargs={'pk': powerfeed.pk})) 2034 self.assertHttpStatus(response, 200) 2035