]>
git.ipfire.org Git - nitsi.git/blob - src/nitsi/machine.py
6 import xml
.etree
.ElementTree
as ET
9 from . import serial_connection
11 logger
= logging
.getLogger("nitsi.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 # self.dom should be always defined
19 # self.snapshot should be also at least None
22 self
.serial_con
= None
25 with
open(vm_xml_file
) as fobj
:
26 self
.vm_xml
= fobj
.read()
27 except FileNotFoundError
as error
:
28 logger
.error("No such file: {}".format(vm_xml_file
))
31 self
.name
= self
.get_name()
32 except BaseException
as error
:
33 logger
.error("Could not get name of the machine: {}".format(vm_xml_file
))
36 self
.log
= logger
.getChild(self
.name
)
37 self
.log
.debug("Name of this machine is {}".format(self
.name
))
40 with
open(snapshot_xml_file
) as fobj
:
41 self
.snapshot_xml
= fobj
.read()
42 except FileNotFoundError
as error
:
43 self
.log
.error("No such file: {}".format(snapshot_xml_file
))
47 if not os
.path
.isfile(self
.image
):
48 self
.log
.error("No such file: {}".format(self
.image
))
50 self
.root_uid
= root_uid
51 self
.disk
= disk
.Disk(image
)
53 self
.username
= username
54 self
.password
= password
57 self
.log
.info("Defining virtual machine")
58 self
.dom
= self
.con
.defineXML(self
.vm_xml
)
60 self
.log
.error("Could not define VM")
64 self
.log
.info("Starting virtual machine")
65 if self
.dom
.create() < 0:
66 self
.log
.error("Could not start VM")
71 self
.log
.info("Shutting down virtual machine")
72 if self
.dom
.shutdown() < 0:
73 self
.log
.error("Could not shutdown VM")
76 self
.log
.warn("Cannot shutdown a not running domain")
79 # We cannot undefine a not defined dom object
81 self
.log
.info("Undefining virtual machine")
84 self
.log
.warn("Cannot undefine a not defined domain")
86 def create_snapshot(self
):
87 self
.log
.info("Creating snapshot of virtual machine")
88 self
.snapshot
= self
.dom
.snapshotCreateXML(self
.snapshot_xml
)
90 if self
.snapshot
== None:
91 self
.log
.error("Could not create snapshot")
94 def revert_snapshot(self
):
95 if self
.snapshot
!= None:
96 self
.log
.info("Reverting snapshot")
97 self
.dom
.revertToSnapshot(self
.snapshot
)
98 self
.log
.info("Deleting snapshot")
99 self
.snapshot
.delete()
101 self
.log
.warn("No active snapshot. Cannot revert and delete snapshot")
103 def is_running(self
):
104 # Only if we have a valid dom object we can check the dom state
108 state
, reason
= self
.dom
.state()
110 if state
== libvirt
.VIR_DOMAIN_RUNNING
:
115 def get_serial_device(self
):
117 if not self
.is_running():
120 xml_root
= ET
.fromstring(self
.dom
.XMLDesc(0))
122 elem
= xml_root
.find("./devices/serial/source")
123 return elem
.get("path")
126 xml_root
= ET
.fromstring(self
.vm_xml
)
128 elem
= xml_root
.find("./name")
131 def check_is_booted_up(self
):
132 serial_con
= serial_connection
.SerialConnection(self
.get_serial_device())
134 serial_con
.write("\n")
135 # This will block till the domain is booted up
140 # This function should initialize the serial connection
141 def serial_init(self
, log_file
=None, log_start_time
=None, longest_machine_name
=10):
143 self
.serial_con
= serial_connection
.SerialConnection(self
.get_serial_device(),
144 username
=self
.username
,
145 password
= self
.password
,
147 log_start_time
=log_start_time
,
149 longest_machine_name
=longest_machine_name
)
150 except BaseException
as e
:
151 self
.log
.error("Could initialize the serial console")
152 self
.log
.exception(e
)
156 # This function should create a ready to use serial connection for this serial domain
157 def serial_connect(self
):
159 # Do the real connect
160 self
.serial_con
.connect()
161 except BaseException
as e
:
162 self
.log
.error("Could not connect to the domain via serial console")
163 self
.log
.exception(e
)
166 def serial_disconnect(self
):
168 self
.serial_con
.disconnect()
169 except BaseException
as e
:
170 self
.log
.error("Could not disconnect from the serial console")
171 self
.log
.exception(e
)
175 return self
.serial_con
.command(cmd
)
177 def copy_in(self
, fr
, to
):
181 self
.disk
.copy_in(fr
, to
)
182 except BaseException
as e
: