How to use Create method of qemu Package

Best Syzkaller code snippet using qemu.Create

config_qemu.go

Source:config_qemu.go Github

copy

Full Screen

...92 Ipconfig13 string `json:"ipconfig13,omitempty"`93 Ipconfig14 string `json:"ipconfig14,omitempty"`94 Ipconfig15 string `json:"ipconfig15,omitempty"`95}96// CreateVm - Tell Proxmox API to make the VM97func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) {98 if config.HasCloudInit() {99 return fmt.Errorf("cloud-init parameters only supported on clones or updates")100 }101 vmr.SetVmType("qemu")102 params := map[string]interface{}{103 "vmid": vmr.vmId,104 "name": config.Name,105 "onboot": config.Onboot,106 "startup": config.Startup,107 "tablet": config.Tablet,108 "agent": config.Agent,109 "ostype": config.QemuOs,110 "sockets": config.QemuSockets,111 "cores": config.QemuCores,112 "cpu": config.QemuCpu,113 "numa": config.QemuNuma,114 "kvm": config.QemuKVM,115 "hotplug": config.Hotplug,116 "memory": config.Memory,117 "boot": config.Boot,118 "description": config.Description,119 "tags": config.Tags,120 "machine": config.Machine,121 "args": config.Args,122 }123 if config.QemuIso != "" {124 params["ide2"] = config.QemuIso + ",media=cdrom"125 }126 if config.Bios != "" {127 params["bios"] = config.Bios128 }129 if config.Balloon >= 1 {130 params["balloon"] = config.Balloon131 }132 if config.QemuVcpus >= 1 {133 params["vcpus"] = config.QemuVcpus134 }135 if vmr.pool != "" {136 params["pool"] = vmr.pool137 }138 if config.Boot != "" {139 params["boot"] = config.Boot140 }141 if config.BootDisk != "" {142 params["bootdisk"] = config.BootDisk143 }144 if config.Scsihw != "" {145 params["scsihw"] = config.Scsihw146 }147 err = config.CreateQemuMachineParam(params)148 if err != nil {149 log.Printf("[ERROR] %q", err)150 }151 // Create disks config.152 err = config.CreateQemuDisksParams(vmr.vmId, params, false)153 if err != nil {154 log.Printf("[ERROR] %q", err)155 }156 // Create EFI disk157 err = config.CreateQemuEfiParams(params)158 if err != nil {159 log.Printf("[ERROR] %q", err)160 }161 // Create vga config.162 vgaParam := QemuDeviceParam{}163 vgaParam = vgaParam.createDeviceParam(config.QemuVga, nil)164 if len(vgaParam) > 0 {165 params["vga"] = strings.Join(vgaParam, ",")166 }167 // Create networks config.168 err = config.CreateQemuNetworksParams(vmr.vmId, params)169 if err != nil {170 log.Printf("[ERROR] %q", err)171 }172 // Create serial interfaces173 err = config.CreateQemuSerialsParams(vmr.vmId, params)174 if err != nil {175 log.Printf("[ERROR] %q", err)176 }177 err = config.CreateQemuPCIsParams(vmr.vmId, params)178 if err != nil {179 log.Printf("[ERROR] %q", err)180 }181 // Create usb interfaces182 err = config.CreateQemuUsbsParams(vmr.vmId, params)183 if err != nil {184 log.Printf("[ERROR] %q", err)185 }186 exitStatus, err := client.CreateQemuVm(vmr.node, params)187 if err != nil {188 return fmt.Errorf("error creating VM: %v, error status: %s (params: %v)", err, exitStatus, params)189 }190 _, err = client.UpdateVMHA(vmr, config.HaState, config.HaGroup)191 if err != nil {192 log.Printf("[ERROR] %q", err)193 }194 return195}196// HasCloudInit - are there cloud-init options?197func (config ConfigQemu) HasCloudInit() bool {198 return config.CIuser != "" ||199 config.CIpassword != "" ||200 config.Searchdomain != "" ||201 config.Nameserver != "" ||202 config.Sshkeys != "" ||203 config.Ipconfig0 != "" ||204 config.Ipconfig1 != "" ||205 config.Ipconfig2 != "" ||206 config.Ipconfig3 != "" ||207 config.Ipconfig4 != "" ||208 config.Ipconfig5 != "" ||209 config.Ipconfig6 != "" ||210 config.Ipconfig7 != "" ||211 config.Ipconfig8 != "" ||212 config.Ipconfig9 != "" ||213 config.Ipconfig10 != "" ||214 config.Ipconfig11 != "" ||215 config.Ipconfig12 != "" ||216 config.Ipconfig13 != "" ||217 config.Ipconfig14 != "" ||218 config.Ipconfig15 != "" ||219 config.CIcustom != ""220}221/*222CloneVm223Example: Request224nodes/proxmox1-xx/qemu/1012/clone225newid:145226name:tf-clone1227target:proxmox1-xx228full:1229storage:xxx230*/231func (config ConfigQemu) CloneVm(sourceVmr *VmRef, vmr *VmRef, client *Client) (err error) {232 vmr.SetVmType("qemu")233 var storage string234 fullclone := "1"235 if config.FullClone != nil {236 fullclone = strconv.Itoa(*config.FullClone)237 }238 if disk0Storage, ok := config.QemuDisks[0]["storage"].(string); ok && len(disk0Storage) > 0 {239 storage = disk0Storage240 }241 params := map[string]interface{}{242 "newid": vmr.vmId,243 "target": vmr.node,244 "name": config.Name,245 "full": fullclone,246 }247 if vmr.pool != "" {248 params["pool"] = vmr.pool249 }250 if fullclone == "1" && storage != "" {251 params["storage"] = storage252 }253 _, err = client.CloneQemuVm(sourceVmr, params)254 return err255}256func (config ConfigQemu) UpdateConfig(vmr *VmRef, client *Client) (err error) {257 configParams := map[string]interface{}{}258 //Array to list deleted parameters259 //deleteParams := []string{}260 if config.Agent != 0 {261 configParams["agent"] = config.Agent262 }263 if config.QemuCores != 0 {264 configParams["cores"] = config.QemuCores265 }266 if config.Memory != 0 {267 configParams["memory"] = config.Memory268 }269 if config.QemuSockets != 0 {270 configParams["sockets"] = config.QemuSockets271 }272 if config.QemuKVM != nil {273 configParams["kvm"] = *config.QemuKVM274 }275 if config.QemuNuma != nil {276 configParams["numa"] = *config.QemuNuma277 }278 if config.Onboot != nil {279 configParams["onboot"] = *config.Onboot280 }281 if config.Tablet != nil {282 configParams["tablet"] = *config.Tablet283 }284 if config.Args != "" {285 configParams["args"] = config.Args286 }287 if config.Tags != "" {288 configParams["tags"] = config.Tags289 }290 if config.Startup != "" {291 configParams["startup"] = config.Startup292 }293 if config.Bios != "" {294 configParams["bios"] = config.Bios295 }296 if config.Hotplug != "" {297 configParams["hotplug"] = config.Hotplug298 }299 if config.Name != "" {300 configParams["name"] = config.Name301 }302 if config.Description != "" {303 configParams["description"] = config.Description304 }305 if config.Balloon >= 1 {306 configParams["balloon"] = config.Balloon307 }308 if config.QemuVcpus >= 1 {309 configParams["vcpus"] = config.QemuVcpus310 }311 if config.BootDisk != "" {312 configParams["bootdisk"] = config.BootDisk313 }314 if config.Hookscript != "" {315 configParams["hookscript"] = config.Hookscript316 }317 if config.QemuCpu != "" {318 configParams["cpu"] = config.QemuCpu319 }320 if config.Scsihw != "" {321 configParams["scsihw"] = config.Scsihw322 }323 // Create disks config.324 configParamsDisk := map[string]interface{}{325 "vmid": vmr.vmId,326 }327 // TODO keep going if error=328 err = config.CreateQemuDisksParams(vmr.vmId, configParamsDisk, false)329 if err != nil {330 log.Printf("[ERROR] %q", err)331 }332 // TODO keep going if error=333 _, err = client.createVMDisks(vmr.node, configParamsDisk)334 if err != nil {335 log.Printf("[ERROR] %q", err)336 }337 //Copy the disks to the global configParams338 for key, value := range configParamsDisk {339 //vmid is only required in createVMDisks340 if key != "vmid" {341 configParams[key] = value342 }343 }344 // Create networks config.345 err = config.CreateQemuNetworksParams(vmr.vmId, configParams)346 if err != nil {347 log.Printf("[ERROR] %q", err)348 }349 // Create vga config.350 vgaParam := QemuDeviceParam{}351 vgaParam = vgaParam.createDeviceParam(config.QemuVga, nil)352 if len(vgaParam) > 0 {353 configParams["vga"] = strings.Join(vgaParam, ",")354 }355 // Create serial interfaces356 err = config.CreateQemuSerialsParams(vmr.vmId, configParams)357 if err != nil {358 log.Printf("[ERROR] %q", err)359 }360 // Create usb interfaces361 err = config.CreateQemuUsbsParams(vmr.vmId, configParams)362 if err != nil {363 log.Printf("[ERROR] %q", err)364 }365 // cloud-init options366 if config.CIuser != "" {367 configParams["ciuser"] = config.CIuser368 }369 if config.CIpassword != "" {370 configParams["cipassword"] = config.CIpassword371 }372 if config.CIcustom != "" {373 configParams["cicustom"] = config.CIcustom374 }375 if config.Searchdomain != "" {376 configParams["searchdomain"] = config.Searchdomain377 }378 if config.Nameserver != "" {379 configParams["nameserver"] = config.Nameserver380 }381 if config.Sshkeys != "" {382 sshkeyEnc := url.PathEscape(config.Sshkeys + "\n")383 sshkeyEnc = strings.Replace(sshkeyEnc, "+", "%2B", -1)384 sshkeyEnc = strings.Replace(sshkeyEnc, "@", "%40", -1)385 sshkeyEnc = strings.Replace(sshkeyEnc, "=", "%3D", -1)386 configParams["sshkeys"] = sshkeyEnc387 }388 if config.Ipconfig0 != "" {389 configParams["ipconfig0"] = config.Ipconfig0390 }391 if config.Ipconfig1 != "" {392 configParams["ipconfig1"] = config.Ipconfig1393 }394 if config.Ipconfig2 != "" {395 configParams["ipconfig2"] = config.Ipconfig2396 }397 if config.Ipconfig3 != "" {398 configParams["ipconfig3"] = config.Ipconfig3399 }400 if config.Ipconfig4 != "" {401 configParams["ipconfig4"] = config.Ipconfig4402 }403 if config.Ipconfig5 != "" {404 configParams["ipconfig5"] = config.Ipconfig5405 }406 if config.Ipconfig6 != "" {407 configParams["ipconfig6"] = config.Ipconfig6408 }409 if config.Ipconfig7 != "" {410 configParams["ipconfig7"] = config.Ipconfig7411 }412 if config.Ipconfig8 != "" {413 configParams["ipconfig8"] = config.Ipconfig8414 }415 if config.Ipconfig9 != "" {416 configParams["ipconfig9"] = config.Ipconfig9417 }418 if config.Ipconfig10 != "" {419 configParams["ipconfig10"] = config.Ipconfig10420 }421 if config.Ipconfig11 != "" {422 configParams["ipconfig11"] = config.Ipconfig11423 }424 if config.Ipconfig12 != "" {425 configParams["ipconfig12"] = config.Ipconfig12426 }427 if config.Ipconfig13 != "" {428 configParams["ipconfig13"] = config.Ipconfig13429 }430 if config.Ipconfig14 != "" {431 configParams["ipconfig14"] = config.Ipconfig14432 }433 if config.Ipconfig15 != "" {434 configParams["ipconfig15"] = config.Ipconfig15435 }436 // if len(deleteParams) > 0 {437 // configParams["delete"] = strings.Join(deleteParams, ", ")438 // }439 _, err = client.SetVmConfig(vmr, configParams)440 if err != nil {441 log.Print(err)442 return err443 }444 _, err = client.UpdateVMHA(vmr, config.HaState, config.HaGroup)445 if err != nil {446 log.Printf("[ERROR] %q", err)447 }448 _, err = client.UpdateVMPool(vmr, config.Pool)449 return err450}451func NewConfigQemuFromJson(input []byte) (config *ConfigQemu, err error) {452 config = &ConfigQemu{}453 err = json.Unmarshal([]byte(input), config)454 if err != nil {455 log.Fatal(err)456 }457 return458}459var (460 rxIso = regexp.MustCompile(`(.*?),media`)461 rxDeviceID = regexp.MustCompile(`\d+`)462 rxDiskName = regexp.MustCompile(`(virtio|scsi|ide|sata)\d+`)463 rxDiskType = regexp.MustCompile(`\D+`)464 rxUnusedDiskName = regexp.MustCompile(`^(unused)\d+`)465 rxNicName = regexp.MustCompile(`net\d+`)466 rxMpName = regexp.MustCompile(`mp\d+`)467 rxSerialName = regexp.MustCompile(`serial\d+`)468 rxUsbName = regexp.MustCompile(`usb\d+`)469 rxDiskPath = regexp.MustCompile(`^\/dev\/.*`)470)471func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err error) {472 var vmConfig map[string]interface{}473 for ii := 0; ii < 3; ii++ {474 vmConfig, err = client.GetVmConfig(vmr)475 if err != nil {476 log.Fatal(err)477 return nil, err478 }479 // this can happen:480 // {"data":{"lock":"clone","digest":"eb54fb9d9f120ba0c3bdf694f73b10002c375c38","description":" qmclone temporary file\n"}})481 if vmConfig["lock"] == nil {482 break483 } else {484 time.Sleep(8 * time.Second)485 }486 }487 if vmConfig["lock"] != nil {488 return nil, fmt.Errorf("vm locked, could not obtain config")489 }490 // vmConfig Sample: map[ cpu:host491 // net0:virtio=62:DF:XX:XX:XX:XX,bridge=vmbr0492 // ide2:local:iso/xxx-xx.iso,media=cdrom memory:2048493 // smbios1:uuid=8b3bf833-aad8-4545-xxx-xxxxxxx digest:aa6ce5xxxxx1b9ce33e4aaeff564d4 sockets:1494 // name:terraform-ubuntu1404-template bootdisk:virtio0495 // virtio0:ProxmoxxxxISCSI:vm-1014-disk-2,size=4G496 // description:Base image497 // cores:2 ostype:l26498 name := ""499 if _, isSet := vmConfig["name"]; isSet {500 name = vmConfig["name"].(string)501 }502 description := ""503 if _, isSet := vmConfig["description"]; isSet {504 description = vmConfig["description"].(string)505 }506 tags := ""507 if _, isSet := vmConfig["tags"]; isSet {508 tags = vmConfig["tags"].(string)509 }510 args := ""511 if _, isSet := vmConfig["args"]; isSet {512 args = vmConfig["args"].(string)513 }514 bios := "seabios"515 if _, isSet := vmConfig["bios"]; isSet {516 bios = vmConfig["bios"].(string)517 }518 onboot := true519 if _, isSet := vmConfig["onboot"]; isSet {520 onboot = Itob(int(vmConfig["onboot"].(float64)))521 }522 startup := ""523 if _, isSet := vmConfig["startup"]; isSet {524 startup = vmConfig["startup"].(string)525 }526 tablet := true527 if _, isSet := vmConfig["tablet"]; isSet {528 tablet = Itob(int(vmConfig["tablet"].(float64)))529 }530 agent := 0531 if _, isSet := vmConfig["agent"]; isSet {532 switch vmConfig["agent"].(type) {533 case float64:534 agent = int(vmConfig["agent"].(float64))535 case string:536 AgentConfList := strings.Split(vmConfig["agent"].(string), ",")537 agent, _ = strconv.Atoi(AgentConfList[0])538 }539 }540 ostype := "other"541 if _, isSet := vmConfig["ostype"]; isSet {542 ostype = vmConfig["ostype"].(string)543 }544 memory := 0.0545 if _, isSet := vmConfig["memory"]; isSet {546 memory = vmConfig["memory"].(float64)547 }548 balloon := 0.0549 if _, isSet := vmConfig["balloon"]; isSet {550 balloon = vmConfig["balloon"].(float64)551 }552 cores := 1.0553 if _, isSet := vmConfig["cores"]; isSet {554 cores = vmConfig["cores"].(float64)555 }556 vcpus := 0.0557 if _, isSet := vmConfig["vcpus"]; isSet {558 vcpus = vmConfig["vcpus"].(float64)559 }560 sockets := 1.0561 if _, isSet := vmConfig["sockets"]; isSet {562 sockets = vmConfig["sockets"].(float64)563 }564 cpu := "host"565 if _, isSet := vmConfig["cpu"]; isSet {566 cpu = vmConfig["cpu"].(string)567 }568 numa := false569 if _, isSet := vmConfig["numa"]; isSet {570 numa = Itob(int(vmConfig["numa"].(float64)))571 }572 //Can be network,disk,cpu,memory,usb573 hotplug := "network,disk,usb"574 if _, isSet := vmConfig["hotplug"]; isSet {575 hotplug = vmConfig["hotplug"].(string)576 }577 //boot by default from hard disk (c), CD-ROM (d), network (n).578 boot := "cdn"579 if _, isSet := vmConfig["boot"]; isSet {580 boot = vmConfig["boot"].(string)581 }582 bootdisk := ""583 if _, isSet := vmConfig["bootdisk"]; isSet {584 bootdisk = vmConfig["bootdisk"].(string)585 }586 kvm := true587 if _, isSet := vmConfig["kvm"]; isSet {588 kvm = Itob(int(vmConfig["kvm"].(float64)))589 }590 scsihw := "lsi"591 if _, isSet := vmConfig["scsihw"]; isSet {592 scsihw = vmConfig["scsihw"].(string)593 }594 hookscript := ""595 if _, isSet := vmConfig["hookscript"]; isSet {596 hookscript = vmConfig["hookscript"].(string)597 }598 config = &ConfigQemu{599 Name: name,600 Description: strings.TrimSpace(description),601 Tags: strings.TrimSpace(tags),602 Args: strings.TrimSpace(args),603 Bios: bios,604 EFIDisk: QemuDevice{},605 Onboot: &onboot,606 Startup: startup,607 Tablet: &tablet,608 Agent: agent,609 QemuOs: ostype,610 Memory: int(memory),611 QemuCores: int(cores),612 QemuSockets: int(sockets),613 QemuCpu: cpu,614 QemuNuma: &numa,615 QemuKVM: &kvm,616 Hotplug: hotplug,617 Boot: boot,618 BootDisk: bootdisk,619 Scsihw: scsihw,620 Hookscript: hookscript,621 QemuDisks: QemuDevices{},622 QemuUnusedDisks: QemuDevices{},623 QemuVga: QemuDevice{},624 QemuNetworks: QemuDevices{},625 QemuSerials: QemuDevices{},626 QemuPCIDevices: QemuDevices{},627 QemuUsbs: QemuDevices{},628 }629 if balloon >= 1 {630 config.Balloon = int(balloon)631 }632 if vcpus >= 1 {633 config.QemuVcpus = int(vcpus)634 }635 if vmConfig["ide2"] != nil {636 isoMatch := rxIso.FindStringSubmatch(vmConfig["ide2"].(string))637 config.QemuIso = isoMatch[1]638 }639 if _, isSet := vmConfig["ciuser"]; isSet {640 config.CIuser = vmConfig["ciuser"].(string)641 }642 if _, isSet := vmConfig["cipassword"]; isSet {643 config.CIpassword = vmConfig["cipassword"].(string)644 }645 if _, isSet := vmConfig["cicustom"]; isSet {646 config.CIcustom = vmConfig["cicustom"].(string)647 }648 if _, isSet := vmConfig["searchdomain"]; isSet {649 config.Searchdomain = vmConfig["searchdomain"].(string)650 }651 if _, isSet := vmConfig["nameserver"]; isSet {652 config.Nameserver = vmConfig["nameserver"].(string)653 }654 if _, isSet := vmConfig["sshkeys"]; isSet {655 config.Sshkeys, _ = url.PathUnescape(vmConfig["sshkeys"].(string))656 }657 if _, isSet := vmConfig["ipconfig0"]; isSet {658 config.Ipconfig0 = vmConfig["ipconfig0"].(string)659 }660 if _, isSet := vmConfig["ipconfig1"]; isSet {661 config.Ipconfig1 = vmConfig["ipconfig1"].(string)662 }663 if _, isSet := vmConfig["ipconfig2"]; isSet {664 config.Ipconfig2 = vmConfig["ipconfig2"].(string)665 }666 if _, isSet := vmConfig["ipconfig3"]; isSet {667 config.Ipconfig3 = vmConfig["ipconfig3"].(string)668 }669 if _, isSet := vmConfig["ipconfig4"]; isSet {670 config.Ipconfig4 = vmConfig["ipconfig4"].(string)671 }672 if _, isSet := vmConfig["ipconfig5"]; isSet {673 config.Ipconfig5 = vmConfig["ipconfig5"].(string)674 }675 if _, isSet := vmConfig["ipconfig6"]; isSet {676 config.Ipconfig6 = vmConfig["ipconfig6"].(string)677 }678 if _, isSet := vmConfig["ipconfig7"]; isSet {679 config.Ipconfig7 = vmConfig["ipconfig7"].(string)680 }681 if _, isSet := vmConfig["ipconfig8"]; isSet {682 config.Ipconfig8 = vmConfig["ipconfig8"].(string)683 }684 if _, isSet := vmConfig["ipconfig9"]; isSet {685 config.Ipconfig9 = vmConfig["ipconfig9"].(string)686 }687 if _, isSet := vmConfig["ipconfig10"]; isSet {688 config.Ipconfig10 = vmConfig["ipconfig10"].(string)689 }690 if _, isSet := vmConfig["ipconfig11"]; isSet {691 config.Ipconfig11 = vmConfig["ipconfig11"].(string)692 }693 if _, isSet := vmConfig["ipconfig12"]; isSet {694 config.Ipconfig12 = vmConfig["ipconfig12"].(string)695 }696 if _, isSet := vmConfig["ipconfig13"]; isSet {697 config.Ipconfig13 = vmConfig["ipconfig13"].(string)698 }699 if _, isSet := vmConfig["ipconfig14"]; isSet {700 config.Ipconfig14 = vmConfig["ipconfig14"].(string)701 }702 if _, isSet := vmConfig["ipconfig15"]; isSet {703 config.Ipconfig15 = vmConfig["ipconfig15"].(string)704 }705 // Add disks.706 diskNames := []string{}707 for k := range vmConfig {708 if diskName := rxDiskName.FindStringSubmatch(k); len(diskName) > 0 {709 diskNames = append(diskNames, diskName[0])710 }711 }712 for _, diskName := range diskNames {713 var isDiskByID bool = false714 diskConfStr := vmConfig[diskName].(string)715 id := rxDeviceID.FindStringSubmatch(diskName)716 diskID, _ := strconv.Atoi(id[0])717 diskType := rxDiskType.FindStringSubmatch(diskName)[0]718 diskConfMap := ParsePMConf(diskConfStr, "volume")719 diskByID := rxDiskPath.FindStringSubmatch(diskConfMap["volume"].(string))720 if len(diskByID) > 0 && diskByID[0] != "" {721 isDiskByID = true722 }723 if diskConfMap["volume"].(string) == "none" {724 continue725 }726 diskConfMap["slot"] = diskID727 diskConfMap["type"] = diskType728 storageName, fileName := ParseSubConf(diskConfMap["volume"].(string), ":")729 diskConfMap["storage"] = storageName730 diskConfMap["file"] = fileName731 filePath := diskConfMap["volume"]732 // Get disk format733 storageContent, err := client.GetStorageContent(vmr, storageName)734 if err != nil {735 log.Fatal(err)736 return nil, err737 }738 var storageFormat string739 contents := storageContent["data"].([]interface{})740 for content := range contents {741 storageContentMap := contents[content].(map[string]interface{})742 if storageContentMap["volid"] == filePath {743 storageFormat = storageContentMap["format"].(string)744 break745 }746 }747 diskConfMap["format"] = storageFormat748 // Get storage type for disk749 var storageStatus map[string]interface{}750 if !isDiskByID {751 storageStatus, err = client.GetStorageStatus(vmr, storageName)752 if err != nil {753 log.Fatal(err)754 return nil, err755 }756 storageType := storageStatus["type"]757 diskConfMap["storage_type"] = storageType758 }759 // cloud-init disks not always have the size sent by the API, which results in a crash760 if diskConfMap["size"] == nil && strings.Contains(fileName.(string), "cloudinit") {761 diskConfMap["size"] = "4M" // default cloud-init disk size762 }763 var sizeInTerabytes = regexp.MustCompile(`[0-9]+T`)764 // Convert to gigabytes if disk size was received in terabytes765 matched := sizeInTerabytes.MatchString(diskConfMap["size"].(string))766 if matched {767 diskConfMap["size"] = fmt.Sprintf("%.0fG", DiskSizeGB(diskConfMap["size"]))768 }769 // And device config to disks map.770 if len(diskConfMap) > 0 {771 config.QemuDisks[diskID] = diskConfMap772 }773 }774 // Add unused disks775 // unused0:local:100/vm-100-disk-1.qcow2776 unusedDiskNames := []string{}777 for k := range vmConfig {778 // look for entries from the config in the format "unusedX:<storagepath>" where X is an integer779 if unusedDiskName := rxUnusedDiskName.FindStringSubmatch(k); len(unusedDiskName) > 0 {780 unusedDiskNames = append(unusedDiskNames, unusedDiskName[0])781 }782 }783 // if len(unusedDiskNames) > 0 {784 // log.Printf("[DEBUG] unusedDiskNames: %v", unusedDiskNames)785 // }786 for _, unusedDiskName := range unusedDiskNames {787 unusedDiskConfStr := vmConfig[unusedDiskName].(string)788 finalDiskConfMap := QemuDevice{}789 // parse "unused0" to get the id '0' as an int790 id := rxDeviceID.FindStringSubmatch(unusedDiskName)791 diskID, err := strconv.Atoi(id[0])792 if err != nil {793 return nil, fmt.Errorf(fmt.Sprintf("Unable to parse unused disk id from input string '%v' tried to convert '%v' to integer.", unusedDiskName, diskID))794 }795 finalDiskConfMap["slot"] = diskID796 // parse the attributes from the unused disk797 // extract the storage and file path from the unused disk entry798 parsedUnusedDiskMap := ParsePMConf(unusedDiskConfStr, "storage+file")799 storageName, fileName := ParseSubConf(parsedUnusedDiskMap["storage+file"].(string), ":")800 finalDiskConfMap["storage"] = storageName801 finalDiskConfMap["file"] = fileName802 config.QemuUnusedDisks[diskID] = finalDiskConfMap803 }804 //Display805 if vga, isSet := vmConfig["vga"]; isSet {806 vgaList := strings.Split(vga.(string), ",")807 vgaMap := QemuDevice{}808 // TODO: keep going if error?809 err = vgaMap.readDeviceConfig(vgaList)810 if err != nil {811 log.Printf("[ERROR] %q", err)812 }813 if len(vgaMap) > 0 {814 config.QemuVga = vgaMap815 }816 }817 // Add networks.818 nicNames := []string{}819 for k := range vmConfig {820 if nicName := rxNicName.FindStringSubmatch(k); len(nicName) > 0 {821 nicNames = append(nicNames, nicName[0])822 }823 }824 for _, nicName := range nicNames {825 nicConfStr := vmConfig[nicName]826 nicConfList := strings.Split(nicConfStr.(string), ",")827 id := rxDeviceID.FindStringSubmatch(nicName)828 nicID, _ := strconv.Atoi(id[0])829 model, macaddr := ParseSubConf(nicConfList[0], "=")830 // Add model and MAC address.831 nicConfMap := QemuDevice{832 "id": nicID,833 "model": model,834 "macaddr": macaddr,835 }836 // Add rest of device config.837 err = nicConfMap.readDeviceConfig(nicConfList[1:])838 if err != nil {839 log.Printf("[ERROR] %q", err)840 }841 switch nicConfMap["firewall"] {842 case 1:843 nicConfMap["firewall"] = true844 case 0:845 nicConfMap["firewall"] = false846 }847 switch nicConfMap["link_down"] {848 case 1:849 nicConfMap["link_down"] = true850 case 0:851 nicConfMap["link_down"] = false852 }853 // And device config to networks.854 if len(nicConfMap) > 0 {855 config.QemuNetworks[nicID] = nicConfMap856 }857 }858 // Add serials859 serialNames := []string{}860 for k := range vmConfig {861 if serialName := rxSerialName.FindStringSubmatch(k); len(serialName) > 0 {862 serialNames = append(serialNames, serialName[0])863 }864 }865 for _, serialName := range serialNames {866 id := rxDeviceID.FindStringSubmatch(serialName)867 serialID, _ := strconv.Atoi(id[0])868 serialConfMap := QemuDevice{869 "id": serialID,870 "type": vmConfig[serialName],871 }872 // And device config to serials map.873 if len(serialConfMap) > 0 {874 config.QemuSerials[serialID] = serialConfMap875 }876 }877 // Add usbs878 usbNames := []string{}879 for k := range vmConfig {880 if usbName := rxUsbName.FindStringSubmatch(k); len(usbName) > 0 {881 usbNames = append(usbNames, usbName[0])882 }883 }884 for _, usbName := range usbNames {885 usbConfStr := vmConfig[usbName]886 usbConfList := strings.Split(usbConfStr.(string), ",")887 id := rxDeviceID.FindStringSubmatch(usbName)888 usbID, _ := strconv.Atoi(id[0])889 _, host := ParseSubConf(usbConfList[0], "=")890 usbConfMap := QemuDevice{891 "id": usbID,892 "host": host,893 }894 err = usbConfMap.readDeviceConfig(usbConfList[1:])895 if err != nil {896 log.Printf("[ERROR] %q", err)897 }898 if usbConfMap["usb3"] == 1 {899 usbConfMap["usb3"] = true900 }901 // And device config to usbs map.902 if len(usbConfMap) > 0 {903 config.QemuUsbs[usbID] = usbConfMap904 }905 }906 // hastate is return by the api for a vm resource type but not the hagroup907 err = client.ReadVMHA(vmr)908 if err == nil {909 config.HaState = vmr.HaState()910 config.HaGroup = vmr.HaGroup()911 } else {912 //log.Printf("[DEBUG] VM %d(%s) has no HA config", vmr.vmId, vmConfig["hostname"])913 return config, nil914 }915 return916}917// Useful waiting for ISO install to complete918func WaitForShutdown(vmr *VmRef, client *Client) (err error) {919 for ii := 0; ii < 100; ii++ {920 vmState, err := client.GetVmState(vmr)921 if err != nil {922 log.Print("Wait error:")923 log.Println(err)924 } else if vmState["status"] == "stopped" {925 return nil926 }927 time.Sleep(5 * time.Second)928 }929 return fmt.Errorf("not shutdown within wait time")930}931// This is because proxmox create/config API won't let us make usernet devices932func SshForwardUsernet(vmr *VmRef, client *Client) (sshPort string, err error) {933 vmState, err := client.GetVmState(vmr)934 if err != nil {935 return "", err936 }937 if vmState["status"] == "stopped" {938 return "", fmt.Errorf("VM must be running first")939 }940 sshPort = strconv.Itoa(vmr.VmId() + 22000)941 _, err = client.MonitorCmd(vmr, "netdev_add user,id=net1,hostfwd=tcp::"+sshPort+"-:22")942 if err != nil {943 return "", err944 }945 _, err = client.MonitorCmd(vmr, "device_add virtio-net-pci,id=net1,netdev=net1,addr=0x13")946 if err != nil {947 return "", err948 }949 return950}951// device_del net1952// netdev_del net1953func RemoveSshForwardUsernet(vmr *VmRef, client *Client) (err error) {954 vmState, err := client.GetVmState(vmr)955 if err != nil {956 return err957 }958 if vmState["status"] == "stopped" {959 return fmt.Errorf("VM must be running first")960 }961 _, err = client.MonitorCmd(vmr, "device_del net1")962 if err != nil {963 return err964 }965 _, err = client.MonitorCmd(vmr, "netdev_del net1")966 if err != nil {967 return err968 }969 return nil970}971func MaxVmId(client *Client) (max int, err error) {972 resp, err := client.GetVmList()973 vms := resp["data"].([]interface{})974 max = 100975 for vmii := range vms {976 vm := vms[vmii].(map[string]interface{})977 vmid := int(vm["vmid"].(float64))978 if vmid > max {979 max = vmid980 }981 }982 return983}984func SendKeysString(vmr *VmRef, client *Client, keys string) (err error) {985 vmState, err := client.GetVmState(vmr)986 if err != nil {987 return err988 }989 if vmState["status"] == "stopped" {990 return fmt.Errorf("VM must be running first")991 }992 for _, r := range keys {993 c := string(r)994 lower := strings.ToLower(c)995 if c != lower {996 c = "shift-" + lower997 } else {998 switch c {999 case "!":1000 c = "shift-1"1001 case "@":1002 c = "shift-2"1003 case "#":1004 c = "shift-3"1005 case "$":1006 c = "shift-4"1007 case "%%":1008 c = "shift-5"1009 case "^":1010 c = "shift-6"1011 case "&":1012 c = "shift-7"1013 case "*":1014 c = "shift-8"1015 case "(":1016 c = "shift-9"1017 case ")":1018 c = "shift-0"1019 case "_":1020 c = "shift-minus"1021 case "+":1022 c = "shift-equal"1023 case " ":1024 c = "spc"1025 case "/":1026 c = "slash"1027 case "\\":1028 c = "backslash"1029 case ",":1030 c = "comma"1031 case "-":1032 c = "minus"1033 case "=":1034 c = "equal"1035 case ".":1036 c = "dot"1037 case "?":1038 c = "shift-slash"1039 }1040 }1041 _, err = client.MonitorCmd(vmr, "sendkey "+c)1042 if err != nil {1043 return err1044 }1045 time.Sleep(1 * time.Millisecond)1046 }1047 return nil1048}1049// Given a QemuDevice, return a param string to give to ProxMox1050func formatDeviceParam(device QemuDevice) string {1051 deviceConfParams := QemuDeviceParam{}1052 deviceConfParams = deviceConfParams.createDeviceParam(device, nil)1053 return strings.Join(deviceConfParams, ",")1054}1055// Given a QemuDevice (represesting a disk), return a param string to give to ProxMox1056func FormatDiskParam(disk QemuDevice) string {1057 diskConfParam := QemuDeviceParam{}1058 if volume, ok := disk["volume"]; ok && volume != "" {1059 diskConfParam = append(diskConfParam, volume.(string))1060 diskConfParam = append(diskConfParam, fmt.Sprintf("size=%v", disk["size"]))1061 } else {1062 volumeInit := fmt.Sprintf("%v:%v", disk["storage"], DiskSizeGB(disk["size"]))1063 diskConfParam = append(diskConfParam, volumeInit)1064 }1065 // Set cache if not none (default).1066 if cache, ok := disk["cache"]; ok && cache != "none" {1067 diskCache := fmt.Sprintf("cache=%v", disk["cache"])1068 diskConfParam = append(diskConfParam, diskCache)1069 }1070 // Mountoptions1071 if mountoptions, ok := disk["mountoptions"]; ok {1072 options := []string{}1073 for opt, enabled := range mountoptions.(map[string]interface{}) {1074 if enabled.(bool) {1075 options = append(options, opt)1076 }1077 }1078 diskMountOpts := fmt.Sprintf("mountoptions=%v", strings.Join(options, ";"))1079 diskConfParam = append(diskConfParam, diskMountOpts)1080 }1081 // Keys that are not used as real/direct conf.1082 ignoredKeys := []string{"key", "slot", "type", "storage", "file", "size", "cache", "volume", "container", "vm", "mountoptions", "storage_type"}1083 // Rest of config.1084 diskConfParam = diskConfParam.createDeviceParam(disk, ignoredKeys)1085 return strings.Join(diskConfParam, ",")1086}1087// Given a QemuDevice (represesting a usb), return a param string to give to ProxMox1088func FormatUsbParam(usb QemuDevice) string {1089 usbConfParam := QemuDeviceParam{}1090 usbConfParam = usbConfParam.createDeviceParam(usb, []string{})1091 return strings.Join(usbConfParam, ",")1092}1093// Create parameters for each Nic device.1094func (c ConfigQemu) CreateQemuNetworksParams(vmID int, params map[string]interface{}) error {1095 // For new style with multi net device.1096 for nicID, nicConfMap := range c.QemuNetworks {1097 nicConfParam := QemuDeviceParam{}1098 // Set Nic name.1099 qemuNicName := "net" + strconv.Itoa(nicID)1100 // Set Mac address.1101 var macAddr string1102 switch nicConfMap["macaddr"] {1103 case nil, "":1104 // Generate random Mac based on time1105 macaddr := make(net.HardwareAddr, 6)1106 rand.Seed(time.Now().UnixNano())1107 rand.Read(macaddr)1108 macaddr[0] = (macaddr[0] | 2) & 0xfe // fix from github issue #181109 macAddr = strings.ToUpper(fmt.Sprintf("%v", macaddr))1110 // Add Mac to source map so it will be returned. (useful for some use case like Terraform)1111 nicConfMap["macaddr"] = macAddr1112 case "repeatable":1113 // Generate deterministic Mac based on VmID and NicID1114 // Assume that rare VM has more than 32 nics1115 macaddr := make(net.HardwareAddr, 6)1116 pairing := vmID<<5 | nicID1117 // Linux MAC vendor - 00:18:591118 macaddr[0] = 0x001119 macaddr[1] = 0x181120 macaddr[2] = 0x591121 macaddr[3] = byte((pairing >> 16) & 0xff)1122 macaddr[4] = byte((pairing >> 8) & 0xff)1123 macaddr[5] = byte(pairing & 0xff)1124 // Convert to string1125 macAddr = strings.ToUpper(fmt.Sprintf("%v", macaddr))1126 // Add Mac to source map so it will be returned. (useful for some use case like Terraform)1127 nicConfMap["macaddr"] = macAddr1128 default:1129 macAddr = nicConfMap["macaddr"].(string)1130 }1131 // use model=mac format for older proxmox compatability as the parameters which will be sent to Proxmox API.1132 nicConfParam = append(nicConfParam, fmt.Sprintf("%v=%v", nicConfMap["model"], macAddr))1133 // Set bridge if not nat.1134 if nicConfMap["bridge"].(string) != "nat" {1135 bridge := fmt.Sprintf("bridge=%v", nicConfMap["bridge"])1136 nicConfParam = append(nicConfParam, bridge)1137 }1138 // Keys that are not used as real/direct conf.1139 ignoredKeys := []string{"id", "bridge", "macaddr", "model"}1140 // Rest of config.1141 nicConfParam = nicConfParam.createDeviceParam(nicConfMap, ignoredKeys)1142 // Add nic to Qemu prams.1143 params[qemuNicName] = strings.Join(nicConfParam, ",")1144 }1145 return nil1146}1147// Create efi parameter.1148func (c ConfigQemu) CreateQemuEfiParams(1149 params map[string]interface{},1150) error {1151 efiParam := QemuDeviceParam{}1152 efiParam = efiParam.createDeviceParam(c.EFIDisk, nil)1153 if len(efiParam) > 0 {1154 storage_info := []string{}1155 storage := ""1156 for _, param := range efiParam {1157 key := strings.Split(param, "=")1158 if key[0] == "storage" {1159 // Proxmox format for disk creation1160 storage = fmt.Sprintf("%s:1", key[1])1161 } else {1162 storage_info = append(storage_info, param)1163 }1164 }1165 if len(storage_info) > 0 {1166 storage = fmt.Sprintf("%s,%s", storage, strings.Join(storage_info, ","))1167 }1168 params["efidisk0"] = storage1169 }1170 return nil1171}1172// Create parameters for each disk.1173func (c ConfigQemu) CreateQemuDisksParams(1174 vmID int,1175 params map[string]interface{},1176 cloned bool,1177) error {1178 // For new style with multi disk device.1179 for diskID, diskConfMap := range c.QemuDisks {1180 // skip the first disk for clones (may not always be right, but a template probably has at least 1 disk)1181 if diskID == 0 && cloned {1182 continue1183 }1184 // Device name.1185 deviceType := diskConfMap["type"].(string)1186 qemuDiskName := deviceType + strconv.Itoa(diskID)1187 // Add back to Qemu prams.1188 params[qemuDiskName] = FormatDiskParam(diskConfMap)1189 }1190 return nil1191}1192// Create parameters for each PCI Device1193func (c ConfigQemu) CreateQemuPCIsParams(1194 vmID int,1195 params map[string]interface{},1196) error {1197 // For new style with multi pci device.1198 for pciConfID, pciConfMap := range c.QemuPCIDevices {1199 qemuPCIName := "hostpci" + strconv.Itoa(pciConfID)1200 var pcistring bytes.Buffer1201 for elem := range pciConfMap {1202 pcistring.WriteString(elem)1203 pcistring.WriteString("=")1204 pcistring.WriteString(fmt.Sprintf("%v", pciConfMap[elem]))1205 pcistring.WriteString(",")1206 }1207 // Add back to Qemu prams.1208 params[qemuPCIName] = strings.TrimSuffix(pcistring.String(), ",")1209 }1210 return nil1211}1212// Create parameters for serial interface1213func (c ConfigQemu) CreateQemuSerialsParams(1214 vmID int,1215 params map[string]interface{},1216) error {1217 // For new style with multi disk device.1218 for serialID, serialConfMap := range c.QemuSerials {1219 // Device name.1220 deviceType := serialConfMap["type"].(string)1221 qemuSerialName := "serial" + strconv.Itoa(serialID)1222 // Add back to Qemu prams.1223 params[qemuSerialName] = deviceType1224 }1225 return nil1226}1227// Create parameters for usb interface1228func (c ConfigQemu) CreateQemuUsbsParams(1229 vmID int,1230 params map[string]interface{},1231) error {1232 for usbID, usbConfMap := range c.QemuUsbs {1233 qemuUsbName := "usb" + strconv.Itoa(usbID)1234 // Add back to Qemu prams.1235 params[qemuUsbName] = FormatUsbParam(usbConfMap)1236 }1237 return nil1238}1239// Create parameters for serial interface1240func (c ConfigQemu) CreateQemuMachineParam(1241 params map[string]interface{},1242) error {1243 if c.Machine == "" {1244 return nil1245 }1246 if matched, _ := regexp.MatchString(machineModels, c.Machine); matched {1247 params["machine"] = c.Machine1248 return nil1249 }1250 return fmt.Errorf("unsupported machine type, fall back to default")1251}1252func (p QemuDeviceParam) createDeviceParam(1253 deviceConfMap QemuDevice,1254 ignoredKeys []string,...

