Merge branch 'release/2.3.0' of ssh://git.yunion.io/~quxuan/onecloud into hotfix/qx-cloud-account

This commit is contained in:
屈轩
2018-10-16 18:38:47 +08:00
120 changed files with 3590 additions and 446 deletions
Generated
+15 -2
View File
@@ -884,6 +884,18 @@
pruneopts = "UT"
revision = "d188e65d659ef53fcdb0691c12f1bba64928b649"
[[projects]]
branch = "master"
digest = "1:119cf7d2c3bc4a3c675e8c30cadf00c8c2ab34a20ba373211dd3a7d66f3e5f32"
name = "github.com/tredoe/osutil"
packages = [
"user/crypt",
"user/crypt/common",
"user/crypt/sha512_crypt",
]
pruneopts = "UT"
revision = "7d3ee1afa71c90fd1514c8f557ae6c5f414208eb"
[[projects]]
digest = "1:98e5cda86f67cd1ac95389d98670b66dea8cae480fe6292b83bccccfe60b4106"
name = "github.com/ugorji/go"
@@ -1223,11 +1235,11 @@
[[projects]]
branch = "master"
digest = "1:49ffc35ec8d3f7789393cd132acd359e8ac1f5d38c7a2b91c484b041840c62c0"
digest = "1:36db56d9ed25cc9cbd34d5553c14d5e1d4ef6501feaddb752c66aeb294e481e6"
name = "yunion.io/x/jsonutils"
packages = ["."]
pruneopts = "UT"
revision = "d1290e94d4753c1748fc7c89f472a523cc0a5c08"
revision = "191bb9c0726440a0b239c344c70b9df567536302"
[[projects]]
branch = "master"
@@ -1362,6 +1374,7 @@
"github.com/moul/http2curl",
"github.com/serialx/hashring",
"github.com/stretchr/testify/assert",
"github.com/tredoe/osutil/user/crypt/sha512_crypt",
"github.com/vmware/govmomi",
"github.com/vmware/govmomi/object",
"github.com/vmware/govmomi/property",
+8
View File
@@ -109,3 +109,11 @@
[[constraint]]
name = "github.com/360EntSecGroup-Skylar/excelize"
version = "v1.3.0"
[[constraint]]
branch = "master"
name = "github.com/tredoe/osutil"
[[constraint]]
branch = "master"
name = "golang.org/x/crypto"
+3 -3
View File
@@ -44,7 +44,7 @@ install: prepare_dir
done
build: prepare_dir
build: prepare_dir fmt
@for PKG in $(CMDS); do \
echo build $$PKG; \
$(GO_BUILD) -o $(BIN_DIR)/`basename $${PKG}` $$PKG; \
@@ -58,11 +58,11 @@ test: prepare_dir
done
cmd/%: prepare_dir
cmd/%: prepare_dir fmt
$(GO_BUILD) -o $(BIN_DIR)/$(shell basename $@) $(REPO_PREFIX)/$@
pkg/%: prepare_dir
pkg/%: prepare_dir fmt
$(GO_INSTALL) $(REPO_PREFIX)/$@
+1 -1
View File
@@ -14,7 +14,7 @@ func init() {
StatMonth string `help:"stat_month of the query"`
StartDate string `help:"start_date of the query"`
EndDate string `help:"end_date of the query"`
QueryType string `help:"query_type of the query"`
QueryType string `help:"query_type of the query"`
Platform string `help:"platform of the query"`
ProjectId string `help:"project_id of the query"`
}
+4 -6
View File
@@ -11,11 +11,11 @@ import (
)
type AnsibleHostsOptions struct {
List bool `help:"List all ansible inventory"`
Host string `help:"List of a host"`
List bool `help:"List all ansible inventory"`
Host string `help:"List of a host"`
PrivateKey string `help:"path to private key to use for ansible"`
Port int `help:"optional port, if port is not 22"`
User string `help:"username to try"`
Port int `help:"optional port, if port is not 22"`
User string `help:"username to try"`
UserBecome string `help:"username to sudo"`
}
@@ -35,7 +35,6 @@ func serverGetNameIP(srv jsonutils.JSONObject) (string, string, error) {
return host, ipList[0], nil
}
func doList(s *mcclient.ClientSession, args *AnsibleHostsOptions) error {
hostVars := jsonutils.NewDict()
hosts := jsonutils.NewArray()
@@ -86,7 +85,6 @@ func doList(s *mcclient.ClientSession, args *AnsibleHostsOptions) error {
return nil
}
func doHost(s *mcclient.ClientSession, host string, args *AnsibleHostsOptions) error {
srv, err := modules.Servers.Get(s, host, nil)
if err != nil {
-1
View File
@@ -7,7 +7,6 @@ import (
func init() {
type CapabilitiesOptions struct {
}
R(&CapabilitiesOptions{}, "capabilities", "Show backend capabilities", func(s *mcclient.ClientSession, args *CapabilitiesOptions) error {
result, err := modules.Capabilities.List(s, nil)
+17
View File
@@ -38,6 +38,7 @@ func init() {
AccessURL string `helo:"hello" metavar:"Azure choices: <AzureGermanCloud、AzureChinaCloud、AzureUSGovernmentCloud、AzurePublicCloud>"`
Desc string `help:"Description"`
Enabled bool `help:"Enabled the account automatically"`
Import bool `help:"Import all sub account automatically"`
}
R(&CloudaccountCreateOptions{}, "cloud-account-create", "Create a cloud account", func(s *mcclient.ClientSession, args *CloudaccountCreateOptions) error {
params := jsonutils.NewDict()
@@ -48,6 +49,9 @@ func init() {
if args.Enabled {
params.Add(jsonutils.JSONTrue, "enabled")
}
if args.Import {
params.Add(jsonutils.JSONTrue, "import")
}
if len(args.AccessURL) > 0 {
params.Add(jsonutils.NewString(args.AccessURL), "access_url")
}
@@ -147,6 +151,19 @@ func init() {
return nil
})
type CloudaccountImportOptions struct {
ID string `help:"ID or Name of cloud account"`
Enabled bool `help:"Import sub accounts with enabled status"`
}
R(&CloudaccountImportOptions{}, "cloud-account-import", "Import sub cloud account", func(s *mcclient.ClientSession, args *CloudaccountImportOptions) error {
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "import", jsonutils.Marshal(map[string]bool{"enabled": args.Enabled}))
if err != nil {
return err
}
printObject(result)
return nil
})
type CloudaccountUpdateCredentialOptions struct {
ID string `help:"ID or Name of cloud account"`
ACCOUNT string `help:"new account"`
+17 -7
View File
@@ -74,12 +74,18 @@ func init() {
return nil
})
R(&DiskDetailOptions{}, "disk-delete", "Delete a disk", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
disk, e := modules.Disks.Delete(s, args.ID, nil)
if e != nil {
return e
type DiskDeleteOptions struct {
ID []string `help:"ID of disks to delete" metavar:"DISK"`
OverridePendingDelete bool `help:"Delete disk directly instead of pending delete"`
}
R(&DiskDeleteOptions{}, "disk-delete", "Delete a disk", func(s *mcclient.ClientSession, args *DiskDeleteOptions) error {
params := jsonutils.NewDict()
if args.OverridePendingDelete {
params.Add(jsonutils.JSONTrue, "override_pending_delete")
}
printObject(disk)
ret := modules.Disks.BatchDeleteWithParam(s, args.ID, params, nil)
printBatchResults(ret, modules.Disks.GetColumns(s))
return nil
})
@@ -202,12 +208,16 @@ func init() {
return nil
})
type DiskResetOptions struct {
DISK string `help:"ID or name of disk"`
SNAPSHOT string `help:"snapshots ID of disk`
DISK string `help:"ID or name of disk"`
SNAPSHOT string `help:"snapshots ID of disk`
AutoStart bool `help:"Autostart guest"`
}
R(&DiskResetOptions{}, "disk-reset", "Resize a disk", func(s *mcclient.ClientSession, args *DiskResetOptions) error {
params := jsonutils.NewDict()
params.Add(jsonutils.NewString(args.SNAPSHOT), "snapshot_id")
if args.AutoStart {
params.Add(jsonutils.JSONTrue, "auto_start")
}
disk, err := modules.Disks.PerformAction(s, args.DISK, "disk-reset", params)
if err != nil {
return err
+1 -1
View File
@@ -13,7 +13,7 @@ func init() {
Unused bool `help:"Only show unused devices"`
Gpu bool `help:"Only show gpu devices"`
Host string `help:"Host ID or Name"`
Zone string `help:"Zone ID or Name"`
Zone string `help:"Zone ID or Name"`
}
R(&DeviceListOptions{}, "isolated-device-list", "List isolated devices like GPU", func(s *mcclient.ClientSession, args *DeviceListOptions) error {
var params *jsonutils.JSONDict
+40 -2
View File
@@ -3,6 +3,7 @@ package shell
import (
"fmt"
"io/ioutil"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
@@ -59,6 +60,14 @@ func init() {
params.Add(jsonutils.JSONFalse, "reset_password")
}
if len(opts.UserDataFile) > 0 {
userdata, err := ioutil.ReadFile(opts.UserDataFile)
if err != nil {
return err
}
params.Add(jsonutils.NewString(string(userdata)), "user_data")
}
count := options.IntV(opts.Count)
if options.BoolV(opts.DryRun) {
results, err := modules.SchedManager.DoScheduleListResult(s, params, count)
@@ -88,12 +97,22 @@ func init() {
return nil
})
R(&options.ServerIdOptions{}, "server-logininfo", "Get login info of a server", func(s *mcclient.ClientSession, opts *options.ServerIdOptions) error {
R(&options.ServerLoginInfoOptions{}, "server-logininfo", "Get login info of a server", func(s *mcclient.ClientSession, opts *options.ServerLoginInfoOptions) error {
srvid, e := modules.Servers.GetId(s, opts.ID, nil)
if e != nil {
return e
}
i, e := modules.Servers.GetLoginInfo(s, srvid, nil)
params := jsonutils.NewDict()
if len(opts.Key) > 0 {
privateKey, e := ioutil.ReadFile(opts.Key)
if e != nil {
return e
}
params.Add(jsonutils.NewString(string(privateKey)), "private_key")
}
i, e := modules.Servers.GetLoginInfo(s, srvid, params)
if e != nil {
return e
}
@@ -467,4 +486,23 @@ func init() {
printObject(result)
return nil
})
type ServerUserDataOptions struct {
ID string `help:"ID or name of server"`
FILE string `help:"Path to user data file"`
}
R(&ServerUserDataOptions{}, "server-set-user-data", "Update server user_data", func(s *mcclient.ClientSession, args *ServerUserDataOptions) error {
params := jsonutils.NewDict()
content, err := ioutil.ReadFile(args.FILE)
if err != nil {
return err
}
params.Add(jsonutils.NewString(string(content)), "user_data")
result, err := modules.Servers.PerformAction(s, args.ID, "user-data", params)
if err != nil {
return err
}
printObject(result)
return nil
})
}
+1 -1
View File
@@ -15,7 +15,7 @@ func init() {
Model string `help:"Specified model specs" choices:"hosts|isolated_devices|guests"`
HostType string `help:"Host type filter" choices:"baremetal|hypervisor|esxi|kubelet|hyperv"`
Gpu bool `help:"Only show gpu devices"`
Zone string `help:"Filter by zone id or name"`
Zone string `help:"Filter by zone id or name"`
}
R(&ListOptions{}, "spec", "List all kinds of model specs", func(s *mcclient.ClientSession, args *ListOptions) error {
var params *jsonutils.JSONDict
+42
View File
@@ -0,0 +1,42 @@
package shell
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
)
func init() {
type SshkeypairQueryOptions struct {
Project string `help:"get keypair for specific project"`
Admin bool `help:"get admin keypair, sysadmin ONLY option"`
}
R(&SshkeypairQueryOptions{}, "sshkeypair-show", "Get ssh keypairs", func(s *mcclient.ClientSession, args *SshkeypairQueryOptions) error {
query := jsonutils.NewDict()
if args.Admin {
query.Add(jsonutils.JSONTrue, "admin")
}
var keys jsonutils.JSONObject
if len(args.Project) == 0 {
listResult, err := modules.Sshkeypairs.List(s, query)
if err != nil {
return err
}
keys = listResult.Data[0]
} else {
result, err := modules.Sshkeypairs.GetById(s, args.Project, query)
if err != nil {
return err
}
keys = result
}
privKey, _ := keys.GetString("private_key")
pubKey, _ := keys.GetString("public_key")
fmt.Print(privKey)
fmt.Print(pubKey)
return nil
})
}
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/util/printutils"
"yunion.io/x/onecloud/pkg/util/excelutils"
"yunion.io/x/onecloud/pkg/util/printutils"
)
func printList(list *modules.ListResult, columns []string) {
@@ -35,7 +35,7 @@ func exportList(list *modules.ListResult, file string, exportKeys string, export
if len(exportKeys) > 0 {
keys = strings.Split(exportKeys, ",")
texts = strings.Split(exportTexts, ",")
}else {
} else {
keys = columns
texts = columns
}
+9 -5
View File
@@ -9,7 +9,7 @@ import (
"yunion.io/x/sqlchemy"
)
func fetchById(manager IModelManager, idStr string) (IModel, error) {
func FetchById(manager IModelManager, idStr string) (IModel, error) {
q := manager.Query()
q = manager.FilterById(q, idStr)
count := q.Count()
@@ -31,7 +31,11 @@ func fetchById(manager IModelManager, idStr string) (IModel, error) {
}
}
func fetchByName(manager IModelManager, owner string, idStr string) (IModel, error) {
func FetchByName(manager IModelManager, userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
var owner string
if userCred != nil {
owner = manager.GetOwnerId(userCred)
}
q := manager.Query()
q = manager.FilterByName(q, idStr)
q = manager.FilterByOwner(q, owner)
@@ -54,10 +58,10 @@ func fetchByName(manager IModelManager, owner string, idStr string) (IModel, err
}
}
func fetchByIdOrName(manager IModelManager, ownerProjId string, idStr string) (IModel, error) {
obj, err := fetchById(manager, idStr)
func FetchByIdOrName(manager IModelManager, userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
obj, err := FetchById(manager, idStr)
if err == sql.ErrNoRows {
return fetchByName(manager, ownerProjId, idStr)
return FetchByName(manager, userCred, idStr)
} else {
return obj, err
}
+3 -3
View File
@@ -39,12 +39,12 @@ type IModelManager interface {
FilterByName(q *sqlchemy.SQuery, name string) *sqlchemy.SQuery
FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery
GetOwnerId(userCred mcclient.TokenCredential) string
GetOwnerId(userCred mcclient.IIdentityProvider) string
// RawFetchById(idStr string) (IModel, error)
FetchById(idStr string) (IModel, error)
FetchByName(ownerProjId string, idStr string) (IModel, error)
FetchByIdOrName(ownerProjId string, idStr string) (IModel, error)
FetchByName(userCred mcclient.IIdentityProvider, idStr string) (IModel, error)
FetchByIdOrName(userCred mcclient.IIdentityProvider, idStr string) (IModel, error)
// create hooks
AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool
+3 -3
View File
@@ -108,7 +108,7 @@ func (manager *SModelBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner string
return q
}
func (manager *SModelBaseManager) GetOwnerId(userCred mcclient.TokenCredential) string {
func (manager *SModelBaseManager) GetOwnerId(userCred mcclient.IIdentityProvider) string {
return ""
}
@@ -116,11 +116,11 @@ func (manager *SModelBaseManager) FetchById(idStr string) (IModel, error) {
return nil, sql.ErrNoRows
}
func (manager *SModelBaseManager) FetchByName(ownerProjId string, idStr string) (IModel, error) {
func (manager *SModelBaseManager) FetchByName(userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
return nil, sql.ErrNoRows
}
func (manager *SModelBaseManager) FetchByIdOrName(ownerProjId string, idStr string) (IModel, error) {
func (manager *SModelBaseManager) FetchByIdOrName(userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
return nil, sql.ErrNoRows
}
+5 -5
View File
@@ -70,15 +70,15 @@ func (manager *SStandaloneResourceBaseManager) ValidateName(name string) error {
}
func (manager *SStandaloneResourceBaseManager) FetchById(idStr string) (IModel, error) {
return fetchById(manager, idStr)
return FetchById(manager, idStr)
}
func (manager *SStandaloneResourceBaseManager) FetchByName(ownerProjId string, idStr string) (IModel, error) {
return fetchByName(manager, ownerProjId, idStr)
func (manager *SStandaloneResourceBaseManager) FetchByName(userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
return FetchByName(manager, userCred, idStr)
}
func (manager *SStandaloneResourceBaseManager) FetchByIdOrName(ownerProjId string, idStr string) (IModel, error) {
return fetchByIdOrName(manager, ownerProjId, idStr)
func (manager *SStandaloneResourceBaseManager) FetchByIdOrName(userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
return FetchByIdOrName(manager, userCred, idStr)
}
func (manager *SStandaloneResourceBaseManager) FetchByExternalId(idStr string) (IStandaloneModel, error) {
+2 -2
View File
@@ -35,7 +35,7 @@ func init() {
}
func (manager *STenantCacheManager) FetchTenantByIdOrName(ctx context.Context, idStr string) (*STenant, error) {
tenant, err := manager.FetchByIdOrName("", idStr)
tenant, err := manager.FetchByIdOrName(nil, idStr)
if err != nil {
if err == sql.ErrNoRows {
return manager.fetchTenantFromKeystone(ctx, idStr)
@@ -63,7 +63,7 @@ func (manager *STenantCacheManager) FetchTenantById(ctx context.Context, idStr s
}
func (manager *STenantCacheManager) FetchTenantByName(ctx context.Context, idStr string) (*STenant, error) {
tenant, err := manager.FetchByName("", idStr)
tenant, err := manager.FetchByName(nil, idStr)
if err != nil {
if err == sql.ErrNoRows {
return manager.fetchTenantFromKeystone(ctx, idStr)
+2 -2
View File
@@ -29,7 +29,7 @@ func init() {
}
func (manager *SUserCacheManager) FetchUserByIdOrName(idStr string) (*SUser, error) {
obj, err := manager.SKeystoneCacheObjectManager.FetchByIdOrName("", idStr)
obj, err := manager.SKeystoneCacheObjectManager.FetchByIdOrName(nil, idStr)
if err != nil {
return nil, err
}
@@ -45,7 +45,7 @@ func (manager *SUserCacheManager) FetchUserById(idStr string) (*SUser, error) {
}
func (manager *SUserCacheManager) FetchUserByName(idStr string) (*SUser, error) {
obj, err := manager.SKeystoneCacheObjectManager.FetchByName("", idStr)
obj, err := manager.SKeystoneCacheObjectManager.FetchByName(nil, idStr)
if err != nil {
return nil, err
}
+1 -1
View File
@@ -110,7 +110,7 @@ func (manager *SVirtualJointResourceBaseManager) ListItemFilter(ctx context.Cont
}
tenant, _ := query.GetString("tenant")
if len(tenant) > 0 {
tc, _ := TenantCacheManager.FetchByIdOrName("", tenant)
tc, _ := TenantCacheManager.FetchTenantByIdOrName(ctx, tenant)
if tc == nil {
return nil, httperrors.NewTenantNotFoundError(fmt.Sprintf("tenant %s not found", tenant))
}
+5 -5
View File
@@ -56,15 +56,15 @@ func (manager *SVirtualResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, ow
return q
}
func (manager *SVirtualResourceBaseManager) FetchByName(ownerProjId string, idStr string) (IModel, error) {
return fetchByName(manager, ownerProjId, idStr)
func (manager *SVirtualResourceBaseManager) FetchByName(userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
return FetchByName(manager, userCred, idStr)
}
func (manager *SVirtualResourceBaseManager) FetchByIdOrName(ownerProjId string, idStr string) (IModel, error) {
return fetchByIdOrName(manager, ownerProjId, idStr)
func (manager *SVirtualResourceBaseManager) FetchByIdOrName(userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
return FetchByIdOrName(manager, userCred, idStr)
}
func (manager *SVirtualResourceBaseManager) GetOwnerId(userCred mcclient.TokenCredential) string {
func (manager *SVirtualResourceBaseManager) GetOwnerId(userCred mcclient.IIdentityProvider) string {
return userCred.GetProjectId()
}
+1 -1
View File
@@ -23,7 +23,7 @@ func (cs Choices) Has(choice string) bool {
func (cs Choices) String() string {
choices := make([]string, len(cs))
i := 0
for choice, _ := range cs {
for choice := range cs {
choices[i] = choice
i++
}
+14 -1
View File
@@ -322,11 +322,24 @@ type ValidatorModelIdOrName struct {
Validator
ModelKeyword string
ProjectId string
UserId string
ModelManager db.IModelManager
Model db.IModel
modelIdKey string
}
func (v *ValidatorModelIdOrName) GetProjectId() string {
return v.ProjectId
}
func (v *ValidatorModelIdOrName) GetUserId() string {
return v.UserId
}
func (v *ValidatorModelIdOrName) GetTenantId() string {
return v.ProjectId
}
func (v *ValidatorModelIdOrName) getValue() interface{} {
return v.Model
}
@@ -361,7 +374,7 @@ func (v *ValidatorModelIdOrName) validate(data *jsonutils.JSONDict) error {
return newModelManagerError(v.ModelKeyword)
}
v.ModelManager = modelManager
model, err := modelManager.FetchByIdOrName(v.ProjectId, modelIdOrName)
model, err := modelManager.FetchByIdOrName(v, modelIdOrName)
if err != nil {
return newModelNotFoundError(v.ModelKeyword, modelIdOrName, err)
}
+3 -1
View File
@@ -135,7 +135,7 @@ type ICloudHost interface {
GetManagerId() string
CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, vswitchId string, ipAddr string, desc string,
passwd string, storageType string, diskSizes []int, publicKey string, extSecGrpId string) (ICloudVM, error)
passwd string, storageType string, diskSizes []int, publicKey string, extSecGrpId string, userData string) (ICloudVM, error)
}
type ICloudVM interface {
@@ -174,6 +174,8 @@ type ICloudVM interface {
UpdateVM(name string) error
UpdateUserData(userData string) error
RebuildRoot(imageId string, passwd string, publicKey string, sysSizeGB int) (string, error)
DeployVM(name string, password string, publicKey string, deleteKeypair bool, description string) error
+22 -1
View File
@@ -139,6 +139,12 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
publicKey, _ := config.GetString("public_key")
adminPublicKey, _ := config.GetString("admin_public_key")
projectPublicKey, _ := config.GetString("project_public_key")
oUserData, _ := config.GetString("user_data")
userData := generateUserData(adminPublicKey, projectPublicKey, oUserData)
resetPassword := jsonutils.QueryBoolean(config, "reset_password", false)
passwd, _ := config.GetString("password")
if resetPassword && len(passwd) == 0 {
@@ -176,7 +182,7 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
}
iVM, err := ihost.CreateVM(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.Cpu, desc.Memory, desc.ExternalNetworkId,
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgrpId)
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgrpId, userData)
if err != nil {
return nil, err
}
@@ -282,6 +288,13 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
if len(userData) > 0 {
err := iVM.UpdateUserData(userData)
if err != nil {
log.Errorf("update userdata fail %s", err)
}
}
err := iVM.DeployVM(name, passwd, publicKey, deleteKeypair, description)
if err != nil {
return nil, err
@@ -306,6 +319,7 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
return data, nil
})
} else if action == "rebuild" {
iVM, err := ihost.GetIVMById(guest.GetExternalId())
if err != nil || iVM == nil {
log.Errorf("cannot find vm %s", err)
@@ -313,6 +327,13 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
}
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
if len(userData) > 0 {
err := iVM.UpdateUserData(userData)
if err != nil {
log.Errorf("update userdata fail %s", err)
}
}
diskId, err := iVM.RebuildRoot(desc.ExternalImageId, passwd, publicKey, desc.SysDiskSize)
if err != nil {
return nil, err
+8 -1
View File
@@ -70,6 +70,13 @@ func (self *SAzureGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gue
if resetPassword && len(passwd) == 0 {
passwd = seclib2.RandomPassword2(12)
}
adminPublicKey, _ := config.GetString("admin_public_key")
projectPublicKey, _ := config.GetString("project_public_key")
oUserData, _ := config.GetString("user_data")
userData := generateUserData(adminPublicKey, projectPublicKey, oUserData)
desc := SManagedVMCreateConfig{}
if err := config.Unmarshal(&desc, "desc"); err != nil {
return err
@@ -98,7 +105,7 @@ func (self *SAzureGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gue
}
if iVM, err := ihost.CreateVM(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.Cpu, desc.Memory, desc.ExternalNetworkId,
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgrpId); err != nil {
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgrpId, userData); err != nil {
return nil, err
} else {
log.Debugf("VMcreated %s, wait status running ...", iVM.GetGlobalId())
+32
View File
@@ -0,0 +1,32 @@
package guestdrivers
import (
"yunion.io/x/onecloud/pkg/util/ansible"
"yunion.io/x/onecloud/pkg/util/cloudinit"
)
func generateUserData(adminPublicKey, projectPublicKey, oUserData string) string {
var oCloudConfig *cloudinit.SCloudConfig = nil
if len(oUserData) > 0 {
oCloudConfig, _ = cloudinit.ParseUserDataBase64(oUserData)
}
ansibleUser := cloudinit.NewUser(ansible.PUBLIC_CLOUD_ANSIBLE_USER)
ansibleUser.SshKey(adminPublicKey).SshKey(projectPublicKey).SudoPolicy(cloudinit.USER_SUDO_NOPASSWD)
cloudConfig := cloudinit.SCloudConfig{
DisableRoot: 0,
SshPwauth: 1,
Users: []cloudinit.SUser{
ansibleUser,
},
}
if oCloudConfig != nil {
cloudConfig.Merge(oCloudConfig)
}
return cloudConfig.UserDataBase64()
}
+2
View File
@@ -11,6 +11,7 @@ import (
"yunion.io/x/onecloud/pkg/compute/capabilities"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/compute/specs"
"yunion.io/x/onecloud/pkg/compute/sshkeys"
"yunion.io/x/onecloud/pkg/compute/usages"
)
@@ -21,6 +22,7 @@ func InitHandlers(app *appsrv.Application) {
usages.AddUsageHandler("", app)
capabilities.AddCapabilityHandler("", app)
specs.AddSpecHandler("", app)
sshkeys.AddSshKeysHandler("", app)
taskman.AddTaskHandler("", app)
+3 -3
View File
@@ -4,12 +4,12 @@ import "time"
const (
BILLING_TYPE_POSTPAID = "postpaid"
BILLING_TYPE_PREPAID = "prepaid"
BILLING_TYPE_PREPAID = "prepaid"
)
type SBillingResourceBase struct {
BillingType string `width:"36" charset:"ascii" nullable:"true" default:"postpaid" list:"user" create:"optional"`
ExpiredAt time.Time `nullable:"true" list:"user" create:"optional"`
BillingType string `width:"36" charset:"ascii" nullable:"true" default:"postpaid" list:"user" create:"optional"`
ExpiredAt time.Time `nullable:"true" list:"user" create:"optional"`
}
func (self *SBillingResourceBase) GetChargeType() string {
+47 -84
View File
@@ -14,6 +14,7 @@ import (
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -49,7 +50,7 @@ type SCloudaccount struct {
Provider string `width:"64" charset:"ascii" list:"admin" create:"admin_required"`
}
func (self *SCloudaccount) getCloudproviders() []SCloudprovider {
func (self *SCloudaccount) GetCloudproviders() []SCloudprovider {
cloudproviders := []SCloudprovider{}
q := CloudproviderManager.Query().Equals("cloudaccount_id", self.Id)
if err := db.FetchModelObjects(CloudproviderManager, q, &cloudproviders); err != nil {
@@ -62,7 +63,7 @@ func (self *SCloudaccount) ValidateDeleteCondition(ctx context.Context) error {
if self.Enabled {
return httperrors.NewInvalidStatusError("account is enabled")
}
if len(self.getCloudproviders()) > 0 {
if len(self.GetCloudproviders()) > 0 {
return httperrors.NewNotEmptyError("Not an empty cloud account")
}
return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx)
@@ -95,7 +96,7 @@ func (self *SCloudaccountManager) ValidateCreateData(ctx context.Context, userCr
return nil, httperrors.NewConflictError("The account has been registered")
}
if subAccount, err := getSubAccounts(name, url, account, secret, provider); err != nil {
if subAccount, err := GetSubAccounts(name, url, account, secret, provider); err != nil {
return nil, err
} else if accounts, err := subAccount.GetArray("data"); err != nil {
return nil, err
@@ -108,8 +109,8 @@ func (self *SCloudaccountManager) ValidateCreateData(ctx context.Context, userCr
func (self *SCloudaccount) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.SEnabledStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerProjId, query, data)
self.savePassword(self.Secret)
if subAccounts, err := data.GetArray("accounts"); err == nil && len(subAccounts) > 0 {
_import, _ := data.Bool("import")
if subAccounts, err := data.GetArray("accounts"); err == nil && _import && len(subAccounts) > 0 {
for _, subAccount := range subAccounts {
name, _ := subAccount.GetString("name")
account, _ := subAccount.GetString("account")
@@ -183,7 +184,7 @@ func (self *SCloudaccount) PerformSync(ctx context.Context, userCred mcclient.To
return nil, httperrors.NewInputParameterError("invalid input %s", err)
}
if self.CanSync() || syncRange.Force {
err = self.startSyncCloudProviderInfoTask(ctx, userCred, nil, "")
err = self.startSyncCloudProviderInfoTask(ctx, userCred, &syncRange, "")
}
return nil, err
}
@@ -220,6 +221,18 @@ func (self *SCloudaccount) PerformUpdateCredential(ctx context.Context, userCred
changed = true
}
if (len(account) > 0 && account != self.Account) || (len(accessUrl) > 0 && accessUrl != self.AccessUrl) {
for _, cloudprovider := range self.GetCloudproviders() {
if cloudprovider.Account == self.Account {
if len(account) > 0 {
if _, err = cloudprovider.GetModelManager().TableSpec().Update(&cloudprovider, func() error {
cloudprovider.Account = account
return nil
}); err != nil {
return nil, err
}
}
}
}
_, err = self.GetModelManager().TableSpec().Update(self, func() error {
if len(account) > 0 {
self.Account = account
@@ -242,15 +255,16 @@ func (self *SCloudaccount) PerformUpdateCredential(ctx context.Context, userCred
}
func (self *SCloudaccount) startSyncCloudProviderInfoTask(ctx context.Context, userCred mcclient.TokenCredential, syncRange *SSyncRange, parentTaskId string) error {
for _, cloudprovider := range self.getCloudproviders() {
params := jsonutils.NewDict()
if syncRange != nil {
params.Add(jsonutils.Marshal(syncRange), "sync_range")
}
if cloudprovider.Enabled {
cloudprovider.startSyncCloudProviderInfoTask(ctx, userCred, nil, "")
}
params := jsonutils.NewDict()
if syncRange != nil {
params.Add(jsonutils.Marshal(syncRange), "sync_range")
}
task, err := taskman.TaskManager.NewTask(ctx, "CloudAccountSyncInfoTask", self, userCred, params, parentTaskId, "", nil)
if err != nil {
log.Errorf("startSyncCloudAccountInfoTask newTask error %s", err)
return err
}
task.ScheduleRun(nil)
return nil
}
@@ -288,10 +302,16 @@ func (self *SCloudaccount) AllowPerformImport(ctx context.Context, userCred mccl
return userCred.IsSystemAdmin()
}
func (self *SCloudaccount) PerformImport(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
func (self *SCloudaccount) GetSubAccounts() (jsonutils.JSONObject, error) {
if secret, err := self.getPassword(); err != nil {
return nil, err
} else if subAccounts, err := getSubAccounts(self.Name, self.AccessUrl, self.Account, secret, self.Provider); err != nil {
} else {
return GetSubAccounts(self.Name, self.AccessUrl, self.Account, secret, self.Provider)
}
}
func (self *SCloudaccount) PerformImport(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if subAccounts, err := self.GetSubAccounts(); err != nil {
return nil, err
} else if accounts, err := subAccounts.GetArray("data"); err != nil {
return nil, err
@@ -321,74 +341,16 @@ func (self *SCloudaccount) PerformImport(ctx context.Context, userCred mcclient.
return nil, err
}
if enabled {
newCloudprovider.startSyncCloudProviderInfoTask(ctx, userCred, &SSyncRange{FullSync: true}, "")
newCloudprovider.StartSyncCloudProviderInfoTask(ctx, userCred, &SSyncRange{FullSync: true}, "")
}
}
}
}
}
return jsonutils.NewDict(), nil
return nil, nil
}
// func (self *SCloudaccount) PerformGetSubAccounts(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
// if !self.Enabled {
// return nil, httperrors.NewInvalidStatusError("Account disabled")
// }
// if provider, err := self.GetDriver(); err != nil {
// return nil, err
// } else if _subAccounts, err := provider.GetSubAccounts(); err != nil {
// return nil, err
// } else {
// result := jsonutils.NewDict()
// data := jsonutils.NewArray()
// accounts := []string{}
// for _, account := range self.getCloudproviders() {
// accounts = append(accounts, account.Account)
// _account := jsonutils.NewDict()
// _account.Add(jsonutils.NewString(account.Account), "account")
// _account.Add(jsonutils.NewString(account.Name), "name")
// _account.Add(jsonutils.JSONTrue, "exist")
// data.Add(_account)
// }
// if _subAccounts != nil {
// if subAccounts, err := _subAccounts.GetArray("data"); err != nil {
// return nil, err
// } else {
// for _, subAccount := range subAccounts {
// if account, err := subAccount.GetString("account"); err != nil {
// log.Errorf("Get subAccount error %v", err)
// } else if !utils.IsInStringArray(account, accounts) {
// _account := subAccount.(*jsonutils.JSONDict)
// _account.Add(jsonutils.JSONFalse, "exist")
// data.Add(_account)
// }
// }
// }
// }
// result.Add(data, "data")
// result.Add(jsonutils.NewInt(int64(data.Length())), "total")
// return result, nil
// }
// }
// func (manager *SCloudaccountManager) AllowPerformGetSubAccounts(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
// return userCred.IsSystemAdmin()
// }
// func (manager *SCloudaccountManager) PerformGetSubAccounts(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
// name, _ := data.GetString("name")
// accessUrl, _ := data.GetString("access_url")
// account, _ := data.GetString("account")
// secret, _ := data.GetString("secret")
// _provider, _ := data.GetString("provider")
// if provider, err := cloudprovider.GetProvider("", name, accessUrl, account, secret, _provider); err != nil {
// return nil, err
// } else {
// return provider.GetSubAccounts()
// }
// }
func getSubAccounts(name, accessUrl, account, secret, provider string) (jsonutils.JSONObject, error) {
func GetSubAccounts(name, accessUrl, account, secret, provider string) (jsonutils.JSONObject, error) {
if provider, err := cloudprovider.GetProvider("", name, accessUrl, account, secret, provider); err != nil {
return nil, err
} else {
@@ -403,27 +365,28 @@ func (self *SCloudaccount) SaveSysInfo(info jsonutils.JSONObject) {
})
}
func (manager *SCloudaccountManager) FetchCloudproviderById(providerId string) *SCloudprovider {
providerObj, err := manager.FetchById(providerId)
func (manager *SCloudaccountManager) FetchCloudaccountById(accountId string) *SCloudaccount {
providerObj, err := manager.FetchById(accountId)
if err != nil {
log.Errorf("%s", err)
return nil
}
return providerObj.(*SCloudprovider)
return providerObj.(*SCloudaccount)
}
func (manager *SCloudaccountManager) FetchCloudproviderByIdOrName(providerId string) *SCloudprovider {
providerObj, err := manager.FetchByIdOrName("", providerId)
func (manager *SCloudaccountManager) FetchCloudaccountByIdOrName(accountId string) *SCloudaccount {
providerObj, err := manager.FetchByIdOrName(nil, accountId)
if err != nil {
if err != sql.ErrNoRows {
log.Errorf("%s", err)
}
return nil
}
return providerObj.(*SCloudprovider)
return providerObj.(*SCloudaccount)
}
func (self *SCloudaccount) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict {
extra.Add(jsonutils.Marshal(self.GetCloudproviders()), "accounts")
return extra
}
@@ -446,7 +409,7 @@ func (manager *SCloudaccountManager) InitializeData() error {
}
newAccounts := map[string]string{}
for _, cloudprovider := range cloudproviders {
Account, providerAccount, providerName := cloudprovider.Account, cloudprovider.Account, cloudprovider.Name
Account, providerAccount, providerName := cloudprovider.Account, "", cloudprovider.Name
if cloudprovider.Provider == CLOUD_PROVIDER_AZURE {
if accountInfo := strings.Split(cloudprovider.Account, "/"); len(accountInfo) == 2 {
if _, ok := newAccounts[accountInfo[0]]; ok {
+49 -13
View File
@@ -4,12 +4,16 @@ import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/pkg/util/timeutils"
"yunion.io/x/pkg/utils"
@@ -51,7 +55,9 @@ type SCloudprovider struct {
Account string `width:"128" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
Secret string `width:"256" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
CloudaccountId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" key_index:"true""`
CloudaccountId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" key_index:"true"`
ProjectId string `name:"tenant_id" width:"128" charset:"ascii" nullable:"true" list:"admin"`
LastSync time.Time `get:"admin" list:"admin"` // = Column(DateTime, nullable=True)
@@ -122,6 +128,35 @@ func (self *SCloudprovider) CanSync() bool {
}
}
func (self *SCloudprovider) SyncProject() (err error) {
projectId := ""
if len(self.ProjectId) == 0 && len(self.Name) > 0 && self.Provider == CLOUD_PROVIDER_AZURE {
s := auth.GetAdminSession(options.Options.Region, "")
if project, err := modules.Projects.GetByName(s, self.Name, nil); err == nil {
if projectId, err = project.GetString("id"); err != nil {
return err
}
} else if strings.Index(err.Error(), "404 NotFoundError") > 0 {
if project, err := modules.Projects.Create(s, jsonutils.Marshal(map[string]string{"name": self.Name})); err != nil {
return err
} else if projectId, err = project.GetString("id"); err != nil {
return err
}
} else {
return err
}
if len(projectId) > 0 {
if _, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.ProjectId = projectId
return nil
}); err != nil {
return err
}
}
}
return nil
}
type SSyncRange struct {
Force bool
FullSync bool
@@ -148,7 +183,7 @@ func (sr *SSyncRange) NeedSyncInfo() bool {
func (sr *SSyncRange) normalizeRegionIds() error {
for i := 0; i < len(sr.Region); i += 1 {
obj, err := CloudregionManager.FetchByIdOrName("", sr.Region[i])
obj, err := CloudregionManager.FetchByIdOrName(nil, sr.Region[i])
if err != nil {
if err == sql.ErrNoRows {
return httperrors.NewResourceNotFoundError("Region %s not found", sr.Region[i])
@@ -163,7 +198,7 @@ func (sr *SSyncRange) normalizeRegionIds() error {
func (sr *SSyncRange) normalizeZoneIds() error {
for i := 0; i < len(sr.Zone); i += 1 {
obj, err := ZoneManager.FetchByIdOrName("", sr.Zone[i])
obj, err := ZoneManager.FetchByIdOrName(nil, sr.Zone[i])
if err != nil {
if err == sql.ErrNoRows {
return httperrors.NewResourceNotFoundError("Zone %s not found", sr.Zone[i])
@@ -178,7 +213,7 @@ func (sr *SSyncRange) normalizeZoneIds() error {
func (sr *SSyncRange) normalizeHostIds() error {
for i := 0; i < len(sr.Host); i += 1 {
obj, err := HostManager.FetchByIdOrName("", sr.Host[i])
obj, err := HostManager.FetchByIdOrName(nil, sr.Host[i])
if err != nil {
if err == sql.ErrNoRows {
return httperrors.NewResourceNotFoundError("Host %s not found", sr.Host[i])
@@ -227,12 +262,15 @@ func (self *SCloudprovider) PerformSync(ctx context.Context, userCred mcclient.T
return nil, httperrors.NewInputParameterError("invalid input %s", err)
}
if self.CanSync() || syncRange.Force {
err = self.startSyncCloudProviderInfoTask(ctx, userCred, &syncRange, "")
err = self.StartSyncCloudProviderInfoTask(ctx, userCred, &syncRange, "")
}
return nil, err
}
func (self *SCloudprovider) startSyncCloudProviderInfoTask(ctx context.Context, userCred mcclient.TokenCredential, syncRange *SSyncRange, parentTaskId string) error {
func (self *SCloudprovider) StartSyncCloudProviderInfoTask(ctx context.Context, userCred mcclient.TokenCredential, syncRange *SSyncRange, parentTaskId string) error {
if err := self.SyncProject(); err != nil {
log.Errorf("Sync cloudprovider project error: %v", err)
}
params := jsonutils.NewDict()
if syncRange != nil {
params.Add(jsonutils.Marshal(syncRange), "sync_range")
@@ -265,12 +303,10 @@ type SAccount struct {
}
func (self *SCloudprovider) getCloudaccount() (*SCloudaccount, error) {
cloudaccount := &SCloudaccount{}
q := CloudaccountManager.Query().Equals("id", self.CloudaccountId)
if err := db.FetchModelObjects(CloudaccountManager, q, cloudaccount); err != nil {
return nil, err
if cloudaccount := CloudaccountManager.FetchCloudaccountById(self.CloudaccountId); cloudaccount != nil {
return cloudaccount, nil
}
return cloudaccount, nil
return nil, fmt.Errorf("Failed to find cloud account for cloud provider %s", self.Name)
}
func (self *SCloudprovider) getAccount() (*SAccount, error) {
@@ -283,7 +319,7 @@ func (self *SCloudprovider) getAccount() (*SAccount, error) {
} else {
account.Secret = passwd
}
if account.Account != self.Account {
if len(self.Account) > 0 && self.Account != cloudaccount.Account {
account.Account = fmt.Sprintf("%s/%s", account.Account, self.Account)
}
return &account, nil
@@ -320,7 +356,7 @@ func (manager *SCloudproviderManager) FetchCloudproviderById(providerId string)
}
func (manager *SCloudproviderManager) FetchCloudproviderByIdOrName(providerId string) *SCloudprovider {
providerObj, err := manager.FetchByIdOrName("", providerId)
providerObj, err := manager.FetchByIdOrName(nil, providerId)
if err != nil {
if err != sql.ErrNoRows {
log.Errorf("%s", err)
+23 -10
View File
@@ -38,6 +38,7 @@ const (
DISK_STARTALLOC = "start_alloc"
DISK_ALLOCATING = "allocating"
DISK_READY = "ready"
DISK_RESET = "reset"
DISK_DEALLOC = "deallocating"
DISK_DEALLOC_FAILED = "dealloc_failed"
DISK_UNKNOWN = "unknown"
@@ -155,7 +156,7 @@ func (manager *SDiskManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
storageStr := jsonutils.GetAnyString(queryDict, []string{"storage", "storage_id"})
if len(storageStr) > 0 {
storageObj, err := StorageManager.FetchByIdOrName(userCred.GetProjectId(), storageStr)
storageObj, err := StorageManager.FetchByIdOrName(userCred, storageStr)
if err != nil {
return nil, httperrors.NewResourceNotFoundError("storage %s not found: %s", storageStr, err)
}
@@ -391,10 +392,8 @@ func (self *SDisk) CleanUpDiskSnapshots(ctx context.Context, userCred mcclient.T
convertSnapshots := jsonutils.NewArray()
deleteSnapshots := jsonutils.NewArray()
for i := 0; i < len(dest); i++ {
if dest[i].CreatedBy == MANUAL && !dest[i].FakeDeleted {
if !dest[i].OutOfChain {
convertSnapshots.Add(jsonutils.NewString(dest[i].Id))
}
if !dest[i].FakeDeleted && !dest[i].OutOfChain {
convertSnapshots.Add(jsonutils.NewString(dest[i].Id))
} else {
deleteSnapshots.Add(jsonutils.NewString(dest[i].Id))
}
@@ -416,6 +415,9 @@ func (self *SDisk) AllowPerformDiskReset(ctx context.Context, userCred mcclient.
}
func (self *SDisk) PerformDiskReset(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if self.Status != DISK_READY {
return nil, httperrors.NewInvalidStatusError("Cannot reset disk in status %s", self.Status)
}
snapshotId, err := data.GetString("snapshot_id")
if err != nil {
return nil, err
@@ -436,13 +438,16 @@ func (self *SDisk) PerformDiskReset(ctx context.Context, userCred mcclient.Token
if snapshot.Status != SNAPSHOT_READY {
return nil, httperrors.NewBadRequestError("Cannot reset disk with snapshot in status %s", snapshot.Status)
}
self.StartResetDisk(ctx, userCred, snapshotId)
autoStart := jsonutils.QueryBoolean(data, "auto_start", false)
self.StartResetDisk(ctx, userCred, snapshotId, autoStart)
return nil, nil
}
func (self *SDisk) StartResetDisk(ctx context.Context, userCred mcclient.TokenCredential, snapshotId string) error {
func (self *SDisk) StartResetDisk(ctx context.Context, userCred mcclient.TokenCredential, snapshotId string, autoStart bool) error {
self.SetStatus(userCred, DISK_RESET, "")
params := jsonutils.NewDict()
params.Set("snapshot_id", jsonutils.NewString(snapshotId))
params.Set("auto_start", jsonutils.NewBool(autoStart))
task, err := taskman.TaskManager.NewTask(ctx, "DiskResetTask", self, userCred, params, "", "", nil)
if err != nil {
return err
@@ -732,7 +737,11 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
self.ExpiredAt = extDisk.GetExpiredAt()
self.ProjectId = userCred.GetProjectId()
if manageId := extDisk.GetIStorge().GetManagerId(); len(manageId) > 0 {
if provider := CloudproviderManager.FetchCloudproviderById(manageId); provider != nil {
self.ProjectId = provider.ProjectId
}
}
return nil
})
if err != nil {
@@ -765,7 +774,11 @@ func (manager *SDiskManager) newFromCloudDisk(ctx context.Context, userCred mccl
disk.ExternalId = extDisk.GetGlobalId()
disk.StorageId = storage.Id
disk.ProjectId = userCred.GetProjectId()
if manageId := extDisk.GetIStorge().GetManagerId(); len(manageId) > 0 {
if provider := CloudproviderManager.FetchCloudproviderById(manageId); provider != nil {
disk.ProjectId = provider.ProjectId
}
}
disk.DiskFormat = extDisk.GetDiskFormat()
disk.DiskSize = extDisk.GetDiskSizeMB()
disk.AutoDelete = extDisk.GetIsAutoDelete()
@@ -1249,7 +1262,7 @@ func (manager *SDiskManager) AutoDiskSnapshot(ctx context.Context, userCred mccl
continue
}
// name
name := guests[0].Name + time.Now().Format("2006-01-02#15:04:05")
name := "Auto-" + guests[0].Name + time.Now().Format("2006-01-02#15:04:05")
snap, err := SnapshotManager.CreateSnapshot(ctx, userCred, AUTO, disk.Id, guests[0].Id, "", name)
if err != nil {
log.Errorln(err)
+16 -7
View File
@@ -84,7 +84,7 @@ func (manager *SElasticipManager) ListItemFilter(ctx context.Context, q *sqlchem
managerFilter, _ := query.GetString("manager")
if len(managerFilter) > 0 {
managerI, err := CloudproviderManager.FetchByIdOrName(userCred.GetProjectId(), managerFilter)
managerI, err := CloudproviderManager.FetchByIdOrName(userCred, managerFilter)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("cloud provider %s not found", managerFilter)
@@ -97,7 +97,7 @@ func (manager *SElasticipManager) ListItemFilter(ctx context.Context, q *sqlchem
regionFilter, _ := query.GetString("region")
if len(regionFilter) > 0 {
regionObj, err := CloudregionManager.FetchByIdOrName(userCred.GetProjectId(), regionFilter)
regionObj, err := CloudregionManager.FetchByIdOrName(userCred, regionFilter)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("cloud region %s not found", regionFilter)
@@ -232,7 +232,12 @@ func (self *SElasticip) SyncWithCloudEip(userCred mcclient.TokenCredential, ext
self.ExternalId = ext.GetGlobalId()
// self.ManagerId = ext.GetManagerId()
self.IsEmulated = ext.IsEmulated()
// self.ProjectId = userCred.GetProjectId()
self.ProjectId = userCred.GetProjectId()
if manageId := ext.GetManagerId(); len(manageId) > 0 {
if provider := CloudproviderManager.FetchCloudproviderById(manageId); provider != nil {
self.ProjectId = provider.ProjectId
}
}
self.ChargeType = ext.GetInternetChargeType()
return nil
@@ -258,7 +263,11 @@ func (manager *SElasticipManager) newFromCloudEip(userCred mcclient.TokenCredent
eip.ChargeType = extEip.GetInternetChargeType()
eip.ProjectId = userCred.GetProjectId()
if manageId := extEip.GetManagerId(); len(manageId) > 0 {
if provider := CloudproviderManager.FetchCloudproviderById(manageId); provider != nil {
eip.ProjectId = provider.ProjectId
}
}
err := manager.TableSpec().Insert(&eip)
if err != nil {
log.Errorf("newFromCloudEip fail %s", err)
@@ -362,7 +371,7 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
if len(regionStr) == 0 {
return nil, httperrors.NewInputParameterError("Missing region/region_id")
}
region, err := CloudregionManager.FetchByIdOrName("", regionStr)
region, err := CloudregionManager.FetchByIdOrName(nil, regionStr)
if err != nil {
if err != sql.ErrNoRows {
return nil, httperrors.NewGeneralError(err)
@@ -377,7 +386,7 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
return nil, httperrors.NewInputParameterError("Missing manager/manager_id")
}
provider, err := CloudproviderManager.FetchByIdOrName("", managerStr)
provider, err := CloudproviderManager.FetchByIdOrName(nil, managerStr)
if err != nil {
if err != sql.ErrNoRows {
return nil, httperrors.NewGeneralError(err)
@@ -490,7 +499,7 @@ func (self *SElasticip) PerformAssociate(ctx context.Context, userCred mcclient.
return nil, httperrors.NewInputParameterError("Unsupported %s", instanceType)
}
vmObj, err := GuestManager.FetchByIdOrName(userCred.GetProjectId(), instanceId)
vmObj, err := GuestManager.FetchByIdOrName(userCred, instanceId)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("server %s not found", instanceId)
+1 -1
View File
@@ -578,4 +578,4 @@ func (manager *SGuestnetworkManager) getRecentlyReleasedIPAddresses(networkId st
}
}
return ret
}
}
+105 -22
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"database/sql"
"encoding/base64"
"fmt"
"net/http"
"strconv"
@@ -29,14 +30,17 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/seclib2"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/compute/sshkeys"
)
const (
@@ -222,7 +226,7 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
hostFilter, _ := queryDict.GetString("host")
if len(hostFilter) > 0 {
host, _ := HostManager.FetchByIdOrName("", hostFilter)
host, _ := HostManager.FetchByIdOrName(nil, hostFilter)
if host == nil {
return nil, httperrors.NewResourceNotFoundError("host %s not found", hostFilter)
}
@@ -231,7 +235,7 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
secgrpFilter, _ := queryDict.GetString("secgroup")
if len(secgrpFilter) > 0 {
secgrp, _ := SecurityGroupManager.FetchByIdOrName("", secgrpFilter)
secgrp, _ := SecurityGroupManager.FetchByIdOrName(nil, secgrpFilter)
if secgrp == nil {
return nil, httperrors.NewResourceNotFoundError("secgroup %s not found", secgrpFilter)
}
@@ -240,7 +244,7 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
zoneFilter, _ := queryDict.GetString("zone")
if len(zoneFilter) > 0 {
zone, _ := ZoneManager.FetchByIdOrName("", zoneFilter)
zone, _ := ZoneManager.FetchByIdOrName(nil, zoneFilter)
if zone == nil {
return nil, httperrors.NewResourceNotFoundError("zone %s not found", zoneFilter)
}
@@ -253,7 +257,7 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
wireFilter, _ := queryDict.GetString("wire")
if len(wireFilter) > 0 {
wire, _ := WireManager.FetchByIdOrName("", wireFilter)
wire, _ := WireManager.FetchByIdOrName(nil, wireFilter)
if wire == nil {
return nil, httperrors.NewResourceNotFoundError("wire %s not found", wireFilter)
}
@@ -265,7 +269,7 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
networkFilter, _ := queryDict.GetString("network")
if len(networkFilter) > 0 {
netI, _ := NetworkManager.FetchByIdOrName(userCred.GetProjectId(), networkFilter)
netI, _ := NetworkManager.FetchByIdOrName(userCred, networkFilter)
if netI == nil {
return nil, httperrors.NewResourceNotFoundError("network %s not found", networkFilter)
}
@@ -279,7 +283,7 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
diskFilter, _ := queryDict.GetString("disk")
if len(diskFilter) > 0 {
diskI, _ := DiskManager.FetchByIdOrName(userCred.GetProjectId(), diskFilter)
diskI, _ := DiskManager.FetchByIdOrName(userCred, diskFilter)
if diskI == nil {
return nil, httperrors.NewResourceNotFoundError("disk %s not found", diskFilter)
}
@@ -312,7 +316,7 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
managerFilter, _ := queryDict.GetString("manager")
if len(managerFilter) > 0 {
managerI, _ := CloudproviderManager.FetchByIdOrName(userCred.GetProjectId(), managerFilter)
managerI, _ := CloudproviderManager.FetchByIdOrName(userCred, managerFilter)
if managerI == nil {
return nil, httperrors.NewResourceNotFoundError("cloud provider %s not found", managerFilter)
}
@@ -323,7 +327,7 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
regionFilter, _ := queryDict.GetString("region")
if len(regionFilter) > 0 {
regionObj, err := CloudregionManager.FetchByIdOrName(userCred.GetProjectId(), regionFilter)
regionObj, err := CloudregionManager.FetchByIdOrName(userCred, regionFilter)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("cloud region %s not found", regionFilter)
@@ -555,7 +559,7 @@ func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.To
err = self.checkUpdateQuota(ctx, userCred, vcpuCount, vmemSize)
if err != nil {
return nil, err
return nil, httperrors.NewOutOfQuotaError(err.Error())
}
if data.Contains("name") {
@@ -640,7 +644,7 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
if len(bmName) == 0 {
bmName, _ = data.GetString("prefer_baremetal")
}
bmObj, err := HostManager.FetchByIdOrName("", bmName)
bmObj, err := HostManager.FetchByIdOrName(nil, bmName)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("Host %s not found", bmName)
@@ -804,7 +808,7 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
keypairId, _ = data.GetString("keypair_id")
}
if len(keypairId) > 0 {
keypairObj, err := KeypairManager.FetchByIdOrName(userCred.GetUserId(), keypairId)
keypairObj, err := KeypairManager.FetchByIdOrName(userCred, keypairId)
if err != nil {
return nil, httperrors.NewResourceNotFoundError("Keypair %s not found", keypairId)
}
@@ -815,7 +819,7 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
if data.Contains("secgroup") {
secGrpId, _ := data.GetString("secgroup")
secGrpObj, err := SecurityGroupManager.FetchByIdOrName(userCred.GetProjectId(), secGrpId)
secGrpObj, err := SecurityGroupManager.FetchByIdOrName(userCred, secGrpId)
if err != nil {
return nil, httperrors.NewResourceNotFoundError("Secgroup %s not found", secGrpId)
}
@@ -937,6 +941,11 @@ func (guest *SGuest) PostCreate(ctx context.Context, userCred mcclient.TokenCred
if osProfileJson != nil {
guest.setOSProfile(ctx, userCred, osProfileJson)
}
userData, _ := data.GetString("user_data")
if len(userData) > 0 {
guest.setUserData(ctx, userCred, userData)
}
}
func (guest *SGuest) setApptags(ctx context.Context, appTags []string, userCred mcclient.TokenCredential) {
@@ -1344,6 +1353,12 @@ func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.Token
self.Machine = extVM.GetMachine()
self.HostId = host.Id
self.ProjectId = userCred.GetProjectId()
if manageId := extVM.GetIHost().GetManagerId(); len(manageId) > 0 {
if provider := CloudproviderManager.FetchCloudproviderById(manageId); provider != nil {
self.ProjectId = provider.ProjectId
}
}
self.Hypervisor = extVM.GetHypervisor()
self.IsEmulated = extVM.IsEmulated()
@@ -1411,7 +1426,13 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
guest.ExpiredAt = extVM.GetExpiredAt()
guest.HostId = host.Id
guest.ProjectId = userCred.GetProjectId()
if manageId := extVM.GetIHost().GetManagerId(); len(manageId) > 0 {
if provider := CloudproviderManager.FetchCloudproviderById(manageId); provider != nil {
guest.ProjectId = provider.ProjectId
}
}
metaData := extVM.GetMetadata()
@@ -1764,9 +1785,10 @@ func (self *SGuest) PerformDeploy(ctx context.Context, userCred mcclient.TokenCr
if kwargs.Contains("__delete_keypair__") || kwargs.Contains("keypair") {
doRestart = true
var kpId string
if !jsonutils.QueryBoolean(kwargs, "__delete_keypair__", false) {
if kwargs.Contains("keypair") {
keypair, _ := kwargs.GetString("keypair")
iKp, err := KeypairManager.FetchByIdOrName(userCred.GetProjectId(), keypair)
iKp, err := KeypairManager.FetchByIdOrName(userCred, keypair)
if err != nil {
return nil, err
}
@@ -1776,11 +1798,18 @@ func (self *SGuest) PerformDeploy(ctx context.Context, userCred mcclient.TokenCr
kp := iKp.(*SKeypair)
kpId = kp.Id
}
if self.KeypairId != kpId {
okey := self.getKeypair()
if okey != nil {
kwargs.Set("delete_public_key", jsonutils.NewString(okey.PublicKey))
}
self.GetModelManager().TableSpec().Update(self, func() error {
self.KeypairId = kpId
return nil
})
kwargs.Set("reset_password", jsonutils.JSONTrue)
}
}
@@ -1795,6 +1824,7 @@ func (self *SGuest) PerformDeploy(ctx context.Context, userCred mcclient.TokenCr
}
return nil, nil
}
return nil, httperrors.NewServerStatusError("Cannot deploy in status %s", self.Status)
}
@@ -1830,7 +1860,7 @@ func (self *SGuest) PerformAttachdisk(ctx context.Context, userCred mcclient.Tok
if diskId, err := data.GetString("disk_id"); err != nil {
return nil, err
} else {
if disk, err := DiskManager.FetchByIdOrName(userCred.GetProjectId(), diskId); err != nil {
if disk, err := DiskManager.FetchByIdOrName(userCred, diskId); err != nil {
return nil, err
} else if disk == nil {
return nil, httperrors.NewResourceNotFoundError("Disk %s not found", diskId)
@@ -2451,7 +2481,7 @@ func (self *SGuest) PerformAssignSecgroup(ctx context.Context, userCred mcclient
} else {
if secgrp, err := data.GetString("secgrp"); err != nil {
return nil, err
} else if sg, err := SecurityGroupManager.FetchByIdOrName(userCred.GetProjectId(), secgrp); err != nil {
} else if sg, err := SecurityGroupManager.FetchByIdOrName(userCred, secgrp); err != nil {
return nil, httperrors.NewNotFoundError("SecurityGroup %s not found", secgrp)
} else {
if _, err := self.GetModelManager().TableSpec().Update(self, func() error {
@@ -2538,7 +2568,7 @@ func (self *SGuest) PerformRebuildRoot(ctx context.Context, userCred mcclient.To
keypairStr := jsonutils.GetAnyString(data, []string{"keypair", "keypair_id"})
if len(keypairStr) > 0 {
keypairObj, err := KeypairManager.FetchByIdOrName(userCred.GetUserId(), keypairStr)
keypairObj, err := KeypairManager.FetchByIdOrName(userCred, keypairStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("keypair %s not found", keypairStr)
@@ -2680,7 +2710,7 @@ func (self *SGuest) PerformDetachdisk(ctx context.Context, userCred mcclient.Tok
return nil, err
}
keepDisk := jsonutils.QueryBoolean(data, "keep_disk", false)
iDisk, err := DiskManager.FetchByIdOrName(userCred.GetProjectId(), diskId)
iDisk, err := DiskManager.FetchByIdOrName(userCred, diskId)
if err != nil {
return nil, err
}
@@ -2735,7 +2765,7 @@ func (self *SGuest) PerformDetachIsolatedDevice(ctx context.Context, userCred mc
logclient.AddActionLog(self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
return nil, httperrors.NewBadRequestError(msg)
}
iDev, err := IsolatedDeviceManager.FetchByIdOrName(userCred.GetProjectId(), device)
iDev, err := IsolatedDeviceManager.FetchByIdOrName(userCred, device)
if err != nil {
msg := fmt.Sprintf("Isolated device %s not found", device)
logclient.AddActionLog(self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
@@ -2785,7 +2815,7 @@ func (self *SGuest) PerformAttachIsolatedDevice(ctx context.Context, userCred mc
logclient.AddActionLog(self, logclient.ACT_GUEST_ATTACH_ISOLATED_DEVICE, msg, userCred, false)
return nil, httperrors.NewBadRequestError(msg)
}
iDev, err := IsolatedDeviceManager.FetchByIdOrName(userCred.GetProjectId(), device)
iDev, err := IsolatedDeviceManager.FetchByIdOrName(userCred, device)
if err != nil {
msg := fmt.Sprintf("Isolated device %s not found", device)
logclient.AddActionLog(self, logclient.ACT_GUEST_ATTACH_ISOLATED_DEVICE, msg, userCred, false)
@@ -3289,10 +3319,29 @@ func (self *SGuest) GetDeployConfigOnHost(ctx context.Context, host *SHost, para
if keypair != nil {
config.Add(jsonutils.NewString(keypair.PublicKey), "public_key")
}
deletePubKey, _ := params.GetString("delete_public_key")
if len(deletePubKey) > 0 {
config.Add(jsonutils.NewString(deletePubKey), "delete_public_key")
}
} else {
config.Add(jsonutils.JSONFalse, "reset_password")
}
// add default public keys
_, adminPubKey, err := sshkeys.GetSshAdminKeypair(ctx)
if err != nil {
log.Errorf("fail to get ssh admin public key %s", err)
}
_, projPubKey, err := sshkeys.GetSshProjectKeypair(ctx, self.ProjectId)
if err != nil {
log.Errorf("fail to get ssh project public key %s", err)
}
config.Add(jsonutils.NewString(adminPubKey), "admin_public_key")
config.Add(jsonutils.NewString(projPubKey), "project_public_key")
config.Add(jsonutils.NewString(deployAction), "action")
onFinish := "shutdown"
@@ -4343,7 +4392,7 @@ func (self *SGuest) PerformAssociateEip(ctx context.Context, userCred mcclient.T
if len(eipStr) == 0 {
return nil, httperrors.NewInputParameterError("missing eip or eip_id")
}
eipObj, err := ElasticipManager.FetchByIdOrName(userCred.GetProjectId(), eipStr)
eipObj, err := ElasticipManager.FetchByIdOrName(userCred, eipStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("eip %s not found", eipStr)
@@ -4496,3 +4545,37 @@ func (self *SGuest) getDefaultStorageType() string {
}
return STORAGE_LOCAL
}
func (self *SGuest) setUserData(ctx context.Context, userCred mcclient.TokenCredential, data string) error {
data = base64.StdEncoding.EncodeToString([]byte(data))
if len(data) > 16*1024 {
return fmt.Errorf("User data is limited to 16 KB.")
}
err := self.SetMetadata(ctx, "user_data", data, userCred)
if err != nil {
return err
}
return nil
}
func (self *SGuest) AllowPerformUserData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred)
}
func (self *SGuest) PerformUserData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
userData, err := data.GetString("user_data")
if err != nil {
return nil, httperrors.NewInputParameterError("missing user_data %s", err)
}
err = self.setUserData(ctx, userCred, userData)
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
if len(self.HostId) > 0 {
err = self.StartSyncTask(ctx, userCred, false, "")
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
}
return nil, nil
}
+4 -4
View File
@@ -153,7 +153,7 @@ func (manager *SHostManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
schedTagStr := jsonutils.GetAnyString(query, []string{"schedtag", "schedtag_id"})
if len(schedTagStr) > 0 {
schedTag, _ := SchedtagManager.FetchByIdOrName("", schedTagStr)
schedTag, _ := SchedtagManager.FetchByIdOrName(nil, schedTagStr)
if schedTag == nil {
return nil, httperrors.NewResourceNotFoundError("Schedtag %s not found", schedTagStr)
}
@@ -163,7 +163,7 @@ func (manager *SHostManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
wireStr := jsonutils.GetAnyString(query, []string{"wire", "wire_id"})
if len(wireStr) > 0 {
wire, _ := WireManager.FetchByIdOrName("", wireStr)
wire, _ := WireManager.FetchByIdOrName(nil, wireStr)
if wire == nil {
return nil, httperrors.NewResourceNotFoundError("Wire %s not found", wireStr)
}
@@ -173,7 +173,7 @@ func (manager *SHostManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
storageStr := jsonutils.GetAnyString(query, []string{"storage", "storage_id"})
if len(storageStr) > 0 {
storage, _ := StorageManager.FetchByIdOrName("", storageStr)
storage, _ := StorageManager.FetchByIdOrName(nil, storageStr)
if storage == nil {
return nil, httperrors.NewResourceNotFoundError("Storage %s not found", storageStr)
}
@@ -183,7 +183,7 @@ func (manager *SHostManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
zoneStr := jsonutils.GetAnyString(query, []string{"zone", "zone_id"})
if len(zoneStr) > 0 {
zone, _ := ZoneManager.FetchByIdOrName("", zoneStr)
zone, _ := ZoneManager.FetchByIdOrName(nil, zoneStr)
if zone == nil {
return nil, httperrors.NewResourceNotFoundError("Zone %s not found", zoneStr)
}
+1 -1
View File
@@ -115,7 +115,7 @@ func (manager *SIsolatedDeviceManager) ListItemFilter(ctx context.Context, q *sq
}
zoneStr := jsonutils.GetAnyString(query, []string{"zone", "zone_id"})
if len(zoneStr) > 0 {
zone, _ := ZoneManager.FetchByIdOrName("", zoneStr)
zone, _ := ZoneManager.FetchByIdOrName(nil, zoneStr)
if zone == nil {
return nil, httperrors.NewResourceNotFoundError("Zone %s not found", zoneStr)
}
+77 -8
View File
@@ -4,10 +4,15 @@ import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/sqlchemy"
"golang.org/x/crypto/ssh"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/util/seclib2"
"yunion.io/x/pkg/utils"
)
type SKeypairManager struct {
@@ -23,11 +28,11 @@ func init() {
type SKeypair struct {
db.SStandaloneResourceBase
Scheme string `width:"12" charset:"ascii" nullable:"true" default:"RSA" list:"user" create:"optional"` // Column(VARCHAR(length=12, charset='ascii'), nullable=True, default='RSA')
Fingerprint string `width:"48" charset:"ascii" nullable:"false" list:"user"` // Column(VARCHAR(length=48, charset='ascii'), nullable=False)
PrivateKey string `width:"2048" charset:"ascii" nullable:"false"` // Column(VARCHAR(length=2048, charset='ascii'), nullable=False)
PublicKey string `width:"1024" charset:"ascii" nullable:"false" list:"user"` // Column(VARCHAR(length=1024, charset='ascii'), nullable=False)
OwnerId string `width:"128" charset:"ascii" index:"true" nullable:"false"` // Column(VARCHAR(length=36, charset='ascii'), index=True, nullable=False)
Scheme string `width:"12" charset:"ascii" nullable:"true" default:"RSA" list:"user" create:"required"` // Column(VARCHAR(length=12, charset='ascii'), nullable=True, default='RSA')
Fingerprint string `width:"48" charset:"ascii" nullable:"false" list:"user" create:"required"` // Column(VARCHAR(length=48, charset='ascii'), nullable=False)
PrivateKey string `width:"2048" charset:"ascii" nullable:"false" create:"optional"` // Column(VARCHAR(length=2048, charset='ascii'), nullable=False)
PublicKey string `width:"1024" charset:"ascii" nullable:"false" list:"user" create:"required"` // Column(VARCHAR(length=1024, charset='ascii'), nullable=False)
OwnerId string `width:"128" charset:"ascii" index:"true" nullable:"false" create:"required"` // Column(VARCHAR(length=36, charset='ascii'), index=True, nullable=False)
}
func (manager *SKeypairManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
@@ -100,7 +105,40 @@ func (self *SKeypair) GetLinkedGuestsCount() int {
}
func (manager *SKeypairManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
// XXX: TODO
publicKey, _ := data.GetString("public_key")
if len(publicKey) == 0 {
scheme, _ := data.GetString("scheme")
if len(scheme) > 0 {
if !utils.IsInStringArray(scheme, []string{"RSA", "DSA"}) {
return nil, httperrors.NewInputParameterError("Unsupported scheme %s", scheme)
}
} else {
scheme = "RSA"
}
var privKey, pubKey string
var err error
if scheme == "RSA" {
privKey, pubKey, err = seclib2.GenerateRSASSHKeypair()
} else {
privKey, pubKey, err = seclib2.GenerateDSASSHKeypair()
}
if err != nil {
log.Errorf("fail to generate ssh keypair %s", err)
return nil, httperrors.NewGeneralError(err)
}
publicKey = pubKey
data.Set("public_key", jsonutils.NewString(pubKey))
data.Set("private_key", jsonutils.NewString(privKey))
}
pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey))
if err != nil {
log.Errorf("invalid public key %s", err)
return nil, httperrors.NewInputParameterError("invalid public")
}
data.Set("fingerprint", jsonutils.NewString(ssh.FingerprintLegacyMD5(pubKey)))
data.Set("scheme", jsonutils.NewString(seclib2.GetPublicKeyScheme(pubKey)))
data.Set("owner_id", jsonutils.NewString(userCred.GetUserId()))
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
}
@@ -124,6 +162,37 @@ func (self *SKeypair) GetOwnerProjectId() string {
return self.OwnerId
}
func (manager *SKeypairManager) GetOwnerId(userCred mcclient.TokenCredential) string {
func (manager *SKeypairManager) GetOwnerId(userCred mcclient.IIdentityProvider) string {
return userCred.GetUserId()
}
func (manager *SKeypairManager) FetchByName(userCred mcclient.IIdentityProvider, idStr string) (db.IModel, error) {
return db.FetchByName(manager, userCred, idStr)
}
func (manager *SKeypairManager) FetchByIdOrName(userCred mcclient.IIdentityProvider, idStr string) (db.IModel, error) {
return db.FetchByIdOrName(manager, userCred, idStr)
}
func (keypair *SKeypair) AllowGetDetailsPrivatekey(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return keypair.OwnerId == userCred.GetUserId()
}
func (keypair *SKeypair) GetDetailsPrivatekey(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
retval := jsonutils.NewDict()
if len(keypair.PrivateKey) > 0 {
retval.Add(jsonutils.NewString(keypair.PrivateKey), "private_key")
retval.Add(jsonutils.NewString(keypair.Name), "name")
retval.Add(jsonutils.NewString(keypair.Scheme), "scheme")
_, err := keypair.GetModelManager().TableSpec().Update(keypair, func() error {
keypair.PrivateKey = ""
return nil
})
if err != nil {
return nil, err
}
db.OpsLog.LogEvent(keypair, db.ACT_FETCH, nil, userCred)
}
return retval, nil
}
+18 -9
View File
@@ -493,6 +493,11 @@ func (self *SNetwork) SyncWithCloudNetwork(userCred mcclient.TokenCredential, ex
self.AllocTimoutSeconds = extNet.GetAllocTimeoutSeconds()
self.ProjectId = userCred.GetProjectId()
if manageId := extNet.GetIWire().GetIVpc().GetManagerId(); len(manageId) > 0 {
if provider := CloudproviderManager.FetchCloudproviderById(manageId); provider != nil {
self.ProjectId = provider.ProjectId
}
}
return nil
})
if err != nil {
@@ -519,7 +524,11 @@ func (manager *SNetworkManager) newFromCloudNetwork(userCred mcclient.TokenCrede
net.AllocTimoutSeconds = extNet.GetAllocTimeoutSeconds()
net.ProjectId = userCred.GetProjectId()
if manageId := extNet.GetIWire().GetIVpc().GetManagerId(); len(manageId) > 0 {
if provider := CloudproviderManager.FetchCloudproviderById(manageId); provider != nil {
net.ProjectId = provider.ProjectId
}
}
err := manager.TableSpec().Insert(&net)
if err != nil {
log.Errorf("newFromCloudZone fail %s", err)
@@ -691,7 +700,7 @@ func parseNetworkInfo(userCred mcclient.TokenCredential, info jsonutils.JSONObje
} else if p == "[vip]" {
netConfig.Vip = true
} else {
netObj, err := NetworkManager.FetchByIdOrName(userCred.GetProjectId(), p)
netObj, err := NetworkManager.FetchByIdOrName(userCred, p)
if err != nil {
return nil, err
}
@@ -710,7 +719,7 @@ func (self *SNetwork) getFreeAddressCount() int {
func isValidNetworkInfo(userCred mcclient.TokenCredential, netConfig *SNetworkConfig) error {
if len(netConfig.Network) > 0 {
netObj, err := NetworkManager.FetchByIdOrName(userCred.GetProjectId(), netConfig.Network)
netObj, err := NetworkManager.FetchByIdOrName(userCred, netConfig.Network)
if err != nil {
return httperrors.NewResourceNotFoundError("Network %s not found %s", err)
}
@@ -971,7 +980,7 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
wireStr := jsonutils.GetAnyString(data, []string{"wire", "wire_id"})
if len(wireStr) > 0 {
wireObj, err := WireManager.FetchByIdOrName(userCred.GetProjectId(), wireStr)
wireObj, err := WireManager.FetchByIdOrName(userCred, wireStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewNotFoundError("wire %s not found", wireStr)
@@ -985,7 +994,7 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
if len(zoneStr) > 0 {
vpcStr := jsonutils.GetAnyString(data, []string{"vpc", "vpc_id"})
if len(vpcStr) > 0 {
zoneObj, err := ZoneManager.FetchByIdOrName(userCred.GetProjectId(), zoneStr)
zoneObj, err := ZoneManager.FetchByIdOrName(userCred, zoneStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewNotFoundError("zone %s not found", zoneStr)
@@ -993,7 +1002,7 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
return nil, httperrors.NewInternalServerError("query zone %s error %s", zoneStr, err)
}
}
vpcObj, err := VpcManager.FetchByIdOrName(userCred.GetProjectId(), vpcStr)
vpcObj, err := VpcManager.FetchByIdOrName(userCred, vpcStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewNotFoundError("vpc %s not found", vpcStr)
@@ -1277,7 +1286,7 @@ func (manager *SNetworkManager) ListItemFilter(ctx context.Context, q *sqlchemy.
}
zoneStr, _ := query.GetString("zone")
if len(zoneStr) > 0 {
zoneObj, err := ZoneManager.FetchByIdOrName(userCred.GetProjectId(), zoneStr)
zoneObj, err := ZoneManager.FetchByIdOrName(userCred, zoneStr)
if err != nil {
return nil, httperrors.NewNotFoundError("Zone %s not found", zoneStr)
}
@@ -1286,7 +1295,7 @@ func (manager *SNetworkManager) ListItemFilter(ctx context.Context, q *sqlchemy.
}
vpcStr, _ := query.GetString("vpc")
if len(vpcStr) > 0 {
vpcObj, err := VpcManager.FetchByIdOrName(userCred.GetProjectId(), vpcStr)
vpcObj, err := VpcManager.FetchByIdOrName(userCred, vpcStr)
if err != nil {
return nil, httperrors.NewNotFoundError("VPC %s not found", vpcStr)
}
@@ -1295,7 +1304,7 @@ func (manager *SNetworkManager) ListItemFilter(ctx context.Context, q *sqlchemy.
}
regionStr := jsonutils.GetAnyString(query, []string{"region_id", "region", "cloudregion_id", "cloudregion"})
if len(regionStr) > 0 {
region, err := CloudregionManager.FetchByIdOrName(userCred.GetProjectId(), regionStr)
region, err := CloudregionManager.FetchByIdOrName(userCred, regionStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("cloud region %s not found", regionStr)
+2 -2
View File
@@ -7,9 +7,9 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/pkg/tristate"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/pkg/tristate"
)
var QuotaManager *quotas.SQuotaManager
@@ -278,7 +278,7 @@ func (self *SQuota) Exceed(request quotas.IQuota, quota quotas.IQuota) error {
if sreq.IsolatedDevice > 0 && self.IsolatedDevice > squota.IsolatedDevice {
return ErrOutOfIsolatedDevice
}
if self.Snapshot > squota.Snapshot {
if sreq.Snapshot > 0 && self.Snapshot > squota.Snapshot {
return ErrOutOfSnapshot
}
return nil
+1 -1
View File
@@ -122,7 +122,7 @@ func (manager *SReservedipManager) ListItemFilter(ctx context.Context, q *sqlche
}
network, _ := query.GetString("network")
if len(network) > 0 {
netObj, _ := NetworkManager.FetchByIdOrName(userCred.GetProjectId(), network)
netObj, _ := NetworkManager.FetchByIdOrName(userCred, network)
if netObj == nil {
return nil, httperrors.NewResourceNotFoundError(fmt.Sprintf("network %s not found", network))
}
+1 -1
View File
@@ -59,7 +59,7 @@ func (manager *SSchedtagManager) AllowCreateItem(ctx context.Context, userCred m
func (manager *SSchedtagManager) ValidateSchedtags(userCred mcclient.TokenCredential, schedtags map[string]string) (map[string]string, error) {
ret := make(map[string]string)
for tag, act := range schedtags {
schedtagObj, err := manager.FetchByIdOrName("", tag)
schedtagObj, err := manager.FetchByIdOrName(nil, tag)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("Invalid schedtag %s", tag)
+2 -2
View File
@@ -98,7 +98,7 @@ func (manager *SSecurityGroupRuleManager) ListItemFilter(ctx context.Context, q
return nil, err
}
if defsecgroup, _ := query.GetString("secgroup"); len(defsecgroup) > 0 {
if secgroup, _ := SecurityGroupManager.FetchByIdOrName(userCred.GetProjectId(), defsecgroup); secgroup != nil {
if secgroup, _ := SecurityGroupManager.FetchByIdOrName(userCred, defsecgroup); secgroup != nil {
sql = sql.Equals("secgroup_id", secgroup.GetId())
} else {
return nil, httperrors.NewNotFoundError(fmt.Sprintf("Security Group %s not found", defsecgroup))
@@ -130,7 +130,7 @@ func (manager *SSecurityGroupRuleManager) ValidateCreateData(
data *jsonutils.JSONDict,
) (*jsonutils.JSONDict, error) {
if defsecgroup, _ := data.GetString("secgroup"); len(defsecgroup) > 0 {
if secgroup, _ := SecurityGroupManager.FetchByIdOrName(userCred.GetProjectId(), defsecgroup); secgroup != nil {
if secgroup, _ := SecurityGroupManager.FetchByIdOrName(userCred, defsecgroup); secgroup != nil {
data.Set("secgroup_id", jsonutils.NewString(secgroup.GetId()))
} else {
return nil, httperrors.NewNotFoundError(fmt.Sprintf("Security Group %s not found", defsecgroup))
+36
View File
@@ -89,6 +89,32 @@ func (manager *SSnapshotManager) ListItemFilter(ctx context.Context, q *sqlchemy
return q, nil
}
func (self *SSnapshot) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query)
return self.getMoreDetails(extra)
}
func (self *SSnapshot) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SVirtualResourceBase.GetExtraDetails(ctx, userCred, query)
return self.getMoreDetails(extra)
}
func (self *SSnapshot) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict {
disk, _ := self.GetDisk()
if disk != nil {
extra.Add(jsonutils.NewString(disk.DiskType), "disk_type")
guests := disk.GetGuests()
if len(guests) == 1 {
extra.Add(jsonutils.NewString(guests[0].Id), "guest")
extra.Add(jsonutils.NewString(guests[0].Status), "guest_status")
}
}
if cloudprovider := self.GetCloudprovider(); cloudprovider != nil {
extra.Add(jsonutils.NewString(cloudprovider.Provider), "provider")
}
return extra
}
func (self *SSnapshot) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return false
}
@@ -199,6 +225,11 @@ func (self *SSnapshotManager) CreateSnapshot(ctx context.Context, userCred mccli
snapshot := &SSnapshot{}
snapshot.SetModelManager(self)
snapshot.ProjectId = userCred.GetProjectId()
if manageId := disk.GetStorage().ManagerId; len(manageId) > 0 {
if provider := CloudproviderManager.FetchCloudproviderById(manageId); provider != nil {
snapshot.ProjectId = provider.ProjectId
}
}
snapshot.DiskId = disk.Id
snapshot.StorageId = disk.StorageId
snapshot.Size = disk.DiskSize
@@ -392,6 +423,11 @@ func (manager *SSnapshotManager) newFromCloudSnapshot(userCred mcclient.TokenCre
snapshot.CloudregionId = region.Id
snapshot.ProjectId = userCred.GetProjectId()
if len(snapshot.ManagerId) > 0 {
if provider := CloudproviderManager.FetchCloudproviderById(snapshot.ManagerId); provider != nil {
snapshot.ProjectId = provider.ProjectId
}
}
err := manager.TableSpec().Insert(&snapshot)
if err != nil {
log.Errorf("newFromCloudEip fail %s", err)
+1 -1
View File
@@ -675,7 +675,7 @@ func (manager *SStorageManager) ListItemFilter(ctx context.Context, q *sqlchemy.
regionStr, _ := query.GetString("region")
if len(regionStr) > 0 {
regionObj, err := CloudregionManager.FetchByIdOrName(userCred.GetProjectId(), regionStr)
regionObj, err := CloudregionManager.FetchByIdOrName(userCred, regionStr)
if err != nil {
return nil, httperrors.NewNotFoundError("Region %s not found: %s", regionStr, err)
}
+4 -4
View File
@@ -54,7 +54,7 @@ func (manager *SWireManager) ValidateCreateData(ctx context.Context, userCred mc
}
if len(vpcStr) > 0 {
vpcObj, err := VpcManager.FetchByIdOrName(userCred.GetProjectId(), vpcStr)
vpcObj, err := VpcManager.FetchByIdOrName(userCred, vpcStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewNotFoundError("Vpc %s not found", vpcStr)
@@ -534,7 +534,7 @@ func (manager *SWireManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
vpcStr := jsonutils.GetAnyString(query, []string{"vpc_id", "vpc"})
if len(vpcStr) > 0 {
vpc, err := VpcManager.FetchByIdOrName(userCred.GetProjectId(), vpcStr)
vpc, err := VpcManager.FetchByIdOrName(userCred, vpcStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewNotFoundError("vpc %s not found", vpcStr)
@@ -547,7 +547,7 @@ func (manager *SWireManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
regionStr := jsonutils.GetAnyString(query, []string{"region_id", "region", "cloudregion_id", "cloudregion"})
if len(regionStr) > 0 {
region, err := CloudregionManager.FetchByIdOrName(userCred.GetProjectId(), regionStr)
region, err := CloudregionManager.FetchByIdOrName(userCred, regionStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewNotFoundError("region %s not found", regionStr)
@@ -605,4 +605,4 @@ func (self *SWire) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict
}
}
return extra
}
}
+1 -1
View File
@@ -523,7 +523,7 @@ func (manager *SZoneManager) ValidateCreateData(ctx context.Context, userCred mc
regionStr := jsonutils.GetAnyString(query, []string{"region", "region_id", "cloudregion", "cloudregion_id"})
var regionId string
if len(regionStr) > 0 {
regionObj, err := CloudregionManager.FetchByIdOrName("", regionStr)
regionObj, err := CloudregionManager.FetchByIdOrName(nil, regionStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("Region %s not found", regionStr)
+1
View File
@@ -0,0 +1 @@
package sshkeys // import "yunion.io/x/onecloud/pkg/compute/sshkeys"
+85
View File
@@ -0,0 +1,85 @@
package sshkeys
import (
"context"
"database/sql"
"fmt"
"net/http"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/appctx"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
)
func AddSshKeysHandler(prefix string, app *appsrv.Application) {
app.AddHandler2("GET", fmt.Sprintf("%s/sshkeypairs", prefix), auth.Authenticate(sshKeysHandler), nil, "get_sshkeys", nil)
app.AddHandler2("GET", fmt.Sprintf("%s/sshkeypairs/<tenant_id>", prefix), auth.Authenticate(adminSshKeysHandler), nil, "get_sshkeys", nil)
}
func adminSshKeysHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
publicOnly := false
userCred := auth.FetchUserCredential(ctx)
if !userCred.IsSystemAdmin() {
publicOnly = true
}
params := appctx.AppContextParams(ctx)
projectId := params["<tenant_id>"]
if len(projectId) == 0 {
httperrors.InputParameterError(w, "empty project_id/tenant_id")
return
}
tenant, err := db.TenantCacheManager.FetchTenantByIdOrName(ctx, projectId)
if err != nil {
if err == sql.ErrNoRows {
httperrors.ResourceNotFoundError(w, "tenant/project %s not found", projectId)
return
} else {
httperrors.GeneralServerError(w, err)
return
}
}
query, err := jsonutils.ParseQueryString(r.URL.RawQuery)
if err != nil {
httperrors.GeneralServerError(w, err)
return
}
isAdmin := jsonutils.QueryBoolean(query, "admin", false)
sendSshKey(ctx, w, userCred, tenant.Id, isAdmin, publicOnly)
}
func sshKeysHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
userCred := auth.FetchUserCredential(ctx)
query, err := jsonutils.ParseQueryString(r.URL.RawQuery)
if err != nil {
httperrors.GeneralServerError(w, err)
return
}
isAdmin := jsonutils.QueryBoolean(query, "admin", false)
sendSshKey(ctx, w, userCred, userCred.GetProjectId(), isAdmin, false)
}
func sendSshKey(ctx context.Context, w http.ResponseWriter, userCred mcclient.TokenCredential, projectId string, isAdmin bool, publicOnly bool) {
var privKey, pubKey string
if isAdmin && userCred.IsSystemAdmin() {
privKey, pubKey, _ = GetSshAdminKeypair(ctx)
} else {
privKey, pubKey, _ = GetSshProjectKeypair(ctx, projectId)
}
ret := jsonutils.NewDict()
if !publicOnly {
ret.Add(jsonutils.NewString(privKey), "private_key")
}
ret.Add(jsonutils.NewString(pubKey), "public_key")
body := jsonutils.NewDict()
body.Add(ret, "sshkeypair")
appsrv.SendJSON(w, body)
}
+46
View File
@@ -0,0 +1,46 @@
package sshkeys
import (
"context"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/seclib2"
)
const (
sshAdminPrivateKey = "admin-ssh-private-key"
sshAdminPublicKey = "admin-ssh-public-key"
sshPrivateKey = "project-ssh-private-key"
sshPublicKey = "project-ssh-public-key"
)
func _getKeys(ctx context.Context, tenantId string, privateKey, publicKey string) (string, string, error) {
tenant, err := db.TenantCacheManager.FetchTenantById(ctx, tenantId)
if err != nil {
return "", "", err
}
private := tenant.GetMetadata(privateKey, nil)
public := tenant.GetMetadata(publicKey, nil)
userCred := auth.AdminCredential()
if len(private) == 0 || len(public) == 0 {
private, public, _ = seclib2.GenerateRSASSHKeypair()
private, _ = utils.EncryptAESBase64(tenantId, private)
tenant.SetMetadata(ctx, privateKey, private, userCred)
tenant.SetMetadata(ctx, publicKey, public, userCred)
}
private, _ = utils.DescryptAESBase64(tenantId, private)
return private, public, nil
}
func GetSshProjectKeypair(ctx context.Context, tenantId string) (string, string, error) {
return _getKeys(ctx, tenantId, sshPrivateKey, sshPublicKey)
}
func GetSshAdminKeypair(ctx context.Context) (string, string, error) {
userCred := auth.AdminCredential()
return _getKeys(ctx, userCred.GetProjectId(), sshAdminPrivateKey, sshAdminPublicKey)
}
@@ -0,0 +1,60 @@
package tasks
import (
"context"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/pkg/utils"
)
type CloudAccountSyncInfoTask struct {
taskman.STask
}
func init() {
taskman.RegisterTask(CloudAccountSyncInfoTask{})
}
func (self *CloudAccountSyncInfoTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
account := obj.(*models.SCloudaccount)
account.MarkStartSync(self.UserCred)
if _, err := account.GetSubAccounts(); err != nil {
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_DISCONNECTED, err.Error())
self.SetStageFailed(ctx, err.Error())
return
}
syncRange := models.SSyncRange{}
syncRangeJson, _ := self.Params.Get("sync_range")
if syncRangeJson != nil {
syncRangeJson.Unmarshal(&syncRange)
}
// do sync
exsitSubTask := false
self.SetStage("on_cloudaccount_sync_complete", nil)
for _, cloudprovider := range account.GetCloudproviders() {
if cloudprovider.Enabled {
exsitSubTask = true
cloudprovider.StartSyncCloudProviderInfoTask(ctx, self.UserCred, &syncRange, self.GetTaskId())
}
}
if !exsitSubTask {
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_CONNECTED, "")
self.SetStageComplete(ctx, nil)
}
}
func (self *CloudAccountSyncInfoTask) OnCloudaccountSyncComplete(ctx context.Context, account *models.SCloudaccount, data jsonutils.JSONObject) {
for _, cloudprovider := range account.GetCloudproviders() {
if cloudprovider.Enabled &&
utils.IsInStringArray(account.Status, []string{models.CLOUD_PROVIDER_START_SYNC, models.CLOUD_PROVIDER_SYNCING}) && time.Now().Sub(cloudprovider.LastSync) < time.Minute*20 {
return
}
}
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_CONNECTED, "")
self.SetStageComplete(ctx, nil)
}
+16
View File
@@ -25,11 +25,13 @@ func (self *DiskResetTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
disk := obj.(*models.SDisk)
storage := disk.GetStorage()
if storage == nil {
disk.SetStatus(self.UserCred, models.DISK_READY, "")
self.SetStageFailed(ctx, "Disk storage not found")
return
}
host := storage.GetMasterHost()
if host == nil {
disk.SetStatus(self.UserCred, models.DISK_READY, "")
self.SetStageFailed(ctx, "Storage master host not found")
return
}
@@ -39,6 +41,7 @@ func (self *DiskResetTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
func (self *DiskResetTask) RequestResetDisk(ctx context.Context, disk *models.SDisk, host *models.SHost) {
snapshotId, err := self.Params.GetString("snapshot_id")
if err != nil {
disk.SetStatus(self.UserCred, models.DISK_READY, "")
self.SetStageFailed(ctx, fmt.Sprintf("Get snapshotId error %s", err.Error()))
return
}
@@ -58,6 +61,7 @@ func (self *DiskResetTask) RequestResetDisk(ctx context.Context, disk *models.SD
self.SetStage("OnRequestResetDisk", nil)
err = host.GetHostDriver().RequestResetDisk(ctx, host, disk, params, self)
if err != nil {
disk.SetStatus(self.UserCred, models.DISK_READY, "")
self.SetStageFailed(ctx, err.Error())
}
}
@@ -83,6 +87,18 @@ func (self *DiskResetTask) OnRequestResetDisk(ctx context.Context, disk *models.
return
}
}
if jsonutils.QueryBoolean(self.Params, "auto_start", false) {
guest := disk.GetGuests()[0]
self.SetStage("OnStartGuest", nil)
guest.StartGueststartTask(ctx, self.UserCred, nil, self.GetTaskId())
} else {
disk.SetStatus(self.UserCred, models.DISK_READY, "")
self.SetStageComplete(ctx, nil)
}
}
func (self *DiskResetTask) OnStartGuest(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
disk.SetStatus(self.UserCred, models.DISK_READY, "")
self.SetStageComplete(ctx, nil)
}
+1 -1
View File
@@ -64,7 +64,7 @@ func getRangeObj(ctx context.Context, man db.IStandaloneModelManager, userCred m
if err != nil {
return nil, err
}
return man.FetchByIdOrName(userCred.GetProjectId(), id)
return man.FetchByIdOrName(userCred, id)
}
func rangeObjHandler(
+12
View File
@@ -71,6 +71,10 @@ func InvalidInputError(w http.ResponseWriter, msg string, params ...interface{})
JsonClientError(w, NewInputParameterError(msg, params...))
}
func InputParameterError(w http.ResponseWriter, msg string, params ...interface{}) {
JsonClientError(w, NewInputParameterError(msg, params...))
}
func MissingParameterError(w http.ResponseWriter, param string) {
JsonClientError(w, NewMissingParameterError(param))
}
@@ -94,3 +98,11 @@ func TenantNotFoundError(w http.ResponseWriter, msg string, params ...interface{
func OutOfQuotaError(w http.ResponseWriter, msg string, params ...interface{}) {
JsonClientError(w, NewOutOfQuotaError(msg, params...))
}
func NotSufficientPrivilegeError(w http.ResponseWriter, msg string, params ...interface{}) {
JsonClientError(w, NewNotSufficientPrivilegeError(msg, params...))
}
func ResourceNotFoundError(w http.ResponseWriter, msg string, params ...interface{}) {
JsonClientError(w, NewResourceNotFoundError(msg, params...))
}
+1 -1
View File
@@ -26,5 +26,5 @@ func init() {
Capabilities = SCapabilityManager{
ResourceManager: NewComputeManager("capability", "capabilities", []string{}, []string{}),
}
registerCompute(&Capabilities)
registerComputeV2(&Capabilities)
}
+1 -1
View File
@@ -14,4 +14,4 @@ func init() {
[]string{"namespace", "namespace_id", "created_by", "updated_by"},
)}
register(&Parameters)
}
}
-4
View File
@@ -1,9 +1,5 @@
package modules
import (
)
type ProjectNodeManager struct {
ResourceManager
}
+1 -1
View File
@@ -7,7 +7,7 @@ var (
func init() {
ResResults = NewMeterManager("res_result", "res_results",
[]string{"res_id", "res_name", "cpu", "mem", "sys_disk", "data_disk", "ips", "res_type", "band_width", "os_distribution", "os_version", "platform", "region_id",
"project_name", "user_name", "start_time", "end_time", "time_length", "cpu_amount", "mem_amount", "disk_amount", "baremetal_amount", "gpu_amount", "res_fee"},
"project_name", "user_name", "start_time", "end_time", "time_length", "cpu_amount", "mem_amount", "disk_amount", "baremetal_amount", "gpu_amount", "res_fee"},
[]string{},
)
register(&ResResults)
+30 -16
View File
@@ -5,6 +5,8 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/seclib2"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/utils"
)
@@ -18,24 +20,35 @@ func (this *ServerManager) GetLoginInfo(s *mcclient.ClientSession, id string, pa
return nil, e
}
ret := jsonutils.NewDict()
login_key, e := data.GetString("login_key")
loginKey, e := data.GetString("login_key")
if e != nil {
return nil, fmt.Errorf("No login key: %s", e)
} else {
passwd, e := utils.DescryptAESBase64(id, login_key)
if e != nil {
return nil, e
}
ret.Add(jsonutils.NewString(passwd), "password")
v, e := data.Get("login_account")
if e == nil {
ret.Add(v, "username")
}
v, e = data.Get("login_key_timestamp")
if e == nil {
ret.Add(v, "updated")
}
}
var privateKey string
if params != nil && !gotypes.IsNil(params) {
privateKey, _ = params.GetString("private_key")
}
var passwd string
if len(privateKey) > 0 {
passwd, e = seclib2.DecryptBase64(privateKey, loginKey)
} else {
passwd, e = utils.DescryptAESBase64(id, loginKey)
}
if e != nil {
return nil, e
}
ret.Add(jsonutils.NewString(passwd), "password")
v, e := data.Get("login_account")
if e == nil {
ret.Add(v, "username")
}
v, e = data.Get("login_key_timestamp")
if e == nil {
ret.Add(v, "updated")
}
return ret, nil
}
@@ -56,7 +69,8 @@ func init() {
"Secgroup", "Secgrp_id",
"vrouter", "vrouter_id",
"Created_at", "Group_name",
"Group_id", "Hypervisor", "os_type"},
"Group_id", "Hypervisor", "os_type",
"expired_at"},
[]string{"Host", "Tenant", "is_system", "auto_delete_at"})}
registerCompute(&Servers)
+2 -2
View File
@@ -8,7 +8,7 @@ func init() {
Snapshots = NewComputeManager("snapshot", "snapshots",
[]string{"ID", "Name", "Size", "Status",
"Disk_id", "Guest_id", "Created_at"},
[]string{"Storage_id", "Create_by", "Location", "Out_of_chain"})
[]string{"Storage_id", "Create_by", "Location", "Out_of_chain", "disk_type", "provider"})
registerCompute(&Snapshots)
registerComputeV2(&Snapshots)
}
+37
View File
@@ -0,0 +1,37 @@
package modules
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SSshkeypairManager struct {
ResourceManager
}
func (this *SSshkeypairManager) List(s *mcclient.ClientSession, params jsonutils.JSONObject) (*ListResult, error) {
url := "/sshkeypairs"
queryStr := params.QueryString()
if len(queryStr) > 0 {
url = fmt.Sprintf("%s?%s", url, queryStr)
}
body, err := this._get(s, url, "sshkeypair")
if err != nil {
return nil, err
}
result := ListResult{Data: []jsonutils.JSONObject{body}}
return &result, nil
}
var (
Sshkeypairs SSshkeypairManager
)
func init() {
Sshkeypairs = SSshkeypairManager{NewComputeManager("sshkeypair", "sshkeypairs",
[]string{},
[]string{})}
registerComputeV2(&Sshkeypairs)
}
+8
View File
@@ -1,7 +1,15 @@
package modules
func registerCompute(mod BaseManagerInterface) {
registerComputeV1(mod)
registerComputeV2(mod)
}
func registerComputeV1(mod BaseManagerInterface) {
_register("v1", mod)
}
func registerComputeV2(mod BaseManagerInterface) {
_register("v2", mod)
}
+7 -3
View File
@@ -24,10 +24,14 @@ func (o ClusterListOptions) Params() *jsonutils.JSONDict {
return params
}
type K8sSupportVersion struct {
K8sVersion string `help:"Cluster kubernetes components version" choices:"v1.10.5|v1.11.3|v1.12.0"`
}
type ClusterCreateOptions struct {
K8sSupportVersion
NAME string `help:"Name of cluster"`
Mode string `help:"Cluster mode" choices:"internal"`
K8sVersion string `help:"Cluster kubernetes components version" choices:"v1.8.10|v1.9.5|v1.10.0"`
InfraImage string `help:"Cluster kubelet infra container image"`
Cidr string `help:"Cluster service CIDR, e.g. 10.43.0.0/16"`
Domain string `help:"Cluster pod domain, e.g. cluster.local"`
@@ -70,8 +74,8 @@ func (o ClusterImportOptions) Params() (*jsonutils.JSONDict, error) {
}
type ClusterUpdateOptions struct {
NAME string `help:"Name of cluster"`
K8sVersion string `help:"Cluster kubernetes components version" choices:"v1.8.10|v1.9.5|v1.10.0"`
NAME string `help:"Name of cluster"`
K8sSupportVersion
}
func (o ClusterUpdateOptions) Params() *jsonutils.JSONDict {
+1 -1
View File
@@ -16,7 +16,7 @@ type TillerCreateOptions struct {
Canary bool `json:"canary_image"`
// Override Tiller image
Image string `json:"tiller_image" default:"yunion/tiller:v2.9.0"`
Image string `json:"tiller_image" default:"yunion/tiller:v2.9.1"`
// Limit the maximum number of revisions saved per release. Use 0 for no limit.
MaxHistory int `json:"history_max"`
}
+6
View File
@@ -31,6 +31,11 @@ type ServerIdOptions struct {
ID string `help:"ID or name of the server" json:"-"`
}
type ServerLoginInfoOptions struct {
ID string `help:"ID or name of the server" json:"-"`
Key string `help:"File name of private key, if password is encrypted by key"`
}
type ServerIdsOptions struct {
ID []string `help:"ID of servers to operate" metavar:"SERVER" json:"-"`
}
@@ -115,6 +120,7 @@ type ServerCreateOptions struct {
Count *int `help:"Create multiple simultaneously" default:"1" json:"-"`
DryRun *bool `help:"Dry run to test scheduler" json:"-"`
RaidConfig []string `help:"Baremetal raid config" json:"-"`
UserDataFile string `help:"user_data file path" json:"-"`
}
func (opts *ServerCreateOptions) Params() (*jsonutils.JSONDict, error) {
+8 -3
View File
@@ -20,19 +20,24 @@ type Endpoint struct {
Interface string
}
type IIdentityProvider interface {
GetProjectId() string
GetUserId() string
GetTenantId() string
}
type TokenCredential interface {
gotypes.ISerializable
IServiceCatalog
IIdentityProvider
GetTokenString() string
GetDomainId() string
GetDomainName() string
GetTenantId() string
GetTenantName() string
GetProjectId() string
GetProjectName() string
GetUserId() string
GetUserName() string
GetRoles() []string
GetExpires() time.Time
+3 -96
View File
@@ -4,8 +4,6 @@ import (
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudprovider"
@@ -21,6 +19,8 @@ const (
ALIYUN_API_VERSION = "2014-05-26"
ALIYUN_BSS_API_VERSION = "2017-12-14"
ALIYUN_RAM_API_VERSION = "2015-05-01"
)
type SAliyunClient struct {
@@ -44,10 +44,6 @@ func jsonRequest(client *sdk.Client, apiName string, params map[string]string) (
return _jsonRequest(client, "ecs.aliyuncs.com", ALIYUN_API_VERSION, apiName, params)
}
func businessRequest(client *sdk.Client, apiName string, params map[string]string) (jsonutils.JSONObject, error) {
return _jsonRequest(client, "business.aliyuncs.com", ALIYUN_BSS_API_VERSION, apiName, params)
}
func _jsonRequest(client *sdk.Client, domain string, version string, apiName string, params map[string]string) (jsonutils.JSONObject, error) {
req := requests.NewCommonRequest()
req.Domain = domain
@@ -58,6 +54,7 @@ func _jsonRequest(client *sdk.Client, domain string, version string, apiName str
req.QueryParams[k] = v
}
}
req.Scheme = "https"
resp, err := client.ProcessCommonRequest(req)
if err != nil {
@@ -94,14 +91,6 @@ func (self *SAliyunClient) jsonRequest(apiName string, params map[string]string)
return jsonRequest(cli, apiName, params)
}
func (self *SAliyunClient) businessRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
cli, err := self.getDefaultClient()
if err != nil {
return nil, err
}
return businessRequest(cli, apiName, params)
}
func (self *SAliyunClient) fetchRegions() error {
body, err := self.jsonRequest("DescribeRegions", map[string]string{"AcceptLanguage": "zh-CN"})
if err != nil {
@@ -218,85 +207,3 @@ func (self *SAliyunClient) GetIStoragecacheById(id string) (cloudprovider.ICloud
}
return nil, cloudprovider.ErrNotFound
}
type SAccountBalance struct {
AvailableAmount float64
AvailableCashAmount float64
CreditAmount float64
MybankCreditAmount float64
Currency string
}
type SCashCoupon struct {
ApplicableProducts string
ApplicableScenarios string
Balance float64
CashCouponId string
CashCouponNo string
EffectiveTime time.Time
ExpiryTime time.Time
GrantedTime time.Time
NominalValue float64
Status string
}
type SPrepaidCard struct {
PrepaidCardId string
PrepaidCardNo string
GrantedTime time.Time
EffectiveTime time.Time
ExpiryTime time.Time
NominalValue float64
Balance float64
ApplicableProducts string
ApplicableScenarios string
}
func (self *SAliyunClient) QueryAccountBalance() (*SAccountBalance, error) {
body, err := self.businessRequest("QueryAccountBalance", nil)
if err != nil {
log.Errorf("QueryAccountBalance fail %s", err)
return nil, err
}
balance := SAccountBalance{}
err = body.Unmarshal(&balance, "Data")
if err != nil {
log.Errorf("Unmarshal AccountBalance fail %s", err)
return nil, err
}
return &balance, nil
}
func (self *SAliyunClient) QueryCashCoupons() ([]SCashCoupon, error) {
params := make(map[string]string)
params["EffectiveOrNot"] = "True"
body, err := self.businessRequest("QueryCashCoupons", params)
if err != nil {
log.Errorf("QueryCashCoupons fail %s", err)
return nil, err
}
coupons := make([]SCashCoupon, 0)
err = body.Unmarshal(&coupons, "Data", "CashCoupon")
if err != nil {
log.Errorf("Unmarshal fail %s", err)
return nil, err
}
return coupons, nil
}
func (self *SAliyunClient) QueryPrepaidCards() ([]SPrepaidCard, error) {
params := make(map[string]string)
params["EffectiveOrNot"] = "True"
body, err := self.businessRequest("QueryPrepaidCards", params)
if err != nil {
log.Errorf("QueryPrepaidCards fail %s", err)
return nil, err
}
cards := make([]SPrepaidCard, 0)
err = body.Unmarshal(&cards, "Data", "PrepaidCard")
if err != nil {
log.Errorf("Unmarshal fail %s", err)
return nil, err
}
return cards, nil
}
+104
View File
@@ -0,0 +1,104 @@
package aliyun
import (
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
)
func businessRequest(client *sdk.Client, apiName string, params map[string]string) (jsonutils.JSONObject, error) {
return _jsonRequest(client, "business.aliyuncs.com", ALIYUN_BSS_API_VERSION, apiName, params)
}
func (self *SAliyunClient) businessRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
cli, err := self.getDefaultClient()
if err != nil {
return nil, err
}
return businessRequest(cli, apiName, params)
}
type SAccountBalance struct {
AvailableAmount float64
AvailableCashAmount float64
CreditAmount float64
MybankCreditAmount float64
Currency string
}
type SCashCoupon struct {
ApplicableProducts string
ApplicableScenarios string
Balance float64
CashCouponId string
CashCouponNo string
EffectiveTime time.Time
ExpiryTime time.Time
GrantedTime time.Time
NominalValue float64
Status string
}
type SPrepaidCard struct {
PrepaidCardId string
PrepaidCardNo string
GrantedTime time.Time
EffectiveTime time.Time
ExpiryTime time.Time
NominalValue float64
Balance float64
ApplicableProducts string
ApplicableScenarios string
}
func (self *SAliyunClient) QueryAccountBalance() (*SAccountBalance, error) {
body, err := self.businessRequest("QueryAccountBalance", nil)
if err != nil {
log.Errorf("QueryAccountBalance fail %s", err)
return nil, err
}
balance := SAccountBalance{}
err = body.Unmarshal(&balance, "Data")
if err != nil {
log.Errorf("Unmarshal AccountBalance fail %s", err)
return nil, err
}
return &balance, nil
}
func (self *SAliyunClient) QueryCashCoupons() ([]SCashCoupon, error) {
params := make(map[string]string)
params["EffectiveOrNot"] = "True"
body, err := self.businessRequest("QueryCashCoupons", params)
if err != nil {
log.Errorf("QueryCashCoupons fail %s", err)
return nil, err
}
coupons := make([]SCashCoupon, 0)
err = body.Unmarshal(&coupons, "Data", "CashCoupon")
if err != nil {
log.Errorf("Unmarshal fail %s", err)
return nil, err
}
return coupons, nil
}
func (self *SAliyunClient) QueryPrepaidCards() ([]SPrepaidCard, error) {
params := make(map[string]string)
params["EffectiveOrNot"] = "True"
body, err := self.businessRequest("QueryPrepaidCards", params)
if err != nil {
log.Errorf("QueryPrepaidCards fail %s", err)
return nil, err
}
cards := make([]SPrepaidCard, 0)
err = body.Unmarshal(&cards, "Data", "PrepaidCard")
if err != nil {
log.Errorf("Unmarshal fail %s", err)
return nil, err
}
return cards, nil
}
+1 -2
View File
@@ -358,7 +358,6 @@ func (self *SDisk) Reset(snapshotId string) error {
return self.storage.zone.region.resetDisk(self.DiskId, snapshotId)
}
func (self *SDisk) GetBillingType() string {
switch self.DiskChargeType {
case PrePaidInstanceChargeType:
@@ -372,4 +371,4 @@ func (self *SDisk) GetBillingType() string {
func (self *SDisk) GetExpiredAt() time.Time {
return self.ExpiredTime
}
}
+5 -4
View File
@@ -165,8 +165,8 @@ func (self *SHost) GetInstanceById(instanceId string) (*SInstance, error) {
func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int,
vswitchId string, ipAddr string, desc string, passwd string,
storageType string, diskSizes []int, publicKey string, secgroupId string) (cloudprovider.ICloudVM, error) {
vmId, err := self._createVM(name, imgId, sysDiskSize, cpu, memMB, vswitchId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, secgroupId)
storageType string, diskSizes []int, publicKey string, secgroupId string, userData string) (cloudprovider.ICloudVM, error) {
vmId, err := self._createVM(name, imgId, sysDiskSize, cpu, memMB, vswitchId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, secgroupId, userData)
if err != nil {
return nil, err
}
@@ -180,7 +180,8 @@ func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int,
func (self *SHost) _createVM(name string, imgId string, sysDiskSize int, cpu int, memMB int,
vswitchId string, ipAddr string, desc string, passwd string,
storageType string, diskSizes []int, publicKey string, secgroupId string) (string, error) {
storageType string, diskSizes []int, publicKey string, secgroupId string,
userData string) (string, error) {
net := self.zone.getNetworkById(vswitchId)
if net == nil {
return "", fmt.Errorf("invalid switch ID %s", vswitchId)
@@ -260,7 +261,7 @@ func (self *SHost) _createVM(name string, imgId string, sysDiskSize int, cpu int
for _, instType := range instanceTypes {
instanceTypeId := instType.InstanceTypeId
log.Debugf("Try instancetype : %s", instanceTypeId)
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair)
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData)
if err != nil {
log.Errorf("Failed for %s: %s", instanceTypeId, err)
} else {
+10 -1
View File
@@ -428,7 +428,7 @@ func (self *SRegion) GetInstance(instanceId string) (*SInstance, error) {
func (self *SRegion) CreateInstance(name string, imageId string, instanceType string, securityGroupId string,
zoneId string, desc string, passwd string, disks []SDisk, vSwitchId string, ipAddr string,
keypair string) (string, error) {
keypair string, userData string) (string, error) {
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["ImageId"] = imageId
@@ -468,6 +468,11 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st
if len(keypair) > 0 {
params["KeyPairName"] = keypair
}
if len(userData) > 0 {
params["UserData"] = userData
}
params["ClientToken"] = utils.GenRequestId(20)
body, err := self.ecsRequest("CreateInstance", params)
@@ -788,3 +793,7 @@ func (self *SInstance) GetBillingType() string {
func (self *SInstance) GetExpiredAt() time.Time {
return self.ExpiredTime
}
func (self *SInstance) UpdateUserData(userData string) error {
return self.host.zone.region.updateInstance(self.InstanceId, "", "", "", "", userData)
}
+222
View File
@@ -0,0 +1,222 @@
package aliyun
import (
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
func ramRequest(client *sdk.Client, apiName string, params map[string]string) (jsonutils.JSONObject, error) {
return _jsonRequest(client, "ram.aliyuncs.com", ALIYUN_RAM_API_VERSION, apiName, params)
}
func (self *SAliyunClient) ramRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
cli, err := self.getDefaultClient()
if err != nil {
return nil, err
}
return ramRequest(cli, apiName, params)
}
type SRole struct {
Arn string
CreateDate time.Time
Description string
RoleId string
RoleName string
AssumeRolePolicyDocument string
}
func (self *SAliyunClient) ListRoles() ([]SRole, error) {
body, err := self.ramRequest("ListRoles", nil)
if err != nil {
log.Errorf("listRoles fail %s", err)
return nil, err
}
roles := make([]SRole, 0)
err = body.Unmarshal(&roles, "Roles", "Role")
if err != nil {
return nil, err
}
return roles, nil
}
func (self *SAliyunClient) GetRole(roleName string) (*SRole, error) {
params := make(map[string]string)
params["RoleName"] = roleName
body, err := self.ramRequest("GetRole", params)
if err != nil {
if isError(err, "EntityNotExist.Role") {
return nil, cloudprovider.ErrNotFound
}
return nil, err
}
role := SRole{}
err = body.Unmarshal(&role, "Role")
if err != nil {
return nil, err
}
return &role, nil
}
func (self *SAliyunClient) createRole(roleName string, document string, desc string) (*SRole, error) {
params := make(map[string]string)
params["RoleName"] = roleName
params["AssumeRolePolicyDocument"] = document
if len(desc) > 0 {
params["Description"] = desc
}
body, err := self.ramRequest("CreateRole", params)
if err != nil {
return nil, err
}
role := SRole{}
err = body.Unmarshal(&role, "Role")
if err != nil {
return nil, err
}
return &role, nil
}
/**
{"AttachmentCount":0,
"CreateDate":"2018-10-12T05:05:16Z",
"DefaultVersion":"v1",
"Description":"只读访问Data Lake Analytics的权限",
"PolicyName":"AliyunDLAReadOnlyAccess",
"PolicyType":"System",
"UpdateDate":"2018-10-12T05:05:16Z"}
*/
type SPolicy struct {
AttachmentCount int
CreateDate time.Time
UpdateDate time.Time
DefaultVersion string
Description string
PolicyName string
PolicyType string
}
func (self *SAliyunClient) ListPolicies(policyType string, role string) ([]SPolicy, error) {
var action string
params := make(map[string]string)
if len(role) > 0 {
params["RoleName"] = role
action = "ListPoliciesForRole"
} else {
params["MaxItems"] = "1000"
if len(policyType) > 0 {
params["PolicyType"] = policyType
}
action = "ListPolicies"
}
body, err := self.ramRequest(action, params)
if err != nil {
log.Errorf("listPolicies fail %s", err)
return nil, err
}
policies := make([]SPolicy, 0)
err = body.Unmarshal(&policies, "Policies", "Policy")
if err != nil {
return nil, err
}
return policies, nil
}
func (self *SAliyunClient) GetPolicy(policyType string, policyName string) (*SPolicy, error) {
params := make(map[string]string)
params["PolicyType"] = policyType
params["PolicyName"] = policyName
body, err := self.ramRequest("GetPolicy", params)
if err != nil {
if isError(err, "EntityNotExist.Role") {
return nil, cloudprovider.ErrNotFound
}
return nil, err
}
policy := SPolicy{}
err = body.Unmarshal(&policy, "Policy")
if err != nil {
return nil, err
}
return &policy, nil
}
func (self *SAliyunClient) createPolicy(name string, document string, desc string) (*SPolicy, error) {
params := make(map[string]string)
params["PolicyName"] = name
params["PolicyDocument"] = document
if len(desc) > 0 {
params["Description"] = desc
}
body, err := self.ramRequest("CreatePolicy", params)
if err != nil {
return nil, err
}
policy := SPolicy{}
err = body.Unmarshal(&policy, "Policy")
if err != nil {
return nil, err
}
return &policy, nil
}
func (self *SAliyunClient) DeletePolicy(policyType string, policyName string) error {
params := make(map[string]string)
params["PolicyName"] = policyName
params["PolicyType"] = policyType
_, err := self.ramRequest("DeletePolicy", params)
return err
}
func (self *SAliyunClient) DeleteRole(roleName string) error {
params := make(map[string]string)
params["RoleName"] = roleName
_, err := self.ramRequest("DeleteRole", params)
return err
}
func (self *SAliyunClient) attachPolicy2Role(policyType string, policyName string, roleName string) error {
params := make(map[string]string)
params["PolicyType"] = policyType
params["PolicyName"] = policyName
params["RoleName"] = roleName
_, err := self.ramRequest("AttachPolicyToRole", params)
if err != nil {
return err
}
return nil
}
+172
View File
@@ -0,0 +1,172 @@
package aliyun
import (
"yunion.io/x/onecloud/pkg/cloudprovider"
)
const (
AliyunECSImageImportRole = "AliyunECSImageImportDefaultRole"
AliyunECSImageImportRoleDocument = `{
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": [
"ecs.aliyuncs.com"
]
}
}
],
"Version": "1"
}`
AliyunECSImageImportRolePolicyType = "System"
AliyunECSImageImportRolePolicy = "AliyunECSImageImportRolePolicy"
AliyunECSImageImportRolePolicyDocument = `{
"Version": "1",
"Statement": [
{
"Action": [
"oss:GetObject",
"oss:GetBucketLocation"
],
"Resource": "*",
"Effect": "Allow"
}
]
}`
)
func (self *SAliyunClient) EnableImageImport() error {
_, err := self.GetRole(AliyunECSImageImportRole)
if err != nil {
if err != cloudprovider.ErrNotFound {
return err
}
_, err = self.createRole(AliyunECSImageImportRole,
AliyunECSImageImportRoleDocument,
"Allow Import External Image from OSS")
if err != nil {
return err
}
}
_, err = self.GetPolicy(AliyunECSImageImportRolePolicyType, AliyunECSImageImportRolePolicy)
if err != nil {
/*if err != cloudprovider.ErrNotFound {
return err
}
_, err = self.createPolicy(AliyunECSImageImportRolePolicy,
AliyunECSImageImportRolePolicyDocument,
"Allow Import External Image policy")
if err != nil {
return err
}*/
return err
}
policies, err := self.ListPolicies("", AliyunECSImageImportRole)
if err != nil {
return err
}
for i := 0; i < len(policies); i += 1 {
if policies[i].PolicyType == AliyunECSImageImportRolePolicyType &&
policies[i].PolicyName == AliyunECSImageImportRolePolicy {
return nil // find policy
}
}
err = self.attachPolicy2Role(AliyunECSImageImportRolePolicyType, AliyunECSImageImportRolePolicy, AliyunECSImageImportRole)
if err != nil {
return err
}
return nil
}
const (
AliyunECSImageExportRole = "AliyunECSImageExportDefaultRole"
AliyunECSImageExportRoleDocument = `{
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": [
"ecs.aliyuncs.com"
]
}
}
],
"Version": "1"
}`
AliyunECSImageExportRolePolicyType = "System"
AliyunECSImageExportRolePolicy = "AliyunECSImageExportRolePolicy"
AliyunECSImageExportRolePolicyDocument = `{
"Version": "1",
"Statement": [
{
"Action": [
"oss:GetObject",
"oss:PutObject",
"oss:DeleteObject",
"oss:GetBucketLocation",
"oss:AbortMultipartUpload",
"oss:ListMultipartUploads",
"oss:ListParts"
],
"Resource": "*",
"Effect": "Allow"
}
]
}`
)
func (self *SAliyunClient) EnableImageExport() error {
_, err := self.GetRole(AliyunECSImageExportRole)
if err != nil {
if err != cloudprovider.ErrNotFound {
return err
}
_, err = self.createRole(AliyunECSImageExportRole,
AliyunECSImageExportRoleDocument,
"Allow Export Import to OSS")
if err != nil {
return err
}
}
_, err = self.GetPolicy(AliyunECSImageExportRolePolicyType, AliyunECSImageExportRolePolicy)
if err != nil {
/*if err != cloudprovider.ErrNotFound {
return err
}
_, err = self.createPolicy(AliyunECSImageImportRolePolicy,
AliyunECSImageImportRolePolicyDocument,
"Allow Import External Image policy")
if err != nil {
return err
}*/
return err
}
policies, err := self.ListPolicies("", AliyunECSImageExportRole)
if err != nil {
return err
}
for i := 0; i < len(policies); i += 1 {
if policies[i].PolicyType == AliyunECSImageExportRolePolicyType &&
policies[i].PolicyName == AliyunECSImageExportRolePolicy {
return nil // find policy
}
}
err = self.attachPolicy2Role(AliyunECSImageExportRolePolicyType, AliyunECSImageExportRolePolicy, AliyunECSImageExportRole)
if err != nil {
return err
}
return nil
}
+6 -3
View File
@@ -475,7 +475,7 @@ func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, me
log.Debugf("Search in zone %s", z.LocalName)
net := z.getNetworkById(vswitchId)
if net != nil {
inst, err := z.getHost().CreateVM(name, imgId, 0, cpu, memGB*1024, vswitchId, "", "", passwd, storageType, dataDiskSizesGB, publicKey, "")
inst, err := z.getHost().CreateVM(name, imgId, 0, cpu, memGB*1024, vswitchId, "", "", passwd, storageType, dataDiskSizesGB, publicKey, "", "")
if err != nil {
return nil, err
}
@@ -601,7 +601,7 @@ func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStorag
return nil, cloudprovider.ErrNotFound
}
func (self *SRegion) updateInstance(instId string, name, desc, passwd, hostname string) error {
func (self *SRegion) updateInstance(instId string, name, desc, passwd, hostname, userData string) error {
params := make(map[string]string)
params["InstanceId"] = instId
if len(name) > 0 {
@@ -616,12 +616,15 @@ func (self *SRegion) updateInstance(instId string, name, desc, passwd, hostname
if len(hostname) > 0 {
params["HostName"] = hostname
}
if len(userData) > 0 {
params["UserData"] = userData
}
_, err := self.ecsRequest("ModifyInstanceAttribute", params)
return err
}
func (self *SRegion) UpdateInstancePassword(instId string, passwd string) error {
return self.updateInstance(instId, "", "", passwd, "")
return self.updateInstance(instId, "", "", passwd, "", "")
}
// func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
+80
View File
@@ -0,0 +1,80 @@
package shell
import (
"yunion.io/x/onecloud/pkg/util/aliyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type ListRolesOptions struct {
}
shellutils.R(&ListRolesOptions{}, "role-list", "List ram roles", func(cli *aliyun.SRegion, args *ListRolesOptions) error {
roles, err := cli.GetClient().ListRoles()
if err != nil {
return err
}
printList(roles, 0, 0, 0, []string{})
return nil
})
type GetRoleOptions struct {
ROLENAME string
}
shellutils.R(&GetRoleOptions{}, "role-show", "Show ram role", func(cli *aliyun.SRegion, args *GetRoleOptions) error {
role, err := cli.GetClient().GetRole(args.ROLENAME)
if err != nil {
return err
}
printObject(role)
return nil
})
type ListPoliciesOptions struct {
PolicyType string
Role string
}
shellutils.R(&ListPoliciesOptions{}, "policy-list", "List ram policies", func(cli *aliyun.SRegion, args *ListPoliciesOptions) error {
policies, err := cli.GetClient().ListPolicies(args.PolicyType, args.Role)
if err != nil {
return err
}
printList(policies, 0, 0, 0, []string{})
return nil
})
type GetPolicyOptions struct {
POLICYTYPE string
POLICYNAME string
}
shellutils.R(&GetPolicyOptions{}, "policy-show", "Show ram policy", func(cli *aliyun.SRegion, args *GetPolicyOptions) error {
policy, err := cli.GetClient().GetPolicy(args.POLICYTYPE, args.POLICYNAME)
if err != nil {
return err
}
printObject(policy)
return nil
})
type DeletePolicyOptions struct {
POLICYTYPE string
POLICYNAME string
}
shellutils.R(&DeletePolicyOptions{}, "policy-delete", "Delete policy", func(cli *aliyun.SRegion, args *DeletePolicyOptions) error {
return cli.GetClient().DeletePolicy(args.POLICYTYPE, args.POLICYNAME)
})
type DeleteRoleOptions struct {
NAME string
}
shellutils.R(&DeleteRoleOptions{}, "role-delete", "Delete role", func(cli *aliyun.SRegion, args *DeleteRoleOptions) error {
return cli.GetClient().DeleteRole(args.NAME)
})
shellutils.R(&ListRolesOptions{}, "enable-image-import", "Enable image import privilege", func(cli *aliyun.SRegion, args *ListRolesOptions) error {
return cli.GetClient().EnableImageImport()
})
shellutils.R(&ListRolesOptions{}, "enable-image-export", "Enable image export privilege", func(cli *aliyun.SRegion, args *ListRolesOptions) error {
return cli.GetClient().EnableImageExport()
})
}
+8 -4
View File
@@ -107,10 +107,7 @@ func (self *SSnapshot) Delete() error {
if self.region == nil {
return fmt.Errorf("not init region for snapshot %s", self.SnapshotId)
}
params := make(map[string]string)
params["SnapshotId"] = self.SnapshotId
_, err := self.region.ecsRequest("DeleteSnapshot", params)
return err
return self.region.DeleteSnapshot(self.SnapshotId)
}
func (self *SSnapshot) GetMetadata() *jsonutils.JSONDict {
@@ -166,3 +163,10 @@ func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSn
return &snapshots[0], nil
}
}
func (self *SRegion) DeleteSnapshot(snapshotId string) error {
params := make(map[string]string)
params["SnapshotId"] = snapshotId
_, err := self.ecsRequest("DeleteSnapshot", params)
return err
}
+19 -1
View File
@@ -120,7 +120,7 @@ func (self *SStoragecache) uploadImage(userCred mcclient.TokenCredential, imageI
log.Errorf("GetOssClient err %s", err)
return "", err
}
bucketName := strings.ToLower(fmt.Sprintf("imgcache-%s-%s", self.region.GetId(), self.region.client.providerId))
bucketName := strings.ToLower(fmt.Sprintf("imgcache-%s-%s", self.region.GetId(), imageId))
exist, err := oss.IsBucketExist(bucketName)
if err != nil {
log.Errorf("IsBucketExist err %s", err)
@@ -136,6 +136,9 @@ func (self *SStoragecache) uploadImage(userCred mcclient.TokenCredential, imageI
} else {
log.Debugf("Bucket %s exists", bucketName)
}
defer oss.DeleteBucket(bucketName) // remove bucket
bucket, err := oss.Bucket(bucketName)
if err != nil {
log.Errorf("Bucket error %s %s", bucketName, err)
@@ -148,6 +151,8 @@ func (self *SStoragecache) uploadImage(userCred mcclient.TokenCredential, imageI
return "", err
}
defer bucket.DeleteObject(imageId) // remove object
imageBaseName := imageId
if imageBaseName[0] >= '0' && imageBaseName[0] <= '9' {
imageBaseName = fmt.Sprintf("img%s", imageId)
@@ -171,6 +176,13 @@ func (self *SStoragecache) uploadImage(userCred mcclient.TokenCredential, imageI
log.Debugf("Import image %s", imageName)
// ensure privileges
err = self.region.GetClient().EnableImageImport()
if err != nil {
log.Errorf("fail to enable import privileges: %s", err)
return "", err
}
task, err := self.region.ImportImage(imageName, osArch, osType, osDist, bucketName, imageId)
if err != nil {
@@ -282,6 +294,12 @@ func (listener *OssProgressListener) ProgressChanged(event *oss.ProgressEvent) {
}
func (self *SStoragecache) downloadImage(userCred mcclient.TokenCredential, imageId string, extId string, path string) (jsonutils.JSONObject, error) {
err := self.region.GetClient().EnableImageExport()
if err != nil {
log.Errorf("fail to enable export privileges: %s", err)
return nil, err
}
tmpImageFile, err := ioutil.TempFile(path, extId)
if err != nil {
return nil, err
+1 -1
View File
@@ -155,4 +155,4 @@ func (self *SVSwitch) Delete() error {
func (self *SVSwitch) GetAllocTimeoutSeconds() int {
return 120 // 2 minutes
}
}
+5
View File
@@ -0,0 +1,5 @@
package ansible
const (
PUBLIC_CLOUD_ANSIBLE_USER = "yunionroot"
)
+1
View File
@@ -0,0 +1 @@
package ansible // import "yunion.io/x/onecloud/pkg/util/ansible"
+1
View File
@@ -0,0 +1 @@
package azure // import "yunion.io/x/onecloud/pkg/util/azure"
+8 -4
View File
@@ -48,7 +48,7 @@ func (self *SHost) Refresh() error {
return nil
}
func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, networkId string, ipAddr string, desc string, passwd string, storageType string, diskSizes []int, publicKey string, secgroupId string) (cloudprovider.ICloudVM, error) {
func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, networkId string, ipAddr string, desc string, passwd string, storageType string, diskSizes []int, publicKey string, secgroupId string, userData string) (cloudprovider.ICloudVM, error) {
nicId := ""
if net := self.zone.getNetworkById(networkId); net == nil {
return nil, fmt.Errorf("invalid network ID %s", networkId)
@@ -57,7 +57,7 @@ func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int,
} else {
nicId = nic.ID
}
vmId, err := self._createVM(name, imgId, sysDiskSize, cpu, memMB, nicId, ipAddr, desc, passwd, storageType, diskSizes, publicKey)
vmId, err := self._createVM(name, imgId, sysDiskSize, cpu, memMB, nicId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, userData)
if err != nil {
self.zone.region.DeleteNetworkInterface(nicId)
return nil, err
@@ -70,7 +70,7 @@ func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int,
}
}
func (self *SHost) _createVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, nicId string, ipAddr string, desc string, passwd string, storageType string, diskSizes []int, publicKey string) (string, error) {
func (self *SHost) _createVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, nicId string, ipAddr string, desc string, passwd string, storageType string, diskSizes []int, publicKey string, userData string) (string, error) {
computeClient := compute.NewVirtualMachinesClientWithBaseURI(self.zone.region.client.baseUrl, self.zone.region.client.subscriptionId)
computeClient.Authorizer = self.zone.region.client.authorizer
@@ -119,7 +119,7 @@ func (self *SHost) _createVM(name string, imgId string, sysDiskSize int, cpu int
// //StorageURI:
// },
// }
sshKeys := []compute.SSHPublicKey{compute.SSHPublicKey{KeyData: &publicKey}}
sshKeys := []compute.SSHPublicKey{{KeyData: &publicKey}}
properties := compute.VirtualMachineProperties{
HardwareProfile: &compute.HardwareProfile{},
StorageProfile: &compute.StorageProfile{
@@ -150,6 +150,10 @@ func (self *SHost) _createVM(name string, imgId string, sysDiskSize int, cpu int
properties.OsProfile.LinuxConfiguration.SSH = &compute.SSHConfiguration{PublicKeys: &sshKeys}
}
if len(userData) > 0 {
properties.OsProfile.CustomData = &userData
}
params := compute.VirtualMachine{Location: &self.zone.region.Name, Name: &name, VirtualMachineProperties: &properties}
//log.Debugf("Create instance params: %s", jsonutils.Marshal(params).PrettyString())
for _, profile := range self.zone.region.getHardwareProfile(cpu, memMB) {
+9 -1
View File
@@ -566,7 +566,7 @@ func (region *SRegion) ReplaceSystemDisk(instanceId, imageId, passwd, publicKey
} else {
osType := compute.OperatingSystemTypes(image.GetOsType())
disk, _ := region.GetDisk(diskId)
sshKeys := []compute.SSHPublicKey{compute.SSHPublicKey{KeyData: &publicKey}}
sshKeys := []compute.SSHPublicKey{{KeyData: &publicKey}}
params := compute.VirtualMachineUpdate{
VirtualMachineProperties: &compute.VirtualMachineProperties{
StorageProfile: &compute.StorageProfile{
@@ -859,3 +859,11 @@ func (self *SInstance) GetBillingType() string {
func (self *SInstance) GetExpiredAt() time.Time {
return time.Now()
}
func (self *SInstance) UpdateUserData(userData string) error {
params := compute.VirtualMachineUpdate{}
params.OsProfile = &compute.OSProfile{
CustomData: &userData,
}
return self.host.zone.region.UpdateInstance(self.ID, params)
}
+1 -1
View File
@@ -340,7 +340,7 @@ func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, me
net := z.getNetworkById(networkId)
if net != nil {
passwd := seclib2.RandomPassword2(12)
inst, err := z.getHost().CreateVM(name, imgId, 30, cpu, memGB*1024, networkId, "", "", passwd, storageType, dataDiskSizesGB, publicKey, "")
inst, err := z.getHost().CreateVM(name, imgId, 30, cpu, memGB*1024, networkId, "", "", passwd, storageType, dataDiskSizesGB, publicKey, "", "")
if err != nil {
return nil, err
}
+227
View File
@@ -0,0 +1,227 @@
package cloudinit
import (
"bytes"
"encoding/base64"
"fmt"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/util/seclib2"
"yunion.io/x/pkg/utils"
)
/*
* cloudconfig
* Reference: https://cloudinit.readthedocs.io/en/latest/topics/examples.html
*
*/
type TSudoPolicy string
const (
CLOUD_CONFIG_HEADER = "#cloud-config\n"
USER_SUDO_NOPASSWD = TSudoPolicy("sudo_nopasswd")
USER_SUDO = TSudoPolicy("sudo")
USER_SUDO_DENY = TSudoPolicy("sudo_deny")
USER_SUDO_NONE = TSudoPolicy("")
)
type SWriteFile struct {
Path string
Permissions string
Owner string
Encoding string
Content string
}
type SUser struct {
Name string
Passwd string
LockPassword string
SshAuthorizedKeys []string
Sudo string
}
type SPhoneHome struct {
Url string
}
type SCloudConfig struct {
Users []SUser
WriteFiles []SWriteFile
Runcmd []string
Bootcmd []string
Packages []string
PhoneHome *SPhoneHome
DisableRoot int
SshPwauth int
}
func NewWriteFile(path string, content string, perm string, owner string, isBase64 bool) SWriteFile {
f := SWriteFile{}
f.Path = path
f.Permissions = perm
f.Owner = owner
if isBase64 {
f.Encoding = "b64"
f.Content = base64.StdEncoding.EncodeToString([]byte(content))
} else {
f.Content = content
}
return f
}
func NewUser(name string) SUser {
u := SUser{Name: name}
return u
}
func (u *SUser) SudoPolicy(policy TSudoPolicy) *SUser {
switch policy {
case USER_SUDO_NOPASSWD:
u.Sudo = "ALL=(ALL) NOPASSWD:ALL"
case USER_SUDO:
u.Sudo = "ALL=(ALL) ALL"
case USER_SUDO_DENY:
u.Sudo = "False"
default:
u.Sudo = ""
}
return u
}
func (u *SUser) SshKey(key string) *SUser {
if u.SshAuthorizedKeys == nil {
u.SshAuthorizedKeys = make([]string, 0)
}
u.SshAuthorizedKeys = append(u.SshAuthorizedKeys, key)
return u
}
func (u *SUser) Password(passwd string) *SUser {
if len(passwd) > 0 {
hash, err := seclib2.GeneratePassword(passwd)
if err != nil {
log.Errorf("GeneratePassword error %s", err)
} else {
u.Passwd = hash
}
u.LockPassword = "false"
}
return u
}
func (conf *SCloudConfig) UserData() string {
var buf bytes.Buffer
jsonConf := jsonutils.Marshal(conf)
buf.WriteString(CLOUD_CONFIG_HEADER)
buf.WriteString(jsonConf.YAMLString())
return buf.String()
}
func (conf *SCloudConfig) UserDataBase64() string {
data := conf.UserData()
return base64.StdEncoding.EncodeToString([]byte(data))
}
func ParseUserDataBase64(b64data string) (*SCloudConfig, error) {
data, err := base64.StdEncoding.DecodeString(b64data)
if err != nil {
return nil, err
}
return ParseUserData(string(data))
}
func ParseUserData(data string) (*SCloudConfig, error) {
if !strings.HasPrefix(data, CLOUD_CONFIG_HEADER) {
msg := "invalid userdata, not starting with #cloud-config"
log.Errorf(msg)
return nil, fmt.Errorf(msg)
}
jsonConf, err := jsonutils.ParseYAML(data)
if err != nil {
log.Errorf("parse userdata yaml error %s", err)
return nil, err
}
config := SCloudConfig{}
err = jsonConf.Unmarshal(&config)
if err != nil {
log.Errorf("unable to unmarchal userdata %s", err)
return nil, err
}
return &config, nil
}
func (conf *SCloudConfig) MergeUser(u SUser) {
for i := 0; i < len(conf.Users); i += 1 {
if u.Name == conf.Users[i].Name {
// find user, merge keys
for j := 0; j < len(u.SshAuthorizedKeys); j += 1 {
if !utils.IsInStringArray(u.SshAuthorizedKeys[j], conf.Users[i].SshAuthorizedKeys) {
conf.Users[i].SshAuthorizedKeys = append(conf.Users[i].SshAuthorizedKeys, u.SshAuthorizedKeys[j])
}
}
return
}
}
// no such user
conf.Users = append(conf.Users, u)
}
func (conf *SCloudConfig) MergeWriteFile(f SWriteFile, replace bool) {
for i := 0; i < len(conf.WriteFiles); i += 1 {
if conf.WriteFiles[i].Path == f.Path {
// find file
if replace {
conf.WriteFiles[i].Content = f.Content
conf.WriteFiles[i].Encoding = f.Encoding
conf.WriteFiles[i].Owner = f.Owner
conf.WriteFiles[i].Permissions = f.Permissions
}
return
}
}
// no such file
conf.WriteFiles = append(conf.WriteFiles, f)
}
func (conf *SCloudConfig) MergeRuncmd(cmd string) {
if !utils.IsInStringArray(cmd, conf.Runcmd) {
conf.Runcmd = append(conf.Runcmd, cmd)
}
}
func (conf *SCloudConfig) MergeBootcmd(cmd string) {
if !utils.IsInStringArray(cmd, conf.Bootcmd) {
conf.Bootcmd = append(conf.Bootcmd, cmd)
}
}
func (conf *SCloudConfig) MergePackage(pkg string) {
if !utils.IsInStringArray(pkg, conf.Packages) {
conf.Packages = append(conf.Packages, pkg)
}
}
func (conf *SCloudConfig) Merge(conf2 *SCloudConfig) {
for _, u := range conf2.Users {
conf.MergeUser(u)
}
for _, f := range conf2.WriteFiles {
conf.MergeWriteFile(f, false)
}
for _, c := range conf2.Runcmd {
conf.MergeRuncmd(c)
}
for _, c := range conf2.Bootcmd {
conf.MergeBootcmd(c)
}
for _, p := range conf2.Packages {
conf.MergePackage(p)
}
}
+49
View File
@@ -0,0 +1,49 @@
package cloudinit
import (
"testing"
)
func TestSCloudConfig_UserData(t *testing.T) {
usr1 := NewUser("root")
usr1.SshKey("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCa4E8wmIOlmh1G8ZRcU2zpnl2frD2lLKdXpbTeUUZEKYFFlYM8TM5UrKrqrMCd3rFjaYGTKWiQwOiWroXlAXausbbVEI29KY+1Vd26qNyejj+CZO9MCj0naIrqa1V0of3TQY5I2U+ToIkyLqVFWhWVa57v/GUxsV2aNTmUS/qz0OPSCFPbGWWB35rsjwnFwq2jF6E8yJgTGDTYZcsghRi3IWfyfeHbSuWdvn6N8XrPBDmNg7h+GSvO6FJlp6MUw1hscECi13GwqXYgJnLG5RMiFH6s0vhozyHkue1vOTcryPHRQD0Jz/INUSaggH8L1HnYSUavOf4Cw25W9HfzgUBf")
usr2 := NewUser("yunion")
usr2.Password("123@yunion").SudoPolicy(USER_SUDO_NOPASSWD)
file1 := NewWriteFile("/etc/ansible/hosts", "gobuild\ncloudev\n", "", "", true)
file2 := NewWriteFile("/etc/hosts", "127.0.0.1 localhost\n", "", "", false)
config := SCloudConfig{
Users: []SUser{
usr1,
usr2,
},
WriteFiles: []SWriteFile{
file1,
file2,
},
Runcmd: []string{
"mkdir /var/run/httpd",
},
PhoneHome: &SPhoneHome{
Url: "http://www.yunion.io/$INSTANCE_ID",
},
DisableRoot: 0,
SshPwauth: 1,
}
userData := config.UserData()
t.Logf("%s", userData)
config2, err := ParseUserData(userData)
if err != nil {
t.Errorf("%s", err)
} else {
userData2 := config2.UserData()
t.Logf("%s", userData2)
if userData != userData2 {
t.Errorf("userData not equal to userData2")
}
}
}
+1
View File
@@ -0,0 +1 @@
package cloudinit // import "yunion.io/x/onecloud/pkg/util/cloudinit"
+2 -2
View File
@@ -358,7 +358,7 @@ func (self *SHost) GetManagerId() string {
}
func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, vswitchId string, ipAddr string, desc string,
passwd string, storageType string, diskSizes []int, publicKey string, secGrpId string) (cloudprovider.ICloudVM, error) {
passwd string, storageType string, diskSizes []int, publicKey string, secGrpId string, userData string) (cloudprovider.ICloudVM, error) {
log.Debugf("CreateVM")
return nil, cloudprovider.ErrNotImplemented
}
}
+5 -1
View File
@@ -244,4 +244,8 @@ func (self *SVirtualMachine) GetBillingType() string {
func (self *SVirtualMachine) GetExpiredAt() time.Time {
return time.Time{}
}
}
func (self *SVirtualMachine) UpdateUserData(userData string) error {
return nil
}
+1
View File
@@ -0,0 +1 @@
package excelutils // import "yunion.io/x/onecloud/pkg/util/excelutils"
+10 -10
View File
@@ -1,9 +1,9 @@
package excelutils
import (
"io"
"bytes"
"fmt"
"io"
"os"
"github.com/360EntSecGroup-Skylar/excelize"
@@ -21,7 +21,7 @@ func decimalBaseMaxWidth(decNum int, base int) int {
}
width := 0
for decNum > 0 {
decNum = decNum/base
decNum = decNum / base
width += 1
}
return width
@@ -29,9 +29,9 @@ func decimalBaseMaxWidth(decNum int, base int) int {
func decimalBaseN(decNum int, base int, width int) (int, int) {
b := 1
for i := 0; i < width - 1; i += 1 {
decNum = decNum/base
b = b*base
for i := 0; i < width-1; i += 1 {
decNum = decNum / base
b = b * base
}
return decNum, b
}
@@ -41,8 +41,8 @@ func decimal2Base(decNum int, base int) []int {
ret := make([]int, width)
for i := width; i > 0; i -= 1 {
ith, divider := decimalBaseN(decNum, base, i)
decNum -= ith*divider
ret[width - i] = ith
decNum -= ith * divider
ret[width-i] = ith
}
return ret
}
@@ -84,18 +84,18 @@ func Export(data []jsonutils.JSONObject, keys []string, texts []string, writer i
exportHeader(xlsx, texts, 1)
for i := 0; i < len(data); i += 1 {
exportRow(xlsx, data[i], keys, i + 2)
exportRow(xlsx, data[i], keys, i+2)
}
return xlsx.Write(writer)
}
func ExportFile(data []jsonutils.JSONObject, keys []string, texts []string, filename string) error {
writer, err:= os.Create(filename)
writer, err := os.Create(filename)
if err != nil {
return err
}
defer writer.Close()
return Export(data, keys, texts, writer)
}
}
+13 -14
View File
@@ -2,7 +2,6 @@ package excelutils
import "testing"
func arrayEqual(a1, a2 []int) bool {
if len(a1) != len(a2) {
return false
@@ -17,10 +16,10 @@ func arrayEqual(a1, a2 []int) bool {
func TestDecimalBaseMaxWidth(t *testing.T) {
cases := []struct {
decIn int
decIn int
baseIn int
want int
} {
want int
}{
{100, 10, 3},
{16, 16, 2},
{15, 16, 1},
@@ -33,12 +32,12 @@ func TestDecimalBaseMaxWidth(t *testing.T) {
}
cases2 := []struct {
decIn int
decIn int
baseIn int
width int
want int
want2 int
} {
width int
want int
want2 int
}{
{100, 10, 3, 1, 100},
{16, 16, 2, 1, 16},
{15, 16, 1, 15, 1},
@@ -52,10 +51,10 @@ func TestDecimalBaseMaxWidth(t *testing.T) {
}
cases3 := []struct {
decIn int
decIn int
baseIn int
want []int
} {
want []int
}{
{100, 10, []int{1, 0, 0}},
{16, 16, []int{1, 0}},
{0, 16, []int{0}},
@@ -76,8 +75,8 @@ func TestDecimalBaseMaxWidth(t *testing.T) {
cases4 := []struct {
decIn int
want string
} {
want string
}{
{0, "A"},
{1, "B"},
{25, "Z"},
+1
View File
@@ -0,0 +1 @@
package imagetools // import "yunion.io/x/onecloud/pkg/util/imagetools"
+108
View File
@@ -0,0 +1,108 @@
package seclib2
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
// https://stackoverflow.com/questions/23897809/different-results-in-go-and-pycrypto-when-using-aes-cfb
// CFB stream with 8 bit segment size
// See http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
type cfb8 struct {
b cipher.Block
blockSize int
in []byte
out []byte
decrypt bool
}
func (x *cfb8) XORKeyStream(dst, src []byte) {
for i := range src {
x.b.Encrypt(x.out, x.in)
copy(x.in[:x.blockSize-1], x.in[1:])
if x.decrypt {
x.in[x.blockSize-1] = src[i]
}
dst[i] = src[i] ^ x.out[0]
if !x.decrypt {
x.in[x.blockSize-1] = dst[i]
}
}
}
// NewCFB8Encrypter returns a Stream which encrypts with cipher feedback mode
// (segment size = 8), using the given Block. The iv must be the same length as
// the Block's block size.
func newCFB8Encrypter(block cipher.Block, iv []byte) cipher.Stream {
return newCFB8(block, iv, false)
}
// NewCFB8Decrypter returns a Stream which decrypts with cipher feedback mode
// (segment size = 8), using the given Block. The iv must be the same length as
// the Block's block size.
func newCFB8Decrypter(block cipher.Block, iv []byte) cipher.Stream {
return newCFB8(block, iv, true)
}
func newCFB8(block cipher.Block, iv []byte, decrypt bool) cipher.Stream {
blockSize := block.BlockSize()
if len(iv) != blockSize {
// stack trace will indicate whether it was de or encryption
panic("cipher.newCFB: IV length must equal block size")
}
x := &cfb8{
b: block,
blockSize: blockSize,
out: make([]byte, blockSize),
in: make([]byte, blockSize),
decrypt: decrypt,
}
copy(x.in, iv)
return x
}
func toAESKey(k []byte) []byte {
if len(k) > 32 {
return k[0:32]
} else {
for len(k) < 32 {
k = append(k, '$')
}
return k
}
}
func decryptAES(k, secret []byte) ([]byte, error) {
block, err := aes.NewCipher(toAESKey(k))
if err != nil {
return nil, err
}
if len(secret) < aes.BlockSize {
return nil, fmt.Errorf("ciphertext too short")
}
iv := secret[:aes.BlockSize]
ciphertext := secret[aes.BlockSize:]
stream := newCFB8Decrypter(block, iv)
stream.XORKeyStream(ciphertext, ciphertext)
return ciphertext, nil
}
func encryptAES(k, msg []byte) ([]byte, error) {
block, err := aes.NewCipher(toAESKey(k))
if err != nil {
return nil, err
}
cipherText := make([]byte, aes.BlockSize+len(msg))
iv := cipherText[:aes.BlockSize]
if _, err = io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
stream := newCFB8Encrypter(block, iv)
stream.XORKeyStream(cipherText[aes.BlockSize:], msg)
return cipherText, nil
}
+24
View File
@@ -0,0 +1,24 @@
package seclib2
import "testing"
func TestAes(t *testing.T) {
secret := "This is a secret for AES!!!"
key := "This is AES key"
code, err := encryptAES([]byte(key), []byte(secret))
if err != nil {
t.Errorf("encrypt error %s", err)
return
}
secret2, err := decryptAES([]byte(key), code)
if err != nil {
t.Errorf("decrypt error %s", err)
return
}
if secret != string(secret2) {
t.Errorf("aes encrypt/decrypt mismatch! %s != %s", secret, string(secret2))
}
}
+117
View File
@@ -0,0 +1,117 @@
package seclib2
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"golang.org/x/crypto/ssh"
"crypto"
"crypto/dsa"
"crypto/ecdsa"
"encoding/base64"
"fmt"
"yunion.io/x/log"
)
func exportSshPublicKey(pubkey interface{}) ([]byte, error) {
pub, err := ssh.NewPublicKey(pubkey)
if err != nil {
return nil, err
}
return ssh.MarshalAuthorizedKey(pub), nil
}
func ssh2CryptoPublicKey(key ssh.PublicKey) crypto.PublicKey {
cryptoPub := key.(ssh.CryptoPublicKey)
return cryptoPub.CryptoPublicKey()
}
func ssh2rsaPublicKey(key ssh.PublicKey) *rsa.PublicKey {
cryptoKey := ssh2CryptoPublicKey(key)
return cryptoKey.(*rsa.PublicKey)
}
func ssh2dsaPublicKey(key ssh.PublicKey) *dsa.PublicKey {
cryptoKey := ssh2CryptoPublicKey(key)
return cryptoKey.(*dsa.PublicKey)
}
func ssh2ecdsaPublicKey(key ssh.PublicKey) *ecdsa.PublicKey {
cryptoKey := ssh2CryptoPublicKey(key)
return cryptoKey.(*ecdsa.PublicKey)
}
func Encrypt(publicKey, origData []byte) ([]byte, error) {
pub, _, _, _, err := ssh.ParseAuthorizedKey(publicKey)
if err != nil {
log.Errorf("parse authorized key error %s", err)
return nil, err
}
if pub.Type() == ssh.KeyAlgoRSA {
return rsa.EncryptOAEP(sha1.New(), rand.Reader, ssh2rsaPublicKey(pub), origData, nil)
} else {
var pubInf interface{}
switch pub.Type() {
case ssh.KeyAlgoDSA:
pubInf = ssh2dsaPublicKey(pub)
case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521:
pubInf = ssh2ecdsaPublicKey(pub)
default:
return nil, fmt.Errorf("unsupported key type %s", pub.Type())
}
pubStr, err := exportSshPublicKey(pubInf)
if err != nil {
return nil, err
}
return encryptAES(pubStr, origData)
}
}
func Decrypt(privateKey, secret []byte) ([]byte, error) {
priv, err := ssh.ParseRawPrivateKey(privateKey)
if err != nil {
return nil, err
}
switch priv.(type) {
case *rsa.PrivateKey:
rsaPriv := priv.(*rsa.PrivateKey)
return rsa.DecryptOAEP(sha1.New(), rand.Reader, rsaPriv, secret, nil)
case *dsa.PrivateKey:
dsaPriv := priv.(*dsa.PrivateKey)
dsaPub, err := exportSshPublicKey(&dsaPriv.PublicKey)
if err != nil {
return nil, err
}
return decryptAES(dsaPub, secret)
case *ecdsa.PrivateKey:
ecdsaPriv := priv.(*ecdsa.PrivateKey)
ecdsaPub, err := exportSshPublicKey(&ecdsaPriv.PublicKey)
if err != nil {
return nil, err
}
return decryptAES(ecdsaPub, secret)
}
return nil, fmt.Errorf("unsupported")
}
func EncryptBase64(publicKey string, message string) (string, error) {
secretBytes, err := Encrypt([]byte(publicKey), []byte(message))
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(secretBytes), nil
}
func DecryptBase64(privateKey string, secret string) (string, error) {
secretBytes, err := base64.StdEncoding.DecodeString(secret)
if err != nil {
return "", err
}
msgBytes, err := Decrypt([]byte(privateKey), secretBytes)
if err != nil {
return "", err
}
return string(msgBytes), nil
}
+20
View File
@@ -0,0 +1,20 @@
package seclib2
import (
"fmt"
"github.com/tredoe/osutil/user/crypt/sha512_crypt"
"yunion.io/x/pkg/util/seclib"
)
func GeneratePassword(passwd string) (string, error) {
salt := seclib.RandomPassword(8)
sha512Crypt := sha512_crypt.New()
return sha512Crypt.Generate([]byte(passwd), []byte(fmt.Sprintf("$6$%s", salt)))
}
func VerifyPassword(passwd string, hash string) error {
sha512Crypt := sha512_crypt.New()
return sha512Crypt.Verify(hash, []byte(passwd))
}
+18
View File
@@ -0,0 +1,18 @@
package seclib2
import "testing"
func TestGeneratePassword(t *testing.T) {
passwd := "Hello world!"
dk, err := GeneratePassword(passwd)
if err != nil {
t.Errorf("%s", err)
return
}
t.Logf("%s", dk)
err = VerifyPassword(passwd, dk)
if err != nil {
t.Errorf("fail to verify %s", err)
}
}
+4 -4
View File
@@ -13,17 +13,17 @@ const (
UPPERS = "ABCDEFGHJKMNPRSTUVWXYZ"
PUNC = "()~@#$%^&*-+={}[]:;<>,.?/"
ALL_DIGITS = "0123456789"
ALL_DIGITS = "0123456789"
ALL_LETTERS = "abcdefghijklmnopqrstuvwxyz"
ALL_UPPERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
ALL_PUNC = "~`!@#$%^&*()-_=+[]{}|:';\",./<>?"
ALL_PUNC = "~`!@#$%^&*()-_=+[]{}|:';\",./<>?"
)
type PasswordStrength struct {
Digits int
Digits int
Lowercases int
Uppercases int
Punctuats int
Punctuats int
}
var CHARS = fmt.Sprintf("%s%s%s%s", DIGITS, LETTERS, UPPERS, PUNC)
+4 -4
View File
@@ -1,8 +1,8 @@
package seclib2
import (
"testing"
"math/rand"
"testing"
"time"
)
@@ -12,10 +12,10 @@ func TestRandomPassword2(t *testing.T) {
}
func TestMeetComplxity(t *testing.T) {
cases := [] struct {
in string
cases := []struct {
in string
want bool
} {
}{
{"123456", false},
{"123abcABC!@#", true},
}

Some files were not shown because too many files have changed in this diff Show More