Esempio n. 1
0
// This does not cover all cases, they should just be added as needed
func newMutation(column, mutator string, value interface{}) mutation {
	switch typedValue := value.(type) {
	case ovs.UUID:
		uuidSlice := []ovs.UUID{typedValue}
		mutateValue, _ := ovs.NewOvsSet(uuidSlice)
		return ovs.NewMutation(column, mutator, mutateValue)
	default:
		var mutateValue interface{}
		var err error
		switch reflect.ValueOf(typedValue).Kind() {
		case reflect.Slice:
			mutateValue, err = ovs.NewOvsSet(typedValue)
		case reflect.Map:
			mutateValue, err = ovs.NewOvsMap(typedValue)
		default:
			panic(fmt.Sprintf(
				"unhandled value in mutation: value %s, type %s",
				value, typedValue))
		}
		if err != nil {
			return err
		}
		return ovs.NewMutation(column, mutator, mutateValue)
	}
}
Esempio n. 2
0
// This does not cover all cases, they should just be added as needed
func newMutation(column, mutator string, value interface{}) mutation {
	switch typedValue := value.(type) {
	case ovs.UUID:
		uuidSlice := []ovs.UUID{typedValue}
		mutateValue, err := ovs.NewOvsSet(uuidSlice)
		if err != nil {
			// An error can only occur if the input is not a slice
			panic("newMutation(): an impossible error occurred")
		}
		return ovs.NewMutation(column, mutator, mutateValue)
	default:
		var mutateValue interface{}
		var err error
		switch reflect.ValueOf(typedValue).Kind() {
		case reflect.Slice:
			mutateValue, err = ovs.NewOvsSet(typedValue)
		case reflect.Map:
			mutateValue, err = ovs.NewOvsMap(typedValue)
		default:
			panic(fmt.Sprintf(
				"unhandled value in mutation: value %s, type %s",
				value, typedValue))
		}
		if err != nil {
			return err
		}
		return ovs.NewMutation(column, mutator, mutateValue)
	}
}
Esempio n. 3
0
// CreateAddressSet creates an address set in OVN.
func (ovsdb Client) CreateAddressSet(lswitch string, name string,
	addresses []string) error {

	addrs, err := ovs.NewOvsSet(addresses)
	if err != nil {
		return err
	}

	addressRow := map[string]interface{}{
		"name":      name,
		"addresses": addrs,
	}

	insertOp := ovs.Operation{
		Op:    "insert",
		Table: "Address_Set",
		Row:   addressRow,
	}

	results, err := ovsdb.transact("OVN_Northbound", insertOp)
	if err != nil {
		return fmt.Errorf("transaction error: creating address set on %s: %s",
			lswitch, err)
	}
	return errorCheck(results, 1)
}
Esempio n. 4
0
// CreateLogicalPort creates a new logical port in OVN.
func (ovsdb Client) CreateLogicalPort(lswitch, name, mac, ip string) error {
	addrs, err := ovs.NewOvsSet([]string{fmt.Sprintf("%s %s", mac, ip)})
	if err != nil {
		return err
	}

	port := map[string]interface{}{"name": name, "addresses": addrs}

	insertOp := ovs.Operation{
		Op:       "insert",
		Table:    "Logical_Switch_Port",
		Row:      port,
		UUIDName: "qlportadd",
	}

	mutateOp := ovs.Operation{
		Op:    "mutate",
		Table: "Logical_Switch",
		Mutations: []interface{}{
			newMutation("ports", "insert", ovs.UUID{GoUUID: "qlportadd"}),
		},
		Where: newCondition("name", "==", lswitch),
	}

	results, err := ovsdb.transact("OVN_Northbound", insertOp, mutateOp)
	if err != nil {
		return fmt.Errorf("transaction error: creating lport %s on %s: %s",
			name, lswitch, err)
	}

	return errorCheck(results, 2)
}
Esempio n. 5
0
func main() {
	ovs, err := ovsdbgo.Connect("127.0.0.1", 6640)
	if err != nil {
		fmt.Println("unable to connect ", err)
		panic(err)
	}
	database := "OpenSwitch"
	db := ovsdbgo.LoadAll(ovs, database)

	// add a new bridge named new_bridge
	transaction := ovsdbgo.Transaction{ovs, db}
	new_bridge := transaction.InsertRow("Bridge")
	new_bridge.Set("name", "bridge02")
	new_bridge_uuid := libovsdb.UUID{ovsdbgo.UuidToUuidName(new_bridge.UUID)}

	// add reference of new created bridge to "bridges" column in System table
	for _, sysRow := range db.Tables["System"].Rows {

		bridges := (sysRow.Data.Fields["bridges"]).(libovsdb.OvsSet)
		new_bridges := make([]interface{}, len(bridges.GoSet)+1)

		for ok, uuid := range bridges.GoSet {
			new_bridges[ok] = uuid
		}
		new_bridges[len(new_bridges)-1] = new_bridge_uuid
		new_bridges_set, _ := libovsdb.NewOvsSet(new_bridges)
		sysRow.Set("bridges", new_bridges_set)
	}
	res, err := transaction.Commit()
	fmt.Println(res, err)
}
Esempio n. 6
0
// 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
}
Esempio n. 7
0
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)
		}
	}
}
Esempio n. 8
0
func insertRoute(vrfId uuid.UUID, opsRoute map[string]interface{}) (ovsdb.Operation, error) {
	v := []ovsdb.UUID{ovsdb.UUID{vrfId.String()}}
	vrfSet, _ := ovsdb.NewOvsSet(v)
	opsRoute["vrf"] = vrfSet

	nexthop := []ovsdb.UUID{ovsdb.UUID{NEXTHOP_TRANSACT_NUUID}}
	nexthopSet, _ := ovsdb.NewOvsSet(nexthop)
	opsRoute["bgp_nexthops"] = nexthopSet

	attrMap, err := ovsdb.NewOvsMap(opsRoute["path_attributes"])
	if err != nil {
		return ovsdb.Operation{}, err
	}

	opsRoute["path_attributes"] = attrMap

	insRouteOp := ovsdb.Operation{
		Op:       "insert",
		Table:    "BGP_Route",
		Row:      opsRoute,
		UUIDName: ROUTE_TRANSACT_NUUID,
	}
	return insRouteOp, nil
}
Esempio n. 9
0
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)
	}
}
Esempio n. 10
0
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
}
Esempio n. 11
0
// 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
}
Esempio n. 12
0
// CreateOFPort creates an openflow port on specified bridge
//
// A port cannot be created without an interface, that is why the "default"
// interface (one with the same name as the port) is created along with it.
func (ovsdb Client) CreateOFPort(bridge, name string) error {
	var ops []ovs.Operation

	ops = append(ops, ovs.Operation{
		Op:       "insert",
		Table:    "Interface",
		Row:      Row{"name": name},
		UUIDName: "diifaceadd",
	})

	ifaces, err := ovs.NewOvsSet([]ovs.UUID{{GoUUID: "diifaceadd"}})
	if err != nil {
		return err
	}

	ops = append(ops, ovs.Operation{
		Op:       "insert",
		Table:    "Port",
		Row:      Row{"name": name, "interfaces": ifaces},
		UUIDName: "diportadd",
	})

	ops = append(ops, ovs.Operation{
		Op:    "mutate",
		Table: "Bridge",
		Mutations: []interface{}{
			newMutation("ports", "insert", ovs.UUID{GoUUID: "diportadd"}),
		},
		Where: []interface{}{newCondition("name", "==", bridge)},
	})

	results, err := ovsdb.Transact("Open_vSwitch", ops...)
	if err != nil {
		return fmt.Errorf(
			"transaction error creating openflow port %s within %s: %s",
			name, bridge, err)
	}
	if err := errorCheck(results, 2, 1); err != nil {
		return fmt.Errorf("error creating openflow port %s within %s: %s",
			name, bridge, err)
	}
	return nil
}
Esempio n. 13
0
// CreatePort creates a new logical port in OVN.
func (ovsdb Client) CreatePort(lswitch, name, mac, ip string) error {
	// OVN Uses name an index into the Logical_Port table so, we need to check
	// no port called name already exists. This isn't strictly necessary, but it
	// makes our lives easier.
	rows, err := ovsdb.selectRows("OVN_Northbound", "Logical_Port",
		newCondition("name", "==", name))
	if err != nil {
		return err
	}
	if len(rows) > 0 {
		return &ExistError{fmt.Sprintf("port %s already exists", name)}
	}

	port := make(map[string]interface{})
	port["name"] = name
	addrs, err := ovs.NewOvsSet([]string{fmt.Sprintf("%s %s", mac, ip)})
	if err != nil {
		return err
	}
	port["addresses"] = addrs

	insertOp := ovs.Operation{
		Op:       "insert",
		Table:    "Logical_Port",
		Row:      port,
		UUIDName: "dilportadd",
	}

	mutateOp := ovs.Operation{
		Op:    "mutate",
		Table: "Logical_Switch",
		Mutations: []interface{}{
			newMutation("ports", "insert", ovs.UUID{GoUUID: "dilportadd"}),
		},
		Where: []interface{}{newCondition("name", "==", lswitch)},
	}

	results, err := ovsdb.Transact("OVN_Northbound", insertOp, mutateOp)
	if err != nil {
		return errors.New("transaction error")
	}
	return errorCheck(results, 2, 1)
}
Esempio n. 14
0
// CreateInterface creates an openflow port on specified bridge.
//
// A port cannot be created without an interface, that is why the "default"
// interface (one with the same name as the port) is created along with it.
func (ovsdb Client) CreateInterface(bridge, name string) error {
	var ops []ovs.Operation

	ops = append(ops, ovs.Operation{
		Op:       "insert",
		Table:    "Interface",
		Row:      row{"name": name},
		UUIDName: "qifaceadd",
	})

	ifaces, err := ovs.NewOvsSet([]ovs.UUID{{GoUUID: "qifaceadd"}})
	if err != nil {
		return err
	}

	ops = append(ops, ovs.Operation{
		Op:       "insert",
		Table:    "Port",
		Row:      row{"name": name, "interfaces": ifaces},
		UUIDName: "qportadd",
	})

	ops = append(ops, ovs.Operation{
		Op:    "mutate",
		Table: "Bridge",
		Mutations: []interface{}{
			newMutation("ports", "insert", ovs.UUID{GoUUID: "qportadd"}),
		},
		Where: newCondition("name", "==", bridge),
	})

	results, err := ovsdb.transact("Open_vSwitch", ops...)
	if err != nil {
		return fmt.Errorf("transaction error: creating interface %s: %s",
			name, err)
	}
	return errorCheck(results, len(ops))
}
Esempio n. 15
0
// 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
}