// commit all transactions to ovsdb-server func (transaction *Transaction) Commit() ([]libovsdb.OperationResult, error) { // iterate over all transactions and create operations operations := make([]libovsdb.Operation, len(transactions)) for count, row := range transactions { if row.operation == DELETE { operations[count] = libovsdb.Operation{ Op: DELETE, Table: row.Table, Where: []interface{}{libovsdb.NewCondition("_uuid", "==", libovsdb.UUID{GoUUID: row.UUID})}} } else if row.operation == INSERT { operations[count] = libovsdb.Operation{ Op: INSERT, Table: row.Table, Row: row.changes, UUIDName: UuidToUuidName(row.UUID)} } else if row.operation == UPDATE { operations[count] = libovsdb.Operation{ Op: UPDATE, Table: row.Table, Row: row.changes, Where: []interface{}{libovsdb.NewCondition("_uuid", "==", libovsdb.UUID{GoUUID: row.UUID})}} } } result, err := transaction.Ovs.Transact(transaction.Db.Name, operations...) return result, err }
func (o *OvsSFlowProbesHandler) UnregisterSFlowProbeFromBridge(bridgeUUID string) error { probeUUID, err := o.retrieveSFlowProbeUUID(probeID(bridgeUUID)) if err != nil { return err } if probeUUID == "" { return nil } operations := []libovsdb.Operation{} bridgeRow := make(map[string]interface{}) bridgeRow["sflow"] = libovsdb.OvsSet{make([]interface{}, 0)} condition := libovsdb.NewCondition("_uuid", "==", libovsdb.UUID{bridgeUUID}) updateOp := libovsdb.Operation{ Op: "update", Table: "Bridge", Row: bridgeRow, Where: []interface{}{condition}, } operations = append(operations, updateOp) _, err = o.ovsClient.Exec(operations...) if err != nil { return err } return nil }
func (o *OvsSFlowProbesHandler) retrieveSFlowProbeUUID(id string) (string, error) { /* FIX(safchain) don't find a way to send a null condition */ condition := libovsdb.NewCondition("_uuid", "!=", libovsdb.UUID{"abc"}) selectOp := libovsdb.Operation{ Op: "select", Table: "sFlow", Where: []interface{}{condition}, } operations := []libovsdb.Operation{selectOp} result, err := o.ovsClient.Exec(operations...) if err != nil { return "", err } for _, o := range result { for _, row := range o.Rows { u := row["_uuid"].([]interface{})[1] uuid := u.(string) if ok, _ := compareProbeID(&row, id); ok { return uuid, nil } } } return "", nil }
func (ovsdber *ovsdber) deletePort(bridgeName string, portName string) error { condition := libovsdb.NewCondition("name", "==", portName) deleteOp := libovsdb.Operation{ Op: "delete", Table: "Port", Where: []interface{}{condition}, } portUUID := portUUIDForName(portName) if portUUID == "" { log.Error("Unable to find a matching Port : ", portName) return fmt.Errorf("Unable to find a matching Port : [ %s ]", portName) } // Deleting a Bridge row in Bridge table requires mutating the open_vswitch table. mutateUUID := []libovsdb.UUID{libovsdb.UUID{portUUID}} mutateSet, _ := libovsdb.NewOvsSet(mutateUUID) mutation := libovsdb.NewMutation("ports", "delete", mutateSet) condition = libovsdb.NewCondition("name", "==", bridgeName) // simple mutate operation mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Bridge", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } operations := []libovsdb.Operation{deleteOp, mutateOp} reply, _ := ovsdber.ovsdb.Transact("Open_vSwitch", operations...) if len(reply) < len(operations) { log.Error("Number of Replies should be atleast equal to number of Operations") return fmt.Errorf("Number of Replies should be atleast equal to number of Operations") } for i, o := range reply { if o.Error != "" && i < len(operations) { log.Error("Transaction Failed due to an error :", o.Error, " in ", operations[i]) return fmt.Errorf("Transaction Failed due to an error: %s in %v", o.Error, operations[i]) } else if o.Error != "" { log.Error("Transaction Failed due to an error :", o.Error) return fmt.Errorf("Transaction Failed due to an error %s", o.Error) } } return nil }
// Silently fails :/ func (ovsdber *ovsdber) addOvsVethPort(bridgeName string, portName string, tag uint) error { namedPortUUID := "port" namedIntfUUID := "intf" // intf row to insert intf := make(map[string]interface{}) intf["name"] = portName intf["type"] = `system` insertIntfOp := libovsdb.Operation{ Op: "insert", Table: "Interface", Row: intf, UUIDName: namedIntfUUID, } // port row to insert port := make(map[string]interface{}) port["name"] = portName port["interfaces"] = libovsdb.UUID{namedIntfUUID} insertPortOp := libovsdb.Operation{ Op: "insert", Table: "Port", Row: port, UUIDName: namedPortUUID, } // Inserting a row in Port table requires mutating the bridge table. mutateUUID := []libovsdb.UUID{libovsdb.UUID{namedPortUUID}} mutateSet, _ := libovsdb.NewOvsSet(mutateUUID) mutation := libovsdb.NewMutation("ports", "insert", mutateSet) condition := libovsdb.NewCondition("name", "==", bridgeName) // Mutate operation mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Bridge", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } operations := []libovsdb.Operation{insertIntfOp, insertPortOp, mutateOp} reply, _ := ovsdber.ovsdb.Transact("Open_vSwitch", operations...) if len(reply) < len(operations) { log.Error("Number of Replies should be atleast equal to number of Operations") } for i, o := range reply { if o.Error != "" && i < len(operations) { msg := fmt.Sprintf("Transaction Failed due to an error ]", o.Error, " details:", o.Details, " in ", operations[i]) return errors.New(msg) } else if o.Error != "" { msg := fmt.Sprintf("Transaction Failed due to an error :", o.Error) return errors.New(msg) } } return nil }
func (ovsdber *ovsdber) addVxlanPort(bridgeName string, portName string, peerAddress string) { namedPortUUID := "port" namedIntfUUID := "intf" options := make(map[string]interface{}) options["remote_ip"] = peerAddress // intf row to insert intf := make(map[string]interface{}) intf["name"] = portName intf["type"] = `vxlan` intf["options"], _ = libovsdb.NewOvsMap(options) insertIntfOp := libovsdb.Operation{ Op: "insert", Table: "Interface", Row: intf, UUIDName: namedIntfUUID, } // port row to insert port := make(map[string]interface{}) port["name"] = portName port["interfaces"] = libovsdb.UUID{namedIntfUUID} insertPortOp := libovsdb.Operation{ Op: "insert", Table: "Port", Row: port, UUIDName: namedPortUUID, } // Inserting a row in Port table requires mutating the bridge table. mutateUUID := []libovsdb.UUID{libovsdb.UUID{namedPortUUID}} mutateSet, _ := libovsdb.NewOvsSet(mutateUUID) mutation := libovsdb.NewMutation("ports", "insert", mutateSet) condition := libovsdb.NewCondition("name", "==", bridgeName) // simple mutate operation mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Bridge", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } operations := []libovsdb.Operation{insertIntfOp, insertPortOp, mutateOp} reply, _ := ovsdber.ovsdb.Transact("Open_vSwitch", operations...) if len(reply) < len(operations) { fmt.Println("Number of Replies should be atleast equal to number of Operations") } for i, o := range reply { if o.Error != "" && i < len(operations) { fmt.Println("Transaction Failed due to an error :", o.Error, " details:", o.Details, " in ", operations[i]) } else if o.Error != "" { fmt.Println("Transaction Failed due to an error :", o.Error) } } }
func deleteRoute(opsRoute map[string]interface{}) ovsdb.Operation { condition := ovsdb.NewCondition("prefix", "==", opsRoute["prefix"]) deleteOp := ovsdb.Operation{ Op: "delete", Table: "BGP_Route", Where: []interface{}{condition}, } return deleteOp }
// 'value' is normally a string, except under special conditions, upon which // this function should recognize them and deal with it appropriately func newCondition(column, function string, value interface{}) condition { if column == "_uuid" { switch t := value.(type) { case ovs.UUID: return ovs.NewCondition(column, function, value) case string: return ovs.NewCondition(column, function, ovs.UUID{GoUUID: value.(string)}) default: log.WithFields(log.Fields{ "value": value, "type": t, }).Error("invalid type for value in condition") return nil } } return ovs.NewCondition(column, function, value) }
func createBridge(ovs *libovsdb.OvsdbClient, bridgeName string) { namedUuid := "gopher" // bridge row to insert bridge := make(map[string]interface{}) bridge["name"] = bridgeName // simple insert operation insertOp := libovsdb.Operation{ Op: "insert", Table: "Bridge", Row: bridge, UUIDName: namedUuid, } // Inserting a Bridge row in Bridge table requires mutating the open_vswitch table. mutateUuid := []libovsdb.UUID{libovsdb.UUID{namedUuid}} mutateSet, _ := libovsdb.NewOvsSet(mutateUuid) mutation := libovsdb.NewMutation("bridges", "insert", mutateSet) condition := libovsdb.NewCondition("_uuid", "==", libovsdb.UUID{getRootUuid()}) // simple mutate operation mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Open_vSwitch", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } operations := []libovsdb.Operation{insertOp, mutateOp} reply, _ := ovs.Transact("Open_vSwitch", operations...) if len(reply) < len(operations) { fmt.Println("Number of Replies should be atleast equal to number of Operations") } ok := true for i, o := range reply { if o.Error != "" && i < len(operations) { fmt.Println("Transaction Failed due to an error :", o.Error, " details:", o.Details, " in ", operations[i]) ok = false } else if o.Error != "" { fmt.Println("Transaction Failed due to an error :", o.Error) ok = false } } if ok { fmt.Println("Bridge Addition Successful : ", reply[0].UUID.GoUuid) } }
func (o *OvsSFlowProbesHandler) retrieveSFlowProbeUUID(monitor *ovsdb.OvsMonitor, probe OvsSFlowProbe) (string, error) { /* FIX(safchain) don't find a way to send a null condition */ condition := libovsdb.NewCondition("_uuid", "!=", libovsdb.UUID{"abc"}) selectOp := libovsdb.Operation{ Op: "select", Table: "sFlow", Where: []interface{}{condition}, } operations := []libovsdb.Operation{selectOp} result, err := monitor.OvsClient.Exec(operations...) if err != nil { return "", err } for _, o := range result { for _, row := range o.Rows { u := row["_uuid"].([]interface{})[1] uuid := u.(string) if targets, ok := row["targets"]; ok { if targets != probe.Target { continue } } if polling, ok := row["polling"]; ok { if uint32(polling.(float64)) != probe.Polling { continue } } if sampling, ok := row["sampling"]; ok { if uint32(sampling.(float64)) != probe.Sampling { continue } } if ok, _ := compareProbeID(&row, probe); ok { return uuid, nil } } } return "", nil }
// deleteBridge deletes the OVS bridge func (ovsdber *ovsdber) deleteBridge(bridgeName string) error { namedBridgeUUID := "bridge" // simple delete operation condition := libovsdb.NewCondition("name", "==", bridgeName) deleteOp := libovsdb.Operation{ Op: "delete", Table: "Bridge", Where: []interface{}{condition}, } // Deleting a Bridge row in Bridge table requires mutating the open_vswitch table. mutateUUID := []libovsdb.UUID{libovsdb.UUID{namedBridgeUUID}} mutateSet, _ := libovsdb.NewOvsSet(mutateUUID) mutation := libovsdb.NewMutation("bridges", "delete", mutateSet) // simple mutate operation mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Open_vSwitch", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } operations := []libovsdb.Operation{deleteOp, mutateOp} reply, _ := ovsdber.ovsdb.Transact("Open_vSwitch", operations...) if len(reply) < len(operations) { log.Error("Number of Replies should be atleast equal to number of Operations") } for i, o := range reply { if o.Error != "" && i < len(operations) { log.Error("Transaction Failed due to an error :", o.Error, " in ", operations[i]) errMsg := fmt.Sprintf("Transaction Failed due to an error: %s in operation: %v", o.Error, operations[i]) return errors.New(errMsg) } else if o.Error != "" { errMsg := fmt.Sprintf("Transaction Failed due to an error : %s", o.Error) return errors.New(errMsg) } } log.Debugf("OVSDB delete bridge transaction succesful") return nil }
func (o *OvsSFlowProbesHandler) registerSFlowProbeOnBridge(probe OvsSFlowProbe, bridgeUUID string) error { probeUUID, err := o.retrieveSFlowProbeUUID(probeID(bridgeUUID)) if err != nil { return err } operations := []libovsdb.Operation{} var uuid libovsdb.UUID if probeUUID != "" { uuid = libovsdb.UUID{probeUUID} logging.GetLogger().Infof("Using already registered OVS SFlow probe \"%s(%s)\"", probe.ID, uuid) } else { insertOp, err := newInsertSFlowProbeOP(probe) if err != nil { return err } uuid = libovsdb.UUID{insertOp.UUIDName} logging.GetLogger().Infof("Registering new OVS SFlow probe \"%s(%s)\"", probe.ID, uuid) operations = append(operations, *insertOp) } bridgeRow := make(map[string]interface{}) bridgeRow["sflow"] = uuid condition := libovsdb.NewCondition("_uuid", "==", libovsdb.UUID{bridgeUUID}) updateOp := libovsdb.Operation{ Op: "update", Table: "Bridge", Row: bridgeRow, Where: []interface{}{condition}, } operations = append(operations, updateOp) _, err = o.ovsClient.Exec(operations...) if err != nil { return err } return nil }
func (o *OvsSFlowAgentsHandler) registerSFLowAgent(monitor *OvsMonitor, agent SFlowAgent, bridgeUUID string) error { agentUUID, err := o.retrieveSFlowAgentUUID(monitor, agent) if err != nil { return err } operations := []libovsdb.Operation{} var uuid libovsdb.UUID if agentUUID != "" { uuid = libovsdb.UUID{agentUUID} logging.GetLogger().Info("Using already registered sFlow agent \"%s(%s)\"", agent.ID, uuid) } else { insertOp, err := newInsertSFlowAgentOP(agent) if err != nil { return err } uuid = libovsdb.UUID{insertOp.UUIDName} logging.GetLogger().Info("Registering new sFlow agent \"%s(%s)\"", agent.ID, uuid) operations = append(operations, *insertOp) } bridgeRow := make(map[string]interface{}) bridgeRow["sflow"] = uuid condition := libovsdb.NewCondition("_uuid", "==", libovsdb.UUID{bridgeUUID}) updateOp := libovsdb.Operation{ Op: "update", Table: "Bridge", Row: bridgeRow, Where: []interface{}{condition}, } operations = append(operations, updateOp) _, err = monitor.OvsClient.Exec(operations...) if err != nil { return err } return nil }
func (ovsdber *ovsdber) portExists(portName string) (bool, error) { condition := libovsdb.NewCondition("name", "==", portName) selectOp := libovsdb.Operation{ Op: "select", Table: "Port", Where: []interface{}{condition}, } operations := []libovsdb.Operation{selectOp} reply, _ := ovsdber.ovsdb.Transact("Open_vSwitch", operations...) if len(reply) < len(operations) { return false, errors.New("Number of Replies should be atleast equal to number of Operations") } if reply[0].Error != "" { errMsg := fmt.Sprintf("Transaction Failed due to an error: %v", reply[0].Error) return false, errors.New(errMsg) } if len(reply[0].Rows) == 0 { return false, nil } return true, nil }
// createOvsdbBridge creates the OVS bridge func (ovsdber *ovsdber) createOvsdbBridge(bridgeName string) error { namedBridgeUUID := "bridge" namedPortUUID := "port" namedIntfUUID := "intf" // intf row to insert intf := make(map[string]interface{}) intf["name"] = bridgeName intf["type"] = `internal` insertIntfOp := libovsdb.Operation{ Op: "insert", Table: "Interface", Row: intf, UUIDName: namedIntfUUID, } // Port row to insert port := make(map[string]interface{}) port["name"] = bridgeName port["interfaces"] = libovsdb.UUID{namedIntfUUID} insertPortOp := libovsdb.Operation{ Op: "insert", Table: "Port", Row: port, UUIDName: namedPortUUID, } // Bridge row to insert bridge := make(map[string]interface{}) bridge["name"] = bridgeName bridge["stp_enable"] = false bridge["ports"] = libovsdb.UUID{namedPortUUID} insertBridgeOp := libovsdb.Operation{ Op: "insert", Table: "Bridge", Row: bridge, UUIDName: namedBridgeUUID, } // Inserting a Bridge row in Bridge table requires mutating the open_vswitch table. mutateUUID := []libovsdb.UUID{libovsdb.UUID{namedBridgeUUID}} mutateSet, _ := libovsdb.NewOvsSet(mutateUUID) mutation := libovsdb.NewMutation("bridges", "insert", mutateSet) condition := libovsdb.NewCondition("_uuid", "==", libovsdb.UUID{ovsdber.getRootUUID()}) // Mutate operation mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Open_vSwitch", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } operations := []libovsdb.Operation{insertIntfOp, insertPortOp, insertBridgeOp, mutateOp} reply, _ := ovsdber.ovsdb.Transact("Open_vSwitch", operations...) if len(reply) < len(operations) { return errors.New("Number of Replies should be atleast equal to number of Operations") } for i, o := range reply { if o.Error != "" && i < len(operations) { return errors.New("Transaction Failed due to an error :" + o.Error + " details : " + o.Details) } else if o.Error != "" { return errors.New("Transaction Failed due to an error :" + o.Error + " details : " + o.Details) } } return nil }
// Base on RFC 7047, empty condition should return all rows from a table. However, // libovsdb does not seem to support that yet. This is the simplist, most common solution // to it. func noCondition() []interface{} { return []interface{}{ovs.NewCondition("_uuid", "!=", ovs.UUID{GoUUID: "_"})} }
func newCondition(column, function string, value interface{}) []interface{} { return []interface{}{ovs.NewCondition(column, function, value)} }