Skip to content

Commit 2ce14c9

Browse files
authored
Merge pull request #385 from semarie/push-xzykrvyyrtyq
2 parents 178fdd0 + 39deaf1 commit 2ce14c9

7 files changed

Lines changed: 69 additions & 51 deletions

File tree

conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def setup_host(hostname_or_ip, *, config=None):
187187
nested_list.append(host_vm)
188188

189189
vif = host_vm.vifs()[0]
190-
mac_address = vif.param_get('MAC')
190+
mac_address = vif.mac_address()
191191
logging.info("Nested host has MAC %s", mac_address)
192192

193193
host_vm.start()

lib/basevm.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
from __future__ import annotations
2+
13
import logging
24

35
from typing import TYPE_CHECKING, Any, List, Literal, Optional, overload
46

57
if TYPE_CHECKING:
6-
import lib.host
8+
from lib.host import Host
79

810
from lib.common import _param_add, _param_clear, _param_get, _param_remove, _param_set
911
from lib.sr import SR
@@ -14,7 +16,7 @@ class BaseVM:
1416
xe_prefix = "vm"
1517
uuid: str
1618

17-
def __init__(self, uuid: str, host: 'lib.host.Host'):
19+
def __init__(self, uuid: str, host: Host):
1820
logging.info("New %s: %s", type(self).__name__, uuid)
1921
self.uuid = uuid
2022
self.host = host
@@ -75,14 +77,14 @@ def vdi_uuids(self, sr_uuid: Optional[str] = None) -> List[str]:
7577
vdis_on_sr.append(vdi)
7678
return vdis_on_sr
7779

78-
def all_vdis_on_host(self, host):
80+
def all_vdis_on_host(self, host: Host) -> bool:
7981
for vdi_uuid in self.vdi_uuids():
8082
sr = SR(self.host.pool.get_vdi_sr_uuid(vdi_uuid), self.host.pool)
8183
if not sr.attached_to_host(host):
8284
return False
8385
return True
8486

85-
def all_vdis_on_sr(self, sr) -> bool:
87+
def all_vdis_on_sr(self, sr: SR) -> bool:
8688
return all(self.host.pool.get_vdi_sr_uuid(vdi_uuid) == sr.uuid for vdi_uuid in self.vdi_uuids())
8789

8890
def get_sr(self) -> SR:

lib/host.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from packaging import version
1111

1212
import lib.commands as commands
13-
import lib.pif as pif
1413

1514
from typing import TYPE_CHECKING, Dict, List, Literal, Mapping, Optional, TypedDict, Union, overload
1615

@@ -33,6 +32,7 @@
3332
wait_for_not,
3433
)
3534
from lib.netutil import wrap_ip
35+
from lib.pif import PIF
3636
from lib.sr import SR
3737
from lib.vdi import VDI
3838
from lib.vm import VM
@@ -313,7 +313,7 @@ def xo_server_reconnect(self):
313313
def vm_cache_key(uri):
314314
return f"[Cache for {strip_suffix(uri, '.xva')}]"
315315

316-
def cached_vm(self, uri, sr_uuid):
316+
def cached_vm(self, uri, sr_uuid) -> Optional[VM]:
317317
assert sr_uuid, "A SR UUID is necessary to use import cache"
318318
cache_key = self.vm_cache_key(uri)
319319
# Look for an existing cache VM
@@ -328,8 +328,9 @@ def cached_vm(self, uri, sr_uuid):
328328
logging.info(f"Reusing cached VM {vm.uuid} for {uri}")
329329
return vm
330330
logging.info("Could not find a VM in cache for %r", uri)
331+
return None
331332

332-
def import_vm(self, uri, sr_uuid=None, use_cache=False):
333+
def import_vm(self, uri, sr_uuid=None, use_cache=False) -> VM:
333334
vm = None
334335
if use_cache:
335336
if '://' in uri and uri.startswith("clone"):
@@ -373,7 +374,7 @@ def import_vm(self, uri, sr_uuid=None, use_cache=False):
373374
vm.param_set('name-description', cache_key)
374375
return vm
375376

376-
def import_iso(self, uri, sr: SR):
377+
def import_iso(self, uri, sr: SR) -> VDI:
377378
random_name = str(uuid.uuid4())
378379

