Esempio n. 1
0
 def test_clean_disabled_boot_arches_hex(self):
     subnet = factory.make_Subnet()
     disabled_arches = random.sample(
         [
             boot_method for _, boot_method in BootMethodRegistry
             if boot_method.arch_octet
         ],
         3,
     )
     form = SubnetForm(
         instance=subnet,
         data={
             "disabled_boot_architectures":
             ",".join([
                 bm.arch_octet.replace("00:", "0x")
                 for bm in disabled_arches
             ])
         },
     )
     self.assertTrue(form.is_valid(), dict(form.errors))
     form.save()
     subnet = reload_object(subnet)
     self.assertEqual(
         sorted([bm.name for bm in disabled_arches]),
         sorted(subnet.disabled_boot_architectures),
     )
Esempio n. 2
0
 def test__creates_subnet(self):
     subnet_name = factory.make_name("subnet")
     subnet_description = factory.make_name("description")
     vlan = factory.make_VLAN()
     network = factory.make_ip4_or_6_network()
     cidr = str(network.cidr)
     gateway_ip = factory.pick_ip_in_network(network)
     dns_servers = []
     for _ in range(2):
         dns_servers.append(
             factory.pick_ip_in_network(network,
                                        but_not=[gateway_ip] + dns_servers))
     form = SubnetForm({
         "name": subnet_name,
         "description": subnet_description,
         "vlan": vlan.id,
         "cidr": cidr,
         "gateway_ip": gateway_ip,
         "dns_servers": ",".join(dns_servers),
     })
     self.assertTrue(form.is_valid(), dict(form.errors))
     subnet = form.save()
     self.assertThat(
         subnet,
         MatchesStructure.byEquality(
             name=subnet_name,
             description=subnet_description,
             vlan=vlan,
             cidr=cidr,
             gateway_ip=gateway_ip,
             dns_servers=dns_servers,
         ),
     )
Esempio n. 3
0
 def test__updates_subnet(self):
     new_name = factory.make_name("subnet")
     new_description = factory.make_name("description")
     subnet = factory.make_Subnet()
     new_vlan = factory.make_VLAN()
     new_network = factory.make_ip4_or_6_network()
     new_cidr = str(new_network.cidr)
     new_gateway_ip = factory.pick_ip_in_network(new_network)
     new_dns_servers = []
     for _ in range(2):
         new_dns_servers.append(
             factory.pick_ip_in_network(new_network,
                                        but_not=[new_gateway_ip] +
                                        new_dns_servers))
     form = SubnetForm(instance=subnet,
                       data={
                           "name": new_name,
                           "description": new_description,
                           "vlan": new_vlan.id,
                           "cidr": new_cidr,
                           "gateway_ip": new_gateway_ip,
                           "dns_servers": ','.join(new_dns_servers),
                       })
     self.assertTrue(form.is_valid(), dict(form.errors))
     form.save()
     subnet = reload_object(subnet)
     self.assertThat(
         subnet,
         MatchesStructure.byEquality(name=new_name,
                                     description=new_description,
                                     vlan=new_vlan,
                                     cidr=new_cidr,
                                     gateway_ip=new_gateway_ip,
                                     dns_servers=new_dns_servers))
Esempio n. 4
0
 def test__removes_host_bits_and_whitespace(self):
     form = SubnetForm({
         "cidr": ' 10.0.0.1/24 ',
     })
     self.assertTrue(form.is_valid(), dict(form.errors))
     subnet = form.save()
     self.assertThat(subnet.cidr, Equals('10.0.0.0/24'))
Esempio n. 5
0
 def test__rejects_ipv6_cidr_with_zero_prefixlen(self):
     form = SubnetForm({"cidr": "::/0"})
     self.assertFalse(form.is_valid(), dict(form.errors))
     self.assertEqual(
         {"cidr": ["Prefix length must be greater than 0."]},
         dict(form.errors),
     )
Esempio n. 6
0
 def test__rejects_invalid_cidr(self):
     form = SubnetForm(
         {"cidr": "ten dot zero dot zero dot zero slash zero"})
     self.assertFalse(form.is_valid(), dict(form.errors))
     self.assertEqual(
         {"cidr": ["Required format: <network>/<prefixlen>."]},
         dict(form.errors),
     )
