OpenShift SDN: Changed ovs.Transaction from pseudo to real atomic transaction#19393
Conversation
|
@openshift/sig-networking PTAL |
danwinship
left a comment
There was a problem hiding this comment.
I think exposing Bundle in the API adds a lot of complexity without much benefit. In particular, if you drop it from the public API, then you can also drop basically all of your changes to fake_ovs, and also remove BundleAddFlowRepr and BundleDeleteFlowRepr as APIs (and just have them be internal details of ovsExec's AddFlow and DeleteFlows implementations).
pkg/util/ovs/ovs.go
Outdated
| stdin := bytes.NewBufferString(stdinString) | ||
| kcmd.SetStdin(stdin) | ||
|
|
||
| glog.V(4).Infof("Executing: %s %s |\n%s", cmd, strings.Join(args, " "), stdinString) |
There was a problem hiding this comment.
The use of | there is weird: it makes it look like you're piping the output of ovs-ofctl to the string.
Actually, just changing | to << should make it clear what's going on, shell-syntax-wise, I think?
pkg/util/ovs/fake_ovs.go
Outdated
| addPrefix := "flow add" | ||
| delPrefix := "flow delete" | ||
|
|
||
| if strings.Contains(bundleFlow, addPrefix) { |
pkg/util/ovs/fake_ovs.go
Outdated
|
|
||
| if isAdd { | ||
| tx.AddFlow(flow) | ||
| fake.addFlowHelper(flow) |
There was a problem hiding this comment.
you need to check the error return here
37d263e to
8207b0b
Compare
8207b0b to
6c4fda1
Compare
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: pravisankar The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
@danwinship Updated, PTAL |
6c4fda1 to
ffc8186
Compare
|
/retest |
pkg/util/ovs/ovs.go
Outdated
|
|
||
| // New returns a new ovs.Interface | ||
| func New(execer exec.Interface, bridge string, minVersion string) (Interface, error) { | ||
| func New(execer exec.Interface, bridge string, minVersion string) (*ovsExec, error) { |
There was a problem hiding this comment.
Hm... isn't that bad style? Maybe you could just have TestBundle() cast it from Interface to *ovsExec.
Alternatively, after the next commit, TestBundle() doesn't really do anything beyond what TestTransactionSuccess() and TestTransactionFailure() do, so you could just drop TestBundle() (and maybe add a TestEmptyTransaction() in the next commit if you want to explicitly test that case too.)
pkg/network/node/ovscontroller.go
Outdated
| @@ -496,7 +491,7 @@ func (oc *ovsController) UpdateEgressNetworkPolicyRules(policies []networkapi.Eg | |||
| otx.DeleteFlows("table=101, reg0=%d, cookie=1/1", vnid) | |||
There was a problem hiding this comment.
UpdateEgressNetworkPolicyRules no longer needs to do the "temporarily drop all outgoing traffic to avoid race conditions" thing.
You can also revert the changes from #19346 since they're no longer needed
pkg/util/ovs/ovs_test.go
Outdated
| fexec := normalSetup() | ||
| addTestResult(t, fexec, "ovs-ofctl -O OpenFlow13 add-flow br0 flow1", "", nil) | ||
| addTestResult(t, fexec, "ovs-ofctl -O OpenFlow13 add-flow br0 flow2", "", nil) | ||
| addTestResult(t, fexec, "ovs-ofctl -O OpenFlow13 bundle br0 -", "", nil) |
There was a problem hiding this comment.
(It would be nice if we could test the stdin value too...)
|
|
||
| func (fake *ovsFake) NewTransaction() Transaction { | ||
| return &ovsFakeTx{fake: fake, err: fake.ensureExists()} | ||
| return &ovsFakeTx{fake: fake, flows: []string{}} |
There was a problem hiding this comment.
Note that there's a mild behavior change here: it used to check that you had called ovsif.AddBridge() on the ovsFake, but now it doesn't. (We apparently don't test this case in fake_ovs_test.go.) Anyway, you could just move the fake.ensureExists() call to Commit
| err := tx.err | ||
| tx.err = nil | ||
| return err | ||
| func (tx *ovsFakeTx) Commit() error { |
There was a problem hiding this comment.
This doesn't actually implement transactional behavior: if you do
tx.AddFlow("table=10, actions=drop")
tx.AddFlow("@!#$!@#$!@#$")
tx.Commit()
then it will return an error saying that the second flow couldn't be parsed, but the "table=10, actions=drop" flow will still have been added.
There should probably be a test of transactionality in fake_ovs_test.go
7176cdf to
68f3e6d
Compare
|
@danwinship Addressed all your comments, PTAL |
68f3e6d to
06ac661
Compare
|
Looks good to me. @dcbw can you take a look please? |
- bundle() enables execution of given add and/or delete ovs flows in a single atomic transaction
- Leverages ovs.bundle() to perform atomic transactions - Now ovs.Transaction interface has AddFlow(), DeleteFlows() and Commit() methods General usage: otx := ovs.NewTransaction() otx.AddFlow(flow1) // No execution, only caches flow context ... otx.DeleteFlows(flowN) // No execution, only caches flow context ... err := otx.Commit() // Executes all cached flows as single atomic transaction - With this change, most of the operations in ovs controller like setup, addHostSubnet, addService, etc. has only one ovs bundle call. So there won't be partial commited changes and it reduces the downtime during watch resync events.
- With ovs atomic transaction, flows are actually executed when Commit() is called so we no longer need the earlier workaround.
06ac661 to
105395d
Compare
|
/lgtm |
|
/retest |
2 similar comments
|
/retest |
|
/retest |
|
/retest Please review the full test history for this PR and help us cut down flakes. |
General usage:
otx := ovs.NewTransaction()
otx.AddFlow(flow1) // No execution, only caches flow context
...
otx.DeleteFlows(flowN) // No execution, only caches flow context
...
err := otx.Commit() // Executes all cached flows as single atomic transaction
addHostSubnet, addService, etc. has only one ovs bundle call. So there
won't be partial commited changes and it reduces the downtime during
watch resync events.