虚拟网卡信息同步

This commit is contained in:
ioito
2019-07-15 20:01:18 +08:00
parent 58279e36b9
commit 4f9ea70487
18 changed files with 1143 additions and 8 deletions
@@ -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
const (
NETWORK_INTERFACE_ASSOCIATE_TYPE_SERVER = "server"
NETWORK_INTERFACE_ASSOCIATE_TYPE_RESERVED = "reserved"
NETWORK_INTERFACE_ASSOCIATE_TYPE_LOADBALANCER = "loadbalancer"
NETWORK_INTERFACE_STATUS_INIT = "init"
NETWORK_INTERFACE_STATUS_CREATING = "creating"
NETWORK_INTERFACE_STATUS_AVAILABLE = "available"
NETWORK_INTERFACE_STATUS_ATTACHING = "attaching"
NETWORK_INTERFACE_STATUS_DETACHING = "detaching"
NETWORK_INTERFACE_STATUS_DELETING = "deleting"
NETWORK_INTERFACE_STATUS_UNKNOWN = "unknown"
)
+20
View File
@@ -108,6 +108,8 @@ type ICloudRegion interface {
GetISkus(zoneId string) ([]ICloudSku, error)
CreateISku(sku *SServerSku) (ICloudSku, error)
GetINetworkInterfaces() ([]ICloudNetworkInterface, error)
GetProvider() string
}
@@ -674,3 +676,21 @@ type ICloudNatSEntry interface {
Delete() error
}
type ICloudNetworkInterface interface {
ICloudResource
GetMacAddress() string
GetAssociateType() string
GetAssociateId() string
GetICloudInterfaceAddresses() ([]ICloudInterfaceAddress, error)
}
type ICloudInterfaceAddress interface {
GetGlobalId() string //返回IP即可
GetINetworkId() string
GetIP() string
IsPrimary() bool
}
+1
View File
@@ -1098,6 +1098,7 @@ func (self *SCloudprovider) RealDelete(ctx context.Context, userCred mcclient.To
NatGatewayManager,
VpcManager,
ElasticipManager,
NetworkInterfaceManager,
CloudproviderRegionManager,
ExternalProjectManager,
CloudregionManager,
+10
View File
@@ -141,6 +141,16 @@ func (self *SCloudregion) GetGuestIncrementCount() (int, error) {
return self.getGuestCountInternal(true)
}
func (self *SCloudregion) GetNetworkInterfaces() ([]SNetworkInterface, error) {
interfaces := []SNetworkInterface{}
q := NetworkInterfaceManager.Query().Equals("cloudregion_id", self.Id)
err := db.FetchModelObjects(NetworkInterfaceManager, q, &interfaces)
if err != nil {
return nil, err
}
return interfaces, nil
}
func (self *SCloudregion) getGuestCountInternal(increment bool) (int, error) {
zoneTable := ZoneManager.Query("id")
if self.Id == api.DEFAULT_REGION_ID {
+46
View File
@@ -882,6 +882,50 @@ func syncRegionSnapshotPolicies(ctx context.Context, userCred mcclient.TokenCred
}
}
func syncRegionNetworkInterfaces(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localRegion *SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *SSyncRange) {
networkInterfaces, err := remoteRegion.GetINetworkInterfaces()
if err != nil {
msg := fmt.Sprintf("GetINetworkInterfaces for region %s failed %s", remoteRegion.GetName(), err)
log.Errorf(msg)
return
}
localInterfaces, remoteInterfaces, result := NetworkInterfaceManager.SyncNetworkInterfaces(ctx, userCred, provider, localRegion, networkInterfaces)
syncResults.Add(NetworkInterfaceManager, result)
msg := result.Result()
log.Infof("SyncNetworkInterfaces for region %s result: %s", localRegion.Name, msg)
if result.IsError() {
return
}
for i := 0; i < len(localInterfaces); i++ {
func() {
lockman.LockObject(ctx, &localInterfaces[i])
defer lockman.ReleaseObject(ctx, &localInterfaces[i])
syncInterfaceAddresses(ctx, userCred, &localInterfaces[i], remoteInterfaces[i])
}()
}
}
func syncInterfaceAddresses(ctx context.Context, userCred mcclient.TokenCredential, localInterface *SNetworkInterface, remoteInterface cloudprovider.ICloudNetworkInterface) {
addresses, err := remoteInterface.GetICloudInterfaceAddresses()
if err != nil {
msg := fmt.Sprintf("GetICloudInterfaceAddresses for networkinterface %s failed %s", remoteInterface.GetName(), err)
log.Errorf(msg)
return
}
result := NetworkinterfacenetworkManager.SyncInterfaceAddresses(ctx, userCred, localInterface, addresses)
msg := result.Result()
notes := fmt.Sprintf("SyncInterfaceAddresses for networkinterface %s result: %s", localInterface.Name, msg)
log.Infof(notes)
if result.IsError() {
return
}
}
func syncPublicCloudProviderInfo(
ctx context.Context,
userCred mcclient.TokenCredential,
@@ -947,6 +991,8 @@ func syncPublicCloudProviderInfo(
syncRegionLoadbalancerCertificates(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
syncRegionLoadbalancers(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
syncRegionNetworkInterfaces(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
log.Debugf("storageCachePairs count %d", len(storageCachePairs))
for i := range storageCachePairs {
// always sync private cloud cached images
@@ -0,0 +1,195 @@
package models
import (
"context"
"fmt"
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
)
type SNetworkinterfacenetworkManager struct {
db.SJointResourceBaseManager
}
var NetworkinterfacenetworkManager *SNetworkinterfacenetworkManager
func init() {
db.InitManager(func() {
NetworkinterfacenetworkManager = &SNetworkinterfacenetworkManager{
SJointResourceBaseManager: db.NewJointResourceBaseManager(
SNetworkinterfacenetwork{},
"networkinterfacenetworks_tbl",
"networkinterfacenetwork",
"networkinterfacenetworks",
NetworkInterfaceManager,
NetworkManager,
),
}
GuestnetworkManager.SetVirtualObject(GuestnetworkManager)
})
}
type SNetworkinterfacenetwork struct {
db.SJointResourceBase
Primary bool `nullable:"false" list:"user"`
IpAddr string `width:"16" charset:"ascii" nullable:"false" list:"user"`
NetworkinterfaceId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"` // Column(VARCHAR(36, charset='ascii'), nullable=False)
NetworkId string `width:"36" charset:"ascii" nullable:"false" list:"admin"`
}
func (manager *SNetworkinterfacenetworkManager) GetMasterFieldName() string {
return "networkinterface_id"
}
func (manager *SNetworkinterfacenetworkManager) GetSlaveFieldName() string {
return "network_id"
}
func (joint *SNetworkinterfacenetwork) Master() db.IStandaloneModel {
return db.JointMaster(joint)
}
func (joint *SNetworkinterfacenetwork) Slave() db.IStandaloneModel {
return db.JointSlave(joint)
}
func (manager *SNetworkinterfacenetworkManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowList(userCred, manager)
}
func (manager *SNetworkinterfacenetworkManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowCreate(userCred, manager)
}
func (manager *SNetworkinterfacenetworkManager) AllowListDescendent(ctx context.Context, userCred mcclient.TokenCredential, model db.IStandaloneModel, query jsonutils.JSONObject) bool {
return db.IsAdminAllowList(userCred, manager)
}
func (manager *SNetworkinterfacenetworkManager) AllowAttach(ctx context.Context, userCred mcclient.TokenCredential, master db.IStandaloneModel, slave db.IStandaloneModel) bool {
return db.IsAdminAllowCreate(userCred, manager)
}
func (self *SNetworkinterfacenetwork) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowGet(userCred, self)
}
func (self *SNetworkinterfacenetwork) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
return db.IsAdminAllowUpdate(userCred, self)
}
func (self *SNetworkinterfacenetwork) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowDelete(userCred, self)
}
func (self *SNetworkinterfacenetwork) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return db.DeleteModel(ctx, userCred, self)
}
func (self *SNetworkinterfacenetwork) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
return db.DetachJoint(ctx, userCred, self)
}
func (manager *SNetworkinterfacenetworkManager) SyncInterfaceAddresses(ctx context.Context, userCred mcclient.TokenCredential, networkinterface *SNetworkInterface, exts []cloudprovider.ICloudInterfaceAddress) compare.SyncResult {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, networkinterface.GetOwnerId()))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, networkinterface.GetOwnerId()))
syncResult := compare.SyncResult{}
dbResources, err := networkinterface.GetNetworks()
if err != nil {
return syncResult
}
removed := make([]SNetworkinterfacenetwork, 0)
commondb := make([]SNetworkinterfacenetwork, 0)
commonext := make([]cloudprovider.ICloudInterfaceAddress, 0)
added := make([]cloudprovider.ICloudInterfaceAddress, 0)
if err := compare.CompareSets(dbResources, exts, &removed, &commondb, &commonext, &added); err != nil {
return syncResult
}
for i := 0; i < len(removed); i += 1 {
err := removed[i].Delete(ctx, userCred)
if err != nil {
syncResult.DeleteError(err)
} else {
syncResult.Delete()
}
}
for i := 0; i < len(commondb); i += 1 {
err := commondb[i].SyncWithCloudkInterfaceAddress(ctx, userCred, commonext[i])
if err != nil {
syncResult.UpdateError(err)
continue
}
syncResult.Update()
}
for i := 0; i < len(added); i += 1 {
err := manager.newFromCloudInterfaceAddress(ctx, userCred, networkinterface, added[i])
if err != nil {
syncResult.AddError(err)
continue
}
syncResult.Add()
}
return syncResult
}
func (self *SNetworkinterfacenetwork) SyncWithCloudkInterfaceAddress(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudInterfaceAddress) error {
diff, err := db.UpdateWithLock(ctx, self, func() error {
self.Primary = ext.IsPrimary()
return nil
})
if err != nil {
return err
}
db.OpsLog.LogSyncUpdate(self, diff, userCred)
return nil
}
func (manager *SNetworkinterfacenetworkManager) newFromCloudInterfaceAddress(ctx context.Context, userCred mcclient.TokenCredential, networkinterface *SNetworkInterface, ext cloudprovider.ICloudInterfaceAddress) error {
address := SNetworkinterfacenetwork{
IpAddr: ext.GetIP(),
NetworkinterfaceId: networkinterface.Id,
Primary: ext.IsPrimary(),
}
address.SetModelManager(manager, &address)
networkId := ext.GetINetworkId()
_network, err := db.FetchByExternalId(NetworkManager, networkId)
if err != nil {
return errors.Wrapf(err, "newFromCloudInterfaceAddress.FetchByExternalId(%s)", networkId)
}
ipAddr, err := netutils.NewIPV4Addr(address.IpAddr)
if err != nil {
return errors.Wrap(err, "netutils.NewIPV4Addr")
}
network := _network.(*SNetwork)
if !network.isAddressInRange(ipAddr) {
return fmt.Errorf("ip %s not in network %s(%s) range", address.IpAddr, network.Name, network.Id)
}
address.NetworkId = network.Id
err = manager.TableSpec().Insert(&address)
if err != nil {
return errors.Wrap(err, "TableSpec().Insert(&address)")
}
db.OpsLog.LogEvent(&address, db.ACT_CREATE, address.GetShortDesc(ctx), userCred)
return nil
}
+265
View File
@@ -0,0 +1,265 @@
// 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/jsonutils"
"yunion.io/x/log"
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/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
)
type SNetworkInterfaceManager struct {
db.SStatusStandaloneResourceBaseManager
}
var NetworkInterfaceManager *SNetworkInterfaceManager
func init() {
NetworkInterfaceManager = &SNetworkInterfaceManager{
SStatusStandaloneResourceBaseManager: db.NewStatusStandaloneResourceBaseManager(
SNetworkInterface{},
"networkinterfaces_tbl",
"networkinterface",
"networkinterfaces",
),
}
NetworkInterfaceManager.SetVirtualObject(NetworkInterfaceManager)
}
type SNetworkInterface struct {
db.SStatusStandaloneResourceBase
db.SExternalizedResourceBase
SManagedResourceBase
SCloudregionResourceBase
Mac string `width:"36" charset:"ascii"`
AssociateType string `width:"36" charset:"ascii" nullable:"true" create:"required"`
AssociateId string `width:"36" charset:"ascii" list:"user"`
}
func (manager *SNetworkInterfaceManager) GetContextManagers() [][]db.IModelManager {
return [][]db.IModelManager{
{CloudregionManager},
}
}
func (self *SNetworkInterfaceManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowList(userCred, self)
}
func (self *SNetworkInterfaceManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowCreate(userCred, self)
}
func (self *SNetworkInterface) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowGet(userCred, self)
}
func (self *SNetworkInterface) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
return db.IsAdminAllowUpdate(userCred, self)
}
func (self *SNetworkInterface) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowDelete(userCred, self)
}
func (manager *SNetworkInterfaceManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
var err error
q, err = managedResourceFilterByAccount(q, query, "", nil)
if err != nil {
return nil, err
}
q, err = manager.SStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
if err != nil {
return nil, err
}
return q, err
}
func (self *SNetworkInterface) 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)
}
return extra
}
func (manager *SNetworkInterfaceManager) getNetworkInterfacesByProviderId(providerId string) ([]SNetworkInterface, error) {
nics := []SNetworkInterface{}
err := fetchByManagerId(manager, providerId, &nics)
if err != nil {
return nil, err
}
return nics, nil
}
func (manager *SNetworkInterfaceManager) SyncNetworkInterfaces(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, exts []cloudprovider.ICloudNetworkInterface) ([]SNetworkInterface, []cloudprovider.ICloudNetworkInterface, compare.SyncResult) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, provider.GetOwnerId()))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, provider.GetOwnerId()))
localResources := make([]SNetworkInterface, 0)
remoteResources := make([]cloudprovider.ICloudNetworkInterface, 0)
syncResult := compare.SyncResult{}
dbResources, err := region.GetNetworkInterfaces()
if err != nil {
syncResult.Error(err)
return nil, nil, syncResult
}
removed := make([]SNetworkInterface, 0)
commondb := make([]SNetworkInterface, 0)
commonext := make([]cloudprovider.ICloudNetworkInterface, 0)
added := make([]cloudprovider.ICloudNetworkInterface, 0)
if err := compare.CompareSets(dbResources, exts, &removed, &commondb, &commonext, &added); err != nil {
syncResult.Error(err)
return nil, nil, syncResult
}
for i := 0; i < len(removed); i += 1 {
err := removed[i].syncRemoveCloudNetworkInterface(ctx, userCred)
if err != nil {
syncResult.DeleteError(err)
} else {
syncResult.Delete()
}
}
for i := 0; i < len(commondb); i += 1 {
err := commondb[i].SyncWithCloudNetworkInterface(ctx, userCred, provider, commonext[i])
if err != nil {
syncResult.UpdateError(err)
continue
}
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
localResources = append(localResources, commondb[i])
remoteResources = append(remoteResources, commonext[i])
syncResult.Update()
}
for i := 0; i < len(added); i += 1 {
new, err := manager.newFromCloudNetworkInterface(ctx, userCred, provider, region, added[i])
if err != nil {
syncResult.AddError(err)
continue
}
syncMetadata(ctx, userCred, new, added[i])
localResources = append(localResources, *new)
remoteResources = append(remoteResources, added[i])
syncResult.Add()
}
return localResources, remoteResources, syncResult
}
func (self *SNetworkInterface) syncRemoveCloudNetworkInterface(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
err := self.ValidateDeleteCondition(ctx)
if err != nil {
return self.SetStatus(userCred, api.NETWORK_INTERFACE_STATUS_UNKNOWN, "sync to delete")
}
return self.Delete(ctx, userCred)
}
func (self *SNetworkInterface) SyncWithCloudNetworkInterface(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudNetworkInterface) error {
diff, err := db.UpdateWithLock(ctx, self, func() error {
self.Status = ext.GetStatus()
self.AssociateType = ext.GetAssociateType()
if associateId := ext.GetAssociateId(); len(associateId) > 0 {
self.Associate(associateId)
}
return nil
})
if err != nil {
return err
}
db.OpsLog.LogSyncUpdate(self, diff, userCred)
return nil
}
func (self *SNetworkInterface) Associate(associateId string) error {
switch self.AssociateType {
case api.NETWORK_INTERFACE_ASSOCIATE_TYPE_SERVER:
guest, err := db.FetchByExternalId(GuestManager, associateId)
if err != nil {
return errors.Wrapf(err, "failed to get guest for networkinterface %s associateId %s", self.Name, associateId)
}
self.AssociateId = guest.GetId()
}
return nil
}
func (manager *SNetworkInterfaceManager) newFromCloudNetworkInterface(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, ext cloudprovider.ICloudNetworkInterface) (*SNetworkInterface, error) {
networkinterface := SNetworkInterface{}
networkinterface.SetModelManager(manager, &networkinterface)
newName, err := db.GenerateName(manager, provider.GetOwnerId(), ext.GetName())
if err != nil {
return nil, err
}
networkinterface.Name = newName
networkinterface.Status = ext.GetStatus()
networkinterface.ExternalId = ext.GetGlobalId()
networkinterface.CloudregionId = region.Id
networkinterface.ManagerId = provider.Id
networkinterface.IsEmulated = ext.IsEmulated()
networkinterface.Mac = ext.GetMacAddress()
networkinterface.AssociateType = ext.GetAssociateType()
if associatId := ext.GetAssociateId(); len(associatId) > 0 {
err := networkinterface.Associate(associatId)
if err != nil {
log.Warningf("associate error: %s", err)
}
}
err = manager.TableSpec().Insert(&networkinterface)
if err != nil {
return nil, errors.Wrap(err, "TableSpec().Insert(&networkinterface)")
}
db.OpsLog.LogEvent(&networkinterface, db.ACT_CREATE, networkinterface.GetShortDesc(ctx), userCred)
return &networkinterface, nil
}
func (self *SNetworkInterface) GetNetworks() ([]SNetworkinterfacenetwork, error) {
networks := []SNetworkinterfacenetwork{}
q := NetworkinterfacenetworkManager.Query().Equals("networkinterface_id", self.Id)
err := db.FetchModelObjects(NetworkinterfacenetworkManager, q, &networks)
if err != nil {
return nil, err
}
return networks, nil
}
+10
View File
@@ -182,6 +182,11 @@ func (self *SNetwork) GetTotalNicCount() (int, error) {
return -1, err
}
total += cnt
cnt, err = self.GetNetworkInterfacesCount()
if err != nil {
return -1, err
}
total += cnt
return total, nil
}
@@ -209,6 +214,10 @@ func (self *SNetwork) GetEipsCount() (int, error) {
return ElasticipManager.Query().Equals("network_id", self.Id).CountWithError()
}
func (self *SNetwork) GetNetworkInterfacesCount() (int, error) {
return NetworkinterfacenetworkManager.Query().Equals("network_id", self.Id).CountWithError()
}
func (self *SNetwork) GetUsedAddresses() map[string]bool {
used := make(map[string]bool)
@@ -219,6 +228,7 @@ func (self *SNetwork) GetUsedAddresses() map[string]bool {
ReservedipManager.Query().SubQuery(),
LoadbalancernetworkManager.Query().SubQuery(),
ElasticipManager.Query().SubQuery(),
NetworkinterfacenetworkManager.Query().SubQuery(),
} {
q := tbl.Query(tbl.Field("ip_addr")).Equals("network_id", self.Id)
rows, err := q.Rows()
+67
View File
@@ -662,6 +662,54 @@ func (net *SNetwork) purgeReservedIps(ctx context.Context, userCred mcclient.Tok
return nil
}
func (nic *SNetworkInterface) purgeNetworkAddres(ctx context.Context, userCred mcclient.TokenCredential) error {
networks, err := nic.GetNetworks()
if err != nil {
return err
}
for i := range networks {
err := networks[i].Delete(ctx, userCred)
if err != nil {
return err
}
}
return nil
}
func (nic *SNetworkInterface) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, nic)
defer lockman.ReleaseObject(ctx, nic)
err := nic.purgeNetworkAddres(ctx, userCred)
if err != nil {
return err
}
err = nic.ValidateDeleteCondition(ctx)
if err != nil {
return err
}
return nic.Delete(ctx, userCred)
}
func (net *SNetwork) purgeNetworkInterfaces(ctx context.Context, userCred mcclient.TokenCredential) error {
networkinterfaceIds := NetworkinterfacenetworkManager.Query("networkinterface_id").Equals("network_id", net.Id).Distinct().SubQuery()
q := NetworkInterfaceManager.Query().In("id", networkinterfaceIds)
interfaces := make([]SNetworkInterface, 0)
err := db.FetchModelObjects(NetworkInterfaceManager, q, &interfaces)
if err != nil {
return err
}
for i := range interfaces {
err = interfaces[i].purge(ctx, userCred)
if err != nil {
return err
}
}
return nil
}
func (net *SNetwork) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, net)
defer lockman.ReleaseObject(ctx, net)
@@ -691,6 +739,11 @@ func (net *SNetwork) purge(ctx context.Context, userCred mcclient.TokenCredentia
return err
}
err = net.purgeNetworkInterfaces(ctx, userCred)
if err != nil {
return err
}
err = net.ValidateDeleteCondition(ctx)
if err != nil {
return err
@@ -972,3 +1025,17 @@ func (manager *SNatGetewayManager) purgeAll(ctx context.Context, userCred mcclie
}
return nil
}
func (manager *SNetworkInterfaceManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
nics, err := manager.getNetworkInterfacesByProviderId(providerId)
if err != nil {
return err
}
for i := range nics {
err = nics[i].purge(ctx, userCred)
if err != nil {
return err
}
}
return nil
}
+2
View File
@@ -110,6 +110,8 @@ func InitHandlers(app *appsrv.Application) {
models.ServerSkuManager,
models.ExternalProjectManager,
models.NetworkInterfaceManager,
models.NetworkinterfacenetworkManager,
} {
db.RegisterModelManager(manager)
handler := db.NewModelHandler(manager)
+19
View File
@@ -0,0 +1,19 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package multicloud
type SNetworkInterfaceBase struct {
SResourceBase
}
+4
View File
@@ -57,3 +57,7 @@ func (self *SRegion) CreateISku(*cloudprovider.SServerSku) (cloudprovider.ICloud
func (self *SRegion) GetISkuById(skuId string) (cloudprovider.ICloudSku, error) {
return nil, fmt.Errorf("Not Support GetISkuById")
}
func (self *SRegion) GetINetworkInterfaces() ([]cloudprovider.ICloudNetworkInterface, error) {
return nil, fmt.Errorf("Not Implement GetINetworkInterfaces")
}
-6
View File
@@ -59,12 +59,6 @@ type SNetworkInterfaces struct {
NetworkInterface []SNetworkInterface
}
type SNetworkInterface struct {
MacAddress string
NetworkInterfaceId string
PrimaryIpAddress string
}
type SOperationLocks struct {
LockReason []string
}
+167
View File
@@ -0,0 +1,167 @@
// 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 aliyun
import (
"fmt"
"time"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SPrivateIp struct {
nic *SNetworkInterface
Primary bool
PrivateIpAddress string
}
func (ip *SPrivateIp) GetGlobalId() string {
return ip.PrivateIpAddress
}
func (ip *SPrivateIp) GetINetworkId() string {
return ip.nic.VSwitchId
}
func (ip *SPrivateIp) GetIP() string {
return ip.PrivateIpAddress
}
func (ip *SPrivateIp) IsPrimary() bool {
return ip.Primary
}
type SPrivateIpSets struct {
PrivateIpSet []SPrivateIp
}
type SNetworkInterface struct {
multicloud.SNetworkInterfaceBase
region *SRegion
InstanceId string
CreationTime time.Time
MacAddress string
NetworkInterfaceName string
PrivateIpSets SPrivateIpSets
ResourceGroupId string
SecurityGroupIds SSecurityGroupIds
Status string
Type string
VSwitchId string
VpcId string
ZoneId string
NetworkInterfaceId string
PrimaryIpAddress string
PrivateIpAddress string
}
func (nic *SNetworkInterface) GetName() string {
return nic.NetworkInterfaceName
}
func (nic *SNetworkInterface) GetId() string {
return nic.NetworkInterfaceId
}
func (nic *SNetworkInterface) GetGlobalId() string {
return nic.NetworkInterfaceId
}
func (nic *SNetworkInterface) GetAssociateId() string {
return nic.InstanceId
}
func (nic *SNetworkInterface) GetAssociateType() string {
return api.NETWORK_INTERFACE_ASSOCIATE_TYPE_SERVER
}
func (nic *SNetworkInterface) GetMacAddress() string {
return nic.MacAddress
}
func (nic *SNetworkInterface) GetStatus() string {
switch nic.Status {
case "Available":
return api.NETWORK_INTERFACE_STATUS_AVAILABLE
}
return nic.Status
}
func (region *SRegion) GetINetworkInterfaces() ([]cloudprovider.ICloudNetworkInterface, error) {
interfaces := []SNetworkInterface{}
for {
parts, total, err := region.GetNetworkInterfaces("", len(interfaces), 50)
if err != nil {
return nil, err
}
interfaces = append(interfaces, parts...)
if len(interfaces) >= total {
break
}
}
ret := []cloudprovider.ICloudNetworkInterface{}
for i := 0; i < len(interfaces); i++ {
// 阿里云实例的弹性网卡已经在guestnetwork同步了
if len(interfaces[i].InstanceId) == 0 {
interfaces[i].region = region
ret = append(ret, &interfaces[i])
}
}
return ret, nil
}
func (nic *SNetworkInterface) GetICloudInterfaceAddresses() ([]cloudprovider.ICloudInterfaceAddress, error) {
address := []cloudprovider.ICloudInterfaceAddress{}
for i := 0; i < len(nic.PrivateIpSets.PrivateIpSet); i++ {
nic.PrivateIpSets.PrivateIpSet[i].nic = nic
address = append(address, &nic.PrivateIpSets.PrivateIpSet[i])
}
return address, nil
}
func (region *SRegion) GetNetworkInterfaces(instanceId string, offset int, limit int) ([]SNetworkInterface, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
}
params := map[string]string{
"RegionId": region.RegionId,
"PageSize": fmt.Sprintf("%d", limit),
"PageNumber": fmt.Sprintf("%d", (offset/limit)+1),
}
if len(instanceId) > 0 {
params["InstanceId"] = instanceId
}
body, err := region.ecsRequest("DescribeNetworkInterfaces", params)
if err != nil {
return nil, 0, errors.Wrap(err, "DescribeNetworkInterfaces")
}
interfaces := []SNetworkInterface{}
err = body.Unmarshal(&interfaces, "NetworkInterfaceSets", "NetworkInterfaceSet")
if err != nil {
return nil, 0, errors.Wrap(err, "Unmarshal")
}
total, _ := body.Int("TotalCount")
return interfaces, int(total), 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/aliyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type NetworkInterfaceListOptions struct {
InstanceId string `help:"Id or instance"`
Offset int
Limit int
}
shellutils.R(&NetworkInterfaceListOptions{}, "network-interface-list", "List networkinterfaces", func(cli *aliyun.SRegion, args *NetworkInterfaceListOptions) error {
interfaces, total, err := cli.GetNetworkInterfaces(args.InstanceId, args.Offset, args.Limit)
if err != nil {
return err
}
printList(interfaces, total, 0, 0, nil)
return nil
})
}
+89 -2
View File
@@ -18,6 +18,11 @@ import (
"fmt"
"net/url"
"time"
"yunion.io/x/onecloud/pkg/multicloud"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type DnsAssignment struct {
@@ -32,12 +37,30 @@ type ExtraDhcpOpt struct {
OptName string
}
type FixedIPs struct {
type SFixedIP struct {
IpAddress string
SubnetID string
}
func (fixip *SFixedIP) GetGlobalId() string {
return fixip.SubnetID
}
func (fixip *SFixedIP) GetIP() string {
return fixip.IpAddress
}
func (fixip *SFixedIP) GetINetworkId() string {
return fixip.SubnetID
}
func (fixip *SFixedIP) IsPrimary() bool {
return true
}
type SPort struct {
multicloud.SNetworkInterfaceBase
region *SRegion
AdminStateUp bool
AllowedAddressPairs []string
CreatedAt time.Time
@@ -49,7 +72,7 @@ type SPort struct {
DnsDomain string
DnsName string
ExtraDhcpOpts []ExtraDhcpOpt
FixedIps []FixedIPs
FixedIps []SFixedIP
ID string
IpAllocation string
MacAddress string
@@ -67,6 +90,70 @@ type SPort struct {
UplinkStatusPropagation bool
}
func (port *SPort) GetName() string {
if len(port.Name) > 0 {
return port.Name
}
return port.ID
}
func (port *SPort) GetId() string {
return port.ID
}
func (port *SPort) GetGlobalId() string {
return port.ID
}
func (port *SPort) GetMacAddress() string {
return port.MacAddress
}
func (port *SPort) GetAssociateType() string {
switch port.DeviceOwner {
case "compute:nova":
return api.NETWORK_INTERFACE_ASSOCIATE_TYPE_SERVER
case "network:router_gateway", "network:dhcp", "network:router_interface":
return api.NETWORK_INTERFACE_ASSOCIATE_TYPE_RESERVED
}
return port.DeviceOwner
}
func (port *SPort) GetAssociateId() string {
return port.DeviceID
}
func (port *SPort) GetStatus() string {
switch port.Status {
case "ACTIVE", "DOWN":
return api.NETWORK_INTERFACE_STATUS_AVAILABLE
}
return port.Status
}
func (port *SPort) GetICloudInterfaceAddresses() ([]cloudprovider.ICloudInterfaceAddress, error) {
address := []cloudprovider.ICloudInterfaceAddress{}
for i := 0; i < len(port.FixedIps); i++ {
address = append(address, &port.FixedIps[i])
}
return address, nil
}
func (region *SRegion) GetINetworkInterfaces() ([]cloudprovider.ICloudNetworkInterface, error) {
ports, err := region.GetPorts("")
if err != nil {
return nil, err
}
ret := []cloudprovider.ICloudNetworkInterface{}
for i := 0; i < len(ports); i++ {
if len(ports[i].DeviceID) == 0 || ports[i].DeviceOwner != "compute:nova" {
ports[i].region = region
ret = append(ret, &ports[i])
}
}
return ret, nil
}
func (region *SRegion) GetPorts(macAddress string) ([]SPort, error) {
base := fmt.Sprintf("/v2.0/ports")
params := url.Values{}
+92
View File
@@ -18,10 +18,15 @@ import (
"fmt"
"time"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/multicloud"
"github.com/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SPrivateIpAddress struct {
nic *SNetworkInterface
Description string
Primary bool
PrivateIpAddress string
@@ -30,7 +35,25 @@ type SPrivateIpAddress struct {
State string
}
func (ip *SPrivateIpAddress) GetGlobalId() string {
return ip.PrivateIpAddress
}
func (ip *SPrivateIpAddress) GetIP() string {
return ip.PrivateIpAddress
}
func (ip *SPrivateIpAddress) GetINetworkId() string {
return ip.nic.SubnetId
}
func (ip *SPrivateIpAddress) IsPrimary() bool {
return ip.Primary
}
type SNetworkInterface struct {
multicloud.SNetworkInterfaceBase
region *SRegion
VpcId string
SubnetId string
NetworkInterfaceId string
@@ -46,6 +69,75 @@ type SNetworkInterface struct {
PrivateIpAddressSet []SPrivateIpAddress
}
func (nic *SNetworkInterface) GetName() string {
return nic.NetworkInterfaceName
}
func (nic *SNetworkInterface) GetId() string {
return nic.NetworkInterfaceId
}
func (nic *SNetworkInterface) GetGlobalId() string {
return nic.NetworkInterfaceId
}
func (nic *SNetworkInterface) GetMacAddress() string {
return nic.MacAddress
}
func (nic *SNetworkInterface) GetAssociateType() string {
return api.NETWORK_INTERFACE_ASSOCIATE_TYPE_SERVER
}
func (nic *SNetworkInterface) GetAssociateId() string {
return nic.Attachment
}
func (nic *SNetworkInterface) GetStatus() string {
switch nic.State {
case "PENDING":
return api.NETWORK_INTERFACE_STATUS_CREATING
case "AVAILABLE":
return api.NETWORK_INTERFACE_STATUS_AVAILABLE
case "ATTACHING":
return api.NETWORK_INTERFACE_STATUS_ATTACHING
case "DETACHING":
return api.NETWORK_INTERFACE_STATUS_DETACHING
case "DELETING":
return api.NETWORK_INTERFACE_STATUS_DELETING
}
return nic.State
}
func (nic *SNetworkInterface) GetICloudInterfaceAddresses() ([]cloudprovider.ICloudInterfaceAddress, error) {
address := []cloudprovider.ICloudInterfaceAddress{}
for i := 0; i < len(nic.PrivateIpAddressSet); i++ {
nic.PrivateIpAddressSet[i].nic = nic
address = append(address, &nic.PrivateIpAddressSet[i])
}
return address, nil
}
func (region *SRegion) GetINetworkInterfaces() ([]cloudprovider.ICloudNetworkInterface, error) {
interfaces := []SNetworkInterface{}
for {
parts, total, err := region.GetNetworkInterfaces([]string{}, "", len(interfaces), 50)
if err != nil {
return nil, err
}
interfaces = append(interfaces, parts...)
if len(interfaces) >= total {
break
}
}
ret := []cloudprovider.ICloudNetworkInterface{}
for i := 0; i < len(interfaces); i++ {
interfaces[i].region = region
ret = append(ret, &interfaces[i])
}
return ret, nil
}
func (region *SRegion) GetNetworkInterfaces(interfaceIds []string, subnetId string, offset int, limit int) ([]SNetworkInterface, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
+91
View File
@@ -17,10 +17,18 @@ package zstack
import (
"fmt"
"yunion.io/x/onecloud/pkg/multicloud"
"github.com/pkg/errors"
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/pkg/util/netutils"
)
type SVirtualIP struct {
multicloud.SNetworkInterfaceBase
region *SRegion
ZStackBasic
IPRangeUUID string `json:"ipRangeUuid"`
L3NetworkUUID string `json:"l3NetworkUuid"`
@@ -36,6 +44,74 @@ type SVirtualIP struct {
ZStackTime
}
type SInterfaceIP struct {
IP string
L3NetworkUUID string
IPRangeUUID string
}
func (ip *SInterfaceIP) GetIP() string {
return ip.IP
}
func (ip *SInterfaceIP) GetINetworkId() string {
return fmt.Sprintf("%s/%s", ip.L3NetworkUUID, ip.IPRangeUUID)
}
func (ip *SInterfaceIP) IsPrimary() bool {
return true
}
func (ip *SInterfaceIP) GetGlobalId() string {
return ip.IP
}
func (vip *SVirtualIP) GetName() string {
if len(vip.Name) > 0 {
return vip.Name
}
return vip.UUID
}
func (vip *SVirtualIP) GetId() string {
return vip.UUID
}
func (vip *SVirtualIP) GetGlobalId() string {
return vip.UUID
}
func (vip *SVirtualIP) GetMacAddress() string {
ip, _ := netutils.NewIPV4Addr(vip.IP)
return ip.ToMac("00:16:")
}
func (vip *SVirtualIP) GetAssociateType() string {
switch vip.UseFor {
case "LoadBalancer":
return api.NETWORK_INTERFACE_ASSOCIATE_TYPE_LOADBALANCER
case "Eip":
return api.NETWORK_INTERFACE_ASSOCIATE_TYPE_RESERVED
}
return vip.UseFor
}
func (vip *SVirtualIP) GetAssociateId() string {
return vip.UsedIPUUID
}
func (vip *SVirtualIP) GetStatus() string {
if vip.State == "Enabled" {
return api.NETWORK_INTERFACE_STATUS_AVAILABLE
}
return api.NETWORK_INTERFACE_STATUS_UNKNOWN
}
func (vip *SVirtualIP) GetICloudInterfaceAddresses() ([]cloudprovider.ICloudInterfaceAddress, error) {
ip := &SInterfaceIP{IP: vip.IP, IPRangeUUID: vip.IPRangeUUID, L3NetworkUUID: vip.L3NetworkUUID}
return []cloudprovider.ICloudInterfaceAddress{ip}, nil
}
func (region *SRegion) GetVirtualIP(vipId string) (*SVirtualIP, error) {
vip := &SVirtualIP{}
return vip, region.client.getResource("vips", vipId, vip)
@@ -84,3 +160,18 @@ func (region *SRegion) CreateVirtualIP(name, desc, ip string, l3Id string) (*SVi
func (region *SRegion) DeleteVirtualIP(vipId string) error {
return region.client.delete("vips", vipId, "")
}
func (region *SRegion) GetINetworkInterfaces() ([]cloudprovider.ICloudNetworkInterface, error) {
vips, err := region.GetVirtualIPs("")
if err != nil {
return nil, errors.Wrap(err, "region.GetVirtualIPs")
}
ret := []cloudprovider.ICloudNetworkInterface{}
for i := 0; i < len(vips); i++ {
if vips[i].UseFor != "Eip" {
vips[i].region = region
ret = append(ret, &vips[i])
}
}
return ret, nil
}