def get_pod_resources(self): """Get the pod resources.""" discovered_pod = DiscoveredPod(architectures=[], cores=0, cpu_speed=0, memory=0, local_storage=0, hints=DiscoveredPodHints( cores=0, cpu_speed=0, memory=0, local_storage=0)) discovered_pod.architectures = [self.get_pod_arch()] discovered_pod.capabilities = [ Capabilities.COMPOSABLE, Capabilities.DYNAMIC_LOCAL_STORAGE, Capabilities.OVER_COMMIT, Capabilities.STORAGE_POOLS, ] discovered_pod.cores = self.get_pod_cpu_count() discovered_pod.cpu_speed = self.get_pod_cpu_speed() discovered_pod.memory = self.get_pod_memory() discovered_pod.storage_pools = self.get_pod_storage_pools() discovered_pod.local_storage = sum( pool.storage for pool in discovered_pod.storage_pools) return discovered_pod
def fake_pod_discovery(self): discovered_pod = DiscoveredPod( architectures=["amd64/generic"], cores=random.randint(2, 4), memory=random.randint(1024, 4096), local_storage=random.randint(1024, 1024 * 1024), cpu_speed=random.randint(2048, 4048), hints=DiscoveredPodHints( cores=random.randint(2, 4), memory=random.randint(1024, 4096), local_storage=random.randint(1024, 1024 * 1024), cpu_speed=random.randint(2048, 4048), ), ) discovered_rack_1 = factory.make_RackController() discovered_rack_2 = factory.make_RackController() failed_rack = factory.make_RackController() self.patch(pods, "discover_pod").return_value = succeed(( { discovered_rack_1.system_id: discovered_pod, discovered_rack_2.system_id: discovered_pod, }, { failed_rack.system_id: factory.make_exception() }, ))
def test__calls_DiscoverPod_on_all_clients(self): rack_ids = [factory.make_name("system_id") for _ in range(3)] pod = DiscoveredPod( architectures=["amd64/generic"], cores=random.randint(1, 8), cpu_speed=random.randint(1000, 3000), memory=random.randint(1024, 4096), local_storage=random.randint(500, 1000), hints=DiscoveredPodHints( cores=random.randint(1, 8), cpu_speed=random.randint(1000, 3000), memory=random.randint(1024, 4096), local_storage=random.randint(500, 1000), ), ) clients = [] for rack_id in rack_ids: client = Mock() client.ident = rack_id client.return_value = succeed({"pod": pod}) clients.append(client) self.patch(pods_module, "getAllClients").return_value = clients discovered = yield discover_pod(factory.make_name("pod"), {}) self.assertEquals(({rack_id: pod for rack_id in rack_ids}, {}), discovered)
def fake_pod_discovery(self): discovered_pod = DiscoveredPod( architectures=['amd64/generic'], cores=random.randint(2, 4), memory=random.randint(1024, 4096), local_storage=random.randint(1024, 1024 * 1024), cpu_speed=random.randint(2048, 4048), hints=DiscoveredPodHints( cores=random.randint(2, 4), memory=random.randint(1024, 4096), local_storage=random.randint(1024, 1024 * 1024), cpu_speed=random.randint(2048, 4048)), storage_pools=[ DiscoveredPodStoragePool( id=factory.make_name('pool_id'), name=factory.make_name('name'), type=factory.make_name('type'), path='/var/lib/path/%s' % factory.make_name('path'), storage=random.randint(1024, 1024 * 1024), ) for _ in range(3) ]) discovered_rack_1 = factory.make_RackController() discovered_rack_2 = factory.make_RackController() failed_rack = factory.make_RackController() self.patch(pods_module, "discover_pod").return_value = ({ discovered_rack_1.system_id: discovered_pod, discovered_rack_2.system_id: discovered_pod, }, { failed_rack.system_id: factory.make_exception(), }) return ( discovered_pod, [discovered_rack_1, discovered_rack_2], [failed_rack])
def test_returns_discovered_pod_and_errors(self): pod_type = factory.make_name("pod") pod = DiscoveredPod( architectures=["amd64/generic"], cores=random.randint(1, 8), cpu_speed=random.randint(1000, 3000), memory=random.randint(1024, 4096), local_storage=random.randint(500, 1000), hints=DiscoveredPodHints( cores=random.randint(1, 8), cpu_speed=random.randint(1000, 3000), memory=random.randint(1024, 4096), local_storage=random.randint(500, 1000), ), ) clients = [] client = Mock() error_rack_id = factory.make_name("system_id") client.ident = error_rack_id exception = UnknownPodType(pod_type) client.return_value = fail(exception) clients.append(client) valid_rack_id = factory.make_name("system_id") client = Mock() client.ident = valid_rack_id client.return_value = succeed({"pod": pod}) clients.append(client) self.patch(pods_module, "getAllClients").return_value = clients discovered = yield discover_pod(pod_type, {}) self.assertEqual( ({valid_rack_id: pod}, {error_rack_id: exception}), discovered )
def discover(self, pod_id, context): """Discover all Pod host resources.""" client = yield self.get_client(pod_id, context) if not client.has_api_extension("virtual-machines"): raise LXDError( "Please upgrade your LXD host to 3.19+ for virtual machine support." ) resources = yield deferToThread(lambda: client.resources) mac_addresses = [] for card in resources["network"]["cards"]: for port in card["ports"]: mac_addresses.append(port["address"]) # After the region creates the Pod object it will sync LXD commissioning # data for all hardware information. return DiscoveredPod( architectures=[ kernel_to_debian_architecture(arch) for arch in client.host_info["environment"]["architectures"] ], name=client.host_info["environment"]["server_name"], mac_addresses=mac_addresses, capabilities=[ Capabilities.COMPOSABLE, Capabilities.DYNAMIC_LOCAL_STORAGE, Capabilities.OVER_COMMIT, Capabilities.STORAGE_POOLS, ], )
class TestDiscoveredPod(MAASTestCase): example = DiscoveredPod( architectures=['amd64/generic'], cores=random.randint(1, 8), cpu_speed=random.randint(1000, 3000), memory=random.randint(1024, 8192), local_storage=0, hints=DiscoveredPodHints( cores=random.randint(1, 8), cpu_speed=random.randint(1000, 2000), memory=random.randint(1024, 8192), local_storage=0), machines=[]) def test_round_trip(self): argument = arguments.AmpDiscoveredPod() encoded = argument.toString(self.example) self.assertThat(encoded, IsInstance(bytes)) decoded = argument.fromString(encoded) self.assertThat(decoded, Equals(self.example))
def test_handles_driver_resolving_to_DiscoveredPod(self): fake_driver = MagicMock() fake_driver.name = factory.make_name("pod") discovered_pod = DiscoveredPod( architectures=['amd64/generic'], cores=random.randint(1, 8), cpu_speed=random.randint(1000, 3000), memory=random.randint(1024, 8192), local_storage=0, hints=DiscoveredPodHints(cores=random.randint(1, 8), cpu_speed=random.randint(1000, 2000), memory=random.randint(1024, 8192), local_storage=0), machines=[]) fake_driver.discover.return_value = succeed(discovered_pod) self.patch(PodDriverRegistry, "get_item").return_value = fake_driver result = yield pods.discover_pod(fake_driver.name, {}) self.assertEquals({ "pod": discovered_pod, }, result)
def test_pod_fromdict(self): hostname = factory.make_name("hostname") cores = random.randint(1, 8) cpu_speed = random.randint(1000, 2000) memory = random.randint(4096, 8192) local_storage = random.randint(4096, 8192) iscsi_storage = random.randint(4096, 8192) hints = dict( cores=random.randint(1, 8), cpu_speed=random.randint(1000, 2000), memory=random.randint(4096, 8192), local_storage=random.randint(4096, 8192), iscsi_storage=random.randint(4096, 8192), ) machines_data = [] for _ in range(3): cores = random.randint(1, 8) cpu_speed = random.randint(1000, 2000) memory = random.randint(4096, 8192) interfaces = [ dict(mac_address=factory.make_mac_address()) for _ in range(3) ] block_devices = [ dict( model=factory.make_name("model"), serial=factory.make_name("serial"), size=random.randint(512, 1024), ) for _ in range(3) ] for _ in range(3): block_devices.append( dict( model=None, serial=None, size=random.randint(512, 1024), type=BlockDeviceType.ISCSI, iscsi_target=self.make_iscsi_target(), )) machines_data.append( dict( hostname=hostname, architecture="amd64/generic", cores=cores, cpu_speed=cpu_speed, memory=memory, interfaces=interfaces, block_devices=block_devices, )) pod_data = dict( architectures=["amd64/generic"], cores=cores, cpu_speed=cpu_speed, memory=memory, local_storage=local_storage, iscsi_storage=iscsi_storage, hints=hints, machines=machines_data, ) pod = DiscoveredPod.fromdict(pod_data) self.assertThat(pod, IsInstance(DiscoveredPod)) self.assertThat( pod, MatchesStructure( architectures=Equals(["amd64/generic"]), cores=Equals(cores), cpu_speed=Equals(cpu_speed), memory=Equals(memory), local_storage=Equals(local_storage), iscsi_storage=Equals(iscsi_storage), hints=MatchesAll( IsInstance(DiscoveredPodHints), MatchesStructure( cores=Equals(hints["cores"]), cpu_speed=Equals(hints["cpu_speed"]), memory=Equals(hints["memory"]), local_storage=Equals(hints["local_storage"]), iscsi_storage=Equals(hints["iscsi_storage"]), ), ), machines=MatchesListwise([ MatchesAll( IsInstance(DiscoveredMachine), MatchesStructure( architecture=Equals("amd64/generic"), cores=Equals(machine["cores"]), cpu_speed=Equals(machine["cpu_speed"]), memory=Equals(machine["memory"]), interfaces=MatchesListwise([ MatchesAll( IsInstance(DiscoveredMachineInterface), MatchesStructure( mac_address=Equals( interface["mac_address"]), vid=Equals(-1), tags=Equals([]), ), ) for interface in machine["interfaces"] ]), block_devices=MatchesListwise([ MatchesAll( IsInstance(DiscoveredMachineBlockDevice), MatchesStructure( model=Equals(block_device["model"]), serial=Equals(block_device["serial"]), size=Equals(block_device["size"]), block_size=Equals(512), tags=Equals([]), type=Equals(BlockDeviceType.PHYSICAL), ), ) for block_device in machine["block_devices"] if "type" not in block_device ] + [ MatchesAll( IsInstance(DiscoveredMachineBlockDevice), MatchesStructure( model=Is(None), serial=Is(None), size=Equals(block_device["size"]), block_size=Equals(512), tags=Equals([]), type=Equals(BlockDeviceType.ISCSI), iscsi_target=Equals( block_device["iscsi_target"]), ), ) for block_device in machine["block_devices"] if "type" in block_device ]), ), ) for machine in machines_data ]), ), )
def test_pod_asdict(self): hostname = factory.make_name("hostname") cores = random.randint(1, 8) cpu_speed = random.randint(1000, 2000) memory = random.randint(4096, 8192) local_storage = random.randint(4096, 8192) local_disks = random.randint(1, 8) iscsi_storage = random.randint(4096, 8192) hints = DiscoveredPodHints( cores=random.randint(1, 8), cpu_speed=random.randint(1000, 2000), memory=random.randint(4096, 8192), local_storage=random.randint(4096, 8192), local_disks=random.randint(1, 8), iscsi_storage=random.randint(4096, 8192), ) machines = [] tags = [factory.make_name("tag") for _ in range(3)] storage_pools = [ DiscoveredPodStoragePool( id=factory.make_name("id"), name=factory.make_name("name"), storage=random.randint(4096, 8192), type="dir", path="/var/%s" % factory.make_name("dir"), ) for _ in range(3) ] for _ in range(3): cores = random.randint(1, 8) cpu_speed = random.randint(1000, 2000) memory = random.randint(4096, 8192) power_state = factory.make_name("unknown") power_parameters = {"power_id": factory.make_name("power_id")} interfaces = [ DiscoveredMachineInterface( mac_address=factory.make_mac_address()) for _ in range(3) ] block_devices = [ DiscoveredMachineBlockDevice( model=factory.make_name("model"), serial=factory.make_name("serial"), size=random.randint(512, 1024), id_path=factory.make_name("/dev/vda"), ) for _ in range(3) ] for _ in range(3): block_devices.append( DiscoveredMachineBlockDevice( model=None, serial=None, size=random.randint(512, 1024), type=BlockDeviceType.ISCSI, iscsi_target=self.make_iscsi_target(), storage_pool=factory.make_name("pool"), )) tags = [factory.make_name("tag") for _ in range(3)] machines.append( DiscoveredMachine( hostname=hostname, architecture="amd64/generic", cores=cores, cpu_speed=cpu_speed, memory=memory, power_state=power_state, power_parameters=power_parameters, interfaces=interfaces, block_devices=block_devices, tags=tags, )) pod = DiscoveredPod( architectures=["amd64/generic"], cores=cores, cpu_speed=cpu_speed, memory=memory, local_storage=local_storage, local_disks=local_disks, iscsi_storage=iscsi_storage, hints=hints, machines=machines, tags=tags, storage_pools=storage_pools, ) self.assertThat( pod.asdict(), MatchesDict({ "architectures": Equals(["amd64/generic"]), "name": Equals(None), "cores": Equals(cores), "cpu_speed": Equals(cpu_speed), "memory": Equals(memory), "local_storage": Equals(local_storage), "local_disks": Equals(local_disks), "iscsi_storage": Equals(iscsi_storage), "mac_addresses": Equals([]), "capabilities": Equals(pod.capabilities), "hints": MatchesDict({ "cores": Equals(hints.cores), "cpu_speed": Equals(hints.cpu_speed), "memory": Equals(hints.memory), "local_storage": Equals(hints.local_storage), "local_disks": Equals(hints.local_disks), "iscsi_storage": Equals(hints.iscsi_storage), }), "machines": MatchesListwise([ MatchesDict({ "hostname": Equals(machine.hostname), "architecture": Equals("amd64/generic"), "cores": Equals(machine.cores), "cpu_speed": Equals(machine.cpu_speed), "memory": Equals(machine.memory), "power_state": Equals(machine.power_state), "power_parameters": Equals(machine.power_parameters), "interfaces": MatchesListwise([ MatchesDict({ "mac_address": Equals(interface.mac_address), "vid": Equals(interface.vid), "tags": Equals(interface.tags), "boot": Equals(False), "attach_type": Is(None), "attach_name": Is(None), }) for interface in machine.interfaces ]), "block_devices": MatchesListwise([ MatchesDict({ "model": Equals(block_device.model), "serial": Equals(block_device.serial), "size": Equals(block_device.size), "block_size": Equals(block_device.block_size), "tags": Equals(block_device.tags), "id_path": Equals(block_device.id_path), "type": Equals(block_device.type), "iscsi_target": Equals(block_device.iscsi_target), "storage_pool": Equals(block_device.storage_pool), }) for block_device in machine.block_devices ]), "tags": Equals(machine.tags), }) for machine in machines ]), "tags": Equals(tags), "storage_pools": MatchesListwise([ MatchesDict({ "id": Equals(pool.id), "name": Equals(pool.name), "storage": Equals(pool.storage), "type": Equals(pool.type), "path": Equals(pool.path), }) for pool in storage_pools ]), }), )
def test_pod(self): hostname = factory.make_name("hostname") cores = random.randint(1, 8) cpu_speed = random.randint(1000, 2000) memory = random.randint(4096, 8192) local_storage = random.randint(4096, 8192) iscsi_storage = random.randint(4096, 8192) hints = DiscoveredPodHints( cores=random.randint(1, 8), cpu_speed=random.randint(1000, 2000), memory=random.randint(4096, 8192), local_storage=random.randint(4096, 8192), iscsi_storage=random.randint(4096, 8192), ) machines = [] for _ in range(3): cores = random.randint(1, 8) cpu_speed = random.randint(1000, 2000) memory = random.randint(4096, 8192) power_state = factory.make_name("unknown") power_parameters = {"power_id": factory.make_name("power_id")} interfaces = [ DiscoveredMachineInterface( mac_address=factory.make_mac_address()) for _ in range(3) ] block_devices = [ DiscoveredMachineBlockDevice( model=factory.make_name("model"), serial=factory.make_name("serial"), size=random.randint(512, 1024), ) for _ in range(3) ] for _ in range(3): block_devices.append( DiscoveredMachineBlockDevice( model=None, serial=None, size=random.randint(512, 1024), type=BlockDeviceType.ISCSI, iscsi_target=self.make_iscsi_target(), )) tags = [factory.make_name("tag") for _ in range(3)] machines.append( DiscoveredMachine( hostname=hostname, architecture="amd64/generic", cores=cores, cpu_speed=cpu_speed, memory=memory, power_state=power_state, power_parameters=power_parameters, interfaces=interfaces, block_devices=block_devices, tags=tags, )) pod = DiscoveredPod( architectures=["amd64/generic"], cores=cores, cpu_speed=cpu_speed, memory=memory, local_storage=local_storage, iscsi_storage=iscsi_storage, hints=hints, machines=machines, ) self.assertEquals(cores, pod.cores) self.assertEquals(cpu_speed, pod.cpu_speed) self.assertEquals(memory, pod.memory) self.assertEquals(local_storage, pod.local_storage) self.assertEquals(iscsi_storage, pod.iscsi_storage) self.assertEquals(machines, pod.machines)
def _discover(self, client: Client, pod_id: int, context: dict): self._check_required_extensions(client) if not client.trusted: # return empty information as the client is not authenticated and # gathering other info requires auth. return DiscoveredPod() self._ensure_project(client) environment = client.host_info["environment"] # After the region creates the Pod object it will sync LXD commissioning # data for all hardware information. discovered_pod = DiscoveredPod( # client.host_info["environment"]["architectures"] reports all the # architectures the host CPU supports, not the architectures LXD # supports. On x86_64 LXD reports [x86_64, i686] however LXD does # not currently support VMs on i686. The LXD API currently does not # have a way to query which architectures are usable for VMs. The # safest bet is to just use the kernel_architecture. architectures=[ kernel_to_debian_architecture( environment["kernel_architecture"]) ], name=environment["server_name"], version=environment["server_version"], capabilities=[ Capabilities.COMPOSABLE, Capabilities.DYNAMIC_LOCAL_STORAGE, Capabilities.OVER_COMMIT, Capabilities.STORAGE_POOLS, ], ) # Discover networks. "unknown" interfaces are considered too to match # ethernets in containers. networks_state = [ net.state() for net in client.networks.all() if net.type in ("unknown", "physical") ] discovered_pod.mac_addresses = list( {state.hwaddr for state in networks_state if state.hwaddr}) # Discover storage pools. storage_pools = client.storage_pools.all() if not storage_pools: raise LXDPodError( "No storage pools exists. Please create a storage pool in LXD." ) pools = [] local_storage = 0 for storage_pool in storage_pools: discovered_storage_pool = self._get_discovered_pod_storage_pool( storage_pool) local_storage += discovered_storage_pool.storage pools.append(discovered_storage_pool) discovered_pod.storage_pools = pools discovered_pod.local_storage = local_storage # Discover VMs. host_cpu_speed = lxd_cpu_speed(client.resources) projects = [project.name for project in client.projects.all()] machines = [] for project in projects: with self._get_client(pod_id, context, project=project) as project_cli: for virtual_machine in project_cli.virtual_machines.all(): discovered_machine = self._get_discovered_machine( project_cli, virtual_machine, storage_pools=discovered_pod.storage_pools, ) discovered_machine.cpu_speed = host_cpu_speed machines.append(discovered_machine) discovered_pod.machines = machines return discovered_pod
def fromString(self, inString): # Circular imports. from provisioningserver.drivers.pod import DiscoveredPod data = super(AmpDiscoveredPod, self).fromString(inString) return DiscoveredPod.fromdict(data)
async def discover(self, pod_id, context): """Discover all Pod host resources.""" # Connect to the Pod and make sure it is valid. client = await self.get_client(pod_id, context) if not client.has_api_extension("virtual-machines"): raise LXDPodError( "Please upgrade your LXD host to 3.19+ for virtual machine support." ) resources = await deferToThread(lambda: client.resources) mac_addresses = [] for card in resources["network"]["cards"]: for port in card["ports"]: mac_addresses.append(port["address"]) # After the region creates the Pod object it will sync LXD commissioning # data for all hardware information. discovered_pod = DiscoveredPod( # client.host_info["environment"]["architectures"] reports all the # architectures the host CPU supports, not the architectures LXD # supports. On x86_64 LXD reports [x86_64, i686] however LXD does # not currently support VMs on i686. The LXD API currently does not # have a way to query which architectures are usable for VMs. The # safest bet is to just use the kernel_architecture. architectures=[ kernel_to_debian_architecture( client.host_info["environment"]["kernel_architecture"]) ], name=client.host_info["environment"]["server_name"], mac_addresses=mac_addresses, capabilities=[ Capabilities.COMPOSABLE, Capabilities.DYNAMIC_LOCAL_STORAGE, Capabilities.OVER_COMMIT, Capabilities.STORAGE_POOLS, ], ) # Check that we have at least one storage pool. # If not, user should be warned that they need to create one. storage_pools = await deferToThread(client.storage_pools.all) if not storage_pools: raise LXDPodError( "No storage pools exists. Please create a storage pool in LXD." ) # Discover Storage Pools. pools = [] storage_pools = await deferToThread(client.storage_pools.all) local_storage = 0 for storage_pool in storage_pools: discovered_storage_pool = self.get_discovered_pod_storage_pool( storage_pool) local_storage += discovered_storage_pool.storage pools.append(discovered_storage_pool) discovered_pod.storage_pools = pools discovered_pod.local_storage = local_storage # Discover VMs. machines = [] virtual_machines = await deferToThread(client.virtual_machines.all) for virtual_machine in virtual_machines: discovered_machine = await self.get_discovered_machine( client, virtual_machine, storage_pools=discovered_pod.storage_pools, ) discovered_machine.cpu_speed = lxd_cpu_speed(resources) machines.append(discovered_machine) discovered_pod.machines = machines # Return the DiscoveredPod. return discovered_pod
def discover(self, pod_id: int, context: dict): """Discover all Pod host resources.""" # Connect to the Pod and make sure it is valid. client = self._get_client(pod_id, context) if not client.has_api_extension("virtual-machines"): raise LXDPodError( "Please upgrade your LXD host to 3.19+ for virtual machine support." ) self._ensure_project(client) # get MACs for host interfaces. "unknown" interfaces are considered too # to match ethernets in containers networks_state = [ net.state() for net in client.networks.all() if net.type in ("unknown", "physical") ] mac_addresses = list( {state.hwaddr for state in networks_state if state.hwaddr}) environment = client.host_info["environment"] # After the region creates the Pod object it will sync LXD commissioning # data for all hardware information. discovered_pod = DiscoveredPod( # client.host_info["environment"]["architectures"] reports all the # architectures the host CPU supports, not the architectures LXD # supports. On x86_64 LXD reports [x86_64, i686] however LXD does # not currently support VMs on i686. The LXD API currently does not # have a way to query which architectures are usable for VMs. The # safest bet is to just use the kernel_architecture. architectures=[ kernel_to_debian_architecture( environment["kernel_architecture"]) ], name=environment["server_name"], version=environment["server_version"], mac_addresses=mac_addresses, capabilities=[ Capabilities.COMPOSABLE, Capabilities.DYNAMIC_LOCAL_STORAGE, Capabilities.OVER_COMMIT, Capabilities.STORAGE_POOLS, ], ) # Check that we have at least one storage pool. # If not, user should be warned that they need to create one. storage_pools = client.storage_pools.all() if not storage_pools: raise LXDPodError( "No storage pools exists. Please create a storage pool in LXD." ) # Discover Storage Pools. pools = [] local_storage = 0 for storage_pool in storage_pools: discovered_storage_pool = self._get_discovered_pod_storage_pool( storage_pool) local_storage += discovered_storage_pool.storage pools.append(discovered_storage_pool) discovered_pod.storage_pools = pools discovered_pod.local_storage = local_storage host_cpu_speed = lxd_cpu_speed(client.resources) # Discover VMs. projects = [project.name for project in client.projects.all()] machines = [] for project in projects: project_cli = self._get_client(pod_id, context, project=project) for virtual_machine in project_cli.virtual_machines.all(): discovered_machine = self._get_discovered_machine( project_cli, virtual_machine, storage_pools=discovered_pod.storage_pools, ) discovered_machine.cpu_speed = host_cpu_speed machines.append(discovered_machine) discovered_pod.machines = machines # Return the DiscoveredPod. return discovered_pod