fix confilct

This commit is contained in:
TangBin
2019-03-21 17:57:36 +08:00
32 changed files with 1126 additions and 679 deletions
+6 -1
View File
@@ -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
})
}
+1 -1
View File
@@ -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"`
+167
View File
@@ -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
View File
@@ -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
}
+1 -1
View File
@@ -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 {
+1
View File
@@ -31,6 +31,7 @@ func (s *BaremetalService) StartService() {
app_common.ServeForeverWithCleanup(app, &o.Options.CommonOptions, func() {
tasks.OnStop()
baremetal.Stop()
})
}
+338
View File
@@ -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()
}
+3
View File
@@ -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 {
+8 -3
View File
@@ -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{
+21 -13
View File
@@ -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
}
+4
View File
@@ -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")
}
+14 -14
View File
@@ -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)
+1 -48
View File
@@ -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
View File
@@ -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
View File
@@ -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()
+1 -2
View File
@@ -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")
+13 -11
View File
@@ -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 {
+14 -14
View File
@@ -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()
+5 -13
View File
@@ -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)
+1
View File
@@ -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)
+4 -6
View File
@@ -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
+10
View File
@@ -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")
+1 -1
View File
@@ -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>"`
+2 -1
View File
@@ -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
View File
@@ -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)
}
}
+13
View File
@@ -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)
}
+7 -1
View File
@@ -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 {
+19
View File
@@ -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()
}
}
+11
View File
@@ -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
View File
@@ -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
+87 -69
View File
@@ -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)
}
}
}