Esempio n. 7
0
 def test__clean_dns_servers_accepts_space_separated_list(self):
     subnet = factory.make_Subnet()
     dns_servers = [
         factory.make_ip_address() for _ in range(random.randint(2, 10))
     ]
     form = SubnetForm(instance=subnet,
                       data={"dns_servers": " ".join(dns_servers)})
     self.assertTrue(form.is_valid(), dict(form.errors))
     form.save()
     subnet = reload_object(subnet)
     self.assertEquals(dns_servers, subnet.dns_servers)
Esempio n. 8
0
 def test__error_for_unknown_vid_in_default_fabric(self):
     fabric = factory.make_Fabric()
     vlan = factory.make_VLAN(fabric=fabric)
     network = factory.make_ip4_or_6_network()
     cidr = str(network.cidr)
     form = SubnetForm({"cidr": cidr, "vid": vlan.vid})
     self.assertFalse(form.is_valid(), dict(form.errors))
     self.assertEqual(
         {"vid": ["No VLAN with vid %s in default fabric." % vlan.vid]},
         dict(form.errors),
     )
Esempio n. 9
0
 def test__error_for_vlan_not_in_fabric(self):
     fabric = factory.make_Fabric()
     vlan = factory.make_VLAN(fabric=Fabric.objects.get_default_fabric())
     network = factory.make_ip4_or_6_network()
     cidr = str(network.cidr)
     form = SubnetForm({"cidr": cidr, "fabric": fabric.id, "vlan": vlan.id})
     self.assertFalse(form.is_valid(), dict(form.errors))
     self.assertEqual(
         {"vlan": ["VLAN %s is not in fabric %s." % (vlan, fabric)]},
         dict(form.errors),
     )
Esempio n. 10
0
 def test_clean_disabled_detects_invalid_arch(self):
     subnet = factory.make_Subnet(disabled_boot_architectures=[])
     form = SubnetForm(
         instance=subnet,
         data={
             "disabled_boot_architectures": factory.make_name("boot_arch")
         },
     )
     self.assertFalse(form.is_valid())
     subnet = reload_object(subnet)
     self.assertEqual([], subnet.disabled_boot_architectures)
Esempio n. 11
0
 def test__creates_subnet_in_default_fabric_with_vid(self):
     vlan = factory.make_VLAN(fabric=Fabric.objects.get_default_fabric())
     network = factory.make_ip4_or_6_network()
     cidr = str(network.cidr)
     form = SubnetForm({"cidr": cidr, "vid": vlan.vid, "vlan": None})
     self.assertTrue(form.is_valid(), dict(form.errors))
     subnet = form.save()
     self.assertThat(
         subnet,
         MatchesStructure.byEquality(name=cidr, cidr=cidr, vlan=vlan),
     )
Esempio n. 12
0
 def test__creates_subnet_name_equal_to_cidr(self):
     vlan = factory.make_VLAN()
     network = factory.make_ip4_or_6_network()
     cidr = str(network.cidr)
     form = SubnetForm({"vlan": vlan.id, "cidr": cidr})
     self.assertTrue(form.is_valid(), dict(form.errors))
     subnet = form.save()
     self.assertThat(
         subnet,
         MatchesStructure.byEquality(name=cidr, vlan=vlan, cidr=cidr),
     )
Esempio n. 13
0
 def test__rejects_provided_space_on_update(self):
     space = factory.make_Space()
     subnet = factory.make_Subnet()
     form = SubnetForm(instance=subnet, data={"space": space.id})
     self.assertFalse(form.is_valid(), dict(form.errors))
     self.assertEqual(
         {
             "space": [
                 "Spaces may no longer be set on subnets. Set the space on the "
                 "underlying VLAN."
             ]
         }, dict(form.errors))
Esempio n. 14
0
 def test__updates_subnet_name_doesnt_remove_dns_server(self):
     # Regression test for lp:1521833
     dns_servers = [
         factory.make_ip_address() for _ in range(random.randint(2, 10))
     ]
     subnet = factory.make_Subnet(dns_servers=dns_servers)
     form = SubnetForm(instance=subnet,
                       data={"name": factory.make_name("subnet")})
     self.assertTrue(form.is_valid(), dict(form.errors))
     form.save()
     subnet = reload_object(subnet)
     self.assertEquals(dns_servers, subnet.dns_servers)
