mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
feat(region): nat op support
This commit is contained in:
@@ -15,265 +15,24 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ElasticipListOptions struct {
|
||||
Region string `help:"List eips in cloudregion"`
|
||||
|
||||
Usable *bool `help:"List all zones that is usable"`
|
||||
UsableEipForAssociateType string `help:"With associate id filter which eip can associate"`
|
||||
UsableEipForAssociateId string `help:"With associate type filter which eip can associate"`
|
||||
|
||||
options.BaseListOptions
|
||||
}
|
||||
R(&ElasticipListOptions{}, "eip-list", "List elastic IPs", func(s *mcclient.ClientSession, opts *ElasticipListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
results, err := modules.Elasticips.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(results, modules.Elasticips.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipCreateOptions struct {
|
||||
NAME string `help:"name of the EIP"`
|
||||
Manager string `help:"cloud provider"`
|
||||
Region string `help:"cloud region in which EIP is allocated"`
|
||||
Bandwidth int `help:"Bandwidth in Mbps"`
|
||||
IpAddr string `help:"IP address of the EIP" json:"ip_addr"`
|
||||
Network string `help:"Network of the EIP"`
|
||||
BgpType string `help:"BgpType of the EIP" positional:"false"`
|
||||
ChargeType string `help:"bandwidth charge type" 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.NAME), "name")
|
||||
if args.Region != "" {
|
||||
params.Add(jsonutils.NewString(args.Region), "region")
|
||||
}
|
||||
if args.Manager != "" {
|
||||
params.Add(jsonutils.NewString(args.Manager), "manager")
|
||||
}
|
||||
if args.Bandwidth != 0 {
|
||||
params.Add(jsonutils.NewInt(int64(args.Bandwidth)), "bandwidth")
|
||||
}
|
||||
|
||||
if len(args.ChargeType) > 0 {
|
||||
params.Add(jsonutils.NewString(args.ChargeType), "charge_type")
|
||||
}
|
||||
|
||||
if len(args.Network) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Network), "network")
|
||||
}
|
||||
if len(args.BgpType) > 0 {
|
||||
params.Add(jsonutils.NewString(args.BgpType), "bgp_type")
|
||||
}
|
||||
|
||||
if len(args.IpAddr) > 0 {
|
||||
params.Add(jsonutils.NewString(args.IpAddr), "ip_addr")
|
||||
}
|
||||
|
||||
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"`
|
||||
|
||||
EnableAutoDellocate bool `help:"enable automatically dellocate when dissociate from instance"`
|
||||
DisableAutoDellocate bool `help:"disable automatically dellocate when dissociate from instance"`
|
||||
}
|
||||
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")
|
||||
}
|
||||
if args.EnableAutoDellocate {
|
||||
params.Add(jsonutils.JSONTrue, "auto_dellocate")
|
||||
} else if args.DisableAutoDellocate {
|
||||
params.Add(jsonutils.JSONFalse, "auto_dellocate")
|
||||
}
|
||||
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 EipDissociateOptions struct {
|
||||
ID string `help:"ID or name of EIP"`
|
||||
AutoDelete bool `help:"automatically delete the dissociate EIP" json:"auto_delete,omitfalse"`
|
||||
}
|
||||
R(&EipDissociateOptions{}, "eip-dissociate", "Dissociate an EIP from an instance", func(s *mcclient.ClientSession, args *EipDissociateOptions) error {
|
||||
params, err := options.StructToParams(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.Elasticips.PerformAction(s, args.ID, "dissociate", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipSingleOptions struct {
|
||||
ID string `help:"ID or name of EIP"`
|
||||
}
|
||||
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
|
||||
})
|
||||
|
||||
R(&EipSingleOptions{}, "eip-syncstatus", "Synchronize status of an EIP", func(s *mcclient.ClientSession, args *EipSingleOptions) error {
|
||||
result, err := modules.Elasticips.PerformAction(s, args.ID, "syncstatus", 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"`
|
||||
BgpType string `help:"desired BGP type"`
|
||||
ChargeType string `help:"bandwidth charge type" 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 args.BgpType != "" {
|
||||
params.Add(jsonutils.NewString(args.BgpType), "bgp_type")
|
||||
}
|
||||
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.Elasticips.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
|
||||
})
|
||||
|
||||
type EipPurgeOptions struct {
|
||||
ID string `help:"ID or name of EIP"`
|
||||
}
|
||||
R(&EipPurgeOptions{}, "eip-purge", "Purge EIP db records", func(s *mcclient.ClientSession, args *EipPurgeOptions) error {
|
||||
result, err := modules.Elasticips.PerformAction(s, args.ID, "purge", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipChangeOwnerOptions struct {
|
||||
ID string `help:"EIP to change owner"`
|
||||
PROJECT string `help:"Project ID or change"`
|
||||
RawId bool `help:"User raw ID, instead of name"`
|
||||
}
|
||||
R(&EipChangeOwnerOptions{}, "eip-change-owner", "Change owner porject of a eip", func(s *mcclient.ClientSession, opts *EipChangeOwnerOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if opts.RawId {
|
||||
projid, err := modules.Projects.GetId(s, opts.PROJECT, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params.Add(jsonutils.NewString(projid), "tenant")
|
||||
params.Add(jsonutils.JSONTrue, "raw_id")
|
||||
} else {
|
||||
params.Add(jsonutils.NewString(opts.PROJECT), "tenant")
|
||||
}
|
||||
srv, err := modules.Elasticips.PerformAction(s, opts.ID, "change-owner", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(srv)
|
||||
return nil
|
||||
})
|
||||
|
||||
cmd := shell.NewResourceCmd(&modules.Elasticips).WithKeyword("eip")
|
||||
cmd.List(&compute.ElasticipListOptions{})
|
||||
cmd.Create(&compute.EipCreateOptions{})
|
||||
cmd.Delete(&options.BaseIdOptions{})
|
||||
cmd.Update(&compute.EipUpdateOptions{})
|
||||
cmd.Show(&options.BaseShowOptions{})
|
||||
cmd.Perform("purge", &options.BaseIdOptions{})
|
||||
cmd.Perform("associate", &compute.EipAssociateOptions{})
|
||||
cmd.Perform("dissociate", &compute.EipDissociateOptions{})
|
||||
cmd.Perform("sync", &options.BaseIdOptions{})
|
||||
cmd.Perform("syncstatus", &options.BaseIdOptions{})
|
||||
cmd.Perform("change-bandwidth", &options.BaseIdOptions{})
|
||||
cmd.Perform("change-owner", &compute.EipChangeOwnerOptions{})
|
||||
}
|
||||
|
||||
29
cmd/climc/shell/compute/nat_sku.go
Normal file
29
cmd/climc/shell/compute/nat_sku.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.NatSkus).WithKeyword("nat-sku")
|
||||
cmd.List(&compute.NatSkuListOption{})
|
||||
cmd.Show(&compute.NatSkuIdOption{})
|
||||
cmd.PerformClass("sync-skus", &options.SkuSyncOptions{})
|
||||
}
|
||||
@@ -20,11 +20,12 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
R(&options.NatDTableListOptions{}, "dnat-list", "List DNAT entries", func(s *mcclient.ClientSession, opts *options.NatDTableListOptions) error {
|
||||
R(&compute.NatDTableListOptions{}, "dnat-list", "List DNAT entries", func(s *mcclient.ClientSession, opts *compute.NatDTableListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -36,7 +37,7 @@ func init() {
|
||||
printList(result, modules.NatDTable.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
R(&options.NatDDeleteShowOptions{}, "dnat-delete", "Delete a DNAT", func(s *mcclient.ClientSession, args *options.NatDDeleteShowOptions) error {
|
||||
R(&compute.NatDDeleteShowOptions{}, "dnat-delete", "Delete a DNAT", func(s *mcclient.ClientSession, args *compute.NatDDeleteShowOptions) error {
|
||||
results, err := modules.NatDTable.Delete(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -44,7 +45,7 @@ func init() {
|
||||
printObject(results)
|
||||
return nil
|
||||
})
|
||||
R(&options.NatDDeleteShowOptions{}, "dnat-show", "Show a DNAT", func(s *mcclient.ClientSession, args *options.NatDDeleteShowOptions) error {
|
||||
R(&compute.NatDDeleteShowOptions{}, "dnat-show", "Show a DNAT", func(s *mcclient.ClientSession, args *compute.NatDDeleteShowOptions) error {
|
||||
results, err := modules.NatDTable.Get(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -53,7 +54,7 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.NatDCreateOptions{}, "dnat-create", "Create a DNAT", func(s *mcclient.ClientSession, args *options.NatDCreateOptions) error {
|
||||
R(&compute.NatDCreateOptions{}, "dnat-create", "Create a DNAT", func(s *mcclient.ClientSession, args *compute.NatDCreateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.NAME), "name")
|
||||
params.Add(jsonutils.NewString(args.NATGATEWAYID), "natgateway_id")
|
||||
|
||||
@@ -15,67 +15,18 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.NatGateways).WithKeyword("nat")
|
||||
|
||||
R(&options.NatGatewayListOptions{}, "natgateway-list", "List NAT gateways", func(s *mcclient.ClientSession, opts *options.NatGatewayListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.NatGateways.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.NatGateways.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.NatGatewayIdOptions{}, "natgateway-show", "Show a NAT gateway", func(s *mcclient.ClientSession, args *options.NatGatewayIdOptions) error {
|
||||
results, err := modules.NatGateways.Get(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(results)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.NatGatewayIdOptions{}, "natgateway-syncstatus", "Sync NAT gateway status", func(s *mcclient.ClientSession, args *options.NatGatewayIdOptions) error {
|
||||
result, err := modules.NatGateways.PerformAction(s, args.ID, "syncstatus", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type NatGatewayListEipOptions struct {
|
||||
ID string `help:"ID"`
|
||||
}
|
||||
|
||||
R(&NatGatewayListEipOptions{}, "natgateway-dnat-resources", "list resources in dnats of natgateway",
|
||||
func(s *mcclient.ClientSession, opts *NatGatewayListEipOptions) error {
|
||||
|
||||
ret, err := modules.NatGateways.PerformAction(s, opts.ID, "dnat-resources", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&NatGatewayListEipOptions{}, "natgateway-snat-resources", "list resources in snats of natgateway",
|
||||
func(s *mcclient.ClientSession, opts *NatGatewayListEipOptions) error {
|
||||
|
||||
ret, err := modules.NatGateways.PerformAction(s, opts.ID, "snat-resources", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
cmd.List(&compute.NatGatewayListOptions{})
|
||||
cmd.Create(&api.NatgatewayCreateInput{})
|
||||
cmd.Show(&compute.NatGatewayIdOptions{})
|
||||
cmd.Delete(&compute.NatGatewayDeleteOption{})
|
||||
cmd.Perform("syncstauts", &compute.NatGatewayIdOptions{})
|
||||
}
|
||||
|
||||
@@ -20,11 +20,12 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
R(&options.NatSTableListOptions{}, "snat-list", "List SNAT entries", func(s *mcclient.ClientSession, opts *options.NatSTableListOptions) error {
|
||||
R(&compute.NatSTableListOptions{}, "snat-list", "List SNAT entries", func(s *mcclient.ClientSession, opts *compute.NatSTableListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -36,7 +37,7 @@ func init() {
|
||||
printList(result, modules.NatSTable.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
R(&options.NatSDeleteShowOptions{}, "snat-delete", "Delete a SNAT", func(s *mcclient.ClientSession, args *options.NatSDeleteShowOptions) error {
|
||||
R(&compute.NatSDeleteShowOptions{}, "snat-delete", "Delete a SNAT", func(s *mcclient.ClientSession, args *compute.NatSDeleteShowOptions) error {
|
||||
results, err := modules.NatSTable.Delete(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -45,7 +46,7 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.NatSDeleteShowOptions{}, "snat-show", "Show a SNAT", func(s *mcclient.ClientSession, args *options.NatSDeleteShowOptions) error {
|
||||
R(&compute.NatSDeleteShowOptions{}, "snat-show", "Show a SNAT", func(s *mcclient.ClientSession, args *compute.NatSDeleteShowOptions) error {
|
||||
results, err := modules.NatSTable.Get(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -54,7 +55,7 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.NatSCreateOptions{}, "snat-create", "Create a SNAT", func(s *mcclient.ClientSession, args *options.NatSCreateOptions) error {
|
||||
R(&compute.NatSCreateOptions{}, "snat-create", "Create a SNAT", func(s *mcclient.ClientSession, args *compute.NatSCreateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.NAME), "name")
|
||||
params.Add(jsonutils.NewString(args.NATGATEWAYID), "natgateway_id")
|
||||
|
||||
@@ -84,6 +84,7 @@ func init() {
|
||||
cmd.Perform("set-auto-renew", new(options.ServerSetAutoRenew))
|
||||
cmd.Perform("save-template", new(options.ServerSaveImageOptions))
|
||||
cmd.Perform("remote-update", new(options.ServerRemoteUpdateOptions))
|
||||
cmd.Perform("create-eip", &options.ServerCreateEipOptions{})
|
||||
|
||||
cmd.Get("vnc", new(options.ServerIdOptions))
|
||||
cmd.Get("desc", new(options.ServerIdOptions))
|
||||
|
||||
@@ -87,3 +87,18 @@ type ElasticipDetails struct {
|
||||
|
||||
type ElasticipSyncstatusInput struct {
|
||||
}
|
||||
|
||||
type ElasticipAssociateInput struct {
|
||||
// 待绑定实例Id
|
||||
InstanceId string `json:"instance_id"`
|
||||
// swagger:ignore
|
||||
InstanceExternalId string `json:"instance_external_id"`
|
||||
|
||||
// swagger:ignore
|
||||
Instance string `json:"instance" yunion-deprecated-by:"instance_id"`
|
||||
|
||||
// 实例类型
|
||||
// enmu: server, natgateway
|
||||
// default: server
|
||||
InstanceType string `json:"instance_type"`
|
||||
}
|
||||
|
||||
@@ -42,6 +42,11 @@ const (
|
||||
|
||||
EIP_CHARGE_TYPE_BY_TRAFFIC = "traffic"
|
||||
EIP_CHARGE_TYPE_BY_BANDWIDTH = "bandwidth"
|
||||
|
||||
INSTANCE_ASSOCIATE_EIP = "associate_eip"
|
||||
INSTANCE_ASSOCIATE_EIP_FAILED = "associate_eip_failed"
|
||||
INSTANCE_DISSOCIATE_EIP = "dissociate_eip"
|
||||
INSTANCE_DISSOCIATE_EIP_FAILED = "dissociate_eip_failed"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -109,10 +109,10 @@ const (
|
||||
VM_RESTORE_STATE = "restore_state"
|
||||
VM_RESTORE_FAILED = "restore_failed"
|
||||
|
||||
VM_ASSOCIATE_EIP = "associate_eip"
|
||||
VM_ASSOCIATE_EIP_FAILED = "associate_eip_failed"
|
||||
VM_DISSOCIATE_EIP = "dissociate_eip"
|
||||
VM_DISSOCIATE_EIP_FAILED = "dissociate_eip_failed"
|
||||
VM_ASSOCIATE_EIP = INSTANCE_ASSOCIATE_EIP
|
||||
VM_ASSOCIATE_EIP_FAILED = INSTANCE_ASSOCIATE_EIP_FAILED
|
||||
VM_DISSOCIATE_EIP = INSTANCE_DISSOCIATE_EIP
|
||||
VM_DISSOCIATE_EIP_FAILED = INSTANCE_DISSOCIATE_EIP_FAILED
|
||||
|
||||
// 公网IP转换Eip中(EIP转换中)
|
||||
VM_START_EIP_CONVERT = "start_eip_convert"
|
||||
|
||||
40
pkg/apis/compute/nat_skus.go
Normal file
40
pkg/apis/compute/nat_skus.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package compute
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
NAT_SKU_AVAILABLE = "available"
|
||||
NAT_SKU_SOLDOUT = "soldout"
|
||||
|
||||
ALIYUN_NAT_SKU_DEFAULT = "Default"
|
||||
)
|
||||
|
||||
type NatSkuListInput struct {
|
||||
apis.EnabledStatusStandaloneResourceListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
RegionalFilterListInput
|
||||
|
||||
PostpaidStatus string `json:"postpaid_stauts"`
|
||||
PrepaidStatus string `json:"prepaid_status"`
|
||||
}
|
||||
|
||||
type NatSkuDetails struct {
|
||||
apis.EnabledStatusStandaloneResourceDetails
|
||||
|
||||
CloudregionResourceInfo
|
||||
}
|
||||
@@ -15,18 +15,26 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
const (
|
||||
NAT_STAUTS_AVAILABLE = "available" //可用
|
||||
NAT_STATUS_ALLOCATE = "allocate" //创建中
|
||||
NAT_STATUS_DEPLOYING = "deploying" //配置中
|
||||
NAT_STATUS_UNKNOWN = "unknown" //未知状态
|
||||
NAT_STATUS_FAILED = "failed" //创建失败
|
||||
NAT_STATUS_DELETED = "deleted" //删除
|
||||
NAT_STATUS_DELETING = "deleting" //删除中
|
||||
NAT_STATUS_DELETE_FAILED = "delete_failed" //删除失败
|
||||
NAT_STAUTS_AVAILABLE = "available" // 可用
|
||||
NAT_STATUS_ALLOCATE = "allocate" // 创建中
|
||||
NAT_STATUS_DEPLOYING = "deploying" // 配置中
|
||||
NAT_STATUS_UNKNOWN = "unknown" // 未知状态
|
||||
NAT_STATUS_CREATE_FAILED = "create_failed" // 创建失败
|
||||
NAT_STATUS_DELETED = "deleted" // 删除
|
||||
NAT_STATUS_DELETING = "deleting" // 删除中
|
||||
NAT_STATUS_DELETE_FAILED = "delete_failed" // 删除失败
|
||||
NAT_STATUS_SET_AUTO_RENEW = "set_auto_renew" // 设置自动续费中
|
||||
NAT_STATUS_SET_AUTO_RENEW_FAILED = "set_auto_renew_failed" // 设置自动续费失败
|
||||
NAT_STATUS_RENEWING = "renewing" // 续费中
|
||||
NAT_STATUS_RENEW_FAILED = "renew_failed" // 续费失败
|
||||
|
||||
NAT_SPEC_SMALL = "small" //小型
|
||||
NAT_SPEC_MIDDLE = "middle" //中型
|
||||
@@ -41,17 +49,15 @@ const (
|
||||
type NatGetewayListInput struct {
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
apis.DeletePreventableResourceBaseListInput
|
||||
|
||||
VpcFilterListInput
|
||||
RegionalFilterListInput
|
||||
ManagedResourceListInput
|
||||
}
|
||||
|
||||
type NatEntryListInput struct {
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
NatGatewayFilterListInput
|
||||
ManagedResourceListInput
|
||||
}
|
||||
|
||||
type NatDEntryListInput struct {
|
||||
@@ -111,3 +117,49 @@ type NatEntryDetails struct {
|
||||
|
||||
type NatGatewaySyncstatusInput struct {
|
||||
}
|
||||
|
||||
type NatgatewayCreateInput struct {
|
||||
apis.StatusInfrasResourceBaseCreateInput
|
||||
|
||||
// 包年包月时间周期
|
||||
Duration string `json:"duration"`
|
||||
|
||||
// 是否自动续费(仅包年包月时生效)
|
||||
// default: false
|
||||
AutoRenew bool `json:"auto_renew"`
|
||||
|
||||
// 到期释放时间,仅后付费支持
|
||||
ExpiredAt time.Time `json:"expired_at"`
|
||||
|
||||
// 计费方式
|
||||
// enum: postpaid, prepaid
|
||||
BillingType string `json:"billing_type"`
|
||||
// swagger:ignore
|
||||
BillingCycle string `json:"billing_cycle"`
|
||||
|
||||
NetworkId string `json:"network_id"`
|
||||
|
||||
// swagger:ignore
|
||||
VpcId string `json:"vpc_id"`
|
||||
|
||||
// 绑定已有弹性公网IP,要求EIP必须和Vpc在同一区域
|
||||
Eip string `json:"eip"`
|
||||
|
||||
// 绑定新建弹性公网IP
|
||||
EipBw int `json:"eip_bw,omitzero"`
|
||||
|
||||
// 弹性公网IP计费类型
|
||||
// enum: bandwidth, traffic
|
||||
// default: traffic
|
||||
EipChargeType string `json:"eip_charge_type,omitempty"`
|
||||
EipBgpType string `json:"eip_bgp_type"`
|
||||
EipAutoDellocate bool `json:"eip_auto_dellocate"`
|
||||
}
|
||||
|
||||
func (opts *NatgatewayCreateInput) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type NatgatewayDeleteInput struct {
|
||||
Force bool `json:"force"`
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
package apis
|
||||
|
||||
import "time"
|
||||
|
||||
type DomainizedResourceInput struct {
|
||||
// 指定项目归属域名称或ID
|
||||
// required: false
|
||||
@@ -350,3 +352,17 @@ type DistinctFieldInput struct {
|
||||
Field []string
|
||||
ExtraField []string
|
||||
}
|
||||
|
||||
type PostpaidExpireInput struct {
|
||||
Duration string `json:"duration"`
|
||||
ExpireTime time.Time `json:"expireType"`
|
||||
}
|
||||
|
||||
type AutoRenewInput struct {
|
||||
// 是否自动续费
|
||||
AutoRenew bool `json:"auto_renew"`
|
||||
}
|
||||
|
||||
type RenewInput struct {
|
||||
Duration string `json:"duration"`
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ const (
|
||||
CLOUD_CAPABILITY_PUBLIC_IP = "public_ip"
|
||||
CLOUD_CAPABILITY_INTERVPCNETWORK = "intervpcnetwork"
|
||||
CLOUD_CAPABILITY_SAML_AUTH = "saml_auth" // 是否支持SAML 2.0
|
||||
CLOUD_CAPABILITY_NAT = "nat" // NAT网关
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
package cloudprovider
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/util/billing"
|
||||
|
||||
// These two structures are designed for modifying snat table and dnat table.
|
||||
// There is a so strange point that they have both field of ExternalIP and ExternalIPID.
|
||||
// The reason is that you must pass ExternalIPID to modify in Huawei Cloud for now.
|
||||
@@ -38,3 +40,13 @@ type SNatDRule struct {
|
||||
ExternalIPID string
|
||||
ExternalPort int
|
||||
}
|
||||
|
||||
type NatGatewayCreateOptions struct {
|
||||
Name string
|
||||
VpcId string
|
||||
NetworkId string
|
||||
Desc string
|
||||
NatSpec string
|
||||
|
||||
BillingCycle *billing.SBillingCycle
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ type IBillingResource interface {
|
||||
GetCreatedAt() time.Time
|
||||
GetExpiredAt() time.Time
|
||||
SetAutoRenew(autoRenew bool) error
|
||||
Renew(bc billing.SBillingCycle) error
|
||||
IsAutoRenew() bool
|
||||
}
|
||||
|
||||
@@ -328,8 +329,6 @@ type ICloudVM interface {
|
||||
|
||||
CreateDisk(ctx context.Context, sizeMb int, uuid string, driver string) error
|
||||
|
||||
Renew(bc billing.SBillingCycle) error
|
||||
|
||||
MigrateVM(hostid string) error
|
||||
LiveMigrateVM(hostid string) error
|
||||
|
||||
@@ -524,6 +523,7 @@ type ICloudVpc interface {
|
||||
|
||||
GetIWireById(wireId string) (ICloudWire, error)
|
||||
GetINatGateways() ([]ICloudNatGateway, error)
|
||||
CreateINatGateway(opts *NatGatewayCreateOptions) (ICloudNatGateway, error)
|
||||
|
||||
GetICloudVpcPeeringConnections() ([]ICloudVpcPeeringConnection, error)
|
||||
GetICloudAccepterVpcPeeringConnections() ([]ICloudVpcPeeringConnection, error)
|
||||
@@ -790,6 +790,8 @@ type ICloudNatGateway interface {
|
||||
// Read the description of these two structures before using.
|
||||
CreateINatDEntry(rule SNatDRule) (ICloudNatDEntry, error)
|
||||
CreateINatSEntry(rule SNatSRule) (ICloudNatSEntry, error)
|
||||
|
||||
Delete() error
|
||||
}
|
||||
|
||||
// ICloudNatDEntry describe a DNat rule which transfer externalIp:externalPort to
|
||||
@@ -874,7 +876,6 @@ type ICloudDBInstance interface {
|
||||
GetIDBInstanceBackups() ([]ICloudDBInstanceBackup, error)
|
||||
|
||||
ChangeConfig(ctx context.Context, config *SManagedDBInstanceChangeConfig) error
|
||||
Renew(bc billing.SBillingCycle) error
|
||||
|
||||
OpenPublicConnection() error
|
||||
ClosePublicConnection() error
|
||||
@@ -995,7 +996,6 @@ type ICloudElasticcache interface {
|
||||
UpdateAuthMode(noPasswordAccess bool, password string) error
|
||||
UpdateInstanceParameters(config jsonutils.JSONObject) error
|
||||
UpdateBackupPolicy(config SCloudElasticCacheBackupPolicyUpdateInput) error
|
||||
Renew(bc billing.SBillingCycle) error
|
||||
|
||||
UpdateSecurityGroups(secgroupIds []string) error
|
||||
}
|
||||
|
||||
@@ -18,16 +18,13 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
@@ -237,58 +234,3 @@ func (self *SAwsGuestDriver) GetGuestInitialStateAfterRebuild() string {
|
||||
func (self *SAwsGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, server *models.SGuest, eip *models.SElasticip, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
if server.Status != api.VM_ASSOCIATE_EIP {
|
||||
server.SetStatus(userCred, api.VM_ASSOCIATE_EIP, "associate eip")
|
||||
}
|
||||
|
||||
extEip, err := eip.GetIEip()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SAwsGuestDriver.RequestAssociateEip fail to find iEIP for eip %s", err)
|
||||
}
|
||||
|
||||
conf := &cloudprovider.AssociateConfig{
|
||||
InstanceId: server.ExternalId,
|
||||
Bandwidth: eip.Bandwidth,
|
||||
AssociateType: api.EIP_ASSOCIATE_TYPE_SERVER,
|
||||
}
|
||||
|
||||
err = extEip.Associate(conf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SAwsGuestDriver.RequestAssociateEip fail to remote associate EIP %s", err)
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(extEip, api.EIP_STATUS_READY, 3*time.Second, 60*time.Second)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SAwsGuestDriver.RequestAssociateEip.WaitStatus")
|
||||
}
|
||||
|
||||
err = eip.AssociateVM(ctx, userCred, server)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SAwsGuestDriver.RequestAssociateEip fail to local associate EIP %s", err)
|
||||
}
|
||||
|
||||
eip.SetStatus(userCred, api.EIP_STATUS_READY, "associate")
|
||||
|
||||
// 如果aws已经绑定了EIP,则要把多余的公有IP删除
|
||||
if extEip.GetMode() == api.EIP_MODE_STANDALONE_EIP {
|
||||
publicIP, err := server.GetPublicIp()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "AwsGuestDriver.GetPublicIp")
|
||||
}
|
||||
|
||||
if publicIP != nil {
|
||||
err = db.DeleteModel(ctx, userCred, publicIP)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "AwsGuestDriver.DeletePublicIp")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -294,10 +294,6 @@ func (self *SBaseGuestDriver) IsSupportPublicIp() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, eip *models.SElasticip, task taskman.ITask) error {
|
||||
return fmt.Errorf("SBaseGuestDriver: Not Implement RequestAssociateEip")
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) NeedStopForChangeSpec(guest *models.SGuest, cpuChanged, memChanged bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -531,10 +531,6 @@ func (self *SESXiGuestDriver) IsSupportEip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, eip *models.SElasticip, task taskman.ITask) error {
|
||||
return fmt.Errorf("ESXiGuestDriver not support associate eip")
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) IsSupportCdrom(guest *models.SGuest) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ func (self *SKVMGuestDriver) RequestAssociateEip(ctx context.Context, userCred m
|
||||
guestnic.Ifname, guestnic.GuestId, guestnic.NetworkId)
|
||||
}
|
||||
|
||||
if err := eip.AssociateVM(ctx, userCred, guest); err != nil {
|
||||
if err := eip.AssociateInstance(ctx, userCred, api.EIP_ASSOCIATE_TYPE_SERVER, guest); err != nil {
|
||||
return errors.Wrapf(err, "associate eip %s(%s) to vm %s(%s)", eip.Name, eip.Id, guest.Name, guest.Id)
|
||||
}
|
||||
if err := eip.SetStatus(userCred, api.EIP_STATUS_READY, api.EIP_STATUS_ASSOCIATE); err != nil {
|
||||
|
||||
@@ -1103,45 +1103,6 @@ func (self *SManagedVirtualizedGuestDriver) IsSupportEip() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, server *models.SGuest, eip *models.SElasticip, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
if server.Status != api.VM_ASSOCIATE_EIP {
|
||||
server.SetStatus(userCred, api.VM_ASSOCIATE_EIP, "associate eip")
|
||||
}
|
||||
|
||||
extEip, err := eip.GetIEip()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ManagedVirtualizedGuestDriver.RequestAssociateEip fail to find iEIP for eip %s", err)
|
||||
}
|
||||
|
||||
conf := &cloudprovider.AssociateConfig{
|
||||
InstanceId: server.ExternalId,
|
||||
Bandwidth: eip.Bandwidth,
|
||||
AssociateType: api.EIP_ASSOCIATE_TYPE_SERVER,
|
||||
}
|
||||
|
||||
err = extEip.Associate(conf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ManagedVirtualizedGuestDriver.RequestAssociateEip fail to remote associate EIP %s", err)
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(extEip, api.EIP_STATUS_READY, 3*time.Second, 60*time.Second)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ManagedVirtualizedGuestDriver.RequestAssociateEip.WaitStatus")
|
||||
}
|
||||
|
||||
err = eip.AssociateVM(ctx, userCred, server)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ManagedVirtualizedGuestDriver.RequestAssociateEip fail to local associate EIP %s", err)
|
||||
}
|
||||
|
||||
eip.SetStatus(userCred, api.EIP_STATUS_READY, api.EIP_STATUS_ASSOCIATE)
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) chooseHostStorage(
|
||||
drv models.IGuestDriver,
|
||||
host *models.SHost,
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
@@ -175,23 +176,21 @@ func ListExpiredPostpaidResources(
|
||||
return q
|
||||
}
|
||||
|
||||
func ParseBillingCycleInput(billingBase *SBillingResourceBase, data jsonutils.JSONObject) (*billing.SBillingCycle, error) {
|
||||
func ParseBillingCycleInput(billingBase *SBillingResourceBase, input apis.PostpaidExpireInput) (*billing.SBillingCycle, error) {
|
||||
var (
|
||||
bc billing.SBillingCycle
|
||||
err error
|
||||
durationStr string
|
||||
)
|
||||
durationStr, _ = data.GetString("duration")
|
||||
if len(durationStr) == 0 {
|
||||
expireTime, err := data.GetTime("expire_time")
|
||||
if err != nil {
|
||||
if len(input.Duration) == 0 {
|
||||
if input.ExpireTime.IsZero() {
|
||||
return nil, httperrors.NewInputParameterError("missing duration/expire_time")
|
||||
}
|
||||
timeC := billingBase.ExpiredAt
|
||||
if timeC.IsZero() {
|
||||
timeC = time.Now()
|
||||
}
|
||||
dur := expireTime.Sub(timeC)
|
||||
dur := input.ExpireTime.Sub(timeC)
|
||||
if dur <= 0 {
|
||||
return nil, httperrors.NewInputParameterError("expire time is before current expire at")
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ type SCapabilities struct {
|
||||
// 支持SAML 2.0
|
||||
SamlAuthBrands []string `json:",allowempty"`
|
||||
DisabledSamlAuthBrands []string `json:",allowempty"`
|
||||
NatBrands []string `json:",allowempty"`
|
||||
DisabledNatBrands []string `json:",allowempty"`
|
||||
PublicIpBrands []string `json:",allowempty"`
|
||||
NetworkManageBrands []string `json:",allowempty"`
|
||||
DisabledNetworkManageBrands []string `json:",allowempty"`
|
||||
@@ -286,6 +288,7 @@ func getBrands(region *SCloudregion, zone *SZone, domainId string, capa *SCapabi
|
||||
capa.PublicIpBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_PUBLIC_IP)
|
||||
capa.LoadbalancerEngineBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_LOADBALANCER)
|
||||
capa.SamlAuthBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_SAML_AUTH)
|
||||
capa.NatBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_NAT)
|
||||
|
||||
if utils.IsInStringArray(api.HYPERVISOR_KVM, capa.Hypervisors) || utils.IsInStringArray(api.HYPERVISOR_BAREMETAL, capa.Hypervisors) {
|
||||
capa.Brands = append(capa.Brands, api.ONECLOUD_BRAND_ONECLOUD)
|
||||
@@ -305,6 +308,7 @@ func getBrands(region *SCloudregion, zone *SZone, domainId string, capa *SCapabi
|
||||
capa.DisabledObjectStorageBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE)
|
||||
capa.DisabledCloudIdBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_CLOUDID)
|
||||
capa.DisabledSamlAuthBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_SAML_AUTH)
|
||||
capa.DisabledNatBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_NAT)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1978,12 +1978,12 @@ func (self *SDBInstance) AllowPerformPostpaidExpire(ctx context.Context, userCre
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "postpaid-expire")
|
||||
}
|
||||
|
||||
func (self *SDBInstance) PerformPostpaidExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
func (self *SDBInstance) PerformPostpaidExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PostpaidExpireInput) (jsonutils.JSONObject, error) {
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return nil, httperrors.NewBadRequestError("dbinstance billing type is %s", self.BillingType)
|
||||
}
|
||||
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, data)
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1851,12 +1851,12 @@ func (self *SElasticcache) AllowPerformPostpaidExpire(ctx context.Context, userC
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "postpaid-expire")
|
||||
}
|
||||
|
||||
func (self *SElasticcache) PerformPostpaidExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
func (self *SElasticcache) PerformPostpaidExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PostpaidExpireInput) (jsonutils.JSONObject, error) {
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return nil, httperrors.NewBadRequestError("elasticcache billing type is %s", self.BillingType)
|
||||
}
|
||||
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, data)
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package models
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/httperrors"
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
)
|
||||
|
||||
type IGetVpc interface {
|
||||
GetName() string
|
||||
type IEipAssociateInstance interface {
|
||||
db.IStatusStandaloneModel
|
||||
GetVpc() (*SVpc, error)
|
||||
}
|
||||
|
||||
func ValidateAssociateEip(obj IGetVpc) error {
|
||||
func ValidateAssociateEip(obj IEipAssociateInstance) error {
|
||||
vpc, err := obj.GetVpc()
|
||||
if err != nil {
|
||||
return httperrors.NewGeneralError(err)
|
||||
|
||||
@@ -248,8 +248,12 @@ func (manager *SElasticipManager) QueryDistinctExtraField(q *sqlchemy.SQuery, fi
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SElasticip) GetRegion() *SCloudregion {
|
||||
return CloudregionManager.FetchRegionById(self.CloudregionId)
|
||||
func (self *SElasticip) GetRegion() (*SCloudregion, error) {
|
||||
region, err := CloudregionManager.FetchById(self.CloudregionId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CloudregionManager.FetchById")
|
||||
}
|
||||
return region.(*SCloudregion), nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) GetNetwork() (*SNetwork, error) {
|
||||
@@ -423,22 +427,11 @@ func (self *SElasticip) SyncInstanceWithCloudEip(ctx context.Context, userCred m
|
||||
return q
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("fail to find vm by external ID %s", vmExtId)
|
||||
return err
|
||||
}
|
||||
switch newRes := extRes.(type) {
|
||||
case *SGuest:
|
||||
err = self.AssociateVM(ctx, userCred, newRes)
|
||||
case *SLoadbalancer:
|
||||
err = self.AssociateLoadbalancer(ctx, userCred, newRes)
|
||||
case *SNatGateway:
|
||||
err = self.AssociateNatGateway(ctx, userCred, newRes)
|
||||
default:
|
||||
return errors.Error("unsupported association type")
|
||||
return errors.Wrapf(err, "db.FetchByExternalIdAndManagerId %s %s", ext.GetAssociationType(), vmExtId)
|
||||
}
|
||||
err = self.AssociateInstance(ctx, userCred, ext.GetAssociationType(), extRes.(db.IStatusStandaloneModel))
|
||||
if err != nil {
|
||||
log.Errorf("fail to associate with new vm %s", err)
|
||||
return err
|
||||
return errors.Wrapf(err, "AssociateInstance")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -720,29 +713,32 @@ func (self *SElasticip) AssociateLoadbalancer(ctx context.Context, userCred mccl
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) AssociateVM(ctx context.Context, userCred mcclient.TokenCredential, vm *SGuest) error {
|
||||
if vm.PendingDeleted || vm.Deleted {
|
||||
return fmt.Errorf("vm is deleted")
|
||||
}
|
||||
if len(self.AssociateType) > 0 && len(self.AssociateId) > 0 {
|
||||
if self.AssociateType == api.EIP_ASSOCIATE_TYPE_SERVER && self.AssociateId == vm.Id {
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("EIP has been associated!!")
|
||||
func (self *SElasticip) AssociateInstance(ctx context.Context, userCred mcclient.TokenCredential, insType string, ins db.IStatusStandaloneModel) error {
|
||||
switch insType {
|
||||
case api.EIP_ASSOCIATE_TYPE_SERVER:
|
||||
vm := ins.(*SGuest)
|
||||
if vm.PendingDeleted || vm.Deleted {
|
||||
return fmt.Errorf("vm is deleted")
|
||||
}
|
||||
}
|
||||
if len(self.AssociateType) > 0 && len(self.AssociateId) > 0 {
|
||||
if self.AssociateType == insType && self.AssociateId == ins.GetId() {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("EIP has been associated!!")
|
||||
}
|
||||
_, err := db.Update(self, func() error {
|
||||
self.AssociateType = api.EIP_ASSOCIATE_TYPE_SERVER
|
||||
self.AssociateId = vm.Id
|
||||
self.AssociateType = insType
|
||||
self.AssociateId = ins.GetId()
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "db.Update")
|
||||
}
|
||||
|
||||
db.OpsLog.LogAttachEvent(ctx, vm, self, userCred, self.GetShortDesc(ctx))
|
||||
db.OpsLog.LogEvent(self, db.ACT_EIP_ATTACH, vm.GetShortDesc(ctx), userCred)
|
||||
db.OpsLog.LogEvent(vm, db.ACT_EIP_ATTACH, self.GetShortDesc(ctx), userCred)
|
||||
db.OpsLog.LogAttachEvent(ctx, ins, self, userCred, self.GetShortDesc(ctx))
|
||||
db.OpsLog.LogEvent(self, db.ACT_EIP_ATTACH, ins.GetShortDesc(ctx), userCred)
|
||||
db.OpsLog.LogEvent(ins, db.ACT_EIP_ATTACH, self.GetShortDesc(ctx), userCred)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -852,9 +848,9 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
|
||||
}
|
||||
|
||||
func (eip *SElasticip) GetQuotaKeys() (quotas.IQuotaKeys, error) {
|
||||
region := eip.GetRegion()
|
||||
region, err := eip.GetRegion()
|
||||
if region == nil {
|
||||
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid region")
|
||||
return nil, errors.Wrapf(err, "eip.GetRegion")
|
||||
}
|
||||
return fetchRegionalQuotaKeys(
|
||||
rbacutils.ScopeProject,
|
||||
@@ -885,12 +881,10 @@ func (self *SElasticip) PostCreate(ctx context.Context, userCred mcclient.TokenC
|
||||
func (self *SElasticip) startEipAllocateTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "EipAllocateTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("newtask EipAllocateTask fail %s", err)
|
||||
return err
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
self.SetStatus(userCred, api.EIP_STATUS_ALLOCATE, "start allocate")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (self *SElasticip) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
@@ -928,131 +922,122 @@ func (self *SElasticip) AllowPerformAssociate(ctx context.Context, userCred mccl
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "associate")
|
||||
}
|
||||
|
||||
func (self *SElasticip) PerformAssociate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
func (self *SElasticip) PerformAssociate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ElasticipAssociateInput) (api.ElasticipAssociateInput, error) {
|
||||
if self.IsAssociated() {
|
||||
return nil, httperrors.NewConflictError("eip has been associated with instance")
|
||||
return input, httperrors.NewConflictError("eip has been associated with instance")
|
||||
}
|
||||
|
||||
if self.Status != api.EIP_STATUS_READY {
|
||||
return nil, httperrors.NewInvalidStatusError("eip cannot associate in status %s", self.Status)
|
||||
return input, httperrors.NewInvalidStatusError("eip cannot associate in status %s", self.Status)
|
||||
}
|
||||
|
||||
if self.Mode == api.EIP_MODE_INSTANCE_PUBLICIP {
|
||||
return nil, httperrors.NewUnsupportOperationError("fixed eip cannot be associated")
|
||||
return input, httperrors.NewUnsupportOperationError("fixed eip cannot be associated")
|
||||
}
|
||||
|
||||
instanceId := jsonutils.GetAnyString(data, []string{"instance", "instance_id"})
|
||||
if len(instanceId) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("instance_id")
|
||||
if len(input.InstanceId) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("instance_id")
|
||||
}
|
||||
instanceType := jsonutils.GetAnyString(data, []string{"instance_type"})
|
||||
if len(instanceType) == 0 {
|
||||
instanceType = api.EIP_ASSOCIATE_TYPE_SERVER
|
||||
if len(input.InstanceType) == 0 {
|
||||
input.InstanceType = api.EIP_ASSOCIATE_TYPE_SERVER
|
||||
}
|
||||
|
||||
if instanceType != api.EIP_ASSOCIATE_TYPE_SERVER {
|
||||
return nil, httperrors.NewInputParameterError("Unsupported %s", instanceType)
|
||||
if !utils.IsInStringArray(input.InstanceType, api.EIP_ASSOCIATE_VALID_TYPES) {
|
||||
return input, httperrors.NewUnsupportOperationError("Unsupported instance type %s", input.InstanceType)
|
||||
}
|
||||
|
||||
vmObj, err := GuestManager.FetchByIdOrName(userCred, 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)
|
||||
|
||||
lockman.LockObject(ctx, server)
|
||||
defer lockman.ReleaseObject(ctx, server)
|
||||
|
||||
if server.PendingDeleted {
|
||||
return nil, httperrors.NewInvalidStatusError("cannot associate pending delete server")
|
||||
}
|
||||
|
||||
// IMPORTANT: this serves as a guard against a guest to have multiple
|
||||
// associated elastic_ips
|
||||
seip, _ := server.GetEipOrPublicIp()
|
||||
if seip != nil {
|
||||
return nil, httperrors.NewInvalidStatusError("instance is already associated with eip")
|
||||
}
|
||||
|
||||
if ok, _ := utils.InStringArray(server.Status, []string{api.VM_READY, api.VM_RUNNING}); !ok {
|
||||
return nil, httperrors.NewInvalidStatusError("cannot associate server in status %s", server.Status)
|
||||
}
|
||||
|
||||
err = ValidateAssociateEip(server)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(self.NetworkId) > 0 {
|
||||
gns, err := server.GetNetworks("")
|
||||
switch input.InstanceType {
|
||||
case api.EIP_ASSOCIATE_TYPE_SERVER:
|
||||
vmObj, err := GuestManager.FetchByIdOrName(userCred, input.InstanceId)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(errors.Wrap(err, "GetNetworks"))
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return input, httperrors.NewResourceNotFoundError("server %s not found", input.InstanceId)
|
||||
}
|
||||
return input, httperrors.NewGeneralError(err)
|
||||
}
|
||||
for _, gn := range gns {
|
||||
if gn.NetworkId == self.NetworkId {
|
||||
return nil, httperrors.NewInputParameterError("cannot associate eip with same network")
|
||||
server := vmObj.(*SGuest)
|
||||
|
||||
lockman.LockObject(ctx, server)
|
||||
defer lockman.ReleaseObject(ctx, server)
|
||||
|
||||
if server.PendingDeleted {
|
||||
return input, httperrors.NewInvalidStatusError("cannot associate pending delete server")
|
||||
}
|
||||
// IMPORTANT: this serves as a guard against a guest to have multiple
|
||||
// associated elastic_ips
|
||||
seip, _ := server.GetEipOrPublicIp()
|
||||
if seip != nil {
|
||||
return input, httperrors.NewInvalidStatusError("instance is already associated with eip")
|
||||
}
|
||||
|
||||
if ok, _ := utils.InStringArray(server.Status, []string{api.VM_READY, api.VM_RUNNING}); !ok {
|
||||
return input, httperrors.NewInvalidStatusError("cannot associate server in status %s", server.Status)
|
||||
}
|
||||
|
||||
err = ValidateAssociateEip(server)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
|
||||
if len(self.NetworkId) > 0 {
|
||||
gns, err := server.GetNetworks("")
|
||||
if err != nil {
|
||||
return input, httperrors.NewGeneralError(errors.Wrap(err, "GetNetworks"))
|
||||
}
|
||||
for _, gn := range gns {
|
||||
if gn.NetworkId == self.NetworkId {
|
||||
return input, httperrors.NewInputParameterError("cannot associate eip with same network")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
eipZone := self.GetZone()
|
||||
if eipZone != nil {
|
||||
serverZone := server.getZone()
|
||||
if serverZone.Id != eipZone.Id {
|
||||
return nil, httperrors.NewInputParameterError("eip and server are not in the same zone")
|
||||
serverRegion := server.getRegion()
|
||||
if serverRegion == nil {
|
||||
return input, httperrors.NewInputParameterError("server region is not found???")
|
||||
}
|
||||
|
||||
eipRegion, err := self.GetRegion()
|
||||
if err != nil {
|
||||
return input, httperrors.NewGeneralError(errors.Wrapf(err, "GetRegion"))
|
||||
}
|
||||
|
||||
if serverRegion.Id != eipRegion.Id {
|
||||
return input, httperrors.NewInputParameterError("eip and server are not in the same region")
|
||||
}
|
||||
eipZone := self.GetZone()
|
||||
if eipZone != nil {
|
||||
serverZone := server.getZone()
|
||||
if serverZone.Id != eipZone.Id {
|
||||
return input, httperrors.NewInputParameterError("eip and server are not in the same zone")
|
||||
}
|
||||
}
|
||||
|
||||
srvHost := server.GetHost()
|
||||
if srvHost == nil {
|
||||
return input, httperrors.NewInputParameterError("server host is not found???")
|
||||
}
|
||||
|
||||
if srvHost.ManagerId != self.ManagerId {
|
||||
return input, httperrors.NewInputParameterError("server and eip are not managed by the same provider")
|
||||
}
|
||||
input.InstanceExternalId = server.ExternalId
|
||||
case api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY:
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
err = self.StartEipAssociateInstanceTask(ctx, userCred, server, "")
|
||||
return nil, err
|
||||
return input, self.StartEipAssociateInstanceTask(ctx, userCred, input, "")
|
||||
}
|
||||
|
||||
func (self *SElasticip) StartEipAssociateInstanceTask(ctx context.Context, userCred mcclient.TokenCredential, server *SGuest, parentTaskId string) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(server.ExternalId), "instance_external_id")
|
||||
params.Add(jsonutils.NewString(server.Id), "instance_id")
|
||||
params.Add(jsonutils.NewString(api.EIP_ASSOCIATE_TYPE_SERVER), "instance_type")
|
||||
|
||||
func (self *SElasticip) StartEipAssociateInstanceTask(ctx context.Context, userCred mcclient.TokenCredential, input api.ElasticipAssociateInput, parentTaskId string) error {
|
||||
params := jsonutils.Marshal(input).(*jsonutils.JSONDict)
|
||||
return self.StartEipAssociateTask(ctx, userCred, params, parentTaskId)
|
||||
}
|
||||
|
||||
func (self *SElasticip) StartEipAssociateTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "EipAssociateTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("create EipAssociateTask task fail %s", err)
|
||||
return err
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
self.SetStatus(userCred, api.EIP_STATUS_ASSOCIATE, "start to associate")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (self *SElasticip) AllowPerformDissociate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
@@ -1138,9 +1123,9 @@ func (self *SElasticip) GetIRegion() (cloudprovider.ICloudRegion, error) {
|
||||
return nil, errors.Wrap(err, "GetDriver")
|
||||
}
|
||||
|
||||
region := self.GetRegion()
|
||||
if region == nil {
|
||||
return nil, fmt.Errorf("fail to find region for eip")
|
||||
region, err := self.GetRegion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetRegion")
|
||||
}
|
||||
|
||||
return provider.GetIRegionById(region.GetExternalId())
|
||||
@@ -1232,6 +1217,7 @@ type NewEipForVMOnHostArgs struct {
|
||||
|
||||
Guest *SGuest
|
||||
Host *SHost
|
||||
Natgateway *SNatGateway
|
||||
PendingUsage quotas.IQuota
|
||||
}
|
||||
|
||||
@@ -1243,12 +1229,21 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
|
||||
autoDellocate = args.AutoDellocate
|
||||
vm = args.Guest
|
||||
host = args.Host
|
||||
nat = args.Natgateway
|
||||
pendingUsage = args.PendingUsage
|
||||
|
||||
region *SCloudregion = nil
|
||||
)
|
||||
var (
|
||||
region = host.GetRegion()
|
||||
regionDriver = region.GetDriver()
|
||||
)
|
||||
|
||||
if host != nil {
|
||||
region = host.GetRegion()
|
||||
} else if nat != nil {
|
||||
region = nat.GetRegion()
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalid host or nat")
|
||||
}
|
||||
|
||||
regionDriver := region.GetDriver()
|
||||
|
||||
if chargeType == "" {
|
||||
chargeType = regionDriver.GetEipDefaultChargeType()
|
||||
@@ -1266,14 +1261,31 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
|
||||
eip.Bandwidth = bw
|
||||
eip.ChargeType = chargeType
|
||||
eip.AutoDellocate = tristate.NewFromBool(autoDellocate)
|
||||
eip.DomainId = vm.DomainId
|
||||
eip.ProjectId = vm.ProjectId
|
||||
if vm != nil {
|
||||
eip.DomainId = vm.DomainId
|
||||
eip.ProjectId = vm.ProjectId
|
||||
} else {
|
||||
eip.DomainId = userCred.GetProjectDomainId()
|
||||
eip.ProjectId = userCred.GetProjectId()
|
||||
}
|
||||
eip.ProjectSrc = string(apis.OWNER_SOURCE_LOCAL)
|
||||
eip.ManagerId = host.ManagerId
|
||||
if host != nil {
|
||||
eip.ManagerId = host.ManagerId
|
||||
} else if nat != nil {
|
||||
vpc, err := nat.GetVpc()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "nat.GetVpc")
|
||||
}
|
||||
eip.ManagerId = vpc.ManagerId
|
||||
}
|
||||
eip.CloudregionId = region.Id
|
||||
eip.Name = fmt.Sprintf("eip-for-%s", vm.GetName())
|
||||
if vm != nil {
|
||||
eip.Name = fmt.Sprintf("eip-for-%s", vm.GetName())
|
||||
} else if nat != nil {
|
||||
eip.Name = fmt.Sprintf("eip-for-%s", nat.GetName())
|
||||
}
|
||||
|
||||
if host.ManagerId == "" {
|
||||
if host != nil && host.ManagerId == "" { // kvm
|
||||
|
||||
hostq := HostManager.Query().SubQuery()
|
||||
wireq := WireManager.Query().SubQuery()
|
||||
@@ -1316,17 +1328,30 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
|
||||
|
||||
err = manager.TableSpec().Insert(ctx, eip)
|
||||
if err != nil {
|
||||
log.Errorf("create EIP record fail %s", err)
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "TableSpec().Insert")
|
||||
}
|
||||
db.OpsLog.LogEvent(eip, db.ACT_CREATE, eip.GetShortDesc(ctx), userCred)
|
||||
|
||||
var ownerId mcclient.IIdentityProvider = nil
|
||||
if vm != nil {
|
||||
ownerId = vm.GetOwnerId()
|
||||
} else if nat != nil {
|
||||
ownerId = nat.GetOwnerId()
|
||||
}
|
||||
|
||||
var provider *SCloudprovider = nil
|
||||
if host != nil {
|
||||
provider = host.GetCloudprovider()
|
||||
} else if nat != nil {
|
||||
provider = nat.GetCloudprovider()
|
||||
}
|
||||
|
||||
eipPendingUsage := &SRegionQuota{Eip: 1}
|
||||
keys := fetchRegionalQuotaKeys(
|
||||
rbacutils.ScopeProject,
|
||||
vm.GetOwnerId(),
|
||||
ownerId,
|
||||
region,
|
||||
host.GetCloudprovider(),
|
||||
provider,
|
||||
)
|
||||
eipPendingUsage.SetKeys(keys)
|
||||
quotas.CancelPendingUsage(ctx, userCred, pendingUsage, eipPendingUsage, true)
|
||||
@@ -1334,19 +1359,15 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
|
||||
return eip, nil
|
||||
}
|
||||
|
||||
func (eip *SElasticip) AllocateAndAssociateVM(ctx context.Context, userCred mcclient.TokenCredential, vm *SGuest, parentTaskId string) error {
|
||||
err := ValidateAssociateEip(vm)
|
||||
func (eip *SElasticip) AllocateAndAssociateInstance(ctx context.Context, userCred mcclient.TokenCredential, ins IEipAssociateInstance, input api.ElasticipAssociateInput, parentTaskId string) error {
|
||||
err := ValidateAssociateEip(ins)
|
||||
if err != nil {
|
||||
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(api.EIP_ASSOCIATE_TYPE_SERVER), "instance_type")
|
||||
|
||||
vm.SetStatus(userCred, api.VM_ASSOCIATE_EIP, "allocate and associate EIP")
|
||||
params := jsonutils.Marshal(input).(*jsonutils.JSONDict)
|
||||
|
||||
db.StatusBaseSetStatus(ins, userCred, api.INSTANCE_ASSOCIATE_EIP, "allocate and associate EIP")
|
||||
return eip.startEipAllocateTask(ctx, userCred, params, parentTaskId)
|
||||
}
|
||||
|
||||
@@ -1498,7 +1519,7 @@ func (self *SElasticip) DoPendingDelete(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
|
||||
func (self *SElasticip) getCloudProviderInfo() SCloudProviderInfo {
|
||||
region := self.GetRegion()
|
||||
region, _ := self.GetRegion()
|
||||
provider := self.GetCloudprovider()
|
||||
return MakeCloudProviderInfo(region, nil, provider)
|
||||
}
|
||||
|
||||
@@ -2972,7 +2972,10 @@ func (self *SGuest) PerformAssociateEip(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
|
||||
eip = eipObj.(*SElasticip)
|
||||
eipRegion := eip.GetRegion()
|
||||
eipRegion, err := eip.GetRegion()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "eip.GetRegion"))
|
||||
}
|
||||
instRegion := self.getRegion()
|
||||
|
||||
if eip.Mode == api.EIP_MODE_INSTANCE_PUBLICIP {
|
||||
@@ -3017,7 +3020,7 @@ func (self *SGuest) PerformAssociateEip(ctx context.Context, userCred mcclient.T
|
||||
return nil, httperrors.NewInputParameterError("cannot associate eip and instance in different provider")
|
||||
}
|
||||
|
||||
self.SetStatus(userCred, api.VM_ASSOCIATE_EIP, "associate eip")
|
||||
self.SetStatus(userCred, api.INSTANCE_ASSOCIATE_EIP, "associate eip")
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(self.ExternalId), "instance_external_id")
|
||||
@@ -3048,7 +3051,7 @@ func (self *SGuest) PerformDissociateEip(ctx context.Context, userCred mcclient.
|
||||
return nil, errors.Wrap(err, "eip is not accessible")
|
||||
}
|
||||
|
||||
self.SetStatus(userCred, api.VM_DISSOCIATE_EIP, "associate eip")
|
||||
self.SetStatus(userCred, api.INSTANCE_DISSOCIATE_EIP, "associate eip")
|
||||
|
||||
autoDelete := (input.AudoDelete != nil && *input.AudoDelete)
|
||||
|
||||
@@ -3126,7 +3129,13 @@ func (self *SGuest) PerformCreateEip(ctx context.Context, userCred mcclient.Toke
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
err = eip.AllocateAndAssociateVM(ctx, userCred, self, "")
|
||||
opts := api.ElasticipAssociateInput{
|
||||
InstanceId: self.Id,
|
||||
InstanceExternalId: self.ExternalId,
|
||||
InstanceType: api.EIP_ASSOCIATE_TYPE_SERVER,
|
||||
}
|
||||
|
||||
err = eip.AllocateAndAssociateInstance(ctx, userCred, self, opts, "")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
@@ -3694,7 +3703,7 @@ func (self *SGuest) AllowPerformPostpaidExpire(ctx context.Context, userCred mcc
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "postpaid-expire")
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformPostpaidExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
func (self *SGuest) PerformPostpaidExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PostpaidExpireInput) (jsonutils.JSONObject, error) {
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return nil, httperrors.NewBadRequestError("guest billing type is %s", self.BillingType)
|
||||
}
|
||||
@@ -3703,7 +3712,7 @@ func (self *SGuest) PerformPostpaidExpire(ctx context.Context, userCred mcclient
|
||||
return nil, httperrors.NewBadRequestError("guest %s unsupport postpaid expire", self.Hypervisor)
|
||||
}
|
||||
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, data)
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -178,7 +178,6 @@ type IGuestDriver interface {
|
||||
IsSupportEip() bool
|
||||
IsSupportPublicIp() bool
|
||||
ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error
|
||||
RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, eip *SElasticip, task taskman.ITask) error
|
||||
|
||||
NeedStopForChangeSpec(guest *SGuest, cpuChanged, memChanged bool) bool
|
||||
|
||||
|
||||
@@ -354,7 +354,10 @@ func (manager *SGuestManager) ListItemFilter(
|
||||
} else {
|
||||
hostQ = hostQ.IsNullOrEmpty("manager_id")
|
||||
}
|
||||
region := eip.GetRegion()
|
||||
region, err := eip.GetRegion()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "eip.GetRegion"))
|
||||
}
|
||||
regionTable := CloudregionManager.Query().SubQuery()
|
||||
sq := hostQ.Join(regionTable, sqlchemy.Equals(zoneTable.Field("cloudregion_id"), regionTable.Field("id"))).
|
||||
Filter(sqlchemy.Equals(regionTable.Field("id"), region.GetId())).SubQuery()
|
||||
@@ -1638,7 +1641,10 @@ func (manager *SGuestManager) validateEip(userCred mcclient.TokenCredential, inp
|
||||
}
|
||||
input.PreferManager = eipCloudprovider.Id
|
||||
|
||||
eipRegion := eip.GetRegion()
|
||||
eipRegion, err := eip.GetRegion()
|
||||
if err != nil {
|
||||
return httperrors.NewGeneralError(errors.Wrapf(err, "eip.GetRegion"))
|
||||
}
|
||||
// preferRegionId, _ := data.GetString("prefer_region_id")
|
||||
if len(preferRegionId) > 0 && preferRegionId != eipRegion.Id {
|
||||
return httperrors.NewConflictError("cannot assoicate with eip %s: different region", eipStr)
|
||||
@@ -4879,7 +4885,7 @@ func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCreden
|
||||
log.Errorf("getEipByExtEip error %v", err)
|
||||
result.AddError(err)
|
||||
} else {
|
||||
err = neip.AssociateVM(ctx, userCred, self)
|
||||
err = neip.AssociateInstance(ctx, userCred, api.EIP_ASSOCIATE_TYPE_SERVER, self)
|
||||
if err != nil {
|
||||
log.Errorf("AssociateVM error %v", err)
|
||||
result.AddError(err)
|
||||
@@ -4909,7 +4915,7 @@ func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCreden
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
err = neip.AssociateVM(ctx, userCred, self)
|
||||
err = neip.AssociateInstance(ctx, userCred, api.EIP_ASSOCIATE_TYPE_SERVER, self)
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
|
||||
331
pkg/compute/models/nat_skus.go
Normal file
331
pkg/compute/models/nat_skus.go
Normal file
@@ -0,0 +1,331 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SNatSkuManager struct {
|
||||
db.SEnabledStatusStandaloneResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
SCloudregionResourceBaseManager
|
||||
}
|
||||
|
||||
var NatSkuManager *SNatSkuManager
|
||||
|
||||
func init() {
|
||||
NatSkuManager = &SNatSkuManager{
|
||||
SEnabledStatusStandaloneResourceBaseManager: db.NewEnabledStatusStandaloneResourceBaseManager(
|
||||
SNatSku{},
|
||||
"nat_skus_tbl",
|
||||
"nat_sku",
|
||||
"nat_skus",
|
||||
),
|
||||
}
|
||||
NatSkuManager.NameRequireAscii = false
|
||||
NatSkuManager.SetVirtualObject(NatSkuManager)
|
||||
}
|
||||
|
||||
type SNatSku struct {
|
||||
db.SEnabledStatusStandaloneResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
SCloudregionResourceBase
|
||||
|
||||
PrepaidStatus string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"admin" default:"available"` // 预付费资源状态 available|soldout
|
||||
PostpaidStatus string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"admin" default:"available"` // 按需付费资源状态 available|soldout
|
||||
|
||||
Cps int `nullable:"false" list:"user" create:"optional" update:"admin"`
|
||||
Conns int `nullable:"false" list:"user" create:"optional" update:"admin"`
|
||||
Pps int `nullable:"false" list:"user" create:"optional" update:"admin"`
|
||||
Throughput int `nullable:"false" list:"user" create:"optional" update:"admin"`
|
||||
|
||||
Provider string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"admin_required" update:"admin"`
|
||||
ZoneIds string `charset:"utf8" nullable:"true" list:"user" update:"admin" create:"admin_optional" json:"zone_ids"`
|
||||
}
|
||||
|
||||
func (manager *SNatSkuManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.NatSkuListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusStandaloneResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SEnabledStatusStandaloneResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SExternalizedResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.ListItemFilter(ctx, q, userCred, query.RegionalFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SCloudregionResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
if len(query.PostpaidStatus) > 0 {
|
||||
q = q.Equals("postpaid_status", query.PostpaidStatus)
|
||||
}
|
||||
if len(query.PrepaidStatus) > 0 {
|
||||
q = q.Equals("prepaid_status", query.PrepaidStatus)
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SNatSkuManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.NatSkuDetails {
|
||||
rows := make([]api.NatSkuDetails, len(objs))
|
||||
|
||||
stdRows := manager.SEnabledStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
regRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
|
||||
for i := range rows {
|
||||
rows[i] = api.NatSkuDetails{
|
||||
EnabledStatusStandaloneResourceDetails: stdRows[i],
|
||||
CloudregionResourceInfo: regRows[i],
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SNatSkuManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SNatSkuManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SNatSkuManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.NatSkuListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusStandaloneResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.RegionalFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SCloudregion) GetNatSkus() ([]SNatSku, error) {
|
||||
skus := []SNatSku{}
|
||||
q := NatSkuManager.Query().Equals("cloudregion_id", self.Id)
|
||||
err := db.FetchModelObjects(NatSkuManager, q, &skus)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return skus, nil
|
||||
}
|
||||
|
||||
func (self SNatSku) GetGlobalId() string {
|
||||
return self.ExternalId
|
||||
}
|
||||
|
||||
func (self *SCloudregion) SyncNatSkus(ctx context.Context, userCred mcclient.TokenCredential, meta *SSkuResourcesMeta) compare.SyncResult {
|
||||
lockman.LockRawObject(ctx, self.Id, "nat-sku")
|
||||
defer lockman.ReleaseRawObject(ctx, self.Id, "nat-sku")
|
||||
|
||||
syncResult := compare.SyncResult{}
|
||||
|
||||
iskus, err := meta.GetNatSkusByRegionExternalId(self.ExternalId)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
|
||||
dbSkus, err := self.GetNatSkus()
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
|
||||
removed := make([]SNatSku, 0)
|
||||
commondb := make([]SNatSku, 0)
|
||||
commonext := make([]SNatSku, 0)
|
||||
added := make([]SNatSku, 0)
|
||||
|
||||
err = compare.CompareSets(dbSkus, iskus, &removed, &commondb, &commonext, &added)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i += 1 {
|
||||
err = removed[i].Delete(ctx, userCred)
|
||||
if err != nil {
|
||||
syncResult.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
syncResult.Delete()
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].syncWithCloudSku(ctx, userCred, commonext[i])
|
||||
if err != nil {
|
||||
syncResult.UpdateError(err)
|
||||
continue
|
||||
}
|
||||
syncResult.Update()
|
||||
}
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
err = self.newFromCloudNatSku(ctx, userCred, added[i])
|
||||
if err != nil {
|
||||
syncResult.AddError(err)
|
||||
} else {
|
||||
syncResult.Add()
|
||||
}
|
||||
}
|
||||
return syncResult
|
||||
}
|
||||
|
||||
func (self *SNatSku) syncWithCloudSku(ctx context.Context, userCred mcclient.TokenCredential, sku SNatSku) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
jsonutils.Update(self, sku)
|
||||
self.Status = api.NAT_SKU_AVAILABLE
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SCloudregion) newFromCloudNatSku(ctx context.Context, userCred mcclient.TokenCredential, isku SNatSku) error {
|
||||
sku := &isku
|
||||
sku.SetModelManager(NatSkuManager, sku)
|
||||
sku.Id = "" //避免使用yunion meta的id,导致出现duplicate entry问题
|
||||
sku.Status = api.NAT_SKU_AVAILABLE
|
||||
sku.CloudregionId = self.Id
|
||||
return NatSkuManager.TableSpec().Insert(ctx, sku)
|
||||
}
|
||||
|
||||
func SyncNatSkus(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
err := SyncRegionNatSkus(ctx, userCred, "", isStart)
|
||||
if err != nil {
|
||||
log.Errorf("SyncRegionNatSkus error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func SyncRegionNatSkus(ctx context.Context, userCred mcclient.TokenCredential, regionId string, isStart bool) error {
|
||||
if isStart {
|
||||
q := NatSkuManager.Query()
|
||||
if len(regionId) > 0 {
|
||||
q = q.Equals("cloudregion_id", regionId)
|
||||
}
|
||||
cnt, err := q.Limit(1).CountWithError()
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return errors.Wrapf(err, "SyncRegionNatSkus.QueryNatSku")
|
||||
}
|
||||
if cnt > 0 {
|
||||
log.Debugf("SyncRegionNatSkus synced skus, skip...")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
q := CloudregionManager.Query()
|
||||
q = q.In("provider", CloudproviderManager.GetPublicProviderProvidersQuery())
|
||||
if len(regionId) > 0 {
|
||||
q = q.Equals("id", regionId)
|
||||
}
|
||||
regions := []SCloudregion{}
|
||||
err := db.FetchModelObjects(CloudregionManager, q, ®ions)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
|
||||
meta, err := FetchSkuResourcesMeta()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "FetchSkuResourcesMeta")
|
||||
}
|
||||
|
||||
for i := range regions {
|
||||
if !regions[i].GetDriver().IsSupportedNatGateway() {
|
||||
log.Infof("region %s(%s) not support nat, skip sync", regions[i].Name, regions[i].Id)
|
||||
continue
|
||||
}
|
||||
result := regions[i].SyncNatSkus(ctx, userCred, meta)
|
||||
msg := result.Result()
|
||||
notes := fmt.Sprintf("SyncNatSkus for region %s result: %s", regions[i].Name, msg)
|
||||
log.Infof(notes)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SNatSkuManager) AllowSyncSkus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, manager, "sync-skus")
|
||||
}
|
||||
|
||||
func (manager *SNatSkuManager) PerformSyncSkus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SkuSyncInput) (jsonutils.JSONObject, error) {
|
||||
return PerformActionSyncSkus(ctx, userCred, manager.Keyword(), input)
|
||||
}
|
||||
|
||||
func (manager *SNatSkuManager) AllowGetPropertySyncTasks(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowGetSpec(userCred, manager, "sync-tasks")
|
||||
}
|
||||
|
||||
func (manager *SNatSkuManager) GetPropertySyncTasks(ctx context.Context, userCred mcclient.TokenCredential, query api.SkuTaskQueryInput) (jsonutils.JSONObject, error) {
|
||||
return GetPropertySkusSyncTasks(ctx, userCred, query)
|
||||
}
|
||||
@@ -60,12 +60,12 @@ func (self *SNatgatewayResourceBase) GetNatgateway() (*SNatGateway, error) {
|
||||
return obj.(*SNatGateway), nil
|
||||
}
|
||||
|
||||
func (self *SNatgatewayResourceBase) GetVpc() *SVpc {
|
||||
nat, _ := self.GetNatgateway()
|
||||
if nat != nil {
|
||||
return nat.GetVpc()
|
||||
func (self *SNatgatewayResourceBase) GetVpc() (*SVpc, error) {
|
||||
nat, err := self.GetNatgateway()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetNatgateway")
|
||||
}
|
||||
return nil
|
||||
return nat.GetVpc()
|
||||
}
|
||||
|
||||
func (self *SNatgatewayResourceBase) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) api.NatGatewayResourceInfo {
|
||||
|
||||
@@ -25,15 +25,22 @@ import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/reflectutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
@@ -41,7 +48,8 @@ type SNatGatewayManager struct {
|
||||
db.SStatusInfrasResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
SVpcResourceBaseManager
|
||||
// SManagedResourceBaseManager
|
||||
|
||||
SDeletePreventableResourceBaseManager
|
||||
}
|
||||
|
||||
var NatGatewayManager *SNatGatewayManager
|
||||
@@ -61,10 +69,11 @@ func init() {
|
||||
type SNatGateway struct {
|
||||
db.SStatusInfrasResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
// SManagedResourceBase
|
||||
SBillingResourceBase
|
||||
SVpcResourceBase
|
||||
|
||||
SDeletePreventableResourceBase
|
||||
|
||||
NatSpec string `list:"user" create:"optional"` // NAT规格
|
||||
}
|
||||
|
||||
@@ -85,6 +94,10 @@ func (man *SNatGatewayManager) ListItemFilter(
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusInfrasResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = man.SDeletePreventableResourceBaseManager.ListItemFilter(ctx, q, userCred, query.DeletePreventableResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SDeletePreventableResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = man.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
|
||||
@@ -128,8 +141,91 @@ func (man *SNatGatewayManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (man *SNatGatewayManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return nil, httperrors.NewNotImplementedError("Not Implemented")
|
||||
func (man *SNatGatewayManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.NatgatewayCreateInput) (api.NatgatewayCreateInput, error) {
|
||||
if len(input.NetworkId) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("network_id")
|
||||
}
|
||||
_network, err := validators.ValidateModel(userCred, NetworkManager, &input.NetworkId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
network := _network.(*SNetwork)
|
||||
vpc := network.GetVpc()
|
||||
if vpc == nil {
|
||||
return input, httperrors.NewGeneralError(errors.Errorf("failed to get network %s %s vpc", network.Name, network.Id))
|
||||
}
|
||||
input.VpcId = vpc.Id
|
||||
region, err := vpc.GetRegion()
|
||||
if err != nil {
|
||||
return input, httperrors.NewGeneralError(errors.Wrapf(err, "vpc.GetRegion"))
|
||||
}
|
||||
if len(input.Duration) > 0 {
|
||||
billingCycle, err := billing.ParseBillingCycle(input.Duration)
|
||||
if err != nil {
|
||||
return input, httperrors.NewInputParameterError("invalid duration %s", input.Duration)
|
||||
}
|
||||
|
||||
if !utils.IsInStringArray(input.BillingType, []string{billing_api.BILLING_TYPE_PREPAID, billing_api.BILLING_TYPE_POSTPAID}) {
|
||||
input.BillingType = billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
|
||||
if input.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
if !region.GetDriver().IsSupportedBillingCycle(billingCycle, man.KeywordPlural()) {
|
||||
return input, httperrors.NewInputParameterError("unsupported duration %s", input.Duration)
|
||||
}
|
||||
}
|
||||
tm := time.Time{}
|
||||
input.BillingCycle = billingCycle.String()
|
||||
input.ExpiredAt = billingCycle.EndAt(tm)
|
||||
}
|
||||
if len(input.Eip) > 0 || input.EipBw > 0 {
|
||||
if len(input.Eip) > 0 {
|
||||
_eip, err := validators.ValidateModel(userCred, ElasticipManager, &input.Eip)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
eip := _eip.(*SElasticip)
|
||||
if eip.Status != api.EIP_STATUS_READY {
|
||||
return input, httperrors.NewInvalidStatusError("eip %s status invalid %s", input.Eip, eip.Status)
|
||||
}
|
||||
|
||||
if eip.IsAssociated() {
|
||||
return input, httperrors.NewResourceBusyError("eip %s has been associated", input.Eip)
|
||||
}
|
||||
|
||||
if eip.CloudregionId != vpc.CloudregionId {
|
||||
return input, httperrors.NewDuplicateResourceError("elastic ip %s and vpc %s not in same region", eip.Name, vpc.Name)
|
||||
}
|
||||
|
||||
provider := eip.GetCloudprovider()
|
||||
if provider != nil && provider.Id != vpc.ManagerId {
|
||||
return input, httperrors.NewConflictError("cannot assoicate with eip %s: different cloudprovider", eip.Id)
|
||||
}
|
||||
} else {
|
||||
// create new
|
||||
}
|
||||
}
|
||||
driver := region.GetDriver()
|
||||
return driver.ValidateCreateNatGateway(ctx, userCred, input)
|
||||
}
|
||||
|
||||
func (self *SNatGateway) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
|
||||
err := self.StartNatGatewayCreateTask(ctx, userCred, data.(*jsonutils.JSONDict))
|
||||
if err != nil {
|
||||
self.SetStatus(userCred, api.NAT_STATUS_CREATE_FAILED, err.Error())
|
||||
return
|
||||
}
|
||||
self.SetStatus(userCred, api.NAT_STATUS_ALLOCATE, "start allocate")
|
||||
}
|
||||
|
||||
func (self *SNatGateway) StartNatGatewayCreateTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "NatGatewayCreateTask", self, userCred, params, "", "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (self *SNatGateway) AllowPerformSnatResources(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
@@ -137,6 +233,7 @@ func (self *SNatGateway) AllowPerformSnatResources(ctx context.Context, userCred
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SNatGateway) PerformSnatResources(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
|
||||
@@ -348,6 +445,8 @@ func (self *SNatGateway) syncRemoveCloudNatGateway(ctx context.Context, userCred
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
|
||||
self.DeletePreventionOff(self, userCred)
|
||||
|
||||
err := self.ValidateDeleteCondition(ctx)
|
||||
if err != nil { // cannot delete
|
||||
return self.SetStatus(userCred, api.NAT_STATUS_UNKNOWN, "sync to delete")
|
||||
@@ -355,6 +454,13 @@ func (self *SNatGateway) syncRemoveCloudNatGateway(ctx context.Context, userCred
|
||||
return self.purge(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SNatGateway) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if self.DisableDelete.IsTrue() {
|
||||
return httperrors.NewInvalidStatusError("Nat is locked, cannot delete")
|
||||
}
|
||||
return self.SStatusInfrasResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SNatGateway) SyncWithCloudNatGateway(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extNat cloudprovider.ICloudNatGateway) error {
|
||||
diff, err := db.UpdateWithLock(ctx, self, func() error {
|
||||
self.Status = extNat.GetStatus()
|
||||
@@ -385,11 +491,6 @@ func (manager *SNatGatewayManager) newFromCloudNatGateway(ctx context.Context, u
|
||||
nat := SNatGateway{}
|
||||
nat.SetModelManager(manager, &nat)
|
||||
|
||||
/*region, err := vpc.GetRegion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "vpc.GetRegion")
|
||||
}*/
|
||||
|
||||
newName, err := db.GenerateName(manager, ownerId, extNat.GetName())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "db.GenerateName")
|
||||
@@ -402,8 +503,6 @@ func (manager *SNatGatewayManager) newFromCloudNatGateway(ctx context.Context, u
|
||||
nat.CreatedAt = extNat.GetCreatedAt()
|
||||
}
|
||||
nat.ExternalId = extNat.GetGlobalId()
|
||||
// nat.CloudregionId = region.Id
|
||||
// nat.ManagerId = provider.Id
|
||||
nat.IsEmulated = extNat.IsEmulated()
|
||||
|
||||
factory, _ := provider.GetProviderFactory()
|
||||
@@ -428,11 +527,53 @@ func (manager *SNatGatewayManager) newFromCloudNatGateway(ctx context.Context, u
|
||||
return &nat, nil
|
||||
}
|
||||
|
||||
// 删除NAT
|
||||
func (self *SNatGateway) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query api.ServerDeleteInput, input api.NatgatewayDeleteInput) error {
|
||||
if !input.Force {
|
||||
eips, err := self.GetEips()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "self.GetEips")
|
||||
}
|
||||
if len(eips) > 0 {
|
||||
return httperrors.NewNotEmptyError("natgateway has bind %d eips", len(eips))
|
||||
}
|
||||
dnat, err := self.GetDTable()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetDTable()")
|
||||
}
|
||||
if len(dnat) > 0 {
|
||||
return httperrors.NewNotEmptyError("natgateway has %d stable", len(dnat))
|
||||
}
|
||||
snat, err := self.GetSTable()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetSTable")
|
||||
}
|
||||
if len(snat) > 0 {
|
||||
return httperrors.NewNotEmptyError("natgateway has %d dtable", len(snat))
|
||||
}
|
||||
}
|
||||
err := self.StartNatGatewayDeleteTask(ctx, userCred, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.SetStatus(userCred, api.NAT_STATUS_DELETING, jsonutils.Marshal(input).String())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SNatGateway) StartNatGatewayDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "NatGatewayDeleteTask", self, userCred, params, "", "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (self *SNatGateway) GetEips() ([]SElasticip, error) {
|
||||
q := ElasticipManager.Query().Equals("associate_id", self.Id)
|
||||
eips := []SElasticip{}
|
||||
if err := db.FetchModelObjects(ElasticipManager, q, &eips); err != nil {
|
||||
return nil, err
|
||||
err := db.FetchModelObjects(ElasticipManager, q, &eips)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return eips, nil
|
||||
}
|
||||
@@ -458,10 +599,10 @@ func (self *SNatGateway) SyncNatGatewayEips(ctx context.Context, userCred mcclie
|
||||
for i := 0; i < len(removed); i += 1 {
|
||||
err := removed[i].Dissociate(ctx, userCred)
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
result.Delete()
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
@@ -480,9 +621,9 @@ func (self *SNatGateway) SyncNatGatewayEips(ctx context.Context, userCred mcclie
|
||||
err = neip.AssociateNatGateway(ctx, userCred, self)
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
result.Add()
|
||||
continue
|
||||
}
|
||||
result.Add()
|
||||
}
|
||||
|
||||
return result
|
||||
@@ -503,15 +644,26 @@ func (self *SNatGateway) PerformSyncstatus(ctx context.Context, userCred mcclien
|
||||
return nil, httperrors.NewBadRequestError("Nat gateway has %d task active, can't sync status", count)
|
||||
}
|
||||
|
||||
return nil, StartResourceSyncStatusTask(ctx, userCred, self, "NatGatewaySyncstatusTask", "")
|
||||
return nil, self.StartSyncstatus(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SNatGateway) StartSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
return StartResourceSyncStatusTask(ctx, userCred, self, "NatGatewaySyncstatusTask", parentTaskId)
|
||||
}
|
||||
|
||||
func (self *SNatGateway) GetVpc() (*SVpc, error) {
|
||||
vpc, err := VpcManager.FetchById(self.VpcId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Fetch vpc by ID %s failed", self.VpcId)
|
||||
}
|
||||
return vpc.(*SVpc), nil
|
||||
}
|
||||
|
||||
func (self *SNatGateway) GetINatGateway() (cloudprovider.ICloudNatGateway, error) {
|
||||
model, err := VpcManager.FetchById(self.VpcId)
|
||||
vpc, err := self.GetVpc()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Fetch vpc by ID failed")
|
||||
return nil, errors.Wrap(err, "GetVpc")
|
||||
}
|
||||
vpc := model.(*SVpc)
|
||||
cloudVpc, err := vpc.GetIVpc()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Fetch IVpc failed")
|
||||
@@ -525,7 +677,11 @@ func (self *SNatGateway) GetINatGateway() (cloudprovider.ICloudNatGateway, error
|
||||
return cloudNatGateways[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Error("CloudNatGateway Not Found")
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, self.ExternalId)
|
||||
}
|
||||
|
||||
func (self *SNatGateway) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SNatGateway) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
@@ -549,7 +705,7 @@ func (self *SNatGateway) RealDelete(ctx context.Context, userCred mcclient.Token
|
||||
return errors.Wrapf(err, "delete snat %s failed", snats[i].GetId())
|
||||
}
|
||||
}
|
||||
return self.Delete(ctx, userCred)
|
||||
return self.SInfrasResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (nm *SNatGatewayManager) NatNameToReal(name string, natgatewayId string) string {
|
||||
@@ -588,7 +744,6 @@ type SNatEntry struct {
|
||||
db.SExternalizedResourceBase
|
||||
|
||||
SNatgatewayResourceBase `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
// NatgatewayId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
}
|
||||
|
||||
func (manager *SNatEntryManager) GetContextManagers() [][]db.IModelManager {
|
||||
@@ -694,6 +849,144 @@ func (manager *SNatEntryManager) FetchCustomizeColumns(
|
||||
return rows
|
||||
}
|
||||
|
||||
func (self *SNatGateway) AllowPerformPostpaidExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "postpaid-expire")
|
||||
}
|
||||
|
||||
func (self *SNatGateway) PerformPostpaidExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PostpaidExpireInput) (jsonutils.JSONObject, error) {
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return nil, httperrors.NewBadRequestError("nat gateway billing type is %s", self.BillingType)
|
||||
}
|
||||
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (self *SNatGateway) SaveRenewInfo(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
|
||||
) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
if billingType == "" {
|
||||
billingType = billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
if self.BillingType == "" {
|
||||
self.BillingType = billingType
|
||||
}
|
||||
if expireAt != nil && !expireAt.IsZero() {
|
||||
self.ExpiredAt = *expireAt
|
||||
} else {
|
||||
self.BillingCycle = bc.String()
|
||||
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.Update")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SNatGateway) AllowPerformRenew(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "renew")
|
||||
}
|
||||
|
||||
func (self *SNatGateway) PerformRenew(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.RenewInput) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(self.Status, []string{api.NAT_STAUTS_AVAILABLE}) {
|
||||
return nil, httperrors.NewInvalidStatusError("Cannot do renew nat gateway in status %s required status %s", self.Status, api.NAT_SKU_AVAILABLE)
|
||||
}
|
||||
|
||||
if len(input.Duration) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("duration")
|
||||
}
|
||||
|
||||
bc, err := billing.ParseBillingCycle(input.Duration)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid duration %s: %s", input.Duration, err)
|
||||
}
|
||||
|
||||
if !self.GetRegion().GetDriver().IsSupportedBillingCycle(bc, NatGatewayManager.KeywordPlural()) {
|
||||
return nil, httperrors.NewInputParameterError("unsupported duration %s", input.Duration)
|
||||
}
|
||||
|
||||
return nil, self.StartRenewTask(ctx, userCred, input.Duration, "")
|
||||
}
|
||||
|
||||
func (self *SNatGateway) StartRenewTask(ctx context.Context, userCred mcclient.TokenCredential, duration string, parentTaskId string) error {
|
||||
data := jsonutils.NewDict()
|
||||
data.Set("duration", jsonutils.NewString(duration))
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "NatGatewayRenewTask", self, userCred, data, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
self.SetStatus(userCred, api.NAT_STATUS_RENEWING, "")
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (self *SNatGateway) AllowPerformSetAutoRenew(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "set-auto-renew")
|
||||
}
|
||||
|
||||
func (self *SNatGateway) SetAutoRenew(autoRenew bool) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.AutoRenew = autoRenew
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// 设置自动续费
|
||||
// 要求NAT状态为available
|
||||
// 要求NAT计费类型为包年包月(预付费)
|
||||
func (self *SNatGateway) PerformSetAutoRenew(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.AutoRenewInput) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(self.Status, []string{api.NAT_STAUTS_AVAILABLE}) {
|
||||
return nil, httperrors.NewUnsupportOperationError("The nat gateway status need be %s, current is %s", api.NAT_STAUTS_AVAILABLE, self.Status)
|
||||
}
|
||||
|
||||
if self.BillingType != billing_api.BILLING_TYPE_PREPAID {
|
||||
return nil, httperrors.NewUnsupportOperationError("Only %s nat gateway support this operation", billing_api.BILLING_TYPE_PREPAID)
|
||||
}
|
||||
|
||||
if self.AutoRenew == input.AutoRenew {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
region := self.GetRegion()
|
||||
if region == nil {
|
||||
return nil, httperrors.NewGeneralError(fmt.Errorf("filed to get nat %s region", self.Name))
|
||||
}
|
||||
|
||||
driver := region.GetDriver()
|
||||
if !driver.IsSupportedNatAutoRenew() {
|
||||
err := self.SetAutoRenew(input.AutoRenew)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
logclient.AddSimpleActionLog(self, logclient.ACT_SET_AUTO_RENEW, input, userCred, true)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, self.StartSetAutoRenewTask(ctx, userCred, input.AutoRenew, "")
|
||||
}
|
||||
|
||||
func (self *SNatGateway) StartSetAutoRenewTask(ctx context.Context, userCred mcclient.TokenCredential, autoRenew bool, parentTaskId string) error {
|
||||
data := jsonutils.NewDict()
|
||||
data.Set("auto_renew", jsonutils.NewBool(autoRenew))
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "NatGatewaySetAutoRenewTask", self, userCred, data, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
self.SetStatus(userCred, api.NAT_STATUS_SET_AUTO_RENEW, "")
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (self *SNatEntry) GetINatGateway() (cloudprovider.ICloudNatGateway, error) {
|
||||
model, err := NatGatewayManager.FetchById(self.NatgatewayId)
|
||||
if err != nil {
|
||||
@@ -731,3 +1024,40 @@ func (self *SNatEntry) ValidateUpdateData(ctx context.Context, userCred mcclient
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (manager *SNatGatewayManager) getExpiredPostpaids() ([]SNatGateway, error) {
|
||||
q := ListExpiredPostpaidResources(manager.Query(), options.Options.ExpiredPrepaidMaxCleanBatchSize)
|
||||
|
||||
nats := make([]SNatGateway, 0)
|
||||
err := db.FetchModelObjects(manager, q, &nats)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return nats, nil
|
||||
}
|
||||
|
||||
func (self *SNatGateway) doExternalSync(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
iNat, err := self.GetINatGateway()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetINatGateway")
|
||||
}
|
||||
return self.SyncWithCloudNatGateway(ctx, userCred, self.GetCloudprovider(), iNat)
|
||||
}
|
||||
|
||||
func (manager *SNatGatewayManager) DeleteExpiredPostpaids(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
nats, err := manager.getExpiredPostpaids()
|
||||
if err != nil {
|
||||
log.Errorf("Nats getExpiredPostpaids error: %v", err)
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(nats); i += 1 {
|
||||
if len(nats[i].ExternalId) > 0 {
|
||||
err := nats[i].doExternalSync(ctx, userCred)
|
||||
if err == nil && nats[i].IsValidPostPaid() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
nats[i].DeletePreventionOff(&nats[i], userCred)
|
||||
nats[i].StartNatGatewayDeleteTask(ctx, userCred, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,9 +177,9 @@ func (man *SNatSEntryManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
}
|
||||
natgateway := model.(*SNatGateway)
|
||||
// get vpc
|
||||
vpc := natgateway.GetVpc()
|
||||
if vpc == nil {
|
||||
return nil, errors.Wrap(httperrors.ErrBadRequest, "invalid natgateway vpc")
|
||||
vpc, err := natgateway.GetVpc()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetVpc")
|
||||
}
|
||||
|
||||
vpcIPV4Range, err := newIPv4RangeFromCIDR(vpc.CidrBlock)
|
||||
|
||||
@@ -1228,12 +1228,14 @@ func (nat *SNatGateway) purge(ctx context.Context, userCred mcclient.TokenCreden
|
||||
return err
|
||||
}
|
||||
|
||||
nat.DeletePreventionOff(nat, userCred)
|
||||
|
||||
err = nat.ValidateDeleteCondition(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nat.Delete(ctx, userCred)
|
||||
return nat.RealDelete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (manager *SNatGatewayManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
|
||||
|
||||
@@ -180,6 +180,16 @@ type IDBInstanceDriver interface {
|
||||
|
||||
RequestRemoteUpdateDBInstance(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, replaceTags bool, task taskman.ITask) error
|
||||
RequestSyncRdsSecurityGroups(ctx context.Context, userCred mcclient.TokenCredential, rds *SDBInstance, task taskman.ITask) error
|
||||
|
||||
INatGatewayDriver
|
||||
|
||||
IElasticIpDriver
|
||||
}
|
||||
|
||||
type INatGatewayDriver interface {
|
||||
IsSupportedNatGateway() bool
|
||||
IsSupportedNatAutoRenew() bool
|
||||
ValidateCreateNatGateway(ctx context.Context, userCred mcclient.TokenCredential, input api.NatgatewayCreateInput) (api.NatgatewayCreateInput, error)
|
||||
}
|
||||
|
||||
type IElasticcacheDriver interface {
|
||||
@@ -236,6 +246,10 @@ type IElasticcacheBackup interface {
|
||||
RequestElasticcacheBackupRestoreInstance(ctx context.Context, userCred mcclient.TokenCredential, ea *SElasticcacheBackup, task taskman.ITask) error
|
||||
}
|
||||
|
||||
type IElasticIpDriver interface {
|
||||
RequestAssociatEip(ctx context.Context, userCred mcclient.TokenCredential, eip *SElasticip, input api.ElasticipAssociateInput, obj db.IStatusStandaloneModel, task taskman.ITask) error
|
||||
}
|
||||
|
||||
var regionDrivers map[string]IRegionDriver
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
)
|
||||
|
||||
func PerformActionSyncSkus(ctx context.Context, userCred mcclient.TokenCredential, resourceKey string, input apis.SkuSyncInput) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(resourceKey, []string{ServerSkuManager.Keyword(), ElasticcacheSkuManager.Keyword(), DBInstanceSkuManager.Keyword()}) {
|
||||
if !utils.IsInStringArray(resourceKey, []string{ServerSkuManager.Keyword(), ElasticcacheSkuManager.Keyword(), DBInstanceSkuManager.Keyword(), NatSkuManager.Keyword()}) {
|
||||
return nil, httperrors.NewUnsupportOperationError("resource %s is not support sync skus", resourceKey)
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ type SSkuResourcesMeta struct {
|
||||
ServerBase string `json:"server_base"`
|
||||
ElasticCacheBase string `json:"elastic_cache_base"`
|
||||
ImageBase string `json:"image_base"`
|
||||
NatBase string `json:"nat_base"`
|
||||
}
|
||||
|
||||
func (self *SSkuResourcesMeta) getZoneIdBySuffix(zoneMaps map[string]string, suffix string) string {
|
||||
@@ -123,6 +124,43 @@ func (self *SSkuResourcesMeta) GetDBInstanceSkusByRegionExternalId(regionExterna
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *SSkuResourcesMeta) GetNatSkusByRegionExternalId(regionExternalId string) ([]SNatSku, error) {
|
||||
regionId, zoneMaps, err := self.GetRegionIdAndZoneMaps(regionExternalId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetRegionIdAndZoneMaps")
|
||||
}
|
||||
result := []SNatSku{}
|
||||
objs, err := self.getObjsByRegion(self.NatBase, regionExternalId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "getSkusByRegion")
|
||||
}
|
||||
for _, obj := range objs {
|
||||
sku := SNatSku{}
|
||||
sku.SetModelManager(NatSkuManager, &sku)
|
||||
err = obj.Unmarshal(&sku)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "obj.Unmarshal")
|
||||
}
|
||||
if len(sku.ZoneIds) > 0 {
|
||||
zoneIds := []string{}
|
||||
for _, zoneExtId := range strings.Split(sku.ZoneIds, ",") {
|
||||
zoneId := self.getZoneIdBySuffix(zoneMaps, zoneExtId) // Huawei rds sku zone1 maybe is cn-north-4f
|
||||
if len(zoneId) == 0 {
|
||||
log.Warningf("invalid nat sku %s(%s) %s zone: %s", sku.Name, sku.Id, sku.CloudregionId, zoneExtId)
|
||||
continue
|
||||
}
|
||||
zoneIds = append(zoneIds, zoneId)
|
||||
}
|
||||
sku.ZoneIds = strings.Join(zoneIds, ",")
|
||||
}
|
||||
sku.Id = ""
|
||||
sku.CloudregionId = regionId
|
||||
|
||||
result = append(result, sku)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *SSkuResourcesMeta) getCloudregion(regionExternalId string) (*SCloudregion, error) {
|
||||
region, err := db.FetchByExternalId(CloudregionManager, regionExternalId)
|
||||
if err != nil {
|
||||
|
||||
@@ -1091,7 +1091,7 @@ func (self *SAliyunRegionDriver) ValidateCreateDBInstanceData(ctx context.Contex
|
||||
|
||||
func (self *SAliyunRegionDriver) IsSupportedBillingCycle(bc billing.SBillingCycle, resource string) bool {
|
||||
switch resource {
|
||||
case models.DBInstanceManager.KeywordPlural(), models.ElasticcacheManager.KeywordPlural():
|
||||
case models.DBInstanceManager.KeywordPlural(), models.ElasticcacheManager.KeywordPlural(), models.NatGatewayManager.KeywordPlural():
|
||||
years := bc.GetYears()
|
||||
months := bc.GetMonths()
|
||||
if (years >= 1 && years <= 3) || (months >= 1 && months <= 9) {
|
||||
@@ -1582,3 +1582,11 @@ func (self *SAliyunRegionDriver) ValidateCreateVpcData(ctx context.Context, user
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SAliyunRegionDriver) ValidateCreateNatGateway(ctx context.Context, userCred mcclient.TokenCredential, input api.NatgatewayCreateInput) (api.NatgatewayCreateInput, error) {
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SAliyunRegionDriver) IsSupportedNatGateway() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1503,3 +1503,59 @@ func (self *SAwsRegionDriver) RequestDeleteVpc(ctx context.Context, userCred mcc
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsRegionDriver) RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, eip *models.SElasticip, input api.ElasticipAssociateInput, obj db.IStatusStandaloneModel, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
iEip, err := eip.GetIEip()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "eip.GetIEip")
|
||||
}
|
||||
|
||||
conf := &cloudprovider.AssociateConfig{
|
||||
InstanceId: input.InstanceExternalId,
|
||||
Bandwidth: eip.Bandwidth,
|
||||
AssociateType: api.EIP_ASSOCIATE_TYPE_SERVER,
|
||||
}
|
||||
|
||||
err = iEip.Associate(conf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "iEip.Associate")
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(iEip, api.EIP_STATUS_READY, 3*time.Second, 60*time.Second)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cloudprovider.WaitStatus")
|
||||
}
|
||||
|
||||
if obj.GetStatus() != api.INSTANCE_ASSOCIATE_EIP {
|
||||
db.StatusBaseSetStatus(obj, userCred, api.INSTANCE_ASSOCIATE_EIP, "associate eip")
|
||||
}
|
||||
|
||||
err = eip.AssociateInstance(ctx, userCred, input.InstanceType, obj)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "eip.AssociateVM")
|
||||
}
|
||||
|
||||
if input.InstanceType == api.EIP_ASSOCIATE_TYPE_SERVER {
|
||||
// 如果aws已经绑定了EIP,则要把多余的公有IP删除
|
||||
if iEip.GetMode() == api.EIP_MODE_STANDALONE_EIP {
|
||||
server := obj.(*models.SGuest)
|
||||
publicIP, err := server.GetPublicIp()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "AwsGuestDriver.GetPublicIp")
|
||||
}
|
||||
|
||||
if publicIP != nil {
|
||||
err = db.DeleteModel(ctx, userCred, publicIP)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "AwsGuestDriver.DeletePublicIp")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eip.SetStatus(userCred, api.EIP_STATUS_READY, "associate")
|
||||
return nil, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"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/compute/models"
|
||||
@@ -432,3 +433,19 @@ func (self *SBaseRegionDriver) RequestElasticcacheSetAutoRenew(ctx context.Conte
|
||||
func (self *SBaseRegionDriver) RequestSyncRdsSecurityGroups(ctx context.Context, userCred mcclient.TokenCredential, rds *models.SDBInstance, task taskman.ITask) error {
|
||||
return errors.Wrapf(cloudprovider.ErrNotImplemented, "RequestSyncRdsSecurityGroups")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) IsSupportedNatGateway() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) ValidateCreateNatGateway(ctx context.Context, userCred mcclient.TokenCredential, input api.NatgatewayCreateInput) (api.NatgatewayCreateInput, error) {
|
||||
return input, httperrors.NewNotImplementedError("ValidateCreateNatGateway")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) IsSupportedNatAutoRenew() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) RequestAssociatEip(ctx context.Context, userCred mcclient.TokenCredential, eip *models.SElasticip, input api.ElasticipAssociateInput, obj db.IStatusStandaloneModel, task taskman.ITask) error {
|
||||
return httperrors.NewNotImplementedError("RequestAssociatEip")
|
||||
}
|
||||
|
||||
@@ -2676,3 +2676,7 @@ func (self *SHuaWeiRegionDriver) ValidateCreateVpcData(ctx context.Context, user
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SHuaWeiRegionDriver) IsSupportedNatGateway() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
@@ -1405,3 +1406,60 @@ func (self *SKVMRegionDriver) IsSupportedElasticcacheSecgroup() bool {
|
||||
func (self *SKVMRegionDriver) GetMaxElasticcacheSecurityGroupCount() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SKVMRegionDriver) RequestAssociatEip(ctx context.Context, userCred mcclient.TokenCredential, eip *models.SElasticip, input api.ElasticipAssociateInput, obj db.IStatusStandaloneModel, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
if input.InstanceType != api.EIP_ASSOCIATE_TYPE_SERVER {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotSupported, "instance type %s", input.InstanceType)
|
||||
}
|
||||
|
||||
guest := obj.(*models.SGuest)
|
||||
|
||||
if guest.GetHypervisor() != api.HYPERVISOR_KVM {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotSupported, "not support associate eip for hypervisor %s", guest.GetHypervisor())
|
||||
}
|
||||
|
||||
lockman.LockObject(ctx, guest)
|
||||
defer lockman.ReleaseObject(ctx, guest)
|
||||
|
||||
var guestnics []models.SGuestnetwork
|
||||
{
|
||||
netq := models.NetworkManager.Query().SubQuery()
|
||||
wirq := models.WireManager.Query().SubQuery()
|
||||
vpcq := models.VpcManager.Query().SubQuery()
|
||||
gneq := models.GuestnetworkManager.Query()
|
||||
q := gneq.Equals("guest_id", guest.Id).
|
||||
IsNullOrEmpty("eip_id")
|
||||
q = q.Join(netq, sqlchemy.Equals(netq.Field("id"), gneq.Field("network_id")))
|
||||
q = q.Join(wirq, sqlchemy.Equals(wirq.Field("id"), netq.Field("wire_id")))
|
||||
q = q.Join(vpcq, sqlchemy.Equals(vpcq.Field("id"), wirq.Field("vpc_id")))
|
||||
q = q.Filter(sqlchemy.NotEquals(vpcq.Field("id"), api.DEFAULT_VPC_ID))
|
||||
if err := db.FetchModelObjects(models.GuestnetworkManager, q, &guestnics); err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
if len(guestnics) == 0 {
|
||||
return nil, errors.Errorf("guest has no nics to associate eip")
|
||||
}
|
||||
}
|
||||
|
||||
guestnic := &guestnics[0]
|
||||
lockman.LockObject(ctx, guestnic)
|
||||
defer lockman.ReleaseObject(ctx, guestnic)
|
||||
if _, err := db.Update(guestnic, func() error {
|
||||
guestnic.EipId = eip.Id
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, errors.Wrapf(err, "set associated eip for guestnic %s (guest:%s, network:%s)",
|
||||
guestnic.Ifname, guestnic.GuestId, guestnic.NetworkId)
|
||||
}
|
||||
|
||||
if err := eip.AssociateInstance(ctx, userCred, api.EIP_ASSOCIATE_TYPE_SERVER, guest); err != nil {
|
||||
return nil, errors.Wrapf(err, "associate eip %s(%s) to vm %s(%s)", eip.Name, eip.Id, guest.Name, guest.Id)
|
||||
}
|
||||
if err := eip.SetStatus(userCred, api.EIP_STATUS_READY, api.EIP_STATUS_ASSOCIATE); err != nil {
|
||||
return nil, errors.Wrapf(err, "set eip status to %s", api.EIP_STATUS_ALLOCATE)
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3157,3 +3157,41 @@ func (self *SManagedVirtualizationRegionDriver) RequestSyncRdsSecurityGroups(ctx
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizationRegionDriver) RequestAssociatEip(ctx context.Context, userCred mcclient.TokenCredential, eip *models.SElasticip, input api.ElasticipAssociateInput, obj db.IStatusStandaloneModel, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
iEip, err := eip.GetIEip()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "eip.GetIEip")
|
||||
}
|
||||
|
||||
conf := &cloudprovider.AssociateConfig{
|
||||
InstanceId: input.InstanceExternalId,
|
||||
Bandwidth: eip.Bandwidth,
|
||||
AssociateType: input.InstanceType,
|
||||
}
|
||||
|
||||
err = iEip.Associate(conf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "extEip.Associate")
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(iEip, api.EIP_STATUS_READY, 3*time.Second, 60*time.Second)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cloudprovider.WaitStatus")
|
||||
}
|
||||
|
||||
if obj.GetStatus() != api.INSTANCE_ASSOCIATE_EIP {
|
||||
db.StatusBaseSetStatus(obj, userCred, api.INSTANCE_ASSOCIATE_EIP, "associate eip")
|
||||
}
|
||||
|
||||
err = eip.AssociateInstance(ctx, userCred, input.InstanceType, obj)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "eip.AssociateVM")
|
||||
}
|
||||
|
||||
eip.SetStatus(userCred, api.EIP_STATUS_READY, api.EIP_STATUS_ASSOCIATE)
|
||||
return nil, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -203,6 +203,8 @@ func InitHandlers(app *appsrv.Application) {
|
||||
|
||||
models.VpcPeeringConnectionManager,
|
||||
models.InterVpcNetworkManager,
|
||||
|
||||
models.NatSkuManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
handler := db.NewModelHandler(manager)
|
||||
|
||||
@@ -129,6 +129,7 @@ func StartService() {
|
||||
cron.AddJobAtIntervals("CleanExpiredPostpaidElasticCaches", time.Duration(opts.PrepaidExpireCheckSeconds)*time.Second, models.ElasticcacheManager.DeleteExpiredPostpaids)
|
||||
cron.AddJobAtIntervals("CleanExpiredPostpaidDBInstances", time.Duration(opts.PrepaidExpireCheckSeconds)*time.Second, models.DBInstanceManager.DeleteExpiredPostpaids)
|
||||
cron.AddJobAtIntervals("CleanExpiredPostpaidServers", time.Duration(opts.PrepaidExpireCheckSeconds)*time.Second, models.GuestManager.DeleteExpiredPostpaidServers)
|
||||
cron.AddJobAtIntervals("CleanExpiredPostpaidNatGateways", time.Duration(opts.PrepaidExpireCheckSeconds)*time.Second, models.NatGatewayManager.DeleteExpiredPostpaids)
|
||||
cron.AddJobAtIntervals("StartHostPingDetectionTask", time.Duration(opts.HostOfflineDetectionInterval)*time.Second, models.HostManager.PingDetectionTask)
|
||||
|
||||
cron.AddJobAtIntervalsWithStartRun("CalculateQuotaUsages", time.Duration(opts.CalculateQuotaUsageIntervalSeconds)*time.Second, models.QuotaManager.CalculateQuotaUsages, true)
|
||||
@@ -151,6 +152,7 @@ func StartService() {
|
||||
cron.AddJobEveryFewHour("SnapshotsCleanup", 1, 35, 0, models.SnapshotManager.CleanupSnapshots, false)
|
||||
cron.AddJobEveryFewDays("SyncSkus", opts.SyncSkusDay, opts.SyncSkusHour, 0, 0, models.SyncServerSkus, true)
|
||||
cron.AddJobEveryFewDays("SyncDBInstanceSkus", opts.SyncSkusDay, opts.SyncSkusHour, 0, 0, models.SyncDBInstanceSkus, true)
|
||||
cron.AddJobEveryFewDays("SyncNatSkus", opts.SyncSkusDay, opts.SyncSkusHour, 0, 0, models.SyncNatSkus, false)
|
||||
cron.AddJobEveryFewDays("SyncElasticCacheSkus", opts.SyncSkusDay, opts.SyncSkusHour, 0, 0, models.SyncElasticCacheSkus, true)
|
||||
cron.AddJobEveryFewDays("StorageSnapshotsRecycle", 1, 2, 0, 0, models.StorageManager.StorageSnapshotsRecycle, false)
|
||||
|
||||
|
||||
@@ -102,6 +102,9 @@ func (self *CloudAccountSyncSkusTask) OnInit(ctx context.Context, obj db.IStanda
|
||||
syncFunc = models.ElasticcacheSkuManager.SyncElasticcacheSkus
|
||||
case models.DBInstanceSkuManager.Keyword():
|
||||
syncFunc = models.DBInstanceSkuManager.SyncDBInstanceSkus
|
||||
case models.NatSkuManager.Keyword():
|
||||
result := region.SyncNatSkus(ctx, self.GetUserCred(), meta)
|
||||
log.Infof("Sync %s %s skus for region %s result: %s", region.Provider, res, region.Name, result.Result())
|
||||
}
|
||||
|
||||
if syncFunc != nil {
|
||||
|
||||
@@ -46,6 +46,9 @@ func (self *CloudRegionSyncSkusTask) OnInit(ctx context.Context, obj db.IStandal
|
||||
syncFunc = models.ElasticcacheSkuManager.SyncElasticcacheSkus
|
||||
case models.DBInstanceSkuManager.Keyword():
|
||||
syncFunc = models.DBInstanceSkuManager.SyncDBInstanceSkus
|
||||
case models.NatSkuManager.Keyword():
|
||||
result := region.SyncNatSkus(ctx, self.GetUserCred(), meta)
|
||||
log.Infof("Sync %s %s skus for region %s result: %s", region.Provider, res, region.Name, result.Result())
|
||||
}
|
||||
|
||||
if syncFunc != nil {
|
||||
|
||||
@@ -58,7 +58,7 @@ func (self *EipAllocateTask) setGuestAllocateEipFailed(eip *models.SElasticip, r
|
||||
return
|
||||
}
|
||||
guest := instance.(*models.SGuest)
|
||||
guest.SetStatus(self.UserCred, api.VM_ASSOCIATE_EIP_FAILED, reason.String())
|
||||
guest.SetStatus(self.UserCred, api.INSTANCE_ASSOCIATE_EIP_FAILED, reason.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
@@ -35,58 +36,98 @@ func init() {
|
||||
taskman.RegisterTask(EipAssociateTask{})
|
||||
}
|
||||
|
||||
func (self *EipAssociateTask) TaskFail(ctx context.Context, eip *models.SElasticip, msg jsonutils.JSONObject, vm *models.SGuest) {
|
||||
eip.SetStatus(self.UserCred, api.EIP_STATUS_READY, msg.String())
|
||||
self.SetStageFailed(ctx, msg)
|
||||
if vm != nil {
|
||||
vm.SetStatus(self.UserCred, api.VM_ASSOCIATE_EIP_FAILED, msg.String())
|
||||
db.OpsLog.LogEvent(vm, db.ACT_EIP_ATTACH, msg, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, vm, logclient.ACT_EIP_ASSOCIATE, msg, self.UserCred, false)
|
||||
func (self *EipAssociateTask) taskFail(ctx context.Context, eip *models.SElasticip, obj db.IStatusStandaloneModel, err error) {
|
||||
eip.SetStatus(self.UserCred, api.EIP_STATUS_READY, err.Error())
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
if obj != nil {
|
||||
db.StatusBaseSetStatus(obj, self.GetUserCred(), api.INSTANCE_ASSOCIATE_EIP_FAILED, err.Error())
|
||||
db.OpsLog.LogEvent(obj, db.ACT_EIP_ATTACH, err, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, obj, logclient.ACT_EIP_ASSOCIATE, err, self.UserCred, false)
|
||||
}
|
||||
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_VM_ASSOCIATE, err, self.UserCred, false)
|
||||
}
|
||||
|
||||
func (self *EipAssociateTask) GetAssociateInput() (api.ElasticipAssociateInput, error) {
|
||||
input := api.ElasticipAssociateInput{}
|
||||
err := self.Params.Unmarshal(&input)
|
||||
if err != nil {
|
||||
return input, errors.Wrapf(err, "self.Params.Unmarshal")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *EipAssociateTask) GetAssociateObj() (db.IStatusStandaloneModel, api.ElasticipAssociateInput, error) {
|
||||
input, err := self.GetAssociateInput()
|
||||
if err != nil {
|
||||
return nil, input, errors.Wrapf(err, "GetAssociateInput")
|
||||
}
|
||||
|
||||
switch input.InstanceType {
|
||||
case api.EIP_ASSOCIATE_TYPE_SERVER:
|
||||
vmObj, err := models.GuestManager.FetchById(input.InstanceId)
|
||||
if err != nil {
|
||||
return nil, input, errors.Wrapf(err, "GuestManager.FetchById(%s)", input.InstanceId)
|
||||
}
|
||||
return vmObj.(*models.SGuest), input, nil
|
||||
case api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY:
|
||||
natObj, err := models.NatGatewayManager.FetchById(input.InstanceId)
|
||||
if err != nil {
|
||||
return nil, input, errors.Wrapf(err, "NatGatewayManager.FetchById(%s)", input.InstanceId)
|
||||
}
|
||||
return natObj.(*models.SNatGateway), input, nil
|
||||
default:
|
||||
return nil, input, fmt.Errorf("invalid instance type %s", input.InstanceType)
|
||||
}
|
||||
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_VM_ASSOCIATE, msg, self.UserCred, false)
|
||||
}
|
||||
|
||||
func (self *EipAssociateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
eip := obj.(*models.SElasticip)
|
||||
|
||||
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)
|
||||
self.TaskFail(ctx, eip, jsonutils.NewString(msg), nil)
|
||||
region, err := eip.GetRegion()
|
||||
if err != nil {
|
||||
self.taskFail(ctx, eip, nil, errors.Wrapf(err, "eip.GetRegion"))
|
||||
return
|
||||
}
|
||||
|
||||
driver := server.GetDriver()
|
||||
if driver == nil {
|
||||
msg := fmt.Sprintf("fail to find guest driver for instanceId %s", instanceId)
|
||||
self.TaskFail(ctx, eip, jsonutils.NewString(msg), nil)
|
||||
ins, input, err := self.GetAssociateObj()
|
||||
if err != nil {
|
||||
self.taskFail(ctx, eip, nil, errors.Wrapf(err, "self.GetAssociateObj"))
|
||||
return
|
||||
}
|
||||
|
||||
db.StatusBaseSetStatus(ins, self.GetUserCred(), api.INSTANCE_ASSOCIATE_EIP, "associate eip")
|
||||
|
||||
self.SetStage("OnAssociateEipComplete", nil)
|
||||
if err := driver.RequestAssociateEip(ctx, self.UserCred, server, eip, self); err != nil {
|
||||
self.TaskFail(ctx, eip, jsonutils.NewString(err.Error()), server)
|
||||
err = region.GetDriver().RequestAssociatEip(ctx, self.UserCred, eip, input, ins, self)
|
||||
if err != nil {
|
||||
self.taskFail(ctx, eip, ins, errors.Wrapf(err, "RequestAssociatEip"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (self *EipAssociateTask) OnAssociateEipComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
eip := obj.(*models.SElasticip)
|
||||
instanceId, _ := self.Params.GetString("instance_id")
|
||||
server := models.GuestManager.FetchGuestById(instanceId)
|
||||
server.StartSyncstatus(ctx, self.UserCred, "")
|
||||
logclient.AddActionLogWithStartable(self, server, logclient.ACT_EIP_ASSOCIATE, nil, self.UserCred, true)
|
||||
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_VM_ASSOCIATE, nil, self.UserCred, true)
|
||||
|
||||
ins, input, err := self.GetAssociateObj()
|
||||
if err == nil {
|
||||
switch input.InstanceType {
|
||||
case api.EIP_ASSOCIATE_TYPE_SERVER:
|
||||
server := ins.(*models.SGuest)
|
||||
server.StartSyncstatus(ctx, self.UserCred, "")
|
||||
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_VM_ASSOCIATE, nil, self.UserCred, true)
|
||||
case api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY:
|
||||
nat := ins.(*models.SNatGateway)
|
||||
nat.StartSyncstatus(ctx, self.UserCred, "")
|
||||
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_NATGATEWAY_ASSOCIATE, nil, self.UserCred, true)
|
||||
}
|
||||
logclient.AddActionLogWithStartable(self, ins, logclient.ACT_EIP_ASSOCIATE, nil, self.UserCred, true)
|
||||
}
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *EipAssociateTask) OnAssociateEipCompleteFailed(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
eip := obj.(*models.SElasticip)
|
||||
instanceId, _ := self.Params.GetString("instance_id")
|
||||
server := models.GuestManager.FetchGuestById(instanceId)
|
||||
self.TaskFail(ctx, eip, data, server)
|
||||
return
|
||||
ins, _, _ := self.GetAssociateObj()
|
||||
self.taskFail(ctx, eip, ins, errors.Errorf(data.String()))
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
@@ -129,17 +130,24 @@ func (self *GuestCreateTask) OnDeployGuestDescComplete(ctx context.Context, obj
|
||||
|
||||
eip := eipObj.(*models.SElasticip)
|
||||
|
||||
input := api.ElasticipAssociateInput{
|
||||
InstanceId: guest.Id,
|
||||
InstanceExternalId: guest.ExternalId,
|
||||
InstanceType: api.EIP_ASSOCIATE_TYPE_SERVER,
|
||||
}
|
||||
|
||||
eipBw, _ := self.Params.Int("eip_bw")
|
||||
if eipBw > 0 {
|
||||
// newly allocated eip, need allocation and associate
|
||||
err = eip.AllocateAndAssociateVM(ctx, self.UserCred, guest, self.GetId())
|
||||
err = eip.AllocateAndAssociateInstance(ctx, self.UserCred, guest, input, self.GetId())
|
||||
err = errors.Wrapf(err, "eip.AllocateAndAssociateInstance")
|
||||
} else {
|
||||
// existing eip, association only
|
||||
err = eip.StartEipAssociateInstanceTask(ctx, self.UserCred, guest, self.GetId())
|
||||
err = eip.StartEipAssociateInstanceTask(ctx, self.UserCred, input, self.GetId())
|
||||
err = errors.Wrapf(err, "eip.StartEipAssociateInstanceTask")
|
||||
}
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to asscociate eip %s %s", eipId, err)
|
||||
self.OnDeployEipCompleteFailed(ctx, obj, jsonutils.NewString(msg))
|
||||
self.OnDeployEipCompleteFailed(ctx, obj, jsonutils.NewString(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -198,10 +206,10 @@ func (self *GuestCreateTask) OnDeployEipComplete(ctx context.Context, obj db.ISt
|
||||
|
||||
func (self *GuestCreateTask) OnDeployEipCompleteFailed(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
guest.SetStatus(self.UserCred, api.VM_ASSOCIATE_EIP_FAILED, "deploy_failed")
|
||||
guest.SetStatus(self.UserCred, api.INSTANCE_ASSOCIATE_EIP_FAILED, "deploy_failed")
|
||||
db.OpsLog.LogEvent(guest, db.ACT_EIP_ATTACH, data, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_EIP_ASSOCIATE, data, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, guest.Id, guest.Name, api.VM_ASSOCIATE_EIP_FAILED, data.String())
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, guest.Id, guest.Name, api.INSTANCE_ASSOCIATE_EIP_FAILED, data.String())
|
||||
self.SetStageFailed(ctx, data)
|
||||
}
|
||||
|
||||
|
||||
195
pkg/compute/tasks/nat_create_task.go
Normal file
195
pkg/compute/tasks/nat_create_task.go
Normal file
@@ -0,0 +1,195 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type NatGatewayCreateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(NatGatewayCreateTask{})
|
||||
}
|
||||
|
||||
func (self *NatGatewayCreateTask) taskFailed(ctx context.Context, nat *models.SNatGateway, err error) {
|
||||
nat.SetStatus(self.UserCred, api.NAT_STATUS_CREATE_FAILED, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, nat, logclient.ACT_ALLOCATE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *NatGatewayCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
nat := obj.(*models.SNatGateway)
|
||||
|
||||
opts := cloudprovider.NatGatewayCreateOptions{
|
||||
Name: nat.Name,
|
||||
Desc: nat.Description,
|
||||
NatSpec: nat.NatSpec,
|
||||
}
|
||||
|
||||
vpc, err := nat.GetVpc()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "nat.GetVpc"))
|
||||
return
|
||||
}
|
||||
|
||||
opts.VpcId = vpc.ExternalId
|
||||
|
||||
networkId, _ := self.GetParams().GetString("network_id")
|
||||
if len(networkId) > 0 {
|
||||
_network, err := models.NetworkManager.FetchById(networkId)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "NetworkManager.FetchById(%s)", networkId))
|
||||
return
|
||||
}
|
||||
network := _network.(*models.SNetwork)
|
||||
opts.NetworkId = network.ExternalId
|
||||
}
|
||||
|
||||
if nat.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
bc, err := billing.ParseBillingCycle(nat.BillingCycle)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "ParseBillingCycle(%s)", nat.BillingCycle))
|
||||
return
|
||||
}
|
||||
bc.AutoRenew = nat.AutoRenew
|
||||
opts.BillingCycle = &bc
|
||||
}
|
||||
|
||||
self.SetStage("OnCreateNatGatewayCreateComplete", nil)
|
||||
taskman.LocalTaskRun(self, func() (jsonutils.JSONObject, error) {
|
||||
iVpc, err := vpc.GetIVpc()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "vpc.GetIVpc")
|
||||
}
|
||||
|
||||
iNat, err := iVpc.CreateINatGateway(&opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "iVpc.CreateINatGateway")
|
||||
}
|
||||
err = db.SetExternalId(nat, self.GetUserCred(), iNat.GetGlobalId())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.SetExternalId")
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(iNat, api.NAT_STAUTS_AVAILABLE, time.Second*5, time.Minute*10)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cloudprovider.WaitStatus")
|
||||
}
|
||||
|
||||
nat.SyncWithCloudNatGateway(ctx, self.GetUserCred(), nat.GetCloudprovider(), iNat)
|
||||
return nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (self *NatGatewayCreateTask) OnCreateNatGatewayCreateComplete(ctx context.Context, nat *models.SNatGateway, body jsonutils.JSONObject) {
|
||||
input := api.NatgatewayCreateInput{}
|
||||
self.GetParams().Unmarshal(&input)
|
||||
if len(input.Eip) > 0 || input.EipBw > 0 {
|
||||
self.SetStage("OnDeployEipComplete", nil)
|
||||
|
||||
var eip *models.SElasticip = nil
|
||||
var err error
|
||||
if len(input.Eip) > 0 {
|
||||
eipObj, err := models.ElasticipManager.FetchById(input.Eip)
|
||||
if err != nil {
|
||||
self.OnDeployEipCompleteFailed(ctx, nat, jsonutils.NewString(errors.Wrapf(err, "ElasticipManager.FetchById(%s)", input.Eip).Error()))
|
||||
return
|
||||
}
|
||||
eip = eipObj.(*models.SElasticip)
|
||||
} else {
|
||||
pendingRegionUsage := models.SRegionQuota{}
|
||||
self.GetPendingUsage(&pendingRegionUsage, 1)
|
||||
self.SetPendingUsage(&pendingRegionUsage, 1)
|
||||
|
||||
eip, err = models.ElasticipManager.NewEipForVMOnHost(ctx, self.UserCred, &models.NewEipForVMOnHostArgs{
|
||||
Bandwidth: input.EipBw,
|
||||
BgpType: input.EipBgpType,
|
||||
ChargeType: input.EipChargeType,
|
||||
AutoDellocate: input.EipAutoDellocate,
|
||||
|
||||
Natgateway: nat,
|
||||
PendingUsage: &pendingRegionUsage,
|
||||
})
|
||||
self.SetPendingUsage(&pendingRegionUsage, 1)
|
||||
if err != nil {
|
||||
self.OnDeployEipCompleteFailed(ctx, nat, jsonutils.NewString(errors.Wrapf(err, "ElasticipManager.NewEipForVMOnHost").Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
opts := api.ElasticipAssociateInput{
|
||||
InstanceId: nat.Id,
|
||||
InstanceExternalId: nat.ExternalId,
|
||||
InstanceType: api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY,
|
||||
}
|
||||
if input.EipBw > 0 {
|
||||
// newly allocated eip, need allocation and associate
|
||||
err = eip.AllocateAndAssociateInstance(ctx, self.UserCred, nat, opts, self.GetId())
|
||||
err = errors.Wrap(err, "AllocateAndAssociateVM")
|
||||
} else {
|
||||
err = eip.StartEipAssociateInstanceTask(ctx, self.UserCred, opts, self.GetId())
|
||||
err = errors.Wrap(err, "StartEipAssociateInstanceTask")
|
||||
}
|
||||
if err != nil {
|
||||
self.OnDeployEipCompleteFailed(ctx, nat, jsonutils.NewString(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
self.OnDeployEipComplete(ctx, nat, nil)
|
||||
}
|
||||
|
||||
func (self *NatGatewayCreateTask) OnCreateNatGatewayCreateCompleteFailed(ctx context.Context, nat *models.SNatGateway, body jsonutils.JSONObject) {
|
||||
self.taskFailed(ctx, nat, errors.Errorf(body.String()))
|
||||
}
|
||||
|
||||
func (self *NatGatewayCreateTask) OnDeployEipCompleteFailed(ctx context.Context, nat *models.SNatGateway, data jsonutils.JSONObject) {
|
||||
nat.SetStatus(self.UserCred, api.INSTANCE_ASSOCIATE_EIP_FAILED, data.String())
|
||||
db.OpsLog.LogEvent(nat, db.ACT_EIP_ATTACH, data, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, nat, logclient.ACT_EIP_ASSOCIATE, data, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, nat.Id, nat.Name, api.INSTANCE_ASSOCIATE_EIP_FAILED, data.String())
|
||||
self.SetStageFailed(ctx, data)
|
||||
}
|
||||
|
||||
func (self *NatGatewayCreateTask) OnDeployEipComplete(ctx context.Context, nat *models.SNatGateway, data jsonutils.JSONObject) {
|
||||
self.SetStage("OnSyncstatusComplete", nil)
|
||||
nat.StartSyncstatus(ctx, self.GetUserCred(), self.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *NatGatewayCreateTask) OnSyncstatusComplete(ctx context.Context, nat *models.SNatGateway, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *NatGatewayCreateTask) OnSyncstatusCompleteFailed(ctx context.Context, nat *models.SNatGateway, data jsonutils.JSONObject) {
|
||||
self.SetStageFailed(ctx, data)
|
||||
}
|
||||
121
pkg/compute/tasks/nat_delete_task.go
Normal file
121
pkg/compute/tasks/nat_delete_task.go
Normal file
@@ -0,0 +1,121 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"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/compute/models"
|
||||
)
|
||||
|
||||
type NatGatewayDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(NatGatewayDeleteTask{})
|
||||
}
|
||||
|
||||
func (self *NatGatewayDeleteTask) taskFailed(ctx context.Context, nat *models.SNatGateway, err error) {
|
||||
nat.SetStatus(self.UserCred, api.NAT_STATUS_DELETE_FAILED, err.Error())
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *NatGatewayDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
nat := obj.(*models.SNatGateway)
|
||||
|
||||
self.SetStage("OnEipDissociateComplete", nil)
|
||||
self.OnEipDissociateComplete(ctx, nat, nil)
|
||||
}
|
||||
|
||||
func (self *NatGatewayDeleteTask) OnEipDissociateComplete(ctx context.Context, nat *models.SNatGateway, data jsonutils.JSONObject) {
|
||||
eips, err := nat.GetEips()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "nat.GetEips"))
|
||||
return
|
||||
}
|
||||
if len(eips) > 0 {
|
||||
eips[0].StartEipDissociateTask(ctx, self.GetUserCred(), false, self.GetTaskId())
|
||||
return
|
||||
}
|
||||
self.doDeleteNatGateway(ctx, nat)
|
||||
}
|
||||
|
||||
func (self *NatGatewayDeleteTask) OnEipDissociateCompleteFailed(ctx context.Context, nat *models.SNatGateway, data jsonutils.JSONObject) {
|
||||
self.SetStageFailed(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *NatGatewayDeleteTask) doDeleteNatGateway(ctx context.Context, nat *models.SNatGateway) {
|
||||
iNat, err := nat.GetINatGateway()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
self.taskComplete(ctx, nat)
|
||||
return
|
||||
}
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "nat.GetINatGateway"))
|
||||
return
|
||||
}
|
||||
|
||||
dnat, err := iNat.GetINatDTable()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "iNat.GetINatDTable"))
|
||||
return
|
||||
}
|
||||
for i := range dnat {
|
||||
err = dnat[i].Delete()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "delete d entry %v", dnat[i]))
|
||||
return
|
||||
}
|
||||
}
|
||||
snat, err := iNat.GetINatSTable()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "GetINatSTable"))
|
||||
return
|
||||
}
|
||||
for i := range snat {
|
||||
err = snat[i].Delete()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "delete s entry %v", snat[i]))
|
||||
}
|
||||
}
|
||||
|
||||
err = iNat.Delete()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "iNat.Delete"))
|
||||
return
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitDeleted(iNat, time.Second*5, time.Minute*3)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "cloudprovider.WaitDeleted"))
|
||||
return
|
||||
}
|
||||
|
||||
self.taskComplete(ctx, nat)
|
||||
}
|
||||
|
||||
func (self *NatGatewayDeleteTask) taskComplete(ctx context.Context, nat *models.SNatGateway) {
|
||||
nat.RealDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
100
pkg/compute/tasks/nat_renew_task.go
Normal file
100
pkg/compute/tasks/nat_renew_task.go
Normal file
@@ -0,0 +1,100 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"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/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type NatGatewayRenewTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(NatGatewayRenewTask{})
|
||||
}
|
||||
|
||||
func (self *NatGatewayRenewTask) taskFailed(ctx context.Context, nat *models.SNatGateway, err error) {
|
||||
db.OpsLog.LogEvent(nat, db.ACT_REW_FAIL, err, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, nat, logclient.ACT_RENEW, err, self.UserCred, false)
|
||||
nat.SetStatus(self.GetUserCred(), api.NAT_STATUS_RENEW_FAILED, err.Error())
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *NatGatewayRenewTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
nat := obj.(*models.SNatGateway)
|
||||
|
||||
duration, _ := self.GetParams().GetString("duration")
|
||||
bc, err := billing.ParseBillingCycle(duration)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "ParseBillingCycle(%s)", duration))
|
||||
return
|
||||
}
|
||||
|
||||
iNat, err := nat.GetINatGateway()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "GetINatGateway"))
|
||||
return
|
||||
}
|
||||
oldExpired := iNat.GetExpiredAt()
|
||||
|
||||
err = iNat.Renew(bc)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "iNat.Renew"))
|
||||
return
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitCreated(15*time.Second, 5*time.Minute, func() bool {
|
||||
err := iNat.Refresh()
|
||||
if err != nil {
|
||||
log.Errorf("failed refresh nat %s error: %v", nat.Name, err)
|
||||
}
|
||||
newExipred := iNat.GetExpiredAt()
|
||||
if newExipred.After(oldExpired) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "wait expired time refresh"))
|
||||
return
|
||||
}
|
||||
|
||||
logclient.AddActionLogWithStartable(self, nat, logclient.ACT_RENEW, map[string]string{"duration": duration}, self.UserCred, true)
|
||||
|
||||
self.SetStage("OnSyncstatusComplete", nil)
|
||||
nat.StartSyncstatus(ctx, self.GetUserCred(), self.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *NatGatewayRenewTask) OnSyncstatusComplete(ctx context.Context, nat *models.SNatGateway, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *NatGatewayRenewTask) OnSyncstatusCompleteFailed(ctx context.Context, nat *models.SNatGateway, reason jsonutils.JSONObject) {
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
68
pkg/compute/tasks/nat_set_auto_renew_task.go
Normal file
68
pkg/compute/tasks/nat_set_auto_renew_task.go
Normal file
@@ -0,0 +1,68 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type NatGatewaySetAutoRenewTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(NatGatewaySetAutoRenewTask{})
|
||||
}
|
||||
|
||||
func (self *NatGatewaySetAutoRenewTask) taskFailed(ctx context.Context, nat *models.SNatGateway, err error) {
|
||||
db.OpsLog.LogEvent(nat, db.ACT_SET_AUTO_RENEW_FAIL, err, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, nat, logclient.ACT_SET_AUTO_RENEW, err, self.GetUserCred(), false)
|
||||
nat.SetStatus(self.GetUserCred(), api.NAT_STATUS_SET_AUTO_RENEW_FAILED, err.Error())
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *NatGatewaySetAutoRenewTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
nat := obj.(*models.SNatGateway)
|
||||
autoRenew := jsonutils.QueryBoolean(self.GetParams(), "auto_renew", false)
|
||||
iNat, err := nat.GetINatGateway()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "GetINatGateway"))
|
||||
return
|
||||
}
|
||||
err = iNat.SetAutoRenew(autoRenew)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, nat, errors.Wrapf(err, "iNat.SetAutoRenew"))
|
||||
return
|
||||
}
|
||||
self.SetStage("OnNatGatewaySyncComplete", nil)
|
||||
nat.StartSyncstatus(ctx, self.GetUserCred(), self.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *NatGatewaySetAutoRenewTask) OnNatGatewaySyncComplete(ctx context.Context, nat *models.SNatGateway, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *NatGatewaySetAutoRenewTask) OnNatGatewaySyncCompleteFailed(ctx context.Context, nat *models.SNatGateway, data jsonutils.JSONObject) {
|
||||
self.SetStageFailed(ctx, data)
|
||||
}
|
||||
@@ -39,7 +39,7 @@ func init() {
|
||||
}
|
||||
|
||||
func (self *SNatDEntryCreateTask) TaskFailed(ctx context.Context, dnatEntry models.INatHelper, reason jsonutils.JSONObject) {
|
||||
dnatEntry.SetStatus(self.UserCred, api.NAT_STATUS_FAILED, reason.String())
|
||||
dnatEntry.SetStatus(self.UserCred, api.NAT_STATUS_CREATE_FAILED, reason.String())
|
||||
db.OpsLog.LogEvent(dnatEntry, db.ACT_ALLOCATE_FAIL, reason.String(), self.UserCred)
|
||||
natgateway, err := dnatEntry.GetNatgateway()
|
||||
if err == nil {
|
||||
|
||||
@@ -39,7 +39,7 @@ func init() {
|
||||
}
|
||||
|
||||
func (self *SNatSEntryCreateTask) TaskFailed(ctx context.Context, snatEntry models.INatHelper, reason jsonutils.JSONObject) {
|
||||
snatEntry.SetStatus(self.UserCred, api.NAT_STATUS_FAILED, reason.String())
|
||||
snatEntry.SetStatus(self.UserCred, api.NAT_STATUS_CREATE_FAILED, reason.String())
|
||||
db.OpsLog.LogEvent(snatEntry, db.ACT_ALLOCATE_FAIL, reason, self.UserCred)
|
||||
natgateway, err := snatEntry.GetNatgateway()
|
||||
if err == nil {
|
||||
|
||||
33
pkg/mcclient/modules/mod_nat_skus.go
Normal file
33
pkg/mcclient/modules/mod_nat_skus.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package modules
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
|
||||
type NatSkusManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
NatSkus NatSkusManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
NatSkus = NatSkusManager{NewComputeManager("nat_sku", "nat_skus",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
registerCompute(&NatSkus)
|
||||
}
|
||||
@@ -840,7 +840,7 @@ func (opts *CloudaccountShareModeOptions) Params() (jsonutils.JSONObject, error)
|
||||
|
||||
type CloudaccountSyncSkusOptions struct {
|
||||
SCloudAccountIdOptions
|
||||
RESOURCE string `help:"Resource of skus" choices:"serversku|elasticcachesku|dbinstance_sku"`
|
||||
RESOURCE string `help:"Resource of skus" choices:"serversku|elasticcachesku|dbinstance_sku|nat_sku"`
|
||||
Force bool `help:"Force sync no matter what"`
|
||||
Provider string `help:"provider to sync"`
|
||||
Region string `help:"region to sync"`
|
||||
|
||||
111
pkg/mcclient/options/compute/eips.go
Normal file
111
pkg/mcclient/options/compute/eips.go
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type ElasticipListOptions struct {
|
||||
Region string `help:"List eips in cloudregion"`
|
||||
|
||||
Usable *bool `help:"List all zones that is usable"`
|
||||
UsableEipForAssociateType string `help:"With associate id filter which eip can associate"`
|
||||
UsableEipForAssociateId string `help:"With associate type filter which eip can associate"`
|
||||
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (opts *ElasticipListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type EipCreateOptions struct {
|
||||
options.BaseCreateOptions
|
||||
Manager *string `help:"cloud provider"`
|
||||
Region *string `help:"cloud region in which EIP is allocated"`
|
||||
Bandwidth *int `help:"Bandwidth in Mbps"`
|
||||
IpAddr *string `help:"IP address of the EIP" json:"ip_addr"`
|
||||
Network *string `help:"Network of the EIP"`
|
||||
BgpType *string `help:"BgpType of the EIP" positional:"false"`
|
||||
ChargeType *string `help:"bandwidth charge type" choices:"traffic|bandwidth"`
|
||||
}
|
||||
|
||||
func (opts *EipCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type EipUpdateOptions struct {
|
||||
options.BaseUpdateOptions
|
||||
|
||||
AutoDellocate *string `help:"enable or disable automatically dellocate when dissociate from instance" choices:"true|false"`
|
||||
}
|
||||
|
||||
func (opts *EipUpdateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type EipAssociateOptions struct {
|
||||
options.BaseIdOptions
|
||||
INSTANCE_ID 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|natgateway"`
|
||||
}
|
||||
|
||||
func (opts *EipAssociateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(map[string]string{"instance_id": opts.INSTANCE_ID, "instance_type": opts.InstanceType}), nil
|
||||
}
|
||||
|
||||
type EipDissociateOptions struct {
|
||||
options.BaseIdOptions
|
||||
AutoDelete bool `help:"automatically delete the dissociate EIP" json:"auto_delete,omitfalse"`
|
||||
}
|
||||
|
||||
func (opts *EipDissociateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(map[string]bool{"auto_delete": opts.AutoDelete}), nil
|
||||
}
|
||||
|
||||
type EipChangeBandwidthOptions struct {
|
||||
options.BaseIdOptions
|
||||
BANDWIDTH int `help:"new bandwidth of EIP"`
|
||||
}
|
||||
|
||||
func (opts *EipChangeBandwidthOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(map[string]int{"bandwidth": opts.BANDWIDTH}), nil
|
||||
}
|
||||
|
||||
type EipChangeOwnerOptions struct {
|
||||
options.BaseIdOptions
|
||||
PROJECT string `help:"Project ID or change"`
|
||||
//RawId bool `help:"User raw ID, instead of name"`
|
||||
}
|
||||
|
||||
func (opts *EipChangeOwnerOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(map[string]string{"tenant": opts.PROJECT}), nil
|
||||
/*
|
||||
params := jsonutils.NewDict()
|
||||
if opts.RawId {
|
||||
projid, err := modules.Projects.GetId(s, opts.PROJECT, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params.Add(jsonutils.NewString(projid), "tenant")
|
||||
params.Add(jsonutils.JSONTrue, "raw_id")
|
||||
} else {
|
||||
params.Add(jsonutils.NewString(opts.PROJECT), "tenant")
|
||||
}
|
||||
*/
|
||||
}
|
||||
41
pkg/mcclient/options/compute/nat_skus.go
Normal file
41
pkg/mcclient/options/compute/nat_skus.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type NatSkuListOption struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (opts *NatSkuListOption) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type NatSkuIdOption struct {
|
||||
ID string `help:"Nat Id or name"`
|
||||
}
|
||||
|
||||
func (opts *NatSkuIdOption) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (opts *NatSkuIdOption) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
@@ -12,26 +12,56 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package options
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type NatGatewayListOptions struct {
|
||||
options.BaseListOptions
|
||||
Vpc string `help:"vpc id or name"`
|
||||
Cloudregion string `help:"cloudreigon id or name"`
|
||||
}
|
||||
|
||||
BaseListOptions
|
||||
func (opts *NatGatewayListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type NatGatewayIdOptions struct {
|
||||
ID string `help:"ID of Nat Gateway"`
|
||||
}
|
||||
|
||||
func (opts *NatGatewayIdOptions) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *NatGatewayIdOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type NatGatewayDeleteOption struct {
|
||||
NatGatewayIdOptions
|
||||
Force bool
|
||||
}
|
||||
|
||||
func (opts *NatGatewayDeleteOption) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(map[string]bool{"force": opts.Force}), nil
|
||||
}
|
||||
|
||||
type NatDTableListOptions struct {
|
||||
Natgateway string `help:"Natgateway name or id"`
|
||||
|
||||
BaseListOptions
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
type NatSTableListOptions struct {
|
||||
Natgateway string `help:"Natgateway name or id"`
|
||||
Network string `help:"Network id or name"`
|
||||
|
||||
BaseListOptions
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
type NatDDeleteShowOptions struct {
|
||||
@@ -42,10 +72,6 @@ type NatSDeleteShowOptions struct {
|
||||
ID string `help:"ID of the SNat"`
|
||||
}
|
||||
|
||||
type NatGatewayIdOptions struct {
|
||||
ID string `help:"ID of Nat Gateway"`
|
||||
}
|
||||
|
||||
type NatDCreateOptions struct {
|
||||
NAME string `help:"DNAT's name"`
|
||||
NATGATEWAYID string `help:"The nat gateway'id to which DNat belongs"`
|
||||
@@ -1078,3 +1078,14 @@ type ServerRemoteUpdateOptions struct {
|
||||
ServerIdOptions
|
||||
computeapi.ServerRemoteUpdateInput
|
||||
}
|
||||
|
||||
type ServerCreateEipOptions struct {
|
||||
BaseIdOptions
|
||||
Bandwidth int `help:"EIP bandwidth in Mbps" default:"5"`
|
||||
BgpType *string `help:"desired BGP type"`
|
||||
ChargeType *string `help:"bandwidth charge type" choices:"traffic|bandwidth"`
|
||||
}
|
||||
|
||||
func (opts *ServerCreateEipOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
@@ -541,6 +541,7 @@ func (region *SAliyunClient) GetCapabilities() []string {
|
||||
cloudprovider.CLOUD_CAPABILITY_DNSZONE,
|
||||
cloudprovider.CLOUD_CAPABILITY_INTERVPCNETWORK,
|
||||
cloudprovider.CLOUD_CAPABILITY_SAML_AUTH,
|
||||
cloudprovider.CLOUD_CAPABILITY_NAT,
|
||||
}
|
||||
return caps
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -85,7 +87,10 @@ func (nat *SNatGetway) GetStatus() string {
|
||||
default:
|
||||
return api.NAT_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SNatGetway) Delete() error {
|
||||
return self.vpc.region.DeleteNatGateway(self.NatGatewayId, false)
|
||||
}
|
||||
|
||||
func (nat *SNatGetway) GetBillingType() string {
|
||||
@@ -93,9 +98,26 @@ func (nat *SNatGetway) GetBillingType() string {
|
||||
}
|
||||
|
||||
func (nat *SNatGetway) GetNatSpec() string {
|
||||
if len(nat.Spec) == 0 {
|
||||
return api.ALIYUN_NAT_SKU_DEFAULT
|
||||
}
|
||||
return nat.Spec
|
||||
}
|
||||
|
||||
func (self *SNatGetway) Refresh() error {
|
||||
nat, total, err := self.vpc.region.GetNatGateways("", self.NatGatewayId, 0, 1)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetNatGateways")
|
||||
}
|
||||
if total > 1 {
|
||||
return errors.Wrapf(cloudprovider.ErrDuplicateId, "get %d natgateways by id %s", total, self.NatGatewayId)
|
||||
}
|
||||
if total == 0 {
|
||||
return errors.Wrapf(cloudprovider.ErrNotFound, self.NatGatewayId)
|
||||
}
|
||||
return jsonutils.Update(self, nat[0])
|
||||
}
|
||||
|
||||
func (nat *SNatGetway) GetCreatedAt() time.Time {
|
||||
return nat.CreationTime
|
||||
}
|
||||
@@ -203,8 +225,7 @@ func (self *SRegion) GetNatGateways(vpcId string, natGwId string, offset, limit
|
||||
|
||||
body, err := self.vpcRequest("DescribeNatGateways", params)
|
||||
if err != nil {
|
||||
log.Errorf("GetVSwitches fail %s", err)
|
||||
return nil, 0, err
|
||||
return nil, 0, errors.Wrapf(err, "DescribeNatGateways")
|
||||
}
|
||||
|
||||
if self.client.debug {
|
||||
@@ -214,9 +235,96 @@ func (self *SRegion) GetNatGateways(vpcId string, natGwId string, offset, limit
|
||||
gateways := make([]SNatGetway, 0)
|
||||
err = body.Unmarshal(&gateways, "NatGateways", "NatGateway")
|
||||
if err != nil {
|
||||
log.Errorf("Unmarshal gateways fail %s", err)
|
||||
return nil, 0, err
|
||||
return nil, 0, errors.Wrapf(err, "body.Unmarshal")
|
||||
}
|
||||
total, _ := body.Int("TotalCount")
|
||||
return gateways, int(total), nil
|
||||
}
|
||||
|
||||
func (self *SVpc) CreateINatGateway(opts *cloudprovider.NatGatewayCreateOptions) (cloudprovider.ICloudNatGateway, error) {
|
||||
nat, err := self.region.CreateNatGateway(opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateNatGateway")
|
||||
}
|
||||
nat.vpc = self
|
||||
return nat, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateNatGateway(opts *cloudprovider.NatGatewayCreateOptions) (*SNatGetway, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"VpcId": opts.VpcId,
|
||||
"VSwitchId": opts.NetworkId,
|
||||
"NatType": "Enhanced",
|
||||
"Name": opts.Name,
|
||||
"Description": opts.Desc,
|
||||
"ClientToken": utils.GenRequestId(20),
|
||||
"InstanceChargeType": "PostPaid",
|
||||
"InternetChargeType": "PayBySpec",
|
||||
}
|
||||
if len(opts.NatSpec) == 0 || opts.NatSpec == api.ALIYUN_NAT_SKU_DEFAULT {
|
||||
params["InternetChargeType"] = "PayByLcu"
|
||||
} else {
|
||||
params["Spec"] = opts.NatSpec
|
||||
}
|
||||
|
||||
if opts.BillingCycle != nil {
|
||||
params["InstanceChargeType"] = "PrePaid"
|
||||
params["PricingCycle"] = "Month"
|
||||
params["AutoPay"] = "false"
|
||||
if opts.BillingCycle.GetYears() > 0 {
|
||||
params["PricingCycle"] = "Year"
|
||||
params["Duration"] = fmt.Sprintf("%d", opts.BillingCycle.GetYears())
|
||||
} else if opts.BillingCycle.GetMonths() > 0 {
|
||||
params["PricingCycle"] = "Year"
|
||||
params["Duration"] = fmt.Sprintf("%d", opts.BillingCycle.GetMonths())
|
||||
}
|
||||
if opts.BillingCycle.AutoRenew {
|
||||
params["AutoPay"] = "true"
|
||||
}
|
||||
}
|
||||
resp, err := self.vpcRequest("CreateNatGateway", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateNatGateway")
|
||||
}
|
||||
natId, err := resp.GetString("NatGatewayId")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Get(NatGatewayId)")
|
||||
}
|
||||
if len(natId) == 0 {
|
||||
return nil, errors.Errorf("empty NatGatewayId after created")
|
||||
}
|
||||
|
||||
var nat *SNatGetway = nil
|
||||
err = cloudprovider.Wait(time.Second*5, time.Minute*15, func() (bool, error) {
|
||||
nats, total, err := self.GetNatGateways("", natId, 0, 1)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "GetNatGateways(%s)", natId)
|
||||
}
|
||||
if total > 1 {
|
||||
return false, errors.Wrapf(cloudprovider.ErrDuplicateId, "get %d nats", total)
|
||||
}
|
||||
if total == 0 {
|
||||
return false, errors.Wrapf(cloudprovider.ErrNotFound, "search %s after %s created", opts.Name, natId)
|
||||
}
|
||||
nat = &nats[0]
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cloudprovider.Wait")
|
||||
}
|
||||
|
||||
return nat, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteNatGateway(natId string, isForce bool) error {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"NatGatewayId": natId,
|
||||
}
|
||||
if isForce {
|
||||
params["Force"] = "true"
|
||||
}
|
||||
_, err := self.vpcRequest("DeleteNatGateway", params)
|
||||
return errors.Wrapf(err, "DeleteNatGateway")
|
||||
}
|
||||
|
||||
@@ -22,11 +22,13 @@ import (
|
||||
|
||||
func init() {
|
||||
type NatGatewayListOptions struct {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
VpcId string `help:"Vpc Id"`
|
||||
NatId string `help:"NatGateway Id"`
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
shellutils.R(&NatGatewayListOptions{}, "natgateway-list", "List NAT gateways", func(cli *aliyun.SRegion, args *NatGatewayListOptions) error {
|
||||
gws, total, e := cli.GetNatGateways("", "", args.Offset, args.Limit)
|
||||
shellutils.R(&NatGatewayListOptions{}, "nat-list", "List NAT gateways", func(cli *aliyun.SRegion, args *NatGatewayListOptions) error {
|
||||
gws, total, e := cli.GetNatGateways(args.VpcId, args.NatId, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
@@ -34,6 +36,15 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type NatGatewayDeleteOptions struct {
|
||||
ID string `help:"Nat Id"`
|
||||
Force bool `help:"Force Delete Nat"`
|
||||
}
|
||||
|
||||
shellutils.R(&NatGatewayDeleteOptions{}, "nat-delete", "Delete nat gateways", func(cli *aliyun.SRegion, args *NatGatewayDeleteOptions) error {
|
||||
return cli.DeleteNatGateway(args.ID, args.Force)
|
||||
})
|
||||
|
||||
type NatSEntryListOptions struct {
|
||||
ID string `help:"SNat Table ID"`
|
||||
Limit int `help:"page size"`
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type SBillingBase struct{}
|
||||
@@ -43,3 +44,7 @@ func (self *SBillingBase) SetAutoRenew(autoRenew bool) error {
|
||||
func (self *SBillingBase) IsAutoRenew() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBillingBase) Renew(bc billing.SBillingCycle) error {
|
||||
return errors.Wrap(cloudprovider.ErrNotImplemented, "Renew")
|
||||
}
|
||||
|
||||
@@ -505,6 +505,7 @@ func (self *SHuaweiClient) GetCapabilities() []string {
|
||||
cloudprovider.CLOUD_CAPABILITY_EVENT,
|
||||
cloudprovider.CLOUD_CAPABILITY_CLOUDID,
|
||||
cloudprovider.CLOUD_CAPABILITY_SAML_AUTH,
|
||||
cloudprovider.CLOUD_CAPABILITY_NAT,
|
||||
}
|
||||
// huawei objectstore is shared across projects(subscriptions)
|
||||
// to avoid multiple project access the same bucket
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package multicloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
@@ -26,13 +26,17 @@ type SNatGatewayBase struct {
|
||||
}
|
||||
|
||||
func (nat *SNatGatewayBase) GetIEips() ([]cloudprovider.ICloudEIP, error) {
|
||||
return nil, fmt.Errorf("Not Implemented GetIEips")
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "GetIEips")
|
||||
}
|
||||
|
||||
func (nat *SNatGatewayBase) GetIDNatEntries() ([]cloudprovider.ICloudNatDEntry, error) {
|
||||
return nil, fmt.Errorf("Not Implemented GetINatDTable")
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "GetIDNatEntries")
|
||||
}
|
||||
|
||||
func (nat *SNatGatewayBase) GetISNatEntries() ([]cloudprovider.ICloudNatSEntry, error) {
|
||||
return nil, fmt.Errorf("Not Implemented GetINatSTable")
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "GetISNatEntries")
|
||||
}
|
||||
|
||||
func (nat *SNatGatewayBase) Delete() error {
|
||||
return errors.Wrapf(cloudprovider.ErrNotImplemented, "Delete")
|
||||
}
|
||||
|
||||
@@ -76,3 +76,7 @@ func (self *SVpc) GetExternalAccessMode() string {
|
||||
func (self *SVpc) AttachInternetGateway(igwId string) error {
|
||||
return errors.Wrap(cloudprovider.ErrNotSupported, "AttachInternetGateway")
|
||||
}
|
||||
|
||||
func (self *SVpc) CreateINatGateway(opts *cloudprovider.NatGatewayCreateOptions) (cloudprovider.ICloudNatGateway, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "CreateINatGateway")
|
||||
}
|
||||
|
||||
@@ -151,6 +151,7 @@ const (
|
||||
|
||||
ACT_VM_ASSOCIATE = "vm_associate"
|
||||
ACT_VM_DISSOCIATE = "vm_dissociate"
|
||||
ACT_NATGATEWAY_ASSOCIATE = "natgateway_associate"
|
||||
ACT_NATGATEWAY_DISSOCIATE = "natgateway_dissociate"
|
||||
ACT_LOADBALANCER_DISSOCIATE = "loadbalancer_dissociate"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user