mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-06-20 23:26:13 +08:00
403 lines
9.7 KiB
Go
403 lines
9.7 KiB
Go
// 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 jdcloud
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
commodels "github.com/jdcloud-api/jdcloud-sdk-go/services/common/models"
|
|
"github.com/jdcloud-api/jdcloud-sdk-go/services/vm/apis"
|
|
"github.com/jdcloud-api/jdcloud-sdk-go/services/vm/client"
|
|
"github.com/jdcloud-api/jdcloud-sdk-go/services/vm/models"
|
|
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/log"
|
|
"yunion.io/x/pkg/errors"
|
|
"yunion.io/x/pkg/util/sets"
|
|
|
|
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
|
|
multicloud.SBillingBase
|
|
multicloud.JdcloudTags
|
|
|
|
host *SHost
|
|
image *SImage
|
|
|
|
models.Instance
|
|
|
|
instanceType *SInstanceType
|
|
}
|
|
|
|
func (i *SInstance) GetBillingType() string {
|
|
return billingType(&i.Charge)
|
|
}
|
|
|
|
func (i *SInstance) GetExpiredAt() time.Time {
|
|
return expireAt(&i.Charge)
|
|
}
|
|
|
|
func (i *SInstance) GetId() string {
|
|
return i.InstanceId
|
|
}
|
|
|
|
func (i *SInstance) GetName() string {
|
|
return i.InstanceName
|
|
}
|
|
|
|
func (i *SInstance) GetGlobalId() string {
|
|
return i.GetId()
|
|
}
|
|
|
|
func (i *SInstance) GetStatus() string {
|
|
switch i.Status {
|
|
case "pending":
|
|
return api.VM_DEPLOYING
|
|
case "starting":
|
|
return api.VM_STARTING
|
|
case "running":
|
|
return api.VM_RUNNING
|
|
case "stopping":
|
|
return api.VM_STOPPING
|
|
case "stopped":
|
|
return api.VM_READY
|
|
case "reboot":
|
|
return api.VM_STARTING
|
|
case "rebuilding":
|
|
return api.VM_REBUILD_ROOT
|
|
case "resizing":
|
|
return api.VM_CHANGE_FLAVOR
|
|
case "deleting":
|
|
return api.VM_DELETING
|
|
default:
|
|
return api.VM_UNKNOWN
|
|
}
|
|
}
|
|
|
|
func (i *SInstance) Refresh() error {
|
|
return nil
|
|
}
|
|
|
|
func (i *SInstance) IsEmulated() bool {
|
|
return false
|
|
}
|
|
|
|
func (i *SInstance) GetBootOrder() string {
|
|
return "dcn"
|
|
}
|
|
|
|
func (i *SInstance) GetVga() string {
|
|
return "std"
|
|
}
|
|
|
|
func (i *SInstance) GetVdi() string {
|
|
return "vnc"
|
|
}
|
|
|
|
func (i *SInstance) GetImage() (*SImage, error) {
|
|
if i.image != nil {
|
|
return i.image, nil
|
|
}
|
|
image, err := i.host.zone.region.GetImage(i.ImageId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
i.image = image
|
|
return i.image, nil
|
|
}
|
|
|
|
func (i *SInstance) GetOsType() cloudprovider.TOsType {
|
|
image, err := i.GetImage()
|
|
if err != nil {
|
|
return cloudprovider.OsTypeLinux
|
|
}
|
|
return image.GetOsType()
|
|
}
|
|
|
|
func (i *SInstance) GetOSName() string {
|
|
image, err := i.GetImage()
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return image.Architecture
|
|
}
|
|
|
|
func (i *SInstance) GetBios() string {
|
|
return "BIOS"
|
|
}
|
|
|
|
func (i *SInstance) GetMachine() string {
|
|
return "pc"
|
|
}
|
|
|
|
func (i *SInstance) GetInstanceType() string {
|
|
return i.InstanceType
|
|
}
|
|
|
|
func (in *SInstance) GetProjectId() string {
|
|
return ""
|
|
}
|
|
|
|
func (in *SInstance) GetIHost() cloudprovider.ICloudHost {
|
|
return in.host
|
|
}
|
|
|
|
func (in *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
|
disks := make([]cloudprovider.ICloudDisk, 0, len(in.DataDisks)+1)
|
|
if in.SystemDisk.DiskCategory != "local" {
|
|
disk := &SDisk{
|
|
Disk: in.SystemDisk.CloudDisk,
|
|
ImageId: in.ImageId,
|
|
IsSystemDisk: true,
|
|
}
|
|
stroage, err := in.host.zone.getStorageByType(disk.DiskType)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "unable to find storage with type %s", disk.DiskType)
|
|
}
|
|
disk.storage = stroage
|
|
disks = append(disks, disk)
|
|
}
|
|
for i := range in.DataDisks {
|
|
disk := &SDisk{
|
|
Disk: in.DataDisks[i].CloudDisk,
|
|
}
|
|
stroage, err := in.host.zone.getStorageByType(disk.DiskType)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "unable to find storage with type %s", disk.DiskType)
|
|
}
|
|
disk.storage = stroage
|
|
disks = append(disks, disk)
|
|
}
|
|
return disks, nil
|
|
}
|
|
|
|
func (in *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
|
|
nis := make([]cloudprovider.ICloudNic, 0, len(in.SecondaryNetworkInterfaces)+1)
|
|
nis = append(nis, &SInstanceNic{
|
|
instance: in,
|
|
InstanceNetworkInterface: in.PrimaryNetworkInterface.NetworkInterface,
|
|
})
|
|
for i := range in.SecondaryNetworkInterfaces {
|
|
nis = append(nis, &SInstanceNic{
|
|
instance: in,
|
|
InstanceNetworkInterface: in.SecondaryNetworkInterfaces[i].NetworkInterface,
|
|
})
|
|
}
|
|
return nis, nil
|
|
}
|
|
|
|
func (in *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
|
eip, err := in.host.zone.region.GetEIPById(in.ElasticIpId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return eip, nil
|
|
}
|
|
|
|
func (in *SInstance) GetSecurityGroupIds() ([]string, error) {
|
|
ids := sets.NewString()
|
|
for _, sg := range in.PrimaryNetworkInterface.NetworkInterface.SecurityGroups {
|
|
ids.Insert(sg.GroupId)
|
|
}
|
|
for i := range in.SecondaryNetworkInterfaces {
|
|
for _, sg := range in.SecondaryNetworkInterfaces[i].NetworkInterface.SecurityGroups {
|
|
ids.Insert(sg.GroupId)
|
|
}
|
|
}
|
|
return ids.UnsortedList(), nil
|
|
}
|
|
|
|
func (in *SInstance) fetchInstanceType() error {
|
|
its, err := in.host.zone.region.InstanceTypes(in.InstanceType)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(its) == 0 {
|
|
return cloudprovider.ErrNotFound
|
|
}
|
|
for i := range its {
|
|
if its[i].InstanceType.InstanceType == in.InstanceType {
|
|
in.instanceType = &its[i]
|
|
return nil
|
|
}
|
|
}
|
|
return cloudprovider.ErrNotFound
|
|
}
|
|
|
|
func (in *SInstance) GetVcpuCount() int {
|
|
if in.instanceType == nil {
|
|
err := in.fetchInstanceType()
|
|
if err != nil {
|
|
log.Errorf("unable to get instance type %s: %v", in.InstanceType, err)
|
|
return 0
|
|
}
|
|
}
|
|
return in.instanceType.GetCpu()
|
|
}
|
|
|
|
func (in *SInstance) GetVmemSizeMB() int {
|
|
if in.instanceType == nil {
|
|
err := in.fetchInstanceType()
|
|
if err != nil {
|
|
log.Errorf("unable to get instance type %s", in.InstanceType)
|
|
return 0
|
|
}
|
|
}
|
|
return in.instanceType.GetMemoryMB()
|
|
}
|
|
|
|
func (in *SInstance) AssignSecurityGroup(id string) error {
|
|
return cloudprovider.ErrNotImplemented
|
|
}
|
|
|
|
func (in *SInstance) SetSecurityGroups(ids []string) error {
|
|
return cloudprovider.ErrNotImplemented
|
|
}
|
|
|
|
func (in *SInstance) GetHypervisor() string {
|
|
return api.HYPERVISOR_JDCLOUD
|
|
}
|
|
|
|
func (in *SInstance) StartVM(ctx context.Context) error {
|
|
return cloudprovider.ErrNotImplemented
|
|
}
|
|
|
|
func (in *SInstance) StopVM(ctx context.Context, opts *cloudprovider.ServerStopOptions) error {
|
|
return cloudprovider.ErrNotImplemented
|
|
}
|
|
|
|
func (in *SInstance) DeleteVM(ctx context.Context) error {
|
|
return cloudprovider.ErrNotImplemented
|
|
}
|
|
|
|
func (in *SInstance) UpdateVM(ctx context.Context, name string) error {
|
|
return cloudprovider.ErrNotSupported
|
|
}
|
|
|
|
func (in *SInstance) UpdateUserData(userData string) error {
|
|
return cloudprovider.ErrNotSupported
|
|
}
|
|
|
|
func (self *SInstance) RebuildRoot(ctx context.Context, config *cloudprovider.SManagedVMRebuildRootConfig) (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 (in *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.SManagedVMChangeConfig) error {
|
|
return cloudprovider.ErrNotImplemented
|
|
}
|
|
|
|
func (in *SInstance) GetVNCInfo() (jsonutils.JSONObject, error) {
|
|
region := in.host.zone.region
|
|
req := apis.NewDescribeInstanceVncUrlRequest(region.ID, in.InstanceId)
|
|
client := client.NewVmClient(region.Credential)
|
|
client.Logger = Logger{}
|
|
resp, err := client.DescribeInstanceVncUrl(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
url := resp.Result.VncUrl
|
|
|
|
ret := jsonutils.NewDict()
|
|
ret.Add(jsonutils.NewString(url), "url")
|
|
ret.Add(jsonutils.NewString("jdcloud"), "protocol")
|
|
ret.Add(jsonutils.NewString(in.GetId()), "instance_id")
|
|
return ret, nil
|
|
}
|
|
|
|
func (in *SInstance) AttachDisk(ctx context.Context, diskId string) error {
|
|
return cloudprovider.ErrNotImplemented
|
|
}
|
|
|
|
func (in *SInstance) DetachDisk(ctx context.Context, diskId string) error {
|
|
return cloudprovider.ErrNotImplemented
|
|
}
|
|
|
|
func (self *SInstance) Renew(bc billing.SBillingCycle) error {
|
|
return cloudprovider.ErrNotImplemented
|
|
}
|
|
|
|
func (self *SInstance) GetError() error {
|
|
return nil
|
|
}
|
|
|
|
func (r *SRegion) GetInstances(zoneId string, ids []string, pangeNumber, pageSize int) ([]SInstance, int, error) {
|
|
filters := []commodels.Filter{}
|
|
if zoneId != "" {
|
|
filters = append(filters, commodels.Filter{
|
|
Name: "az",
|
|
Values: []string{zoneId},
|
|
})
|
|
}
|
|
if len(ids) > 0 {
|
|
filters = append(filters, commodels.Filter{
|
|
Name: "instanceId",
|
|
Values: ids,
|
|
})
|
|
}
|
|
req := apis.NewDescribeInstancesRequestWithAllParams(r.ID, &pangeNumber, &pageSize, filters)
|
|
client := client.NewVmClient(r.Credential)
|
|
client.Logger = Logger{}
|
|
resp, err := client.DescribeInstances(req)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
if resp.Error.Code >= 400 {
|
|
return nil, 0, fmt.Errorf(resp.Error.Message)
|
|
}
|
|
ins := make([]SInstance, len(resp.Result.Instances))
|
|
for i := range ins {
|
|
ins[i] = SInstance{
|
|
Instance: resp.Result.Instances[i],
|
|
}
|
|
}
|
|
return ins, resp.Result.TotalCount, nil
|
|
}
|
|
|
|
func (r *SRegion) GetInstanceById(id string) (*SInstance, error) {
|
|
req := apis.NewDescribeInstanceRequest(r.ID, id)
|
|
client := client.NewVmClient(r.Credential)
|
|
client.Logger = Logger{}
|
|
resp, err := client.DescribeInstance(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &SInstance{
|
|
Instance: resp.Result.Instance,
|
|
}, nil
|
|
}
|
|
|
|
func (r *SRegion) FillHost(instance *SInstance) {
|
|
izone, err := r.getIZoneByRealId(instance.Az)
|
|
if err != nil {
|
|
log.Errorf("unable to find zone %s: %v", instance.Az, err)
|
|
return
|
|
}
|
|
zone := izone.(*SZone)
|
|
instance.host = &SHost{
|
|
zone: zone,
|
|
}
|
|
}
|