Merge ~paelzer/uvtool:per-arch-templates-onmaster into uvtool:master

Proposed by Christian Ehrhardt 
Status: Merged
Approved by: Robie Basak
Approved revision: aa7a10fa8578ae17b9bdf60b2fb6ea310373c6c0
Merged at revision: aa7a10fa8578ae17b9bdf60b2fb6ea310373c6c0
Proposed branch: ~paelzer/uvtool:per-arch-templates-onmaster
Merge into: uvtool:master
Diff against target: 297 lines (+109/-31)
7 files modified
contrib/README (+0/-5)
man/uvt-kvm.1 (+12/-1)
setup.py (+4/-1)
template-aarch64.xml (+14/-10)
template-ppc64le.xml (+0/-0)
template-s390x.xml (+22/-0)
uvtool/libvirt/kvm.py (+57/-14)
Reviewer Review Type Date Requested Status
Robie Basak Approve
Review via email: mp+332412@code.launchpad.net

Description of the change

Hi,
as discussed the re-written and tested contribution for better multi-arch support.

Suggestion for the debian/changelog when you carry this from master:

  * Select the default template per host architecture (LP: #1452016)
    - Provide and auto-select per arch templates for aarch64, ppc64le and s390x
    - reject console redirection on s390x due to sclp console.
    - Track UNDEF_FLAGS to handle nvram being used and properly removed in
      aarch64 use cases.
    - create: add guest-arch option to override default template arch
    - Document template architecture changes in man pages

A matching commit for the changelog would be at https://git.launchpad.net/~paelzer/uvtool/commit/?id=c4679bb197635fb5ee54061282f83ab33cb82a09
Those two branches are identical other than this commit to debian/changelog.

A testable build is in https://launchpad.net/~ci-train-ppa-service/+archive/ubuntu/2972

To post a comment you must log in.
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Hmm, all spawning was fine, but the nvram cleanup on arm does need an improvement.
Expect a follow up fix into this branch rather soon.

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

In fact the destroy now works (as I tested before), but it throws an error messages.
Maybe it does a try to remove before where the flag I added is still missing.

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Ok, now also the destroy action works as intended.

Revision history for this message
Robie Basak (racb) wrote :

Looks good, thanks! Comments requesting some minor changes inline.

review: Needs Fixing
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

All minor changes agreed, pushing follow up fixes to this MP now

Revision history for this message
Robie Basak (racb) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/contrib/README b/contrib/README
2index f0bfd07..7fb3968 100644
3--- a/contrib/README
4+++ b/contrib/README
5@@ -1,11 +1,6 @@
6 Here are some pieces contributed by others that haven't made it into uvtool
7 proper yet. They may change or disappear between releases.
8
9-Additional architecture support:
10-
11-arch/arm64.xml - contributed by Ali in LP: #1349854
12-arch/ppc64el.xml - contributed by Christian Ehrhardt in LP: #1573820
13-
14 Others:
15
16 ussh/ - contributed by Scott Moser in https://gist.github.com/smoser/88a5a77ab0debf268b945d46314ea447
17diff --git a/man/uvt-kvm.1 b/man/uvt-kvm.1
18index 9db5c33..e6fae4f 100644
19--- a/man/uvt-kvm.1
20+++ b/man/uvt-kvm.1
21@@ -372,6 +372,8 @@ This options enables retrospective examination of VM console output, but
22 breaks
23 .B virsh\ console
24 for interactive use.
25+On s390x this option is currently not supported due to incompatibilties with
26+the sclp console used.
27
28 .SH CLOUD-INIT CONFIGURATION OPTIONS
29
30@@ -452,7 +454,16 @@ a new VM's definition. This is dynamically altered before domain
31 creation; see LIBVIRT DOMAIN DEFINITION OPTIONS.
32
33 Default:
34-.IR /usr/share/uvtool/default.xml .
35+.IR /usr/share/uvtool/libvirt/template.xml .
36+
37+.TP
38+.BI --guest-arch\ architecture
39+Specify the architecture of the guest template file that will be selected.
40+If an explicit \fB--template\fR is given then \fB--guest-arch\fR has no effect.
41+If neither \fB--template\fR nor \fB--guest-arch\fR are set the hosts
42+architecture will be used to determine the default xml template.
43+
44+Default: The architecture of the host system.
45
46 .TP
47 .BI --user-data\ user_data_file
48diff --git a/setup.py b/setup.py
49index 59404b7..9f7d8eb 100644
50--- a/setup.py
51+++ b/setup.py
52@@ -29,6 +29,9 @@ distutils.core.setup(
53 packages=['uvtool.libvirt'],
54 scripts=glob.glob('bin/*'),
55 data_files=[
56- ('/usr/share/uvtool/libvirt', ['template.xml', 'remote-wait.sh'])
57+ ('/usr/share/uvtool/libvirt', ['template.xml', 'remote-wait.sh',
58+ 'template-aarch64.xml',
59+ 'template-ppc64le.xml',
60+ 'template-s390x.xml'])
61 ],
62 )
63diff --git a/contrib/arch/arm64.xml b/template-aarch64.xml
64index fa57a2a..bef38ff 100644
65--- a/contrib/arch/arm64.xml
66+++ b/template-aarch64.xml
67@@ -1,22 +1,26 @@
68-<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
69+<domain type='kvm'>
70 <os>
71 <type arch='aarch64' machine='virt'>hvm</type>
72- <loader readonly='yes' type='rom'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
73- <boot dev='hd' />
74+ <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
75+ <nvram template='/usr/share/AAVMF/AAVMF_CODE.fd'>/tmp/AAVMF_CODE.fd</nvram>
76+ <boot dev='hd'/>
77 </os>
78+ <features>
79+ <acpi/>
80+ <apic/>
81+ <pae/>
82+ </features>
83 <cpu mode='custom' match='exact'>
84 <model fallback='allow'>host</model>
85 </cpu>
86- <clock offset='utc'/>
87 <devices>
88- <emulator>/usr/bin/qemu-system-aarch64</emulator>
89- <console type='pty'/>
90- <console type='pty'>
91- <target type='virtio' port='0'/>
92- </console>
93 <interface type='network'>
94 <source network='default'/>
95 <model type='virtio'/>
96 </interface>
97- </devices>
98+ <serial type='pty'>
99+ <source path='/dev/pts/3'/>
100+ <target port='0'/>
101+ </serial>
102+ </devices>
103 </domain>
104diff --git a/contrib/arch/ppc64el.xml b/template-ppc64le.xml
105index e861561..e861561 100644
106--- a/contrib/arch/ppc64el.xml
107+++ b/template-ppc64le.xml
108diff --git a/template-s390x.xml b/template-s390x.xml
109new file mode 100644
110index 0000000..ac65e6a
111--- /dev/null
112+++ b/template-s390x.xml
113@@ -0,0 +1,22 @@
114+<domain type='kvm'>
115+ <os>
116+ <type>hvm</type>
117+ <boot dev='hd'/>
118+ </os>
119+ <features>
120+ <acpi/>
121+ <apic/>
122+ <pae/>
123+ </features>
124+ <devices>
125+ <interface type='network'>
126+ <source network='default'/>
127+ <model type='virtio'/>
128+ </interface>
129+ <console type='pty' tty='/dev/pts/3'>
130+ <source path='/dev/pts/3'/>
131+ <target type='sclp' port='0'/>
132+ <alias name='console0'/>
133+ </console>
134+ </devices>
135+</domain>
136diff --git a/uvtool/libvirt/kvm.py b/uvtool/libvirt/kvm.py
137index ac24ad3..ba1d971 100755
138--- a/uvtool/libvirt/kvm.py
139+++ b/uvtool/libvirt/kvm.py
140@@ -27,6 +27,7 @@ import errno
141 import functools
142 import itertools
143 import os
144+import platform
145 import shutil
146 import signal
147 import string
148@@ -47,7 +48,10 @@ import uvtool.libvirt.simplestreams
149 import uvtool.ssh
150 import uvtool.wait
151
152+
153+ARCH = platform.machine()
154 DEFAULT_TEMPLATE = '/usr/share/uvtool/libvirt/template.xml'
155+
156 DEFAULT_REMOTE_WAIT_SCRIPT = '/usr/share/uvtool/libvirt/remote-wait.sh'
157 POOL_NAME = 'uvtool'
158
159@@ -63,6 +67,21 @@ class InsecureError(RuntimeError):
160 pass
161
162
163+def get_template_path(arch):
164+ if arch == 'aarch64':
165+ return '/usr/share/uvtool/libvirt/template-aarch64.xml'
166+ elif arch == 'ppc64le':
167+ return '/usr/share/uvtool/libvirt/template-ppc64le.xml'
168+ elif arch == 's390x':
169+ return '/usr/share/uvtool/libvirt/template-s390x.xml'
170+ elif arch == 'x86_64' or arch == 'i686':
171+ return DEFAULT_TEMPLATE
172+ else:
173+ print("Warning: unknown architecture '%s' using defaults" % arch,
174+ file=sys.stderr)
175+ return DEFAULT_TEMPLATE
176+
177+
178 # From: http://www.chiark.greenend.org.uk/ucgi/~cjwatson/blosxom/2009-07-02-python-sigpipe.html
179 def subprocess_setup():
180 # Python installs a SIGPIPE handler by default. This is usually not what
181@@ -285,8 +304,8 @@ def create_cow_volume_by_path(backing_volume_path, new_volume_name,
182 return pool.createXML(etree.tostring(new_vol), 0)
183
184
185-def compose_domain_xml(name, volumes, cpu=1, memory=512, unsafe_caching=False,
186- template_path=DEFAULT_TEMPLATE, log_console_output=False, bridge=None,
187+def compose_domain_xml(name, volumes, template_path, cpu=1, memory=512,
188+ unsafe_caching=False, log_console_output=False, bridge=None,
189 ssh_known_hosts=None):
190 tree = etree.parse(template_path)
191 domain = tree.getroot()
192@@ -339,14 +358,18 @@ def compose_domain_xml(name, volumes, cpu=1, memory=512, unsafe_caching=False,
193 )
194
195 if log_console_output:
196- print(
197- "Warning: logging guest console output introduces a DoS " +
198+ if ARCH == 's390x':
199+ raise CLIError("logging guest console output is currently"
200+ "not supported on s390x.")
201+ else:
202+ print(
203+ "Warning: logging guest console output introduces a DoS " +
204 "security problem on the host and should not be used in " +
205 "production.",
206- file=sys.stderr
207- )
208- etree.strip_elements(devices, 'serial')
209- devices.append(E.serial(E.target(port='0'), type='stdio'))
210+ file=sys.stderr
211+ )
212+ etree.strip_elements(devices, 'serial')
213+ devices.append(E.serial(E.target(port='0'), type='stdio'))
214
215 if ssh_known_hosts:
216 metadata = domain.find('metadata')
217@@ -373,8 +396,8 @@ def get_base_image(filters):
218 return result[0]
219
220
221-def create(hostname, filters, user_data_fobj, meta_data_fobj, memory=512,
222- cpu=1, disk=2, unsafe_caching=False, template_path=DEFAULT_TEMPLATE,
223+def create(hostname, filters, user_data_fobj, meta_data_fobj, template_path,
224+ memory=512, cpu=1, disk=2, unsafe_caching=False,
225 log_console_output=False, bridge=None, backing_image_file=None,
226 start=True, ssh_known_hosts=None, ephemeral_disks=None):
227 if backing_image_file is None:
228@@ -425,7 +448,12 @@ def create(hostname, filters, user_data_fobj, meta_data_fobj, memory=512,
229 try:
230 domain.create()
231 except:
232- domain.undefine()
233+ if ARCH == 'aarch64':
234+ # aarch runs with nvram per our default template, flag
235+ # needed to be able to remove those on undefine
236+ domain.undefineFlags(libvirt.VIR_DOMAIN_UNDEFINE_NVRAM)
237+ else:
238+ domain.undefine()
239 raise
240 except:
241 for vol in undo_volume_creation:
242@@ -463,7 +491,12 @@ def destroy(hostname):
243
244 delete_domain_volumes(conn, domain)
245
246- domain.undefine()
247+ if ARCH == 'aarch64':
248+ # aarch runs with nvram per our default template, flag
249+ # needed to be able to remove those on undefine
250+ domain.undefineFlags(libvirt.VIR_DOMAIN_UNDEFINE_NVRAM)
251+ else:
252+ domain.undefine()
253
254
255 def get_lts_series():
256@@ -607,6 +640,14 @@ def main_create(parser, args):
257 meta_data_fobj = apply_default_fobj(
258 args, 'meta_data', create_default_meta_data
259 )
260+
261+ template = get_template_path(ARCH)
262+ if args.guest_arch:
263+ template = get_template_path(args.guest_arch)
264+ # an explicit template overrides general and guest-arch defaults
265+ if args.template:
266+ template = args.template
267+
268 if args.backing_image_file:
269 abs_image_backing_file = os.path.abspath(args.backing_image_file)
270 else:
271@@ -619,7 +660,7 @@ def main_create(parser, args):
272 disk=args.disk,
273 log_console_output=args.log_console_output,
274 memory=args.memory,
275- template_path=args.template,
276+ template_path=template,
277 unsafe_caching=args.unsafe_caching,
278 start=not args.no_start,
279 ssh_known_hosts=ssh_known_hosts,
280@@ -746,7 +787,7 @@ def main(args):
281 create_subparser.set_defaults(func=main_create)
282 create_subparser.add_argument(
283 '--developer', '-d', nargs=0, action=DeveloperOptionAction)
284- create_subparser.add_argument('--template', default=DEFAULT_TEMPLATE)
285+ create_subparser.add_argument('--template', default=None)
286 create_subparser.add_argument('--memory', default=512, type=int)
287 create_subparser.add_argument('--cpu', default=1, type=int)
288 create_subparser.add_argument('--disk', default=8, type=int)
289@@ -760,6 +801,8 @@ def main(args):
290 create_subparser.add_argument(
291 '--meta-data', type=argparse.FileType('rb'))
292 create_subparser.add_argument('--password')
293+ create_subparser.add_argument('--guest-arch',
294+ help='guest arch to select template, default is the host architecture')
295 create_subparser.add_argument('--log-console-output', action='store_true')
296 create_subparser.add_argument('--backing-image-file')
297 create_subparser.add_argument('--run-script-once', action='append')

Subscribers

People subscribed via source and target branches