home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 2006-11-29 | 30.9 KB | 1,046 lines
/** * File: modules/VM_Common.ycp * Package: VM configuration - common function for all virtualization architectures * Authors: Ladislav Slezak <lslezak@suse.cz> * Michael G. Fritch <mgfritch@novell.com> * * $Id: VM_Common.ycp 34434 2006-11-16 21:34:28Z mgfritch $ */ { module "VM_Common"; import "Report"; import "Popup"; import "Label"; import "Pkg"; import "Package"; import "Arch"; import "ProductControl"; import "HTML"; import "PackageCallbacksInit"; import "String"; textdomain "vm"; global integer source_id = 0; global symbol inst_type = `cdrom; global string custom_source = ""; global integer default_memory_size = 256; global integer memory_size = default_memory_size; global integer default_number_of_cpus = 1; global integer number_of_cpus = default_number_of_cpus; global string default_start_mode = "manual"; global string start_mode = default_start_mode; global string on_poweroff = "destroy"; global string on_reboot = "restart"; global string on_crash = "restart"; global integer default_ne2000 = 0; // if virtual network card is AMD PCnet, then 0, else 1(NE2000) global integer ne2000 = default_ne2000; global integer default_stdvga = 0; // if graphics card is Cirrus Logic, then 0, else 1(Standard VGA) global integer stdvga = default_stdvga; global integer default_sdl = 1; // if graphics view is DirectMedia Layer(SDL) then 1, else 0 (VNC) global integer sdl = default_sdl; global integer default_localtime = 0; // if hardware clock is set to local time then 1, else 0 (UTC) global integer localtime = default_localtime; global string default_MAC = ""; global string MAC_address = default_MAC; global boolean random_MAC = true; global string config_name = ""; // activation mode - in virtual machine installation proposal global map start_mode_names = $[ "manual" : _("Manually"), "onboot" : _("Automatically") ]; // virtual network card - in virtual machine installation proposal global map ne2000_names = $[ 0 : _("AMD PCnet"), 1 : _("NE2000") ]; // virtual graphics card - in virtual machine installation proposal global map stdvga_names = $[ 0 : _("Cirrus Logic"), 1 : _("Standard VGA") ]; // graphics viewer - in virtual machine installation proposal global map sdl_names = $[ 0 : _("VNC"), 1 : _("SDL") ]; // hardware clock - in virtual machine installation proposal global map localtime_names = $[ 0 : _("UTC"), 1 : _("Local Time") ]; global string extra_args = ""; global string hidden_args = ""; global string root_device = ""; global string autoyast_profile = ""; global map autoyast_profile_settings = $[]; global boolean default_use_dhcp = false; global boolean use_dhcp = default_use_dhcp; global boolean default_use_static = false; global boolean use_static = default_use_static; global string ip = ""; global string netmask = ""; global string gateway = ""; global string proposal_type = "install"; string custom_kernel = ""; string custom_initrd = ""; boolean use_custom_kernel = false; boolean modified = false; string default_type = "para"; string virtualization_type = default_type; // currently "para" or "full" string yast_tmp_dir = ""; global define list<string> CPUflags() { // check only the first processor (assume the same processors) string cpuinfo_flags = (string) SCR::Read(.proc.cpuinfo.value."0"."flags"); list<string> cpuflags = (size(cpuinfo_flags) > 0) ? splitstring(cpuinfo_flags, " ") : []; y2milestone("Detected CPU flags: %1", cpuflags); return cpuflags; } global define boolean VirtualizationCPU() { list<string> cpuflags = CPUflags(); // vmx = Intel VT-x, svm = AMD Pacifica return contains(cpuflags, "vmx") || contains(cpuflags, "svm"); } global define string GetVirtualizationType() { return virtualization_type; } global define boolean SetVirtualizationType(string type) { if (!contains(["para", "full"], type)) { y2warning("Unknown virtualization type: %1", type); return false; } modified = virtualization_type != type; virtualization_type = type; return true; } global boolean ResetVirtualizationType() { string virt_type = default_type; // FIXME: when full virt hardware is supported the following line should be uncommented. // if (VirtualizationCPU()) virt_type = "full"; // full virt hardware detected, default all vm's to full virtualization return SetVirtualizationType(virt_type); } global string GetVirtualizationProposal() { string val = (virtualization_type == "para") ? _("Paravirtualization") : _("Full Virtualization"); return HTML::List([val]); } global boolean GetModified() { return modified; } global void SetModified(boolean modif) { modified = modif; } global map Export() { map ret = $[ "source_id" : source_id, "inst_type" : inst_type, "custom_source" : custom_source, "memory_size" : memory_size, "number_of_cpus" : number_of_cpus, "start_mode" : start_mode, "on_poweroff" : on_poweroff, "on_reboot" : on_reboot, "on_crash" : on_crash, "ne2000" : ne2000, "stdvga" : stdvga, "sdl" : sdl, "localtime" : localtime, "MAC_address" : MAC_address, "random_MAC" : random_MAC, "config_name" : config_name, "extra_args" : extra_args, "hidden_args" : hidden_args, "root_device" : root_device, "use_dhcp" : use_dhcp, "use_static" : use_static, "ip" : ip, "netmask" : netmask, "gateway" : gateway, "custom_kernel" : custom_kernel, "custom_initrd" : custom_initrd, "use_custom_kernel" : use_custom_kernel, "virtualization_type" : virtualization_type ]; // export configured source as custom (source index may point later to another source) if (inst_type == `network_configured && source_id != nil && source_id > 0) { map general_data = Pkg::SourceGeneralData (source_id); string url = general_data["url"]:""; y2milestone("Exporting source config: %1", url); ret["custom_source"] = url; ret["inst_type"] = `network_custom; } y2debug("VM_Common::Export() returned: %1", ret); return ret; } global void Import(map input) { y2debug("VM_Common::Import(%1)", input); source_id = input["source_id"]:source_id; inst_type = input["inst_type"]:inst_type; custom_source = input["custom_source"]:custom_source; memory_size = input["memory_size"]:memory_size; number_of_cpus = input["number_of_cpus"]:number_of_cpus; start_mode = input["start_mode"]:start_mode; on_poweroff = input["on_poweroff"]:on_poweroff; on_reboot = input["on_reboot"]:on_reboot; on_crash = input["on_crash"]:on_crash; ne2000 = input["ne2000"]:ne2000; stdvga = input["stdvga"]:stdvga; sdl = input["sdl"]:sdl; localtime = input["localtime"]:localtime; MAC_address = input["MAC_address"]:MAC_address; random_MAC = input["random_MAC"]:random_MAC; config_name = input["config_name"]:config_name; extra_args = input["extra_args"]:extra_args; hidden_args = input["hidden_args"]:hidden_args; root_device = input["root_device"]:root_device; use_dhcp = input["use_dhcp"]:use_dhcp; use_static = input["use_static"]:use_static; ip = input["ip"]:ip; netmask = input["netmask"]:netmask; gateway = input["gateway"]:gateway; custom_kernel = input["custom_kernel"]:custom_kernel; custom_initrd = input["custom_initrd"]:custom_initrd; use_custom_kernel = input["use_custom_kernel"]:use_custom_kernel; virtualization_type = input["virtualization_type"]:virtualization_type; } /** * Displays a formatted popup error message, with a details button. * @param errorMessage string - a simple message describing the error * @param out map - output of the executed command * @param cmd string - the executed command * @return void */ global void PopupErrorDetails(string errorMessage, map out, string cmd) ``{ string message = _("Undefined Error"); if (errorMessage != nil && errorMessage != "") message = errorMessage; Popup::ClearFeedback(); // Details button on a popup error message if (!Popup::AnyQuestion( Label::ErrorMsg(), message, Label::OKButton(), _("&Details..."), `focus )) { string description = sformat("<pre>command: %1 return \n %2 %3</pre>", cmd, out["stderr"]:"", out["stdout"]:""); UI::OpenDialog (`opt(`decorated ), `HBox( `VSpacing(16), `VBox ( `HSpacing (100), // popup window header `Heading (message), `VSpacing (0.5), `RichText (description), `VSpacing (1.0), // push button label `PushButton (`id(`ok), `opt(`default, `key_F10), Label::OKButton()) ) ) ); UI::SetFocus (`id(`ok)); UI::UserInput (); UI::CloseDialog (); } } global string GetAutoYastProposal() { // proposal items // %1 = an absolute filename path to the AutoYaST profile. return HTML::List([ sformat(_("AutoYaST Profile: %1"), (autoyast_profile != "") ? // none AutoYast profile has been selected autoyast_profile : _("<I>none</I>"))]); } global map<string,any> GetAutoYastProposalWarning() { map<string,any> ret = $[]; if (GetVirtualizationType() == "full" && autoyast_profile != "") { // error in the installation proposal - do not allow to continue ret = $[ // warning text in proposal dialog "warning" : _("The AutoYaST profile for VM cannot be configured here in full virtualization mode.<BR>Configure it inside the VM after boot."), "warning_level" : `warning ]; } return ret; } global boolean SetAutoYastProfile(string profile) { modified = (profile != autoyast_profile); autoyast_profile = profile; return true; } global string GetAutoYastProfile() { return autoyast_profile; } global map<string, string> restart_mapping = $[ // combobox item // restart mode - when the virtual machine is restarted "always" : _("Always"), // combobox item // restart mode - when the virtual machine is restarted "never" : _("Never"), // combobox item // restart mode - when the virtual machine is restarted "onreboot" : _("On Reboot") ]; // used for values on_poweroff, on_reboot, on_crash global map<string, string> lifecycle_event_mapping = $[ // combobox item // lifecycle_event mode (on_poweroff, on_reboot, on_crash) - destroy virtual machine "destroy" : _("Destroy"), // combobox item // lifecycle_event mode (on_poweroff, on_reboot, on_crash) - restart virtual machine "restart" : _("Restart"), // combobox item // lifecycle_event mode (on_poweroff, on_reboot, on_crash) - preserve virtual machine "preserve" : _("Preserve"), // combobox item // lifecycle_event mode (on_poweroff, on_reboot, on_crash) - rename and restart virtual machine "rename-restart" : _("Rename and restart"), ]; global define string GetKernelImage() { return custom_kernel; } global define boolean SetKernelImage(string im) { custom_kernel = im; return true; } global define string GetInitrdImage() { return custom_initrd; } global define boolean SetInitrdImage(string im) { custom_initrd = im; return true; } global define boolean SetCustomKernel(boolean use_custom) { use_custom_kernel = use_custom; return true; } global define boolean GetCustomKernel() { return use_custom_kernel; } global integer ProposeSelection () ``{ list <integer> sources = Pkg::SourceGetCurrent (false); y2milestone("sources: %1", sources); integer sid = nil; foreach(integer src, sources, ``{ map general_data = Pkg::SourceGeneralData(src); y2milestone("general_data: %1", general_data); string srcurl = general_data["url"]:""; // use only network sources in proposal if (regexpmatch(srcurl, "^(ftp)|(nfs)|(smb)|(http)://")) { y2milestone("Found network source: %1", src); sid = src; } } ); return sid; } global string GetDefaultRouteInterface() { // grab the default route from the route table string cmd = "/sbin/route | /usr/bin/grep -E '^default'"; y2milestone("Executing: %1", cmd); map out = (map)SCR::Execute(.target.bash_output, cmd); y2milestone("route output: %1", out); // get the interface assigned to the default route list<string> output = splitstring(out["stdout"]:"", " \t\n"); output = filter(string tmpstr, output, ``(tmpstr != nil && tmpstr != "")); y2milestone("output=%1", output); string default_interface = output[size(output)-1]:""; default_interface = String::CutBlanks(default_interface); y2milestone("default_interface=%1", default_interface); // default to eth0 if an error occurs if (default_interface == nil || default_interface == "") default_interface = "eth0"; y2milestone("GetDefaultRouteInterface returned '%1'", default_interface); return default_interface; } global boolean IsNetWareKernel(string kernel) { list<string> names = splitstring(kernel, "/"); string name = names[size(names) - 1]:""; return (tolower(name) == "xnloader.sys"); } global void SetNetWareHiddenArgs() { string args = ""; // Set the display string cmd = "set | grep 'DISPLAY' | grep -v 'BASH_EXECUTION_STRING'"; y2milestone("Executing: %1", cmd); map retmap = (map) SCR::Execute(.target.bash_output, cmd); y2milestone("retmap=%1", retmap); string display_value = deletechars(retmap["stdout"]:"", "\n"); // remove all newlines display_value = String::CutBlanks(display_value); list<string> display_list = (list<string>)splitstring(display_value, "=:"); y2milestone("display_list=%1", display_list); // Add display= if (display_list[1]:"" == nil || display_list[1]:"" == "" || display_list[1]:"" == "localhost" || display_list[1]:"" == "127.0.0.1") { // get the inferface assigned to the default route string default_interface = GetDefaultRouteInterface(); // get the IP address of the interface used in the default route import "IP"; list<map> ifconfig =(list<map>)SCR::Read(.run.ifconfig); ifconfig = filter(map iface, ifconfig, ``( iface["name"]:"" == default_interface)); integer ipint = ifconfig[0,"value", "inet", "addr"]:0; if (ipint != nil && ipint > 0) { args = args + sformat(" DISPLAY=%1:%2", IP::ToString(ipint), display_list[2]:"0"); } else { // use the display value as is... args = args + display_value; } } else { // use the display value as is... args = args + display_value; } VM_Common::hidden_args = args; y2milestone("hidden_args=%1", hidden_args); } global void SetLinuxHiddenArgs() { string arg = (VM_Common::proposal_type == "install") ? "install=$URL_INSTALL" : ""; VM_Common::hidden_args = arg; } global void SetHiddenArgs(string kernel) { if (IsNetWareKernel(kernel)) SetNetWareHiddenArgs(); else SetLinuxHiddenArgs(); } global list<string> CreateSourceProposal(symbol inst_type, integer source_id, string custom) { list<string> ret = []; if (inst_type == `cdrom || inst_type == `iso) { if (inst_type == `iso) { // installation proposal item ret = add(ret, sformat("%1 (%2)", _("Installation Device: ISO Image File"), custom)); } else if (inst_type == `cdrom) { // installation proposal item ret = add(ret, sformat("%1 (%2)", _("Installation Device: CD/DVD Device"), custom)); } if (use_custom_kernel) { // installation proposal item // %1 = absolute pathname the to a Xen-Enabled kernel ret = add(ret, sformat(_("Kernel: %1"), custom_kernel)); if (custom_initrd != "") // installation proposal item // %1 = absolute pathname to a Xen-Enabled initrd (ramdisk) ret = add(ret, sformat(_("RAM Disk Image: %1"), custom_initrd)); SetHiddenArgs(custom_kernel); } else { // SUSE installation source SetLinuxHiddenArgs(); } } else { // network install (SUSE instsources only!) string desc = ""; SetLinuxHiddenArgs(); y2milestone("inst_type: %1, source_id: %2", inst_type, source_id); if (inst_type == `network_configured && source_id != nil && source_id >= 0) { map product_data = Pkg::SourceProductData (source_id); map general_data = Pkg::SourceGeneralData (source_id); desc = product_data["label"]:"unknown" + " (" + general_data["url"]:"" + ")"; } else if (inst_type == `network_custom || inst_type == `cdrom || inst_type == `iso) { // installation proposal header desc = _("Custom Installation Source") + " (" + custom_source + ")"; } else if (inst_type == `slp) { // installation proposal header desc = _("SLP Installation Source"); } // %1 = installation source description or URL ret = [ sformat(_("SUSE Installation Source: %1"), desc) ]; } return ret; } global map CreateSourceProposalWarning(symbol inst_type, integer source_id, string custom) { map ret = $[]; if (inst_type == `network_configured && (source_id == nil || source_id < 0) && virtualization_type == "para") { ret = $[ "warning" : // error message in proposal _("OS installation source is not configured"), "warning_level" : `blocker ]; } else if ((inst_type == `network_custom || inst_type == `cdrom || inst_type == `iso) && (custom == nil || custom == "") && virtualization_type == "para") { ret = $[ "warning" : // error message in proposal _("OS installation source is not configured"), "warning_level" : `blocker ]; } // TODO: check custom installation source - parse URL, try to open it... /* else if (inst_type == `network_custom) { // installation proposal header ret = _("Custom Installation Source") + " (" + custom_source + ")"; } */ return ret; } global define boolean CreateDiskImage(string file, integer image_mb, boolean sparse) ``{ boolean ret = true; if ( ! sparse ) { // non-sparse images might take a long time to create (Bugzilla #167145) // Popup Feedback message Popup::ShowFeedback(_("Preparing Disk Image"), sformat("%1 (%2 MB)\n\n%3", file, image_mb, _("This might take a while."))); } string dd_options = (sparse) ? (" bs=1 count=1 " + sformat ("seek=%1", (image_mb*1024*1024)-1)) : (" bs=1M " + sformat ("count=%1", image_mb)); string cmd = "/bin/dd if=/dev/zero of='" + file + "'" + dd_options; y2milestone("Creating disk image %1 (%2MB)", file, image_mb); y2debug("dd command: %1", cmd); map result = (map) SCR::Execute (.target.bash_output, cmd); y2debug("result=%1", result); Popup::ClearFeedback(); if (result["exit"]:-1 != 0) { //PopupErrorDetails(sformat(_("Cannot create disk image %1"), file), result, cmd); // FIXME: somehow the output from the dd command is not captured by .target.bash_output y2error("Cannot create disk image %1", file); // Popup error message // %1 = absolute pathname to a loopback disk image (i.e '/var/lib/xen/images/vm1/hda') Report::Error(sformat(_("Cannot create the following disk image: %1 Please, ensure there is enough free disk space to create the specified disk image. "), file)); // try to remove part of the image if it exists SCR::Execute (.target.bash, "/bin/rm -- '" + file + "'"); ret = false; } return ret; } global define boolean CreateExt2Image(string image, integer image_mb) { // create sparse image file if (!VM_Common::CreateDiskImage(image, image_mb, true)) { return false; } // create Ext2 file system (built in FS, no kernel module required) // reserve 0% percent for root string command = "/sbin/mkfs.ext2 -F -m 0 -- '" + image + "'"; y2milestone("executing: %1", command); integer out = (integer)SCR::Execute(.target.bash, command); y2milestone("mkfs.ext2 result: %1", out); if (out != 0) { y2error("Cannot make a file system on the disk image"); return false; } return true; } global define string GetTmpDir() { if (yast_tmp_dir == nil || yast_tmp_dir == "") { // get temporary directory map output = (map)SCR::Execute(.target.bash_output, "mktemp -d"); // Let bash create a tmp dir yast_tmp_dir = deletechars(output["stdout"]:"", "\n\t "); if (yast_tmp_dir == "" || yast_tmp_dir == nil) { y2warning("Using /tmp directory for temporary files!"); yast_tmp_dir = "/tmp"; } } y2milestone("Using tmp directory: %1", yast_tmp_dir); return yast_tmp_dir; } global boolean RemoveTmpDir() { boolean ret = false; if (yast_tmp_dir != nil && yast_tmp_dir != "" && yast_tmp_dir != "/tmp") { y2milestone("Removing tmp dir: %1", yast_tmp_dir); integer bash_ret = (integer)SCR::Execute(.target.bash, sformat("rm -rf %1", yast_tmp_dir)); if (bash_ret == 0) { yast_tmp_dir = ""; ret = true; } } return ret; } global define boolean CreateImageWithProfile(string image, string profile) { // create 16MB image if (!CreateExt2Image(image, 16)) { return false; } // make directory for temporary device mounting string dir = GetTmpDir() + "/mnt"; SCR::Execute(.target.mkdir, dir); // mount the image string command = sformat("/bin/mount -o loop -- '%1' '%2'", image, dir); integer result = (integer)SCR::Execute (.target.bash, command); if (result != 0) { y2error("Cannot mount image %1 to %2", image, dir); SCR::Execute (.target.bash, "/bin/rm -- '" + image + "'"); return false; } boolean ret = true; // copy the profile command = sformat("/bin/cp -- '%1' '%2'", profile, dir); result = (integer) SCR::Execute (.target.bash, command); if (result != 0) { y2error("Cannot copy profile %1 to %2", profile, dir); ret = false; } SCR::Execute(.target.umount, dir); if (! ret) SCR::Execute (.target.bash, "/bin/rm -- '" + image + "'"); return ret; } // uses source_id variable global define string GetPackage(string package) { PackageCallbacksInit::SetMediaCallbacks(); // ensure that appropriate sources are enabled and the remaining ones disabled list<map<string,any> > source_data = Pkg::SourceEditGet(); source_data = maplist (map<string,any> src, source_data, { if (src["SrcId"]:-1 == source_id) src["enabled"] = true; return src; }); Pkg::SourceEditSet (source_data); // get info about the package (media number and path to the package) map<string,any> pkginfo = $[]; list<map<string,any> > pkginfoA = Pkg::PkgPropertiesAll(package); y2milestone("pkginfoAll: %1", pkginfoA); foreach(map<string,any> pk, pkginfoA, { if (pk["status"]:`unknown == `available && pk["srcid"]:-1 == source_id) { // x86_64 arch: use x86_64 packages, not i386 if (Arch::x86_64() && pk["arch"]:"unknown" != "x86_64") { continue; } pkginfo = pk; } } ); string pkg_path = pkginfo["path"]:""; string ret = ""; // check whether the package was found if (pkg_path != "" && pkg_path != nil) { // get local location ret = Pkg::SourceProvideFile(source_id, pkginfo["medianr"]:0, pkg_path); string tmpdir = VM_Common::GetTmpDir(); string target = sformat ("%1/%2.rpm", tmpdir, package); SCR::Execute (.target.bash, sformat ("/bin/cp %1 %2", ret, target)); ret = target; } return ret; } global define boolean InstallPackages(list<string> packages) { return Package::InstallAll(packages); } global define boolean CopyFile(string source, string target) { y2milestone("copying file %1 to %2", source, target); // -a (archive) = preserve mode and timestamps // -b (backup) = make a backup of the target file return (SCR::Execute(.target.bash, sformat("/bin/cp -a -b -- '%1' '%2'", source, target))) == 0; } global define string PackageArch() { string arch = ""; if (Arch::i386()) { arch = "i586"; } else if (Arch::x86_64()) { arch = "x86_64"; } else { arch = Arch::arch_short(); y2warning("Unknown architecture, using arch=%1", arch); } return arch; } global define string GetFileNameFromPath(string fname) { string ret = ""; if (fname != nil) { list<string> parts = splitstring(fname, "/"); ret = parts[size(parts) - 1]:""; } return ret; } // kernel_filename = "./boot/vmlinuz-*-xen" // kernel_regexp = "vmlinuz-*-xen" // Extract kernel from RPM file global define string ExtractKernelImage(string package, string target, string kernel_filename, string kernel_regexp) { string tmpdir = VM_Common::GetTmpDir(); SCR::Execute(.target.mkdir, tmpdir); string cmd = sformat("cd '%1' && /usr/bin/rpm2cpio '%2' | /usr/bin/cpio -idvum -- '%3'", tmpdir, package, kernel_filename); map out = (map)SCR::Execute(.target.bash_output, cmd); y2milestone("out: %1", out); cmd = sformat("/usr/bin/find '%1' -type f -name '%2'", tmpdir + "/boot", kernel_regexp); out = (map)SCR::Execute(.target.bash_output, cmd); y2milestone("out: %1", out); list<string> stdout = splitstring(out["stdout"]:"", "\n"); string file = stdout[0]:""; y2milestone("found kernel: %1", file); if (file != nil && file != "") { CopyFile(file, target); return GetFileNameFromPath(file); } return ""; } global define map<integer,boolean> InstSourceStatus() { map<integer,boolean> ret = $[]; list<integer> sources = Pkg::SourceGetCurrent(false); foreach(integer src, sources, { map general_data = Pkg::SourceGeneralData(src); y2milestone("general_data: %1", general_data); ret[src] = general_data["enabled"]:false; } ); return ret; } global define map<string,string> DisableAllSources() { map<string,string> ret = $[]; list<integer> sources = Pkg::SourceGetCurrent (false); foreach(integer src, sources, { Pkg::SourceSetEnabled(src, false); } ); return ret; } global define void SetSourceState(map<integer,boolean> state) { list<integer> sources = Pkg::SourceGetCurrent (false); foreach(integer src, boolean enabled, state, { Pkg::SourceSetEnabled(src, enabled); } ); } global define integer IsInstSourceDefined(string url) { list<integer> sources = Pkg::SourceGetCurrent (false); integer ret = -1; foreach(integer src, sources, { map general_data = Pkg::SourceGeneralData(src); if (url == general_data["url"]:"") { ret = src; } } ); return ret; } global define string ParseFstab(string fstab) { map out = (map) SCR::Execute(.target.bash_output, sformat("/bin/grep -E \"[[:space:]]/[[:space:]]\" '%1' | /usr/bin/awk '{print $1}'", fstab)); string rdev = ""; if (out["exit"]:-1 == 0 ) { rdev = (string) (out["stdout"]:""); list<string> root_dev_list = splitstring(rdev, "\n"); rdev = root_dev_list[0]:""; y2milestone("Found root device: %1", rdev); } else { y2error("Cannot read fstab root device entry: %1", out); } return rdev; } global define list<string> SearchFile(string dir, string name) { list<string> ret = []; string cmd = sformat("cd -- '%1' && ls -1 -- '%2'", dir, name); map outputmap = (map)SCR::Execute(.target.bash_output, cmd); string outputstring = outputmap["stdout"]:""; if (outputstring != nil && outputstring != "") { ret = splitstring(outputstring, "\n"); // remove empty lines ret = filter(string f, ret, {return f != nil && f != "";}); } return ret; } global define boolean TryMount(string image, integer offset, string mntpoint) { y2milestone("TryMount: image=%1, offset=%2, mntpoint=%3", image, offset, mntpoint); boolean result = (boolean) SCR::Execute(.target.mount, [image, mntpoint], sformat("-o loop,offset=%1", offset)); y2milestone("result: %1", result); return result; } global string vm_control_file = "/usr/share/YaST2/control/vm_install.xml"; global void InitProductControl() { ProductControl::custom_control_file = vm_control_file; if (!ProductControl::Init()) { // popup error message // %1 = absolute pathname to a product control file (i.e. '/usr/share/YaST2/control/vm_install.xml') Report::Error(sformat(_("Control file %1 was not found."), ProductControl::custom_control_file)); } } global define string getMACproposal() { string mac = ""; if (random_MAC == true) { // part of proposal - MAC address is not specified, assign random mac = _("Random MAC address"); if (MAC_address != nil && MAC_address != "") { // add proposed value mac = sformat("%1 (Proposed value '%2')", mac, MAC_address); } } else { mac = MAC_address; } return mac; } global define boolean CreateInstallationImage(string kernelpkg, string target) { string arch = VM_Common::PackageArch(); // get installation package string inst = VM_Common::GetPackage("install-initrd"); y2milestone("image rpm: %1", inst); if (inst == nil || inst == "") { y2error("Cannot obtain install-initrd package."); return false; } string tmpdir = VM_Common::GetTmpDir(); SCR::Execute(.target.mkdir, tmpdir); string cmd = sformat("cd -- '%1' && /usr/bin/rpm2cpio '%2' | /usr/bin/cpio -idvum", tmpdir, inst); map out = (map)SCR::Execute(.target.bash_output, cmd); y2debug("out: %1", out); cmd = sformat("/bin/ls -1 %1/*.gz", tmpdir + "/usr/lib/install-initrd"); out = (map)SCR::Execute(.target.bash_output, cmd); y2debug("out: %1", out); list<string> stdout = splitstring(out["stdout"]:"", "\n"); y2debug("found base initrd files: %1", stdout); string file = stdout[0]:""; y2milestone("found initrd: %1", file); // create the image cmd = sformat("%1/usr/sbin/mkinstallinitrd --kernel-rpm '%2' --libdir '%3' '%4'", tmpdir, kernelpkg, tmpdir + "/usr/lib/install-initrd", target); out = (map)SCR::Execute(.target.bash_output, cmd); y2milestone("mkinstallinitrd output: %1", out); return out["exit"]:1 == 0; } string GetTwoHexDigits() { string hex = "0123456789abcdef"; return substring(hex, random(16), 1) + substring(hex, random(16), 1); } global string Propose_MAC_address(string option) { srandom(time()); string ret = "00:16:3e:" + GetTwoHexDigits() + ":" + GetTwoHexDigits() + ":" + GetTwoHexDigits(); // TODO detect if the address is already in use on the network y2milestone("Proposed MAC: %1", ret); return ret; } global boolean isGraphicalDisplay() { // check whether X window system is accessible by testing // for the existance of the DISPLAY enviroment value (#194389) boolean ret = true; string cmd = "echo $DISPLAY"; map result = (map) SCR::Execute(.target.bash_output, cmd); string display_val = deletechars(result["stdout"]:"", String::CSpace()); y2milestone("DISPLAY=%1", display_val); if (display_val == nil || display_val == "") { ret = false; } y2milestone("X check (isGraphicalDisplay): %1", ret); return ret; } /* EOF */ }