ctyun sync

This commit is contained in:
TangBin
2019-10-30 19:06:36 +08:00
parent 074dbb6fc5
commit 273e372fb3
58 changed files with 5762 additions and 0 deletions
+34
View File
@@ -236,6 +236,17 @@ func init() {
return nil
})
R(&options.SCtyunCloudAccountCreateOptions{}, "cloud-account-create-ctyun", "Create a Ctyun cloud account", func(s *mcclient.ClientSession, args *options.SCtyunCloudAccountCreateOptions) error {
params := jsonutils.Marshal(args)
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("Ctyun"), "provider")
result, err := modules.Cloudaccounts.Create(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
type CloudaccountUpdateOptions struct {
ID string `help:"ID or Name of cloud account"`
Name string `help:"New name to update"`
@@ -413,6 +424,19 @@ func init() {
return nil
})
R(&options.SCtyunCloudAccountUpdateOptions{}, "cloud-account-update-ctyun", "update a Ctyun cloud account", func(s *mcclient.ClientSession, args *options.SCtyunCloudAccountUpdateOptions) error {
params := jsonutils.Marshal(args).(*jsonutils.JSONDict)
if params.Size() == 0 {
return InvalidUpdateError()
}
result, err := modules.Cloudaccounts.Update(s, args.ID, params)
if err != nil {
return err
}
printObject(result)
return nil
})
type CloudaccountShowOptions struct {
ID string `help:"ID or Name of cloud account"`
}
@@ -597,6 +621,16 @@ func init() {
return nil
})
R(&options.SCtyunCloudAccountUpdateCredentialOptions{}, "cloud-account-update-credential-ctyun", "Update credential of an Ctyun cloud account", func(s *mcclient.ClientSession, args *options.SCtyunCloudAccountUpdateCredentialOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "update-credential", params)
if err != nil {
return err
}
printObject(result)
return nil
})
type CloudaccountSyncOptions struct {
ID string `help:"ID or Name of cloud account"`
Force bool `help:"Force sync no matter what"`
+138
View File
@@ -0,0 +1,138 @@
// 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 main
import (
"fmt"
"os"
"yunion.io/x/structarg"
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
_ "yunion.io/x/onecloud/pkg/multicloud/ctyun/shell"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
type BaseOptions struct {
Help bool `help:"Show help" default:"false"`
Debug bool `help:"Show debug" default:"false"`
AccessKey string `help:"Access key" default:"$CTYUN_ACCESS_KEY"`
Secret string `help:"Secret" default:"$CTYUN_SECRET"`
RegionId string `help:"RegionId" default:"$CTYUN_REGION"`
SUBCOMMAND string `help:"ctyuncli subcommand" subcommand:"true"`
}
func getSubcommandParser() (*structarg.ArgumentParser, error) {
parse, e := structarg.NewArgumentParser(&BaseOptions{},
"ctyuncli",
"Command-line interface to ctyun API.",
`See "ctyuncli help COMMAND" for help on a specific command.`)
if e != nil {
return nil, e
}
subcmd := parse.GetSubcommand()
if subcmd == nil {
return nil, fmt.Errorf("No subcommand argument.")
}
type HelpOptions struct {
SUBCOMMAND string `help:"sub-command name"`
}
shellutils.R(&HelpOptions{}, "help", "Show help of a subcommand", func(args *HelpOptions) error {
helpstr, e := subcmd.SubHelpString(args.SUBCOMMAND)
if e != nil {
return e
} else {
fmt.Print(helpstr)
return nil
}
})
for _, v := range shellutils.CommandTable {
_, e := subcmd.AddSubParser(v.Options, v.Command, v.Desc, v.Callback)
if e != nil {
return nil, e
}
}
return parse, nil
}
func showErrorAndExit(e error) {
fmt.Fprintf(os.Stderr, "%s", e)
fmt.Fprintln(os.Stderr)
os.Exit(1)
}
func newClient(options *BaseOptions) (*ctyun.SRegion, error) {
if len(options.AccessKey) == 0 {
return nil, fmt.Errorf("Missing accessKey")
}
if len(options.Secret) == 0 {
return nil, fmt.Errorf("Missing secret")
}
cli, err := ctyun.NewSCtyunClient("", "", "",
options.AccessKey, options.Secret, options.Debug)
if err != nil {
return nil, err
}
region := cli.GetRegion(options.RegionId)
if region == nil {
return nil, fmt.Errorf("No such region %s", options.RegionId)
}
return region, nil
}
func main() {
parser, e := getSubcommandParser()
if e != nil {
showErrorAndExit(e)
}
e = parser.ParseArgs(os.Args[1:], false)
options := parser.Options().(*BaseOptions)
if options.Help {
fmt.Print(parser.HelpString())
} else {
subcmd := parser.GetSubcommand()
subparser := subcmd.GetSubParser()
if e != nil {
if subparser != nil {
fmt.Print(subparser.Usage())
} else {
fmt.Print(parser.Usage())
}
showErrorAndExit(e)
} else {
suboptions := subparser.Options()
if options.SUBCOMMAND == "help" {
e = subcmd.Invoke(suboptions)
} else {
var region *ctyun.SRegion
region, e = newClient(options)
if e != nil {
showErrorAndExit(e)
}
e = subcmd.Invoke(region, suboptions)
}
if e != nil {
showErrorAndExit(e)
}
}
}
}
+3
View File
@@ -40,6 +40,7 @@ const (
CLOUD_PROVIDER_UCLOUD = "Ucloud"
CLOUD_PROVIDER_ZSTACK = "ZStack"
CLOUD_PROVIDER_GOOGLE = "Google"
CLOUD_PROVIDER_CTYUN = "Ctyun"
CLOUD_PROVIDER_GENERICS3 = "S3"
CLOUD_PROVIDER_CEPH = "Ceph"
@@ -65,6 +66,7 @@ const (
CLOUD_ACCESS_ENV_AZURE_CHINA = CLOUD_PROVIDER_AZURE
CLOUD_ACCESS_ENV_HUAWEI_GLOBAL = CLOUD_PROVIDER_HUAWEI + "-int"
CLOUD_ACCESS_ENV_HUAWEI_CHINA = CLOUD_PROVIDER_HUAWEI
CLOUD_ACCESS_ENV_CTYUN_CHINA = CLOUD_PROVIDER_CTYUN
)
var (
@@ -84,6 +86,7 @@ var (
CLOUD_PROVIDER_UCLOUD,
CLOUD_PROVIDER_ZSTACK,
CLOUD_PROVIDER_GOOGLE,
CLOUD_PROVIDER_CTYUN,
}
)
+17
View File
@@ -37,6 +37,23 @@ const (
CITY_KAOHSIUNG = "Kaohsiung" //高雄市
CITY_CHENG_DU = "Chengdu" //成都
CITY_CHONG_QING = "Chongqing" //重庆
CITY_LAN_ZHOU = "Lanzhou" //兰州
CITY_TAI_YUAN = "Taiyuan" //太原
CITY_TIAN_JIN = "Tianjin" //天津
CITY_WU_LU_MU_QI = "Wulumuqi" //乌鲁木齐
CITY_NAN_NING = "Nanning" //南宁
CITY_ZHENG_ZHOU = "Zhengzhou" //郑州
CITY_KUN_MING = "Kunming" //昆明
CITY_XI_AN = "Xian" //西安
CITY_HAI_KOU = "Haikou" //海口
CITY_WU_HU = "Wuhu" //芜湖
CITY_FU_ZHOU = "Fuzhou" //福州
CITY_WU_HAN = "Wuhan" //武汉
CITY_CHANG_SHA = "Changsha" //长沙
CITY_SHU_ZHOU = "Shuzhou" //苏州
CITY_BAO_DING = "Baoding" //保定
CITY_NAN_JING = "Nanjing" //南京
CITY_FO_SHAN = "Foshan" //佛山
// 日本
CITY_TOKYO = "Tokyo" //东京
+5
View File
@@ -141,6 +141,7 @@ const (
HYPERVISOR_UCLOUD = "ucloud"
HYPERVISOR_ZSTACK = "zstack"
HYPERVISOR_GOOGLE = "google"
HYPERVISOR_CTYUN = "ctyun"
// HYPERVISOR_DEFAULT = HYPERVISOR_KVM
HYPERVISOR_DEFAULT = HYPERVISOR_KVM
@@ -163,6 +164,7 @@ var HYPERVISORS = []string{
HYPERVISOR_UCLOUD,
HYPERVISOR_ZSTACK,
HYPERVISOR_GOOGLE,
HYPERVISOR_CTYUN,
}
var ONECLOUD_HYPERVISORS = []string{
@@ -179,6 +181,7 @@ var PUBLIC_CLOUD_HYPERVISORS = []string{
HYPERVISOR_HUAWEI,
HYPERVISOR_UCLOUD,
HYPERVISOR_GOOGLE,
HYPERVISOR_CTYUN,
}
var PRIVATE_CLOUD_HYPERVISORS = []string{
@@ -202,6 +205,7 @@ var HYPERVISOR_HOSTTYPE = map[string]string{
HYPERVISOR_UCLOUD: HOST_TYPE_UCLOUD,
HYPERVISOR_ZSTACK: HOST_TYPE_ZSTACK,
HYPERVISOR_GOOGLE: HOST_TYPE_GOOGLE,
HYPERVISOR_CTYUN: HOST_TYPE_CTYUN,
}
var HOSTTYPE_HYPERVISOR = map[string]string{
@@ -218,6 +222,7 @@ var HOSTTYPE_HYPERVISOR = map[string]string{
HOST_TYPE_UCLOUD: HYPERVISOR_UCLOUD,
HOST_TYPE_ZSTACK: HYPERVISOR_ZSTACK,
HOST_TYPE_GOOGLE: HYPERVISOR_GOOGLE,
HOST_TYPE_CTYUN: HYPERVISOR_CTYUN,
}
const (
+2
View File
@@ -32,6 +32,7 @@ const (
HOST_TYPE_UCLOUD = "ucloud"
HOST_TYPE_ZSTACK = "zstack"
HOST_TYPE_GOOGLE = "google"
HOST_TYPE_CTYUN = "ctyun"
HOST_TYPE_DEFAULT = HOST_TYPE_HYPERVISOR
@@ -108,6 +109,7 @@ var HOST_TYPES = []string{
HOST_TYPE_OPENSTACK,
HOST_TYPE_UCLOUD,
HOST_TYPE_ZSTACK,
HOST_TYPE_CTYUN,
}
var NIC_TYPES = []string{NIC_TYPE_IPMI, NIC_TYPE_ADMIN}
+14
View File
@@ -1,3 +1,17 @@
// 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 compute
import "yunion.io/x/onecloud/pkg/apis"
+5
View File
@@ -75,6 +75,11 @@ const (
STORAGE_GOOGLE_LOCAL_STORAGE = "local-storage" //本地SSD暂存盘 (最多8个)
STORAGE_GOOGLE_PD_STANDARD = "pd-standard" //标准永久性磁盘
STORAGE_GOOGLE_PD_SSD = "pd-ssd" //SSD永久性磁盘
// ctyun storage type
STORAGE_CTYUN_SSD = "SSD" // 超高IO云硬盘
STORAGE_CTYUN_SAS = "SAS" // 高IO云硬盘
STORAGE_CTYUN_SATA = "SATA" // 普通IO云硬盘
)
const (
+14
View File
@@ -1,3 +1,17 @@
// 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 apis
type BaseListInput struct {
+104
View File
@@ -0,0 +1,104 @@
// 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 guestdrivers
import (
"fmt"
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
)
type SCtyunGuestDriver struct {
SManagedVirtualizedGuestDriver
}
func (self *SCtyunGuestDriver) GetHypervisor() string {
return api.HYPERVISOR_CTYUN
}
func (self *SCtyunGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_CTYUN
}
func (self *SCtyunGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PUBLIC_CLOUD,
api.CLOUD_PROVIDER_CTYUN,
}
}
func (self *SCtyunGuestDriver) GetDefaultSysDiskBackend() string {
return api.STORAGE_CTYUN_SAS
}
func (self *SCtyunGuestDriver) GetDeployStatus() ([]string, error) {
return []string{api.VM_READY, api.VM_RUNNING}, nil
}
func (self *SCtyunGuestDriver) GetMinimalSysDiskSizeGb() int {
return 10
}
func (self *SCtyunGuestDriver) GetGuestInitialStateAfterCreate() string {
return api.VM_RUNNING
}
func (self *SCtyunGuestDriver) GetDetachDiskStatus() ([]string, error) {
return []string{api.VM_READY, api.VM_RUNNING}, nil
}
func (self *SCtyunGuestDriver) GetAttachDiskStatus() ([]string, error) {
return []string{api.VM_READY, api.VM_RUNNING}, nil
}
func (self *SCtyunGuestDriver) GetChangeConfigStatus() ([]string, error) {
return []string{api.VM_READY}, nil
}
func (self *SCtyunGuestDriver) GetRebuildRootStatus() ([]string, error) {
return []string{api.VM_READY, api.VM_RUNNING}, nil
}
func (self *SCtyunGuestDriver) GetGuestInitialStateAfterRebuild() string {
return api.VM_RUNNING
}
func (self *SCtyunGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
if !utils.IsInStringArray(guest.Status, []string{api.VM_RUNNING, api.VM_READY}) {
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
}
if !utils.IsInStringArray(storage.StorageType, []string{api.STORAGE_CTYUN_SATA, api.STORAGE_CTYUN_SAS, api.STORAGE_CTYUN_SSD}) {
return fmt.Errorf("Cannot resize disk with unsupported volumes type %s", storage.StorageType)
}
return nil
}
func (self *SCtyunGuestDriver) GetLinuxDefaultAccount(desc cloudprovider.SManagedVMCreateConfig) string {
if desc.OsType == "Windows" {
return "Administrator"
}
return "root"
}
func init() {
driver := SCtyunGuestDriver{}
models.RegisterGuestDriver(&driver)
}
+65
View File
@@ -0,0 +1,65 @@
// 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 hostdrivers
import (
"context"
"fmt"
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SCtyunHostDriver struct {
SManagedVirtualizationHostDriver
}
func init() {
driver := SCtyunHostDriver{}
models.RegisterHostDriver(&driver)
}
func (self *SCtyunHostDriver) GetHostType() string {
return api.HOST_TYPE_CTYUN
}
func (self *SCtyunHostDriver) GetHypervisor() string {
return api.HYPERVISOR_CTYUN
}
// 系统盘必须至少40G
func (self *SCtyunHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
switch storage.StorageType {
case api.STORAGE_CTYUN_SSD, api.STORAGE_CTYUN_SATA, api.STORAGE_CTYUN_SAS:
if sizeGb < 10 || sizeGb > 32768 {
return fmt.Errorf("The %s disk size must be in the range of 10G ~ 32768GB", storage.StorageType)
}
default:
return fmt.Errorf("Not support create %s disk", storage.StorageType)
}
return nil
}
func (self *SCtyunHostDriver) ValidateResetDisk(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, guests []models.SGuest, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
if len(guests) >= 1 {
return nil, httperrors.NewBadRequestError("Disk must be dettached")
}
return data, nil
}
+51
View File
@@ -0,0 +1,51 @@
// 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/compute/models"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SCtyunRegionDriver struct {
SManagedVirtualizationRegionDriver
}
func init() {
driver := SCtyunRegionDriver{}
models.RegisterRegionDriver(&driver)
}
func (self *SCtyunRegionDriver) GetProvider() string {
return api.CLOUD_PROVIDER_CTYUN
}
func (self *SCtyunRegionDriver) 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 *SCtyunRegionDriver) 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 *SCtyunRegionDriver) 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())
}
@@ -1,3 +1,17 @@
// 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.
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,3 +1,17 @@
// 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.
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
+14
View File
@@ -1,3 +1,17 @@
// 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.
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
+14
View File
@@ -144,6 +144,11 @@ type SS3CloudAccountCreateOptions struct {
Endpoint string `help:"S3 endpoint" required:"true" positional:"true" json:"endpoint"`
}
type SCtyunCloudAccountCreateOptions struct {
SCloudAccountCreateBaseOptions
SAccessKeyCredentialWithEnvironment
}
// update credential options
type SCloudAccountUpdateCredentialBaseOptions struct {
@@ -200,6 +205,11 @@ type SS3CloudAccountUpdateCredentialOptions struct {
SAccessKeyCredential
}
type SCtyunCloudAccountUpdateCredentialOptions struct {
SCloudAccountUpdateCredentialBaseOptions
SAccessKeyCredential
}
// update
type SCloudAccountUpdateBaseOptions struct {
@@ -257,3 +267,7 @@ type SZStackCloudAccountUpdateOptions struct {
type SS3CloudAccountUpdateOptions struct {
SCloudAccountUpdateBaseOptions
}
type SCtyunCloudAccountUpdateOptions struct {
SCloudAccountUpdateBaseOptions
}
+289
View File
@@ -0,0 +1,289 @@
// 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 ctyun
import (
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/util/httputils"
)
const (
CTYUN_API_HOST = "https://api.ctyun.cn"
CLOUD_PROVIDER_CTYUN = api.CLOUD_PROVIDER_CTYUN
CLOUD_PROVIDER_CTYUN_CN = "天翼云"
CTYUN_DEFAULT_REGION = "cn-bj4"
CTYUN_API_VERSION = "2019-11-22"
)
type SCtyunClient struct {
httpClient *http.Client
debug bool
providerId string
providerName string
projectId string // 项目ID.
accessKey string
secret string
iregions []cloudprovider.ICloudRegion
}
func NewSCtyunClient(providerId string, providerName string, projectId string, accessKey string, secret string, debug bool) (*SCtyunClient, error) {
client := &SCtyunClient{httpClient: http.DefaultClient, providerId: providerId, providerName: providerName, projectId: projectId, accessKey: accessKey, secret: secret, debug: debug}
err := client.init()
if err != nil {
return nil, err
}
return client, nil
}
func (client *SCtyunClient) init() error {
err := client.fetchRegions()
if err != nil {
return err
}
return nil
}
func (client *SCtyunClient) fetchRegions() error {
resp, err := client.DoGet("/apiproxy/v3/order/getZoneConfig", map[string]string{})
if err != nil {
return err
}
zones := []SZone{}
err = resp.Unmarshal(&zones, "returnObj")
if err != nil {
return err
}
regionIds := []string{}
regions := map[string]SRegion{}
for i := range zones {
zone := zones[i]
if region, ok := regions[zone.RegionID]; !ok {
regionIds = append(regionIds, zone.RegionID)
region = SRegion{
client: client,
Description: zone.ZoneName,
ID: zone.RegionID,
ParentRegionID: zone.RegionID,
izones: []cloudprovider.ICloudZone{&zone},
}
zone.region = &region
zone.host = &SHost{projectId: client.projectId, zone: &zone}
regions[zone.RegionID] = region
} else {
zone.region = &region
zone.host = &SHost{projectId: client.projectId, zone: &zone}
region.izones = append(region.izones, &zone)
}
}
client.iregions = []cloudprovider.ICloudRegion{}
for k := range regions {
region := regions[k]
client.iregions = append(client.iregions, &region)
}
return nil
}
func (client *SCtyunClient) DoGet(apiName string, queries map[string]string) (jsonutils.JSONObject, error) {
return formRequest(client, httputils.GET, apiName, queries, nil)
}
func (client *SCtyunClient) DoPost(apiName string, params map[string]jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return formRequest(client, httputils.POST, apiName, nil, params)
}
func formRequest(client *SCtyunClient, method httputils.THttpMethod, apiName string, queries map[string]string, params map[string]jsonutils.JSONObject) (jsonutils.JSONObject, error) {
header := http.Header{}
// signer
{
content := []string{}
for k, v := range queries {
content = append(content, v)
header.Set(k, v)
}
for _, v := range params {
c, _ := v.GetString()
content = append(content, c)
}
// contentMd5 := fmt.Sprintf("%x", md5.Sum([]byte(strings.Join(content, "\n"))))
// contentMd5 = base64.StdEncoding.EncodeToString([]byte(contentMd5))
contentRaw := strings.Join(content, "\n")
contentMd5 := utils.GetMD5Base64([]byte(contentRaw))
// EEE, d MMM yyyy HH:mm:ss z
// Mon, 2 Jan 2006 15:04:05 MST
requestDate := time.Now().Format("Mon, 2 Jan 2006 15:04:05 MST")
hashMac := hmac.New(sha1.New, []byte(client.secret))
hashRawString := strings.Join([]string{contentMd5, requestDate, apiName}, "\n")
hashMac.Write([]byte(hashRawString))
hsum := base64.StdEncoding.EncodeToString(hashMac.Sum(nil))
header.Set("accessKey", client.accessKey)
header.Set("contentMD5", contentMd5)
header.Set("requestDate", requestDate)
header.Set("hmac", hsum)
// 平台类型,整数类型,取值范围:2或3,传2表示2.0自营资源,传3表示3.0合营资源,该参数不需要加密。
header.Set("platform", "3")
}
ioData := strings.NewReader("")
if method == httputils.GET {
for k, v := range queries {
header.Set(k, v)
}
} else {
datas := url.Values{}
for k, v := range params {
c, _ := v.GetString()
datas.Add(k, c)
}
ioData = strings.NewReader(datas.Encode())
}
header.Set("Content-Length", strconv.FormatInt(int64(ioData.Len()), 10))
header.Set("Content-Type", "application/x-www-form-urlencoded")
ctx := context.Background()
MAX_RETRY := 3
retry := 0
for retry < MAX_RETRY {
resp, err := httputils.Request(
client.httpClient,
ctx,
method,
CTYUN_API_HOST+apiName,
header,
ioData,
client.debug)
_, jsonResp, err := httputils.ParseJSONResponse(resp, err, client.debug)
if err == nil {
if code, _ := jsonResp.Int("statusCode"); code != 800 {
return nil, &httputils.JSONClientError{Code: 400, Details: jsonResp.String()}
}
return jsonResp, nil
}
switch e := err.(type) {
case *httputils.JSONClientError:
if e.Code >= 499 {
time.Sleep(3 * time.Second)
retry += 1
continue
} else {
return nil, err
}
default:
return nil, err
}
}
return nil, fmt.Errorf("timeout for request: %s", params)
}
func (self *SCtyunClient) GetIRegions() []cloudprovider.ICloudRegion {
return self.iregions
}
func (self *SCtyunClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
subAccounts := make([]cloudprovider.SSubAccount, 0)
for i := range self.iregions {
iregion := self.iregions[i]
s := cloudprovider.SSubAccount{
Name: fmt.Sprintf("%s-%s", self.providerName, iregion.GetId()),
State: api.CLOUD_PROVIDER_CONNECTED,
Account: fmt.Sprintf("%s/%s", self.accessKey, iregion.GetId()),
HealthStatus: api.CLOUD_PROVIDER_HEALTH_NORMAL,
}
subAccounts = append(subAccounts, s)
}
return subAccounts, nil
}
func (client *SCtyunClient) GetAccountId() string {
return client.accessKey
}
func (self *SCtyunClient) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
for i := 0; i < len(self.iregions); i += 1 {
if self.iregions[i].GetGlobalId() == id {
return self.iregions[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
func (self *SCtyunClient) GetIProjects() ([]cloudprovider.ICloudProject, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SCtyunClient) GetAccessEnv() string {
return api.CLOUD_ACCESS_ENV_CTYUN_CHINA
}
func (self *SCtyunClient) GetRegions() []SRegion {
regions := make([]SRegion, len(self.iregions))
for i := 0; i < len(regions); i += 1 {
region := self.iregions[i].(*SRegion)
regions[i] = *region
}
return regions
}
func (self *SCtyunClient) GetRegion(regionId string) *SRegion {
if len(regionId) == 0 {
regionId = CTYUN_DEFAULT_REGION
}
for i := 0; i < len(self.iregions); i += 1 {
if self.iregions[i].GetId() == regionId {
return self.iregions[i].(*SRegion)
}
}
return nil
}
+440
View File
@@ -0,0 +1,440 @@
// 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 ctyun
import (
"context"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
// http://ctyun-api-url/apiproxy/v3/ondemand/queryVolumes
type SDisk struct {
storage *SStorage
multicloud.SDisk
diskDetails *DiskDetails
ID string `json:"id"`
Status string `json:"status"`
Name string `json:"name"`
CreatedAt int64 `json:"created_at"`
UpdatedAt string `json:"updated_at"`
Multiattach bool `json:"multiattach"`
ReplicationStatus string `json:"replication_status"`
SizeGB int64 `json:"size"`
Metadata Metadata `json:"metadata"`
VolumeType string `json:"volume_type"`
UserID string `json:"user_id"`
Shareable bool `json:"shareable"`
Encrypted bool `json:"encrypted"`
Bootable string `json:"bootable"`
AvailabilityZone string `json:"availability_zone"`
Attachments []Attachment `json:"attachments"`
MasterOrderID string `json:"masterOrderId"`
IsSysVolume int `json:"isSysVolume"`
WorkOrderResourceID string `json:"workOrderResourceId"`
ExpireTime int64 `json:"expireTime"`
IsFreeze int64 `json:"isFreeze"`
}
type Attachment struct {
VolumeID string `json:"volume_id"`
AttachmentID string `json:"attachment_id"`
AttachedAt string `json:"attached_at"`
ServerID string `json:"server_id"`
Device string `json:"device"`
ID string `json:"id"`
}
type Metadata struct {
OrderID string `json:"orderID"`
AttachedMode string `json:"attached_mode"`
ResourceSpecCode string `json:"resourceSpecCode"`
ProductID string `json:"productID"`
Readonly string `json:"readonly"`
}
type DiskDetails struct {
ID string `json:"id"`
ResEbsID string `json:"resEbsId"`
Size int64 `json:"size"`
Name string `json:"name"`
RegionID string `json:"regionId"`
AccountID string `json:"accountId"`
UserID string `json:"userId"`
HostID string `json:"hostId"`
OrderID string `json:"orderId"`
Status int64 `json:"status"`
Type string `json:"type"`
VolumeStatus int64 `json:"volumeStatus"`
CreateDate int64 `json:"createDate"`
DueDate int64 `json:"dueDate"`
ZoneID string `json:"zoneId"`
ZoneName string `json:"zoneName"`
IsSysVolume int64 `json:"isSysVolume"`
IsPackaged int64 `json:"isPackaged"`
WorkOrderResourceID string `json:"workOrderResourceId"`
IsFreeze int64 `json:"isFreeze"`
}
func (self *SDisk) GetBillingType() string {
if self.ExpireTime > 0 {
return billing_api.BILLING_TYPE_PREPAID
}
return billing_api.BILLING_TYPE_POSTPAID
}
func (self *SDisk) GetCreatedAt() time.Time {
return time.Unix(self.CreatedAt/1000, 0)
}
func (self *SDisk) GetExpiredAt() time.Time {
return time.Unix(self.ExpireTime/1000, 0)
}
func (self *SDisk) GetId() string {
return self.ID
}
func (self *SDisk) GetName() string {
if len(self.Name) > 0 {
return self.Name
}
return self.ID
}
func (self *SDisk) GetGlobalId() string {
return self.GetId()
}
func (self *SDisk) GetStatus() string {
switch self.Status {
case "creating", "downloading":
return api.DISK_ALLOCATING
case "available", "in-use":
return api.DISK_READY
case "error":
return api.DISK_ALLOC_FAILED
case "attaching":
return api.DISK_ATTACHING
case "detaching":
return api.DISK_DETACHING
case "restoring-backup":
return api.DISK_REBUILD
case "backing-up":
return api.DISK_BACKUP_STARTALLOC
case "error_restoring":
return api.DISK_BACKUP_ALLOC_FAILED
case "uploading":
return api.DISK_SAVING
case "extending":
return api.DISK_RESIZING
case "error_extending":
return api.DISK_ALLOC_FAILED
case "deleting":
return api.DISK_DEALLOC
case "error_deleting":
return api.DISK_DEALLOC_FAILED
case "rollbacking":
return api.DISK_REBUILD
case "error_rollbacking":
return api.DISK_UNKNOWN
default:
return api.DISK_UNKNOWN
}
}
func (self *SDisk) Refresh() error {
new, err := self.storage.zone.region.GetDisk(self.GetId())
if err != nil {
return err
}
return jsonutils.Update(self, new)
}
func (self *SDisk) IsEmulated() bool {
return false
}
func (self *SDisk) GetMetadata() *jsonutils.JSONDict {
data := jsonutils.NewDict()
data.Add(jsonutils.NewString(api.HYPERVISOR_CTYUN), "hypervisor")
return data
}
func (self *SDisk) GetProjectId() string {
return ""
}
func (self *SDisk) GetIStorage() (cloudprovider.ICloudStorage, error) {
return self.storage, nil
}
func (self *SDisk) GetIStorageId() string {
return self.storage.GetId()
}
func (self *SDisk) GetDiskFormat() string {
return "vhd"
}
func (self *SDisk) GetDiskSizeMB() int {
return int(self.SizeGB * 1024)
}
func (self *SDisk) GetIsAutoDelete() bool {
if len(self.Attachments) == 0 {
return false
}
if self.Bootable == "true" {
return true
}
return false
}
func (self *SDisk) GetTemplateId() string {
return ""
}
func (self *SDisk) GetDiskType() string {
if self.Bootable == "true" {
return api.DISK_TYPE_SYS
} else {
return api.DISK_TYPE_DATA
}
}
func (self *SDisk) GetFsFormat() string {
return ""
}
func (self *SDisk) GetIsNonPersistent() bool {
return false
}
func (self *SDisk) GetDriver() string {
return "scsi"
}
func (self *SDisk) GetCacheMode() string {
return "none"
}
func (self *SDisk) GetMountpoint() string {
if len(self.Attachments) > 0 {
return self.Attachments[0].Device
}
return ""
}
func (self *SDisk) GetAccessPath() string {
return ""
}
func (self *SDisk) Delete(ctx context.Context) error {
return cloudprovider.ErrNotImplemented
}
func (self *SDisk) CreateISnapshot(ctx context.Context, name string, desc string) (cloudprovider.ICloudSnapshot, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SDisk) GetISnapshot(idStr string) (cloudprovider.ICloudSnapshot, error) {
return self.storage.zone.region.GetSnapshot(self.GetId(), idStr)
}
// GET http://ctyun-api-url/apiproxy/v3/ondemand/queryVBSs
func (self *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
snapshots, err := self.storage.zone.region.GetSnapshots(self.GetId())
if err != nil {
return nil, errors.Wrap(err, "SDisk.GetISnapshots")
}
isnapshots := []cloudprovider.ICloudSnapshot{}
for i := range snapshots {
isnapshots[i] = &snapshots[i]
}
return isnapshots, nil
}
// POST http://ctyun-api-url/apiproxy/v3/ondemand/updateDiskBackupPolicy
func (self *SDisk) GetExtSnapshotPolicyIds() ([]string, error) {
return []string{}, nil
}
func (self *SDisk) Resize(ctx context.Context, newSizeMB int64) error {
return cloudprovider.ErrNotImplemented
}
func (self *SDisk) Reset(ctx context.Context, snapshotId string) (string, error) {
return "", cloudprovider.ErrNotImplemented
}
func (self *SDisk) Rebuild(ctx context.Context) error {
return cloudprovider.ErrNotImplemented
}
func (self *SDisk) GetDiskDetails() (*DiskDetails, error) {
if self.diskDetails != nil {
return self.diskDetails, nil
}
details, err := self.storage.zone.region.GetDiskDetailByDiskId(self.GetId())
if err != nil {
return nil, errors.Wrap(err, "SDisk.GetDiskDetails.GetDiskDetailByDiskId")
}
self.diskDetails = details
return self.diskDetails, nil
}
func (self *SRegion) GetDisks() ([]SDisk, error) {
params := map[string]string{
"regionId": self.GetId(),
}
resp, err := self.client.DoGet("/apiproxy/v3/ondemand/queryVolumes", params)
if err != nil {
return nil, errors.Wrap(err, "Region.GetDisks.DoGet")
}
disks := make([]SDisk, 0)
err = resp.Unmarshal(&disks, "returnObj", "volumes")
if err != nil {
return nil, errors.Wrap(err, "Region.GetDisks.Unmarshal")
}
for i := range disks {
izone, err := self.GetIZoneById(disks[i].AvailabilityZone)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetDisk.GetIZoneById")
}
disks[i].storage = &SStorage{
zone: izone.(*SZone),
storageType: disks[i].VolumeType,
}
}
return disks, nil
}
func (self *SRegion) GetDisk(diskId string) (*SDisk, error) {
params := map[string]string{
"regionId": self.GetId(),
"volumeId": diskId,
}
resp, err := self.client.DoGet("/apiproxy/v3/ondemand/queryVolumes", params)
if err != nil {
return nil, errors.Wrap(err, "Region.GetDisks.DoGet")
}
disks := make([]SDisk, 0)
err = resp.Unmarshal(&disks, "returnObj", "volumes")
if err != nil {
return nil, errors.Wrap(err, "Region.GetDisks.Unmarshal")
}
if len(disks) == 0 {
return nil, errors.Wrap(cloudprovider.ErrNotFound, "SRegion.GetDisk")
} else if len(disks) == 1 {
izone, err := self.GetIZoneById(disks[0].AvailabilityZone)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetDisk.GetIZoneById")
}
disks[0].storage = &SStorage{
zone: izone.(*SZone),
storageType: disks[0].VolumeType,
}
return &disks[0], nil
} else {
return nil, errors.Wrap(cloudprovider.ErrDuplicateId, "SRegion.GetDisk")
}
}
func (self *SRegion) GetDiskDetailByDiskId(diskId string) (*DiskDetails, error) {
params := map[string]string{
"volumeId": diskId,
"regionId": self.GetId(),
}
resp, err := self.client.DoGet("/apiproxy/v3/queryDataDiskDetail", params)
if err != nil {
return nil, errors.Wrap(err, "Region.GetDiskDetailByDiskId.DoGet")
}
disk := &DiskDetails{}
err = resp.Unmarshal(disk, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "Region.GetDiskDetailByDiskId.Unmarshal")
}
return disk, nil
}
func (self *SRegion) CreateDisk(zoneId, name, diskType, size string) (*SDisk, error) {
diskParams := jsonutils.NewDict()
diskParams.Set("regionId", jsonutils.NewString(self.GetId()))
diskParams.Set("zoneId", jsonutils.NewString(zoneId))
diskParams.Set("name", jsonutils.NewString(name))
diskParams.Set("type", jsonutils.NewString(diskType))
diskParams.Set("size", jsonutils.NewString(size))
diskParams.Set("count", jsonutils.NewString("1"))
params := map[string]jsonutils.JSONObject{
"createVolumeInfo": diskParams,
}
resp, err := self.client.DoPost("/apiproxy/v3/ondemand/createVolume", params)
if err != nil {
return nil, errors.Wrap(err, "Region.CreateDisk.DoPost")
}
disk := &SDisk{}
err = resp.Unmarshal(disk)
if err != nil {
return nil, errors.Wrap(err, "Region.CreateDisk.Unmarshal")
}
izone, err := self.GetIZoneById(disk.AvailabilityZone)
if err != nil {
return nil, errors.Wrap(err, "SRegion.CreateDisk.GetIZoneById")
}
disk.storage = &SStorage{
zone: izone.(*SZone),
storageType: disk.VolumeType,
}
return disk, nil
}
+214
View File
@@ -0,0 +1,214 @@
// 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 ctyun
import (
"strconv"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SDiskBacupPolicy struct {
region *SRegion
PolicyResourceCount int64 `json:"policy_resource_count"`
BackupPolicyName string `json:"backup_policy_name"`
ScheduledPolicy ScheduledPolicy `json:"scheduled_policy"`
BackupPolicyID string `json:"backup_policy_id"`
}
type ScheduledPolicy struct {
RententionNum int `json:"rentention_num"`
StartTime string `json:"start_time"`
Status string `json:"status"`
RemainFirstBackupOfCurMonth string `json:"remain_first_backup_of_curMonth"`
Frequency int `json:"frequency"`
}
func (self *SDiskBacupPolicy) GetId() string {
return self.BackupPolicyID
}
func (self *SDiskBacupPolicy) GetName() string {
return self.BackupPolicyName
}
func (self *SDiskBacupPolicy) GetGlobalId() string {
return self.GetId()
}
func (self *SDiskBacupPolicy) GetStatus() string {
if self.ScheduledPolicy.Status == "ON" || self.ScheduledPolicy.Status == "OFF" {
return api.SNAPSHOT_POLICY_READY
}
return api.SNAPSHOT_POLICY_UNKNOWN
}
func (self *SDiskBacupPolicy) Refresh() error {
policy, err := self.region.GetDiskBackupPolicy(self.GetId())
if err != nil {
return errors.Wrap(err, "SDiskBacupPolicy.Refresh")
}
err = jsonutils.Update(self, policy)
if err != nil {
return errors.Wrap(err, "SDiskBacupPolicy.Refresh.Update")
}
return nil
}
func (self *SDiskBacupPolicy) IsEmulated() bool {
return false
}
func (self *SDiskBacupPolicy) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SDiskBacupPolicy) GetProjectId() string {
return ""
}
func (self *SDiskBacupPolicy) IsActivated() bool {
if self.ScheduledPolicy.Status == "ON" {
return true
}
return false
}
func (self *SDiskBacupPolicy) GetRetentionDays() int {
return self.ScheduledPolicy.RententionNum
}
func (self *SDiskBacupPolicy) GetRepeatWeekdays() ([]int, error) {
return []int{self.ScheduledPolicy.Frequency}, nil
}
func (self *SDiskBacupPolicy) GetTimePoints() ([]int, error) {
ret, err := strconv.Atoi(self.ScheduledPolicy.StartTime[0:2])
return []int{ret}, err
}
func (self *SRegion) GetDiskBackupPolices() ([]SDiskBacupPolicy, error) {
params := map[string]string{
"regionId": self.GetId(),
}
resp, err := self.client.DoGet("/apiproxy/v3/ondemand/queryDiskBackupPolicys", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetDiskBackupPolices.DoGet")
}
ret := make([]SDiskBacupPolicy, 0)
err = resp.Unmarshal(&ret, "returnObj", "backup_policies")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetDiskBackupPolices.Unmarshal")
}
for i := range ret {
ret[i].region = self
}
return ret, nil
}
func (self *SRegion) GetDiskBackupPolicy(policyId string) (*SDiskBacupPolicy, error) {
polices, err := self.GetDiskBackupPolices()
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetDiskBackupPolicy.GetDiskBackupPolices")
}
for i := range polices {
policy := polices[i]
if policy.BackupPolicyID == policyId {
return &policy, nil
}
}
return nil, errors.Wrap(cloudprovider.ErrNotFound, "SRegion.GetDiskBackupPolicy")
}
func (self *SRegion) CreateDiskBackupPolicy(name, startTime, frequency, rententionNum, firstBackup, status string) error {
policyParams := jsonutils.NewDict()
policyParams.Set("policyName", jsonutils.NewString(name))
scheduleParams := jsonutils.NewDict()
scheduleParams.Set("startTime", jsonutils.NewString(startTime))
scheduleParams.Set("frequency", jsonutils.NewString(frequency))
scheduleParams.Set("rententionNum", jsonutils.NewString(rententionNum))
scheduleParams.Set("firstBackup", jsonutils.NewString(firstBackup))
scheduleParams.Set("status", jsonutils.NewString(status))
policyParams.Set("scheduledPolicy", scheduleParams)
params := map[string]jsonutils.JSONObject{
"regionId": jsonutils.NewString(self.GetId()),
"jsonStr": policyParams,
}
_, err := self.client.DoPost("/apiproxy/v3/ondemand/createDiskBackupPolicy", params)
if err != nil {
return errors.Wrap(err, "SRegion.CreateDiskBackupPolicy.DoPost")
}
return nil
}
func (self *SRegion) BindingDiskBackupPolicy(policyId, resourceId, resourceType string) error {
policyParams := jsonutils.NewDict()
policyParams.Set("policyId", jsonutils.NewString(policyId))
resourcesParams := jsonutils.NewArray()
resourcesParam := jsonutils.NewDict()
resourcesParam.Set("resourceId", jsonutils.NewString(resourceId))
resourcesParam.Set("resourceType", jsonutils.NewString(resourceType))
resourcesParams.Add(resourcesParam)
policyParams.Set("resources", resourcesParams)
params := map[string]jsonutils.JSONObject{
"regionId": jsonutils.NewString(self.GetId()),
"jsonStr": policyParams,
}
_, err := self.client.DoPost("/apiproxy/v3/ondemand/bindResourceToPolicy", params)
if err != nil {
return errors.Wrap(err, "SRegion.BindingDiskBackupPolicy.DoPost")
}
return nil
}
func (self *SRegion) UnBindDiskBackupPolicy(policyId, resourceId string) error {
resourcesParams := jsonutils.NewArray()
resourcesParam := jsonutils.NewDict()
resourcesParam.Set("resource_id", jsonutils.NewString(resourceId))
resourcesParams.Add(resourcesParam)
params := map[string]jsonutils.JSONObject{
"regionId": jsonutils.NewString(self.GetId()),
"jsonStr": resourcesParams,
"policyId": jsonutils.NewString(policyId),
}
_, err := self.client.DoPost("/apiproxy/v3/ondemand/unBindResourceToPolicy", params)
if err != nil {
return errors.Wrap(err, "SRegion.UnBindDiskBackupPolicy.DoPost")
}
return nil
}
+1
View File
@@ -0,0 +1 @@
package ctyun // import "yunion.io/x/onecloud/pkg/multicloud/ctyun"
+264
View File
@@ -0,0 +1,264 @@
// 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 ctyun
import (
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SEip struct {
region *SRegion
IPVersion int64 `json:"ip_version"`
BandwidthShareType string `json:"bandwidth_share_type"`
Type string `json:"type"`
PrivateIPAddress string `json:"private_ip_address"`
EnterpriseProjectID string `json:"enterprise_project_id"`
Status string `json:"status"`
PublicIPAddress string `json:"public_ip_address"`
ID string `json:"id"`
TenantID string `json:"tenant_id"`
Profile Profile `json:"profile"`
BandwidthName string `json:"bandwidth_name"`
BandwidthID string `json:"bandwidth_id"`
PortID string `json:"port_id"`
BandwidthSize int `json:"bandwidth_size"`
CreateTime int64 `json:"create_time"`
MasterOrderID string `json:"masterOrderId"`
WorkOrderResourceID string `json:"workOrderResourceId"`
ExpireTime int64 `json:"expireTime"`
IsFreeze int64 `json:"isFreeze"`
}
func (self *SEip) GetBillingType() string {
if len(self.MasterOrderID) > 0 {
return billing_api.BILLING_TYPE_PREPAID
} else {
return billing_api.BILLING_TYPE_POSTPAID
}
}
func (self *SEip) GetCreatedAt() time.Time {
return time.Unix(self.CreateTime/1000, 0)
}
func (self *SEip) GetExpiredAt() time.Time {
return time.Unix(self.ExpireTime/1000, 0)
}
func (self *SEip) GetId() string {
return self.ID
}
func (self *SEip) GetName() string {
return self.BandwidthName
}
func (self *SEip) GetGlobalId() string {
return self.GetId()
}
func (self *SEip) GetStatus() string {
switch self.Status {
case "bind", "unbind":
return api.EIP_STATUS_READY
case "binding":
return api.EIP_STATUS_ALLOCATE
case "error":
return api.EIP_STATUS_ALLOCATE_FAIL
case "unbinding":
return api.EIP_STATUS_DEALLOCATE
default:
return api.EIP_STATUS_UNKNOWN
}
}
func (self *SEip) Refresh() error {
if self.IsEmulated() {
return nil
}
new, err := self.region.GetEip(self.ID)
if err != nil {
return err
}
return jsonutils.Update(self, new)
}
func (self *SEip) IsEmulated() bool {
return false
}
func (self *SEip) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SEip) GetProjectId() string {
return ""
}
func (self *SEip) GetIpAddr() string {
return self.PublicIPAddress
}
func (self *SEip) GetMode() string {
return api.EIP_MODE_STANDALONE_EIP
}
func (self *SEip) GetINetworkId() string {
return ""
}
func (self *SEip) GetAssociationType() string {
orders, err := self.region.GetOrder(self.WorkOrderResourceID)
if err != nil {
log.Errorf("SEip.GetAssociationType %s", err)
return ""
}
for i := range orders {
order := orders[i]
if strings.Contains(order.ResourceType, "LOADBALANCER") {
return api.EIP_ASSOCIATE_TYPE_ELB
} else {
return api.EIP_ASSOCIATE_TYPE_SERVER
}
}
return ""
}
func (self *SEip) GetAssociationExternalId() string {
return self.WorkOrderResourceID
}
// http://ctyun-api-url/apiproxy/v3/queryNetworkDetail
func (self *SEip) GetBandwidth() int {
return self.BandwidthSize
}
func (self *SEip) GetInternetChargeType() string {
// todo: fix me
return api.EIP_CHARGE_TYPE_BY_BANDWIDTH
}
func (self *SEip) Delete() error {
return cloudprovider.ErrNotImplemented
}
func (self *SEip) Associate(instanceId string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SEip) Dissociate() error {
return cloudprovider.ErrNotImplemented
}
func (self *SEip) ChangeBandwidth(bw int) error {
return cloudprovider.ErrNotImplemented
}
type Profile struct {
OrderID string `json:"order_id"`
RegionID string `json:"region_id"`
UserID string `json:"user_id"`
ProductID string `json:"product_id"`
}
func (self *SRegion) GetEips() ([]SEip, error) {
params := map[string]string{
"regionId": self.GetId(),
}
eips := make([]SEip, 0)
resp, err := self.client.DoGet("/apiproxy/v3/ondemand/queryIps", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetEips.DoGet")
}
err = resp.Unmarshal(&eips, "returnObj", "publicips")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetEips.Unmarshal")
}
for i := range eips {
eips[i].region = self
}
return eips, nil
}
func (self *SRegion) GetEip(eipId string) (*SEip, error) {
params := map[string]string{
"regionId": self.GetId(),
"publicIpId": eipId,
}
eips := make([]SEip, 0)
resp, err := self.client.DoGet("/apiproxy/v3/ondemand/queryIps", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetEip.DoGet")
}
err = resp.Unmarshal(&eips, "returnObj", "publicips")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetEip.Unmarshal")
}
if len(eips) == 0 {
return nil, errors.Wrap(cloudprovider.ErrNotFound, "SRegion.GetEip")
} else if len(eips) == 1 {
eips[0].region = self
return &eips[0], nil
} else {
return nil, errors.Wrap(cloudprovider.ErrDuplicateId, "SRegion.GetEip")
}
}
func (self *SRegion) CreateEip(zoneId, name, size, shareType string) (*SEip, error) {
eipParams := jsonutils.NewDict()
eipParams.Set("regionId", jsonutils.NewString(self.GetId()))
eipParams.Set("zoneId", jsonutils.NewString(zoneId))
eipParams.Set("name", jsonutils.NewString(name))
eipParams.Set("type", jsonutils.NewString("5_telcom"))
eipParams.Set("size", jsonutils.NewString(size))
eipParams.Set("shareType", jsonutils.NewString(shareType))
params := map[string]jsonutils.JSONObject{
"createIpInfo": eipParams,
}
eip := &SEip{}
resp, err := self.client.DoPost("/apiproxy/v3/ondemand/createIp", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.CreateEip.DoPost")
}
err = resp.Unmarshal(eip, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.CreateEip.Unmarshal")
}
eip.region = self
return eip, nil
}
+231
View File
@@ -0,0 +1,231 @@
// 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 ctyun
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SHost struct {
multicloud.SHostBase
zone *SZone
projectId string
}
func (self *SHost) GetId() string {
return fmt.Sprintf("%s-%s", self.zone.region.client.providerId, self.zone.GetId())
}
func (self *SHost) GetName() string {
return fmt.Sprintf("%s-%s", self.zone.region.client.providerName, self.zone.GetId())
}
func (self *SHost) GetGlobalId() string {
return self.GetId()
}
func (self *SHost) GetStatus() string {
return api.HOST_STATUS_RUNNING
}
func (self *SHost) Refresh() error {
return nil
}
func (self *SHost) IsEmulated() bool {
return true
}
func (self *SHost) GetMetadata() *jsonutils.JSONDict {
return nil
}
// http://ctyun-api-url/apiproxy/v3/ondemand/queryVMs
func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
vms, err := self.zone.region.GetVMs()
if err != nil {
return nil, errors.Wrap(err, "SHost.GetVMs")
}
ivms := make([]cloudprovider.ICloudVM, len(vms))
for i := range vms {
ivms[i] = &vms[i]
}
return ivms, nil
}
// http://ctyun-api-url/apiproxy/v3/ondemand/queryVMDetail
// http://ctyun-api-url/apiproxy/v3/queryVMDetail
func (self *SHost) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
return self.zone.region.GetIVMById(id)
}
func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) {
return self.zone.GetIWires()
}
func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
return self.zone.GetIStorages()
}
func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
return self.zone.GetIStorageById(id)
}
func (self *SHost) GetEnabled() bool {
return true
}
func (self *SHost) GetHostStatus() string {
return api.HOST_ONLINE
}
func (self *SHost) GetAccessIp() string {
return ""
}
func (self *SHost) GetAccessMac() string {
return ""
}
func (self *SHost) GetSysInfo() jsonutils.JSONObject {
info := jsonutils.NewDict()
info.Add(jsonutils.NewString(api.CLOUD_PROVIDER_CTYUN), "manufacture")
return info
}
func (self *SHost) GetSN() string {
return ""
}
func (self *SHost) GetCpuCount() int {
return 0
}
func (self *SHost) GetNodeCount() int8 {
return 0
}
func (self *SHost) GetCpuDesc() string {
return ""
}
func (self *SHost) GetCpuMhz() int {
return 0
}
func (self *SHost) GetMemSizeMB() int {
return 0
}
func (self *SHost) GetStorageSizeMB() int {
return 0
}
func (self *SHost) GetStorageType() string {
return api.DISK_TYPE_HYBRID
}
func (self *SHost) GetHostType() string {
return api.HOST_TYPE_CTYUN
}
func (self *SHost) GetIsMaintenance() bool {
return false
}
func (self *SHost) GetVersion() string {
return CTYUN_API_VERSION
}
func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
return nil, cloudprovider.ErrNotSupported
}
func (self *SRegion) getVMs(vmId string) ([]SInstance, error) {
params := map[string]string{
"regionId": self.GetId(),
}
if len(vmId) > 0 {
params["vmId"] = vmId
}
resp, err := self.client.DoGet("/apiproxy/v3/ondemand/queryVMs", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.getVMs.DoGet")
}
ret := make([]SInstance, 0)
err = resp.Unmarshal(&ret, "returnObj", "servers")
if err != nil {
return nil, errors.Wrap(err, "SRegion.getVMs.Unmarshal")
}
for i := range ret {
izone, err := self.GetIZoneById(ret[i].OSEXTAZAvailabilityZone)
if err != nil {
return nil, errors.Wrap(err, "SRegion.getVMs.GetIZoneById")
}
ret[i].host = &SHost{
zone: izone.(*SZone),
projectId: self.client.projectId,
}
}
return ret, nil
}
func (self *SRegion) GetVMs() ([]SInstance, error) {
return self.getVMs("")
}
func (self *SRegion) GetVMById(vmId string) (*SInstance, error) {
vms, err := self.getVMs(vmId)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetVMById")
}
if len(vms) == 0 {
return nil, errors.Wrap(cloudprovider.ErrNotFound, "SRegion.GetVMById")
} else if len(vms) == 1 {
izone, err := self.GetIZoneById(vms[0].OSEXTAZAvailabilityZone)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetVMById.GetIZoneById")
}
vms[0].host = &SHost{
zone: izone.(*SZone),
projectId: self.client.projectId,
}
return &vms[0], nil
} else {
return nil, errors.Wrap(cloudprovider.ErrDuplicateId, "SRegion.GetVMById")
}
}
+204
View File
@@ -0,0 +1,204 @@
// 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 ctyun
import (
"context"
"strconv"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/util/imagetools"
)
const (
ImageOwnerPublic string = "gold" // 公共镜像:gold
ImageOwnerSelf string = "private" // 私有镜像:private
ImageOwnerShared string = "shared" // 共享镜像:shared
)
// http://ctyun-api-url/apiproxy/v3/order/getImages
type SImage struct {
storageCache *SStoragecache
ID string `json:"id"`
OSType string `json:"osType"`
Platform string `json:"platform"`
Name string `json:"name"`
OSBit int64 `json:"osBit"`
MinRAM int64 `json:"minRam"`
MinDisk int64 `json:"minDisk"`
ImageType string `json:"imageType"`
Virtual bool `json:"virtual"`
}
func (self *SImage) GetCreatedAt() time.Time {
return time.Time{}
}
func (self *SImage) GetId() string {
return self.ID
}
func (self *SImage) GetName() string {
return self.Name
}
func (self *SImage) GetGlobalId() string {
return self.GetId()
}
func (self *SImage) GetStatus() string {
return api.CACHED_IMAGE_STATUS_READY
}
func (self *SImage) Refresh() error {
new, err := self.storageCache.region.GetImage(self.GetId())
if err != nil {
return err
}
return jsonutils.Update(self, new)
}
func (self *SImage) IsEmulated() bool {
return false
}
func (self *SImage) GetMetadata() *jsonutils.JSONDict {
data := jsonutils.NewDict()
if self.OSBit > 0 {
data.Add(jsonutils.NewString(self.GetOsArch()), "os_arch")
}
if len(self.OSType) > 0 {
data.Add(jsonutils.NewString(self.GetOsType()), "os_name")
}
if len(self.Platform) > 0 {
data.Add(jsonutils.NewString(self.GetOsDist()), "os_distribution")
}
data.Add(jsonutils.NewString(self.GetOsVersion()), "os_version")
return data
}
func (self *SImage) Delete(ctx context.Context) error {
return cloudprovider.ErrNotImplemented
}
func (self *SImage) GetIStoragecache() cloudprovider.ICloudStoragecache {
return self.storageCache
}
func (self *SImage) GetSizeByte() int64 {
return self.MinDisk * 1024 * 1024 * 1024
}
func (self *SImage) GetImageType() string {
switch self.ImageType {
case "gold":
return cloudprovider.CachedImageTypeSystem
case "private":
return cloudprovider.CachedImageTypeCustomized
case "shared":
return cloudprovider.CachedImageTypeShared
default:
return cloudprovider.CachedImageTypeCustomized
}
}
func (self *SImage) GetImageStatus() string {
return cloudprovider.IMAGE_STATUS_ACTIVE
}
func (self *SImage) GetOsType() string {
return self.OSType
}
func (self *SImage) GetOsDist() string {
return self.Platform
}
func (self *SImage) GetOsVersion() string {
return imagetools.NormalizeImageInfo(self.Name, "", "", "", "").OsVersion
}
func (self *SImage) GetOsArch() string {
return strconv.Itoa(int(self.OSBit))
}
func (self *SImage) GetMinOsDiskSizeGb() int {
return int(self.MinDisk)
}
func (self *SImage) GetMinRamSizeMb() int {
return int(self.MinRAM)
}
func (self *SImage) GetImageFormat() string {
return ""
}
func (self *SImage) GetCreateTime() time.Time {
return time.Time{}
}
func (self *SRegion) GetImages(imageType string) ([]SImage, error) {
params := map[string]string{
"regionId": self.GetId(),
"imageType": imageType,
}
resp, err := self.client.DoGet("/apiproxy/v3/order/getImages", params)
if err != nil {
return nil, errors.Wrap(err, "Region.GetImages.DoGet")
}
images := make([]SImage, 0)
err = resp.Unmarshal(&images, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "Region.GetImages.Unmarshal")
}
for i := range images {
images[i].storageCache = &SStoragecache{
region: self,
}
}
return images, nil
}
func (self *SRegion) GetImage(imageId string) (*SImage, error) {
images, err := self.GetImages("")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetImage.GetImages")
}
for i := range images {
if images[i].GetId() == imageId {
images[i].storageCache = &SStoragecache{
region: self,
}
return &images[i], nil
}
}
return nil, errors.Wrap(cloudprovider.ErrNotFound, "SRegion.GetImage")
}
+560
View File
@@ -0,0 +1,560 @@
// 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 ctyun
import (
"context"
"fmt"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/billing"
)
type SInstance struct {
multicloud.SInstanceBase
host *SHost
image *SImage
vmDetails *InstanceDetails
HostID string `json:"hostId"`
ID string `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
TenantID string `json:"tenant_id"`
Metadata Metadata `json:"metadata"`
Image Image `json:"image"`
Flavor FlavorObj `json:"flavor"`
Addresses map[string][]Address `json:"addresses"`
UserID string `json:"user_id"`
Created int64 `json:"created"`
DueDate int64 `json:"dueDate"`
SecurityGroups []SecurityGroup `json:"security_groups"`
OSEXTAZAvailabilityZone string `json:"OS-EXT-AZ:availability_zone"`
OSExtendedVolumesVolumesAttached []Volume `json:"os-extended-volumes:volumes_attached"`
}
type InstanceDetails struct {
HostID string `json:"hostId"`
Name string `json:"name"`
Status string `json:"status"`
PrivateIPS []PrivateIP `json:"privateIps"`
PublicIPS []PublicIP `json:"publicIps"`
Volumes []Volume `json:"volumes"`
Created string `json:"created"`
FlavorObj FlavorObj `json:"flavorObj"`
}
type Address struct {
Addr string `json:"addr"`
OSEXTIPSType string `json:"OS-EXT-IPS:type"`
Version int64 `json:"version"`
OSEXTIPSMACMACAddr string `json:"OS-EXT-IPS-MAC:mac_addr"`
}
type Image struct {
Id string `json:"id"`
}
type SecurityGroup struct {
Name string `json:"name"`
}
type FlavorObj struct {
Name string `json:"name"`
CPUNum int `json:"cpuNum"`
MemSize int `json:"memSize"`
ID string `json:"id"`
}
type PrivateIP struct {
ID string `json:"id"`
Address string `json:"address"`
}
type PublicP struct {
ID string `json:"id"`
Address string `json:"address"`
Bandwidth string `json:"bandwidth"`
}
func (self *SInstance) GetBillingType() string {
if self.DueDate > 0 {
return billing_api.BILLING_TYPE_PREPAID
} else {
return billing_api.BILLING_TYPE_POSTPAID
}
}
func (self *SInstance) GetCreatedAt() time.Time {
return time.Unix(self.Created/1000, 0)
}
func (self *SInstance) GetExpiredAt() time.Time {
return time.Unix(self.DueDate/1000, 0)
}
func (self *SInstance) GetId() string {
return self.ID
}
func (self *SInstance) GetName() string {
return self.Name
}
func (self *SInstance) GetGlobalId() string {
return self.GetId()
}
func (self *SInstance) GetStatus() string {
switch self.Status {
case "RUNNING", "ACTIVE":
return api.VM_RUNNING
case "RESTARTING", "BUILD", "RESIZE", "VERIFY_RESIZE":
return api.VM_STARTING
case "STOPPING", "HARD_REBOOT":
return api.VM_STOPPING
case "STOPPED", "SHUTOFF":
return api.VM_READY
default:
return api.VM_UNKNOWN
}
}
func (self *SInstance) Refresh() error {
new, err := self.host.zone.region.GetVMById(self.GetId())
new.host = self.host
if err != nil {
return err
}
if new.Status == "DELETED" {
log.Debugf("Instance already terminated.")
return cloudprovider.ErrNotFound
}
return jsonutils.Update(self, new)
}
func (self *SInstance) IsEmulated() bool {
return false
}
func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
data := jsonutils.NewDict()
lowerOs := self.GetOSType()
if strings.HasPrefix(lowerOs, "win") {
lowerOs = "win"
}
priceKey := fmt.Sprintf("%s::%s::%s", self.host.zone.region.GetId(), self.GetInstanceType(), lowerOs)
data.Add(jsonutils.NewString(priceKey), "price_key")
data.Add(jsonutils.NewString(self.host.zone.GetGlobalId()), "zone_ext_id")
return data
}
func (self *SInstance) GetProjectId() string {
return ""
}
func (self *SInstance) GetIHost() cloudprovider.ICloudHost {
return self.host
}
// GET http://ctyun-api-url/apiproxy/v3/queryDataDiskByVMId
func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
err := self.Refresh()
if err != nil {
return nil, errors.Wrap(err, "SInstance.GetIDisks.Refresh")
}
disks, err := self.host.zone.region.GetVMDisks(self.GetId())
if err != nil {
return nil, errors.Wrap(err, "SInstance.GetIDisks.GetVMDisks")
}
idisks := make([]cloudprovider.ICloudDisk, 0)
for i := range disks {
disk := disks[i]
idisks[i] = &disk
}
return idisks, nil
}
func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
nics, err := self.host.zone.region.GetNics(self.GetId())
if err != nil {
return nil, errors.Wrap(err, "SInstance.GetINics")
}
inics := make([]cloudprovider.ICloudNic, len(nics))
for i := range nics {
inics[i] = &nics[i]
}
return inics, nil
}
// GET http://ctyun-api-urlapiproxy/v3/queryNetworkByVMId
func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
detail, err := self.GetDetails()
if err != nil {
return nil, errors.Wrap(err, "SInstance.GetIEIP.GetDetails")
}
if len(detail.PublicIPS) > 0 {
return self.host.zone.region.GetEip(detail.PublicIPS[0].ID)
}
return nil, nil
}
func (self *SInstance) GetDetails() (*InstanceDetails, error) {
if self.vmDetails != nil {
return self.vmDetails, nil
}
detail, err := self.host.zone.region.GetVMDetails(self.GetId())
if err != nil {
return nil, errors.Wrap(err, "SInstance.GetDetails")
}
self.vmDetails = detail
return self.vmDetails, nil
}
func (self *SInstance) GetVcpuCount() int {
return self.Flavor.CPUNum
}
func (self *SInstance) GetVmemSizeMB() int {
return self.Flavor.MemSize * 1024
}
func (self *SInstance) GetBootOrder() string {
return "dcn"
}
func (self *SInstance) GetVga() string {
return "std"
}
func (self *SInstance) GetVdi() string {
return "vnc"
}
func (self *SInstance) GetImage() (*SImage, error) {
if self.image != nil {
return self.image, nil
}
image, err := self.host.zone.region.GetImage(self.Image.Id)
if err != nil {
return nil, errors.Wrap(err, "SInstance.GetImage")
}
self.image = image
return self.image, nil
}
func (self *SInstance) GetOSType() string {
image, err := self.GetImage()
if err != nil {
log.Errorf("SInstance.GetOSType %s", err)
return ""
}
return image.OSType
}
func (self *SInstance) GetOSName() string {
image, err := self.GetImage()
if err != nil {
log.Errorf("SInstance.GetOSName %s", err)
return ""
}
return image.Name
}
func (self *SInstance) GetBios() string {
return "BIOS"
}
func (self *SInstance) GetMachine() string {
return "pc"
}
func (self *SInstance) GetInstanceType() string {
return self.Flavor.ID
}
func (self *SInstance) GetSecurityGroupIds() ([]string, error) {
return nil, nil
}
func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) SetSecurityGroups(secgroupIds []string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) GetHypervisor() string {
return api.HYPERVISOR_CTYUN
}
func (self *SInstance) StartVM(ctx context.Context) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) StopVM(ctx context.Context, isForce bool) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) DeleteVM(ctx context.Context) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) UpdateVM(ctx context.Context, name string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) UpdateUserData(userData string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) RebuildRoot(ctx context.Context, imageId string, passwd string, publicKey string, sysSizeGB int) (string, error) {
return "", cloudprovider.ErrNotImplemented
}
func (self *SInstance) DeployVM(ctx context.Context, name string, username string, password string, publicKey string, deleteKeypair bool, description string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.SManagedVMChangeConfig) error {
return cloudprovider.ErrNotImplemented
}
// http://ctyun-api-url/apiproxy/v3/queryVncUrl
func (self *SInstance) GetVNCInfo() (jsonutils.JSONObject, error) {
url, err := self.host.zone.region.GetInstanceVNCUrl(self.GetId())
if err != nil {
return nil, err
}
ret := jsonutils.NewDict()
ret.Add(jsonutils.NewString(url), "url")
ret.Add(jsonutils.NewString("ctyun"), "protocol")
ret.Add(jsonutils.NewString(self.GetId()), "instance_id")
return ret, nil
}
func (self *SInstance) AttachDisk(ctx context.Context, diskId string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) DetachDisk(ctx context.Context, diskId string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) CreateDisk(ctx context.Context, sizeMb int, uuid string, driver string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) Renew(bc billing.SBillingCycle) error {
return cloudprovider.ErrNotImplemented
}
func (self *SInstance) GetError() error {
return nil
}
func (self *SRegion) GetVMDisks(vmId string) ([]SDisk, error) {
params := map[string]string{
"VMId": vmId,
}
resp, err := self.client.DoGet("/apiproxy/v3/queryDataDiskByVMId", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetVMDisks.DoGet")
}
ret := make([]SDisk, 0)
err = resp.Unmarshal(&ret, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetVMDisks.Unmarshal")
}
disks := []SDisk{}
for i := 0; i < len(ret); i += 1 {
// 将系统盘放到第0个位置
if ret[i].IsSysVolume == 1 {
_temp := ret[0]
disks[0] = ret[i]
disks[i] = _temp
}
}
return ret, nil
}
type SDiskDetails struct {
HostID string `json:"hostId"`
Name string `json:"name"`
Status string `json:"status"`
PrivateIPS []PrivateIP `json:"privateIps"`
PublicIPS []PublicIP `json:"publicIps"`
Volumes []Volume `json:"volumes"`
Created string `json:"created"`
FlavorObj FlavorObj `json:"flavorObj"`
}
type PublicIP struct {
ID string `json:"id"`
Address string `json:"address"`
Bandwidth string `json:"bandwidth"`
}
type Volume struct {
ID string `json:"id"`
Status string `json:"status"`
Type string `json:"type"`
Size string `json:"size"`
Name string `json:"name"`
Bootable bool `json:"bootable"`
}
func (self *SRegion) GetVMDetails(vmId string) (*InstanceDetails, error) {
params := map[string]string{
"regionId": self.GetId(),
"vmId": vmId,
}
resp, err := self.client.DoGet("/apiproxy/v3/ondemand/queryVMDetail", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetVMDetails.DoGet")
}
details := &InstanceDetails{}
err = resp.Unmarshal(details, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetVMDetails.Unmarshal")
}
return details, nil
}
type SVncInfo struct {
Type string `json:"type"`
URL string `json:"url"`
}
func (self *SRegion) GetInstanceVNCUrl(vmId string) (string, error) {
params := map[string]string{
"regionId": self.GetId(),
"vmId": vmId,
}
resp, err := self.client.DoGet("/apiproxy/v3/queryVncUrl", params)
if err != nil {
return "", errors.Wrap(err, "")
}
ret := SVncInfo{}
err = resp.Unmarshal(&ret, "returnObj", "console")
if err != nil {
return "", errors.Wrap(err, "")
}
return ret.URL, nil
}
func (self *SRegion) CreateInstance(zoneId, name, imageId, volumetype, flavorRef, vpcid, subnetId, secGroupId, adminPass string) error {
rootParams := jsonutils.NewDict()
rootParams.Set("volumetype", jsonutils.NewString(volumetype))
nicParams := jsonutils.NewArray()
nicParam := jsonutils.NewDict()
nicParam.Set("subnet_id", jsonutils.NewString(subnetId))
nicParams.Add(nicParam)
secgroupParams := jsonutils.NewArray()
secgroupParam := jsonutils.NewDict()
secgroupParam.Set("id", jsonutils.NewString(secGroupId))
secgroupParams.Add(secgroupParam)
extParams := jsonutils.NewDict()
extParams.Set("regionID", jsonutils.NewString(self.GetId()))
serverParams := jsonutils.NewDict()
serverParams.Set("availability_zone", jsonutils.NewString(zoneId))
serverParams.Set("name", jsonutils.NewString(name))
serverParams.Set("imageRef", jsonutils.NewString(imageId))
serverParams.Set("root_volume", rootParams)
serverParams.Set("flavorRef", jsonutils.NewString(flavorRef))
// todo: fix me
serverParams.Set("osType", jsonutils.NewString("Linux"))
serverParams.Set("vpcid", jsonutils.NewString(vpcid))
serverParams.Set("security_groups", secgroupParams)
serverParams.Set("nics", nicParams)
serverParams.Set("adminPass", jsonutils.NewString(adminPass))
serverParams.Set("count", jsonutils.NewString("1"))
serverParams.Set("extendparam", extParams)
vmParams := jsonutils.NewDict()
vmParams.Set("server", serverParams)
params := map[string]jsonutils.JSONObject{
"createVMInfo": vmParams,
}
_, err := self.client.DoPost("/apiproxy/v3/ondemand/createVM", params)
if err != nil {
return errors.Wrap(err, "SRegion.CreateInstance.DoPost")
}
return nil
}
func (self *SRegion) GetJob(jobId string) (jsonutils.JSONObject, error) {
params := map[string]string{
"regionId": self.GetId(),
"jobId": jobId,
}
resp, err := self.client.DoGet("/apiproxy/v3/queryJobStatus", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetJob.DoGet")
}
ret := jsonutils.NewDict()
err = resp.Unmarshal(&ret)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetJob.Unmarshal")
}
return ret, nil
}
+90
View File
@@ -0,0 +1,90 @@
// 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 ctyun
import (
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SInstanceNic struct {
instance *SInstance
ipAddr string
FixedIPS []FixedIP `json:"fixed_ips"`
PortState string `json:"port_state"`
PortID string `json:"port_id"`
MACAddr string `json:"mac_addr"`
NetID string `json:"net_id"`
}
type FixedIP struct {
IPAddress string `json:"ip_address"`
SubnetID string `json:"subnet_id"`
}
func (self *SInstanceNic) GetIP() string {
return self.ipAddr
}
func (self *SInstanceNic) GetMAC() string {
ip, _ := netutils.NewIPV4Addr(self.ipAddr)
return ip.ToMac("00:16:")
}
func (self *SInstanceNic) GetDriver() string {
return "virtio"
}
func (self *SInstanceNic) GetINetwork() cloudprovider.ICloudNetwork {
network, err := self.instance.host.zone.region.GetNetwork(self.NetID)
if err != nil {
log.Errorf("SInstanceNic.GetINetwork %s", err)
return nil
}
return network
}
func (self *SRegion) GetNics(vmId string) ([]SInstanceNic, error) {
params := map[string]string{
"regionId": self.GetId(),
"vmId": vmId,
}
resp, err := self.client.DoGet("/apiproxy/v3/queryNetworkCards", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetNics.DoGet")
}
ret := make([]SInstanceNic, 0)
err = resp.Unmarshal(&ret, "returnObj", "interfaceAttachments")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetNics.Unmarshal")
}
for i := range ret {
ins, err := self.GetVMById(vmId)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetNics")
}
ret[i].instance = ins
}
return ret, nil
}
+19
View File
@@ -0,0 +1,19 @@
// 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 ctyun
// http://ctyun-api-url/apiproxy/v3/order/getZoneConfig
type SKeypair struct {
}
@@ -0,0 +1,61 @@
// 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 ctyun
import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
"cn-beijing1": {Latitude: 39.997743, Longitude: 116.304542, City: api.CITY_BEI_JING, CountryCode: api.COUNTRY_CODE_CN},
"cn-hz1": {Latitude: 30.274084, Longitude: 120.155067, City: api.CITY_HANG_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-gslz1": {Latitude: 36.0613769373, Longitude: 103.8341600069, City: api.CITY_LAN_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-sxty1": {Latitude: 37.8705857132, Longitude: 112.5506634865, City: api.CITY_TAI_YUAN, CountryCode: api.COUNTRY_CODE_CN},
"cn-sh1": {Latitude: 31.210344, Longitude: 121.455364, City: api.CITY_SHANG_HAI, CountryCode: api.COUNTRY_CODE_CN},
"cn-gz1": {Latitude: 26.6470035286, Longitude: 106.6302113880, City: api.CITY_GUI_YANG, CountryCode: api.COUNTRY_CODE_CN},
"cn-sdqd1": {Latitude: 36.067108, Longitude: 120.382607, City: api.CITY_QING_DAO, CountryCode: api.COUNTRY_CODE_CN},
"cn-tj1": {Latitude: 39.0850853357, Longitude: 117.1993482089, City: api.CITY_TIAN_JIN, CountryCode: api.COUNTRY_CODE_CN},
"cn-xjcj1": {Latitude: 43.8266013700, Longitude: 87.6168405804, City: api.CITY_WU_LU_MU_QI, CountryCode: api.COUNTRY_CODE_CN},
"cn-cq1": {Latitude: 29.431585, Longitude: 106.912254, City: api.CITY_CHONG_QING, CountryCode: api.COUNTRY_CODE_CN},
"cn-gxnn1": {Latitude: 22.8167372565, Longitude: 108.3669005333, City: api.CITY_NAN_NING, CountryCode: api.COUNTRY_CODE_CN},
"cn-hazz1": {Latitude: 34.7533581487, Longitude: 113.6313915479, City: api.CITY_ZHENG_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-ynkm1": {Latitude: 24.8796595146, Longitude: 102.8332118852, City: api.CITY_KUN_MING, CountryCode: api.COUNTRY_CODE_CN},
"cn-xian1": {Latitude: 34.3412614674, Longitude: 108.9398165260, City: api.CITY_XI_AN, CountryCode: api.COUNTRY_CODE_CN},
"cn-hihk1": {Latitude: 20.0442268036, Longitude: 110.1998910288, City: api.CITY_HAI_KOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-ahwh1": {Latitude: 31.3524675159, Longitude: 118.4331307290, City: api.CITY_WU_HU, CountryCode: api.COUNTRY_CODE_CN},
"cn-fz1": {Latitude: 26.0741979397, Longitude: 119.2964466153, City: api.CITY_FU_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-nmhh1": {Latitude: 40.842358, Longitude: 111.749992, City: api.CITY_HU_HE_HAO_TE, CountryCode: api.COUNTRY_CODE_CN},
"cn-shanghai2": {Latitude: 31.210344, Longitude: 121.455364, City: api.CITY_SHANG_HAI, CountryCode: api.COUNTRY_CODE_CN},
"cn-snxy1": {Latitude: 34.3412614674, Longitude: 108.9398165260, City: api.CITY_XI_AN, CountryCode: api.COUNTRY_CODE_CN},
"cn-hbwh1": {Latitude: 30.5927599029, Longitude: 114.3052387810, City: api.CITY_WU_HAN, CountryCode: api.COUNTRY_CODE_CN},
"cn-hncs1": {Latitude: 28.2277765095, Longitude: 112.9388453666, City: api.CITY_CHANG_SHA, CountryCode: api.COUNTRY_CODE_CN},
"cn-guangzhou2": {Latitude: 23.12911, Longitude: 113.264385, City: api.CITY_GUANG_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-guizhou2": {Latitude: 26.6470035286, Longitude: 106.6302113880, City: api.CITY_GUI_YANG, CountryCode: api.COUNTRY_CODE_CN},
"cn-jssz1": {Latitude: 31.2983479333, Longitude: 120.5831894861, City: api.CITY_SHU_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-sccd1": {Latitude: 30.572815, Longitude: 104.066803, City: api.CITY_CHENG_DU, CountryCode: api.COUNTRY_CODE_CN},
"cn-guangzhou3": {Latitude: 23.12911, Longitude: 113.264385, City: api.CITY_GUANG_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-shanghai3": {Latitude: 31.210344, Longitude: 121.455364, City: api.CITY_SHANG_HAI, CountryCode: api.COUNTRY_CODE_CN},
"cn-neimeng4": {Latitude: 40.842358, Longitude: 111.749992, City: api.CITY_HU_HE_HAO_TE, CountryCode: api.COUNTRY_CODE_CN},
"cn-beijing3": {Latitude: 39.904202, Longitude: 116.407394, City: api.CITY_BEI_JING, CountryCode: api.COUNTRY_CODE_CN},
"cn-baoding1": {Latitude: 38.8739745619, Longitude: 115.4646082830, City: api.CITY_BAO_DING, CountryCode: api.COUNTRY_CODE_CN},
"cn-nj2": {Latitude: 32.0584065670, Longitude: 118.7964897811, City: api.CITY_NAN_JING, CountryCode: api.COUNTRY_CODE_CN},
"cn-gdgz1": {Latitude: 23.12911, Longitude: 113.264385, City: api.CITY_GUANG_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-bj4": {Latitude: 39.904202, Longitude: 116.407394, City: api.CITY_BEI_JING, CountryCode: api.COUNTRY_CODE_CN},
"cn-neimeng5": {Latitude: 40.842358, Longitude: 111.749992, City: api.CITY_HU_HE_HAO_TE, CountryCode: api.COUNTRY_CODE_CN},
"cn-shanghai5": {Latitude: 31.210344, Longitude: 121.455364, City: api.CITY_SHANG_HAI, CountryCode: api.COUNTRY_CODE_CN},
"cn-sh6": {Latitude: 31.210344, Longitude: 121.455364, City: api.CITY_SHANG_HAI, CountryCode: api.COUNTRY_CODE_CN},
"cn-gdfs2": {Latitude: 23.0218629843, Longitude: 113.1219225896, City: api.CITY_FO_SHAN, CountryCode: api.COUNTRY_CODE_CN},
}
+241
View File
@@ -0,0 +1,241 @@
// 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 ctyun
import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/netutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SNetwork struct {
vpc *SVpc
wire *SWire
CIDR string `json:"cidr"`
FirstDcn string `json:"firstDcn"`
Gateway string `json:"gateway"`
Name string `json:"name"`
NeutronSubnetID string `json:"neutronSubnetId"`
RegionID string `json:"regionId"`
ResVLANID string `json:"resVlanId"`
SecondDcn string `json:"secondDcn"`
VLANStatus string `json:"vlanStatus"`
VpcID string `json:"vpcId"`
ZoneID string `json:"zoneId"`
ZoneName string `json:"zoneName"`
}
func (self *SNetwork) GetId() string {
return self.ResVLANID
}
func (self *SNetwork) GetName() string {
return self.Name
}
func (self *SNetwork) GetGlobalId() string {
return self.GetId()
}
func (self *SNetwork) GetStatus() string {
switch self.VLANStatus {
case "ACTIVE", "UNKNOWN":
return api.NETWORK_STATUS_AVAILABLE
case "ERROR":
return api.NETWORK_STATUS_UNKNOWN
default:
return api.NETWORK_STATUS_UNKNOWN
}
}
func (self *SNetwork) Refresh() error {
log.Debugf("network refresh %s", self.GetId())
new, err := self.wire.region.GetNetwork(self.GetId())
if err != nil {
return err
}
return jsonutils.Update(self, new)
}
func (self *SNetwork) IsEmulated() bool {
return false
}
func (self *SNetwork) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SNetwork) GetProjectId() string {
return ""
}
func (self *SNetwork) GetIWire() cloudprovider.ICloudWire {
return self.wire
}
func (self *SNetwork) GetIpStart() string {
pref, _ := netutils.NewIPV4Prefix(self.CIDR)
startIp := pref.Address.NetAddr(pref.MaskLen) // 0
startIp = startIp.StepUp() // 1
startIp = startIp.StepUp() // 2
return startIp.String()
}
func (self *SNetwork) GetIpEnd() string {
pref, _ := netutils.NewIPV4Prefix(self.CIDR)
endIp := pref.Address.BroadcastAddr(pref.MaskLen) // 255
endIp = endIp.StepDown() // 254
endIp = endIp.StepDown() // 253
endIp = endIp.StepDown() // 252
return endIp.String()
}
func (self *SNetwork) GetIpMask() int8 {
pref, _ := netutils.NewIPV4Prefix(self.CIDR)
return pref.MaskLen
}
func (self *SNetwork) GetGateway() string {
pref, _ := netutils.NewIPV4Prefix(self.CIDR)
endIp := pref.Address.BroadcastAddr(pref.MaskLen) // 255
endIp = endIp.StepDown() // 254
return endIp.String()
}
func (self *SNetwork) GetServerType() string {
return api.NETWORK_TYPE_GUEST
}
func (self *SNetwork) GetIsPublic() bool {
return true
}
func (self *SNetwork) GetPublicScope() rbacutils.TRbacScope {
return rbacutils.ScopeDomain
}
func (self *SNetwork) Delete() error {
return cloudprovider.ErrNotImplemented
}
func (self *SNetwork) GetAllocTimeoutSeconds() int {
return 120
}
func (self *SRegion) GetNetwroks(vpcId string) ([]SNetwork, error) {
querys := map[string]string{
"regionId": self.GetId(),
}
if len(vpcId) > 0 {
querys["vpcId"] = vpcId
}
networks := make([]SNetwork, 0)
resp, err := self.client.DoGet("/apiproxy/v3/getSubnets", querys)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetNetwroks.DoGet")
}
err = resp.Unmarshal(&networks, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetNetwroks.Unmarshal")
}
for i := range networks {
vpc, err := self.GetVpc(networks[i].VpcID)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetNetwork.GetVpc")
}
networks[i].vpc = vpc
networks[i].wire = &SWire{
region: self,
vpc: vpc,
}
networks[i].wire.addNetwork(&networks[i])
}
return networks, err
}
func (self *SRegion) GetNetwork(subnetId string) (*SNetwork, error) {
querys := map[string]string{
"subnetId": subnetId,
"regionId": self.GetId(),
}
resp, err := self.client.DoGet("/apiproxy/v3/querySubnetDetail", querys)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetNetwork.DoGet")
}
network := &SNetwork{}
err = resp.Unmarshal(network, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetNetwork.Unmarshal")
}
vpc, err := self.GetVpc(network.VpcID)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetNetwork.GetVpc")
}
network.vpc = vpc
network.wire = &SWire{
region: self,
vpc: vpc,
}
network.wire.addNetwork(network)
return network, err
}
func (self *SRegion) CreateNetwork(vpcId, zoneId, name, cidr, gatewayIp, dhcpEnable string) (*SNetwork, error) {
networkParams := jsonutils.NewDict()
networkParams.Set("regionId", jsonutils.NewString(self.GetId()))
networkParams.Set("zoneId", jsonutils.NewString(zoneId))
networkParams.Set("name", jsonutils.NewString(name))
networkParams.Set("cidr", jsonutils.NewString(cidr))
networkParams.Set("gatewayIp", jsonutils.NewString(gatewayIp))
networkParams.Set("dhcpEnable", jsonutils.NewString(dhcpEnable))
networkParams.Set("vpcId", jsonutils.NewString(vpcId))
// DNS地址,如果主机需要访问公网就需要填写该值,不填写就不能使用DNS解析
// networkParams.Set("primaryDns", jsonutils.NewString(primaryDns))
// networkParams.Set("secondaryDns", jsonutils.NewString(secondaryDns))
params := map[string]jsonutils.JSONObject{
"jsonStr": networkParams,
}
network := &SNetwork{}
resp, err := self.client.DoPost("/apiproxy/v3/createSubnet", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.CreateNetwork.DoPost")
}
err = resp.Unmarshal(network, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.CreateNetwork.Unmarshal")
}
return network, err
}
+93
View File
@@ -0,0 +1,93 @@
// 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 ctyun
import "yunion.io/x/pkg/errors"
type SOrder struct {
OrderItemID string `json:"orderItemId"`
InstanceID string `json:"instanceId"`
AccountID string `json:"accountId"`
UserID string `json:"userId"`
InnerOrderID string `json:"innerOrderId"`
InnerOrderItemID string `json:"innerOrderItemId"`
ProductID string `json:"productId"`
MasterOrderID string `json:"masterOrderId"`
OrderID string `json:"orderId"`
MasterResourceID string `json:"masterResourceId"`
ResourceID string `json:"resourceId"`
ServiceTag string `json:"serviceTag"`
ResourceType string `json:"resourceType"`
ResourceInfo string `json:"resourceInfo"`
StartDate int64 `json:"startDate"`
ExpireDate int64 `json:"expireDate"`
CreateDate int64 `json:"createDate"`
UpdateDate int64 `json:"updateDate"`
Status int64 `json:"status"`
WorkOrderID string `json:"workOrderId"`
WorkOrderItemID string `json:"workOrderItemId"`
SalesEntryID string `json:"salesEntryId"`
OrderStatus int64 `json:"orderStatus"`
ToOndemand string `json:"toOndemand"`
ItemValue string `json:"itemValue"`
ChargingStatus int64 `json:"chargingStatus"`
ChargingDate int64 `json:"chargingDate"`
ResourceConfig string `json:"resourceConfig"`
AutoToOnDemand bool `json:"autoToOnDemand"`
BuildingChannel int64 `json:"buildingChannel"`
IsPlatformSpecific bool `json:"isPlatformSpecific"`
BillingOwner int64 `json:"billingOwner"`
IsPackage bool `json:"isPackage"`
CanRelease bool `json:"canRelease"`
IsChargeOff bool `json:"isChargeOff"`
IsPublicTest int64 `json:"isPublicTest"`
Master bool `json:"master"`
ResourceConfigMap ResourceConfigMap `json:"resourceConfigMap"`
}
type ResourceConfigMap struct {
AvailabilityZone string `json:"availability_zone"`
Value string `json:"value"`
Number string `json:"number"`
IsSystemVolume bool `json:"isSystemVolume"`
VolumeType string `json:"volumeType"`
Size int64 `json:"size"`
ZoneID string `json:"zoneId"`
RegionID string `json:"regionId"`
Version string `json:"version"`
CycleCnt int64 `json:"cycleCnt"`
CycleType int64 `json:"cycleType"`
ResEbsID string `json:"resEbsId"`
ActualResourceID string `json:"actualResourceId"`
}
func (self *SRegion) GetOrder(orderId string) ([]SOrder, error) {
params := map[string]string{
"masterOrderId": orderId,
}
resp, err := self.client.DoGet("/apiproxy/v3/order/queryResourceInfoByMasterOrderId", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetOrder.DoGet")
}
ret := make([]SOrder, 0)
err = resp.Unmarshal(&ret, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetOrder.DoGet")
}
return ret, nil
}
+66
View File
@@ -0,0 +1,66 @@
// 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 ctyun
import (
"strings"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
)
// GET http://ctyun-api-url/apiproxy/v3/ondemand/queryProjectIds
type SProject struct {
Enabled bool `json:"enabled"`
Name string `json:"name"`
Description string `json:"description"`
ID string `json:"id"`
}
func (self *SProject) GetRegionID() string {
return strings.Split(self.Name, "_")[1]
}
func (self *SProject) GetHealthStatus() string {
if self.Enabled {
return api.CLOUD_PROVIDER_HEALTH_NORMAL
}
return api.CLOUD_PROVIDER_HEALTH_SUSPENDED
}
func (self *SCtyunClient) FetchProjects() ([]SProject, error) {
client, err := NewSCtyunClient("", "", "", self.accessKey, self.secret, self.debug)
if err != nil {
return nil, errors.Wrap(err, "CtyunClient.FetchProjects")
}
projects := make([]SProject, 0)
resp, err := client.DoGet("/apiproxy/v3/ondemand/queryProjectIds", map[string]string{})
if err != nil {
return nil, errors.Wrap(err, "CtyunClient.FetchProjects.DoGet")
}
err = resp.Unmarshal(&projects, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "CtyunClient.FetchProjects.Unmarshal")
}
return projects, err
}
func (self *SRegion) FetchProjects() ([]SProject, error) {
return self.client.FetchProjects()
}
+1
View File
@@ -0,0 +1 @@
package provider // import "yunion.io/x/onecloud/pkg/multicloud/ctyun/provider"
+165
View File
@@ -0,0 +1,165 @@
// 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 provider
import (
"context"
"strings"
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
)
type SCtyunProviderFactory struct {
cloudprovider.SPublicCloudBaseProviderFactor
}
func (self *SCtyunProviderFactory) GetId() string {
return ctyun.CLOUD_PROVIDER_CTYUN
}
func (self *SCtyunProviderFactory) GetName() string {
return ctyun.CLOUD_PROVIDER_CTYUN_CN
}
func (self *SCtyunProviderFactory) IsSupportPrepaidResources() bool {
return true
}
func (self *SCtyunProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, input *api.CloudaccountCreateInput) error {
if len(input.AccessKeyId) == 0 {
return httperrors.NewMissingParameterError("access_key_id")
}
if len(input.AccessKeySecret) == 0 {
return httperrors.NewMissingParameterError("access_key_secret")
}
if len(input.Environment) == 0 {
return httperrors.NewMissingParameterError("environment")
}
input.Account = input.AccessKeyId
input.Secret = input.AccessKeySecret
input.AccessUrl = input.Environment
return nil
}
func (self *SCtyunProviderFactory) ValidateUpdateCloudaccountCredential(ctx context.Context, userCred mcclient.TokenCredential, input *api.CloudaccountCredentialInput, cloudaccount string) (*cloudprovider.SCloudaccount, error) {
if len(input.AccessKeyId) == 0 {
return nil, httperrors.NewMissingParameterError("access_key_id")
}
if len(input.AccessKeySecret) == 0 {
return nil, httperrors.NewMissingParameterError("access_key_secret")
}
account := &cloudprovider.SCloudaccount{
Account: input.AccessKeyId,
Secret: input.AccessKeySecret,
}
return account, nil
}
func (self *SCtyunProviderFactory) GetProvider(providerId, providerName, url, account, secret string) (cloudprovider.ICloudProvider, error) {
segs := strings.Split(account, "/")
projectId := ""
if len(segs) == 2 {
projectId = segs[1]
account = segs[0]
}
client, err := ctyun.NewSCtyunClient(providerId, providerName, projectId, account, secret, false)
if err != nil {
return nil, err
}
return &SCtyunProvider{
SBaseProvider: cloudprovider.NewBaseProvider(self),
client: client,
}, nil
}
func (self *SCtyunProviderFactory) GetClientRC(url, account, secret string) (map[string]string, error) {
return map[string]string{
"CTYUN_ACCESS_URL": url,
"CTYUN_ACCESS_KEY": account,
"CTYUN_SECRET": secret,
"CTYUN_REGION": ctyun.CTYUN_DEFAULT_REGION,
}, nil
}
func init() {
factory := SCtyunProviderFactory{}
cloudprovider.RegisterFactory(&factory)
}
type SCtyunProvider struct {
cloudprovider.SBaseProvider
client *ctyun.SCtyunClient
}
func (self *SCtyunProvider) GetIGlobalnetworks() ([]cloudprovider.ICloudGlobalnetwork, error) {
return []cloudprovider.ICloudGlobalnetwork{}, nil
}
func (self *SCtyunProvider) GetIGlobalnetworkById(id string) (cloudprovider.ICloudGlobalnetwork, error) {
return nil, cloudprovider.ErrNotFound
}
func (self *SCtyunProvider) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
return self.client.GetSubAccounts()
}
func (self *SCtyunProvider) GetAccountId() string {
return self.client.GetAccountId()
}
func (self *SCtyunProvider) GetIRegions() []cloudprovider.ICloudRegion {
return self.client.GetIRegions()
}
func (self *SCtyunProvider) GetSysInfo() (jsonutils.JSONObject, error) {
regions := self.client.GetIRegions()
info := jsonutils.NewDict()
info.Add(jsonutils.NewInt(int64(len(regions))), "region_count")
info.Add(jsonutils.NewString(ctyun.CTYUN_API_VERSION), "api_version")
return info, nil
}
func (self *SCtyunProvider) GetVersion() string {
return ctyun.CTYUN_API_VERSION
}
func (self *SCtyunProvider) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
return self.client.GetIRegionById(id)
}
func (self *SCtyunProvider) GetBalance() (float64, string, error) {
return 0.0, api.CLOUD_PROVIDER_HEALTH_NORMAL, cloudprovider.ErrNotSupported
}
func (self *SCtyunProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) {
return self.client.GetIProjects()
}
func (self *SCtyunProvider) GetStorageClasses(regionId string) []string {
return []string{
"STANDARD", "WARM", "COLD",
}
}
func (self *SCtyunProvider) GetCloudRegionExternalIdPrefix() string {
return self.client.GetAccessEnv() + "/"
}
+451
View File
@@ -0,0 +1,451 @@
// 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 ctyun
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/secrules"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SRegion struct {
cloudprovider.SFakeOnPremiseRegion
multicloud.SRegion
multicloud.SNoObjectStorageRegion
client *SCtyunClient
storageCache *SStoragecache
Description string `json:"description"`
ID string `json:"id"`
ParentRegionID string `json:"parent_region_id"`
Type string `json:"type"`
izones []cloudprovider.ICloudZone
ivpcs []cloudprovider.ICloudVpc
}
func (self *SRegion) fetchIVpcs() error {
vpcs, err := self.GetVpcs()
if err != nil {
return errors.Wrap(err, "SRegion.fetchIVpcs")
}
self.ivpcs = make([]cloudprovider.ICloudVpc, 0)
for i := range vpcs {
vpc := vpcs[i]
vpc.region = self
self.ivpcs = append(self.ivpcs, &vpc)
}
return nil
}
func (self *SRegion) fetchInfrastructure() error {
if err := self.fetchIVpcs(); err != nil {
return err
}
for i := 0; i < len(self.ivpcs); i += 1 {
vpc := self.ivpcs[i].(*SVpc)
wire := SWire{region: self, vpc: vpc}
vpc.addWire(&wire)
for j := 0; j < len(self.izones); j += 1 {
zone := self.izones[j].(*SZone)
zone.addWire(&wire)
}
}
return nil
}
func (self *SRegion) GetVpcs() ([]SVpc, error) {
vpcs := make([]SVpc, 0)
params := map[string]string{
"regionId": self.GetId(),
}
resp, err := self.client.DoGet("/apiproxy/v3/getVpcs", params)
if err != nil {
return nil, err
}
err = resp.Unmarshal(&vpcs, "returnObj")
if err != nil {
return nil, err
}
return vpcs, nil
}
func (self *SRegion) CreateVpc(name, cidr string) (*SVpc, error) {
params := map[string]jsonutils.JSONObject{
"regionId": jsonutils.NewString(self.GetId()),
"name": jsonutils.NewString(name),
"cidr": jsonutils.NewString(cidr),
}
resp, err := self.client.DoPost("/apiproxy/v3/createVPC", params)
if err != nil {
return nil, err
}
vpc := &SVpc{}
err = resp.Unmarshal(vpc, "returnObj")
if err != nil {
return nil, err
}
vpc.region = self
return vpc, nil
}
func (self *SRegion) GetClient() *SCtyunClient {
return self.client
}
func (self *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) {
return self.GetSecurityGroupDetails(secgroupId)
}
func (self *SRegion) GetISecurityGroupByName(vpcId string, name string) (cloudprovider.ICloudSecurityGroup, error) {
segroups, err := self.GetSecurityGroups(vpcId)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetISecurityGroupByName.GetSecurityGroups")
}
for i := range segroups {
if segroups[i].Name == name {
return &segroups[i], nil
}
}
return nil, errors.Wrap(cloudprovider.ErrNotFound, "SRegion.GetISecurityGroupByName.GetSecurityGroups")
}
func (self *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetId() string {
return self.ID
}
func (self *SRegion) GetName() string {
return self.ID
}
func (self *SRegion) GetGlobalId() string {
return fmt.Sprintf("%s/%s", self.client.GetAccessEnv(), self.ID)
}
func (self *SRegion) GetStatus() string {
return api.CLOUD_REGION_STATUS_INSERVER
}
func (self *SRegion) Refresh() error {
return nil
}
func (self *SRegion) IsEmulated() bool {
return false
}
func (self *SRegion) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
if info, ok := LatitudeAndLongitude[self.ID]; ok {
return info
}
return cloudprovider.SGeographicInfo{}
}
// http://ctyun-api-url/apiproxy/v3/order/getZoneConfig
func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
if self.izones == nil {
var err error
err = self.fetchInfrastructure()
if err != nil {
return nil, err
}
}
return self.izones, nil
}
// http://ctyun-api-url/apiproxy/v3/getVpcs
// http://ctyun-api-url/apiproxy/v3/getVpcs
func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
if self.ivpcs == nil {
err := self.fetchInfrastructure()
if err != nil {
return nil, err
}
}
return self.ivpcs, nil
}
// http://ctyun-api-url/apiproxy/v3/ondemand/queryIps
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
eips, err := self.GetEips()
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetIEips.GetEips")
}
ieips := make([]cloudprovider.ICloudEIP, len(eips))
for i := range eips {
ieips[i] = &eips[i]
}
return ieips, nil
}
func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
return self.GetVpc(id)
}
func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for i := 0; i < len(izones); i += 1 {
if izones[i].GetGlobalId() == id {
return izones[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
func (self *SRegion) GetIEipById(id string) (cloudprovider.ICloudEIP, error) {
return self.GetEip(id)
}
func (self *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
return self.GetVMById(id)
}
func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
return self.GetDisk(id)
}
func (self *SRegion) DeleteSecurityGroup(vpcId, secgroupId string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SRegion) SyncSecurityGroup(secgroupId string, vpcId string, name string, desc string, rules []secrules.SecurityRule) (string, error) {
return "", cloudprovider.ErrNotImplemented
}
func (self *SRegion) CreateIVpc(name string, desc string, cidr string) (cloudprovider.ICloudVpc, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
snapshots, err := self.GetSnapshots("")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetISnapshots.GetSnapshots")
}
isnapshots := make([]cloudprovider.ICloudSnapshot, len(snapshots))
for i := range snapshots {
isnapshots[i] = &snapshots[i]
}
return isnapshots, nil
}
func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
snapshots, err := self.GetSnapshots("")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetISnapshotById.GetSnapshots")
}
for i := range snapshots {
if snapshots[i].GetId() == snapshotId {
return &snapshots[i], nil
}
}
return nil, errors.Wrap(cloudprovider.ErrNotFound, "SRegion.GetISnapshotById")
}
func (self *SRegion) CreateSnapshotPolicy(*cloudprovider.SnapshotPolicyInput) (string, error) {
return "", cloudprovider.ErrNotImplemented
}
func (self *SRegion) UpdateSnapshotPolicy(*cloudprovider.SnapshotPolicyInput, string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SRegion) DeleteSnapshotPolicy(string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SRegion) ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SRegion) CancelSnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetISnapshotPolicies() ([]cloudprovider.ICloudSnapshotPolicy, error) {
polices, err := self.GetDiskBackupPolices()
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetISnapshotPolicies.GetDiskBackupPolices")
}
ipolices := make([]cloudprovider.ICloudSnapshotPolicy, len(polices))
for i := range polices {
ipolices[i] = &polices[i]
}
return ipolices, nil
}
func (self *SRegion) GetISnapshotPolicyById(snapshotPolicyId string) (cloudprovider.ICloudSnapshotPolicy, error) {
return self.GetDiskBackupPolicy(snapshotPolicyId)
}
func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) {
iHosts := make([]cloudprovider.ICloudHost, 0)
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for i := 0; i < len(izones); i += 1 {
iZoneHost, err := izones[i].GetIHosts()
if err != nil {
return nil, err
}
iHosts = append(iHosts, iZoneHost...)
}
return iHosts, nil
}
func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for i := 0; i < len(izones); i += 1 {
ihost, err := izones[i].GetIHostById(id)
if err == nil {
return ihost, nil
} else if err != cloudprovider.ErrNotFound {
return nil, err
}
}
return nil, cloudprovider.ErrNotFound
}
func (self *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
iStores := make([]cloudprovider.ICloudStorage, 0)
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for i := 0; i < len(izones); i += 1 {
iZoneStores, err := izones[i].GetIStorages()
if err != nil {
return nil, err
}
iStores = append(iStores, iZoneStores...)
}
return iStores, nil
}
func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for i := 0; i < len(izones); i += 1 {
istore, err := izones[i].GetIStorageById(id)
if err == nil {
return istore, nil
} else if err != cloudprovider.ErrNotFound {
return nil, err
}
}
return nil, cloudprovider.ErrNotFound
}
func (self *SRegion) GetIStoragecaches() ([]cloudprovider.ICloudStoragecache, error) {
storageCache := self.getStoragecache()
return []cloudprovider.ICloudStoragecache{storageCache}, nil
}
func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
storageCache := self.getStoragecache()
if storageCache.GetGlobalId() == id {
return storageCache, nil
}
return nil, cloudprovider.ErrNotFound
}
func (self *SRegion) GetProvider() string {
return api.CLOUD_PROVIDER_CTYUN
}
func (self *SRegion) GetInstances(instanceId string) ([]SInstance, error) {
params := map[string]string{
"regionId": self.GetId(),
}
resp, err := self.client.DoGet("/apiproxy/v3/ondemand/queryVMs", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetInstances.DoGet")
}
ret := make([]SInstance, 0)
err = resp.Unmarshal(&ret, "returnObj", "servers")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetInstances.Unmarshal")
}
return ret, nil
}
func (self *SRegion) GetInstanceFlavors() ([]FlavorObj, error) {
params := map[string]string{
"regionId": self.GetId(),
}
resp, err := self.client.DoGet("/apiproxy/v3/order/getFlavors", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetInstanceFlavors.DoGet")
}
ret := make([]FlavorObj, 0)
err = resp.Unmarshal(&ret, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetInstanceFlavors.Unmarshal")
}
return ret, nil
}
+103
View File
@@ -0,0 +1,103 @@
// 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 ctyun
import (
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
)
type SSecurityGroupRule struct {
secgroup *SSecurityGroup
PortRangeMax int64 `json:"port_range_max"`
SecurityGroupID string `json:"security_group_id"`
RemoteGroupId string `json:"remote_group_id"`
Description string `json:"description"`
RemoteIPPrefix string `json:"remote_ip_prefix"`
Protocol string `json:"protocol"`
Ethertype string `json:"ethertype"`
UpdatedAt string `json:"updated_at"`
Direction string `json:"direction"`
TenantID string `json:"tenant_id"`
ID string `json:"id"`
ProjectID string `json:"project_id"`
PortRangeMin int64 `json:"port_range_min"`
CreatedAt string `json:"created_at"`
}
func (self *SRegion) GetSecurityGroupRules(secgroupId string) ([]SSecurityGroupRule, error) {
params := map[string]string{
"regionId": self.GetId(),
"securityGroupId": secgroupId,
}
resp, err := self.client.DoGet("/apiproxy/v3/getSecurityGroupRules", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetSecurityGroupRules.DoGet")
}
ret := make([]SSecurityGroupRule, 0)
err = resp.Unmarshal(&ret, "returnObj", "security_group_rules")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetSecurityGroupRules.Unmarshal")
}
secgroup, err := self.GetSecurityGroupDetails(secgroupId)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetSecurityGroupRules.GetSecurityGroupDetails")
}
for i := range ret {
ret[i].secgroup = secgroup
}
return ret, nil
}
func (self *SRegion) CreateSecurityGroupRule(groupId, direction, ethertype, protocol, remoteIpPrefix string, portRangeMin, portRangeMax int64) error {
ruleParams := jsonutils.NewDict()
ruleParams.Set("regionId", jsonutils.NewString(self.GetId()))
ruleParams.Set("securityGroupId", jsonutils.NewString(groupId))
ruleParams.Set("direction", jsonutils.NewString(direction))
ruleParams.Set("ethertype", jsonutils.NewString(ethertype))
if len(protocol) > 0 {
ruleParams.Set("protocol", jsonutils.NewString(protocol))
}
if len(remoteIpPrefix) > 0 {
ruleParams.Set("remoteIpPrefix", jsonutils.NewString(remoteIpPrefix))
}
if portRangeMin > 0 {
ruleParams.Set("portRangeMin", jsonutils.NewInt(portRangeMin))
}
if portRangeMax > 0 {
ruleParams.Set("portRangeMax", jsonutils.NewInt(portRangeMax))
}
params := map[string]jsonutils.JSONObject{
"jsonStr": ruleParams,
}
_, err := self.client.DoPost("/apiproxy/v3/createSecurityGroupRule", params)
if err != nil {
return errors.Wrap(err, "SRegion.CreateSecurityGroupRule.DoPost")
}
return err
}
+266
View File
@@ -0,0 +1,266 @@
// 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 ctyun
import (
"net"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SSecurityGroup struct {
region *SRegion
vpc *SVpc
ID string `json:"id"`
ResSecurityGroupID string `json:"resSecurityGroupId"`
Name string `json:"name"`
AccountID string `json:"accountId"`
UserID string `json:"userId"`
RegionID string `json:"regionId"`
ZoneID string `json:"zoneId"`
VpcID string `json:"vpcId"`
CreateDate int64 `json:"createDate"`
Status int64 `json:"status"`
}
func (self *SSecurityGroup) SyncRules(rules []secrules.SecurityRule) error {
return cloudprovider.ErrNotImplemented
}
func (self *SSecurityGroup) Delete() error {
return cloudprovider.ErrNotImplemented
}
func (self *SSecurityGroup) GetId() string {
return self.ResSecurityGroupID
}
func (self *SSecurityGroup) GetName() string {
if len(self.Name) > 0 {
return self.Name
}
return self.ResSecurityGroupID
}
func (self *SSecurityGroup) GetGlobalId() string {
return self.GetId()
}
func (self *SSecurityGroup) GetStatus() string {
return ""
}
func (self *SSecurityGroup) Refresh() error {
if new, err := self.region.GetSecurityGroupDetails(self.GetId()); err != nil {
return err
} else {
return jsonutils.Update(self, new)
}
}
func (self *SSecurityGroup) IsEmulated() bool {
return false
}
func (self *SSecurityGroup) GetMetadata() *jsonutils.JSONDict {
return jsonutils.NewDict()
}
func (self *SSecurityGroup) GetDescription() string {
return ""
}
// 判断是否兼容云端安全组规则
func compatibleSecurityGroupRule(r SSecurityGroupRule) bool {
// 忽略了源地址是安全组的规则
if len(r.RemoteGroupId) > 0 {
return false
}
// 忽略IPV6
if r.Ethertype == "IPv6" {
return false
}
return true
}
func (self *SSecurityGroup) GetRules() ([]secrules.SecurityRule, error) {
_rules, err := self.region.GetSecurityGroupRules(self.GetId())
if err != nil {
return nil, errors.Wrap(err, "SSecurityGroup.GetRules.GetSecurityGroupRules")
}
rules := make([]secrules.SecurityRule, 0)
for _, r := range _rules {
if !compatibleSecurityGroupRule(r) {
continue
}
rule, err := self.GetSecurityRule(r, false)
if err != nil {
return rules, err
}
rules = append(rules, rule)
}
return rules, nil
}
func (self *SSecurityGroup) GetSecurityRule(remoteRule SSecurityGroupRule, withRuleId bool) (secrules.SecurityRule, error) {
var err error
var direction secrules.TSecurityRuleDirection
if remoteRule.Direction == "ingress" {
direction = secrules.SecurityRuleIngress
} else {
direction = secrules.SecurityRuleEgress
}
protocol := secrules.PROTO_ANY
if remoteRule.Protocol != "" {
protocol = remoteRule.Protocol
}
var portStart int
var portEnd int
if protocol == secrules.PROTO_ICMP {
portStart = -1
portEnd = -1
} else {
portStart = int(remoteRule.PortRangeMin)
portEnd = int(remoteRule.PortRangeMax)
}
ipNet := &net.IPNet{}
if len(remoteRule.RemoteIPPrefix) > 0 {
_, ipNet, err = net.ParseCIDR(remoteRule.RemoteIPPrefix)
} else {
_, ipNet, err = net.ParseCIDR("0.0.0.0/0")
}
if err != nil {
return secrules.SecurityRule{}, err
}
// withRuleId.将ruleId附加到description字段。该hook有特殊目的,仅在同步安全组时使用。
desc := ""
if withRuleId {
desc = remoteRule.ID
} else {
desc = remoteRule.Description
}
rule := secrules.SecurityRule{
Priority: 1,
Action: secrules.SecurityRuleAllow,
IPNet: ipNet,
Protocol: protocol,
Direction: direction,
PortStart: portStart,
PortEnd: portEnd,
Ports: nil,
Description: desc,
}
err = rule.ValidateRule()
return rule, err
}
func (self *SSecurityGroup) GetVpcId() string {
if len(self.VpcID) == 0 {
return "normal"
}
return self.VpcID
}
func (self *SRegion) GetSecurityGroupDetails(groupId string) (*SSecurityGroup, error) {
params := map[string]string{
"regionId": self.GetId(),
"securityGroupId": groupId,
}
resp, err := self.client.DoGet("/apiproxy/v3/querySecurityGroupDetail", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetSecurityGroupDetails")
}
ret := &SSecurityGroup{}
err = resp.Unmarshal(&ret, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetSecurityGroupDetails.Unmarshal")
}
ret.region = self
return ret, nil
}
func (self *SRegion) GetSecurityGroups(vpcId string) ([]SSecurityGroup, error) {
params := map[string]string{
"regionId": self.GetId(),
"vpcId": vpcId,
}
resp, err := self.client.DoGet("/apiproxy/v3/getSecurityGroups", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetSecurityGroups")
}
ret := make([]SSecurityGroup, 0)
err = resp.Unmarshal(&ret, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetSecurityGroups.Unmarshal")
}
for i := range ret {
ret[i].region = self
}
return ret, nil
}
func (self *SRegion) CreateSecurityGroup(vpcId, name string) (*SSecurityGroup, error) {
params := map[string]jsonutils.JSONObject{
"regionId": jsonutils.NewString(self.GetId()),
"vpcId": jsonutils.NewString(vpcId),
"name": jsonutils.NewString(name),
}
resp, err := self.client.DoPost("/apiproxy/v3/createSecurityGroup", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.CreateSecurityGroup.DoPost")
}
ret := &SSecurityGroup{}
err = resp.Unmarshal(ret, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.CreateSecurityGroup.Unmarshal")
}
vpc, err := self.GetVpc(vpcId)
if err != nil {
return nil, errors.Wrap(err, "SRegion.CreateSecurityGroup.GetVpc")
}
ret.vpc = vpc
ret.region = self
return ret, nil
}
+48
View File
@@ -0,0 +1,48 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type VDiskListOptions struct {
}
shellutils.R(&VDiskListOptions{}, "disk-list", "List disks", func(cli *ctyun.SRegion, args *VDiskListOptions) error {
disks, e := cli.GetDisks()
if e != nil {
return e
}
printList(disks, 0, 0, 0, nil)
return nil
})
type DiskCreateOptions struct {
ZoneId string `help:"zone id"`
Name string `help:"disk name"`
DiskType string `help:"disk type" choice:"SSD|SAS|SATA"`
Size string `help:"disk size"`
}
shellutils.R(&DiskCreateOptions{}, "disk-create", "Create disk", func(cli *ctyun.SRegion, args *DiskCreateOptions) error {
disk, e := cli.CreateDisk(args.ZoneId, args.Name, args.DiskType, args.Size)
if e != nil {
return e
}
printObject(disk)
return nil
})
}
@@ -0,0 +1,77 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type VPolicyListOptions struct {
}
shellutils.R(&VPolicyListOptions{}, "policy-list", "List polices", func(cli *ctyun.SRegion, args *VPolicyListOptions) error {
polices, e := cli.GetDiskBackupPolices()
if e != nil {
return e
}
printList(polices, 0, 0, 0, nil)
return nil
})
type PolicyCreateOptions struct {
Name string `help:"policy name"`
StartTime string `help:"startTime"`
Frequency string `help:"frequency"`
RententionNum string `help:"rententionNum"`
FirstBackup string `help:"firstBackup"`
Status string `help:"status"`
}
shellutils.R(&PolicyCreateOptions{}, "policy-create", "Create policy", func(cli *ctyun.SRegion, args *PolicyCreateOptions) error {
e := cli.CreateDiskBackupPolicy(args.Name, args.StartTime, args.Frequency, args.RententionNum, args.FirstBackup, args.Status)
if e != nil {
return e
}
return nil
})
type BindingDiskBackupPolicyOptions struct {
PolicyId string `help:"policy id"`
ResourceId string `help:"resource id"`
ResourceType string `help:"resource type"`
}
shellutils.R(&BindingDiskBackupPolicyOptions{}, "policy-bind", "Binding policy", func(cli *ctyun.SRegion, args *BindingDiskBackupPolicyOptions) error {
e := cli.BindingDiskBackupPolicy(args.PolicyId, args.ResourceId, args.ResourceType)
if e != nil {
return e
}
return nil
})
type UnBindDiskBackupPolicyOptions struct {
PolicyId string `help:"policy id"`
ResourceId string `help:"resourceId"`
}
shellutils.R(&UnBindDiskBackupPolicyOptions{}, "policy-unbind", "Unbind policy", func(cli *ctyun.SRegion, args *UnBindDiskBackupPolicyOptions) error {
e := cli.UnBindDiskBackupPolicy(args.PolicyId, args.ResourceId)
if e != nil {
return e
}
return nil
})
}
+1
View File
@@ -0,0 +1 @@
package shell // import "yunion.io/x/onecloud/pkg/multicloud/ctyun/shell"
+48
View File
@@ -0,0 +1,48 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type VEipListOptions struct {
}
shellutils.R(&VEipListOptions{}, "eip-list", "List eips", func(cli *ctyun.SRegion, args *VEipListOptions) error {
eips, e := cli.GetEips()
if e != nil {
return e
}
printList(eips, 0, 0, 0, nil)
return nil
})
type EipCreateOptions struct {
ZoneId string `help:"zone id"`
Name string `help:"eip name"`
Size string `help:"size"`
ShareType string `help:"share type" choice:"PER|WHOLE"`
}
shellutils.R(&EipCreateOptions{}, "eip-create", "Create eip", func(cli *ctyun.SRegion, args *EipCreateOptions) error {
eip, e := cli.CreateEip(args.ZoneId, args.Name, args.Size, args.ShareType)
if e != nil {
return e
}
printObject(eip)
return nil
})
}
+34
View File
@@ -0,0 +1,34 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type VImageListOptions struct {
ImageType string `help:"image type" choices:"gold|private|shared"`
}
shellutils.R(&VImageListOptions{}, "image-list", "List images", func(cli *ctyun.SRegion, args *VImageListOptions) error {
images, e := cli.GetImages(args.ImageType)
if e != nil {
return e
}
printList(images, 0, 0, 0, nil)
return nil
})
}
+55
View File
@@ -0,0 +1,55 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type InstanceListOptions struct {
Id string `help:"ID of instance to show"`
}
shellutils.R(&InstanceListOptions{}, "instance-list", "List intances", func(cli *ctyun.SRegion, args *InstanceListOptions) error {
instances, e := cli.GetInstances(args.Id)
if e != nil {
return e
}
printList(instances, 0, 0, 0, []string{})
return nil
})
type InstanceCreateOptions struct {
ZoneId string `help:"zone ID of instance"`
NAME string `help:"name of instance"`
ADMINPASS string `help:"admin password of instance"`
ImageId string `help:"image Id of instance"`
VolumeType string `help:"volume type of instance"`
Flavor string `help:"Flavor of instance"`
VpcId string `help:"Vpc of instance"`
SubnetId string `help:"subnet Id of instance"`
SecGroupId string `help:"security group Id of instance"`
}
shellutils.R(&InstanceCreateOptions{}, "instance-create", "Create intance", func(cli *ctyun.SRegion, args *InstanceCreateOptions) error {
e := cli.CreateInstance(args.ZoneId, args.NAME, args.ImageId, args.VolumeType, args.Flavor, args.VpcId, args.SubnetId, args.SecGroupId, args.ADMINPASS)
if e != nil {
return e
}
return nil
})
}
+34
View File
@@ -0,0 +1,34 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type VJobShowOptions struct {
JOBID string `help:"Job ID"`
}
shellutils.R(&VJobShowOptions{}, "job-show", "Show job", func(cli *ctyun.SRegion, args *VJobShowOptions) error {
job, e := cli.GetJob(args.JOBID)
if e != nil {
return e
}
printObject(job)
return nil
})
}
+51
View File
@@ -0,0 +1,51 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type VNetworkListOptions struct {
Vpc string `help:"Vpc ID"`
}
shellutils.R(&VNetworkListOptions{}, "subnet-list", "List subnets", func(cli *ctyun.SRegion, args *VNetworkListOptions) error {
vswitches, e := cli.GetNetwroks(args.Vpc)
if e != nil {
return e
}
printList(vswitches, 0, 0, 0, nil)
return nil
})
type NetworkCreateOptions struct {
VpcId string `help:"vpc id"`
ZoneId string `help:"zone id"`
Name string `help:"subnet name"`
Cidr string `help:"cidr"`
GatewayIp string `help:"gateway ip"`
DhcpEnable string `help:"gateway ip" choice:"true|false"`
}
shellutils.R(&NetworkCreateOptions{}, "subnet-create", "Create subnet", func(cli *ctyun.SRegion, args *NetworkCreateOptions) error {
vpc, e := cli.CreateNetwork(args.VpcId, args.ZoneId, args.Name, args.Cidr, args.GatewayIp, args.DhcpEnable)
if e != nil {
return e
}
printObject(vpc)
return nil
})
}
+25
View File
@@ -0,0 +1,25 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import "yunion.io/x/onecloud/pkg/util/printutils"
func printList(data interface{}, total, offset, limit int, columns []string) {
printutils.PrintInterfaceList(data, total, offset, limit, columns)
}
func printObject(obj interface{}) {
printutils.PrintInterfaceObject(obj)
}
+33
View File
@@ -0,0 +1,33 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type VProjectListOptions struct {
}
shellutils.R(&VProjectListOptions{}, "project-list", "List projects", func(cli *ctyun.SRegion, args *VProjectListOptions) error {
projects, e := cli.FetchProjects()
if e != nil {
return e
}
printList(projects, 0, 0, 0, nil)
return nil
})
}
+30
View File
@@ -0,0 +1,30 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type RegionListOptions struct {
}
shellutils.R(&RegionListOptions{}, "region-list", "List regions", func(cli *ctyun.SRegion, args *RegionListOptions) error {
regions := cli.GetClient().GetRegions()
printList(regions, 0, 0, 0, nil)
return nil
})
}
+77
View File
@@ -0,0 +1,77 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type VSecurityGroupListOptions struct {
Vpc string `help:"Vpc ID"`
}
shellutils.R(&VSecurityGroupListOptions{}, "secgroup-list", "List secgroups", func(cli *ctyun.SRegion, args *VSecurityGroupListOptions) error {
secgroups, e := cli.GetSecurityGroups(args.Vpc)
if e != nil {
return e
}
printList(secgroups, 0, 0, 0, nil)
return nil
})
type VSecurityGroupRuleListOptions struct {
Group string `help:"Security Group ID"`
}
shellutils.R(&VSecurityGroupRuleListOptions{}, "secrule-list", "List secgroup rules", func(cli *ctyun.SRegion, args *VSecurityGroupRuleListOptions) error {
secrules, e := cli.GetSecurityGroupRules(args.Group)
if e != nil {
return e
}
printList(secrules, 0, 0, 0, nil)
return nil
})
type SecurityGroupCreateOptions struct {
VpcId string `help:"vpc id"`
Name string `help:"secgroup name"`
}
shellutils.R(&SecurityGroupCreateOptions{}, "secgroup-create", "Create secgroup", func(cli *ctyun.SRegion, args *SecurityGroupCreateOptions) error {
vpc, e := cli.CreateSecurityGroup(args.VpcId, args.Name)
if e != nil {
return e
}
printObject(vpc)
return nil
})
type SecurityGroupRuleCreateOptions struct {
Group string `help:"secgroup id"`
Direction string `help:"direction"`
Ethertype string `help:"ethertype" choice:"IPv4|IPv6"`
Protocol string `help:"protocol,icmptcpudpand so on "`
IpPrefix string `help:"remote ip prefix"`
PortMin int64 `help:"portRangeMin"`
PortMax int64 `help:"portRangeMax"`
}
shellutils.R(&SecurityGroupRuleCreateOptions{}, "secrule-create", "Create secgroup rule", func(cli *ctyun.SRegion, args *SecurityGroupRuleCreateOptions) error {
e := cli.CreateSecurityGroupRule(args.Group, args.Direction, args.Ethertype, args.Protocol, args.IpPrefix, args.PortMin, args.PortMax)
if e != nil {
return e
}
return nil
})
}
+46
View File
@@ -0,0 +1,46 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/ctyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type VpcListOptions struct {
}
shellutils.R(&VpcListOptions{}, "vpc-list", "List vpcs", func(cli *ctyun.SRegion, args *VpcListOptions) error {
vpcs, e := cli.GetVpcs()
if e != nil {
return e
}
printList(vpcs, 0, 0, 0, nil)
return nil
})
type VpcCreateOptions struct {
NAME string `help:"vpc name"`
CIDR string `help:"10.0.0.0/8~10.255.255.0/24或者172.16.0.0/12 ~ 172.31.255.0/24或者192.168.0.0/16 ~ 192.168.255.0/24"`
}
shellutils.R(&VpcCreateOptions{}, "vpc-create", "Create vpc", func(cli *ctyun.SRegion, args *VpcCreateOptions) error {
vpc, e := cli.CreateVpc(args.NAME, args.CIDR)
if e != nil {
return e
}
printObject(vpc)
return nil
})
}
+152
View File
@@ -0,0 +1,152 @@
// 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 ctyun
import (
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SSnapshot struct {
region *SRegion
Status string `json:"status"`
Description string `json:"description"`
AvailabilityZone string `json:"availability_zone"`
VolumeID string `json:"volume_id"`
FailReason string `json:"fail_reason"`
ID string `json:"id"`
Size int64 `json:"size"`
Container string `json:"container"`
Name string `json:"name"`
CreatedAt string `json:"created_at"`
}
func (self *SSnapshot) GetId() string {
return self.ID
}
func (self *SSnapshot) GetName() string {
return self.Name
}
func (self *SSnapshot) GetGlobalId() string {
return self.GetId()
}
func (self *SSnapshot) GetStatus() string {
switch self.Status {
case "available":
return api.SNAPSHOT_READY
case "creating":
return api.SNAPSHOT_CREATING
case "deleting":
return api.SNAPSHOT_DELETING
case "error_deleting", "error":
return api.SNAPSHOT_FAILED
case "rollbacking":
return api.SNAPSHOT_ROLLBACKING
default:
return api.SNAPSHOT_UNKNOWN
}
}
func (self *SSnapshot) Refresh() error {
snapshot, err := self.region.GetSnapshot(self.VolumeID, self.GetId())
if err != nil {
return err
}
if err := jsonutils.Update(self, snapshot); err != nil {
return err
}
return nil
}
func (self *SSnapshot) IsEmulated() bool {
return false
}
func (self *SSnapshot) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SSnapshot) GetProjectId() string {
return ""
}
func (self *SSnapshot) GetSizeMb() int32 {
return 0
}
func (self *SSnapshot) GetDiskId() string {
return self.VolumeID
}
func (self *SSnapshot) GetDiskType() string {
return api.DISK_TYPE_SYS
}
func (self *SSnapshot) Delete() error {
return cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetSnapshot(diskId string, snapshotId string) (*SSnapshot, error) {
snapshots, err := self.GetSnapshots(diskId)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetSnapshot.GetSnapshots")
}
for i := range snapshots {
snapshot := snapshots[i]
if snapshot.ID == snapshotId {
snapshot.region = self
return &snapshot, nil
}
}
return nil, errors.Wrap(errors.ErrNotFound, "SRegion.GetSnapshot")
}
func (self *SRegion) GetSnapshots(diskId string) ([]SSnapshot, error) {
params := map[string]string{
"regionId": self.GetId(),
}
if len(diskId) > 0 {
params["volumeId"] = diskId
}
resp, err := self.client.DoGet("/apiproxy/v3/ondemand/queryVBSDetails", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetSnapshots.DoGet")
}
ret := make([]SSnapshot, 0)
err = resp.Unmarshal(&ret, "returnObj", "backups")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetSnapshots.Unmarshal")
}
for i := range ret {
ret[i].region = self
}
return ret, nil
}
+154
View File
@@ -0,0 +1,154 @@
// 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 ctyun
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
var StorageTypes = []string{
api.STORAGE_CTYUN_SAS,
api.STORAGE_CTYUN_SATA,
api.STORAGE_CTYUN_SSD,
}
type SStorage struct {
zone *SZone
storageType string
}
func (self *SStorage) GetId() string {
return fmt.Sprintf("%s-%s-%s", self.zone.region.client.providerId, self.zone.GetId(), self.storageType)
}
func (self *SStorage) GetName() string {
return fmt.Sprintf("%s-%s-%s", self.zone.region.client.providerName, self.zone.GetId(), self.storageType)
}
func (self *SStorage) GetGlobalId() string {
return fmt.Sprintf("%s-%s-%s", self.zone.region.client.providerId, self.zone.GetGlobalId(), self.storageType)
}
func (self *SStorage) GetStatus() string {
return api.STORAGE_ONLINE
}
func (self *SStorage) Refresh() error {
return nil
}
func (self *SStorage) IsEmulated() bool {
return true
}
func (self *SStorage) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
return self.zone.region.getStoragecache()
}
func (self *SStorage) GetIZone() cloudprovider.ICloudZone {
return self.zone
}
// http://ctyun-api-url/apiproxy/v3/ondemand/queryVolumes
// http://ctyun-api-url/apiproxy/v3/queryDataDisks
func (self *SStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
disks, err := self.zone.region.GetDisks()
if err != nil {
return nil, err
}
// 按storage type 过滤出disk
filtedDisks := make([]SDisk, 0)
for i := range disks {
disk := disks[i]
if disk.VolumeType == self.storageType && disk.AvailabilityZone == self.zone.GetId() {
filtedDisks = append(filtedDisks, disk)
}
}
idisks := make([]cloudprovider.ICloudDisk, len(filtedDisks))
for i := 0; i < len(filtedDisks); i += 1 {
filtedDisks[i].storage = self
idisks[i] = &filtedDisks[i]
}
return idisks, nil
}
func (self *SStorage) GetStorageType() string {
return self.storageType
}
func (self *SStorage) GetMediumType() string {
if self.storageType == api.STORAGE_CTYUN_SSD {
return api.DISK_TYPE_SSD
} else {
return api.DISK_TYPE_ROTATE
}
}
func (self *SStorage) GetCapacityMB() int64 {
return 0
}
func (self *SStorage) GetStorageConf() jsonutils.JSONObject {
return jsonutils.NewDict()
}
func (self *SStorage) GetEnabled() bool {
return true
}
func (self *SStorage) CreateIDisk(name string, sizeGb int, desc string) (cloudprovider.ICloudDisk, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SStorage) GetIDiskById(idStr string) (cloudprovider.ICloudDisk, error) {
if len(idStr) == 0 {
log.Debugf("GetIDiskById disk id should not be empty")
return nil, cloudprovider.ErrNotFound
}
if disk, err := self.zone.region.GetDisk(idStr); err != nil {
return nil, err
} else {
disk.storage = self
return disk, nil
}
}
func (self *SStorage) GetMountPoint() string {
return ""
}
func (self *SStorage) IsSysDiskStore() bool {
return true
}
func (self *SRegion) getStoragecache() *SStoragecache {
if self.storageCache == nil {
self.storageCache = &SStoragecache{region: self}
}
return self.storageCache
}
+124
View File
@@ -0,0 +1,124 @@
// 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 ctyun
import (
"context"
"fmt"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SStoragecache struct {
region *SRegion
iimages []cloudprovider.ICloudImage
}
func (self *SStoragecache) CreateIImage(snapshotId, imageName, osType, imageDesc string) (cloudprovider.ICloudImage, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SStoragecache) DownloadImage(userCred mcclient.TokenCredential, imageId string, extId string, path string) (jsonutils.JSONObject, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SStoragecache) UploadImage(ctx context.Context, userCred mcclient.TokenCredential, image *cloudprovider.SImageCreateOption, isForce bool) (string, error) {
return "", cloudprovider.ErrNotImplemented
}
func GetBucketName(regionId string, imageId string) string {
return fmt.Sprintf("imgcache-%s-%s", strings.ToLower(regionId), imageId)
}
func (self *SStoragecache) fetchImages() error {
imagesGold, err := self.region.GetImages(ImageOwnerPublic)
if err != nil {
return err
}
imagesSelf, err := self.region.GetImages(ImageOwnerSelf)
if err != nil {
return err
}
self.iimages = make([]cloudprovider.ICloudImage, len(imagesGold)+len(imagesSelf))
for i := range imagesGold {
imagesGold[i].storageCache = self
self.iimages[i] = &imagesGold[i]
}
for i := range imagesSelf {
imagesSelf[i].storageCache = self
self.iimages[i+len(imagesGold)] = &imagesSelf[i]
}
return nil
}
func (self *SStoragecache) GetId() string {
return fmt.Sprintf("%s-%s", self.region.client.providerId, self.region.GetId())
}
func (self *SStoragecache) GetName() string {
return fmt.Sprintf("%s-%s", self.region.client.providerName, self.region.GetId())
}
func (self *SStoragecache) GetGlobalId() string {
return fmt.Sprintf("%s-%s", self.region.client.providerId, self.region.GetGlobalId())
}
func (self *SStoragecache) GetStatus() string {
return "available"
}
func (self *SStoragecache) Refresh() error {
return nil
}
func (self *SStoragecache) IsEmulated() bool {
return false
}
func (self *SStoragecache) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SStoragecache) GetIImages() ([]cloudprovider.ICloudImage, error) {
if self.iimages == nil {
err := self.fetchImages()
if err != nil {
return nil, err
}
}
return self.iimages, nil
}
func (self *SStoragecache) GetIImageById(extId string) (cloudprovider.ICloudImage, error) {
image, err := self.region.GetImage(extId)
if err != nil {
return nil, errors.Wrap(err, "SStoragecache.GetIImageById.GetImage")
}
image.storageCache = self
return image, err
}
func (self *SStoragecache) GetPath() string {
return ""
}
+214
View File
@@ -0,0 +1,214 @@
// 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 ctyun
import (
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SVpc struct {
multicloud.SVpc
region *SRegion
iwires []cloudprovider.ICloudWire
secgroups []cloudprovider.ICloudSecurityGroup
ResVpcID string `json:"resVpcId"`
Name string `json:"name"`
CIDR string `json:"cidr"`
ZoneID string `json:"zoneId"`
ZoneName string `json:"zoneName"`
VpcStatus string `json:"vpcStatus"`
RegionID string `json:"regionId"`
CreateDate int64 `json:"createDate"`
}
func (self *SVpc) addWire(wire *SWire) {
if self.iwires == nil {
self.iwires = make([]cloudprovider.ICloudWire, 0)
}
self.iwires = append(self.iwires, wire)
}
func (self *SVpc) GetId() string {
return self.ResVpcID
}
func (self *SVpc) GetName() string {
if len(self.Name) > 0 {
return self.Name
}
return self.ResVpcID
}
func (self *SVpc) GetGlobalId() string {
return self.GetId()
}
func (self *SVpc) GetStatus() string {
return api.VPC_STATUS_AVAILABLE
}
func (self *SVpc) Refresh() error {
new, err := self.region.GetVpc(self.GetId())
if err != nil {
return err
}
return jsonutils.Update(self, new)
}
func (self *SVpc) IsEmulated() bool {
return false
}
func (self *SVpc) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SVpc) GetRegion() cloudprovider.ICloudRegion {
return self.region
}
func (self *SVpc) GetIsDefault() bool {
return false
}
func (self *SVpc) GetCidrBlock() string {
return self.CIDR
}
func (self *SVpc) GetIWires() ([]cloudprovider.ICloudWire, error) {
if self.iwires == nil {
err := self.fetchNetworks()
if err != nil {
return nil, err
}
}
return self.iwires, nil
}
// http://ctyun-api-url/apiproxy/v3/getSecurityGroupRules
// http://ctyun-api-url/apiproxy/v3/getSecurityGroups
func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
if self.secgroups == nil {
err := self.fetchSecurityGroups()
if err != nil {
return nil, err
}
}
return self.secgroups, nil
}
func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) {
rts := []cloudprovider.ICloudRouteTable{}
return rts, nil
}
func (self *SVpc) Delete() error {
return cloudprovider.ErrNotImplemented
}
func (self *SVpc) GetIWireById(wireId string) (cloudprovider.ICloudWire, error) {
if self.iwires == nil {
err := self.fetchNetworks()
if err != nil {
return nil, err
}
}
for i := 0; i < len(self.iwires); i += 1 {
if self.iwires[i].GetGlobalId() == wireId {
return self.iwires[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
func (self *SVpc) fetchSecurityGroups() error {
secgroups, err := self.region.GetSecurityGroups("")
if err != nil {
return err
}
self.secgroups = make([]cloudprovider.ICloudSecurityGroup, len(secgroups))
for i := 0; i < len(secgroups); i++ {
secgroups[i].vpc = self
self.secgroups[i] = &secgroups[i]
}
return nil
}
func (self *SVpc) getWireByRegionId(regionId string) *SWire {
if len(regionId) == 0 {
return nil
}
for i := 0; i < len(self.iwires); i++ {
wire := self.iwires[i].(*SWire)
if wire.region.GetId() == regionId {
return wire
}
}
return nil
}
func (self *SVpc) fetchNetworks() error {
networks, err := self.region.GetNetwroks(self.GetId())
if err != nil {
return err
}
if len(networks) == 0 {
self.iwires = append(self.iwires, &SWire{region: self.region, vpc: self})
return nil
}
for i := 0; i < len(networks); i += 1 {
wire := self.getWireByRegionId(self.region.GetId())
networks[i].wire = wire
wire.addNetwork(&networks[i])
}
return nil
}
func (self *SRegion) GetVpc(vpcId string) (*SVpc, error) {
params := map[string]string{
"vpcId": vpcId,
"regionId": self.GetId(),
}
vpc := &SVpc{}
resp, err := self.client.DoGet("/apiproxy/v3/queryVPCDetail", params)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetVpc.DoGet")
}
err = resp.Unmarshal(vpc, "returnObj")
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetVpc.Unmarshal")
}
vpc.region = self
return vpc, nil
}
+115
View File
@@ -0,0 +1,115 @@
// 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 ctyun
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SWire struct {
region *SRegion
vpc *SVpc
inetworks []cloudprovider.ICloudNetwork
}
func (self *SWire) GetId() string {
return fmt.Sprintf("%s-%s", self.vpc.GetId(), self.region.GetId())
}
func (self *SWire) GetName() string {
return self.GetId()
}
func (self *SWire) GetGlobalId() string {
return fmt.Sprintf("%s-%s", self.vpc.GetGlobalId(), self.region.GetGlobalId())
}
func (self *SWire) GetStatus() string {
return "available"
}
func (self *SWire) Refresh() error {
return nil
}
func (self *SWire) IsEmulated() bool {
return true
}
func (self *SWire) GetMetadata() *jsonutils.JSONDict {
return nil
}
// http://ctyun-api-url/apiproxy/v3/queryVPCDetail
func (self *SWire) GetIVpc() cloudprovider.ICloudVpc {
return self.vpc
}
func (self *SWire) GetIZone() cloudprovider.ICloudZone {
return nil
}
// http://ctyun-api-url/apiproxy/v3/getSubnets
func (self *SWire) GetINetworks() ([]cloudprovider.ICloudNetwork, error) {
if self.inetworks == nil {
err := self.vpc.fetchNetworks()
if err != nil {
return nil, err
}
}
return self.inetworks, nil
}
func (self *SWire) GetBandwidth() int {
return 10000
}
func (self *SWire) GetINetworkById(netid string) (cloudprovider.ICloudNetwork, error) {
networks, err := self.GetINetworks()
if err != nil {
return nil, err
}
for i := 0; i < len(networks); i += 1 {
if networks[i].GetGlobalId() == netid {
return networks[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
func (self *SWire) CreateINetwork(name string, cidr string, desc string) (cloudprovider.ICloudNetwork, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SWire) addNetwork(network *SNetwork) {
if self.inetworks == nil {
self.inetworks = make([]cloudprovider.ICloudNetwork, 0)
}
find := false
for i := 0; i < len(self.inetworks); i += 1 {
if self.inetworks[i].GetId() == network.GetId() {
find = true
break
}
}
if !find {
self.inetworks = append(self.inetworks, network)
}
}
+134
View File
@@ -0,0 +1,134 @@
// 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 ctyun
import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SZone struct {
region *SRegion
host *SHost
iwires []cloudprovider.ICloudWire
istorages []cloudprovider.ICloudStorage
/* 支持的磁盘种类集合 */
storageTypes []string
RegionID string `json:"regionId"`
ZoneID string `json:"zoneId"`
ZoneName string `json:"zoneName"`
ZoneType string `json:"zoneType"`
}
func (self *SZone) addWire(wire *SWire) {
if self.iwires == nil {
self.iwires = make([]cloudprovider.ICloudWire, 0)
}
self.iwires = append(self.iwires, wire)
}
func (self *SZone) GetId() string {
return self.ZoneID
}
func (self *SZone) GetName() string {
return self.ZoneName
}
func (self *SZone) GetGlobalId() string {
return self.GetId()
}
func (self *SZone) GetStatus() string {
return "enable"
}
func (self *SZone) Refresh() error {
return nil
}
func (self *SZone) IsEmulated() bool {
return false
}
func (self *SZone) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SZone) GetIRegion() cloudprovider.ICloudRegion {
return self.region
}
func (self *SZone) GetIHosts() ([]cloudprovider.ICloudHost, error) {
return []cloudprovider.ICloudHost{self.getHost()}, nil
}
func (self *SZone) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
host := self.getHost()
if host.GetGlobalId() == id {
return host, nil
}
return nil, cloudprovider.ErrNotFound
}
func (self *SZone) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
if self.istorages == nil {
self.fetchStorages()
}
return self.istorages, nil
}
func (self *SZone) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
if self.istorages == nil {
self.fetchStorages()
}
for i := 0; i < len(self.istorages); i += 1 {
if self.istorages[i].GetGlobalId() == id {
return self.istorages[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
func (self *SZone) getHost() *SHost {
if self.host == nil {
self.host = &SHost{zone: self, projectId: self.region.client.projectId}
}
return self.host
}
func (self *SZone) fetchStorages() error {
self.getStorageType()
self.istorages = make([]cloudprovider.ICloudStorage, len(self.storageTypes))
for i, sc := range self.storageTypes {
storage := SStorage{zone: self, storageType: sc}
self.istorages[i] = &storage
}
return nil
}
func (self *SZone) getStorageType() {
if len(self.storageTypes) == 0 {
self.storageTypes = StorageTypes
}
}
func (self *SZone) GetIWires() ([]cloudprovider.ICloudWire, error) {
return self.iwires, nil
}
+14
View File
@@ -1 +1,15 @@
// 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 google // import "yunion.io/x/onecloud/pkg/multicloud/google"
+14
View File
@@ -1 +1,15 @@
// 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 provider // import "yunion.io/x/onecloud/pkg/multicloud/google/provider"
+14
View File
@@ -1 +1,15 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell // import "yunion.io/x/onecloud/pkg/multicloud/google/shell"
+1
View File
@@ -20,6 +20,7 @@ import (
_ "yunion.io/x/onecloud/pkg/multicloud/aliyun/provider"
_ "yunion.io/x/onecloud/pkg/multicloud/aws/provider"
_ "yunion.io/x/onecloud/pkg/multicloud/azure/provider"
_ "yunion.io/x/onecloud/pkg/multicloud/ctyun/provider"
_ "yunion.io/x/onecloud/pkg/multicloud/esxi/provider" // private clouds
_ "yunion.io/x/onecloud/pkg/multicloud/google/provider" // public clouds
_ "yunion.io/x/onecloud/pkg/multicloud/huawei/provider"