Merge pull request #9298 from ioito/hotfix/qx-openstack-network

fix(region): support openstack subnet allocation pools
This commit is contained in:
Zexi Li
2020-12-10 17:17:29 +08:00
committed by GitHub
6 changed files with 139 additions and 22 deletions
+8 -8
View File
@@ -37,12 +37,12 @@ func init() {
taskman.RegisterTask(NetworkDeleteTask{})
}
func (self *NetworkDeleteTask) taskFailed(ctx context.Context, network *models.SNetwork, reason jsonutils.JSONObject) {
log.Errorf("network delete task fail: %s", reason)
network.SetStatus(self.UserCred, api.NETWORK_STATUS_DELETE_FAILED, reason.String())
db.OpsLog.LogEvent(network, db.ACT_ALLOCATE_FAIL, reason, self.UserCred)
logclient.AddActionLogWithStartable(self, network, logclient.ACT_DELETE, reason, self.UserCred, false)
self.SetStageFailed(ctx, reason)
func (self *NetworkDeleteTask) taskFailed(ctx context.Context, network *models.SNetwork, err error) {
log.Errorf("network delete task fail: %v", err)
network.SetStatus(self.UserCred, api.NETWORK_STATUS_DELETE_FAILED, err.Error())
db.OpsLog.LogEvent(network, db.ACT_ALLOCATE_FAIL, err, self.UserCred)
logclient.AddActionLogWithStartable(self, network, logclient.ACT_DELETE, err, self.UserCred, false)
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
}
func (self *NetworkDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
@@ -55,13 +55,13 @@ func (self *NetworkDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneMod
if inet != nil {
err = inet.Delete()
if err != nil {
self.taskFailed(ctx, network, jsonutils.NewString(err.Error()))
self.taskFailed(ctx, network, errors.Wrapf(err, "inet.Delete"))
return
}
} else if errors.Cause(err) == cloudprovider.ErrNotFound {
// already deleted, do nothing
} else {
self.taskFailed(ctx, network, jsonutils.NewString(err.Error()))
self.taskFailed(ctx, network, errors.Wrapf(err, "network.GetINetwork"))
return
}
+6 -2
View File
@@ -215,8 +215,11 @@ func (eip *SEipAddress) GetINetworkId() string {
return ""
}
for _, network := range networks {
if network.Contains(eip.FloatingIPAddress) {
return network.Id
for _, pool := range network.AllocationPools {
if pool.Contains(eip.FloatingIPAddress) {
network.AllocationPools = []AllocationPool{pool}
return network.GetGlobalId()
}
}
}
log.Errorf("failed to find eip %s(%s) networkId", eip.FloatingIPAddress, eip.FloatingNetworkId)
@@ -244,6 +247,7 @@ func (eip *SEipAddress) GetProjectId() string {
}
func (region *SRegion) CreateEip(vpcId, networkId, ip string, projectId string) (*SEipAddress, error) {
_, networkId = getNetworkId(networkId)
params := map[string]map[string]string{
"floatingip": map[string]string{
"floating_network_id": vpcId,
+10 -1
View File
@@ -19,6 +19,7 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/onecloud/pkg/cloudprovider"
@@ -94,7 +95,15 @@ func (nic *SInstancePort) GetINetwork() cloudprovider.ICloudNetwork {
log.Errorf("failed to found network by %s error: %v", nic.FixedIps[i].SubnetId, err)
return nil
}
return network
for _, pool := range network.AllocationPools {
start, _ := netutils.NewIPV4Addr(pool.Start)
end, _ := netutils.NewIPV4Addr(pool.End)
ipPool := netutils.NewIPV4AddrRange(start, end)
ip, _ := netutils.NewIPV4Addr(nic.FixedIps[i].IpAddress)
ipPool.Contains(ip)
network.AllocationPools = []AllocationPool{pool}
return network
}
}
}
return nil
+88 -8
View File
@@ -17,6 +17,7 @@ package openstack
import (
"fmt"
"net/url"
"strings"
"time"
"github.com/pkg/errors"
@@ -31,8 +32,38 @@ import (
)
type AllocationPool struct {
Start string
End string
Start string `json:"start"`
End string `json:"end"`
}
func (p AllocationPool) IsValid() bool {
for _, ip := range []string{p.Start, p.End} {
_, err := netutils.NewIPV4Addr(ip)
if err != nil {
return false
}
}
return true
}
func (p AllocationPool) Equals(s AllocationPool) bool {
return p.Start == s.Start && p.End == s.End
}
func (p AllocationPool) Contains(ip string) bool {
start, err := netutils.NewIPV4Addr(p.Start)
if err != nil {
return false
}
end, err := netutils.NewIPV4Addr(p.End)
if err != nil {
return false
}
addr, err := netutils.NewIPV4Addr(ip)
if err != nil {
return false
}
return netutils.NewIPV4AddrRange(start, end).Contains(addr)
}
type SNextLinks []SNextLink
@@ -102,6 +133,9 @@ func (network *SNetwork) GetName() string {
}
func (network *SNetwork) GetGlobalId() string {
if len(network.AllocationPools) > 0 {
return fmt.Sprintf("%s|%s-%s", network.Id, network.AllocationPools[0].Start, network.AllocationPools[0].End)
}
return network.Id
}
@@ -114,7 +148,29 @@ func (network *SNetwork) GetStatus() string {
}
func (network *SNetwork) Delete() error {
return network.wire.zone.region.DeleteNetwork(network.Id)
nw, err := network.wire.zone.region.GetNetwork(network.Id)
if err != nil {
return errors.Wrapf(err, "GetNetwork(%s)", network.Id)
}
if len(nw.AllocationPools) <= 1 || len(network.AllocationPools) == 0 {
return network.wire.zone.region.DeleteNetwork(network.Id)
}
pools := []AllocationPool{}
for i := range nw.AllocationPools {
if nw.AllocationPools[i].Equals(network.AllocationPools[0]) {
continue
}
pools = append(pools, nw.AllocationPools[i])
}
params := map[string]interface{}{
"subnet": map[string]interface{}{
"allocation_pools": pools,
},
}
resource := fmt.Sprintf("/v2.0/subnets/%s", network.Id)
_, err = network.wire.zone.region.vpcUpdate(resource, jsonutils.Marshal(params))
return err
}
func (region *SRegion) DeleteNetwork(networkId string) error {
@@ -156,11 +212,12 @@ func (network *SNetwork) GetIPRange() netutils.IPV4AddrRange {
}
func (network *SNetwork) Contains(ipAddr string) bool {
ip, err := netutils.NewIPV4Addr(ipAddr)
if err != nil {
return false
for _, pool := range network.AllocationPools {
if pool.Contains(ipAddr) {
return true
}
}
return network.GetIPRange().Contains(ip)
return false
}
func (network *SNetwork) GetIpMask() int8 {
@@ -183,7 +240,21 @@ func (network *SNetwork) GetServerType() string {
return api.NETWORK_TYPE_GUEST
}
func getNetworkId(networkId string) (AllocationPool, string) {
pool := AllocationPool{}
if !strings.Contains(networkId, "|") {
return pool, networkId
}
info := strings.Split(networkId, "|")
networkId = info[0]
ipInfo := strings.Split(info[1], "-")
pool.Start, pool.End = ipInfo[0], ipInfo[1]
return pool, networkId
}
func (region *SRegion) GetNetwork(networkId string) (*SNetwork, error) {
var pool AllocationPool
pool, networkId = getNetworkId(networkId)
resource := fmt.Sprintf("/v2.0/subnets/%s", networkId)
resp, err := region.vpcGet(resource)
if err != nil {
@@ -194,7 +265,16 @@ func (region *SRegion) GetNetwork(networkId string) (*SNetwork, error) {
if err != nil {
return nil, err
}
return network, nil
if len(pool.Start) == 0 && len(pool.End) == 0 {
return network, nil
}
for _, _pool := range network.AllocationPools {
if _pool.Equals(pool) {
network.AllocationPools = []AllocationPool{pool}
return network, nil
}
}
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", networkId)
}
func (region *SRegion) GetNetworks(vpcId string) ([]SNetwork, error) {
+14 -1
View File
@@ -39,6 +39,8 @@ type ExtraDhcpOpt struct {
}
type SFixedIP struct {
port *SPort
IpAddress string
SubnetID string
}
@@ -52,7 +54,17 @@ func (fixip *SFixedIP) GetIP() string {
}
func (fixip *SFixedIP) GetINetworkId() string {
return fixip.SubnetID
network, err := fixip.port.region.GetNetwork(fixip.SubnetID)
if err != nil {
return ""
}
for _, pool := range network.AllocationPools {
if pool.Contains(fixip.IpAddress) {
network.AllocationPools = []AllocationPool{pool}
return network.GetGlobalId()
}
}
return ""
}
func (fixip *SFixedIP) IsPrimary() bool {
@@ -137,6 +149,7 @@ func (port *SPort) GetStatus() string {
func (port *SPort) GetICloudInterfaceAddresses() ([]cloudprovider.ICloudInterfaceAddress, error) {
address := []cloudprovider.ICloudInterfaceAddress{}
for i := 0; i < len(port.FixedIps); i++ {
port.FixedIps[i].port = port
address = append(address, &port.FixedIps[i])
}
return address, nil
+13 -2
View File
@@ -87,14 +87,25 @@ func (wire *SWire) GetINetworkById(netid string) (cloudprovider.ICloudNetwork, e
return networks[i], nil
}
}
return nil, cloudprovider.ErrNotFound
return nil, errors.Wrapf(cloudprovider.ErrNotFound, netid)
}
func (wire *SWire) GetINetworks() ([]cloudprovider.ICloudNetwork, error) {
networks, err := wire.vpc.region.GetNetworks(wire.vpc.Id)
_networks, err := wire.vpc.region.GetNetworks(wire.vpc.Id)
if err != nil {
return nil, errors.Wrapf(err, "GetNetworks(%s)", wire.vpc.Id)
}
networks := []SNetwork{}
for i := range _networks {
pools := _networks[i].AllocationPools
for j := range pools {
if !pools[j].IsValid() {
continue
}
_networks[i].AllocationPools = []AllocationPool{pools[j]}
networks = append(networks, _networks[i])
}
}
inetworks := []cloudprovider.ICloudNetwork{}
for i := range networks {
networks[i].wire = wire