Full Screen

Full Screen

qemu_test.go

Source:qemu_test.go Github

copy

Full Screen

...62 }63 testQemuKernelParameters(t, params, expectedOut, true)64 testQemuKernelParameters(t, params, expectedOut, false)65}66func TestQemuCreateVM(t *testing.T) {67 qemuConfig := newQemuConfig()68 assert := assert.New(t)69 store, err := persist.GetDriver()70 assert.NoError(err)71 q := &qemu{72 config: HypervisorConfig{73 VMStorePath: store.RunVMStoragePath(),74 RunStorePath: store.RunStoragePath(),75 },76 }77 sandbox := &Sandbox{78 ctx: context.Background(),79 id: "testSandbox",80 config: &SandboxConfig{81 HypervisorConfig: qemuConfig,82 },83 }84 // Create the hypervisor fake binary85 testQemuPath := filepath.Join(testDir, testHypervisor)86 _, err = os.Create(testQemuPath)87 assert.NoError(err)88 // Create parent dir path for hypervisor.json89 parentDir := filepath.Join(store.RunStoragePath(), sandbox.id)90 assert.NoError(os.MkdirAll(parentDir, DirMode))91 network, err := NewNetwork()92 assert.NoError(err)93 err = q.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)94 assert.NoError(err)95 assert.NoError(os.RemoveAll(parentDir))96 assert.Exactly(qemuConfig, q.config)97}98func TestQemuCreateVMMissingParentDirFail(t *testing.T) {99 qemuConfig := newQemuConfig()100 assert := assert.New(t)101 store, err := persist.GetDriver()102 assert.NoError(err)103 q := &qemu{104 config: HypervisorConfig{105 VMStorePath: store.RunVMStoragePath(),106 RunStorePath: store.RunStoragePath(),107 },108 }109 sandbox := &Sandbox{110 ctx: context.Background(),111 id: "testSandbox",112 config: &SandboxConfig{113 HypervisorConfig: qemuConfig,114 },115 }116 // Create the hypervisor fake binary117 testQemuPath := filepath.Join(testDir, testHypervisor)118 _, err = os.Create(testQemuPath)119 assert.NoError(err)120 // Ensure parent dir path for hypervisor.json does not exist.121 parentDir := filepath.Join(store.RunStoragePath(), sandbox.id)122 assert.NoError(os.RemoveAll(parentDir))123 network, err := NewNetwork()124 assert.NoError(err)125 err = q.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)126 assert.NoError(err)127}128func TestQemuCPUTopology(t *testing.T) {129 assert := assert.New(t)130 vcpus := 1131 q := &qemu{132 arch: &qemuArchBase{},133 config: HypervisorConfig{134 NumVCPUs: uint32(vcpus),135 DefaultMaxVCPUs: uint32(vcpus),136 },137 }138 expectedOut := govmmQemu.SMP{139 CPUs: uint32(vcpus),140 Sockets: uint32(vcpus),141 Cores: defaultCores,142 Threads: defaultThreads,143 MaxCPUs: uint32(vcpus),144 }145 smp := q.cpuTopology()146 assert.Exactly(smp, expectedOut)147}148func TestQemuMemoryTopology(t *testing.T) {149 mem := uint32(1000)150 maxMem := memory.TotalMemory() / 1024 / 1024 //MiB151 slots := uint32(8)152 assert := assert.New(t)153 q := &qemu{154 arch: &qemuArchBase{},155 config: HypervisorConfig{156 MemorySize: mem,157 MemSlots: slots,158 DefaultMaxMemorySize: maxMem,159 },160 }161 memMax := fmt.Sprintf("%dM", int(maxMem))162 expectedOut := govmmQemu.Memory{163 Size: fmt.Sprintf("%dM", mem),164 Slots: uint8(slots),165 MaxMem: memMax,166 }167 memory, err := q.memoryTopology()168 assert.NoError(err)169 assert.Exactly(memory, expectedOut)170}171func TestQemuKnobs(t *testing.T) {172 assert := assert.New(t)173 sandbox, err := createQemuSandboxConfig()174 assert.NoError(err)175 q := &qemu{176 config: HypervisorConfig{177 VMStorePath: sandbox.store.RunVMStoragePath(),178 RunStorePath: sandbox.store.RunStoragePath(),179 },180 }181 network, err := NewNetwork()182 assert.NoError(err)183 err = q.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)184 assert.NoError(err)185 assert.Equal(q.qemuConfig.Knobs.NoUserConfig, true)186 assert.Equal(q.qemuConfig.Knobs.NoDefaults, true)187 assert.Equal(q.qemuConfig.Knobs.NoGraphic, true)188 assert.Equal(q.qemuConfig.Knobs.NoReboot, true)189}190func testQemuAddDevice(t *testing.T, devInfo interface{}, devType DeviceType, expected []govmmQemu.Device) {191 assert := assert.New(t)192 q := &qemu{193 ctx: context.Background(),194 arch: &qemuArchBase{},195 }196 err := q.AddDevice(context.Background(), devInfo, devType)197 assert.NoError(err)198 assert.Exactly(q.qemuConfig.Devices, expected)199}200func TestQemuAddDeviceFsDev(t *testing.T) {201 mountTag := "testMountTag"202 hostPath := "testHostPath"203 expectedOut := []govmmQemu.Device{204 govmmQemu.FSDevice{205 Driver: govmmQemu.Virtio9P,206 FSDriver: govmmQemu.Local,207 ID: fmt.Sprintf("extra-9p-%s", mountTag),208 Path: hostPath,209 MountTag: mountTag,210 SecurityModel: govmmQemu.None,211 Multidev: govmmQemu.Remap,212 },213 }214 volume := types.Volume{215 MountTag: mountTag,216 HostPath: hostPath,217 }218 testQemuAddDevice(t, volume, FsDev, expectedOut)219}220func TestQemuAddDeviceVhostUserBlk(t *testing.T) {221 socketPath := "/test/socket/path"222 devID := "testDevID"223 expectedOut := []govmmQemu.Device{224 govmmQemu.VhostUserDevice{225 SocketPath: socketPath,226 CharDevID: utils.MakeNameID("char", devID, maxDevIDSize),227 VhostUserType: govmmQemu.VhostUserBlk,228 },229 }230 vDevice := config.VhostUserDeviceAttrs{231 DevID: devID,232 SocketPath: socketPath,233 Type: config.VhostUserBlk,234 }235 testQemuAddDevice(t, vDevice, VhostuserDev, expectedOut)236}237func TestQemuAddDeviceSerialPortDev(t *testing.T) {238 deviceID := "channelTest"239 id := "charchTest"240 hostPath := "/tmp/hyper_test.sock"241 name := "sh.hyper.channel.test"242 expectedOut := []govmmQemu.Device{243 govmmQemu.CharDevice{244 Driver: govmmQemu.VirtioSerialPort,245 Backend: govmmQemu.Socket,246 DeviceID: deviceID,247 ID: id,248 Path: hostPath,249 Name: name,250 },251 }252 socket := types.Socket{253 DeviceID: deviceID,254 ID: id,255 HostPath: hostPath,256 Name: name,257 }258 testQemuAddDevice(t, socket, SerialPortDev, expectedOut)259}260func TestQemuAddDeviceKataVSOCK(t *testing.T) {261 assert := assert.New(t)262 dir := t.TempDir()263 vsockFilename := filepath.Join(dir, "vsock")264 contextID := uint64(3)265 port := uint32(1024)266 vsockFile, err := os.Create(vsockFilename)267 assert.NoError(err)268 defer vsockFile.Close()269 expectedOut := []govmmQemu.Device{270 govmmQemu.VSOCKDevice{271 ID: fmt.Sprintf("vsock-%d", contextID),272 ContextID: contextID,273 VHostFD: vsockFile,274 },275 }276 vsock := types.VSock{277 ContextID: contextID,278 Port: port,279 VhostFd: vsockFile,280 }281 testQemuAddDevice(t, vsock, VSockPCIDev, expectedOut)282}283func TestQemuGetSandboxConsole(t *testing.T) {284 assert := assert.New(t)285 store, err := persist.GetDriver()286 assert.NoError(err)287 q := &qemu{288 ctx: context.Background(),289 config: HypervisorConfig{290 VMStorePath: store.RunVMStoragePath(),291 RunStorePath: store.RunStoragePath(),292 },293 }294 sandboxID := "testSandboxID"295 expected := filepath.Join(store.RunVMStoragePath(), sandboxID, consoleSocket)296 proto, result, err := q.GetVMConsole(q.ctx, sandboxID)297 assert.NoError(err)298 assert.Equal(result, expected)299 assert.Equal(proto, consoleProtoUnix)300}301func TestQemuCapabilities(t *testing.T) {302 assert := assert.New(t)303 q := &qemu{304 ctx: context.Background(),305 arch: &qemuArchBase{},306 }307 caps := q.Capabilities(q.ctx)308 assert.True(caps.IsBlockDeviceHotplugSupported())309}310func TestQemuQemuPath(t *testing.T) {311 assert := assert.New(t)312 f, err := os.CreateTemp("", "qemu")313 assert.NoError(err)314 defer func() { _ = f.Close() }()315 defer func() { _ = os.Remove(f.Name()) }()316 expectedPath := f.Name()317 qemuConfig := newQemuConfig()318 qemuConfig.HypervisorPath = expectedPath319 qkvm := &qemuArchBase{320 qemuMachine: govmmQemu.Machine{321 Type: "q35",322 Options: "",323 },324 qemuExePath: expectedPath,325 }326 q := &qemu{327 config: qemuConfig,328 arch: qkvm,329 }330 // get config hypervisor path331 path, err := q.qemuPath()332 assert.NoError(err)333 assert.Equal(path, expectedPath)334 // config hypervisor path does not exist335 q.config.HypervisorPath = "/abc/rgb/123"336 path, err = q.qemuPath()337 assert.Error(err)338 assert.Equal(path, "")339 // get arch hypervisor path340 q.config.HypervisorPath = ""341 path, err = q.qemuPath()342 assert.NoError(err)343 assert.Equal(path, expectedPath)344}345func TestHotplugUnsupportedDeviceType(t *testing.T) {346 assert := assert.New(t)347 qemuConfig := newQemuConfig()348 q := &qemu{349 ctx: context.Background(),350 id: "qemuTest",351 config: qemuConfig,352 }353 _, err := q.HotplugAddDevice(context.Background(), &MemoryDevice{0, 128, uint64(0), false}, FsDev)354 assert.Error(err)355 _, err = q.HotplugRemoveDevice(context.Background(), &MemoryDevice{0, 128, uint64(0), false}, FsDev)356 assert.Error(err)357}358func TestQMPSetupShutdown(t *testing.T) {359 assert := assert.New(t)360 qemuConfig := newQemuConfig()361 q := &qemu{362 config: qemuConfig,363 }364 q.qmpShutdown()365 q.qmpMonitorCh.qmp = &govmmQemu.QMP{}366 err := q.qmpSetup()367 assert.Nil(err)368}369func TestQemuCleanup(t *testing.T) {370 assert := assert.New(t)371 q := &qemu{372 ctx: context.Background(),373 config: newQemuConfig(),374 }375 err := q.Cleanup(q.ctx)376 assert.Nil(err)377}378func TestQemuGrpc(t *testing.T) {379 assert := assert.New(t)380 config := newQemuConfig()381 q := &qemu{382 id: "testqemu",383 config: config,384 }385 json, err := q.toGrpc(context.Background())386 assert.Nil(err)387 var q2 qemu388 err = q2.fromGrpc(context.Background(), &config, json)389 assert.Nil(err)390 assert.True(q.id == q2.id)391}392func TestQemuFileBackedMem(t *testing.T) {393 assert := assert.New(t)394 // Check default Filebackedmem location for virtio-fs395 sandbox, err := createQemuSandboxConfig()396 assert.NoError(err)397 network, err := NewNetwork()398 assert.NoError(err)399 q := &qemu{400 config: HypervisorConfig{401 VMStorePath: sandbox.store.RunVMStoragePath(),402 RunStorePath: sandbox.store.RunStoragePath(),403 },404 }405 sandbox.config.HypervisorConfig.SharedFS = config.VirtioFS406 err = q.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)407 assert.NoError(err)408 assert.Equal(q.qemuConfig.Knobs.FileBackedMem, true)409 assert.Equal(q.qemuConfig.Knobs.MemShared, true)410 assert.Equal(q.qemuConfig.Memory.Path, fallbackFileBackedMemDir)411 // Check failure for VM templating412 sandbox, err = createQemuSandboxConfig()413 assert.NoError(err)414 q = &qemu{415 config: HypervisorConfig{416 VMStorePath: sandbox.store.RunVMStoragePath(),417 RunStorePath: sandbox.store.RunStoragePath(),418 },419 }420 sandbox.config.HypervisorConfig.BootToBeTemplate = true421 sandbox.config.HypervisorConfig.SharedFS = config.VirtioFS422 sandbox.config.HypervisorConfig.MemoryPath = fallbackFileBackedMemDir423 err = q.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)424 expectErr := errors.New("VM templating has been enabled with either virtio-fs or file backed memory and this configuration will not work")425 assert.Equal(expectErr.Error(), err.Error())426 // Check Setting of non-existent shared-mem path427 sandbox, err = createQemuSandboxConfig()428 assert.NoError(err)429 q = &qemu{430 config: HypervisorConfig{431 VMStorePath: sandbox.store.RunVMStoragePath(),432 RunStorePath: sandbox.store.RunStoragePath(),433 },434 }435 sandbox.config.HypervisorConfig.FileBackedMemRootDir = "/tmp/xyzabc"436 err = q.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)437 assert.NoError(err)438 assert.Equal(q.qemuConfig.Knobs.FileBackedMem, false)439 assert.Equal(q.qemuConfig.Knobs.MemShared, false)440 assert.Equal(q.qemuConfig.Memory.Path, "")441 // Check setting vhost-user storage with Hugepages442 sandbox, err = createQemuSandboxConfig()443 assert.NoError(err)444 q = &qemu{445 config: HypervisorConfig{446 VMStorePath: sandbox.store.RunVMStoragePath(),447 RunStorePath: sandbox.store.RunStoragePath(),448 },449 }450 sandbox.config.HypervisorConfig.EnableVhostUserStore = true451 sandbox.config.HypervisorConfig.HugePages = true452 err = q.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)453 assert.NoError(err)454 assert.Equal(q.qemuConfig.Knobs.MemShared, true)455 // Check failure for vhost-user storage456 sandbox, err = createQemuSandboxConfig()457 assert.NoError(err)458 q = &qemu{459 config: HypervisorConfig{460 VMStorePath: sandbox.store.RunVMStoragePath(),461 RunStorePath: sandbox.store.RunStoragePath(),462 },463 }464 sandbox.config.HypervisorConfig.EnableVhostUserStore = true465 sandbox.config.HypervisorConfig.HugePages = false466 err = q.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)467 expectErr = errors.New("Vhost-user-blk/scsi is enabled without HugePages. This configuration will not work")468 assert.Equal(expectErr.Error(), err.Error())469}470func createQemuSandboxConfig() (*Sandbox, error) {471 qemuConfig := newQemuConfig()472 sandbox := Sandbox{473 ctx: context.Background(),474 id: "testSandbox",475 config: &SandboxConfig{476 HypervisorConfig: qemuConfig,477 },478 }479 store, err := persist.GetDriver()480 if err != nil {481 return &Sandbox{}, err482 }483 sandbox.store = store484 return &sandbox, nil485}486func TestQemuGetpids(t *testing.T) {487 assert := assert.New(t)488 qemuConfig := newQemuConfig()489 q := &qemu{}490 pids := q.GetPids()491 assert.NotNil(pids)492 assert.True(len(pids) == 1)493 assert.True(pids[0] == 0)494 q = &qemu{495 config: qemuConfig,496 }497 f, err := os.CreateTemp("", "qemu-test-")498 assert.Nil(err)499 tmpfile := f.Name()500 f.Close()501 defer os.Remove(tmpfile)502 q.qemuConfig.PidFile = tmpfile503 pids = q.GetPids()504 assert.True(len(pids) == 1)505 assert.True(pids[0] == 0)506 err = os.WriteFile(tmpfile, []byte("100"), 0)507 assert.Nil(err)508 pids = q.GetPids()509 assert.True(len(pids) == 1)510 assert.True(pids[0] == 100)511 q.state.VirtiofsDaemonPid = 200...

Full Screen

Full Screen

qemu.go

Source:qemu.go Github

copy

Full Screen

1/*2Copyright 2020 Salvatore Mazzarino3Licensed under the Apache License, Version 2.0 (the "License");4you may not use this file except in compliance with the License.5You may obtain a copy of the License at6 https://www.apache.org/licenses/LICENSE-2.07Unless required by applicable law or agreed to in writing, software8distributed under the License is distributed on an "AS IS" BASIS,9WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.10See the License for the specific language governing permissions and11limitations under the License.12*/13package hypervisor14import (15 "bufio"16 "context"17 "fmt"18 "io"19 "net"20 "os"21 "os/signal"22 "strconv"23 "syscall"24 "time"25 log "github.com/sirupsen/logrus"26 "github.com/kata-containers/govmm/qemu"27 "github.com/giantswarm/containervmm/pkg/api"28 "github.com/giantswarm/containervmm/pkg/logs"29 "github.com/giantswarm/containervmm/pkg/util"30)31const (32 // Path of QEMU (installed in the Docker container)33 binPath = "/usr/bin/qemu-system-x86_64"34 // QEMU QMP Socket35 qmpUDS = "/tmp/qmp-socket"36 // console socket37 consoleUDS = "console.sock"38 // shutdown timeout39 powerdownTimeout = 1 * time.Minute40)41// These kernel parameters will be appended42var kernelParams = [][]string{43 {"tsc", "reliable"},44 {"no_timer_check", ""},45 {"rcupdate.rcu_expedited", "1"},46 {"i8042.direct", "1"},47 {"i8042.dumbkbd", "1"},48 {"i8042.nopnp", "1"},49 {"i8042.noaux", "1"},50 {"noreplace-smp", ""},51 {"reboot", "k"},52 // this is used to read the VM output via the UNIX socket53 {"console", "hvc0"},54 {"console", "hvc1"},55 {"cryptomgr.notests", ""},56 {"net.ifnames", "0"},57 {"pci", "lastbus=0"},58}59type qmpLogger struct {60 *log.Logger61}62func ExecuteQEMU(guest api.Guest) error {63 // create a context64 ctx := context.Background()65 // set the list of QEMU parameters66 qemuConfig, err := createSandbox(ctx, guest)67 if err != nil {68 return fmt.Errorf("failed to create sandbox: %v", err)69 }70 if _, err := qemu.LaunchQemu(qemuConfig, newQMPLogger()); err != nil {71 return fmt.Errorf("failed to launch QEMU instance: %v", err)72 }73 if err := watchConsole(); err != nil {74 return fmt.Errorf("failed to watch console output: %v", err)75 }76 // This channel will be closed when the instance dies.77 disconnectedCh := make(chan struct{})78 // Set up our options.79 cfg := qemu.QMPConfig{Logger: newQMPLogger()}80 // Start monitoring the qemu instance. This functon will block until we have81 // connect to the QMP socket and received the welcome message.82 q, _, err := qemu.QMPStart(ctx, qmpUDS, cfg, disconnectedCh)83 if err != nil {84 return fmt.Errorf("failed to connect to the QMP socket: %v", err)85 }86 // This has to be the first command executed in a QMP session.87 if err := q.ExecuteQMPCapabilities(ctx); err != nil {88 return fmt.Errorf("failed to run QMP commmand: %v", err)89 }90 installSignalHandlers(ctx, q)91 // disconnectedCh is closed when the VM exits. This line blocks until this92 // event occurs.93 <-disconnectedCh94 return nil95}96func newQMPLogger() qmpLogger {97 return qmpLogger{98 logs.Logger,99 }100}101func (l qmpLogger) V(level int32) bool {102 return l.IsLevelEnabled(log.Level(level))103}104func createSandbox(ctx context.Context, guest api.Guest) (qemu.Config, error) {105 knobs := qemu.Knobs{106 NoUserConfig: true,107 NoDefaults: true,108 NoGraphic: true,109 Daemonize: true,110 }111 kernel, err := kernel(guest)112 if err != nil {113 return qemu.Config{}, fmt.Errorf("failed to create kernel object: %v", err)114 }115 mem := memory(guest)116 smp, err := smp(guest)117 if err != nil {118 return qemu.Config{}, fmt.Errorf("failed to create smp object: %v", err)119 }120 devices := buildDevices(guest)121 config := qemu.Config{122 Name: guest.Name,123 Path: binPath,124 Ctx: ctx,125 CPUModel: cpuModel(),126 Machine: machine(),127 VGA: vga(),128 Knobs: knobs,129 Kernel: kernel,130 Memory: mem,131 SMP: smp,132 QMPSockets: qmpSockets(),133 Devices: devices,134 }135 fwcfgs := fwcfgs(guest.OS.IgnitionConfig)136 if fwcfgs != nil {137 config.FwCfg = fwcfgs138 }139 return config, nil140}141func cpuModel() string {142 return "host,pmu=off"143}144func machine() qemu.Machine {145 defaultType := "q35"146 kvmAcceleration := "kvm"147 m := qemu.Machine{148 Type: defaultType,149 Acceleration: kvmAcceleration,150 }151 return m152}153func vga() string {154 return "none"155}156func kernel(guest api.Guest) (qemu.Kernel, error) {157 var kp [][]string158 if !util.FileExists(guest.OS.Kernel) {159 return qemu.Kernel{}, fmt.Errorf("file %s not found", guest.OS.Kernel)160 }161 if !util.FileExists(guest.OS.Initrd) {162 return qemu.Kernel{}, fmt.Errorf("file %s not found", guest.OS.Initrd)163 }164 k := qemu.Kernel{165 Path: guest.OS.Kernel,166 InitrdPath: guest.OS.Initrd,167 }168 for i := range guest.Disks {169 d := guest.Disks[i]170 if d.IsRoot {171 diskSerial := fmt.Sprintf("/dev/disk/by-id/virtio-%s", d.ID)172 rootDisk := []string{"root", diskSerial}173 kp = append(kp, rootDisk)174 break175 }176 }177 // if ignition is found add the parameter178 // Ref: https://docs.flatcar-linux.org/ignition/what-is-ignition/#when-is-ignition-executed179 if guest.OS.IgnitionConfig != "" {180 kp = append(kp, []string{"flatcar.first_boot", "1"})181 }182 kp = append(kp, kernelParams...)183 k.Params = serializeKernelParams(kp)184 return k, nil185}186func serializeKernelParams(params [][]string) string {187 var paramsStr string188 var lastElemIndex = len(params) - 1189 for i, p := range params {190 paramsStr += fmt.Sprintf("%s=%s", p[0], p[1])191 if i != lastElemIndex {192 paramsStr += " "193 }194 }195 return paramsStr196}197func memory(guest api.Guest) qemu.Memory {198 m := qemu.Memory{Size: guest.Memory}199 return m200}201func smp(guest api.Guest) (qemu.SMP, error) {202 cpus, err := strconv.Atoi(guest.CPUs)203 if err != nil {204 return qemu.SMP{}, err205 }206 s := qemu.SMP{CPUs: uint32(cpus)}207 return s, nil208}209func fwcfgs(ignitionConfig string) []qemu.FwCfg {210 var f []qemu.FwCfg211 if ignitionConfig == "" {212 return nil213 }214 name := "opt/org.flatcar-linux/config"215 fwcfg := qemu.FwCfg{216 Name: name,217 File: ignitionConfig,218 }219 f = append(f, fwcfg)220 return f221}222func qmpSockets() []qemu.QMPSocket {223 var q []qemu.QMPSocket224 qmpSocket := qemu.QMPSocket{225 Type: qemu.Unix,226 Name: qmpUDS,227 Server: true,228 NoWait: true,229 }230 q = append(q, qmpSocket)231 return q232}233func buildDevices(guest api.Guest) []qemu.Device {234 var devices []qemu.Device235 // append all the network devices236 devices = appendNetworkDevices(devices, guest.NICs)237 // append all the block devices238 devices = appendBlockDevices(devices, guest.Disks)239 // append all the FS devices240 devices = appendFSDevices(devices, guest.HostVolumes)241 // append console device242 devices = appendConsoleDevice(devices)243 // add random device244 id := "rng0"245 filename := "/dev/urandom"246 rngDevice := qemu.RngDevice{247 ID: id,248 Filename: filename,249 }250 devices = append(devices, rngDevice)251 return devices252}253func appendNetworkDevices(devices []qemu.Device, guestNICs []api.NetworkInterface) []qemu.Device {254 for i := range guestNICs {255 nd := guestNICs[i]256 device := buildNetworkDevice(nd)257 devices = append(devices, device)258 }259 return devices260}261func buildNetworkDevice(guestNIC api.NetworkInterface) qemu.NetDevice {262 return qemu.NetDevice{263 Type: qemu.TAP,264 ID: guestNIC.TAP,265 Driver: qemu.VirtioNetPCI,266 IFName: guestNIC.TAP,267 MACAddress: guestNIC.MacAddr,268 // we configure NIC - no need to use any scripts269 Script: "no",270 DownScript: "no",271 }272}273func appendBlockDevices(devices []qemu.Device, guestDisks []api.Disk) []qemu.Device {274 for i := range guestDisks {275 blkDevice := guestDisks[i]276 device := buildBlockDevice(blkDevice)277 devices = append(devices, device)278 }279 return devices280}281func buildBlockDevice(disk api.Disk) qemu.BlockDevice {282 // we define here because in the lib is not defined283 var RAW qemu.BlockDeviceFormat = "raw"284 blk := qemu.BlockDevice{285 Driver: qemu.VirtioBlock,286 ID: disk.ID,287 AIO: qemu.Threads,288 File: disk.File,289 Format: RAW,290 Interface: qemu.NoInterface,291 Transport: qemu.TransportPCI,292 }293 return blk294}295func appendConsoleDevice(devices []qemu.Device) []qemu.Device {296 serial := qemu.SerialDevice{297 Driver: qemu.VirtioSerial,298 ID: "serial0",299 }300 devices = append(devices, serial)301 console := qemu.CharDevice{302 Driver: qemu.Console,303 Backend: qemu.Socket,304 DeviceID: "console0",305 ID: "charconsole0",306 Path: consoleUDS,307 }308 devices = append(devices, console)309 return devices310}311func buildHostVolumeDevice(index int, hostVolume api.HostVolume) qemu.FSDevice {312 id := fmt.Sprintf("fsdev%d", index)313 fsdev := qemu.FSDevice{314 Driver: qemu.Virtio9P,315 FSDriver: qemu.Local,316 ID: id,317 Path: hostVolume.HostPath,318 MountTag: hostVolume.MountTag,319 SecurityModel: qemu.None,320 }321 return fsdev322}323func appendFSDevices(devices []qemu.Device, guestHostVolumes []api.HostVolume) []qemu.Device {324 for i := range guestHostVolumes {325 fsDevice := guestHostVolumes[i]326 device := buildHostVolumeDevice(i, fsDevice)327 devices = append(devices, device)328 }329 return devices330}331func watchConsole() error {332 conn, err := net.Dial("unix", consoleUDS)333 if err != nil {334 return err335 }336 go func() {337 scanner := bufio.NewScanner(conn)338 for scanner.Scan() {339 log.Infof("%s", scanner.Text())340 }341 if err := scanner.Err(); err != nil {342 if err == io.EOF {343 log.Info("console watcher quits")344 } else {345 log.Error("Failed to read console logs")346 }347 }348 }()349 return nil350}351func installSignalHandlers(ctx context.Context, q *qemu.QMP) {352 go func() {353 c := make(chan os.Signal, 1)354 signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)355 for {356 switch s := <-c; {357 case s == syscall.SIGTERM || s == os.Interrupt:358 log.Infof("Caught SIGTERM, requesting clean shutdown")359 ctxTimeout, cancel := context.WithTimeout(ctx, powerdownTimeout)360 err := q.ExecuteSystemPowerdown(ctxTimeout)361 cancel()362 if err != nil {363 log.Errorf("QEMU shutdown failed with error: %v", err)364 err = q.ExecuteQuit(ctx)365 if err != nil {366 log.Errorf("QEMU quit failed with error: %v", err)367 }368 }369 q.Shutdown()370 case s == syscall.SIGQUIT:371 log.Infof("Caught SIGQUIT, forcing shutdown")372 err := q.ExecuteStop(ctx)373 if err != nil {374 log.Errorf("QEMU stop failed with error: %v", err)375 }376 }377 }378 }()379}...

Full Screen

Full Screen

Create

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 q, err := qemu.NewQemu("/usr/bin/qemu-system-x86_64", "qemu-system-x86_64")4 if err != nil {5 panic(err)6 }7 q.Setargs([]string{"-m", "256", "-hda", "ubuntu.img"})8 if err := q.Create(); err != nil {9 panic(err)10 }11 if err := q.Wait(); err != nil {12 panic(err)13 }14 fmt.Println("VM Exited")15}

Full Screen

Full Screen

Create

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 q := qemu.NewQemu("/usr/bin/qemu-system-x86_64", "x86_64")4 q.QEMUOptions = append(q.QEMUOptions, "-hda", "disk.img")5 q.QEMUOptions = append(q.QEMUOptions, "-m", "512")6 q.QEMUOptions = append(q.QEMUOptions, "-nographic")7 q.QEMUOptions = append(q.QEMUOptions, "-netdev", "user,id=user.0,hostfwd=tcp::2222-:22")8 q.QEMUOptions = append(q.QEMUOptions, "-device", "e1000,netdev=user.0")9 err := q.Create()10 if err != nil {11 fmt.Println(err)12 }13}

