Skip to content

Commit 80fd925

Browse files
committed
lib: add more abstractions for Host, Network, PIF, Tunnel, VIF, VLAN
For several tests related to network (mostly traffic rules for now), we need more classes and functions to manipulate xapi objects. - create and manipulate Tunnel - create and manipulate VLAN - additional properties on Network, PIF, VIF - additional function on Host to get service status Signed-off-by: Sebastien Rodot <sebastien.rodot@vates.tech>
1 parent 0845a30 commit 80fd925

6 files changed

Lines changed: 184 additions & 0 deletions

File tree

lib/host.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
from lib.network import Network
3232
from lib.pif import PIF
3333
from lib.sr import SR
34+
from lib.tunnel import Tunnel
35+
from lib.vlan import VLAN
3436
from lib.vm import VM
3537
from lib.xo import xo_cli, xo_object_exists
3638

@@ -716,6 +718,9 @@ def yum_restore_saved_state(self) -> None:
716718
self.saved_packages_list = None
717719
self.saved_rollback_id = None
718720

721+
def service_started(self, name: str) -> bool:
722+
return self.ssh(f'systemctl is-active {name}', check=False) == 'active'
723+
719724
def reboot(self, verify: bool = False) -> None:
720725
logging.info(f"[{self}] Reboot host")
721726
# Running `reboot` directly immediately disconnects the ssh session and makes the ssh client return with an
@@ -1051,6 +1056,9 @@ def pifs(self, device: str | None = None) -> list[PIF]:
10511056

10521057
return [PIF(uuid, self) for uuid in safe_split(self.xe("pif-list", args, minimal=True))]
10531058

