1
1
package ovs
2
2
3
3
import (
4
+ "bytes"
4
5
"fmt"
5
6
"strconv"
6
7
"strings"
@@ -72,6 +73,9 @@ type Interface interface {
72
73
// strings, one per flow. If flow is not "" then it describes the flows to dump.
73
74
DumpFlows (flow string , args ... interface {}) ([]string , error )
74
75
76
+ // Bundle executes all given flows as a single atomic transaction
77
+ Bundle (flows []string ) error
78
+
75
79
// NewTransaction begins a new OVS transaction. If an error occurs at
76
80
// any step in the transaction, it will be recorded until
77
81
// EndTransaction(), and any further calls on the transaction will be
@@ -138,13 +142,23 @@ func New(execer exec.Interface, bridge string, minVersion string) (Interface, er
138
142
return ovsif , nil
139
143
}
140
144
141
- func (ovsif * ovsExec ) exec (cmd string , args ... string ) (string , error ) {
145
+ func (ovsif * ovsExec ) execWithStdin (cmd string , stdinArgs [] string , args ... string ) (string , error ) {
142
146
if cmd == OVS_OFCTL {
143
147
args = append ([]string {"-O" , "OpenFlow13" }, args ... )
144
148
}
145
- glog .V (4 ).Infof ("Executing: %s %s" , cmd , strings .Join (args , " " ))
146
149
147
- output , err := ovsif .execer .Command (cmd , args ... ).CombinedOutput ()
150
+ kcmd := ovsif .execer .Command (cmd , args ... )
151
+ if stdinArgs != nil {
152
+ stdinString := strings .Join (stdinArgs , "\n " )
153
+ stdin := bytes .NewBufferString (stdinString )
154
+ kcmd .SetStdin (stdin )
155
+
156
+ glog .V (4 ).Infof ("Executing: %s %s |\n %s" , cmd , strings .Join (args , " " ), stdinString )
157
+ } else {
158
+ glog .V (4 ).Infof ("Executing: %s %s" , cmd , strings .Join (args , " " ))
159
+ }
160
+
161
+ output , err := kcmd .CombinedOutput ()
148
162
if err != nil {
149
163
glog .V (2 ).Infof ("Error executing %s: %s" , cmd , string (output ))
150
164
return "" , err
@@ -161,6 +175,10 @@ func (ovsif *ovsExec) exec(cmd string, args ...string) (string, error) {
161
175
return outStr , nil
162
176
}
163
177
178
+ func (ovsif * ovsExec ) exec (cmd string , args ... string ) (string , error ) {
179
+ return ovsif .execWithStdin (cmd , nil , args ... )
180
+ }
181
+
164
182
func (ovsif * ovsExec ) AddBridge (properties ... string ) error {
165
183
args := []string {"add-br" , ovsif .bridge }
166
184
if len (properties ) > 0 {
@@ -334,3 +352,28 @@ func (ovsif *ovsExec) DumpFlows(flow string, args ...interface{}) ([]string, err
334
352
}
335
353
return flows , nil
336
354
}
355
+
356
+ func (ovsif * ovsExec ) Bundle (flows []string ) error {
357
+ if len (flows ) == 0 {
358
+ return nil
359
+ }
360
+
361
+ _ , err := ovsif .execWithStdin (OVS_OFCTL , flows , "bundle" , ovsif .bridge , "-" )
362
+ return err
363
+ }
364
+
365
+ // BundleAddFlowRepr converts regular flow add rule to bundle compatible flow rule
366
+ func BundleAddFlowRepr (flow string , args ... interface {}) string {
367
+ if len (args ) > 0 {
368
+ flow = fmt .Sprintf (flow , args ... )
369
+ }
370
+ return fmt .Sprintf ("flow add %s" , flow )
371
+ }
372
+
373
+ // BundleDeleteFlowRepr converts regular flow delete rule to bundle compatible flow rule
374
+ func BundleDeleteFlowRepr (flow string , args ... interface {}) string {
375
+ if len (args ) > 0 {
376
+ flow = fmt .Sprintf (flow , args ... )
377
+ }
378
+ return fmt .Sprintf ("flow delete %s" , flow )
379
+ }
0 commit comments