class TestCachingMachineGetSystemInfo(IsolatedAsyncioTestCase): _server: TrueNASServer _machine: CachingMachine def setUp(self): self._server = TrueNASServer() async def asyncSetUp(self): self._machine = await CachingMachine.create( self._server.host, username=self._server.username, password=self._server.password, secure=False, ) async def asyncTearDown(self): await self._machine.close() await self._server.stop() async def test_get_system_info(self) -> None: HOSTNAME = "some.hostname.com" self._server.register_method_handler( "system.info", lambda *args: { "hostname": HOSTNAME, }, ) info = await self._machine.get_system_info() self.assertTrue("hostname" in info) self.assertEqual(info["hostname"], HOSTNAME)
class TestPool(IsolatedAsyncioTestCase): _server: TrueNASServer _machine: CachingMachine def setUp(self): self._server = TrueNASServer() async def asyncSetUp(self): self._machine = await CachingMachine.create( self._server.host, username=self._server.username, password=self._server.password, secure=False, ) async def asyncTearDown(self): await self._machine.close() await self._server.stop() async def test_pool_data_interpretation(self) -> None: ENCRYPT = 0 GUID = "1234ABCD" ID = 100 IS_DECRYPTED = True NAME = "testpool" self._server.register_method_handler( "pool.query", lambda *args: [ { "encrypt": ENCRYPT, "encryptkey": "", "guid": GUID, "id": ID, "is_decrypted": IS_DECRYPTED, "name": NAME, "status": "ONLINE", "state": "FINISHED", "topology": {}, }, ], ) await self._machine.get_pools() self.assertEqual(len(self._machine.pools), 1) pool = self._machine.pools[0] self.assertEqual(pool.encrypt, ENCRYPT) self.assertEqual(pool.guid, GUID) self.assertEqual(pool.id, ID) self.assertEqual(pool.is_decrypted, IS_DECRYPTED) self.assertEqual(pool.name, NAME) self.assertEqual(pool.status, PoolStatus.ONLINE) # Need to work on the return type of scan.state # self.assertEqual(pool.scan["state"], PoolScanState.FINISHED) async def test_availability(self) -> None: ENCRYPT = 0 GUID = "1234ABCD" ID = 100 IS_DECRYPTED = True NAME = "testpool" self._server.register_method_handler( "pool.query", lambda *args: [ { "encrypt": ENCRYPT, "encryptkey": "", "guid": GUID, "id": ID, "is_decrypted": IS_DECRYPTED, "name": NAME, "status": "ONLINE", "topology": {}, }, ], ) await self._machine.get_pools() pool = self._machine.pools[0] self.assertTrue(pool.available) self._server.register_method_handler( "pool.query", lambda *args: [], override=True, ) await self._machine.get_pools() self.assertFalse(pool.available) self.assertEqual(len(self._machine.pools), 0) async def test_unavailable_caching(self) -> None: """Certain properites have caching even if no longer available""" ENCRYPT = 0 GUID = "1234ABCD" ID = 100 IS_DECRYPTED = True NAME = "testpool" self._server.register_method_handler( "pool.query", lambda *args: [ { "encrypt": ENCRYPT, "encryptkey": "", "guid": GUID, "id": ID, "is_decrypted": IS_DECRYPTED, "name": NAME, "status": "ONLINE", "topology": {}, }, ], ) await self._machine.get_pools() pool = self._machine.pools[0] assert pool is not None self._server.register_method_handler( "pool.query", lambda *args: [], override=True, ) await self._machine.get_pools() self.assertEqual(pool.encrypt, ENCRYPT) self.assertEqual(pool.guid, GUID) self.assertEqual(pool.id, ID) self.assertEqual(pool.is_decrypted, IS_DECRYPTED) self.assertEqual(pool.name, NAME) self.assertEqual(pool.status, PoolStatus.ONLINE) async def test_same_instance_after_get_pools(self) -> None: self._server.register_method_handler( "pool.query", lambda *args: [ { "guid": 500, "name": "test_pool", }, ], ) await self._machine.get_pools() original_pool = self._machine.pools[0] await self._machine.get_pools() new_pool = self._machine.pools[0] self.assertIs(original_pool, new_pool) def test_eq_impl(self) -> None: self._machine._pool_fetcher._state = { # type: ignore "200": { "guid": 200, "name": "test_pool", } } a = CachingPool(self._machine._pool_fetcher, "200") # type: ignore b = CachingPool(self._machine._pool_fetcher, "200") # type: ignore self.assertEqual(a, b)
def setUp(self): self._server = TrueNASServer()
class TestVirtualMachine(IsolatedAsyncioTestCase): _server: TrueNASServer _machine: CachingMachine def setUp(self): self._server = TrueNASServer() async def asyncSetUp(self): self._machine = await CachingMachine.create( self._server.host, username=self._server.username, password=self._server.password, secure=False, ) async def asyncTearDown(self): await self._machine.close() await self._server.stop() async def test_running_data_interpretation(self) -> None: DESCRIPTION = "Some Desc" ID = 1 NAME = "vm01" self._server.register_method_handler( "vm.query", lambda *args: [ { "description": DESCRIPTION, "id": ID, "name": NAME, "status": { "pid": 42, "state": "RUNNING" }, }, ], ) await self._machine.get_vms() self.assertEqual(len(self._machine.vms), 1) vm = self._machine.vms[0] self.assertEqual(vm.description, DESCRIPTION) self.assertEqual(vm.id, ID) self.assertEqual(vm.name, NAME) self.assertEqual(vm.status, VirtualMachineState.RUNNING) async def test_stopped_data_interpretation(self) -> None: DESCRIPTION = "" ID = 3 NAME = "vm02" self._server.register_method_handler( "vm.query", lambda *args: [ { "description": DESCRIPTION, "id": ID, "name": NAME, "status": { "pid": None, "state": "STOPPED" }, }, ], ) await self._machine.get_vms() self.assertEqual(len(self._machine.vms), 1) vm = self._machine.vms[0] self.assertEqual(vm.description, DESCRIPTION) self.assertEqual(vm.id, ID) self.assertEqual(vm.name, NAME) self.assertEqual(vm.status, VirtualMachineState.STOPPED) async def test_availability(self) -> None: self._server.register_method_handler( "vm.query", lambda *args: [ { "description": "Some Desc", "id": 1, "name": "vm01", "status": { "pid": 42, "state": "RUNNING" }, }, ], ) await self._machine.get_vms() vm = self._machine.vms[0] self.assertTrue(vm.available) self._server.register_method_handler( "vm.query", lambda *args: [], override=True, ) await self._machine.get_vms() self.assertFalse(vm.available) self.assertEqual(len(self._machine.vms), 0) async def test_unavailable_caching(self) -> None: """Certain properites have caching even if no longer available""" DESCRIPTION = "Some Desc" ID = 1 NAME = "vm01" self._server.register_method_handler( "vm.query", lambda *args: [ { "description": DESCRIPTION, "id": ID, "name": NAME, "status": { "pid": 42, "state": "RUNNING" }, }, ], ) await self._machine.get_vms() vm = self._machine.vms[0] assert vm is not None self._server.register_method_handler( "vm.query", lambda *args: [], override=True, ) await self._machine.get_vms() self.assertEqual(vm.description, DESCRIPTION) self.assertEqual(vm.id, ID) self.assertEqual(vm.name, NAME) with self.assertRaises(AssertionError): vm.status async def test_same_instance_after_get_vms(self) -> None: self._server.register_method_handler( "vm.query", lambda *args: [ { "description": "Some Desc", "id": 1, "name": "vm01", "status": { "pid": 42, "state": "RUNNING" }, }, ], ) await self._machine.get_vms() original_vm = self._machine.vms[0] await self._machine.get_vms() new_vm = self._machine.vms[0] self.assertIs(original_vm, new_vm) async def test_start(self) -> None: ID = 42 self._server.register_method_handler( "vm.query", lambda *args: [ { "description": "Some Desc", "id": 42, "name": "vm01", "status": { "pid": None, "state": "STOPPED" }, }, ], ) def start_handler(id, kwargs) -> None: self.assertEqual(id, ID) self.assertFalse(kwargs["overcommit"]) return None self._server.register_method_handler( "vm.start", start_handler, ) await self._machine.get_vms() vm = self._machine.vms[0] assert vm is not None self.assertEqual(await vm.start(), None) async def test_stop(self) -> None: ID = 42 self._server.register_method_handler( "vm.query", lambda *args: [ { "description": "Some Desc", "id": 42, "name": "vm01", "status": { "pid": 10, "state": "RUNNING" }, }, ], ) def stop_handler(id, force) -> bool: self.assertEqual(id, ID) self.assertFalse(force) return True self._server.register_method_handler( "vm.stop", stop_handler, ) await self._machine.get_vms() vm = self._machine.vms[0] assert vm is not None self.assertTrue(await vm.stop()) async def test_restart(self) -> None: ID = 42 self._server.register_method_handler( "vm.query", lambda *args: [ { "description": "Some Desc", "id": 42, "name": "vm01", "status": { "pid": 10, "state": "RUNNING" }, }, ], ) def restart_handler(id) -> bool: self.assertEqual(id, ID) return True self._server.register_method_handler( "vm.restart", restart_handler, ) await self._machine.get_vms() vm = self._machine.vms[0] assert vm is not None self.assertTrue(await vm.restart()) def test_eq_impl(self) -> None: self._machine._vm_fetcher._state = { 42: { "description": "", "id": 42, "name": "somename", "status": { "pid": 10, "state": "RUNNING" }, } } a = CachingVirtualMachine(self._machine._vm_fetcher, 42) b = CachingVirtualMachine(self._machine._vm_fetcher, 42) self.assertEqual(a, b)
class TestVirtualMachine(IsolatedAsyncioTestCase): _server: TrueNASServer _machine: CachingMachine def setUp(self): self._server = TrueNASServer() async def asyncSetUp(self): self._machine = await CachingMachine.create( self._server.host, username=self._server.username, password=self._server.password, secure=False, ) async def asyncTearDown(self): await self._machine.close() await self._server.stop() async def test_running_data_interpretation(self) -> None: DESCRIPTION = "Some Desc" ID = 1 NAME = "vm01" self._server.register_method_handler( "vm.query", lambda *args: [ { "description": DESCRIPTION, "id": ID, "name": NAME, "status": { "pid": 42, "state": "RUNNING" }, }, ], ) await self._machine.get_vms() self.assertEqual(len(self._machine.vms), 1) vm = self._machine.vms[0] self.assertEqual(vm.description, DESCRIPTION) self.assertEqual(vm.id, ID) self.assertEqual(vm.name, NAME) self.assertEqual(vm.status, VirtualMachineState.RUNNING) async def test_stopped_data_interpretation(self) -> None: DESCRIPTION = "" ID = 3 NAME = "vm02" self._server.register_method_handler( "vm.query", lambda *args: [ { "description": DESCRIPTION, "id": ID, "name": NAME, "status": { "pid": None, "state": "STOPPED" }, }, ], ) await self._machine.get_vms() self.assertEqual(len(self._machine.vms), 1) vm = self._machine.vms[0] self.assertEqual(vm.description, DESCRIPTION) self.assertEqual(vm.id, ID) self.assertEqual(vm.name, NAME) self.assertEqual(vm.status, VirtualMachineState.STOPPED) async def test_availability(self) -> None: self._server.register_method_handler( "vm.query", lambda *args: [ { "description": "Some Desc", "id": 1, "name": "vm01", "status": { "pid": 42, "state": "RUNNING" }, }, ], ) await self._machine.get_vms() vm = self._machine.vms[0] self.assertTrue(vm.available) self._server.register_method_handler( "vm.query", lambda *args: [], override=True, ) await self._machine.get_vms() self.assertFalse(vm.available) self.assertEqual(len(self._machine.vms), 0) async def test_unavailable_caching(self) -> None: """Certain properites have caching even if no longer available""" DESCRIPTION = "Some Desc" ID = 1 NAME = "vm01" self._server.register_method_handler( "vm.query", lambda *args: [ { "description": DESCRIPTION, "id": ID, "name": NAME, "status": { "pid": 42, "state": "RUNNING" }, }, ], ) await self._machine.get_vms() vm = self._machine.vms[0] assert vm is not None self._server.register_method_handler( "vm.query", lambda *args: [], override=True, ) await self._machine.get_vms() self.assertEqual(vm.description, DESCRIPTION) self.assertEqual(vm.id, ID) self.assertEqual(vm.name, NAME) with self.assertRaises(AssertionError): vm.status async def test_same_instance_after_get_vms(self) -> None: self._server.register_method_handler( "vm.query", lambda *args: [ { "description": "Some Desc", "id": 1, "name": "vm01", "status": { "pid": 42, "state": "RUNNING" }, }, ], ) await self._machine.get_vms() original_vm = self._machine.vms[0] await self._machine.get_vms() new_vm = self._machine.vms[0] self.assertIs(original_vm, new_vm) async def test_start(self) -> None: ID = 42 self._server.register_method_handler( "vm.query", lambda *args: [ { "description": "Some Desc", "id": 42, "name": "vm01", "status": { "pid": None, "state": "STOPPED" }, }, ], ) def start_handler(id, kwargs) -> None: self.assertEqual(id, ID) self.assertFalse(kwargs["overcommit"]) return None self._server.register_method_handler( "vm.start", start_handler, ) await self._machine.get_vms() vm = self._machine.vms[0] assert vm is not None self.assertEqual(await vm.start(), None) async def test_stop(self) -> None: ID = 42 self._server.register_method_handler( "vm.query", lambda *args: [ { "description": "Some Desc", "id": 42, "name": "vm01", "status": { "pid": 10, "state": "RUNNING" }, }, ], ) def stop_handler(id, options: Dict[str, bool]) -> TJobId: JOB_ID = 42 self.assertEqual(id, ID) self.assertFalse(options["force_after_timeout"]) self._server.send_subscription_data({ "msg": "changed", "collection": "core.get_jobs", "id": JOB_ID, "fields": { "id": JOB_ID, "method": "vm.stop", "arguments": [ID, { "force_after_timeout": False }], "logs_path": None, "logs_excerpt": None, "progress": { "percent": 100, "description": None, "extra": None, }, "result": None, "error": None, "exception": None, "exc_info": None, "state": "SUCCESS", "time_started": datetime.datetime(2021, 1, 8, 21, 30, 0, tzinfo=datetime.timezone.utc), "time_finished": datetime.datetime(2021, 1, 8, 21, 30, 1, tzinfo=datetime.timezone.utc), }, }) return JOB_ID self._server.register_method_handler( "vm.stop", stop_handler, ) self._server.register_method_handler( "vm.status", lambda id: { "state": "STOPPED", "pid": 42, "domain_state": "STOPPED" }, ) await self._machine.get_vms() vm = self._machine.vms[0] assert vm is not None self.assertTrue(await vm.stop()) async def test_restart(self) -> None: ID = 42 self._server.register_method_handler( "vm.query", lambda *args: [ { "description": "Some Desc", "id": 42, "name": "vm01", "status": { "pid": 10, "state": "RUNNING" }, }, ], ) def restart_handler(id) -> TJobId: JOB_ID = 42 self.assertEqual(id, ID) self._server.send_subscription_data({ "msg": "changed", "collection": "core.get_jobs", "id": JOB_ID, "fields": { "id": JOB_ID, "method": "vm.restart", "arguments": [ID], "logs_path": None, "logs_excerpt": None, "progress": { "percent": 100, "description": None, "extra": None, }, "result": None, "error": None, "exception": None, "exc_info": None, "state": "SUCCESS", "time_started": datetime.datetime(2021, 1, 8, 21, 30, 0, tzinfo=datetime.timezone.utc), "time_finished": datetime.datetime(2021, 1, 8, 21, 30, 1, tzinfo=datetime.timezone.utc), }, }) return JOB_ID self._server.register_method_handler( "vm.restart", restart_handler, ) self._server.register_method_handler( "vm.status", lambda id: { "state": "RUNNING", "pid": 42, "domain_state": "RUNNING" }, ) await self._machine.get_vms() vm = self._machine.vms[0] assert vm is not None self.assertTrue(await vm.restart()) def test_eq_impl(self) -> None: self._machine._vm_fetcher._state = { # type: ignore "42": { "description": "", "id": 42, "name": "somename", "status": { "pid": 10, "state": "RUNNING" }, } } a = CachingVirtualMachine(self._machine._vm_fetcher, 42) # type: ignore b = CachingVirtualMachine(self._machine._vm_fetcher, 42) # type: ignore self.assertEqual(a, b)
class TestDisk(IsolatedAsyncioTestCase): _server: TrueNASServer _machine: CachingMachine def setUp(self): self._server = TrueNASServer() async def asyncSetUp(self): self._machine = await CachingMachine.create( self._server.host, username=self._server.username, password=self._server.password, secure=False, ) async def asyncTearDown(self): await self._machine.close() await self._server.stop() async def test_ssd_data_interpretation(self) -> None: DESCRIPTION = "Some Desc" MODEL = "Samsung SSD 860 EVO 250GB" NAME = "ada0" SERIAL = "NOTREALSERIAL" SIZE = 250059350016 self._server.register_method_handler( "disk.query", lambda *args: [ { "description": DESCRIPTION, "model": MODEL, "name": NAME, "serial": SERIAL, "size": SIZE, "type": "SSD", }, ], ) await self._machine.get_disks() self.assertEqual(len(self._machine.disks), 1) disk = self._machine.disks[0] self.assertEqual( disk.description, DESCRIPTION, ) self.assertEqual(disk.model, MODEL) self.assertEqual(disk.name, NAME) self.assertEqual(disk.serial, SERIAL) self.assertEqual(disk.size, SIZE) self.assertEqual(disk.temperature, None) self.assertEqual(disk.type, DiskType.SSD) async def test_hddd_data_interpretation(self) -> None: DESCRIPTION = "Some Desc" MODEL = "ATA WDC WD60EFAX-68S" NAME = "da0" SERIAL = "NOTREALSERIAL" SIZE = 6001175126016 self._server.register_method_handler( "disk.query", lambda *args: [ { "description": DESCRIPTION, "model": MODEL, "name": NAME, "serial": SERIAL, "size": SIZE, "type": "HDD", }, ], ) await self._machine.get_disks() self.assertEqual(len(self._machine.disks), 1) disk = self._machine.disks[0] self.assertEqual( disk.description, DESCRIPTION, ) self.assertEqual(disk.model, MODEL) self.assertEqual(disk.name, NAME) self.assertEqual(disk.serial, SERIAL) self.assertEqual(disk.size, SIZE) self.assertEqual(disk.temperature, None) self.assertEqual(disk.type, DiskType.HDD) async def test_temperature(self) -> None: TEMPERATURE = 42 self._server.register_method_handler( "disk.query", lambda *args: [ { "description": "Some Desc", "model": "Samsung SSD 860 EVO 250GB", "name": "ada0", "serial": "NOTREALSERIAL", "size": 250059350016, "type": "SSD", }, ], ) self._server.register_method_handler( "disk.temperatures", lambda *args: {"ada0": TEMPERATURE}, ) await self._machine.get_disks(include_temperature=True) self.assertEqual(len(self._machine.disks), 1) disk = self._machine.disks[0] self.assertEqual(disk.temperature, TEMPERATURE) async def test_availability(self) -> None: self._server.register_method_handler( "disk.query", lambda *args: [ { "description": "Some Desc", "model": "Samsung SSD 860 EVO 250GB", "name": "ada0", "serial": "NOTREALSERIAL", "size": 250059350016, "type": "SSD", }, ], ) self._server.register_method_handler( "disk.temperatures", lambda *args: {"ada0": 42}, ) await self._machine.get_disks() disk = self._machine.disks[0] self.assertTrue(disk.available) self._server.register_method_handler( "disk.query", lambda *args: [], override=True, ) await self._machine.get_disks() self.assertFalse(disk.available) self.assertEqual( len(self._machine._disk_fetcher._cached_disks), 0 # type: ignore ) async def test_unavailable_caching(self) -> None: """Certain properites have caching even if no longer available""" DESCRIPTION = "Some Desc" MODEL = "ATA WDC WD60EFAX-68S" NAME = "da0" SERIAL = "NOTREALSERIAL" SIZE = 6001175126016 self._server.register_method_handler( "disk.query", lambda *args: [ { "description": DESCRIPTION, "model": MODEL, "name": NAME, "serial": SERIAL, "size": SIZE, "type": "HDD", }, ], ) self._server.register_method_handler( "disk.temperatures", lambda *args: {NAME: 42}, ) await self._machine.get_disks() disk = self._machine.disks[0] assert disk is not None self._server.register_method_handler( "disk.query", lambda *args: [], override=True, ) await self._machine.get_disks() self.assertEqual(disk.model, MODEL) self.assertEqual(disk.name, NAME) self.assertEqual(disk.serial, SERIAL) self.assertEqual(disk.size, SIZE) with self.assertRaises(AssertionError): disk.temperature self.assertEqual(disk.type, DiskType.HDD) async def test_same_instance_after_get_disks(self) -> None: self._server.register_method_handler( "disk.query", lambda *args: [ { "description": "Some Desc", "model": "Samsung SSD 860 EVO 250GB", "name": "ada0", "serial": "NOTREALSERIAL", "size": 250059350016, "type": "SSD", }, ], ) self._server.register_method_handler( "disk.temperatures", lambda *args: {"ada0": 42}, ) await self._machine.get_disks() original_disk = self._machine.disks[0] await self._machine.get_disks() new_disk = self._machine.disks[0] self.assertIs(original_disk, new_disk) def test_eq_impl(self) -> None: self._machine._disk_fetcher._state = { # type: ignore "ada0": { "description": "", "model": "", "name": "ada0", "serial": "someserial", "size": 256, "temperature": 42, "type": "SSD", } } a = CachingDisk(self._machine._disk_fetcher, "ada0") # type: ignore b = CachingDisk(self._machine._disk_fetcher, "ada0") # type: ignore self.assertEqual(a, b) async def test_serial_with_edge_whitespace(self) -> None: SERIAL = "NOTREALSERIAL" self._server.register_method_handler( "disk.query", lambda *args: [ { "description": "Some Desc", "model": "Samsung SSD 860 EVO 250GB", "name": "ada0", "serial": f" {SERIAL} ", "size": 250059350016, "type": "SSD", }, ], ) await self._machine.get_disks() self.assertEqual(len(self._machine.disks), 1) disk = self._machine.disks[0] self.assertEqual(disk.serial, SERIAL)
class TestJail(IsolatedAsyncioTestCase): _server: TrueNASServer _machine: CachingMachine def setUp(self): self._server = TrueNASServer() async def asyncSetUp(self): self._machine = await CachingMachine.create( self._server.host, api_key=self._server.api_key, secure=False, ) async def asyncTearDown(self): await self._machine.close() await self._server.stop() async def test_running_data_interpretation(self) -> None: NAME = "jail01" self._server.register_method_handler( "jail.query", lambda *args: [ { "id": NAME, "state": "up", }, ], ) await self._machine.get_jails() self.assertEqual(len(self._machine.jails), 1) jail = self._machine.jails[0] self.assertEqual(jail.name, NAME) self.assertEqual(jail.status, JailStatus.UP) async def test_stopped_data_interpretation(self) -> None: NAME = "jail01" self._server.register_method_handler( "jail.query", lambda *args: [ { "id": NAME, "state": "down", }, ], ) await self._machine.get_jails() self.assertEqual(len(self._machine.jails), 1) jail = self._machine.jails[0] self.assertEqual(jail.name, NAME) self.assertEqual(jail.status, JailStatus.DOWN) async def test_availability(self) -> None: self._server.register_method_handler( "jail.query", lambda *args: [ { "id": "jail01", "state": "up", }, ], ) await self._machine.get_jails() jail = self._machine.jails[0] self.assertTrue(jail.available) self._server.register_method_handler( "jail.query", lambda *args: [], override=True, ) await self._machine.get_jails() self.assertFalse(jail.available) self.assertEqual(len(self._machine.jails), 0) async def test_same_instance_after_get_jails(self) -> None: self._server.register_method_handler( "jail.query", lambda *args: [ { "id": "jail01", "state": "up", }, ], ) await self._machine.get_jails() original_jail = self._machine.jails[0] await self._machine.get_jails() new_jail = self._machine.jails[0] self.assertIs(original_jail, new_jail) async def test_start(self) -> None: NAME = "jail01" self._server.register_method_handler( "jail.query", lambda *args: [ { "id": NAME, "state": "up", }, ], ) await self._machine.get_jails() jail = self._machine.jails[0] with self.assertRaises(RuntimeError): await jail.start() self._server.register_method_handler( "jail.query", lambda *args: [ { "id": NAME, "state": "down", }, ], override=True, ) def start_handler(name) -> int: JOB_ID = 42 self.assertEqual(name, NAME) self._server.send_subscription_data( { "msg": "changed", "collection": "core.get_jobs", "id": JOB_ID, "fields": { "id": JOB_ID, "method": "jail.start", "arguments": [NAME], "logs_path": None, "logs_excerpt": None, "progress": { "percent": 100, "description": None, "extra": None, }, "result": True, "error": None, "exception": None, "exc_info": None, "state": "SUCCESS", "time_started": datetime.datetime(2021, 1, 7, 21, 30, 0, tzinfo=datetime.timezone.utc), "time_finished": datetime.datetime(2021, 1, 7, 21, 30, 1, tzinfo=datetime.timezone.utc), }, }, ), return JOB_ID self._server.register_method_handler( "jail.start", start_handler, ) await self._machine.get_jails() jail = self._machine.jails[0] self.assertTrue(await jail.start()) async def test_stop(self) -> None: NAME = "jail01" self._server.register_method_handler( "jail.query", lambda *args: [ { "id": NAME, "state": "down", }, ], ) await self._machine.get_jails() jail = self._machine.jails[0] with self.assertRaises(RuntimeError): await jail.stop() self._server.register_method_handler( "jail.query", lambda *args: [ { "id": NAME, "state": "up", }, ], override=True, ) def stop_handler(name, force) -> int: JOB_ID = 42 self.assertEqual(name, NAME) self.assertFalse(force) self._server.send_subscription_data( { "msg": "changed", "collection": "core.get_jobs", "id": JOB_ID, "fields": { "id": JOB_ID, "method": "jail.stop", "arguments": [NAME], "logs_path": None, "logs_excerpt": None, "progress": { "percent": 100, "description": None, "extra": None, }, "result": None, # For some reason, TrueNAS has a null result for this... "error": None, "exception": None, "exc_info": None, "state": "SUCCESS", "time_started": datetime.datetime(2021, 1, 7, 21, 30, 0, tzinfo=datetime.timezone.utc), "time_finished": datetime.datetime(2021, 1, 7, 21, 30, 1, tzinfo=datetime.timezone.utc), }, }, ) return JOB_ID self._server.register_method_handler( "jail.stop", stop_handler, ) await self._machine.get_jails() jail = self._machine.jails[0] self.assertTrue(await jail.stop()) async def test_restart(self) -> None: NAME = "jail01" self._server.register_method_handler( "jail.query", lambda *args: [ { "id": NAME, "state": "down", }, ], ) await self._machine.get_jails() jail = self._machine.jails[0] with self.assertRaises(RuntimeError): await jail.restart() self._server.register_method_handler( "jail.query", lambda *args: [ { "id": NAME, "state": "up", }, ], override=True, ) def restart_handler(name) -> int: JOB_ID = 42 self.assertEqual(name, NAME) self._server.send_subscription_data( { "msg": "changed", "collection": "core.get_jobs", "id": JOB_ID, "fields": { "id": JOB_ID, "method": "jail.start", "arguments": [NAME], "logs_path": None, "logs_excerpt": None, "progress": { "percent": 100, "description": None, "extra": None, }, "result": True, "error": None, "exception": None, "exc_info": None, "state": "SUCCESS", "time_started": datetime.datetime(2021, 1, 7, 21, 30, 0, tzinfo=datetime.timezone.utc), "time_finished": datetime.datetime(2021, 1, 7, 21, 30, 1, tzinfo=datetime.timezone.utc), }, }, ), return JOB_ID self._server.register_method_handler( "jail.restart", restart_handler, ) await self._machine.get_jails() jail = self._machine.jails[0] self.assertTrue(await jail.restart()) def test_eq_impl(self) -> None: self._machine._jail_fetcher._state = { # type: ignore "jail01": { "id": "jail01", "state": "up" } } a = CachingJail(self._machine._jail_fetcher, "jail01") # type: ignore b = CachingJail(self._machine._jail_fetcher, "jail01") # type: ignore self.assertEqual(a, b)
class TestPool(IsolatedAsyncioTestCase): _server: TrueNASServer _machine: CachingMachine def setUp(self): self._server = TrueNASServer() async def asyncSetUp(self): self._machine = await CachingMachine.create( self._server.host, api_key=self._server.api_key, secure=False, ) async def asyncTearDown(self): await self._machine.close() await self._server.stop() async def test_dataset_data_interpretation(self) -> None: AVAILABLE_BYTES = 841462824960 COMMENTS = "this is a comment" COMPRESSION_RATIO = 1.19 DATASET_ID = "ssd0" POOL_NAME = "ssd0" USED_BYTES = 602317275136 self._server.register_method_handler( "pool.dataset.query", lambda *args: [ { "available": { "parsed": AVAILABLE_BYTES, "rawvalue": str(AVAILABLE_BYTES), "source": "NONE", "value": "784G", }, "comments": { "parsed": COMMENTS, "rawvalue": COMMENTS, "source": "LOCAL", "value": COMMENTS, }, "compressratio": { "parsed": str(COMPRESSION_RATIO), "rawvalue": str(COMPRESSION_RATIO), "source": "NONE", "value": f"{COMPRESSION_RATIO}x", }, "id": DATASET_ID, "pool": POOL_NAME, "type": "FILESYSTEM", "used": { "parsed": USED_BYTES, "rawvalue": str(USED_BYTES), "source": "NONE", "value": "266G", }, }, ], ) await self._machine.get_datasets() self.assertEqual(len(self._machine.datasets), 1) dataset = self._machine.datasets[0] self.assertEqual(dataset.available_bytes, AVAILABLE_BYTES) assert dataset.comments self.assertEqual(dataset.comments.parsedValue, COMMENTS) self.assertEqual(dataset.comments.rawValue, COMMENTS) self.assertEqual(dataset.comments.source, DatasetPropertySource.LOCAL) self.assertEqual(dataset.comments.value, COMMENTS) self.assertEqual(dataset.compression_ratio, COMPRESSION_RATIO) self.assertEqual(dataset.id, DATASET_ID) self.assertEqual(dataset.pool_name, POOL_NAME) self.assertEqual(dataset.total_bytes, USED_BYTES + AVAILABLE_BYTES) self.assertEqual(dataset.type, DatasetType.FILESYSTEM) self.assertEqual(dataset.used_bytes, USED_BYTES) async def test_dataset_data_interpretation_no_comments(self) -> None: AVAILABLE_BYTES = 841462824960 COMPRESSION_RATIO = 1.19 DATASET_ID = "ssd0/myvol" POOL_NAME = "ssd0" USED_BYTES = 602317275136 self._server.register_method_handler( "pool.dataset.query", lambda *args: [ { "available": { "parsed": AVAILABLE_BYTES, "rawvalue": str(AVAILABLE_BYTES), "source": "NONE", "value": "784G", }, "compressratio": { "parsed": str(COMPRESSION_RATIO), "rawvalue": str(COMPRESSION_RATIO), "source": "NONE", "value": f"{COMPRESSION_RATIO}x", }, "id": DATASET_ID, "pool": POOL_NAME, "type": "VOLUME", "used": { "parsed": USED_BYTES, "rawvalue": str(USED_BYTES), "source": "NONE", "value": "266G", }, }, ], ) await self._machine.get_datasets() self.assertEqual(len(self._machine.datasets), 1) dataset = self._machine.datasets[0] self.assertEqual(dataset.available_bytes, AVAILABLE_BYTES) self.assertEqual(dataset.comments, None) self.assertEqual(dataset.compression_ratio, COMPRESSION_RATIO) self.assertEqual(dataset.id, DATASET_ID) self.assertEqual(dataset.pool_name, POOL_NAME) self.assertEqual(dataset.total_bytes, USED_BYTES + AVAILABLE_BYTES) self.assertEqual(dataset.type, DatasetType.VOLUME) self.assertEqual(dataset.used_bytes, USED_BYTES) async def test_availability(self) -> None: self._server.register_method_handler( "pool.dataset.query", lambda *args: [ { "available": { "parsed": 841396957184, "rawvalue": "841396957184", "source": "NONE", "value": "784G", }, "compressratio": { "parsed": "1.19", "rawvalue": "1.19", "source": "NONE", "value": "1.19x", }, "id": "ssd0/iscsi/sdwilsh-desktop", "pool": "ssd0", "type": "VOLUME", "used": { "parsed": 285263630336, "rawvalue": "285263630336", "source": "NONE", "value": "266G", }, }, ], ) await self._machine.get_datasets() dataset = self._machine.datasets[0] self.assertTrue(dataset.available) self._server.register_method_handler( "pool.dataset.query", lambda *args: [], override=True, ) await self._machine.get_datasets() self.assertFalse(dataset.available) self.assertEqual(len(self._machine.datasets), 0) async def test_unavailable_caching(self) -> None: """Certain properites have caching even if no longer available""" AVAILABLE_BYTES = 841462824960 COMMENTS = "this is a comment" COMPRESSION_RATIO = 1.19 DATASET_ID = "ssd0" POOL_NAME = "ssd0" USED_BYTES = 602317275136 self._server.register_method_handler( "pool.dataset.query", lambda *args: [ { "available": { "parsed": AVAILABLE_BYTES, "rawvalue": str(AVAILABLE_BYTES), "source": "NONE", "value": "784G", }, "comments": { "parsed": COMMENTS, "rawvalue": COMMENTS, "source": "INHERITED", "value": COMMENTS, }, "compressratio": { "parsed": str(COMPRESSION_RATIO), "rawvalue": str(COMPRESSION_RATIO), "source": "NONE", "value": f"{COMPRESSION_RATIO}x", }, "id": DATASET_ID, "pool": POOL_NAME, "type": "FILESYSTEM", "used": { "parsed": USED_BYTES, "rawvalue": str(USED_BYTES), "source": "NONE", "value": "266G", }, }, ], ) await self._machine.get_datasets() dataset = self._machine.datasets[0] assert dataset is not None self._server.register_method_handler( "pool.dataset.query", lambda *args: [], override=True, ) await self._machine.get_datasets() self.assertEqual(dataset.available_bytes, AVAILABLE_BYTES) assert dataset.comments self.assertEqual(dataset.comments.parsedValue, COMMENTS) self.assertEqual(dataset.comments.rawValue, COMMENTS) self.assertEqual(dataset.comments.source, DatasetPropertySource.INHERITED) self.assertEqual(dataset.comments.value, COMMENTS) self.assertEqual(dataset.compression_ratio, COMPRESSION_RATIO) self.assertEqual(dataset.id, DATASET_ID) self.assertEqual(dataset.pool_name, POOL_NAME) self.assertEqual(dataset.total_bytes, USED_BYTES + AVAILABLE_BYTES) self.assertEqual(dataset.type, DatasetType.FILESYSTEM) self.assertEqual(dataset.used_bytes, USED_BYTES) async def test_same_instance_after_get_datasets(self) -> None: self._server.register_method_handler( "pool.dataset.query", lambda *args: [ { "id": "ssd0", }, ], ) await self._machine.get_datasets() original_dataset = self._machine.datasets[0] await self._machine.get_datasets() new_dataset = self._machine.datasets[0] self.assertIs(original_dataset, new_dataset) def test_eq_impl(self) -> None: self._machine._dataset_fetcher._state = { # type: ignore "ssd0": { "id": "ssd0", } } a = CachingDataset(self._machine._dataset_fetcher, "ssd0") # type: ignore b = CachingDataset(self._machine._dataset_fetcher, "ssd0") # type: ignore self.assertEqual(a, b)
class TestJob(IsolatedAsyncioTestCase): _server: TrueNASServer _machine: CachingMachine def setUp(self): self._server = TrueNASServer() async def asyncSetUp(self): self._machine = await CachingMachine.create( self._server.host, api_key=self._server.api_key, secure=False, ) async def asyncTearDown(self): await self._machine.close() await self._server.stop() async def test_running_data_interpretation(self) -> None: JOB_ID = 42 self._server.register_method_handler( "core.get_jobs", lambda *args: [ { "arguments": ["jail01"], "error": None, "exc_info": None, "exception": None, "id": JOB_ID, "logs_excerpt": None, "logs_path": None, "method": "jail.start", "progress": { "description": None, "extra": None, "percent": None }, "result": None, "state": "RUNNING", "time_finished": None, "time_started": datetime.datetime(2021, 1, 6, 17, 51, 29, 741000, tzinfo=datetime.timezone.utc), }, ], ) job = await self._machine.get_job(42) self.assertEqual(job.id, JOB_ID) self.assertEqual(job.method, "jail.start") self.assertEqual(job.status, JobStatus.RUNNING) async def test_success_data_interpretation(self) -> None: JOB_ID = 42 self._server.register_method_handler( "core.get_jobs", lambda *args: [{ "arguments": ["jail01"], "error": None, "exc_info": None, "exception": None, "id": JOB_ID, "logs_excerpt": None, "logs_path": None, "method": "jail.start", "progress": { "description": None, "extra": None, "percent": 100 }, "result": True, "state": "SUCCESS", "time_finished": datetime.datetime(2021, 1, 6, 17, 51, 41, 281000, tzinfo=datetime.timezone.utc), "time_started": datetime.datetime(2021, 1, 6, 17, 51, 29, 741000, tzinfo=datetime.timezone.utc), }], ) job = await self._machine.get_job(42) self.assertEqual(job.id, JOB_ID) self.assertEqual(job.method, "jail.start") self.assertEqual(job.result, True) self.assertEqual(job.status, JobStatus.SUCCESS) async def test_failed_data_interpretation(self) -> None: JOB_ID = 42 self._server.register_method_handler( "core.get_jobs", lambda *args: [{ "arguments": ["jail01"], "error": "[EFAULT] jail01 is not running", "exc_info": { "extra": None, "type": "CallError" }, "exception": "Traceback (most recent call last):...", "id": JOB_ID, "logs_excerpt": None, "logs_path": None, "method": "jail.stop", "progress": { "description": None, "extra": None, "percent": None }, "result": None, "state": "FAILED", "time_finished": datetime.datetime(2021, 1, 6, 5, 22, 38, 286000, tzinfo=datetime.timezone.utc), "time_started": datetime.datetime(2021, 1, 6, 5, 22, 37, 945000, tzinfo=datetime.timezone.utc), }], ) job = await self._machine.get_job(42) self.assertEqual(job.error, "[EFAULT] jail01 is not running") self.assertEqual(job.id, JOB_ID) self.assertEqual(job.method, "jail.stop") self.assertEqual(job.status, JobStatus.FAILED) async def test_waiting_data_interpretation(self) -> None: JOB_ID = 42 self._server.register_method_handler( "core.get_jobs", lambda *args: [ { "arguments": ["jail01"], "error": None, "exc_info": None, "exception": None, "id": JOB_ID, "logs_excerpt": None, "logs_path": None, "method": "jail.stop", "progress": { "description": None, "extra": None, "percent": None }, "result": None, "state": "WAITING", "time_finished": None, "time_started": datetime.datetime(2021, 1, 6, 18, 8, 38, 561000, tzinfo=datetime.timezone.utc), }, ], ) job = await self._machine.get_job(42) self.assertEqual(job.id, JOB_ID) self.assertEqual(job.method, "jail.stop") self.assertEqual(job.status, JobStatus.WAITING)