]>
Commit | Line | Data |
---|---|---|
a6a7fe20 JS |
1 | #!/usr/bin/python3 |
2 | ||
3 | import xml.etree.ElementTree as ET | |
4 | ||
2fa4467d | 5 | from nitsi.disk import disk |
a6a7fe20 | 6 | |
2fa4467d | 7 | from nitsi.serial_connection import serial_connection |
a6a7fe20 | 8 | |
a6a7fe20 JS |
9 | import os |
10 | import libvirt | |
11 | ||
1ed8ca9f JS |
12 | import logging |
13 | ||
14 | logger = logging.getLogger("nitsi.machine") | |
a6a7fe20 JS |
15 | |
16 | class 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 | ||
b4936764 | 120 | def login(self, log_file): |
a6a7fe20 | 121 | try: |
b4936764 | 122 | self.serial_con = serial_connection(self.get_serial_device(), username=self.username, log_file=log_file, name=self.name) |
a6a7fe20 JS |
123 | self.serial_con.login(self.password) |
124 | except BaseException as e: | |
125 | self.log.error("Could not connect to the domain via serial console") | |
61bf2ba3 JS |
126 | self.log.exception(e) |
127 | raise e | |
a6a7fe20 JS |
128 | |
129 | def cmd(self, cmd): | |
130 | return self.serial_con.command(cmd) | |
131 | ||
132 | def copy_in(self, fr, to): | |
133 | try: | |
134 | self.disk.mount(self.root_uid, "/") | |
135 | self.disk.copy_in(fr, to) | |
136 | except BaseException as e: | |
137 | self.log.error(e) | |
138 | finally: | |
139 | self.disk.umount("/") | |
140 | self.disk.close() |