def test_update_sets_relay_vlan(self): vlan = factory.make_VLAN() relay_vlan = factory.make_VLAN() form = VLANForm(instance=vlan, data={"relay_vlan": relay_vlan.id}) self.assertTrue(form.is_valid(), form.errors) form.save() vlan = reload_object(vlan) self.assertEquals(relay_vlan.id, vlan.relay_vlan.id)
def test_update_setting_both_racks_to_same_fails(self): vlan = factory.make_VLAN() rack = factory.make_RackController(vlan=vlan) form = VLANForm(instance=vlan, data={ "primary_rack": rack.system_id, "secondary_rack": rack.system_id, }) self.assertFalse(form.is_valid())
def test_update_clears_relay_vlan_when_empty(self): relay_vlan = factory.make_VLAN() vlan = factory.make_VLAN(relay_vlan=relay_vlan) form = VLANForm(instance=vlan, data={"relay_vlan": ""}) self.assertTrue(form.is_valid(), form.errors) form.save() vlan = reload_object(vlan) self.assertIsNone(vlan.relay_vlan)
def test_update_clears_space_vlan_when_empty(self): space = factory.make_Space() vlan = factory.make_VLAN(space=space) form = VLANForm(instance=vlan, data={"space": ""}) self.assertTrue(form.is_valid(), form.errors) form.save() vlan = reload_object(vlan) self.assertIsNone(vlan.space)
def test_update_sets_space_by_specifier(self): vlan = factory.make_VLAN() space = factory.make_Space() form = VLANForm(instance=vlan, data={"space": "name:" + space.name}) self.assertTrue(form.is_valid(), form.errors) form.save() vlan = reload_object(vlan) self.assertEquals(space.id, vlan.space.id)
def test_update_sets_primary_rack(self): vlan = factory.make_VLAN() rack = factory.make_RackController(vlan=vlan) form = VLANForm(instance=vlan, data={ "primary_rack": rack.system_id, }) self.assertTrue(form.is_valid(), form.errors) form.save() self.assertEqual(rack, reload_object(vlan).primary_rack)
def test_update_unsets_secondary_rack(self): vlan = factory.make_VLAN() rack = factory.make_RackController(vlan=vlan) vlan.secondary_rack = rack vlan.save() form = VLANForm(instance=vlan, data={"secondary_rack": ""}) self.assertTrue(form.is_valid(), form.errors) form.save() self.assertEqual(None, reload_object(vlan).secondary_rack)
def test_update_validates_subnet_with_dhcp_on(self): vlan = factory.make_VLAN() rack = factory.make_RackController(vlan=vlan) vlan.primary_rack = rack vlan.save() form = VLANForm(instance=reload_object(vlan), data={ "dhcp_on": "true", }) self.assertFalse(form.is_valid())
def test_update_secondary_set_to_existing_primary_fails(self): vlan = factory.make_VLAN() rack = factory.make_RackController(vlan=vlan) vlan.primary_rack = rack vlan.save() form = VLANForm(instance=reload_object(vlan), data={ "secondary_rack": rack.system_id, }) self.assertFalse(form.is_valid())
def test__requires_vid(self): fabric = factory.make_Fabric() form = VLANForm(fabric=fabric, data={}) self.assertFalse(form.is_valid(), form.errors) self.assertEqual({ "vid": [ "This field is required.", "VID must be between 0 and 4094.", ], }, form.errors)
def test_allows_moving_vlan_to_new_fabric_if_vid_is_unique(self): fabric0 = Fabric.objects.get_default_fabric() fabric1 = factory.make_Fabric() fabric1_untagged = fabric1.get_default_vlan() form = VLANForm( instance=fabric1_untagged, data={"fabric": fabric0.id, "vid": 10} ) is_valid = form.is_valid() self.assertThat(is_valid, Equals(True)) form.save()
def test_deletes_empty_fabrics(self): fabric0 = Fabric.objects.get_default_fabric() fabric1 = factory.make_Fabric() fabric1_untagged = fabric1.get_default_vlan() form = VLANForm( instance=fabric1_untagged, data={"fabric": fabric0.id, "vid": 10} ) is_valid = form.is_valid() self.assertThat(is_valid, Equals(True)) form.save() self.assertThat(reload_object(fabric1), Equals(None))
def test_update_turns_dhcp_on(self): vlan = factory.make_VLAN() factory.make_ipv4_Subnet_with_IPRanges(vlan=vlan) rack = factory.make_RackController(vlan=vlan) vlan.primary_rack = rack vlan.save() form = VLANForm(instance=reload_object(vlan), data={"dhcp_on": "true"}) self.assertTrue(form.is_valid(), form.errors) form.save() vlan = reload_object(vlan) self.assertTrue(vlan.dhcp_on)
def test__creates_vlan_with_default_mtu(self): fabric = factory.make_Fabric() vlan_name = factory.make_name("vlan") vid = random.randint(1, 1000) form = VLANForm(fabric=fabric, data={"name": vlan_name, "vid": vid}) self.assertTrue(form.is_valid(), form.errors) vlan = form.save() self.assertEqual(vlan_name, vlan.name) self.assertEqual(vid, vlan.vid) self.assertEqual(fabric, vlan.fabric) self.assertEqual(DEFAULT_MTU, vlan.mtu)
def test_update_setting_secondary_fails_when_primary_dead(self): vlan = factory.make_VLAN() rack = factory.make_RackController(vlan=vlan) vlan.primary_rack = rack vlan.save() service = Service.objects.get(node=rack, name="rackd") service.status = SERVICE_STATUS.DEAD service.save() second_rack = factory.make_RackController(vlan=vlan) form = VLANForm(instance=vlan, data={"secondary_rack": second_rack.system_id}) self.assertFalse(form.is_valid())
def test_update_blank_primary_sets_to_secondary(self): vlan = factory.make_VLAN() primary_rack = factory.make_RackController(vlan=vlan) secondary_rack = factory.make_RackController(vlan=vlan) vlan.primary_rack = primary_rack vlan.secondary_rack = secondary_rack vlan.save() form = VLANForm(instance=reload_object(vlan), data={"primary_rack": ""}) self.assertTrue(form.is_valid(), form.errors) form.save() vlan = reload_object(vlan) self.assertEqual(secondary_rack, vlan.primary_rack) self.assertEqual(None, vlan.secondary_rack)
def create(self, request, fabric_id): """Create a VLAN. :param name: Name of the VLAN. :param description: Description of the VLAN. :param vid: VLAN ID of the VLAN. """ fabric = Fabric.objects.get_fabric_or_404(fabric_id, request.user, NODE_PERMISSION.ADMIN) form = VLANForm(fabric=fabric, data=request.data) if form.is_valid(): return form.save() else: raise MAASAPIValidationError(form.errors)
def test_update_setting_secondary_allowed_when_primary_on(self): vlan = factory.make_VLAN() rack = factory.make_RackController(vlan=vlan) vlan.primary_rack = rack vlan.save() service = Service.objects.get(node=rack, name="rackd") service.status = SERVICE_STATUS.RUNNING service.save() second_rack = factory.make_RackController(vlan=vlan) form = VLANForm(instance=vlan, data={"secondary_rack": second_rack.system_id}) self.assertTrue(form.is_valid()) form.save() vlan = reload_object(vlan) self.assertEqual(second_rack, vlan.secondary_rack)
def test__vlans_already_using_relay_vlan_not_shown(self): fabric = Fabric.objects.get_default_fabric() relay_vlan = factory.make_VLAN() factory.make_VLAN(relay_vlan=relay_vlan) form = VLANForm(fabric=fabric, data={}) self.assertItemsEqual([fabric.get_default_vlan(), relay_vlan], form.fields['relay_vlan'].queryset)
def test__cannot_move_vlan_with_overlapping_vid(self): fabric0 = Fabric.objects.get_default_fabric() fabric1 = factory.make_Fabric() fabric1_untagged = fabric1.get_default_vlan() form = VLANForm(instance=fabric1_untagged, data={ "fabric": fabric0.id }) is_valid = form.is_valid() self.assertThat(is_valid, Equals(False)) self.assertThat(dict(form.errors), Equals( {'__all__': [ 'A VLAN with the specified VID already ' 'exists in the destination fabric.' ]} )) with ExpectedException(ValueError): form.save()
def test__updates_vlan(self): vlan = factory.make_VLAN() new_name = factory.make_name("vlan") new_description = factory.make_name("description") new_vid = random.randint(1, 1000) new_mtu = random.randint(552, 4096) form = VLANForm(instance=vlan, data={ "name": new_name, "description": new_description, "vid": new_vid, "mtu": new_mtu, }) self.assertTrue(form.is_valid(), form.errors) form.save() self.assertEqual(new_name, reload_object(vlan).name) self.assertEqual(new_description, reload_object(vlan).description) self.assertEqual(new_vid, reload_object(vlan).vid) self.assertEqual(new_mtu, reload_object(vlan).mtu)
def test_update_can_delete_primary_and_set_dhcp_on_with_secondary(self): vlan = factory.make_VLAN() factory.make_ipv4_Subnet_with_IPRanges(vlan=vlan) primary_rack = factory.make_RackController(vlan=vlan) secondary_rack = factory.make_RackController(vlan=vlan) vlan.primary_rack = primary_rack vlan.secondary_rack = secondary_rack vlan.save() form = VLANForm( instance=reload_object(vlan), data={"primary_rack": "", "dhcp_on": "true"}, ) self.assertTrue(form.is_valid(), form.errors) form.save() vlan = reload_object(vlan) self.assertEqual(secondary_rack, vlan.primary_rack) self.assertEqual(None, vlan.secondary_rack) self.assertTrue(vlan.dhcp_on)
def update(self, request, **kwargs): """Update VLAN. :param name: Name of the VLAN. :type name: unicode :param description: Description of the VLAN. :type description: unicode :param vid: VLAN ID of the VLAN. :type vid: integer :param mtu: The MTU to use on the VLAN. :type mtu: integer :param dhcp_on: Whether or not DHCP should be managed on the VLAN. :type dhcp_on: boolean :param primary_rack: The primary rack controller managing the VLAN. :type primary_rack: system_id :param secondary_rack: The secondary rack controller manging the VLAN. :type secondary_rack: system_id :param relay_vlan: Only set when this VLAN will be using a DHCP relay to forward DHCP requests to another VLAN that MAAS is or will run the DHCP server. MAAS will not run the DHCP relay itself, it must be configured to proxy reqests to the primary and/or secondary rack controller interfaces for the VLAN specified in this field. :type relay_vlan: ID of VLAN :param space: The space this VLAN should be placed in. Passing in an empty string (or the string 'undefined') will cause the VLAN to be placed in the 'undefined' space. :type space: unicode Returns 404 if the fabric or VLAN is not found. """ vlan = self._get_vlan(request.user, NODE_PERMISSION.ADMIN, **kwargs) data = {} # If the user passed in a space, make the undefined space name a # synonym for the empty space. But the Django request data object is # immutable, so we must first copy its contents into our own dict. for k, v in request.data.items(): data[k] = v if 'space' in data and data['space'] == Space.UNDEFINED: data['space'] = '' form = VLANForm(instance=vlan, data=data) if form.is_valid(): return form.save() else: raise MAASAPIValidationError(form.errors)
def test__creates_vlan(self): fabric = factory.make_Fabric() vlan_name = factory.make_name("vlan") vlan_description = factory.make_name("description") vid = random.randint(1, 1000) mtu = random.randint(552, 4096) form = VLANForm(fabric=fabric, data={ "name": vlan_name, "description": vlan_description, "vid": vid, "mtu": mtu, }) self.assertTrue(form.is_valid(), form.errors) vlan = form.save() self.assertEqual(vlan_name, vlan.name) self.assertEqual(vlan_description, vlan.description) self.assertEqual(vid, vlan.vid) self.assertEqual(fabric, vlan.fabric) self.assertEqual(mtu, vlan.mtu)
def configure_dhcp(self, parameters): """Helper method to look up rack controllers based on the parameters provided in the action input, and then reconfigure DHCP on the VLAN based on them. Requires a dictionary of parameters containing an ordered list of each desired rack controller system_id. If no controllers are specified, disables DHCP on the VLAN. """ vlan = self.get_object(parameters) self.user = reload_object(self.user) assert self.user.has_perm(NodePermission.admin, vlan), "Permission denied." # Make sure the dictionary both exists, and has the expected number # of parameters, to prevent spurious log statements. if 'extra' in parameters: self._configure_iprange_and_gateway(parameters['extra']) if 'relay_vlan' not in parameters: iprange_count = IPRange.objects.filter(type=IPRANGE_TYPE.DYNAMIC, subnet__vlan=vlan).count() if iprange_count == 0: raise ValueError( "Cannot configure DHCP: At least one dynamic range is " "required.") controllers = parameters.get('controllers', []) data = { "dhcp_on": True if len(controllers) > 0 else False, "primary_rack": controllers[0] if len(controllers) > 0 else None, "secondary_rack": controllers[1] if len(controllers) > 1 else None, } if 'relay_vlan' in parameters: data['relay_vlan'] = parameters['relay_vlan'] form = VLANForm(instance=vlan, data=data) if form.is_valid(): form.save() else: raise HandlerValidationError(form.errors)
def create(self, request, fabric_id): """@description-title Create a VLAN @description Creates a new VLAN. @param (int) "{fabric_id}" [required=true] The fabric_id on which to add the new VLAN. @param (string) "name" [required=false] Name of the VLAN. @param (string) "description" [required=false] Description of the new VLAN. @param (int) "vid" [required=true] VLAN ID of the new VLAN. @param (int) "mtu" [required=false] The MTU to use on the VLAN. @param (string) "space" [required=false] The space this VLAN should be placed in. Passing in an empty string (or the string 'undefined') will cause the VLAN to be placed in the 'undefined' space. @success (http-status-code) "200" 200 @success (json) "success-json" A JSON object containing information about the new VLAN. @success-example "success-json" [exkey=vlan-create] placeholder text @error (http-status-code) "404" 404 @error (content) "not-found" The requested fabric_id is not found. @error-example "not-found" Not Found """ fabric = Fabric.objects.get_fabric_or_404(fabric_id, request.user, NodePermission.admin) form = VLANForm(fabric=fabric, data=request.data) if form.is_valid(): return form.save() else: raise MAASAPIValidationError(form.errors)
def create(self, request, fabric_id): """Create a VLAN. :param name: Name of the VLAN. :type name: unicode :param description: Description of the VLAN. :type description: unicode :param vid: VLAN ID of the VLAN. :type vid: integer :param mtu: The MTU to use on the VLAN. :type mtu: integer :param space: The space this VLAN should be placed in. Passing in an empty string (or the string 'undefined') will cause the VLAN to be placed in the 'undefined' space. :type space: unicode """ fabric = Fabric.objects.get_fabric_or_404(fabric_id, request.user, NodePermission.admin) form = VLANForm(fabric=fabric, data=request.data) if form.is_valid(): return form.save() else: raise MAASAPIValidationError(form.errors)
def test__doest_require_name_vid_or_mtu_on_update(self): vlan = factory.make_VLAN() form = VLANForm(instance=vlan, data={}) self.assertTrue(form.is_valid(), form.errors)
def test__no_relay_vlans_allowed_when_dhcp_on(self): vlan = factory.make_VLAN(dhcp_on=True) factory.make_VLAN() form = VLANForm(instance=vlan, data={}) self.assertItemsEqual([], form.fields["relay_vlan"].queryset)
def test__self_vlan_not_used_in_relay_vlan_field(self): fabric = Fabric.objects.get_default_fabric() relay_vlan = fabric.get_default_vlan() form = VLANForm(instance=relay_vlan, data={}) self.assertItemsEqual([], form.fields["relay_vlan"].queryset)