Esempio n. 15
0
 def test_clears_gateway_and_dns_ervers(self):
     subnet = factory.make_Subnet()
     form = SubnetForm(
         instance=subnet, data={"gateway_ip": "", "dns_servers": ""}
     )
     self.assertTrue(form.is_valid(), dict(form.errors))
     form.save()
     subnet = reload_object(subnet)
     self.assertThat(
         subnet,
         MatchesStructure.byEquality(gateway_ip=None, dns_servers=[]),
     )
Esempio n. 16
0
    def update(self, request, id):
        """\
        Update the specified subnet.

        Please see the documentation for the 'create' operation for detailed
        descriptions of each parameter.

        Optional parameters
        -------------------

        name
          Name of the subnet.

        description
          Description of the subnet.

        vlan
          VLAN this subnet belongs to.

        space
          Space this subnet is in.

        cidr
          The network CIDR for this subnet.

        gateway_ip
          The gateway IP address for this subnet.

        rdns_mode
          How reverse DNS is handled for this subnet.

        allow_dns
          Configure MAAS DNS to allow DNS resolution from this subnet.

        allow_proxy
          Configure maas-proxy to allow requests from this subnet.

        dns_servers
          Comma-seperated list of DNS servers for this subnet.

        managed
          If False, MAAS should not manage this subnet. (Default: True)

        Returns 404 if the subnet is not found.
        """
        subnet = Subnet.objects.get_subnet_or_404(id, request.user,
                                                  NodePermission.admin)
        form = SubnetForm(instance=subnet, data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
Esempio n. 17
0
 def test__creates_subnet_in_default_vlan_in_fabric(self):
     fabric = factory.make_Fabric()
     network = factory.make_ip4_or_6_network()
     cidr = str(network.cidr)
     form = SubnetForm({"cidr": cidr, "fabric": fabric.id, "vlan": None})
     self.assertTrue(form.is_valid(), dict(form.errors))
     subnet = form.save()
     self.assertThat(
         subnet,
         MatchesStructure.byEquality(name=cidr,
                                     cidr=cidr,
                                     vlan=fabric.get_default_vlan()),
     )
Esempio n. 18
0
 def test__rejects_space_on_create(self):
     space = factory.make_Space()
     form = SubnetForm({
         "space": space.id,
         "cidr": factory._make_random_network()
     })
     self.assertFalse(form.is_valid(), dict(form.errors))
     self.assertEqual(
         {
             "space": [
                 "Spaces may no longer be set on subnets. Set the space on the "
                 "underlying VLAN."
             ]
         }, dict(form.errors))
Esempio n. 19
0
 def test__creates_subnet_in_default_fabric_and_vlan(self):
     network = factory.make_ip4_or_6_network()
     cidr = str(network.cidr)
     form = SubnetForm({"cidr": cidr})
     self.assertTrue(form.is_valid(), dict(form.errors))
     subnet = form.save()
     self.assertThat(
         subnet,
         MatchesStructure.byEquality(
             name=cidr,
             cidr=cidr,
             vlan=Fabric.objects.get_default_fabric().get_default_vlan(),
         ),
     )
Esempio n. 20
0
 def test__doesnt_overwrite_other_fields(self):
     new_name = factory.make_name("subnet")
     subnet = factory.make_Subnet()
     form = SubnetForm(instance=subnet, data={
         "name": new_name,
     })
     self.assertTrue(form.is_valid(), dict(form.errors))
     form.save()
     subnet = reload_object(subnet)
     self.assertThat(
         subnet,
         MatchesStructure.byEquality(name=new_name,
                                     vlan=subnet.vlan,
                                     cidr=subnet.cidr,
                                     gateway_ip=subnet.gateway_ip,
                                     dns_servers=subnet.dns_servers))
Esempio n. 21
0
 def test__error_for_unknown_vid_in_fabric(self):
     fabric = factory.make_Fabric()
     vlan = factory.make_VLAN(fabric=Fabric.objects.get_default_fabric())
     network = factory.make_ip4_or_6_network()
     cidr = str(network.cidr)
     form = SubnetForm({
         "cidr": cidr,
         "fabric": fabric.id,
         "vid": vlan.vid,
     })
     self.assertFalse(form.is_valid(), dict(form.errors))
     self.assertEqual(
         {
             "vid":
             ["No VLAN with vid %s in fabric %s." % (vlan.vid, fabric)]
         }, dict(form.errors))
Esempio n. 22
0
    def test_clean_disabled_boot_arches_cannot_disable_fake_boot_arch(self):
        # The Windows boot loader responds to bootloader configuration requests
        # but isc-dhcpd is not configured to respond to a boot octet nor a
        # user-class. Thus it is unable to be disabled.
        subnet = factory.make_Subnet(disabled_boot_architectures=[])
        choices = [
            boot_method.name for _, boot_method in BootMethodRegistry
            if not boot_method.arch_octet and not boot_method.user_class
        ]

        form = SubnetForm(
            instance=subnet,
            data={"disabled_boot_architectures": random.choice(choices)},
        )
        self.assertFalse(form.is_valid())
        subnet = reload_object(subnet)
        self.assertEqual([], subnet.disabled_boot_architectures)
Esempio n. 23
0
 def test__creates_subnet_in_fabric_with_vid(self):
     fabric = factory.make_Fabric()
     vlan = factory.make_VLAN(fabric=fabric)
     network = factory.make_ip4_or_6_network()
     cidr = str(network.cidr)
     form = SubnetForm({
         "cidr": cidr,
         "fabric": fabric.id,
         "vid": vlan.vid,
         "vlan": None,
     })
     self.assertTrue(form.is_valid(), form.errors)
     subnet = form.save()
     self.assertThat(
         subnet, MatchesStructure.byEquality(name=cidr,
                                             cidr=cidr,
                                             vlan=vlan))
Esempio n. 24
0
    def test_clean_disabled_boot_arches_name_space_seperated_list(self):
        subnet = factory.make_Subnet()
        disabled_arches = random.sample(
            [
                boot_method.name for _, boot_method in BootMethodRegistry
                if boot_method.arch_octet or boot_method.user_class
            ],
            3,
        )

        form = SubnetForm(
            instance=subnet,
            data={"disabled_boot_architectures": " ".join(disabled_arches)},
        )
        self.assertTrue(form.is_valid(), dict(form.errors))
        form.save()
        subnet = reload_object(subnet)
        self.assertEqual(sorted(disabled_arches),
                         sorted(subnet.disabled_boot_architectures))
Esempio n. 25
0
 def test__updates_subnet_name_to_cidr(self):
     subnet = factory.make_Subnet()
     subnet.name = subnet.cidr
     subnet.save()
     new_network = factory.make_ip4_or_6_network()
     new_cidr = str(new_network.cidr)
     new_gateway_ip = factory.pick_ip_in_network(new_network)
     form = SubnetForm(instance=subnet,
                       data={
                           "cidr": new_cidr,
                           "gateway_ip": new_gateway_ip,
                       })
     self.assertTrue(form.is_valid(), dict(form.errors))
     form.save()
     subnet = reload_object(subnet)
     self.assertThat(
         subnet,
         MatchesStructure.byEquality(name=new_cidr,
                                     cidr=new_cidr,
                                     gateway_ip=new_gateway_ip))
Esempio n. 26
0
    def create(self, request):
        """\
        Create a subnet.

        Required parameters
        -------------------

        cidr
          The network CIDR for this subnet.


        Optional parameters
        -------------------

        name
          Name of the subnet.

        description
          Description of the subnet.

        vlan
          VLAN this subnet belongs to. Defaults to the default VLAN for the
          provided fabric or defaults to the default VLAN in the default fabric
          (if unspecified).

        fabric
          Fabric for the subnet. Defaults to the fabric the
          provided VLAN belongs to, or defaults to the default fabric.

        vid
          VID of the VLAN this subnet belongs to. Only used when vlan is
          not provided. Picks the VLAN with this VID in the provided
          fabric or the default fabric if one is not given.

        space
          Space this subnet is in. Defaults to the default space.

        gateway_ip
          The gateway IP address for this subnet.

        rdns_mode
          How reverse DNS is handled for this subnet.
          One of: 0 (Disabled), 1 (Enabled), or 2 (RFC2317).  Disabled
          means no reverse zone is created; Enabled means generate the
          reverse zone; RFC2317 extends Enabled to create the necessary
          parent zone with the appropriate CNAME resource records for the
          network, if the network is small enough to require the support
          described in RFC2317.

        allow_dns
          Configure MAAS DNS to allow DNS resolution from this subnet.

        allow_proxy
          Configure maas-proxy to allow requests from this
          subnet.

        dns_servers
          Comma-seperated list of DNS servers for this subnet.

        managed
          In MAAS 2.0+, all subnets are assumed to be managed by default.

          Only managed subnets allow DHCP to be enabled on their related
          dynamic ranges. (Thus, dynamic ranges become "informational
          only"; an indication that another DHCP server is currently
          handling them, or that MAAS will handle them when the subnet is
          enabled for management.)

          Managed subnets do not allow IP allocation by default. The
          meaning of a "reserved" IP range is reversed for an unmanaged
          subnet. (That is, for managed subnets, "reserved" means "MAAS
          cannot allocate any IP address within this reserved block". For
          unmanaged subnets, "reserved" means "MAAS must allocate IP
          addresses only from reserved IP ranges".
        """
        form = SubnetForm(data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
Esempio n. 27
0
    def create(self, request):
        """@description-title Create a subnet
        @description Creates a new subnet.

        @param (string) "cidr" [required=true] The network CIDR for this
        subnet.
        @param-example "cidr"
            192.168.1.1/24

        @param (string) "name" [required=false] The subnet's name.

        @param (string) "description" [required=false] The subnet's
        description.

        @param (string) "vlan" [required=false] VLAN this subnet belongs to.
        Defaults to the default VLAN for the provided fabric or defaults to the
        default VLAN in the default fabric (if unspecified).

        @param (string) "fabric" [required=false] Fabric for the subnet.
        Defaults to the fabric the provided VLAN belongs to, or defaults to the
        default fabric.

        @param (int) "vid" [required=false] VID of the VLAN this subnet belongs
        to. Only used when vlan is not provided. Picks the VLAN with this VID
        in the provided fabric or the default fabric if one is not given.

        @param (string) "space" [required=false] Space this subnet is in.
        Defaults to the default space.

        @param (string) "gateway_ip" [required=false] The gateway IP address
        for this subnet.

        @param (int) "rdns_mode" [required=false,formatting=true] How reverse
        DNS is handled for this subnet.  One of:

        - ``0`` Disabled: No reverse zone is created.
        - ``1`` Enabled: Generate reverse zone.
        - ``2`` RFC2317: Extends '1' to create the necessary parent zone with
          the appropriate CNAME resource records for the network, if the the
          network is small enough to require the support described in RFC2317.

        @param (int) "allow_dns" [required=false] Configure MAAS DNS to allow
        DNS resolution from this subnet. '0' == False,'1' == True.

        @param (int) "allow_proxy" [required=false] Configure maas-proxy to
        allow requests from this subnet. '0' == False, '1' == True.

        @param (string) "dns_servers" [required=false] Comma-seperated list of
        DNS servers for this subnet.

        @param (int) "managed" [required=false,formatting=true] In MAAS 2.0+,
        all subnets are assumed to be managed by default.

        @param (string) "disabled_boot_architectures" [required=false] A comma
        or space seperated list of boot architectures which will not be
        responded to by isc-dhcpd. Values may be the MAAS name for the boot
        architecture, the IANA hex value, or the isc-dhcpd octet.

        Only managed subnets allow DHCP to be enabled on their related dynamic
        ranges. (Thus, dynamic ranges become "informational only"; an
        indication that another DHCP server is currently handling them, or that
        MAAS will handle them when the subnet is enabled for management.)

        Managed subnets do not allow IP allocation by default. The meaning of a
        "reserved" IP range is reversed for an unmanaged subnet. (That is, for
        managed subnets, "reserved" means "MAAS cannot allocate any IP address
        within this reserved block". For unmanaged subnets, "reserved" means
        "MAAS must allocate IP addresses only from reserved IP ranges."

        @success (http-status-code) "server-success" 200
        @success (json) "success-json" A JSON object containing information
        about the new subnet.
        @success-example "success-json" [exkey=subnets-create] placeholder text
        """
        form = SubnetForm(data=request.data)
        if form.is_valid():
            return form.save()
        else:
            raise MAASAPIValidationError(form.errors)
Esempio n. 28
0
 def test__requires_cidr(self):
     form = SubnetForm({})
     self.assertFalse(form.is_valid(), dict(form.errors))
     self.assertEqual({"cidr": ["This field is required."]},
                      dict(form.errors))
Esempio n. 29
0
 def test__doest_require_vlan_or_cidr_on_update(self):
     subnet = factory.make_Subnet()
     form = SubnetForm(instance=subnet, data={})
     self.assertTrue(form.is_valid(), dict(form.errors))