diff --git a/pkg/controller/subnet.go b/pkg/controller/subnet.go index 6d53bffe1e8..8ee39b446b4 100644 --- a/pkg/controller/subnet.go +++ b/pkg/controller/subnet.go @@ -487,15 +487,15 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error { return err } - cachedSubnet, err = c.subnetsLister.Get(key) + subnet, err = c.config.KubeOvnClient.KubeovnV1().Subnets().Get(context.Background(), key, metav1.GetOptions{}) if err != nil { if k8serrors.IsNotFound(err) { return nil } + klog.Errorf("failed to get subnet %s error %v", key, err) return err } - subnet = cachedSubnet.DeepCopy() deleted, err := c.handleSubnetFinalizer(subnet) if err != nil { klog.Errorf("handle subnet finalizer failed %v", err) @@ -625,6 +625,13 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error { c.patchSubnetStatus(subnet, "CreateLogicalSwitchFailed", err.Error()) return err } + + if needRouter { + if err := c.reconcileRouterPortBySubnet(vpc, subnet); err != nil { + klog.Errorf("failed to connect switch %s to router %s, %v", subnet.Name, vpc.Name, err) + return err + } + } } else { // logical switch exists, only update other_config if err := c.ovnLegacyClient.SetLogicalSwitchConfig(subnet.Name, vpc.Status.Router, subnet.Spec.Protocol, subnet.Spec.CIDRBlock, subnet.Spec.Gateway, subnet.Spec.ExcludeIps, needRouter); err != nil { diff --git a/pkg/controller/vpc.go b/pkg/controller/vpc.go index fde0b09d723..12489b30341 100644 --- a/pkg/controller/vpc.go +++ b/pkg/controller/vpc.go @@ -199,6 +199,35 @@ func (c *Controller) reconcileRouterPorts(vpc *kubeovnv1.Vpc) error { return nil } +func (c *Controller) reconcileRouterPortBySubnet(vpc *kubeovnv1.Vpc, subnet *kubeovnv1.Subnet) error { + router := vpc.Name + routerPortName := ovs.LogicalRouterPortName(router, subnet.Name) + exists, err := c.ovnClient.LogicalRouterPortExists(routerPortName) + if err != nil { + return err + } + + if !exists { + subnet, err := c.subnetsLister.Get(subnet.Name) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil + } + klog.Errorf("failed to get subnet %s, err %v", subnet.Name, err) + return err + } + + networks := util.GetIpAddrWithMask(subnet.Spec.Gateway, subnet.Spec.CIDRBlock) + klog.Infof("router port does not exist, trying to create %s with ip %s", routerPortName, networks) + + if err := c.ovnClient.AddLogicalRouterPort(router, routerPortName, "", networks); err != nil { + klog.Errorf("failed to create router port %s, err %v", routerPortName, err) + return err + } + } + return nil +} + type VpcLoadBalancer struct { TcpLoadBalancer string TcpSessLoadBalancer string @@ -660,17 +689,13 @@ func (c *Controller) getVpcSubnets(vpc *kubeovnv1.Vpc) (subnets []string, defaul } for _, subnet := range allSubnets { - deleted, err := c.handleSubnetFinalizer(subnet) - if err != nil { - klog.Errorf("handle subnet finalizer failed %v", err) - return nil, "", err + if subnet.Spec.Vpc != vpc.Name || !subnet.DeletionTimestamp.IsZero() { + continue } - if !deleted && subnet.Spec.Vpc == vpc.Name { - subnets = append(subnets, subnet.Name) - if subnet.Spec.Default { - defaultSubnet = subnet.Name - } + subnets = append(subnets, subnet.Name) + if subnet.Spec.Default { + defaultSubnet = subnet.Name } } return diff --git a/pkg/ovs/ovn-nb-logical_switch.go b/pkg/ovs/ovn-nb-logical_switch.go new file mode 100644 index 00000000000..a2fb093787d --- /dev/null +++ b/pkg/ovs/ovn-nb-logical_switch.go @@ -0,0 +1,27 @@ +package ovs + +import ( + "context" + "fmt" + + "github.com/ovn-org/libovsdb/client" + + "github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb" +) + +func (c OvnClient) GetLogicalSwitch(name string, ignoreNotFound bool) (*ovnnb.LogicalSwitch, error) { + ls := &ovnnb.LogicalSwitch{Name: name} + if err := c.ovnNbClient.Get(context.TODO(), ls); err != nil { + if ignoreNotFound && err == client.ErrNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to get logical switch %s: %v", name, err) + } + + return ls, nil +} + +func (c OvnClient) LogicalSwitchExists(name string) (bool, error) { + ls, err := c.GetLogicalSwitch(name, true) + return ls != nil, err +} diff --git a/pkg/ovs/ovn-nb-logical_switch_port.go b/pkg/ovs/ovn-nb-logical_switch_port.go index a3f81bb20be..89a9e02b220 100644 --- a/pkg/ovs/ovn-nb-logical_switch_port.go +++ b/pkg/ovs/ovn-nb-logical_switch_port.go @@ -5,8 +5,12 @@ import ( "fmt" "github.com/ovn-org/libovsdb/client" + "github.com/ovn-org/libovsdb/model" + "github.com/ovn-org/libovsdb/ovsdb" + "k8s.io/klog/v2" + ovsclient "github.com/kubeovn/kube-ovn/pkg/ovsdb/client" "github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb" "github.com/kubeovn/kube-ovn/pkg/util" ) @@ -66,3 +70,54 @@ func (c OvnClient) LogicalSwitchPortExists(name string) (bool, error) { lsp, err := c.GetLogicalSwitchPort(name, true) return lsp != nil, err } + +func (c OvnClient) AddSwitchRouterPort(ls, lr string) error { + klog.Infof("add %s to %s", ls, lr) + lsTolr := fmt.Sprintf("%s-%s", ls, lr) + lrTols := fmt.Sprintf("%s-%s", lr, ls) + + logicalSwitch, err := c.GetLogicalSwitch(ls, false) + if err != nil { + return err + } + + var ops []ovsdb.Operation + + lsp := &ovnnb.LogicalSwitchPort{ + UUID: ovsclient.NamedUUID(), + Name: lsTolr, + Type: "router", + Addresses: []string{"router"}, + Options: map[string]string{"router-port": lrTols}, + ExternalIDs: map[string]string{"vendor": util.CniTypeName}, + } + + // ensure there is no port in the same name, before we create it in the transaction + waitOp := ConstructWaitForNameNotExistsOperation(lsTolr, "Logical_Switch_Port") + ops = append(ops, waitOp) + + createOps, err := c.ovnNbClient.Create(lsp) + if err != nil { + return err + } + ops = append(ops, createOps...) + + mutationOps, err := c.ovnNbClient. + Where(logicalSwitch). + Mutate(logicalSwitch, + model.Mutation{ + Field: &logicalSwitch.Ports, + Mutator: ovsdb.MutateOperationInsert, + Value: []string{lsp.UUID}, + }, + ) + if err != nil { + return err + } + ops = append(ops, mutationOps...) + + if err := Transact(c.ovnNbClient, "lsp-add", ops, c.ovnNbClient.Timeout); err != nil { + return fmt.Errorf("failed to create logical switch port %s: %v", lsTolr, err) + } + return nil +} diff --git a/pkg/ovs/ovn-nbctl-legacy.go b/pkg/ovs/ovn-nbctl-legacy.go index 29c43c2f834..19d2d20cf95 100644 --- a/pkg/ovs/ovn-nbctl-legacy.go +++ b/pkg/ovs/ovn-nbctl-legacy.go @@ -456,9 +456,7 @@ func (c LegacyClient) CreateLogicalSwitch(ls, lr, subnet, gateway string, needRo } if needRouter { - ip := util.GetIpAddrWithMask(gateway, subnet) - mac := util.GenerateMac() - if err := c.createRouterPort(ls, lr, ip, mac); err != nil { + if err := c.createRouterPort(ls, lr); err != nil { klog.Errorf("failed to connect switch %s to router, %v", ls, err) return err } @@ -791,8 +789,8 @@ func (c LegacyClient) RemoveRouterPort(ls, lr string) error { return nil } -func (c LegacyClient) createRouterPort(ls, lr, ip, mac string) error { - klog.Infof("add %s to %s with ip=%s, mac=%s", ls, lr, ip, mac) +func (c LegacyClient) createRouterPort(ls, lr string) error { + klog.Infof("add %s to %s", ls, lr) lsTolr := fmt.Sprintf("%s-%s", ls, lr) lrTols := fmt.Sprintf("%s-%s", lr, ls) _, err := c.ovnNbCommand(MayExist, "lsp-add", ls, lsTolr, "--", @@ -804,20 +802,6 @@ func (c LegacyClient) createRouterPort(ls, lr, ip, mac string) error { klog.Errorf("failed to create switch router port %s: %v", lsTolr, err) return err } - if len(ip) == 0 { - klog.Errorf("failed to create switch router port: ip is empty") - return err - } - ipStr := strings.Split(ip, ",") - if len(ipStr) == 2 { - _, err = c.ovnNbCommand(MayExist, "lrp-add", lr, lrTols, mac, ipStr[0], ipStr[1]) - } else { - _, err = c.ovnNbCommand(MayExist, "lrp-add", lr, lrTols, mac, ipStr[0]) - } - if err != nil { - klog.Errorf("failed to create router port %s: %v", lrTols, err) - return err - } return nil }