Feature: host support centos 6 (#406)

This commit is contained in:
Jian Qiu
2019-04-15 16:11:10 +08:00
committed by yunion-ci-robot
parent dfa0285dec
commit 3d4766611c
22 changed files with 491 additions and 213 deletions
+3 -3
View File
@@ -1245,9 +1245,9 @@ func fillDiskConfigByImage(ctx context.Context, userCred mcclient.TokenCredentia
}
diskConfig.ImageId = image.Id
diskConfig.ImageProperties = image.Properties
if len(diskConfig.Format) == 0 {
diskConfig.Format = image.DiskFormat
}
// if len(diskConfig.Format) == 0 {
// diskConfig.Format = image.DiskFormat
// }
// diskConfig.ImageDiskFormat = image.DiskFormat
CachedimageManager.ImageAddRefCount(image.Id)
if diskConfig.SizeMb < image.MinDiskMB {
+12 -1
View File
@@ -30,6 +30,7 @@ import (
"yunion.io/x/onecloud/pkg/util/ethernet/arp"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/qemutils"
"yunion.io/x/onecloud/pkg/util/sysutils"
)
const (
@@ -383,8 +384,18 @@ func (s *SKVMGuestInstance) generateStartScript(data *jsonutils.JSONDict) (strin
cpuType = ""
if osname == OS_NAME_MACOS {
cpuType = "Penryn,vendor=GenuineIntel"
} else {
} else if options.HostOptions.HostCpuPassthrough {
cpuType = "host"
} else {
cpuType = "qemu64"
if sysutils.IsProcessorIntel() {
cpuType += ",+vmx"
cpuType += ",+ssse3,+sse4.1,+sse4.2,-x2apic,+aes,+avx"
cpuType += ",+vme,+pat,+ss,+pclmulqdq,+xsave"
cpuType += ",level=13"
} else if sysutils.IsProcessorAmd() {
cpuType += ",+svm"
}
}
if !guestManger.GetHost().IsNestedVirtualization() {
+24 -159
View File
@@ -51,16 +51,6 @@ import (
"yunion.io/x/onecloud/pkg/util/winutils"
)
var (
KVM_MODULE_INTEL = "kvm-intel"
KVM_MODULE_AMD = "kvm-amd"
KVM_MODULE_UNSUPPORT = "unsupport"
HOST_NEST_UNSUPPORT = "0"
HOST_NEST_SUPPORT = "1"
HOST_NEST_ENABLE = "3"
)
type SHostInfo struct {
isRegistered bool
IsRegistered chan struct{}
@@ -70,9 +60,6 @@ type SHostInfo struct {
saved bool
pinger *SHostPingTask
kvmModuleSupport string
nestStatus string
Cpu *SCPUInfo
Mem *SMemory
sysinfo *SSysInfo
@@ -121,10 +108,7 @@ func (h *SHostInfo) GetMediumType() string {
}
func (h *SHostInfo) IsKvmSupport() bool {
if h.kvmModuleSupport == KVM_MODULE_UNSUPPORT {
return false
}
return true
return sysutils.IsKvmSupport()
}
func (h *SHostInfo) IsNestedVirtualization() bool {
@@ -290,9 +274,8 @@ func (h *SHostInfo) detectHostInfo() error {
}
h.sysinfo.SDMISystemInfo = sysinfo
h.detectiveKVMModuleSupport()
h.detectiveNestSupport()
h.tryEnableNest()
h.detectKvmModuleSupport()
h.detectNestSupport()
if err := h.detectiveSyssoftwareInfo(); err != nil {
return err
@@ -458,149 +441,18 @@ func (h *SHostInfo) resetIptables() error {
return nil
}
func (h *SHostInfo) detectiveKVMModuleSupport() {
if len(h.kvmModuleSupport) == 0 {
h.kvmModuleSupport = h._detectiveKVMModuleSupport()
}
func (h *SHostInfo) detectKvmModuleSupport() string {
return sysutils.GetKVMModuleSupport()
}
func (h *SHostInfo) _detectiveKVMModuleSupport() string {
var km = KVM_MODULE_UNSUPPORT
if h.modprobeKvmModule(KVM_MODULE_INTEL, false, false) {
km = KVM_MODULE_INTEL
} else if h.modprobeKvmModule(KVM_MODULE_AMD, false, false) {
km = KVM_MODULE_AMD
}
return km
}
func (h *SHostInfo) modprobeKvmModule(name string, remove, nest bool) bool {
var params = []string{"modprobe"}
if remove {
params = append(params, "-r")
}
params = append(params, name)
if nest {
params = append(params, "nested=1")
}
if _, err := procutils.NewCommand(params[0], params[1:]...).Run(); err != nil {
return false
}
return true
}
func (h *SHostInfo) getKvmModuleSupport() string {
if len(h.kvmModuleSupport) == 0 {
h.detectiveKVMModuleSupport()
}
return h.kvmModuleSupport
}
func (h *SHostInfo) detectiveNestSupport() {
if len(h.nestStatus) == 0 {
h.nestStatus = h._detectiveNestSupport()
}
h.sysinfo.Nest = h.nestStatus2Str(h.nestStatus)
}
func (h *SHostInfo) _detectiveNestSupport() string {
var (
moduleName = h.getKvmModuleSupport()
nestStatus = HOST_NEST_UNSUPPORT
)
if moduleName != KVM_MODULE_UNSUPPORT && h._isNestSupport(moduleName) {
nestStatus = HOST_NEST_SUPPORT
}
return nestStatus
}
func (h *SHostInfo) _isNestSupport(name string) bool {
output, err := procutils.NewCommand("modinfo", name).Run()
if err != nil {
log.Errorln(err)
return false
}
// TODO Test
var re = regexp.MustCompile(`parm:\s*nested:`)
for _, line := range strings.Split(string(output), "\n") {
if re.MatchString(line) {
return true
}
}
return false
}
func (h *SHostInfo) nestStatus2Str(status string) string {
if status == HOST_NEST_ENABLE {
return "enabled"
func (h *SHostInfo) detectNestSupport() {
if sysutils.IsNestEnabled() {
h.sysinfo.Nest = "enabled"
} else {
return "disbaled"
h.sysinfo.Nest = "disabled"
}
}
func (h *SHostInfo) tryEnableNest() {
if h.nestStatus == HOST_NEST_SUPPORT {
if h.loadKvmModuleWithNest(h.kvmModuleSupport) {
h.nestStatus = HOST_NEST_ENABLE
}
}
h.sysinfo.Nest = h.nestStatus2Str(h.nestStatus)
}
func (h *SHostInfo) loadKvmModuleWithNest(name string) bool {
var notload = true
if h.checkKvmModuleInstall(name) {
nest := h.getModuleParameter(name, "nested")
if nest == "Y" {
return true
}
notload = h.unloadKvmModule(name)
}
if notload {
if h.modprobeKvmModule(name, false, true) {
return true
}
}
return false
}
func (h *SHostInfo) unloadKvmModule(name string) bool {
return h.modprobeKvmModule(name, true, false)
}
func (h *SHostInfo) getModuleParameter(name, moduel string) string {
pa := path.Join("/sys/module/", strings.Replace(name, "-", "_", -1), "/parameters/", moduel)
if f, err := os.Stat(pa); err == nil {
if f.IsDir() {
return ""
}
cont, err := fileutils2.FileGetContents(pa)
if err != nil {
log.Errorln(err)
return ""
}
return strings.TrimSpace(cont)
}
return ""
}
func (h *SHostInfo) checkKvmModuleInstall(name string) bool {
output, err := procutils.NewCommand("lsmod").Run()
if err != nil {
log.Errorln(err)
return false
}
for _, line := range strings.Split(string(output), "\n") {
lm := strings.Split(line, " ")
if len(lm) > 0 && utils.IsInStringArray(strings.Replace(name, "-", "_", -1), lm) {
return true
}
}
return false
}
func (h *SHostInfo) detectiveOsDist() {
files, err := procutils.NewCommand("sh", "-c", "ls /etc/*elease").Run()
if err != nil {
@@ -819,7 +671,7 @@ func (h *SHostInfo) getHostInfo(zoneId string) {
func (h *SHostInfo) setHostname(name string) {
h.FullName = name
_, err := procutils.NewCommand("hostnamectl", "set-hostname", name).Run()
err := sysutils.SetHostname(name)
if err != nil {
log.Errorln("Fail to set system hostname: %s", err)
}
@@ -829,8 +681,21 @@ func (h *SHostInfo) fetchHostname() string {
if len(options.HostOptions.Hostname) > 0 {
return options.HostOptions.Hostname
} else {
hn, err := os.Hostname()
if err != nil {
log.Fatalf("fail to get hostname %s", err)
return ""
}
dotIdx := strings.IndexByte(hn, '.')
if dotIdx >= 0 {
hn = hn[:dotIdx]
}
hn = strings.ToLower(hn)
if len(hn) == 0 {
hn = "host"
}
masterIp := h.GetMasterIp()
return "host-" + masterIp
return hn + "-" + strings.Replace(masterIp, ".", "-", -1)
}
}
+2
View File
@@ -100,6 +100,8 @@ type SHostOptions struct {
EnableTelegraf bool `default:"true" help:"enable send monitoring data to telegraf"`
WindowsDefaultAdminUser bool `default:"true" help:"Default account for Windows system is Administrator"`
HostCpuPassthrough bool `default:"true" help:"if it is true, set qemu cpu type as -cpu host, otherwise, qemu64. default is true"`
}
var HostOptions SHostOptions
@@ -127,7 +127,9 @@ func (c *SLocalImageCacheManager) PrefetchImageCache(ctx context.Context, data i
if err != nil {
return nil, err
}
format, _ := body.GetString("format")
// format, _ := body.GetString("format")
// force qcow2 for KVM
format := "qcow2"
srcUrl, _ := body.GetString("src_url")
if imgCache := c.AcquireImage(ctx, imageId, storageManager.GetZone(),
+1 -1
View File
@@ -25,7 +25,7 @@ type SDocker struct {
}
func NewDockerService() *SDocker {
return &SDocker{&SBaseSystemService{"docker", nil}}
return &SDocker{NewBaseSystemService("docker", nil)}
}
func (s *SDocker) GetConfig(kwargs map[string]interface{}) string {
+1 -1
View File
@@ -29,7 +29,7 @@ type SFluentbit struct {
}
func NewFluentbitService() *SFluentbit {
return &SFluentbit{&SBaseSystemService{"fluentbit", nil}}
return &SFluentbit{NewBaseSystemService("fluentbit", nil)}
}
func (s *SFluentbit) GetConfig(kwargs map[string]interface{}) string {
+1 -1
View File
@@ -21,7 +21,7 @@ type SKubeAgent struct {
}
func NewKubeAgentService() *SKubeAgent {
return &SKubeAgent{&SBaseSystemService{"yunion-kube-agent", nil}}
return &SKubeAgent{NewBaseSystemService("yunion-kube-agent", nil)}
}
func (s *SKubeAgent) GetConfig(kwargs map[string]interface{}) string {
+1 -1
View File
@@ -19,7 +19,7 @@ type SLxcfs struct {
}
func NewLxcfsService() *SLxcfs {
return &SLxcfs{&SBaseSystemService{"lxcfs", nil}}
return &SLxcfs{NewBaseSystemService("lxcfs", nil)}
}
func (s *SLxcfs) Reload(kwargs map[string]interface{}) error {
+1 -1
View File
@@ -21,7 +21,7 @@ type SNtpd struct {
}
func NewNtpdService() *SNtpd {
return &SNtpd{&SBaseSystemService{"ntpd", nil}}
return &SNtpd{NewBaseSystemService("ntpd", nil)}
}
func (s *SNtpd) GetConfig(kwargs map[string]interface{}) string {
+1 -1
View File
@@ -19,7 +19,7 @@ type SOpenvswitch struct {
}
func NewOpenvswitchService() *SOpenvswitch {
return &SOpenvswitch{&SBaseSystemService{"openvswitch", nil}}
return &SOpenvswitch{NewBaseSystemService("openvswitch", nil)}
}
func (s *SOpenvswitch) Reload(kwargs map[string]interface{}) error {
+1 -1
View File
@@ -19,7 +19,7 @@ type SHostSdnagent struct {
}
func NewHostSdnagentService() *SHostSdnagent {
return &SHostSdnagent{&SBaseSystemService{"yunion-host-sdnagent", nil}}
return &SHostSdnagent{NewBaseSystemService("yunion-host-sdnagent", nil)}
}
func (s *SHostSdnagent) Reload(kwargs map[string]interface{}) error {
@@ -0,0 +1,15 @@
package system_service
type SServiceStatus struct {
Loaded bool
Active bool
}
type IServiceManager interface {
Detect() bool
Start(srvname string) error
Enable(srvname string) error
Stop(srvname string) error
Disable(srvname string) error
GetStatus(srvname string) SServiceStatus
}
+23 -41
View File
@@ -15,12 +15,9 @@
package system_service
import (
"strings"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/procutils"
)
type ISystemService interface {
@@ -34,7 +31,6 @@ type ISystemService interface {
BgReload(kwargs map[string]interface{})
Enable() error
Disable() error
GetStatus() map[string]string
Reload(kwargs map[string]interface{}) error
}
@@ -60,8 +56,21 @@ func GetService(name string) ISystemService {
}
type SBaseSystemService struct {
name string
urls interface{}
manager IServiceManager
name string
urls interface{}
}
func NewBaseSystemService(name string, urls interface{}) *SBaseSystemService {
ss := SBaseSystemService{}
if SysVServiceManager.Detect() {
ss.manager = SysVServiceManager
} else {
ss.manager = SystemdServiceManager
}
ss.name = name
ss.urls = urls
return &ss
}
func (s *SBaseSystemService) reload(conf, conFile string) error {
@@ -81,28 +90,8 @@ func (s *SBaseSystemService) reload(conf, conFile string) error {
}
func (s *SBaseSystemService) IsInstalled() bool {
status := s.GetStatus()
if loaded, ok := status["loaded"]; ok && loaded == "loaded" {
return true
}
return false
}
func (s *SBaseSystemService) GetStatus() map[string]string {
res, _ := procutils.NewCommand("systemctl", "status", s.name).Run()
var ret = make(map[string]string, 0)
lines := strings.Split(string(res), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if len(line) > 0 {
if strings.HasPrefix(line, "Loaded:") {
ret["loaded"] = strings.Split(line, " ")[1]
} else if strings.HasPrefix(line, "Active:") {
ret["active"] = strings.Split(line, " ")[1]
}
}
}
return ret
status := s.manager.GetStatus(s.name)
return status.Loaded
}
func (s *SBaseSystemService) Start(enable bool) error {
@@ -111,8 +100,7 @@ func (s *SBaseSystemService) Start(enable bool) error {
return err
}
}
_, err := procutils.NewCommand("systemctl", "restart", s.name).Run()
return err
return s.manager.Start(s.name)
}
func (s *SBaseSystemService) Stop(disable bool) error {
@@ -121,16 +109,12 @@ func (s *SBaseSystemService) Stop(disable bool) error {
return err
}
}
_, err := procutils.NewCommand("systemctl", "stop", s.name).Run()
return err
return s.manager.Stop(s.name)
}
func (s *SBaseSystemService) IsActive() bool {
status := s.GetStatus()
if active, ok := status["active"]; ok && active == "active" {
return true
}
return false
status := s.manager.GetStatus(s.name)
return status.Active
}
func (s *SBaseSystemService) GetConfig(map[string]interface{}) string {
@@ -150,11 +134,9 @@ func (s *SBaseSystemService) GetConf() interface{} {
}
func (s *SBaseSystemService) Enable() error {
_, err := procutils.NewCommand("systemctl", "enable", s.name).Run()
return err
return s.manager.Enable(s.name)
}
func (s *SBaseSystemService) Disable() error {
_, err := procutils.NewCommand("systemctl", "disable", s.name).Run()
return err
return s.manager.Disable(s.name)
}
+66
View File
@@ -0,0 +1,66 @@
package system_service
import (
"strings"
"yunion.io/x/onecloud/pkg/util/procutils"
)
var (
SystemdServiceManager IServiceManager = &SSystemdServiceManager{}
)
type SSystemdServiceManager struct {
}
func (manager *SSystemdServiceManager) Detect() bool {
_, err := procutils.NewCommand("systemctl", "--version").Run()
return err == nil
}
func (manager *SSystemdServiceManager) Start(srvname string) error {
_, err := procutils.NewCommand("systemctl", "restart", srvname).Run()
return err
}
func (manager *SSystemdServiceManager) Enable(srvname string) error {
_, err := procutils.NewCommand("systemctl", "enable", srvname).Run()
return err
}
func (manager *SSystemdServiceManager) Stop(srvname string) error {
_, err := procutils.NewCommand("systemctl", "stop", srvname).Run()
return err
}
func (manager *SSystemdServiceManager) Disable(srvname string) error {
_, err := procutils.NewCommand("systemctl", "disable", srvname).Run()
return err
}
func (manager *SSystemdServiceManager) GetStatus(srvname string) SServiceStatus {
res, _ := procutils.NewCommand("systemctl", "status", srvname).Run()
return parseSystemdStatus(string(res), srvname)
}
func parseSystemdStatus(res string, srvname string) SServiceStatus {
var ret SServiceStatus
lines := strings.Split(string(res), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if len(line) > 0 {
if strings.HasPrefix(line, "Loaded:") {
parts := strings.Split(line, " ")
if len(parts) > 1 && parts[1] == "loaded" {
ret.Loaded = true
}
} else if strings.HasPrefix(line, "Active:") {
parts := strings.Split(line, " ")
if len(parts) > 1 && parts[1] == "active" {
ret.Active = true
}
}
}
}
return ret
}
@@ -0,0 +1,32 @@
package system_service
import (
"testing"
)
func TestParseSystemd(t *testing.T) {
cases := []struct {
in string
name string
wantLoaded bool
wantActive bool
}{
{`openvswitch.service - LSB: Open vSwitch switch
Loaded: loaded (/etc/rc.d/init.d/openvswitch; bad; vendor preset: disabled)
Active: active (running) since Wed 2019-04-10 15:11:23 CST; 4 days ago
Docs: man:systemd-sysv-generator(8)
Process: 3686 ExecStart=/etc/rc.d/init.d/openvswitch start (code=exited, status=0/SUCCESS)
CGroup: /system.slice/openvswitch.service
├─3722 ovsdb-server: monitoring pid 3723 (healthy)
├─3723 ovsdb-server /etc/openvswitch/conf.db -vconsole:emer -vsysl...
├─3774 ovs-vswitchd: monitoring pid 3775 (healthy)
└─3775 ovs-vswitchd unix:/var/run/openvswitch/db.sock -vconsole:em...`, "openvswitch", true, true},
{"Unit yunion-host.service could not be found.", "yunion-host", false, false},
}
for _, c := range cases {
status := parseSystemdStatus(c.in, c.name)
if status.Loaded != c.wantLoaded || status.Active != c.wantActive {
t.Errorf("parseSystemdStatus %s Loaded: want %v got %v Active: want %v got %v", c.name, c.wantLoaded, status.Loaded, c.wantActive, status.Active)
}
}
}
+61
View File
@@ -0,0 +1,61 @@
package system_service
import (
"strings"
"yunion.io/x/onecloud/pkg/util/procutils"
)
var (
SysVServiceManager IServiceManager = &SSysVServiceManager{}
)
type SSysVServiceManager struct {
}
func (manager *SSysVServiceManager) Detect() bool {
_, err := procutils.NewCommand("chkconfig", "--version").Run()
return err == nil
}
func (manager *SSysVServiceManager) Start(srvname string) error {
_, err := procutils.NewCommand("service", srvname, "restart").Run()
return err
}
func (manager *SSysVServiceManager) Enable(srvname string) error {
_, err := procutils.NewCommand("chkconfig", srvname, "on").Run()
return err
}
func (manager *SSysVServiceManager) Stop(srvname string) error {
_, err := procutils.NewCommand("service", srvname, "stop").Run()
return err
}
func (manager *SSysVServiceManager) Disable(srvname string) error {
_, err := procutils.NewCommand("chkconfig", srvname, "off").Run()
return err
}
func (manager *SSysVServiceManager) GetStatus(srvname string) SServiceStatus {
res, _ := procutils.NewCommand("chkconfig", "--list", srvname).Run()
res2, _ := procutils.NewCommand("service", srvname, "status").Run()
return parseSysvStatus(string(res), string(res2), srvname)
}
func parseSysvStatus(res string, res2 string, srvname string) SServiceStatus {
var ret SServiceStatus
lines := strings.Split(res, "\n")
for _, line := range lines {
parts := strings.Split(strings.TrimSpace(line), "\t")
if len(parts) > 1 && strings.TrimSpace(parts[0]) == srvname {
ret.Loaded = true
if strings.Index(res2, "running") > 0 {
ret.Active = true
}
break
}
}
return ret
}
+25
View File
@@ -0,0 +1,25 @@
package system_service
import (
"testing"
)
func TestParseSysv(t *testing.T) {
cases := []struct {
in1 string
in2 string
name string
wantLoaded bool
wantActive bool
}{
{`openvswitch 0:off 1:off 2:off 3:off 4:off 5:off 6:off`, `ovsdb-server is running with pid 114553
ovs-vswitchd is running with pid 114563`, "openvswitch", true, true},
{`yunion-host 0:off 1:off 2:on 3:on 4:on 5:on 6:off`, "", "yunion-host", true, false},
}
for _, c := range cases {
status := parseSysvStatus(c.in1, c.in2, c.name)
if status.Loaded != c.wantLoaded || status.Active != c.wantActive {
t.Errorf("parseSysVStatus %s Loaded want %v got %v Active want %v got %v", c.name, c.wantLoaded, status.Loaded, c.wantActive, status.Active)
}
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ type STelegraf struct {
}
func NewTelegrafService() *STelegraf {
return &STelegraf{&SBaseSystemService{"telegraf", nil}}
return &STelegraf{NewBaseSystemService("telegraf", nil)}
}
func (s *STelegraf) GetConfig(kwargs map[string]interface{}) string {
+8
View File
@@ -97,6 +97,14 @@ func Zerofiles(sPath string) error {
return nil
}
func FileSetContents(filename string, content string) error {
return FilePutContents(filename, content, false)
}
func FileAppendContents(filename string, content string) error {
return FilePutContents(filename, content, true)
}
func FilePutContents(filename string, content string, modAppend bool) error {
var mode = os.O_WRONLY | os.O_CREATE
if modAppend {
+30
View File
@@ -0,0 +1,30 @@
package sysutils
import (
"fmt"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/procutils"
)
func setHostname7(name string) error {
_, err := procutils.NewCommand("hostnamectl", "set-hostname", name).Run()
return err
}
func setHostname6(name string) error {
_, err := procutils.NewCommand("hostname", name).Run()
if err != nil {
return err
}
cont := fmt.Sprintf("NETWORKING=yes\nHOSTNAME=%s\n", name)
return fileutils2.FileSetContents("/etc/sysconfig/network", cont)
}
func SetHostname(name string) error {
err := setHostname7(name)
if err != nil {
err = setHostname6(name)
}
return err
}
+179
View File
@@ -0,0 +1,179 @@
package sysutils
import (
"os"
"path"
"regexp"
"strings"
"yunion.io/x/log"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/procutils"
)
const (
KVM_MODULE_INTEL = "kvm-intel"
KVM_MODULE_AMD = "kvm-amd"
KVM_MODULE_UNSUPPORT = "unsupport"
HOST_NEST_UNSUPPORT = "0"
HOST_NEST_SUPPORT = "1"
HOST_NEST_ENABLE = "3"
)
var (
kvmModuleSupport string
nestStatus string
)
func GetKVMModuleSupport() string {
if len(kvmModuleSupport) == 0 {
kvmModuleSupport = detectiveKVMModuleSupport()
}
return kvmModuleSupport
}
func IsKvmSupport() bool {
GetKVMModuleSupport()
if kvmModuleSupport == KVM_MODULE_UNSUPPORT {
return false
}
return true
}
func IsProcessorIntel() bool {
GetKVMModuleSupport()
if kvmModuleSupport == KVM_MODULE_INTEL {
return true
}
return false
}
func IsProcessorAmd() bool {
GetKVMModuleSupport()
if kvmModuleSupport == KVM_MODULE_AMD {
return true
}
return false
}
func detectiveKVMModuleSupport() string {
var km = KVM_MODULE_UNSUPPORT
if ModprobeKvmModule(KVM_MODULE_INTEL, false, false) {
km = KVM_MODULE_INTEL
} else if ModprobeKvmModule(KVM_MODULE_AMD, false, false) {
km = KVM_MODULE_AMD
}
return km
}
func ModprobeKvmModule(name string, remove, nest bool) bool {
var params = []string{"modprobe"}
if remove {
params = append(params, "-r")
}
params = append(params, name)
if nest {
params = append(params, "nested=1")
}
if _, err := procutils.NewCommand(params[0], params[1:]...).Run(); err != nil {
return false
}
return true
}
func IsNestEnabled() bool {
return GetNestSupport() == HOST_NEST_ENABLE
}
func GetNestSupport() string {
if len(nestStatus) == 0 {
nestStatus = detectNestSupport()
}
return nestStatus
}
func detectNestSupport() string {
moduleName := GetKVMModuleSupport()
nestStatus := HOST_NEST_UNSUPPORT
if moduleName != KVM_MODULE_UNSUPPORT && isNestSupport(moduleName) {
nestStatus = HOST_NEST_SUPPORT
}
if nestStatus == HOST_NEST_SUPPORT && loadKvmModuleWithNest(moduleName) {
nestStatus = HOST_NEST_ENABLE
}
return nestStatus
}
func isNestSupport(name string) bool {
output, err := procutils.NewCommand("modinfo", name).Run()
if err != nil {
log.Errorln(err)
return false
}
// TODO Test
var re = regexp.MustCompile(`parm:\s*nested:`)
for _, line := range strings.Split(string(output), "\n") {
if re.MatchString(line) {
return true
}
}
return false
}
func loadKvmModuleWithNest(name string) bool {
var notload = true
if IsKernelModuleLoaded(name) {
nest := GetKernelModuleParameter(name, "nested")
if nest == "Y" {
return true
}
notload = unloadKvmModule(name)
}
if notload {
if ModprobeKvmModule(name, false, true) {
return true
}
}
return false
}
func unloadKvmModule(name string) bool {
return ModprobeKvmModule(name, true, false)
}
func GetKernelModuleParameter(name, moduel string) string {
pa := path.Join("/sys/module/", strings.Replace(name, "-", "_", -1), "/parameters/", moduel)
if f, err := os.Stat(pa); err == nil {
if f.IsDir() {
return ""
}
cont, err := fileutils2.FileGetContents(pa)
if err != nil {
log.Errorln(err)
return ""
}
return strings.TrimSpace(cont)
}
return ""
}
func IsKernelModuleLoaded(name string) bool {
output, err := procutils.NewCommand("lsmod").Run()
if err != nil {
log.Errorln(err)
return false
}
for _, line := range strings.Split(string(output), "\n") {
lm := strings.Split(line, " ")
if len(lm) > 0 && utils.IsInStringArray(strings.Replace(name, "-", "_", -1), lm) {
return true
}
}
return false
}