X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=mclu_boot.ml;h=625aea21cc08d74a59be9d4396e0a0510b0e0381;hb=837399023dce58f8fdd9a3c6c5e39af087bacceb;hp=451beb8125c7c48463a3433298e14ff0667fb4a0;hpb=f2a17d80287a2afc8f2204035536c81950649e2e;p=mclu.git diff --git a/mclu_boot.ml b/mclu_boot.ml index 451beb8..625aea2 100644 --- a/mclu_boot.ml +++ b/mclu_boot.ml @@ -163,7 +163,29 @@ Try: `mclu on %s'\n" hostname hostname; let format, extension = "qcow2", "qcow2" in let remote_template = sprintf "/tmp/mclu%s.sh" (string_random8 ()) in let remote_template_wrapper = sprintf "/tmp/mclu%s.sh" (string_random8 ()) in + let xml_template_wrapper = sprintf "/tmp/mclu%s.sh" (string_random8 ()) in let remote_image = sprintf "/var/tmp/%s.%s" name extension in + let remote_external_kernel_dir = sprintf "/var/tmp/%s.boot" name in + let remote_external_kernel = sprintf "/var/tmp/%s.boot/kernel" name in + let remote_external_initrd = sprintf "/var/tmp/%s.boot/initrd" name in + let remote_arch = node.MS.node_status.node_info.model in + + (* Guest arch defaults to the node host arch, but can be overridden + * in the template. + *) + let guest_arch = + match template_info.Template.guest_arch with + | Some arch -> arch + | None -> remote_arch in + + (* UEFI firmware and NVRAM on remote, if required. *) + let nvram = + match guest_arch with + | "aarch64" -> + Some ("/usr/share/edk2.git/aarch64/QEMU_EFI-pflash.raw", + "/usr/share/edk2.git/aarch64/vars-template-pflash.raw", + remote_image ^ ".nvram") + | _ -> None in (* Get ready to generate the guest XML. *) let vcpus = !vcpus in @@ -174,23 +196,66 @@ Try: `mclu on %s'\n" hostname hostname; sprintf "52:54:00:%02x:%02x:%02x" (Random.int 256) (Random.int 256) (Random.int 256) in - (* Generate the guest XML. XXX Quoting. *) - let xml = sprintf "\ + (* Generate the guest XML. *) + let generate_standard_xml () = + (* XXX Better quoting. *) + let xml = sprintf "\ %s %Ld %Ld %d +" name (memory /^ 1024L) (memory /^ 1024L) vcpus in + + let xml = xml ^ "\ - hvm +" in + let xml = + match guest_arch with + | "arm" | "armv7" | "armv7l" | "armv7hl" -> + xml ^ "\ + hvm +" + | "aarch64" -> + xml ^ "\ + hvm +" + | _ -> + xml ^ "\ + hvm +" in + + let xml = + match nvram with + | Some (loader, nvram_template, nvram) -> + xml ^ sprintf "\ + %s + %s +" loader nvram_template nvram + | None -> xml in + + let xml = xml ^ + if template_info.Template.needs_external_kernel then + sprintf "\ + %s + %s +" remote_external_kernel remote_external_initrd + else "" in + + let xml = xml ^ + match template_info.Template.cmdline with + | Some cmdline -> sprintf " %s\n" cmdline + | None -> "" in + + let xml = xml ^ "\ - + @@ -200,14 +265,14 @@ Try: `mclu on %s'\n" hostname hostname; restart restart -" name (memory /^ 1024L) (memory /^ 1024L) vcpus in +" in - let xml = xml ^ sprintf "\ + let xml = xml ^ sprintf "\ " format remote_image in - let xml = xml ^ + let xml = xml ^ match template_info.Template.disk_bus with | Some "ide" -> " \n" @@ -216,22 +281,23 @@ Try: `mclu on %s'\n" hostname hostname; | Some bus -> eprintf "mclu: unknown disk-bus: %s\n" bus; exit 1 in - let xml = xml ^ "\ + let xml = xml ^ "\ " in - let xml = xml ^ - if template_info.Template.disk_bus = Some "virtio-scsi" then - " \n" - else - "" in - - (* XXX Don't hard-code bridge name here. *) - let network_model = - match template_info with - | { Template.network_model = None } -> "virtio" - | { Template.network_model = Some d } -> d in - let xml = xml ^ sprintf "\ + let xml = + xml ^ + if template_info.Template.disk_bus = Some "virtio-scsi" then + " \n" + else + "" in + + (* XXX Don't hard-code bridge name here. *) + let network_model = + match template_info with + | { Template.network_model = None } -> "virtio" + | { Template.network_model = Some d } -> d in + let xml = xml ^ sprintf "\ @@ -239,13 +305,19 @@ Try: `mclu on %s'\n" hostname hostname; " mac_addr network_model in - let xml = xml ^ "\ + let xml = xml ^ "\ +" in + let xml = + match guest_arch with + | "i386" | "i486" | "i586" | "i686" + | "x86_64" -> + xml ^ "\ @@ -253,8 +325,63 @@ Try: `mclu on %s'\n" hostname hostname; +" + | _ -> xml in + let xml = xml ^ "\ " in + xml + + and generate_custom_xml () = + (* Generate a wrapper script to make passing the variables + * to the template easier. + *) + let () = + let chan = open_out xml_template_wrapper in + let fpf fs = fprintf chan fs in + fpf "#!/bin/sh\n"; + fpf "export format=%s\n" (quote format); + fpf "export initrd=%s\n" (quote remote_external_initrd); + fpf "export kernel=%s\n" (quote remote_external_kernel); + fpf "export mac_addr=%s\n" (quote mac_addr); + fpf "export memory_kb=%Ld\n" (memory /^ 1024L); + fpf "export name=%s\n" (quote name); + fpf "export output=%s\n" (quote remote_image); + fpf "export vcpus=%d\n" vcpus; + fpf "%s xml\n" template_filename; + close_out chan; + Unix.chmod xml_template_wrapper 0o755 in + + if verbose then printf "%s\n%!" xml_template_wrapper; + let chan = Unix.open_process_in xml_template_wrapper in + let lines = ref [] in + (try while true do lines := input_line chan :: !lines done + with End_of_file -> ()); + let stat = Unix.close_process_in chan in + (match stat with + | Unix.WEXITED 0 -> () + | Unix.WEXITED i -> + eprintf "mclu: template '%s' subcmd xml exited with error %d\n" + template_filename i; + exit 1 + | Unix.WSIGNALED i -> + eprintf "mclu: template '%s' subcmd xml killed by signal %d\n" + template_filename i; + exit 1 + | Unix.WSTOPPED i -> + eprintf "mclu: template '%s' subcmd xml stopped by signal %d\n" + template_filename i; + exit 1 + ); + let xml = String.concat "\n" (List.rev !lines) in + xml + in + + let xml = + if not template_info.Template.has_xml_target then + generate_standard_xml () + else + generate_custom_xml () in (* Copy the template to remote. *) let cmd = @@ -272,11 +399,13 @@ Try: `mclu on %s'\n" hostname hostname; let () = let chan = open_out remote_template_wrapper in let fpf fs = fprintf chan fs in - fpf "#!/bin/sh\n"; + fpf "#!/bin/bash\n"; + fpf "set -e\n"; (* XXX Don't hard-code network_bridge here. *) fpf "export LIBGUESTFS_BACKEND_SETTINGS=network_bridge=br0\n"; fpf "export base_image=%s\n" (quote template_info.Template.base_image); fpf "export format=%s\n" (quote format); + fpf "export guest_arch=%s\n" (quote guest_arch); fpf "export name=%s\n" (quote name); fpf "export output=%s\n" (quote remote_image); (match size with @@ -287,7 +416,21 @@ Try: `mclu on %s'\n" hostname hostname; | "" -> () | tz -> fpf "export timezone=%s\n" (quote (sprintf "--timezone %s" tz)) ); + (match nvram with + | Some (_, nvram_template, nvram) -> + fpf "cp %s %s\n" (quote nvram_template) (quote nvram) + | None -> () + ); fpf "%s build\n" remote_template; + if template_info.Template.needs_external_kernel then ( + fpf "rm -rf %s\n" (quote remote_external_kernel_dir); + fpf "mkdir %s\n" (quote remote_external_kernel_dir); + fpf "pushd %s\n" (quote remote_external_kernel_dir); + fpf "virt-builder --get-kernel %s\n" (quote remote_image); + fpf "ln vmlinuz-* kernel\n"; + fpf "ln init* initrd\n"; + fpf "popd\n"; + ); close_out chan; Unix.chmod remote_template_wrapper 0o755 in