Skip to content

Commit

Permalink
guestnetworks,hosts: add alloc mapped ip addr for use in onecloud vpc
Browse files Browse the repository at this point in the history
  • Loading branch information
yousong committed Apr 24, 2020
1 parent 12639e0 commit 3142957
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 1 deletion.
16 changes: 15 additions & 1 deletion pkg/compute/models/guestnetworks.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ type SGuestnetwork struct {

// bind配对网卡MAC地址
TeamWith string `width:"32" charset:"ascii" nullable:"false" list:"user"`

// IPv4映射地址,当子网属于私有云vpc的时候分配,用于访问外网
MappedIpAddr string `width:"16" charset:"ascii" nullable:"true" list:"user"`
}

func (manager *SGuestnetworkManager) GetSlaveFieldName() string {
Expand Down Expand Up @@ -195,7 +198,8 @@ func (manager *SGuestnetworkManager) GenerateMac(netId string, suggestion string
return "", fmt.Errorf("maximal retry reached")
}

func (manager *SGuestnetworkManager) newGuestNetwork(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, network *SNetwork,
func (manager *SGuestnetworkManager) newGuestNetwork(
ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, network *SNetwork,
index int8, address string, mac string, driver string, bwLimit int,
virtual bool, reserved bool,
allocDir api.IPAllocationDirection,
Expand Down Expand Up @@ -254,6 +258,16 @@ func (manager *SGuestnetworkManager) newGuestNetwork(ctx context.Context, userCr
}
gn.IpAddr = ipAddr
}

if vpc := network.GetVpc(); vpc == nil {
return nil, fmt.Errorf("cannot find vpc of network %s(%s)", network.Id, network.Name)
} else if vpc.Id != api.DEFAULT_VPC_ID && vpc.GetProviderName() == api.CLOUD_PROVIDER_ONECLOUD {
var err error
gn.MappedIpAddr, err = GuestnetworkManager.allocMappedIpAddr(ctx)
if err != nil {
return nil, err
}
}
}
ifname, err = gn.checkOrAllocateIfname(network, ifname)
if err != nil {
Expand Down
20 changes: 20 additions & 0 deletions pkg/compute/models/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ type SHost struct {

// 主机启动模式, 可能值位PXE和ISO
BootMode string `width:"8" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`

// IPv4地址,作为么有云vpc访问外网时的网关
OvnMappedIpAddr string `width:"16" charset:"ascii" nullable:"true" list:"user"`
}

func (manager *SHostManager) GetContextManagers() [][]db.IModelManager {
Expand Down Expand Up @@ -3122,6 +3125,23 @@ func (self *SHost) PostUpdate(ctx context.Context, userCred mcclient.TokenCreden
if data.Contains("cpu_cmtbound") || data.Contains("mem_cmtbound") {
self.ClearSchedDescCache()
}

if self.OvnVersion != "" && self.OvnMappedIpAddr == "" {
addr, err := HostManager.allocOvnMappedIpAddr(ctx)
if err != nil {
log.Errorf("host %s(%s): alloc vpc mapped addr: %v",
self.Name, self.Id, err)
return
}
if _, err := db.Update(self, func() error {
self.OvnMappedIpAddr = addr
return nil
}); err != nil {
log.Errorf("host %s(%s): db update vpc mapped addr: %v",
self.Name, self.Id, err)
return
}
}
}

func (self *SHost) UpdateDnsRecords(isAdd bool) {
Expand Down
93 changes: 93 additions & 0 deletions pkg/compute/models/vpcs_mapped_address.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package models

import (
"context"

"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/utils"

api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
)

const (
errMappedIpExhausted = errors.Error("mapped ip exhaused")
)

func (man *SGuestnetworkManager) allocMappedIpAddr(ctx context.Context) (string, error) {
const (
LOCK_CLASS = "guestnetworks-mapped-addr"
LOCK_OBJ = "the-addr"
)
lockman.LockRawObject(ctx, LOCK_CLASS, LOCK_OBJ)
defer lockman.ReleaseRawObject(ctx, LOCK_CLASS, LOCK_OBJ)
return man.allocMappedIpAddr_(ctx)
}

func (man *SGuestnetworkManager) allocMappedIpAddr_(ctx context.Context) (string, error) {
var (
used []string
ip string
)

q := man.Query("mapped_ip_addr").IsNotEmpty("mapped_ip_addr")
rows, err := q.Rows()
if err != nil {
return "", err
}
for rows.Next() {
if err := rows.Scan(&ip); err != nil {
return "", errors.Wrap(err, "scan guest mapped ip")
}
used = append(used, ip)
}

sip := api.VpcMappedIPStart()
eip := api.VpcMappedIPEnd()
for i := sip; i <= eip; i++ {
s := i.String()
if !utils.IsInStringArray(s, used) {
return s, nil
}
}
return "", errors.Wrap(errMappedIpExhausted, "guests")
}

func (man *SHostManager) allocOvnMappedIpAddr(ctx context.Context) (string, error) {
const (
LOCK_CLASS = "hosts-vpc-mapped-addr"
LOCK_OBJ = "the-addr"
)
lockman.LockRawObject(ctx, LOCK_CLASS, LOCK_OBJ)
defer lockman.ReleaseRawObject(ctx, LOCK_CLASS, LOCK_OBJ)
return man.allocOvnMappedIpAddr_(ctx)
}

func (man *SHostManager) allocOvnMappedIpAddr_(ctx context.Context) (string, error) {
var (
used []string
ip string
)

q := man.Query("ovn_mapped_ip_addr").IsNotEmpty("ovn_mapped_ip_addr")
rows, err := q.Rows()
if err != nil {
return "", err
}
for rows.Next() {
if err := rows.Scan(&ip); err != nil {
return "", errors.Wrap(err, "scan host mapped ip")
}
used = append(used, ip)
}

sip := api.VpcMappedHostIPStart()
eip := api.VpcMappedHostIPEnd()
for i := sip; i <= eip; i++ {
s := i.String()
if !utils.IsInStringArray(s, used) {
return s, nil
}
}
return "", errors.Wrap(errMappedIpExhausted, "hosts")
}

0 comments on commit 3142957

Please sign in to comment.