forked from submariner-io/submariner
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement the OVNKubernetes handler for the np syncer
Programs the integration with OVN via goovn and ovn-nbctl commandline tools reacting to local and remote endpoint changes. Related-Issue: submariner-io#859 Related-Issue: submariner-io#778 Signed-off-by: Miguel Angel Ajo <majopela@redhat.com>
- Loading branch information
Showing
15 changed files
with
835 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package ovn | ||
|
||
import ( | ||
"crypto/tls" | ||
"crypto/x509" | ||
"io/ioutil" | ||
"os" | ||
|
||
goovn "github.com/ebay/go-ovn" | ||
"github.com/pkg/errors" | ||
|
||
"github.com/submariner-io/submariner/pkg/networkplugin-syncer/handlers/ovn/nbctl" | ||
) | ||
|
||
const ( | ||
ovnCert = "/ovn-cert/tls.crt" | ||
ovnPrivKey = "/ovn-cert/tls.key" | ||
ovnCABundle = "/ovn-ca/ca-bundle.crt" | ||
defaultOVNNBDB = "ssl:ovnkube-db.openshift-ovn-kubernetes.svc.cluster.local:9641" | ||
defaultOVNSBDB = "ssl:ovnkube-db.openshift-ovn-kubernetes.svc.cluster.local:9642" | ||
) | ||
|
||
func (ovn *SyncHandler) initClients() error { | ||
tlsConfig, err := getOVNTLSConfig() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ovn.nbctl = nbctl.New(defaultOVNNBDB, ovnPrivKey, ovnCert, ovnCABundle) | ||
|
||
ovn.nbdb, err = goovn.NewClient(&goovn.Config{ | ||
Addr: getOVNNBDBAddress(), | ||
Reconnect: true, | ||
TLSConfig: tlsConfig, | ||
Db: goovn.DBNB}) | ||
|
||
if err != nil { | ||
return errors.Wrap(err, "Error creating NBDB connection") | ||
} | ||
|
||
ovn.sbdb, err = goovn.NewClient(&goovn.Config{ | ||
Addr: getOVNSBDBAddress(), | ||
Reconnect: true, | ||
TLSConfig: tlsConfig, | ||
Db: goovn.DBSB}) | ||
|
||
if err != nil { | ||
return errors.Wrap(err, "Error creating SBDB connection") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func getOVNNBDBAddress() string { | ||
addr := os.Getenv("OVN_NBDB") | ||
if addr == "" { | ||
return defaultOVNNBDB | ||
} | ||
|
||
return addr | ||
} | ||
|
||
func getOVNSBDBAddress() string { | ||
addr := os.Getenv("OVN_SBDB") | ||
if addr == "" { | ||
return defaultOVNSBDB | ||
} | ||
|
||
return addr | ||
} | ||
|
||
func getOVNTLSConfig() (*tls.Config, error) { | ||
cert, err := tls.LoadX509KeyPair(ovnCert, ovnPrivKey) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "Failure loading ovn certificates") | ||
} | ||
|
||
rootCAs := x509.NewCertPool() | ||
|
||
data, err := ioutil.ReadFile(ovnCABundle) | ||
|
||
if err != nil { | ||
return nil, errors.Wrap(err, "Failure loading OVNDB CA bundle") | ||
} | ||
|
||
rootCAs.AppendCertsFromPEM(data) | ||
|
||
return &tls.Config{ | ||
Certificates: []tls.Certificate{cert}, | ||
RootCAs: rootCAs, | ||
ServerName: "ovn", | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package ovn | ||
|
||
import ( | ||
"errors" | ||
|
||
goovn "github.com/ebay/go-ovn" | ||
|
||
submV1 "github.com/submariner-io/submariner/pkg/apis/submariner.io/v1" | ||
"github.com/submariner-io/submariner/pkg/event" | ||
"github.com/submariner-io/submariner/pkg/networkplugin-syncer/handlers/ovn/nbctl" | ||
) | ||
|
||
type SyncHandler struct { | ||
event.HandlerBase | ||
nbctl *nbctl.NbCtl | ||
nbdb goovn.Client | ||
sbdb goovn.Client | ||
localEndpoint *submV1.Endpoint | ||
remoteEndpoints map[string]*submV1.Endpoint | ||
lastOvnGwChassis string | ||
} | ||
|
||
func (ovn *SyncHandler) GetName() string { | ||
return "ovn-sync-handler" | ||
} | ||
|
||
func (ovn *SyncHandler) GetNetworkPlugin() string { | ||
return "OVNKubernetes" | ||
} | ||
|
||
func NewSyncHandler() *SyncHandler { | ||
return &SyncHandler{ | ||
remoteEndpoints: make(map[string]*submV1.Endpoint), | ||
} | ||
} | ||
|
||
func (ovn *SyncHandler) Init() error { | ||
if err := ovn.initClients(); err != nil { | ||
return err | ||
} | ||
|
||
if err := ovn.ensureSubmarinerInfra(); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (ovn *SyncHandler) LocalEndpointCreated(endpoint *submV1.Endpoint) error { | ||
ovn.localEndpoint = endpoint | ||
|
||
return ovn.updateGatewayNode() | ||
} | ||
|
||
func (ovn *SyncHandler) LocalEndpointUpdated(endpoint *submV1.Endpoint) error { | ||
ovn.localEndpoint = endpoint | ||
|
||
return ovn.updateGatewayNode() | ||
} | ||
|
||
func (ovn *SyncHandler) LocalEndpointRemoved(endpoint *submV1.Endpoint) error { | ||
if ovn.localEndpoint.Name == endpoint.Name { | ||
ovn.localEndpoint = nil | ||
} | ||
|
||
return ovn.updateGatewayNode() | ||
} | ||
|
||
func (ovn *SyncHandler) RemoteEndpointCreated(endpoint *submV1.Endpoint) error { | ||
ovn.remoteEndpoints[endpoint.Name] = endpoint | ||
return ovn.updateRemoteEndpointsInfra() | ||
} | ||
|
||
func (ovn *SyncHandler) RemoteEndpointUpdated(endpoint *submV1.Endpoint) error { | ||
ovn.remoteEndpoints[endpoint.Name] = endpoint | ||
return ovn.updateRemoteEndpointsInfra() | ||
} | ||
|
||
func (ovn *SyncHandler) RemoteEndpointRemoved(endpoint *submV1.Endpoint) error { | ||
delete(ovn.remoteEndpoints, endpoint.Name) | ||
return ovn.updateRemoteEndpointsInfra() | ||
} | ||
|
||
var WaitingForLocalEndpoint = errors.New("Waiting for the local endpoint details before we can " + | ||
"setup any remote-endpoint related information, this will be retried.") | ||
|
||
func (ovn *SyncHandler) updateRemoteEndpointsInfra() error { | ||
if ovn.localEndpoint == nil { | ||
// If we don't have information on the localEndpoint chances are that we are not detecting | ||
// the local endpoint yet (right CLUSTER_ID set), with the risk of setting up local routes as | ||
// remote routes and breaking the cluster. | ||
return WaitingForLocalEndpoint // this will be retried eventually | ||
} | ||
|
||
// Synchronize the policy rules inserted by submariner in the ovn_cluster_router, those point to submariner_router | ||
err := ovn.setupOvnClusterRouterRemoteRules() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Synchronize the routing rules inserted into submariner_router pointing to the remote clusters via the node IP in | ||
// the ovs external network bridge used by OVN kubernetes to talk to the host. | ||
err = ovn.updateSubmarinerRouterRemoteRoutes() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.