예제 #1
0
파일: ui.go 프로젝트: weldpua2008/deployer
func uiNUMATopologyHeader(ui *gui.DialogUi, c *guest.Config) string {
	ui.HelpButton(true)
	ui.SetHelpLabel("Back")
	ui.SetTitle("VA NUMA Configuration")
	ui.SetExtraLabel("Edit")

	var hdr string
	for _, n := range c.NUMAs {
		for _, nic := range n.NICs {
			if nic.HostNIC.Type == host.NicTypePhys || nic.HostNIC.Type == host.NicTypePhysVF {
				hdr += fmt.Sprintf("\nNUMA %d: %s", nic.HostNIC.NUMANode, nic.HostNIC.PCIAddr)
			}
		}
	}

	hdr += "\n"
	if hdr != "\n" {
		hdr = " \n---------------- PCI Devices Topology ---------------" + hdr
		hdr += "-----------------------------------------------------\n\n"
	}

	hdr += " __________________ CPU/NUMA Topology ________________\n"
	hdr += "|____________ VA ___________|_________ Host __________|\n"
	hdr += "|____ vCPU ___|___ vNUMA ___|_________CPU(s) _________|"
	return hdr
}
예제 #2
0
파일: ui.go 프로젝트: weldpua2008/deployer
// UiEulaMsg prints out appropriate EULA message
func UiEulaMsg(ui *gui.DialogUi, pathToEula string) {
	ui.SetOkLabel("Agree")
	ui.SetExtraLabel("Disagree")
	ui.SetTitle("End User License Agreement")
	ui.SetSize(30, 80)
	if err := ui.Textbox(pathToEula); err != nil {
		os.Exit(1)
	}
}
예제 #3
0
파일: ui.go 프로젝트: weldpua2008/deployer
func uiHeaderSelectNics(ui *gui.DialogUi) int {
	str := " ___________________________________________________________________________________________________________________________"
	width := len(str)
	str += "\n|____________________________________________________HOST__________________________________________________________|___VM___|"

	str += fmt.Sprintf("\n|________%s________|__%s__|_______________ %s _________________|__%s__|__%s__|", "Port Name", "PCI Address", "Network Interface Description", "NUMA", "Port")
	ui.SetLabel(str)
	ui.SetExtraLabel("Next")
	ui.SetOkLabel("Select")
	ui.HelpButton(true)
	ui.SetHelpLabel("Back")
	return width
}
예제 #4
0
파일: ui.go 프로젝트: weldpua2008/deployer
func uiNetworkPolicySelector(ui *gui.DialogUi, net *xmlinput.Network) ([]xmlinput.ConnectionMode, error) {
	matrix := make(map[string][]xmlinput.ConnectionMode)
	for _, mode := range net.UiModeBinding {
		if _, ok := matrix[mode.Appear]; !ok {
			matrix[mode.Appear] = make([]xmlinput.ConnectionMode, 0)
		}
		matrix[mode.Appear] = append(matrix[mode.Appear], mode.Type)
	}

	var temp []string
	index := 1
	for appear, _ := range matrix {
		temp = append(temp, strconv.Itoa(index), appear)
		index++
	}

	length := len(matrix)
	ui.SetSize(length+8, 50)
	ui.SetTitle(fmt.Sprintf("Network interface type for network \"%s\"", net.Name))
	ui.HelpButton(true)
	ui.SetHelpLabel("Back")
	if net.Optional {
		ui.SetExtraLabel("Skip")
	}
	val, err := ui.Menu(length, temp[0:]...)
	if err != nil {
		return nil, err
	}
	resultInt, err := strconv.Atoi(val)
	if err != nil {
		return nil, utils.FormatError(err)
	}
	if resultInt != 1 {
		resultInt++
	}
	return matrix[temp[resultInt]], nil
}
예제 #5
0
파일: ui.go 프로젝트: weldpua2008/deployer
func UiNUMATopology(ui *gui.DialogUi, c *guest.Config, d deployer.EnvDriver, totalCpusOnHost int) (bool, error) {
	var list []string

	// file, err := os.Create("/tmp/UiNUMATopology.txt")
	// if err != nil {
	// 	return false, nil
	// }
	// defer file.Close()

	isChanged := false
	hCPUnotOnce := ""
	CheckIfCPUdoubleUsed := true

MainLoop:
	for {
		// file.WriteString("[UiNUMATopology] MainLoop: \n")
		list = make([]string, 0)
		tempData := make(map[int]map[int]string)
		// file.WriteString("[UiNUMATopology] totalCpusOnHost: " + strconv.Itoa(totalCpusOnHost) + " \n")
		for _, n := range c.NUMAs {
			// file.WriteString("[UiNUMATopology] c.NUMAs\n")
			// file.WriteString("[UiNUMATopology] len(n.CPUPin): " + strconv.Itoa(len(n.CPUPin)) + "\n")
			keys := make([]int, 0)
			for vcpu, _ := range n.CPUPin {
				keys = append(keys, vcpu)
				// file.WriteString("[UiNUMATopology] vcpu: " + strconv.Itoa(vcpu) + "\n")
			}

			sort.Ints(keys)
			var hostCpu string
			for _, k := range keys {
				if len(n.CPUPin[k]) > 1 {
					if len(n.CPUPin[k]) == totalCpusOnHost {
						CheckIfCPUdoubleUsed = false
						hostCpu = "0-" + strconv.Itoa(totalCpusOnHost-1)
					} else {
						var tmpStrSlice []string
						for _, c := range n.CPUPin[k] {
							tmpStrSlice = append(tmpStrSlice, strconv.Itoa(c))
						}
						hostCpu = strings.Join(tmpStrSlice, ",")
					}
				} else {
					hostCpu = strconv.Itoa(n.CPUPin[k][0])
				}
				// file.WriteString("[UiNUMATopology] hostCpu: " + hostCpu + "\n")
				tempData[k] = make(map[int]string)
				tempData[k][n.CellID] = hostCpu

				// file.WriteString("tempData[" + strconv.Itoa(k) + "][" + strconv.Itoa(n.CellID) + "] = " + hostCpu + "  \n")
			}
		}

		// we need to represent sorted vCPU IDs and not vNUMA IDs
		keys := make([]int, 0)
		for k, _ := range tempData {
			keys = append(keys, k)
		}

		duplicate_frequency := make(map[string]int)
		sort.Ints(keys)
		for _, key := range keys {
			for k, v := range tempData[key] {
				list = append(list, strconv.Itoa(key), fmt.Sprintf("%-10s%-18d%-7s", " ", k, v))
				temphCPU := v
				_, exist := duplicate_frequency[temphCPU]
				if exist {
					duplicate_frequency[temphCPU] += 1 // increase counter by 1 if already in the map
				} else {
					duplicate_frequency[temphCPU] = 1 // else start counting from 1
				}
				// file.WriteString("k: " + strconv.Itoa(k) + " v: " + v + "  \n")
			}
		}

		hCPUnotOnce = ""
		for k_dup, v_dup := range duplicate_frequency {
			if v_dup > 1 {
				hCPUnotOnce = k_dup
				break
			}
		}

		ui.SetLabel(uiNUMATopologyHeader(ui, c))
		result, err := ui.Menu(len(list), list[0:]...)
		// file.WriteString("[UiNUMATopology] result: " + result + " err: " + err.Error() + " len(list): " + strconv.Itoa(len(list)) + " \n")

		if err == nil {
			if hCPUnotOnce != "" && isChanged && CheckIfCPUdoubleUsed {
				ui.Output(gui.Warning, "CPU "+hCPUnotOnce+" is assigned to more than one vCPU")
				continue
			}
			break
		}
		if err.Error() != gui.DialogNext {
			// file.WriteString("[UiNUMATopology] err.Error() != gui.DialogNext " + err.Error() + " \n")
			return isChanged, err
		}

	InternalLoop:
		for {
			// file.WriteString("[UiNUMATopology] InternalLoop: \n")

			ui.SetTitle("VA vCPU Configuration")
			ui.SetExtraLabel("Help")
			// file.WriteString("result: (" + result + ") \n")
			resultInt, err := strconv.Atoi(result)
			if err != nil {
				// file.WriteString("[UiNUMATopology] strconv.Atoi(result) " + err.Error() + "\n")
				return isChanged, err
			}

			var vnumaStr string
			var cpusStr string
			tempDataLen := len(tempData)
			for k, v := range tempData[resultInt] {
				vnumaStr = strconv.Itoa(k)
				cpusStr = v
				// tempDataLen++
			}
			// file.WriteString("resultInt: (" + result + ") \n")
			// DE11527
			index := resultInt
			resultInt--

			// var vnumaPredecStr string
			// for k, _ := range tempData[resultInt] {
			// 	vnumaPredecStr = strconv.Itoa(k)
			// 	// file.WriteString("vnumaPredecStr: (" + vnumaPredecStr + ") ")
			// }

			var lst []string
			label := "Set affinity for vCPU " + result

			var vnumaMinus1 string
			var vnumaPlus1 string
			var vnumaIndex string
			var vnumaTemp string
			if tempDataLen > 3 {
				if index > (tempDataLen - 1) {
					index = index - tempDataLen
				}

				indexMinus1 := index - 1

				if indexMinus1 < 0 {
					indexMinus1 = tempDataLen + indexMinus1
				}
				indexPlus1 := index + 1

				if indexPlus1 > tempDataLen {
					indexPlus1 = indexPlus1 - tempDataLen
				}

				for k, _ := range tempData[indexMinus1] {
					vnumaMinus1 = strconv.Itoa(k)
				}

				for k, _ := range tempData[indexPlus1] {
					vnumaPlus1 = strconv.Itoa(k)
				}
				for k, _ := range tempData[index] {
					vnumaIndex = strconv.Itoa(k)
				}

				if index == (tempDataLen - 1) {
					// vnumaPlus1 = vnumaIndex

					for k, _ := range tempData[0] {
						vnumaTemp = strconv.Itoa(k)
					}
					if vnumaTemp != vnumaIndex {
						vnumaPlus1 = vnumaIndex
					} else {
						vnumaPlus1 = "vnumaPlus1"
					}

				}
				if index == 0 {
					// vnumaMinus1 = vnumaIndex
					for k, _ := range tempData[tempDataLen-1] {
						vnumaTemp = strconv.Itoa(k)
					}
					if vnumaTemp != vnumaIndex {
						vnumaMinus1 = vnumaIndex
					} else {
						vnumaMinus1 = "vnumaIndex"
					}
				}
			} else {
				vnumaMinus1 = "-1"
				vnumaPlus1 = "+1"
			}

			// xxxxxx := d.Id()
			// file.WriteString("d.Id(): (" + xxxxxx + ") ")
			// file.WriteString("vnumaStr: (" + vnumaStr + ") vnumaPredecStr: (" + vnumaPredecStr + ") \n")
			// file.WriteString("indexMinus1: (" + strconv.Itoa(indexMinus1) + ") index: (" + strconv.Itoa(index) + ")  indexPlus1: (" + strconv.Itoa(indexPlus1) + ")\n")
			// file.WriteString("vnumaMinus1: (" + vnumaMinus1 + ") vnumaPlus1: (" + vnumaPlus1 + ") \n")
			// file.WriteString("tempDataLen: (" + strconv.Itoa(tempDataLen) + ")  \n")
			// if vnumaStr == vnumaPredecStr && d.Id() == "QEMU-Libvirt" {
			if vnumaMinus1 == vnumaPlus1 && d.Id() == "QEMU-Libvirt" {
				lst = []string{"VA vNUMA ID : ", "1", "1", vnumaStr, "1", "15", "2", "0", "2"}
				label += "\n\nIMPORTANT! Some QEMU versions do not support\n" +
					"disjoint NUMA CPU ranges therefore vNUMA configuration\n" +
					"is disabled for this vCPU.\n"
			} else {
				lst = []string{"VA vNUMA ID : ", "1", "1", vnumaStr, "1", "15", "2", "0", "0"}
			}

			lst = append(lst, "Host CPU(s) : ", "2", "1", cpusStr, "2", "15", "30", "0", "0")
			r, err := ui.Mixedform(label, false, lst[0:]...)
			if err != nil {
				if err.Error() == gui.DialogNext {
					uiShowNumaTopologyHelpMsg(ui)
					continue
				}
				return isChanged, err
			}
			if len(r) < 2 {
				continue
			}

			vcpuInt, err := strconv.Atoi(result)
			if err != nil {
				continue
			}

			vnumaInt, err := strconv.Atoi(r[0])
			if err != nil {
				ui.Output(gui.Warning, "Illegal input \""+r[0]+"\"", "Press <OK> to return to menu.")
				continue
			}
			if err := verifyRange(vnumaInt, len(c.NUMAs)); err != nil {
				ui.Output(gui.Warning, err.Error(), "Press <OK> to return to menu.")
				continue
			}

			hostCpus := r[1]
			cpus := make([]int, 0)
			if strings.Contains(hostCpus, ",") {
				for _, e := range strings.Split(hostCpus, ",") {
					if strings.Contains(e, "-") {
						cpus, err = splitByHypen(e, totalCpusOnHost)
						if err != nil {
							ui.Output(gui.Warning, err.Error(), "Press <OK> to return to menu.")
							continue InternalLoop
						}
					} else {
						cpu, err := strconv.Atoi(e)
						if err != nil {
							ui.Output(gui.Warning, "Illegal input \""+e+"\"", "Press <OK> to return to menu.")
							continue InternalLoop
						}
						if err := verifyRange(cpu, totalCpusOnHost); err != nil {
							ui.Output(gui.Warning, err.Error(), "Press <OK> to return to menu.")
							continue InternalLoop
						}
						cpus = append(cpus, cpu)
					}
				}
			} else if strings.Contains(hostCpus, "-") {
				cpus, err = splitByHypen(hostCpus, totalCpusOnHost)
				if err != nil {
					ui.Output(gui.Warning, err.Error(), "Press <OK> to return to menu.")
					continue
				}
			} else {
				cpu, err := strconv.Atoi(hostCpus)
				if err != nil {
					ui.Output(gui.Warning, "Illegal input \""+hostCpus+"\"", "Press <OK> to return to menu.")
					continue
				}
				if err := verifyRange(cpu, totalCpusOnHost); err != nil {
					ui.Output(gui.Warning, err.Error(), "Press <OK> to return to menu.")
					continue
				}
				cpus = append(cpus, cpu)
			}

			// delete the old entry
			isChanged = true
			for _, n := range c.NUMAs {
				for vcpu, _ := range n.CPUPin {
					if vcpu == vcpuInt {
						delete(n.CPUPin, vcpu)
					}
				}
			}

			sort.Ints(cpus)
			// set the new entry
			c.NUMAs[vnumaInt].CPUPin[vcpuInt] = cpus
			continue MainLoop
		}
		break
	}

	// ui.Output(gui.Warning, "CPU "+hCPUnotOnce+" is assigned to more than one vCPU")

	// if isChanged {
	// 	file.WriteString("isChanged\n")
	// } else {
	// 	file.WriteString("NotChanged\n")
	// }
	// if isChanged {
	// 	ui.Output(gui.Warning, "CPU j is assigned to more than one vCPU")
	// 	continue MainLoop
	// }
	// file.WriteString("return: \n")
	return isChanged, nil
}