mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 10:46:58 +08:00
Merge pull request #3805 from rainzm/feature/guest_template
feature: Guest Template & Service Catalog
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
type GuestTemplateListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
R(&GuestTemplateListOptions{}, "server-template-list", "List server template", func(s *mcclient.ClientSession,
|
||||
opts *GuestTemplateListOptions) error {
|
||||
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.GuestTemplate.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.GuestTemplate.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type GuestTemplateCreateOptions struct {
|
||||
options.ServerCreateOptionalOptions
|
||||
NAME string `help:"Name of server template" json:"-"`
|
||||
}
|
||||
|
||||
R(&GuestTemplateCreateOptions{}, "server-template-create", "Create a server template",
|
||||
func(s *mcclient.ClientSession,
|
||||
opts *GuestTemplateCreateOptions) error {
|
||||
|
||||
params, err := opts.OptionalParams()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if options.BoolV(opts.DryRun) {
|
||||
fmt.Println("no support operator")
|
||||
return nil
|
||||
}
|
||||
|
||||
dict := jsonutils.NewDict()
|
||||
if opts.GenerateName {
|
||||
dict.Add(jsonutils.NewString(opts.NAME), "generate_name")
|
||||
} else {
|
||||
dict.Add(jsonutils.NewString(opts.NAME), "name")
|
||||
}
|
||||
dict.Add(params.JSON(params), "content")
|
||||
tem, err := modules.GuestTemplate.Create(s, dict)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(tem)
|
||||
return nil
|
||||
})
|
||||
|
||||
type GuestTemplateUpdateOptions struct {
|
||||
options.ServerCreateOptionalOptions
|
||||
ID string `help:"ID of server template"`
|
||||
name string `help:"name of server template"`
|
||||
}
|
||||
|
||||
R(&GuestTemplateUpdateOptions{}, "server-template-update", "Update a server template",
|
||||
func(s *mcclient.ClientSession, opts *GuestTemplateUpdateOptions) error {
|
||||
|
||||
params, err := opts.OptionalParams()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if options.BoolV(opts.DryRun) {
|
||||
fmt.Println("no support operator")
|
||||
return nil
|
||||
}
|
||||
dict := jsonutils.NewDict()
|
||||
if len(opts.name) != 0 {
|
||||
dict.Add(jsonutils.NewString(opts.name), "name")
|
||||
}
|
||||
dict.Add(params.JSON(params), "content")
|
||||
tem, err := modules.GuestTemplate.Update(s, opts.ID, dict)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(tem)
|
||||
return nil
|
||||
})
|
||||
|
||||
type GuestTemplateOptions struct {
|
||||
ID string `help:"ID or Name of server template"`
|
||||
}
|
||||
|
||||
R(&GuestTemplateOptions{}, "server-template-show", "Show a server template",
|
||||
func(s *mcclient.ClientSession, opts *GuestTemplateOptions) error {
|
||||
tem, err := modules.GuestTemplate.Get(s, opts.ID, jsonutils.JSONNull)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(tem)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&GuestTemplateOptions{}, "server-tempalte-delete", "Delete a server template",
|
||||
func(s *mcclient.ClientSession, opts *GuestTemplateOptions) error {
|
||||
|
||||
tem, err := modules.GuestTemplate.Delete(s, opts.ID, jsonutils.JSONNull)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(tem)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
R(&GuestTemplateOptions{}, "server-template-private", "Private server template",
|
||||
func(s *mcclient.ClientSession, opts *GuestTemplateOptions) error {
|
||||
tem, err := modules.GuestTemplate.PerformAction(s, opts.ID, "private", jsonutils.JSONNull)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(tem)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
type GuestTemplatePublicOptions struct {
|
||||
ID string `help:"ID or Name of server template"`
|
||||
PublicScope string `help:"public scope"`
|
||||
}
|
||||
|
||||
R(&GuestTemplatePublicOptions{}, "server-template-public", "Public server template",
|
||||
func(s *mcclient.ClientSession, opts *GuestTemplatePublicOptions) error {
|
||||
|
||||
dict := jsonutils.NewDict()
|
||||
if len(opts.PublicScope) != 0 {
|
||||
dict.Add(jsonutils.NewString(opts.PublicScope), "public_scope")
|
||||
}
|
||||
tem, err := modules.GuestTemplate.PerformAction(s, opts.ID, "public", dict)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(tem)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ServiceCatalogListOpions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
R(&ServiceCatalogListOpions{}, "service-catalog-list", "List service catalog", func(s *mcclient.ClientSession,
|
||||
opts *ServiceCatalogListOpions) error {
|
||||
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret, err := modules.ServiceCatalog.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(ret, modules.ServiceCatalog.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type ServiceCatalogCreateOptions struct {
|
||||
NAME string `help:"Name of service catalog"`
|
||||
GuestTemplate string `help:"guest template of service catalog"`
|
||||
IconUrl string `help:"icon url of service catalog"`
|
||||
GenerateName bool `help:"whether to generate name"`
|
||||
}
|
||||
|
||||
R(&ServiceCatalogCreateOptions{}, "service-catalog-create", "Create a service catalog",
|
||||
func(s *mcclient.ClientSession, opts *ServiceCatalogCreateOptions) error {
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
if opts.GenerateName {
|
||||
params.Add(jsonutils.NewString(opts.NAME), "generate_name")
|
||||
} else {
|
||||
params.Add(jsonutils.NewString(opts.NAME), "name")
|
||||
}
|
||||
if len(opts.GuestTemplate) != 0 {
|
||||
params.Add(jsonutils.NewString(opts.GuestTemplate), "guest_template")
|
||||
}
|
||||
if len(opts.IconUrl) != 0 {
|
||||
params.Add(jsonutils.NewString(opts.IconUrl), "icon_url")
|
||||
}
|
||||
serviceCatalog, err := modules.ServiceCatalog.Create(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(serviceCatalog)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
type ServiceCatalogOptions struct {
|
||||
ID string `help:"ID or name of service catalog"`
|
||||
}
|
||||
|
||||
R(&ServiceCatalogOptions{}, "service-catalog-show", "show a service catalog", func(s *mcclient.ClientSession,
|
||||
opts *ServiceCatalogOptions) error {
|
||||
|
||||
sc, err := modules.ServiceCatalog.Get(s, opts.ID, jsonutils.JSONNull)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(sc)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&ServiceCatalogOptions{}, "service-catalog-delete", "delete a service catalog", func(s *mcclient.ClientSession,
|
||||
opts *ServiceCatalogOptions) error {
|
||||
|
||||
sc, err := modules.ServiceCatalog.Delete(s, opts.ID, jsonutils.JSONNull)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(sc)
|
||||
return nil
|
||||
})
|
||||
|
||||
type ServiceCatalogUpdateOptions struct {
|
||||
ServiceCatalogOptions
|
||||
Name string `help:"Name of service catalog"`
|
||||
GuestTemplate string `help:"guest template of service catalog"`
|
||||
IconUrl string `help:"icon url of service catalog"`
|
||||
}
|
||||
|
||||
R(&ServiceCatalogUpdateOptions{}, "service-catalog-update", "update a service catalog",
|
||||
func(s *mcclient.ClientSession, opts *ServiceCatalogUpdateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if len(opts.Name) > 0 {
|
||||
params.Add(jsonutils.NewString(opts.Name), "name")
|
||||
}
|
||||
if len(opts.GuestTemplate) > 0 {
|
||||
params.Add(jsonutils.NewString(opts.GuestTemplate), "guest_template")
|
||||
}
|
||||
if len(opts.IconUrl) > 0 {
|
||||
params.Add(jsonutils.NewString(opts.IconUrl), "icon_url")
|
||||
}
|
||||
sc, err := modules.ServiceCatalog.Update(s, opts.ID, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(sc)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
type ServiceCatalogDeployOptions struct {
|
||||
ServiceCatalogOptions
|
||||
Name string `help:"Name of guest"`
|
||||
GenerateName bool `help:"whether to generate name for guest"`
|
||||
Count int `help:"count of guest"`
|
||||
ProjectID string `help:"project id of guest"`
|
||||
}
|
||||
|
||||
R(&ServiceCatalogDeployOptions{}, "service-catalog-deploy", "deploy", func(s *mcclient.ClientSession,
|
||||
opts *ServiceCatalogDeployOptions) error {
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
if opts.GenerateName {
|
||||
params.Add(jsonutils.NewString(opts.Name), "generate_name")
|
||||
} else {
|
||||
params.Add(jsonutils.NewString(opts.Name), "name")
|
||||
}
|
||||
if opts.Count != 0 {
|
||||
params.Add(jsonutils.NewInt(int64(opts.Count)), "count")
|
||||
}
|
||||
if len(opts.ProjectID) > 0 {
|
||||
params.Add(jsonutils.NewString(opts.ProjectID), "project_id")
|
||||
}
|
||||
|
||||
sc, err := modules.ServiceCatalog.PerformAction(s, opts.ID, "deploy", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(sc)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type GuesttemplateCreateInput struct {
|
||||
apis.Meta
|
||||
|
||||
// description: guest template name
|
||||
// unique: true
|
||||
// required: true
|
||||
// example: hello
|
||||
Name string `json:"name"`
|
||||
|
||||
// description: the content of guest template
|
||||
// required: true
|
||||
Content jsonutils.JSONObject `json:"content"`
|
||||
}
|
||||
|
||||
type GuesttemplateDetails struct {
|
||||
apis.Meta
|
||||
apis.SharableVirtualResourceDetails
|
||||
SGuestTemplate
|
||||
|
||||
Config GuesttemplateConfigInfo `json:"config"`
|
||||
}
|
||||
|
||||
type GuesttemplateConfigInfo struct {
|
||||
Region string `json:"region"`
|
||||
Zone string `json:"zone"`
|
||||
Hypervisor string `json:"hypervisor"`
|
||||
OsType string `json:"os_type"`
|
||||
Sku GuesttemplateSku `json:"sku"`
|
||||
Disks []GuesttemplateDisk `json:"disks"`
|
||||
Keypair string `json:"keypair"`
|
||||
Nets []GuesttemplateNetwork `json:"nets"`
|
||||
Secgroup string `json:"secgroup"`
|
||||
IsolatedDeviceConfig []IsolatedDeviceConfig `json:"isolated_device_config"`
|
||||
Image string `json:"image"`
|
||||
}
|
||||
|
||||
type GuesttemplateDisk struct {
|
||||
Backend string `json:"backend"`
|
||||
DiskType string `json:"disk_type"`
|
||||
Index int `json:"index"`
|
||||
SizeMb int `json:"size_mb"`
|
||||
}
|
||||
|
||||
type GuesttemplateNetwork struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
GuestIpStart string `json:"guest_ip_start"`
|
||||
GuestIpEnd string `json:"guest_up_end"`
|
||||
VlanId int `json:"vlan_id"`
|
||||
}
|
||||
|
||||
type GuesttemplateSku struct {
|
||||
Name string `json:"name"`
|
||||
CpuCoreCount int `json:"cpu_core_count"`
|
||||
MemorySizeMb int `json:"memory_size_mb"`
|
||||
InstanceTypeCategory string `json:"instance_type_category`
|
||||
InstanceTypeFamily string `json:"instance_type_family"`
|
||||
}
|
||||
|
||||
type GuesttemplatePublicInput struct {
|
||||
apis.Meta
|
||||
|
||||
// description: the scope about public operator
|
||||
// required: true
|
||||
// example: system
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package compute
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type ServiceCatalogCreateInput struct {
|
||||
apis.Meta
|
||||
|
||||
// description: service catalog name
|
||||
// uniqure: true
|
||||
// required: true
|
||||
// example: hello
|
||||
Name string `json:"name`
|
||||
|
||||
// description: service catalog icon url
|
||||
// example: https://yunion.io/files/hello.png
|
||||
IconUrl string `json:"icon_url"`
|
||||
|
||||
// description: the id or name of guest template
|
||||
// example: good
|
||||
GuestTemplate string `json:"guest_template"`
|
||||
}
|
||||
|
||||
type ServiceCatalogDeploy struct {
|
||||
|
||||
// description: name of the new vm
|
||||
// example: hello
|
||||
Name string `json:"name"`
|
||||
|
||||
// description: generate name automatically if name is repeated, and only one of name and this shoudle be given
|
||||
// example: hello
|
||||
GenerateName string `json:"generate_name"`
|
||||
|
||||
// description: the count of the new vm
|
||||
// example: 1
|
||||
Count int `json:"count"`
|
||||
}
|
||||
@@ -549,6 +549,18 @@ type SGuestJointsBase struct {
|
||||
GuestId string `json:"guest_id"`
|
||||
}
|
||||
|
||||
// SGuestTemplate is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestTemplate.
|
||||
type SGuestTemplate struct {
|
||||
apis.SSharableVirtualResourceBase
|
||||
VcpuCount int `json:"vcpu_count"`
|
||||
VmemSize int `json:"vmem_size"`
|
||||
OsType string `json:"os_type"`
|
||||
ImageType string `json:"image_type"`
|
||||
ImageId string `json:"image_id"`
|
||||
Hypervisor string `json:"hypervisor"`
|
||||
Content interface{} `json:"content"`
|
||||
}
|
||||
|
||||
// SGuestdisk is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestdisk.
|
||||
type SGuestdisk struct {
|
||||
SGuestJointsBase
|
||||
@@ -1191,6 +1203,13 @@ type SServerSku struct {
|
||||
Provider string `json:"provider"`
|
||||
}
|
||||
|
||||
// SServiceCatalog is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SServiceCatalog.
|
||||
type SServiceCatalog struct {
|
||||
apis.SSharableVirtualResourceBase
|
||||
IconUrl string `json:"icon_url"`
|
||||
GuestTemplateID string `json:"guest_template_id"`
|
||||
}
|
||||
|
||||
// SSnapshot is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SSnapshot.
|
||||
type SSnapshot struct {
|
||||
apis.SVirtualResourceBase
|
||||
|
||||
@@ -48,6 +48,7 @@ type SImage struct {
|
||||
SizeBytes int64 `json:"size"`
|
||||
Status string
|
||||
// UpdatedAt time.Time
|
||||
PublicScope string
|
||||
}
|
||||
|
||||
func CloudImage2Image(image ICloudImage) SImage {
|
||||
|
||||
@@ -0,0 +1,397 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
|
||||
computeapis "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"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/onecloud/pkg/util/logclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
|
||||
const (
|
||||
IMAGE_TYPE_NORMAL = "normal"
|
||||
IMAGE_TYPE_GUEST = "guest"
|
||||
)
|
||||
|
||||
type SGuestTemplateManager struct {
|
||||
db.SSharableVirtualResourceBaseManager
|
||||
}
|
||||
|
||||
type SGuestTemplate struct {
|
||||
db.SSharableVirtualResourceBase
|
||||
|
||||
VcpuCount int `nullable:"false" default:"1" create:"optional"`
|
||||
VmemSize int `nullable:"false" create:"optional"`
|
||||
OsType string `width:"36" charset:"ascii" nullable:"true" create:"optional"`
|
||||
ImageType string `width:"10" charset:"ascii" nullabel:"true" default:"normal" create:"optional"`
|
||||
ImageId string `width:"128" charset:"ascii" create:"optional"`
|
||||
Hypervisor string `width:"16" charset:"ascii" default:"kvm" create:"optional"`
|
||||
|
||||
Content jsonutils.JSONObject `nullable:"false" list:"user" update:"user" create:"optional"`
|
||||
}
|
||||
|
||||
var GuestTemplateManager *SGuestTemplateManager
|
||||
|
||||
func init() {
|
||||
GuestTemplateManager = &SGuestTemplateManager{
|
||||
SSharableVirtualResourceBaseManager: db.NewSharableVirtualResourceBaseManager(
|
||||
SGuestTemplate{},
|
||||
"guesttemplates_tbl",
|
||||
"servertemplate",
|
||||
"servertemplates",
|
||||
),
|
||||
}
|
||||
|
||||
GuestTemplateManager.SetVirtualObject(GuestTemplateManager)
|
||||
}
|
||||
|
||||
func (gtm *SGuestTemplateManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *computeapis.GuesttemplateCreateInput) (*jsonutils.JSONDict, error) {
|
||||
|
||||
if input.Content == nil {
|
||||
return nil, httperrors.NewMissingParameterError("content")
|
||||
}
|
||||
|
||||
data, err := gtm.validateData(ctx, userCred, ownerId, query, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gtm.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
func (gt *SGuestTemplate) PostCreate(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
|
||||
logclient.AddActionLogWithContext(ctx, gt, logclient.ACT_CREATE, nil, userCred, true)
|
||||
}
|
||||
|
||||
func (gt *SGuestTemplate) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
logclient.AddActionLogWithContext(ctx, gt, logclient.ACT_UPDATE, nil, userCred, true)
|
||||
}
|
||||
|
||||
func (gtm *SGuestTemplateManager) validateData(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, cinput *computeapis.GuesttemplateCreateInput) (*jsonutils.JSONDict, error) {
|
||||
if cinput.Content == nil {
|
||||
return cinput.JSON(cinput), nil
|
||||
}
|
||||
content := cinput.Content
|
||||
data := cinput.JSON(cinput)
|
||||
// not support guest image and guest snapshot for now
|
||||
if content.Contains("instance_snapshot_id") {
|
||||
return nil, httperrors.NewInputParameterError(
|
||||
"no support for instance snapshot in guest template for now")
|
||||
}
|
||||
// I don't hope cinput.Content same with data["content"] will change in GuestManager.validateCreateData
|
||||
copy := jsonutils.DeepCopy(content).(*jsonutils.JSONDict)
|
||||
input, err := GuestManager.validateCreateData(ctx, userCred, ownerId, query, copy)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
// fill field
|
||||
data.Add(jsonutils.NewInt(int64(input.VmemSize)), "vmem_size")
|
||||
data.Add(jsonutils.NewInt(int64(input.VcpuCount)), "vcpu_count")
|
||||
data.Add(jsonutils.NewString(input.OsType), "os_type")
|
||||
data.Add(jsonutils.NewString(input.Hypervisor), "hypervisor")
|
||||
|
||||
if len(input.GuestImageID) > 0 {
|
||||
data.Add(jsonutils.NewString(IMAGE_TYPE_GUEST), "image_type")
|
||||
data.Add(jsonutils.NewString(input.GuestImageID), "image_id")
|
||||
} else {
|
||||
data.Add(jsonutils.NewString(input.Disks[0].ImageId), "image_id")
|
||||
data.Add(jsonutils.NewString(IMAGE_TYPE_NORMAL), "image_type")
|
||||
}
|
||||
|
||||
// hide some properties
|
||||
contentDict := content.(*jsonutils.JSONDict)
|
||||
contentDict.Remove("name")
|
||||
contentDict.Remove("generate_name")
|
||||
// "__count__" was converted to "count" by apigateway
|
||||
contentDict.Remove("count")
|
||||
contentDict.Remove("project_id")
|
||||
|
||||
data.Add(contentDict, "content")
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (gt *SGuestTemplate) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, cinput *computeapis.GuesttemplateCreateInput) (*jsonutils.JSONDict, error) {
|
||||
|
||||
data, err := GuestTemplateManager.validateData(ctx, userCred, gt.GetOwnerId(), query, cinput)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
return gt.SSharableVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
}
|
||||
|
||||
func (gt *SGuestTemplate) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject) (*computeapis.GuesttemplateDetails, error) {
|
||||
|
||||
out := &computeapis.GuesttemplateDetails{}
|
||||
err := gt.SSharableVirtualResourceBase.GetExtraDetailsV2(ctx, userCred, query, &out.SharableVirtualResourceDetails)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
gt.getMoreDetailsV2(ctx, userCred, out)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (gt *SGuestTemplate) getMoreDetailsV2(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
out *computeapis.GuesttemplateDetails) {
|
||||
|
||||
input, err := cmdline.FetchServerCreateInputByJSON(gt.Content)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
configInfo := computeapis.GuesttemplateConfigInfo{}
|
||||
if len(input.PreferRegion) != 0 {
|
||||
region := CloudregionManager.FetchRegionById(input.PreferRegion)
|
||||
if region != nil {
|
||||
input.PreferRegion = region.GetName()
|
||||
}
|
||||
configInfo.Region = input.PreferRegion
|
||||
|
||||
}
|
||||
if len(input.PreferZone) != 0 {
|
||||
zone := ZoneManager.FetchZoneById(input.PreferZone)
|
||||
if zone != nil {
|
||||
input.PreferZone = zone.GetName()
|
||||
}
|
||||
configInfo.Zone = input.PreferZone
|
||||
}
|
||||
configInfo.Hypervisor = gt.Hypervisor
|
||||
configInfo.OsType = gt.OsType
|
||||
|
||||
// sku deal
|
||||
if len(input.InstanceType) > 0 {
|
||||
skuOutput := computeapis.GuesttemplateSku{}
|
||||
provider := GetDriver(gt.Hypervisor).GetProvider()
|
||||
sku, err := ServerSkuManager.FetchSkuByNameAndProvider(input.InstanceType, provider, true)
|
||||
if err != nil {
|
||||
skuOutput.Name = input.InstanceType
|
||||
skuOutput.MemorySizeMb = gt.VmemSize
|
||||
skuOutput.CpuCoreCount = gt.VcpuCount
|
||||
} else {
|
||||
skuOutput.Name = sku.Name
|
||||
skuOutput.MemorySizeMb = sku.MemorySizeMB
|
||||
skuOutput.CpuCoreCount = sku.CpuCoreCount
|
||||
skuOutput.InstanceTypeCategory = sku.InstanceTypeCategory
|
||||
skuOutput.InstanceTypeFamily = sku.InstanceTypeFamily
|
||||
}
|
||||
configInfo.Sku = skuOutput
|
||||
}
|
||||
|
||||
// disk deal
|
||||
disks := make([]computeapis.GuesttemplateDisk, len(input.Disks))
|
||||
for i := range input.Disks {
|
||||
disks[i] = computeapis.GuesttemplateDisk{
|
||||
Backend: input.Disks[i].Backend,
|
||||
DiskType: input.Disks[i].DiskType,
|
||||
Index: input.Disks[i].Index,
|
||||
SizeMb: input.Disks[i].SizeMb,
|
||||
}
|
||||
}
|
||||
configInfo.Disks = disks
|
||||
|
||||
// keypair
|
||||
if len(input.KeypairId) > 0 {
|
||||
model, err := KeypairManager.FetchById(input.KeypairId)
|
||||
if err == nil {
|
||||
keypair := model.(*SKeypair)
|
||||
configInfo.Keypair = keypair.GetName()
|
||||
}
|
||||
}
|
||||
|
||||
// network
|
||||
if len(input.Networks) > 0 {
|
||||
networkList := make([]computeapis.GuesttemplateNetwork, 0, len(input.Networks))
|
||||
networkIdList := make([]string, len(input.Networks))
|
||||
for i := range input.Networks {
|
||||
networkIdList[i] = input.Networks[i].Network
|
||||
}
|
||||
networkSet := sets.NewString(networkIdList...)
|
||||
|
||||
q := NetworkManager.Query("id", "name", "guest_ip_start", "guest_ip_end", "vlan_id").In("id", networkIdList)
|
||||
q.All(&networkList)
|
||||
|
||||
for _, p := range networkList {
|
||||
if networkSet.Has(p.ID) {
|
||||
networkSet.Delete(p.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// some specified network
|
||||
for _, id := range networkSet.UnsortedList() {
|
||||
networkList = append(networkList, computeapis.GuesttemplateNetwork{ID: id})
|
||||
}
|
||||
|
||||
configInfo.Nets = networkList
|
||||
}
|
||||
|
||||
// secgroup
|
||||
if len(input.SecgroupId) > 0 {
|
||||
secgroup := SecurityGroupManager.FetchSecgroupById(input.SecgroupId)
|
||||
if secgroup != nil {
|
||||
input.SecgroupId = secgroup.GetName()
|
||||
}
|
||||
configInfo.Secgroup = input.SecgroupId
|
||||
}
|
||||
|
||||
// isolatedDevices
|
||||
if input.IsolatedDevices != nil && len(input.IsolatedDevices) != 0 {
|
||||
configInfo.IsolatedDeviceConfig = make([]computeapis.IsolatedDeviceConfig, len(input.IsolatedDevices))
|
||||
for i := range configInfo.IsolatedDeviceConfig {
|
||||
configInfo.IsolatedDeviceConfig[i] = *input.IsolatedDevices[i]
|
||||
}
|
||||
}
|
||||
|
||||
// fill image info
|
||||
switch gt.ImageType {
|
||||
case IMAGE_TYPE_NORMAL:
|
||||
image, err := CachedimageManager.getImageInfo(ctx, userCred, gt.ImageId, false)
|
||||
if err == nil {
|
||||
configInfo.Image = image.Name
|
||||
} else {
|
||||
configInfo.Image = gt.ImageId
|
||||
}
|
||||
case IMAGE_TYPE_GUEST:
|
||||
s := auth.GetSession(ctx, userCred, options.Options.Region, "")
|
||||
ret, err := modules.GuestImages.Get(s, gt.ImageId, jsonutils.JSONNull)
|
||||
if err != nil || !ret.Contains("id") {
|
||||
configInfo.Image = gt.ImageId
|
||||
} else {
|
||||
name, _ := ret.GetString("id")
|
||||
configInfo.Image = name
|
||||
}
|
||||
default:
|
||||
// no arrivals
|
||||
}
|
||||
|
||||
out.Config = configInfo
|
||||
return
|
||||
}
|
||||
|
||||
func (gt *SGuestTemplate) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
|
||||
// image, network, secgroup, instancegroup
|
||||
input, err := cmdline.FetchServerCreateInputByJSON(gt.Content)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fail to convert content of guest template to ServerCreateInput")
|
||||
}
|
||||
|
||||
// check for below private resource in the guest template
|
||||
privateResource := map[string]int{
|
||||
"keypair": len(input.KeypairId),
|
||||
"instance group": len(input.InstanceGroupIds),
|
||||
"instance snapshot": len(input.InstanceSnapshotId),
|
||||
}
|
||||
for k, v := range privateResource {
|
||||
if v > 0 {
|
||||
return nil, gt.genForbiddenError(k, "", "")
|
||||
}
|
||||
}
|
||||
|
||||
targetScopeStr, _ := data.GetString("scope")
|
||||
targetScope := rbacutils.String2ScopeDefault(targetScopeStr, rbacutils.ScopeSystem)
|
||||
|
||||
// check if secgroup is public
|
||||
if len(input.SecgroupId) > 0 {
|
||||
model, err := SecurityGroupManager.FetchByIdOrName(userCred, input.SecgroupId)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("there is no such secgroup %s descripted by guest template",
|
||||
input.SecgroupId)
|
||||
}
|
||||
secgroup := model.(*SSecurityGroup)
|
||||
sgScope := rbacutils.String2Scope(secgroup.PublicScope)
|
||||
if !secgroup.IsPublic || !sgScope.HigherEqual(targetScope) {
|
||||
return nil, gt.genForbiddenError("security group", input.SecgroupId, string(targetScope))
|
||||
}
|
||||
}
|
||||
|
||||
// check if networks is public
|
||||
if len(input.Networks) > 0 {
|
||||
for i := range input.Networks {
|
||||
str := input.Networks[i].Network
|
||||
model, err := NetworkManager.FetchByIdOrName(userCred, str)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewResourceNotFoundError(
|
||||
"there is no such secgroup %s descripted by guest template")
|
||||
}
|
||||
network := model.(*SNetwork)
|
||||
netScope := rbacutils.String2Scope(network.PublicScope)
|
||||
if !network.IsPublic || !netScope.HigherEqual(targetScope) {
|
||||
return nil, gt.genForbiddenError("network", str, string(targetScope))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if image is public
|
||||
var (
|
||||
isPublic bool
|
||||
publicScope string
|
||||
)
|
||||
switch gt.ImageType {
|
||||
case IMAGE_TYPE_NORMAL:
|
||||
image, err := CachedimageManager.GetImageById(ctx, userCred, gt.ImageId, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "fail to fetch image %s descripted by guest template", gt.ImageId)
|
||||
}
|
||||
isPublic, publicScope = image.IsPublic, image.PublicScope
|
||||
case IMAGE_TYPE_GUEST:
|
||||
s := auth.GetSession(ctx, userCred, options.Options.Region, "")
|
||||
ret, err := modules.GuestImages.Get(s, gt.ImageId, jsonutils.JSONNull)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "fail to fetch guest image %s descripted by guest template", gt.ImageId)
|
||||
}
|
||||
isPublic = jsonutils.QueryBoolean(ret, "is_public", false)
|
||||
publicScope, _ = ret.GetString("public_scope")
|
||||
default:
|
||||
//no arrivals
|
||||
}
|
||||
igScope := rbacutils.String2Scope(publicScope)
|
||||
if !isPublic || !igScope.HigherEqual(targetScope) {
|
||||
return nil, gt.genForbiddenError("image", "", string(targetScope))
|
||||
}
|
||||
|
||||
return gt.SSharableVirtualResourceBase.PerformPublic(ctx, userCred, query, data)
|
||||
}
|
||||
|
||||
func (gt *SGuestTemplate) genForbiddenError(resourceName, resourceStr, scope string) error {
|
||||
var msg string
|
||||
if len(resourceStr) == 0 {
|
||||
msg = fmt.Sprintf("the %s in guest template is not a public resource", resourceName)
|
||||
} else {
|
||||
msg = fmt.Sprintf("the %s '%s' in guest template is not a public resource", resourceName, resourceStr)
|
||||
}
|
||||
if len(scope) > 0 {
|
||||
msg += fmt.Sprintf(" in %s scope", scope)
|
||||
}
|
||||
return httperrors.NewForbiddenError(msg)
|
||||
}
|
||||
@@ -4877,6 +4877,12 @@ func (self *SGuestManager) checkGuestImage(ctx context.Context, input *api.Serve
|
||||
return errors.Wrap(err, "get guest image from glance error")
|
||||
}
|
||||
|
||||
// input.GuestImageID maybe name of guestimage
|
||||
if ret.Contains("id") {
|
||||
id, _ := ret.GetString("id")
|
||||
input.GuestImageID = id
|
||||
}
|
||||
|
||||
images := &api.SImagesInGuest{}
|
||||
err = ret.Unmarshal(images)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"net/url"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
computeapis "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"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"
|
||||
)
|
||||
|
||||
type SServiceCatalogManager struct {
|
||||
db.SSharableVirtualResourceBaseManager
|
||||
}
|
||||
|
||||
type SServiceCatalog struct {
|
||||
db.SSharableVirtualResourceBase
|
||||
|
||||
IconUrl string `charset:"ascii" create:"optional" list:"user" get:"user"`
|
||||
GuestTemplateID string `width:"128" charset:"ascii" create:"optional" list:"user" get:"user"`
|
||||
}
|
||||
|
||||
var ServiceCatalogManager *SServiceCatalogManager
|
||||
|
||||
func init() {
|
||||
ServiceCatalogManager = &SServiceCatalogManager{
|
||||
SSharableVirtualResourceBaseManager: db.NewSharableVirtualResourceBaseManager(
|
||||
SServiceCatalog{},
|
||||
"servicecatalogs_tbl",
|
||||
"servicecatalog",
|
||||
"servicecatalogs",
|
||||
),
|
||||
}
|
||||
ServiceCatalogManager.SetVirtualObject(ServiceCatalogManager)
|
||||
}
|
||||
|
||||
func (scm *SServiceCatalogManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *computeapis.ServiceCatalogCreateInput) (*jsonutils.JSONDict,
|
||||
error) {
|
||||
|
||||
if len(input.GuestTemplate) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("guest_template")
|
||||
}
|
||||
|
||||
model, err := GuestTemplateManager.FetchByIdOrName(userCred, input.GuestTemplate)
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("no such guest template")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gt := model.(*SGuestTemplate)
|
||||
//scope := rbacutils.String2Scope(gt.PublicScope)
|
||||
//if !gt.IsPublic || scope != rbacutils.ScopeSystem {
|
||||
// return nil, httperrors.NewForbiddenError("guest template must be public in scope system")
|
||||
//}
|
||||
if userCred.GetProjectId() != gt.ProjectId {
|
||||
return nil, httperrors.NewForbiddenError("guest template must has same project id with the request")
|
||||
}
|
||||
|
||||
data := input.JSON(input)
|
||||
data.Remove("guest_template")
|
||||
data.Add(jsonutils.NewString(model.GetId()), "guest_template_id")
|
||||
|
||||
// check url
|
||||
if len(input.IconUrl) == 0 {
|
||||
return data, nil
|
||||
}
|
||||
url, err := url.Parse(input.IconUrl)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("fail to parse icon url '%s'", input.IconUrl)
|
||||
}
|
||||
data.Add(jsonutils.NewString(url.String()), "icon_url")
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (sc *SServiceCatalog) AllowPerformDeploy(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
|
||||
return sc.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, sc, "deploy")
|
||||
}
|
||||
|
||||
func (sc *SServiceCatalog) PerformDeploy(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, input *computeapis.ServiceCatalogDeploy) (jsonutils.JSONObject, error) {
|
||||
|
||||
if len(input.Name) == 0 && len(input.GenerateName) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("name or generate_name")
|
||||
}
|
||||
model, err := GuestTemplateManager.FetchById(sc.GuestTemplateID)
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("no such guest_template %s", sc.GuestTemplateID)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
guestTempalte := model.(*SGuestTemplate)
|
||||
content := guestTempalte.Content
|
||||
contentDict := content.(*jsonutils.JSONDict)
|
||||
if len(input.GenerateName) != 0 {
|
||||
contentDict.Add(jsonutils.NewString(input.GenerateName), "generate_name")
|
||||
} else {
|
||||
contentDict.Add(jsonutils.NewString(input.Name), "name")
|
||||
}
|
||||
if input.Count != 0 {
|
||||
input.Count = 1
|
||||
}
|
||||
contentDict.Add(jsonutils.NewInt(int64(input.Count)), "count")
|
||||
s := auth.GetSession(ctx, userCred, options.Options.Region, "")
|
||||
_, err = modules.Servers.Create(s, content)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fail to create guest")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
@@ -137,6 +137,9 @@ func InitHandlers(app *appsrv.Application) {
|
||||
models.ElasticcacheBackupManager,
|
||||
models.ElasticcacheSkuManager,
|
||||
models.GlobalNetworkManager,
|
||||
|
||||
models.GuestTemplateManager,
|
||||
models.ServiceCatalogManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
handler := db.NewModelHandler(manager)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package modules
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
|
||||
type SGuestTemplateManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var GuestTemplate SGuestTemplateManager
|
||||
|
||||
func init() {
|
||||
GuestTemplate = SGuestTemplateManager{NewComputeManager("servertemplate", "servertemplates",
|
||||
[]string{"ID", "Name", "Public_Scope", "Is_Public", "Project_Id", "Content"},
|
||||
[]string{})}
|
||||
registerCompute(&GuestTemplate)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package modules
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
|
||||
type SServiceCatalog struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var ServiceCatalog SServiceCatalog
|
||||
|
||||
func init() {
|
||||
ServiceCatalog = SServiceCatalog{NewComputeManager("servicecatalog", "servicecatalogs",
|
||||
[]string{"ID", "Name", "Public_Scope", "Is_Public", "Icon_Url", "Guest_Template_ID"},
|
||||
[]string{})}
|
||||
|
||||
registerCompute(&ServiceCatalog)
|
||||
}
|
||||
@@ -245,9 +245,14 @@ type ServerCreateFromInstanceSnapshot struct {
|
||||
}
|
||||
|
||||
type ServerCreateOptions struct {
|
||||
ServerCreateOptionalOptions
|
||||
|
||||
NAME string `help:"Name of server" json:"-"`
|
||||
}
|
||||
|
||||
type ServerCreateOptionalOptions struct {
|
||||
ServerConfigs
|
||||
|
||||
NAME string `help:"Name of server" json:"-"`
|
||||
MemSpec string `help:"Memory size Or Instance Type" metavar:"MEMSPEC" json:"-"`
|
||||
|
||||
Keypair string `help:"SSH Keypair"`
|
||||
@@ -340,7 +345,7 @@ func (o *ServerCreateOptions) ToScheduleInput() (*schedapi.ScheduleInput, error)
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (opts *ServerCreateOptions) Params() (*computeapi.ServerCreateInput, error) {
|
||||
func (opts *ServerCreateOptionalOptions) OptionalParams() (*computeapi.ServerCreateInput, error) {
|
||||
config, err := opts.ServerConfigs.Data()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -370,11 +375,6 @@ func (opts *ServerCreateOptions) Params() (*computeapi.ServerCreateInput, error)
|
||||
Secgroups: opts.Secgroups,
|
||||
}
|
||||
|
||||
if opts.GenerateName {
|
||||
params.GenerateName = opts.NAME
|
||||
} else {
|
||||
params.Name = opts.NAME
|
||||
}
|
||||
if regutils.MatchSize(opts.MemSpec) {
|
||||
memSize, err := fileutils.GetSizeMb(opts.MemSpec, 'M', 1024)
|
||||
if err != nil {
|
||||
@@ -429,6 +429,22 @@ func (opts *ServerCreateOptions) Params() (*computeapi.ServerCreateInput, error)
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (opts *ServerCreateOptions) Params() (*computeapi.ServerCreateInput, error) {
|
||||
|
||||
params, err := opts.OptionalParams()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts.GenerateName {
|
||||
params.GenerateName = opts.NAME
|
||||
} else {
|
||||
params.Name = opts.NAME
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
type ServerStopOptions struct {
|
||||
ID []string `help:"ID or Name of server" json:"-"`
|
||||
Force *bool `help:"Stop server forcefully" json:"is_force"`
|
||||
|
||||
Reference in New Issue
Block a user