1059+
def tunnels(self) -> list[Tunnel]:
1060+
return [Tunnel(self, uuid) for uuid in safe_split(self.xe("tunnel-list", {}, minimal=True))]
1061+
10541062
def create_bond(self, network: Network, pifs: list[PIF], mode: str | None = None) -> Bond:
10551063
args: dict[str, str | bool | dict[str, str]] = {
10561064
'network-uuid': network.uuid,
@@ -1078,3 +1086,35 @@ def create_network(self, label: str, description: str | None = None) -> Network:
10781086
logging.info(f"[{self}] New Network: {uuid}")
10791087

10801088
return Network(self, uuid)
1089+
1090+
def create_vlan(self, network: Network, pif: PIF, vlan: int) -> VLAN:
1091+
args: dict[str, str | bool | dict[str, str]] = {
1092+
'network-uuid': network.uuid,
1093+
'pif-uuid': pif.uuid,
1094+
'vlan': str(vlan),
1095+
}
1096+
1097+
untagged_pif_uuid = self.xe("vlan-create", args, minimal=True)
1098+
uuid = self.xe("pif-param-get", {
1099+
"uuid": untagged_pif_uuid,
1100+
"param-name": "vlan-master-of",
1101+
})
1102+
logging.info(f"New VLAN: {uuid} (untagged-pif: {untagged_pif_uuid})")
1103+
1104+
return VLAN(self, uuid)
1105+
1106+
def create_tunnel(self, network: Network, pif: PIF, protocol: str) -> Tunnel:
1107+
args: dict[str, str | bool | dict[str, str]] = {
1108+
'network-uuid': network.uuid,
1109+
'pif-uuid': pif.uuid,
1110+
'protocol': protocol,
1111+
}
1112+
1113+
access_pif_uuid = self.xe("tunnel-create", args, minimal=True)
1114+
uuid = self.xe("pif-param-get", {
1115+
"uuid": access_pif_uuid,
1116+
"param-name": "tunnel-access-PIF-of",
1117+
})
1118+
logging.info(f"New Tunnel: {uuid} (access-pif: {access_pif_uuid})")
1119+
1120+
return Tunnel(self, uuid)

lib/network.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,8 @@ def managed(self) -> bool:
6464

6565
def MTU(self) -> int:
6666
return int(self.param_get('MTU') or '0')
67+
68+
def bridge(self) -> str:
69+
bridge = self.param_get('bridge')
70+
assert bridge is not None, "network must have a bridge"
71+
return bridge

lib/pif.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,20 @@ def network_uuid(self) -> str:
6666
assert uuid is not None, "unexpected PIF without network-uuid"
6767
return uuid
6868

69+
def ip_configuration_mode(self) -> str:
70+
mode = self.param_get("IP-configuration-mode")
71+
assert mode
72+
return mode
73+
74+
def vlan(self) -> int | None:
75+
vlan_str = self.param_get('VLAN')
76+
assert vlan_str
77+
vlan = int(vlan_str)
78+
if vlan == -1:
79+
return None
80+
else:
81+
return vlan
82+
6983
def reconfigure_ip(self, mode: str) -> None:
7084
self.host.xe("pif-reconfigure-ip", {
7185
"uuid": self.uuid,

lib/tunnel.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
5+
from lib.common import _param_add, _param_clear, _param_get, _param_remove, _param_set
6+
from lib.pif import PIF
7+
8+
from typing import TYPE_CHECKING, Literal, overload
9+
10+
if TYPE_CHECKING:
11+
from lib.host import Host
12+
13+
class Tunnel:
14+
xe_prefix = "tunnel"
15+
16+
def __init__(self, host: Host, uuid: str):
17+
self.host = host
18+
self.uuid = uuid
19+
20+
@overload
21+
def param_get(self, param_name: str, key: str | None = ..., accept_unknown_key: Literal[False] = ...) -> str:
22+
...
23+
24+
@overload
25+
def param_get(
26+
self, param_name: str, key: str | None = ..., accept_unknown_key: Literal[True] = ...
27+
) -> str | None:
28+
...
29+
30+
def param_get(self, param_name: str, key: str | None = None, accept_unknown_key: bool = False) -> str | None:
31+
return _param_get(self.host, self.xe_prefix, self.uuid, param_name, key, accept_unknown_key)
32+
33+
def param_set(self, param_name: str, value: str | bool | dict[str, str], key: str | None = None) -> None:
34+
_param_set(self.host, self.xe_prefix, self.uuid, param_name, value, key)
35+
36+
def param_remove(self, param_name: str, key: str, accept_unknown_key: bool = False) -> None:
37+
_param_remove(self.host, self.xe_prefix, self.uuid, param_name, key, accept_unknown_key)
38+
39+
def param_add(self, param_name: str, value: str, key: str | None = None) -> None:
40+
_param_add(self.host, self.xe_prefix, self.uuid, param_name, value, key)
41+
42+
def param_clear(self, param_name: str) -> None:
43+
_param_clear(self.host, self.xe_prefix, self.uuid, param_name)
44+
45+
def destroy(self):
46+
logging.info(f"Destroying Tunnel: {self.uuid}")
47+
self.host.xe('tunnel-destroy', {'uuid': self.uuid})
48+
49+
def access_pif(self) -> PIF:
50+
uuid = self.param_get("access-PIF")
51+
assert uuid
52+
return PIF(uuid, self.host)
53+
54+
def transport_pif(self) -> PIF:
55+
uuid = self.param_get("transport-PIF")
56+
assert uuid
57+
return PIF(uuid, self.host)

lib/vif.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import time
55

66
from lib.common import _param_add, _param_clear, _param_get, _param_remove, _param_set
7+
from lib.network import Network
78

89
from typing import TYPE_CHECKING, Literal, overload
910

@@ -134,3 +135,8 @@ def configure_ipv6(
134135
gateway: str | None = None,
135136
) -> None:
136137
self._configure("ipv6", mode, address, gateway)
138+
139+
def network(self) -> Network:
140+
network_uuid = self.param_get('network-uuid')
141+
assert network_uuid is not None, "VIF must have a network-uuid"
142+
return Network(self.vm.host, network_uuid)

lib/vlan.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
5+
from lib.common import _param_add, _param_clear, _param_get, _param_remove, _param_set
6+
from lib.pif import PIF
7+
8+
from typing import TYPE_CHECKING, Literal, overload
9+
10+
if TYPE_CHECKING:
11+
from lib.host import Host
12+
13+
class VLAN:
14+
xe_prefix = "vlan"
15+
16+
def __init__(self, host: Host, uuid: str):
17+
self.host = host
18+
self.uuid = uuid
19+
20+
@overload
21+
def param_get(self, param_name: str, key: str | None = ..., accept_unknown_key: Literal[False] = ...) -> str:
22+
...
23+
24+
@overload
25+
def param_get(
26+
self, param_name: str, key: str | None = ..., accept_unknown_key: Literal[True] = ...
27+
) -> str | None:
28+
...
29+
30+
def param_get(self, param_name: str, key: str | None = None, accept_unknown_key: bool = False) -> str | None:
31+
return _param_get(self.host, self.xe_prefix, self.uuid, param_name, key, accept_unknown_key)
32+
33+
def param_set(self, param_name: str, value: str | bool | dict[str, str], key: str | None = None) -> None:
34+
_param_set(self.host, self.xe_prefix, self.uuid, param_name, value, key)
35+
36+
def param_remove(self, param_name: str, key: str, accept_unknown_key: bool = False) -> None:
37+
_param_remove(self.host, self.xe_prefix, self.uuid, param_name, key, accept_unknown_key)
38+
39+
def param_add(self, param_name: str, value: str, key: str | None = None) -> None:
40+
_param_add(self.host, self.xe_prefix, self.uuid, param_name, value, key)
41+
42+
def param_clear(self, param_name: str) -> None:
43+
_param_clear(self.host, self.xe_prefix, self.uuid, param_name)
44+
45+
def destroy(self):
46+
logging.info(f"Destroying VLAN: {self.uuid}")
47+
self.host.xe('vlan-destroy', {'uuid': self.uuid})
48+
49+
def tag(self) -> int:
50+
tag = self.param_get('tag')
51+
assert tag
52+
return int(tag)
53+
54+
def tagged_pif(self) -> PIF:
55+
uuid = self.param_get("tagged-PIF")
56+
assert uuid
57+
return PIF(uuid, self.host)
58+
59+
def untagged_pif(self) -> PIF:
60+
uuid = self.param_get("untagged-PIF")
61+
assert uuid
62+
return PIF(uuid, self.host)

0 commit comments

Comments
 (0)