target/arm: Introduce gen_exception
[qemu/rayw.git] / tests / vm / centos.aarch64
blob96c450f8be5e14e6649ea4ce4219de344a7f21b2
1 #!/usr/bin/env python3
3 # Centos aarch64 image
5 # Copyright 2020 Linaro
7 # Authors:
8 #  Robert Foley <robert.foley@linaro.org>
9 #  Originally based on ubuntu.aarch64
11 # This code is licensed under the GPL version 2 or later.  See
12 # the COPYING file in the top-level directory.
15 import os
16 import sys
17 import subprocess
18 import basevm
19 import time
20 import traceback
21 import aarch64vm
23 DEFAULT_CONFIG = {
24     'cpu'          : "max",
25     'machine'      : "virt,gic-version=max",
26     'install_cmds' : "yum install -y make ninja-build git python3 gcc gcc-c++ flex bison, "\
27         "yum install -y glib2-devel perl pixman-devel zlib-devel, "\
28         "alternatives --set python /usr/bin/python3, "\
29         "sudo dnf config-manager "\
30         "--add-repo=https://download.docker.com/linux/centos/docker-ce.repo,"\
31         "sudo dnf install --nobest -y docker-ce.aarch64,"\
32         "systemctl enable docker",
33     # We increase beyond the default time since during boot
34     # it can take some time (many seconds) to log into the VM.
35     'ssh_timeout'  : 60,
38 class CentosAarch64VM(basevm.BaseVM):
39     name = "centos.aarch64"
40     arch = "aarch64"
41     login_prompt = "localhost login:"
42     prompt = '[root@localhost ~]#'
43     image_name = "CentOS-8-aarch64-1905-dvd1.iso"
44     image_link = "http://mirrors.usc.edu/pub/linux/distributions/centos/8.0.1905/isos/aarch64/"
45     image_link += image_name
46     BUILD_SCRIPT = """
47         set -e;
48         cd $(mktemp -d);
49         sudo chmod a+r /dev/vdb;
50         tar --checkpoint=.10 -xf /dev/vdb;
51         ./configure {configure_opts};
52         make --output-sync {target} -j{jobs} {verbose};
53     """
54     def set_key_perm(self):
55         """Set permissions properly on certain files to allow
56            ssh access."""
57         self.console_wait_send(self.prompt,
58                                "/usr/sbin/restorecon -R -v /root/.ssh\n")
59         self.console_wait_send(self.prompt,
60                 "/usr/sbin/restorecon -R -v "\
61                 "/home/{}/.ssh\n".format(self._config["guest_user"]))
63     def create_kickstart(self):
64         """Generate the kickstart file used to generate the centos image."""
65         # Start with the template for the kickstart.
66         ks_file = self._source_path + "/tests/vm/centos-8-aarch64.ks"
67         subprocess.check_call("cp {} ./ks.cfg".format(ks_file), shell=True)
68         # Append the ssh keys to the kickstart file
69         # as the post processing phase of installation.
70         with open("ks.cfg", "a") as f:
71             # Add in the root pw and guest user.
72             rootpw = "rootpw --plaintext {}\n"
73             f.write(rootpw.format(self._config["root_pass"]))
74             add_user = "user --groups=wheel --name={} "\
75                        "--password={} --plaintext\n"
76             f.write(add_user.format(self._config["guest_user"],
77                                     self._config["guest_pass"]))
78             # Add the ssh keys.
79             f.write("%post --log=/root/ks-post.log\n")
80             f.write("mkdir -p /root/.ssh\n")
81             addkey = 'echo "{}" >> /root/.ssh/authorized_keys\n'
82             addkey_cmd = addkey.format(self._config["ssh_pub_key"])
83             f.write(addkey_cmd)
84             f.write('mkdir -p /home/{}/.ssh\n'.format(self._config["guest_user"]))
85             addkey = 'echo "{}" >> /home/{}/.ssh/authorized_keys\n'
86             addkey_cmd = addkey.format(self._config["ssh_pub_key"],
87                                        self._config["guest_user"])
88             f.write(addkey_cmd)
89             f.write("%end\n")
90         # Take our kickstart file and create an .iso from it.
91         # The .iso will be provided to qemu as we boot
92         # from the install dvd.
93         # Anaconda will recognize the label "OEMDRV" and will
94         # start the automated installation.
95         gen_iso_img = 'genisoimage -output ks.iso -volid "OEMDRV" ks.cfg'
96         subprocess.check_call(gen_iso_img, shell=True)
98     def wait_for_shutdown(self):
99         """We wait for qemu to shutdown the VM and exit.
100            While this happens we display the console view
101            for easier debugging."""
102         # The image creation is essentially done,
103         # so whether or not the wait is successful we want to
104         # wait for qemu to exit (the self.wait()) before we return.
105         try:
106             self.console_wait("reboot: Power down")
107         except Exception as e:
108             sys.stderr.write("Exception hit\n")
109             if isinstance(e, SystemExit) and e.code == 0:
110                 return 0
111             traceback.print_exc()
112         finally:
113             self.wait()
115     def build_base_image(self, dest_img):
116         """Run through the centos installer to create
117            a base image with name dest_img."""
118         # We create the temp image, and only rename
119         # to destination when we are done.
120         img = dest_img + ".tmp"
121         # Create an empty image.
122         # We will provide this as the install destination.
123         qemu_img_create = "qemu-img create {} 50G".format(img)
124         subprocess.check_call(qemu_img_create, shell=True)
126         # Create our kickstart file to be fed to the installer.
127         self.create_kickstart()
128         # Boot the install dvd with the params as our ks.iso
129         os_img = self._download_with_cache(self.image_link)
130         dvd_iso = "centos-8-dvd.iso"
131         subprocess.check_call(["cp", "-f", os_img, dvd_iso])
132         extra_args = "-cdrom ks.iso"
133         extra_args += " -drive file={},if=none,id=drive1,cache=writeback"
134         extra_args += " -device virtio-blk,drive=drive1,bootindex=1"
135         extra_args = extra_args.format(dvd_iso).split(" ")
136         self.boot(img, extra_args=extra_args)
137         self.console_wait_send("change the selection", "\n")
138         # We seem to need to hit esc (chr(27)) twice to abort the
139         # media check, which takes a long time.
140         # Waiting a bit seems to be more reliable before hitting esc.
141         self.console_wait("Checking")
142         time.sleep(5)
143         self.console_wait_send("Checking", chr(27))
144         time.sleep(5)
145         self.console_wait_send("Checking", chr(27))
146         print("Found Checking")
147         # Give sufficient time for the installer to create the image.
148         self.console_init(timeout=7200)
149         self.wait_for_shutdown()
150         os.rename(img, dest_img)
151         print("Done with base image build: {}".format(dest_img))
153     def check_create_base_img(self, img_base, img_dest):
154         """Create a base image using the installer.
155            We will use the base image if it exists.
156            This helps cut down on install time in case we
157            need to restart image creation,
158            since the base image creation can take a long time."""
159         if not os.path.exists(img_base):
160             print("Generate new base image: {}".format(img_base))
161             self.build_base_image(img_base);
162         else:
163             print("Use existing base image: {}".format(img_base))
164         # Save a copy of the base image and copy it to dest.
165         # which we will use going forward.
166         subprocess.check_call(["cp", img_base, img_dest])
168     def boot(self, img, extra_args=None):
169         aarch64vm.create_flash_images(self._tmpdir, self._efi_aarch64)
170         default_args = aarch64vm.get_pflash_args(self._tmpdir)
171         if extra_args:
172             extra_args.extend(default_args)
173         else:
174             extra_args = default_args
175         # We always add these performance tweaks
176         # because without them, we boot so slowly that we
177         # can time out finding the boot efi device.
178         if '-smp' not in extra_args and \
179            '-smp' not in self._config['extra_args'] and \
180            '-smp' not in self._args:
181             # Only add if not already there to give caller option to change it.
182             extra_args.extend(["-smp", "8"])
183         # We have overridden boot() since aarch64 has additional parameters.
184         # Call down to the base class method.
185         super(CentosAarch64VM, self).boot(img, extra_args=extra_args)
187     def build_image(self, img):
188         img_tmp = img + ".tmp"
189         self.check_create_base_img(img + ".base", img_tmp)
191         # Boot the new image for the first time to finish installation.
192         self.boot(img_tmp)
193         self.console_init()
194         self.console_wait_send(self.login_prompt, "root\n")
195         self.console_wait_send("Password:",
196                                "{}\n".format(self._config["root_pass"]))
198         self.set_key_perm()
199         self.console_wait_send(self.prompt, "rpm -q centos-release\n")
200         enable_adapter = "sed -i 's/ONBOOT=no/ONBOOT=yes/g'" \
201                          " /etc/sysconfig/network-scripts/ifcfg-enp0s1\n"
202         self.console_wait_send(self.prompt, enable_adapter)
203         self.console_wait_send(self.prompt, "ifup enp0s1\n")
204         self.console_wait_send(self.prompt,
205                                'echo "qemu  ALL=(ALL) NOPASSWD:ALL" | '\
206                                'sudo tee /etc/sudoers.d/qemu\n')
207         self.console_wait(self.prompt)
209         # Rest of the commands we issue through ssh.
210         self.wait_ssh(wait_root=True)
212         # If the user chooses *not* to do the second phase,
213         # then we will jump right to the graceful shutdown
214         if self._config['install_cmds'] != "":
215             install_cmds = self._config['install_cmds'].split(',')
216             for cmd in install_cmds:
217                 self.ssh_root(cmd)
218         self.ssh_root("poweroff")
219         self.wait_for_shutdown()
220         os.rename(img_tmp, img)
221         print("image creation complete: {}".format(img))
222         return 0
224 if __name__ == "__main__":
225     defaults = aarch64vm.get_config_defaults(CentosAarch64VM, DEFAULT_CONFIG)
226     sys.exit(basevm.main(CentosAarch64VM, defaults))