379380
vdi_uuid = self.xe(
@@ -404,7 +405,7 @@ def import_iso(self, uri, sr: SR):
404405

405406
return VDI(vdi_uuid, sr=sr)
406407

407-
def vm_from_template(self, name, template):
408+
def vm_from_template(self, name, template) -> VM:
408409
params = {
409410
"new-name-label": prefix_object_name(name),
410411
"template": template,
@@ -413,7 +414,7 @@ def vm_from_template(self, name, template):
413414
vm_uuid = self.xe('vm-install', params)
414415
return VM(vm_uuid, self)
415416

416-
def pool_has_vm(self, vm_uuid, vm_type='vm'):
417+
def pool_has_vm(self, vm_uuid, vm_type='vm') -> bool:
417418
if vm_type == 'snapshot':
418419
return self.xe('snapshot-list', {'uuid': vm_uuid}, minimal=True) == vm_uuid
419420
else:
@@ -436,7 +437,7 @@ def is_enabled(self) -> bool:
436437
# If XAPI is not ready yet, or the host is down, this will throw. We return False in that case.
437438
return False
438439

439-
def has_updates(self):
440+
def has_updates(self) -> bool:
440441
try:
441442
# yum check-update returns 100 if there are updates, 1 if there's an error, 0 if no updates
442443
self.ssh(['yum', 'check-update'])
@@ -504,14 +505,14 @@ def packages(self):
504505
self.ssh(['rpm', '-qa', '--qf', '%{NAME}-%{VERSION}-%{RELEASE}-%{ARCH}-%{EPOCH}\\\\n']).splitlines()
505506
)
506507

507-
def check_packages_available(self, packages):
508+
def check_packages_available(self, packages) -> bool:
508509
""" Check if a given package list is available in the YUM repositories. """
509510
return len(self.ssh(['repoquery'] + packages).splitlines()) == len(packages)
510511

511512
def get_available_package_versions(self, package):
512513
return self.ssh(['repoquery', '--show-duplicates', package]).splitlines()
513514

514-
def is_package_installed(self, package):
515+
def is_package_installed(self, package) -> bool:
515516
return self.ssh_with_result(['rpm', '-q', package]).returncode == 0
516517

517518
def yum_save_state(self):
@@ -563,12 +564,12 @@ def reboot(self, verify=False):
563564
"Wait for ssh up on host", timeout_secs=10 * 60, retry_delay_secs=5)
564565
wait_for(self.is_enabled, "Wait for XAPI to be ready", timeout_secs=30 * 60)
565566

566-
def management_network(self):
567+
def management_network(self) -> str:
567568
return self.xe('network-list', {'bridge': self.inventory['MANAGEMENT_INTERFACE']}, minimal=True)
568569

569-
def management_pif(self):
570+
def management_pif(self) -> PIF:
570571
uuid = self.xe('pif-list', {'management': True, 'host-uuid': self.uuid}, minimal=True)
571-
return pif.PIF(uuid, self)
572+
return PIF(uuid, self)
572573

573574
def rescan_block_devices_info(self) -> None:
574575
"""
@@ -607,17 +608,17 @@ def disk_is_available(self, disk: DiskDevName) -> bool:
607608
"""
608609
return len(self.ssh(['lsblk', '--noheadings', '-o', 'MOUNTPOINT', '/dev/' + disk]).strip()) == 0
609610

610-
def file_exists(self, filepath, regular_file=True):
611+
def file_exists(self, filepath, regular_file=True) -> bool:
611612
option = '-f' if regular_file else '-e'
612613
return self.ssh_with_result(['test', option, filepath]).returncode == 0
613614

614-
def binary_exists(self, binary):
615+
def binary_exists(self, binary) -> bool:
615616
return self.ssh_with_result(['which', binary]).returncode == 0
616617

617-
def is_symlink(self, filepath):
618+
def is_symlink(self, filepath) -> bool:
618619
return self.ssh_with_result(['test', '-L', filepath]).returncode == 0
619620