Full Screen

Full Screen

Create

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 q, err := qemu.NewQemu("/usr/bin/qemu-system-x86_64", qemu.Virtio9P, qemu.VirtioNet)4 if err != nil {5 fmt.Println(err)6 }7 err = q.Create()8 if err != nil {9 fmt.Println(err)10 }11 err = q.Start()12 if err != nil {13 fmt.Println(err)14 }15}16import (17func main() {18 q, err := qemu.NewQemu("/usr/bin/qemu-system-x86_64", qemu.Virtio9P, qemu.VirtioNet)19 if err != nil {20 fmt.Println(err)21 }22 err = q.Create()23 if err != nil {24 fmt.Println(err)25 }26 err = q.Start()27 if err != nil {28 fmt.Println(err)29 }30 err = q.Exec("echo", "Hello World")31 if err != nil {32 fmt.Println(err)33 }34}35import (36func main() {37 q, err := qemu.NewQemu("/usr/bin/qemu-system-x86_64", qemu.Virtio9P, qemu.VirtioNet)38 if err != nil {39 fmt.Println(err)40 }41 err = q.Create()42 if err != nil {43 fmt.Println(err)44 }45 err = q.Start()46 if err != nil {47 fmt.Println(err)48 }49 err = q.Exec("echo", "Hello World")50 if err != nil {

Full Screen

Full Screen

Create

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 qemu := qemu.NewQemu("/usr/bin/qemu-system-x86_64")4 qemu.AddDevice("virtio-net-pci", "net0", "mac=52:54:00:12:34:56")5 qemu.AddDevice("virtio-blk-pci", "drive0", "file=/path/to/disk.img,format=raw")6 qemu.AddDevice("virtio-serial-pci", "serial0")7 qemu.AddDevice("virtconsole", "console0", "chardev=char0")8 qemu.AddDevice("virtio-rng-pci", "rng0")9 qemu.AddDevice("virtio-balloon-pci", "balloon0")10 qemu.AddDevice("virtio-9p-pci", "fs0", "fsdev=fsdev0,mount_tag=hostshare")11 qemu.AddDevice("fsdev", "fsdev0", "path=/path/to/hostshare,security_model=none")12 qemu.AddDevice("chardev", "char0", "socket,path=/tmp/qemu.sock,server,nowait")13 qemu.AddDevice("virtio-scsi-pci", "scsi0")14 qemu.AddDevice("scsi-hd", "drive1", "file=/path/to/disk2.img,format=raw")15 qemu.AddDevice("scsi-cd", "drive2", "file=/path/to/cdrom.iso,format=raw")16 qemu.AddDevice("scsi-block", "drive3", "file=/path/to/disk3.img,format=raw")17 qemu.AddDevice("scsi-generic", "drive4", "file=/path/to/disk4.img,format=raw")18 qemu.AddDevice("usb-ehci", "ehci0")19 qemu.AddDevice("usb-uhci", "uhci0")20 qemu.AddDevice("usb-uhci", "uhci1")21 qemu.AddDevice("usb-uhci", "uhci2")22 qemu.AddDevice("usb-mouse", "mouse0")23 qemu.AddDevice("usb-kbd", "kbd0")24 qemu.AddDevice("usb-tablet", "tablet0")25 qemu.AddDevice("usb-storage", "usb0", "drive=drive1")26 qemu.AddDevice("usb-storage",

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Syzkaller automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful