mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-30 18:23:35 +08:00
fix confilct
This commit is contained in:
@@ -253,7 +253,7 @@ func init() {
|
||||
}
|
||||
req.Add(jsonutils.NewArray(data...), key)
|
||||
}
|
||||
fmt.Println(req.String())
|
||||
fmt.Println("Request:", req.String())
|
||||
|
||||
var token mcclient.TokenCredential
|
||||
if len(args.User) > 0 {
|
||||
@@ -273,6 +273,11 @@ func init() {
|
||||
}
|
||||
printObject(result)
|
||||
|
||||
fmt.Println("userCred:", token)
|
||||
m := policy.PolicyManager.MatchedPolicies(false, token)
|
||||
fmt.Println("matched policies:", m)
|
||||
m = policy.PolicyManager.MatchedPolicies(true, token)
|
||||
fmt.Println("matched admin policies:", m)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ type ServerCreateInput struct {
|
||||
Description string `json:"description"`
|
||||
BootOrder string `json:"boot_order"`
|
||||
ResetPassword *bool `json:"reset_password"`
|
||||
DisableDelete bool `json:"disable_delete"`
|
||||
DisableDelete *bool `json:"disable_delete"`
|
||||
ShutdownBehavior string `json:"shutdown_behavior"`
|
||||
AutoStart bool `json:"auto_start"`
|
||||
DeployConfigs []*DeployConfig `json:"deploy_configs"`
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
package compute
|
||||
|
||||
const (
|
||||
VM_INIT = "init"
|
||||
VM_UNKNOWN = "unknown"
|
||||
VM_SCHEDULE = "schedule"
|
||||
VM_SCHEDULE_FAILED = "sched_fail"
|
||||
VM_CREATE_NETWORK = "network"
|
||||
VM_NETWORK_FAILED = "net_fail"
|
||||
VM_DEVICE_FAILED = "dev_fail"
|
||||
VM_CREATE_FAILED = "create_fail"
|
||||
VM_CREATE_DISK = "disk"
|
||||
VM_DISK_FAILED = "disk_fail"
|
||||
VM_START_DEPLOY = "start_deploy"
|
||||
VM_DEPLOYING = "deploying"
|
||||
VM_DEPLOY_FAILED = "deploy_fail"
|
||||
VM_READY = "ready"
|
||||
VM_START_START = "start_start"
|
||||
VM_STARTING = "starting"
|
||||
VM_START_FAILED = "start_fail" // # = ready
|
||||
VM_RUNNING = "running"
|
||||
VM_START_STOP = "start_stop"
|
||||
VM_STOPPING = "stopping"
|
||||
VM_STOP_FAILED = "stop_fail" // # = running
|
||||
|
||||
VM_BACKUP_STARTING = "backup_starting"
|
||||
VM_BACKUP_CREATING = "backup_creating"
|
||||
VM_BACKUP_CREATE_FAILED = "backup_create_fail"
|
||||
VM_DEPLOYING_BACKUP = "deploying_backup"
|
||||
VM_DEPLOYING_BACKUP_FAILED = "deploging_backup_fail"
|
||||
VM_DELETING_BACKUP = "deleting_backup"
|
||||
VM_BACKUP_DELETE_FAILED = "backup_delete_fail"
|
||||
VM_SWITCH_TO_BACKUP = "switch_to_backup"
|
||||
VM_SWITCH_TO_BACKUP_FAILED = "switch_to_backup_fail"
|
||||
|
||||
VM_ATTACH_DISK_FAILED = "attach_disk_fail"
|
||||
VM_DETACH_DISK_FAILED = "detach_disk_fail"
|
||||
|
||||
VM_START_SUSPEND = "start_suspend"
|
||||
VM_SUSPENDING = "suspending"
|
||||
VM_SUSPEND = "suspend"
|
||||
VM_SUSPEND_FAILED = "suspend_failed"
|
||||
|
||||
VM_START_DELETE = "start_delete"
|
||||
VM_DELETE_FAIL = "delete_fail"
|
||||
VM_DELETING = "deleting"
|
||||
|
||||
VM_DEALLOCATED = "deallocated"
|
||||
|
||||
VM_START_MIGRATE = "start_migrate"
|
||||
VM_MIGRATING = "migrating"
|
||||
VM_MIGRATE_FAILED = "migrate_failed"
|
||||
|
||||
VM_CHANGE_FLAVOR = "change_flavor"
|
||||
VM_CHANGE_FLAVOR_FAIL = "change_flavor_fail"
|
||||
VM_REBUILD_ROOT = "rebuild_root"
|
||||
VM_REBUILD_ROOT_FAIL = "rebuild_root_fail"
|
||||
|
||||
VM_START_SNAPSHOT = "snapshot_start"
|
||||
VM_SNAPSHOT = "snapshot"
|
||||
VM_SNAPSHOT_DELETE = "snapshot_delete"
|
||||
VM_BLOCK_STREAM = "block_stream"
|
||||
VM_MIRROR_FAIL = "mirror_failed"
|
||||
VM_SNAPSHOT_SUCC = "snapshot_succ"
|
||||
VM_SNAPSHOT_FAILED = "snapshot_failed"
|
||||
|
||||
VM_SYNCING_STATUS = "syncing"
|
||||
VM_SYNC_CONFIG = "sync_config"
|
||||
VM_SYNC_FAIL = "sync_fail"
|
||||
|
||||
VM_RESIZE_DISK = "resize_disk"
|
||||
VM_RESIZE_DISK_FAILED = "resize_disk_fail"
|
||||
VM_START_SAVE_DISK = "start_save_disk"
|
||||
VM_SAVE_DISK = "save_disk"
|
||||
VM_SAVE_DISK_FAILED = "save_disk_failed"
|
||||
|
||||
VM_RESTORING_SNAPSHOT = "restoring_snapshot"
|
||||
VM_RESTORE_DISK = "restore_disk"
|
||||
VM_RESTORE_STATE = "restore_state"
|
||||
VM_RESTORE_FAILED = "restore_failed"
|
||||
|
||||
VM_ASSOCIATE_EIP = "associate_eip"
|
||||
VM_ASSOCIATE_EIP_FAILED = "associate_eip_failed"
|
||||
VM_DISSOCIATE_EIP = "dissociate_eip"
|
||||
VM_DISSOCIATE_EIP_FAILED = "dissociate_eip_failed"
|
||||
|
||||
VM_REMOVE_STATEFILE = "remove_state"
|
||||
|
||||
VM_ADMIN = "admin"
|
||||
|
||||
SHUTDOWN_STOP = "stop"
|
||||
SHUTDOWN_TERMINATE = "terminate"
|
||||
|
||||
HYPERVISOR_KVM = "kvm"
|
||||
HYPERVISOR_CONTAINER = "container"
|
||||
HYPERVISOR_BAREMETAL = "baremetal"
|
||||
HYPERVISOR_ESXI = "esxi"
|
||||
HYPERVISOR_HYPERV = "hyperv"
|
||||
HYPERVISOR_XEN = "xen"
|
||||
|
||||
HYPERVISOR_ALIYUN = "aliyun"
|
||||
HYPERVISOR_QCLOUD = "qcloud"
|
||||
HYPERVISOR_AZURE = "azure"
|
||||
HYPERVISOR_AWS = "aws"
|
||||
HYPERVISOR_HUAWEI = "huawei"
|
||||
HYPERVISOR_OPENSTACK = "openstack"
|
||||
HYPERVISOR_UCLOUD = "ucloud"
|
||||
|
||||
// HYPERVISOR_DEFAULT = HYPERVISOR_KVM
|
||||
HYPERVISOR_DEFAULT = HYPERVISOR_KVM
|
||||
)
|
||||
|
||||
var VM_RUNNING_STATUS = []string{VM_START_START, VM_STARTING, VM_RUNNING, VM_BLOCK_STREAM}
|
||||
var VM_CREATING_STATUS = []string{VM_CREATE_NETWORK, VM_CREATE_DISK, VM_START_DEPLOY, VM_DEPLOYING}
|
||||
|
||||
var HYPERVISORS = []string{HYPERVISOR_KVM,
|
||||
HYPERVISOR_BAREMETAL,
|
||||
HYPERVISOR_ESXI,
|
||||
HYPERVISOR_CONTAINER,
|
||||
HYPERVISOR_ALIYUN,
|
||||
HYPERVISOR_AZURE,
|
||||
HYPERVISOR_AWS,
|
||||
HYPERVISOR_QCLOUD,
|
||||
HYPERVISOR_HUAWEI,
|
||||
HYPERVISOR_OPENSTACK,
|
||||
HYPERVISOR_UCLOUD,
|
||||
}
|
||||
|
||||
var PUBLIC_CLOUD_HYPERVISORS = []string{
|
||||
HYPERVISOR_ALIYUN,
|
||||
HYPERVISOR_AWS,
|
||||
HYPERVISOR_AZURE,
|
||||
HYPERVISOR_QCLOUD,
|
||||
HYPERVISOR_HUAWEI,
|
||||
HYPERVISOR_OPENSTACK,
|
||||
HYPERVISOR_UCLOUD,
|
||||
}
|
||||
|
||||
// var HYPERVISORS = []string{HYPERVISOR_ALIYUN}
|
||||
|
||||
var HYPERVISOR_HOSTTYPE = map[string]string{
|
||||
HYPERVISOR_KVM: HOST_TYPE_HYPERVISOR,
|
||||
HYPERVISOR_BAREMETAL: HOST_TYPE_BAREMETAL,
|
||||
HYPERVISOR_ESXI: HOST_TYPE_ESXI,
|
||||
HYPERVISOR_CONTAINER: HOST_TYPE_KUBELET,
|
||||
HYPERVISOR_ALIYUN: HOST_TYPE_ALIYUN,
|
||||
HYPERVISOR_AZURE: HOST_TYPE_AZURE,
|
||||
HYPERVISOR_AWS: HOST_TYPE_AWS,
|
||||
HYPERVISOR_QCLOUD: HOST_TYPE_QCLOUD,
|
||||
HYPERVISOR_HUAWEI: HOST_TYPE_HUAWEI,
|
||||
HYPERVISOR_OPENSTACK: HOST_TYPE_OPENSTACK,
|
||||
HYPERVISOR_UCLOUD: HOST_TYPE_UCLOUD,
|
||||
}
|
||||
|
||||
var HOSTTYPE_HYPERVISOR = map[string]string{
|
||||
HOST_TYPE_HYPERVISOR: HYPERVISOR_KVM,
|
||||
HOST_TYPE_BAREMETAL: HYPERVISOR_BAREMETAL,
|
||||
HOST_TYPE_ESXI: HYPERVISOR_ESXI,
|
||||
HOST_TYPE_KUBELET: HYPERVISOR_CONTAINER,
|
||||
HOST_TYPE_ALIYUN: HYPERVISOR_ALIYUN,
|
||||
HOST_TYPE_AZURE: HYPERVISOR_AZURE,
|
||||
HOST_TYPE_AWS: HYPERVISOR_AWS,
|
||||
HOST_TYPE_QCLOUD: HYPERVISOR_QCLOUD,
|
||||
HOST_TYPE_HUAWEI: HYPERVISOR_HUAWEI,
|
||||
HOST_TYPE_OPENSTACK: HYPERVISOR_OPENSTACK,
|
||||
HOST_TYPE_UCLOUD: HYPERVISOR_UCLOUD,
|
||||
}
|
||||
+52
-287
@@ -4,96 +4,67 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
o "yunion.io/x/onecloud/pkg/baremetal/options"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/pxe"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/agent"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
)
|
||||
|
||||
const (
|
||||
AGENT_TYPE_BAREMETAL = "baremetal"
|
||||
)
|
||||
|
||||
var (
|
||||
baremetalAgent *SBaremetalAgent
|
||||
)
|
||||
|
||||
type SZone struct {
|
||||
Name string `json:"name"`
|
||||
Id string `json:"id"`
|
||||
}
|
||||
|
||||
type SBaremetalAgent struct {
|
||||
PXEServer *pxe.Server
|
||||
ListenInterface *net.Interface
|
||||
AgentId string
|
||||
AgentName string
|
||||
Zone *SZone
|
||||
Manager *SBaremetalManager
|
||||
agent.SBaseAgent
|
||||
|
||||
PXEServer *pxe.Server
|
||||
Manager *SBaremetalManager
|
||||
}
|
||||
|
||||
func newBaremetalAgent() (*SBaremetalAgent, error) {
|
||||
iface, err := net.InterfaceByName(o.Options.ListenInterface)
|
||||
agent := &SBaremetalAgent{}
|
||||
err := agent.Init(agent, o.Options.ListenInterface)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ips, err := getIfaceIPs(iface)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ips) == 0 {
|
||||
return nil, fmt.Errorf("Interface %s ip address not found", o.Options.ListenInterface)
|
||||
}
|
||||
log.Debugf("Interface %s ip address: %v", iface.Name, ips)
|
||||
|
||||
agent := &SBaremetalAgent{
|
||||
ListenInterface: iface,
|
||||
}
|
||||
return agent, nil
|
||||
}
|
||||
|
||||
func GetAdminSession() *mcclient.ClientSession {
|
||||
func (agent *SBaremetalAgent) GetAgentType() string {
|
||||
return AGENT_TYPE_BAREMETAL
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) GetPort() int {
|
||||
return o.Options.Port
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) GetEnableSsl() bool {
|
||||
return o.Options.EnableSsl
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) GetZoneName() string {
|
||||
return o.Options.Zone
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) GetAdminSession() *mcclient.ClientSession {
|
||||
return auth.GetAdminSession(context.TODO(), o.Options.Region, "v2")
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) GetListenIPs() ([]net.IP, error) {
|
||||
ips, err := getIfaceIPs(agent.ListenInterface)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ips) == 0 {
|
||||
return nil, fmt.Errorf("Interface %s ip address not found", agent.ListenInterface.Name)
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) GetListenIP() (net.IP, error) {
|
||||
ips, err := agent.GetListenIPs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.Options.ListenAddress == "" {
|
||||
return ips[0], nil
|
||||
}
|
||||
if o.Options.ListenAddress == "0.0.0.0" {
|
||||
return net.ParseIP(o.Options.ListenAddress), nil
|
||||
}
|
||||
for _, ip := range ips {
|
||||
if ip.String() == o.Options.ListenAddress {
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Not found ListenAddress %s on %s", o.Options.ListenAddress, o.Options.ListenInterface)
|
||||
return agent.FindListenIP(o.Options.ListenAddress)
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) GetDHCPServerListenIP() (net.IP, error) {
|
||||
ips, err := agent.GetListenIPs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ips := agent.GetListenIPs()
|
||||
|
||||
// baremetal dhcp server can't bind address 0.0.0.0:67, conflict with host agent
|
||||
// but can bind specific ip address, because socket set reuseaddr option
|
||||
@@ -109,19 +80,7 @@ func (agent *SBaremetalAgent) GetDHCPServerListenIP() (net.IP, error) {
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) GetAccessIP() (net.IP, error) {
|
||||
ips, err := agent.GetListenIPs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.Options.AccessAddress == "" {
|
||||
return ips[0], nil
|
||||
}
|
||||
for _, ip := range ips {
|
||||
if ip.String() == o.Options.AccessAddress {
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Not found AccessAddress %s on %s", o.Options.AccessAddress, o.Options.ListenInterface)
|
||||
return agent.FindAccessIP(o.Options.AccessAddress)
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) GetDHCPServerIP() (net.IP, error) {
|
||||
@@ -132,60 +91,7 @@ func (agent *SBaremetalAgent) GetDHCPServerIP() (net.IP, error) {
|
||||
return agent.GetListenIP()
|
||||
}
|
||||
|
||||
func getIfaceIPs(iface *net.Interface) ([]net.IP, error) {
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ips := make([]net.IP, 0)
|
||||
for _, a := range addrs {
|
||||
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||
if ipnet.IP.To4() != nil {
|
||||
ips = append(ips, ipnet.IP)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) startRegister() {
|
||||
if agent.AgentId != "" {
|
||||
return
|
||||
}
|
||||
|
||||
var delayRetryTime time.Duration = 30 * time.Second
|
||||
|
||||
for {
|
||||
err := agent.register()
|
||||
if err != nil {
|
||||
log.Errorf("Register error: %v, retry after %s...", err, delayRetryTime)
|
||||
time.Sleep(delayRetryTime)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) register() error {
|
||||
session := GetAdminSession()
|
||||
var err error
|
||||
err = agent.fetchZone(session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = agent.createOrUpdateBaremetalAgent(session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("Baremetal %s:%s register success, do offline", agent.AgentName, agent.AgentId)
|
||||
err = agent.doOffline(session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
agent.tuneSystem()
|
||||
|
||||
func (agent *SBaremetalAgent) StartService() error {
|
||||
manager, err := NewBaremetalManager(agent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("New baremetal manager error: %v", err)
|
||||
@@ -198,6 +104,15 @@ func (agent *SBaremetalAgent) register() error {
|
||||
|
||||
agent.Manager = manager
|
||||
agent.startPXEServices(manager)
|
||||
|
||||
agent.DoOnline(agent.GetAdminSession())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) StopService() error {
|
||||
if agent.Manager != nil {
|
||||
agent.Manager.Stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -205,167 +120,9 @@ func (agent *SBaremetalAgent) GetManager() *SBaremetalManager {
|
||||
return agent.Manager
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) getZoneByIP(session *mcclient.ClientSession) (jsonutils.JSONObject, error) {
|
||||
params := jsonutils.NewDict()
|
||||
listenIP, err := agent.GetListenIP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Add(jsonutils.NewString(listenIP.String()), "ip")
|
||||
networks, err := modules.Networks.List(session, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(networks.Data) == 0 {
|
||||
return nil, fmt.Errorf("Not found networks by agent listen ip: %s", listenIP)
|
||||
}
|
||||
wireId, err := networks.Data[0].GetString("wire_id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wire, err := modules.Wires.Get(session, wireId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zoneId, err := wire.GetString("zone_id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
zone, err := modules.Zones.Get(session, zoneId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return zone, nil
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) fetchZone(session *mcclient.ClientSession) error {
|
||||
zoneName := o.Options.Zone
|
||||
var zoneInfoObj jsonutils.JSONObject
|
||||
var err error
|
||||
if zoneName != "" {
|
||||
zoneInfoObj, err = modules.Zones.Get(session, zoneName, nil)
|
||||
} else {
|
||||
zoneInfoObj, err = agent.getZoneByIP(session)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
zone := SZone{}
|
||||
err = zoneInfoObj.Unmarshal(&zone)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
agent.Zone = &zone
|
||||
return nil
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) createOrUpdateBaremetalAgent(session *mcclient.ClientSession) error {
|
||||
params := jsonutils.NewDict()
|
||||
naccessIP, err := agent.GetAccessIP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params.Add(jsonutils.NewString(naccessIP.String()), "access_ip")
|
||||
ret, err := modules.Baremetalagents.List(session, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var (
|
||||
cloudObj jsonutils.JSONObject
|
||||
agentId string
|
||||
agentName string
|
||||
)
|
||||
// create or update BaremetalAgent
|
||||
if len(ret.Data) == 0 {
|
||||
cloudObj, err = agent.createBaremetalAgent(session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
cloudBmAgent := ret.Data[0]
|
||||
accessIP, _ := cloudBmAgent.GetString("access_ip")
|
||||
managerUri, _ := cloudBmAgent.GetString("manager_uri")
|
||||
zoneId, _ := cloudBmAgent.GetString("zone_id")
|
||||
agentId, _ := cloudBmAgent.GetString("id")
|
||||
if naccessIP.String() != accessIP ||
|
||||
agent.GetManagerUri() != managerUri ||
|
||||
zoneId != agent.Zone.Id {
|
||||
cloudObj, err = agent.updateBaremetalAgent(session, agentId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
cloudObj = cloudBmAgent
|
||||
}
|
||||
}
|
||||
|
||||
agentId, err = cloudObj.GetString("id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
agentName, err = cloudObj.GetString("name")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
agent.AgentId = agentId
|
||||
agent.AgentName = agentName
|
||||
return nil
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) GetManagerUri() string {
|
||||
accessIP, _ := agent.GetAccessIP()
|
||||
proto := "http"
|
||||
if o.Options.EnableSsl {
|
||||
proto = "https"
|
||||
}
|
||||
return fmt.Sprintf("%s://%s:%d", proto, accessIP, o.Options.Port)
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) getCreateUpdateInfo() (jsonutils.JSONObject, error) {
|
||||
accessIP, err := agent.GetAccessIP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params := jsonutils.NewDict()
|
||||
if agent.AgentId == "" {
|
||||
params.Add(jsonutils.NewString(fmt.Sprintf("baremetal_%s", accessIP)), "name")
|
||||
}
|
||||
params.Add(jsonutils.NewString(accessIP.String()), "access_ip")
|
||||
params.Add(jsonutils.NewString(agent.GetManagerUri()), "manager_uri")
|
||||
params.Add(jsonutils.NewString(agent.Zone.Id), "zone_id")
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) createBaremetalAgent(session *mcclient.ClientSession) (jsonutils.JSONObject, error) {
|
||||
params, err := agent.getCreateUpdateInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return modules.Baremetalagents.Create(session, params)
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) updateBaremetalAgent(session *mcclient.ClientSession, id string) (jsonutils.JSONObject, error) {
|
||||
params, err := agent.getCreateUpdateInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return modules.Baremetalagents.Update(session, id, params)
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) doOffline(session *mcclient.ClientSession) error {
|
||||
_, err := modules.Baremetalagents.PerformAction(session, agent.AgentId, "offline", nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) doOnline(session *mcclient.ClientSession) error {
|
||||
_, err := modules.Baremetalagents.PerformAction(session, agent.AgentId, "online", nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) tuneSystem() {
|
||||
func (agent *SBaremetalAgent) TuneSystem() error {
|
||||
agent.disableUDPOffloading()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (agent *SBaremetalAgent) disableUDPOffloading() {
|
||||
@@ -409,8 +166,16 @@ func Start() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
baremetalAgent.startRegister()
|
||||
return baremetalAgent.Start()
|
||||
}
|
||||
|
||||
func Stop() error {
|
||||
if baremetalAgent != nil {
|
||||
log.Infof("baremetalAgent stop ...")
|
||||
tmpAgent := baremetalAgent
|
||||
baremetalAgent = nil
|
||||
tmpAgent.Stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ func (m *SBaremetalManager) killAllIPMITool() {
|
||||
}
|
||||
|
||||
func (m *SBaremetalManager) GetClientSession() *mcclient.ClientSession {
|
||||
return GetAdminSession()
|
||||
return m.Agent.GetAdminSession()
|
||||
}
|
||||
|
||||
func (m *SBaremetalManager) GetZoneId() string {
|
||||
|
||||
@@ -31,6 +31,7 @@ func (s *BaremetalService) StartService() {
|
||||
|
||||
app_common.ServeForeverWithCleanup(app, &o.Options.CommonOptions, func() {
|
||||
tasks.OnStop()
|
||||
baremetal.Stop()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
type IAgent interface {
|
||||
GetAgentType() string
|
||||
GetAccessIP() (net.IP, error)
|
||||
GetListenIP() (net.IP, error)
|
||||
GetPort() int
|
||||
GetEnableSsl() bool
|
||||
GetZoneName() string
|
||||
GetAdminSession() *mcclient.ClientSession
|
||||
TuneSystem() error
|
||||
StartService() error
|
||||
StopService() error
|
||||
}
|
||||
|
||||
type SZoneInfo struct {
|
||||
Name string `json:"name"`
|
||||
Id string `json:"id"`
|
||||
}
|
||||
|
||||
type SBaseAgent struct {
|
||||
virtual interface{}
|
||||
|
||||
ListenInterface *net.Interface
|
||||
ListenIPs []net.IP
|
||||
AgentId string
|
||||
AgentName string
|
||||
Zone *SZoneInfo
|
||||
|
||||
stop bool
|
||||
}
|
||||
|
||||
func getIfaceIPs(iface *net.Interface) ([]net.IP, error) {
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ips := make([]net.IP, 0)
|
||||
for _, a := range addrs {
|
||||
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||
if ipnet.IP.To4() != nil {
|
||||
ips = append(ips, ipnet.IP)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) IAgent() IAgent {
|
||||
return agent.virtual.(IAgent)
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) Init(iagent IAgent, ifname string) error {
|
||||
iface, err := net.InterfaceByName(ifname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var ips []net.IP
|
||||
MAX := 60
|
||||
wait := 0
|
||||
for wait < MAX {
|
||||
ips, err = getIfaceIPs(iface)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ips) == 0 {
|
||||
time.Sleep(2 * time.Second)
|
||||
wait += 2
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(ips) == 0 {
|
||||
return fmt.Errorf("Interface %s ip address not found", ifname)
|
||||
}
|
||||
log.Debugf("Interface %s ip address: %v", iface.Name, ips)
|
||||
agent.virtual = iagent
|
||||
agent.ListenInterface = iface
|
||||
agent.ListenIPs = ips
|
||||
return nil
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) GetListenIPs() []net.IP {
|
||||
return agent.ListenIPs
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) FindListenIP(listenAddr string) (net.IP, error) {
|
||||
ips := agent.GetListenIPs()
|
||||
if listenAddr == "" {
|
||||
return ips[0], nil
|
||||
}
|
||||
if listenAddr == "0.0.0.0" {
|
||||
return net.ParseIP(listenAddr), nil
|
||||
}
|
||||
for _, ip := range ips {
|
||||
if ip.String() == listenAddr {
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Not found Address %s on Interface %s", listenAddr, agent.ListenInterface)
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) FindAccessIP(accessAddr string) (net.IP, error) {
|
||||
if accessAddr == "0.0.0.0" {
|
||||
return nil, fmt.Errorf("Access address must be specific, should not be 0.0.0.0")
|
||||
}
|
||||
return agent.FindListenIP(accessAddr)
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) startRegister() error {
|
||||
// if agent.AgentId != "" {
|
||||
// return
|
||||
// }
|
||||
|
||||
var delayRetryTime = 30 * time.Second
|
||||
var lastTry time.Time
|
||||
|
||||
for !agent.stop {
|
||||
if time.Now().Sub(lastTry) >= delayRetryTime {
|
||||
session := agent.IAgent().GetAdminSession()
|
||||
err := agent.register(session)
|
||||
if err == nil {
|
||||
log.Infof("Register success!")
|
||||
return nil
|
||||
}
|
||||
log.Errorf("Register error: %v, retry after %s...", err, delayRetryTime)
|
||||
lastTry = time.Now()
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
return fmt.Errorf("Error Stop")
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) register(session *mcclient.ClientSession) error {
|
||||
var err error
|
||||
err = agent.fetchZone(session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = agent.createOrUpdateBaremetalAgent(session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("%s %s:%s register success, do offline", agent.IAgent().GetAgentType(), agent.AgentName, agent.AgentId)
|
||||
err = agent.doOffline(session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) fetchZone(session *mcclient.ClientSession) error {
|
||||
zoneName := agent.IAgent().GetZoneName()
|
||||
var zoneInfoObj jsonutils.JSONObject
|
||||
var err error
|
||||
if zoneName != "" {
|
||||
zoneInfoObj, err = modules.Zones.Get(session, zoneName, nil)
|
||||
} else {
|
||||
zoneInfoObj, err = agent.getZoneByIP(session)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
zone := SZoneInfo{}
|
||||
err = zoneInfoObj.Unmarshal(&zone)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
agent.Zone = &zone
|
||||
return nil
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) getZoneByIP(session *mcclient.ClientSession) (jsonutils.JSONObject, error) {
|
||||
params := jsonutils.NewDict()
|
||||
listenIP, err := agent.IAgent().GetListenIP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Add(jsonutils.NewString(listenIP.String()), "ip")
|
||||
params.Add(jsonutils.JSONTrue, "is_on_premise")
|
||||
networks, err := modules.Networks.List(session, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(networks.Data) == 0 {
|
||||
return nil, fmt.Errorf("Not found networks by agent listen ip: %s", listenIP)
|
||||
}
|
||||
wireId, err := networks.Data[0].GetString("wire_id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wire, err := modules.Wires.Get(session, wireId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zoneId, err := wire.GetString("zone_id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
zone, err := modules.Zones.Get(session, zoneId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return zone, nil
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) createOrUpdateBaremetalAgent(session *mcclient.ClientSession) error {
|
||||
params := jsonutils.NewDict()
|
||||
naccessIP, err := agent.IAgent().GetAccessIP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params.Add(jsonutils.NewString(naccessIP.String()), "access_ip")
|
||||
params.Add(jsonutils.NewString(agent.IAgent().GetAgentType()), "agent_type")
|
||||
ret, err := modules.Baremetalagents.List(session, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var (
|
||||
cloudObj jsonutils.JSONObject
|
||||
agentId string
|
||||
agentName string
|
||||
)
|
||||
// create or update BaremetalAgent
|
||||
if len(ret.Data) == 0 {
|
||||
cloudObj, err = agent.createBaremetalAgent(session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
cloudBmAgent := ret.Data[0]
|
||||
accessIP, _ := cloudBmAgent.GetString("access_ip")
|
||||
managerUri, _ := cloudBmAgent.GetString("manager_uri")
|
||||
zoneId, _ := cloudBmAgent.GetString("zone_id")
|
||||
agentId, _ := cloudBmAgent.GetString("id")
|
||||
if naccessIP.String() != accessIP ||
|
||||
agent.GetManagerUri() != managerUri ||
|
||||
zoneId != agent.Zone.Id {
|
||||
cloudObj, err = agent.updateBaremetalAgent(session, agentId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
cloudObj = cloudBmAgent
|
||||
}
|
||||
}
|
||||
|
||||
agentId, err = cloudObj.GetString("id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
agentName, err = cloudObj.GetString("name")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
agent.AgentId = agentId
|
||||
agent.AgentName = agentName
|
||||
return nil
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) GetManagerUri() string {
|
||||
accessIP, _ := agent.IAgent().GetAccessIP()
|
||||
proto := "http"
|
||||
if agent.IAgent().GetEnableSsl() {
|
||||
proto = "https"
|
||||
}
|
||||
return fmt.Sprintf("%s://%s:%d", proto, accessIP, agent.IAgent().GetPort())
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) getCreateUpdateInfo() (jsonutils.JSONObject, error) {
|
||||
accessIP, err := agent.IAgent().GetAccessIP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params := jsonutils.NewDict()
|
||||
if agent.AgentId == "" {
|
||||
params.Add(jsonutils.NewString(fmt.Sprintf("%s_%s", agent.IAgent().GetAgentType(), accessIP)), "name")
|
||||
}
|
||||
params.Add(jsonutils.NewString(accessIP.String()), "access_ip")
|
||||
params.Add(jsonutils.NewString(agent.GetManagerUri()), "manager_uri")
|
||||
params.Add(jsonutils.NewString(agent.Zone.Id), "zone_id")
|
||||
params.Add(jsonutils.NewString(agent.IAgent().GetAgentType()), "agent_type")
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) createBaremetalAgent(session *mcclient.ClientSession) (jsonutils.JSONObject, error) {
|
||||
params, err := agent.getCreateUpdateInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return modules.Baremetalagents.Create(session, params)
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) updateBaremetalAgent(session *mcclient.ClientSession, id string) (jsonutils.JSONObject, error) {
|
||||
params, err := agent.getCreateUpdateInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return modules.Baremetalagents.Update(session, id, params)
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) doOffline(session *mcclient.ClientSession) error {
|
||||
_, err := modules.Baremetalagents.PerformAction(session, agent.AgentId, "offline", nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) DoOnline(session *mcclient.ClientSession) error {
|
||||
_, err := modules.Baremetalagents.PerformAction(session, agent.AgentId, "online", nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) Start() error {
|
||||
err := agent.startRegister()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
agent.IAgent().TuneSystem()
|
||||
return agent.IAgent().StartService()
|
||||
}
|
||||
|
||||
func (agent *SBaseAgent) Stop() {
|
||||
agent.stop = true
|
||||
agent.IAgent().StopService()
|
||||
}
|
||||
@@ -310,6 +310,9 @@ func FetchScheduleInputByJSON(obj jsonutils.JSONObject) (*scheduler.ScheduleInpu
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if obj.Contains("scheduler") {
|
||||
obj, _ = obj.Get("scheduler")
|
||||
}
|
||||
conf := &input.ServerConfig
|
||||
conf.ServerConfigs, err = FetchServerConfigsByJSON(obj)
|
||||
if err != nil {
|
||||
|
||||
@@ -23,9 +23,10 @@ func TestFetchServerConfigsByJSON(t *testing.T) {
|
||||
args: args{jsonutils.Marshal(map[string]string{
|
||||
"disk.0": "1g:centos",
|
||||
"net.0": "192.168.222.3:inf0",
|
||||
"net.1": "[random]",
|
||||
"schedtag.0": "ssd:require",
|
||||
"schedtag.1": "container:exclude",
|
||||
"isolated_device.0": "vendor=nvidia:p400",
|
||||
"isolated_device.0": "vendor=NVIDIA:GeForce GTX 1050 Ti",
|
||||
"baremetal_disk_config.0": "raid0:[1,2]",
|
||||
})},
|
||||
want: &compute.ServerConfigs{
|
||||
@@ -42,6 +43,10 @@ func TestFetchServerConfigsByJSON(t *testing.T) {
|
||||
Network: "inf0",
|
||||
Address: "192.168.222.3",
|
||||
},
|
||||
{
|
||||
Index: 1,
|
||||
Exit: false,
|
||||
},
|
||||
},
|
||||
Schedtags: []*compute.SchedtagConfig{
|
||||
{
|
||||
@@ -55,8 +60,8 @@ func TestFetchServerConfigsByJSON(t *testing.T) {
|
||||
},
|
||||
IsolatedDevices: []*compute.IsolatedDeviceConfig{
|
||||
{
|
||||
Vendor: "nvidia",
|
||||
Model: "p400",
|
||||
Vendor: "NVIDIA",
|
||||
Model: "GeForce GTX 1050 Ti",
|
||||
},
|
||||
},
|
||||
BaremetalDiskConfigs: []*compute.BaremetalDiskConfig{
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/conditionparser"
|
||||
"yunion.io/x/onecloud/pkg/util/hashcache"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
@@ -148,6 +147,7 @@ func (manager *SPolicyManager) SyncOnce() error {
|
||||
manager.adminPolicies = adminPolicies
|
||||
|
||||
manager.lastSync = time.Now()
|
||||
manager.cache.Invalidate()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -231,27 +231,21 @@ func (manager *SPolicyManager) allowWithoutCache(isAdmin bool, userCred mcclient
|
||||
log.Warningf("no policies fetched")
|
||||
return rbacutils.Deny
|
||||
}
|
||||
var userCredJson jsonutils.JSONObject
|
||||
if userCred != nil {
|
||||
userCredJson = userCred.ToJson()
|
||||
} else {
|
||||
userCredJson = jsonutils.NewDict()
|
||||
}
|
||||
currentPriv := rbacutils.Deny
|
||||
for _, p := range policies {
|
||||
result := p.Allow(userCredJson, service, resource, action, extra...)
|
||||
result := p.Allow(userCred, service, resource, action, extra...)
|
||||
if currentPriv.StricterThan(result) {
|
||||
currentPriv = result
|
||||
}
|
||||
}
|
||||
if !isAdmin && manager.defaultPolicy != nil {
|
||||
result := manager.defaultPolicy.Allow(userCredJson, service, resource, action, extra...)
|
||||
result := manager.defaultPolicy.Allow(userCred, service, resource, action, extra...)
|
||||
if currentPriv.StricterThan(result) {
|
||||
currentPriv = result
|
||||
}
|
||||
}
|
||||
if consts.IsRbacDebug() {
|
||||
log.Debugf("[RBAC: %v] %s %s %s %#v permission %s userCred: %s", isAdmin, service, resource, action, extra, currentPriv, userCredJson)
|
||||
log.Debugf("[RBAC: %v] %s %s %s %#v permission %s userCred: %s", isAdmin, service, resource, action, extra, currentPriv, userCred)
|
||||
}
|
||||
return unifyRbacResult(isAdmin, currentPriv)
|
||||
}
|
||||
@@ -365,12 +359,26 @@ func (manager *SPolicyManager) IsAdminCapable(userCred mcclient.TokenCredential)
|
||||
return true
|
||||
}
|
||||
|
||||
userCredJson := userCred.ToJson()
|
||||
for _, p := range manager.adminPolicies {
|
||||
match, _ := conditionparser.Eval(p.Condition, userCredJson)
|
||||
if match {
|
||||
if p.Match(userCred) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (manager *SPolicyManager) MatchedPolicies(isAdmin bool, userCred mcclient.TokenCredential) []string {
|
||||
var policies map[string]rbacutils.SRbacPolicy
|
||||
if isAdmin {
|
||||
policies = manager.adminPolicies
|
||||
} else {
|
||||
policies = manager.policies
|
||||
}
|
||||
ret := make([]string, 0)
|
||||
for k, p := range policies {
|
||||
if p.Match(userCred) {
|
||||
ret = append(ret, k)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -268,3 +268,7 @@ func (self *SBaseGuestDriver) GetLinuxDefaultAccount(desc cloudprovider.SManaged
|
||||
func (self *SBaseGuestDriver) OnGuestChangeCpuMemFailed(ctx context.Context, guest *models.SGuest, data *jsonutils.JSONDict, task taskman.ITask) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestSyncConfigOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
|
||||
return fmt.Errorf("SBaseGuestDriver: Not Implement")
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ func (self *SESXiGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
return options.Options.DefaultDiskSizeMB / 1024
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) RequestSyncConfigOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
// func (self *SESXiGuestDriver) RequestSyncConfigOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
|
||||
// task.ScheduleRun(nil)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (self *SESXiGuestDriver) GetMaxSecurityGroupCount() int {
|
||||
//暂不支持绑定安全组
|
||||
@@ -49,11 +49,11 @@ func (self *SESXiGuestDriver) GetMaxSecurityGroupCount() int {
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) GetDetachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY}, nil
|
||||
return []string{models.VM_READY, models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) GetAttachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY}, nil
|
||||
return []string{models.VM_READY, models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) GetChangeConfigStatus() ([]string, error) {
|
||||
@@ -64,14 +64,14 @@ func (self *SESXiGuestDriver) CanKeepDetachDisk() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) RequestDeleteDetachedDisk(ctx context.Context, disk *models.SDisk, task taskman.ITask, isPurge bool) error {
|
||||
err := disk.RealDelete(ctx, task.GetUserCred())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
// func (self *SESXiGuestDriver) RequestDeleteDetachedDisk(ctx context.Context, disk *models.SDisk, task taskman.ITask, isPurge bool) error {
|
||||
// err := disk.RealDelete(ctx, task.GetUserCred())
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// task.ScheduleRun(nil)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (self *SESXiGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, task taskman.ITask) error {
|
||||
task.ScheduleRun(nil)
|
||||
|
||||
@@ -717,7 +717,7 @@ func (self *SManagedVirtualizedGuestDriver) RequestSyncConfigOnHost(ctx context.
|
||||
return nil, err
|
||||
}
|
||||
for _, disk := range removed {
|
||||
if err := iVM.DetachDisk(ctx, disk.GetId()); err != nil {
|
||||
if err := iVM.DetachDisk(ctx, disk.GetGlobalId()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -731,53 +731,6 @@ func (self *SManagedVirtualizedGuestDriver) RequestSyncConfigOnHost(ctx context.
|
||||
return nil
|
||||
}
|
||||
|
||||
/*func (self *SManagedVirtualizedGuestDriver) RequestSyncConfigOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
if ihost, err := host.GetIHost(); err != nil {
|
||||
return nil, err
|
||||
} else if iVM, err := ihost.GetIVMById(guest.ExternalId); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if fw_only, _ := task.GetParams().Bool("fw_only"); fw_only {
|
||||
if err := iVM.SyncSecurityGroup(guest.SecgrpId, guest.GetSecgroupName(), guest.GetSecRules()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if iDisks, err := iVM.GetIDisks(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
disks := make([]models.SDisk, 0)
|
||||
for _, guestdisk := range guest.GetDisks() {
|
||||
disk := guestdisk.GetDisk()
|
||||
disks = append(disks, *disk)
|
||||
}
|
||||
|
||||
added := make([]models.SDisk, 0)
|
||||
commondb := make([]models.SDisk, 0)
|
||||
commonext := make([]cloudprovider.ICloudDisk, 0)
|
||||
removed := make([]cloudprovider.ICloudDisk, 0)
|
||||
|
||||
if err := compare.CompareSets(disks, iDisks, &added, &commondb, &commonext, &removed); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, disk := range removed {
|
||||
if err := iVM.DetachDisk(ctx, disk.GetId()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for _, disk := range added {
|
||||
if err := iVM.AttachDisk(ctx, disk.ExternalId); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
return nil
|
||||
}*/
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) RequestRenewInstance(guest *models.SGuest, bc billing.SBillingCycle) (time.Time, error) {
|
||||
iVM, err := guest.GetIVM()
|
||||
if err != nil {
|
||||
|
||||
+137
-152
@@ -41,170 +41,127 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
VM_INIT = "init"
|
||||
VM_UNKNOWN = "unknown"
|
||||
VM_SCHEDULE = "schedule"
|
||||
VM_SCHEDULE_FAILED = "sched_fail"
|
||||
VM_CREATE_NETWORK = "network"
|
||||
VM_NETWORK_FAILED = "net_fail"
|
||||
VM_DEVICE_FAILED = "dev_fail"
|
||||
VM_CREATE_FAILED = "create_fail"
|
||||
VM_CREATE_DISK = "disk"
|
||||
VM_DISK_FAILED = "disk_fail"
|
||||
VM_START_DEPLOY = "start_deploy"
|
||||
VM_DEPLOYING = "deploying"
|
||||
VM_DEPLOY_FAILED = "deploy_fail"
|
||||
VM_READY = "ready"
|
||||
VM_START_START = "start_start"
|
||||
VM_STARTING = "starting"
|
||||
VM_START_FAILED = "start_fail" // # = ready
|
||||
VM_RUNNING = "running"
|
||||
VM_START_STOP = "start_stop"
|
||||
VM_STOPPING = "stopping"
|
||||
VM_STOP_FAILED = "stop_fail" // # = running
|
||||
VM_INIT = api.VM_INIT
|
||||
VM_UNKNOWN = api.VM_UNKNOWN
|
||||
VM_SCHEDULE = api.VM_SCHEDULE
|
||||
VM_SCHEDULE_FAILED = api.VM_SCHEDULE_FAILED
|
||||
VM_CREATE_NETWORK = api.VM_CREATE_NETWORK
|
||||
VM_NETWORK_FAILED = api.VM_NETWORK_FAILED
|
||||
VM_DEVICE_FAILED = api.VM_DEVICE_FAILED
|
||||
VM_CREATE_FAILED = api.VM_CREATE_FAILED
|
||||
VM_CREATE_DISK = api.VM_CREATE_DISK
|
||||
VM_DISK_FAILED = api.VM_DISK_FAILED
|
||||
VM_START_DEPLOY = api.VM_START_DEPLOY
|
||||
VM_DEPLOYING = api.VM_DEPLOYING
|
||||
VM_DEPLOY_FAILED = api.VM_DEPLOY_FAILED
|
||||
VM_READY = api.VM_READY
|
||||
VM_START_START = api.VM_START_START
|
||||
VM_STARTING = api.VM_STARTING
|
||||
VM_START_FAILED = api.VM_START_FAILED // # = ready
|
||||
VM_RUNNING = api.VM_RUNNING
|
||||
VM_START_STOP = api.VM_START_STOP
|
||||
VM_STOPPING = api.VM_STOPPING
|
||||
VM_STOP_FAILED = api.VM_STOP_FAILED // # = running
|
||||
|
||||
VM_BACKUP_STARTING = "backup_starting"
|
||||
VM_BACKUP_CREATING = "backup_creating"
|
||||
VM_BACKUP_CREATE_FAILED = "backup_create_fail"
|
||||
VM_DEPLOYING_BACKUP = "deploying_backup"
|
||||
VM_DEPLOYING_BACKUP_FAILED = "deploging_backup_fail"
|
||||
VM_DELETING_BACKUP = "deleting_backup"
|
||||
VM_BACKUP_DELETE_FAILED = "backup_delete_fail"
|
||||
VM_SWITCH_TO_BACKUP = "switch_to_backup"
|
||||
VM_SWITCH_TO_BACKUP_FAILED = "switch_to_backup_fail"
|
||||
VM_BACKUP_STARTING = api.VM_BACKUP_STARTING
|
||||
VM_BACKUP_CREATING = api.VM_BACKUP_CREATING
|
||||
VM_BACKUP_CREATE_FAILED = api.VM_BACKUP_CREATE_FAILED
|
||||
VM_DEPLOYING_BACKUP = api.VM_DEPLOYING_BACKUP
|
||||
VM_DEPLOYING_BACKUP_FAILED = api.VM_DEPLOYING_BACKUP_FAILED
|
||||
VM_DELETING_BACKUP = api.VM_DELETING_BACKUP
|
||||
VM_BACKUP_DELETE_FAILED = api.VM_BACKUP_DELETE_FAILED
|
||||
VM_SWITCH_TO_BACKUP = api.VM_SWITCH_TO_BACKUP
|
||||
VM_SWITCH_TO_BACKUP_FAILED = api.VM_SWITCH_TO_BACKUP_FAILED
|
||||
|
||||
VM_ATTACH_DISK_FAILED = "attach_disk_fail"
|
||||
VM_DETACH_DISK_FAILED = "detach_disk_fail"
|
||||
VM_ATTACH_DISK_FAILED = api.VM_ATTACH_DISK_FAILED
|
||||
VM_DETACH_DISK_FAILED = api.VM_DETACH_DISK_FAILED
|
||||
|
||||
VM_START_SUSPEND = "start_suspend"
|
||||
VM_SUSPENDING = "suspending"
|
||||
VM_SUSPEND = "suspend"
|
||||
VM_SUSPEND_FAILED = "suspend_failed"
|
||||
VM_START_SUSPEND = api.VM_START_SUSPEND
|
||||
VM_SUSPENDING = api.VM_SUSPENDING
|
||||
VM_SUSPEND = api.VM_SUSPEND
|
||||
VM_SUSPEND_FAILED = api.VM_SUSPEND_FAILED
|
||||
|
||||
VM_START_DELETE = "start_delete"
|
||||
VM_DELETE_FAIL = "delete_fail"
|
||||
VM_DELETING = "deleting"
|
||||
VM_START_DELETE = api.VM_START_DELETE
|
||||
VM_DELETE_FAIL = api.VM_DELETE_FAIL
|
||||
VM_DELETING = api.VM_DELETING
|
||||
|
||||
VM_DEALLOCATED = "deallocated"
|
||||
VM_DEALLOCATED = api.VM_DEALLOCATED
|
||||
|
||||
VM_START_MIGRATE = "start_migrate"
|
||||
VM_MIGRATING = "migrating"
|
||||
VM_MIGRATE_FAILED = "migrate_failed"
|
||||
VM_START_MIGRATE = api.VM_START_MIGRATE
|
||||
VM_MIGRATING = api.VM_MIGRATING
|
||||
VM_MIGRATE_FAILED = api.VM_MIGRATE_FAILED
|
||||
|
||||
VM_CHANGE_FLAVOR = "change_flavor"
|
||||
VM_CHANGE_FLAVOR_FAIL = "change_flavor_fail"
|
||||
VM_REBUILD_ROOT = "rebuild_root"
|
||||
VM_REBUILD_ROOT_FAIL = "rebuild_root_fail"
|
||||
VM_CHANGE_FLAVOR = api.VM_CHANGE_FLAVOR
|
||||
VM_CHANGE_FLAVOR_FAIL = api.VM_CHANGE_FLAVOR_FAIL
|
||||
VM_REBUILD_ROOT = api.VM_REBUILD_ROOT
|
||||
VM_REBUILD_ROOT_FAIL = api.VM_REBUILD_ROOT_FAIL
|
||||
|
||||
VM_START_SNAPSHOT = "snapshot_start"
|
||||
VM_SNAPSHOT = "snapshot"
|
||||
VM_SNAPSHOT_DELETE = "snapshot_delete"
|
||||
VM_BLOCK_STREAM = "block_stream"
|
||||
VM_MIRROR_FAIL = "mirror_failed"
|
||||
VM_SNAPSHOT_SUCC = "snapshot_succ"
|
||||
VM_SNAPSHOT_FAILED = "snapshot_failed"
|
||||
VM_START_SNAPSHOT = api.VM_START_SNAPSHOT
|
||||
VM_SNAPSHOT = api.VM_SNAPSHOT
|
||||
VM_SNAPSHOT_DELETE = api.VM_SNAPSHOT_DELETE
|
||||
VM_BLOCK_STREAM = api.VM_BLOCK_STREAM
|
||||
VM_MIRROR_FAIL = api.VM_MIRROR_FAIL
|
||||
VM_SNAPSHOT_SUCC = api.VM_SNAPSHOT_SUCC
|
||||
VM_SNAPSHOT_FAILED = api.VM_SNAPSHOT_FAILED
|
||||
|
||||
VM_SYNCING_STATUS = "syncing"
|
||||
VM_SYNC_CONFIG = "sync_config"
|
||||
VM_SYNC_FAIL = "sync_fail"
|
||||
VM_SYNCING_STATUS = api.VM_SYNCING_STATUS
|
||||
VM_SYNC_CONFIG = api.VM_SYNC_CONFIG
|
||||
VM_SYNC_FAIL = api.VM_SYNC_FAIL
|
||||
|
||||
VM_RESIZE_DISK = "resize_disk"
|
||||
VM_RESIZE_DISK_FAILED = "resize_disk_fail"
|
||||
VM_START_SAVE_DISK = "start_save_disk"
|
||||
VM_SAVE_DISK = "save_disk"
|
||||
VM_SAVE_DISK_FAILED = "save_disk_failed"
|
||||
VM_RESIZE_DISK = api.VM_RESIZE_DISK
|
||||
VM_RESIZE_DISK_FAILED = api.VM_RESIZE_DISK_FAILED
|
||||
VM_START_SAVE_DISK = api.VM_START_SAVE_DISK
|
||||
VM_SAVE_DISK = api.VM_SAVE_DISK
|
||||
VM_SAVE_DISK_FAILED = api.VM_SAVE_DISK_FAILED
|
||||
|
||||
VM_RESTORING_SNAPSHOT = "restoring_snapshot"
|
||||
VM_RESTORE_DISK = "restore_disk"
|
||||
VM_RESTORE_STATE = "restore_state"
|
||||
VM_RESTORE_FAILED = "restore_failed"
|
||||
VM_RESTORING_SNAPSHOT = api.VM_RESTORING_SNAPSHOT
|
||||
VM_RESTORE_DISK = api.VM_RESTORE_DISK
|
||||
VM_RESTORE_STATE = api.VM_RESTORE_STATE
|
||||
VM_RESTORE_FAILED = api.VM_RESTORE_FAILED
|
||||
|
||||
VM_ASSOCIATE_EIP = "associate_eip"
|
||||
VM_ASSOCIATE_EIP_FAILED = "associate_eip_failed"
|
||||
VM_DISSOCIATE_EIP = "dissociate_eip"
|
||||
VM_DISSOCIATE_EIP_FAILED = "dissociate_eip_failed"
|
||||
VM_ASSOCIATE_EIP = api.VM_ASSOCIATE_EIP
|
||||
VM_ASSOCIATE_EIP_FAILED = api.VM_ASSOCIATE_EIP_FAILED
|
||||
VM_DISSOCIATE_EIP = api.VM_DISSOCIATE_EIP
|
||||
VM_DISSOCIATE_EIP_FAILED = api.VM_DISSOCIATE_EIP_FAILED
|
||||
|
||||
VM_REMOVE_STATEFILE = "remove_state"
|
||||
VM_REMOVE_STATEFILE = api.VM_REMOVE_STATEFILE
|
||||
|
||||
VM_ADMIN = "admin"
|
||||
VM_ADMIN = api.VM_ADMIN
|
||||
|
||||
SHUTDOWN_STOP = "stop"
|
||||
SHUTDOWN_TERMINATE = "terminate"
|
||||
SHUTDOWN_STOP = api.SHUTDOWN_STOP
|
||||
SHUTDOWN_TERMINATE = api.SHUTDOWN_TERMINATE
|
||||
|
||||
HYPERVISOR_KVM = "kvm"
|
||||
HYPERVISOR_CONTAINER = "container"
|
||||
HYPERVISOR_BAREMETAL = "baremetal"
|
||||
HYPERVISOR_ESXI = "esxi"
|
||||
HYPERVISOR_HYPERV = "hyperv"
|
||||
HYPERVISOR_XEN = "xen"
|
||||
HYPERVISOR_KVM = api.HYPERVISOR_KVM
|
||||
HYPERVISOR_CONTAINER = api.HYPERVISOR_CONTAINER
|
||||
HYPERVISOR_BAREMETAL = api.HYPERVISOR_BAREMETAL
|
||||
HYPERVISOR_ESXI = api.HYPERVISOR_ESXI
|
||||
HYPERVISOR_HYPERV = api.HYPERVISOR_HYPERV
|
||||
HYPERVISOR_XEN = api.HYPERVISOR_XEN
|
||||
|
||||
HYPERVISOR_ALIYUN = "aliyun"
|
||||
HYPERVISOR_QCLOUD = "qcloud"
|
||||
HYPERVISOR_AZURE = "azure"
|
||||
HYPERVISOR_AWS = "aws"
|
||||
HYPERVISOR_HUAWEI = "huawei"
|
||||
HYPERVISOR_OPENSTACK = "openstack"
|
||||
HYPERVISOR_UCLOUD = "ucloud"
|
||||
HYPERVISOR_ALIYUN = api.HYPERVISOR_ALIYUN
|
||||
HYPERVISOR_QCLOUD = api.HYPERVISOR_QCLOUD
|
||||
HYPERVISOR_AZURE = api.HYPERVISOR_AZURE
|
||||
HYPERVISOR_AWS = api.HYPERVISOR_AWS
|
||||
HYPERVISOR_HUAWEI = api.HYPERVISOR_HUAWEI
|
||||
HYPERVISOR_OPENSTACK = api.HYPERVISOR_OPENSTACK
|
||||
HYPERVISOR_UCLOUD = api.HYPERVISOR_UCLOUD
|
||||
|
||||
// HYPERVISOR_DEFAULT = HYPERVISOR_KVM
|
||||
HYPERVISOR_DEFAULT = HYPERVISOR_KVM
|
||||
)
|
||||
|
||||
var VM_RUNNING_STATUS = []string{VM_START_START, VM_STARTING, VM_RUNNING, VM_BLOCK_STREAM}
|
||||
var VM_CREATING_STATUS = []string{VM_CREATE_NETWORK, VM_CREATE_DISK, VM_START_DEPLOY, VM_DEPLOYING}
|
||||
var VM_RUNNING_STATUS = api.VM_RUNNING_STATUS
|
||||
var VM_CREATING_STATUS = api.VM_CREATING_STATUS
|
||||
|
||||
var HYPERVISORS = []string{HYPERVISOR_KVM,
|
||||
HYPERVISOR_BAREMETAL,
|
||||
HYPERVISOR_ESXI,
|
||||
HYPERVISOR_CONTAINER,
|
||||
HYPERVISOR_ALIYUN,
|
||||
HYPERVISOR_AZURE,
|
||||
HYPERVISOR_AWS,
|
||||
HYPERVISOR_QCLOUD,
|
||||
HYPERVISOR_HUAWEI,
|
||||
HYPERVISOR_OPENSTACK,
|
||||
HYPERVISOR_UCLOUD,
|
||||
}
|
||||
var HYPERVISORS = api.HYPERVISORS
|
||||
|
||||
var PUBLIC_CLOUD_HYPERVISORS = []string{
|
||||
HYPERVISOR_ALIYUN,
|
||||
HYPERVISOR_AWS,
|
||||
HYPERVISOR_AZURE,
|
||||
HYPERVISOR_QCLOUD,
|
||||
HYPERVISOR_HUAWEI,
|
||||
HYPERVISOR_OPENSTACK,
|
||||
HYPERVISOR_UCLOUD,
|
||||
}
|
||||
var PUBLIC_CLOUD_HYPERVISORS = api.PUBLIC_CLOUD_HYPERVISORS
|
||||
|
||||
// var HYPERVISORS = []string{HYPERVISOR_ALIYUN}
|
||||
|
||||
var HYPERVISOR_HOSTTYPE = map[string]string{
|
||||
HYPERVISOR_KVM: HOST_TYPE_HYPERVISOR,
|
||||
HYPERVISOR_BAREMETAL: HOST_TYPE_BAREMETAL,
|
||||
HYPERVISOR_ESXI: HOST_TYPE_ESXI,
|
||||
HYPERVISOR_CONTAINER: HOST_TYPE_KUBELET,
|
||||
HYPERVISOR_ALIYUN: HOST_TYPE_ALIYUN,
|
||||
HYPERVISOR_AZURE: HOST_TYPE_AZURE,
|
||||
HYPERVISOR_AWS: HOST_TYPE_AWS,
|
||||
HYPERVISOR_QCLOUD: HOST_TYPE_QCLOUD,
|
||||
HYPERVISOR_HUAWEI: HOST_TYPE_HUAWEI,
|
||||
HYPERVISOR_OPENSTACK: HOST_TYPE_OPENSTACK,
|
||||
HYPERVISOR_UCLOUD: HOST_TYPE_UCLOUD,
|
||||
}
|
||||
var HYPERVISOR_HOSTTYPE = api.HYPERVISOR_HOSTTYPE
|
||||
|
||||
var HOSTTYPE_HYPERVISOR = map[string]string{
|
||||
HOST_TYPE_HYPERVISOR: HYPERVISOR_KVM,
|
||||
HOST_TYPE_BAREMETAL: HYPERVISOR_BAREMETAL,
|
||||
HOST_TYPE_ESXI: HYPERVISOR_ESXI,
|
||||
HOST_TYPE_KUBELET: HYPERVISOR_CONTAINER,
|
||||
HOST_TYPE_ALIYUN: HYPERVISOR_ALIYUN,
|
||||
HOST_TYPE_AZURE: HYPERVISOR_AZURE,
|
||||
HOST_TYPE_AWS: HYPERVISOR_AWS,
|
||||
HOST_TYPE_QCLOUD: HYPERVISOR_QCLOUD,
|
||||
HOST_TYPE_HUAWEI: HYPERVISOR_HUAWEI,
|
||||
HOST_TYPE_OPENSTACK: HYPERVISOR_OPENSTACK,
|
||||
HOST_TYPE_UCLOUD: HYPERVISOR_UCLOUD,
|
||||
}
|
||||
var HOSTTYPE_HYPERVISOR = api.HOSTTYPE_HYPERVISOR
|
||||
|
||||
type SGuestManager struct {
|
||||
db.SVirtualResourceBaseManager
|
||||
@@ -356,7 +313,7 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
|
||||
secgrpFilter = secgrpFilter[1:]
|
||||
notIn = true
|
||||
}
|
||||
secgrp, _ := SecurityGroupManager.FetchByIdOrName(nil, secgrpFilter)
|
||||
secgrp, _ := SecurityGroupManager.FetchByIdOrName(userCred, secgrpFilter)
|
||||
if secgrp == nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("secgroup %s not found", secgrpFilter)
|
||||
}
|
||||
@@ -752,32 +709,61 @@ func (guest *SGuest) ValidateResizeDisk(disk *SDisk, storage *SStorage) error {
|
||||
return guest.GetDriver().ValidateResizeDisk(guest, disk, storage)
|
||||
}
|
||||
|
||||
func ValidateMemData(vmemSize int, driver IGuestDriver) (int, error) {
|
||||
if vmemSize > 0 {
|
||||
maxVmemGb := driver.GetMaxVMemSizeGB()
|
||||
if vmemSize < 8 || vmemSize > maxVmemGb*1024 {
|
||||
return 0, httperrors.NewInputParameterError("Memory size must be 8MB ~ %d GB", maxVmemGb)
|
||||
}
|
||||
}
|
||||
return vmemSize, nil
|
||||
}
|
||||
|
||||
func ValidateCpuData(vcpuCount int, driver IGuestDriver) (int, error) {
|
||||
maxVcpuCount := driver.GetMaxVCpuCount()
|
||||
if vcpuCount < 1 || vcpuCount > maxVcpuCount {
|
||||
return 0, httperrors.NewInputParameterError("CPU core count must be 1 ~ %d", maxVcpuCount)
|
||||
}
|
||||
return vcpuCount, nil
|
||||
}
|
||||
|
||||
func ValidateMemCpuData(vmemSize, vcpuCount int, hypervisor string) (int, int, error) {
|
||||
if len(hypervisor) == 0 {
|
||||
hypervisor = HYPERVISOR_DEFAULT
|
||||
}
|
||||
driver := GetDriver(hypervisor)
|
||||
|
||||
if vmemSize > 0 {
|
||||
maxVmemGb := driver.GetMaxVMemSizeGB()
|
||||
if vmemSize < 8 || vmemSize > maxVmemGb*1024 {
|
||||
return 0, 0, httperrors.NewInputParameterError("Memory size must be 8MB ~ %d GB", maxVmemGb)
|
||||
}
|
||||
var err error
|
||||
vmemSize, err = ValidateMemData(vmemSize, driver)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
maxVcpuCount := driver.GetMaxVCpuCount()
|
||||
if vcpuCount < 1 || vcpuCount > maxVcpuCount {
|
||||
return 0, 0, httperrors.NewInputParameterError("CPU core count must be 1 ~ %d", maxVcpuCount)
|
||||
vcpuCount, err = ValidateCpuData(vcpuCount, driver)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return vmemSize, vcpuCount, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
memSize, _ := data.Int("vmem_size")
|
||||
cpuCount, _ := data.Int("vcpu_count")
|
||||
vmemSize, vcpuCount, err := ValidateMemCpuData(int(memSize), int(cpuCount), self.Hypervisor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var err error
|
||||
var vmemSize int
|
||||
var vcpuCount int
|
||||
|
||||
driver := GetDriver(self.Hypervisor)
|
||||
|
||||
if memSize, _ := data.Int("vmem_size"); memSize != 0 {
|
||||
vmemSize, err = ValidateMemData(int(memSize), driver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if cpuCount, _ := data.Int("vcpu_count"); cpuCount != 0 {
|
||||
vcpuCount, err = ValidateCpuData(int(cpuCount), driver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if vmemSize > 0 || vcpuCount > 0 {
|
||||
@@ -2731,8 +2717,7 @@ func (self *SGuest) createDiskOnHost(
|
||||
}
|
||||
|
||||
func (self *SGuest) CreateIsolatedDeviceOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, devs []*api.IsolatedDeviceConfig, pendingUsage quotas.IQuota) error {
|
||||
for idx := 0; idx < len(devs); idx += 1 {
|
||||
devConfig := devs[idx]
|
||||
for _, devConfig := range devs {
|
||||
err := self.createIsolatedDeviceOnHost(ctx, userCred, host, devConfig, pendingUsage)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+33
-10
@@ -963,24 +963,43 @@ func (self *SHost) GetHardwareSpecification() *jsonutils.JSONDict {
|
||||
}
|
||||
|
||||
type SStorageCapacity struct {
|
||||
Capacity int
|
||||
Used int
|
||||
Wasted int
|
||||
VCapacity int
|
||||
Capacity int `json:"capacity,omitzero"`
|
||||
Used int `json:"used_capacity,omitzero"`
|
||||
Wasted int `json:"waste_capacity,omitzero"`
|
||||
VCapacity int `json:"virtual_capacity,omitzero"`
|
||||
}
|
||||
|
||||
func (capa SStorageCapacity) GetFree() int {
|
||||
return capa.VCapacity - capa.Used - capa.Wasted
|
||||
func (cap *SStorageCapacity) GetFree() int {
|
||||
return cap.VCapacity - cap.Used - cap.Wasted
|
||||
}
|
||||
|
||||
func (cap *SStorageCapacity) GetCommitRate() float64 {
|
||||
if cap.Capacity > 0 {
|
||||
return float64(int(float64(cap.Used)*100.0/float64(cap.Capacity)+0.5) / 100.0)
|
||||
} else {
|
||||
return 0.0
|
||||
}
|
||||
}
|
||||
|
||||
func (cap *SStorageCapacity) Add(cap2 SStorageCapacity) {
|
||||
cap.Capacity += cap2.Capacity
|
||||
cap.Used += cap2.Used
|
||||
cap.Wasted += cap2.Wasted
|
||||
cap.VCapacity += cap2.VCapacity
|
||||
}
|
||||
|
||||
func (cap *SStorageCapacity) ToJson() *jsonutils.JSONDict {
|
||||
ret := jsonutils.Marshal(cap).(*jsonutils.JSONDict)
|
||||
ret.Add(jsonutils.NewFloat(cap.GetCommitRate()), "commit_rate")
|
||||
ret.Add(jsonutils.NewInt(int64(cap.GetFree())), "free_capacity")
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *SHost) GetAttachedStorageCapacity() SStorageCapacity {
|
||||
ret := SStorageCapacity{}
|
||||
storages := self.GetAttachedStorages("")
|
||||
for _, s := range storages {
|
||||
ret.Capacity += s.GetCapacity()
|
||||
ret.Used += s.GetUsedCapacity(tristate.True)
|
||||
ret.Wasted += s.GetUsedCapacity(tristate.False)
|
||||
ret.VCapacity += int(float32(s.GetCapacity()) * s.GetOvercommitBound())
|
||||
ret.Add(s.getStorageCapacity())
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@@ -2187,6 +2206,7 @@ func (self *SHost) getMoreDetails(ctx context.Context, extra *jsonutils.JSONDict
|
||||
extra.Add(jsonutils.NewInt(int64(capa.Wasted)), "storage_waste")
|
||||
extra.Add(jsonutils.NewInt(int64(capa.VCapacity)), "storage_virtual")
|
||||
extra.Add(jsonutils.NewInt(int64(capa.GetFree())), "storage_free")
|
||||
extra.Add(jsonutils.NewFloat(capa.GetCommitRate()), "storage_commit_rate")
|
||||
extra.Add(self.GetHardwareSpecification(), "spec")
|
||||
|
||||
// extra = self.SManagedResourceBase.getExtraDetails(ctx, extra)
|
||||
@@ -3031,6 +3051,9 @@ func (self *SHost) EnableNetif(ctx context.Context, userCred mcclient.TokenCrede
|
||||
} else if requireDesignatedIp {
|
||||
log.Errorf("Cannot allocate IP %s, not reachable", ipAddr)
|
||||
return fmt.Errorf("Cannot allocate IP %s, not reachable", ipAddr)
|
||||
} else {
|
||||
// the ipaddr is not usable, should be reset to empty
|
||||
ipAddr = ""
|
||||
}
|
||||
}
|
||||
wire := netif.GetWire()
|
||||
|
||||
@@ -357,7 +357,7 @@ func (manager *SIsolatedDeviceManager) findHostUnusedByModel(model string, hostI
|
||||
devs := make([]SIsolatedDevice, 0)
|
||||
q := manager.findUnusedQuery()
|
||||
q = q.Equals("model", model).Equals("host_id", hostId)
|
||||
err := q.All(&devs)
|
||||
err := db.FetchModelObjects(manager, q, &devs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -444,7 +444,6 @@ func (self *SIsolatedDevice) GetSpec(statusCheck bool) *jsonutils.JSONDict {
|
||||
}
|
||||
|
||||
func (man *SIsolatedDeviceManager) GetSpecIdent(spec *jsonutils.JSONDict) []string {
|
||||
log.Errorf("gpu get specIdent: %s", spec)
|
||||
devType, _ := spec.GetString("dev_type")
|
||||
vendor, _ := spec.GetString("vendor")
|
||||
model, _ := spec.GetString("model")
|
||||
|
||||
@@ -705,19 +705,21 @@ type SNicConfig struct {
|
||||
}
|
||||
|
||||
func parseNetworkInfo(userCred mcclient.TokenCredential, info *api.NetworkConfig) (*api.NetworkConfig, error) {
|
||||
netObj, err := NetworkManager.FetchByIdOrName(userCred, info.Network)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(NetworkManager.Keyword(), info.Network)
|
||||
if info.Network != "" {
|
||||
netObj, err := NetworkManager.FetchByIdOrName(userCred, info.Network)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(NetworkManager.Keyword(), info.Network)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
net := netObj.(*SNetwork)
|
||||
if net.IsOwner(userCred) || net.IsPublic || db.IsAdminAllowGet(userCred, net) {
|
||||
info.Network = netObj.GetId()
|
||||
} else {
|
||||
return nil, err
|
||||
return nil, httperrors.NewForbiddenError("no allow to access network %s", info.Network)
|
||||
}
|
||||
}
|
||||
net := netObj.(*SNetwork)
|
||||
if net.IsOwner(userCred) || net.IsPublic || db.IsAdminAllowGet(userCred, net) {
|
||||
info.Network = netObj.GetId()
|
||||
} else {
|
||||
return nil, httperrors.NewForbiddenError("no allow to access network %s", info.Network)
|
||||
}
|
||||
|
||||
if info.BwLimit == 0 {
|
||||
|
||||
@@ -332,21 +332,21 @@ func (self *SStorage) GetStorageCachePath(mountPoint, imageCachePath string) str
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SStorage) getStorageCapacity() SStorageCapacity {
|
||||
capa := SStorageCapacity{}
|
||||
|
||||
capa.Capacity = self.GetCapacity()
|
||||
capa.Used = self.GetUsedCapacity(tristate.True)
|
||||
capa.Wasted = self.GetUsedCapacity(tristate.False)
|
||||
capa.VCapacity = int(float32(self.GetCapacity()) * self.GetOvercommitBound())
|
||||
|
||||
return capa
|
||||
}
|
||||
|
||||
func (self *SStorage) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict {
|
||||
used := self.GetUsedCapacity(tristate.True)
|
||||
waste := self.GetUsedCapacity(tristate.False)
|
||||
vcapa := float32(self.GetCapacity()) * self.GetOvercommitBound()
|
||||
extra.Add(jsonutils.NewInt(int64(used)), "used_capacity")
|
||||
extra.Add(jsonutils.NewInt(int64(waste)), "waste_capacity")
|
||||
extra.Add(jsonutils.NewFloat(float64(vcapa)), "virtual_capacity")
|
||||
extra.Add(jsonutils.NewFloat(float64(vcapa-float32(used)-float32(waste))), "free_capacity")
|
||||
if self.GetCapacity() > 0 {
|
||||
value := float64(used * 1.0 / self.GetCapacity())
|
||||
value = float64(int(value*100+0.5) / 100.0)
|
||||
extra.Add(jsonutils.NewFloat(value), "commit_rate")
|
||||
} else {
|
||||
extra.Add(jsonutils.NewFloat(0.0), "commit_rate")
|
||||
}
|
||||
capa := self.getStorageCapacity()
|
||||
extra.Update(capa.ToJson())
|
||||
|
||||
extra.Add(jsonutils.NewFloat(float64(self.GetOvercommitBound())), "commit_bound")
|
||||
|
||||
info := self.getCloudProviderInfo()
|
||||
|
||||
@@ -356,26 +356,18 @@ func (self *GuestLiveMigrateTask) OnResumeDestGuestComplete(ctx context.Context,
|
||||
func (self *GuestLiveMigrateTask) OnUndeploySrcGuestComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
db.OpsLog.LogEvent(guest, db.ACT_MIGRATE, "", self.UserCred)
|
||||
status, _ := self.Params.GetString("guest_status")
|
||||
if status != models.VM_RUNNING {
|
||||
guest.SetStatus(self.UserCred, status, "")
|
||||
self.SetStageComplete(ctx, nil)
|
||||
} else {
|
||||
self.SetStage("OnStartGeustComplete", nil)
|
||||
guest.StartGueststartTask(ctx, self.UserCred, nil, self.GetTaskId())
|
||||
if status != guest.Status {
|
||||
self.SetStage("OnGuestSyncStatus", nil)
|
||||
guest.StartSyncstatus(ctx, self.UserCred, self.GetTaskId())
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GuestLiveMigrateTask) OnStartGeustComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
func (self *GuestLiveMigrateTask) OnGuestSyncStatus(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *GuestMigrateTask) TaskFailed(ctx context.Context, guest *models.SGuest, reason string) {
|
||||
status, _ := self.Params.GetString("guest_status")
|
||||
if status != models.VM_RUNNING {
|
||||
guest.SetStatus(self.UserCred, status, "")
|
||||
} else {
|
||||
guest.StartGueststartTask(ctx, self.UserCred, nil, "")
|
||||
}
|
||||
guest.SetStatus(self.UserCred, models.VM_MIGRATE_FAILED, reason)
|
||||
db.OpsLog.LogEvent(guest, db.ACT_MIGRATE_FAIL, reason, self.UserCred)
|
||||
self.SetStageFailed(ctx, reason)
|
||||
notifyclient.NotifySystemError(guest.Id, guest.Name, models.VM_MIGRATE_FAILED, reason)
|
||||
|
||||
@@ -40,6 +40,7 @@ func (self *GuestSyncConfTask) OnSyncComplete(ctx context.Context, obj db.IStand
|
||||
db.OpsLog.LogEvent(guest, db.ACT_SYNC_CONF, nil, self.UserCred)
|
||||
self.SetStageComplete(ctx, guest.GetShortDesc(ctx))
|
||||
} else if data.Contains("task") {
|
||||
// XXX this is only applied to KVM, which will call task_complete twice
|
||||
self.SetStage("on_disk_sync_complete", nil)
|
||||
} else {
|
||||
self.OnDiskSyncComplete(ctx, guest, data)
|
||||
|
||||
@@ -291,12 +291,10 @@ func (s *SKVMGuestInstance) generateStartScript(data *jsonutils.JSONDict) (strin
|
||||
}
|
||||
|
||||
var devAddrs = []string{}
|
||||
isolatedParams, err := s.Desc.GetArray("isolated_devices")
|
||||
if err != nil {
|
||||
for _, params := range isolatedParams {
|
||||
devAddr, _ := params.GetString("addr")
|
||||
devAddrs = append(devAddrs, devAddr)
|
||||
}
|
||||
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)
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ func (man *IsolatedDeviceManager) fillPCIDevices() error {
|
||||
}
|
||||
for idx, gpu := range gpus {
|
||||
man.Devices = append(man.Devices, newGPUHPCDevice(gpu))
|
||||
log.Infof("GPU device: %d => %#v", idx, gpu)
|
||||
log.Infof("Add GPU device: %d => %#v", idx, gpu)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -328,6 +328,7 @@ func (dev *sGPUBaseDevice) CustomProbe() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
grubCmdline = strings.TrimSpace(grubCmdline)
|
||||
params := sets.NewString(strings.Split(grubCmdline, " ")...)
|
||||
if !params.IsSuperset(sets.NewString("intel_iommu=on",
|
||||
"vfio_iommu_type1.allow_unsafe_interrupts=1")) {
|
||||
@@ -614,7 +615,7 @@ func (d *PCIDevice) getKernelDriver() (string, error) {
|
||||
begin := strings.Index(line, prompt)
|
||||
if begin >= 0 {
|
||||
end := begin + len(prompt)
|
||||
return line[end : len(line)-1], nil
|
||||
return line[end:], nil
|
||||
}
|
||||
}
|
||||
// no driver in use
|
||||
@@ -729,6 +730,8 @@ func getPassthroughGPUS() ([]*PCIDevice, error) {
|
||||
log.Errorf("Device %#v get kernel driver error: %v", dev, err)
|
||||
} else if drv == VFIO_PCI_KERNEL_DRIVER {
|
||||
ret = append(ret, dev)
|
||||
} else {
|
||||
log.Warningf("GPU %v use kernel driver %q, skip it", dev, drv)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
|
||||
type SPolicyManager struct {
|
||||
@@ -17,7 +18,16 @@ func policyReadFilter(session *mcclient.ClientSession, s jsonutils.JSONObject, q
|
||||
ret := ss.CopyIncludes("id", "type")
|
||||
blobStr, _ := ss.GetString("blob")
|
||||
if len(blobStr) > 0 {
|
||||
policy := rbacutils.SRbacPolicy{}
|
||||
blobJson, _ := jsonutils.ParseString(blobStr)
|
||||
err := policy.Decode(blobJson)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blobJson, err = policy.Encode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var format string
|
||||
if query != nil {
|
||||
format, _ = query.GetString("format")
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
type SchedulerTestBaseOptions struct {
|
||||
*ServerConfigs
|
||||
ServerConfigs
|
||||
|
||||
Mem int `help:"Memory size (MB), default 512" metavar:"MEMORY" default:"512"`
|
||||
Ncpu int `help:"#CPU cores of VM server, default 1" default:"1" metavar:"<SERVER_CPU_COUNT>"`
|
||||
|
||||
@@ -347,7 +347,8 @@ func (opts *ServerCreateOptions) Params() (*computeapi.ServerCreateInput, error)
|
||||
}
|
||||
|
||||
if BoolV(opts.AllowDelete) {
|
||||
params.DisableDelete = false
|
||||
disableDelete := false
|
||||
params.DisableDelete = &disableDelete
|
||||
}
|
||||
|
||||
if BoolV(opts.DryRun) {
|
||||
|
||||
+67
-17
@@ -15,6 +15,7 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
computedb "yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
computemodels "yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/core"
|
||||
@@ -121,18 +122,24 @@ func NewGuestReservedResourceUsedByBuilder(b *HostBuilder, host *computemodels.S
|
||||
mem int64 = 0
|
||||
disk int64 = 0
|
||||
)
|
||||
for _, g := range gst {
|
||||
dSize, err2 := g.DiskSize(true)
|
||||
if err2 != nil {
|
||||
err = err2
|
||||
return
|
||||
guestDiskSize := func(g *computemodels.SGuest, onlyLocal bool) int {
|
||||
size := 0
|
||||
for _, gd := range g.GetDisks() {
|
||||
disk := gd.GetDisk()
|
||||
if !onlyLocal || disk.IsLocal() {
|
||||
size += disk.DiskSize
|
||||
}
|
||||
}
|
||||
disk += dSize
|
||||
if o.GetOptions().IgnoreNonrunningGuests && !g.IsRunning() {
|
||||
return size
|
||||
}
|
||||
for _, g := range gst {
|
||||
dSize := guestDiskSize(&g, true)
|
||||
disk += int64(dSize)
|
||||
if o.GetOptions().IgnoreNonrunningGuests && !utils.IsInStringArray(g.Status, api.VM_RUNNING_STATUS) {
|
||||
continue
|
||||
}
|
||||
cpu += g.VCPUCount
|
||||
mem += g.VMemSize
|
||||
cpu += int64(g.VcpuCount)
|
||||
mem += int64(g.VmemSize)
|
||||
}
|
||||
ret.CPUCount = cpu
|
||||
ret.MemorySize = mem
|
||||
@@ -464,8 +471,9 @@ func (h *HostDesc) UnusedIsolatedDevicesByType(devType string) []*IsolatedDevice
|
||||
|
||||
func (h *HostDesc) UnusedIsolatedDevicesByVendorModel(vendorModel string) []*IsolatedDeviceDesc {
|
||||
ret := make([]*IsolatedDeviceDesc, 0)
|
||||
vm := NewVendorModelByStr(vendorModel)
|
||||
for _, dev := range h.UnusedIsolatedDevices() {
|
||||
if strings.Contains(dev.VendorModel(), vendorModel) {
|
||||
if dev.GetVendorModel().IsMatch(vm) {
|
||||
ret = append(ret, dev)
|
||||
}
|
||||
}
|
||||
@@ -1192,8 +1200,50 @@ func (i *IsolatedDeviceDesc) VendorID() string {
|
||||
return strings.Split(i.VendorDeviceID, ":")[0]
|
||||
}
|
||||
|
||||
func (i *IsolatedDeviceDesc) VendorModel() string {
|
||||
return fmt.Sprintf("%s:%s", i.VendorID(), i.Model)
|
||||
type VendorModel struct {
|
||||
Vendor string
|
||||
Model string
|
||||
}
|
||||
|
||||
func NewVendorModelByStr(desc string) *VendorModel {
|
||||
vm := new(VendorModel)
|
||||
// desc format is '<vendor>:<model>'
|
||||
parts := strings.Split(desc, ":")
|
||||
if len(parts) == 1 {
|
||||
vm.Model = parts[0]
|
||||
} else if len(parts) == 2 {
|
||||
vm.Vendor = parts[0]
|
||||
vm.Model = parts[1]
|
||||
}
|
||||
return vm
|
||||
}
|
||||
|
||||
func (vm *VendorModel) IsMatch(target *VendorModel) bool {
|
||||
if vm.Model == "" || target.Model == "" {
|
||||
return false
|
||||
}
|
||||
vendorMatch := false
|
||||
modelMatch := false
|
||||
if target.Vendor != "" {
|
||||
if vm.Vendor == target.Vendor {
|
||||
vendorMatch = true
|
||||
} else if api.ID_VENDOR_MAP[vm.Vendor] == target.Vendor {
|
||||
vendorMatch = true
|
||||
}
|
||||
} else {
|
||||
vendorMatch = true
|
||||
}
|
||||
if vm.Model == target.Model {
|
||||
modelMatch = true
|
||||
}
|
||||
return vendorMatch && modelMatch
|
||||
}
|
||||
|
||||
func (i *IsolatedDeviceDesc) GetVendorModel() *VendorModel {
|
||||
return &VendorModel{
|
||||
Vendor: i.VendorID(),
|
||||
Model: i.Model,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *HostBuilder) getIsolatedDevices(hostID string) (devs []*models.IsolatedDevice) {
|
||||
@@ -1219,8 +1269,8 @@ func (b *HostBuilder) getUsedIsolatedDevices(hostID string) (devs []*models.Isol
|
||||
return
|
||||
}
|
||||
|
||||
func (b *HostBuilder) getIsolatedDeviceGuests(hostID string) (guests []*models.Guest) {
|
||||
guests = make([]*models.Guest, 0)
|
||||
func (b *HostBuilder) getIsolatedDeviceGuests(hostID string) (guests []computemodels.SGuest) {
|
||||
guests = make([]computemodels.SGuest, 0)
|
||||
usedDevs := b.getUsedIsolatedDevices(hostID)
|
||||
if len(usedDevs) == 0 {
|
||||
return
|
||||
@@ -1231,9 +1281,9 @@ func (b *HostBuilder) getIsolatedDeviceGuests(hostID string) (guests []*models.G
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
guest := g.(*models.Guest)
|
||||
if !ids.Has(guest.ID) {
|
||||
ids.Insert(guest.ID)
|
||||
guest := g.(computemodels.SGuest)
|
||||
if !ids.Has(guest.Id) {
|
||||
ids.Insert(guest.Id)
|
||||
guests = append(guests, guest)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,3 +683,16 @@ func (self *SDatastore) RemoveDir(ctx context.Context, remotePath string) error
|
||||
func (self *SDatastore) IsSysDiskStore() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SDatastore) MoveVmdk(ctx context.Context, srcPath string, dstPath string) error {
|
||||
dm := object.NewVirtualDiskManager(self.manager.client.Client)
|
||||
defer dm.Destroy(ctx)
|
||||
|
||||
srcUrl := self.GetPathUrl(srcPath)
|
||||
dstUrl := self.GetPathUrl(dstPath)
|
||||
task, err := dm.MoveVirtualDisk(ctx, srcUrl, nil, dstUrl, nil, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return task.Wait(ctx)
|
||||
}
|
||||
|
||||
@@ -120,8 +120,14 @@ func (self *SVirtualMachine) UpdateVM(ctx context.Context, name string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
// TODO: detach disk to a separate directory, so as to keep disk independent of VM
|
||||
|
||||
func (self *SVirtualMachine) DetachDisk(ctx context.Context, diskId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
vdisk, err := self.GetIDiskById(diskId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return self.doDetachDisk(ctx, vdisk.(*SVirtualDisk), false)
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) AttachDisk(ctx context.Context, diskId string) error {
|
||||
|
||||
@@ -8,12 +8,22 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var initTime = time.Time{}
|
||||
|
||||
type cacheNode struct {
|
||||
key string
|
||||
expire time.Time
|
||||
value interface{}
|
||||
}
|
||||
|
||||
func (node *cacheNode) reset() {
|
||||
if !node.expire.IsZero() {
|
||||
node.key = ""
|
||||
node.expire = initTime
|
||||
node.value = nil
|
||||
}
|
||||
}
|
||||
|
||||
type Cache struct {
|
||||
table []cacheNode
|
||||
lock *sync.Mutex
|
||||
@@ -101,3 +111,12 @@ func (c *Cache) AtomicSet(key string, val interface{}) {
|
||||
defer c.lock.Unlock()
|
||||
c.Set(key, val)
|
||||
}
|
||||
|
||||
func (c *Cache) Invalidate() {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
for i := range c.table {
|
||||
c.table[i].reset()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,4 +46,15 @@ func TestCache(t *testing.T) {
|
||||
if v != nil {
|
||||
t.Errorf("key 123 shoud expire")
|
||||
}
|
||||
|
||||
c.Set("123", 1234)
|
||||
v = c.Get("123")
|
||||
if v == nil || v.(int) != 1234 {
|
||||
t.Error("Key 123 not found")
|
||||
}
|
||||
c.Invalidate()
|
||||
v = c.Get("123")
|
||||
if v != nil {
|
||||
t.Error("Key 123 should not found")
|
||||
}
|
||||
}
|
||||
|
||||
+79
-12
@@ -2,11 +2,11 @@ package rbacutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/conditionparser"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
type TRbacResult string
|
||||
@@ -45,6 +45,8 @@ type SRbacPolicy struct {
|
||||
Condition string
|
||||
IsAdmin bool
|
||||
Rules []SRbacRule
|
||||
Projects []string
|
||||
Roles []string
|
||||
}
|
||||
|
||||
type SRbacRule struct {
|
||||
@@ -188,9 +190,48 @@ func CompactRules(rules []SRbacRule) []SRbacRule {
|
||||
return output
|
||||
}
|
||||
|
||||
var (
|
||||
tenantEqualsPattern = regexp.MustCompile(`tenant\s*==\s*['"]?(\w+)['"]?`)
|
||||
roleContainsPattern = regexp.MustCompile(`roles.contains\(['"]?(\w+)['"]?\)`)
|
||||
)
|
||||
|
||||
func searchMatchStrings(pattern *regexp.Regexp, condstr string) []string {
|
||||
ret := make([]string, 0)
|
||||
matches := pattern.FindAllStringSubmatch(condstr, -1)
|
||||
for _, match := range matches {
|
||||
ret = append(ret, match[1])
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func searchMatchTenants(condstr string) []string {
|
||||
return searchMatchStrings(tenantEqualsPattern, condstr)
|
||||
}
|
||||
|
||||
func searchMatchRoles(condstr string) []string {
|
||||
return searchMatchStrings(roleContainsPattern, condstr)
|
||||
}
|
||||
|
||||
func (policy *SRbacPolicy) Decode(policyJson jsonutils.JSONObject) error {
|
||||
policy.Condition, _ = policyJson.GetString("condition")
|
||||
policy.IsAdmin = jsonutils.QueryBoolean(policyJson, "is_admin", false)
|
||||
if policyJson.Contains("projects") {
|
||||
projectJson, _ := policyJson.GetArray("projects")
|
||||
policy.Projects = jsonutils.JSONArray2StringArray(projectJson)
|
||||
}
|
||||
if policyJson.Contains("roles") {
|
||||
roleJson, _ := policyJson.GetArray("roles")
|
||||
policy.Roles = jsonutils.JSONArray2StringArray(roleJson)
|
||||
}
|
||||
|
||||
if len(policy.Projects) == 0 && len(policy.Roles) == 0 && len(policy.Condition) > 0 {
|
||||
// XXX hack
|
||||
// for smooth transtion from condition to projects&roles
|
||||
policy.Projects = searchMatchTenants(policy.Condition)
|
||||
policy.Roles = searchMatchRoles(policy.Condition)
|
||||
}
|
||||
// empty condition, no longer use this field
|
||||
policy.Condition = ""
|
||||
|
||||
ruleJson, err := policyJson.Get("policy")
|
||||
if err != nil {
|
||||
@@ -288,7 +329,7 @@ func (rule *SRbacRule) toStringArray() []string {
|
||||
strArr = append(strArr, rule.Extra...)
|
||||
}
|
||||
i := len(strArr) - 1
|
||||
for i >= 0 && (len(strArr[i]) == 0 || strArr[i] == WILD_MATCH) {
|
||||
for i > 0 && (len(strArr[i]) == 0 || strArr[i] == WILD_MATCH) {
|
||||
i -= 1
|
||||
}
|
||||
return strArr[0 : i+1]
|
||||
@@ -346,12 +387,18 @@ func (policy *SRbacPolicy) Encode() (jsonutils.JSONObject, error) {
|
||||
}
|
||||
|
||||
ret := jsonutils.NewDict()
|
||||
ret.Add(jsonutils.NewString(policy.Condition), "condition")
|
||||
// ret.Add(jsonutils.NewString(policy.Condition), "condition")
|
||||
if policy.IsAdmin {
|
||||
ret.Add(jsonutils.JSONTrue, "is_admin")
|
||||
} else {
|
||||
ret.Add(jsonutils.JSONFalse, "is_admin")
|
||||
}
|
||||
if len(policy.Projects) > 0 {
|
||||
ret.Add(jsonutils.NewStringArray(policy.Projects), "projects")
|
||||
}
|
||||
if len(policy.Roles) > 0 {
|
||||
ret.Add(jsonutils.NewStringArray(policy.Roles), "roles")
|
||||
}
|
||||
ret.Add(rules, "policy")
|
||||
return ret, nil
|
||||
}
|
||||
@@ -369,17 +416,37 @@ func (policy *SRbacPolicy) Explain(request [][]string) [][]string {
|
||||
return output
|
||||
}
|
||||
|
||||
func (policy *SRbacPolicy) Allow(userCred jsonutils.JSONObject, service, resource, action string, extra ...string) TRbacResult {
|
||||
if len(policy.Condition) > 0 {
|
||||
match, err := conditionparser.Eval(policy.Condition, userCred)
|
||||
if err != nil {
|
||||
log.Errorf("eval condition %s fail %s", policy.Condition, err)
|
||||
return Deny
|
||||
func contains(s1 []string, s string) bool {
|
||||
for i := range s1 {
|
||||
if s1[i] == s {
|
||||
return true
|
||||
}
|
||||
if !match {
|
||||
return Deny
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func intersect(s1 []string, s2 []string) bool {
|
||||
for i := range s1 {
|
||||
for j := range s2 {
|
||||
if s1[i] == s2[j] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (policy *SRbacPolicy) Match(userCred mcclient.TokenCredential) bool {
|
||||
if (len(policy.Projects) == 0 || (userCred != nil && contains(policy.Projects, userCred.GetProjectName()))) && (len(policy.Roles) == 0 || (userCred != nil && intersect(policy.Roles, userCred.GetRoles()))) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (policy *SRbacPolicy) Allow(userCred mcclient.TokenCredential, service, resource, action string, extra ...string) TRbacResult {
|
||||
if !policy.Match(userCred) {
|
||||
return Deny
|
||||
}
|
||||
rule := policy.GetMatchRule(service, resource, action, extra...)
|
||||
if rule == nil {
|
||||
return Deny
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
func TestSRabcRule_Match(t *testing.T) {
|
||||
@@ -179,60 +181,6 @@ func TestSRabcPolicy_Encode(t *testing.T) {
|
||||
t.Logf("%s", policyStr1)
|
||||
}
|
||||
|
||||
func TestSRbacPolicy_Allow(t *testing.T) {
|
||||
userCredStr := `{"domain":"Default","domain_id":"default","expires":"2018-10-28T05:33:54.000000Z","roles":"admin,teamleader","tenant":"system","tenant_id":"5d65667d112e47249ae66dbd7bc07030","token":"gAAAAABb0_jC2Qz2PpB00-pieLi4exKXq4O3QrvoqerpqoSxbp9pOLLdNWaAg0cPcd8eAjkiPhSo7VWQAVodoxnad95LdNbUf_1It8R_wXVDtO20caB7oLcas1oQt8b1cG0a7qagauP0iWVSW_dq_e92rD5Hd3SHn3Lw6ycrp_eHLskz_8EbPiI","user":"sysadmin","user_id":"dddf386b6ff24572b2e6a771d768495e"}`
|
||||
|
||||
userCred, err := jsonutils.ParseString(userCredStr)
|
||||
if err != nil {
|
||||
t.Errorf("parse json fail %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
policy string
|
||||
ops []string
|
||||
want TRbacResult
|
||||
}{
|
||||
{
|
||||
`{
|
||||
"condition": "tenant==\"system\" && roles.contains(\"admin\")",
|
||||
"is_admin": true,
|
||||
"policy": {
|
||||
"*": "allow"
|
||||
}
|
||||
}`,
|
||||
[]string{"compute", "servers", "list"},
|
||||
Allow,
|
||||
},
|
||||
{
|
||||
`{"is_admin":"false","policy":{"*":{"*":{"*":"allow","delete":"deny"}}}}`,
|
||||
[]string{"compute", "servers", "delete"},
|
||||
Deny,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
policyJson, err := jsonutils.ParseString(c.policy)
|
||||
if err != nil {
|
||||
t.Errorf("fail to parse json string %s", err)
|
||||
return
|
||||
}
|
||||
policy := SRbacPolicy{}
|
||||
|
||||
err = policy.Decode(policyJson)
|
||||
if err != nil {
|
||||
t.Errorf("decode error %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
isAllow := policy.Allow(userCred, c.ops[0], c.ops[1], c.ops[2])
|
||||
if isAllow != c.want {
|
||||
t.Errorf("%s %#v expect %#v, but get %#v", policyJson.String(), c.ops, c.want, isAllow)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSRabcPolicy_Explain(t *testing.T) {
|
||||
policyStr := `{
|
||||
"condition": "usercred.project != \"system\" && usercred.roles==\"projectowner\"",
|
||||
@@ -281,24 +229,94 @@ func TestSRabcPolicy_Explain(t *testing.T) {
|
||||
t.Logf("%#v", output)
|
||||
}
|
||||
|
||||
func TestTRbacResult_IsHigherPrivilege(t *testing.T) {
|
||||
cases := []struct {
|
||||
t1 TRbacResult
|
||||
t2 TRbacResult
|
||||
want bool
|
||||
}{
|
||||
{Allow, Allow, false},
|
||||
{Allow, OwnerAllow, true},
|
||||
{Deny, Deny, false},
|
||||
{Deny, OwnerAllow, false},
|
||||
{Deny, Allow, false},
|
||||
{OwnerAllow, Allow, false},
|
||||
}
|
||||
func TestConditionParser(t *testing.T) {
|
||||
condition := `tenant=="system" && roles.contains("admin")`
|
||||
tenants := searchMatchTenants(condition)
|
||||
t.Logf("%s", tenants)
|
||||
roles := searchMatchRoles(condition)
|
||||
t.Logf("%s", roles)
|
||||
}
|
||||
|
||||
func TestSRbacPolicyMatch(t *testing.T) {
|
||||
cases := []struct {
|
||||
policy SRbacPolicy
|
||||
userCred mcclient.TokenCredential
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
SRbacPolicy{},
|
||||
&mcclient.SSimpleToken{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
SRbacPolicy{},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
SRbacPolicy{
|
||||
Projects: []string{"system"},
|
||||
},
|
||||
&mcclient.SSimpleToken{
|
||||
Project: "system",
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
SRbacPolicy{
|
||||
Projects: []string{"system"},
|
||||
},
|
||||
&mcclient.SSimpleToken{
|
||||
Project: "demo",
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
SRbacPolicy{
|
||||
Projects: []string{"system"},
|
||||
Roles: []string{"admin"},
|
||||
},
|
||||
&mcclient.SSimpleToken{
|
||||
Project: "system",
|
||||
Roles: "admin",
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
SRbacPolicy{
|
||||
Projects: []string{"system"},
|
||||
Roles: []string{"admin"},
|
||||
},
|
||||
&mcclient.SSimpleToken{
|
||||
Project: "system",
|
||||
Roles: "admin,_member_",
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
SRbacPolicy{
|
||||
Projects: []string{"system"},
|
||||
Roles: []string{"admin"},
|
||||
},
|
||||
&mcclient.SSimpleToken{
|
||||
Project: "system",
|
||||
Roles: "_member_",
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
SRbacPolicy{
|
||||
Projects: []string{"system"},
|
||||
Roles: []string{"admin"},
|
||||
},
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
got := c.t1.IsHigherPrivilege(c.t2)
|
||||
got := c.policy.Match(c.userCred)
|
||||
if got != c.want {
|
||||
t.Errorf("%s IsHigherPrivilege %s want %v got %v", c.t1, c.t2, c.want, got)
|
||||
t.Errorf("%#v %#v got %v want %v", c.policy, c.userCred, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user