forked from saschpe/libvirt-hook-qemu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
qemu
executable file
·92 lines (73 loc) · 3.22 KB
/
qemu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/python
"""Libvirt port-forwarding hook.
Libvirt hook for setting up firewalld port-forwarding rules when using NAT-ed
networking.
"""
__author__ = "Przemysław Szypowicz <[email protected]>"
__version__ = "0.2.0"
import os
import json
import subprocess
import sys
CONFIG_PATH = os.path.dirname(os.path.abspath(__file__))
CONFIG_FILENAME = os.path.join(CONFIG_PATH, "qemu.json")
CONFIG_SCHEMA_FILENAME = os.path.join(CONFIG_PATH, "qemu.schema.json")
FIREWALLD_BINARY = subprocess.check_output(["which", "firewall-cmd"]).strip()
def host_ip():
"""Returns the default route interface IP (if any).
In other words, the public IP used to access the virtualization host. It
is used as default public IP for guest forwarding rules should they not
specify a different public IP to forward from.
"""
if not hasattr(host_ip, "_host_ip"):
cmd = "ip route | grep default | cut -d' ' -f5"
default_route_interface = subprocess.check_output(cmd, shell=True).decode().strip()
cmd = "ip addr show {0} | grep -E 'inet .*{0}' | cut -d' ' -f6 | cut -d'/' -f1".format(default_route_interface)
host_ip._host_ip = subprocess.check_output(cmd, shell=True).decode().strip()
return host_ip._host_ip
def config(validate=True):
"""Returns the hook configuration.
Assumes that the file /etc/libvirt/hooks/qemu.json exists and contains
JSON-formatted configuration data. Optionally tries to validate the
configuration if the 'jsonschema' module is available.
Args:
validate: Use JSON schema validation
"""
if not hasattr(config, "_conf"):
with open(CONFIG_FILENAME, "r") as f:
config._conf = json.load(f)
if validate:
# Try schema validation but avoid hard 'jsonschema' requirement:
try:
import jsonschema
with open(CONFIG_SCHEMA_FILENAME, "r") as f:
config._schema = json.load(f)
jsonschema.validate(config._conf,
config._schema,
format_checker=jsonschema.FormatChecker())
except ImportError:
pass
return config._conf
def firewalld_forward(action, domain):
"""Set iptables port-forwarding rules based on domain configuration.
Args:
action: iptables rule actions (one of '-I', '-A' or '-D')
domain: Libvirt domain configuration
"""
public_ip = domain.get("public_ip", host_ip())
# Iterate over protocols (tcp, udp, icmp, ...)
for protocol in domain["port_map"]:
# Iterate over all public/private port pairs for the protocol
for public_port, private_port in domain["port_map"].get(protocol):
args = [FIREWALLD_BINARY,
"--{0}-forward-port=port={1}:proto=tcp:toport={2}:toaddr={3}".format(action,public_port,private_port,domain["private_ip"])]
subprocess.call(args)
if __name__ == "__main__":
vir_domain, action = sys.argv[1:3]
domain = config().get(vir_domain)
if domain is None:
sys.exit(0)
if action in ["stopped", "reconnect"]:
firewalld_forward("remove", domain)
if action in ["start", "reconnect"]:
firewalld_forward("add", domain)