mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #161 in YUNIONIO/onecloud from ~QIUJIAN/onecloud:feature/qj-elastic-ip to release/2.1.0
* commit '82bbb2054b9d72b542ea5d4d3aea931fe1103f26': fix log 修正:1. 已经绑定的EIP禁止删除 2. 删除server时候清除public IP记录 浮动IP支持 temp commit
This commit is contained in:
+16
-8
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
prompt "github.com/c-bata/go-prompt"
|
||||
"github.com/c-bata/go-prompt"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/version"
|
||||
@@ -28,7 +28,7 @@ type BaseOptions struct {
|
||||
Version bool `help:"Show version"`
|
||||
Timeout int `default:"600" help:"Number of seconds to wait for a response"`
|
||||
Insecure bool `default:"false" help:"Allow skip server cert verification if URL is https" short-token:"k"`
|
||||
NoCachedToken bool `default:"false" help:"Force not use cached token"`
|
||||
NoCachedToken bool `default:"$NO_CACHED_TOKEN|false" help:"Force not use cached token"`
|
||||
OsUsername string `default:"$OS_USERNAME" help:"Username, defaults to env[OS_USERNAME]"`
|
||||
OsPassword string `default:"$OS_PASSWORD" help:"Password, defaults to env[OS_PASSWORD]"`
|
||||
// OsProjectId string `default:"$OS_PROJECT_ID" help:"Proejct ID, defaults to env[OS_PROJECT_ID]"`
|
||||
@@ -126,8 +126,11 @@ func newClientSession(options *BaseOptions) (*mcclient.ClientSession, error) {
|
||||
options.Insecure)
|
||||
|
||||
var cacheToken mcclient.TokenCredential
|
||||
tokenCachePath := filepath.Join(os.TempDir(), "OS_AUTH_CACHE_TOKEN")
|
||||
authUrlAlter := strings.Replace(options.OsAuthURL, "/", "", -1)
|
||||
authUrlAlter = strings.Replace(authUrlAlter, ":", "", -1)
|
||||
tokenCachePath := filepath.Join(os.TempDir(), fmt.Sprintf("OS_AUTH_CACHE_TOKEN-%s-%s-%s-%s", authUrlAlter, options.OsUsername, options.OsDomainName, options.OsProjectName))
|
||||
cacheFile, err := os.Open(tokenCachePath)
|
||||
|
||||
if err == nil && cacheFile != nil && !options.NoCachedToken {
|
||||
fileInfo, _ := cacheFile.Stat()
|
||||
dur, err := time.ParseDuration("-24h")
|
||||
@@ -138,13 +141,14 @@ func newClientSession(options *BaseOptions) (*mcclient.ClientSession, error) {
|
||||
err := json.Unmarshal(bytesToken, token)
|
||||
if err != nil {
|
||||
fmt.Printf("Unmarshal token error:%s", err)
|
||||
} else {
|
||||
} else if token.IsValid() {
|
||||
cacheToken = token
|
||||
}
|
||||
}
|
||||
cacheFile.Close()
|
||||
}
|
||||
}
|
||||
|
||||
if cacheToken == nil {
|
||||
token, err := client.Authenticate(options.OsUsername,
|
||||
options.OsPassword,
|
||||
@@ -158,12 +162,16 @@ func newClientSession(options *BaseOptions) (*mcclient.ClientSession, error) {
|
||||
if err != nil {
|
||||
fmt.Printf("Marshal token error:%s", err)
|
||||
} else {
|
||||
fo, _ := os.Create(tokenCachePath)
|
||||
fo.Write(bytesCacheToken)
|
||||
fo.Close()
|
||||
fo, err := os.Create(tokenCachePath)
|
||||
if err != nil {
|
||||
fmt.Printf("Save token cache fail: %s", err)
|
||||
} else {
|
||||
fo.Write(bytesCacheToken)
|
||||
fo.Close()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("******** Use Token Cache At %s ********\n", tokenCachePath)
|
||||
// fmt.Printf("******** Use Token Cache At %s ********\n", tokenCachePath)
|
||||
}
|
||||
|
||||
session := client.NewSession(options.OsRegionName,
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ElasticipListOptions struct {
|
||||
Manager string `help:"Show servers imported from manager"`
|
||||
Region string `help:"Show servers in cloudregion"`
|
||||
|
||||
options.BaseListOptions
|
||||
}
|
||||
R(&ElasticipListOptions{}, "eip-list", "List elastic IPs", func(s *mcclient.ClientSession, args *ElasticipListOptions) error {
|
||||
var params *jsonutils.JSONDict
|
||||
{
|
||||
var err error
|
||||
params, err = args.BaseListOptions.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(args.Manager) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Manager), "manager")
|
||||
}
|
||||
if len(args.Region) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Region), "region")
|
||||
}
|
||||
results, err := modules.Elasticips.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(results, modules.Elasticips.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipCreateOptions struct {
|
||||
MANAGER string `help:"cloud provider"`
|
||||
REGION string `help:"cloud region in which EIP is allocated"`
|
||||
NAME string `help:"name of the EIP"`
|
||||
BW int `help:"Bandwidth in Mbps"`
|
||||
ChargeType string `help:"bandwidth charge type, either traffic or bandwidth" choices:"traffic|bandwidth"`
|
||||
}
|
||||
R(&EipCreateOptions{}, "eip-create", "Create an EIP", func(s *mcclient.ClientSession, args *EipCreateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.MANAGER), "manager")
|
||||
params.Add(jsonutils.NewString(args.REGION), "region")
|
||||
params.Add(jsonutils.NewString(args.NAME), "name")
|
||||
params.Add(jsonutils.NewInt(int64(args.BW)), "bandwidth")
|
||||
|
||||
if len(args.ChargeType) > 0 {
|
||||
params.Add(jsonutils.NewString(args.ChargeType), "charge_type")
|
||||
}
|
||||
|
||||
result, err := modules.Elasticips.Create(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipDeleteOptions struct {
|
||||
ID string `help:"ID or name of EIP"`
|
||||
}
|
||||
R(&EipDeleteOptions{}, "eip-delete", "Delete an EIP", func(s *mcclient.ClientSession, args *EipDeleteOptions) error {
|
||||
result, err := modules.Elasticips.Delete(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipUpdateOptions struct {
|
||||
ID string `help:"ID or name of EIP"`
|
||||
Name string `help:"New name of EIP"`
|
||||
Desc string `help:"New description of EIP"`
|
||||
}
|
||||
R(&EipUpdateOptions{}, "eip-update", "Update EIP properties", func(s *mcclient.ClientSession, args *EipUpdateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if len(args.Name) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Name), "name")
|
||||
}
|
||||
if len(args.Desc) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Desc), "description")
|
||||
}
|
||||
result, err := modules.Elasticips.Update(s, args.ID, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipAssociateOptions struct {
|
||||
ID string `help:"ID or name of EIP"`
|
||||
INSTANCEID string `help:"ID of instance the eip associated with"`
|
||||
InstanceType string `default:"server" help:"Instance type that the eip associated with, default is server" choices:"server"`
|
||||
}
|
||||
R(&EipAssociateOptions{}, "eip-associate", "Associate an EIP to an instance", func(s *mcclient.ClientSession, args *EipAssociateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.InstanceType), "instance_type")
|
||||
params.Add(jsonutils.NewString(args.INSTANCEID), "instance_id")
|
||||
result, err := modules.Elasticips.PerformAction(s, args.ID, "associate", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipSingleOptions struct {
|
||||
ID string `help:"ID or name of EIP"`
|
||||
}
|
||||
R(&EipSingleOptions{}, "eip-dissociate", "Dissociate an EIP from an instance", func(s *mcclient.ClientSession, args *EipSingleOptions) error {
|
||||
result, err := modules.Elasticips.PerformAction(s, args.ID, "dissociate", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&EipSingleOptions{}, "eip-sync", "Synchronize status of an EIP", func(s *mcclient.ClientSession, args *EipSingleOptions) error {
|
||||
result, err := modules.Elasticips.PerformAction(s, args.ID, "sync", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type ServerCreateEipOptions struct {
|
||||
ID string `help:"server ID or name"`
|
||||
BW int `help:"EIP bandwidth in Mbps"`
|
||||
ChargeType string `help:"bandwidth charge type, either traffic or bandwidth" choices:"traffic|bandwidth"`
|
||||
}
|
||||
R(&ServerCreateEipOptions{}, "server-create-eip", "allocate an EIP and associate EIP to server", func(s *mcclient.ClientSession, args *ServerCreateEipOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewInt(int64(args.BW)), "bandwidth")
|
||||
|
||||
if len(args.ChargeType) > 0 {
|
||||
params.Add(jsonutils.NewString(args.ChargeType), "charge_type")
|
||||
}
|
||||
|
||||
result, err := modules.Servers.PerformAction(s, args.ID, "create-eip", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipShowOptions struct {
|
||||
ID string `help:"ID or name of EIP"`
|
||||
}
|
||||
R(&EipShowOptions{}, "eip-show", "show details of an EIP", func(s *mcclient.ClientSession, args *EipShowOptions) error {
|
||||
result, err := modules.Servers.Get(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipChangeBandwidthOptions struct {
|
||||
ID string `help:"ID or name of the EIP"`
|
||||
BW int `help:"new bandwidth of EIP"`
|
||||
}
|
||||
R(&EipChangeBandwidthOptions{}, "eip-change-bandwidth", "Change maximal bandwidth of EIP", func(s *mcclient.ClientSession, args *EipChangeBandwidthOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewInt(int64(args.BW)), "bandwidth")
|
||||
result, err := modules.Elasticips.PerformAction(s, args.ID, "change-bandwidth", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -133,6 +133,8 @@ const (
|
||||
ACT_GUEST_ATTACH_ISOLATED_DEVICE_FAIL = "guest_attach_isolated_deivce_fail"
|
||||
ACT_GUEST_DETACH_ISOLATED_DEVICE = "guest_detach_isolated_deivce"
|
||||
ACT_GUEST_DETACH_ISOLATED_DEVICE_FAIL = "guest_detach_isolated_deivce_fail"
|
||||
|
||||
ACT_CHANGE_BANDWIDTH = "eip_change_bandwidth"
|
||||
)
|
||||
|
||||
type SOpsLogManager struct {
|
||||
|
||||
@@ -29,6 +29,7 @@ type ICloudRegion interface {
|
||||
|
||||
GetIZones() ([]ICloudZone, error)
|
||||
GetIVpcs() ([]ICloudVpc, error)
|
||||
GetIEips() ([]ICloudEIP, error)
|
||||
|
||||
GetIZoneById(id string) (ICloudZone, error)
|
||||
GetIVpcById(id string) (ICloudVpc, error)
|
||||
@@ -38,6 +39,10 @@ type ICloudRegion interface {
|
||||
|
||||
CreateIVpc(name string, desc string, cidr string) (ICloudVpc, error)
|
||||
|
||||
CreateEIP(bwMbps int) (ICloudEIP, error)
|
||||
|
||||
GetIEipById(id string) (ICloudEIP, error)
|
||||
|
||||
GetProvider() string
|
||||
}
|
||||
|
||||
@@ -134,7 +139,7 @@ type ICloudVM interface {
|
||||
GetIDisks() ([]ICloudDisk, error)
|
||||
GetINics() ([]ICloudNic, error)
|
||||
|
||||
GetEIP() ICloudEIP
|
||||
GetIEIP() (ICloudEIP, error)
|
||||
|
||||
// GetStatus() string
|
||||
// GetRemoteStatus() string
|
||||
@@ -175,9 +180,25 @@ type ICloudNic interface {
|
||||
}
|
||||
|
||||
type ICloudEIP interface {
|
||||
GetIP() string
|
||||
GetAllocationId() string
|
||||
GetChargeType() string
|
||||
ICloudResource
|
||||
|
||||
GetIpAddr() string
|
||||
GetMode() string
|
||||
GetAssociationType() string
|
||||
GetAssociationExternalId() string
|
||||
|
||||
GetBandwidth() int
|
||||
|
||||
GetInternetChargeType() string
|
||||
|
||||
GetManagerId() string
|
||||
|
||||
Delete() error
|
||||
|
||||
Associate(instanceId string) error
|
||||
Dissociate() error
|
||||
|
||||
ChangeBandwidth(bw int) error
|
||||
}
|
||||
|
||||
type ICloudSecurityGroup interface {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package cloudprovider
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
)
|
||||
|
||||
func WaitStatus(res ICloudResource, expect string, interval time.Duration, timeout time.Duration) error {
|
||||
startTime := time.Now()
|
||||
@@ -9,6 +13,7 @@ func WaitStatus(res ICloudResource, expect string, interval time.Duration, timeo
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("status %s expect %s", res.GetStatus(), expect)
|
||||
if res.GetStatus() == expect {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ func InitHandlers(app *appsrv.Application) {
|
||||
models.SecurityGroupRuleManager,
|
||||
models.VCenterManager,
|
||||
models.DnsRecordManager,
|
||||
models.ElasticipManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
handler := db.NewModelHandler(manager)
|
||||
|
||||
@@ -86,6 +86,10 @@ func (self *SCloudprovider) getStoragecacheCount() int {
|
||||
return StoragecacheManager.Query().Equals("manager_id", self.Id).Count()
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) getEipCount() int {
|
||||
return ElasticipManager.Query().Equals("manager_id", self.Id).Count()
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
}
|
||||
@@ -383,7 +387,9 @@ func (manager *SCloudproviderManager) FetchCloudproviderById(providerId string)
|
||||
func (manager *SCloudproviderManager) FetchCloudproviderByIdOrName(providerId string) *SCloudprovider {
|
||||
providerObj, err := manager.FetchByIdOrName("", providerId)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
if err != sql.ErrNoRows {
|
||||
log.Errorf("%s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return providerObj.(*SCloudprovider)
|
||||
@@ -394,6 +400,7 @@ type SCloudproviderUsage struct {
|
||||
VpcCount int
|
||||
StorageCount int
|
||||
StorageCacheCount int
|
||||
EipCount int
|
||||
}
|
||||
|
||||
func (usage *SCloudproviderUsage) isEmpty() bool {
|
||||
@@ -409,6 +416,9 @@ func (usage *SCloudproviderUsage) isEmpty() bool {
|
||||
if usage.StorageCacheCount > 0 {
|
||||
return false
|
||||
}
|
||||
if usage.EipCount > 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -418,6 +428,7 @@ func (self *SCloudprovider) getUsage() *SCloudproviderUsage {
|
||||
usage.VpcCount = self.getVpcCount()
|
||||
usage.StorageCount = self.getStorageCount()
|
||||
usage.StorageCacheCount = self.getStoragecacheCount()
|
||||
usage.EipCount = self.getEipCount()
|
||||
|
||||
return &usage
|
||||
}
|
||||
|
||||
@@ -0,0 +1,750 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
)
|
||||
|
||||
const (
|
||||
EIP_MODE_INSTANCE_PUBLICIP = "public_ip"
|
||||
EIP_MODE_STANDALONE_EIP = "elastic_ip"
|
||||
|
||||
EIP_ASSOCIATE_TYPE_SERVER = "server"
|
||||
|
||||
EIP_STATUS_READY = "ready"
|
||||
EIP_STATUS_UNKNOWN = "unknown"
|
||||
EIP_STATUS_ALLOCATE = "allocate"
|
||||
EIP_STATUS_ALLOCATE_FAIL = "allocate_fail"
|
||||
EIP_STATUS_DEALLOCATE = "deallocate"
|
||||
EIP_STATUS_DEALLOCATE_FAIL = "deallocate_fail"
|
||||
EIP_STATUS_ASSOCIATE = "associate"
|
||||
EIP_STATUS_ASSOCIATE_FAIL = "associate_fail"
|
||||
EIP_STATUS_DISSOCIATE = "dissociate"
|
||||
EIP_STATUS_DISSOCIATE_FAIL = "dissociate_fail"
|
||||
|
||||
EIP_CHARGE_TYPE_BY_TRAFFIC = "traffic"
|
||||
EIP_CHARGE_TYPE_BY_BANDWIDTH = "bandwidth"
|
||||
EIP_CHARGE_TYPE_DEFAULT = EIP_CHARGE_TYPE_BY_TRAFFIC
|
||||
)
|
||||
|
||||
type SElasticipManager struct {
|
||||
db.SVirtualResourceBaseManager
|
||||
}
|
||||
|
||||
var ElasticipManager *SElasticipManager
|
||||
|
||||
func init() {
|
||||
ElasticipManager = &SElasticipManager{SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(SElasticip{}, "elasticips_tbl", "eip", "eips")}
|
||||
}
|
||||
|
||||
type SElasticip struct {
|
||||
db.SVirtualResourceBase
|
||||
|
||||
SManagedResourceBase
|
||||
|
||||
Mode string `width:"32" charset:"ascii" list:"user"`
|
||||
|
||||
IpAddr string `width:"17" charset:"ascii" list:"user"`
|
||||
|
||||
AssociateType string `width:"32" charset:"ascii" list:"user"`
|
||||
AssociateId string `width:"128" charset:"ascii" list:"user"`
|
||||
|
||||
Bandwidth int `list:"user" create:"required"`
|
||||
|
||||
ChargeType string `list:"user" create:"required" default:"traffic"`
|
||||
|
||||
AutoDellocate tristate.TriState `default:"false" get:"user" create:"optional"`
|
||||
|
||||
CloudregionId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
}
|
||||
|
||||
|
||||
func (manager *SElasticipManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
managerFilter, _ := query.GetString("manager")
|
||||
if len(managerFilter) > 0 {
|
||||
managerI, err := CloudproviderManager.FetchByIdOrName(userCred.GetProjectId(), managerFilter)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("cloud provider %s not found", managerFilter)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
}
|
||||
q = q.Equals("manager_id", managerI.GetId())
|
||||
}
|
||||
|
||||
regionFilter, _ := query.GetString("region")
|
||||
if len(regionFilter) > 0 {
|
||||
regionObj, err := CloudregionManager.FetchByIdOrName(userCred.GetProjectId(), regionFilter)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("cloud region %s not found", regionFilter)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
}
|
||||
q = q.Equals("cloudregion_id", regionObj.GetId())
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) getEipsByRegion(region *SCloudregion, provider *SCloudprovider) ([]SElasticip, error) {
|
||||
eips := make([]SElasticip, 0)
|
||||
q := manager.Query().Equals("cloudregion_id", region.Id)
|
||||
if provider != nil {
|
||||
q = q.Equals("manager_id", provider.Id)
|
||||
}
|
||||
err := db.FetchModelObjects(manager, q, &eips)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return eips, nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) GetRegion() *SCloudregion {
|
||||
return CloudregionManager.FetchRegionById(self.CloudregionId)
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) SyncEips(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, eips []cloudprovider.ICloudEIP) (compare.SyncResult) {
|
||||
// localEips := make([]SElasticip, 0)
|
||||
// remoteEips := make([]cloudprovider.ICloudEIP, 0)
|
||||
syncResult := compare.SyncResult{}
|
||||
|
||||
dbEips, err := manager.getEipsByRegion(region, provider)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
|
||||
removed := make([]SElasticip, 0)
|
||||
commondb := make([]SElasticip, 0)
|
||||
commonext := make([]cloudprovider.ICloudEIP, 0)
|
||||
added := make([]cloudprovider.ICloudEIP, 0)
|
||||
|
||||
err = compare.CompareSets(dbEips, eips, &removed, &commondb, &commonext, &added)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i += 1 {
|
||||
err = removed[i].SetStatus(userCred, EIP_STATUS_UNKNOWN, "sync to delete")
|
||||
if err != nil {
|
||||
syncResult.DeleteError(err)
|
||||
} else {
|
||||
syncResult.Delete()
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].SyncWithCloudEip(userCred, commonext[i])
|
||||
if err != nil {
|
||||
syncResult.UpdateError(err)
|
||||
} else {
|
||||
syncResult.Update()
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
_, err := manager.newFromCloudEip(userCred, added[i], region)
|
||||
if err != nil {
|
||||
syncResult.AddError(err)
|
||||
} else {
|
||||
syncResult.Add()
|
||||
}
|
||||
}
|
||||
|
||||
return syncResult
|
||||
}
|
||||
|
||||
func (self *SElasticip) SyncInstanceWithCloudEip(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudEIP) error {
|
||||
vm := self.getVM()
|
||||
vmExtId := ext.GetAssociationExternalId()
|
||||
|
||||
if vm == nil && len(vmExtId) == 0 {
|
||||
return nil
|
||||
}
|
||||
if vm != nil && vm.ExternalId == vmExtId {
|
||||
return nil
|
||||
}
|
||||
|
||||
if vm != nil { // dissociate
|
||||
err := self.Dissociate(ctx, userCred)
|
||||
if err != nil {
|
||||
log.Errorf("fail to dissociate vm: %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(vmExtId) > 0 {
|
||||
newVM, err := GuestManager.FetchByExternalId(vmExtId)
|
||||
if err != nil {
|
||||
log.Errorf("fail to find vm by external ID %s", vmExtId)
|
||||
return err
|
||||
}
|
||||
err = self.AssociateVM(userCred, newVM.(*SGuest))
|
||||
if err != nil {
|
||||
log.Errorf("fail to associate with new vm %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) SyncWithCloudEip(userCred mcclient.TokenCredential, ext cloudprovider.ICloudEIP) error {
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
|
||||
// self.Name = ext.GetName()
|
||||
self.Bandwidth = ext.GetBandwidth()
|
||||
self.IpAddr = ext.GetIpAddr()
|
||||
self.Mode = ext.GetMode()
|
||||
self.Status = ext.GetStatus()
|
||||
self.ExternalId = ext.GetGlobalId()
|
||||
// self.ManagerId = ext.GetManagerId()
|
||||
self.IsEmulated = ext.IsEmulated()
|
||||
// self.ProjectId = userCred.GetProjectId()
|
||||
self.ChargeType = ext.GetInternetChargeType()
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("SyncWithCloudEip fail %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) newFromCloudEip(userCred mcclient.TokenCredential, extEip cloudprovider.ICloudEIP, region *SCloudregion) (*SElasticip, error) {
|
||||
eip := SElasticip{}
|
||||
eip.SetModelManager(manager)
|
||||
|
||||
eip.Name = extEip.GetName()
|
||||
eip.Status = extEip.GetStatus()
|
||||
eip.ExternalId = extEip.GetGlobalId()
|
||||
eip.IpAddr = extEip.GetIpAddr()
|
||||
eip.Mode = extEip.GetMode()
|
||||
eip.IsEmulated = extEip.IsEmulated()
|
||||
eip.ManagerId = extEip.GetManagerId()
|
||||
eip.CloudregionId = region.Id
|
||||
eip.ChargeType = extEip.GetInternetChargeType()
|
||||
|
||||
eip.ProjectId = userCred.GetProjectId()
|
||||
|
||||
err := manager.TableSpec().Insert(&eip)
|
||||
if err != nil {
|
||||
log.Errorf("newFromCloudEip fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
return &eip, nil
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) getEipForInstance(instanceType string, instanceId string) (*SElasticip, error) {
|
||||
eip := SElasticip{}
|
||||
|
||||
q := manager.Query()
|
||||
q = q.Equals("associate_type", instanceType)
|
||||
q = q.Equals("associate_id", instanceId)
|
||||
|
||||
err := q.First(&eip)
|
||||
|
||||
if err != nil {
|
||||
if err != sql.ErrNoRows {
|
||||
log.Errorf("getEipForInstance query fail %s", err)
|
||||
return nil, err
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
eip.SetModelManager(manager)
|
||||
|
||||
return &eip, nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) getVM() *SGuest {
|
||||
if self.AssociateType == "server" && len(self.AssociateId) > 0 {
|
||||
return GuestManager.FetchGuestById(self.AssociateId)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) Dissociate(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if len(self.AssociateType) == 0 {
|
||||
return nil
|
||||
}
|
||||
vm := self.getVM()
|
||||
if vm == nil {
|
||||
log.Errorf("dissociate VM not exists???")
|
||||
}
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
self.AssociateId = ""
|
||||
self.AssociateType = ""
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if vm != nil {
|
||||
db.OpsLog.LogEvent(self, db.ACT_EIP_DETACH, vm.GetShortDesc(), userCred)
|
||||
}
|
||||
if self.Mode == EIP_MODE_INSTANCE_PUBLICIP {
|
||||
self.Delete(ctx, userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) AssociateVM(userCred mcclient.TokenCredential, vm *SGuest) error {
|
||||
if len(self.AssociateType) > 0 {
|
||||
return fmt.Errorf("EIP has been associated!!")
|
||||
}
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
self.AssociateType = "server"
|
||||
self.AssociateId = vm.Id
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_EIP_ATTACH, vm.GetShortDesc(), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) getEipByExtEip(userCred mcclient.TokenCredential, extEip cloudprovider.ICloudEIP, region *SCloudregion) (*SElasticip, error) {
|
||||
eipObj, err := manager.FetchByExternalId(extEip.GetGlobalId())
|
||||
if err == nil {
|
||||
return eipObj.(*SElasticip), nil
|
||||
}
|
||||
if err != sql.ErrNoRows {
|
||||
log.Errorf("FetchByExternalId fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return manager.newFromCloudEip(userCred, extEip, region)
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
regionStr := jsonutils.GetAnyString(data, []string {"region", "region_id"})
|
||||
if len(regionStr) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("Missing region/region_id")
|
||||
}
|
||||
region, err := CloudregionManager.FetchByIdOrName("", regionStr)
|
||||
if err != nil {
|
||||
if err != sql.ErrNoRows {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
} else {
|
||||
return nil, httperrors.NewResourceNotFoundError("Region %s not found", regionStr)
|
||||
}
|
||||
}
|
||||
data.Add(jsonutils.NewString(region.GetId()), "cloudregion_id")
|
||||
|
||||
managerStr := jsonutils.GetAnyString(data, []string{"manager", "manager_id"})
|
||||
if len(managerStr) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("Missing manager/manager_id")
|
||||
}
|
||||
|
||||
provider, err := CloudproviderManager.FetchByIdOrName("", managerStr)
|
||||
if err != nil {
|
||||
if err != sql.ErrNoRows {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
} else {
|
||||
return nil, httperrors.NewResourceNotFoundError("Cloud provider %s not found", managerStr)
|
||||
}
|
||||
}
|
||||
data.Add(jsonutils.NewString(provider.GetId()), "manager_id")
|
||||
|
||||
chargeType := jsonutils.GetAnyString(data, []string{"charge_type"})
|
||||
if len(chargeType) == 0 {
|
||||
chargeType = EIP_CHARGE_TYPE_DEFAULT
|
||||
}
|
||||
|
||||
if ! utils.IsInStringArray(chargeType, []string{EIP_CHARGE_TYPE_BY_BANDWIDTH, EIP_CHARGE_TYPE_BY_TRAFFIC}) {
|
||||
return nil, httperrors.NewInputParameterError("charge type %s not supported", chargeType)
|
||||
}
|
||||
|
||||
data.Add(jsonutils.NewString(chargeType), "charge_type")
|
||||
|
||||
eipPendingUsage := &SQuota{Eip: 1}
|
||||
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, userCred.GetProjectId(), eipPendingUsage)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError("Out of eip quota: %s", err)
|
||||
}
|
||||
|
||||
data, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SVirtualResourceBase.PostCreate(ctx, userCred, ownerProjId, query, data)
|
||||
eipPendingUsage := &SQuota{Eip: 1}
|
||||
self.startEipAllocateTask(ctx, userCred, nil, eipPendingUsage)
|
||||
}
|
||||
|
||||
func (self *SElasticip) startEipAllocateTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, pendingUsage quotas.IQuota) error {
|
||||
/*params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(instanceExtId), "instance_external_id")
|
||||
params.Add(jsonutils.NewString(instanceId), "instance_id")
|
||||
params.Add(jsonutils.NewString(instanceType), "instance_type")
|
||||
*/
|
||||
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "EipAllocateTask", self, userCred, params, "", "", pendingUsage)
|
||||
if err != nil {
|
||||
log.Errorf("newtask EipAllocateTask fail %s", err)
|
||||
return err
|
||||
}
|
||||
self.SetStatus(userCred, EIP_STATUS_ALLOCATE, "start allocate")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
log.Infof("Elasticip delete do nothing")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return self.SVirtualResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SElasticip) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
return self.StartEipDeallocateTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SElasticip) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if len(self.AssociateId) > 0 {
|
||||
return fmt.Errorf("eip is associated with instance")
|
||||
}
|
||||
return self.SVirtualResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SElasticip) StartEipDeallocateTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "EipDeallocateTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("newTask EipDeallocateTask fail %s", err)
|
||||
return err
|
||||
}
|
||||
self.SetStatus(userCred, EIP_STATUS_DEALLOCATE, "start to delete")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) AllowPerformAssociate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred)
|
||||
}
|
||||
|
||||
func (self *SElasticip) PerformAssociate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if len(self.AssociateId) > 0 {
|
||||
return nil, httperrors.NewConflictError("eip has been associated with instance")
|
||||
}
|
||||
|
||||
if self.Status != EIP_STATUS_READY {
|
||||
return nil, httperrors.NewInvalidStatusError("eip cannot associate in status %s", self.Status)
|
||||
}
|
||||
|
||||
if self.Mode == EIP_MODE_INSTANCE_PUBLICIP {
|
||||
return nil, httperrors.NewUnsupportOperationError("fixed eip cannot be associated")
|
||||
}
|
||||
|
||||
instanceId := jsonutils.GetAnyString(data, []string{"instance", "instance_id"})
|
||||
if len(instanceId) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("Missing instance_id")
|
||||
}
|
||||
instanceType := jsonutils.GetAnyString(data, []string{"instance_type"})
|
||||
if len(instanceType) == 0 {
|
||||
instanceType = EIP_ASSOCIATE_TYPE_SERVER
|
||||
}
|
||||
|
||||
if instanceType != EIP_ASSOCIATE_TYPE_SERVER {
|
||||
return nil, httperrors.NewInputParameterError("Unsupported %s", instanceType)
|
||||
}
|
||||
|
||||
vmObj, err := GuestManager.FetchByIdOrName(userCred.GetProjectId(), instanceId)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("server %s not found", instanceId)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
}
|
||||
|
||||
server := vmObj.(*SGuest)
|
||||
|
||||
if ok, _ := utils.InStringArray(server.Status, []string{VM_READY, VM_RUNNING}); !ok {
|
||||
return nil, httperrors.NewInvalidStatusError("cannot associate server in status %s", server.Status)
|
||||
}
|
||||
|
||||
serverRegion := server.getRegion()
|
||||
if serverRegion == nil {
|
||||
return nil, httperrors.NewInputParameterError("server region is not found???")
|
||||
}
|
||||
|
||||
eipRegion := self.GetRegion()
|
||||
if eipRegion == nil {
|
||||
return nil, httperrors.NewInputParameterError("eip region is not found???")
|
||||
}
|
||||
|
||||
if serverRegion.Id != eipRegion.Id {
|
||||
return nil, httperrors.NewInputParameterError("eip and server are not in the same region")
|
||||
}
|
||||
|
||||
srvHost := server.GetHost()
|
||||
if srvHost == nil {
|
||||
return nil, httperrors.NewInputParameterError("server host is not found???")
|
||||
}
|
||||
|
||||
if srvHost.ManagerId != self.ManagerId {
|
||||
return nil, httperrors.NewInputParameterError("server and eip are not managed by the same provider")
|
||||
}
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(server.ExternalId), "instance_external_id")
|
||||
params.Add(jsonutils.NewString(server.Id), "instance_id")
|
||||
params.Add(jsonutils.NewString(EIP_ASSOCIATE_TYPE_SERVER), "instance_type")
|
||||
|
||||
err = self.StartEipAssociateTask(ctx, userCred, params)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (self *SElasticip) StartEipAssociateTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "EipAssociateTask", self, userCred, params, "", "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("create EipAssociateTask task fail %s", err)
|
||||
return err
|
||||
}
|
||||
self.SetStatus(userCred, EIP_STATUS_ASSOCIATE, "start to associate")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) AllowPerformDissociate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred)
|
||||
}
|
||||
|
||||
func (self *SElasticip) PerformDissociate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if len(self.AssociateId) == 0 {
|
||||
return nil, httperrors.NewConflictError("eip is not associated with instance")
|
||||
}
|
||||
|
||||
if self.Status != EIP_STATUS_READY {
|
||||
return nil, httperrors.NewInvalidStatusError("eip cannot dissociate in status %s", self.Status)
|
||||
}
|
||||
|
||||
if self.Mode == EIP_MODE_INSTANCE_PUBLICIP {
|
||||
return nil, httperrors.NewUnsupportOperationError("fixed public eip cannot be dissociated")
|
||||
}
|
||||
|
||||
err := self.StartEipDissociateTask(ctx, userCred, "")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (self *SElasticip) StartEipDissociateTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "EipDissociateTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("create EipDissociateTask fail %s", err)
|
||||
return nil
|
||||
}
|
||||
self.SetStatus(userCred, EIP_STATUS_DISSOCIATE, "start to dissociate")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) GetIRegion() (cloudprovider.ICloudRegion, error) {
|
||||
provider, err := self.GetDriver()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
region := self.GetRegion()
|
||||
if region == nil {
|
||||
return nil, fmt.Errorf("fail to find region for eip")
|
||||
}
|
||||
|
||||
return provider.GetIRegionById(region.GetExternalId())
|
||||
}
|
||||
|
||||
func (self *SElasticip) GetIEip() (cloudprovider.ICloudEIP, error) {
|
||||
iregion, err := self.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iregion.GetIEipById(self.GetExternalId())
|
||||
}
|
||||
|
||||
func (self *SElasticip) AllowPerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred)
|
||||
}
|
||||
|
||||
func (self *SElasticip) PerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
/*if self.Status != EIP_STATUS_READY && ! strings.HasSuffix(self.Status, "_fail") {
|
||||
return nil, httperrors.NewInvalidStatusError("eip cannot syncstatus in status %s", self.Status)
|
||||
}*/
|
||||
|
||||
if self.Mode == EIP_MODE_INSTANCE_PUBLICIP {
|
||||
return nil, httperrors.NewUnsupportOperationError("fixed eip cannot be dissociated")
|
||||
}
|
||||
|
||||
err := self.StartEipSyncstatusTask(ctx, userCred, "")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (self *SElasticip) StartEipSyncstatusTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "EipSyncstatusTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("create EipSyncstatusTask fail %s", err)
|
||||
return err
|
||||
}
|
||||
self.SetStatus(userCred, "sync", "synchronize")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
extra := self.SVirtualResourceBase.GetExtraDetails(ctx, userCred, query)
|
||||
return self.getMoreDetails(extra)
|
||||
}
|
||||
|
||||
func (self *SElasticip) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
extra := self.SVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query)
|
||||
return self.getMoreDetails(extra)
|
||||
}
|
||||
|
||||
func (self *SElasticip) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict {
|
||||
vm := self.getVM()
|
||||
if vm != nil {
|
||||
extra.Add(jsonutils.NewString(vm.GetName()), "associate_name")
|
||||
}
|
||||
return extra
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) allocateEipAndAssociateVM(ctx context.Context, userCred mcclient.TokenCredential, vm *SGuest, bw int, chargeType string, managerId string, regionId string) error {
|
||||
eipPendingUsage := &SQuota{Eip: 1}
|
||||
err := QuotaManager.CheckSetPendingQuota(ctx, userCred, userCred.GetProjectId(), eipPendingUsage)
|
||||
if err != nil {
|
||||
return httperrors.NewOutOfQuotaError("Out of eip quota: %s", err)
|
||||
}
|
||||
|
||||
eip := SElasticip{}
|
||||
eip.SetModelManager(manager)
|
||||
|
||||
eip.Mode = EIP_MODE_STANDALONE_EIP
|
||||
eip.AutoDellocate = tristate.True
|
||||
eip.Bandwidth = bw
|
||||
eip.ChargeType = chargeType
|
||||
eip.ProjectId = vm.ProjectId
|
||||
eip.ManagerId = managerId
|
||||
eip.CloudregionId = regionId
|
||||
eip.Name = fmt.Sprintf("eip-for-%s", vm.GetName())
|
||||
|
||||
err = manager.TableSpec().Insert(&eip)
|
||||
if err != nil {
|
||||
log.Errorf("create EIP record fail %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(vm.ExternalId), "instance_external_id")
|
||||
params.Add(jsonutils.NewString(vm.Id), "instance_id")
|
||||
params.Add(jsonutils.NewString(EIP_ASSOCIATE_TYPE_SERVER), "instance_type")
|
||||
|
||||
return eip.startEipAllocateTask(ctx, userCred, params, eipPendingUsage)
|
||||
}
|
||||
|
||||
func (self *SElasticip) AllowPerformChangeBandwidth(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred)
|
||||
}
|
||||
|
||||
func (self *SElasticip) PerformChangeBandwidth(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if self.Status != EIP_STATUS_READY {
|
||||
return nil, httperrors.NewInvalidStatusError("cannot change bandwidth in status %s", self.Status)
|
||||
}
|
||||
|
||||
bandwidth, err := data.Int("bandwidth")
|
||||
if err != nil || bandwidth <= 0 {
|
||||
return nil, httperrors.NewInputParameterError("Invalid bandwidth")
|
||||
}
|
||||
err = self.StartEipChangeBandwidthTask(ctx, userCred, bandwidth)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) StartEipChangeBandwidthTask(ctx context.Context, userCred mcclient.TokenCredential, bandwidth int64) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewInt(bandwidth), "bandwidth")
|
||||
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "EipChangeBandwidthTask", self, userCred, params, "", "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("create EipChangeBandwidthTask fail %s", err)
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) DoChangeBandwidth(userCred mcclient.TokenCredential, bandwidth int) error {
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
self.Bandwidth = bandwidth
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("DoChangeBandwidth update fail %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
changes := jsonutils.NewDict()
|
||||
changes.Add(jsonutils.NewInt(int64(self.Bandwidth)), "obw")
|
||||
changes.Add(jsonutils.NewInt(int64(bandwidth)), "nbw")
|
||||
db.OpsLog.LogEvent(self, db.ACT_CHANGE_BANDWIDTH, changes, userCred)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type EipUsage struct {
|
||||
PublicIPCount int
|
||||
EIPCount int
|
||||
EIPUsedCount int
|
||||
}
|
||||
|
||||
func (u EipUsage) Total() int {
|
||||
return u.PublicIPCount + u.EIPCount
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) TotalCount(projectId string) EipUsage {
|
||||
usage := EipUsage{}
|
||||
q1 := manager.Query().Equals("mode", EIP_MODE_INSTANCE_PUBLICIP)
|
||||
q2 := manager.Query().Equals("mode", EIP_MODE_STANDALONE_EIP)
|
||||
q3 := manager.Query().Equals("mode", EIP_MODE_STANDALONE_EIP).IsNotEmpty("associate_id")
|
||||
if len(projectId) > 0 {
|
||||
q1 = q1.Equals("tenant_id", projectId)
|
||||
q2 = q2.Equals("tenant_id", projectId)
|
||||
q3 = q3.Equals("tenant_id", projectId)
|
||||
}
|
||||
usage.PublicIPCount = q1.Count()
|
||||
usage.EIPCount = q2.Count()
|
||||
usage.EIPUsedCount = q3.Count()
|
||||
return usage
|
||||
}
|
||||
@@ -298,6 +298,24 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
|
||||
q = q.In("host_id", sq)
|
||||
}
|
||||
|
||||
regionFilter, _ := queryDict.GetString("region")
|
||||
if len(regionFilter) > 0 {
|
||||
regionObj, err := CloudregionManager.FetchByIdOrName(userCred.GetProjectId(), regionFilter)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("cloud region %s not found", regionFilter)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
}
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
zones := ZoneManager.Query().SubQuery()
|
||||
sq := hosts.Query(hosts.Field("id"))
|
||||
sq = sq.Join(zones, sqlchemy.Equals(hosts.Field("zone_id"), zones.Field("id")))
|
||||
sq = sq.Filter(sqlchemy.Equals(zones.Field("cloudregion_id"), regionObj.GetId()))
|
||||
q = q.In("host_id", sq)
|
||||
}
|
||||
|
||||
gpu, _ := queryDict.GetString("gpu")
|
||||
if len(gpu) != 0 {
|
||||
isodev := IsolatedDeviceManager.Query().SubQuery()
|
||||
@@ -924,6 +942,10 @@ func (self *SGuest) GetCustomizeColumns(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
}
|
||||
extra.Add(jsonutils.NewString(strings.Join(self.getRealIPs(), ",")), "ips")
|
||||
eip, _ := self.GetEip()
|
||||
if eip != nil {
|
||||
extra.Add(jsonutils.NewString(eip.IpAddr), "eip")
|
||||
}
|
||||
extra.Add(jsonutils.NewInt(int64(self.getDiskSize())), "disk")
|
||||
// flavor??
|
||||
// extra.Add(jsonutils.NewString(self.getFlavorName()), "flavor")
|
||||
@@ -989,6 +1011,10 @@ func (self *SGuest) GetExtraDetails(ctx context.Context, userCred mcclient.Token
|
||||
}
|
||||
extra.Add(jsonutils.NewString(self.getAdminSecurityRules()), "admin_security_rules")
|
||||
}
|
||||
eip, _ := self.GetEip()
|
||||
if eip != nil {
|
||||
extra.Add(jsonutils.NewString(eip.IpAddr), "eip")
|
||||
}
|
||||
return self.moreExtraInfo(extra)
|
||||
}
|
||||
|
||||
@@ -1120,6 +1146,10 @@ func (self *SGuest) getIPs() []string {
|
||||
ips := self.getRealIPs()
|
||||
vips := self.getVirtualIPs()
|
||||
ips = append(ips, vips...)
|
||||
eip, _ := self.GetEip()
|
||||
if eip != nil {
|
||||
ips = append(ips, eip.IpAddr)
|
||||
}
|
||||
return ips
|
||||
}
|
||||
|
||||
@@ -1131,6 +1161,14 @@ func (self *SGuest) getZone() *SZone {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) getRegion() *SCloudregion {
|
||||
zone := self.getZone()
|
||||
if zone != nil {
|
||||
return zone.GetRegion()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) GetOS() string {
|
||||
if len(self.OsType) > 0 {
|
||||
return self.OsType
|
||||
@@ -3543,6 +3581,156 @@ func (manager *SGuestManager) CleanPendingDeleteServers(ctx context.Context, use
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) GetEip() (*SElasticip, error) {
|
||||
return ElasticipManager.getEipForInstance("server", self.Id)
|
||||
}
|
||||
|
||||
func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCredential, extEip cloudprovider.ICloudEIP) compare.SyncResult {
|
||||
result := compare.SyncResult{}
|
||||
|
||||
eip, err := self.GetEip()
|
||||
if err != nil {
|
||||
result.Error(fmt.Errorf("getEip error %s", err))
|
||||
return result
|
||||
}
|
||||
|
||||
if eip == nil && extEip == nil {
|
||||
// do nothing
|
||||
} else if eip == nil && extEip != nil {
|
||||
// add
|
||||
neip, err := ElasticipManager.getEipByExtEip(userCred, extEip, self.getRegion())
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
err = neip.AssociateVM(userCred, self)
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
result.Add()
|
||||
}
|
||||
}
|
||||
} else if eip != nil && extEip == nil {
|
||||
// remove
|
||||
err = eip.Dissociate(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
} else {
|
||||
result.Delete()
|
||||
}
|
||||
} else {
|
||||
// sync
|
||||
if eip.IpAddr != extEip.GetIpAddr() {
|
||||
// remove then add
|
||||
err = eip.Dissociate(ctx, userCred)
|
||||
if err != nil {
|
||||
// fail to remove
|
||||
result.DeleteError(err)
|
||||
} else {
|
||||
result.Delete()
|
||||
neip, err := ElasticipManager.getEipByExtEip(userCred, extEip, self.getRegion())
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
err = neip.AssociateVM(userCred, self)
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
result.Add()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// do nothing
|
||||
err := eip.SyncWithCloudEip(userCred, extEip)
|
||||
if err != nil {
|
||||
result.UpdateError(err)
|
||||
} else {
|
||||
result.Update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *SGuest) GetIVM() (cloudprovider.ICloudVM, error) {
|
||||
if len(self.ExternalId) == 0 {
|
||||
msg := fmt.Sprintf("GetIVM: not managed by a provider")
|
||||
log.Errorf(msg)
|
||||
return nil, fmt.Errorf(msg)
|
||||
}
|
||||
host := self.GetHost()
|
||||
if host == nil {
|
||||
msg := fmt.Sprintf("GetIVM: No valid host")
|
||||
log.Errorf(msg)
|
||||
return nil, fmt.Errorf(msg)
|
||||
}
|
||||
ihost, err := host.GetIHost()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetIVM: getihost fail %s", err)
|
||||
log.Errorf(msg)
|
||||
return nil, fmt.Errorf(msg)
|
||||
}
|
||||
return ihost.GetIVMById(self.ExternalId)
|
||||
}
|
||||
|
||||
func (self *SGuest) AllowPerformCreateEip(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred)
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformCreateEip(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
bw, err := data.Int("bandwidth")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Missing bandwidth")
|
||||
}
|
||||
|
||||
chargeType, _ := data.GetString("charge_type")
|
||||
if len(chargeType) == 0 {
|
||||
chargeType = EIP_CHARGE_TYPE_DEFAULT
|
||||
}
|
||||
|
||||
if len(self.ExternalId) == 0 {
|
||||
return nil, httperrors.NewInvalidStatusError("Not a managed VM")
|
||||
}
|
||||
host := self.GetHost()
|
||||
if host == nil {
|
||||
return nil, httperrors.NewInvalidStatusError("No host???")
|
||||
}
|
||||
|
||||
_, err = host.GetDriver()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInvalidStatusError("No valid cloud provider")
|
||||
}
|
||||
|
||||
region := host.GetRegion()
|
||||
if region == nil {
|
||||
return nil, httperrors.NewInvalidStatusError("No cloudregion???")
|
||||
}
|
||||
|
||||
err = ElasticipManager.allocateEipAndAssociateVM(ctx, userCred, self, int(bw), chargeType, host.ManagerId, region.Id)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) DeleteEip(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
eip, err := self.GetEip()
|
||||
if err != nil {
|
||||
log.Errorf("Delete eip fail for get Eip %s", err)
|
||||
return err
|
||||
}
|
||||
if eip == nil {
|
||||
return nil
|
||||
}
|
||||
err = eip.Delete(ctx, userCred)
|
||||
if err != nil {
|
||||
log.Errorf("Delete eip fail %s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) SetDisableDelete(val bool) error {
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
if val {
|
||||
|
||||
@@ -1435,13 +1435,6 @@ func (self *SHost) GetIHost() (cloudprovider.ICloudHost, error) {
|
||||
return nil, fmt.Errorf("No cloudprovide for host: %s", err)
|
||||
}
|
||||
ihost, err := provider.GetIHostById(self.ExternalId)
|
||||
|
||||
/* izone, err := self.GetIZone()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to find izone by id %s", err)
|
||||
}
|
||||
ihost, err := izone.GetIHostById(self.ExternalId)*/
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("fail to find ihost by id %s", err)
|
||||
return nil, fmt.Errorf("fail to find ihost by id %s", err)
|
||||
|
||||
@@ -71,7 +71,7 @@ func (self *SQuota) FetchUsage(projectId string) error {
|
||||
diskSize := totalDiskSize(projectId, tristate.None, tristate.None, false)
|
||||
net := totalGuestNicCount(projectId, nil, false)
|
||||
guest := totalGuestResourceCount(projectId, nil, nil, "", false, false, "")
|
||||
|
||||
eipUsage := ElasticipManager.TotalCount(projectId)
|
||||
// XXX
|
||||
// keypair belongs to user
|
||||
// keypair := totalKeypairCount(projectId)
|
||||
@@ -80,7 +80,7 @@ func (self *SQuota) FetchUsage(projectId string) error {
|
||||
self.Memory = guest.TotalMemSize
|
||||
self.Storage = diskSize
|
||||
self.Port = net.InternalNicCount + net.InternalVirtualNicCount
|
||||
self.Eip = 0
|
||||
self.Eip = eipUsage.Total()
|
||||
self.Eport = net.ExternalNicCount + net.ExternalVirtualNicCount
|
||||
self.Bw = net.InternalBandwidth
|
||||
self.Ebw = net.ExternalBandwidth
|
||||
|
||||
@@ -7,14 +7,15 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -35,7 +35,7 @@ type ComputeOptions struct {
|
||||
DefaultMemoryQuota int `default:"51200" help:"Common memory quota per tenant in MB, default 50G"`
|
||||
DefaultStorageQuota int `default:"3072000" help:"Common storage quota per tenant in MB, default 3000G"`
|
||||
DefaultPortQuota int `default:"50" help:"Common network port quota per tenant, default 50"`
|
||||
DefaultEipQuota int `default:"0" help:"Common floating IP quota per tenant, default 0"`
|
||||
DefaultEipQuota int `default:"5" help:"Common floating IP quota per tenant, default 0"`
|
||||
DefaultEportQuota int `default:"50" help:"Common exit network port quota per tenant, default 50"`
|
||||
DefaultBwQuota int `default:"500000" help:"Common network port bandwidth in mbps quota per tenant, default 50*10Gbps"`
|
||||
DefaultEbwQuota int `default:"1000" help:"Common exit network port bandwidth quota per tenant, default 1Gbps"`
|
||||
|
||||
@@ -109,6 +109,8 @@ func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider,
|
||||
continue
|
||||
}
|
||||
|
||||
syncRegionEips(ctx, provider, task, &localRegions[i], remoteRegions[i])
|
||||
|
||||
localZones, remoteZones := syncRegionZones(ctx, provider, task, &localRegions[i], remoteRegions[i])
|
||||
|
||||
syncRegionVPCs(ctx, provider, task, &localRegions[i], remoteRegions[i])
|
||||
@@ -126,6 +128,25 @@ func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider,
|
||||
}
|
||||
}
|
||||
|
||||
func syncRegionEips(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion) {
|
||||
eips, err := remoteRegion.GetIEips()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetIEips for region %s failed %s", remoteRegion.GetName(), err)
|
||||
log.Errorf(msg)
|
||||
logSyncFailed(provider, task, msg)
|
||||
return
|
||||
}
|
||||
|
||||
result := models.ElasticipManager.SyncEips(ctx, task.UserCred, provider, localRegion, eips)
|
||||
msg := result.Result()
|
||||
log.Infof("SyncEips for region %s result: %s", localRegion.Name, msg)
|
||||
if result.IsError() {
|
||||
logSyncFailed(provider, task, msg)
|
||||
return
|
||||
}
|
||||
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred)
|
||||
}
|
||||
|
||||
func syncRegionZones(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion) ([]models.SZone, []cloudprovider.ICloudZone) {
|
||||
zones, err := remoteRegion.GetIZones()
|
||||
if err != nil {
|
||||
@@ -384,6 +405,7 @@ func syncHostVMs(ctx context.Context, provider *models.SCloudprovider, task *Clo
|
||||
for i := 0; i < len(localVMs); i += 1 {
|
||||
syncVMNics(ctx, provider, task, localHost, &localVMs[i], remoteVMs[i])
|
||||
syncVMDisks(ctx, provider, task, localHost, &localVMs[i], remoteVMs[i])
|
||||
syncVMEip(ctx, provider, task, &localVMs[i], remoteVMs[i])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,3 +448,21 @@ func syncVMDisks(ctx context.Context, provider *models.SCloudprovider, task *Clo
|
||||
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred)
|
||||
logclient.AddActionLog(provider, getAction(task.Params), notes, task.UserCred, true)
|
||||
}
|
||||
|
||||
func syncVMEip(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localVM *models.SGuest, remoteVM cloudprovider.ICloudVM) {
|
||||
eip, err := remoteVM.GetIEIP()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetIEIP for VM %s failed %s", remoteVM.GetName(), err)
|
||||
log.Errorf(msg)
|
||||
logSyncFailed(provider, task, msg)
|
||||
return
|
||||
}
|
||||
result := localVM.SyncVMEip(ctx, task.UserCred, eip)
|
||||
msg := result.Result()
|
||||
log.Infof("syncVMEip for VM %s result: %s", localVM.Name, msg)
|
||||
if result.IsError() {
|
||||
logSyncFailed(provider, task, msg)
|
||||
return
|
||||
}
|
||||
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred)
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
|
||||
type EipAllocateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(EipAllocateTask{})
|
||||
}
|
||||
|
||||
func (self *EipAllocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
eip := obj.(*models.SElasticip)
|
||||
|
||||
iregion, err := eip.GetIRegion()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to find iregion for eip %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_ALLOCATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
extEip, err := iregion.CreateEIP(eip.Bandwidth)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("create eip fail %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_ALLOCATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = eip.SyncWithCloudEip(self.UserCred, extEip)
|
||||
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("sync eip fail %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_ALLOCATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
eipPendingUsage := &models.SQuota{Eip: 1}
|
||||
err = models.QuotaManager.CancelPendingUsage(ctx, self.UserCred, self.UserCred.GetProjectId(), eipPendingUsage, eipPendingUsage)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("CancelPendingUsage fail %s", err)
|
||||
}
|
||||
|
||||
if self.Params != nil && self.Params.Contains("instance_id") {
|
||||
self.SetStage("on_eip_associate_complete", nil)
|
||||
err = eip.StartEipAssociateTask(ctx, self.UserCred, self.Params)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("start associate task fail %s", err)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
}
|
||||
} else {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *EipAllocateTask) OnEipAssociateComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type EipAssociateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(EipAssociateTask{})
|
||||
}
|
||||
|
||||
func (self *EipAssociateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
eip := obj.(*models.SElasticip)
|
||||
|
||||
extEip, err := eip.GetIEip()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to find iEIP for eip %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_ASSOCIATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
instanceId, _ := self.Params.GetString("instance_id")
|
||||
server := models.GuestManager.FetchGuestById(instanceId)
|
||||
if server == nil {
|
||||
msg := fmt.Sprintf("fail to find server for instanceId %s", instanceId)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_ASSOCIATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = extEip.Associate(server.ExternalId)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to remote associate EIP %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_ASSOCIATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = eip.AssociateVM(self.UserCred, server)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to local associate EIP %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_ASSOCIATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_READY, "associate")
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
|
||||
)
|
||||
|
||||
type EipChangeBandwidthTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(EipChangeBandwidthTask{})
|
||||
}
|
||||
|
||||
func (self *EipChangeBandwidthTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
eip := obj.(*models.SElasticip)
|
||||
|
||||
extEip, err := eip.GetIEip()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to find iEip %s", err)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
bandwidth, _ := self.Params.Int("bandwidth")
|
||||
if bandwidth <= 0 {
|
||||
msg := fmt.Sprintf("invalid bandwidth %d", bandwidth)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = extEip.ChangeBandwidth(int(bandwidth))
|
||||
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to find iEip %s", err)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = eip.DoChangeBandwidth(self.UserCred, int(bandwidth))
|
||||
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to synchronize iEip bandwidth %s", err)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
|
||||
)
|
||||
|
||||
type EipDeallocateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(EipDeallocateTask{})
|
||||
}
|
||||
|
||||
func (self *EipDeallocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
eip := obj.(*models.SElasticip)
|
||||
|
||||
if len(eip.ExternalId) > 0 {
|
||||
expEip, err := eip.GetIEip()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to find iEIP for eip %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_DEALLOCATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = expEip.Delete()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to delete iEIP %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_DEALLOCATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err := eip.RealDelete(ctx, self.UserCred)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to delete EIP %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_DEALLOCATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package tasks
|
||||
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type EipDissociateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(EipDissociateTask{})
|
||||
}
|
||||
|
||||
func (self *EipDissociateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
eip := obj.(*models.SElasticip)
|
||||
|
||||
extEip, err := eip.GetIEip()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to find iEIP for eip %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_DISSOCIATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
if len(extEip.GetAssociationExternalId()) > 0 {
|
||||
err = extEip.Dissociate()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to remote dissociate eip %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_DISSOCIATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = eip.Dissociate(ctx, self.UserCred)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to local dissociate eip %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_DISSOCIATE_FAIL, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_READY, "dissociate")
|
||||
|
||||
if eip.AutoDellocate.IsTrue() {
|
||||
self.SetStage("on_auto_dellocate_complete", nil)
|
||||
eip.StartEipDeallocateTask(ctx, self.UserCred, self.Id)
|
||||
} else {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *EipDissociateTask) OnAutoDellocateComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
|
||||
type EipSyncstatusTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(EipSyncstatusTask{})
|
||||
}
|
||||
|
||||
func (self *EipSyncstatusTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
eip := obj.(*models.SElasticip)
|
||||
|
||||
extEip, err := eip.GetIEip()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to find ieip for eip %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_UNKNOWN, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = extEip.Refresh()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to refresh eip status %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_UNKNOWN, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = eip.SyncWithCloudEip(self.UserCred, extEip)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to sync eip status %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_UNKNOWN, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = eip.SyncInstanceWithCloudEip(ctx, self.UserCred, extEip)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to sync eip status %s", err)
|
||||
eip.SetStatus(self.UserCred, models.EIP_STATUS_UNKNOWN, msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -31,6 +31,20 @@ func (self *GuestDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel
|
||||
|
||||
func (self *GuestDeleteTask) OnGuestStopComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
|
||||
eip, _ := guest.GetEip()
|
||||
if eip != nil && eip.Mode != models.EIP_MODE_INSTANCE_PUBLICIP {
|
||||
// detach floating EIP only
|
||||
self.SetStage("on_eip_dissociate_complete", nil)
|
||||
eip.StartEipDissociateTask(ctx, self.UserCred, self.GetTaskId())
|
||||
} else {
|
||||
self.OnEipDissociateComplete(ctx, obj, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnEipDissociateComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
|
||||
if options.Options.EnablePendingDelete && !guest.PendingDeleted &&
|
||||
!jsonutils.QueryBoolean(self.Params, "purge", false) &&
|
||||
!jsonutils.QueryBoolean(self.Params, "override_pending_delete", false) {
|
||||
@@ -102,6 +116,7 @@ func (self *GuestDeleteTask) OnGuestDeleteComplete(ctx context.Context, obj db.I
|
||||
guest.LeaveAllGroups(self.UserCred)
|
||||
guest.DetachAllNetworks(ctx, self.UserCred)
|
||||
guest.EjectIso(self.UserCred)
|
||||
guest.DeleteEip(ctx, self.UserCred)
|
||||
guest.GetDriver().OnDeleteGuestFinalCleanup(ctx, guest, self.UserCred)
|
||||
self.DeleteGuest(ctx, guest)
|
||||
}
|
||||
|
||||
@@ -212,6 +212,7 @@ func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandalo
|
||||
IsolatedDeviceUsage(rangeObj, hostTypes),
|
||||
WireUsage(rangeObj, hostTypes),
|
||||
NetworkUsage(userCred, rangeObj),
|
||||
EipUsage(),
|
||||
)
|
||||
|
||||
return
|
||||
@@ -336,3 +337,13 @@ func IsolatedDeviceUsage(rangeObj db.IStandaloneModel, hostType []string) Usage
|
||||
count[prefix] = ret.Devices
|
||||
return count
|
||||
}
|
||||
|
||||
func EipUsage() Usage {
|
||||
eipUsage := models.ElasticipManager.TotalCount("")
|
||||
count := make(map[string]interface{})
|
||||
count["eip.all"] = eipUsage.Total()
|
||||
count["eip.public_ip"] = eipUsage.PublicIPCount
|
||||
count["eip.floating_ip"] = eipUsage.EIPCount
|
||||
count["eip.floating_ip.used"] = eipUsage.EIPUsedCount
|
||||
return count
|
||||
}
|
||||
@@ -11,7 +11,7 @@ func NewJsonClientError(code int, title string, msg string, error httputils.Erro
|
||||
return &err
|
||||
}
|
||||
|
||||
func errorMessage(msg string, params ...interface{}) (string, httputils.Error) {
|
||||
func errorMessage(msg string, params []interface{}) (string, httputils.Error) {
|
||||
fileds := make([]string, len(params))
|
||||
for i, v := range params {
|
||||
fileds[i] = fmt.Sprint(v)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package modules
|
||||
|
||||
var (
|
||||
Elasticips ResourceManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
Elasticips = NewComputeManager("eip", "eips",
|
||||
[]string{"ID", "Name", "IP_Addr", "Status",
|
||||
"Associate_Type", "Associate_ID",
|
||||
"Associate_Name",
|
||||
"Bandwidth", "Charge_Type",
|
||||
},
|
||||
[]string{})
|
||||
|
||||
registerCompute(&Elasticips)
|
||||
}
|
||||
@@ -50,7 +50,7 @@ var (
|
||||
func init() {
|
||||
Servers = ServerManager{NewComputeManager("server", "servers",
|
||||
[]string{"ID", "Name", "Billing_type",
|
||||
"IPs", "Disk", "Status",
|
||||
"IPs", "EIP", "Disk", "Status",
|
||||
"vcpu_count", "vmem_size",
|
||||
"ext_bw", "Zone_name",
|
||||
"Secgroup", "Secgrp_id",
|
||||
|
||||
@@ -146,7 +146,7 @@ type BaseListOptions struct {
|
||||
Offset *int `default:"0" help:"Page offset"`
|
||||
OrderBy []string `help:"Name of the field to be ordered by"`
|
||||
Order string `help:"List order" choices:"desc|asc"`
|
||||
Details *bool `help:"Show more details"`
|
||||
Details *bool `help:"Show more details" default:"false"`
|
||||
Search string `help:"Filter results by a simple keyword search"`
|
||||
Meta *bool `help:"Piggyback metadata information"`
|
||||
Filter []string `help:"Filters"`
|
||||
|
||||
@@ -20,6 +20,8 @@ type ServerListOptions struct {
|
||||
AdminSecgroup string `help:"AdminSecgroup ID or Name"`
|
||||
Hypervisor string `help:"Show server of hypervisor" choices:"kvm|esxi|container|baremetal|aliyun"`
|
||||
Manager string `help:"Show servers imported from manager"`
|
||||
Region string `help:"Show servers in cloudregion"`
|
||||
|
||||
BaseListOptions
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"time"
|
||||
"yunion.io/x/log"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type TInternetChargeType string
|
||||
|
||||
const (
|
||||
InternetChargeByTraffic = TInternetChargeType("PayByTraffic")
|
||||
InternetChargeByBandwidth = TInternetChargeType("PayByBandwidth")
|
||||
)
|
||||
|
||||
const (
|
||||
EIP_STATUS_ASSOCIATING = "Associating"
|
||||
EIP_STATUS_UNASSOCIATING = "Unassociating"
|
||||
EIP_STATUS_INUSE = "InUse"
|
||||
EIP_STATUS_AVAILABLE = "Available"
|
||||
|
||||
EIP_OPERATION_LOCK_FINANCIAL = "financial"
|
||||
EIP_OPERATION_LOCK_SECURITY = "security"
|
||||
|
||||
|
||||
EIP_INSTANCE_TYPE_ECS = "EcsInstance" // (默认值):VPC类型的ECS实例
|
||||
EIP_INTANNCE_TYPE_SLB = "SlbInstance" // :VPC类型的SLB实例
|
||||
EIP_INSTANCE_TYPE_NAT = "Nat" // :NAT网关
|
||||
EIP_INSTANCE_TYPE_HAVIP = "HaVip" // :HAVIP
|
||||
)
|
||||
|
||||
type SEipAddress struct {
|
||||
region *SRegion
|
||||
|
||||
AllocationId string
|
||||
|
||||
InternetChargeType string
|
||||
|
||||
IpAddress string
|
||||
Status string
|
||||
|
||||
InstanceType string
|
||||
InstanceId string
|
||||
Bandwidth int /* Mbps */
|
||||
|
||||
AllocationTime time.Time
|
||||
|
||||
OperationLocks string
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetId() string {
|
||||
return self.AllocationId
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetName() string {
|
||||
return self.IpAddress
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetGlobalId() string {
|
||||
return self.AllocationId
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetStatus() string {
|
||||
switch self.Status {
|
||||
case EIP_STATUS_AVAILABLE, EIP_STATUS_INUSE:
|
||||
return models.EIP_STATUS_READY
|
||||
case EIP_STATUS_ASSOCIATING:
|
||||
return models.EIP_STATUS_ASSOCIATE
|
||||
case EIP_STATUS_UNASSOCIATING:
|
||||
return models.EIP_STATUS_DISSOCIATE
|
||||
default:
|
||||
return models.EIP_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEipAddress) Refresh() error {
|
||||
if self.IsEmulated() {
|
||||
return nil
|
||||
}
|
||||
new, err := self.region.GetEip(self.AllocationId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SEipAddress) IsEmulated() bool {
|
||||
if self.AllocationId == self.InstanceId {
|
||||
// fixed Public IP
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetIpAddr() string {
|
||||
return self.IpAddress
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetMode() string {
|
||||
if self.InstanceId == self.AllocationId {
|
||||
return models.EIP_MODE_INSTANCE_PUBLICIP
|
||||
} else {
|
||||
return models.EIP_MODE_STANDALONE_EIP
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetAssociationType() string {
|
||||
switch self.InstanceType {
|
||||
case EIP_INSTANCE_TYPE_ECS:
|
||||
return "server"
|
||||
default:
|
||||
log.Fatalf("unsupported type: %s", self.InstanceType)
|
||||
return "unsupported"
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetAssociationExternalId() string {
|
||||
return self.InstanceId
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetManagerId() string {
|
||||
return self.region.client.providerId
|
||||
}
|
||||
|
||||
func (self *SEipAddress) Delete() error {
|
||||
return self.region.DeallocateEIP(self.AllocationId)
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetBandwidth() int {
|
||||
return self.Bandwidth
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetInternetChargeType() string {
|
||||
switch self.InternetChargeType {
|
||||
case string(InternetChargeByTraffic):
|
||||
return models.EIP_CHARGE_TYPE_BY_TRAFFIC
|
||||
case string(InternetChargeByBandwidth):
|
||||
return models.EIP_CHARGE_TYPE_BY_BANDWIDTH
|
||||
default:
|
||||
return models.EIP_CHARGE_TYPE_BY_TRAFFIC
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEipAddress) Associate(instanceId string) error {
|
||||
err := self.region.AssociateEip(self.AllocationId, instanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cloudprovider.WaitStatus(self, models.EIP_STATUS_READY, 10*time.Second, 180*time.Second)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SEipAddress) Dissociate() error {
|
||||
err := self.region.DissociateEip(self.AllocationId, self.InstanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cloudprovider.WaitStatus(self, models.EIP_STATUS_READY, 10*time.Second, 180*time.Second)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SEipAddress) ChangeBandwidth(bw int) error {
|
||||
return self.region.UpdateEipBandwidth(self.AllocationId, bw)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetEips(eipId string, offset int, limit int) ([]SEipAddress, int, error) {
|
||||
if limit > 50 || limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
|
||||
params := make(map[string]string)
|
||||
params["RegionId"] = region.RegionId
|
||||
params["PageSize"] = fmt.Sprintf("%d", limit)
|
||||
params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
|
||||
|
||||
if len(eipId) > 0 {
|
||||
params["AllocationId"] = eipId
|
||||
}
|
||||
|
||||
body, err := region.ecsRequest("DescribeEipAddresses", params)
|
||||
if err != nil {
|
||||
log.Errorf("DescribeEipAddresses fail %s", err)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// log.Errorf("%s", body)
|
||||
|
||||
eips := make([]SEipAddress, 0)
|
||||
err = body.Unmarshal(&eips, "EipAddresses", "EipAddress")
|
||||
if err != nil {
|
||||
log.Errorf("Unmarshal EipAddress details fail %s", err)
|
||||
return nil, 0, err
|
||||
}
|
||||
total, _ := body.Int("TotalCount")
|
||||
for i := 0; i < len(eips); i += 1 {
|
||||
eips[i].region = region
|
||||
}
|
||||
return eips, int(total), nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetEip(eipId string) (*SEipAddress, error) {
|
||||
eips, total, err := region.GetEips(eipId, 0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if total != 1 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return &eips[0], nil
|
||||
}
|
||||
|
||||
func (region *SRegion) AllocateEIP(bwMbps int, chargeType TInternetChargeType) (*SEipAddress, error) {
|
||||
params := make(map[string]string)
|
||||
|
||||
params["Bandwidth"] = fmt.Sprintf("%d", bwMbps)
|
||||
params["InternetChargeType"] = string(chargeType)
|
||||
params["InstanceChargeType"] = "PostPaid"
|
||||
params["ClientToken"] = utils.GenRequestId(20)
|
||||
|
||||
body, err := region.ecsRequest("AllocateEipAddress", params)
|
||||
if err != nil {
|
||||
log.Errorf("AllocateEipAddress fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eipId, err := body.GetString("AllocationId")
|
||||
if err != nil {
|
||||
log.Errorf("fail to get AllocationId after EIP allocation??? %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return region.GetEip(eipId)
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateEIP(bwMbps int) (cloudprovider.ICloudEIP, error) {
|
||||
eip, err := region.AllocateEIP(bwMbps, InternetChargeByTraffic)
|
||||
return eip, err
|
||||
}
|
||||
|
||||
func (region *SRegion) DeallocateEIP(eipId string) (error) {
|
||||
params := make(map[string]string)
|
||||
params["AllocationId"] = eipId
|
||||
|
||||
_, err := region.ecsRequest("ReleaseEipAddress", params)
|
||||
if err != nil {
|
||||
log.Errorf("ReleaseEipAddress fail %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) AssociateEip(eipId string, instanceId string) (error) {
|
||||
params := make(map[string]string)
|
||||
params["AllocationId"] = eipId
|
||||
params["InstanceId"] = instanceId
|
||||
|
||||
_, err := region.ecsRequest("AssociateEipAddress", params)
|
||||
if err != nil {
|
||||
log.Errorf("AssociateEipAddress fail %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) DissociateEip(eipId string, instanceId string) (error) {
|
||||
params := make(map[string]string)
|
||||
params["AllocationId"] = eipId
|
||||
params["InstanceId"] = instanceId
|
||||
|
||||
_, err := region.ecsRequest("UnassociateEipAddress", params)
|
||||
if err != nil {
|
||||
log.Errorf("UnassociateEipAddress fail %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) UpdateEipBandwidth(eipId string, bw int) error {
|
||||
params := make(map[string]string)
|
||||
params["AllocationId"] = eipId
|
||||
params["Bandwidth"] = fmt.Sprintf("%d", bw)
|
||||
|
||||
_, err := region.ecsRequest("ModifyEipAddressAttribute", params)
|
||||
if err != nil {
|
||||
log.Errorf("ModifyEipAddressAttribute fail %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
+20
-22
@@ -34,24 +34,6 @@ type SDedicatedHostAttribute struct {
|
||||
DedicatedHostName string
|
||||
}
|
||||
|
||||
type SEipAddress struct {
|
||||
AllocationId string
|
||||
InternetChargeType string
|
||||
IpAddress string
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetIP() string {
|
||||
return self.IpAddress
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetAllocationId() string {
|
||||
return self.AllocationId
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetChargeType() string {
|
||||
return self.GetChargeType()
|
||||
}
|
||||
|
||||
type SIpAddress struct {
|
||||
IpAddress []string
|
||||
}
|
||||
@@ -247,10 +229,6 @@ func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
|
||||
return nics, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetEIP() cloudprovider.ICloudEIP {
|
||||
return &self.EipAddress
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVcpuCount() int8 {
|
||||
return self.Cpu
|
||||
}
|
||||
@@ -723,3 +701,23 @@ func (self *SInstance) SyncSecurityGroup(secgroupId string, name string, rules [
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
if len(self.PublicIpAddress.IpAddress) > 0 {
|
||||
eip := SEipAddress{}
|
||||
eip.region = self.host.zone.region
|
||||
eip.IpAddress = self.PublicIpAddress.IpAddress[0]
|
||||
eip.InstanceId = self.InstanceId
|
||||
eip.InstanceType = EIP_INSTANCE_TYPE_ECS
|
||||
eip.Status = EIP_STATUS_INUSE
|
||||
eip.AllocationId = self.InstanceId // fixed
|
||||
eip.AllocationTime = self.CreationTime
|
||||
eip.Bandwidth = self.InternetMaxBandwidthOut
|
||||
eip.InternetChargeType = self.InternetChargeType
|
||||
return &eip, nil
|
||||
} else if len(self.EipAddress.IpAddress) > 0 {
|
||||
return self.host.zone.region.GetEip(self.EipAddress.AllocationId)
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
@@ -570,3 +570,37 @@ func (self *SRegion) updateInstance(instId string, name, desc, passwd, hostname
|
||||
func (self *SRegion) UpdateInstancePassword(instId string, passwd string) error {
|
||||
return self.updateInstance(instId, "", "", passwd, "")
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
|
||||
eips, total, err := self.GetEips("", 0, 50)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for len(eips) < total {
|
||||
var parts []SEipAddress
|
||||
parts, total, err = self.GetEips("", len(eips), 50)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eips = append(eips, parts...)
|
||||
}
|
||||
ret := make([]cloudprovider.ICloudEIP, len(eips))
|
||||
for i := 0; i < len(eips); i += 1 {
|
||||
ret[i] = &eips[i]
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
|
||||
eips, total, err := self.GetEips(eipId, 0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if total == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if total > 1 {
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
}
|
||||
return &eips[0], nil
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aliyun"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type EipListOptions struct {
|
||||
Offset int `help:"List offset"`
|
||||
Limit int `help:"List limit"`
|
||||
}
|
||||
shellutils.R(&EipListOptions{}, "eip-list", "List eips", func(cli *aliyun.SRegion, args *EipListOptions) error {
|
||||
eips, total, e := cli.GetEips("", args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(eips, total, args.Offset, args.Limit, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipAllocateOptions struct {
|
||||
BW int `help:"Bandwidth limit in Mbps"`
|
||||
}
|
||||
shellutils.R(&EipAllocateOptions{}, "eip-create", "Allocate an EIP", func(cli *aliyun.SRegion, args *EipAllocateOptions) error {
|
||||
eip, err := cli.AllocateEIP(args.BW, aliyun.InternetChargeByTraffic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(eip)
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipReleaseOptions struct {
|
||||
ID string `help:"EIP allocation ID"`
|
||||
}
|
||||
shellutils.R(&EipReleaseOptions{}, "eip-delete", "Release an EIP", func(cli *aliyun.SRegion, args *EipReleaseOptions) error {
|
||||
err := cli.DeallocateEIP(args.ID)
|
||||
return err
|
||||
})
|
||||
|
||||
type EipAssociateOptions struct {
|
||||
ID string `help:"EIP allocation ID"`
|
||||
INSTANCE string `help:"Instance ID"`
|
||||
}
|
||||
shellutils.R(&EipAssociateOptions{}, "eip-associate", "Associate an EIP", func(cli *aliyun.SRegion, args *EipAssociateOptions) error {
|
||||
err := cli.AssociateEip(args.ID, args.INSTANCE)
|
||||
return err
|
||||
})
|
||||
shellutils.R(&EipAssociateOptions{}, "eip-dissociate", "Dissociate an EIP", func(cli *aliyun.SRegion, args *EipAssociateOptions) error {
|
||||
err := cli.DissociateEip(args.ID, args.INSTANCE)
|
||||
return err
|
||||
})
|
||||
}
|
||||
@@ -109,8 +109,8 @@ func (self *SVirtualMachine) GetINics() ([]cloudprovider.ICloudNic, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetEIP() cloudprovider.ICloudEIP {
|
||||
return nil
|
||||
func (self *SVirtualMachine) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetVcpuCount() int8 {
|
||||
|
||||
Reference in New Issue
Block a user