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