def test_actual_instance_returns_PhysicalBlockDevice(self): block_device = factory.make_PhysicalBlockDevice() parent_type = BlockDevice.objects.get(id=block_device.id) self.assertIsInstance( parent_type.actual_instance, PhysicalBlockDevice)
def test_get_numa_nodes_indexes_only_own_device(self): block_device = factory.make_PhysicalBlockDevice() cache_set = factory.make_CacheSet(block_device=block_device) self.assertEqual(cache_set.get_numa_node_indexes(), [0])
class TestFilesystemMountableTypes(MAASServerTestCase): """Tests the `Filesystem` model with mountable filesystems.""" scenarios_fstypes_with_storage = tuple( (displayname, { "fstype": name }) for name, displayname in FILESYSTEM_FORMAT_TYPE_CHOICES_DICT.items() if name in Filesystem.TYPES_REQUIRING_STORAGE) scenarios_fstypes_without_storage = tuple( (displayname, { "fstype": name }) for name, displayname in FILESYSTEM_FORMAT_TYPE_CHOICES_DICT.items() if name not in Filesystem.TYPES_REQUIRING_STORAGE) scenarios_substrate_storage = ( ( "partition", { "make_substrate": lambda: { "partition": factory.make_Partition() }, "can_be_unmounted": True, }, ), ( "block-device", { "make_substrate": lambda: { "block_device": factory.make_PhysicalBlockDevice() }, "can_be_unmounted": True, }, ), ) scenarios_substrate_node = (( "node", { "make_substrate": lambda: { "node": factory.make_Node() }, "can_be_unmounted": False, }, ), ) scenarios = chain( multiply_scenarios(scenarios_fstypes_with_storage, scenarios_substrate_storage), multiply_scenarios(scenarios_fstypes_without_storage, scenarios_substrate_node), ) def test_can_create_mountable_filesystem(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem(fstype=self.fstype, **substrate) self.assertThat(filesystem, IsInstance(Filesystem)) self.assertThat(filesystem.fstype, Equals(self.fstype)) self.assertThat(filesystem.is_mountable, Is(True)) self.assertThat(filesystem, MatchesStructure.byEquality(**substrate)) def test_cannot_mount_two_filesystems_at_same_point(self): substrate = self.make_substrate() filesystem1 = factory.make_Filesystem(fstype=self.fstype, **substrate) filesystem2 = factory.make_Filesystem(node=filesystem1.get_node()) mount_point = factory.make_absolute_path() filesystem1.mount_point = mount_point filesystem1.save() filesystem2.mount_point = mount_point # Filesystems that can be mounted at a directory complain when mounted # at the same directory as another filesystem. if filesystem1.uses_mount_point: error = self.assertRaises(ValidationError, filesystem2.save) self.assertThat( error.messages, Equals([ "Another filesystem is already mounted at %s." % mount_point ]), ) else: self.assertThat(filesystem2.save(), Is(None)) def test_can_mount_unacquired_and_acquired_filesystem_at_same_point(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem(fstype=self.fstype, **substrate) filesystem.id = None filesystem.acquired = True self.assertThat(filesystem.save(), Is(None)) def test_mount_point_is_none_for_filesystems_that_do_not_use_one(self): substrate = self.make_substrate() mount_point = factory.make_name("mount-point") filesystem = factory.make_Filesystem(fstype=self.fstype, mount_point=mount_point, **substrate) if filesystem.uses_mount_point: self.assertThat(filesystem.mount_point, Equals(mount_point)) else: self.assertThat(filesystem.mount_point, Equals("none")) def test_filesystem_is_mounted_when_mount_point_is_set(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem(fstype=self.fstype, **substrate) if self.can_be_unmounted: # Some filesystems can be unmounted. By default that's how the # factory makes them, so we need to set mount_point to see how # is_mounted behaves. self.assertThat(filesystem.is_mounted, Is(False)) filesystem.mount_point = factory.make_name("path") self.assertThat(filesystem.is_mounted, Is(True)) else: # Some filesystems cannot be unmounted, and the factory ensures # that they're always created with a mount point. We can unset # mount_point and observe a change in is_mounted, but we'll be # prevented from saving the amended filesystem. self.assertThat(filesystem.is_mounted, Is(True)) filesystem.mount_point = None self.assertThat(filesystem.is_mounted, Is(False)) error = self.assertRaises(ValidationError, filesystem.save) self.assertThat( error.messages, Equals(["RAM-backed filesystems must be mounted."]), )
def test_path(self): block_device = factory.make_PhysicalBlockDevice() self.assertEqual( "/dev/disk/by-dname/%s" % block_device.name, block_device.path)
def test_get_name(self): block_device_name = factory.make_name("bd") block_device = factory.make_PhysicalBlockDevice(name=block_device_name) table = factory.make_PartitionTable(block_device=block_device) partition = factory.make_Partition(partition_table=table) self.assertEqual("%s-part1" % block_device_name, partition.get_name())
def create_physicalblockdevice(self, params=None): if params is None: params = {} return factory.make_PhysicalBlockDevice(**params)
def test_create_partition_if_boot_disk_raises_ValueError(self): node = factory.make_Node(with_boot_disk=False) boot_disk = factory.make_PhysicalBlockDevice(node=node) factory.make_PartitionTable(block_device=boot_disk) with ExpectedException(ValueError): boot_disk.create_partition_if_boot_disk()
def test_read(self): node = factory.make_Node() block_devices = [ factory.make_PhysicalBlockDevice(node=node) for _ in range(3) ] block_device_ids = [bd.id for bd in block_devices] bd_filesystems = [ factory.make_Filesystem(fstype=FILESYSTEM_TYPE.LVM_PV, block_device=bd) for bd in block_devices ] partitions = [ factory.make_Partition(partition_table=factory.make_PartitionTable( block_device=factory.make_PhysicalBlockDevice(node=node))) for _ in range(3) ] partitions_ids = [partition.id for partition in partitions] partition_filesystems = [ factory.make_Filesystem(fstype=FILESYSTEM_TYPE.LVM_PV, partition=partition) for partition in partitions ] volume_group = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, filesystems=bd_filesystems + partition_filesystems, ) logical_volume_ids = [ factory.make_VirtualBlockDevice(filesystem_group=volume_group, size=bd.size).id for bd in block_devices ] uri = get_volume_group_uri(volume_group) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_volume_group = json.loads( response.content.decode(settings.DEFAULT_CHARSET)) parsed_device_ids = [ device["id"] for device in parsed_volume_group["devices"] ] parsed_logical_volume_ids = [ lv["id"] for lv in parsed_volume_group["logical_volumes"] ] self.assertThat( parsed_volume_group, ContainsDict({ "id": Equals(volume_group.id), "uuid": Equals(volume_group.uuid), "name": Equals(volume_group.name), "size": Equals(volume_group.get_size()), "human_size": Equals(human_readable_bytes(volume_group.get_size())), "available_size": Equals(volume_group.get_lvm_free_space()), "human_available_size": Equals(human_readable_bytes( volume_group.get_lvm_free_space())), "used_size": Equals(volume_group.get_lvm_allocated_size()), "human_used_size": Equals( human_readable_bytes( volume_group.get_lvm_allocated_size())), "resource_uri": Equals(get_volume_group_uri(volume_group, test_plural=False)), "system_id": Equals(node.system_id), }), ) self.assertItemsEqual(block_device_ids + partitions_ids, parsed_device_ids) self.assertItemsEqual(logical_volume_ids, parsed_logical_volume_ids)
def test_get_cache_set_for_block_device(self): block_device = factory.make_PhysicalBlockDevice() cache_set = factory.make_CacheSet(block_device=block_device) self.assertEqual( cache_set, CacheSet.objects.get_cache_set_for_block_device(block_device))
def test_get_or_create_cache_set_for_block_device_creates_new(self): block_device = factory.make_PhysicalBlockDevice() cache_set = CacheSet.objects.get_or_create_cache_set_for_block_device( block_device) self.assertEqual(block_device, cache_set.get_device())
def test_get_device(self): block_device = factory.make_PhysicalBlockDevice() cache_set = factory.make_CacheSet(block_device=block_device) self.assertEqual(block_device, cache_set.get_device())
def test_get_filesystem(self): block_device = factory.make_PhysicalBlockDevice() cache_set = factory.make_CacheSet(block_device=block_device) self.assertEqual(block_device.get_effective_filesystem(), cache_set.get_filesystem())
def test_save_sets_table_type_to_mbr_for_boot_when_type_miss_match(self): node = factory.make_Node(with_boot_disk=False, bios_boot_method="pxe") boot_disk = factory.make_PhysicalBlockDevice(node=node) partition_table = factory.make_PartitionTable( block_device=BlockDevice.objects.get(id=boot_disk.id)) self.assertEqual(PARTITION_TABLE_TYPE.MBR, partition_table.table_type)
def test_clears_all_objects(self): node = factory.make_Node() physical_block_devices = [ factory.make_PhysicalBlockDevice(node=node, size=10 * 1000**3) for _ in range(3) ] filesystem = factory.make_Filesystem( block_device=physical_block_devices[0]) partition_table = factory.make_PartitionTable( block_device=physical_block_devices[1]) partition = factory.make_Partition(partition_table=partition_table) fslvm = factory.make_Filesystem( block_device=physical_block_devices[2], fstype=FILESYSTEM_TYPE.LVM_PV, ) vgroup = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, filesystems=[fslvm]) vbd1 = factory.make_VirtualBlockDevice(filesystem_group=vgroup, size=2 * 1000**3) vbd2 = factory.make_VirtualBlockDevice(filesystem_group=vgroup, size=3 * 1000**3) filesystem_on_vbd1 = factory.make_Filesystem( block_device=vbd1, fstype=FILESYSTEM_TYPE.LVM_PV) vgroup_on_vgroup = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, filesystems=[filesystem_on_vbd1], ) vbd3_on_vbd1 = factory.make_VirtualBlockDevice( filesystem_group=vgroup_on_vgroup, size=1 * 1000**3) clear_full_storage_configuration( node, PhysicalBlockDevice=PhysicalBlockDevice, VirtualBlockDevice=VirtualBlockDevice, PartitionTable=PartitionTable, Filesystem=Filesystem, FilesystemGroup=FilesystemGroup, ) for pbd in physical_block_devices: self.expectThat( reload_object(pbd), Not(Is(None)), "Physical block device should not have been deleted.", ) self.expectThat( reload_object(filesystem), Is(None), "Filesystem should have been removed.", ) self.expectThat( reload_object(partition_table), Is(None), "PartitionTable should have been removed.", ) self.expectThat( reload_object(partition), Is(None), "Partition should have been removed.", ) self.expectThat( reload_object(fslvm), Is(None), "LVM PV Filesystem should have been removed.", ) self.expectThat( reload_object(vgroup), Is(None), "Volume group should have been removed.", ) self.expectThat( reload_object(vbd1), Is(None), "Virtual block device should have been removed.", ) self.expectThat( reload_object(vbd2), Is(None), "Virtual block device should have been removed.", ) self.expectThat( reload_object(filesystem_on_vbd1), Is(None), "Filesystem on virtual block device should have been removed.", ) self.expectThat( reload_object(vgroup_on_vgroup), Is(None), "Volume group on virtual block device should have been removed.", ) self.expectThat( reload_object(vbd3_on_vbd1), Is(None), "Virtual block device on another virtual block device should have " "been removed.", )
def test_create_partition_if_boot_disk_returns_None_if_not_boot_disk(self): node = factory.make_Node() not_boot_disk = factory.make_PhysicalBlockDevice(node=node) self.assertIsNone(not_boot_disk.create_partition_if_boot_disk())
def populate_main(): """Populate the main data all in one transaction.""" admin = factory.make_admin(username="******", password="******", completed_intro=False) # noqa user1, _ = factory.make_user_with_keys(username="******", password="******", completed_intro=False) user2, _ = factory.make_user_with_keys(username="******", password="******", completed_intro=False) # Physical zones. zones = [ factory.make_Zone(name="zone-north"), factory.make_Zone(name="zone-south"), ] # DNS domains. domains = [ Domain.objects.get_default_domain(), factory.make_Domain("sample"), factory.make_Domain("ubnt"), ] # Create the fabrics that will be used by the regions, racks, # machines, and devices. fabric0 = Fabric.objects.get_default_fabric() fabric0_untagged = fabric0.get_default_vlan() fabric0_vlan10 = factory.make_VLAN(fabric=fabric0, vid=10) fabric1 = factory.make_Fabric() fabric1_untagged = fabric1.get_default_vlan() fabric1_vlan42 = factory.make_VLAN(fabric=fabric1, vid=42) empty_fabric = factory.make_Fabric() # noqa # Create some spaces. space_mgmt = factory.make_Space("management") space_storage = factory.make_Space("storage") space_internal = factory.make_Space("internal") space_ipv6_testbed = factory.make_Space("ipv6-testbed") # Subnets used by regions, racks, machines, and devices. subnet_1 = factory.make_Subnet( cidr="172.16.1.0/24", gateway_ip="172.16.1.1", vlan=fabric0_untagged, space=space_mgmt, ) subnet_2 = factory.make_Subnet( cidr="172.16.2.0/24", gateway_ip="172.16.2.1", vlan=fabric1_untagged, space=space_mgmt, ) subnet_3 = factory.make_Subnet( cidr="172.16.3.0/24", gateway_ip="172.16.3.1", vlan=fabric0_vlan10, space=space_storage, ) subnet_4 = factory.make_Subnet( # noqa cidr="172.16.4.0/24", gateway_ip="172.16.4.1", vlan=fabric0_vlan10, space=space_internal, ) subnet_2001_db8_42 = factory.make_Subnet( # noqa cidr="2001:db8:42::/64", gateway_ip="", vlan=fabric1_vlan42, space=space_ipv6_testbed, ) ipv4_subnets = [subnet_1, subnet_2, subnet_3, subnet_4] # Static routes on subnets. factory.make_StaticRoute(source=subnet_1, destination=subnet_2) factory.make_StaticRoute(source=subnet_1, destination=subnet_3) factory.make_StaticRoute(source=subnet_1, destination=subnet_4) factory.make_StaticRoute(source=subnet_2, destination=subnet_1) factory.make_StaticRoute(source=subnet_2, destination=subnet_3) factory.make_StaticRoute(source=subnet_2, destination=subnet_4) factory.make_StaticRoute(source=subnet_3, destination=subnet_1) factory.make_StaticRoute(source=subnet_3, destination=subnet_2) factory.make_StaticRoute(source=subnet_3, destination=subnet_4) factory.make_StaticRoute(source=subnet_4, destination=subnet_1) factory.make_StaticRoute(source=subnet_4, destination=subnet_2) factory.make_StaticRoute(source=subnet_4, destination=subnet_3) # Load builtin scripts in the database so we can generate fake results # below. load_builtin_scripts() hostname = gethostname() region_rack = get_one( Node.objects.filter(node_type=NODE_TYPE.REGION_AND_RACK_CONTROLLER, hostname=hostname)) # If "make run" executes before "make sampledata", the rack may have # already registered. if region_rack is None: region_rack = factory.make_Node( node_type=NODE_TYPE.REGION_AND_RACK_CONTROLLER, hostname=hostname, interface=False, ) # Get list of mac addresses that should be used for the region # rack controller. This will make sure the RegionAdvertisingService # picks the correct region on first start-up and doesn't get multiple. mac_addresses = get_mac_addresses() def get_next_mac(): try: return mac_addresses.pop() except IndexError: return factory.make_mac_address() # Region and rack controller (hostname of dev machine) # eth0 - fabric 0 - untagged # eth1 - fabric 0 - untagged # eth2 - fabric 1 - untagged - 172.16.2.2/24 - static # bond0 - fabric 0 - untagged - 172.16.1.2/24 - static # bond0.10 - fabric 0 - 10 - 172.16.3.2/24 - static eth0 = factory.make_Interface( INTERFACE_TYPE.PHYSICAL, name="eth0", node=region_rack, vlan=fabric0_untagged, mac_address=get_next_mac(), ) eth1 = factory.make_Interface( INTERFACE_TYPE.PHYSICAL, name="eth1", node=region_rack, vlan=fabric0_untagged, mac_address=get_next_mac(), ) eth2 = factory.make_Interface( INTERFACE_TYPE.PHYSICAL, name="eth2", node=region_rack, vlan=fabric1_untagged, mac_address=get_next_mac(), ) bond0 = factory.make_Interface( INTERFACE_TYPE.BOND, name="bond0", node=region_rack, vlan=fabric0_untagged, parents=[eth0, eth1], mac_address=eth0.mac_address, ) bond0_10 = factory.make_Interface( INTERFACE_TYPE.VLAN, node=region_rack, vlan=fabric0_vlan10, parents=[bond0], ) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip="172.16.1.2", subnet=subnet_1, interface=bond0, ) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip="172.16.2.2", subnet=subnet_2, interface=eth2, ) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip="172.16.3.2", subnet=subnet_3, interface=bond0_10, ) fabric0_untagged.primary_rack = region_rack fabric0_untagged.save() fabric1_untagged.primary_rack = region_rack fabric1_untagged.save() fabric0_vlan10.primary_rack = region_rack fabric0_vlan10.save() # Rack controller (happy-rack) # eth0 - fabric 0 - untagged # eth1 - fabric 0 - untagged # eth2 - fabric 1 - untagged - 172.16.2.3/24 - static # bond0 - fabric 0 - untagged - 172.16.1.3/24 - static # bond0.10 - fabric 0 - 10 - 172.16.3.3/24 - static rack = factory.make_Node( node_type=NODE_TYPE.RACK_CONTROLLER, hostname="happy-rack", interface=False, ) eth0 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, name="eth0", node=rack, vlan=fabric0_untagged) eth1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, name="eth1", node=rack, vlan=fabric0_untagged) eth2 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, name="eth2", node=rack, vlan=fabric1_untagged) bond0 = factory.make_Interface( INTERFACE_TYPE.BOND, name="bond0", node=rack, vlan=fabric0_untagged, parents=[eth0, eth1], ) bond0_10 = factory.make_Interface(INTERFACE_TYPE.VLAN, node=rack, vlan=fabric0_vlan10, parents=[bond0]) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip="172.16.1.3", subnet=subnet_1, interface=bond0, ) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip="172.16.2.3", subnet=subnet_2, interface=eth2, ) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip="172.16.3.3", subnet=subnet_3, interface=bond0_10, ) fabric0_untagged.secondary_rack = rack fabric0_untagged.save() fabric1_untagged.secondary_rack = rack fabric1_untagged.save() fabric0_vlan10.secondary_rack = rack fabric0_vlan10.save() # Region controller (happy-region) # eth0 - fabric 0 - untagged # eth1 - fabric 0 - untagged # eth2 - fabric 1 - untagged - 172.16.2.4/24 - static # bond0 - fabric 0 - untagged - 172.16.1.4/24 - static # bond0.10 - fabric 0 - 10 - 172.16.3.4/24 - static region = factory.make_Node( node_type=NODE_TYPE.REGION_CONTROLLER, hostname="happy-region", interface=False, ) eth0 = factory.make_Interface( INTERFACE_TYPE.PHYSICAL, name="eth0", node=region, vlan=fabric0_untagged, ) eth1 = factory.make_Interface( INTERFACE_TYPE.PHYSICAL, name="eth1", node=region, vlan=fabric0_untagged, ) eth2 = factory.make_Interface( INTERFACE_TYPE.PHYSICAL, name="eth2", node=region, vlan=fabric1_untagged, ) bond0 = factory.make_Interface( INTERFACE_TYPE.BOND, name="bond0", node=region, vlan=fabric0_untagged, parents=[eth0, eth1], ) bond0_10 = factory.make_Interface(INTERFACE_TYPE.VLAN, node=region, vlan=fabric0_vlan10, parents=[bond0]) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip="172.16.1.4", subnet=subnet_1, interface=bond0, ) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip="172.16.2.4", subnet=subnet_2, interface=eth2, ) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip="172.16.3.4", subnet=subnet_3, interface=bond0_10, ) # Create one machine for every status. Each machine has a random interface # and storage configration. node_statuses = [ status for status in map_enum(NODE_STATUS).items() if status not in [NODE_STATUS.MISSING, NODE_STATUS.RESERVED, NODE_STATUS.RETIRED] ] machines = [] test_scripts = [ script.name for script in Script.objects.filter(script_type=SCRIPT_TYPE.TESTING) ] for _, status in node_statuses: owner = None if status in ALLOCATED_NODE_STATUSES: owner = random.choice([admin, user1, user2]) elif status in [ NODE_STATUS.COMMISSIONING, NODE_STATUS.FAILED_RELEASING, ]: owner = admin machine = factory.make_Node( status=status, owner=owner, zone=random.choice(zones), interface=False, with_boot_disk=False, power_type="manual", domain=random.choice(domains), memory=random.choice([1024, 4096, 8192]), description=random.choice([ "", "Scheduled for removeal", "Firmware old", "Earmarked for Project Fuse in April", ]), cpu_count=random.randint(2, 8), ) machine.set_random_hostname() machines.append(machine) # Create random network configuration. RandomInterfaceFactory.create_random(machine) # Add random storage devices and set a random layout. for _ in range(random.randint(1, 5)): factory.make_PhysicalBlockDevice( node=machine, size=random.randint(LARGE_BLOCK_DEVICE, LARGE_BLOCK_DEVICE * 10), ) if status in [ NODE_STATUS.READY, NODE_STATUS.ALLOCATED, NODE_STATUS.DEPLOYING, NODE_STATUS.DEPLOYED, NODE_STATUS.FAILED_DEPLOYMENT, NODE_STATUS.RELEASING, NODE_STATUS.FAILED_RELEASING, ]: machine.set_storage_layout( random.choice([ layout for layout in STORAGE_LAYOUTS.keys() if layout != "vmfs6" ])) if status != NODE_STATUS.READY: machine._create_acquired_filesystems() # Add a random amount of events. for _ in range(random.randint(25, 100)): factory.make_Event(node=machine) # Add in commissioning and testing results. if status != NODE_STATUS.NEW: for _ in range(0, random.randint(1, 10)): css = ScriptSet.objects.create_commissioning_script_set( machine) scripts = set() for __ in range(1, len(test_scripts)): scripts.add(random.choice(test_scripts)) tss = ScriptSet.objects.create_testing_script_set( machine, list(scripts)) machine.current_commissioning_script_set = css machine.current_testing_script_set = tss machine.save() # Fill in historic results for script_set in machine.scriptset_set.all(): if script_set in [css, tss]: continue for script_result in script_set: # Can't use script_result.store_result as it will try to # process the result and fail on the fake data. script_result.exit_status = random.randint(0, 255) if script_result.exit_status == 0: script_result.status = SCRIPT_STATUS.PASSED else: script_result.status = random.choice( list(SCRIPT_STATUS_FAILED)) script_result.started = factory.make_date() script_result.ended = script_result.started + timedelta( seconds=random.randint(0, 10000)) script_result.stdout = Bin( factory.make_string().encode("utf-8")) script_result.stderr = Bin( factory.make_string().encode("utf-8")) script_result.output = Bin( factory.make_string().encode("utf-8")) script_result.save() # Only add in results in states where commissiong should be completed. if status not in [NODE_STATUS.NEW, NODE_STATUS.COMMISSIONING]: if status == NODE_STATUS.FAILED_COMMISSIONING: exit_status = random.randint(1, 255) script_status = random.choice(list(SCRIPT_STATUS_FAILED)) else: exit_status = 0 script_status = SCRIPT_STATUS.PASSED for script_result in css: # Can't use script_result.store_result as it will try to # process the result and fail on the fake data. script_result.status = script_status script_result.exit_status = exit_status script_result.started = factory.make_date() script_result.ended = script_result.started + timedelta( seconds=random.randint(0, 10000)) script_result.stdout = Bin( factory.make_string().encode("utf-8")) script_result.stderr = Bin( factory.make_string().encode("utf-8")) script_result.output = Bin( factory.make_string().encode("utf-8")) script_result.save() elif status == NODE_STATUS.COMMISSIONING: for script_result in css: script_result.status = random.choice( list(SCRIPT_STATUS_RUNNING_OR_PENDING)) if script_result.status != SCRIPT_STATUS.PENDING: script_result.started = factory.make_date() script_result.save() # Only add in results in states where testing should be completed. if status not in [NODE_STATUS.NEW, NODE_STATUS.TESTING]: if status == NODE_STATUS.FAILED_TESTING: exit_status = random.randint(1, 255) script_status = random.choice(list(SCRIPT_STATUS_FAILED)) else: exit_status = 0 script_status = SCRIPT_STATUS.PASSED for script_result in tss: # Can't use script_result.store_result as it will try to # process the result and fail on the fake data. script_result.status = script_status script_result.exit_status = exit_status script_result.started = factory.make_date() script_result.ended = script_result.started + timedelta( seconds=random.randint(0, 10000)) script_result.stdout = Bin( factory.make_string().encode("utf-8")) script_result.stderr = Bin( factory.make_string().encode("utf-8")) script_result.output = Bin( factory.make_string().encode("utf-8")) script_result.save() elif status == NODE_STATUS.TESTING: for script_result in tss: script_result.status = random.choice( list(SCRIPT_STATUS_RUNNING_OR_PENDING)) if script_result.status != SCRIPT_STATUS.PENDING: script_result.started = factory.make_date() script_result.save() # Add installation results. if status in [ NODE_STATUS.DEPLOYING, NODE_STATUS.DEPLOYED, NODE_STATUS.FAILED_DEPLOYMENT, ]: script_set = ScriptSet.objects.create_installation_script_set( machine) machine.current_installation_script_set = script_set machine.save() if status == NODE_STATUS.DEPLOYED: for script_result in machine.current_installation_script_set: stdout = factory.make_string().encode("utf-8") script_result.store_result(0, stdout) elif status == NODE_STATUS.FAILED_DEPLOYMENT: for script_result in machine.current_installation_script_set: exit_status = random.randint(1, 255) stdout = factory.make_string().encode("utf-8") stderr = factory.make_string().encode("utf-8") script_result.store_result(exit_status, stdout, stderr) # Add children devices to the deployed machine. if status == NODE_STATUS.DEPLOYED: boot_interface = machine.get_boot_interface() for _ in range(5): device = factory.make_Device( interface=True, domain=machine.domain, parent=machine, vlan=boot_interface.vlan, ) device.set_random_hostname() RandomInterfaceFactory.assign_ip( device.get_boot_interface(), alloc_type=IPADDRESS_TYPE.STICKY, ) # Create a few pods to and assign a random set of the machines to the pods. pods = [None] pod_storage_pools = defaultdict(list) machines_in_pods = defaultdict(list) for _ in range(3): subnet = random.choice(ipv4_subnets) ip = factory.pick_ip_in_Subnet(subnet) ip_address = factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip=ip, subnet=subnet) power_address = "qemu+ssh://ubuntu@%s/system" % ip pod = factory.make_Pod( pod_type="virsh", parameters={"power_address": power_address}, ip_address=ip_address, capabilities=[ Capabilities.DYNAMIC_LOCAL_STORAGE, Capabilities.COMPOSABLE, ], ) for _ in range(3): pool = factory.make_PodStoragePool(pod) pod_storage_pools[pod].append(pool) pod.default_storage_pool = pool pod.save() pods.append(pod) for _ in range(3): subnet = random.choice(ipv4_subnets) ip = factory.pick_ip_in_Subnet(subnet) ip_address = factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, ip=ip, subnet=subnet) power_address = "%s" % ip pod = factory.make_Pod( pod_type="rsd", parameters={ "power_address": power_address, "power_user": "******", "power_pass": "******", }, ip_address=ip_address, capabilities=[ Capabilities.DYNAMIC_LOCAL_STORAGE, Capabilities.COMPOSABLE, ], ) for _ in range(3): pool = factory.make_PodStoragePool(pod) pod_storage_pools[pod].append(pool) pod.default_storage_pool = pool pod.save() pods.append(pod) for machine in machines: # Add the machine to the pod if its lucky day! pod = random.choice(pods) if pod is not None: machine.bmc = pod machine.instance_power_parameters = {"power_id": machine.hostname} machine.save() machines_in_pods[pod].append(machine) # Assign the block devices on the machine to a storage pool. for block_device in machine.physicalblockdevice_set.all(): block_device.storage_pool = random.choice( pod_storage_pools[pod]) block_device.save() # Update the pod attributes so that it has more available then used. for pod in pods[1:]: pod.cores = pod.get_used_cores() + random.randint(4, 8) pod.memory = pod.get_used_memory() + random.choice( [1024, 2048, 4096, 4096 * 4, 4096 * 8]) pod.local_storage = sum(pool.storage for pool in pod_storage_pools[pod]) pod.save() # Create a few devices. for _ in range(10): device = factory.make_Device(interface=True) device.set_random_hostname() # Add some DHCP snippets. # - Global factory.make_DHCPSnippet( name="foo class", description="adds class for vender 'foo'", value=VersionedTextFile.objects.create(data=dedent("""\ class "foo" { match if substring ( option vendor-class-identifier, 0, 3) = "foo"; } """)), ) factory.make_DHCPSnippet( name="bar class", description="adds class for vender 'bar'", value=VersionedTextFile.objects.create(data=dedent("""\ class "bar" { match if substring ( option vendor-class-identifier, 0, 3) = "bar"; } """)), enabled=False, ) # - Subnet factory.make_DHCPSnippet( name="600 lease time", description="changes lease time to 600 secs.", value=VersionedTextFile.objects.create(data="default-lease-time 600;"), subnet=subnet_1, ) factory.make_DHCPSnippet( name="7200 max lease time", description="changes max lease time to 7200 secs.", value=VersionedTextFile.objects.create(data="max-lease-time 7200;"), subnet=subnet_2, enabled=False, ) # - Node factory.make_DHCPSnippet( name="boot from other server", description="instructs device to boot from other server", value=VersionedTextFile.objects.create(data=dedent("""\ filename "test-boot"; server-name "boot.from.me"; """)), node=device, ) # Add notifications for admins, users, and each individual user, and for # each notification category. factory.make_Notification( "Attention admins! Core critical! Meltdown imminent! Evacuate " "habitat immediately!", admins=True, category="error", ) factory.make_Notification( "Dear users, rumours of a core meltdown are unfounded. Please " "return to your home-pods and places of business.", users=True, category="warning", ) factory.make_Notification( "FREE! For the next 2 hours get FREE blueberry and iodine pellets " "at the nutri-dispensers.", users=True, category="success", ) for user in User.objects.all(): context = {"name": user.username.capitalize()} factory.make_Notification( "Greetings, {name}! Get away from the habitat for the weekend and " "visit the Mare Nubium with MAAS Tours. Use the code METAL to " "claim a special gift!", user=user, context=context, category="info", )
def test_update_invalid_numa_node(self): block_device = factory.make_PhysicalBlockDevice() form = UpdatePhysicalBlockDeviceForm(instance=block_device, data={"numa_node": 3}) self.assertFalse(form.is_valid()) self.assertEqual({"numa_node": ["Invalid NUMA node"]}, form.errors)
def test_path(self): block_device = factory.make_PhysicalBlockDevice() table = factory.make_PartitionTable(block_device=block_device) partition = factory.make_Partition(partition_table=table) self.assertEqual("%s-part1" % block_device.path, partition.path)
def test_requires_no_fields(self): block_device = factory.make_PhysicalBlockDevice() form = UpdateDeployedPhysicalBlockDeviceForm(instance=block_device, data={}) self.assertTrue(form.is_valid(), form.errors) self.assertItemsEqual([], form.errors.keys())
class TestMountFilesystemForm(MAASServerTestCase): scenarios = ( ( "partition", { "make_substrate": lambda: { "partition": factory.make_Partition() } }, ), ( "block-device", { "make_substrate": lambda: { "block_device": factory.make_PhysicalBlockDevice() } }, ), ) def test_requires_mount_point_when_fs_uses_mount_point(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem( fstype=FILESYSTEM_TYPE.EXT4, **substrate ) form = MountFilesystemForm(filesystem, data={}) self.assertTrue(filesystem.uses_mount_point) self.assertFalse(form.is_valid(), form.errors) self.assertItemsEqual(["mount_point"], form.errors.keys()) def test_ignores_mount_point_when_fs_does_not_use_mount_point(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem( fstype=FILESYSTEM_TYPE.SWAP, **substrate ) form = MountFilesystemForm(filesystem, data={}) self.assertFalse(filesystem.uses_mount_point) self.assertTrue(form.is_valid(), form.errors) def test_is_not_valid_if_invalid_absolute_path(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem( fstype=FILESYSTEM_TYPE.EXT4, **substrate ) data = {"mount_point": factory.make_absolute_path()[1:]} form = MountFilesystemForm(filesystem, data=data) self.assertFalse( form.is_valid(), "Should be invalid because it's not an absolute path.", ) self.assertEqual( {"mount_point": ["Enter a valid value."]}, form._errors ) def test_is_not_valid_if_absolute_path_empty(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem( fstype=FILESYSTEM_TYPE.EXT4, **substrate ) data = {"mount_point": ""} form = MountFilesystemForm(filesystem, data=data) self.assertFalse( form.is_valid(), "Should be invalid because its not an absolute path.", ) self.assertEqual( {"mount_point": ["This field is required."]}, form._errors ) def test_is_not_valid_if_invalid_absolute_path_too_long(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem( fstype=FILESYSTEM_TYPE.EXT4, **substrate ) mount_point = factory.make_absolute_path(directory_length=4096) data = {"mount_point": mount_point} form = MountFilesystemForm(filesystem, data=data) self.assertFalse( form.is_valid(), "Should be invalid because its not an absolute path.", ) self.assertEqual( { "mount_point": [ "Ensure this value has at most 4095 characters " "(it has %s)." % len(mount_point) ] }, form._errors, ) def test_is_not_valid_if_substrate_in_filesystem_group(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem( fstype=FILESYSTEM_TYPE.LVM_PV, **substrate ) factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, filesystems=[filesystem] ) data = {"mount_point": factory.make_absolute_path()} form = MountFilesystemForm(filesystem, data=data) self.assertFalse( form.is_valid(), "Should be invalid because block device is in a filesystem group.", ) self.assertEqual( { "__all__": [ "Filesystem is part of a filesystem group, and cannot be " "mounted." ] }, form._errors, ) def test_sets_mount_point_and_options_on_filesystem(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem( fstype=FILESYSTEM_TYPE.EXT4, **substrate ) self.assertThat(filesystem.is_mounted, Is(False)) mount_point = factory.make_absolute_path() mount_options = factory.make_name("options") data = { "mount_point": mount_point, # Whitespace is stripped by form validation. "mount_options": " " + mount_options + "\t\n", } form = MountFilesystemForm(filesystem, data=data) self.assertTrue(form.is_valid(), form._errors) form.save() self.assertEqual(mount_point, filesystem.mount_point) self.assertEqual(mount_options, filesystem.mount_options) self.assertThat(filesystem.is_mounted, Is(True)) def test_sets_mount_point_to_none_and_options_on_swap(self): substrate = self.make_substrate() filesystem = factory.make_Filesystem( fstype=FILESYSTEM_TYPE.SWAP, **substrate ) self.assertThat(filesystem.is_mounted, Is(False)) mount_options = factory.make_name("options") data = {"mount_options": mount_options} form = MountFilesystemForm(filesystem, data=data) self.assertTrue(form.is_valid(), form._errors) form.save() self.assertEqual("none", filesystem.mount_point) self.assertEqual(mount_options, filesystem.mount_options) self.assertThat(filesystem.is_mounted, Is(True))
def test_read(self): node = factory.make_Node(with_boot_disk=False) # Add three physical block devices physical_block_devices = [ factory.make_PhysicalBlockDevice(node=node, size=10 * 1000**3) for _ in range(3) ] # Partition and add a LVM_PV filesystem to the last two physical block # devices. Leave the first partition alone. lvm_pv_filesystems = [ factory.make_Filesystem(block_device=device, fstype=FILESYSTEM_TYPE.LVM_PV) for device in physical_block_devices[1:] ] # Make a filesystem_group (analogous to a volume group) on top of our # two lvm-pm filesystems. filesystem_group = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.LVM_VG, filesystems=lvm_pv_filesystems, ) # Make a VirtualBlockDevice on top of the filesystem group we just # made. virtual_block_device = factory.make_VirtualBlockDevice( filesystem_group=filesystem_group, size=10 * 1000**3) # Add some iSCSI block devices. iscsi_block_devices = [ factory.make_ISCSIBlockDevice(node=node, size=10 * 1000**3) for _ in range(3) ] uri = get_blockdevices_uri(node) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) devices = json_load_bytes(response.content) # We should have seven devices, three physical, one virtual, and # three iscsi. self.assertEqual(len(devices), 7) self.assertEqual(len([d for d in devices if d["type"] == "physical"]), 3) self.assertEqual(len([d for d in devices if d["type"] == "virtual"]), 1) self.assertEqual(len([d for d in devices if d["type"] == "iscsi"]), 3) # The IDs we expect and the IDs we got through the API should match. expected_device_ids = [ d.id for d in (physical_block_devices + [virtual_block_device] + iscsi_block_devices) ] result_device_ids = [d["id"] for d in devices] self.assertItemsEqual(expected_device_ids, result_device_ids) # Validate that every one has a resource_uri. for d in devices: self.expectThat( d, Contains("resource_uri"), "Device(%s:%s) is missing a resource_uri." % (d["type"], d["id"]), )
def test_get_parent_returns_block_device(self): block_device = factory.make_PhysicalBlockDevice() filesystem = factory.make_Filesystem(block_device=block_device) self.assertEqual(block_device, filesystem.get_parent())
def test_delete_returns_403_when_not_admin(self): block_device = factory.make_PhysicalBlockDevice() uri = get_blockdevice_uri(block_device) response = self.client.delete(uri) self.assertEqual(http.client.FORBIDDEN, response.status_code, response.content)
def test_get_block_size_returns_block_device_block_size(self): block_device = factory.make_PhysicalBlockDevice() fs = factory.make_Filesystem(block_device=block_device) self.assertEqual(fs.block_device.block_size, fs.get_block_size())
def test_save_sets_table_type_to_gpt_for_none_boot_disk(self): node = factory.make_Node(with_boot_disk=False, bios_boot_method="pxe") factory.make_PhysicalBlockDevice(node=node) other_disk = factory.make_PhysicalBlockDevice(node=node) partition_table = factory.make_PartitionTable(block_device=other_disk) self.assertEqual(PARTITION_TABLE_TYPE.GPT, partition_table.table_type)
def test_type_physical(self): block_device = factory.make_PhysicalBlockDevice() self.assertEqual("physical", block_device.type)
def test_class_start_commissioning_can_override_global_param(self): node = factory.make_Node(status=NODE_STATUS.READY) commissioning_bd = factory.make_PhysicalBlockDevice(node=node) testing_bd = factory.make_PhysicalBlockDevice(node=node) user = factory.make_admin() global_commissioning_script = factory.make_Script( script_type=SCRIPT_TYPE.COMMISSIONING, parameters={"storage": { "type": "storage" }}, ) commissioning_script = factory.make_Script( script_type=SCRIPT_TYPE.COMMISSIONING, parameters={"storage": { "type": "storage" }}, ) global_testing_script = factory.make_Script( script_type=SCRIPT_TYPE.TESTING, parameters={"storage": { "type": "storage" }}, ) testing_script = factory.make_Script( script_type=SCRIPT_TYPE.TESTING, parameters={"storage": { "type": "storage" }}, ) mock_start_commissioning = self.patch_autospec(node, "start_commissioning") commissioning_input = random.choice([ str(commissioning_bd.id), commissioning_bd.name, commissioning_bd.model, commissioning_bd.serial, "%s:%s" % (commissioning_bd.model, commissioning_bd.serial), ] + commissioning_bd.tags) testing_input = random.choice([ str(testing_bd.id), testing_bd.name, testing_bd.model, testing_bd.serial, "%s:%s" % (testing_bd.model, testing_bd.serial), ] + testing_bd.tags) form = CommissionForm( instance=node, user=user, data={ "commissioning_scripts": "%s,%s" % ( global_commissioning_script.name, commissioning_script.name, ), "testing_scripts": "%s,%s" % (global_testing_script.name, testing_script.name), "storage": "all", "%s_storage" % commissioning_script.name: commissioning_input, "%s_storage" % testing_script.name: testing_input, }, ) self.assertTrue(form.is_valid(), form.errors) node = form.save() self.assertIsNotNone(node) self.assertThat( mock_start_commissioning, MockCalledOnceWith( user, False, False, False, False, [global_commissioning_script.name, commissioning_script.name], [global_testing_script.name, testing_script.name], { global_commissioning_script.name: { "storage": "all" }, commissioning_script.name: { "storage": commissioning_input }, global_testing_script.name: { "storage": "all" }, testing_script.name: { "storage": testing_input }, }, ), )
def test_create_partition_raises_ValueError(self): disk = factory.make_PhysicalBlockDevice(node=factory.make_Node()) factory.make_PartitionTable(block_device=disk) with ExpectedException(ValueError): disk.create_partition()
def test_read(self): node = factory.make_Node() block_devices = [ factory.make_PhysicalBlockDevice(node=node) for _ in range(3) ] block_device_ids = [bd.id for bd in block_devices] bd_filesystems = [ factory.make_Filesystem(fstype=FILESYSTEM_TYPE.RAID, block_device=bd) for bd in block_devices ] spare_block_devices = [ factory.make_PhysicalBlockDevice(node=node) for _ in range(3) ] spare_block_device_ids = [bd.id for bd in spare_block_devices] spare_bd_filesystems = [ factory.make_Filesystem(fstype=FILESYSTEM_TYPE.RAID_SPARE, block_device=bd) for bd in spare_block_devices ] partitions = [ factory.make_Partition(partition_table=factory.make_PartitionTable( block_device=factory.make_PhysicalBlockDevice(node=node))) for _ in range(3) ] partitions_ids = [partition.id for partition in partitions] partition_filesystems = [ factory.make_Filesystem(fstype=FILESYSTEM_TYPE.RAID, partition=partition) for partition in partitions ] spare_partitions = [ factory.make_Partition(partition_table=factory.make_PartitionTable( block_device=factory.make_PhysicalBlockDevice(node=node))) for _ in range(3) ] spare_partitions_ids = [partition.id for partition in spare_partitions] spare_partition_filesystems = [ factory.make_Filesystem(fstype=FILESYSTEM_TYPE.RAID_SPARE, partition=partition) for partition in spare_partitions ] raid = factory.make_FilesystemGroup( group_type=FILESYSTEM_GROUP_TYPE.RAID_5, filesystems=(bd_filesystems + spare_bd_filesystems + partition_filesystems + spare_partition_filesystems)) uri = get_raid_device_uri(raid) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_raid = json.loads( response.content.decode(settings.DEFAULT_CHARSET)) parsed_device_ids = [device["id"] for device in parsed_raid["devices"]] parsed_spare_device_ids = [ device["id"] for device in parsed_raid["spare_devices"] ] self.assertThat( parsed_raid, ContainsDict({ "id": Equals(raid.id), "uuid": Equals(raid.uuid), "name": Equals(raid.name), "level": Equals(raid.group_type), "size": Equals(raid.get_size()), "human_size": Equals(human_readable_bytes(raid.get_size())), "resource_uri": Equals(get_raid_device_uri(raid)), "system_id": Equals(node.system_id), })) self.assertItemsEqual(block_device_ids + partitions_ids, parsed_device_ids) self.assertItemsEqual(spare_block_device_ids + spare_partitions_ids, parsed_spare_device_ids) self.assertEqual(raid.virtual_device.id, parsed_raid["virtual_device"]["id"])