mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-06-07 23:09:17 +08:00
feat(region): bind network ip macs
Signed-off-by: wanyaoqi <d3lx.yq@gmail.com>
This commit is contained in:
33
cmd/climc/shell/compute/network_ip_mac.go
Normal file
33
cmd/climc/shell/compute/network_ip_mac.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
cmd := shell.NewResourceCmd(&modules.NetworkIpMacs)
|
||||
cmd.List(&options.NetworkIpMacListOptions{})
|
||||
cmd.Update(&options.NetworkIpMacUpdateOptions{})
|
||||
cmd.Show(&options.NetworkIpMacIdOptions{})
|
||||
cmd.Delete(&options.NetworkIpMacIdOptions{})
|
||||
cmd.Create(&options.NetworkIpMacCreateOptions{})
|
||||
type NetworkIpMacBatchCreateOptions struct {
|
||||
NETWORK string `help:"network id" json:"network_id"`
|
||||
IpMac map[string]string `help:"ip mac map" json:"ip_mac"`
|
||||
}
|
||||
R(&NetworkIpMacBatchCreateOptions{},
|
||||
"network-ip-mac-batch-create",
|
||||
"Network ip mac bind batch create",
|
||||
func(s *mcclient.ClientSession, args *NetworkIpMacBatchCreateOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
_, err := modules.NetworkIpMacs.PerformClassAction(s, "batch-create", params)
|
||||
return err
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -69,6 +69,14 @@ type NetworkFilterListInput struct {
|
||||
NetworkFilterListBase
|
||||
}
|
||||
|
||||
type NetworkIpMacListInput struct {
|
||||
apis.StandaloneAnonResourceListInput
|
||||
|
||||
NetworkId string `json:"network_id"`
|
||||
MacAddr []string `json:"mac_addr"`
|
||||
IpAddr []string `json:"ip_addr"`
|
||||
}
|
||||
|
||||
type NetworkListInput struct {
|
||||
apis.SharableVirtualResourceListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
@@ -151,6 +159,14 @@ type NetworkResourceInfo struct {
|
||||
WireResourceInfo
|
||||
}
|
||||
|
||||
type NetworkIpMacCreateInput struct {
|
||||
apis.StandaloneAnonResourceCreateInput
|
||||
|
||||
NetworkId string `json:"network_id"`
|
||||
MacAddr string `json:"mac_addr"`
|
||||
IpAddr string `json:"ip_addr"`
|
||||
}
|
||||
|
||||
type NetworkCreateInput struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
|
||||
@@ -280,6 +296,14 @@ type NetworkDetails struct {
|
||||
Schedtags []SchedtagShortDescDetails `json:"schedtags"`
|
||||
}
|
||||
|
||||
type NetworkIpMacDetails struct {
|
||||
apis.StandaloneAnonResourceDetails
|
||||
|
||||
NetworkId string `json:"network_id"`
|
||||
IpAddr string `json:"ip_addr"`
|
||||
MacAddr string `json:"mac_addr"`
|
||||
}
|
||||
|
||||
type NetworkReserveIpInput struct {
|
||||
apis.Meta
|
||||
|
||||
@@ -345,6 +369,13 @@ type NetworkSyncInput struct {
|
||||
apis.Meta
|
||||
}
|
||||
|
||||
type NetworkIpMacUpdateInput struct {
|
||||
apis.StandaloneAnonResourceBaseUpdateInput
|
||||
|
||||
MacAddr string `json:"mac_addr"`
|
||||
IpAddr string `json:"ip_addr"`
|
||||
}
|
||||
|
||||
type NetworkUpdateInput struct {
|
||||
apis.SharableVirtualResourceBaseUpdateInput
|
||||
|
||||
@@ -392,3 +423,8 @@ type NetworkSetBgpTypeInput struct {
|
||||
// example: ChinaTelecom, BGP, etc.
|
||||
BgpType string `json:"bgp_type"`
|
||||
}
|
||||
|
||||
type NetworkIpMacBatchCreateInput struct {
|
||||
NetworkId string `json:"network_id"`
|
||||
IpMac map[string]string `json:"ip_mac"`
|
||||
}
|
||||
|
||||
@@ -3194,6 +3194,9 @@ func (args *Attach2NetworkArgs) onceArgs(i int) attach2NetworkOnceArgs {
|
||||
|
||||
pendingUsage: args.PendingUsage,
|
||||
}
|
||||
if ipBindMac := NetworkIpMacManager.GetMacFromIp(r.network.Id, r.ipAddr); ipBindMac != "" {
|
||||
r.nicConf.Mac = ipBindMac
|
||||
}
|
||||
if i > 0 {
|
||||
r.ipAddr = ""
|
||||
r.bwLimit = 0
|
||||
|
||||
@@ -43,6 +43,7 @@ func InitDB() error {
|
||||
SecurityGroupCacheManager,
|
||||
NetworkManager,
|
||||
NetworkAddressManager,
|
||||
NetworkIpMacManager,
|
||||
GuestManager,
|
||||
HostManager,
|
||||
LoadbalancerCertificateManager,
|
||||
|
||||
276
pkg/compute/models/network_ip_mac.go
Normal file
276
pkg/compute/models/network_ip_mac.go
Normal file
@@ -0,0 +1,276 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SNetworkIpMacManager struct {
|
||||
db.SStandaloneAnonResourceBaseManager
|
||||
}
|
||||
|
||||
var NetworkIpMacManager *SNetworkIpMacManager
|
||||
|
||||
func GetNetworkIpMacManager() *SNetworkIpMacManager {
|
||||
if NetworkIpMacManager != nil {
|
||||
return NetworkIpMacManager
|
||||
}
|
||||
NetworkIpMacManager = &SNetworkIpMacManager{
|
||||
SStandaloneAnonResourceBaseManager: db.NewStandaloneAnonResourceBaseManager(
|
||||
SNetworkIpMac{},
|
||||
"network_ip_macs_tbl",
|
||||
"network_ip_mac",
|
||||
"network_ip_macs",
|
||||
),
|
||||
}
|
||||
NetworkIpMacManager.SetVirtualObject(NetworkIpMacManager)
|
||||
return NetworkIpMacManager
|
||||
}
|
||||
|
||||
func init() {
|
||||
GetNetworkIpMacManager()
|
||||
}
|
||||
|
||||
type SNetworkIpMac struct {
|
||||
db.SStandaloneAnonResourceBase
|
||||
|
||||
NetworkId string `width:"36" charset:"ascii" nullable:"false" list:"user" index:"true" create:"required"`
|
||||
// MAC地址
|
||||
MacAddr string `width:"32" charset:"ascii" nullable:"false" list:"user" index:"true" create:"required"`
|
||||
// IPv4地址
|
||||
IpAddr string `width:"16" charset:"ascii" nullable:"false" list:"user" index:"true" create:"required"`
|
||||
}
|
||||
|
||||
func (manager *SNetworkIpMacManager) NetworkMacAddrInUse(networkId, macAddr string) (bool, error) {
|
||||
count, err := manager.Query().
|
||||
Equals("network_id", networkId).
|
||||
Equals("mac_addr", macAddr).CountWithError()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
func (manager *SNetworkIpMacManager) NetworkIpAddrInUse(networkId, ipAddr string) (bool, error) {
|
||||
count, err := manager.Query().
|
||||
Equals("network_id", networkId).
|
||||
Equals("ip_addr", ipAddr).CountWithError()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
func (manager *SNetworkIpMacManager) ValidateCreateData(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.NetworkIpMacCreateInput,
|
||||
) (api.NetworkIpMacCreateInput, error) {
|
||||
if input.NetworkId == "" {
|
||||
return input, httperrors.NewMissingParameterError("network_id")
|
||||
}
|
||||
if input.IpAddr == "" {
|
||||
return input, httperrors.NewMissingParameterError("ip_addr")
|
||||
}
|
||||
if input.MacAddr == "" {
|
||||
return input, httperrors.NewMissingParameterError("mac_addr")
|
||||
}
|
||||
|
||||
iNetwork, err := NetworkManager.FetchByIdOrName(userCred, input.NetworkId)
|
||||
if err == sql.ErrNoRows {
|
||||
return input, httperrors.NewNotFoundError("network %s not found", input.NetworkId)
|
||||
} else if err != nil {
|
||||
return input, errors.Wrap(err, "fetch network")
|
||||
}
|
||||
network := iNetwork.(*SNetwork)
|
||||
if network.ServerType != api.NETWORK_TYPE_GUEST {
|
||||
return input, httperrors.NewBadRequestError("network type %s can't set ip mac", network.ServerType)
|
||||
}
|
||||
|
||||
input.NetworkId = network.Id
|
||||
input.MacAddr = strings.ToLower(input.MacAddr)
|
||||
return input, manager.validateIpMac(input.IpAddr, input.MacAddr, network)
|
||||
}
|
||||
|
||||
func (self *SNetworkIpMac) ValidateUpdateData(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, input api.NetworkIpMacUpdateInput,
|
||||
) (api.NetworkIpMacUpdateInput, error) {
|
||||
if input.IpAddr == "" && input.MacAddr == "" {
|
||||
return input, httperrors.NewInputParameterError("missing update field")
|
||||
}
|
||||
|
||||
if input.IpAddr != "" {
|
||||
iNetwork, err := NetworkManager.FetchByIdOrName(userCred, self.NetworkId)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "fetch network")
|
||||
}
|
||||
network := iNetwork.(*SNetwork)
|
||||
if !network.Contains(input.IpAddr) {
|
||||
return input, errors.Errorf("network %s not contains ip addr %s", network.GetName(), input.IpAddr)
|
||||
}
|
||||
if ipInUse, err := NetworkIpMacManager.NetworkIpAddrInUse(self.NetworkId, input.IpAddr); err != nil {
|
||||
return input, errors.Wrap(err, "check ip addr in use")
|
||||
} else if ipInUse {
|
||||
return input, errors.Errorf("ip addr %s is in use", input.IpAddr)
|
||||
}
|
||||
} else {
|
||||
input.IpAddr = self.IpAddr
|
||||
}
|
||||
|
||||
if input.MacAddr != "" {
|
||||
if !utils.IsMatchMacAddr(input.MacAddr) {
|
||||
return input, errors.Errorf("mac address %s is not valid", input.MacAddr)
|
||||
}
|
||||
input.MacAddr = strings.ToLower(input.MacAddr)
|
||||
if macInUse, err := NetworkIpMacManager.NetworkMacAddrInUse(self.NetworkId, input.MacAddr); err != nil {
|
||||
return input, errors.Wrap(err, "check mac addr in use")
|
||||
} else if macInUse {
|
||||
return input, errors.Errorf("mac addr %s is in use", input.MacAddr)
|
||||
}
|
||||
} else {
|
||||
input.MacAddr = self.MacAddr
|
||||
}
|
||||
|
||||
if gn, err := GuestnetworkManager.getGuestNicByIP(self.NetworkId, input.IpAddr); err != nil {
|
||||
return input, errors.Wrap(err, "failed get guest nic")
|
||||
} else if gn != nil && gn.MacAddr != input.MacAddr {
|
||||
return input, errors.Errorf("input ip mac conflict with guest %s nic %d", gn.GuestId, gn.Index)
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SNetworkIpMacManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
input api.NetworkIpMacListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SStandaloneAnonResourceBaseManager.ListItemFilter(ctx, q, userCred, input.StandaloneAnonResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStandaloneAnonResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
if input.NetworkId != "" {
|
||||
iNetwork, err := NetworkManager.FetchByIdOrName(userCred, input.NetworkId)
|
||||
if err != nil {
|
||||
return q, errors.Wrap(err, "fetch network")
|
||||
}
|
||||
q = q.Equals("network_id", iNetwork.GetId())
|
||||
}
|
||||
if input.MacAddr != nil {
|
||||
q = q.In("mac_addr", input.MacAddr)
|
||||
}
|
||||
if input.IpAddr != nil {
|
||||
q = q.In("ip_addr", input.IpAddr)
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SNetworkIpMacManager) GetMacFromIp(networkId, ipAddr string) string {
|
||||
q := manager.Query("mac_addr").Equals("network_id", networkId).Equals("ip_addr", ipAddr)
|
||||
if q.Count() != 1 {
|
||||
return ""
|
||||
}
|
||||
var nim = new(SNetworkIpMac)
|
||||
if err := q.First(nim); err != nil {
|
||||
log.Errorf("failed get mac addr form ip %s: %s", ipAddr, err)
|
||||
return ""
|
||||
}
|
||||
return nim.MacAddr
|
||||
}
|
||||
|
||||
func (manager *SNetworkIpMacManager) validateIpMac(ip, mac string, network *SNetwork) error {
|
||||
if !network.Contains(ip) {
|
||||
return httperrors.NewBadRequestError("network %s not contains ip addr %s", network.GetName(), ip)
|
||||
}
|
||||
if ipInUse, err := manager.NetworkIpAddrInUse(network.Id, ip); err != nil {
|
||||
return errors.Wrap(err, "check ip addr in use")
|
||||
} else if ipInUse {
|
||||
return httperrors.NewBadRequestError("ip addr %s is in use", ip)
|
||||
}
|
||||
|
||||
if !utils.IsMatchMacAddr(mac) {
|
||||
return httperrors.NewBadRequestError("mac address %s is not valid", mac)
|
||||
}
|
||||
if macInUse, err := manager.NetworkMacAddrInUse(network.Id, mac); err != nil {
|
||||
return errors.Wrap(err, "check mac addr in use")
|
||||
} else if macInUse {
|
||||
return httperrors.NewBadRequestError("mac addr %s is in use", mac)
|
||||
}
|
||||
|
||||
if gn, err := GuestnetworkManager.getGuestNicByIP(network.Id, ip); err != nil {
|
||||
return errors.Wrap(err, "failed get guest nic")
|
||||
} else if gn != nil && gn.MacAddr != mac {
|
||||
return httperrors.NewBadRequestError("input ip mac conflict with guest %s nic %d", gn.GuestId, gn.Index)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SNetworkIpMacManager) PerformBatchCreate(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.NetworkIpMacBatchCreateInput,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
iNetwork, err := NetworkManager.FetchByIdOrName(userCred, input.NetworkId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetch network")
|
||||
}
|
||||
network := iNetwork.(*SNetwork)
|
||||
if network.ServerType != api.NETWORK_TYPE_GUEST {
|
||||
return nil, errors.Errorf("network type %s can't set ip mac", network.ServerType)
|
||||
}
|
||||
input.NetworkId = network.Id
|
||||
|
||||
var errs = []error{}
|
||||
for ip, mac := range input.IpMac {
|
||||
if err := manager.validateIpMac(ip, mac, network); err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
nim := &SNetworkIpMac{
|
||||
NetworkId: input.NetworkId,
|
||||
IpAddr: ip,
|
||||
MacAddr: mac,
|
||||
}
|
||||
if err := manager.TableSpec().Insert(ctx, nim); err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if len(errs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.NewAggregate(errs)
|
||||
}
|
||||
func (manager *SNetworkIpMacManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.NetworkIpMacDetails {
|
||||
rows := make([]api.NetworkIpMacDetails, len(objs))
|
||||
|
||||
baseRows := manager.SStandaloneAnonResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
|
||||
for i := range rows {
|
||||
rows[i] = api.NetworkIpMacDetails{
|
||||
StandaloneAnonResourceDetails: baseRows[i],
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
@@ -124,6 +124,7 @@ func InitHandlers(app *appsrv.Application) {
|
||||
models.DiskManager,
|
||||
models.NetworkManager,
|
||||
models.NetworkAddressManager,
|
||||
models.NetworkIpMacManager,
|
||||
models.ReservedipManager,
|
||||
models.KeypairManager,
|
||||
models.IsolatedDeviceManager,
|
||||
|
||||
18
pkg/mcclient/modules/compute/mod_network_ip_macs.go
Normal file
18
pkg/mcclient/modules/compute/mod_network_ip_macs.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
var (
|
||||
NetworkIpMacs modulebase.ResourceManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
NetworkIpMacs = modules.NewComputeManager("network_ip_mac", "network_ip_macs",
|
||||
[]string{"ID", "Network_id", "Ip_addr", "Mac_addr"},
|
||||
[]string{})
|
||||
|
||||
modules.RegisterCompute(&NetworkIpMacs)
|
||||
}
|
||||
@@ -16,6 +16,7 @@ package options
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
)
|
||||
@@ -151,3 +152,61 @@ func (opts *NetworkIdOptions) GetId() string {
|
||||
func (opts *NetworkIdOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type NetworkIpMacIdOptions struct {
|
||||
ID string `help:"ID or Name of the network_ip_mac to show"`
|
||||
}
|
||||
|
||||
func (opts *NetworkIpMacIdOptions) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *NetworkIpMacIdOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type NetworkIpMacListOptions struct {
|
||||
BaseListOptions
|
||||
|
||||
Network string `help:"search networks" json:"network_id"`
|
||||
MacAddr []string `help:"search by mac addr"`
|
||||
IpAddr []string `help:"search by ip addr"`
|
||||
}
|
||||
|
||||
func (opts *NetworkIpMacListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type NetworkIpMacUpdateOptions struct {
|
||||
ID string `help:"ID or Name of resource to update"`
|
||||
|
||||
MacAddr string `help:"update mac addr"`
|
||||
IpAddr string `help:"update ip addr"`
|
||||
}
|
||||
|
||||
func (opts *NetworkIpMacUpdateOptions) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *NetworkIpMacUpdateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type NetworkIpMacCreateOptions struct {
|
||||
NETWORK string `help:"network id" json:"network_id"`
|
||||
MACADDR string `help:"mac address" json:"mac_addr"`
|
||||
IPADDR string `help:"ip address" json:"ip_addr"`
|
||||
}
|
||||
|
||||
func (opts *NetworkIpMacCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
if opts.NETWORK == "" {
|
||||
return nil, errors.Errorf("missing network params")
|
||||
}
|
||||
if opts.MACADDR == "" {
|
||||
return nil, errors.Errorf("missing mac_addr params")
|
||||
}
|
||||
if opts.IPADDR == "" {
|
||||
return nil, errors.Errorf("missing ip_addr params")
|
||||
}
|
||||
return ListStructToParams(opts)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user