mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-29 03:51:54 +08:00
rebase master
This commit is contained in:
Generated
-4
@@ -1799,11 +1799,7 @@
|
||||
"utils",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
<<<<<<< HEAD
|
||||
revision = "740ce1e70d2417c195f669bbddf8ade8ec967419"
|
||||
=======
|
||||
revision = "91e7c6f49631cea6aa6b65d6d3e9e779f13ebc1e"
|
||||
>>>>>>> 细化存储信息
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
||||
@@ -47,7 +47,7 @@ func init() {
|
||||
type CloudregionCityListOptions struct {
|
||||
Manager string `help:"List objects belonging to the cloud provider"`
|
||||
Account string `help:"List objects belonging to the cloud account"`
|
||||
Provider string `help:"List objects from the provider" choices:"VMware|Aliyun|Qcloud|Azure|Aws|Huawei|Openstack"`
|
||||
Provider string `help:"List objects from the provider" choices:"VMware|Aliyun|Qcloud|Azure|Aws|Huawei|Openstack|Ucloud|ZStack"`
|
||||
City string `help:"List regions in the specified city"`
|
||||
|
||||
PublicCloud *bool `help:"List objects belonging to public cloud" json:"public_cloud"`
|
||||
|
||||
@@ -47,7 +47,9 @@ func init() {
|
||||
MANAGER string `help:"cloud provider"`
|
||||
REGION string `help:"cloud region in which EIP is allocated"`
|
||||
NAME string `help:"name of the EIP"`
|
||||
BW int `help:"Bandwidth in Mbps"`
|
||||
Bandwidth int `help:"Bandwidth in Mbps"`
|
||||
Ip string `help:"IP address of the EIP"`
|
||||
Network string `help:"Network of the EIP"`
|
||||
ChargeType string `help:"bandwidth charge type, either traffic or bandwidth" choices:"traffic|bandwidth"`
|
||||
}
|
||||
R(&EipCreateOptions{}, "eip-create", "Create an EIP", func(s *mcclient.ClientSession, args *EipCreateOptions) error {
|
||||
@@ -55,12 +57,22 @@ func init() {
|
||||
params.Add(jsonutils.NewString(args.MANAGER), "manager")
|
||||
params.Add(jsonutils.NewString(args.REGION), "region")
|
||||
params.Add(jsonutils.NewString(args.NAME), "name")
|
||||
params.Add(jsonutils.NewInt(int64(args.BW)), "bandwidth")
|
||||
if args.Bandwidth != 0 {
|
||||
params.Add(jsonutils.NewInt(int64(args.Bandwidth)), "bandwidth")
|
||||
}
|
||||
|
||||
if len(args.ChargeType) > 0 {
|
||||
params.Add(jsonutils.NewString(args.ChargeType), "charge_type")
|
||||
}
|
||||
|
||||
if len(args.Network) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Network), "network")
|
||||
}
|
||||
|
||||
if len(args.Ip) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Ip), "ip")
|
||||
}
|
||||
|
||||
result, err := modules.Elasticips.Create(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -234,16 +234,16 @@ func init() {
|
||||
})
|
||||
|
||||
type NetworkCreateOptions2 struct {
|
||||
Wire string `help:"ID or Name of wire in which the network is created"`
|
||||
Vpc string `help:"ID or Name of vpc in which the network is created"`
|
||||
Zone string `help:"ID or Name of zone in which the network is created"`
|
||||
NETWORK string `help:"Name of new network"`
|
||||
PREFIX string `help:"Start of IPv4 address range"`
|
||||
Desc string `help:"Description" metavar:"DESCRIPTION"`
|
||||
Wire string `help:"ID or Name of wire in which the network is created"`
|
||||
Vpc string `help:"ID or Name of vpc in which the network is created"`
|
||||
Zone string `help:"ID or Name of zone in which the network is created"`
|
||||
NAME string `help:"Name of new network"`
|
||||
PREFIX string `help:"Start of IPv4 address range"`
|
||||
Desc string `help:"Description" metavar:"DESCRIPTION"`
|
||||
}
|
||||
R(&NetworkCreateOptions2{}, "network-create2", "Create a virtual network", func(s *mcclient.ClientSession, args *NetworkCreateOptions2) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.NETWORK), "name")
|
||||
params.Add(jsonutils.NewString(args.NAME), "name")
|
||||
params.Add(jsonutils.NewString(args.PREFIX), "guest_ip_prefix")
|
||||
if len(args.Desc) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Desc), "description")
|
||||
|
||||
@@ -150,7 +150,7 @@ func init() {
|
||||
})
|
||||
|
||||
type ServerSkuSpecsListOptions struct {
|
||||
Provider string `help:"List objects from the provider" choices:"OneCloud|VMware|Aliyun|Qcloud|Azure|Aws|Huawei|Openstack|Ucloud" json:"provider"`
|
||||
Provider string `help:"List objects from the provider" choices:"OneCloud|VMware|Aliyun|Qcloud|Azure|Aws|Huawei|Openstack|Ucloud|ZStack" json:"provider"`
|
||||
PublicCloud *bool `help:"List objects belonging to public cloud" json:"public_cloud"`
|
||||
Zone string `help:"zone Id or name"`
|
||||
PostpaidStatus *string `help:"skus available status for postpaid instance" choices:"available|soldout"`
|
||||
|
||||
@@ -22,8 +22,8 @@ import (
|
||||
)
|
||||
|
||||
type GeneralUsageOptions struct {
|
||||
HostType []string `help:"Host types" choices:"hypervisor|baremetal|esxi|xen|kubelet|hyperv|aliyun|azure|aws|huawei|qcloud"`
|
||||
Provider []string `help:"Provider" choices:"VMware|Aliyun|Azure|Aws|Qcloud|Huawei"`
|
||||
HostType []string `help:"Host types" choices:"hypervisor|baremetal|esxi|xen|kubelet|hyperv|aliyun|azure|aws|huawei|qcloud|openstack|ucloud|zstack"`
|
||||
Provider []string `help:"Provider" choices:"VMware|Aliyun|Azure|Aws|Qcloud|Huawei|OpenStack|Ucloud|ZStack"`
|
||||
Project string
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ var (
|
||||
CLOUD_PROVIDER_HUAWEI,
|
||||
CLOUD_PROVIDER_OPENSTACK,
|
||||
CLOUD_PROVIDER_UCLOUD,
|
||||
CLOUD_PROVIDER_ZSTACK,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -191,8 +191,9 @@ var HOSTTYPE_HYPERVISOR = map[string]string{
|
||||
}
|
||||
|
||||
const (
|
||||
VM_AWS_DEFAULT_LOGIN_USER = "ec2user"
|
||||
VM_AZURE_DEFAULT_LOGIN_USER = "toor"
|
||||
VM_AWS_DEFAULT_LOGIN_USER = "ec2user"
|
||||
VM_AZURE_DEFAULT_LOGIN_USER = "toor"
|
||||
VM_ZSTACK_DEFAULT_LOGIN_USER = "root"
|
||||
|
||||
VM_METADATA_APP_TAGS = "app_tags"
|
||||
VM_METADATA_CREATE_PARAMS = "create_params"
|
||||
|
||||
@@ -87,6 +87,7 @@ var HOST_TYPES = []string{
|
||||
HOST_TYPE_QCLOUD,
|
||||
HOST_TYPE_HUAWEI,
|
||||
HOST_TYPE_OPENSTACK,
|
||||
HOST_TYPE_UCLOUD,
|
||||
HOST_TYPE_ZSTACK,
|
||||
}
|
||||
|
||||
|
||||
@@ -66,9 +66,7 @@ const (
|
||||
|
||||
// Zstack storage type
|
||||
STORAGE_ZSTACK_LOCAL_STORAGE = "localstorage"
|
||||
STORAGE_ZSTACK_ROOT = "root"
|
||||
STORAGE_ZSTACK_DATA = "data"
|
||||
STORAGE_ZSTACK_IMAGECACHE = "imagecache"
|
||||
STORAGE_ZSTACK_CEPH = "ceph"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -100,7 +98,7 @@ var (
|
||||
STORAGE_HUAWEI_SSD, STORAGE_HUAWEI_SAS, STORAGE_HUAWEI_SATA,
|
||||
STORAGE_OPENSTACK_ISCSI, STORAGE_UCLOUD_CLOUD_NORMAL, STORAGE_UCLOUD_CLOUD_SSD,
|
||||
STORAGE_UCLOUD_LOCAL_NORMAL, STORAGE_UCLOUD_LOCAL_SSD, STORAGE_UCLOUD_EXCLUSIVE_LOCAL_DISK,
|
||||
STORAGE_ZSTACK_LOCAL_STORAGE, STORAGE_ZSTACK_ROOT, STORAGE_ZSTACK_DATA, STORAGE_ZSTACK_IMAGECACHE,
|
||||
STORAGE_ZSTACK_LOCAL_STORAGE, STORAGE_ZSTACK_CEPH,
|
||||
}
|
||||
|
||||
STORAGE_LIMITED_TYPES = []string{STORAGE_LOCAL, STORAGE_BAREMETAL, STORAGE_NAS, STORAGE_RBD, STORAGE_NFS}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package cloudprovider
|
||||
|
||||
type SEip struct {
|
||||
Name string
|
||||
BandwidthMbps int
|
||||
ChargeType string
|
||||
BGPType string
|
||||
NetworkExternalId string
|
||||
IP string
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func (region *SFakeOnPremiseRegion) CreateIVpc(name string, desc string, cidr st
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (region *SFakeOnPremiseRegion) CreateEIP(name string, bwMbps int, chargeType string, bgpType string) (ICloudEIP, error) {
|
||||
func (region *SFakeOnPremiseRegion) CreateEIP(eip *SEip) (ICloudEIP, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ type ICloudRegion interface {
|
||||
SyncSecurityGroup(secgroupId string, vpcId string, name string, desc string, rules []secrules.SecurityRule) (string, error)
|
||||
|
||||
CreateIVpc(name string, desc string, cidr string) (ICloudVpc, error)
|
||||
CreateEIP(name string, bwMbps int, chargeType string, bgpType string) (ICloudEIP, error)
|
||||
CreateEIP(eip *SEip) (ICloudEIP, error)
|
||||
|
||||
GetISnapshots() ([]ICloudSnapshot, error)
|
||||
GetISnapshotById(snapshotId string) (ICloudSnapshot, error)
|
||||
@@ -275,6 +275,7 @@ type ICloudEIP interface {
|
||||
|
||||
GetIpAddr() string
|
||||
GetMode() string
|
||||
GetINetworkId() string
|
||||
GetAssociationType() string
|
||||
GetAssociationExternalId() string
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
)
|
||||
|
||||
type CloudSyncOptions struct {
|
||||
Provider string `help:"Public cloud provider" choices:"Aliyun|Azure|Aws|Qcloud"`
|
||||
Provider string `help:"Public cloud provider" choices:"Aliyun|Azure|Aws|Qcloud|OpenStack|Ucloud|Huawei|ZStack"`
|
||||
Environment string `help:"environment of public cloud"`
|
||||
Cloudregion string `help:"region of public cloud"`
|
||||
Zone string `help:"availability zone of public cloud"`
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
@@ -120,6 +121,10 @@ func (self *SBaseGuestDriver) GetChangeConfigStatus() ([]string, error) {
|
||||
return []string{}, fmt.Errorf("This Guest driver dose not implement GetChangeConfigStatus")
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
|
||||
return httperrors.NewInputParameterError("Not Implement ValidateCreateEip")
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
|
||||
return fmt.Errorf("This Guest driver dose not implement ValidateResizeDisk")
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
@@ -104,6 +105,10 @@ func (self *SESXiGuestDriver) GetDeployStatus() ([]string, error) {
|
||||
return []string{api.VM_READY}, nil
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
|
||||
return httperrors.NewInputParameterError("%s not support create eip", self.GetHypervisor())
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
|
||||
if !utils.IsInStringArray(guest.Status, []string{api.VM_READY}) {
|
||||
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
|
||||
|
||||
@@ -165,6 +165,10 @@ func (self *SManagedVirtualizedGuestDriver) ValidateCreateData(ctx context.Conte
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) RequestDetachDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package guestdrivers
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
@@ -90,6 +91,10 @@ func (self *SOpenStackGuestDriver) GetDeployStatus() ([]string, error) {
|
||||
return []string{api.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
|
||||
return httperrors.NewInputParameterError("%s not support create eip, it only support bind eip", self.GetHypervisor())
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
var err error
|
||||
input, err = self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, input)
|
||||
@@ -99,6 +104,9 @@ func (self *SOpenStackGuestDriver) ValidateCreateData(ctx context.Context, userC
|
||||
if len(input.Networks) >= 2 {
|
||||
return nil, httperrors.NewInputParameterError("cannot support more than 1 nic")
|
||||
}
|
||||
if len(input.Eip) > 0 || input.EipBw > 0 {
|
||||
return nil, httperrors.NewUnsupportOperationError("%s not support create virtual machine with eip", self.GetHypervisor())
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -42,6 +43,10 @@ func (self *SZStackGuestDriver) GetHypervisor() string {
|
||||
return api.HYPERVISOR_ZSTACK
|
||||
}
|
||||
|
||||
func (self *SZStackGuestDriver) GetProvider() string {
|
||||
return api.CLOUD_PROVIDER_ZSTACK
|
||||
}
|
||||
|
||||
func (self *SZStackGuestDriver) GetDefaultSysDiskBackend() string {
|
||||
return api.STORAGE_ZSTACK_LOCAL_STORAGE
|
||||
}
|
||||
@@ -53,11 +58,14 @@ func (self *SZStackGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
func (self *SZStackGuestDriver) GetStorageTypes() []string {
|
||||
return []string{
|
||||
api.STORAGE_ZSTACK_LOCAL_STORAGE,
|
||||
api.STORAGE_ZSTACK_DATA,
|
||||
api.STORAGE_ZSTACK_ROOT,
|
||||
api.STORAGE_ZSTACK_CEPH,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SZStackGuestDriver) GetMaxSecurityGroupCount() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (self *SZStackGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
|
||||
return self.chooseHostStorage(self, host, backend, storageIds)
|
||||
}
|
||||
@@ -86,9 +94,6 @@ func (self *SZStackGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *m
|
||||
if !utils.IsInStringArray(guest.Status, []string{api.VM_READY, api.VM_RUNNING}) {
|
||||
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
|
||||
}
|
||||
if !utils.IsInStringArray(storage.StorageType, []string{api.STORAGE_ZSTACK_LOCAL_STORAGE, api.STORAGE_ZSTACK_ROOT, api.STORAGE_ZSTACK_DATA}) {
|
||||
return fmt.Errorf("Cannot resize %s disk", storage.StorageType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -96,6 +101,10 @@ func (self *SZStackGuestDriver) RequestDetachDisk(ctx context.Context, guest *mo
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SZStackGuestDriver) ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
|
||||
return httperrors.NewInputParameterError("%s not support create eip, it only support bind eip", self.GetHypervisor())
|
||||
}
|
||||
|
||||
func (self *SZStackGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
input, err := self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, input)
|
||||
if err != nil {
|
||||
@@ -104,6 +113,9 @@ func (self *SZStackGuestDriver) ValidateCreateData(ctx context.Context, userCred
|
||||
if len(input.Networks) > 2 {
|
||||
return nil, httperrors.NewInputParameterError("cannot support more than 1 nic")
|
||||
}
|
||||
if len(input.Eip) > 0 || input.EipBw > 0 {
|
||||
return nil, httperrors.NewUnsupportOperationError("%s not support create virtual machine with eip", self.GetHypervisor())
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -115,6 +127,10 @@ func (self *SZStackGuestDriver) GetGuestInitialStateAfterRebuild() string {
|
||||
return api.VM_READY
|
||||
}
|
||||
|
||||
func (self *SZStackGuestDriver) IsNeedInjectPasswordByCloudInit() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SZStackGuestDriver) GetLinuxDefaultAccount(desc cloudprovider.SManagedVMCreateConfig) string {
|
||||
userName := "root"
|
||||
if desc.ImageType == "system" && desc.OsType == "Windows" {
|
||||
|
||||
@@ -16,7 +16,6 @@ package hostdrivers
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
@@ -41,8 +40,5 @@ func (self *SZStackHostDriver) ValidateAttachStorage(host *models.SHost, storage
|
||||
}
|
||||
|
||||
func (self *SZStackHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
|
||||
if utils.IsInStringArray(storage.StorageType, []string{api.STORAGE_ZSTACK_IMAGECACHE, api.STORAGE_ZSTACK_ROOT}) {
|
||||
return httperrors.NewUnsupportOperationError("Not support create %s disk", storage.StorageType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -793,10 +793,11 @@ func syncPublicCloudProviderInfo(
|
||||
|
||||
// no need to lock public cloud region as cloud region for public cloud is readonly
|
||||
|
||||
syncRegionEips(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
|
||||
|
||||
// 需要先同步vpc,避免私有云eip找不到network
|
||||
syncRegionVPCs(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
|
||||
|
||||
syncRegionEips(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
|
||||
|
||||
for j := 0; j < len(localZones); j += 1 {
|
||||
|
||||
if len(syncRange.Zone) > 0 && !utils.IsInStringArray(localZones[j].Id, syncRange.Zone) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang-plus/errors"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
@@ -60,14 +61,15 @@ type SElasticip struct {
|
||||
SManagedResourceBase
|
||||
SBillingResourceBase
|
||||
|
||||
Mode string `width:"32" charset:"ascii" list:"user"`
|
||||
NetworkId string `width:"36" charset:"ascii" nullable:"false" get:"user" list:"user" create:"optional"`
|
||||
Mode string `width:"32" charset:"ascii" list:"user"`
|
||||
|
||||
IpAddr string `width:"17" charset:"ascii" list:"user"`
|
||||
IpAddr string `width:"17" charset:"ascii" list:"user" create:"optional"`
|
||||
|
||||
AssociateType string `width:"32" charset:"ascii" list:"user"`
|
||||
AssociateId string `width:"256" charset:"ascii" list:"user"`
|
||||
|
||||
Bandwidth int `list:"user" create:"required"`
|
||||
Bandwidth int `list:"user" create:"optional" default:"0"`
|
||||
|
||||
ChargeType string `name:"charge_type" list:"user" create:"required"`
|
||||
BgpType string `list:"user" create:"optional"` // 目前只有华为云此字段是必需填写的。
|
||||
@@ -362,6 +364,15 @@ func (manager *SElasticipManager) newFromCloudEip(ctx context.Context, userCred
|
||||
eip.ManagerId = provider.Id
|
||||
eip.CloudregionId = region.Id
|
||||
eip.ChargeType = extEip.GetInternetChargeType()
|
||||
if networkId := extEip.GetINetworkId(); len(networkId) > 0 {
|
||||
network, err := NetworkManager.FetchByExternalId(networkId)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to found network by externalId %s error: %v", networkId, err)
|
||||
log.Errorf(msg)
|
||||
return nil, errors.New(msg)
|
||||
}
|
||||
eip.NetworkId = network.GetId()
|
||||
}
|
||||
|
||||
err = manager.TableSpec().Insert(&eip)
|
||||
if err != nil {
|
||||
@@ -484,7 +495,7 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
|
||||
if len(regionStr) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("region_id")
|
||||
}
|
||||
region, err := CloudregionManager.FetchByIdOrName(nil, regionStr)
|
||||
_region, err := CloudregionManager.FetchByIdOrName(nil, regionStr)
|
||||
if err != nil {
|
||||
if err != sql.ErrNoRows {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
@@ -492,6 +503,7 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
|
||||
return nil, httperrors.NewResourceNotFoundError("Region %s not found", regionStr)
|
||||
}
|
||||
}
|
||||
region := _region.(*SCloudregion)
|
||||
data.Add(jsonutils.NewString(region.GetId()), "cloudregion_id")
|
||||
|
||||
managerStr := jsonutils.GetAnyString(data, []string{"manager", "manager_id"})
|
||||
@@ -532,13 +544,18 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
|
||||
return nil, httperrors.NewOutOfQuotaError("Out of eip quota: %s", err)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
return region.GetDriver().ValidateCreateEipData(ctx, userCred, data)
|
||||
}
|
||||
|
||||
func (self *SElasticip) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SVirtualResourceBase.PostCreate(ctx, userCred, ownerProjId, query, data)
|
||||
params := jsonutils.NewDict()
|
||||
if data.Contains("ip") {
|
||||
ip, _ := data.GetString("ip")
|
||||
params.Add(jsonutils.NewString(ip), "ip")
|
||||
}
|
||||
eipPendingUsage := &SQuota{Eip: 1}
|
||||
self.startEipAllocateTask(ctx, userCred, nil, eipPendingUsage)
|
||||
self.startEipAllocateTask(ctx, userCred, params, eipPendingUsage)
|
||||
}
|
||||
|
||||
func (self *SElasticip) startEipAllocateTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, pendingUsage quotas.IQuota) error {
|
||||
|
||||
@@ -2434,16 +2434,19 @@ func (self *SGuest) AllowPerformCreateEip(ctx context.Context, userCred mcclient
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformCreateEip(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
bw, err := data.Int("bandwidth")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("bandwidth")
|
||||
}
|
||||
|
||||
var bw int64
|
||||
chargeType, _ := data.GetString("charge_type")
|
||||
if len(chargeType) == 0 {
|
||||
chargeType = api.EIP_CHARGE_TYPE_DEFAULT
|
||||
}
|
||||
|
||||
if chargeType == api.EIP_CHARGE_TYPE_BY_BANDWIDTH {
|
||||
bw, _ = data.Int("bandwidth")
|
||||
if bw == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("bandwidth")
|
||||
}
|
||||
}
|
||||
|
||||
if len(self.ExternalId) == 0 {
|
||||
return nil, httperrors.NewInvalidStatusError("Not a managed VM")
|
||||
}
|
||||
@@ -2452,7 +2455,7 @@ func (self *SGuest) PerformCreateEip(ctx context.Context, userCred mcclient.Toke
|
||||
return nil, httperrors.NewInvalidStatusError("No host???")
|
||||
}
|
||||
|
||||
_, err = host.GetDriver()
|
||||
_, err := host.GetDriver()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInvalidStatusError("No valid cloud provider")
|
||||
}
|
||||
@@ -2462,6 +2465,11 @@ func (self *SGuest) PerformCreateEip(ctx context.Context, userCred mcclient.Toke
|
||||
return nil, httperrors.NewInvalidStatusError("No cloudregion???")
|
||||
}
|
||||
|
||||
err = self.GetDriver().ValidateCreateEip(ctx, userCred, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eipPendingUsage := &SQuota{Eip: 1}
|
||||
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, userCred.GetProjectId(), eipPendingUsage)
|
||||
if err != nil {
|
||||
|
||||
@@ -151,6 +151,7 @@ type IGuestDriver interface {
|
||||
RequestSyncToBackup(ctx context.Context, guest *SGuest, task taskman.ITask) error
|
||||
|
||||
IsSupportEip() bool
|
||||
ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error
|
||||
|
||||
NeedStopForChangeSpec(guest *SGuest) bool
|
||||
|
||||
|
||||
@@ -3056,6 +3056,8 @@ func (self *SGuest) GetDeployConfigOnHost(ctx context.Context, userCred mcclient
|
||||
if strings.HasSuffix(host.Name, "-classic") {
|
||||
registerVpcId, externalVpcId = "classic", "classic"
|
||||
}
|
||||
case api.HYPERVISOR_ZSTACK:
|
||||
break
|
||||
default:
|
||||
return nil, fmt.Errorf("Unknown guest %s hypervisor %s for sync secgroup", self.Name, self.Hypervisor)
|
||||
}
|
||||
|
||||
@@ -171,6 +171,11 @@ func (self *SNetwork) GetTotalNicCount() (int, error) {
|
||||
return -1, err
|
||||
}
|
||||
total += cnt
|
||||
cnt, err = self.GetEipsCount()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
total += cnt
|
||||
return total, nil
|
||||
}
|
||||
|
||||
@@ -194,6 +199,10 @@ func (self *SNetwork) GetLoadbalancerIpsCount() (int, error) {
|
||||
return LoadbalancernetworkManager.Query().Equals("network_id", self.Id).CountWithError()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetEipsCount() (int, error) {
|
||||
return ElasticipManager.Query().Equals("network_id", self.Id).CountWithError()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetUsedAddresses() map[string]bool {
|
||||
used := make(map[string]bool)
|
||||
|
||||
@@ -203,6 +212,7 @@ func (self *SNetwork) GetUsedAddresses() map[string]bool {
|
||||
HostnetworkManager.Query().SubQuery(),
|
||||
ReservedipManager.Query().SubQuery(),
|
||||
LoadbalancernetworkManager.Query().SubQuery(),
|
||||
ElasticipManager.Query().SubQuery(),
|
||||
} {
|
||||
q := tbl.Query(tbl.Field("ip_addr")).Equals("network_id", self.Id)
|
||||
rows, err := q.Rows()
|
||||
@@ -883,6 +893,8 @@ func (self *SNetwork) getMoreDetails(ctx context.Context, extra *jsonutils.JSOND
|
||||
extra.Add(jsonutils.NewInt(int64(bmVnics)), "bm_vnics")
|
||||
lbVnics, _ := self.GetLoadbalancerIpsCount()
|
||||
extra.Add(jsonutils.NewInt(int64(lbVnics)), "lb_vnics")
|
||||
eips, _ := self.GetEipsCount()
|
||||
extra.Add(jsonutils.NewInt(int64(eips)), "eip_vnics")
|
||||
groupVnics, _ := self.GetGroupNicsCount()
|
||||
extra.Add(jsonutils.NewInt(int64(groupVnics)), "group_vnics")
|
||||
reserveVnics, _ := self.GetReservedNicsCount()
|
||||
|
||||
@@ -552,6 +552,22 @@ func (net *SNetwork) purgeLoadbalancernetworks(ctx context.Context, userCred mcc
|
||||
return nil
|
||||
}
|
||||
|
||||
func (net *SNetwork) purgeEipnetworks(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
q := ElasticipManager.Query().Equals("network_id", net.Id)
|
||||
eips := make([]SElasticip, 0)
|
||||
err := db.FetchModelObjects(ElasticipManager, q, &eips)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range eips {
|
||||
err = eips[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (net *SNetwork) purgeReservedIps(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
q := ReservedipManager.Query().Equals("network_id", net.Id)
|
||||
rips := make([]SReservedip, 0)
|
||||
@@ -588,6 +604,10 @@ func (net *SNetwork) purge(ctx context.Context, userCred mcclient.TokenCredentia
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = net.purgeEipnetworks(ctx, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = net.purgeReservedIps(ctx, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -73,6 +73,8 @@ type IRegionDriver interface {
|
||||
RequestDeleteLoadbalancerListenerRule(ctx context.Context, userCred mcclient.TokenCredential, lbr *SLoadbalancerListenerRule, task taskman.ITask) error
|
||||
|
||||
ValidateCreateVpcData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
|
||||
|
||||
ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
|
||||
}
|
||||
|
||||
var regionDrivers map[string]IRegionDriver
|
||||
|
||||
@@ -541,7 +541,7 @@ func providerFilter(q *sqlchemy.SQuery, provider string, public_cloud bool) *sql
|
||||
q = q.Equals("provider", provider)
|
||||
} else if public_cloud {
|
||||
q = q.IsNotEmpty("provider")
|
||||
q = q.NotIn("provider", []string{api.CLOUD_PROVIDER_OPENSTACK})
|
||||
q = q.NotIn("provider", []string{api.CLOUD_PROVIDER_OPENSTACK, api.CLOUD_PROVIDER_ZSTACK})
|
||||
} else {
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.IsNull(q.Field("provider")),
|
||||
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
@@ -304,3 +306,7 @@ func (self *SKVMRegionDriver) RequestDeleteLoadbalancerListenerRule(ctx context.
|
||||
func (self *SKVMRegionDriver) ValidateCreateVpcData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SKVMRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return nil, httperrors.NewNotImplementedError("Not Implement EIP")
|
||||
}
|
||||
|
||||
@@ -828,3 +828,7 @@ func (self *SManagedVirtualizationRegionDriver) RequestDeleteLoadbalancerListene
|
||||
func (self *SManagedVirtualizationRegionDriver) ValidateCreateVpcData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizationRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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 regiondrivers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
type SZStackRegionDriver struct {
|
||||
SManagedVirtualizationRegionDriver
|
||||
}
|
||||
|
||||
func init() {
|
||||
driver := SZStackRegionDriver{}
|
||||
models.RegisterRegionDriver(&driver)
|
||||
}
|
||||
|
||||
func (self *SZStackRegionDriver) GetProvider() string {
|
||||
return api.CLOUD_PROVIDER_ZSTACK
|
||||
}
|
||||
|
||||
func (self *SZStackRegionDriver) ValidateCreateLoadbalancerData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer", self.GetProvider())
|
||||
}
|
||||
|
||||
func (self *SZStackRegionDriver) ValidateCreateLoadbalancerAclData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer acl", self.GetProvider())
|
||||
}
|
||||
|
||||
func (self *SZStackRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer certificate", self.GetProvider())
|
||||
}
|
||||
|
||||
func (self *SZStackRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
networkV := validators.NewModelIdOrNameValidator("network", "network", "")
|
||||
err := networkV.Validate(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
network := networkV.Model.(*models.SNetwork)
|
||||
|
||||
vpc := network.GetVpc()
|
||||
if vpc == nil {
|
||||
return nil, httperrors.NewInputParameterError("failed to found vpc for network %s(%s)", network.Name, network.Id)
|
||||
}
|
||||
region, err := vpc.GetRegion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if region.GetDriver().GetProvider() != self.GetProvider() {
|
||||
return nil, httperrors.NewUnsupportOperationError("network %s(%s) does not belong to %s", network.Name, network.Id, self.GetProvider())
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
@@ -18,11 +18,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
@@ -79,7 +82,51 @@ func (self *EipAllocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel
|
||||
return
|
||||
}
|
||||
|
||||
extEip, err := iregion.CreateEIP(eip.Name, eip.Bandwidth, eip.ChargeType, eip.BgpType)
|
||||
args := &cloudprovider.SEip{
|
||||
Name: eip.Name,
|
||||
BandwidthMbps: eip.Bandwidth,
|
||||
ChargeType: eip.ChargeType,
|
||||
BGPType: eip.BgpType,
|
||||
IP: eip.IpAddr,
|
||||
}
|
||||
|
||||
if len(eip.NetworkId) > 0 {
|
||||
_network, err := models.NetworkManager.FetchById(eip.NetworkId)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to found network %s error: %v", eip.NetworkId, err)
|
||||
self.onFailed(ctx, eip, msg)
|
||||
return
|
||||
}
|
||||
network := _network.(*models.SNetwork)
|
||||
ip, _ := self.GetParams().GetString("ip")
|
||||
if len(ip) > 0 {
|
||||
lockman.LockObject(ctx, network)
|
||||
defer lockman.ReleaseObject(ctx, network)
|
||||
|
||||
addrTable := network.GetUsedAddresses()
|
||||
ipAddr, err := network.GetFreeIP(ctx, self.UserCred, addrTable, nil, ip, models.IPAllocationNone, false)
|
||||
if err != nil {
|
||||
self.onFailed(ctx, eip, err.Error())
|
||||
return
|
||||
}
|
||||
if ipAddr != ip {
|
||||
msg := fmt.Sprintf("candidate ip %s is occupoed!", ip)
|
||||
self.onFailed(ctx, eip, msg)
|
||||
return
|
||||
}
|
||||
_, err = db.Update(eip, func() error {
|
||||
eip.IpAddr = ipAddr
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
self.onFailed(ctx, eip, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
args.NetworkExternalId = network.ExternalId
|
||||
}
|
||||
|
||||
extEip, err := iregion.CreateEIP(args)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("create eip fail %s", err)
|
||||
eip.SetStatus(self.UserCred, api.EIP_STATUS_ALLOCATE_FAIL, msg)
|
||||
|
||||
@@ -207,7 +207,7 @@ type BaseListOptions struct {
|
||||
|
||||
Manager string `help:"List objects belonging to the cloud provider" json:"manager,omitempty"`
|
||||
Account string `help:"List objects belonging to the cloud account" json:"account,omitempty"`
|
||||
Provider string `help:"List objects from the provider" choices:"OneCloud|VMware|Aliyun|Qcloud|Azure|Aws|Huawei|Openstack|Ucloud" json:"provider,omitempty"`
|
||||
Provider string `help:"List objects from the provider" choices:"OneCloud|VMware|Aliyun|Qcloud|Azure|Aws|Huawei|Openstack|Ucloud|ZStack" json:"provider,omitempty"`
|
||||
Brand string `help:"List objects belonging to a special brand"`
|
||||
CloudEnv string `help:"Cloud environment" choices:"public|private|onpremise|private_or_onpremise" json:"cloud_env,omitempty"`
|
||||
PublicCloud *bool `help:"List objects belonging to public cloud" json:"public_cloud"`
|
||||
|
||||
@@ -39,7 +39,7 @@ type ServerListOptions struct {
|
||||
Gpu *bool `help:"Show gpu servers"`
|
||||
Secgroup string `help:"Secgroup ID or Name"`
|
||||
AdminSecgroup string `help:"AdminSecgroup ID or Name"`
|
||||
Hypervisor string `help:"Show server of hypervisor" choices:"kvm|esxi|container|baremetal|aliyun|azure|aws|huawei|ucloud"`
|
||||
Hypervisor string `help:"Show server of hypervisor" choices:"kvm|esxi|container|baremetal|aliyun|azure|aws|huawei|ucloud|zstack"`
|
||||
Region string `help:"Show servers in cloudregion"`
|
||||
WithEip *bool `help:"Show Servers with EIP"`
|
||||
WithoutEip *bool `help:"Show Servers without EIP"`
|
||||
@@ -126,7 +126,7 @@ type ServerConfigs struct {
|
||||
Host string `help:"Preferred host where virtual server should be created" json:"prefer_host"`
|
||||
BackupHost string `help:"Perfered host where virtual backup server should be created"`
|
||||
|
||||
Hypervisor string `help:"Hypervisor type" choices:"kvm|esxi|baremetal|container|aliyun|azure|qcloud|aws|huawei|openstack|ucloud"`
|
||||
Hypervisor string `help:"Hypervisor type" choices:"kvm|esxi|baremetal|container|aliyun|azure|qcloud|aws|huawei|openstack|ucloud|zstack"`
|
||||
ResourceType string `help:"Resource type" choices:"shared|prepaid|dedicated"`
|
||||
Backup bool `help:"Create server with backup server"`
|
||||
|
||||
|
||||
@@ -182,6 +182,10 @@ func (self *SEipAddress) GetBandwidth() int {
|
||||
return self.Bandwidth
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetINetworkId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetInternetChargeType() string {
|
||||
switch self.InternetChargeType {
|
||||
case InternetChargeByTraffic:
|
||||
@@ -282,16 +286,15 @@ func (region *SRegion) AllocateEIP(bwMbps int, chargeType TInternetChargeType) (
|
||||
return region.GetEip(eipId)
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateEIP(name string, bwMbps int, chargeType string, bgpType string) (cloudprovider.ICloudEIP, error) {
|
||||
func (region *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
|
||||
var ctype TInternetChargeType
|
||||
switch chargeType {
|
||||
switch eip.ChargeType {
|
||||
case api.EIP_CHARGE_TYPE_BY_TRAFFIC:
|
||||
ctype = InternetChargeByTraffic
|
||||
case api.EIP_CHARGE_TYPE_BY_BANDWIDTH:
|
||||
ctype = InternetChargeByBandwidth
|
||||
}
|
||||
eip, err := region.AllocateEIP(bwMbps, ctype)
|
||||
return eip, err
|
||||
return region.AllocateEIP(eip.BandwidthMbps, ctype)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeallocateEIP(eipId string) error {
|
||||
|
||||
+7
-3
@@ -124,6 +124,10 @@ func (self *SEipAddress) GetBandwidth() int {
|
||||
return self.Bandwidth
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetINetworkId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetInternetChargeType() string {
|
||||
// todo : implement me
|
||||
return api.EIP_CHARGE_TYPE_BY_TRAFFIC
|
||||
@@ -250,14 +254,14 @@ func (self *SRegion) AllocateEIP(domainType string) (*SEipAddress, error) {
|
||||
return self.GetEip(*eip.AllocationId)
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateEIP(name string, bwMbps int, chargeType string, bgpType string) (cloudprovider.ICloudEIP, error) {
|
||||
func (self *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
|
||||
// todo: aws 不支持指定bwMbps, chargeType ?
|
||||
log.Debugf("CreateEip: aws not support specific params name/bwMbps/chargeType.")
|
||||
ieip, err := self.AllocateEIP("vpc")
|
||||
if err == nil && len(name) > 0 {
|
||||
if err == nil && len(eip.Name) > 0 {
|
||||
eipId := ieip.GetId()
|
||||
k := "Name"
|
||||
nameTag := &ec2.Tag{Key: &k, Value: &name}
|
||||
nameTag := &ec2.Tag{Key: &k, Value: &eip.Name}
|
||||
params := &ec2.CreateTagsInput{}
|
||||
params.SetResources([]*string{&eipId})
|
||||
params.SetTags([]*ec2.Tag{nameTag})
|
||||
|
||||
@@ -77,6 +77,10 @@ func (self *SClassicEipAddress) GetBandwidth() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SClassicEipAddress) GetINetworkId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SClassicEipAddress) GetGlobalId() string {
|
||||
return strings.ToLower(self.ID)
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@ func (region *SRegion) AllocateEIP(eipName string) (*SEipAddress, error) {
|
||||
return &eip, cloudprovider.WaitStatus(&eip, api.EIP_STATUS_READY, 10*time.Second, 300*time.Second)
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateEIP(eipName string, bwMbps int, chargeType string, bgpType string) (cloudprovider.ICloudEIP, error) {
|
||||
return region.AllocateEIP(eipName)
|
||||
func (region *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
|
||||
return region.AllocateEIP(eip.Name)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetEip(eipId string) (*SEipAddress, error) {
|
||||
@@ -199,6 +199,10 @@ func (self *SEipAddress) GetBandwidth() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetINetworkId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetGlobalId() string {
|
||||
return strings.ToLower(self.ID)
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ func ParseJSONResponse(resp *http.Response, err error, debug bool) (http.Header,
|
||||
if ce.Code == 0 {
|
||||
ce.Code = resp.StatusCode
|
||||
}
|
||||
if edetail := jsonutils.GetAnyString(jrbody2, []string{"message", "detail", "error_msg"}); len(edetail) > 0 {
|
||||
if edetail := jsonutils.GetAnyString(jrbody2, []string{"message", "detail", "details", "error_msg"}); len(edetail) > 0 {
|
||||
ce.Details = edetail
|
||||
}
|
||||
if eclass := jsonutils.GetAnyString(jrbody2, []string{"title", "type", "error_code"}); len(eclass) > 0 {
|
||||
|
||||
@@ -178,6 +178,10 @@ func (self *SEipAddress) GetBandwidth() int {
|
||||
return int(self.BandwidthSize) // Mb
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetINetworkId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetInternetChargeType() string {
|
||||
// https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090603.html
|
||||
bandwidth, err := self.region.GetEipBandwidth(self.BandwidthID)
|
||||
|
||||
+11
-11
@@ -379,9 +379,9 @@ func (self *SRegion) CreateIVpc(name string, desc string, cidr string) (cloudpro
|
||||
// 华东-上海二:5_sbgp
|
||||
// 华北-北京一:5_bgp、5_sbgp
|
||||
// 亚太-香港:5_bgp
|
||||
func (self *SRegion) CreateEIP(name string, bwMbps int, chargeType string, bgpType string) (cloudprovider.ICloudEIP, error) {
|
||||
func (self *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
|
||||
var ctype TInternetChargeType
|
||||
switch chargeType {
|
||||
switch eip.ChargeType {
|
||||
case api.EIP_CHARGE_TYPE_BY_TRAFFIC:
|
||||
ctype = InternetChargeByTraffic
|
||||
case api.EIP_CHARGE_TYPE_BY_BANDWIDTH:
|
||||
@@ -389,27 +389,27 @@ func (self *SRegion) CreateEIP(name string, bwMbps int, chargeType string, bgpTy
|
||||
}
|
||||
|
||||
// todo: 如何避免hardcode。集成到cloudmeta服务中?
|
||||
if len(bgpType) == 0 {
|
||||
if len(eip.BGPType) == 0 {
|
||||
switch self.GetId() {
|
||||
case "cn-north-1", "cn-east-2", "cn-south-1":
|
||||
bgpType = "5_sbgp"
|
||||
eip.BGPType = "5_sbgp"
|
||||
case "cn-northeast-1":
|
||||
bgpType = "5_telcom"
|
||||
eip.BGPType = "5_telcom"
|
||||
case "cn-north-4", "ap-southeast-1", "ap-southeast-2", "eu-west-0":
|
||||
bgpType = "5_bgp"
|
||||
eip.BGPType = "5_bgp"
|
||||
default:
|
||||
bgpType = "5_bgp"
|
||||
eip.BGPType = "5_bgp"
|
||||
}
|
||||
}
|
||||
|
||||
eip, err := self.AllocateEIP(name, bwMbps, ctype, bgpType)
|
||||
eip.region = self
|
||||
ieip, err := self.AllocateEIP(eip.Name, eip.BandwidthMbps, ctype, eip.BGPType)
|
||||
ieip.region = self
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(eip, api.EIP_STATUS_READY, 5*time.Second, 60*time.Second)
|
||||
return eip, err
|
||||
err = cloudprovider.WaitStatus(ieip, api.EIP_STATUS_READY, 5*time.Second, 60*time.Second)
|
||||
return ieip, err
|
||||
}
|
||||
|
||||
func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
|
||||
@@ -402,7 +402,7 @@ func (region *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateEIP(name string, bwMbps int, chargeType string, bgpType string) (cloudprovider.ICloudEIP, error) {
|
||||
func (region *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +161,10 @@ func (self *SEipAddress) GetBandwidth() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetINetworkId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetBillingType() string {
|
||||
return billing_api.BILLING_TYPE_POSTPAID
|
||||
}
|
||||
@@ -292,15 +296,15 @@ func (region *SRegion) AllocateEIP(name string, bwMbps int, chargeType TInternet
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateEIP(name string, bwMbps int, chargeType string, bgpType string) (cloudprovider.ICloudEIP, error) {
|
||||
func (region *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
|
||||
var ctype TInternetChargeType
|
||||
switch chargeType {
|
||||
switch eip.ChargeType {
|
||||
case api.EIP_CHARGE_TYPE_BY_TRAFFIC:
|
||||
ctype = InternetChargeByTraffic
|
||||
case api.EIP_CHARGE_TYPE_BY_BANDWIDTH:
|
||||
ctype = InternetChargeByBandwidth
|
||||
}
|
||||
return region.AllocateEIP(name, bwMbps, ctype)
|
||||
return region.AllocateEIP(eip.Name, eip.BandwidthMbps, ctype)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeallocateEIP(eipId string) error {
|
||||
|
||||
+12
-8
@@ -177,6 +177,10 @@ func (self *SEip) GetBandwidth() int {
|
||||
return self.BandwidthMb
|
||||
}
|
||||
|
||||
func (self *SEip) GetINetworkId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 弹性IP的计费模式, 枚举值为: "Bandwidth", 带宽计费; "Traffic", 流量计费; "ShareBandwidth",共享带宽模式. 默认为 "Bandwidth".
|
||||
func (self *SEip) GetInternetChargeType() string {
|
||||
switch self.PayMode {
|
||||
@@ -207,21 +211,21 @@ func (self *SEip) ChangeBandwidth(bw int) error {
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/allocate_eip
|
||||
// 增加共享带宽模式ShareBandwidth
|
||||
func (self *SRegion) CreateEIP(name string, bwMbps int, chargeType string, bgpType string) (cloudprovider.ICloudEIP, error) {
|
||||
if len(bgpType) == 0 {
|
||||
func (self *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
|
||||
if len(eip.BGPType) == 0 {
|
||||
if strings.HasPrefix(self.GetId(), "cn-") {
|
||||
bgpType = "Bgp"
|
||||
eip.BGPType = "Bgp"
|
||||
} else {
|
||||
bgpType = "International"
|
||||
eip.BGPType = "International"
|
||||
}
|
||||
}
|
||||
|
||||
params := NewUcloudParams()
|
||||
params.Set("OperatorName", bgpType)
|
||||
params.Set("Bandwidth", bwMbps)
|
||||
params.Set("Name", name)
|
||||
params.Set("OperatorName", eip.BGPType)
|
||||
params.Set("Bandwidth", eip.BandwidthMbps)
|
||||
params.Set("Name", eip.Name)
|
||||
var payMode string
|
||||
switch chargeType {
|
||||
switch eip.ChargeType {
|
||||
case api.EIP_CHARGE_TYPE_BY_TRAFFIC:
|
||||
payMode = "Traffic"
|
||||
case api.EIP_CHARGE_TYPE_BY_BANDWIDTH:
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
"yunion.io/x/onecloud/pkg/util/ucloud"
|
||||
)
|
||||
@@ -37,7 +38,12 @@ func init() {
|
||||
BGP string `help:"bgp type" choices:"Bgp|International"`
|
||||
}
|
||||
shellutils.R(&EipAllocateOptions{}, "eip-create", "Allocate an EIP", func(cli *ucloud.SRegion, args *EipAllocateOptions) error {
|
||||
eip, err := cli.CreateEIP(args.NAME, args.BW, ucloud.EIP_CHARGE_TYPE_BY_TRAFFIC, args.BGP)
|
||||
option := cloudprovider.SEip{
|
||||
Name: args.NAME,
|
||||
BandwidthMbps: args.BW,
|
||||
BGPType: args.BGP,
|
||||
}
|
||||
eip, err := cli.CreateEIP(&option)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package zstack
|
||||
|
||||
type SConfiguration struct {
|
||||
Name string
|
||||
Category string
|
||||
Description string
|
||||
DefaultValue string
|
||||
Value string
|
||||
}
|
||||
|
||||
func (region *SRegion) GetConfigrations() ([]SConfiguration, error) {
|
||||
configrations := []SConfiguration{}
|
||||
return configrations, region.client.listAll("global-configurations", []string{}, &configrations)
|
||||
}
|
||||
+41
-40
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
type SDisk struct {
|
||||
localStorage *SLocalStorage
|
||||
cephStorage *SCephStorage
|
||||
storage *SStorage
|
||||
region *SRegion
|
||||
|
||||
ZStackBasic
|
||||
@@ -24,7 +24,7 @@ type SDisk struct {
|
||||
DiskOfferingUUID string `json:"diskOfferingUuid"`
|
||||
RootImageUUID string `json:"rootImageUuid"`
|
||||
InstallPath string `json:"installPath"`
|
||||
Type string `json:"Type"`
|
||||
Type string `json:"type"`
|
||||
Format string `json:"format"`
|
||||
Size int `json:"size"`
|
||||
ActualSize int `json:"actualSize"`
|
||||
@@ -36,36 +36,38 @@ type SDisk struct {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetDisk(diskId string) (*SDisk, error) {
|
||||
disks, err := region.GetDisks("", []string{diskId}, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(disks) == 1 {
|
||||
if disks[0].UUID == diskId {
|
||||
return &disks[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(disks) == 0 || len(diskId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
disk := &SDisk{region: region}
|
||||
return disk, region.client.getResource("volumes", diskId, disk)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetDiskWithStorage(diskId string) (*SDisk, error) {
|
||||
disk, err := region.GetDisk(diskId)
|
||||
if err != nil {
|
||||
log.Errorf("Get Disk %s error: %v", diskId, err)
|
||||
return nil, err
|
||||
}
|
||||
disk.region = region
|
||||
storage, err := region.GetPrimaryStorage(disk.PrimaryStorageUUID)
|
||||
storage, err := region.GetStorage(disk.PrimaryStorageUUID)
|
||||
if err != nil {
|
||||
log.Errorf("Get primary storage %s error: %v", disk.PrimaryStorageUUID, err)
|
||||
return nil, err
|
||||
}
|
||||
switch storage.Type {
|
||||
case StorageTypeLocal:
|
||||
if len(disk.VMInstanceUUID) > 0 {
|
||||
instance, err := region.GetInstance(disk.VMInstanceUUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hostId := instance.LastHostUUID
|
||||
if len(hostId) == 0 {
|
||||
hostId = instance.HostUUID
|
||||
}
|
||||
disk.localStorage = &SLocalStorage{region: region, primaryStorageID: storage.UUID, HostUUID: hostId}
|
||||
return disk, nil
|
||||
}
|
||||
tags, err := region.GetSysTags("", "VolumeVO", disk.UUID, "")
|
||||
if err != nil {
|
||||
log.Errorf("get disk tag error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(tags); i++ {
|
||||
@@ -84,23 +86,8 @@ func (region *SRegion) GetDiskWithStorage(diskId string) (*SDisk, error) {
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
case StorageTypeCeph:
|
||||
storage, err := region.GetPrimaryStorage(disk.PrimaryStorageUUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(storage.Pools); i++ {
|
||||
if strings.Contains(disk.InstallPath, storage.Pools[i].PoolName) {
|
||||
zone, err := region.GetZone(storage.ZoneUUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cephStorage := storage.Pools[i]
|
||||
cephStorage.zone = zone
|
||||
disk.cephStorage = &cephStorage
|
||||
return disk, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("failed to found ceph storage for disk %s", disk.Name)
|
||||
disk.storage = storage
|
||||
return disk, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupport StorageType %s", storage.Type)
|
||||
}
|
||||
@@ -156,8 +143,8 @@ func (disk *SDisk) GetIStorage() (cloudprovider.ICloudStorage, error) {
|
||||
if disk.localStorage != nil {
|
||||
return disk.localStorage, nil
|
||||
}
|
||||
if disk.cephStorage != nil {
|
||||
return disk.cephStorage, nil
|
||||
if disk.storage != nil {
|
||||
return disk.storage, nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
@@ -167,7 +154,10 @@ func (disk *SDisk) GetStatus() string {
|
||||
case "Ready":
|
||||
return api.DISK_READY
|
||||
case "NotInstantiated":
|
||||
return api.DISK_READY
|
||||
//数据云盘特有的状态。在这个连接状态中,数据云盘只存在于数据库的表记录中。NotInstantiated状态的数据云盘可以挂载到任何类型虚拟机管理程序管理的云主机上;当挂载到云主机上后,数据云盘的hypervisorType域会存储云主机对应的虚拟机管理程序类型,在主存储上被实例化为虚拟机管理程序类型的实际二进制文件,同时连接状态会改为就绪(Ready);在这之后,这些数据云盘就只能被重新挂载到相同类型虚拟机管理程序管理的云主机上了。
|
||||
return api.DISK_INIT
|
||||
case "Creating":
|
||||
return api.DISK_ALLOCATING
|
||||
default:
|
||||
log.Errorf("Unknown disk %s(%s) status %s", disk.Name, disk.UUID, disk.Status)
|
||||
return api.DISK_UNKNOWN
|
||||
@@ -258,12 +248,23 @@ func (region *SRegion) CreateDisk(name string, storageId string, hostId string,
|
||||
params["systemTags"] = []string{"ceph::pool::" + poolName}
|
||||
}
|
||||
resp, err := region.client.post("volumes/data", jsonutils.Marshal(params))
|
||||
disk := &SDisk{}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disk := &SDisk{region: region}
|
||||
return disk, resp.Unmarshal(disk, "inventory")
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteDisk(diskId string) error {
|
||||
return region.client.delete("volumes", diskId, "Enforcing")
|
||||
err := region.client.delete("volumes", diskId, "Enforcing")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params := map[string]interface{}{
|
||||
"expungeDataVolume": jsonutils.NewDict(),
|
||||
}
|
||||
_, err = region.client.put("volumes", diskId, jsonutils.Marshal(params))
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) ResizeDisk(diskId string, sizeMb int64) error {
|
||||
|
||||
+52
-22
@@ -1,6 +1,7 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -22,20 +23,8 @@ type SEipAddress struct {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetEip(eipId string) (*SEipAddress, error) {
|
||||
eips, err := region.GetEips(eipId, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(eips) == 1 {
|
||||
if eips[0].UUID == eipId {
|
||||
return &eips[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(eips) == 0 || len(eipId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
eip := &SEipAddress{region: region}
|
||||
return eip, region.client.getResource("eips", eipId, eip)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetEips(eipId, instanceId string) ([]SEipAddress, error) {
|
||||
@@ -104,17 +93,13 @@ func (eip *SEipAddress) GetAssociationType() string {
|
||||
func (eip *SEipAddress) GetAssociationExternalId() string {
|
||||
if len(eip.VMNicUUID) > 0 {
|
||||
instances, err := eip.region.GetInstances("", "", eip.VMNicUUID)
|
||||
if err != nil && len(instances) == 1 {
|
||||
if err == nil && len(instances) == 1 {
|
||||
return instances[0].UUID
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (eip *SEipAddress) GetManagerId() string {
|
||||
return eip.region.client.providerID
|
||||
}
|
||||
|
||||
func (eip *SEipAddress) GetBillingType() string {
|
||||
return ""
|
||||
}
|
||||
@@ -128,23 +113,31 @@ func (eip *SEipAddress) GetExpiredAt() time.Time {
|
||||
}
|
||||
|
||||
func (eip *SEipAddress) Delete() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return eip.region.DeleteVirtualIP(eip.VipUUID)
|
||||
}
|
||||
|
||||
func (eip *SEipAddress) GetBandwidth() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (eip *SEipAddress) GetINetworkId() string {
|
||||
vip, err := eip.region.GetVirtualIP(eip.VipUUID)
|
||||
if err == nil {
|
||||
return eip.region.GetNetworkId(vip)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (eip *SEipAddress) GetInternetChargeType() string {
|
||||
return api.EIP_CHARGE_TYPE_BY_TRAFFIC
|
||||
}
|
||||
|
||||
func (eip *SEipAddress) Associate(instanceId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return eip.region.AssociateEip(instanceId, eip.UUID)
|
||||
}
|
||||
|
||||
func (eip *SEipAddress) Dissociate() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return eip.region.DisassociateEip(eip.UUID)
|
||||
}
|
||||
|
||||
func (eip *SEipAddress) ChangeBandwidth(bw int) error {
|
||||
@@ -154,3 +147,40 @@ func (eip *SEipAddress) ChangeBandwidth(bw int) error {
|
||||
func (eip *SEipAddress) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateEip(name string, vipId string, desc string) (*SEipAddress, error) {
|
||||
params := map[string]map[string]string{
|
||||
"params": {
|
||||
"name": name,
|
||||
"description": desc,
|
||||
"vipUuid": vipId,
|
||||
},
|
||||
}
|
||||
eip := &SEipAddress{region: region}
|
||||
resp, err := region.client.post("eips", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return eip, resp.Unmarshal(eip, "inventory")
|
||||
}
|
||||
|
||||
func (region *SRegion) AssociateEip(instanceId, eipId string) error {
|
||||
instance, err := region.GetInstance(instanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(instance.VMNics) == 0 {
|
||||
return fmt.Errorf("instance %s does not have any nic", instance.Name)
|
||||
}
|
||||
resource := fmt.Sprintf("eips/%s/vm-instances/nics/%s", eipId, instance.VMNics[0].UUID)
|
||||
params := map[string]interface{}{
|
||||
"params": jsonutils.NewDict(),
|
||||
}
|
||||
_, err = region.client.post(resource, jsonutils.Marshal(params))
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) DisassociateEip(eipId string) error {
|
||||
resource := fmt.Sprintf("eips/%s/vm-instances/nics", eipId)
|
||||
return region.client.delete(resource, "", "")
|
||||
}
|
||||
|
||||
+199
-26
@@ -1,7 +1,12 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -28,6 +33,35 @@ type SHost struct {
|
||||
ZStackTime
|
||||
}
|
||||
|
||||
func (region *SRegion) GetHosts(zoneId string, hostId string) ([]SHost, error) {
|
||||
hosts := []SHost{}
|
||||
params := []string{}
|
||||
if len(zoneId) > 0 {
|
||||
params = append(params, "q=zone.uuid="+zoneId)
|
||||
}
|
||||
if len(hostId) > 0 {
|
||||
params = append(params, "q=uuid="+hostId)
|
||||
}
|
||||
if SkipEsxi {
|
||||
params = append(params, "q=hypervisorType!=ESX")
|
||||
}
|
||||
return hosts, region.client.listAll("hosts", params, &hosts)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetHost(hostId string) (*SHost, error) {
|
||||
host := &SHost{}
|
||||
err := region.client.getResource("hosts", hostId, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zone, err := region.GetZone(host.ZoneUUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
host.zone = zone
|
||||
return host, nil
|
||||
}
|
||||
|
||||
func (host *SHost) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
@@ -45,25 +79,21 @@ func (host *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
||||
}
|
||||
|
||||
func (host *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
primaryStorages, err := host.zone.region.GetPrimaryStorages(host.zone.UUID, host.ClusterUUID, "")
|
||||
storages, err := host.zone.region.GetStorages(host.zone.UUID, host.ClusterUUID, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
istorages := []cloudprovider.ICloudStorage{}
|
||||
for i := 0; i < len(primaryStorages); i++ {
|
||||
switch primaryStorages[i].Type {
|
||||
for i := 0; i < len(storages); i++ {
|
||||
switch storages[i].Type {
|
||||
case StorageTypeLocal:
|
||||
storages, err := host.zone.region.getILocalStorages(host.zone, primaryStorages[i].UUID, host.UUID)
|
||||
localStorages, err := host.zone.region.getILocalStorages(storages[i].UUID, host.UUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
istorages = append(istorages, storages...)
|
||||
istorages = append(istorages, localStorages...)
|
||||
case StorageTypeCeph:
|
||||
storages, err := host.zone.region.getICephStorages(host.zone, primaryStorages[i].UUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
istorages = append(istorages, storages...)
|
||||
istorages = append(istorages, &storages[i])
|
||||
case StorageTypeVCenter:
|
||||
}
|
||||
}
|
||||
@@ -88,21 +118,12 @@ func (host *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
|
||||
}
|
||||
|
||||
func (host *SHost) GetIVMById(instanceId string) (cloudprovider.ICloudVM, error) {
|
||||
instances, err := host.zone.region.GetInstances(host.UUID, instanceId, "")
|
||||
instance, err := host.zone.region.GetInstance(instanceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(instances) == 1 {
|
||||
if instances[0].UUID == instanceId {
|
||||
instances[0].host = host
|
||||
return &instances[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(instances) == 0 || len(instanceId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
instance.host = host
|
||||
return instance, nil
|
||||
}
|
||||
|
||||
func (host *SHost) GetId() string {
|
||||
@@ -179,7 +200,7 @@ func (host *SHost) GetMemSizeMB() int {
|
||||
}
|
||||
|
||||
func (host *SHost) GetStorageSizeMB() int {
|
||||
storages, err := host.zone.region.GetPrimaryStorages(host.zone.UUID, host.ClusterUUID, "")
|
||||
storages, err := host.zone.region.GetStorages(host.zone.UUID, host.ClusterUUID, "")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
@@ -206,12 +227,164 @@ func (host *SHost) GetHostType() string {
|
||||
return api.HOST_TYPE_ZSTACK
|
||||
}
|
||||
|
||||
func (host *SHost) GetManagerId() string {
|
||||
return host.zone.region.client.providerID
|
||||
func (region *SRegion) cleanDisks(diskIds []string) {
|
||||
for i := 0; i < len(diskIds); i++ {
|
||||
err := region.DeleteDisk(diskIds[i])
|
||||
if err != nil {
|
||||
log.Errorf("clean disk %s error: %v", diskIds[i], err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (region *SRegion) createDataDisks(name, hostId string, storages []cloudprovider.ICloudStorage, disks []cloudprovider.SDiskInfo) ([]string, error) {
|
||||
diskIds := []string{}
|
||||
for i := 0; i < len(disks); i++ {
|
||||
for j := 0; j < len(storages); j++ {
|
||||
poolName := ""
|
||||
if storages[i].GetStorageType() == disks[i].StorageType {
|
||||
switch disks[i].StorageType {
|
||||
case "localstorage":
|
||||
poolName = ""
|
||||
case "ceph":
|
||||
hostId = ""
|
||||
storage := storages[j].(*SStorage)
|
||||
poolName, _ := storage.GetDataPoolName()
|
||||
if len(poolName) == 0 {
|
||||
return []string{}, fmt.Errorf("failed to found data pool for ceph storage %s", storage.Name)
|
||||
}
|
||||
default:
|
||||
return diskIds, fmt.Errorf("not support storageType %s", disks[i].StorageType)
|
||||
}
|
||||
name := fmt.Sprintf("vdisk_%s_%d", name, time.Now().UnixNano())
|
||||
disk, err := region.CreateDisk(name, storages[j].GetId(), hostId, poolName, disks[i].SizeGB, "")
|
||||
if err != nil {
|
||||
return diskIds, err
|
||||
}
|
||||
diskIds = append(diskIds, disk.UUID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return diskIds, nil
|
||||
}
|
||||
|
||||
func (host *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
storages, err := host.GetIStorages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
diskIds, err := host.zone.region.createDataDisks(desc.Name, host.UUID, storages, desc.DataDisks)
|
||||
if err != nil {
|
||||
defer host.zone.region.cleanDisks(diskIds)
|
||||
return nil, err
|
||||
}
|
||||
rootStorageId := ""
|
||||
for i := 0; i < len(storages); i++ {
|
||||
if storages[i].GetStorageType() == desc.SysDisk.StorageType {
|
||||
rootStorageId = storages[i].GetId()
|
||||
}
|
||||
}
|
||||
if len(rootStorageId) == 0 {
|
||||
return nil, fmt.Errorf("failed to found appropriate storage for root disk")
|
||||
}
|
||||
instance, err := host.zone.region._createVM(desc, host.UUID, rootStorageId)
|
||||
if err != nil {
|
||||
defer host.zone.region.cleanDisks(diskIds)
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(diskIds); i++ {
|
||||
err = host.zone.region.AttachDisk(instance.UUID, diskIds[i])
|
||||
if err != nil {
|
||||
log.Errorf("failed to attach disk %s into instance %s error: %v", diskIds[i], instance.Name, err)
|
||||
}
|
||||
}
|
||||
err = host.zone.region.AssignSecurityGroup(instance.UUID, desc.ExternalSecgroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return host.GetIVMById(instance.UUID)
|
||||
}
|
||||
|
||||
func (region *SRegion) _createVM(desc *cloudprovider.SManagedVMCreateConfig, hostId string, rootStorageId string) (*SInstance, error) {
|
||||
l3Id := strings.Split(desc.ExternalNetworkId, "/")[0]
|
||||
if len(l3Id) == 0 {
|
||||
return nil, fmt.Errorf("invalid networkid: %s", desc.ExternalNetworkId)
|
||||
}
|
||||
_, err := region.GetL3Network(l3Id)
|
||||
if err != nil {
|
||||
log.Errorf("failed to found l3network %s error: %v", l3Id, err)
|
||||
return nil, err
|
||||
}
|
||||
offerings := map[string]string{}
|
||||
if len(desc.InstanceType) > 0 {
|
||||
offering, err := region.GetInstanceOfferingByType(desc.InstanceType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offerings[offering.Name] = offering.UUID
|
||||
} else {
|
||||
_offerings, err := region.GetInstanceOfferings("", "", desc.Cpu, desc.MemoryMB)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, offering := range _offerings {
|
||||
offerings[offering.Name] = offering.UUID
|
||||
}
|
||||
if len(offerings) == 0 {
|
||||
return nil, fmt.Errorf("instance type %dC%dMB not avaiable", desc.Cpu, desc.MemoryMB)
|
||||
}
|
||||
}
|
||||
return region.CreateInstance(desc, l3Id, hostId, rootStorageId, offerings)
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateInstance(desc *cloudprovider.SManagedVMCreateConfig, l3Id, hostId, rootStorageId string, offerings map[string]string) (*SInstance, error) {
|
||||
instance := &SInstance{}
|
||||
systemTags := []string{
|
||||
"cdroms::Empty::None::None",
|
||||
"usbRedirect::false",
|
||||
fmt.Sprintf("staticIp::%s::%s", l3Id, desc.IpAddr),
|
||||
"vmConsoleMode::vnc",
|
||||
"cleanTraffic::false",
|
||||
}
|
||||
if len(desc.UserData) > 0 {
|
||||
systemTags = append(systemTags, "userdata::"+desc.UserData)
|
||||
}
|
||||
if len(desc.PublicKey) > 0 {
|
||||
systemTags = append(systemTags, "sshkey::"+desc.PublicKey)
|
||||
}
|
||||
var err error
|
||||
for offerName, offerId := range offerings {
|
||||
params := map[string]interface{}{
|
||||
"params": map[string]interface{}{
|
||||
"name": desc.Name,
|
||||
"description": desc.Description,
|
||||
"instanceOfferingUuid": offerId,
|
||||
"imageUuid": desc.ExternalImageId,
|
||||
"l3NetworkUuids": []string{
|
||||
l3Id,
|
||||
},
|
||||
"hostUuid": hostId,
|
||||
"dataVolumeSystemTags": []string{},
|
||||
"rootVolumeSystemTags": []string{},
|
||||
"vmMachineType": "",
|
||||
"tagUuids": []string{},
|
||||
"defaultL3NetworkUuid": l3Id,
|
||||
"primaryStorageUuidForRootVolume": rootStorageId,
|
||||
"dataDiskOfferingUuids": []string{},
|
||||
"systemTags": systemTags,
|
||||
"vmNicConfig": []string{},
|
||||
},
|
||||
}
|
||||
log.Debugf("Try instanceOffering : %s", offerName)
|
||||
err = region.client.create("vm-instances", jsonutils.Marshal(params), instance)
|
||||
if err == nil {
|
||||
return instance, nil
|
||||
}
|
||||
log.Errorf("create %s instance failed error: %v", offerName, err)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("instance type %dC%dMB not avaiable", desc.Cpu, desc.MemoryMB)
|
||||
}
|
||||
|
||||
func (host *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
|
||||
|
||||
+94
-14
@@ -1,12 +1,19 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
@@ -79,6 +86,8 @@ func (image *SImage) GetStatus() string {
|
||||
switch image.Status {
|
||||
case "Ready":
|
||||
return api.CACHED_IMAGE_STATUS_READY
|
||||
case "Downloading":
|
||||
return api.CACHED_IMAGE_STATUS_CACHING
|
||||
default:
|
||||
log.Errorf("Unknown image status: %s", image.Status)
|
||||
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
|
||||
@@ -142,20 +151,8 @@ func (image *SImage) GetCreateTime() time.Time {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetImage(imageId string) (*SImage, error) {
|
||||
images, err := region.GetImages(imageId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(images) == 1 {
|
||||
if images[0].UUID == imageId {
|
||||
return &images[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(images) == 0 || len(imageId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
image := &SImage{storageCache: region.getStorageCache()}
|
||||
return image, region.client.getResource("images", imageId, image)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetImages(imageId string) ([]SImage, error) {
|
||||
@@ -169,3 +166,86 @@ func (region *SRegion) GetImages(imageId string) ([]SImage, error) {
|
||||
}
|
||||
return images, region.client.listAll("images", params, &images)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetBackupStorageUUID() ([]string, error) {
|
||||
imageServers, err := region.GetImageServers("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(imageServers) == 0 {
|
||||
return nil, fmt.Errorf("failed to found any image servers")
|
||||
}
|
||||
servers := ImageServers(imageServers)
|
||||
sort.Sort(servers)
|
||||
return []string{servers[0].UUID}, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateImage(imageName, format, osType, desc string, reader io.Reader, size int64) (*SImage, error) {
|
||||
backupStorageUUIDs, err := region.GetBackupStorageUUID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
platform := ""
|
||||
switch osType {
|
||||
case "linux":
|
||||
platform = "Linux"
|
||||
case "windows":
|
||||
platform = "Windows"
|
||||
default:
|
||||
platform = "Other"
|
||||
}
|
||||
parmas := map[string]interface{}{
|
||||
"params": map[string]interface{}{
|
||||
"name": imageName,
|
||||
"url": fmt.Sprintf("upload://%s", imageName),
|
||||
"description": desc,
|
||||
"mediaType": "RootVolumeTemplate",
|
||||
"system": false,
|
||||
"format": format,
|
||||
"platform": platform,
|
||||
"backupStorageUuids": backupStorageUUIDs,
|
||||
"systemTags": []string{"qemuga", "bootMode::Legacy"},
|
||||
},
|
||||
}
|
||||
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
part, err := writer.CreateFormFile("", imageName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reader == nil {
|
||||
return nil, fmt.Errorf("invalid reader")
|
||||
}
|
||||
|
||||
if size == 0 {
|
||||
return nil, fmt.Errorf("invalid image size")
|
||||
}
|
||||
|
||||
_, err = io.Copy(part, reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = writer.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
image := &SImage{storageCache: region.getStorageCache()}
|
||||
err = region.client.create("images", jsonutils.Marshal(parmas), image)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(image.BackupStorageRefs) < 0 {
|
||||
return nil, fmt.Errorf("no InstallPath reture")
|
||||
}
|
||||
header := http.Header{}
|
||||
header.Add("X-IMAGE-UUID", image.UUID)
|
||||
header.Add("X-IMAGE-SIZE", fmt.Sprintf("%d", size))
|
||||
header.Add("Content-Type", writer.FormDataContentType())
|
||||
_, err = httputils.Request(httputils.GetDefaultClient(), context.Background(), "POST", image.BackupStorageRefs[0].InstallPath, header, body, false)
|
||||
return image, err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package zstack
|
||||
|
||||
type ImageServers []SImageServer
|
||||
|
||||
type SImageServer struct {
|
||||
ZStackBasic
|
||||
|
||||
Hostname string `json:"hostname"`
|
||||
Username string `json:"username"`
|
||||
SSHPort int `json:"sshPort"`
|
||||
URL string `json:"url"`
|
||||
TotalCapacity int `json:"totalCapacity"`
|
||||
AvailableCapacity int `json:"availableCapacity"`
|
||||
Type string `json:"type"`
|
||||
State string `json:"state"`
|
||||
Status string `json:"status"`
|
||||
AttachedZoneUUIDs []string `json:"attachedZoneUuids"`
|
||||
ZStackTime
|
||||
}
|
||||
|
||||
func (v ImageServers) Len() int {
|
||||
return len(v)
|
||||
}
|
||||
|
||||
func (v ImageServers) Swap(i, j int) {
|
||||
v[i], v[j] = v[j], v[i]
|
||||
}
|
||||
|
||||
func (v ImageServers) Less(i, j int) bool {
|
||||
if v[i].AvailableCapacity < v[j].AvailableCapacity {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (region *SRegion) GetImageServers(zoneId string) ([]SImageServer, error) {
|
||||
servers := []SImageServer{}
|
||||
params := []string{"q=state=Enabled", "q=status=Connected", "q=type=ImageStoreBackupStorage"}
|
||||
if SkipEsxi {
|
||||
params = append(params, "q=type!=VCenter")
|
||||
}
|
||||
if len(zoneId) > 0 {
|
||||
params = append(params, "q=zone.uuid="+zoneId)
|
||||
}
|
||||
return servers, region.client.listAll("backup-storage", params, &servers)
|
||||
}
|
||||
+267
-31
@@ -11,6 +11,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
@@ -45,20 +46,8 @@ type SInstance struct {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetInstance(instanceId string) (*SInstance, error) {
|
||||
instances, err := region.GetInstances("", instanceId, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(instances) == 1 {
|
||||
if instances[0].UUID == instanceId {
|
||||
return &instances[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(instances) == 0 || len(instanceId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
instance := &SInstance{}
|
||||
return instance, region.client.getResource("vm-instances", instanceId, instance)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetInstances(hostId string, instanceId string, nicId string) ([]SInstance, error) {
|
||||
@@ -168,7 +157,31 @@ func (instance *SInstance) GetVmemSizeMB() int {
|
||||
}
|
||||
|
||||
func (instance *SInstance) GetBootOrder() string {
|
||||
return "dcn"
|
||||
return instance.host.zone.region.GetBootOrder(instance.UUID)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetBootOrder(instanceId string) string {
|
||||
resp, err := region.client.get("vm-instances", instanceId, "boot-orders")
|
||||
if err != nil {
|
||||
return "dcn"
|
||||
}
|
||||
orders := []string{}
|
||||
err = resp.Unmarshal(&orders, "orders")
|
||||
if err != nil {
|
||||
return "dcn"
|
||||
}
|
||||
order := ""
|
||||
for _, _order := range orders {
|
||||
switch _order {
|
||||
case "CdRom":
|
||||
order += "c"
|
||||
case "HardDisk":
|
||||
order += "d"
|
||||
default:
|
||||
log.Errorf("Unknown BootOrder %s for instance %s", _order, instanceId)
|
||||
}
|
||||
}
|
||||
return order
|
||||
}
|
||||
|
||||
func (instance *SInstance) GetVga() string {
|
||||
@@ -222,11 +235,41 @@ func (instance *SInstance) GetHypervisor() string {
|
||||
}
|
||||
|
||||
func (instance *SInstance) StartVM(ctx context.Context) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
err := instance.host.zone.region.StartVM(instance.UUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cloudprovider.WaitStatus(instance, api.VM_RUNNING, 5*time.Second, 5*time.Minute)
|
||||
}
|
||||
|
||||
func (region *SRegion) StartVM(instanceId string) error {
|
||||
params := map[string]interface{}{
|
||||
"startVmInstance": jsonutils.NewDict(),
|
||||
}
|
||||
_, err := region.client.put("vm-instances", instanceId, jsonutils.Marshal(params))
|
||||
return err
|
||||
}
|
||||
|
||||
func (instance *SInstance) StopVM(ctx context.Context, isForce bool) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
err := instance.host.zone.region.StopVM(instance.UUID, isForce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cloudprovider.WaitStatus(instance, api.VM_READY, 5*time.Second, 5*time.Minute)
|
||||
}
|
||||
|
||||
func (region *SRegion) StopVM(instanceId string, isForce bool) error {
|
||||
option := "grace"
|
||||
if isForce {
|
||||
option = "cold"
|
||||
}
|
||||
params := map[string]interface{}{
|
||||
"stopVmInstance": map[string]string{
|
||||
"type": option,
|
||||
},
|
||||
}
|
||||
_, err := region.client.put("vm-instances", instanceId, jsonutils.Marshal(params))
|
||||
return err
|
||||
}
|
||||
|
||||
func (instance *SInstance) GetVNCInfo() (jsonutils.JSONObject, error) {
|
||||
@@ -235,43 +278,172 @@ func (instance *SInstance) GetVNCInfo() (jsonutils.JSONObject, error) {
|
||||
return nil, err
|
||||
}
|
||||
authURL, _ := url.Parse(instance.host.zone.region.client.authURL)
|
||||
url := fmt.Sprintf("%s://%s:5000/thirdparty/vnc_auto.html?host=%s&port=%d&token=%s&title=%s", info.Scheme, authURL.Host, info.Hostname, info.Port, info.Token, instance.Name)
|
||||
password, _ := instance.host.zone.region.GetInstanceConsolePassword(instance.UUID)
|
||||
if len(password) > 0 {
|
||||
url = url + fmt.Sprintf("&password=%s", password)
|
||||
}
|
||||
return jsonutils.Marshal(map[string]string{
|
||||
"url": fmt.Sprintf("%s://%s:5000/thirdparty/vnc_auto.html?host=%s&port=%d&token=%s&title=%s", info.Scheme, authURL.Host, info.Hostname, info.Port, info.Token, instance.Name),
|
||||
"url": url,
|
||||
"protocol": "zstack",
|
||||
"instance_id": instance.UUID,
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (instance *SInstance) UpdateVM(ctx context.Context, name string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
params := map[string]interface{}{
|
||||
"updateVmInstance": map[string]string{
|
||||
"name": name,
|
||||
},
|
||||
}
|
||||
return instance.host.zone.region.UpdateVM(instance.UUID, jsonutils.Marshal(params))
|
||||
}
|
||||
|
||||
func (region *SRegion) UpdateVM(instanceId string, params jsonutils.JSONObject) error {
|
||||
_, err := region.client.put("vm-instances", instanceId, params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (instance *SInstance) DeployVM(ctx context.Context, name string, password string, publicKey string, deleteKeypair bool, description string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
if instance.Name != name || instance.Description != description {
|
||||
params := map[string]interface{}{
|
||||
"updateVmInstance": map[string]string{
|
||||
"name": name,
|
||||
"description": description,
|
||||
},
|
||||
}
|
||||
err := instance.host.zone.region.UpdateVM(instance.UUID, jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(password) > 0 {
|
||||
params := map[string]interface{}{
|
||||
"changeVmPassword": map[string]string{
|
||||
"account": api.VM_ZSTACK_DEFAULT_LOGIN_USER,
|
||||
"password": password,
|
||||
},
|
||||
}
|
||||
err := instance.host.zone.region.UpdateVM(instance.UUID, jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(publicKey) > 0 {
|
||||
params := map[string]interface{}{
|
||||
"setVmSshKey": map[string]string{
|
||||
"SshKey": publicKey,
|
||||
},
|
||||
}
|
||||
err := instance.host.zone.region.UpdateVM(instance.UUID, jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if deleteKeypair {
|
||||
err := instance.host.zone.region.client.delete("vm-instances", fmt.Sprintf("%s/ssh-keys", instance.UUID), "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (instance *SInstance) RebuildRoot(ctx context.Context, imageId string, passwd string, publicKey string, sysSizeGB int) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
return instance.host.zone.region.RebuildRoot(instance.UUID, imageId, sysSizeGB)
|
||||
}
|
||||
|
||||
func (region *SRegion) RebuildRoot(instanceId, imageId string, sysSizeGB int) (string, error) {
|
||||
params := map[string]interface{}{
|
||||
"changeVmImage": map[string]string{
|
||||
"imageUuid": imageId,
|
||||
},
|
||||
}
|
||||
instance := &SInstance{}
|
||||
resp, err := region.client.put("vm-instances", instanceId, jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = resp.Unmarshal(instance, "inventory")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
disk, err := region.GetDisk(instance.RootVolumeUUID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if sysSizeGB > disk.GetDiskSizeMB()*1024 {
|
||||
return instance.RootVolumeUUID, region.ResizeDisk(disk.UUID, int64(sysSizeGB)*1024)
|
||||
}
|
||||
return instance.RootVolumeUUID, nil
|
||||
}
|
||||
|
||||
func (instance *SInstance) ChangeConfig(ctx context.Context, ncpu int, vmem int) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
offerings, err := instance.host.zone.region.GetInstanceOfferings("", "", ncpu, vmem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, offering := range offerings {
|
||||
log.Debugf("try instance offering %s(%s) ...", offering.Name, offering.UUID)
|
||||
err := instance.host.zone.region.ChangeConfig(instance.UUID, offering.UUID)
|
||||
if err != nil {
|
||||
log.Errorf("failed to change config for instance %s(%s) error: %v", instance.Name, instance.UUID, err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("Failed to change vm config, specification not supported")
|
||||
}
|
||||
|
||||
func (instance *SInstance) ChangeConfig2(ctx context.Context, instanceType string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
offering, err := instance.host.zone.region.GetInstanceOfferingByType(instanceType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return instance.host.zone.region.ChangeConfig(instance.UUID, offering.UUID)
|
||||
}
|
||||
|
||||
func (region *SRegion) ChangeConfig(instanceId, offeringId string) error {
|
||||
params := map[string]interface{}{
|
||||
"changeInstanceOffering": map[string]string{
|
||||
"instanceOfferingUuid": offeringId,
|
||||
},
|
||||
}
|
||||
return region.UpdateVM(instanceId, jsonutils.Marshal(params))
|
||||
}
|
||||
|
||||
func (instance *SInstance) AttachDisk(ctx context.Context, diskId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return instance.host.zone.region.AttachDisk(instance.UUID, diskId)
|
||||
}
|
||||
|
||||
func (region *SRegion) AttachDisk(instanceId string, diskId string) error {
|
||||
_, err := region.client.post(fmt.Sprintf("volumes/%s/vm-instances/%s", diskId, instanceId), jsonutils.NewDict())
|
||||
return err
|
||||
}
|
||||
|
||||
func (instance *SInstance) DetachDisk(ctx context.Context, diskId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return instance.host.zone.region.DetachDisk(instance.UUID, diskId)
|
||||
}
|
||||
|
||||
func (region *SRegion) DetachDisk(instanceId, diskId string) error {
|
||||
url := fmt.Sprintf("volumes/%s/vm-instances?vmUuid=%s", diskId, instanceId)
|
||||
return region.client.delete(url, "", "")
|
||||
}
|
||||
|
||||
func (instance *SInstance) DeleteVM(ctx context.Context) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return instance.host.zone.region.DeleteVM(instance.UUID)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteVM(instanceId string) error {
|
||||
err := region.client.delete("vm-instances", instanceId, "Enforcing")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params := map[string]interface{}{
|
||||
"expungeVmInstance": jsonutils.NewDict(),
|
||||
}
|
||||
_, err = region.client.put("vm-instances", instanceId, jsonutils.Marshal(params))
|
||||
return err
|
||||
}
|
||||
|
||||
func (instance *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
@@ -289,11 +461,75 @@ func (instance *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
}
|
||||
|
||||
func (instance *SInstance) AssignSecurityGroup(secgroupId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return instance.host.zone.region.AssignSecurityGroup(instance.UUID, secgroupId)
|
||||
}
|
||||
|
||||
func (instance *SInstance) SetSecurityGroups(secgroupIds []string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
currentIds, err := instance.GetSecurityGroupIds()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, id := range currentIds {
|
||||
if !utils.IsInStringArray(id, secgroupIds) {
|
||||
err := instance.host.zone.region.RevokeSecurityGroup(instance.UUID, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, id := range secgroupIds {
|
||||
if !utils.IsInStringArray(id, currentIds) {
|
||||
err := instance.host.zone.region.AssignSecurityGroup(instance.UUID, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) AssignSecurityGroup(instanceId, secgroupId string) error {
|
||||
instance, err := region.GetInstance(instanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secgroup, err := region.GetSecurityGroup(secgroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(instance.VMNics) > 0 {
|
||||
if !utils.IsInStringArray(instance.VMNics[0].L3NetworkUUID, secgroup.AttachedL3NetworkUUIDs) {
|
||||
resource := fmt.Sprintf("security-groups/%s/l3-networks/%s", secgroupId, instance.VMNics[0].L3NetworkUUID)
|
||||
_, err := region.client.post(resource, jsonutils.NewDict())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
params := map[string]interface{}{
|
||||
"params": map[string]interface{}{
|
||||
"vmNicUuids": []string{instance.VMNics[0].UUID},
|
||||
},
|
||||
}
|
||||
resource := fmt.Sprintf("security-groups/%s/vm-instances/nics", secgroupId)
|
||||
_, err = region.client.post(resource, jsonutils.Marshal(params))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) RevokeSecurityGroup(instanceId, secgroupId string) error {
|
||||
instance, err := region.GetInstance(instanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, nic := range instance.VMNics {
|
||||
resource := fmt.Sprintf("security-groups/%s/vm-instances/nics?vmNicUuids=%s", secgroupId, nic.UUID)
|
||||
err := region.client.delete(resource, "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (instance *SInstance) GetBillingType() string {
|
||||
@@ -309,15 +545,15 @@ func (instance *SInstance) GetExpiredAt() time.Time {
|
||||
}
|
||||
|
||||
func (instance *SInstance) UpdateUserData(userData string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (instance *SInstance) CreateDisk(ctx context.Context, sizeMb int, uuid string, driver string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (instance *SInstance) Renew(bc billing.SBillingCycle) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (instance *SInstance) GetProjectId() string {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/log"
|
||||
@@ -43,14 +41,9 @@ func (nic *SInstanceNic) GetINetwork() cloudprovider.ICloudNetwork {
|
||||
log.Errorf("failed to found networks for nic %v error: %v", jsonutils.Marshal(nic).String(), err)
|
||||
return nil
|
||||
}
|
||||
ip, err := netutils.NewIPV4Addr(nic.IP)
|
||||
if err != nil {
|
||||
log.Errorf("Invalid ip address %s error: %v", nic.IP, err)
|
||||
return nil
|
||||
}
|
||||
for i := 0; i < len(networks); i++ {
|
||||
if networks[i].GetIPRange().Contains(ip) {
|
||||
l3Network, err := nic.instance.host.zone.region.GetL3Network(nic.instance.host.zone.UUID, "", networks[i].L3NetworkUUID)
|
||||
if networks[i].Contains(nic.IP) {
|
||||
l3Network, err := nic.instance.host.zone.region.GetL3Network(networks[i].L3NetworkUUID)
|
||||
if err != nil {
|
||||
log.Errorf("failed to found l3Network for network %v error: %v", jsonutils.Marshal(networks[i]).String(), err)
|
||||
return nil
|
||||
|
||||
+62
-17
@@ -1,6 +1,8 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
@@ -54,21 +56,9 @@ func (region *SRegion) GetNetwork(zoneId, wireId, l3Id, networkId string) (*SNet
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
}
|
||||
|
||||
func (region *SRegion) GetL3Network(zoneId string, wireId string, l3Id string) (*SL3Network, error) {
|
||||
l3Networks, err := region.GetL3Networks(zoneId, wireId, l3Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(l3Networks) == 1 {
|
||||
if l3Networks[0].UUID == l3Id {
|
||||
return &l3Networks[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(l3Networks) == 0 || len(l3Id) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
func (region *SRegion) GetL3Network(l3Id string) (*SL3Network, error) {
|
||||
l3network := &SL3Network{}
|
||||
return l3network, region.client.getResource("l3-networks", l3Id, l3network)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetL3Networks(zoneId string, wireId string, l3Id string) ([]SL3Network, error) {
|
||||
@@ -115,7 +105,7 @@ func (network *SNetwork) GetName() string {
|
||||
}
|
||||
|
||||
func (network *SNetwork) GetGlobalId() string {
|
||||
return network.UUID
|
||||
return fmt.Sprintf("%s/%s", network.L3NetworkUUID, network.UUID)
|
||||
}
|
||||
|
||||
func (network *SNetwork) IsEmulated() bool {
|
||||
@@ -131,7 +121,18 @@ func (network *SNetwork) Delete() error {
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteNetwork(networkId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
network, err := region.GetNetwork("", "", "", networkId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l3, err := region.GetL3Network(network.L3NetworkUUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(l3.Networks) == 1 {
|
||||
return region.client.delete("l3-networks", l3.UUID, "")
|
||||
}
|
||||
return region.client.delete("l3-networks/ip-ranges", networkId, "")
|
||||
}
|
||||
|
||||
func (network *SNetwork) GetIWire() cloudprovider.ICloudWire {
|
||||
@@ -160,6 +161,14 @@ func (network *SNetwork) GetIPRange() netutils.IPV4AddrRange {
|
||||
return netutils.NewIPV4AddrRange(start, end)
|
||||
}
|
||||
|
||||
func (network *SNetwork) Contains(ipAddr string) bool {
|
||||
ip, err := netutils.NewIPV4Addr(ipAddr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return network.GetIPRange().Contains(ip)
|
||||
}
|
||||
|
||||
func (network *SNetwork) GetIpMask() int8 {
|
||||
return int8(network.PrefixLen)
|
||||
}
|
||||
@@ -184,3 +193,39 @@ func (network *SNetwork) Refresh() error {
|
||||
func (network *SNetwork) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateNetwork(name string, cidr string, wireId string, desc string) (*SNetwork, error) {
|
||||
params := map[string]interface{}{
|
||||
"params": map[string]interface{}{
|
||||
"name": name,
|
||||
"type": "L3BasicNetwork",
|
||||
"l2NetworkUuid": wireId,
|
||||
"category": "Private",
|
||||
"system": false,
|
||||
},
|
||||
}
|
||||
l3 := &SL3Network{}
|
||||
resp, err := region.client.post("l3-networks", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = resp.Unmarshal(l3, "inventory")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
region.AttachServiceForl3Network(l3.UUID, []string{"Flat", "SecurityGroup"})
|
||||
params = map[string]interface{}{
|
||||
"params": map[string]interface{}{
|
||||
"name": name,
|
||||
"networkCidr": cidr,
|
||||
},
|
||||
}
|
||||
resource := fmt.Sprintf("l3-networks/%s/ip-ranges/by-cidr", l3.UUID)
|
||||
resp, err = region.client.post(resource, jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
region.client.delete("l3-networks", l3.UUID, "")
|
||||
return nil, err
|
||||
}
|
||||
network := &SNetwork{}
|
||||
return network, resp.Unmarshal(network, "inventory")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
type SNetworkService struct {
|
||||
IPsec []string `json:"IPsec"`
|
||||
VRouterRoute []string `json:"VRouterRoute"`
|
||||
VipQos []string `json:"VipQos"`
|
||||
DNS []string `json:"DNS"`
|
||||
SNAT []string `json:"SNAT"`
|
||||
LoadBalancer []string `json:"LoadBalancer"`
|
||||
Userdata []string `json:"Userdata"`
|
||||
SecurityGroup []string `json:"SecurityGroup"`
|
||||
Eip []string `json:"Eip"`
|
||||
DHCP []string `json:"DHCP"`
|
||||
CentralizedDNS []string `json:"CentralizedDNS"`
|
||||
HostRoute []string `json:"HostRoute"`
|
||||
PortForwarding []string `json:"PortForwarding"`
|
||||
}
|
||||
|
||||
type SNetworkServiceProvider struct {
|
||||
ZStackBasic
|
||||
ZStackTime
|
||||
Type string `json:"type"`
|
||||
NetworkServiceTypes []string `json:"networkServiceTypes"`
|
||||
AttachedL2NetworkUUIDs []string `json:"attachedL2NetworkUuids"`
|
||||
}
|
||||
|
||||
type SNetworkServiceRef struct {
|
||||
L3NetworkUUID string `json:"l3NetworkUuid"`
|
||||
NetworkServiceProviderUUID string `json:"networkServiceProviderUuid"`
|
||||
NetworkServiceType string `json:"networkServiceType"`
|
||||
}
|
||||
|
||||
func (region *SRegion) GetNetworkServices() (*SNetworkService, error) {
|
||||
service := &SNetworkService{}
|
||||
resp, err := region.client.get("network-services/types", "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return service, resp.Unmarshal(service, "types")
|
||||
}
|
||||
|
||||
func (region *SRegion) GetNetworkServiceProviders(Type string) ([]SNetworkServiceProvider, error) {
|
||||
providers := []SNetworkServiceProvider{}
|
||||
params := []string{}
|
||||
if len(Type) > 0 {
|
||||
params = append(params, "q=type="+Type)
|
||||
}
|
||||
return providers, region.client.listAll("network-services/providers", params, &providers)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetNetworkServiceRef(l3Id string, Type string) ([]SNetworkServiceRef, error) {
|
||||
refs := []SNetworkServiceRef{}
|
||||
params := []string{}
|
||||
if len(l3Id) > 0 {
|
||||
params = append(params, "q=l3NetworkUuid="+l3Id)
|
||||
}
|
||||
if len(Type) > 0 {
|
||||
params = append(params, "q=networkServiceType="+Type)
|
||||
}
|
||||
return refs, region.client.listAll("l3-networks/network-services/refs", params, &refs)
|
||||
}
|
||||
|
||||
func (region *SRegion) AttachServiceForl3Network(l3Id string, services []string) error {
|
||||
networkServices := map[string][]string{}
|
||||
refs, err := region.GetNetworkServiceRef(l3Id, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currentServices := []string{}
|
||||
for i := 0; i < len(refs); i++ {
|
||||
currentServices = append(currentServices, refs[i].NetworkServiceType)
|
||||
}
|
||||
for _, service := range services {
|
||||
networkServiceProviders, err := region.GetNetworkServiceProviders(service)
|
||||
if err != nil || len(networkServiceProviders) == 0 {
|
||||
msg := fmt.Sprintf("failed to find network services %s error: %v", service, err)
|
||||
log.Errorln(msg)
|
||||
return fmt.Errorf(msg)
|
||||
}
|
||||
attachServices := []string{}
|
||||
for i := 0; i < len(networkServiceProviders[0].NetworkServiceTypes); i++ {
|
||||
if !utils.IsInStringArray(networkServiceProviders[0].NetworkServiceTypes[i], currentServices) {
|
||||
attachServices = append(attachServices, networkServiceProviders[0].NetworkServiceTypes[i])
|
||||
}
|
||||
}
|
||||
if len(attachServices) > 0 {
|
||||
networkServices[networkServiceProviders[0].UUID] = attachServices
|
||||
}
|
||||
}
|
||||
|
||||
if len(networkServices) == 0 {
|
||||
return nil
|
||||
}
|
||||
params := map[string]interface{}{
|
||||
"params": map[string]interface{}{
|
||||
"networkServices": networkServices,
|
||||
},
|
||||
}
|
||||
resource := fmt.Sprintf("l3-networks/%s/network-services", l3Id)
|
||||
_, err = region.client.post(resource, jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
log.Errorf("failed to attach network services %s to l3network %s error: %v", services, l3Id, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) RemoveNetworkService(l3Id string, service string) error {
|
||||
return region.client.delete("l3-networks", fmt.Sprintf("%s/network-services?networkServices=%s", l3Id, service), "")
|
||||
}
|
||||
+23
-11
@@ -1,8 +1,9 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
@@ -22,28 +23,39 @@ type SInstanceOffering struct {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetInstanceOffering(offerId string) (*SInstanceOffering, error) {
|
||||
offerings, err := region.GetInstanceOfferings(offerId)
|
||||
offer := &SInstanceOffering{region: region}
|
||||
return offer, region.client.getResource("instance-offerings", offerId, offer)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetInstanceOfferingByType(instanceType string) (*SInstanceOffering, error) {
|
||||
offerings, err := region.GetInstanceOfferings("", instanceType, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(offerings) == 1 {
|
||||
if offerings[0].UUID == offerId {
|
||||
return &offerings[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
return &offerings[0], nil
|
||||
}
|
||||
if len(offerings) == 0 || len(offerId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
if len(offerings) == 0 {
|
||||
return nil, fmt.Errorf("instanceType %s not found", instanceType)
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
return nil, fmt.Errorf("duplicate instanceType %s", instanceType)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetInstanceOfferings(offerId string) ([]SInstanceOffering, error) {
|
||||
func (region *SRegion) GetInstanceOfferings(offerId string, name string, cpu int, memorySizeMb int) ([]SInstanceOffering, error) {
|
||||
offerings := []SInstanceOffering{}
|
||||
params := []string{"q=type=UserVM"}
|
||||
params := []string{"q=type=UserVM", "q=state=Enabled"}
|
||||
if len(offerId) > 0 {
|
||||
params = append(params, "q=uuid="+offerId)
|
||||
}
|
||||
if len(name) > 0 {
|
||||
params = append(params, "q=name="+name)
|
||||
}
|
||||
if cpu != 0 {
|
||||
params = append(params, fmt.Sprintf("q=cpuNum=%d", cpu))
|
||||
}
|
||||
if memorySizeMb != 0 {
|
||||
params = append(params, fmt.Sprintf("q=memorySize=%d", memorySizeMb*1024*1024))
|
||||
}
|
||||
if err := region.client.listAll("instance-offerings", params, &offerings); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+46
-21
@@ -2,6 +2,7 @@ package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -35,11 +36,11 @@ func (region *SRegion) GetId() string {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetName() string {
|
||||
return fmt.Sprintf("%s %s", CLOUD_PROVIDER_ZSTACK, region.Name)
|
||||
return region.client.providerName
|
||||
}
|
||||
|
||||
func (region *SRegion) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s/%s", CLOUD_PROVIDER_ZSTACK, region.Name)
|
||||
return fmt.Sprintf("%s/%s", CLOUD_PROVIDER_ZSTACK, region.client.providerID)
|
||||
}
|
||||
|
||||
func (region *SRegion) IsEmulated() bool {
|
||||
@@ -64,7 +65,7 @@ func (region *SRegion) Refresh() error {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
return region.GetHost("", id)
|
||||
return region.GetHost(id)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
@@ -114,6 +115,10 @@ func (region *SRegion) GetIStoragecaches() ([]cloudprovider.ICloudStoragecache,
|
||||
return []cloudprovider.ICloudStoragecache{region.storageCache}, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) getStorageCache() *SStoragecache {
|
||||
return &SStoragecache{region: region}
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIVpcById(vpcId string) (cloudprovider.ICloudVpc, error) {
|
||||
return &SVpc{region: region}, nil
|
||||
}
|
||||
@@ -132,20 +137,8 @@ func (region *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetZone(zoneId string) (*SZone, error) {
|
||||
zones, err := region.GetZones(zoneId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(zones) == 1 {
|
||||
if zones[0].UUID == zoneId {
|
||||
return &zones[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(zones) == 0 || len(zoneId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
zone := &SZone{region: region}
|
||||
return zone, region.client.getResource("zones", zoneId, zone)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetZones(zoneId string) ([]SZone, error) {
|
||||
@@ -206,8 +199,23 @@ func (region *SRegion) CreateIVpc(name string, desc string, cidr string) (cloudp
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateEIP(name string, bwMbps int, chargeType string, bgpType string) (cloudprovider.ICloudEIP, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
func (region *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
|
||||
if len(eip.NetworkExternalId) == 0 {
|
||||
return nil, fmt.Errorf("networkId cannot be empty")
|
||||
}
|
||||
networkInfo := strings.Split(eip.NetworkExternalId, "/")
|
||||
if len(networkInfo) != 2 {
|
||||
return nil, fmt.Errorf("invalid network externalId, it should be `l3networId/networkId` format")
|
||||
}
|
||||
_, err := region.GetL3Network(networkInfo[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vip, err := region.CreateVirtualIP(eip.Name, "", eip.IP, networkInfo[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return region.CreateEip(eip.Name, vip.UUID, "")
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
|
||||
@@ -284,7 +292,7 @@ func (region *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloud
|
||||
}
|
||||
|
||||
func (region *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error) {
|
||||
offerings, err := region.GetInstanceOfferings("")
|
||||
offerings, err := region.GetInstanceOfferings("", "", 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -296,5 +304,22 @@ func (region *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error)
|
||||
}
|
||||
|
||||
func (region *SRegion) SyncSecurityGroup(secgroupId string, vpcId string, name string, desc string, rules []secrules.SecurityRule) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
if len(secgroupId) > 0 {
|
||||
_, err := region.GetSecurityGroup(secgroupId)
|
||||
if err != nil {
|
||||
if err == cloudprovider.ErrNotFound {
|
||||
secgroupId = ""
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(secgroupId) == 0 {
|
||||
secgroup, err := region.CreateSecurityGroup(name, desc)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
secgroupId = secgroup.UUID
|
||||
}
|
||||
return secgroupId, region.syncSecgroupRules(secgroupId, rules)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
@@ -25,6 +25,28 @@ type SSecurityGroupRule struct {
|
||||
ZStackTime
|
||||
}
|
||||
|
||||
type SSecurityGroupRuleSet []SSecurityGroupRule
|
||||
|
||||
func (v SSecurityGroupRuleSet) Len() int {
|
||||
return len(v)
|
||||
}
|
||||
|
||||
func (v SSecurityGroupRuleSet) Swap(i, j int) {
|
||||
v[i], v[j] = v[j], v[i]
|
||||
}
|
||||
|
||||
func (v SSecurityGroupRuleSet) Less(i, j int) bool {
|
||||
rule, err := v[i].toRule()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_rule, err := v[j].toRule()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return strings.Compare(rule.String(), _rule.String()) <= 0
|
||||
}
|
||||
|
||||
type SSecurityGroup struct {
|
||||
region *SRegion
|
||||
|
||||
@@ -38,20 +60,8 @@ type SSecurityGroup struct {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetSecurityGroup(secgroupId string) (*SSecurityGroup, error) {
|
||||
secgroups, err := region.GetSecurityGroups(secgroupId, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(secgroups) == 1 {
|
||||
if secgroups[0].UUID == secgroupId {
|
||||
return &secgroups[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(secgroups) == 0 || len(secgroupId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
secgroup := &SSecurityGroup{region: region}
|
||||
return secgroup, region.client.getResource("security-groups", secgroupId, secgroup)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetSecurityGroups(secgroupId string, instanceId string) ([]SSecurityGroup, error) {
|
||||
@@ -94,33 +104,44 @@ func (self *SSecurityGroup) GetDescription() string {
|
||||
return self.Description
|
||||
}
|
||||
|
||||
func (rule *SSecurityGroupRule) toRule() (*secrules.SecurityRule, error) {
|
||||
r := &secrules.SecurityRule{
|
||||
Direction: secrules.DIR_IN,
|
||||
Action: secrules.SecurityRuleAllow,
|
||||
Priority: 1,
|
||||
Protocol: secrules.PROTO_ANY,
|
||||
PortStart: rule.StartPort,
|
||||
PortEnd: rule.EndPort,
|
||||
}
|
||||
_, ipNet, err := net.ParseCIDR(rule.AllowedCIDR)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.IPNet = ipNet
|
||||
if rule.Type == "Egress" {
|
||||
r.Direction = secrules.DIR_OUT
|
||||
}
|
||||
if rule.Protocol != "ALL" {
|
||||
r.Protocol = strings.ToLower(rule.Protocol)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetRules() ([]secrules.SecurityRule, error) {
|
||||
rules := []secrules.SecurityRule{}
|
||||
priority := 100
|
||||
outRuleCount := 0
|
||||
for i := 0; i < len(self.Rules); i++ {
|
||||
if self.Rules[i].IPVersion == 4 {
|
||||
rule := secrules.SecurityRule{
|
||||
Direction: secrules.DIR_IN,
|
||||
Action: secrules.SecurityRuleAllow,
|
||||
Priority: priority,
|
||||
Protocol: secrules.PROTO_ANY,
|
||||
PortStart: self.Rules[i].StartPort,
|
||||
PortEnd: self.Rules[i].EndPort,
|
||||
}
|
||||
_, ipNet, err := net.ParseCIDR(self.Rules[i].AllowedCIDR)
|
||||
rule, err := self.Rules[i].toRule()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rule.IPNet = ipNet
|
||||
if self.Rules[i].Type == "Egress" {
|
||||
rule.Direction = secrules.DIR_OUT
|
||||
if rule.Direction == secrules.DIR_OUT {
|
||||
outRuleCount++
|
||||
}
|
||||
if self.Rules[i].Protocol != "ALL" {
|
||||
rule.Protocol = strings.ToLower(self.Rules[i].Protocol)
|
||||
}
|
||||
rules = append(rules, rule)
|
||||
rule.Priority = priority
|
||||
rules = append(rules, *rule)
|
||||
priority--
|
||||
}
|
||||
}
|
||||
@@ -155,3 +176,135 @@ func (self *SSecurityGroup) Refresh() error {
|
||||
func (self *SSecurityGroup) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (region *SRegion) AddSecurityGroupRule(secgroupId string, rules []secrules.SecurityRule) error {
|
||||
ruleParam := []map[string]interface{}{}
|
||||
for _, rule := range rules {
|
||||
Type := "Ingress"
|
||||
if rule.Direction == secrules.DIR_OUT {
|
||||
Type = "Egress"
|
||||
}
|
||||
protocol := "ALL"
|
||||
if rule.Protocol != secrules.PROTO_ANY {
|
||||
protocol = strings.ToUpper(rule.Protocol)
|
||||
}
|
||||
if rule.Protocol == secrules.PROTO_ICMP {
|
||||
rule.PortStart = -1
|
||||
rule.PortEnd = -1
|
||||
rule.Ports = []int{}
|
||||
}
|
||||
if len(rule.Ports) > 0 {
|
||||
for _, port := range rule.Ports {
|
||||
ruleParam = append(ruleParam, map[string]interface{}{
|
||||
"type": Type,
|
||||
"startPort": port,
|
||||
"endPort": port,
|
||||
"protocol": protocol,
|
||||
"allowedCidr": rule.IPNet.String(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
ruleParam = append(ruleParam, map[string]interface{}{
|
||||
"type": Type,
|
||||
"startPort": rule.PortStart,
|
||||
"endPort": rule.PortEnd,
|
||||
"protocol": protocol,
|
||||
"allowedCidr": rule.IPNet.String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
if len(ruleParam) > 0 {
|
||||
params := map[string]interface{}{
|
||||
"parms": map[string]interface{}{
|
||||
"rules": ruleParam,
|
||||
},
|
||||
}
|
||||
return region.client.create(fmt.Sprintf("security-groups/%s/rules", secgroupId), jsonutils.Marshal(params), nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteSecurityGroupRules(ruleIds []string) error {
|
||||
resource := fmt.Sprintf("security-groups/rules?ruleUuids=%s", strings.Join(ruleIds, ","))
|
||||
return region.client.delete(resource, "", "")
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateSecurityGroup(name, desc string) (*SSecurityGroup, error) {
|
||||
secgroup := &SSecurityGroup{}
|
||||
params := map[string]map[string]string{
|
||||
"params": {
|
||||
"name": name,
|
||||
"description": desc,
|
||||
},
|
||||
}
|
||||
return secgroup, region.client.create("security-groups", jsonutils.Marshal(params), secgroup)
|
||||
}
|
||||
|
||||
func (region *SRegion) syncSecgroupRules(secgroupId string, rules []secrules.SecurityRule) error {
|
||||
secgroup, err := region.GetSecurityGroup(secgroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inRules, outRules := secrules.SecurityRuleSet{}, secrules.SecurityRuleSet{}
|
||||
for i := 0; i < len(rules); i++ {
|
||||
if rules[i].Direction == secrules.DIR_IN {
|
||||
inRules = append(inRules, rules[i])
|
||||
} else {
|
||||
outRules = append(outRules, rules[i])
|
||||
}
|
||||
}
|
||||
|
||||
if len(outRules) > 0 {
|
||||
rule := secrules.MustParseSecurityRule("out:allow any")
|
||||
outRules = append(outRules, *rule)
|
||||
}
|
||||
|
||||
rules = inRules.AllowList()
|
||||
rules = append(rules, outRules.AllowList()...)
|
||||
for i := 0; i < len(rules); i++ {
|
||||
rules[i].Priority = 1
|
||||
}
|
||||
|
||||
sort.Sort(secrules.SecurityRuleSet(rules))
|
||||
sort.Sort(SSecurityGroupRuleSet(secgroup.Rules))
|
||||
|
||||
delRuleIds := []string{}
|
||||
addRules := []secrules.SecurityRule{}
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(rules) || j < len(secgroup.Rules) {
|
||||
if i < len(rules) && j < len(secgroup.Rules) {
|
||||
_rule, err := secgroup.Rules[j].toRule()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ruleStr := _rule.String()
|
||||
ruleStr := rules[i].String()
|
||||
cmp := strings.Compare(_ruleStr, ruleStr)
|
||||
if cmp == 0 {
|
||||
i++
|
||||
j++
|
||||
} else if cmp > 0 {
|
||||
delRuleIds = append(delRuleIds, secgroup.Rules[j].UUID)
|
||||
j++
|
||||
} else {
|
||||
addRules = append(addRules, rules[i])
|
||||
i++
|
||||
}
|
||||
} else if i >= len(rules) {
|
||||
delRuleIds = append(delRuleIds, secgroup.Rules[j].UUID)
|
||||
j++
|
||||
} else if j >= len(secgroup.Rules) {
|
||||
addRules = append(addRules, rules[i])
|
||||
i++
|
||||
}
|
||||
}
|
||||
if len(delRuleIds) > 0 {
|
||||
err = region.DeleteSecurityGroupRules(delRuleIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return region.AddSecurityGroupRule(secgroupId, addRules)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
"yunion.io/x/onecloud/pkg/util/zstack"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ConfigrationListOptions struct {
|
||||
}
|
||||
shellutils.R(&ConfigrationListOptions{}, "configration-list", "List configration", func(cli *zstack.SRegion, args *ConfigrationListOptions) error {
|
||||
configrations, err := cli.GetConfigrations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(configrations, len(configrations), 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -20,6 +20,23 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type DiskIdOptions struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
shellutils.R(&DiskIdOptions{}, "disk-show", "Show disk", func(cli *zstack.SRegion, args *DiskIdOptions) error {
|
||||
disk, err := cli.GetDisk(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(disk)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&DiskIdOptions{}, "disk-delete", "Delete disk", func(cli *zstack.SRegion, args *DiskIdOptions) error {
|
||||
return cli.DeleteDisk(args.ID)
|
||||
})
|
||||
|
||||
type DiskCreateOptions struct {
|
||||
NAME string
|
||||
Description string
|
||||
@@ -38,14 +55,6 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type DiskDelete struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
shellutils.R(&DiskDelete{}, "disk-delete", "Delete disk", func(cli *zstack.SRegion, args *DiskDelete) error {
|
||||
return cli.DeleteDisk(args.ID)
|
||||
})
|
||||
|
||||
type DiskResize struct {
|
||||
ID string
|
||||
SIZEGB int64
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
"yunion.io/x/onecloud/pkg/util/zstack"
|
||||
)
|
||||
@@ -18,4 +20,29 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type ImageCreateOptions struct {
|
||||
FILE string
|
||||
FORMAT string `choices:"qcow2|raw|iso"`
|
||||
PLATFORM string `choices:"Linux|Windows|Other"`
|
||||
Desc string
|
||||
}
|
||||
|
||||
shellutils.R(&ImageCreateOptions{}, "image-create", "Create image", func(cli *zstack.SRegion, args *ImageCreateOptions) error {
|
||||
f, err := os.Open(args.FILE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
finfo, err := f.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
image, err := cli.CreateImage(args.FILE, args.FORMAT, args.PLATFORM, args.Desc, f, finfo.Size())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(image)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
"yunion.io/x/onecloud/pkg/util/zstack"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ImageServerListOptions struct {
|
||||
ZoneId string
|
||||
}
|
||||
shellutils.R(&ImageServerListOptions{}, "image-server-list", "List image servers", func(cli *zstack.SRegion, args *ImageServerListOptions) error {
|
||||
servers, err := cli.GetImageServers(args.ZoneId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(servers, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -26,6 +26,10 @@ func init() {
|
||||
ID string
|
||||
}
|
||||
|
||||
shellutils.R(&InstanceOperation{}, "instance-delete", "Delete instance", func(cli *zstack.SRegion, args *InstanceOperation) error {
|
||||
return cli.DeleteVM(args.ID)
|
||||
})
|
||||
|
||||
shellutils.R(&InstanceOperation{}, "instance-console-password", "Show instance console password", func(cli *zstack.SRegion, args *InstanceOperation) error {
|
||||
password, err := cli.GetInstanceConsolePassword(args.ID)
|
||||
if err != nil {
|
||||
@@ -44,4 +48,35 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&InstanceOperation{}, "instance-start", "Start instance", func(cli *zstack.SRegion, args *InstanceOperation) error {
|
||||
return cli.StartVM(args.ID)
|
||||
})
|
||||
|
||||
shellutils.R(&InstanceOperation{}, "instance-boot-order", "Show instance boot order", func(cli *zstack.SRegion, args *InstanceOperation) error {
|
||||
fmt.Println(cli.GetBootOrder(args.ID))
|
||||
return nil
|
||||
})
|
||||
|
||||
type InstanceStopOption struct {
|
||||
ID string
|
||||
IsForce bool
|
||||
}
|
||||
|
||||
shellutils.R(&InstanceStopOption{}, "instance-stop", "Start instance", func(cli *zstack.SRegion, args *InstanceStopOption) error {
|
||||
return cli.StopVM(args.ID, args.IsForce)
|
||||
})
|
||||
|
||||
type InstanceSecgroupOption struct {
|
||||
ID string
|
||||
SECGRPID string
|
||||
}
|
||||
|
||||
shellutils.R(&InstanceSecgroupOption{}, "instance-assign-secgroup", "Assign secgroup for a instance", func(cli *zstack.SRegion, args *InstanceSecgroupOption) error {
|
||||
return cli.AssignSecurityGroup(args.ID, args.SECGRPID)
|
||||
})
|
||||
|
||||
shellutils.R(&InstanceSecgroupOption{}, "instance-revoke-secgroup", "Assign secgroup for a instance", func(cli *zstack.SRegion, args *InstanceSecgroupOption) error {
|
||||
return cli.RevokeSecurityGroup(args.ID, args.SECGRPID)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
"yunion.io/x/onecloud/pkg/util/zstack"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type InstanceOfferingListOptions struct {
|
||||
OfferId string
|
||||
Name string
|
||||
Cpu int
|
||||
MemoryMb int
|
||||
}
|
||||
shellutils.R(&InstanceOfferingListOptions{}, "instance-offering-list", "List instance offerings", func(cli *zstack.SRegion, args *InstanceOfferingListOptions) error {
|
||||
offerings, err := cli.GetInstanceOfferings(args.OfferId, args.Name, args.Cpu, args.MemoryMb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(offerings, len(offerings), 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -20,4 +20,102 @@ func init() {
|
||||
printList(networks, len(networks), 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type NetworkDeleteOptions struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
shellutils.R(&NetworkDeleteOptions{}, "network-delete", "Delete network", func(cli *zstack.SRegion, args *NetworkDeleteOptions) error {
|
||||
return cli.DeleteNetwork(args.ID)
|
||||
})
|
||||
|
||||
type NetworkCreateOptions struct {
|
||||
NAME string
|
||||
Desc string
|
||||
WIRE string
|
||||
CIDR string
|
||||
}
|
||||
|
||||
shellutils.R(&NetworkCreateOptions{}, "network-create", "Create network", func(cli *zstack.SRegion, args *NetworkCreateOptions) error {
|
||||
network, err := cli.CreateNetwork(args.NAME, args.CIDR, args.WIRE, args.Desc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(network)
|
||||
return nil
|
||||
})
|
||||
|
||||
type L3NetworkListOptions struct {
|
||||
ZoneId string
|
||||
WireId string
|
||||
Id string
|
||||
}
|
||||
|
||||
shellutils.R(&L3NetworkListOptions{}, "l3network-list", "List networks", func(cli *zstack.SRegion, args *L3NetworkListOptions) error {
|
||||
l3networks, err := cli.GetL3Networks(args.ZoneId, args.WireId, args.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(l3networks, len(l3networks), 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type NetworkServicesOptions struct {
|
||||
}
|
||||
|
||||
shellutils.R(&NetworkServicesOptions{}, "network-service-list", "List network services", func(cli *zstack.SRegion, args *NetworkServicesOptions) error {
|
||||
service, err := cli.GetNetworkServices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(service)
|
||||
return nil
|
||||
})
|
||||
|
||||
type NetworkServiceProviderOptions struct {
|
||||
Type string
|
||||
}
|
||||
|
||||
shellutils.R(&NetworkServiceProviderOptions{}, "network-service-provider-list", "List network service providers", func(cli *zstack.SRegion, args *NetworkServiceProviderOptions) error {
|
||||
providers, err := cli.GetNetworkServiceProviders(args.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(providers, len(providers), 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type NetworkServiceAttachOptions struct {
|
||||
Services []string
|
||||
ID string
|
||||
}
|
||||
|
||||
shellutils.R(&NetworkServiceAttachOptions{}, "network-service-attach", "Attach network service to l3network", func(cli *zstack.SRegion, args *NetworkServiceAttachOptions) error {
|
||||
cli.AttachServiceForl3Network(args.ID, args.Services)
|
||||
return nil
|
||||
})
|
||||
|
||||
type NetworkServiceRefOptions struct {
|
||||
L3Id string
|
||||
Type string
|
||||
}
|
||||
|
||||
shellutils.R(&NetworkServiceRefOptions{}, "network-service-ref", "List network service ref", func(cli *zstack.SRegion, args *NetworkServiceRefOptions) error {
|
||||
refs, err := cli.GetNetworkServiceRef(args.L3Id, args.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(refs, len(refs), 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type NetworkServiceRemoveOptions struct {
|
||||
L3ID string
|
||||
SERVICE string `choices:"Userdata|DHCP|VipQos|HostRoute|Eip|SecurityGroup|DNS|SNAT"`
|
||||
}
|
||||
|
||||
shellutils.R(&NetworkServiceRemoveOptions{}, "remove-network-service", "Remove l3network service", func(cli *zstack.SRegion, args *NetworkServiceRemoveOptions) error {
|
||||
return cli.RemoveNetworkService(args.L3ID, args.SERVICE)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
"yunion.io/x/onecloud/pkg/util/zstack"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type OfferingListOptions struct {
|
||||
OfferId string
|
||||
}
|
||||
shellutils.R(&OfferingListOptions{}, "offering-list", "List instance offerings", func(cli *zstack.SRegion, args *OfferingListOptions) error {
|
||||
offerings, err := cli.GetInstanceOfferings(args.OfferId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(offerings, len(offerings), 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -11,8 +11,8 @@ func init() {
|
||||
ClusterId string
|
||||
Id string
|
||||
}
|
||||
shellutils.R(&StorageListOptions{}, "primary-storage-list", "List storages", func(cli *zstack.SRegion, args *StorageListOptions) error {
|
||||
storages, err := cli.GetPrimaryStorages(args.ZoneId, args.ClusterId, args.Id)
|
||||
shellutils.R(&StorageListOptions{}, "storage-list", "List storages", func(cli *zstack.SRegion, args *StorageListOptions) error {
|
||||
storages, err := cli.GetStorages(args.ZoneId, args.ClusterId, args.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
"yunion.io/x/onecloud/pkg/util/zstack"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type VipListOptions struct {
|
||||
VipId string
|
||||
}
|
||||
shellutils.R(&VipListOptions{}, "vip-list", "List vips", func(cli *zstack.SRegion, args *VipListOptions) error {
|
||||
vips, err := cli.GetVirtualIPs(args.VipId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(vips, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type VipCreateOptions struct {
|
||||
NAME string
|
||||
Desc string
|
||||
Ip string
|
||||
L3ID string
|
||||
}
|
||||
|
||||
shellutils.R(&VipCreateOptions{}, "vip-create", "Create vip", func(cli *zstack.SRegion, args *VipCreateOptions) error {
|
||||
vip, err := cli.CreateVirtualIP(args.NAME, args.Desc, args.Ip, args.L3ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(vip)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
@@ -76,20 +75,8 @@ func (snapshot *SSnapshot) IsEmulated() bool {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetSnapshot(snapshotId string) (*SSnapshot, error) {
|
||||
snapshots, err := region.GetSnapshots(snapshotId, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(snapshots) == 1 {
|
||||
if snapshots[0].UUID == snapshotId {
|
||||
return &snapshots[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(snapshots) == 0 || len(snapshotId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
snapshot := &SSnapshot{region: region}
|
||||
return snapshot, region.client.getResource("volume-snapshots", snapshotId, snapshot)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetSnapshots(snapshotId string, diskId string) ([]SSnapshot, error) {
|
||||
|
||||
+225
-12
@@ -1,35 +1,248 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type TStorageType string
|
||||
|
||||
type TCephPoolType string
|
||||
|
||||
const (
|
||||
StorageTypeCeph = TStorageType("Ceph")
|
||||
StorageTypeLocal = TStorageType("LocalStorage")
|
||||
StorageTypeVCenter = TStorageType("VCenter")
|
||||
|
||||
CephPoolTypeData = TCephPoolType("Data")
|
||||
CephPoolTypeRoot = TCephPoolType("Root")
|
||||
CephPoolTypeImageCache = TCephPoolType("ImageCache")
|
||||
)
|
||||
|
||||
type SPool struct {
|
||||
UUID string `json:"uuid"`
|
||||
PrimaryStorageUUID string `json:"primaryStorageUuid"`
|
||||
PoolName string `json:"poolName"`
|
||||
Type TCephPoolType `json:"type"`
|
||||
AvailableCapacity int64 `json:"availableCapacity"`
|
||||
UsedCapacity int64 `json:"usedCapacity"`
|
||||
ReplicatedSize int64 `json:"replicatedSize"`
|
||||
TotalCapacity int64 `json:"totalCapacity"`
|
||||
ZStackTime
|
||||
}
|
||||
|
||||
type SStorage struct {
|
||||
region *SRegion
|
||||
|
||||
ZStackBasic
|
||||
VCenterUUID string `json:"VCenterUuid"`
|
||||
Datastore string `json:"datastore"`
|
||||
ZoneUUID string `json:"zoneUuid"`
|
||||
URL string `json:"url"`
|
||||
TotalCapacity int64 `json:"totalCapacity"`
|
||||
AvailableCapacity int `json:"availableCapacity"`
|
||||
TotalPhysicalCapacity int `json:"totalPhysicalCapacity"`
|
||||
AvailablePhysicalCapacity int `json:"availablePhysicalCapacity"`
|
||||
Type TStorageType `json:"type"`
|
||||
State string `json:"state"`
|
||||
Status string `json:"status"`
|
||||
MountPath string `json:"mountPath"`
|
||||
AttachedClusterUUIDs []string `json:"attachedClusterUuids"`
|
||||
|
||||
Pools []SPool `json:"pools"`
|
||||
|
||||
ZStackTime
|
||||
}
|
||||
|
||||
func (region *SRegion) getIStorages(zondId string) ([]cloudprovider.ICloudStorage, error) {
|
||||
primaryStorages, err := region.GetPrimaryStorages(zondId, "", "")
|
||||
primaryStorages, err := region.GetStorages(zondId, "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
istorage := []cloudprovider.ICloudStorage{}
|
||||
for _, primaryStorage := range primaryStorages {
|
||||
zone, err := region.GetZone(primaryStorage.ZoneUUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(primaryStorages); i++ {
|
||||
primaryStorage := primaryStorages[i]
|
||||
switch primaryStorage.Type {
|
||||
case StorageTypeLocal:
|
||||
ilocalStorages, err := region.getILocalStorages(zone, primaryStorage.UUID, "")
|
||||
ilocalStorages, err := region.getILocalStorages(primaryStorage.UUID, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
istorage = append(istorage, ilocalStorages...)
|
||||
case StorageTypeCeph:
|
||||
icephStorage, err := region.getICephStorages(zone, primaryStorage.UUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
istorage = append(istorage, icephStorage...)
|
||||
primaryStorage.region = region
|
||||
istorage = append(istorage, &primaryStorage)
|
||||
case StorageTypeVCenter:
|
||||
}
|
||||
}
|
||||
return istorage, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetStorage(storageId string) (*SStorage, error) {
|
||||
if len(storageId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
storages, err := region.GetStorages("", "", storageId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(storages) == 1 && storages[0].UUID == storageId {
|
||||
storages[0].region = region
|
||||
return &storages[0], nil
|
||||
}
|
||||
if len(storages) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
}
|
||||
|
||||
func (region *SRegion) GetStorages(zoneId, clusterId, storageId string) ([]SStorage, error) {
|
||||
storages := []SStorage{}
|
||||
params := []string{}
|
||||
if len(zoneId) > 0 {
|
||||
params = append(params, "q=zone.uuid="+zoneId)
|
||||
}
|
||||
if len(clusterId) > 0 {
|
||||
params = append(params, "q=cluster.uuid="+clusterId)
|
||||
}
|
||||
if SkipEsxi {
|
||||
params = append(params, "q=type!=VCenter")
|
||||
}
|
||||
if len(storageId) > 0 {
|
||||
params = append(params, "q=uuid="+storageId)
|
||||
}
|
||||
return storages, region.client.listAll("primary-storage", params, &storages)
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetStatus() string {
|
||||
if storage.Status == "Connected" {
|
||||
return api.STORAGE_ONLINE
|
||||
}
|
||||
return api.STORAGE_OFFLINE
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetId() string {
|
||||
return storage.UUID
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetName() string {
|
||||
return storage.Name
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetGlobalId() string {
|
||||
return storage.GetId()
|
||||
}
|
||||
|
||||
func (storage *SStorage) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetIZone() cloudprovider.ICloudZone {
|
||||
zone, err := storage.region.GetZone(storage.ZoneUUID)
|
||||
if err != nil {
|
||||
log.Errorf("failed to find zone for storage %s(%s)", storage.Name, storage.UUID)
|
||||
return nil
|
||||
}
|
||||
return zone
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
disks, err := storage.region.GetDisks(storage.UUID, []string{}, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
idisks := []cloudprovider.ICloudDisk{}
|
||||
for i := 0; i < len(disks); i++ {
|
||||
disks[i].storage = storage
|
||||
disks[i].region = storage.region
|
||||
idisks = append(idisks, &disks[i])
|
||||
}
|
||||
return idisks, nil
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetStorageType() string {
|
||||
return strings.ToLower(string(storage.Type))
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetMediumType() string {
|
||||
return api.DISK_TYPE_ROTATE
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetCapacityMB() int64 {
|
||||
return storage.TotalCapacity / 1024 / 1024
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetStorageConf() jsonutils.JSONObject {
|
||||
conf := jsonutils.NewDict()
|
||||
return conf
|
||||
}
|
||||
|
||||
func (storage *SStorage) Refresh() error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
storage.region.GetIStoragecaches()
|
||||
return storage.region.storageCache
|
||||
}
|
||||
|
||||
func (storage *SStorage) CreateIDisk(name string, sizeGb int, desc string) (cloudprovider.ICloudDisk, error) {
|
||||
poolName, err := storage.GetDataPoolName()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disk, err := storage.region.CreateDisk(name, storage.UUID, "", poolName, sizeGb, desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disk.storage = storage
|
||||
return disk, nil
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetIDiskById(diskId string) (cloudprovider.ICloudDisk, error) {
|
||||
disk, err := storage.region.GetDisk(diskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if disk.PrimaryStorageUUID != storage.UUID {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
disk.region = storage.region
|
||||
disk.storage = storage
|
||||
return disk, nil
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetMountPoint() string {
|
||||
poolName, _ := storage.GetDataPoolName()
|
||||
if len(poolName) > 0 {
|
||||
return fmt.Sprintf("ceph://%s", poolName)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (storage *SStorage) IsSysDiskStore() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (storage *SStorage) GetDataPoolName() (string, error) {
|
||||
for _, pool := range storage.Pools {
|
||||
if pool.Type == CephPoolTypeData {
|
||||
return pool.PoolName, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("failed to found storage %s(%s) data pool name", storage.Name, storage.UUID)
|
||||
}
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type TCephPoolType string
|
||||
|
||||
const (
|
||||
CephPoolTypeData = TCephPoolType("Data")
|
||||
CephPoolTypeRoot = TCephPoolType("Root")
|
||||
CephPoolTypeImageCache = TCephPoolType("ImageCache")
|
||||
)
|
||||
|
||||
type SCephStorage struct {
|
||||
zone *SZone
|
||||
|
||||
UUID string `json:"uuid"`
|
||||
PrimaryStorageUUID string `json:"primaryStorageUuid"`
|
||||
PoolName string `json:"poolName"`
|
||||
Type TCephPoolType `json:"type"`
|
||||
AvailableCapacity int64 `json:"availableCapacity"`
|
||||
UsedCapacity int64 `json:"usedCapacity"`
|
||||
ReplicatedSize int64 `json:"replicatedSize"`
|
||||
TotalCapacity int64 `json:"totalCapacity"`
|
||||
ZStackTime
|
||||
}
|
||||
|
||||
func (region *SRegion) getICephStorages(zone *SZone, storageId string) ([]cloudprovider.ICloudStorage, error) {
|
||||
storage, err := region.GetPrimaryStorage(storageId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
istorages := []cloudprovider.ICloudStorage{}
|
||||
for i := 0; i < len(storage.Pools); i++ {
|
||||
storage.Pools[i].zone = zone
|
||||
istorages = append(istorages, &storage.Pools[i])
|
||||
}
|
||||
return istorages, nil
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", storage.PrimaryStorageUUID, storage.UUID)
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetName() string {
|
||||
primaryStorage, err := storage.zone.region.GetPrimaryStorage(storage.PrimaryStorageUUID)
|
||||
if err != nil {
|
||||
return "Unknown"
|
||||
}
|
||||
return fmt.Sprintf("%s/%s", primaryStorage.Name, storage.PoolName)
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetGlobalId() string {
|
||||
return storage.GetId()
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetIZone() cloudprovider.ICloudZone {
|
||||
return storage.zone
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
if storage.Type == CephPoolTypeImageCache {
|
||||
return []cloudprovider.ICloudDisk{}, nil
|
||||
}
|
||||
disks, err := storage.zone.region.GetDisks(storage.PrimaryStorageUUID, []string{}, string(storage.Type))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
idisks := []cloudprovider.ICloudDisk{}
|
||||
for i := 0; i < len(disks); i++ {
|
||||
disks[i].cephStorage = storage
|
||||
disks[i].region = storage.zone.region
|
||||
idisks = append(idisks, &disks[i])
|
||||
}
|
||||
return idisks, nil
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetStorageType() string {
|
||||
return strings.ToLower(string(storage.Type))
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetMediumType() string {
|
||||
return api.DISK_TYPE_ROTATE
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetCapacityMB() int64 {
|
||||
return storage.TotalCapacity / 1024 / 1024
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetStorageConf() jsonutils.JSONObject {
|
||||
conf := jsonutils.NewDict()
|
||||
return conf
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetManagerId() string {
|
||||
return storage.zone.region.client.providerID
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetStatus() string {
|
||||
primaryStorage, err := storage.zone.region.GetPrimaryStorage(storage.PrimaryStorageUUID)
|
||||
if err != nil {
|
||||
return api.STORAGE_OFFLINE
|
||||
}
|
||||
return primaryStorage.GetStatus()
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) Refresh() error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
storage.zone.region.GetIStoragecaches()
|
||||
return storage.zone.region.storageCache
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) CreateIDisk(name string, sizeGb int, desc string) (cloudprovider.ICloudDisk, error) {
|
||||
if storage.Type == CephPoolTypeData {
|
||||
disk, err := storage.zone.region.CreateDisk(name, storage.PrimaryStorageUUID, "", storage.PoolName, sizeGb, desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disk.cephStorage = storage
|
||||
return disk, nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetIDiskById(diskId string) (cloudprovider.ICloudDisk, error) {
|
||||
disks, err := storage.zone.region.GetDisks(storage.PrimaryStorageUUID, []string{diskId}, storage.PoolName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(disks) == 1 {
|
||||
if disks[0].UUID == diskId {
|
||||
disks[0].region = storage.zone.region
|
||||
disks[0].cephStorage = storage
|
||||
return &disks[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(disks) == 0 || len(diskId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) GetMountPoint() string {
|
||||
return "ceph://" + storage.PoolName
|
||||
}
|
||||
|
||||
func (storage *SCephStorage) IsSysDiskStore() bool {
|
||||
return storage.Type == CephPoolTypeRoot
|
||||
}
|
||||
@@ -5,12 +5,13 @@ import (
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SLocalStorage struct {
|
||||
zone *SZone
|
||||
region *SRegion
|
||||
|
||||
primaryStorageID string
|
||||
HostUUID string `json:"hostUuid"`
|
||||
@@ -48,19 +49,19 @@ func (region *SRegion) GetLocalStorages(storageId string, hostId string) ([]SLoc
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(localStorage); i++ {
|
||||
localStorage[i].region = region
|
||||
localStorage[i].primaryStorageID = storageId
|
||||
}
|
||||
return localStorage, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) getILocalStorages(zone *SZone, storageId, hostId string) ([]cloudprovider.ICloudStorage, error) {
|
||||
func (region *SRegion) getILocalStorages(storageId, hostId string) ([]cloudprovider.ICloudStorage, error) {
|
||||
storages, err := region.GetLocalStorages(storageId, hostId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
istorage := []cloudprovider.ICloudStorage{}
|
||||
for i := 0; i < len(storages); i++ {
|
||||
storages[i].zone = zone
|
||||
istorage = append(istorage, &storages[i])
|
||||
}
|
||||
return istorage, nil
|
||||
@@ -71,15 +72,15 @@ func (storage *SLocalStorage) GetMetadata() *jsonutils.JSONDict {
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", storage.primaryStorageID, storage.HostUUID)
|
||||
return storage.primaryStorageID
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) GetName() string {
|
||||
primaryStorage, err := storage.zone.region.GetPrimaryStorage(storage.primaryStorageID)
|
||||
primaryStorage, err := storage.region.GetStorage(storage.primaryStorageID)
|
||||
if err != nil {
|
||||
return "Unknown"
|
||||
}
|
||||
host, err := storage.zone.region.GetHost(storage.zone.UUID, storage.HostUUID)
|
||||
host, err := storage.region.GetHost(storage.HostUUID)
|
||||
if err != nil {
|
||||
return "Unknown"
|
||||
}
|
||||
@@ -87,7 +88,7 @@ func (storage *SLocalStorage) GetName() string {
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) GetGlobalId() string {
|
||||
return storage.GetId()
|
||||
return fmt.Sprintf("%s/%s", storage.primaryStorageID, storage.HostUUID)
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) IsEmulated() bool {
|
||||
@@ -95,11 +96,20 @@ func (storage *SLocalStorage) IsEmulated() bool {
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) GetIZone() cloudprovider.ICloudZone {
|
||||
return storage.zone
|
||||
host, err := storage.region.GetHost(storage.HostUUID)
|
||||
if err != nil {
|
||||
log.Errorf("failed get host info %s error: %v", storage.HostUUID, err)
|
||||
return nil
|
||||
}
|
||||
zone, err := storage.region.GetZone(host.ZoneUUID)
|
||||
if err != nil {
|
||||
log.Errorf("failed get zone info %s error: %v", host.ZoneUUID, err)
|
||||
}
|
||||
return zone
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
tags, err := storage.zone.region.GetSysTags("", "VolumeVO", "", "localStorage::hostUuid::"+storage.HostUUID)
|
||||
tags, err := storage.region.GetSysTags("", "VolumeVO", "", "localStorage::hostUuid::"+storage.HostUUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -107,14 +117,17 @@ func (storage *SLocalStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
for i := 0; i < len(tags); i++ {
|
||||
diskIds = append(diskIds, tags[i].ResourceUUID)
|
||||
}
|
||||
disks, err := storage.zone.region.GetDisks(storage.primaryStorageID, diskIds, "")
|
||||
idisks := []cloudprovider.ICloudDisk{}
|
||||
if len(diskIds) == 0 {
|
||||
return idisks, nil
|
||||
}
|
||||
disks, err := storage.region.GetDisks(storage.primaryStorageID, diskIds, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
idisks := []cloudprovider.ICloudDisk{}
|
||||
for i := 0; i < len(disks); i++ {
|
||||
disks[i].localStorage = storage
|
||||
disks[i].region = storage.zone.region
|
||||
disks[i].region = storage.region
|
||||
idisks = append(idisks, &disks[i])
|
||||
}
|
||||
return idisks, nil
|
||||
@@ -137,12 +150,8 @@ func (storage *SLocalStorage) GetStorageConf() jsonutils.JSONObject {
|
||||
return conf
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) GetManagerId() string {
|
||||
return storage.zone.region.client.providerID
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) GetStatus() string {
|
||||
primaryStorage, err := storage.zone.region.GetPrimaryStorage(storage.primaryStorageID)
|
||||
primaryStorage, err := storage.region.GetStorage(storage.primaryStorageID)
|
||||
if err != nil {
|
||||
return api.STORAGE_OFFLINE
|
||||
}
|
||||
@@ -159,12 +168,12 @@ func (storage *SLocalStorage) GetEnabled() bool {
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
storage.zone.region.GetIStoragecaches()
|
||||
return storage.zone.region.storageCache
|
||||
storage.region.GetIStoragecaches()
|
||||
return storage.region.storageCache
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) CreateIDisk(name string, sizeGb int, desc string) (cloudprovider.ICloudDisk, error) {
|
||||
disk, err := storage.zone.region.CreateDisk(name, storage.primaryStorageID, storage.HostUUID, "", sizeGb, desc)
|
||||
disk, err := storage.region.CreateDisk(name, storage.primaryStorageID, storage.HostUUID, "", sizeGb, desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -173,23 +182,16 @@ func (storage *SLocalStorage) CreateIDisk(name string, sizeGb int, desc string)
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) GetIDiskById(diskId string) (cloudprovider.ICloudDisk, error) {
|
||||
tags, err := storage.zone.region.GetSysTags("", "VolumeVO", diskId, "localStorage::hostUuid::"+storage.HostUUID)
|
||||
disk, err := storage.region.GetDisk(diskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(tags) == 1 {
|
||||
disk, err := storage.zone.region.GetDisk(diskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disk.localStorage = storage
|
||||
disk.region = storage.zone.region
|
||||
return disk, nil
|
||||
}
|
||||
if len(tags) == 0 || len(diskId) == 0 {
|
||||
if disk.PrimaryStorageUUID != storage.primaryStorageID {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
disk.localStorage = storage
|
||||
disk.region = storage.region
|
||||
return disk, nil
|
||||
}
|
||||
|
||||
func (storage *SLocalStorage) GetMountPoint() string {
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type TStorageType string
|
||||
|
||||
const (
|
||||
StorageTypeCeph = TStorageType("Ceph")
|
||||
StorageTypeLocal = TStorageType("LocalStorage")
|
||||
StorageTypeVCenter = TStorageType("VCenter")
|
||||
)
|
||||
|
||||
type SPrimaryStorage struct {
|
||||
zone *SZone
|
||||
|
||||
ZStackBasic
|
||||
VCenterUUID string `json:"VCenterUuid"`
|
||||
Datastore string `json:"datastore"`
|
||||
ZoneUUID string `json:"zoneUuid"`
|
||||
URL string `json:"url"`
|
||||
TotalCapacity int64 `json:"totalCapacity"`
|
||||
AvailableCapacity int `json:"availableCapacity"`
|
||||
TotalPhysicalCapacity int `json:"totalPhysicalCapacity"`
|
||||
AvailablePhysicalCapacity int `json:"availablePhysicalCapacity"`
|
||||
Type TStorageType `json:"type"`
|
||||
State string `json:"state"`
|
||||
Status string `json:"status"`
|
||||
MountPath string `json:"mountPath"`
|
||||
AttachedClusterUUIDs []string `json:"attachedClusterUuids"`
|
||||
|
||||
Pools []SCephStorage `json:"pools"`
|
||||
|
||||
ZStackTime
|
||||
}
|
||||
|
||||
func (region *SRegion) GetPrimaryStorage(storageId string) (*SPrimaryStorage, error) {
|
||||
storages, err := region.GetPrimaryStorages("", "", storageId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(storages) == 1 {
|
||||
if storages[0].UUID == storageId {
|
||||
return &storages[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(storages) == 0 || len(storageId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
}
|
||||
|
||||
func (region *SRegion) GetPrimaryStorages(zoneId, clusterId, storageId string) ([]SPrimaryStorage, error) {
|
||||
storages := []SPrimaryStorage{}
|
||||
params := []string{}
|
||||
if len(zoneId) > 0 {
|
||||
params = append(params, "q=zone.uuid="+zoneId)
|
||||
}
|
||||
if len(clusterId) > 0 {
|
||||
params = append(params, "q=cluster.uuid="+clusterId)
|
||||
}
|
||||
if SkipEsxi {
|
||||
params = append(params, "q=type!=VCenter")
|
||||
}
|
||||
if len(storageId) > 0 {
|
||||
params = append(params, "q=uuid="+storageId)
|
||||
}
|
||||
return storages, region.client.listAll("primary-storage", params, &storages)
|
||||
}
|
||||
|
||||
func (storage *SPrimaryStorage) GetStatus() string {
|
||||
if storage.Status == "Connected" {
|
||||
return api.STORAGE_ONLINE
|
||||
}
|
||||
return api.STORAGE_OFFLINE
|
||||
}
|
||||
@@ -3,10 +3,17 @@ package zstack
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/image/options"
|
||||
"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/qemuimg"
|
||||
)
|
||||
|
||||
type SStoragecache struct {
|
||||
@@ -41,10 +48,6 @@ func (scache *SStoragecache) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (scache *SStoragecache) GetManagerId() string {
|
||||
return scache.region.client.providerID
|
||||
}
|
||||
|
||||
func (scache *SStoragecache) GetIImages() ([]cloudprovider.ICloudImage, error) {
|
||||
images, err := scache.region.GetImages("")
|
||||
if err != nil {
|
||||
@@ -71,8 +74,45 @@ func (scache *SStoragecache) GetPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (scache *SStoragecache) UploadImage(ctx context.Context, userCred mcclient.TokenCredential, imageId string, osArch, osType, osDist, osVersion string, extId string, isForce bool) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
func (scache *SStoragecache) UploadImage(ctx context.Context, userCred mcclient.TokenCredential, image *cloudprovider.SImageCreateOption, isForce bool) (string, error) {
|
||||
if len(image.ExternalId) > 0 {
|
||||
log.Debugf("UploadImage: Image external ID exists %s", image.ExternalId)
|
||||
|
||||
img, err := scache.region.GetImage(image.ExternalId)
|
||||
if err != nil {
|
||||
log.Errorf("GetImageStatus error %s", err)
|
||||
}
|
||||
status := img.GetStatus()
|
||||
if api.CACHED_IMAGE_STATUS_READY == status && !isForce {
|
||||
return image.ExternalId, nil
|
||||
}
|
||||
log.Debugf("image %s status %s", image.ExternalId, status)
|
||||
} else {
|
||||
log.Debugf("UploadImage: no external ID")
|
||||
}
|
||||
|
||||
return scache.uploadImage(ctx, userCred, image, isForce)
|
||||
}
|
||||
|
||||
func (self *SStoragecache) uploadImage(ctx context.Context, userCred mcclient.TokenCredential, image *cloudprovider.SImageCreateOption, isForce bool) (string, error) {
|
||||
s := auth.GetAdminSession(ctx, options.Options.Region, "")
|
||||
|
||||
meta, reader, err := modules.Images.Download(s, image.ImageId, string(qemuimg.QCOW2), false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
log.Infof("meta data %s", meta)
|
||||
|
||||
size, _ := meta.Int("size")
|
||||
img, err := self.region.CreateImage(image.ImageName, string(qemuimg.QCOW2), image.OsType, "", reader, size)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = cloudprovider.WaitStatus(img, api.CACHED_IMAGE_STATUS_READY, time.Second*5, time.Minute*5)
|
||||
if err != nil {
|
||||
log.Errorf("waitting for image %s(%s) status ready timeout", img.Name, img.UUID)
|
||||
}
|
||||
return img.UUID, err
|
||||
}
|
||||
|
||||
func (scache *SStoragecache) CreateIImage(snapshoutId, imageName, osType, imageDesc string) (cloudprovider.ICloudImage, error) {
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
)
|
||||
|
||||
type SVirtualIP struct {
|
||||
ZStackBasic
|
||||
IPRangeUUID string `json:"ipRangeUuid"`
|
||||
L3NetworkUUID string `json:"l3NetworkUuid"`
|
||||
IP string `json:"ip"`
|
||||
State string `json:"state"`
|
||||
Gateway string `json:"gateway"`
|
||||
Netmask string `json:"netmask"`
|
||||
PrefixLen int `json:"prefixLen"`
|
||||
ServiceProvider string `json:"serviceProvider"`
|
||||
PeerL3NetworkUuids []string `json:"peerL3NetworkUuids"`
|
||||
UseFor string `json:"useFor"`
|
||||
UsedIPUUID string `json:"usedIpUuid"`
|
||||
ZStackTime
|
||||
}
|
||||
|
||||
func (region *SRegion) GetVirtualIP(vipId string) (*SVirtualIP, error) {
|
||||
vip := &SVirtualIP{}
|
||||
return vip, region.client.getResource("vips", vipId, vip)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetNetworkId(vip *SVirtualIP) string {
|
||||
networks, err := region.GetNetworks("", "", vip.L3NetworkUUID, "")
|
||||
if err == nil {
|
||||
for _, network := range networks {
|
||||
if network.Contains(vip.IP) {
|
||||
return fmt.Sprintf("%s/%s", vip.L3NetworkUUID, network.UUID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (region *SRegion) GetVirtualIPs(vipId string) ([]SVirtualIP, error) {
|
||||
vips := []SVirtualIP{}
|
||||
params := []string{}
|
||||
if len(vipId) > 0 {
|
||||
params = append(params, "q=uuid="+vipId)
|
||||
}
|
||||
return vips, region.client.listAll("vips", params, &vips)
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateVirtualIP(name, desc, ip string, l3Id string) (*SVirtualIP, error) {
|
||||
vip := SVirtualIP{}
|
||||
params := map[string]map[string]string{
|
||||
"params": {
|
||||
"name": name,
|
||||
"description": desc,
|
||||
"requiredIp": ip,
|
||||
"l3NetworkUuid": l3Id,
|
||||
},
|
||||
}
|
||||
resp, err := region.client.post("vips", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &vip, resp.Unmarshal(&vip, "inventory")
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteVirtualIP(vipId string) error {
|
||||
return region.client.delete("vips", vipId, "")
|
||||
}
|
||||
@@ -24,7 +24,7 @@ func (vpc *SVpc) GetId() string {
|
||||
}
|
||||
|
||||
func (vpc *SVpc) GetName() string {
|
||||
return DEFAULT_VPC_NAME
|
||||
return fmt.Sprintf("%s-VPC", vpc.region.client.providerName)
|
||||
}
|
||||
|
||||
func (vpc *SVpc) GetGlobalId() string {
|
||||
@@ -95,10 +95,6 @@ func (vpc *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (vpc *SVpc) GetManagerId() string {
|
||||
return vpc.region.client.providerID
|
||||
}
|
||||
|
||||
func (vpc *SVpc) Delete() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
+19
-16
@@ -1,6 +1,7 @@
|
||||
package zstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -22,20 +23,8 @@ type SWire struct {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetWire(wireId string) (*SWire, error) {
|
||||
wires, err := region.GetWires("", wireId, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(wires) == 1 {
|
||||
if wires[0].UUID == wireId {
|
||||
return &wires[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(wires) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
wire := &SWire{vpc: region.GetVpc()}
|
||||
return wire, region.client.getResource("l2-networks", wireId, wire)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetWires(zoneId string, wireId string, clusterId string) ([]SWire, error) {
|
||||
@@ -121,9 +110,23 @@ func (wire *SWire) GetBandwidth() int {
|
||||
}
|
||||
|
||||
func (wire *SWire) CreateINetwork(name string, cidr string, desc string) (cloudprovider.ICloudNetwork, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
network, err := wire.vpc.region.CreateNetwork(name, cidr, wire.UUID, desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
network.wire = wire
|
||||
return network, nil
|
||||
}
|
||||
|
||||
func (wire *SWire) GetINetworkById(netid string) (cloudprovider.ICloudNetwork, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
idInfo := strings.Split(netid, "/")
|
||||
if len(idInfo) == 2 {
|
||||
network, err := wire.vpc.region.GetNetwork(wire.ZoneUUID, wire.UUID, idInfo[0], idInfo[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
network.wire = wire
|
||||
return network, nil
|
||||
}
|
||||
return nil, fmt.Errorf("invalid netid %s", netid)
|
||||
}
|
||||
|
||||
+4
-33
@@ -85,43 +85,14 @@ func (zone *SZone) GetIStorageById(storageId string) (cloudprovider.ICloudStorag
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (region *SRegion) GetHosts(zoneId string, hostId string) ([]SHost, error) {
|
||||
hosts := []SHost{}
|
||||
params := []string{}
|
||||
if len(zoneId) > 0 {
|
||||
params = append(params, "q=zone.uuid="+zoneId)
|
||||
}
|
||||
if len(hostId) > 0 {
|
||||
params = append(params, "q=uuid="+hostId)
|
||||
}
|
||||
if SkipEsxi {
|
||||
params = append(params, "q=hypervisorType!=ESX")
|
||||
}
|
||||
return hosts, region.client.listAll("hosts", params, &hosts)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetHost(zoneId string, hostId string) (*SHost, error) {
|
||||
hosts, err := region.GetHosts(zoneId, hostId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(hosts) == 1 {
|
||||
if hosts[0].UUID == hostId {
|
||||
return &hosts[0], nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(hosts) == 0 || len(hostId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
}
|
||||
|
||||
func (zone *SZone) GetIHostById(hostId string) (cloudprovider.ICloudHost, error) {
|
||||
host, err := zone.region.GetHost(zone.UUID, hostId)
|
||||
host, err := zone.region.GetHost(hostId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if host.ZoneUUID != zone.UUID {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
host.zone = zone
|
||||
return host, nil
|
||||
}
|
||||
|
||||
@@ -141,6 +141,9 @@ func (cli *SZStackClient) _list(resource string, start int, limit int, params []
|
||||
}
|
||||
|
||||
func (cli *SZStackClient) getDeleteURL(resource, resourceId, deleteMode string) string {
|
||||
if len(resourceId) == 0 {
|
||||
return cli.authURL + fmt.Sprintf("/zstack/%s/%s", ZSTACK_API_VERSION, resource)
|
||||
}
|
||||
url := cli.authURL + fmt.Sprintf("/zstack/%s/%s/%s", ZSTACK_API_VERSION, resource, resourceId)
|
||||
if len(deleteMode) > 0 {
|
||||
url += "?deleteMode=" + deleteMode
|
||||
@@ -171,6 +174,12 @@ func (cli *SZStackClient) _delete(resource, resourceId, deleteMode string) (json
|
||||
}
|
||||
|
||||
func (cli *SZStackClient) getURL(resource, resourceId, spec string) string {
|
||||
if len(resourceId) == 0 {
|
||||
return cli.authURL + fmt.Sprintf("/zstack/%s/%s", ZSTACK_API_VERSION, resource)
|
||||
}
|
||||
if len(spec) == 0 {
|
||||
return cli.authURL + fmt.Sprintf("/zstack/%s/%s/%s", ZSTACK_API_VERSION, resource, resourceId)
|
||||
}
|
||||
return cli.authURL + fmt.Sprintf("/zstack/%s/%s/%s/%s", ZSTACK_API_VERSION, resource, resourceId, spec)
|
||||
}
|
||||
|
||||
@@ -199,6 +208,27 @@ func (cli *SZStackClient) _put(resource, resourceId string, params jsonutils.JSO
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (cli *SZStackClient) getResource(resource, resourceId string, retval interface{}) error {
|
||||
if len(resourceId) == 0 {
|
||||
return cloudprovider.ErrNotFound
|
||||
}
|
||||
resp, err := cli._get(resource, resourceId, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
inventories, err := resp.GetArray("inventories")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(inventories) == 1 {
|
||||
return inventories[0].Unmarshal(retval)
|
||||
}
|
||||
if len(inventories) == 0 {
|
||||
return cloudprovider.ErrNotFound
|
||||
}
|
||||
return cloudprovider.ErrDuplicateId
|
||||
}
|
||||
|
||||
func (cli *SZStackClient) get(resource, resourceId string, spec string) (jsonutils.JSONObject, error) {
|
||||
return cli._get(resource, resourceId, spec)
|
||||
}
|
||||
@@ -210,7 +240,25 @@ func (cli *SZStackClient) _get(resource, resourceId string, spec string) (jsonut
|
||||
header.Add("Authorization", "OAuth "+cli.sessionID)
|
||||
requestURL := cli.getURL(resource, resourceId, spec)
|
||||
_, resp, err := httputils.JSONRequest(client, context.Background(), "GET", requestURL, header, nil, cli.debug)
|
||||
return resp, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.Contains("location") {
|
||||
location, _ := resp.GetString("location")
|
||||
return cli.wait(client, header, "get", requestURL, jsonutils.NewDict(), location)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (cli *SZStackClient) create(resource string, params jsonutils.JSONObject, retval interface{}) error {
|
||||
resp, err := cli._post(resource, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if retval == nil {
|
||||
return nil
|
||||
}
|
||||
return resp.Unmarshal(retval, "inventory")
|
||||
}
|
||||
|
||||
func (cli *SZStackClient) post(resource string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
|
||||
@@ -12,7 +12,3 @@ type ZStackBasic struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
const (
|
||||
DEFAULT_VPC_NAME = "ZStackVPC"
|
||||
)
|
||||
|
||||
@@ -31,6 +31,7 @@ const (
|
||||
SPICE = "spice"
|
||||
WMKS = "wmks"
|
||||
VMRC = "vmrc"
|
||||
ZSTACK = "zstack"
|
||||
)
|
||||
|
||||
type RemoteConsoleInfo struct {
|
||||
@@ -108,7 +109,7 @@ func (info *RemoteConsoleInfo) GetConnectParams() (string, error) {
|
||||
return info.getAliyunURL()
|
||||
case QCLOUD:
|
||||
return info.getQcloudURL()
|
||||
case OPENSTACK, VMRC:
|
||||
case OPENSTACK, VMRC, ZSTACK:
|
||||
return info.Url, nil
|
||||
default:
|
||||
return "", fmt.Errorf("Can't convert protocol %s to connect params", info.Protocol)
|
||||
|
||||
Reference in New Issue
Block a user