Merge pull request #6364 from yousong/feature/yousong-eip

Feature/yousong eip
This commit is contained in:
Zexi Li
2020-06-03 17:23:24 +08:00
committed by GitHub
47 changed files with 1999 additions and 414 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
FROM registry.cn-beijing.aliyuncs.com/yunionio/host-base:v0.1.0
FROM registry.cn-beijing.aliyuncs.com/yunionio/host-base:v0.2.0
MAINTAINER "Yaoqi Wan wanyaoqi@yunionyun.com"
+1 -1
View File
@@ -1,4 +1,4 @@
FROM registry.cn-beijing.aliyuncs.com/yunionio/openvswitch:2.9.6-1
FROM registry.cn-beijing.aliyuncs.com/yunionio/openvswitch:2.10.4-0
MAINTAINER "Yousong Zhou <zhouyousong@yunion.cn>"
+8 -4
View File
@@ -46,9 +46,9 @@ func init() {
})
type EipCreateOptions struct {
MANAGER string `help:"cloud provider"`
REGION string `help:"cloud region in which EIP is allocated"`
NAME string `help:"name of the EIP"`
Manager string `help:"cloud provider"`
Region string `help:"cloud region in which EIP is allocated"`
Bandwidth int `help:"Bandwidth in Mbps"`
Ip string `help:"IP address of the EIP"`
Network string `help:"Network of the EIP"`
@@ -56,9 +56,13 @@ func init() {
}
R(&EipCreateOptions{}, "eip-create", "Create an EIP", func(s *mcclient.ClientSession, args *EipCreateOptions) error {
params := jsonutils.NewDict()
params.Add(jsonutils.NewString(args.MANAGER), "manager")
params.Add(jsonutils.NewString(args.REGION), "region")
params.Add(jsonutils.NewString(args.NAME), "name")
if args.Region != "" {
params.Add(jsonutils.NewString(args.Region), "region")
}
if args.Manager != "" {
params.Add(jsonutils.NewString(args.Manager), "manager")
}
if args.Bandwidth != 0 {
params.Add(jsonutils.NewInt(int64(args.Bandwidth)), "bandwidth")
}
+3 -3
View File
@@ -37,7 +37,7 @@ func init() {
Region string `help:"search networks belongs to a CloudRegion" json:"cloudregion"`
City string `help:"search networks belongs to a city"`
Usable *bool `help:"search usable networks"`
ServerType string `help:"search networks belongs to a ServerType" choices:"guest|baremetal|container|pxe|ipmi"`
ServerType string `help:"search networks belongs to a ServerType" choices:"baremetal|container|eip|guest|ipmi|pxe"`
Schedtag string `help:"filter networks by schedtag"`
Status string `help:"filter by network status"`
@@ -68,7 +68,7 @@ func init() {
ID string `help:"ID or Name of zone to update"`
Name string `help:"Name of zone"`
Desc string `metavar:"<DESCRIPTION>" help:"Description"`
ServerType string `help:"server type," choices:"baremetal|guest|container|pxe|ipmi"`
ServerType string `help:"server type," choices:"baremetal|container|eip|guest|ipmi|pxe"`
StartIp string `help:"Start ip"`
EndIp string `help:"end ip"`
NetMask int64 `help:"Netmask"`
@@ -227,7 +227,7 @@ func init() {
VlanId int64 `help:"Vlan ID" default:"1"`
IfnameHint string `help:"Hint for ifname generation"`
AllocPolicy string `help:"Address allocation policy" choices:"none|stepdown|stepup|random"`
ServerType string `help:"Server type" choices:"baremetal|guest|container|pxe|ipmi"`
ServerType string `help:"Server type" choices:"baremetal|container|eip|guest|ipmi|pxe"`
Desc string `help:"Description" metavar:"DESCRIPTION"`
}
R(&NetworkCreateOptions{}, "network-create", "Create a virtual network", func(s *mcclient.ClientSession, args *NetworkCreateOptions) error {
+22 -13
View File
@@ -29,9 +29,10 @@ func init() {
type VpcListOptions struct {
options.BaseListOptions
Usable *bool `help:"Filter usable vpcs"`
Region string `help:"ID or Name of region" json:"-"`
Globalvpc string `help:"Filter by globalvpc"`
Usable *bool `help:"Filter usable vpcs"`
Region string `help:"ID or Name of region" json:"-"`
Globalvpc string `help:"Filter by globalvpc"`
ExternalAccessMode string `help:"Filter by external access mode" choices:"distgw|eip|eip-distgw"`
}
R(&VpcListOptions{}, "vpc-list", "List VPCs", func(s *mcclient.ClientSession, opts *VpcListOptions) error {
params, err := options.ListStructToParams(opts)
@@ -58,13 +59,14 @@ func init() {
})
type VpcCreateOptions struct {
REGION string `help:"ID or name of the region where the VPC is created"`
Id string `help:"ID of the new VPC"`
NAME string `help:"Name of the VPC"`
CIDR string `help:"CIDR block"`
Default bool `help:"default VPC for the region" default:"false"`
Desc string `help:"Description of the VPC"`
Manager string `help:"ID or Name of Cloud provider"`
REGION string `help:"ID or name of the region where the VPC is created"`
Id string `help:"ID of the new VPC"`
NAME string `help:"Name of the VPC"`
CIDR string `help:"CIDR block"`
Default bool `help:"default VPC for the region" default:"false"`
Desc string `help:"Description of the VPC"`
Manager string `help:"ID or Name of Cloud provider"`
ExternalAccessMode string `help:"Filter by external access mode" choices:"distgw|eip|eip-distgw" default:"eip-distgw"`
}
R(&VpcCreateOptions{}, "vpc-create", "Create a VPC", func(s *mcclient.ClientSession, args *VpcCreateOptions) error {
params := jsonutils.NewDict()
@@ -73,6 +75,9 @@ func init() {
if len(args.Id) > 0 {
params.Add(jsonutils.NewString(args.Id), "id")
}
if len(args.ExternalAccessMode) > 0 {
params.Add(jsonutils.NewString(args.ExternalAccessMode), "external_access_mode")
}
if len(args.Desc) > 0 {
params.Add(jsonutils.NewString(args.Desc), "description")
}
@@ -112,15 +117,19 @@ func init() {
})
type VpcUpdateOptions struct {
ID string `help:"ID or name of the VPC"`
Name string `help:"New name of the VPC"`
Desc string `help:"Description of the VPC"`
ID string `help:"ID or name of the VPC"`
Name string `help:"New name of the VPC"`
Desc string `help:"Description of the VPC"`
ExternalAccessMode string `help:"Filter by external access mode" choices:"distgw|eip|eip-distgw"`
}
R(&VpcUpdateOptions{}, "vpc-update", "Update a VPC", func(s *mcclient.ClientSession, args *VpcUpdateOptions) error {
params := jsonutils.NewDict()
if len(args.Name) > 0 {
params.Add(jsonutils.NewString(args.Name), "name")
}
if len(args.ExternalAccessMode) > 0 {
params.Add(jsonutils.NewString(args.ExternalAccessMode), "external_access_mode")
}
if len(args.Desc) > 0 {
params.Add(jsonutils.NewString(args.Desc), "description")
}
+1 -1
View File
@@ -129,7 +129,7 @@ require (
yunion.io/x/executor v0.0.0-20200227030256-a18417815e74
yunion.io/x/jsonutils v0.0.0-20200415132054-2bf8a5e94501
yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3
yunion.io/x/ovsdb v0.0.0-20200512112253-a3601d1ee987
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7
yunion.io/x/pkg v0.0.0-20200516092703-0a53bc9270aa
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
yunion.io/x/sqlchemy v0.0.0-20200312002602-1177cd8fbc57
+6
View File
@@ -769,6 +769,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yousong/ovsdb v0.0.0-20200526055947-05168ba66aaf h1:MfwaIeKiVUqeWZSKyO5GwOccti0O/ENZDdqOkB3OPnU=
github.com/yousong/ovsdb v0.0.0-20200526055947-05168ba66aaf/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
github.com/yunionio/go-ceph v0.0.0-20190912101231-6f05a06b3859 h1:wu596gn6sV3j5wy+GDfiG8nwtzIDpalJihfmC/TjoYc=
github.com/yunionio/go-ceph v0.0.0-20190912101231-6f05a06b3859/go.mod h1:8XuBae5AzsgotLArJSewMruYVaQs8AlfsK5jBCG8T9Y=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
@@ -1117,6 +1119,10 @@ yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3 h1:5Wc5hkB8PtMudmHuzCyok960Ru
yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U=
yunion.io/x/ovsdb v0.0.0-20200512112253-a3601d1ee987 h1:BlHpXbNhqG1rZ57io0+XI4L9ckWunn7LHR2JQikGqQg=
yunion.io/x/ovsdb v0.0.0-20200512112253-a3601d1ee987/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
yunion.io/x/ovsdb v0.0.0-20200526062315-c921cb58f76e h1:v5AnakAKVOvYoYEtsTkntcr4MIgawTAI106/5mmaMAs=
yunion.io/x/ovsdb v0.0.0-20200526062315-c921cb58f76e/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7 h1:gjqNa2uQzIEXyySsbvVz0UltTEbGsnFFlvnzOpCfHdo=
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20200302034534-fdf44d54b070/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
+2
View File
@@ -61,6 +61,8 @@ type SElasticipCreateInput struct {
// enum: traffic, bandwidth
ChargeType string `json:"charge_type"`
Mode string `json:"mode"`
// 子网名称或Id
// 私有云创建此参数必传,例如Openstack, ZStack
Network string `json:"network"`
+2
View File
@@ -27,6 +27,7 @@ const (
NETWORK_TYPE_CONTAINER = "container"
NETWORK_TYPE_PXE = "pxe"
NETWORK_TYPE_IPMI = "ipmi"
NETWORK_TYPE_EIP = "eip"
STATIC_ALLOC = "static"
@@ -53,6 +54,7 @@ var (
NETWORK_TYPE_CONTAINER,
NETWORK_TYPE_PXE,
NETWORK_TYPE_IPMI,
NETWORK_TYPE_EIP,
}
REGIONAL_NETWORK_PROVIDERS = []string{
+13
View File
@@ -72,6 +72,16 @@ type VpcCreateInput struct {
// CIDR_BLOCK
CidrBlock string `json:"cidr_block"`
// Vpc外网访问模式
ExternalAccessMode string `json:"external_access_mode"`
}
type VpcUpdateInput struct {
apis.EnabledStatusInfrasResourceBaseUpdateInput
// Vpc外网访问模式
ExternalAccessMode string `json:"external_access_mode"`
}
type VpcResourceInput struct {
@@ -81,6 +91,9 @@ type VpcResourceInput struct {
// Deprecated
// filter by vpc Id
VpcId string `json:"vpc_id" "yunion:deprecated-by":"vpc"`
// Vpc外网访问模式
ExternalAccessMode string `json:"external_access_mode"`
}
type VpcFilterListInputBase struct {
+44
View File
@@ -4,6 +4,20 @@ import (
"yunion.io/x/pkg/util/netutils"
)
const (
VPC_EXTERNAL_ACCESS_MODE_DISTGW = "distgw" // distgw only
VPC_EXTERNAL_ACCESS_MODE_EIP_DISTGW = "eip-distgw" // eip when available, distgw otherwise
VPC_EXTERNAL_ACCESS_MODE_EIP = "eip" // eip only
)
var (
VPC_EXTERNAL_ACCESS_MODES = []string{
VPC_EXTERNAL_ACCESS_MODE_DISTGW,
VPC_EXTERNAL_ACCESS_MODE_EIP_DISTGW,
VPC_EXTERNAL_ACCESS_MODE_EIP,
}
)
const (
sVpcMappedCidr = "100.64.0.0/17"
VpcMappedIPMask = 17
@@ -25,10 +39,24 @@ const (
// reserved: [10.64.127.0 , 10.64.127.255]
)
const (
sVpcEipGatewayCidr = "100.64.128.0/17"
VpcEipGatewayIPMask = 17
sVpcEipGatewayIP = "100.64.128.2"
VpcEipGatewayMac = "ee:ee:ee:ee:ee:ef"
sVpcEipGatewayIP3 = "100.64.128.3"
VpcEipGatewayMac3 = "ee:ee:ee:ee:ee:f0"
)
var (
vpcMappedCidr netutils.IPV4Prefix
vpcMappedGatewayIP netutils.IPV4Addr
vpcEipGatewayCidr netutils.IPV4Prefix
vpcEipGatewayIP netutils.IPV4Addr
vpcEipGatewayIP3 netutils.IPV4Addr
vpcMappedHostIPStart netutils.IPV4Addr
vpcMappedHostIPEnd netutils.IPV4Addr
@@ -53,6 +81,10 @@ func init() {
vpcMappedCidr = mp(netutils.NewIPV4Prefix(sVpcMappedCidr))
vpcMappedGatewayIP = mi(netutils.NewIPV4Addr(sVpcMappedGatewayIP))
vpcEipGatewayCidr = mp(netutils.NewIPV4Prefix(sVpcEipGatewayCidr))
vpcEipGatewayIP = mi(netutils.NewIPV4Addr(sVpcEipGatewayIP))
vpcEipGatewayIP3 = mi(netutils.NewIPV4Addr(sVpcEipGatewayIP3))
vpcMappedHostIPStart = mi(netutils.NewIPV4Addr(sVpcMappedHostIPStart))
vpcMappedHostIPEnd = mi(netutils.NewIPV4Addr(sVpcMappedHostIPEnd))
@@ -68,6 +100,18 @@ func VpcMappedGatewayIP() netutils.IPV4Addr {
return vpcMappedGatewayIP
}
func VpcEipGatewayCidr() netutils.IPV4Prefix {
return vpcEipGatewayCidr
}
func VpcEipGatewayIP() netutils.IPV4Addr {
return vpcEipGatewayIP
}
func VpcEipGatewayIP3() netutils.IPV4Addr {
return vpcEipGatewayIP3
}
func VpcMappedHostIPStart() netutils.IPV4Addr {
return vpcMappedHostIPStart
}
+4
View File
@@ -919,6 +919,8 @@ type SGuestnetwork struct {
TeamWith string `json:"team_with"`
// IPv4映射地址,当子网属于私有云vpc的时候分配,用于访问外网
MappedIpAddr string `json:"mapped_ip_addr"`
// 网卡关联的Eip实例
EipId string `json:"eip_id"`
}
// SGuestsecgroup is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestsecgroup.
@@ -2097,6 +2099,8 @@ type SVpc struct {
// CIDR地址段
// example: 192.168.222.0/24
CidrBlock string `json:"cidr_block"`
// Vpc外网访问模式
ExternalAccessMode string `json:"external_access_mode"`
}
// SVpcResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SVpcResourceBase.
+56
View File
@@ -23,10 +23,13 @@ import (
"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/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
@@ -302,6 +305,59 @@ func (self *SKVMGuestDriver) OnDeleteGuestFinalCleanup(ctx context.Context, gues
return nil
}
func (self *SKVMGuestDriver) IsSupportEip() bool {
return true
}
func (self *SKVMGuestDriver) ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
return nil
}
func (self *SKVMGuestDriver) RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, eip *models.SElasticip, task taskman.ITask) error {
defer task.ScheduleRun(nil)
lockman.LockObject(ctx, guest)
defer lockman.ReleaseObject(ctx, guest)
var guestnics []models.SGuestnetwork
{
netq := models.NetworkManager.Query().SubQuery()
wirq := models.WireManager.Query().SubQuery()
vpcq := models.VpcManager.Query().SubQuery()
gneq := models.GuestnetworkManager.Query()
q := gneq.Equals("guest_id", guest.Id).
IsNullOrEmpty("eip_id")
q = q.Join(netq, sqlchemy.Equals(netq.Field("id"), gneq.Field("network_id")))
q = q.Join(wirq, sqlchemy.Equals(wirq.Field("id"), netq.Field("wire_id")))
q = q.Join(vpcq, sqlchemy.Equals(vpcq.Field("id"), wirq.Field("vpc_id")))
q = q.Filter(sqlchemy.NotEquals(vpcq.Field("id"), api.DEFAULT_VPC_ID))
if err := db.FetchModelObjects(models.GuestnetworkManager, q, &guestnics); err != nil {
return err
}
if len(guestnics) == 0 {
return errors.Errorf("guest has no nics to associate eip")
}
}
guestnic := &guestnics[0]
lockman.LockObject(ctx, guestnic)
defer lockman.ReleaseObject(ctx, guestnic)
if _, err := db.Update(guestnic, func() error {
guestnic.EipId = eip.Id
return nil
}); err != nil {
return errors.Wrapf(err, "set associated eip for guestnic %s (guest:%s, network:%s)",
guestnic.Ifname, guestnic.GuestId, guestnic.NetworkId)
}
if err := eip.AssociateVM(ctx, userCred, guest); err != nil {
return errors.Wrapf(err, "associate eip %s(%s) to vm %s(%s)", eip.Name, eip.Id, guest.Name, guest.Id)
}
if err := eip.SetStatus(userCred, api.EIP_STATUS_READY, api.EIP_STATUS_ASSOCIATE); err != nil {
return errors.Wrapf(err, "set eip status to %s", api.EIP_STATUS_ALLOCATE)
}
return nil
}
func (self *SKVMGuestDriver) NeedStopForChangeSpec(guest *models.SGuest, cpuChanged, memChanged bool) bool {
return guest.GetMetadata("hotplug_cpu_mem", nil) != "enable" ||
(memChanged && guest.GetMetadata("__hugepage", nil) == "native")
+84 -50
View File
@@ -80,7 +80,7 @@ type SElasticip struct {
// | elastic_ip | 弹性公网IP |
//
// example: elastic_ip
Mode string `width:"32" charset:"ascii" list:"user"`
Mode string `width:"32" charset:"ascii" get:"user" list:"user" create:"optional"`
// IP地址
IpAddr string `width:"17" charset:"ascii" list:"user" create:"optional"`
@@ -148,7 +148,7 @@ func (manager *SElasticipManager) ListItemFilter(
return nil, httperrors.NewGeneralError(err)
}
guest := serverObj.(*SGuest)
if utils.IsInStringArray(guest.Hypervisor, api.PRIVATE_CLOUD_HYPERVISORS) {
if guest.Hypervisor == api.HYPERVISOR_KVM || utils.IsInStringArray(guest.Hypervisor, api.PRIVATE_CLOUD_HYPERVISORS) {
zone := guest.getZone()
networks := NetworkManager.Query().SubQuery()
wires := WireManager.Query().SubQuery()
@@ -161,7 +161,11 @@ func (manager *SElasticipManager) ListItemFilter(
q = q.Equals("cloudregion_id", region.Id)
}
managerId := guest.GetHost().ManagerId
q = q.Equals("manager_id", managerId)
if managerId != "" {
q = q.Equals("manager_id", managerId)
} else {
q = q.IsNullOrEmpty("manager_id")
}
default:
return nil, httperrors.NewInputParameterError("Not support associate type %s, only support %s", associateType, api.EIP_ASSOCIATE_VALID_TYPES)
}
@@ -772,24 +776,29 @@ func (manager *SElasticipManager) getEipByExtEip(ctx context.Context, userCred m
}
func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.SElasticipCreateInput) (*jsonutils.JSONDict, error) {
var (
region *SCloudregion
provider *SCloudprovider
err error
)
for _, cloudregion := range []string{input.Cloudregion, input.Region, input.RegionId} {
if len(cloudregion) > 0 {
input.Cloudregion = cloudregion
break
}
}
if len(input.Cloudregion) == 0 {
return nil, httperrors.NewMissingParameterError("cloudregion")
if input.Cloudregion == "" {
input.Cloudregion = api.DEFAULT_REGION_ID
}
_region, err := CloudregionManager.FetchByIdOrName(nil, input.Cloudregion)
if err != nil {
if obj, err := CloudregionManager.FetchByIdOrName(nil, input.Cloudregion); err != nil {
if err != sql.ErrNoRows {
return nil, httperrors.NewGeneralError(err)
} else {
return nil, httperrors.NewResourceNotFoundError("Region %s not found", input.Cloudregion)
}
} else {
region = obj.(*SCloudregion)
}
region := _region.(*SCloudregion)
input.CloudregionId = region.GetId()
for _, cloudprovider := range []string{input.Cloudprovider, input.Manager, input.ManagerId} {
@@ -798,20 +807,21 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
break
}
}
if len(input.Cloudprovider) == 0 {
return nil, httperrors.NewMissingParameterError("cloudprovider")
if input.Cloudprovider != "" {
providerObj, err := CloudproviderManager.FetchByIdOrName(nil, input.Cloudprovider)
if err != nil {
if err != sql.ErrNoRows {
return nil, httperrors.NewGeneralError(err)
} else {
return nil, httperrors.NewResourceNotFoundError("Cloud provider %s not found", input.Cloudprovider)
}
}
provider = providerObj.(*SCloudprovider)
input.ManagerId = provider.Id
}
providerObj, err := CloudproviderManager.FetchByIdOrName(nil, input.Cloudprovider)
if err != nil {
if err != sql.ErrNoRows {
return nil, httperrors.NewGeneralError(err)
} else {
return nil, httperrors.NewResourceNotFoundError("Cloud provider %s not found", input.Cloudprovider)
}
}
provider := providerObj.(*SCloudprovider)
input.ManagerId = provider.Id
// publicIp cannot be created standalone
input.Mode = api.EIP_MODE_STANDALONE_EIP
if len(input.ChargeType) == 0 {
input.ChargeType = api.EIP_CHARGE_TYPE_DEFAULT
@@ -821,19 +831,19 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
return nil, httperrors.NewInputParameterError("charge type %s not supported", input.ChargeType)
}
input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput)
if err != nil {
if input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput); err != nil {
return nil, err
}
err = region.GetDriver().ValidateCreateEipData(ctx, userCred, &input)
if err = region.GetDriver().ValidateCreateEipData(ctx, userCred, &input); err != nil {
return nil, err
}
//避免参数重名后还有pending.eip残留
eipPendingUsage := &SRegionQuota{Eip: 1}
quotaKeys := fetchRegionalQuotaKeys(rbacutils.ScopeProject, ownerId, region, provider)
eipPendingUsage.SetKeys(quotaKeys)
err = quotas.CheckSetPendingQuota(ctx, userCred, eipPendingUsage)
if err != nil {
if err = quotas.CheckSetPendingQuota(ctx, userCred, eipPendingUsage); err != nil {
return nil, err
}
@@ -883,7 +893,7 @@ func (self *SElasticip) startEipAllocateTask(ctx context.Context, userCred mccli
}
func (self *SElasticip) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
log.Infof("Elasticip delete do nothing")
// Elasticip delete do nothing
return nil
}
@@ -961,6 +971,8 @@ func (self *SElasticip) PerformAssociate(ctx context.Context, userCred mcclient.
return nil, httperrors.NewInvalidStatusError("cannot associate pending delete server")
}
// IMPORTANT: this serves as a guard against a guest to have multiple
// associated elastic_ips
seip, _ := server.GetEip()
if seip != nil {
return nil, httperrors.NewInvalidStatusError("instance is already associated with eip")
@@ -1088,16 +1100,9 @@ func (self *SElasticip) PerformDissociate(ctx context.Context, userCred mcclient
}
autoDelete := jsonutils.QueryBoolean(data, "auto_delete", false)
switch self.AssociateType {
case api.EIP_ASSOCIATE_TYPE_SERVER:
guest := self.GetAssociateVM()
if guest == nil {
return nil, httperrors.NewInputParameterError("unable to found guest for elasticip %s(%s)", self.Name, self.IpAddr)
}
return nil, guest.StartGuestDissociateEipTask(ctx, userCred, self, autoDelete, "")
default:
return nil, self.StartEipDissociateTask(ctx, userCred, autoDelete, "")
}
err := self.StartEipDissociateTask(ctx, userCred, autoDelete, "")
return nil, err
}
func (self *SElasticip) StartEipDissociateTask(ctx context.Context, userCred mcclient.TokenCredential, autoDelete bool, parentTaskId string) error {
@@ -1146,8 +1151,11 @@ func (self *SElasticip) PerformSyncstatus(ctx context.Context, userCred mcclient
if self.Mode == api.EIP_MODE_INSTANCE_PUBLICIP {
return nil, httperrors.NewUnsupportOperationError("fixed eip cannot sync status")
}
return nil, StartResourceSyncStatusTask(ctx, userCred, self, "EipSyncstatusTask", "")
if self.IsManaged() {
return nil, StartResourceSyncStatusTask(ctx, userCred, self, "EipSyncstatusTask", "")
} else {
return nil, self.SetStatus(userCred, api.EIP_STATUS_READY, "eip sync status")
}
}
func (self *SElasticip) AllowPerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
@@ -1155,15 +1163,13 @@ func (self *SElasticip) AllowPerformSync(ctx context.Context, userCred mcclient.
}
func (self *SElasticip) PerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
/*if self.Status != EIP_STATUS_READY && !strings.HasSuffix(self.Status, "_fail") {
return nil, httperrors.NewInvalidStatusError("eip cannot syncstatus in status %s", self.Status)
}*/
if self.Mode == api.EIP_MODE_INSTANCE_PUBLICIP {
return nil, httperrors.NewUnsupportOperationError("fixed eip cannot sync status")
}
return nil, StartResourceSyncStatusTask(ctx, userCred, self, "EipSyncstatusTask", "")
if self.IsManaged() {
return nil, StartResourceSyncStatusTask(ctx, userCred, self, "EipSyncstatusTask", "")
}
return nil, nil
}
func (self *SElasticip) GetExtraDetails(
@@ -1229,6 +1235,32 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
eip.ManagerId = host.ManagerId
eip.CloudregionId = region.Id
eip.Name = fmt.Sprintf("eip-for-%s", vm.GetName())
if host.ManagerId == "" {
hostq := HostManager.Query().SubQuery()
wireq := WireManager.Query().SubQuery()
hostwireq := HostwireManager.Query().SubQuery()
q := NetworkManager.Query()
q = q.Join(wireq, sqlchemy.Equals(wireq.Field("id"), q.Field("wire_id")))
q = q.Join(hostwireq, sqlchemy.Equals(hostwireq.Field("wire_id"), wireq.Field("id")))
q = q.Join(hostq, sqlchemy.Equals(hostq.Field("id"), host.Id))
q = q.Equals("server_type", api.NETWORK_TYPE_EIP)
var nets []SNetwork
if err := db.FetchModelObjects(NetworkManager, q, &nets); err != nil {
return nil, errors.Wrapf(err, "fetch eip networks usable in host %s(%s)",
host.Name, host.Id)
}
for i := range nets {
net := &nets[i]
cnt, err := net.GetFreeAddressCount()
if err != nil {
continue
}
if cnt > 0 {
eip.NetworkId = net.Id
break
}
}
}
var err error
eip.Name, err = db.GenerateName(manager, userCred, eip.Name)
@@ -1280,13 +1312,15 @@ func (self *SElasticip) PerformChangeBandwidth(ctx context.Context, userCred mcc
return nil, httperrors.NewInputParameterError("Invalid bandwidth")
}
factory, err := self.GetProviderFactory()
if err != nil {
return nil, err
}
if self.IsManaged() {
factory, err := self.GetProviderFactory()
if err != nil {
return nil, err
}
if err := factory.ValidateChangeBandwidth(self.AssociateId, bandwidth); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
if err := factory.ValidateChangeBandwidth(self.AssociateId, bandwidth); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
}
err = self.StartEipChangeBandwidthTask(ctx, userCred, bandwidth)
+17 -32
View File
@@ -2901,32 +2901,18 @@ func (self *SGuest) PerformDissociateEip(ctx context.Context, userCred mcclient.
return nil, httperrors.NewInvalidStatusError("No eip to dissociate")
}
if eip.Mode != api.EIP_MODE_STANDALONE_EIP {
return nil, httperrors.NewNotSupportedError("%s not support dissociate", eip.Mode)
}
self.SetStatus(userCred, api.VM_DISSOCIATE_EIP, "associate eip")
autoDelete := jsonutils.QueryBoolean(data, "auto_delete", false)
err = self.StartGuestDissociateEipTask(ctx, userCred, eip, autoDelete, "")
err = eip.StartEipDissociateTask(ctx, userCred, autoDelete, "")
if err != nil {
return nil, errors.Wrap(err, "StartGuestDissociateEipTask")
log.Errorf("fail to start dissociate task %s", err)
return nil, httperrors.NewGeneralError(err)
}
return nil, nil
}
func (self *SGuest) StartGuestDissociateEipTask(ctx context.Context, userCred mcclient.TokenCredential, eip *SElasticip, autoDelete bool, parentTaskId string) error {
self.SetStatus(userCred, api.VM_DISSOCIATE_EIP, "associate eip")
eip.SetStatus(userCred, api.EIP_STATUS_DISSOCIATE, "start to dissociate")
params := jsonutils.NewDict()
params.Add(jsonutils.NewBool(autoDelete), "auto_delete")
task, err := taskman.TaskManager.NewTask(ctx, "GuestDissociateEipTask", self, userCred, params, parentTaskId, "", nil)
if err != nil {
eip.SetStatus(userCred, api.EIP_STATUS_READY, "")
return errors.Wrap(err, "NewTask")
}
task.ScheduleRun(nil)
return nil
}
func (self *SGuest) AllowPerformCreateEip(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "create-eip")
}
@@ -2946,25 +2932,24 @@ func (self *SGuest) PerformCreateEip(ctx context.Context, userCred mcclient.Toke
}
autoDellocate, _ := data.Bool("auto_dellocate")
if len(self.ExternalId) == 0 {
return nil, httperrors.NewInvalidStatusError("Not a managed VM")
}
host := self.GetHost()
if host == nil {
return nil, httperrors.NewInvalidStatusError("No host???")
}
_, err := host.GetDriver()
if err != nil {
return nil, httperrors.NewInvalidStatusError("No valid cloud provider")
{
if self.ExternalId != "" {
_, err := host.GetDriver()
if err != nil {
return nil, httperrors.NewInvalidStatusError("No valid cloud provider")
}
}
region := host.GetRegion()
if region == nil {
return nil, httperrors.NewInvalidStatusError("No cloudregion???")
}
}
region := host.GetRegion()
if region == nil {
return nil, httperrors.NewInvalidStatusError("No cloudregion???")
}
err = self.GetDriver().ValidateCreateEip(ctx, userCred, data)
err := self.GetDriver().ValidateCreateEip(ctx, userCred, data)
if err != nil {
return nil, err
}
+3
View File
@@ -100,6 +100,9 @@ type SGuestnetwork struct {
// IPv4映射地址,当子网属于私有云vpc的时候分配,用于访问外网
MappedIpAddr string `width:"16" charset:"ascii" nullable:"true" list:"user"`
// 网卡关联的Eip实例
EipId string `width:"36" charset:"ascii" nullable:"true" list:"user"`
}
func (manager *SGuestnetworkManager) GetSlaveFieldName() string {
+11 -4
View File
@@ -323,15 +323,22 @@ func (manager *SGuestManager) ListItemFilter(
return nil, httperrors.NewGeneralError(err)
}
eip := eipObj.(*SElasticip)
hostTable := HostManager.Query().SubQuery()
zoneTable := ZoneManager.Query().SubQuery()
hostQ := hostTable.Query(hostTable.Field("id")).Join(zoneTable,
sqlchemy.Equals(zoneTable.Field("id"), hostTable.Field("zone_id"))).Equals("manager_id", eip.ManagerId)
if len(eip.NetworkId) > 0 {
sq := GuestnetworkManager.Query("guest_id").Equals("network_id", eip.NetworkId).SubQuery()
q = q.NotIn("id", sq)
}
hostTable := HostManager.Query().SubQuery()
zoneTable := ZoneManager.Query().SubQuery()
hostQ := hostTable.Query(hostTable.Field("id"))
hostQ = hostQ.Join(zoneTable,
sqlchemy.Equals(zoneTable.Field("id"), hostTable.Field("zone_id")))
if eip.ManagerId != "" {
hostQ = hostQ.Equals("manager_id", eip.ManagerId)
} else {
hostQ = hostQ.IsNullOrEmpty("manager_id")
}
region := eip.GetRegion()
regionTable := CloudregionManager.Query().SubQuery()
sq := hostQ.Join(regionTable, sqlchemy.Equals(zoneTable.Field("cloudregion_id"), regionTable.Field("id"))).
+3
View File
@@ -1360,6 +1360,9 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
if vpc.Status != api.VPC_STATUS_AVAILABLE {
return input, httperrors.NewInvalidStatusError("VPC not ready")
}
if input.ServerType == api.NETWORK_TYPE_EIP && vpc.Id != api.DEFAULT_VPC_ID {
return input, httperrors.NewInputParameterError("eip network can only exist in default vpc, got %s(%s)", vpc.Name, vpc.Id)
}
var (
ipStart = ipRange.StartIp()
+45 -8
View File
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
@@ -80,11 +81,8 @@ type SVpc struct {
// example: 192.168.222.0/24
CidrBlock string `charset:"ascii" nullable:"true" list:"domain" create:"domain_optional"`
// 区域Id
// CloudregionId string `width:"36" charset:"ascii" nullable:"false" list:"domain" create:"domain_required" default:"default"`
// 全局VPC Id
// GlobalvpcId string `width:"36" charset:"ascii" list:"user" json:"globalvpc_id"`
// Vpc外网访问模式
ExternalAccessMode string `width:"16" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
}
func (manager *SVpcManager) GetContextManagers() [][]db.IModelManager {
@@ -127,6 +125,19 @@ func (self *SVpc) GetNatgateways() ([]SNatGateway, error) {
return nats, nil
}
func (self *SVpc) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.VpcUpdateInput) (api.VpcUpdateInput, error) {
if input.ExternalAccessMode != "" {
if !utils.IsInStringArray(input.ExternalAccessMode, api.VPC_EXTERNAL_ACCESS_MODES) {
return input, httperrors.NewInputParameterError("invalid external_access_mode %q, want %s",
input.ExternalAccessMode, api.VPC_EXTERNAL_ACCESS_MODES)
}
}
if _, err := self.SEnabledStatusInfrasResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusInfrasResourceBaseUpdateInput); err != nil {
return input, err
}
return input, nil
}
func (self *SVpc) ValidateDeleteCondition(ctx context.Context) error {
cnt, err := self.GetNetworkCount()
if err != nil {
@@ -561,8 +572,7 @@ func (self *SVpc) markAllNetworksUnknown(userCred mcclient.TokenCredential) erro
}
func (manager *SVpcManager) InitializeData() error {
vpcObj, err := manager.FetchById(api.DEFAULT_VPC_ID)
if err != nil {
if vpcObj, err := manager.FetchById(api.DEFAULT_VPC_ID); err != nil {
if err == sql.ErrNoRows {
defVpc := SVpc{}
defVpc.SetModelManager(VpcManager, &defVpc)
@@ -594,6 +604,27 @@ func (manager *SVpcManager) InitializeData() error {
return err
}
}
{ // initialize default external_access_mode for onecloud vpc
var vpcs []SVpc
q := manager.Query().
IsNullOrEmpty("manager_id").
IsNullOrEmpty("external_id").
IsNullOrEmpty("external_access_mode")
if err := db.FetchModelObjects(manager, q, &vpcs); err != nil {
return errors.Wrap(err, "fetch onecloud vpc with external_access_mode not set")
}
for i := range vpcs {
vpc := &vpcs[i]
if _, err := db.Update(vpc, func() error {
vpc.ExternalAccessMode = api.VPC_EXTERNAL_ACCESS_MODE_EIP_DISTGW
return nil
}); err != nil {
return errors.Wrap(err, "db set default external_access_mode")
}
}
}
return nil
}
@@ -635,8 +666,14 @@ func (manager *SVpcManager) ValidateCreateData(
input.Cloudprovider = managerObj.GetId()
// data.Add(jsonutils.NewString(managerObj.GetId()), "manager_id")
} else {
// data.Set("status", jsonutils.NewString(api.VPC_STATUS_AVAILABLE))
input.Status = api.VPC_STATUS_AVAILABLE
if input.ExternalAccessMode == "" {
input.ExternalAccessMode = api.VPC_EXTERNAL_ACCESS_MODE_EIP_DISTGW
}
if !utils.IsInStringArray(input.ExternalAccessMode, api.VPC_EXTERNAL_ACCESS_MODES) {
return input, httperrors.NewInputParameterError("invalid external_access_mode %q, want %s",
input.Status, api.VPC_EXTERNAL_ACCESS_MODES)
}
}
cidrBlock := input.CidrBlock
+29 -1
View File
@@ -16,6 +16,7 @@ package regiondrivers
import (
"context"
"database/sql"
"fmt"
"regexp"
@@ -897,7 +898,34 @@ func (self *SKVMRegionDriver) RequestDeleteVpc(ctx context.Context, userCred mcc
}
func (self *SKVMRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error {
return httperrors.NewNotImplementedError("Not Implement EIP")
if len(input.Network) == 0 {
return httperrors.NewMissingParameterError("network")
}
_network, err := models.NetworkManager.FetchByIdOrName(userCred, input.Network)
if err != nil {
if err == sql.ErrNoRows {
return httperrors.NewResourceNotFoundError("failed to found network %s", input.Network)
}
return httperrors.NewGeneralError(err)
}
network := _network.(*models.SNetwork)
if network.ServerType != api.NETWORK_TYPE_EIP {
return httperrors.NewInputParameterError("bad network type %q, want %q", network.ServerType, api.NETWORK_TYPE_EIP)
}
input.NetworkId = network.Id
vpc := network.GetVpc()
if vpc == nil {
return httperrors.NewInputParameterError("failed to found vpc for network %s(%s)", network.Name, network.Id)
}
region, err := vpc.GetRegion()
if err != nil {
return err
}
if region.GetDriver().GetProvider() != self.GetProvider() {
return httperrors.NewUnsupportOperationError("network %s(%s) does not belong to %s", network.Name, network.Id, self.GetProvider())
}
return nil
}
func (self *SKVMRegionDriver) ValidateSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot) error {
+42 -35
View File
@@ -61,15 +61,10 @@ func (self *EipAllocateTask) setGuestAllocateEipFailed(eip *models.SElasticip, r
}
func (self *EipAllocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
eip := obj.(*models.SElasticip)
iregion, err := eip.GetIRegion()
if err != nil {
msg := fmt.Sprintf("fail to find iregion for eip %s", err)
eip.SetStatus(self.UserCred, api.EIP_STATUS_ALLOCATE_FAIL, msg)
self.onFailed(ctx, eip, msg)
return
}
var (
eip = obj.(*models.SElasticip)
eipIsManaged = eip.IsManaged()
)
args := &cloudprovider.SEip{
Name: eip.Name,
@@ -79,7 +74,7 @@ func (self *EipAllocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel
IP: eip.IpAddr,
}
if len(eip.NetworkId) > 0 {
if eip.NetworkId != "" {
_network, err := models.NetworkManager.FetchById(eip.NetworkId)
if err != nil {
msg := fmt.Sprintf("failed to found network %s error: %v", eip.NetworkId, err)
@@ -87,18 +82,18 @@ func (self *EipAllocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel
return
}
network := _network.(*models.SNetwork)
ip, _ := self.GetParams().GetString("ip")
if len(ip) > 0 {
reqIp, _ := self.GetParams().GetString("ip")
if reqIp != "" || !eipIsManaged {
lockman.LockObject(ctx, network)
defer lockman.ReleaseObject(ctx, network)
ipAddr, err := network.GetFreeIP(ctx, self.UserCred, nil, nil, ip, api.IPAllocationNone, false)
ipAddr, err := network.GetFreeIP(ctx, self.UserCred, nil, nil, reqIp, api.IPAllocationNone, false)
if err != nil {
self.onFailed(ctx, eip, err.Error())
return
}
if ipAddr != ip {
msg := fmt.Sprintf("candidate ip %s is occupied!", ip)
if reqIp != "" && ipAddr != reqIp {
msg := fmt.Sprintf("requested ip %s is occupied!", reqIp)
self.onFailed(ctx, eip, msg)
return
}
@@ -110,37 +105,49 @@ func (self *EipAllocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel
self.onFailed(ctx, eip, err.Error())
return
}
if !eipIsManaged {
eip.SetStatus(self.UserCred, api.EIP_STATUS_READY, "allocated from network")
}
}
args.NetworkExternalId = network.ExternalId
}
_cloudprovider := eip.GetCloudprovider()
args.ProjectId, err = _cloudprovider.SyncProject(ctx, self.GetUserCred(), eip.ProjectId)
if err != nil {
log.Errorf("failed to sync project %s for create %s eip %s error: %v", eip.ProjectId, _cloudprovider.Provider, eip.Name, err)
}
if eipIsManaged {
var err error
extEip, err := iregion.CreateEIP(args)
if err != nil {
msg := fmt.Sprintf("create eip fail %s", err)
eip.SetStatus(self.UserCred, api.EIP_STATUS_ALLOCATE_FAIL, msg)
self.onFailed(ctx, eip, msg)
return
}
_cloudprovider := eip.GetCloudprovider()
args.ProjectId, err = _cloudprovider.SyncProject(ctx, self.GetUserCred(), eip.ProjectId)
if err != nil {
log.Errorf("failed to sync project %s for create %s eip %s error: %v", eip.ProjectId, _cloudprovider.Provider, eip.Name, err)
}
err = eip.SyncWithCloudEip(ctx, self.UserCred, eip.GetCloudprovider(), extEip, nil)
iregion, err := eip.GetIRegion()
if err != nil {
msg := fmt.Sprintf("fail to find iregion for eip %s", err)
eip.SetStatus(self.UserCred, api.EIP_STATUS_ALLOCATE_FAIL, msg)
self.onFailed(ctx, eip, msg)
return
}
if err != nil {
msg := fmt.Sprintf("sync eip fail %s", err)
eip.SetStatus(self.UserCred, api.EIP_STATUS_ALLOCATE_FAIL, msg)
self.onFailed(ctx, eip, msg)
return
extEip, err := iregion.CreateEIP(args)
if err != nil {
msg := fmt.Sprintf("create eip fail %s", err)
eip.SetStatus(self.UserCred, api.EIP_STATUS_ALLOCATE_FAIL, msg)
self.onFailed(ctx, eip, msg)
return
}
if err := eip.SyncWithCloudEip(ctx, self.UserCred, eip.GetCloudprovider(), extEip, nil); err != nil {
msg := fmt.Sprintf("sync eip fail %s", err)
eip.SetStatus(self.UserCred, api.EIP_STATUS_ALLOCATE_FAIL, msg)
self.onFailed(ctx, eip, msg)
return
}
}
if self.Params != nil && self.Params.Contains("instance_id") {
self.SetStage("on_eip_associate_complete", nil)
err = eip.StartEipAssociateTask(ctx, self.UserCred, self.Params, self.GetId())
if err != nil {
if err := eip.StartEipAssociateTask(ctx, self.UserCred, self.Params, self.GetId()); err != nil {
msg := fmt.Sprintf("start associate task fail %s", err)
self.SetStageFailed(ctx, msg)
}
+16 -17
View File
@@ -44,14 +44,6 @@ func (self *EipChangeBandwidthTask) TaskFail(ctx context.Context, eip *models.SE
func (self *EipChangeBandwidthTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
eip := obj.(*models.SElasticip)
extEip, err := eip.GetIEip()
if err != nil {
msg := fmt.Sprintf("fail to find iEip %s", err)
self.TaskFail(ctx, eip, msg)
return
}
bandwidth, _ := self.Params.Int("bandwidth")
if bandwidth <= 0 {
msg := fmt.Sprintf("invalid bandwidth %d", bandwidth)
@@ -59,22 +51,29 @@ func (self *EipChangeBandwidthTask) OnInit(ctx context.Context, obj db.IStandalo
return
}
err = extEip.ChangeBandwidth(int(bandwidth))
if eip.IsManaged() {
extEip, err := eip.GetIEip()
if err != nil {
msg := fmt.Sprintf("fail to find iEip %s", err)
self.TaskFail(ctx, eip, msg)
return
}
err = extEip.ChangeBandwidth(int(bandwidth))
if err != nil {
msg := fmt.Sprintf("fail to find iEip %s", err)
self.TaskFail(ctx, eip, msg)
return
}
if err != nil {
msg := fmt.Sprintf("fail to find iEip %s", err)
self.TaskFail(ctx, eip, msg)
return
}
err = eip.DoChangeBandwidth(self.UserCred, int(bandwidth))
if err != nil {
if err := eip.DoChangeBandwidth(self.UserCred, int(bandwidth)); err != nil {
msg := fmt.Sprintf("fail to synchronize iEip bandwidth %s", err)
self.TaskFail(ctx, eip, msg)
return
}
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_CHANGE_BANDWIDTH, nil, self.UserCred, true)
self.SetStageComplete(ctx, nil)
}
+5 -1
View File
@@ -48,7 +48,7 @@ func (self *EipDeallocateTask) taskFail(ctx context.Context, eip *models.SElasti
func (self *EipDeallocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
eip := obj.(*models.SElasticip)
if len(eip.ExternalId) > 0 {
if eip.ExternalId != "" {
expEip, err := eip.GetIEip()
if err != nil {
if errors.Cause(err) != cloudprovider.ErrNotFound && errors.Cause(err) != cloudprovider.ErrInvalidProvider {
@@ -66,6 +66,10 @@ func (self *EipDeallocateTask) OnInit(ctx context.Context, obj db.IStandaloneMod
}
}
if eip.IsManaged() {
// TODO clear out guestnics
}
err := eip.RealDelete(ctx, self.UserCred)
if err != nil {
msg := fmt.Sprintf("fail to delete EIP %s", err)
+41 -14
View File
@@ -23,6 +23,7 @@ import (
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/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
@@ -63,7 +64,6 @@ func (self *EipDissociateTask) OnInit(ctx context.Context, obj db.IStandaloneMod
eip := obj.(*models.SElasticip)
if eip.IsAssociated() {
var (
model db.IModel
logOp string
@@ -85,25 +85,52 @@ func (self *EipDissociateTask) OnInit(ctx context.Context, obj db.IStandaloneMod
self.TaskFail(ctx, eip, "unsupported associate type", nil)
return
}
lockman.LockObject(ctx, model)
defer lockman.ReleaseObject(ctx, model)
extEip, err := eip.GetIEip()
if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound {
msg := fmt.Sprintf("fail to find iEIP for eip %s", err)
self.TaskFail(ctx, eip, msg, model)
return
}
if err == nil && len(extEip.GetAssociationExternalId()) > 0 {
err = extEip.Dissociate()
if err != nil {
msg := fmt.Sprintf("fail to remote dissociate eip %s", err)
if eip.IsManaged() {
extEip, err := eip.GetIEip()
if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound {
msg := fmt.Sprintf("fail to find iEIP for eip %s", err)
self.TaskFail(ctx, eip, msg, model)
return
}
if err == nil && len(extEip.GetAssociationExternalId()) > 0 {
err = extEip.Dissociate()
if err != nil {
msg := fmt.Sprintf("fail to remote dissociate eip %s", err)
self.TaskFail(ctx, eip, msg, model)
return
}
}
} else {
var guestnics []models.SGuestnetwork
q := models.GuestnetworkManager.Query().
Equals("guest_id", model.GetId()).
Equals("eip_id", eip.Id)
if err := db.FetchModelObjects(models.GuestnetworkManager, q, &guestnics); err != nil {
msg := errors.Wrapf(err, "fetch guest nic associated with eip %s(%s)", eip.Name, eip.Id).Error()
self.TaskFail(ctx, eip, msg, model)
return
}
var errs []error
for i := range guestnics {
guestnic := &guestnics[i]
if _, err := db.Update(guestnic, func() error {
guestnic.EipId = ""
return nil
}); err != nil {
errs = append(errs, errors.Wrapf(err, "nic %s", guestnic.Ifname))
}
}
if len(errs) > 0 {
err := errors.NewAggregate(errs)
msg := errors.Wrapf(err, "disassociate eip %s(%s)", eip.Name, eip.Id).Error()
self.TaskFail(ctx, eip, msg, model)
}
}
err = eip.Dissociate(ctx, self.UserCred)
if err != nil {
if err := eip.Dissociate(ctx, self.UserCred); err != nil {
msg := fmt.Sprintf("fail to local dissociate eip %s", err)
self.TaskFail(ctx, eip, msg, model)
return
@@ -1,91 +0,0 @@
// 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 tasks
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/util/logclient"
)
type GuestDissociateEipTask struct {
SGuestBaseTask
}
func init() {
taskman.RegisterTask(GuestDissociateEipTask{})
}
func (self *GuestDissociateEipTask) TaskFail(ctx context.Context, guest *models.SGuest, eip *models.SElasticip, err error) {
guest.SetStatus(self.UserCred, api.VM_DISSOCIATE_EIP_FAILED, err.Error())
if eip != nil {
eip.SetStatus(self.UserCred, api.EIP_STATUS_READY, err.Error())
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_VM_DISSOCIATE, err, self.UserCred, false)
}
self.SetStageFailed(ctx, err.Error())
db.OpsLog.LogEvent(guest, db.ACT_EIP_DETACH, err.Error(), self.GetUserCred())
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_EIP_DISSOCIATE, err, self.UserCred, false)
}
func (self *GuestDissociateEipTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
guest := obj.(*models.SGuest)
eip, err := guest.GetEip()
if err != nil {
self.TaskFail(ctx, guest, nil, errors.Wrap(err, "guest.GetEip"))
return
}
extEip, err := eip.GetIEip()
if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound {
self.TaskFail(ctx, guest, eip, errors.Wrap(err, "eip.GetIEip"))
return
}
if err == nil && len(extEip.GetAssociationExternalId()) > 0 {
err = extEip.Dissociate()
if err != nil {
self.TaskFail(ctx, guest, eip, errors.Wrap(err, "extEip.Dissociate"))
return
}
}
err = eip.Dissociate(ctx, self.UserCred)
if err != nil {
self.TaskFail(ctx, guest, eip, errors.Wrap(err, "eip.Dissociate"))
return
}
eip.SetStatus(self.UserCred, api.EIP_STATUS_READY, "dissociate")
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_EIP_DISSOCIATE, nil, self.UserCred, true)
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_VM_DISSOCIATE, nil, self.UserCred, true)
guest.StartSyncstatus(ctx, self.UserCred, "")
self.SetStageComplete(ctx, nil)
autoDelete := jsonutils.QueryBoolean(self.GetParams(), "auto_delete", false)
if eip.AutoDellocate.IsTrue() || autoDelete {
eip.StartEipDeallocateTask(ctx, self.UserCred, "")
}
}
+6
View File
@@ -118,10 +118,16 @@ type SHostOptions struct {
AllowSwitchVMs bool `help:"allow machines run as switch (spoof mac)" default:"true"`
AllowRouterVMs bool `help:"allow machines run as router (spoof ip)" default:"true"`
SdnPidFile string `help:"pid file for sdnagent" default:"$SDN_PID_FILE|/var/run/yunion-sdnagent.pid"`
SdnEnableGuestMan bool `help:"enable guest network manager in sdnagent" default:"$SDN_ENABLE_GUEST_MAN|true"`
SdnEnableEipMan bool `help:"enable eip network manager in sdnagent" default:"$SDN_ENABLE_EIP_MAN|false"`
OvnSouthDatabase string `help:"address for accessing ovn south database" default:"$HOST_OVN_SOUTH_DATABASE|unix:/var/run/openvswitch/ovnsb_db.sock"`
OvnEncapIp string `help:"encap ip for ovn datapath. Default to output src address of default route" default:"$HOST_OVN_ENCAP_IP"`
OvnIntegrationBridge string `help:"name of integration bridge for logical ports" default:"$HOST_OVN_INTEGRATION_BRIDGE|brvpc"`
OvnMappedBridge string `help:"name of bridge for mapped traffic management" default:"$HOST_OVN_MAPPED_BRIDGE|brmapped"`
OvnEipBridge string `help:"name of bridge for eip traffic management" default:"$HOST_OVN_EIP_BRIDGE|breip"`
OvnUnderlayMtu int `help:"mtu of ovn underlay network" default:"1500"`
EnableHealthChecker bool `help:"enable host health checker" default:"true"`
HealthDriver string `help:"Component save host health state" default:"etcd"`
+29
View File
@@ -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 iproute2
import (
"syscall"
"yunion.io/x/pkg/errors"
)
func IsErrSrch(err error) bool {
err = errors.Cause(err)
if e, ok := err.(syscall.Errno); ok && e == 3 {
return true
}
return false
}
+4
View File
@@ -48,6 +48,10 @@ func (l *Link) addErr(err error, fmtStr string, vals ...interface{}) {
l.errs = append(l.errs, errors.Wrapf(err, fmtStr, vals...))
}
func (l *Link) addErr2(err error) {
l.errs = append(l.errs, err)
}
func (l *Link) Err() error {
err := errors.NewAggregate(l.errs)
if err != nil {
+85 -33
View File
@@ -89,25 +89,57 @@ func (route *Route) AddByIPNet(ipnet *net.IPNet, gw net.IP) *Route {
}
func (route *Route) AddByCidr(cidr string, gwStr string) *Route {
var (
dst *net.IPNet
gw net.IP
err error
)
if _, dst, err = net.ParseCIDR(cidr); err != nil {
route.addErr(err, "parse cidr")
dst, gw, err := route.parseCidr(cidr, gwStr)
if err != nil {
route.addErr2(err)
return route
}
return route.AddByIPNet(dst, gw)
}
func (route *Route) parseCidr(cidr, gwStr string) (dst *net.IPNet, gw net.IP, err error) {
if _, dst, err = net.ParseCIDR(cidr); err != nil {
err = errors.Wrap(err, "parse cidr")
return
}
if gwStr != "" {
gw = net.ParseIP(gwStr)
if len(gw) == 0 {
route.addErr(errBadIP, "gwStr: %s", gwStr)
return route
err = errors.Wrapf(errBadIP, "gwStr: %s", gwStr)
return
}
}
return
}
return route.AddByIPNet(dst, gw)
func (route *Route) parse(netStr, maskStr, gwStr string) (ip net.IP, mask net.IPMask, gw net.IP, err error) {
if ip = net.ParseIP(netStr); len(ip) == 0 {
err = errors.Wrapf(errBadIP, "netStr %s", netStr)
return
}
if maskIp := net.ParseIP(maskStr); len(maskIp) == 0 {
err = errors.Wrapf(errBadIP, "maskStr %s", maskStr)
return
} else {
if ip := maskIp.To4(); len(ip) > 0 {
maskIp = ip
}
mask = net.IPMask(maskIp)
ones, bits := mask.Size()
if ones == 0 && bits == 0 {
err = errors.Wrapf(errBadIP, "bad mask %s", maskStr)
return
}
}
if gwStr != "" {
if gw = net.ParseIP(gwStr); len(gw) == 0 {
err = errors.Wrapf(errBadIP, "gwStr %s", gwStr)
return
}
}
return
}
func (route *Route) Add(netStr, maskStr, gwStr string) *Route {
@@ -117,29 +149,9 @@ func (route *Route) Add(netStr, maskStr, gwStr string) *Route {
gw net.IP
)
if ip = net.ParseIP(netStr); len(ip) == 0 {
route.addErr(errBadIP, "netStr %s", netStr)
return route
}
if maskIp := net.ParseIP(maskStr); len(maskIp) == 0 {
route.addErr(errBadIP, "maskStr %s", maskStr)
return route
} else {
if ip := maskIp.To4(); len(ip) > 0 {
maskIp = ip
}
mask = net.IPMask(maskIp)
ones, bits := mask.Size()
if ones == 0 && bits == 0 {
route.addErr(errBadIP, "bad mask %s", maskStr)
return route
}
}
if gwStr != "" {
if gw = net.ParseIP(gwStr); len(gw) == 0 {
route.addErr(errBadIP, "gwStr %s", gwStr)
return route
}
ip, mask, gw, err := route.parse(netStr, maskStr, gwStr)
if err != nil {
route.addErr2(err)
}
ipnet := &net.IPNet{
@@ -149,6 +161,46 @@ func (route *Route) Add(netStr, maskStr, gwStr string) *Route {
return route.AddByIPNet(ipnet, gw)
}
func (route *Route) Del(netStr, maskStr string) *Route {
ip, mask, _, err := route.parse(netStr, maskStr, "")
if err != nil {
route.addErr2(err)
return route
}
ipnet := &net.IPNet{
IP: ip,
Mask: mask,
}
return route.DelByIPNet(ipnet)
}
func (route *Route) DelByCidr(cidr string) *Route {
dst, _, err := route.parseCidr(cidr, "")
if err != nil {
route.addErr2(err)
return route
}
return route.DelByIPNet(dst)
}
func (route *Route) DelByIPNet(ipnet *net.IPNet) *Route {
link, ok := route.link()
if !ok {
return route
}
r := &netlink.Route{
LinkIndex: link.Attrs().Index,
Dst: ipnet,
}
if err := netlink.RouteDel(r); err != nil {
route.addErr(err, "RouteDel %s", r)
return route
}
return route
}
func RouteGetByDst(dstStr string) ([]netlink.Route, error) {
dstIp := net.ParseIP(dstStr)
routes, err := netlink.RouteGet(dstIp)
+12
View File
@@ -48,4 +48,16 @@ func TestRoute(t *testing.T) {
}
})
t.Run("route del", func(t *testing.T) {
ifname := genDummyName(t)
dum := addDummy(t, ifname)
defer delDummy(t, dum)
r := NewRoute(ifname)
r.DelByCidr("10.1.1.30/32")
if err := r.Err(); !IsErrSrch(err) {
t.Errorf("expecting ESRCH, got %v", err)
}
})
}
+17 -2
View File
@@ -49,6 +49,7 @@ type Network struct {
Vpc *Vpc `json:"-"`
Wire *Wire `json:"-"`
Guestnetworks Guestnetworks `json:"-"`
Elasticips Elasticips `json:"-"`
}
func (el *Network) Copy() *Network {
@@ -60,8 +61,9 @@ func (el *Network) Copy() *Network {
type Guestnetwork struct {
compute_models.SGuestnetwork
Guest *Guest `json:"-"`
Network *Network `json:"-"`
Guest *Guest `json:"-"`
Network *Network `json:"-"`
Elasticip *Elasticip `json:"-"`
}
func (el *Guestnetwork) Copy() *Guestnetwork {
@@ -134,3 +136,16 @@ func (el *SecurityGroupRule) Copy() *SecurityGroupRule {
SSecurityGroupRule: el.SSecurityGroupRule,
}
}
type Elasticip struct {
compute_models.SElasticip
Network *Network `json:"-"`
Guestnetwork *Guestnetwork `json:"-"`
}
func (el *Elasticip) Copy() *Elasticip {
return &Elasticip{
SElasticip: el.SElasticip,
}
}
+73
View File
@@ -31,6 +31,7 @@ type (
Hosts map[string]*Host
SecurityGroups map[string]*SecurityGroup
SecurityGroupRules map[string]*SecurityGroupRule
Elasticips map[string]*Elasticip
Guestnetworks map[string]*Guestnetwork // key: guestId/ifname
Guestsecgroups map[string]*Guestsecgroup // key: guestId/secgroupId
@@ -293,6 +294,30 @@ func (ms Networks) joinGuestnetworks(subEntries Guestnetworks) bool {
return true
}
func (ms Networks) joinElasticips(subEntries Elasticips) bool {
for _, m := range ms {
m.Elasticips = Elasticips{}
}
correct := true
for _, subEntry := range subEntries {
netId := subEntry.NetworkId
m, ok := ms[netId]
if !ok {
log.Warningf("eip %s(%s): network %s not found", subEntry.Name, subEntry.Id, netId)
correct = false
continue
}
if _, ok := m.Elasticips[subEntry.Id]; ok {
log.Warningf("elasticip %s(%s) already joined", subEntry.Name, subEntry.Id)
correct = false
continue
}
subEntry.Network = m
m.Elasticips[subEntry.Id] = subEntry
}
return correct
}
func (set Guestnetworks) ModelManager() mcclient_modulebase.IBaseManager {
return &mcclient_modules.Servernetworks
}
@@ -332,6 +357,33 @@ func (set Guestnetworks) joinGuests(subEntries Guests) bool {
return true
}
func (set Guestnetworks) joinElasticips(subEntries Elasticips) bool {
correct := true
for _, gn := range set {
eipId := gn.EipId
if eipId == "" {
continue
}
eip, ok := subEntries[eipId]
if !ok {
log.Warningf("guestnetwork %s(%s): eip %s not found", gn.GuestId, gn.Ifname, eipId)
correct = false
continue
}
if eip.Guestnetwork != nil {
if eip.Guestnetwork != gn {
log.Errorf("eip %s associated to more than 1 guestnetwork: %s(%s), %s(%s)", eipId,
eip.Guestnetwork.GuestId, eip.Guestnetwork.Ifname, gn.GuestId, gn.Ifname)
correct = false
}
continue
}
eip.Guestnetwork = gn
gn.Elasticip = eip
}
return correct
}
func (set SecurityGroups) ModelManager() mcclient_modulebase.IBaseManager {
return &mcclient_modules.SecGroups
}
@@ -459,3 +511,24 @@ func (set Guestsecgroups) join(secgroups SecurityGroups, guests Guests) bool {
c1 := set.joinGuests(guests)
return c0 && c1
}
func (set Elasticips) ModelManager() mcclient_modulebase.IBaseManager {
return &mcclient_modules.Elasticips
}
func (set Elasticips) NewModel() db.IModel {
return &Elasticip{}
}
func (set Elasticips) AddModel(i db.IModel) {
m := i.(*Elasticip)
set[m.Id] = m
}
func (set Elasticips) Copy() apihelper.IModelSet {
setCopy := Elasticips{}
for id, el := range set {
setCopy[id] = el.Copy()
}
return setCopy
}
+8
View File
@@ -30,6 +30,7 @@ type ModelSetsMaxUpdatedAt struct {
SecurityGroupRules time.Time
Guestnetworks time.Time
Guestsecgroups time.Time
Elasticips time.Time
}
func NewModelSetsMaxUpdatedAt() *ModelSetsMaxUpdatedAt {
@@ -43,6 +44,7 @@ func NewModelSetsMaxUpdatedAt() *ModelSetsMaxUpdatedAt {
SecurityGroupRules: apihelper.PseudoZeroTime,
Guestnetworks: apihelper.PseudoZeroTime,
Guestsecgroups: apihelper.PseudoZeroTime,
Elasticips: apihelper.PseudoZeroTime,
}
}
@@ -56,6 +58,7 @@ type ModelSets struct {
SecurityGroupRules SecurityGroupRules
Guestnetworks Guestnetworks
Guestsecgroups Guestsecgroups
Elasticips Elasticips
}
func NewModelSets() *ModelSets {
@@ -69,6 +72,7 @@ func NewModelSets() *ModelSets {
SecurityGroupRules: SecurityGroupRules{},
Guestnetworks: Guestnetworks{},
Guestsecgroups: Guestsecgroups{},
Elasticips: Elasticips{},
}
}
@@ -84,6 +88,7 @@ func (mss *ModelSets) ModelSetList() []apihelper.IModelSet {
mss.SecurityGroupRules,
mss.Guestnetworks,
mss.Guestsecgroups,
mss.Elasticips,
}
}
@@ -102,6 +107,7 @@ func (mss *ModelSets) copy_() *ModelSets {
SecurityGroupRules: mss.SecurityGroupRules.Copy().(SecurityGroupRules),
Guestnetworks: mss.Guestnetworks.Copy().(Guestnetworks),
Guestsecgroups: mss.Guestsecgroups.Copy().(Guestsecgroups),
Elasticips: mss.Elasticips.Copy().(Elasticips),
}
return mssCopy
}
@@ -143,11 +149,13 @@ func (mss *ModelSets) join() bool {
p = append(p, mss.Wires.joinNetworks(mss.Networks))
p = append(p, mss.Vpcs.joinNetworks(mss.Networks))
p = append(p, mss.Networks.joinGuestnetworks(mss.Guestnetworks))
p = append(p, mss.Networks.joinElasticips(mss.Elasticips))
p = append(p, mss.Guests.joinHosts(mss.Hosts))
p = append(p, mss.Guests.joinSecurityGroups(mss.SecurityGroups))
p = append(p, mss.SecurityGroups.joinSecurityGroupRules(mss.SecurityGroupRules))
p = append(p, mss.Guestsecgroups.join(mss.SecurityGroups, mss.Guests))
p = append(p, mss.Guestnetworks.joinGuests(mss.Guests))
p = append(p, mss.Guestnetworks.joinElasticips(mss.Elasticips))
for _, b := range p {
if !b {
return false
+5
View File
@@ -39,6 +39,7 @@ type VpcAgentOptions struct {
OvnWorkerCheckInterval int `default:"180"`
OvnNorthDatabase string `help:"address for accessing ovn north database. Default to local unix socket"`
OvnUnderlayMtu int `help:"mtu of ovn underlay network" default:"1500"`
}
type Options struct {
@@ -67,6 +68,10 @@ func (opts *Options) ValidateThenInit() error {
opts.OvnWorkerCheckInterval = 60
}
if opts.OvnUnderlayMtu <= 576 {
opts.OvnUnderlayMtu = 576
}
if db, err := ovsutils.NormalizeDbHost(opts.OvnNorthDatabase); err != nil {
return err
} else {
+30
View File
@@ -0,0 +1,30 @@
package ovn
import (
apis "yunion.io/x/onecloud/pkg/apis/compute"
agentmodels "yunion.io/x/onecloud/pkg/vpcagent/models"
)
func vpcHasDistgw(vpc *agentmodels.Vpc) bool {
mode := vpc.ExternalAccessMode
switch mode {
case
apis.VPC_EXTERNAL_ACCESS_MODE_DISTGW,
apis.VPC_EXTERNAL_ACCESS_MODE_EIP_DISTGW:
return true
default:
return false
}
}
func vpcHasEipgw(vpc *agentmodels.Vpc) bool {
mode := vpc.ExternalAccessMode
switch mode {
case
apis.VPC_EXTERNAL_ACCESS_MODE_EIP,
apis.VPC_EXTERNAL_ACCESS_MODE_EIP_DISTGW:
return true
default:
return false
}
}
+261 -58
View File
@@ -51,6 +51,7 @@ func DumpOVNNorthbound(ctx context.Context, cli *ovnutil.OvnNbCtl) (*OVNNorthbou
&db.LogicalRouterStaticRoute,
&db.ACL,
&db.DHCPOptions,
&db.QoS,
}
args := []string{"--format=json", "list", "<tbl>"}
for _, itbl := range itbls {
@@ -85,41 +86,91 @@ func (keeper *OVNNorthboundKeeper) ClaimVpc(ctx context.Context, vpc *agentmodel
vpcLr := &ovn_nb.LogicalRouter{
Name: vpcLrName(vpc.Id),
}
vpcHostLs := &ovn_nb.LogicalSwitch{
Name: vpcHostLsName(vpc.Id),
}
vpcRhp := &ovn_nb.LogicalRouterPort{
Name: vpcRhpName(vpc.Id),
Mac: apis.VpcMappedGatewayMac,
Networks: []string{fmt.Sprintf("%s/%d", apis.VpcMappedGatewayIP(), apis.VpcMappedIPMask)},
}
vpcHrp := &ovn_nb.LogicalSwitchPort{
Name: vpcHrpName(vpc.Id),
Type: "router",
Addresses: []string{"router"},
Options: map[string]string{
"router-port": vpcRhpName(vpc.Id),
},
}
allFound, args := cmp(&keeper.DB, ocVersion,
vpcLr,
vpcHostLs,
vpcRhp,
vpcHrp,
irows := []types.IRow{vpcLr}
// distgw
var (
vpcHostLs *ovn_nb.LogicalSwitch
vpcRhp *ovn_nb.LogicalRouterPort
vpcHrp *ovn_nb.LogicalSwitchPort
)
if vpcHasDistgw(vpc) {
vpcHostLs = &ovn_nb.LogicalSwitch{
Name: vpcHostLsName(vpc.Id),
}
vpcRhp = &ovn_nb.LogicalRouterPort{
Name: vpcRhpName(vpc.Id),
Mac: apis.VpcMappedGatewayMac,
Networks: []string{fmt.Sprintf("%s/%d", apis.VpcMappedGatewayIP(), apis.VpcMappedIPMask)},
}
vpcHrp = &ovn_nb.LogicalSwitchPort{
Name: vpcHrpName(vpc.Id),
Type: "router",
Addresses: []string{"router"},
Options: map[string]string{
"router-port": vpcRhpName(vpc.Id),
},
}
irows = append(irows,
vpcHostLs,
vpcRhp,
vpcHrp,
)
}
// eipgw
var (
vpcEipLs *ovn_nb.LogicalSwitch
vpcRep *ovn_nb.LogicalRouterPort
vpcErp *ovn_nb.LogicalSwitchPort
)
if vpcHasEipgw(vpc) {
vpcEipLs = &ovn_nb.LogicalSwitch{
Name: vpcEipLsName(vpc.Id),
}
vpcRep = &ovn_nb.LogicalRouterPort{
Name: vpcRepName(vpc.Id),
Mac: apis.VpcEipGatewayMac,
Networks: []string{fmt.Sprintf("%s/%d", apis.VpcEipGatewayIP(), apis.VpcEipGatewayIPMask)},
}
vpcErp = &ovn_nb.LogicalSwitchPort{
Name: vpcErpName(vpc.Id),
Type: "router",
Addresses: []string{"router"},
Options: map[string]string{
"router-port": vpcRepName(vpc.Id),
},
}
irows = append(irows,
vpcEipLs,
vpcRep,
vpcErp,
)
}
allFound, args := cmp(&keeper.DB, ocVersion, irows...)
if allFound {
return nil
}
args = append(args, ovnCreateArgs(vpcLr, vpcLr.Name)...)
args = append(args, ovnCreateArgs(vpcHostLs, vpcHostLs.Name)...)
args = append(args, ovnCreateArgs(vpcRhp, vpcRhp.Name)...)
args = append(args, ovnCreateArgs(vpcHrp, vpcHrp.Name)...)
args = append(args, "--", "add", "Logical_Switch", vpcHostLs.Name, "ports", "@"+vpcHrp.Name)
args = append(args, "--", "add", "Logical_Router", vpcLr.Name, "ports", "@"+vpcRhp.Name)
if vpcHasDistgw(vpc) {
args = append(args, ovnCreateArgs(vpcHostLs, vpcHostLs.Name)...)
args = append(args, ovnCreateArgs(vpcRhp, vpcRhp.Name)...)
args = append(args, ovnCreateArgs(vpcHrp, vpcHrp.Name)...)
args = append(args, "--", "add", "Logical_Switch", vpcHostLs.Name, "ports", "@"+vpcHrp.Name)
args = append(args, "--", "add", "Logical_Router", vpcLr.Name, "ports", "@"+vpcRhp.Name)
}
if vpcHasEipgw(vpc) {
args = append(args, ovnCreateArgs(vpcEipLs, vpcEipLs.Name)...)
args = append(args, ovnCreateArgs(vpcRep, vpcRep.Name)...)
args = append(args, ovnCreateArgs(vpcErp, vpcErp.Name)...)
args = append(args, "--", "add", "Logical_Switch", vpcEipLs.Name, "ports", "@"+vpcErp.Name)
args = append(args, "--", "add", "Logical_Router", vpcLr.Name, "ports", "@"+vpcRep.Name)
}
return keeper.cli.Must(ctx, "ClaimVpc", args)
}
func (keeper *OVNNorthboundKeeper) ClaimNetwork(ctx context.Context, network *agentmodels.Network) error {
func (keeper *OVNNorthboundKeeper) ClaimNetwork(ctx context.Context, network *agentmodels.Network, mtu int) error {
var (
rpMac = mac.HashMac(network.Id, "rp")
dhcpMac = mac.HashMac(network.Id, "dhcp")
@@ -151,6 +202,7 @@ func (keeper *OVNNorthboundKeeper) ClaimNetwork(ctx context.Context, network *ag
mdIp, "0.0.0.0",
"0.0.0.0/0", network.GuestGateway,
}
mtu -= 58
dhcpopts := &ovn_nb.DHCPOptions{
Cidr: fmt.Sprintf("%s/%d", network.GuestIpStart, network.GuestIpMask),
Options: map[string]string{
@@ -159,6 +211,7 @@ func (keeper *OVNNorthboundKeeper) ClaimNetwork(ctx context.Context, network *ag
"lease_time": fmt.Sprintf("%d", 86400),
"router": network.GuestGateway,
"classless_static_route": fmt.Sprintf("{%s}", strings.Join(routes, ",")),
"mtu": fmt.Sprintf("%d", mtu),
},
ExternalIds: map[string]string{
externalKeyOcRef: network.Id,
@@ -200,7 +253,7 @@ func (keeper *OVNNorthboundKeeper) ClaimVpcHost(ctx context.Context, vpc *agentm
)
vpcHostLsp := &ovn_nb.LogicalSwitchPort{
Name: vpcHostLspName(vpc.Id, host.Id),
Addresses: []string{fmt.Sprintf("%s %s", mac.HashMac(host.Id), host.OvnMappedIpAddr)},
Addresses: []string{fmt.Sprintf("%s %s", mac.HashVpcHostDistgwMac(host.Id), host.OvnMappedIpAddr)},
}
if m := keeper.DB.LogicalSwitchPort.FindOneMatchNonZeros(vpcHostLsp); m != nil {
m.SetExternalId(externalKeyOcVersion, ocVersion)
@@ -222,18 +275,50 @@ func (keeper *OVNNorthboundKeeper) ClaimVpcHost(ctx context.Context, vpc *agentm
return keeper.cli.Must(ctx, "ClaimVpcHost", args)
}
func (keeper *OVNNorthboundKeeper) ClaimVpcEipgw(ctx context.Context, vpc *agentmodels.Vpc) error {
var (
ocVersion = fmt.Sprintf("%s.%d", vpc.UpdatedAt, vpc.UpdateVersion)
eipgwVip = apis.VpcEipGatewayIP3().String()
)
vpcEipLsp := &ovn_nb.LogicalSwitchPort{
Name: vpcEipLspName(vpc.Id, eipgwVip),
Addresses: []string{fmt.Sprintf("%s %s", apis.VpcEipGatewayMac3, eipgwVip)},
}
if m := keeper.DB.LogicalSwitchPort.FindOneMatchNonZeros(vpcEipLsp); m != nil {
m.SetExternalId(externalKeyOcVersion, ocVersion)
return nil
} else {
args := []string{
"--bare", "--columns=_uuid", "find", vpcEipLsp.OvsdbTableName(),
fmt.Sprintf("name=%q", vpcEipLsp.Name),
}
res := keeper.cli.Must(ctx, "find vpcEipLsp", args)
vpcEipLspUuid := strings.TrimSpace(res.Output)
if vpcEipLspUuid != "" {
return nil
}
}
var args []string
args = append(args, ovnCreateArgs(vpcEipLsp, vpcEipLsp.Name)...)
args = append(args, "--", "add", "Logical_Switch", vpcEipLsName(vpc.Id), "ports", "@"+vpcEipLsp.Name)
return keeper.cli.Must(ctx, "ClaimVpcEipgw", args)
}
func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestnetwork *agentmodels.Guestnetwork) error {
var (
guest = guestnetwork.Guest
network = guestnetwork.Network
vpc = network.Vpc
host = guest.Host
eip = guestnetwork.Elasticip
lportName = gnpName(guestnetwork.NetworkId, guestnetwork.Ifname)
ocVersion = fmt.Sprintf("%s.%d", guestnetwork.UpdatedAt, guestnetwork.UpdateVersion)
ocGnrRef = fmt.Sprintf("gnr/%s/%s/%s", vpc.Id, guestnetwork.GuestId, guestnetwork.Ifname)
ocAclRef = fmt.Sprintf("acl/%s/%s/%s", network.Id, guestnetwork.GuestId, guestnetwork.Ifname)
dhcpOpt string
lportName = gnpName(guestnetwork.NetworkId, guestnetwork.Ifname)
ocVersion = fmt.Sprintf("%s.%d", guestnetwork.UpdatedAt, guestnetwork.UpdateVersion)
ocGnrDefaultRef = fmt.Sprintf("gnrDefault/%s/%s/%s", vpc.Id, guestnetwork.GuestId, guestnetwork.Ifname)
ocAclRef = fmt.Sprintf("acl/%s/%s/%s", network.Id, guestnetwork.GuestId, guestnetwork.Ifname)
ocQosRef = fmt.Sprintf("qos/%s/%s/%s", network.Id, guestnetwork.GuestId, guestnetwork.Ifname)
ocQosEipRef = fmt.Sprintf("qos-eip/%s/%s/%s", vpc.Id, guestnetwork.GuestId, guestnetwork.Ifname)
dhcpOpt string
)
{
@@ -262,16 +347,107 @@ func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestn
Addresses: []string{fmt.Sprintf("%s %s", guestnetwork.MacAddr, guestnetwork.IpAddr)},
PortSecurity: []string{fmt.Sprintf("%s %s/%d", guestnetwork.MacAddr, guestnetwork.IpAddr, guestnetwork.Network.GuestIpMask)},
Dhcpv4Options: &dhcpOpt,
Options: map[string]string{},
}
gnrPolicy := "src-ip"
gnr := &ovn_nb.LogicalRouterStaticRoute{
Policy: &gnrPolicy,
IpPrefix: guestnetwork.IpAddr + "/32",
Nexthop: host.OvnMappedIpAddr,
ExternalIds: map[string]string{
externalKeyOcRef: ocGnrRef,
},
var qosVif []*ovn_nb.QoS
if bwMbps := guestnetwork.BwLimit; bwMbps > 0 {
var (
kbps = int64(bwMbps * 1000)
kbur = int64(kbps * 2)
)
qosVif = []*ovn_nb.QoS{
&ovn_nb.QoS{
Priority: 2000,
Direction: "from-lport",
Match: fmt.Sprintf("inport == %q", lportName),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosRef,
},
},
&ovn_nb.QoS{
Priority: 1000,
Direction: "to-lport",
Match: fmt.Sprintf("outport == %q", lportName),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosRef,
},
},
}
}
var (
gnrDefault *ovn_nb.LogicalRouterStaticRoute
qosEip []*ovn_nb.QoS
)
{
gnrDefaultPolicy := "src-ip"
ptr := func(s string) *string {
return &s
}
if eip != nil && vpcHasEipgw(vpc) {
gnrDefault = &ovn_nb.LogicalRouterStaticRoute{
Policy: &gnrDefaultPolicy,
IpPrefix: guestnetwork.IpAddr + "/32",
Nexthop: apis.VpcEipGatewayIP3().String(),
OutputPort: ptr(vpcRepName(vpc.Id)),
ExternalIds: map[string]string{
externalKeyOcRef: ocGnrDefaultRef,
},
}
if bwMbps := eip.Bandwidth; bwMbps > 0 {
var (
kbps = int64(bwMbps * 1000)
kbur = int64(kbps * 2)
eipgwVip = apis.VpcEipGatewayIP3().String()
)
qosEip = []*ovn_nb.QoS{
&ovn_nb.QoS{
Priority: 2000,
Direction: "from-lport",
Match: fmt.Sprintf("inport == %q && ip4 && ip4.dst == %s", vpcEipLspName(vpc.Id, eipgwVip), guestnetwork.IpAddr),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosEipRef,
},
},
&ovn_nb.QoS{
Priority: 3000,
Direction: "from-lport",
Match: fmt.Sprintf("inport == %q", lportName),
Bandwidth: map[string]int64{
"rate": kbps,
"burst": kbur,
},
ExternalIds: map[string]string{
externalKeyOcRef: ocQosEipRef,
},
},
}
}
} else if vpcHasDistgw(vpc) {
gnrDefault = &ovn_nb.LogicalRouterStaticRoute{
Policy: &gnrDefaultPolicy,
IpPrefix: guestnetwork.IpAddr + "/32",
Nexthop: host.OvnMappedIpAddr,
OutputPort: ptr(vpcRhpName(vpc.Id)),
ExternalIds: map[string]string{
externalKeyOcRef: ocGnrDefaultRef,
},
}
}
}
var acls []*ovn_nb.ACL
@@ -291,24 +467,46 @@ func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestn
}
irows := []types.IRow{
gnp, gnr,
gnp,
}
if gnrDefault != nil {
irows = append(irows, gnrDefault)
}
for _, acl := range acls {
irows = append(irows, acl)
}
for _, qos := range qosVif {
irows = append(irows, qos)
}
for _, qos := range qosEip {
irows = append(irows, qos)
}
allFound, args := cmp(&keeper.DB, ocVersion, irows...)
if allFound {
return nil
}
args = append(args, ovnCreateArgs(gnp, gnp.Name)...)
args = append(args, ovnCreateArgs(gnr, "gnr")...)
args = append(args, "--", "add", "Logical_Switch", netLsName(guestnetwork.NetworkId), "ports", "@"+gnp.Name)
args = append(args, "--", "add", "Logical_Router", vpcLrName(vpc.Id), "static_routes", "@gnr")
if gnrDefault != nil {
args = append(args, ovnCreateArgs(gnrDefault, "gnrDefault")...)
args = append(args, "--", "add", "Logical_Router", vpcLrName(vpc.Id), "static_routes", "@gnrDefault")
}
for i, acl := range acls {
ref := fmt.Sprintf("acl%d", i)
args = append(args, ovnCreateArgs(acl, ref)...)
args = append(args, "--", "add", "Logical_Switch", netLsName(guestnetwork.NetworkId), "acls", "@"+ref)
}
for i, qos := range qosVif {
ref := fmt.Sprintf("qosVif%d", i)
args = append(args, ovnCreateArgs(qos, ref)...)
args = append(args, "--", "add", "Logical_Switch", netLsName(guestnetwork.NetworkId), "qos_rules", "@"+ref)
}
for i, qos := range qosEip {
ref := fmt.Sprintf("qosEip%d", i)
args = append(args, ovnCreateArgs(qos, ref)...)
args = append(args, "--", "add", "Logical_Switch", vpcEipLsName(vpc.Id), "qos_rules", "@"+ref)
}
return keeper.cli.Must(ctx, "ClaimGuestnetwork", args)
}
@@ -322,6 +520,7 @@ func (keeper *OVNNorthboundKeeper) Mark(ctx context.Context) {
&db.LogicalRouterStaticRoute,
&db.ACL,
&db.DHCPOptions,
&db.QoS,
}
for _, itbl := range itbls {
for _, irow := range itbl.Rows() {
@@ -359,13 +558,8 @@ func (keeper *OVNNorthboundKeeper) Sweep(ctx context.Context) error {
for _, irow := range db.LogicalRouterStaticRoute.Rows() {
_, ok := irow.GetExternalId(externalKeyOcVersion)
if !ok {
ref, ok := irow.GetExternalId(externalKeyOcRef)
if ok {
parts := strings.SplitN(ref, "/", 4)
if len(parts) == 4 {
vpcId := parts[1]
args = append(args, "--", "remove", "Logical_Router", vpcLrName(vpcId), "static_routes", irow.OvsdbUuid())
}
for _, lr := range db.LogicalRouter.FindLogicalRouterStaticRouteReferrer_static_routes(irow.OvsdbUuid()) {
args = append(args, "--", "--if-exists", "remove", "Logical_Router", lr.Name, "static_routes", irow.OvsdbUuid())
}
}
}
@@ -378,13 +572,8 @@ func (keeper *OVNNorthboundKeeper) Sweep(ctx context.Context) error {
for _, irow := range db.ACL.Rows() {
_, ok := irow.GetExternalId(externalKeyOcVersion)
if !ok {
ref, ok := irow.GetExternalId(externalKeyOcRef)
if ok {
parts := strings.SplitN(ref, "/", 4)
if len(parts) == 4 {
networkId := parts[1]
args = append(args, "--", "remove", "Logical_Switch", netLsName(networkId), "acls", irow.OvsdbUuid())
}
for _, ls := range db.LogicalSwitch.FindACLReferrer_acls(irow.OvsdbUuid()) {
args = append(args, "--", "--if-exists", "remove", "Logical_Switch", ls.Name, "acls", irow.OvsdbUuid())
}
}
}
@@ -392,5 +581,19 @@ func (keeper *OVNNorthboundKeeper) Sweep(ctx context.Context) error {
keeper.cli.Must(ctx, "Sweep acls", args)
}
}
{ // remove unused QoS rows
var args []string
for _, irow := range db.QoS.Rows() {
_, ok := irow.GetExternalId(externalKeyOcVersion)
if !ok {
for _, ls := range db.LogicalSwitch.FindQoSReferrer_qos_rules(irow.OvsdbUuid()) {
args = append(args, "--", "--if-exists", "remove", "Logical_Switch", ls.Name, "qos_rules", irow.OvsdbUuid())
}
}
}
if len(args) > 0 {
keeper.cli.Must(ctx, "Sweep qos", args)
}
}
return nil
}
+4
View File
@@ -20,3 +20,7 @@ func HashMac(in ...string) string {
}
return mac
}
func HashVpcHostDistgwMac(hostId string) string {
return HashMac(hostId)
}
+18
View File
@@ -8,6 +8,7 @@ func vpcLrName(vpcId string) string {
return fmt.Sprintf("vpc-r/%s", vpcId)
}
// distgw
func vpcHostLsName(vpcId string) string {
return fmt.Sprintf("vpc-h/%s", vpcId)
}
@@ -24,6 +25,23 @@ func vpcHostLspName(vpcId string, hostId string) string {
return fmt.Sprintf("vpc-h/%s/%s", vpcId, hostId)
}
// eipgw
func vpcEipLsName(vpcId string) string {
return fmt.Sprintf("vpc-e/%s", vpcId)
}
func vpcRepName(vpcId string) string {
return fmt.Sprintf("vpc-re/%s", vpcId)
}
func vpcErpName(vpcId string) string {
return fmt.Sprintf("vpc-er/%s", vpcId)
}
func vpcEipLspName(vpcId string, eipgwId string) string {
return fmt.Sprintf("vpc-ep/%s/%s", vpcId, eipgwId)
}
func netLsName(netId string) string {
return fmt.Sprintf("subnet/%s", netId)
}
+35 -29
View File
@@ -120,41 +120,47 @@ func (w *Worker) run(ctx context.Context, mss *agentmodels.ModelSets) (err error
continue
}
ovndb.ClaimVpc(ctx, vpc)
if vpcHasEipgw(vpc) {
ovndb.ClaimVpcEipgw(ctx, vpc)
}
for _, network := range vpc.Networks {
ovndb.ClaimNetwork(ctx, network)
ovndb.ClaimNetwork(ctx, network, w.opts.OvnUnderlayMtu)
for _, guestnetwork := range network.Guestnetworks {
if guestnetwork.Guest == nil {
continue
}
var (
guest = guestnetwork.Guest
network = guestnetwork.Network
vpc = network.Vpc
host = guest.Host
)
if host.OvnVersion == "" {
// Just in case. This should never happen
log.Errorf("host %s(%s) of vpc guestnetwork (%s,%s) has no ovn support",
host.Id, host.Name, guestnetwork.NetworkId, guestnetwork.IpAddr)
continue
}
if host.OvnMappedIpAddr == "" {
// trigger ovn mapped ip addr allocation
apiVersion := "v2"
s := auth.GetAdminSession(ctx, w.opts.Region, apiVersion)
j, err := mcclient_modules.Hosts.Update(s, host.Id, nil)
if err != nil {
log.Errorf("host %s(%s) dummy update err: %v", host.Id, host.Name, err)
continue
}
j.Unmarshal(host) // update local copy in place
if host.OvnMappedIpAddr == "" {
log.Errorf("host %s(%s) has no mapped addr", host.Id, host.Name)
continue
}
}
ovndb.ClaimVpcHost(ctx, vpc, host)
if vpcHasDistgw(vpc) {
var (
guest = guestnetwork.Guest
network = guestnetwork.Network
vpc = network.Vpc
host = guest.Host
)
if host.OvnVersion == "" {
// Just in case. This should never happen
log.Errorf("host %s(%s) of vpc guestnetwork (%s,%s) has no ovn support",
host.Id, host.Name, guestnetwork.NetworkId, guestnetwork.IpAddr)
continue
}
if host.OvnMappedIpAddr == "" {
// trigger ovn mapped ip addr allocation
apiVersion := "v2"
s := auth.GetAdminSession(ctx, w.opts.Region, apiVersion)
j, err := mcclient_modules.Hosts.Update(s, host.Id, nil)
if err != nil {
log.Errorf("host %s(%s) dummy update err: %v", host.Id, host.Name, err)
continue
}
j.Unmarshal(host) // update local copy in place
if host.OvnMappedIpAddr == "" {
log.Errorf("host %s(%s) has no mapped addr", host.Id, host.Name)
continue
}
}
ovndb.ClaimVpcHost(ctx, vpc, host)
}
ovndb.ClaimGuestnetwork(ctx, guestnetwork)
}
}
+1
View File
@@ -161,6 +161,7 @@ func OvnNbctlArgsDestroy(irows []types.IRow) []string {
newArgs = []string{"--", "--if-exists", "lrp-del", irow.OvsdbUuid()}
case *ovn_nb.LogicalRouterStaticRoute:
case *ovn_nb.ACL:
case *ovn_nb.QoS:
default:
if !irow.OvsdbIsRoot() {
panic(irow.OvsdbTableName())
+1 -1
View File
@@ -996,7 +996,7 @@ yunion.io/x/jsonutils
# yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3
yunion.io/x/log
yunion.io/x/log/hooks
# yunion.io/x/ovsdb v0.0.0-20200512112253-a3601d1ee987
# yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7
yunion.io/x/ovsdb/cli_util
yunion.io/x/ovsdb/schema/ovn_nb
yunion.io/x/ovsdb/types
+752
View File
@@ -23,8 +23,11 @@ type OVNNorthbound struct {
LogicalRouterStaticRoute LogicalRouterStaticRouteTable
LogicalSwitch LogicalSwitchTable
LogicalSwitchPort LogicalSwitchPortTable
Meter MeterTable
MeterBand MeterBandTable
NAT NATTable
NBGlobal NBGlobalTable
PortGroup PortGroupTable
QoS QoSTable
SSL SSLTable
}
@@ -93,6 +96,16 @@ func (db OVNNorthbound) FindOneMatchNonZeros(irow types.IRow) types.IRow {
return r
}
return nil
case *Meter:
if r := db.Meter.FindOneMatchNonZeros(row); r != nil {
return r
}
return nil
case *MeterBand:
if r := db.MeterBand.FindOneMatchNonZeros(row); r != nil {
return r
}
return nil
case *NAT:
if r := db.NAT.FindOneMatchNonZeros(row); r != nil {
return r
@@ -103,6 +116,11 @@ func (db OVNNorthbound) FindOneMatchNonZeros(irow types.IRow) types.IRow {
return r
}
return nil
case *PortGroup:
if r := db.PortGroup.FindOneMatchNonZeros(row); r != nil {
return r
}
return nil
case *QoS:
if r := db.QoS.FindOneMatchNonZeros(row); r != nil {
return r
@@ -179,6 +197,16 @@ func (db OVNNorthbound) FindOneMatchByAnyIndex(irow types.IRow) types.IRow {
return r
}
return nil
case *Meter:
if r := db.Meter.OvsdbGetByAnyIndex(row); r != nil {
return r
}
return nil
case *MeterBand:
if r := db.MeterBand.OvsdbGetByAnyIndex(row); r != nil {
return r
}
return nil
case *NAT:
if r := db.NAT.OvsdbGetByAnyIndex(row); r != nil {
return r
@@ -189,6 +217,11 @@ func (db OVNNorthbound) FindOneMatchByAnyIndex(irow types.IRow) types.IRow {
return r
}
return nil
case *PortGroup:
if r := db.PortGroup.OvsdbGetByAnyIndex(row); r != nil {
return r
}
return nil
case *QoS:
if r := db.QoS.OvsdbGetByAnyIndex(row); r != nil {
return r
@@ -258,6 +291,7 @@ type ACL struct {
ExternalIds map[string]string `json:"external_ids"`
Log bool `json:"log"`
Match string `json:"match"`
Meter *string `json:"meter"`
Name *string `json:"name"`
Priority int64 `json:"priority"`
Severity *string `json:"severity"`
@@ -284,6 +318,7 @@ func (row *ACL) OvsdbCmdArgs() []string {
r = append(r, types.OvsdbCmdArgsMapStringString("external_ids", row.ExternalIds)...)
r = append(r, types.OvsdbCmdArgsBoolean("log", row.Log)...)
r = append(r, types.OvsdbCmdArgsString("match", row.Match)...)
r = append(r, types.OvsdbCmdArgsStringOptional("meter", row.Meter)...)
r = append(r, types.OvsdbCmdArgsStringOptional("name", row.Name)...)
r = append(r, types.OvsdbCmdArgsInteger("priority", row.Priority)...)
r = append(r, types.OvsdbCmdArgsStringOptional("severity", row.Severity)...)
@@ -311,6 +346,8 @@ func (row *ACL) SetColumn(name string, val interface{}) (err error) {
row.Log = types.EnsureBoolean(val)
case "match":
row.Match = types.EnsureString(val)
case "meter":
row.Meter = types.EnsureStringOptional(val)
case "name":
row.Name = types.EnsureStringOptional(val)
case "priority":
@@ -345,6 +382,9 @@ func (row *ACL) MatchNonZeros(row1 *ACL) bool {
if !types.MatchStringIfNonZero(row.Match, row1.Match) {
return false
}
if !types.MatchStringOptionalIfNonZero(row.Meter, row1.Meter) {
return false
}
if !types.MatchStringOptionalIfNonZero(row.Name, row1.Name) {
return false
}
@@ -1546,6 +1586,54 @@ func (row *LogicalRouter) MatchNonZeros(row1 *LogicalRouter) bool {
return true
}
func (tbl LogicalRouterTable) FindLoadBalancerReferrer_load_balancer(refUuid string) (r []*LogicalRouter) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.LoadBalancer {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (tbl LogicalRouterTable) FindNATReferrer_nat(refUuid string) (r []*LogicalRouter) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.Nat {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (tbl LogicalRouterTable) FindLogicalRouterPortReferrer_ports(refUuid string) (r []*LogicalRouter) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.Ports {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (tbl LogicalRouterTable) FindLogicalRouterStaticRouteReferrer_static_routes(refUuid string) (r []*LogicalRouter) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.StaticRoutes {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (row *LogicalRouter) HasExternalIds() bool {
return true
}
@@ -1760,6 +1848,18 @@ func (row *LogicalRouterPort) MatchNonZeros(row1 *LogicalRouterPort) bool {
return true
}
func (tbl LogicalRouterPortTable) FindGatewayChassisReferrer_gateway_chassis(refUuid string) (r []*LogicalRouterPort) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.GatewayChassis {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (row *LogicalRouterPort) HasExternalIds() bool {
return true
}
@@ -2107,6 +2207,66 @@ func (row *LogicalSwitch) MatchNonZeros(row1 *LogicalSwitch) bool {
return true
}
func (tbl LogicalSwitchTable) FindACLReferrer_acls(refUuid string) (r []*LogicalSwitch) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.Acls {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (tbl LogicalSwitchTable) FindDNSReferrer_dns_records(refUuid string) (r []*LogicalSwitch) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.DnsRecords {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (tbl LogicalSwitchTable) FindLoadBalancerReferrer_load_balancer(refUuid string) (r []*LogicalSwitch) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.LoadBalancer {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (tbl LogicalSwitchTable) FindLogicalSwitchPortReferrer_ports(refUuid string) (r []*LogicalSwitch) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.Ports {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (tbl LogicalSwitchTable) FindQoSReferrer_qos_rules(refUuid string) (r []*LogicalSwitch) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.QosRules {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (row *LogicalSwitch) HasExternalIds() bool {
return true
}
@@ -2356,6 +2516,26 @@ func (row *LogicalSwitchPort) MatchNonZeros(row1 *LogicalSwitchPort) bool {
return true
}
func (tbl LogicalSwitchPortTable) FindDHCPOptionsReferrer_dhcpv4_options(refUuid string) (r []*LogicalSwitchPort) {
for i := range tbl {
row := &tbl[i]
if row.Dhcpv4Options != nil && *row.Dhcpv4Options == refUuid {
r = append(r, row)
}
}
return r
}
func (tbl LogicalSwitchPortTable) FindDHCPOptionsReferrer_dhcpv6_options(refUuid string) (r []*LogicalSwitchPort) {
for i := range tbl {
row := &tbl[i]
if row.Dhcpv6Options != nil && *row.Dhcpv6Options == refUuid {
r = append(r, row)
}
}
return r
}
func (row *LogicalSwitchPort) HasExternalIds() bool {
return true
}
@@ -2386,6 +2566,353 @@ func (row *LogicalSwitchPort) RemoveExternalId(k string) (string, bool) {
return r, ok
}
type MeterTable []Meter
var _ types.ITable = &MeterTable{}
func (tbl MeterTable) OvsdbTableName() string {
return "Meter"
}
func (tbl MeterTable) OvsdbIsRoot() bool {
return true
}
func (tbl MeterTable) Rows() []types.IRow {
r := make([]types.IRow, len(tbl))
for i := range tbl {
r[i] = &tbl[i]
}
return r
}
func (tbl MeterTable) NewRow() types.IRow {
return &Meter{}
}
func (tbl *MeterTable) AppendRow(irow types.IRow) {
row := irow.(*Meter)
*tbl = append(*tbl, *row)
}
func (tbl MeterTable) OvsdbHasIndex() bool {
return true
}
func (row *Meter) MatchByName(row1 *Meter) bool {
if !types.MatchString(row.Name, row1.Name) {
return false
}
return true
}
func (tbl MeterTable) GetByName(row1 *Meter) *Meter {
for i := range tbl {
row := &tbl[i]
if row.MatchByName(row1) {
return row
}
}
return nil
}
func (tbl MeterTable) OvsdbGetByAnyIndex(irow1 types.IRow) types.IRow {
row1 := irow1.(*Meter)
if !(types.IsZeroString(row1.Name)) {
if row := tbl.GetByName(row1); row != nil {
return row
}
}
return nil
}
func (tbl MeterTable) FindOneMatchNonZeros(row1 *Meter) *Meter {
for i := range tbl {
row := &tbl[i]
if row.MatchNonZeros(row1) {
return row
}
}
return nil
}
type Meter struct {
Uuid string `json:"_uuid"`
Version string `json:"_version"`
Bands []string `json:"bands"`
ExternalIds map[string]string `json:"external_ids"`
Name string `json:"name"`
Unit string `json:"unit"`
}
var _ types.IRow = &Meter{}
func (row *Meter) OvsdbTableName() string {
return "Meter"
}
func (row *Meter) OvsdbIsRoot() bool {
return true
}
func (row *Meter) OvsdbUuid() string {
return row.Uuid
}
func (row *Meter) OvsdbCmdArgs() []string {
r := []string{}
r = append(r, types.OvsdbCmdArgsUuidMultiples("bands", row.Bands)...)
r = append(r, types.OvsdbCmdArgsMapStringString("external_ids", row.ExternalIds)...)
r = append(r, types.OvsdbCmdArgsString("name", row.Name)...)
r = append(r, types.OvsdbCmdArgsString("unit", row.Unit)...)
return r
}
func (row *Meter) SetColumn(name string, val interface{}) (err error) {
defer func() {
if panicErr := recover(); panicErr != nil {
err = errors.Wrapf(panicErr.(error), "%s: %#v", name, fmt.Sprintf("%#v", val))
}
}()
switch name {
case "_uuid":
row.Uuid = types.EnsureUuid(val)
case "_version":
row.Version = types.EnsureUuid(val)
case "bands":
row.Bands = types.EnsureUuidMultiples(val)
case "external_ids":
row.ExternalIds = types.EnsureMapStringString(val)
case "name":
row.Name = types.EnsureString(val)
case "unit":
row.Unit = types.EnsureString(val)
default:
panic(types.ErrUnknownColumn)
}
return
}
func (row *Meter) MatchNonZeros(row1 *Meter) bool {
if !types.MatchUuidIfNonZero(row.Uuid, row1.Uuid) {
return false
}
if !types.MatchUuidIfNonZero(row.Version, row1.Version) {
return false
}
if !types.MatchUuidMultiplesIfNonZero(row.Bands, row1.Bands) {
return false
}
if !types.MatchMapStringStringIfNonZero(row.ExternalIds, row1.ExternalIds) {
return false
}
if !types.MatchStringIfNonZero(row.Name, row1.Name) {
return false
}
if !types.MatchStringIfNonZero(row.Unit, row1.Unit) {
return false
}
return true
}
func (tbl MeterTable) FindMeterBandReferrer_bands(refUuid string) (r []*Meter) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.Bands {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (row *Meter) HasExternalIds() bool {
return true
}
func (row *Meter) SetExternalId(k, v string) {
if row.ExternalIds == nil {
row.ExternalIds = map[string]string{}
}
row.ExternalIds[k] = v
}
func (row *Meter) GetExternalId(k string) (string, bool) {
if row.ExternalIds == nil {
return "", false
}
r, ok := row.ExternalIds[k]
return r, ok
}
func (row *Meter) RemoveExternalId(k string) (string, bool) {
if row.ExternalIds == nil {
return "", false
}
r, ok := row.ExternalIds[k]
if ok {
delete(row.ExternalIds, k)
}
return r, ok
}
type MeterBandTable []MeterBand
var _ types.ITable = &MeterBandTable{}
func (tbl MeterBandTable) OvsdbTableName() string {
return "Meter_Band"
}
func (tbl MeterBandTable) OvsdbIsRoot() bool {
return false
}
func (tbl MeterBandTable) Rows() []types.IRow {
r := make([]types.IRow, len(tbl))
for i := range tbl {
r[i] = &tbl[i]
}
return r
}
func (tbl MeterBandTable) NewRow() types.IRow {
return &MeterBand{}
}
func (tbl *MeterBandTable) AppendRow(irow types.IRow) {
row := irow.(*MeterBand)
*tbl = append(*tbl, *row)
}
func (tbl MeterBandTable) OvsdbHasIndex() bool {
return false
}
func (tbl MeterBandTable) OvsdbGetByAnyIndex(irow1 types.IRow) types.IRow {
return nil
}
func (tbl MeterBandTable) FindOneMatchNonZeros(row1 *MeterBand) *MeterBand {
for i := range tbl {
row := &tbl[i]
if row.MatchNonZeros(row1) {
return row
}
}
return nil
}
type MeterBand struct {
Uuid string `json:"_uuid"`
Version string `json:"_version"`
Action string `json:"action"`
BurstSize int64 `json:"burst_size"`
ExternalIds map[string]string `json:"external_ids"`
Rate int64 `json:"rate"`
}
var _ types.IRow = &MeterBand{}
func (row *MeterBand) OvsdbTableName() string {
return "Meter_Band"
}
func (row *MeterBand) OvsdbIsRoot() bool {
return false
}
func (row *MeterBand) OvsdbUuid() string {
return row.Uuid
}
func (row *MeterBand) OvsdbCmdArgs() []string {
r := []string{}
r = append(r, types.OvsdbCmdArgsString("action", row.Action)...)
r = append(r, types.OvsdbCmdArgsInteger("burst_size", row.BurstSize)...)
r = append(r, types.OvsdbCmdArgsMapStringString("external_ids", row.ExternalIds)...)
r = append(r, types.OvsdbCmdArgsInteger("rate", row.Rate)...)
return r
}
func (row *MeterBand) SetColumn(name string, val interface{}) (err error) {
defer func() {
if panicErr := recover(); panicErr != nil {
err = errors.Wrapf(panicErr.(error), "%s: %#v", name, fmt.Sprintf("%#v", val))
}
}()
switch name {
case "_uuid":
row.Uuid = types.EnsureUuid(val)
case "_version":
row.Version = types.EnsureUuid(val)
case "action":
row.Action = types.EnsureString(val)
case "burst_size":
row.BurstSize = types.EnsureInteger(val)
case "external_ids":
row.ExternalIds = types.EnsureMapStringString(val)
case "rate":
row.Rate = types.EnsureInteger(val)
default:
panic(types.ErrUnknownColumn)
}
return
}
func (row *MeterBand) MatchNonZeros(row1 *MeterBand) bool {
if !types.MatchUuidIfNonZero(row.Uuid, row1.Uuid) {
return false
}
if !types.MatchUuidIfNonZero(row.Version, row1.Version) {
return false
}
if !types.MatchStringIfNonZero(row.Action, row1.Action) {
return false
}
if !types.MatchIntegerIfNonZero(row.BurstSize, row1.BurstSize) {
return false
}
if !types.MatchMapStringStringIfNonZero(row.ExternalIds, row1.ExternalIds) {
return false
}
if !types.MatchIntegerIfNonZero(row.Rate, row1.Rate) {
return false
}
return true
}
func (row *MeterBand) HasExternalIds() bool {
return true
}
func (row *MeterBand) SetExternalId(k, v string) {
if row.ExternalIds == nil {
row.ExternalIds = map[string]string{}
}
row.ExternalIds[k] = v
}
func (row *MeterBand) GetExternalId(k string) (string, bool) {
if row.ExternalIds == nil {
return "", false
}
r, ok := row.ExternalIds[k]
return r, ok
}
func (row *MeterBand) RemoveExternalId(k string) (string, bool) {
if row.ExternalIds == nil {
return "", false
}
r, ok := row.ExternalIds[k]
if ok {
delete(row.ExternalIds, k)
}
return r, ok
}
type NATTable []NAT
var _ types.ITable = &NATTable{}
@@ -2696,6 +3223,28 @@ func (row *NBGlobal) MatchNonZeros(row1 *NBGlobal) bool {
return true
}
func (tbl NBGlobalTable) FindConnectionReferrer_connections(refUuid string) (r []*NBGlobal) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.Connections {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (tbl NBGlobalTable) FindSSLReferrer_ssl(refUuid string) (r []*NBGlobal) {
for i := range tbl {
row := &tbl[i]
if row.Ssl != nil && *row.Ssl == refUuid {
r = append(r, row)
}
}
return r
}
func (row *NBGlobal) HasExternalIds() bool {
return true
}
@@ -2726,6 +3275,209 @@ func (row *NBGlobal) RemoveExternalId(k string) (string, bool) {
return r, ok
}
type PortGroupTable []PortGroup
var _ types.ITable = &PortGroupTable{}
func (tbl PortGroupTable) OvsdbTableName() string {
return "Port_Group"
}
func (tbl PortGroupTable) OvsdbIsRoot() bool {
return true
}
func (tbl PortGroupTable) Rows() []types.IRow {
r := make([]types.IRow, len(tbl))
for i := range tbl {
r[i] = &tbl[i]
}
return r
}
func (tbl PortGroupTable) NewRow() types.IRow {
return &PortGroup{}
}
func (tbl *PortGroupTable) AppendRow(irow types.IRow) {
row := irow.(*PortGroup)
*tbl = append(*tbl, *row)
}
func (tbl PortGroupTable) OvsdbHasIndex() bool {
return true
}
func (row *PortGroup) MatchByName(row1 *PortGroup) bool {
if !types.MatchString(row.Name, row1.Name) {
return false
}
return true
}
func (tbl PortGroupTable) GetByName(row1 *PortGroup) *PortGroup {
for i := range tbl {
row := &tbl[i]
if row.MatchByName(row1) {
return row
}
}
return nil
}
func (tbl PortGroupTable) OvsdbGetByAnyIndex(irow1 types.IRow) types.IRow {
row1 := irow1.(*PortGroup)
if !(types.IsZeroString(row1.Name)) {
if row := tbl.GetByName(row1); row != nil {
return row
}
}
return nil
}
func (tbl PortGroupTable) FindOneMatchNonZeros(row1 *PortGroup) *PortGroup {
for i := range tbl {
row := &tbl[i]
if row.MatchNonZeros(row1) {
return row
}
}
return nil
}
type PortGroup struct {
Uuid string `json:"_uuid"`
Version string `json:"_version"`
Acls []string `json:"acls"`
ExternalIds map[string]string `json:"external_ids"`
Name string `json:"name"`
Ports []string `json:"ports"`
}
var _ types.IRow = &PortGroup{}
func (row *PortGroup) OvsdbTableName() string {
return "Port_Group"
}
func (row *PortGroup) OvsdbIsRoot() bool {
return true
}
func (row *PortGroup) OvsdbUuid() string {
return row.Uuid
}
func (row *PortGroup) OvsdbCmdArgs() []string {
r := []string{}
r = append(r, types.OvsdbCmdArgsUuidMultiples("acls", row.Acls)...)
r = append(r, types.OvsdbCmdArgsMapStringString("external_ids", row.ExternalIds)...)
r = append(r, types.OvsdbCmdArgsString("name", row.Name)...)
r = append(r, types.OvsdbCmdArgsUuidMultiples("ports", row.Ports)...)
return r
}
func (row *PortGroup) SetColumn(name string, val interface{}) (err error) {
defer func() {
if panicErr := recover(); panicErr != nil {
err = errors.Wrapf(panicErr.(error), "%s: %#v", name, fmt.Sprintf("%#v", val))
}
}()
switch name {
case "_uuid":
row.Uuid = types.EnsureUuid(val)
case "_version":
row.Version = types.EnsureUuid(val)
case "acls":
row.Acls = types.EnsureUuidMultiples(val)
case "external_ids":
row.ExternalIds = types.EnsureMapStringString(val)
case "name":
row.Name = types.EnsureString(val)
case "ports":
row.Ports = types.EnsureUuidMultiples(val)
default:
panic(types.ErrUnknownColumn)
}
return
}
func (row *PortGroup) MatchNonZeros(row1 *PortGroup) bool {
if !types.MatchUuidIfNonZero(row.Uuid, row1.Uuid) {
return false
}
if !types.MatchUuidIfNonZero(row.Version, row1.Version) {
return false
}
if !types.MatchUuidMultiplesIfNonZero(row.Acls, row1.Acls) {
return false
}
if !types.MatchMapStringStringIfNonZero(row.ExternalIds, row1.ExternalIds) {
return false
}
if !types.MatchStringIfNonZero(row.Name, row1.Name) {
return false
}
if !types.MatchUuidMultiplesIfNonZero(row.Ports, row1.Ports) {
return false
}
return true
}
func (tbl PortGroupTable) FindACLReferrer_acls(refUuid string) (r []*PortGroup) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.Acls {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (tbl PortGroupTable) FindLogicalSwitchPortReferrer_ports(refUuid string) (r []*PortGroup) {
for i := range tbl {
row := &tbl[i]
for _, val := range row.Ports {
if val == refUuid {
r = append(r, row)
}
}
}
return r
}
func (row *PortGroup) HasExternalIds() bool {
return true
}
func (row *PortGroup) SetExternalId(k, v string) {
if row.ExternalIds == nil {
row.ExternalIds = map[string]string{}
}
row.ExternalIds[k] = v
}
func (row *PortGroup) GetExternalId(k string) (string, bool) {
if row.ExternalIds == nil {
return "", false
}
r, ok := row.ExternalIds[k]
return r, ok
}
func (row *PortGroup) RemoveExternalId(k string) (string, bool) {
if row.ExternalIds == nil {
return "", false
}
r, ok := row.ExternalIds[k]
if ok {
delete(row.ExternalIds, k)
}
return r, ok
}
type QoSTable []QoS
var _ types.ITable = &QoSTable{}
+50 -2
View File
@@ -1,7 +1,7 @@
{
"name": "OVN_Northbound",
"version": "5.10.0",
"cksum": "626737541 17810",
"version": "5.13.0",
"cksum": "1278623084 20312",
"tables": {
"NB_Global": {
"columns": {
@@ -114,6 +114,24 @@
"min": 0, "max": "unlimited"}}},
"indexes": [["name"]],
"isRoot": true},
"Port_Group": {
"columns": {
"name": {"type": "string"},
"ports": {"type": {"key": {"type": "uuid",
"refTable": "Logical_Switch_Port",
"refType": "weak"},
"min": 0,
"max": "unlimited"}},
"acls": {"type": {"key": {"type": "uuid",
"refTable": "ACL",
"refType": "strong"},
"min": 0,
"max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"indexes": [["name"]],
"isRoot": true},
"Load_Balancer": {
"columns": {
"name": {"type": "string"},
@@ -148,6 +166,7 @@
"notice", "info",
"debug"]]},
"min": 0, "max": 1}},
"meter": {"type": {"key": "string", "min": 0, "max": 1}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
@@ -177,6 +196,35 @@
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"isRoot": false},
"Meter": {
"columns": {
"name": {"type": "string"},
"unit": {"type": {"key": {"type": "string",
"enum": ["set", ["kbps", "pktps"]]}}},
"bands": {"type": {"key": {"type": "uuid",
"refTable": "Meter_Band",
"refType": "strong"},
"min": 1,
"max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"indexes": [["name"]],
"isRoot": true},
"Meter_Band": {
"columns": {
"action": {"type": {"key": {"type": "string",
"enum": ["set", ["drop"]]}}},
"rate": {"type": {"key": {"type": "integer",
"minInteger": 1,
"maxInteger": 4294967295}}},
"burst_size": {"type": {"key": {"type": "integer",
"minInteger": 0,
"maxInteger": 4294967295}}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"isRoot": false},
"Logical_Router": {
"columns": {
"name": {"type": "string"},
+33 -2
View File
@@ -1,7 +1,7 @@
{
"name": "OVN_Southbound",
"version": "1.15.0",
"cksum": "70426956 13327",
"version": "1.16.0",
"cksum": "3046632234 14844",
"tables": {
"SB_Global": {
"columns": {
@@ -55,6 +55,14 @@
"max": "unlimited"}}},
"indexes": [["name"]],
"isRoot": true},
"Port_Group": {
"columns": {
"name": {"type": "string"},
"ports": {"type": {"key": "string",
"min": 0,
"max": "unlimited"}}},
"indexes": [["name"]],
"isRoot": true},
"Logical_Flow": {
"columns": {
"logical_datapath": {"type": {"key": {"type": "uuid",
@@ -90,6 +98,29 @@
"indexes": [["datapath", "tunnel_key"],
["datapath", "name"]],
"isRoot": true},
"Meter": {
"columns": {
"name": {"type": "string"},
"unit": {"type": {"key": {"type": "string",
"enum": ["set", ["kbps", "pktps"]]}}},
"bands": {"type": {"key": {"type": "uuid",
"refTable": "Meter_Band",
"refType": "strong"},
"min": 1,
"max": "unlimited"}}},
"indexes": [["name"]],
"isRoot": true},
"Meter_Band": {
"columns": {
"action": {"type": {"key": {"type": "string",
"enum": ["set", ["drop"]]}}},
"rate": {"type": {"key": {"type": "integer",
"minInteger": 1,
"maxInteger": 4294967295}}},
"burst_size": {"type": {"key": {"type": "integer",
"minInteger": 0,
"maxInteger": 4294967295}}}},
"isRoot": false},
"Datapath_Binding": {
"columns": {
"tunnel_key": {
+4
View File
@@ -22,6 +22,8 @@ type Table struct {
MaxRows int
IsRoot bool
Indexes [][]string
schema *Schema
}
type Columns map[string]Column
@@ -118,6 +120,8 @@ func ParseSchema(r io.Reader) (*Schema, error) {
},
},
},
schema: sch,
}
for colName, pcol := range ptbl.Columns {
col := Column{
+96
View File
@@ -293,6 +293,65 @@ func (tbl *Table) gen(w writer) {
w.Writef(`}`)
w.Writef(``)
for _, colName := range tbl.OrderedColumnNames() {
var (
col = tbl.Columns[colName]
)
if col.Type.Key.Type == Uuid && col.Type.Key.RefTable != "" {
var (
refTbl = tbl.schema.Tables[col.Type.Key.RefTable]
refRowTyp = refTbl.rowTypeName()
)
w.Writef(`func (tbl %s) Find%sReferrer_%s(refUuid string) (r []*%s) {`, tblTyp, refRowTyp, col.Name, tbl.rowTypeName())
w.Writef(` for i := range tbl {`)
w.Writef(` row := &tbl[i]`)
ordinal := col.ordinal()
switch ordinal {
case ordinalAtom:
w.Writef(` if row.%s == refUuid {`, col.goField())
case ordinalOptional:
w.Writef(` if row.%s != nil && *row.%s == refUuid {`, col.goField(), col.goField())
case ordinalMultiples:
w.Writef(` for _, val := range row.%s {`, col.goField())
w.Writef(` if val == refUuid {`)
case ordinalMap:
w.Writef(` for val := range row.%s {`, col.goField())
w.Writef(` if val == refUuid {`)
default:
panic(fmt.Sprintf("table %s column %s: unexpected ordinal %#v",
tbl.Name, col.Name, ordinal))
}
w.Writef(` r = append(r, row)`)
w.Writef(` }`)
if ordinal == ordinalMultiples || ordinal == ordinalMap {
w.Writef(` }`)
}
w.Writef(` }`)
w.Writef(` return r`)
w.Writef(`}`)
w.Writef(``)
}
if col.Type.Value.Type.isValid() &&
col.Type.Value.Type == Uuid && col.Type.Value.RefTable != "" {
var (
refTbl = tbl.schema.Tables[col.Type.Value.RefTable]
refRowTyp = refTbl.rowTypeName()
)
w.Writef(`func (tbl %s) Find%sReferrer2_%s(refUuid string) (r []*%s) {`, tblTyp, refRowTyp, col.Name, tbl.rowTypeName())
w.Writef(` for i := range tbl {`)
w.Writef(` row := &tbl[i]`)
w.Writef(` for _, val := range row.%s {`, col.goField())
w.Writef(` if val == refUuid {`)
w.Writef(` r = append(r, row)`)
w.Writef(` }`)
w.Writef(` }`)
w.Writef(` }`)
w.Writef(` return r`)
w.Writef(`}`)
w.Writef(``)
}
}
{
_, ok := tbl.Columns["external_ids"]
g := func(f func()) {
@@ -393,6 +452,43 @@ func (col *Column) goTags() string {
return fmt.Sprintf("`json:\"%s\"`", col.Name)
}
type ordinal int
const (
ordinalAtom ordinal = iota
ordinalOptional
ordinalMultiples
ordinalMap
)
func (col *Column) ordinal() ordinal {
var (
typ = &col.Type
atomV = typ.Value.Type
)
if atomV.isValid() {
return ordinalMap
}
if typ.MaxUnlimited {
return ordinalMultiples
}
min, max := typ.Min, typ.Max
if min == 0 {
if max == 0 {
panic(fmt.Sprintf("column type with min, max both being 0"))
} else if max == 1 {
return ordinalOptional
} else {
return ordinalMultiples
}
} else if max == 1 {
return ordinalAtom
} else {
return ordinalMultiples
}
}
func (col *Column) funcNameSuffix() string {
var (
typ = &col.Type
+16 -11
View File
@@ -1,6 +1,6 @@
{"name": "Open_vSwitch",
"version": "7.15.1",
"cksum": "3682332033 23608",
"version": "7.16.1",
"cksum": "1452282319 23860",
"tables": {
"Open_vSwitch": {
"columns": {
@@ -47,7 +47,12 @@
"min": 0, "max": "unlimited"}},
"iface_types": {
"type": {"key": {"type": "string"},
"min": 0, "max": "unlimited"}}},
"min": 0, "max": "unlimited"}},
"dpdk_initialized": {
"type": "boolean"},
"dpdk_version": {
"type": {"key": {"type": "string"},
"min": 0, "max": 1}}},
"isRoot": true,
"maxRows": 1},
"Bridge": {
@@ -101,7 +106,7 @@
"OpenFlow14",
"OpenFlow15",
"OpenFlow16"]]},
"min": 0, "max": "unlimited"}},
"min": 0, "max": "unlimited"}},
"fail_mode": {
"type": {"key": {"type": "string",
"enum": ["set", ["standalone", "secure"]]},
@@ -358,16 +363,16 @@
"Flow_Table": {
"columns": {
"name": {
"type": {"key": "string", "min": 0, "max": 1}},
"type": {"key": "string", "min": 0, "max": 1}},
"flow_limit": {
"type": {"key": {"type": "integer", "minInteger": 0},
"min": 0, "max": 1}},
"type": {"key": {"type": "integer", "minInteger": 0},
"min": 0, "max": 1}},
"overflow_policy": {
"type": {"key": {"type": "string",
"enum": ["set", ["refuse", "evict"]]},
"min": 0, "max": 1}},
"type": {"key": {"type": "string",
"enum": ["set", ["refuse", "evict"]]},
"min": 0, "max": 1}},
"groups": {
"type": {"key": "string", "min": 0, "max": "unlimited"}},
"type": {"key": "string", "min": 0, "max": "unlimited"}},
"prefixes": {
"type": {"key": "string", "min": 0, "max": 3}},
"external_ids": {