支持natgateway同步

This commit is contained in:
ioito
2019-06-12 11:49:19 +08:00
parent 2541ebc16c
commit 0d31819208
53 changed files with 2324 additions and 135 deletions
+2 -1
View File
@@ -18,7 +18,8 @@ const (
EIP_MODE_INSTANCE_PUBLICIP = "public_ip"
EIP_MODE_STANDALONE_EIP = "elastic_ip"
EIP_ASSOCIATE_TYPE_SERVER = "server"
EIP_ASSOCIATE_TYPE_SERVER = "server"
EIP_ASSOCIATE_TYPE_NAT_GATEWAY = "natgateway"
EIP_STATUS_READY = "ready"
EIP_STATUS_UNKNOWN = "unknown"
+12
View File
@@ -0,0 +1,12 @@
package compute
const (
NAT_STAUTS_AVAILABLE = "available" //可用
NAT_STATUS_ALLOCATE = "allocate" //创建中
NAT_STATUS_DEPLOYING = "deploying" //配置中
NAT_STATUS_UNKNOWN = "unknown"
QCLOUD_NAT_SPEC_SMALL = "Small"
QCLOUD_NAT_SPEC_MIDDLE = "Middle"
QCLOUD_NAT_SPEC_LARGE = "Large"
)
+31
View File
@@ -393,6 +393,7 @@ type ICloudVpc interface {
Delete() error
GetIWireById(wireId string) (ICloudWire, error)
GetINatGateways() ([]ICloudNatGateway, error)
}
type ICloudWire interface {
@@ -615,3 +616,33 @@ type ICloudSku interface {
type ICloudProject interface {
ICloudResource
}
type ICloudNatGateway interface {
ICloudResource
IBillingResource
// 获取 NAT 规格
GetNatSpec() string
GetIEips() ([]ICloudEIP, error)
GetINatDTables() ([]ICloudNatDTable, error)
GetINatSTables() ([]ICloudNatSTable, error)
}
type ICloudNatDTable interface {
ICloudResource
GetIpProtocol() string
GetExternalIp() string
GetExternalPort() int
GetInternalIp() string
GetInternalPort() int
}
type ICloudNatSTable interface {
ICloudResource
GetIP() string
GetSourceCIDR() string
GetNetworkId() string
}
+1
View File
@@ -998,6 +998,7 @@ func (self *SCloudprovider) RealDelete(ctx context.Context, userCred mcclient.To
LoadbalancerManager,
LoadbalancerAclManager,
LoadbalancerCertificateManager,
NatGatewayManager,
VpcManager,
ElasticipManager,
CloudproviderRegionManager,
+79 -1
View File
@@ -198,7 +198,7 @@ func syncRegionVPCs(ctx context.Context, userCred mcclient.TokenCredential, sync
syncVpcWires(ctx, userCred, syncResults, provider, &localVpcs[j], remoteVpcs[j], syncRange)
syncVpcSecGroup(ctx, userCred, syncResults, provider, &localVpcs[j], remoteVpcs[j], syncRange)
syncVpcRouteTables(ctx, userCred, syncResults, provider, &localVpcs[j], remoteVpcs[j], syncRange)
syncVpcNatgateways(ctx, userCred, syncResults, provider, &localVpcs[j], remoteVpcs[j], syncRange)
}()
}
}
@@ -234,6 +234,84 @@ func syncVpcRouteTables(ctx context.Context, userCred mcclient.TokenCredential,
}
}
func syncVpcNatgateways(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localVpc *SVpc, remoteVpc cloudprovider.ICloudVpc, syncRange *SSyncRange) {
natGateways, err := remoteVpc.GetINatGateways()
if err != nil {
msg := fmt.Sprintf("GetINatGateways for vpc %s failed %s", remoteVpc.GetId(), err)
log.Errorf(msg)
return
}
localNatGateways, remoteNatGateways, result := NatGatewayManager.SyncNatGateways(ctx, userCred, provider, localVpc, natGateways)
syncResults.Add(NatGatewayManager, result)
msg := result.Result()
notes := fmt.Sprintf("SyncNatGateways for VPC %s result: %s", localVpc.Name, msg)
log.Infof(notes)
if result.IsError() {
return
}
for i := 0; i < len(localNatGateways); i++ {
func() {
lockman.LockObject(ctx, &localNatGateways[i])
defer lockman.ReleaseObject(ctx, &localNatGateways[i])
syncNatGatewayEips(ctx, userCred, provider, &localNatGateways[i], remoteNatGateways[i])
syncNatDtables(ctx, userCred, provider, &localNatGateways[i], remoteNatGateways[i])
syncNatStables(ctx, userCred, provider, &localNatGateways[i], remoteNatGateways[i])
}()
}
}
func syncNatGatewayEips(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, localNatGateway *SNatGateway, remoteNatGateway cloudprovider.ICloudNatGateway) {
eips, err := remoteNatGateway.GetIEips()
if err != nil {
msg := fmt.Sprintf("GetIEIPs for NatGateway %s failed %s", remoteNatGateway.GetName(), err)
log.Errorf(msg)
return
}
result := localNatGateway.SyncNatGatewayEips(ctx, userCred, provider, eips)
msg := result.Result()
log.Infof("SyncNatGatewayEips for NatGateway %s result: %s", localNatGateway.Name, msg)
if result.IsError() {
return
}
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, userCred)
}
func syncNatDtables(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, localNatGateway *SNatGateway, remoteNatGateway cloudprovider.ICloudNatGateway) {
dtables, err := remoteNatGateway.GetINatDTables()
if err != nil {
msg := fmt.Sprintf("GetINatDTables for NatGateway %s failed %s", remoteNatGateway.GetName(), err)
log.Errorf(msg)
return
}
result := NatDTableManager.SyncNatDTables(ctx, userCred, provider.GetOwnerId(), provider, localNatGateway, dtables)
msg := result.Result()
log.Infof("SyncNatDTables for NatGateway %s result: %s", localNatGateway.Name, msg)
if result.IsError() {
return
}
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, userCred)
}
func syncNatStables(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, localNatGateway *SNatGateway, remoteNatGateway cloudprovider.ICloudNatGateway) {
stables, err := remoteNatGateway.GetINatSTables()
if err != nil {
msg := fmt.Sprintf("GetINatSTables for NatGateway %s failed %s", remoteNatGateway.GetName(), err)
log.Errorf(msg)
return
}
result := NatSTableManager.SyncNatSTables(ctx, userCred, provider.GetOwnerId(), provider, localNatGateway, stables)
msg := result.Result()
log.Infof("SyncNatSTables for NatGateway %s result: %s", localNatGateway.Name, msg)
if result.IsError() {
return
}
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, userCred)
}
func syncVpcWires(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localVpc *SVpc, remoteVpc cloudprovider.ICloudVpc, syncRange *SSyncRange) {
wires, err := remoteVpc.GetIWires()
if err != nil {
+60 -5
View File
@@ -439,24 +439,49 @@ func (self *SElasticip) IsAssociated() bool {
if self.GetAssociateVM() != nil {
return true
}
if self.GetAssociateNatGateway() != nil {
return true
}
return false
}
func (self *SElasticip) GetAssociateVM() *SGuest {
if self.AssociateType == "server" && len(self.AssociateId) > 0 {
if self.AssociateType == api.EIP_ASSOCIATE_TYPE_SERVER && len(self.AssociateId) > 0 {
return GuestManager.FetchGuestById(self.AssociateId)
}
return nil
}
func (self *SElasticip) GetAssociateNatGateway() *SNatGateway {
if self.AssociateType == api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY && len(self.AssociateId) > 0 {
natGateway, err := NatGatewayManager.FetchById(self.AssociateId)
if err != nil {
return nil
}
return natGateway.(*SNatGateway)
}
return nil
}
func (self *SElasticip) Dissociate(ctx context.Context, userCred mcclient.TokenCredential) error {
if len(self.AssociateType) == 0 {
return nil
}
vm := self.GetAssociateVM()
if vm == nil {
log.Errorf("dissociate VM not exists???")
var vm *SGuest
var nat *SNatGateway
switch self.AssociateType {
case api.EIP_ASSOCIATE_TYPE_SERVER:
vm = self.GetAssociateVM()
if vm == nil {
log.Errorf("dissociate VM not exists???")
}
case api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY:
nat = self.GetAssociateNatGateway()
if nat == nil {
log.Errorf("dissociate Nat gateway not exists???")
}
}
_, err := db.Update(self, func() error {
self.AssociateId = ""
self.AssociateType = ""
@@ -470,6 +495,13 @@ func (self *SElasticip) Dissociate(ctx context.Context, userCred mcclient.TokenC
db.OpsLog.LogEvent(self, db.ACT_EIP_DETACH, vm.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(vm, db.ACT_EIP_DETACH, self.GetShortDesc(ctx), userCred)
}
if nat != nil {
db.OpsLog.LogDetachEvent(ctx, nat, self, userCred, self.GetShortDesc(ctx))
db.OpsLog.LogEvent(self, db.ACT_EIP_DETACH, nat.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(nat, db.ACT_EIP_DETACH, self.GetShortDesc(ctx), userCred)
}
if self.Mode == api.EIP_MODE_INSTANCE_PUBLICIP {
self.Delete(ctx, userCred)
}
@@ -484,7 +516,7 @@ func (self *SElasticip) AssociateVM(ctx context.Context, userCred mcclient.Token
return fmt.Errorf("EIP has been associated!!")
}
_, err := db.Update(self, func() error {
self.AssociateType = "server"
self.AssociateType = api.EIP_ASSOCIATE_TYPE_SERVER
self.AssociateId = vm.Id
return nil
})
@@ -499,6 +531,29 @@ func (self *SElasticip) AssociateVM(ctx context.Context, userCred mcclient.Token
return nil
}
func (self *SElasticip) AssociateNatGateway(ctx context.Context, userCred mcclient.TokenCredential, nat *SNatGateway) error {
if nat.Deleted {
return fmt.Errorf("nat gateway is deleted")
}
if len(self.AssociateType) > 0 {
return fmt.Errorf("Eip has been associated!!")
}
_, err := db.Update(self, func() error {
self.AssociateType = api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY
self.AssociateId = nat.Id
return nil
})
if err != nil {
return err
}
db.OpsLog.LogAttachEvent(ctx, nat, self, userCred, self.GetShortDesc(ctx))
db.OpsLog.LogEvent(self, db.ACT_EIP_ATTACH, nat.GetShortDesc(ctx), userCred)
db.OpsLog.LogEvent(nat, db.ACT_EIP_ATTACH, self.GetShortDesc(ctx), userCred)
return nil
}
func (manager *SElasticipManager) getEipByExtEip(ctx context.Context, userCred mcclient.TokenCredential, extEip cloudprovider.ICloudEIP, provider *SCloudprovider, region *SCloudregion, syncOwnerId mcclient.IIdentityProvider) (*SElasticip, error) {
eipObj, err := db.FetchByExternalId(manager, extEip.GetGlobalId())
if err == nil {
+250
View File
@@ -0,0 +1,250 @@
// 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"
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SNatDTableManager struct {
db.SStatusStandaloneResourceBaseManager
}
var NatDTableManager *SNatDTableManager
func init() {
NatDTableManager = &SNatDTableManager{
SStatusStandaloneResourceBaseManager: db.NewStatusStandaloneResourceBaseManager(
SNatDTable{},
"natdtables_tbl",
"natdtable",
"natdtables",
),
}
}
type SNatDTable struct {
db.SStatusStandaloneResourceBase
db.SExternalizedResourceBase
ExternalIP string `width:"17" charset:"ascii" list:"user" create:"required"`
ExternalPort int `list:"user" create:"required"`
InternalIP string `width:"17" charset:"ascii" list:"user" create:"required"`
InternalPort int `list:"user" create:"required"`
IpProtocol string `width:"8" charset:"ascii" list:"user" create:"required"`
NatgatewayId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
}
func (manager *SNatDTableManager) GetContextManagers() [][]db.IModelManager {
return [][]db.IModelManager{
{NatGatewayManager},
}
}
func (self *SNatDTableManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowList(userCred, self)
}
func (self *SNatDTableManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowCreate(userCred, self)
}
func (self *SNatDTable) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowGet(userCred, self)
}
func (self *SNatDTable) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
return db.IsAdminAllowUpdate(userCred, self)
}
func (self *SNatDTable) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowDelete(userCred, self)
}
func (self *SNatDTable) GetNatgateway() (*SNatGateway, error) {
_natgateway, err := NatGatewayManager.FetchById(self.NatgatewayId)
if err != nil {
return nil, err
}
return _natgateway.(*SNatGateway), nil
}
func (man *SNatDTableManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
q, err := man.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
if err != nil {
return nil, err
}
data := query.(*jsonutils.JSONDict)
q, err = validators.ApplyModelFilters(q, data, []*validators.ModelFilterOptions{
{Key: "natgateway", ModelKeyword: "natgateway", OwnerId: userCred},
})
if err != nil {
return nil, err
}
q, err = managedResourceFilterByAccount(q, query, "natgateway_id", func() *sqlchemy.SQuery {
natgateways := NatGatewayManager.Query().SubQuery()
return natgateways.Query(natgateways.Field("id"))
})
return q, nil
}
func (man *SNatDTableManager) 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 (manager *SNatDTableManager) SyncNatDTables(ctx context.Context, userCred mcclient.TokenCredential, syncOwnerId mcclient.IIdentityProvider, provider *SCloudprovider, nat *SNatGateway, extDtables []cloudprovider.ICloudNatDTable) compare.SyncResult {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, syncOwnerId))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, syncOwnerId))
result := compare.SyncResult{}
dbNatDTables, err := nat.GetDTables()
if err != nil {
result.Error(err)
return result
}
removed := make([]SNatDTable, 0)
commondb := make([]SNatDTable, 0)
commonext := make([]cloudprovider.ICloudNatDTable, 0)
added := make([]cloudprovider.ICloudNatDTable, 0)
if err := compare.CompareSets(dbNatDTables, extDtables, &removed, &commondb, &commonext, &added); err != nil {
result.Error(err)
return result
}
for i := 0; i < len(removed); i += 1 {
err := removed[i].syncRemoveCloudNatDTable(ctx, userCred)
if err != nil {
result.DeleteError(err)
} else {
result.Delete()
}
}
for i := 0; i < len(commondb); i += 1 {
err := commondb[i].SyncWithCloudNatDTable(ctx, userCred, commonext[i])
if err != nil {
result.UpdateError(err)
continue
}
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
result.Update()
}
for i := 0; i < len(added); i += 1 {
routeTableNew, err := manager.newFromCloudNatDTable(ctx, userCred, nat, added[i])
if err != nil {
result.AddError(err)
continue
}
syncMetadata(ctx, userCred, routeTableNew, added[i])
result.Add()
}
return result
}
func (self *SNatDTable) syncRemoveCloudNatDTable(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
err := self.ValidateDeleteCondition(ctx)
if err != nil { // cannot delete
return self.SetStatus(userCred, api.VPC_STATUS_UNKNOWN, "sync to delete")
}
return self.Delete(ctx, userCred)
}
func (self *SNatDTable) SyncWithCloudNatDTable(ctx context.Context, userCred mcclient.TokenCredential, extTable cloudprovider.ICloudNatDTable) error {
diff, err := db.UpdateWithLock(ctx, self, func() error {
self.Status = extTable.GetStatus()
self.ExternalIP = extTable.GetExternalIp()
self.ExternalPort = extTable.GetExternalPort()
self.InternalIP = extTable.GetInternalIp()
self.InternalPort = extTable.GetInternalPort()
self.IpProtocol = extTable.GetIpProtocol()
return nil
})
if err != nil {
return err
}
db.OpsLog.LogSyncUpdate(self, diff, userCred)
return nil
}
func (manager *SNatDTableManager) newFromCloudNatDTable(ctx context.Context, userCred mcclient.TokenCredential, nat *SNatGateway, extTable cloudprovider.ICloudNatDTable) (*SNatDTable, error) {
table := SNatDTable{}
table.SetModelManager(manager, &table)
newName, err := db.GenerateName(manager, manager.GetOwnerId(userCred), extTable.GetName())
if err != nil {
return nil, err
}
table.Name = newName
table.Status = extTable.GetStatus()
table.ExternalId = extTable.GetGlobalId()
table.IsEmulated = extTable.IsEmulated()
table.NatgatewayId = nat.Id
table.ExternalIP = extTable.GetExternalIp()
table.ExternalPort = extTable.GetExternalPort()
table.InternalIP = extTable.GetInternalIp()
table.InternalPort = extTable.GetInternalPort()
table.IpProtocol = extTable.GetIpProtocol()
err = manager.TableSpec().Insert(&table)
if err != nil {
log.Errorf("newFromCloudNatDTable fail %s", err)
return nil, err
}
db.OpsLog.LogEvent(&table, db.ACT_CREATE, table.GetShortDesc(ctx), userCred)
return &table, nil
}
func (self *SNatDTable) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
extra, err := self.SStatusStandaloneResourceBase.GetExtraDetails(ctx, userCred, query)
if err != nil {
return nil, err
}
return extra, nil
}
func (self *SNatDTable) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SStatusStandaloneResourceBase.GetCustomizeColumns(ctx, userCred, query)
natgateway, err := self.GetNatgateway()
if err != nil {
log.Errorf("failed to get naggateway %s for dtable %s(%s) error: %v", self.NatgatewayId, self.Name, self.Id, err)
return extra
}
extra.Add(jsonutils.NewString(natgateway.Name), "natgateway")
return extra
}
+365
View File
@@ -0,0 +1,365 @@
// 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"
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SNatGetewayManager struct {
db.SStatusStandaloneResourceBaseManager
}
var NatGatewayManager *SNatGetewayManager
func init() {
NatGatewayManager = &SNatGetewayManager{
SStatusStandaloneResourceBaseManager: db.NewStatusStandaloneResourceBaseManager(
SNatGateway{},
"natgateways_tbl",
"natgateway",
"natgateways",
),
}
}
type SNatGateway struct {
db.SStatusStandaloneResourceBase
db.SExternalizedResourceBase
SManagedResourceBase
SCloudregionResourceBase
SBillingResourceBase
VpcId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"optional"`
NatSpec string `list:"user" get:"user" list:"user" create:"optional"` // NAT规格
}
func (manager *SNatGetewayManager) GetContextManagers() [][]db.IModelManager {
return [][]db.IModelManager{
{CloudregionManager},
}
}
func (self *SNatGetewayManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowList(userCred, self)
}
func (self *SNatGetewayManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowCreate(userCred, self)
}
func (self *SNatGateway) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowGet(userCred, self)
}
func (self *SNatGateway) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
return db.IsAdminAllowUpdate(userCred, self)
}
func (self *SNatGateway) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowDelete(userCred, self)
}
func (man *SNatGetewayManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
q, err := man.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
if err != nil {
return nil, err
}
data := query.(*jsonutils.JSONDict)
q, err = validators.ApplyModelFilters(q, data, []*validators.ModelFilterOptions{
{Key: "vpc", ModelKeyword: "vpc", OwnerId: userCred},
{Key: "cloudregion", ModelKeyword: "cloudregion", OwnerId: userCred},
})
if err != nil {
return nil, err
}
q, err = managedResourceFilterByAccount(q, query, "", nil)
if err != nil {
return nil, err
}
return q, nil
}
func (man *SNatGetewayManager) 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 (self *SNatGateway) GetVpc() (*SVpc, error) {
_vpc, err := VpcManager.FetchById(self.VpcId)
if err != nil {
return nil, err
}
return _vpc.(*SVpc), nil
}
func (manager *SNatGetewayManager) getNatgatewaysByProviderId(providerId string) ([]SNatGateway, error) {
nats := []SNatGateway{}
err := fetchByManagerId(manager, providerId, &nats)
if err != nil {
return nil, err
}
return nats, nil
}
func (self *SNatGateway) GetDTables() ([]SNatDTable, error) {
tables := []SNatDTable{}
q := NatDTableManager.Query().Equals("natgateway_id", self.Id)
err := db.FetchModelObjects(NatDTableManager, q, &tables)
if err != nil {
return nil, err
}
return tables, nil
}
func (self *SNatGateway) GetSTables() ([]SNatSTable, error) {
tables := []SNatSTable{}
q := NatSTableManager.Query().Equals("natgateway_id", self.Id)
err := db.FetchModelObjects(NatSTableManager, q, &tables)
if err != nil {
return nil, err
}
return tables, nil
}
func (self *SNatGateway) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
extra, err := self.SStatusStandaloneResourceBase.GetExtraDetails(ctx, userCred, query)
if err != nil {
return nil, err
}
return extra, nil
}
func (self *SNatGateway) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SStatusStandaloneResourceBase.GetCustomizeColumns(ctx, userCred, query)
accountInfo := self.SManagedResourceBase.GetCustomizeColumns(ctx, userCred, query)
if accountInfo != nil {
extra.Update(accountInfo)
}
regionInfo := self.SCloudregionResourceBase.GetCustomizeColumns(ctx, userCred, query)
if regionInfo != nil {
extra.Update(regionInfo)
}
vpc, err := self.GetVpc()
if err != nil {
log.Errorf("failed to found vpc info for nat gateway %s(%s) error: %v", self.Name, self.Id, err)
return extra
}
extra.Add(jsonutils.NewString(vpc.Name), "vpc")
return extra
}
func (manager *SNatGetewayManager) SyncNatGateways(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, vpc *SVpc, cloudNatGateways []cloudprovider.ICloudNatGateway) ([]SNatGateway, []cloudprovider.ICloudNatGateway, compare.SyncResult) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, provider.GetOwnerId()))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, provider.GetOwnerId()))
localNatGateways := make([]SNatGateway, 0)
remoteNatGateways := make([]cloudprovider.ICloudNatGateway, 0)
syncResult := compare.SyncResult{}
dbNatGateways, err := vpc.GetNatgateways()
if err != nil {
syncResult.Error(err)
return nil, nil, syncResult
}
removed := make([]SNatGateway, 0)
commondb := make([]SNatGateway, 0)
commonext := make([]cloudprovider.ICloudNatGateway, 0)
added := make([]cloudprovider.ICloudNatGateway, 0)
if err := compare.CompareSets(dbNatGateways, cloudNatGateways, &removed, &commondb, &commonext, &added); err != nil {
syncResult.Error(err)
return nil, nil, syncResult
}
for i := 0; i < len(removed); i += 1 {
err := removed[i].syncRemoveCloudNatGateway(ctx, userCred)
if err != nil {
syncResult.DeleteError(err)
} else {
syncResult.Delete()
}
}
for i := 0; i < len(commondb); i += 1 {
err := commondb[i].SyncWithCloudNatGateway(ctx, userCred, provider, commonext[i])
if err != nil {
syncResult.UpdateError(err)
continue
}
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
localNatGateways = append(localNatGateways, commondb[i])
remoteNatGateways = append(remoteNatGateways, commonext[i])
syncResult.Update()
}
for i := 0; i < len(added); i += 1 {
routeTableNew, err := manager.newFromCloudNatGateway(ctx, userCred, provider, vpc, added[i])
if err != nil {
syncResult.AddError(err)
continue
}
syncMetadata(ctx, userCred, routeTableNew, added[i])
localNatGateways = append(localNatGateways, *routeTableNew)
remoteNatGateways = append(remoteNatGateways, added[i])
syncResult.Add()
}
return localNatGateways, remoteNatGateways, syncResult
}
func (self *SNatGateway) syncRemoveCloudNatGateway(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
err := self.ValidateDeleteCondition(ctx)
if err != nil { // cannot delete
return self.SetStatus(userCred, api.VPC_STATUS_UNKNOWN, "sync to delete")
}
return self.Delete(ctx, userCred)
}
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()
self.NatSpec = extNat.GetNatSpec()
factory, _ := provider.GetProviderFactory()
if factory.IsSupportPrepaidResources() {
self.BillingType = extNat.GetBillingType()
self.ExpiredAt = extNat.GetExpiredAt()
}
return nil
})
if err != nil {
return err
}
db.OpsLog.LogSyncUpdate(self, diff, userCred)
return nil
}
func (manager *SNatGetewayManager) newFromCloudNatGateway(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, vpc *SVpc, extNat cloudprovider.ICloudNatGateway) (*SNatGateway, error) {
nat := SNatGateway{}
nat.SetModelManager(manager, &nat)
region, err := vpc.GetRegion()
if err != nil {
return nil, err
}
newName, err := db.GenerateName(manager, manager.GetOwnerId(userCred), extNat.GetName())
if err != nil {
return nil, err
}
nat.Name = newName
nat.VpcId = vpc.Id
nat.Status = extNat.GetStatus()
nat.NatSpec = extNat.GetNatSpec()
if createdAt := extNat.GetCreatedAt(); !createdAt.IsZero() {
nat.CreatedAt = extNat.GetCreatedAt()
}
nat.ExternalId = extNat.GetGlobalId()
nat.CloudregionId = region.Id
nat.ManagerId = provider.Id
nat.IsEmulated = extNat.IsEmulated()
factory, _ := provider.GetProviderFactory()
if factory.IsSupportPrepaidResources() {
nat.BillingType = extNat.GetBillingType()
nat.ExpiredAt = extNat.GetExpiredAt()
}
err = manager.TableSpec().Insert(&nat)
if err != nil {
log.Errorf("newFromCloudNatGateway fail %s", err)
return nil, err
}
db.OpsLog.LogEvent(&nat, db.ACT_CREATE, nat.GetShortDesc(ctx), userCred)
return &nat, 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
}
return eips, nil
}
func (self *SNatGateway) SyncNatGatewayEips(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extEips []cloudprovider.ICloudEIP) compare.SyncResult {
result := compare.SyncResult{}
dbEips, err := self.GetEips()
if err != nil {
result.AddError(err)
return result
}
removed := make([]SElasticip, 0)
commondb := make([]SElasticip, 0)
commonext := make([]cloudprovider.ICloudEIP, 0)
added := make([]cloudprovider.ICloudEIP, 0)
if err := compare.CompareSets(dbEips, extEips, &removed, &commondb, &commonext, &added); err != nil {
result.Error(err)
return result
}
for i := 0; i < len(removed); i += 1 {
err := removed[i].Dissociate(ctx, userCred)
if err != nil {
result.AddError(err)
} else {
result.Delete()
}
}
for i := 0; i < len(added); i += 1 {
neip, err := ElasticipManager.getEipByExtEip(ctx, userCred, added[i], provider, self.GetRegion(), provider.GetOwnerId())
if err != nil {
result.AddError(err)
continue
}
if len(neip.AssociateId) > 0 && neip.AssociateId != self.Id {
err = neip.Dissociate(ctx, userCred)
if err != nil {
result.AddError(err)
continue
}
}
err = neip.AssociateNatGateway(ctx, userCred, self)
if err != nil {
result.AddError(err)
} else {
result.Add()
}
}
return result
}
+271
View File
@@ -0,0 +1,271 @@
// 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"
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SNatSTableManager struct {
db.SStatusStandaloneResourceBaseManager
}
var NatSTableManager *SNatSTableManager
func init() {
NatSTableManager = &SNatSTableManager{
SStatusStandaloneResourceBaseManager: db.NewStatusStandaloneResourceBaseManager(
SNatSTable{},
"natstables_tbl",
"natstable",
"natstables",
),
}
}
type SNatSTable struct {
db.SStatusStandaloneResourceBase
db.SExternalizedResourceBase
IP string `width:"17" charset:"ascii" list:"user" create:"required"`
SourceCIDR string `width:"22" charset:"ascii" list:"user" create:"required"`
NetworkId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"optional"`
NatgatewayId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
}
func (manager *SNatSTableManager) GetContextManagers() [][]db.IModelManager {
return [][]db.IModelManager{
{NatGatewayManager},
}
}
func (self *SNatSTableManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowList(userCred, self)
}
func (self *SNatSTableManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowCreate(userCred, self)
}
func (self *SNatSTable) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowGet(userCred, self)
}
func (self *SNatSTable) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
return db.IsAdminAllowUpdate(userCred, self)
}
func (self *SNatSTable) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowDelete(userCred, self)
}
func (self *SNatSTable) GetNatgateway() (*SNatGateway, error) {
_natgateway, err := NatGatewayManager.FetchById(self.NatgatewayId)
if err != nil {
return nil, err
}
return _natgateway.(*SNatGateway), nil
}
func (self *SNatSTable) GetNetwork() (*SNetwork, error) {
_network, err := NetworkManager.FetchById(self.NatgatewayId)
if err != nil {
return nil, err
}
return _network.(*SNetwork), nil
}
func (man *SNatSTableManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
q, err := man.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
if err != nil {
return nil, err
}
data := query.(*jsonutils.JSONDict)
q, err = validators.ApplyModelFilters(q, data, []*validators.ModelFilterOptions{
{Key: "network", ModelKeyword: "network", OwnerId: userCred},
{Key: "natgateway", ModelKeyword: "natgateway", OwnerId: userCred},
})
if err != nil {
return nil, err
}
q, err = managedResourceFilterByAccount(q, query, "natgateway_id", func() *sqlchemy.SQuery {
natgateways := NatGatewayManager.Query().SubQuery()
return natgateways.Query(natgateways.Field("id"))
})
return q, nil
}
func (man *SNatSTableManager) 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 (manager *SNatSTableManager) SyncNatSTables(ctx context.Context, userCred mcclient.TokenCredential, syncOwnerId mcclient.IIdentityProvider, provider *SCloudprovider, nat *SNatGateway, extTables []cloudprovider.ICloudNatSTable) compare.SyncResult {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, syncOwnerId))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, syncOwnerId))
result := compare.SyncResult{}
dbNatSTables, err := nat.GetSTables()
if err != nil {
result.Error(err)
return result
}
removed := make([]SNatSTable, 0)
commondb := make([]SNatSTable, 0)
commonext := make([]cloudprovider.ICloudNatSTable, 0)
added := make([]cloudprovider.ICloudNatSTable, 0)
if err := compare.CompareSets(dbNatSTables, extTables, &removed, &commondb, &commonext, &added); err != nil {
result.Error(err)
return result
}
for i := 0; i < len(removed); i += 1 {
err := removed[i].syncRemoveCloudNatSTable(ctx, userCred)
if err != nil {
result.DeleteError(err)
} else {
result.Delete()
}
}
for i := 0; i < len(commondb); i += 1 {
err := commondb[i].SyncWithCloudNatSTable(ctx, userCred, commonext[i])
if err != nil {
result.UpdateError(err)
continue
}
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
result.Update()
}
for i := 0; i < len(added); i += 1 {
routeTableNew, err := manager.newFromCloudNatSTable(ctx, userCred, nat, added[i])
if err != nil {
result.AddError(err)
continue
}
syncMetadata(ctx, userCred, routeTableNew, added[i])
result.Add()
}
return result
}
func (self *SNatSTable) syncRemoveCloudNatSTable(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
err := self.ValidateDeleteCondition(ctx)
if err != nil { // cannot delete
return self.SetStatus(userCred, api.VPC_STATUS_UNKNOWN, "sync to delete")
}
return self.Delete(ctx, userCred)
}
func (self *SNatSTable) SyncWithCloudNatSTable(ctx context.Context, userCred mcclient.TokenCredential, extTable cloudprovider.ICloudNatSTable) error {
diff, err := db.UpdateWithLock(ctx, self, func() error {
self.Status = extTable.GetStatus()
self.IP = extTable.GetIP()
self.SourceCIDR = extTable.GetSourceCIDR()
if extNetworkId := extTable.GetNetworkId(); len(extNetworkId) > 0 {
network, err := db.FetchByExternalId(NetworkManager, extNetworkId)
if err != nil {
return err
}
self.NetworkId = network.GetId()
}
return nil
})
if err != nil {
return err
}
db.OpsLog.LogSyncUpdate(self, diff, userCred)
return nil
}
func (manager *SNatSTableManager) newFromCloudNatSTable(ctx context.Context, userCred mcclient.TokenCredential, nat *SNatGateway, extTable cloudprovider.ICloudNatSTable) (*SNatSTable, error) {
table := SNatSTable{}
table.SetModelManager(manager, &table)
newName, err := db.GenerateName(manager, manager.GetOwnerId(userCred), extTable.GetName())
if err != nil {
return nil, err
}
table.Name = newName
table.Status = extTable.GetStatus()
table.ExternalId = extTable.GetGlobalId()
table.IsEmulated = extTable.IsEmulated()
table.NatgatewayId = nat.Id
table.IP = extTable.GetIP()
table.SourceCIDR = extTable.GetSourceCIDR()
if extNetworkId := extTable.GetNetworkId(); len(extNetworkId) > 0 {
network, err := db.FetchByExternalId(NetworkManager, extNetworkId)
if err != nil {
return nil, err
}
table.NetworkId = network.GetId()
}
err = manager.TableSpec().Insert(&table)
if err != nil {
log.Errorf("newFromCloudNatSTable fail %s", err)
return nil, err
}
db.OpsLog.LogEvent(&table, db.ACT_CREATE, table.GetShortDesc(ctx), userCred)
return &table, nil
}
func (self *SNatSTable) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
extra, err := self.SStatusStandaloneResourceBase.GetExtraDetails(ctx, userCred, query)
if err != nil {
return nil, err
}
return extra, nil
}
func (self *SNatSTable) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SStatusStandaloneResourceBase.GetCustomizeColumns(ctx, userCred, query)
natgateway, err := self.GetNatgateway()
if err != nil {
log.Errorf("failed to get naggateway %s for stable %s(%s) error: %v", self.NatgatewayId, self.Name, self.Id, err)
return extra
}
extra.Add(jsonutils.NewString(natgateway.Name), "natgateway")
network, err := self.GetNetwork()
if err != nil {
log.Errorf("failed to get network %s for stable %s(%s) error: %v", self.NetworkId, self.Name, self.Id, err)
return extra
}
extra.Add(jsonutils.NewString(network.Name), "network")
return extra
}
+90
View File
@@ -830,3 +830,93 @@ func (manager *SCloudregionManager) purgeAll(ctx context.Context, userCred mccli
}
return nil
}
func (table *SNatSTable) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, table)
defer lockman.ReleaseObject(ctx, table)
err := table.ValidateDeleteCondition(ctx)
if err != nil {
return err
}
return table.Delete(ctx, userCred)
}
func (nat *SNatGateway) purgeSTables(ctx context.Context, userCred mcclient.TokenCredential) error {
tables, err := nat.GetSTables()
if err != nil {
return err
}
for i := range tables {
err = tables[i].purge(ctx, userCred)
if err != nil {
return err
}
}
return nil
}
func (table *SNatDTable) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, table)
defer lockman.ReleaseObject(ctx, table)
err := table.ValidateDeleteCondition(ctx)
if err != nil {
return err
}
return table.Delete(ctx, userCred)
}
func (nat *SNatGateway) purgeDTables(ctx context.Context, userCred mcclient.TokenCredential) error {
tables, err := nat.GetDTables()
if err != nil {
return err
}
for i := range tables {
err = tables[i].purge(ctx, userCred)
if err != nil {
return err
}
}
return nil
}
func (nat *SNatGateway) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, nat)
defer lockman.ReleaseObject(ctx, nat)
err := nat.purgeDTables(ctx, userCred)
if err != nil {
return err
}
err = nat.purgeSTables(ctx, userCred)
if err != nil {
return err
}
err = nat.ValidateDeleteCondition(ctx)
if err != nil {
return err
}
return nat.Delete(ctx, userCred)
}
func (manager *SNatGetewayManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
nats, err := manager.getNatgatewaysByProviderId(providerId)
if err != nil {
return err
}
for i := range nats {
err = nats[i].purge(ctx, userCred)
if err != nil {
return err
}
}
return nil
}
+27 -1
View File
@@ -108,13 +108,37 @@ func (self *SVpc) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCr
return self.SEnabledStatusStandaloneResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
}
func (self *SVpc) getNatgatewayQuery() *sqlchemy.SQuery {
return NatGatewayManager.Query().Equals("vpc_id", self.Id)
}
func (self *SVpc) GetNatgatewayCount() (int, error) {
return self.getNatgatewayQuery().CountWithError()
}
func (self *SVpc) GetNatgateways() ([]SNatGateway, error) {
nats := []SNatGateway{}
err := db.FetchModelObjects(NatGatewayManager, self.getNatgatewayQuery(), &nats)
if err != nil {
return nil, err
}
return nats, nil
}
func (self *SVpc) ValidateDeleteCondition(ctx context.Context) error {
cnt, err := self.GetNetworkCount()
if err != nil {
return httperrors.NewInternalServerError("GetNetworkCount fail %s", err)
}
if cnt > 0 {
return httperrors.NewNotEmptyError("VPC not empty")
return httperrors.NewNotEmptyError("VPC not empty, please delete network first")
}
cnt, err = self.GetNatgatewayCount()
if err != nil {
return httperrors.NewInternalServerError("GetNatgatewayCount fail %v", err)
}
if cnt > 0 {
return httperrors.NewNotEmptyError("VPC not empty, please delete nat gateway first")
}
if self.Id == api.DEFAULT_VPC_ID {
return httperrors.NewProtectedResourceError("not allow to delete default vpc")
@@ -183,6 +207,8 @@ func (self *SVpc) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict
extra.Add(jsonutils.NewInt(int64(cnt)), "network_count")
cnt, _ = self.GetRouteTableCount()
extra.Add(jsonutils.NewInt(int64(cnt)), "routetable_count")
cnt, _ = self.GetNatgatewayCount()
extra.Add(jsonutils.NewInt(int64(cnt)), "natgateway_count")
/* region, err := self.GetRegion()
if err != nil {
log.Errorf("failed getting region for vpc %s(%s)", self.Name, self.Id)
+3
View File
@@ -81,6 +81,9 @@ func InitHandlers(app *appsrv.Application) {
// models.VCenterManager,
models.DnsRecordManager,
models.ElasticipManager,
models.NatGatewayManager,
models.NatDTableManager,
models.NatSTableManager,
models.SnapshotManager,
models.SnapshotPolicyManager,
models.BaremetalagentManager,
+27
View File
@@ -0,0 +1,27 @@
// 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
var (
NatDTables ResourceManager
)
func init() {
NatDTables = NewComputeManager("natdtable", "natdtables",
[]string{"ID", "Name", "Status", "Natgateway_Id", "Natgateway", "External_IP", "External_Port", "Internal_IP", "Internal_Port", "Ip_Protocol"},
[]string{})
registerCompute(&NatDTables)
}
+27
View File
@@ -0,0 +1,27 @@
// 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
var (
NatGateways ResourceManager
)
func init() {
NatGateways = NewComputeManager("natgateway", "natgateways",
[]string{"ID", "Name", "Enabled", "Status", "Cloudregion_Id", "Region", "Vpc_Id", "Charge_Type", "Nat_Spec"},
[]string{})
registerCompute(&NatGateways)
}
+27
View File
@@ -0,0 +1,27 @@
// 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
var (
NatSTables ResourceManager
)
func init() {
NatSTables = NewComputeManager("natstable", "natstables",
[]string{"ID", "Name", "Status", "IP", "Natgateway_Id", "Natgateway", "Network", "Network_Id", "Source_CIDR"},
[]string{})
registerCompute(&NatSTables)
}
+35
View File
@@ -0,0 +1,35 @@
// 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 options
type NatGatewayListOptions struct {
Vpc string `help:"vpc id or name"`
Cloudregion string `help:"cloudreigon id or name"`
BaseListOptions
}
type NatDTableListOptions struct {
Natgateway string `help:"Natgateway name or id"`
BaseListOptions
}
type NatSTableListOptions struct {
Natgateway string `help:"Natgateway name or id"`
Network string `help:"Network id or name"`
BaseListOptions
}
+17
View File
@@ -0,0 +1,17 @@
package multicloud
import "time"
type SBillingBase struct{}
func (self *SBillingBase) GetBillingType() string {
return ""
}
func (self *SBillingBase) GetCreatedAt() time.Time {
return time.Time{}
}
func (self *SBillingBase) GetExpiredAt() time.Time {
return time.Time{}
}
+24
View File
@@ -0,0 +1,24 @@
package multicloud
import (
"fmt"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SNatGatewayBase struct {
SResourceBase
SBillingBase
}
func (nat *SNatGatewayBase) GetIEips() ([]cloudprovider.ICloudEIP, error) {
return nil, fmt.Errorf("Not Implemented GetIEips")
}
func (nat *SNatGatewayBase) GetINatDTables() ([]cloudprovider.ICloudNatDTable, error) {
return nil, fmt.Errorf("Not Implemented GetINatDTables")
}
func (nat *SNatGatewayBase) GetINatSTables() ([]cloudprovider.ICloudNatSTable, error) {
return nil, fmt.Errorf("Not Implemented GetINatSTables")
}
+17
View File
@@ -0,0 +1,17 @@
package multicloud
import "yunion.io/x/jsonutils"
type SResourceBase struct{}
func (self *SResourceBase) IsEmulated() bool {
return false
}
func (self *SResourceBase) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SResourceBase) Refresh() error {
return nil
}
+15
View File
@@ -0,0 +1,15 @@
package multicloud
import (
"fmt"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SVpc struct {
SResourceBase
}
func (self *SVpc) GetINatGateways() ([]cloudprovider.ICloudNatGateway, error) {
return nil, fmt.Errorf("Not Implemented GetNatGateways")
}
+25 -3
View File
@@ -16,6 +16,7 @@ package aliyun
import (
"fmt"
"strings"
"time"
"yunion.io/x/jsonutils"
@@ -151,7 +152,9 @@ func (self *SEipAddress) GetMode() string {
func (self *SEipAddress) GetAssociationType() string {
switch self.InstanceType {
case EIP_INSTANCE_TYPE_ECS:
return "server"
return api.EIP_ASSOCIATE_TYPE_SERVER
case EIP_INSTANCE_TYPE_NAT:
return api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY
default:
log.Fatalf("unsupported type: %s", self.InstanceType)
return "unsupported"
@@ -219,7 +222,7 @@ func (self *SEipAddress) ChangeBandwidth(bw int) error {
return self.region.UpdateEipBandwidth(self.AllocationId, bw)
}
func (region *SRegion) GetEips(eipId string, offset int, limit int) ([]SEipAddress, int, error) {
func (region *SRegion) GetEips(eipId string, associatedId string, offset int, limit int) ([]SEipAddress, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
}
@@ -233,6 +236,15 @@ func (region *SRegion) GetEips(eipId string, offset int, limit int) ([]SEipAddre
params["AllocationId"] = eipId
}
if len(associatedId) > 0 {
params["AssociatedInstanceId"] = associatedId
for prefix, instanceType := range map[string]string{"i-": "EcsInstance", "ngw-": "Nat", "lb-": "SlbInstance"} {
if strings.HasPrefix(associatedId, prefix) {
params["AssociatedInstanceType"] = instanceType
}
}
}
body, err := region.ecsRequest("DescribeEipAddresses", params)
if err != nil {
log.Errorf("DescribeEipAddresses fail %s", err)
@@ -253,7 +265,7 @@ func (region *SRegion) GetEips(eipId string, offset int, limit int) ([]SEipAddre
}
func (region *SRegion) GetEip(eipId string) (*SEipAddress, error) {
eips, total, err := region.GetEips(eipId, 0, 1)
eips, total, err := region.GetEips(eipId, "", 0, 1)
if err != nil {
return nil, err
}
@@ -312,6 +324,11 @@ func (region *SRegion) AssociateEip(eipId string, instanceId string) error {
params := make(map[string]string)
params["AllocationId"] = eipId
params["InstanceId"] = instanceId
for prefix, instanceType := range map[string]string{"i-": "EcsInstance", "lb-": "SlbInstance", "ngw-": "Nat"} {
if strings.HasPrefix(instanceId, prefix) {
params["InstanceType"] = instanceType
}
}
_, err := region.ecsRequest("AssociateEipAddress", params)
if err != nil {
@@ -324,6 +341,11 @@ func (region *SRegion) DissociateEip(eipId string, instanceId string) error {
params := make(map[string]string)
params["AllocationId"] = eipId
params["InstanceId"] = instanceId
for prefix, instanceType := range map[string]string{"i-": "EcsInstance", "lb-": "SlbInstance", "ngw-": "Nat"} {
if strings.HasPrefix(instanceId, prefix) {
params["InstanceType"] = instanceType
}
}
_, err := region.ecsRequest("UnassociateEipAddress", params)
if err != nil {
+109
View File
@@ -0,0 +1,109 @@
package aliyun
import (
"fmt"
"strconv"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SForwardTableEntry struct {
multicloud.SResourceBase
nat *SNatGetway
ForwardEntryId string
ForwardEntryName string
IpProtocol string
Status string
ExternalIp string
ForwardTableId string
ExternalPort string
InternalPort string
InternalIp string
}
func (dtable *SForwardTableEntry) GetName() string {
if len(dtable.ForwardEntryName) > 0 {
return dtable.ForwardEntryName
}
return dtable.ForwardEntryId
}
func (dtable *SForwardTableEntry) GetId() string {
return dtable.ForwardEntryId
}
func (dtable *SForwardTableEntry) GetGlobalId() string {
return dtable.ForwardEntryId
}
func (dtable *SForwardTableEntry) GetStatus() string {
switch dtable.Status {
case "Available":
return api.NAT_STAUTS_AVAILABLE
default:
return api.NAT_STATUS_UNKNOWN
}
}
func (dtable *SForwardTableEntry) GetIpProtocol() string {
return dtable.IpProtocol
}
func (dtable *SForwardTableEntry) GetExternalIp() string {
return dtable.ExternalIp
}
func (dtable *SForwardTableEntry) GetExternalPort() int {
port, _ := strconv.Atoi(dtable.ExternalPort)
return port
}
func (dtable *SForwardTableEntry) GetInternalIp() string {
return dtable.InternalIp
}
func (dtable *SForwardTableEntry) GetInternalPort() int {
port, _ := strconv.Atoi(dtable.InternalPort)
return port
}
func (region *SRegion) GetAllDTables(tableId string) ([]SForwardTableEntry, error) {
dtables := []SForwardTableEntry{}
for {
part, total, err := region.GetForwardTableEntries(tableId, len(dtables), 50)
if err != nil {
return nil, err
}
dtables = append(dtables, part...)
if len(dtables) >= total {
break
}
}
return dtables, nil
}
func (region *SRegion) GetForwardTableEntries(tableId string, offset int, limit int) ([]SForwardTableEntry, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
}
params := make(map[string]string)
params["RegionId"] = region.RegionId
params["PageSize"] = fmt.Sprintf("%d", limit)
params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
params["ForwardTableId"] = tableId
body, err := region.vpcRequest("DescribeForwardTableEntries", params)
if err != nil {
return nil, 0, err
}
dtables := []SForwardTableEntry{}
err = body.Unmarshal(&dtables, "ForwardTableEntries", "ForwardTableEntry")
if err != nil {
return nil, 0, err
}
total, _ := body.Int("TotalCount")
return dtables, int(total), nil
}
+101 -94
View File
@@ -18,7 +18,11 @@ import (
"fmt"
"time"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/compute"
)
type SBandwidthPackageIds struct {
@@ -34,15 +38,18 @@ type SSnatTableIds struct {
}
type SNatGetway struct {
multicloud.SNatGatewayBase
vpc *SVpc
BandwidthPackageIds SBandwidthPackageIds
BusinessStatus string
CreationTime time.Time
ExpiredTime time.Time
Description string
ForwardTableIds SForwardTableIds
SnatTableIds SSnatTableIds
InstanceChargeType string
InstanceChargeType TChargeType
Name string
NatGatewayId string
RegionId string
@@ -51,6 +58,99 @@ type SNatGetway struct {
VpcId string
}
func (nat *SNatGetway) GetId() string {
return nat.NatGatewayId
}
func (nat *SNatGetway) GetGlobalId() string {
return nat.NatGatewayId
}
func (nat *SNatGetway) GetName() string {
if len(nat.Name) > 0 {
return nat.Name
}
return nat.NatGatewayId
}
func (nat *SNatGetway) GetStatus() string {
switch nat.Status {
case "Initiating":
return api.NAT_STATUS_ALLOCATE
case "Available":
return api.NAT_STAUTS_AVAILABLE
case "Pending":
return api.NAT_STATUS_DEPLOYING
default:
return api.NAT_STATUS_UNKNOWN
}
}
func (nat *SNatGetway) GetBillingType() string {
return convertChargeType(nat.InstanceChargeType)
}
func (nat *SNatGetway) GetNatSpec() string {
return nat.Spec
}
func (nat *SNatGetway) GetCreatedAt() time.Time {
return nat.CreationTime
}
func (nat *SNatGetway) GetExpiredAt() time.Time {
return nat.ExpiredTime
}
func (nat *SNatGetway) GetIEips() ([]cloudprovider.ICloudEIP, error) {
eips := []SEipAddress{}
for {
parts, total, err := nat.vpc.region.GetEips("", nat.NatGatewayId, len(eips), 50)
if err != nil {
return nil, err
}
eips = append(eips, parts...)
if len(eips) >= total {
break
}
}
ieips := []cloudprovider.ICloudEIP{}
for i := 0; i < len(eips); i++ {
eips[i].region = nat.vpc.region
ieips = append(ieips, &eips[i])
}
return ieips, nil
}
func (nat *SNatGetway) GetINatDTables() ([]cloudprovider.ICloudNatDTable, error) {
itables := []cloudprovider.ICloudNatDTable{}
for _, dtableId := range nat.ForwardTableIds.ForwardTableId {
dtables, err := nat.vpc.region.GetAllDTables(dtableId)
if err != nil {
return nil, err
}
for i := 0; i < len(dtables); i++ {
dtables[i].nat = nat
itables = append(itables, &dtables[i])
}
}
return itables, nil
}
func (nat *SNatGetway) GetINatSTables() ([]cloudprovider.ICloudNatSTable, error) {
stables, err := nat.getSnatEntries()
if err != nil {
return nil, err
}
itables := []cloudprovider.ICloudNatSTable{}
for i := 0; i < len(stables); i++ {
stables[i].nat = nat
itables = append(itables, &stables[i])
}
return itables, nil
}
func (self *SRegion) GetNatGateways(vpcId string, natGwId string, offset, limit int) ([]SNatGetway, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
@@ -85,96 +185,3 @@ func (self *SRegion) GetNatGateways(vpcId string, natGwId string, offset, limit
total, _ := body.Int("TotalCount")
return gateways, int(total), nil
}
type SSNATTableEntry struct {
SnatEntryId string
SnatIp string
SnatTableId string `json:"snat_table_id"`
SourceCIDR string `json:"source_cidr"`
SourceVSwitchId string `json:"source_vswitch_id"`
Status string
}
func (self *SRegion) GetSNATEntries(tableId string, offset, limit int) ([]SSNATTableEntry, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
}
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["PageSize"] = fmt.Sprintf("%d", limit)
params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
params["SnatTableId"] = tableId
body, err := self.vpcRequest("DescribeSnatTableEntries", params)
if err != nil {
log.Errorf("DescribeSnatTableEntries fail %s", err)
return nil, 0, err
}
if self.client.Debug {
log.Debugf("%s", body.PrettyString())
}
entries := make([]SSNATTableEntry, 0)
err = body.Unmarshal(&entries, "SnatTableEntries", "SnatTableEntry")
if err != nil {
log.Errorf("Unmarshal entries fail %s", err)
return nil, 0, err
}
total, _ := body.Int("TotalCount")
return entries, int(total), nil
}
func (region *SRegion) DeleteSnatEntry(tableId string, entryId string) error {
params := make(map[string]string)
params["RegionId"] = region.RegionId
params["SnatTableId"] = tableId
params["SnatEntryId"] = entryId
_, err := region.vpcRequest("DeleteSnatEntry", params)
return err
}
func (nat *SNatGetway) getSnatEntriesForTable(tblId string) ([]SSNATTableEntry, error) {
entries := make([]SSNATTableEntry, 0)
entryTotal := -1
for entryTotal < 0 || len(entries) < entryTotal {
parts, total, err := nat.vpc.region.GetSNATEntries(tblId, len(entries), 50)
if err != nil {
return nil, err
}
if len(parts) > 0 {
entries = append(entries, parts...)
}
entryTotal = total
}
return entries, nil
}
func (nat *SNatGetway) getSnatEntries() ([]SSNATTableEntry, error) {
entries := make([]SSNATTableEntry, 0)
for i := range nat.SnatTableIds.SnatTableId {
sentries, err := nat.getSnatEntriesForTable(nat.SnatTableIds.SnatTableId[i])
if err != nil {
return nil, err
}
entries = append(entries, sentries...)
}
return entries, nil
}
func (nat *SNatGetway) dissociateWithVswitch(vswitchId string) error {
entries, err := nat.getSnatEntries()
if err != nil {
return err
}
for i := range entries {
log.Debugf("%s", entries[i])
if entries[i].SourceVSwitchId == vswitchId {
err := nat.vpc.region.DeleteSnatEntry(entries[i].SnatTableId, entries[i].SnatEntryId)
if err != nil {
return err
}
}
}
return nil
}
+143
View File
@@ -0,0 +1,143 @@
package aliyun
import (
"fmt"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/log"
)
type SSNATTableEntry struct {
multicloud.SResourceBase
nat *SNatGetway
SnatEntryId string
SnatEntryName string
SnatIp string
SnatTableId string `json:"snat_table_id"`
SourceCIDR string `json:"source_cidr"`
SourceVSwitchId string `json:"source_vswitch_id"`
Status string
}
func (stable *SSNATTableEntry) GetName() string {
if len(stable.SnatEntryName) > 0 {
return stable.SnatEntryName
}
return stable.SnatEntryId
}
func (stable *SSNATTableEntry) GetId() string {
return stable.SnatEntryId
}
func (stable *SSNATTableEntry) GetGlobalId() string {
return stable.SnatEntryId
}
func (stable *SSNATTableEntry) GetStatus() string {
switch stable.Status {
case "Available":
return api.NAT_STAUTS_AVAILABLE
default:
return api.NAT_STATUS_UNKNOWN
}
}
func (stable *SSNATTableEntry) GetIP() string {
return stable.SnatIp
}
func (stable *SSNATTableEntry) GetSourceCIDR() string {
return stable.SourceCIDR
}
func (stable *SSNATTableEntry) GetNetworkId() string {
return stable.SourceVSwitchId
}
func (self *SRegion) GetSNATEntries(tableId string, offset, limit int) ([]SSNATTableEntry, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
}
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["PageSize"] = fmt.Sprintf("%d", limit)
params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
params["SnatTableId"] = tableId
body, err := self.vpcRequest("DescribeSnatTableEntries", params)
if err != nil {
log.Errorf("DescribeSnatTableEntries fail %s", err)
return nil, 0, err
}
if self.client.Debug {
log.Debugf("%s", body.PrettyString())
}
entries := make([]SSNATTableEntry, 0)
err = body.Unmarshal(&entries, "SnatTableEntries", "SnatTableEntry")
if err != nil {
log.Errorf("Unmarshal entries fail %s", err)
return nil, 0, err
}
total, _ := body.Int("TotalCount")
return entries, int(total), nil
}
func (region *SRegion) DeleteSnatEntry(tableId string, entryId string) error {
params := make(map[string]string)
params["RegionId"] = region.RegionId
params["SnatTableId"] = tableId
params["SnatEntryId"] = entryId
_, err := region.vpcRequest("DeleteSnatEntry", params)
return err
}
func (nat *SNatGetway) getSnatEntriesForTable(tblId string) ([]SSNATTableEntry, error) {
entries := make([]SSNATTableEntry, 0)
entryTotal := -1
for entryTotal < 0 || len(entries) < entryTotal {
parts, total, err := nat.vpc.region.GetSNATEntries(tblId, len(entries), 50)
if err != nil {
return nil, err
}
if len(parts) > 0 {
entries = append(entries, parts...)
}
entryTotal = total
}
return entries, nil
}
func (nat *SNatGetway) getSnatEntries() ([]SSNATTableEntry, error) {
entries := make([]SSNATTableEntry, 0)
for i := range nat.SnatTableIds.SnatTableId {
sentries, err := nat.getSnatEntriesForTable(nat.SnatTableIds.SnatTableId[i])
if err != nil {
return nil, err
}
entries = append(entries, sentries...)
}
return entries, nil
}
func (nat *SNatGetway) dissociateWithVswitch(vswitchId string) error {
entries, err := nat.getSnatEntries()
if err != nil {
return err
}
for i := range entries {
log.Debugf("%v", entries[i])
if entries[i].SourceVSwitchId == vswitchId {
err := nat.vpc.region.DeleteSnatEntry(entries[i].SnatTableId, entries[i].SnatEntryId)
if err != nil {
return err
}
}
}
return nil
}
+4 -4
View File
@@ -115,7 +115,7 @@ func (self *SRegion) vpcRequest(action string, params map[string]string) (jsonut
if err != nil {
return nil, err
}
return jsonRequest(client, "vpc.aliyuncs.com", ALIYUN_API_VERSION_VPC, action, params, self.Debug)
return jsonRequest(client, "vpc.aliyuncs.com", ALIYUN_API_VERSION_VPC, action, params, self.client.Debug)
}
type LBRegion struct {
@@ -689,13 +689,13 @@ func (self *SRegion) UpdateInstancePassword(instId string, passwd string) error
// }
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
eips, total, err := self.GetEips("", 0, 50)
eips, total, err := self.GetEips("", "", 0, 50)
if err != nil {
return nil, err
}
for len(eips) < total {
var parts []SEipAddress
parts, total, err = self.GetEips("", len(eips), 50)
parts, total, err = self.GetEips("", "", len(eips), 50)
if err != nil {
return nil, err
}
@@ -709,7 +709,7 @@ func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
}
func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
eips, total, err := self.GetEips(eipId, 0, 1)
eips, total, err := self.GetEips(eipId, "", 0, 1)
if err != nil {
return nil, err
}
+4 -3
View File
@@ -21,11 +21,12 @@ import (
func init() {
type EipListOptions struct {
Offset int `help:"List offset"`
Limit int `help:"List limit"`
AssociateId string `help:"Id of associate resource"`
Offset int `help:"List offset"`
Limit int `help:"List limit"`
}
shellutils.R(&EipListOptions{}, "eip-list", "List eips", func(cli *aliyun.SRegion, args *EipListOptions) error {
eips, total, e := cli.GetEips("", args.Offset, args.Limit)
eips, total, e := cli.GetEips("", args.AssociateId, args.Offset, args.Limit)
if e != nil {
return e
}
+14
View File
@@ -47,4 +47,18 @@ func init() {
return nil
})
type DNatEntryListOptions struct {
ID string `help:"DNat Table ID"`
Limit int `help:"page size"`
Offset int `help:"page offset"`
}
shellutils.R(&DNatEntryListOptions{}, "dnat-entry-list", "List DNAT entries", func(cli *aliyun.SRegion, args *DNatEntryListOptions) error {
entries, total, e := cli.GetForwardTableEntries(args.ID, args.Offset, args.Limit)
if e != nil {
return e
}
printList(entries, total, args.Offset, args.Limit, []string{})
return nil
})
}
+24
View File
@@ -18,6 +18,8 @@ import (
"strings"
"time"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -40,6 +42,8 @@ type SVSwitchIds struct {
}
type SVpc struct {
multicloud.SVpc
region *SRegion
iwires []cloudprovider.ICloudWire
@@ -263,3 +267,23 @@ func (self *SVpc) getNatGateways() ([]SNatGetway, error) {
}
return natgatways, nil
}
func (self *SVpc) GetINatGateways() ([]cloudprovider.ICloudNatGateway, error) {
nats := []SNatGetway{}
for {
parts, total, err := self.region.GetNatGateways(self.VpcId, "", len(nats), 50)
if err != nil {
return nil, err
}
nats = append(nats, parts...)
if len(nats) >= total {
break
}
}
inats := []cloudprovider.ICloudNatGateway{}
for i := 0; i < len(nats); i++ {
nats[i].vpc = self
inats = append(inats, &nats[i])
}
return inats, nil
}
+1 -1
View File
@@ -113,7 +113,7 @@ func (self *SEipAddress) GetMode() string {
func (self *SEipAddress) GetAssociationType() string {
// todo : ?
return "server"
return api.EIP_ASSOCIATE_TYPE_SERVER
}
func (self *SEipAddress) GetAssociationExternalId() string {
+3
View File
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SUserCIDRs struct {
@@ -32,6 +33,8 @@ type SUserCIDRs struct {
}
type SVpc struct {
multicloud.SVpc
region *SRegion
iwires []cloudprovider.ICloudWire
+1 -1
View File
@@ -70,7 +70,7 @@ func (self *SClassicEipAddress) GetAssociationExternalId() string {
}
func (self *SClassicEipAddress) GetAssociationType() string {
return "server"
return api.EIP_ASSOCIATE_TYPE_SERVER
}
func (self *SClassicEipAddress) GetBandwidth() int {
+3
View File
@@ -21,6 +21,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type ClassicAddressSpace struct {
@@ -42,6 +43,8 @@ type ClassicVpcProperties struct {
}
type SClassicVpc struct {
multicloud.SVpc
region *SRegion
iwires []cloudprovider.ICloudWire
+1 -1
View File
@@ -192,7 +192,7 @@ func (self *SEipAddress) GetAssociationExternalId() string {
}
func (self *SEipAddress) GetAssociationType() string {
return "server"
return api.EIP_ASSOCIATE_TYPE_SERVER
}
func (self *SEipAddress) GetBandwidth() int {
+3
View File
@@ -20,6 +20,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type AddressSpace struct {
@@ -46,6 +47,8 @@ type VirtualNetworkPropertiesFormat struct {
}
type SVpc struct {
multicloud.SVpc
region *SRegion
iwires []cloudprovider.ICloudWire
+1 -1
View File
@@ -156,7 +156,7 @@ func (self *SEipAddress) GetMode() string {
}
func (self *SEipAddress) GetAssociationType() string {
return "server"
return api.EIP_ASSOCIATE_TYPE_SERVER
}
func (self *SEipAddress) GetAssociationExternalId() string {
+3
View File
@@ -21,10 +21,13 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
// https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090625.html
type SVpc struct {
multicloud.SVpc
region *SRegion
iwires []cloudprovider.ICloudWire
+1 -1
View File
@@ -151,7 +151,7 @@ func (eip *SEipAddress) GetMode() string {
}
func (eip *SEipAddress) GetAssociationType() string {
return "server"
return api.EIP_ASSOCIATE_TYPE_SERVER
}
func (eip *SEipAddress) GetAssociationExternalId() string {
+3
View File
@@ -21,6 +21,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
const (
@@ -31,6 +32,8 @@ const (
)
type SVpc struct {
multicloud.SVpc
region *SRegion
iwires []cloudprovider.ICloudWire
+20 -16
View File
@@ -16,6 +16,7 @@ package qcloud
import (
"fmt"
"strings"
"time"
"yunion.io/x/jsonutils"
@@ -133,15 +134,14 @@ func (self *SEipAddress) GetMode() string {
}
func (self *SEipAddress) GetAssociationType() string {
switch self.AddressType {
case EIP_TYPE_EIP, EIP_TYPE_ANYCASTEIP, EIP_TYPE_WANIP:
return "server"
case EIP_TYPE_CALCIP:
return "server"
default:
log.Fatalf("unsupported type: %s", self.AddressType)
return "unsupported"
if len(self.InstanceId) > 0 {
for prefix, instanceType := range map[string]string{"nat-": api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY, "ins-": api.EIP_ASSOCIATE_TYPE_SERVER} {
if strings.HasPrefix(prefix, self.InstanceId) {
return instanceType
}
}
}
return ""
}
func (self *SEipAddress) GetAssociationExternalId() string {
@@ -154,8 +154,10 @@ func (self *SEipAddress) Delete() error {
func (self *SEipAddress) GetBandwidth() int {
if len(self.InstanceId) > 0 {
if instance, err := self.region.GetInstance(self.InstanceId); err == nil {
return instance.InternetAccessible.InternetMaxBandwidthOut
if strings.HasPrefix(self.InstanceId, "ins-") {
if instance, err := self.region.GetInstance(self.InstanceId); err == nil {
return instance.InternetAccessible.InternetMaxBandwidthOut
}
}
}
return 0
@@ -179,12 +181,14 @@ func (self *SEipAddress) GetExpiredAt() time.Time {
func (self *SEipAddress) GetInternetChargeType() string {
if len(self.InstanceId) > 0 {
if instance, err := self.region.GetInstance(self.InstanceId); err == nil {
switch instance.InternetAccessible.InternetChargeType {
case InternetChargeTypeTrafficPostpaidByHour:
return api.EIP_CHARGE_TYPE_BY_TRAFFIC
default:
return api.EIP_CHARGE_TYPE_BY_BANDWIDTH
if strings.HasPrefix(self.InstanceId, "ins-") {
if instance, err := self.region.GetInstance(self.InstanceId); err == nil {
switch instance.InternetAccessible.InternetChargeType {
case InternetChargeTypeTrafficPostpaidByHour:
return api.EIP_CHARGE_TYPE_BY_TRAFFIC
default:
return api.EIP_CHARGE_TYPE_BY_BANDWIDTH
}
}
}
}
+84
View File
@@ -0,0 +1,84 @@
package qcloud
import (
"fmt"
"time"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SDTable struct {
multicloud.SResourceBase
nat *SNatGateway
Eip string
NatId string
Description string
UniqVpcId string
Proto string
Pport int
Eport int
Owner string
VpcId int
PipType int
Pip string
UniqNatId string
CreateTime time.Time
}
func (table *SDTable) GetName() string {
if len(table.Description) > 0 {
return table.Description
}
return fmt.Sprintf("%s/%s/%d", table.Eip, table.Proto, table.Eport)
}
func (table *SDTable) GetId() string {
return fmt.Sprintf("%s/%s/%d", table.NatId, table.Eip, table.Eport)
}
func (table *SDTable) GetGlobalId() string {
return table.GetId()
}
func (table *SDTable) GetStatus() string {
return api.NAT_STAUTS_AVAILABLE
}
func (table *SDTable) GetExternalIp() string {
return table.Eip
}
func (table *SDTable) GetExternalPort() int {
return table.Eport
}
func (table *SDTable) GetInternalIp() string {
return table.Pip
}
func (table *SDTable) GetInternalPort() int {
return table.Pport
}
func (table *SDTable) GetIpProtocol() string {
return table.Proto
}
func (region *SRegion) GetDTables(natId, vpcId string) ([]SDTable, error) {
param := map[string]string{}
param["vpcId"] = vpcId
param["natId"] = natId
body, err := region.vpc2017Request("GetDnaptRule", param)
if err != nil {
return nil, err
}
tables := []SDTable{}
err = body.Unmarshal(&tables, "data", "detail")
if err != nil {
return nil, err
}
return tables, nil
}
+130
View File
@@ -0,0 +1,130 @@
package qcloud
import (
"fmt"
"time"
"yunion.io/x/onecloud/pkg/cloudprovider"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SNatGateway struct {
multicloud.SNatGatewayBase
vpc *SVpc
NatId string `json:"natId"`
NatName string `json:"natName"`
ProductionStatus float32 `json:"productionStatus"`
State float32 `json:"state"`
UnVpcId string `json:"unVpcId"`
VpcId float32 `json:"vpcId"`
VpcName string `json:"vpcName"`
Zone string `json:"zone"`
Bandwidth float32 `json:"bandwidth"`
CreateTime time.Time `json:"createTime"`
EipCount float32 `json:"eipCount"`
MaxConcurrent float32 `json:"maxConcurrent"`
}
func (nat *SNatGateway) GetName() string {
if len(nat.NatName) > 0 {
return nat.NatName
}
return nat.NatId
}
func (nat *SNatGateway) GetId() string {
return nat.NatId
}
func (nat *SNatGateway) GetGlobalId() string {
return nat.NatId
}
func (nat *SNatGateway) GetStatus() string {
// NAT网关状态,0:运行中, 1:不可用, 2:欠费停服
switch int(nat.State) {
case 0:
return api.NAT_STAUTS_AVAILABLE
case 1, 2:
return api.NAT_STATUS_UNKNOWN
default:
return api.NAT_STATUS_UNKNOWN
}
}
func (nat *SNatGateway) GetNatSpec() string {
switch int(nat.MaxConcurrent) {
case 100 * 10000:
return api.QCLOUD_NAT_SPEC_SMALL
case 300 * 10000:
return api.QCLOUD_NAT_SPEC_MIDDLE
case 1000 * 10000:
return api.QCLOUD_NAT_SPEC_LARGE
}
return ""
}
func (nat *SNatGateway) GetIEips() ([]cloudprovider.ICloudEIP, error) {
eips := []SEipAddress{}
for {
part, total, err := nat.vpc.region.GetEips("", nat.NatId, len(eips), 50)
if err != nil {
return nil, err
}
eips = append(eips, part...)
if len(eips) >= total {
break
}
}
ieips := []cloudprovider.ICloudEIP{}
for i := 0; i < len(eips); i++ {
eips[i].region = nat.vpc.region
ieips = append(ieips, &eips[i])
}
return ieips, nil
}
func (nat *SNatGateway) GetINatSTables() ([]cloudprovider.ICloudNatSTable, error) {
return []cloudprovider.ICloudNatSTable{}, nil
}
func (nat *SNatGateway) GetINatDTables() ([]cloudprovider.ICloudNatDTable, error) {
tables, err := nat.vpc.region.GetDTables(nat.NatId, nat.vpc.VpcId)
if err != nil {
return nil, err
}
itables := []cloudprovider.ICloudNatDTable{}
for i := 0; i < len(tables); i++ {
tables[i].nat = nat
itables = append(itables, &tables[i])
}
return itables, nil
}
func (region *SRegion) GetNatGateways(vpcId string, offset int, limit int) ([]SNatGateway, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
}
params := make(map[string]string)
params["Limit"] = fmt.Sprintf("%d", limit)
params["Offset"] = fmt.Sprintf("%d", offset)
if len(vpcId) > 0 {
params["vpcId"] = vpcId
}
body, err := region.vpc2017Request("DescribeNatGateway", params)
if err != nil {
return nil, 0, err
}
nats := []SNatGateway{}
err = body.Unmarshal(&nats, "data")
if err != nil {
return nil, 0, err
}
total, _ := body.Float("totalCount")
return nats, int(total), nil
}
+48
View File
@@ -117,6 +117,12 @@ func wssRequest(client *common.Client, apiName string, params map[string]string,
return _phpJsonRequest(client, &wssJsonResponse{}, domain, "/v2/index.php", "", apiName, params, debug)
}
// 2017版API
func vpc2017Request(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) {
domain := "vpc.api.qcloud.com"
return _phpJsonRequest(client, &vpc2017JsonResponse{}, domain, "/v2/index.php", "", apiName, params, debug)
}
func billingRequest(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) {
domain := "billing.tencentcloudapi.com"
return _jsonRequest(client, domain, QCLOUD_BILLING_API_VERSION, apiName, params, debug, true)
@@ -154,6 +160,40 @@ func (r *phpJsonRequest) GetPath() string {
return r.Path
}
// 2017vpc专用response
type vpc2017JsonResponse struct {
Code int `json:"code"`
CodeDesc string `json:"codeDesc"`
Message string `json:"message"`
TotalCount int `json:"totalCount"`
Response *interface{} `json:"data"`
}
func (r *vpc2017JsonResponse) ParseErrorFromHTTPResponse(body []byte) (err error) {
resp := &vpc2017JsonResponse{}
err = json.Unmarshal(body, resp)
if err != nil {
return
}
if resp.Code != 0 {
return errors.NewTencentCloudSDKError(resp.CodeDesc, resp.Message, "")
}
return nil
}
func (r *vpc2017JsonResponse) GetResponse() *interface{} {
if r.Response == nil {
result, _ := jsonutils.Parse([]byte(`{"data":[],"totalCount":0}`))
return func(resp interface{}) *interface{} {
return &resp
}(result)
}
return func(resp interface{}) *interface{} {
return &resp
}(jsonutils.Marshal(r))
}
// SSL证书专用response
type wssJsonResponse struct {
Code int `json:"code"`
@@ -363,6 +403,14 @@ func (client *SQcloudClient) wssRequest(apiName string, params map[string]string
return wssRequest(cli, apiName, params, client.Debug)
}
func (client *SQcloudClient) vpc2017Request(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
cli, err := client.getDefaultClient()
if err != nil {
return nil, err
}
return vpc2017Request(cli, apiName, params, client.Debug)
}
func (client *SQcloudClient) billingRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
cli, err := client.getDefaultClient()
if err != nil {
+5
View File
@@ -614,6 +614,11 @@ func (self *SRegion) vpcRequest(apiName string, params map[string]string) (jsonu
return self.client.vpcRequest(apiName, params)
}
func (self *SRegion) vpc2017Request(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
params["Region"] = self.Region
return self.client.vpc2017Request(apiName, params)
}
func (self *SRegion) cvmRequest(apiName string, params map[string]string, retry bool) (jsonutils.JSONObject, error) {
params["Region"] = self.Region
return self.client.jsonRequest(apiName, params, retry)
+35
View File
@@ -0,0 +1,35 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/util/qcloud"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type NatDTableListOptions struct {
VPCID string `help:"Vpc ID"`
NATID string `help:"Nat ID"`
}
shellutils.R(&NatDTableListOptions{}, "dtable-list", "List nat dtables", func(cli *qcloud.SRegion, args *NatDTableListOptions) error {
tables, err := cli.GetDTables(args.NATID, args.VPCID)
if err != nil {
return err
}
printList(tables, len(tables), 0, 0, []string{})
return nil
})
}
+36
View File
@@ -0,0 +1,36 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/util/qcloud"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type NatGatewayListOptions struct {
VpcId string `help:"Vpc ID"`
Offset int `help:"List offset"`
Limit int `help:"List limit"`
}
shellutils.R(&NatGatewayListOptions{}, "natgateway-list", "List nat gateway", func(cli *qcloud.SRegion, args *NatGatewayListOptions) error {
nats, total, e := cli.GetNatGateways(args.VpcId, args.Offset, args.Limit)
if e != nil {
return e
}
printList(nats, total, args.Offset, args.Limit, []string{})
return nil
})
}
+23
View File
@@ -21,9 +21,12 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SVpc struct {
multicloud.SVpc
region *SRegion
iwires []cloudprovider.ICloudWire
@@ -115,6 +118,26 @@ func (self *SVpc) getWireByZoneId(zoneId string) *SWire {
return nil
}
func (self *SVpc) GetINatGateways() ([]cloudprovider.ICloudNatGateway, error) {
nats := []SNatGateway{}
for {
part, total, err := self.region.GetNatGateways(self.VpcId, len(nats), 50)
if err != nil {
return nil, err
}
nats = append(nats, part...)
if len(nats) >= total {
break
}
}
inats := []cloudprovider.ICloudNatGateway{}
for i := 0; i < len(nats); i++ {
nats[i].vpc = self
inats = append(inats, &nats[i])
}
return inats, nil
}
func (self *SVpc) fetchNetworks() error {
networks, total, err := self.region.GetNetworks(nil, self.VpcId, 0, 50)
if err != nil {
+1 -1
View File
@@ -159,7 +159,7 @@ func (self *SEip) GetMode() string {
}
func (self *SEip) GetAssociationType() string {
return "server"
return api.EIP_ASSOCIATE_TYPE_SERVER
}
// 已绑定的资源类型, 枚举值为: uhost, 云主机;natgwNAT网关;ulb:负载均衡器;upm: 物理机; hadoophost: 大数据集群;fortresshost:堡垒机;udockhost:容器;udhost:私有专区主机;vpngwIPSec VPNucdr:云灾备;dbaudit:数据库审计。
+3
View File
@@ -21,9 +21,12 @@ import (
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SVPC struct {
multicloud.SVpc
region *SRegion
iwires []cloudprovider.ICloudWire
+1 -1
View File
@@ -101,7 +101,7 @@ func (eip *SEipAddress) GetMode() string {
}
func (eip *SEipAddress) GetAssociationType() string {
return "server"
return api.EIP_ASSOCIATE_TYPE_SERVER
}
func (eip *SEipAddress) GetAssociationExternalId() string {
+3
View File
@@ -19,11 +19,14 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
api "yunion.io/x/onecloud/pkg/apis/compute"
)
type SVpc struct {
multicloud.SVpc
region *SRegion
iwires []cloudprovider.ICloudWire