support create arm virtual machine

This commit is contained in:
wanyaoqi
2020-08-24 17:22:40 +08:00
parent bb0d81bc06
commit 7d94c4e46f
21 changed files with 118 additions and 11 deletions
+6
View File
@@ -141,6 +141,10 @@ type DiskConfig struct {
// requried: false
Mountpoint string `json:"mountpoint"`
// 操作系统CPU架构
// required: false
OsArch string `json:"os_arch"`
//后端存储类型,若指定了存储ID,此参数会根据存储设置,若不指定,则作为调度的一个参考
//
//
@@ -472,6 +476,8 @@ type ServerCreateInput struct {
// swagger:ignore
OsType string `json:"os_type"`
// swagger:ignore
OsArch string `json:"os_arch"`
// swagger:ignore
DisableUsbKbd bool `json:"disable_usb_kbd"`
// swagger:ignore
OsProfile jsonutils.JSONObject `json:"__os_profile__"`
+5
View File
@@ -170,6 +170,11 @@ const (
CPU_MODE_HOST = "host"
)
const (
CPU_ARCH_X86 = "x86"
CPU_ARCH_ARM = "arm"
)
var VM_RUNNING_STATUS = []string{VM_START_START, VM_STARTING, VM_RUNNING, VM_BLOCK_STREAM, VM_BLOCK_STREAM_FAIL}
var VM_CREATING_STATUS = []string{VM_CREATE_NETWORK, VM_CREATE_DISK, VM_START_DEPLOY, VM_DEPLOYING}
+4
View File
@@ -129,3 +129,7 @@ const (
HOST_HEALTH_STATUS_RUNNING = "running"
HOST_HEALTH_LOCK_PREFIX = "host-health"
)
const (
CPU_ARCH_AARCH64 = "aarch64"
)
+2
View File
@@ -41,6 +41,8 @@ type SnapshotCreateInput struct {
OutOfChain bool `json:"out_of_chain"`
// swagger:ignore
ManagerId string `json:"manager_id"`
// swagger:ignore
OsArch string `json:"os_arch"`
}
type SSnapshotPolicyCreateInput struct {
+1
View File
@@ -78,6 +78,7 @@ type ScheduleInput struct {
CpuDesc string `json:"cpu_desc"`
CpuMicrocode string `json:"cpu_microcode"`
CpuMode string `json:"cpu_mode"`
OsArch string `json:"os_arch"`
PendingUsages []jsonutils.JSONObject
}
+2 -1
View File
@@ -361,7 +361,8 @@ func (self *SKVMGuestDriver) RequestAssociateEip(ctx context.Context, userCred m
func (self *SKVMGuestDriver) NeedStopForChangeSpec(guest *models.SGuest, cpuChanged, memChanged bool) bool {
return guest.GetMetadata("hotplug_cpu_mem", nil) != "enable" ||
(memChanged && guest.GetMetadata("__hugepage", nil) == "native")
(memChanged && guest.GetMetadata("__hugepage", nil) == "native") ||
guest.OsArch == api.CPU_ARCH_ARM
}
func (self *SKVMGuestDriver) RequestChangeVmConfig(ctx context.Context, guest *models.SGuest, task taskman.ITask, instanceType string, vcpuCount, vmemSize int64) error {
+8
View File
@@ -115,6 +115,9 @@ type SDisk struct {
// example: sys
DiskType string `width:"32" charset:"ascii" nullable:"true" list:"user" update:"admin" json:"disk_type"`
// cpu架构
OsArch string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"optional"`
// # is persistent
Nonpersistent bool `default:"false" list:"user" json:"nonpersistent"`
}
@@ -1688,6 +1691,7 @@ func fillDiskConfigBySnapshot(userCred mcclient.TokenCredential, diskConfig *api
diskConfig.Backend = storage.StorageType
diskConfig.Fs = ""
diskConfig.Mountpoint = ""
diskConfig.OsArch = snapshot.OsArch
}
return nil
}
@@ -1716,6 +1720,9 @@ func fillDiskConfigByImage(ctx context.Context, userCred mcclient.TokenCredentia
if diskConfig.SizeMb != api.DISK_SIZE_AUTOEXTEND && diskConfig.SizeMb < image.MinDiskMB {
diskConfig.SizeMb = image.MinDiskMB // MB
}
if strings.Contains(image.Properties["os_arch"], "aarch") {
diskConfig.OsArch = api.CPU_ARCH_ARM
}
}
return nil
}
@@ -1766,6 +1773,7 @@ func (self *SDisk) fetchDiskInfo(diskConfig *api.DiskConfig) {
}
self.DiskFormat = diskConfig.Format
self.DiskSize = diskConfig.SizeMb
self.OsArch = diskConfig.OsArch
}
type DiskInfo struct {
+18 -1
View File
@@ -195,6 +195,15 @@ func (self *SGuest) PerformSaveImage(ctx context.Context, userCred mcclient.Toke
osType = "Linux"
}
properties.Add(jsonutils.NewString(osType), "os_type")
if self.OsArch == api.CPU_ARCH_ARM {
var osArch string
if osArch = self.GetMetadata("os_arch", nil); len(osArch) == 0 {
host := self.GetHost()
osArch = host.CpuArchitecture
}
properties.Add(jsonutils.NewString(osArch), "os_arch")
kwargs.Set("os_arch", jsonutils.NewString(self.OsArch))
}
kwargs.Add(properties, "properties")
kwargs.Add(jsonutils.NewBool(restart), "restart")
@@ -261,8 +270,16 @@ func (self *SGuest) PerformSaveGuestImage(ctx context.Context, userCred mcclient
osType = "Linux"
}
properties.Add(jsonutils.NewString(osType), "os_type")
if self.OsArch == api.CPU_ARCH_ARM {
var osArch string
if osArch = self.GetMetadata("os_arch", nil); len(osArch) == 0 {
host := self.GetHost()
osArch = host.CpuArchitecture
}
properties.Add(jsonutils.NewString(osArch), "os_arch")
kwargs.Set("os_arch", jsonutils.NewString(self.OsArch))
}
kwargs.Add(properties, "properties")
kwargs.Add(images, "images")
s := auth.GetSession(ctx, userCred, options.Options.Region, "")
+8
View File
@@ -146,6 +146,9 @@ type SGuest struct {
// 虚拟化技术
// example: kvm
Hypervisor string `width:"16" charset:"ascii" nullable:"false" default:"kvm" list:"user" create:"required"`
// 虚拟机CPU架构
// example: x86 arm
OsArch string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"optional"`
// 套餐名称
InstanceType string `width:"64" charset:"utf8" nullable:"true" list:"user" create:"optional"`
@@ -1146,6 +1149,10 @@ func (manager *SGuestManager) validateCreateData(
}
}
if arch := imgProperties["os_arch"]; strings.Contains(arch, "aarch") {
input.OsArch = api.CPU_ARCH_ARM
}
if len(imgProperties) == 0 {
imgProperties = map[string]string{"os_type": "Linux"}
}
@@ -4867,6 +4874,7 @@ func (self *SGuest) ToSchedDesc() *schedapi.ScheduleInput {
config.Hypervisor = self.GetHypervisor()
desc.ServerConfig = *config
desc.OsArch = self.OsArch
return desc
}
+4
View File
@@ -527,6 +527,10 @@ func (manager *SHostManager) CustomizeFilterList(ctx context.Context, q *sqlchem
return filters, nil
}
func (self *SHost) IsArmHost() bool {
return self.CpuArchitecture == api.CPU_ARCH_AARCH64
}
func (self *SHost) GetZone() *SZone {
if len(self.ZoneId) == 0 {
return nil
+3
View File
@@ -66,6 +66,8 @@ type SInstanceSnapshot struct {
KeypairId string `width:"36" charset:"ascii" nullable:"true" list:"user"`
// 操作系统类型
OsType string `width:"36" charset:"ascii" nullable:"true" list:"user"`
// CPU架构
OsArch string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"optional"`
// 套餐名称
InstanceType string `width:"64" charset:"utf8" nullable:"true" list:"user" create:"optional"`
}
@@ -283,6 +285,7 @@ func (manager *SInstanceSnapshotManager) CreateInstanceSnapshot(
instanceSnapshot.SecGroups = jsonutils.Marshal(secIds)
}
instanceSnapshot.OsType = guest.OsType
instanceSnapshot.OsArch = guest.OsArch
instanceSnapshot.ServerMetadata = serverMetadata
instanceSnapshot.InstanceType = guest.InstanceType
err := manager.TableSpec().Insert(ctx, instanceSnapshot)
+2
View File
@@ -72,6 +72,7 @@ type SSnapshot struct {
DiskType string `width:"32" charset:"ascii" nullable:"true" list:"user" create:"optional"`
// 操作系统类型
OsType string `width:"32" charset:"ascii" nullable:"true" list:"user" create:"optional"`
OsArch string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"optional"`
// create disk from snapshot, snapshot as disk backing file
RefCount int `nullable:"false" default:"0" list:"user"`
@@ -346,6 +347,7 @@ func (manager *SSnapshotManager) ValidateCreateData(
input.DiskId = disk.Id
input.DiskType = disk.DiskType
input.Size = disk.DiskSize
input.OsArch = disk.OsArch
storage := disk.GetStorage()
if len(disk.ExternalId) == 0 {
+16 -1
View File
@@ -14,18 +14,27 @@
package fsdriver
import (
"strings"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/util/procutils"
)
type newRootFsDriverFunc func(part IDiskPartition) IRootFsDriver
var (
privatePrefixes []string
rootfsDrivers = make([]newRootFsDriverFunc, 0)
hostCpuArch string
)
func GetRootfsDrivers() []newRootFsDriverFunc {
return rootfsDrivers
}
func Init(initPrivatePrefixes []string) {
func Init(initPrivatePrefixes []string) error {
if len(initPrivatePrefixes) > 0 {
privatePrefixes = make([]string, len(initPrivatePrefixes))
copy(privatePrefixes, initPrivatePrefixes)
@@ -41,4 +50,10 @@ func Init(initPrivatePrefixes []string) {
rootfsDrivers = append(rootfsDrivers, NewEsxiRootFs)
rootfsDrivers = append(rootfsDrivers, NewWindowsRootFs)
rootfsDrivers = append(rootfsDrivers, NewAndroidRootFs)
cpuArch, err := procutils.NewCommand("uname", "-m").Output()
if err != nil {
return errors.Wrap(err, "get cpu architecture")
}
hostCpuArch = strings.TrimSpace(string(cpuArch))
return nil
}
+11 -3
View File
@@ -23,7 +23,7 @@ import (
"syscall"
"github.com/pkg/errors"
yaml "gopkg.in/yaml.v2"
"gopkg.in/yaml.v2"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -325,9 +325,17 @@ func (l *sLinuxRootFs) GetOs() string {
func (l *sLinuxRootFs) GetArch(rootFs IDiskPartition) string {
if rootFs.Exists("/lib64", false) && rootFs.Exists("/usr/lib64", false) {
return "x86_64"
if hostCpuArch == "aarch64" {
return "aarch64"
} else {
return "x86_64"
}
} else {
return "x86"
if hostCpuArch == "aarch64" {
return "aarch32"
} else {
return "x86"
}
}
}
+1 -1
View File
@@ -98,7 +98,7 @@ func (w *SWindowsRootFs) GetReleaseInfo(IDiskPartition) *deployapi.ReleaseInfo {
if tool.CheckPath() {
distro := tool.GetProductName()
version := tool.GetVersion()
arch := tool.GetArch()
arch := tool.GetArch(hostCpuArch)
lan := tool.GetInstallLanguage()
return &deployapi.ReleaseInfo{
Distro: distro,
@@ -376,7 +376,9 @@ func (s *SDeployService) InitService() {
if err := s.PrepareEnv(); err != nil {
log.Fatalln(err)
}
fsdriver.Init(DeployOption.PrivatePrefixes)
if err := fsdriver.Init(DeployOption.PrivatePrefixes); err != nil {
log.Fatalln(err)
}
s.O = &DeployOption.BaseOptions
if len(DeployOption.DeployServerSocketPath) == 0 {
log.Fatalf("missing deploy server socket path")
+2
View File
@@ -67,6 +67,8 @@ type SGuestImage struct {
db.SSharableVirtualResourceBase
Protected tristate.TriState `nullable:"false" default:"true" list:"user" get:"user" create:"optional" update:"user"`
// 操作系统CPU架构
OsArch string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"optional"`
}
func (manager *SGuestImageManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential,
+2
View File
@@ -134,6 +134,8 @@ type SImage struct {
IsGuestImage tristate.TriState `nullable:"false" default:"false" create:"optional" list:"user"`
// 是否是数据盘镜像
IsData tristate.TriState `nullable:"false" default:"false" create:"optional" list:"user"`
// 操作系统CPU架构
OsArch string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"optional"`
// image copy from url, save origin checksum before probe
// 从镜像时长导入的镜像校验和
@@ -41,6 +41,7 @@ const (
ErrSubtotalOfSplitExceedsDiskSize = `subtotal of split exceeds disk size`
ErrBaremetalHasAlreadyBeenOccupied = `baremetal has already been occupied`
ErrPrepaidHostOccupied = `prepaid host occupied`
ErrHostCpuArchitectureNotMatch = `host cpu architecture not match`
ErrUnknown = `unknown error`
)
@@ -15,6 +15,7 @@
package guest
import (
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/scheduler/algorithm/predicates"
"yunion.io/x/onecloud/pkg/scheduler/core"
)
@@ -53,6 +54,13 @@ func (f *CPUPredicate) Execute(u *core.Unit, c core.Candidater) (bool, []core.Pr
useRsvd := h.UseReserved()
getter := c.Getter()
if d.OsArch == compute.CPU_ARCH_ARM {
host := getter.Host()
if !host.IsArmHost() {
h.Exclude(predicates.ErrHostCpuArchitectureNotMatch)
return h.GetResult()
}
}
freeCPUCount := getter.FreeCPUCount(useRsvd)
reqCPUCount := int64(d.Ncpu)
if freeCPUCount < reqCPUCount {
+11 -3
View File
@@ -605,13 +605,21 @@ func (w *SWinRegTool) GetInstallLanguage() string {
}
}
func (w *SWinRegTool) GetArch() string {
func (w *SWinRegTool) GetArch(hostCpuArch string) string {
prodKey := `HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\CurrentVersion`
ver := w.GetRegistry(prodKey)
if len(ver) > 0 {
return "x86_64"
if hostCpuArch == "aarch64" {
return "aarch64"
} else {
return "x86_64"
}
} else {
return "x86"
if hostCpuArch == "aarch64" {
return "aarch32"
} else {
return "x86"
}
}
}