Skip to content

Commit 011041e

Browse files
committed
Add more abstractions for Host, Network, PIF, Tunnel, VIF, VLAN
Signed-off-by: Sebastien Rodot <sebastien.rodot@vates.tech>
1 parent a2ad167 commit 011041e

6 files changed

Lines changed: 181 additions & 0 deletions

File tree

lib/host.py

Lines changed: 37 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

@@ -1037,6 +1039,9 @@ def pifs(self, device: str | None = None) -> list[PIF]:
10371039

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

1042+
def tunnels(self) -> list[Tunnel]:
1043+
return [Tunnel(self, uuid) for uuid in safe_split(self.xe("tunnel-list", {}, minimal=True))]
1044+
10401045
def create_bond(self, network: Network, pifs: list[PIF], mode: str | None = None) -> Bond:
10411046
args: dict[str, str | bool | dict[str, str]] = {
10421047
'network-uuid': network.uuid,
@@ -1064,3 +1069,35 @@ def create_network(self, label: str, description: str | None = None) -> Network:
10641069
logging.info(f"[{self}] New Network: {uuid}")
10651070

10661071
return Network(self, uuid)
1072+
1073+
def create_vlan(self, network: Network, pif: PIF, vlan: int) -> VLAN:
1074+
args: dict[str, str | bool | dict[str, str]] = {
1075+
'network-uuid': network.uuid,
1076+
'pif-uuid': pif.uuid,
1077+
'vlan': str(vlan),
1078+
}
1079+
1080+
untagged_pif_uuid = self.xe("vlan-create", args, minimal=True)
1081+
uuid = self.xe("pif-param-get", {
1082+
"uuid": untagged_pif_uuid,
1083+
"param-name": "vlan-master-of",
1084+
})
1085+
logging.info(f"New VLAN: {uuid} (untagged-pif: {untagged_pif_uuid})")
1086+
1087+
return VLAN(self, uuid)
1088+
1089+
def create_tunnel(self, network: Network, pif: PIF, protocol: str) -> Tunnel:
1090+
args: dict[str, str | bool | dict[str, str]] = {
1091+
'network-uuid': network.uuid,
1092+
'pif-uuid': pif.uuid,
1093+
'protocol': protocol,
1094+
}
1095+
1096+
access_pif_uuid = self.xe("tunnel-create", args, minimal=True)
1097+
uuid = self.xe("pif-param-get", {
1098+
"uuid": access_pif_uuid,
1099+
"param-name": "tunnel-access-PIF-of",
1100+
})
1101+
logging.info(f"New Tunnel: {uuid} (access-pif: {access_pif_uuid})")
1102+
1103+
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
@@ -3,6 +3,7 @@
33
import logging
44

55
from lib.common import _param_add, _param_clear, _param_get, _param_remove, _param_set
6+
from lib.network import Network
67

78
from typing import TYPE_CHECKING
89

@@ -64,3 +65,8 @@ def plug(self) -> None:
6465
def unplug(self) -> None:
6566
logging.info("Unplugging VIF %s on VM %s", self.param_get('device'), self.vm.uuid)
6667
self.vm.host.xe('vif-unplug', {'uuid': self.uuid})
68+
69+
def network(self) -> Network:
70+
network_uuid = self.param_get('network-uuid')
71+
assert network_uuid is not None, "VIF must have a network-uuid"
72+
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)