diff --git a/cmd/climc/shell/images.go b/cmd/climc/shell/images.go index 933988d4ed..aa80653594 100644 --- a/cmd/climc/shell/images.go +++ b/cmd/climc/shell/images.go @@ -46,7 +46,7 @@ type ImageOptionalOptions struct { OsDist string `help:"Distribution name of OS" metavar:"OS_DISTRIBUTION"` OsVersion string `help:"Version of OS"` OsCodename string `help:"Codename of OS"` - OsArch string `help:"Os hardware architecture" choices:"x86|x86_64"` + OsArch string `help:"Os hardware architecture" choices:"x86|x86_64|aarch32|aarch64"` OsLang string `help:"OS Language" choices:"zh_CN|en_US"` Preference int64 `help:"Disk preferences"` Notes string `help:"Notes about the image"` diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 09033ddb1e..9f3e7b1c10 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -93,14 +93,15 @@ type SHost struct { SysInfo jsonutils.JSONObject `nullable:"true" search:"admin" list:"admin" update:"admin" create:"admin_optional"` // Column(JSONEncodedDict, nullable=True) SN string `width:"128" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(VARCHAR(128, charset='ascii'), nullable=True) - CpuCount int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True) # cpu count - NodeCount int8 `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True) - CpuDesc string `width:"64" charset:"ascii" nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(VARCHAR(64, charset='ascii'), nullable=True) - CpuMhz int `nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # cpu MHz - CpuCache int `nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # cpu Cache in KB - CpuReserved int `nullable:"true" default:"0" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True, default=0) - CpuCmtbound float32 `nullable:"true" default:"8" list:"admin" update:"admin" create:"admin_optional"` // = Column(Float, nullable=True) - CpuMicrocode string `width:"64" charset:"ascii" nullable:"true" get:"admin" update:"admin" create:"admin_optional"` + CpuCount int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True) # cpu count + NodeCount int8 `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True) + CpuDesc string `width:"64" charset:"ascii" nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(VARCHAR(64, charset='ascii'), nullable=True) + CpuMhz int `nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # cpu MHz + CpuCache int `nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # cpu Cache in KB + CpuReserved int `nullable:"true" default:"0" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True, default=0) + CpuCmtbound float32 `nullable:"true" default:"8" list:"admin" update:"admin" create:"admin_optional"` // = Column(Float, nullable=True) + CpuMicrocode string `width:"64" charset:"ascii" nullable:"true" get:"admin" update:"admin" create:"admin_optional"` + CpuArchitecture string `width:"16" charset:"ascii" nullable:"true" get:"user" update:"admin" create:"admin_optional"` MemSize int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # memory size in MB MemReserved int `nullable:"true" default:"0" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True, default=0) # memory reserved in MB diff --git a/pkg/hostman/guestman/qemu-arm.go b/pkg/hostman/guestman/qemu-arm.go new file mode 100644 index 0000000000..9bce85c346 --- /dev/null +++ b/pkg/hostman/guestman/qemu-arm.go @@ -0,0 +1,309 @@ +package guestman + +import ( + "fmt" + + "yunion.io/x/jsonutils" + "yunion.io/x/pkg/utils" + + options "yunion.io/x/onecloud/pkg/hostman/options" + "yunion.io/x/onecloud/pkg/hostman/storageman" + fileutils2 "yunion.io/x/onecloud/pkg/util/fileutils2" + "yunion.io/x/onecloud/pkg/util/qemutils" +) + +func (s *SKVMGuestInstance) getArmMachine() string { + return "virt-2.12" +} + +func (s *SKVMGuestInstance) getArmVdiskDesc(disk jsonutils.JSONObject) string { + diskIndex, _ := disk.Int("index") + diskDriver, _ := disk.GetString("driver") + + if diskDriver == DISK_DRIVER_IDE || diskDriver == DISK_DRIVER_SATA { + // unsupported configuration: IDE controllers are unsupported + // for this QEMU binary or machine type + // replace with scsi + diskDriver = DISK_DRIVER_SCSI + } + + var cmd = "" + cmd += fmt.Sprintf(" -device %s", s.GetDiskDeviceModel(diskDriver)) + cmd += fmt.Sprintf(",drive=drive_%d", diskIndex) + if diskDriver == DISK_DRIVER_VIRTIO { + cmd += fmt.Sprintf(",bus=%s,addr=0x%x", s.GetPciBus(), s.GetDiskAddr(int(diskIndex))) + } else if utils.IsInStringArray(diskDriver, []string{DISK_DRIVER_SCSI, DISK_DRIVER_PVSCSI}) { + cmd += ",bus=scsi.0" + } + cmd += fmt.Sprintf(",id=drive_%d", diskIndex) + return cmd +} + +// arm cpu unsupport hackintosh +func (s *SKVMGuestInstance) generateArmStartScript(data *jsonutils.JSONDict) (string, error) { + var ( + uuid, _ = s.Desc.GetString("uuid") + mem, _ = s.Desc.Int("mem") + cpu, _ = s.Desc.Int("cpu") + name, _ = s.Desc.GetString("name") + nics, _ = s.Desc.GetArray("nics") + disks, _ = s.Desc.GetArray("disks") + osname = s.getOsname() + cmd = "" + ) + + vncPort, _ := data.Int("vnc_port") + + qemuVersion := options.HostOptions.DefaultQemuVersion + if data.Contains("qemu_version") { + qemuVersion, _ = data.GetString("qemu_version") + } + if qemuVersion == "latest" { + qemuVersion = "" + } + + var devAddrs = []string{} + isolatedParams, _ := s.Desc.GetArray("isolated_devices") + for _, params := range isolatedParams { + devAddr, _ := params.GetString("addr") + devAddrs = append(devAddrs, devAddr) + } + isolatedDevsParams := s.manager.GetHost().GetIsolatedDeviceManager().GetQemuParams(devAddrs) + + for _, nic := range nics { + downscript := s.getNicDownScriptPath(nic) + ifname, _ := nic.GetString("ifname") + cmd += fmt.Sprintf("%s %s\n", downscript, ifname) + } + + if options.HostOptions.HugepagesOption == "native" { + cmd += fmt.Sprintf("mkdir -p /dev/hugepages/%s\n", uuid) + cmd += fmt.Sprintf("mount -t hugetlbfs -o size=%dM hugetlbfs-%s /dev/hugepages/%s\n", + mem, uuid, uuid) + } + + cmd += "sleep 1\n" + cmd += fmt.Sprintf("echo %d > %s\n", vncPort, s.GetVncFilePath()) + + for _, disk := range disks { + diskPath, _ := disk.GetString("path") + d := storageman.GetManager().GetDiskByPath(diskPath) + if d == nil { + return "", fmt.Errorf("get disk %s by storage error", diskPath) + } + + diskIndex, _ := disk.Int("index") + cmd += d.GetDiskSetupScripts(int(diskIndex)) + } + + cmd += fmt.Sprintf("STATE_FILE=`ls -d %s* | head -n 1`\n", s.getStateFilePathRootPrefix()) + cmd += fmt.Sprintf("PID_FILE=%s\n", s.GetPidFilePath()) + + var qemuCmd = qemutils.GetQemu(qemuVersion) + if len(qemuCmd) == 0 { + qemuCmd = qemutils.GetQemu("") + } + + cmd += fmt.Sprintf("DEFAULT_QEMU_CMD='%s'\n", qemuCmd) + cmd += "if [ -n \"$STATE_FILE\" ]; then\n" + cmd += " QEMU_VER=`echo $STATE_FILE" + + ` | grep -o '_[[:digit:]]\+\.[[:digit:]]\+.*'` + "`\n" + cmd += " QEMU_CMD=\"qemu-system-x86_64\"\n" + cmd += " QEMU_LOCAL_PATH=\"/usr/local/bin/$QEMU_CMD\"\n" + cmd += " QEMU_LOCAL_PATH_VER=\"/usr/local/qemu-$QEMU_VER/bin/$QEMU_CMD\"\n" + cmd += " QEMU_BIN_PATH=\"/usr/bin/$QEMU_CMD\"\n" + cmd += " if [ -f \"$QEMU_LOCAL_PATH_VER\" ]; then\n" + cmd += " QEMU_CMD=$QEMU_LOCAL_PATH_VER\n" + cmd += " elif [ -f \"$QEMU_LOCAL_PATH\" ]; then\n" + cmd += " QEMU_CMD=$QEMU_LOCAL_PATH\n" + cmd += " elif [ -f \"$QEMU_BIN_PATH\" ]; then\n" + cmd += " QEMU_CMD=$QEMU_BIN_PATH\n" + cmd += " fi\n" + cmd += "else\n" + cmd += " QEMU_CMD=$DEFAULT_QEMU_CMD\n" + cmd += "fi\n" + cmd += "function nic_speed() {\n" + cmd += " $QEMU_CMD " + + if s.IsKvmSupport() { + cmd += "-enable-kvm" + } else { + cmd += "-no-kvm" + } + + cmd += " -device virtio-net-pci,? 2>&1 | grep .speed= > /dev/null\n" + cmd += " if [ \"$?\" -eq \"0\" ]; then\n" + cmd += " echo \",speed=$1\"\n" + cmd += " fi\n" + cmd += "}\n" + + // Generate Start VM script + cmd += `CMD="$QEMU_CMD` + var accel, cpuType string + if s.IsKvmSupport() { + cmd += " -enable-kvm" + accel = "kvm" + if options.HostOptions.HostCpuPassthrough { + cpuType = "host" + } else { + // * under KVM, -cpu max is the same as -cpu host + // * under TCG, -cpu max means "emulate with as many features as possible" + cpuType = "max" + } + } else { + cmd += " -no-kvm" + accel = "tcg" + cpuType = "max" + } + + cmd += fmt.Sprintf(" -cpu %s", cpuType) + + cmd += s.getMonitorDesc("hmqmon", s.GetHmpMonitorPort(int(vncPort)), MODE_READLINE) + if options.HostOptions.EnableQmpMonitor { + cmd += s.getMonitorDesc("qmqmon", s.GetQmpMonitorPort(int(vncPort)), MODE_CONTROL) + } + + cmd += " -rtc base=utc,clock=host,driftfix=none" + cmd += " -daemonize" + cmd += " -nodefaults -nodefconfig" + cmd += fmt.Sprintf(" -machine %s,accel=%s,gic-version=3", s.getArmMachine(), accel) + cmd += " -k en-us" + + // warning: Number of hotpluggable cpus requested (128) + // exceeds the recommended cpus supported by KVM (32) + cmd += fmt.Sprintf(" -smp %d,maxcpus=32", cpu) + cmd += fmt.Sprintf(" -name %s", name) + cmd += fmt.Sprintf(" -m %dM,slots=4,maxmem=262144M", mem) + + if options.HostOptions.HugepagesOption == "native" { + cmd += fmt.Sprintf(" -mem-prealloc -mem-path %s", fmt.Sprintf("/dev/hugepages/%s", uuid)) + } + + bootOrder, _ := s.Desc.GetString("boot_order") + cmd += fmt.Sprintf(" -boot order=%s", bootOrder) + + // arm unsupport bios + cmd += fmt.Sprintf(" -bios %s", options.HostOptions.OvmfPath) + + cmd += " -device qemu-xhci,p2=8,p3=8,id=usb" + cmd += " -device usb-tablet,id=input0,bus=usb.0,port=1" + cmd += " -device usb-kbd,id=input1,bus=usb.0,port=2" + cmd += " -device virtio-gpu-pci,id=video0,max_outputs=1" + + if s.IsVdiSpice() { + cmd += " -device qxl-vga,id=video0,ram_size=141557760,vram_size=141557760" + cmd += " -device intel-hda,id=sound0" + cmd += " -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0" + cmd += fmt.Sprintf(" -spice port=%d,password=87654312,seamless-migration=on", 5900+vncPort) + // # ,streaming-video=all,playback-compression=on,jpeg-wan-compression=always,zlib-glz-wan-compression=always,image-compression=glz" % (5900+vnc_port) + cmd += fmt.Sprintf(" -device virtio-serial-pci,id=virtio-serial0,max_ports=16,bus=%s", s.GetPciBus()) + cmd += " -chardev spicevmc,name=vdagent,id=vdagent" + cmd += " -device virtserialport,nr=1,bus=virtio-serial0.0,chardev=vdagent,name=com.redhat.spice.0" + + // # usb redirect + cmd += " -device ich9-usb-ehci1,id=usb" + cmd += " -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,multifunction=on" + cmd += " -device ich9-usb-uhci2,masterbus=usb.0,firstport=2" + cmd += " -device ich9-usb-uhci3,masterbus=usb.0,firstport=4" + cmd += " -chardev spicevmc,name=usbredir,id=usbredirchardev1" + cmd += " -device usb-redir,chardev=usbredirchardev1,id=usbredirdev1" + cmd += " -chardev spicevmc,name=usbredir,id=usbredirchardev2" + cmd += " -device usb-redir,chardev=usbredirchardev2,id=usbredirdev2" + } else { + cmd += fmt.Sprintf(" -vnc :%d", vncPort) + if options.HostOptions.SetVncPassword { + cmd += ",password" + } + } + + var diskDrivers = []string{} + for _, disk := range disks { + diskDriver, _ := disk.GetString("driver") + if diskDriver == DISK_DRIVER_IDE || diskDriver == DISK_DRIVER_SATA { + // unsupported configuration: IDE controllers are unsupported + // for this QEMU binary or machine type + // replace with scsi + diskDriver = DISK_DRIVER_SCSI + } + diskDrivers = append(diskDrivers, diskDriver) + } + + if utils.IsInStringArray(DISK_DRIVER_SCSI, diskDrivers) { + cmd += " -device virtio-scsi-pci,id=scsi" + } else if utils.IsInStringArray(DISK_DRIVER_PVSCSI, diskDrivers) { + cmd += " -device pvscsi,id=scsi" + } + + for _, disk := range disks { + format, _ := disk.GetString("format") + cmd += s.getDriveDesc(disk, format) + cmd += s.getArmVdiskDesc(disk) + } + + cdrom, _ := s.Desc.Get("cdrom") + if cdrom != nil && cdrom.Contains("path") { + cdromPath, _ := cdrom.GetString("path") + if len(cdromPath) > 0 { + cmd += fmt.Sprintf("-cdrom %s", cdromPath) + } + } + + for i := 0; i < len(nics); i++ { + if osname == OS_NAME_VMWARE { + nics[i].(*jsonutils.JSONDict).Set("driver", jsonutils.NewString("vmxnet3")) + } + nicCmd, err := s.getNetdevDesc(nics[i]) + if err != nil { + return "", err + } else { + cmd += nicCmd + } + cmd += s.getVnicDesc(nics[i]) + } + + if isolatedDevsParams != nil { + for _, each := range isolatedDevsParams.Devices { + cmd += each + } + } + + cmd += fmt.Sprintf(" -pidfile %s", s.GetPidFilePath()) + extraOptions, _ := s.Desc.GetMap("extra_options") + for k, v := range extraOptions { + cmd += fmt.Sprintf(" -%s %s", k, v.String()) + } + + // cmd += s.getQgaDesc() + if fileutils2.Exists("/dev/random") { + cmd += " -object rng-random,filename=/dev/random,id=rng0" + cmd += " -device virtio-rng-pci,rng=rng0,max-bytes=1024,period=1000" + } + + if jsonutils.QueryBoolean(data, "need_migrate", false) { + migratePort := s.manager.GetFreePortByBase(LIVE_MIGRATE_PORT_BASE) + s.Desc.Set("live_migrate_dest_port", jsonutils.NewInt(int64(migratePort))) + cmd += fmt.Sprintf(" -incoming tcp:0:%d", migratePort) + } else if jsonutils.QueryBoolean(s.Desc, "is_slave", false) { + cmd += fmt.Sprintf(" -incoming tcp:0:%d", + s.manager.GetFreePortByBase(LIVE_MIGRATE_PORT_BASE)) + } else if jsonutils.QueryBoolean(s.Desc, "is_master", false) { + cmd += " -S" + } + // cmd += fmt.Sprintf(" -D %s", path.Join(s.HomeDir(), "log")) + + // -device pvpanic: 'pvpanic' is not a valid device model name + // if !s.disablePvpanicDev() { + // cmd += " -device pvpanic" + // } + + cmd += "\"\n" + cmd += "if [ ! -z \"$STATE_FILE\" ] && [ -d \"$STATE_FILE\" ] && [ -f \"$STATE_FILE/content\" ]; then\n" + cmd += " $CMD --incoming \"exec: cat $STATE_FILE/content\"\n" + cmd += "elif [ ! -z \"$STATE_FILE\" ] && [ -f $STATE_FILE ]; then\n" + cmd += " $CMD --incoming \"exec: cat $STATE_FILE\"\n" + cmd += "else\n" + cmd += " $CMD\n" + cmd += "fi\n" + + return cmd, nil +} diff --git a/pkg/hostman/guestman/qemu-kvmhelper.go b/pkg/hostman/guestman/qemu-kvmhelper.go index 39a910ce31..0add978f24 100644 --- a/pkg/hostman/guestman/qemu-kvmhelper.go +++ b/pkg/hostman/guestman/qemu-kvmhelper.go @@ -294,6 +294,14 @@ func (s *SKVMGuestInstance) getQgaDesc() string { } func (s *SKVMGuestInstance) generateStartScript(data *jsonutils.JSONDict) (string, error) { + if s.manager.host.GetCpuArchitecture() == "aarch64" { + return s.generateArmStartScript(data) + } else { + return s._generateStartScript(data) + } +} + +func (s *SKVMGuestInstance) _generateStartScript(data *jsonutils.JSONDict) (string, error) { var ( uuid, _ = s.Desc.GetString("uuid") mem, _ = s.Desc.Int("mem") diff --git a/pkg/hostman/hostinfo/hostbridge/hostbridge.go b/pkg/hostman/hostinfo/hostbridge/hostbridge.go index 4722badf38..af50d8557d 100644 --- a/pkg/hostman/hostinfo/hostbridge/hostbridge.go +++ b/pkg/hostman/hostinfo/hostbridge/hostbridge.go @@ -22,6 +22,7 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/pkg/errors" "yunion.io/x/pkg/utils" "yunion.io/x/onecloud/pkg/hostman/options" @@ -114,6 +115,11 @@ func (d *SBaseBridgeDriver) BringupInterface() error { } func (d *SBaseBridgeDriver) ConfirmToConfig() (bool, error) { + output, err := procutils.NewCommand("ifconfig").Run() + if err != nil { + return false, errors.Wrapf(err, "exec ifconfig %s", output) + } + exist, err := d.drv.Exists() if err != nil { return false, err diff --git a/pkg/hostman/hostinfo/hostinfo.go b/pkg/hostman/hostinfo/hostinfo.go index 39402bad3f..229b7ebe05 100644 --- a/pkg/hostman/hostinfo/hostinfo.go +++ b/pkg/hostman/hostinfo/hostinfo.go @@ -278,18 +278,14 @@ func (h *SHostInfo) detectHostInfo() error { } func (h *SHostInfo) checkSystemServices() error { - for _, srv := range []string{"ntpd", "telegraf"} { + for _, srv := range []string{"ntpd"} { srvinst := system_service.GetService(srv) - if srvinst == nil { - return fmt.Errorf("service %s not found", srv) - } else { - if !srvinst.IsInstalled() { - return fmt.Errorf("Service %s not installed", srv) - } + if !srvinst.IsInstalled() { + return fmt.Errorf("Service %s not installed", srv) } } - for _, srv := range []string{"host_sdnagent", "host-deployer"} { + for _, srv := range []string{"host_sdnagent", "host-deployer", "telegraf"} { srvinst := system_service.GetService(srv) if !srvinst.IsInstalled() { log.Warningf("Service %s not installed", srv) @@ -583,7 +579,8 @@ func (h *SHostInfo) tryCreateNetworkOnWire() { masterIp, mask := h.GetMasterNicIpAndMask() log.Debugf("Get master ip %s and mask %d", masterIp, mask) if len(masterIp) == 0 || mask == 0 { - return + log.Errorf("master ip %s mask %d", masterIp, mask) + h.onFail() } params := jsonutils.NewDict() params.Set("ip", jsonutils.NewString(masterIp)) @@ -765,7 +762,10 @@ func (h *SHostInfo) updateHostRecord(hostId string) { } content.Set("cpu_desc", jsonutils.NewString(h.Cpu.cpuInfoProc.Model)) content.Set("cpu_microcode", jsonutils.NewString(h.Cpu.cpuInfoProc.Microcode)) - content.Set("cpu_mhz", jsonutils.NewInt(int64(h.Cpu.cpuInfoProc.Freq))) + content.Set("cpu_architecture", jsonutils.NewString(h.Cpu.CpuArchitecture)) + if h.Cpu.cpuInfoProc.Freq > 0 { + content.Set("cpu_mhz", jsonutils.NewInt(int64(h.Cpu.cpuInfoProc.Freq))) + } content.Set("cpu_cache", jsonutils.NewInt(int64(h.Cpu.cpuInfoProc.Cache))) content.Set("mem_size", jsonutils.NewInt(int64(h.Mem.MemInfo.Total))) content.Set("storage_driver", jsonutils.NewString(api.DISK_DRIVER_LINUX)) @@ -1382,6 +1382,10 @@ func (h *SHostInfo) getHostname() string { return h.fetchHostname() } +func (h *SHostInfo) GetCpuArchitecture() string { + return h.Cpu.CpuArchitecture +} + func NewHostInfo() (*SHostInfo, error) { var res = new(SHostInfo) res.sysinfo = &SSysInfo{} @@ -1392,6 +1396,12 @@ func NewHostInfo() (*SHostInfo, error) { res.Cpu = cpu } + if cpu.CpuArchitecture == "aarch64" { + qemutils.UseAarch64() + } else if cpu.CpuArchitecture != "x86_64" { + return nil, fmt.Errorf("unsupport cpu architecture %s", cpu.CpuArchitecture) + } + log.Infof("CPU Model %s Microcode %s", cpu.cpuInfoProc.Model, cpu.cpuInfoProc.Microcode) mem, err := DetectMemoryInfo() diff --git a/pkg/hostman/hostinfo/hostinfohelper.go b/pkg/hostman/hostinfo/hostinfohelper.go index 8bcd95e69e..1464f5d33b 100644 --- a/pkg/hostman/hostinfo/hostinfohelper.go +++ b/pkg/hostman/hostinfo/hostinfohelper.go @@ -29,6 +29,7 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/pkg/errors" "yunion.io/x/pkg/util/netutils" "yunion.io/x/pkg/util/regutils" @@ -45,9 +46,10 @@ import ( ) type SCPUInfo struct { - CpuCount int - cpuFreq int64 // MHZ - cpuFeatures []string + CpuCount int + cpuFreq int64 // MHZ + cpuFeatures []string + CpuArchitecture string cpuInfoProc *types.SCPUInfo cpuInfoDmi *types.SDMICPUInfo @@ -61,12 +63,16 @@ func DetectCpuInfo() (*SCPUInfo, error) { if err != nil { return nil, err } - strCpuFreq := spec["cpu_freq"] - freq, err := strconv.ParseFloat(strCpuFreq, 64) - if err != nil { - log.Errorln(err) - return nil, err + var freq float64 + strCpuFreq, ok := spec["cpu_freq"] + if ok { + freq, err = strconv.ParseFloat(strCpuFreq, 64) + if err != nil { + log.Errorln(err) + return nil, err + } } + cpuinfo.cpuFreq = int64(freq) log.Infof("cpuinfo freq %d", cpuinfo.cpuFreq) @@ -75,24 +81,25 @@ func DetectCpuInfo() (*SCPUInfo, error) { // cpu.Percent(interval, false) ret, err := fileutils2.FileGetContents("/proc/cpuinfo") if err != nil { - log.Errorln(err) - return nil, err + return nil, errors.Wrap(err, "get cpuinfo") } cpuinfo.cpuInfoProc, err = sysutils.ParseCPUInfo(strings.Split(ret, "\n")) if err != nil { - log.Errorln(err) - return nil, err + return nil, errors.Wrap(err, "parse cpu info") } bret, err := procutils.NewCommand("dmidecode", "-t", "4").Run() if err != nil { - log.Errorln(err) - return nil, err + return nil, errors.Wrap(err, "get dmidecode info -t 4") } cpuinfo.cpuInfoDmi = sysutils.ParseDMICPUInfo(strings.Split(string(bret), "\n")) if err != nil { - log.Errorln(err) - return nil, err + return nil, errors.Wrap(err, "parse dmi cpuinfo") } + cpuArch, err := procutils.NewCommand("uname", "-p").Run() + if err != nil { + return nil, errors.Wrap(err, "get cpu architecture") + } + cpuinfo.CpuArchitecture = strings.TrimSpace(string(cpuArch)) return cpuinfo, nil } @@ -253,7 +260,7 @@ func NewNIC(desc string) (*SNIC, error) { if len(nic.Ip) > 0 { var max, wait = 30, 0 for wait < max { - inf := netutils2.NewNetInterface(nic.Inter) + inf := netutils2.NewNetInterfaceWithExpectIp(nic.Inter, nic.Ip) if inf.Addr == nic.Ip { mask, _ := inf.Mask.Size() if mask > 0 { @@ -263,6 +270,10 @@ func NewNIC(desc string) (*SNIC, error) { } br := netutils2.NewNetInterface(nic.Bridge) if br.Addr == nic.Ip { + mask, _ := br.Mask.Size() + if nic.Mask == 0 && mask > 0 { + nic.Mask = mask + } break } time.Sleep(time.Second * 2) diff --git a/pkg/hostman/hostutils/hostutils.go b/pkg/hostman/hostutils/hostutils.go index 3ab9340f22..e5c3f261a8 100644 --- a/pkg/hostman/hostutils/hostutils.go +++ b/pkg/hostman/hostutils/hostutils.go @@ -40,6 +40,7 @@ type IHost interface { GetHostId() string GetMediumType() string GetMasterIp() string + GetCpuArchitecture() string IsKvmSupport() bool IsNestedVirtualization() bool diff --git a/pkg/util/netutils2/netutils.go b/pkg/util/netutils2/netutils.go index af5841f872..170bb69de8 100644 --- a/pkg/util/netutils2/netutils.go +++ b/pkg/util/netutils2/netutils.go @@ -280,6 +280,13 @@ func NewNetInterface(name string) *SNetInterface { return n } +func NewNetInterfaceWithExpectIp(name string, expectIp string) *SNetInterface { + n := new(SNetInterface) + n.name = name + n.fetchConfig(expectIp) + return n +} + func (n *SNetInterface) String() string { return n.name } @@ -292,13 +299,17 @@ func (n *SNetInterface) Exist() bool { func (n *SNetInterface) FetchInter() *net.Interface { inter, err := net.InterfaceByName(n.name) if err != nil { - log.Errorln(err) + log.Errorf("fetch interface %s error %s", n.name, err) return nil } return inter } func (n *SNetInterface) FetchConfig() { + n.fetchConfig("") +} + +func (n *SNetInterface) fetchConfig(expectIp string) { n.Addr = "" n.Mask = nil n.Mac = "" @@ -316,7 +327,11 @@ func (n *SNetInterface) FetchConfig() { if ipnet.IP.To4() != nil { n.Addr = ipnet.IP.String() n.Mask = ipnet.Mask - break + if len(expectIp) > 0 && n.Addr != expectIp { + continue + } else { + break + } } } } diff --git a/pkg/util/qemutils/qemutils.go b/pkg/util/qemutils/qemutils.go index fa5d8bca37..1fa1f48754 100644 --- a/pkg/util/qemutils/qemutils.go +++ b/pkg/util/qemutils/qemutils.go @@ -31,8 +31,14 @@ const ( USER_BIN = "/usr/bin" ) +var qemuSystemCmd = "qemu-system-x86_64" + +func UseAarch64() { + qemuSystemCmd = "qemu-system-aarch64" +} + func GetQemu(version string) string { - return getQemuCmd("qemu-system-x86_64", version) + return getQemuCmd(qemuSystemCmd, version) } func GetQemuNbd() string { diff --git a/pkg/util/sysutils/kvm.go b/pkg/util/sysutils/kvm.go index 98bf71d2c0..ea8cb1b32b 100644 --- a/pkg/util/sysutils/kvm.go +++ b/pkg/util/sysutils/kvm.go @@ -31,7 +31,9 @@ import ( const ( KVM_MODULE_INTEL = "kvm-intel" KVM_MODULE_AMD = "kvm-amd" + KVM_MODULE = "kvm" KVM_MODULE_UNSUPPORT = "unsupport" + KVM_MODULE_BUILDIN = "buildin" HOST_NEST_UNSUPPORT = "0" HOST_NEST_SUPPORT = "1" @@ -80,6 +82,13 @@ func detectiveKVMModuleSupport() string { km = KVM_MODULE_INTEL } else if ModprobeKvmModule(KVM_MODULE_AMD, false, false) { km = KVM_MODULE_AMD + } else if ModprobeKvmModule(KVM_MODULE, false, false) { + km = KVM_MODULE + } + if km == KVM_MODULE_UNSUPPORT { + if fileutils2.Exists("/dev/kvm") { + km = KVM_MODULE_BUILDIN + } } return km } diff --git a/pkg/util/sysutils/sysutils.go b/pkg/util/sysutils/sysutils.go index 01f35cc2fd..57331020f5 100644 --- a/pkg/util/sysutils/sysutils.go +++ b/pkg/util/sysutils/sysutils.go @@ -105,13 +105,13 @@ func ParseCPUInfo(lines []string) (*types.SCPUInfo, error) { } } if len(model) == 0 { - return nil, fmt.Errorf("Not found model name") + log.Errorf("Failed to get cpu model") } if len(freq) == 0 { - return nil, fmt.Errorf("Not found cpu MHz") + log.Errorf("Failed to get cpu MHz") } if len(cache) == 0 { - return nil, fmt.Errorf("Not found cache size") + log.Errorf("Failed to get cpu cache size") } model = strings.TrimSpace(model) info := &types.SCPUInfo{ @@ -119,9 +119,13 @@ func ParseCPUInfo(lines []string) (*types.SCPUInfo, error) { Model: model, Microcode: microcode, } - info.Cache, _ = strconv.Atoi(cache) - freqF, _ := strconv.ParseFloat(freq, 32) - info.Freq = int(freqF) + if len(cache) > 0 { + info.Cache, _ = strconv.Atoi(cache) + } + if len(freq) > 0 { + freqF, _ := strconv.ParseFloat(freq, 32) + info.Freq = int(freqF) + } return info, nil }