1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import binascii
17 import os
18 import sys
19
20 try:
21 import libvirt
22 except ImportError:
23
24
25 libvirt = None
26
27 from rhn.i18n import sstr
28
29 from virtualization.domain_config import DomainConfig
30 from virtualization.errors import VirtualizationException
31 from virtualization.util import dehyphenize_uuid, \
32 hyphenize_uuid, \
33 is_host_uuid
34
35
36
37
38
39 CONFIG_DIR = '/etc/sysconfig/rhn/virt'
40 STANDARD_CONFIG_TEMPLATE = """
41 <domain type='xen'>
42 <name>%(name)s</name>
43 <bootloader>/usr/bin/pygrub</bootloader>
44 <memory>%(mem_kb)s</memory>
45 <vcpu>%(vcpus)s</vcpu>
46 <uuid>%(uuid)s</uuid>
47 <on_reboot>restart</on_reboot>
48 <on_poweroff>destroy</on_poweroff>
49 <on_crash>preserve</on_crash>
50 <devices>
51 <disk type='file'>
52 <source file='%(disk)s'/>
53 <target dev='xvda'/>
54 </disk>
55 <interface type='bridge'>
56 <source bridge='xenbr0'/>
57 <mac address='%(mac)s'/>
58 <script path='/etc/xen/scripts/vif-bridge'/>
59 </interface>
60 </devices>
61 </domain>
62 """
63
64
65
66
67
69
71 self.__path = CONFIG_DIR
72 self.conn = libvirt.openReadOnly(None)
73 if not self.conn:
74 raise VirtualizationException("Failed to open connection to hypervisor.")
75
76 - def get_config_path(self, uuid):
77 cfg_filename = "%s.xml" % uuid
78 cfg_pathname = os.path.join(self.__path, cfg_filename)
79 return cfg_pathname
80
81 - def is_known_config(self, uuid):
82 """
83 Returns true if a config for the given uuid is saved in the directory.
84 """
85 path = self.get_config_path(uuid)
86 return os.path.exists(path)
87
88 - def load_config(self, uuid):
89 """
90 This function loads a domain's configuration by its UUID. A
91 DomainConfig object is returned.
92 """
93 return DomainConfig(self.__path, uuid)
94
95 - def create_standard_config(self, uuid, name, mem_kb, vcpus, disk, mac):
96
97 boot_params = { 'name' : name,
98 'mem_kb' : mem_kb,
99 'vcpus' : vcpus,
100 'uuid' : hyphenize_uuid(uuid),
101 'disk' : disk,
102 'mac' : mac }
103
104 xml = STANDARD_CONFIG_TEMPLATE % boot_params
105
106 self.__write_xml_file(uuid, xml)
107
108 - def save_unknown_domain_configs(self, domain_uuids):
109 """
110 This function saves the configuration for any domains whose UUIDs are
111 passed in the domain_uuids list. If the UUID is already known, it is
112 skipped.
113 """
114
115 for uuid in domain_uuids:
116
117 uuid = sstr(uuid)
118
119
120 if not is_host_uuid(uuid) and not self.is_known_config(uuid):
121
122
123
124 dehyphenized_uuid = dehyphenize_uuid(uuid)
125 uuid_as_num = binascii.unhexlify(dehyphenized_uuid)
126
127
128 try:
129 domain = self.conn.lookupByUUID(uuid_as_num)
130 except libvirt.libvirtError:
131 lve = sys.exc_info()[1]
132 raise VirtualizationException("Failed to obtain handle to domain %s: %s" % (uuid, repr(lve)))
133
134
135 xml = domain.XMLDesc(0)
136
137
138
139 cfg_file_path = self.__write_xml_file(uuid, xml)
140 new_config = DomainConfig(self.__path, uuid)
141
142
143
144
145 if not new_config.isInstallerConfig():
146
147
148
149 self.__fixup_config_for_restart(new_config)
150
151
152
153 new_config.save()
154
155 else:
156
157 os.unlink(cfg_file_path)
158
160 """
161 This function edits the given configuration so that it can be used in
162 subsequent calls to libvirt's createLinux call. Specifically, the
163 following modifications are made:
164
165 - Remove the "id" attribute from the <domain> tag. The "id" is
166 whatever the hypervisor wants to assign to it, so we should not
167 try to assign it explicitly.
168
169 - Determine whether the config contains an <os> section.
170 - If it does, check whether the kernel and the initrd files
171 it refers to actually exist on disk.
172 - If so, do nothing.
173 - If not, remove the entire <os> section and insert a
174 <bootloader> section if one does not yet exist. These
175 files might not exist if the instance was started by xm
176 using a bootloader such as pygrub, which makes temporary
177 copies of the kernel & initrd and then removes them after
178 starting the instance.
179 - If it does not, ensure there is a <bootloader> section or
180 add one if needed.
181 """
182
183
184 if config.hasConfigItem(DomainConfig.DOMAIN_ID):
185 config.removeConfigItem(DomainConfig.DOMAIN_ID)
186
187 if self.conn.getType() == 'QEMU':
188
189 return
190
191 boot_images_exist = 0
192
193 if config.hasConfigItem(DomainConfig.KERNEL_PATH) and \
194 config.hasConfigItem(DomainConfig.RAMDISK_PATH):
195
196 kernel_path = config.getConfigItem(DomainConfig.KERNEL_PATH)
197 ramdisk_path = config.getConfigItem(DomainConfig.KERNEL_PATH)
198
199 if os.path.exists(kernel_path) and os.path.exists(ramdisk_path):
200 boot_images_exist = 1
201
202
203
204 if not boot_images_exist:
205 if config.hasConfigItem(DomainConfig.OS):
206 config.removeConfigItem(DomainConfig.OS)
207
208 if not config.hasConfigItem(DomainConfig.BOOTLOADER):
209 config.setConfigItem(DomainConfig.BOOTLOADER, "/usr/bin/pygrub")
210
211
212 - def __write_xml_file(self, uuid, xml):
213 cfg_pathname = self.get_config_path(uuid)
214 cfg_file = open(cfg_pathname, "w")
215 cfg_file.write(xml.strip())
216 cfg_file.close()
217
218 return cfg_pathname
219