620-
def sr_create(self, sr_type, label, device_config, shared=False, verify=False):
621+
def sr_create(self, sr_type, label, device_config, shared=False, verify=False) -> SR:
621622
params = {
622623
'host-uuid': self.uuid,
623624
'type': sr_type,
@@ -637,10 +638,10 @@ def sr_create(self, sr_type, label, device_config, shared=False, verify=False):
637638
wait_for(sr.exists, "Wait for SR to exist")
638639
return sr
639640

640-
def is_master(self):
641+
def is_master(self) -> bool:
641642
return self.ssh(['cat', '/etc/xensource/pool.conf']) == 'master'
642643

643-
def local_vm_srs(self):
644+
def local_vm_srs(self) -> list[SR]:
644645
srs = []
645646
sr_uuids = safe_split(self.xe('pbd-list', {'host-uuid': self.uuid, 'params': 'sr-uuid'}, minimal=True))
646647
for sr_uuid in sr_uuids:
@@ -649,7 +650,7 @@ def local_vm_srs(self):
649650
srs.append(sr)
650651
return srs
651652

652-
def main_sr_uuid(self):
653+
def main_sr_uuid(self) -> str:
653654
""" Main SR is the default SR, the first local SR, or a specific SR depending on data.py's DEFAULT_SR. """
654655
try:
655656
from data import DEFAULT_SR
@@ -695,7 +696,7 @@ def call_plugin(self, plugin_name: str, function: str,
695696
params['args:%s' % k] = v
696697
return self.xe('host-call-plugin', params)
697698

698-
def join_pool(self, pool):
699+
def join_pool(self, pool: Pool):
699700
master = pool.master
700701
self.xe('pool-join', {
701702
'master-address': master.hostname_or_ip,

lib/pool.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import logging
24
import os
35
import traceback
@@ -95,19 +97,19 @@ def exec_on_hosts_on_error_continue(self, func, host_list=[]):
9597
if errors:
9698
raise Exception(f"One or more exceptions were raised in `exec_on_hosts_on_error_continue`: {errors}")
9799

98-
def hosts_uuids(self):
100+
def hosts_uuids(self) -> list[str]:
99101
return safe_split(self.master.xe('host-list', {}, minimal=True))
100102

101-
def host_ip(self, host_uuid):
103+
def host_ip(self, host_uuid) -> str:
102104
return self.master.xe('host-param-get', {'uuid': host_uuid, 'param-name': 'address'})
103105

104-
def get_host_by_uuid(self, host_uuid):
106+
def get_host_by_uuid(self, host_uuid) -> Host:
105107
for host in self.hosts:
106108
if host.uuid == host_uuid:
107109
return host
108110
raise Exception(f"Host with uuid {host_uuid} not found in pool.")
109111

110-
def first_host_that_isnt(self, host):
112+
def first_host_that_isnt(self, host: Host) -> Optional[Host]:
111113
for h in self.hosts:
112114
if h != host:
113115
return h
@@ -122,15 +124,15 @@ def first_shared_sr(self) -> Optional[SR]:
122124
def get_vdi_sr_uuid(self, vdi_uuid: str) -> str:
123125
return self.master.xe('vdi-param-get', {'uuid': vdi_uuid, 'param-name': 'sr-uuid'})
124126

125-
def get_iso_sr(self):
127+
def get_iso_sr(self) -> SR:
126128
uuids = safe_split(self.master.xe('sr-list', {'type': 'iso',
127129
'content-type': 'iso',
128130
'is-tools-sr': False},
129131
minimal=True))
130132
assert len(uuids) == 1 # we may need to allow finer selection if this triggers
131133
return SR(uuids[0], self)
132134

133-
def push_iso(self, local_file, remote_filename=None):
135+
def push_iso(self, local_file, remote_filename=None) -> str:
134136
iso_sr = self.get_iso_sr()
135137
mountpoint = f"/run/sr-mount/{iso_sr.uuid}"
136138
if remote_filename is None:
@@ -280,7 +282,7 @@ def install_custom_uefi_certs(self, auths: Iterable[EFIAuth]):
280282
finally:
281283
host.ssh(['rm', '-f'] + list(auths_dict.values()))
282284

283-
def eject_host(self, host):
285+
def eject_host(self, host: Host):
284286
master = self.master
285287
master.xe('pool-eject', {'host-uuid': host.uuid, 'force': True})
286288
wait_for_not(lambda: host.uuid in self.hosts_uuids(), f"Wait for host {host} to be ejected of pool {master}.")

lib/sr.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1+
from __future__ import annotations
2+
13
import logging
24
import time
35

6+
from typing import TYPE_CHECKING, Optional
7+
8+
if TYPE_CHECKING:
9+
from lib.host import Host
10+
from lib.pool import Pool
11+
412
import lib.commands as commands
513
from lib.common import (
614
GiB,
@@ -14,12 +22,12 @@
1422
from lib.vdi import VDI, ImageFormat
1523

1624
class SR:
17-
def __init__(self, uuid, pool):
25+
def __init__(self, uuid, pool: Pool):
1826
self.uuid = uuid
1927
self.pool = pool
20-
self._is_shared = None # cached value for is_shared()
21-
self._main_host = None # cached value for main_host()
22-
self._type = None # cache value for get_type()
28+
self._is_shared: Optional[bool] = None # cached value for is_shared()
29+
self._main_host: Optional[Host] = None # cached value for main_host()
30+
self._type: Optional[str] = None # cache value for get_type()
2331

2432
def pbd_uuids(self):
2533
return safe_split(self.pool.master.xe('pbd-list', {'sr-uuid': self.uuid}, minimal=True))
@@ -143,7 +151,7 @@ def hosts_uuids(self):
143151
def attached_to_host(self, host):
144152
return host.uuid in self.hosts_uuids()
145153

146-
def main_host(self):
154+
def main_host(self) -> Host:
147155
""" Returns the host in case of a local SR, the master host in case of a shared SR. """
148156
if self._main_host is None:
149157
if self.is_shared():
@@ -155,7 +163,7 @@ def main_host(self):
155163
def content_type(self):
156164
return self.pool.master.xe('sr-param-get', {'uuid': self.uuid, 'param-name': 'content-type'})
157165

158-
def is_shared(self):
166+
def is_shared(self) -> bool:
159167
if self._is_shared is None:
160168
self._is_shared = strtobool(self.pool.master.xe('sr-param-get',
161169
{'uuid': self.uuid, 'param-name': 'shared'}))

lib/vif.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,8 @@ def move(self, network_uuid):
3939

4040
def destroy(self):
4141
self.vm.host.xe('vif-destroy', {'uuid': self.uuid})
42+
43+
def mac_address(self) -> str:
44+
mac_address = self.param_get('MAC')
45+
assert mac_address is not None, "VIF must have a MAC address"
46+
return mac_address

0 commit comments

Comments
 (0)