]> git.ipfire.org Git - nitsi.git/blame - src/nitsi/machine.py
Merge branch 'master' of ssh://git.ipfire.org/pub/git/people/jschlag/nitsi
[nitsi.git] / src / nitsi / machine.py
CommitLineData
a6a7fe20
JS
1#!/usr/bin/python3
2
3import xml.etree.ElementTree as ET
4
2fa4467d 5from nitsi.disk import disk
a6a7fe20 6
2fa4467d 7from nitsi.serial_connection import serial_connection
a6a7fe20 8
a6a7fe20
JS
9import os
10import libvirt
11
1ed8ca9f
JS
12import logging
13
14logger = logging.getLogger("nitsi.machine")
a6a7fe20
JS
15
16class machine():
7005787e 17 def __init__(self, libvirt_con, vm_xml_file, snapshot_xml_file, image, root_uid, username, password):
1ed8ca9f 18 self.log = logger.getChild(os.path.basename(vm_xml_file))
7005787e 19 self.con = libvirt_con
a6a7fe20
JS
20 try:
21 with open(vm_xml_file) as fobj:
22 self.vm_xml = fobj.read()
23 except FileNotFoundError as error:
341e7373
JS
24 logger.error("No such file: {}".format(vm_xml_file))
25
26 try:
27 self.name = self.get_name()
28 except BaseException as error:
29 logger.error("Could not get name of the machine: {}".format(vm_xml_file))
30 raise error
31
32 self.log = logger.getChild(self.name)
33 self.log.debug("Name of this machine is {}".format(self.name))
a6a7fe20
JS
34
35 try:
36 with open(snapshot_xml_file) as fobj:
37 self.snapshot_xml = fobj.read()
38 except FileNotFoundError as error:
39 self.log.error("No such file: {}".format(snapshot_xml_file))
40
41 self.image = image
42
43 if not os.path.isfile(self.image):
44 self.log.error("No such file: {}".format(self.image))
45
46 self.root_uid = root_uid
47 self.disk = disk(image)
48
49 self.username = username
50 self.password = password
51
52 def define(self):
8b744f18 53 self.dom = self.con.defineXML(self.vm_xml)
a6a7fe20
JS
54 if self.dom == None:
55 self.log.error("Could not define VM")
56 raise BaseException
57
58 def start(self):
59 if self.dom.create() < 0:
60 self.log.error("Could not start VM")
61 raise BaseException
62
63 def shutdown(self):
64 if self.is_running():
65 if self.dom.shutdown() < 0:
66 self.log.error("Could not shutdown VM")
67 raise BaseException
68 else:
69 self.log.error("Domain is not running")
70
71 def undefine(self):
72 self.dom.undefine()
73
74 def create_snapshot(self):
75
76 self.snapshot = self.dom.snapshotCreateXML(self.snapshot_xml)
77
78 if not self.snapshot:
79 self.log.error("Could not create snapshot")
80 raise BaseException
81
82 def revert_snapshot(self):
83 self.dom.revertToSnapshot(self.snapshot)
84 self.snapshot.delete()
85
86 def is_running(self):
87
88 state, reason = self.dom.state()
89
90 if state == libvirt.VIR_DOMAIN_RUNNING:
91 return True
92 else:
93 return False
94
95 def get_serial_device(self):
96
97 if not self.is_running():
98 raise BaseException
99
100 xml_root = ET.fromstring(self.dom.XMLDesc(0))
101
102 elem = xml_root.find("./devices/serial/source")
103 return elem.get("path")
104
341e7373
JS
105 def get_name(self):
106 xml_root = ET.fromstring(self.vm_xml)
107
108 elem = xml_root.find("./name")
109 return elem.text
110
a6a7fe20
JS
111 def check_is_booted_up(self):
112 serial_con = serial_connection(self.get_serial_device())
113
114 serial_con.write("\n")
115 # This will block till the domain is booted up
116 serial_con.read(1)
117
118 #serial_con.close()
119
fc35cba1 120 def login(self, log_file, log_start_time=None, longest_machine_name=10):
a6a7fe20 121 try:
6c352a80
JS
122 self.serial_con = serial_connection(self.get_serial_device(),
123 username=self.username,
124 log_file=log_file,
125 log_start_time=log_start_time,
fc35cba1
JS
126 name=self.name,
127 longest_machine_name=longest_machine_name)
a6a7fe20
JS
128 self.serial_con.login(self.password)
129 except BaseException as e:
130 self.log.error("Could not connect to the domain via serial console")
61bf2ba3
JS
131 self.log.exception(e)
132 raise e
a6a7fe20
JS
133
134 def cmd(self, cmd):
135 return self.serial_con.command(cmd)
136
137 def copy_in(self, fr, to):
138 try:
139 self.disk.mount(self.root_uid, "/")
140 self.disk.copy_in(fr, to)
141 except BaseException as e:
142 self.log.error(e)
143 finally:
144 self.disk.umount("/")
145 self.disk.close()