示例#1
0
// IsAciConfigured returns true if aci is configured on netmaster.
func IsAciConfigured() (res bool, err error) {
	// Get the state driver
	stateDriver, uErr := utils.GetStateDriver()
	if uErr != nil {
		log.Warnf("Couldn't read global config %v", uErr)
		return false, uErr
	}

	// read global config
	masterGc := &mastercfg.GlobConfig{}
	masterGc.StateDriver = stateDriver
	uErr = masterGc.Read("config")
	if core.ErrIfKeyExists(uErr) != nil {
		log.Errorf("Couldn't read global config %v", uErr)
		return false, uErr
	}

	if uErr != nil {
		log.Warnf("Couldn't read global config %v", uErr)
		return false, nil
	}

	if masterGc.NwInfraType != "aci" {
		log.Debugf("NwInfra type is %v, no ACI", masterGc.NwInfraType)
		return false, nil
	}

	return true, nil
}
示例#2
0
func createContainerEpOper(netPlugin *plugin.NetPlugin, contUUID, contName string) error {
	epIDs, err := getEpIDByContainerName(netPlugin, contName)
	if err != nil {
		log.Debugf("unable to find ep for container %s, error %v\n", contName, err)
		return err
	}

	for _, epID := range epIDs {
		operEp := &drivers.OvsOperEndpointState{}
		operEp.StateDriver = netPlugin.StateDriver
		err = operEp.Read(epID)
		if core.ErrIfKeyExists(err) != nil {
			return err
		}

		if err == nil {
			operEp.ContUUID = contUUID
			err = operEp.Write()
			if err != nil {
				log.Errorf("error updating oper state for ep %s \n", contName)
				return err
			}

			log.Infof("updating container '%s' with id '%s' \n", contName, contUUID)
		} else {
			err = netPlugin.CreateEndpoint(epID)
			if err != nil {
				log.Errorf("Endpoint creation failed. Error: %s", err)
				return err
			}
			log.Infof("Endpoint operation create succeeded")
		}
	}
	return err
}
示例#3
0
// Init initializes the OVS driver.
func (d *OvsDriver) Init(config *core.Config, info *core.InstanceInfo) error {

	if config == nil || info == nil || info.StateDriver == nil {
		return core.Errorf("Invalid arguments. cfg: %+v, instance-info: %+v",
			config, info)
	}

	_, ok := config.V.(*OvsDriverConfig)
	if !ok {
		return core.Errorf("Invalid type passed")
	}

	d.oper.StateDriver = info.StateDriver
	d.localIP = info.VtepIP
	// restore the driver's runtime state if it exists
	err := d.oper.Read(info.HostLabel)
	if core.ErrIfKeyExists(err) != nil {
		log.Printf("Failed to read driver oper state for key %q. Error: %s",
			info.HostLabel, err)
		return err
	} else if err != nil {
		// create the oper state as it is first time start up
		d.oper.ID = info.HostLabel
		d.oper.CurrPortNum = 0
		err = d.oper.Write()
		if err != nil {
			return err
		}
	}

	log.Infof("Initializing ovsdriver")

	// Init switch DB
	d.switchDb = make(map[string]*OvsSwitch)

	// Create Vxlan switch
	d.switchDb["vxlan"], err = NewOvsSwitch(vxlanBridgeName, "vxlan", info.VtepIP,
		info.FwdMode)
	if err != nil {
		log.Fatalf("Error creating vlan switch. Err: %v", err)
	}
	// Create Vlan switch
	d.switchDb["vlan"], err = NewOvsSwitch(vlanBridgeName, "vlan", info.VtepIP,
		info.FwdMode, info.VlanIntf)
	if err != nil {
		log.Fatalf("Error creating vlan switch. Err: %v", err)
	}

	// Add uplink to VLAN switch
	if info.VlanIntf != "" {
		err = d.switchDb["vlan"].AddUplinkPort(info.VlanIntf)
		if err != nil {
			log.Errorf("Could not add uplink %s to vlan OVS. Err: %v", info.VlanIntf, err)
		}
	}

	return nil
}
示例#4
0
// The following function derives the number of available vlan tags.
// XXX: Since it is run at netmaster, it is guaranteed to have a consistent view of
// resource usage. Revisit if this assumption changes, as then it might need to
// be moved to resource-manager
func deriveAvailableVLANs(stateDriver core.StateDriver) (*bitset.BitSet, error) {
	// available vlans = vlan-space - For each tenant (vlans + local-vxlan-vlans)
	availableVLANs := netutils.CreateBitset(12)

	// get all vlans
	readVLANRsrc := &resources.AutoVLANCfgResource{}
	readVLANRsrc.StateDriver = stateDriver
	vlanRsrcs, err := readVLANRsrc.ReadAll()
	if core.ErrIfKeyExists(err) != nil {
		return nil, err
	} else if err != nil {
		vlanRsrcs = []core.State{}
	}
	for _, rsrc := range vlanRsrcs {
		cfg := rsrc.(*resources.AutoVLANCfgResource)
		availableVLANs = availableVLANs.Union(cfg.VLANs)
	}

	//get all vxlan-vlans
	readVXLANRsrc := &resources.AutoVXLANCfgResource{}
	readVXLANRsrc.StateDriver = stateDriver
	vxlanRsrcs, err := readVXLANRsrc.ReadAll()
	if core.ErrIfKeyExists(err) != nil {
		return nil, err
	} else if err != nil {
		vxlanRsrcs = []core.State{}
	}
	for _, rsrc := range vxlanRsrcs {
		cfg := rsrc.(*resources.AutoVXLANCfgResource)
		availableVLANs = availableVLANs.Union(cfg.LocalVLANs)
	}

	// subtract to get availableVLANs
	availableVLANs = availableVLANs.Complement()
	clearReservedVLANs(availableVLANs)
	return availableVLANs, nil
}
示例#5
0
文件: gstate.go 项目: vvb/netplugin
// AssignDefaultNetwork assigns a default network for a tenant based on the configuration
// in case configuration is absent it uses the provided network name to be the default
// network. It records the default network in oper state (derived or configured)
func (gc *Cfg) AssignDefaultNetwork(networkName string) (string, error) {
	g := &Oper{}
	g.StateDriver = gc.StateDriver
	if err := g.Read(""); core.ErrIfKeyExists(err) != nil {
		return "", err
	}
	if g.DefaultNetwork != "" {
		return "", nil
	}

	// not checking if this network exists within a tenant
	g.DefaultNetwork = networkName

	if err := g.Write(); err != nil {
		log.Errorf("error '%s' updating goper state %v \n", err, g)
		return "", err
	}

	return g.DefaultNetwork, nil
}
示例#6
0
文件: gstate.go 项目: vvb/netplugin
// UnassignNetwork clears the oper state w.r.t. default network name
func (gc *Cfg) UnassignNetwork(networkName string) error {
	if networkName == "" {
		return nil
	}

	g := &Oper{}
	g.StateDriver = gc.StateDriver
	if err := g.Read(""); core.ErrIfKeyExists(err) != nil {
		return err
	}

	if networkName == g.DefaultNetwork {
		g.DefaultNetwork = ""
		if err := g.Write(); err != nil {
			log.Errorf("error '%s' updating goper state %v \n", err, g)
			return err
		}
	}

	return nil
}
// XXX: It might be better to keep cache of resources and avoid frequent etcd reads
func (rm *StateResourceManager) findResource(id, desc string) (core.Resource, bool, error) {
	alreadyExists := false
	rsrcType, ok := resourceRegistry[desc]
	if !ok {
		return nil, alreadyExists,
			core.Errorf("No resource found for description: %q", desc)
	}

	val := reflect.New(rsrcType)
	// sanity checks
	if !val.Elem().FieldByName("CommonState").IsValid() {
		return nil, false, core.Errorf("The state structure %v is missing core.CommonState", rsrcType)
	}
	//the following works as every core.State is expected to embed core.CommonState struct
	val.Elem().FieldByName("CommonState").FieldByName("StateDriver").Set(reflect.ValueOf(rm.stateDriver))
	val.Elem().FieldByName("CommonState").FieldByName("ID").Set(reflect.ValueOf(id))

	rsrc := val.Interface().(core.Resource)
	rsrcs, err := rsrc.ReadAll()
	if core.ErrIfKeyExists(err) != nil {
		return nil, alreadyExists, err
	} else if err != nil {
		// set the slice as empty in case of 'key not found' error
		rsrcs = []core.State{}
	}

	for _, r := range rsrcs {
		//the following works as every core.State is expected to embed core.CommonState struct
		cs := reflect.ValueOf(r).Elem().FieldByName("CommonState").Interface().(core.CommonState)
		if cs.ID == id {
			alreadyExists = true
			return r.(core.Resource), alreadyExists, nil
		}
	}
	return rsrc, alreadyExists, nil
}
示例#8
0
// DeleteDelta deletes any existing configuration from netmaster's statestore
// that is not present in the configuration passed. This may result in
// generating Delete triggers for the netplugin
func DeleteDelta(allCfg *intent.Config) error {
	stateDriver, err := utils.GetStateDriver()
	if err != nil {
		return err
	}

	readEp := &mastercfg.CfgEndpointState{}
	readEp.StateDriver = stateDriver
	epCfgs, err := readEp.ReadAll()
	if core.ErrIfKeyExists(err) != nil {
		return err
	} else if err != nil {
		err = nil
		epCfgs = []core.State{}
	}
	for _, epCfg := range epCfgs {
		cfg := epCfg.(*mastercfg.CfgEndpointState)
		if !epPresent(allCfg, cfg.ID) {
			_, err1 := DeleteEndpointID(stateDriver, cfg.ID)
			if err1 != nil {
				log.Errorf("error '%s' deleting epid %s \n", err1, cfg.ID)
				err = err1
				continue
			}
		}
	}

	readNet := &mastercfg.CfgNetworkState{}
	readNet.StateDriver = stateDriver
	nwCfgs, err := readNet.ReadAll()
	if core.ErrIfKeyExists(err) != nil {
		return err
	} else if err != nil {
		err = nil
		nwCfgs = []core.State{}
	}
	for _, nwCfg := range nwCfgs {
		cfg := nwCfg.(*mastercfg.CfgNetworkState)
		if !netPresent(allCfg, cfg.ID) {
			err1 := DeleteNetworkID(stateDriver, cfg.ID)
			if err1 != nil {
				log.Errorf("error '%s' deleting net %s \n", err1, cfg.ID)
				err = err1
				continue
			}
		}
	}

	readGlbl := &gstate.Cfg{}
	readGlbl.StateDriver = stateDriver
	gCfgs, err := readGlbl.ReadAll()
	if core.ErrIfKeyExists(err) != nil {
		return err
	} else if err != nil {
		err = nil
		gCfgs = []core.State{}
	}
	for _, gCfg := range gCfgs {
		cfg := gCfg.(*gstate.Cfg)
		if !tenantPresent(allCfg, cfg.Tenant) {
			err1 := DeleteTenantID(stateDriver, cfg.Tenant)
			if err1 != nil {
				log.Errorf("error '%s' deleting tenant %s \n", err1, cfg.Tenant)
				err = err1
				continue
			}
		}
	}

	return err
}
示例#9
0
// CreateEndpoint creates an endpoint by named identifier
func (d *OvsDriver) CreateEndpoint(id string) error {
	var (
		err          error
		intfName     string
		epgKey       string
		epgBandwidth int64
		dscp         int
	)

	cfgEp := &mastercfg.CfgEndpointState{}
	cfgEp.StateDriver = d.oper.StateDriver
	err = cfgEp.Read(id)
	if err != nil {
		return err
	}

	// Get the nw config.
	cfgNw := mastercfg.CfgNetworkState{}
	cfgNw.StateDriver = d.oper.StateDriver
	err = cfgNw.Read(cfgEp.NetID)
	if err != nil {
		log.Errorf("Unable to get network %s. Err: %v", cfgEp.NetID, err)
		return err
	}

	pktTagType := cfgNw.PktTagType
	pktTag := cfgNw.PktTag
	cfgEpGroup := &mastercfg.EndpointGroupState{}
	// Read pkt tags from endpoint group if available
	if cfgEp.EndpointGroupKey != "" {
		cfgEpGroup.StateDriver = d.oper.StateDriver

		err = cfgEpGroup.Read(cfgEp.EndpointGroupKey)
		if err == nil {
			log.Debugf("pktTag: %v ", cfgEpGroup.PktTag)
			pktTagType = cfgEpGroup.PktTagType
			pktTag = cfgEpGroup.PktTag
			epgKey = cfgEp.EndpointGroupKey
			dscp = cfgEpGroup.DSCP
			log.Infof("Received endpoint create with bandwidth:%s", cfgEpGroup.Bandwidth)
			if cfgEpGroup.Bandwidth != "" {
				epgBandwidth = netutils.ConvertBandwidth(cfgEpGroup.Bandwidth)
			}

		} else if core.ErrIfKeyExists(err) == nil {
			log.Infof("EPG %s not found: %v. will use network based tag ", cfgEp.EndpointGroupKey, err)
		} else {
			return err
		}
	}

	// Find the switch based on network type
	var sw *OvsSwitch
	if pktTagType == "vxlan" {
		sw = d.switchDb["vxlan"]
	} else {
		sw = d.switchDb["vlan"]
	}

	// Skip Veth pair creation for infra nw endpoints
	skipVethPair := (cfgNw.NwType == "infra")

	operEp := &OvsOperEndpointState{}
	operEp.StateDriver = d.oper.StateDriver
	err = operEp.Read(id)
	if core.ErrIfKeyExists(err) != nil {
		return err
	} else if err == nil {
		// check if oper state matches cfg state. In case of mismatch cleanup
		// up the EP and continue add new one. In case of match just return.
		if operEp.Matches(cfgEp) {
			log.Printf("Found matching oper state for ep %s, noop", id)

			// Ask the switch to update the port
			err = sw.UpdatePort(operEp.PortName, cfgEp, pktTag, cfgNw.PktTag, dscp, skipVethPair)
			if err != nil {
				log.Errorf("Error creating port %s. Err: %v", intfName, err)
				return err
			}

			return nil
		}
		log.Printf("Found mismatching oper state for Ep, cleaning it. Config: %+v, Oper: %+v",
			cfgEp, operEp)
		d.DeleteEndpoint(operEp.ID)
	}

	if cfgNw.NwType == "infra" {
		// For infra nw, port name is network name
		intfName = cfgNw.NetworkName
	} else {
		// Get the interface name to use
		intfName, err = d.getIntfName()
		if err != nil {
			return err
		}
	}

	// Get OVS port name
	ovsPortName := getOvsPortName(intfName, skipVethPair)

	// Ask the switch to create the port
	err = sw.CreatePort(intfName, cfgEp, pktTag, cfgNw.PktTag, cfgEpGroup.Burst, dscp, skipVethPair, epgBandwidth)
	if err != nil {
		log.Errorf("Error creating port %s. Err: %v", intfName, err)
		return err
	}

	// save local endpoint info
	d.oper.localEpInfoMutex.Lock()
	d.oper.LocalEpInfo[id] = &EpInfo{
		Ovsportname: ovsPortName,
		EpgKey:      epgKey,
		BridgeType:  pktTagType,
	}
	d.oper.localEpInfoMutex.Unlock()
	err = d.oper.Write()
	if err != nil {
		return err
	}
	// Save the oper state
	operEp = &OvsOperEndpointState{
		NetID:       cfgEp.NetID,
		EndpointID:  cfgEp.EndpointID,
		ServiceName: cfgEp.ServiceName,
		IPAddress:   cfgEp.IPAddress,
		MacAddress:  cfgEp.MacAddress,
		IntfName:    cfgEp.IntfName,
		PortName:    intfName,
		HomingHost:  cfgEp.HomingHost,
		VtepIP:      cfgEp.VtepIP}
	operEp.StateDriver = d.oper.StateDriver
	operEp.ID = id
	err = operEp.Write()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			operEp.Clear()
		}
	}()
	return nil
}
示例#10
0
// Init initializes the OVS driver.
func (d *OvsDriver) Init(info *core.InstanceInfo) error {

	if info == nil || info.StateDriver == nil {
		return core.Errorf("Invalid arguments. instance-info: %+v", info)
	}

	d.oper.StateDriver = info.StateDriver
	d.localIP = info.VtepIP
	// restore the driver's runtime state if it exists
	err := d.oper.Read(info.HostLabel)
	if core.ErrIfKeyExists(err) != nil {
		log.Errorf("Failed to read driver oper state for key %q. Error: %s",
			info.HostLabel, err)
		return err
	} else if err != nil {
		// create the oper state as it is first time start up
		d.oper.ID = info.HostLabel
		d.oper.CurrPortNum = 0

		// create local endpoint info map
		d.oper.LocalEpInfo = make(map[string]*EpInfo)

		// write the oper
		err = d.oper.Write()
		if err != nil {
			return err
		}
	}

	// make sure LocalEpInfo exists
	if d.oper.LocalEpInfo == nil {
		d.oper.LocalEpInfo = make(map[string]*EpInfo)
		// write the oper
		err = d.oper.Write()
		if err != nil {
			return err
		}
	}

	log.Infof("Initializing ovsdriver")

	// Init switch DB
	d.switchDb = make(map[string]*OvsSwitch)

	// Create Vxlan switch
	d.switchDb["vxlan"], err = NewOvsSwitch(vxlanBridgeName, "vxlan", info.VtepIP,
		info.FwdMode)
	if err != nil {
		log.Fatalf("Error creating vlan switch. Err: %v", err)
	}
	// Create Vlan switch
	d.switchDb["vlan"], err = NewOvsSwitch(vlanBridgeName, "vlan", info.VtepIP,
		info.FwdMode, info.VlanIntf)
	if err != nil {
		log.Fatalf("Error creating vlan switch. Err: %v", err)
	}

	// Add uplink to VLAN switch
	if info.VlanIntf != "" {
		err = d.switchDb["vlan"].AddUplinkPort(info.VlanIntf)
		if err != nil {
			log.Errorf("Could not add uplink %s to vlan OVS. Err: %v", info.VlanIntf, err)
		}
	}

	// Create Host Access switch
	d.switchDb["host"], err = NewOvsSwitch(hostBridgeName, "host", info.VtepIP,
		info.FwdMode)
	if err != nil {
		log.Fatalf("Error creating host switch. Err: %v", err)
	}

	if maxPortNum > 0xfffe {
		log.Fatalf("Host bridge logic assumes maxPortNum <= 0xfffe")
	}

	// Add host port.
	err = d.switchDb["host"].AddHostPort(hostPortName, maxPortNum, true)
	if err != nil {
		log.Errorf("Could not add host port %s to OVS. Err: %v", hostPortName, err)
	}

	// Add a masquerade rule to ip tables.
	netutils.SetIPMasquerade(hostPortName, hostPvtSubnet)

	// Initialize the node proxy
	d.HostProxy, err = NewNodeProxy()

	return err
}
示例#11
0
// CreateEndpoint creates an endpoint by named identifier
func (d *OvsDriver) CreateEndpoint(id string) error {
	var (
		err      error
		intfName string
	)

	cfgEp := &mastercfg.CfgEndpointState{}
	cfgEp.StateDriver = d.oper.StateDriver
	err = cfgEp.Read(id)
	if err != nil {
		return err
	}

	// Ignore VTEP endpoints and uplink endpoints
	// FIXME: we need to stop publiching these from netmaster
	if cfgEp.VtepIP != "" {
		return nil
	}
	if cfgEp.IntfName != "" {
		return nil
	}

	cfgEpGroup := &mastercfg.EndpointGroupState{}
	cfgEpGroup.StateDriver = d.oper.StateDriver
	err = cfgEpGroup.Read(strconv.Itoa(cfgEp.EndpointGroupID))
	if err == nil {
		log.Debugf("pktTag: %v ", cfgEpGroup.PktTag)
	} else if core.ErrIfKeyExists(err) == nil {
		// FIXME: this should be deprecated once we remove old style intent
		// In case EpGroup is not specified, get the tag from nw.
		// this is mainly for the intent based system tests
		log.Warnf("%v will use network based tag ", err)
		cfgNw := mastercfg.CfgNetworkState{}
		cfgNw.StateDriver = d.oper.StateDriver
		err1 := cfgNw.Read(cfgEp.NetID)
		if err1 != nil {
			log.Errorf("Unable to get tag neither epg nor nw")
			return err1
		}

		cfgEpGroup.PktTagType = cfgNw.PktTagType
		cfgEpGroup.PktTag = cfgNw.PktTag
	} else {
		return err
	}

	// Find the switch based on network type
	var sw *OvsSwitch
	if cfgEpGroup.PktTagType == "vxlan" {
		sw = d.switchDb["vxlan"]
	} else {
		sw = d.switchDb["vlan"]
	}

	operEp := &OvsOperEndpointState{}
	operEp.StateDriver = d.oper.StateDriver
	err = operEp.Read(id)
	if core.ErrIfKeyExists(err) != nil {
		return err
	} else if err == nil {
		// check if oper state matches cfg state. In case of mismatch cleanup
		// up the EP and continue add new one. In case of match just return.
		if operEp.Matches(cfgEp) {
			log.Printf("Found matching oper state for ep %s, noop", id)

			// Ask the switch to update the port
			err = sw.UpdatePort(operEp.PortName, cfgEp, cfgEpGroup.PktTag)
			if err != nil {
				log.Errorf("Error creating port %s. Err: %v", intfName, err)
				return err
			}

			return nil
		}
		log.Printf("Found mismatching oper state for Ep, cleaning it. Config: %+v, Oper: %+v",
			cfgEp, operEp)
		d.DeleteEndpoint(operEp.ID)
	}

	// add an internal ovs port with vlan-tag information from the state

	// XXX: revisit, the port name might need to come from user. Also revisit
	// the algorithm to take care of port being deleted and reuse unused port
	// numbers
	d.oper.CurrPortNum++
	err = d.oper.Write()
	if err != nil {
		return err
	}
	intfName = d.getIntfName()

	// Ask the switch to create the port
	err = sw.CreatePort(intfName, cfgEp, cfgEpGroup.PktTag)
	if err != nil {
		log.Errorf("Error creating port %s. Err: %v", intfName, err)
		return err
	}

	// Save the oper state
	operEp = &OvsOperEndpointState{
		NetID:       cfgEp.NetID,
		AttachUUID:  cfgEp.AttachUUID,
		ContName:    cfgEp.ContName,
		ServiceName: cfgEp.ServiceName,
		IPAddress:   cfgEp.IPAddress,
		MacAddress:  cfgEp.MacAddress,
		IntfName:    cfgEp.IntfName,
		PortName:    intfName,
		HomingHost:  cfgEp.HomingHost,
		VtepIP:      cfgEp.VtepIP}
	operEp.StateDriver = d.oper.StateDriver
	operEp.ID = id
	err = operEp.Write()
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			operEp.Clear()
		}
	}()

	return nil
}
示例#12
0
// CreateEndpoint creates an endpoint by named identifier
func (d *OvsDriver) CreateEndpoint(id string) error {
	var (
		err      error
		intfName string
	)

	cfgEp := &mastercfg.CfgEndpointState{}
	cfgEp.StateDriver = d.oper.StateDriver
	err = cfgEp.Read(id)
	if err != nil {
		return err
	}

	// Get the nw config.
	cfgNw := mastercfg.CfgNetworkState{}
	cfgNw.StateDriver = d.oper.StateDriver
	err = cfgNw.Read(cfgEp.NetID)
	if err != nil {
		log.Errorf("Unable to get network %s. Err: %v", cfgEp.NetID, err)
		return err
	}

	cfgEpGroup := &mastercfg.EndpointGroupState{}
	cfgEpGroup.StateDriver = d.oper.StateDriver
	err = cfgEpGroup.Read(strconv.Itoa(cfgEp.EndpointGroupID))
	if err == nil {
		log.Debugf("pktTag: %v ", cfgEpGroup.PktTag)
	} else if core.ErrIfKeyExists(err) == nil {
		log.Infof("%v will use network based tag ", err)
		cfgEpGroup.PktTagType = cfgNw.PktTagType
		cfgEpGroup.PktTag = cfgNw.PktTag
	} else {
		return err
	}

	// Find the switch based on network type
	var sw *OvsSwitch
	if cfgEpGroup.PktTagType == "vxlan" {
		sw = d.switchDb["vxlan"]
	} else {
		sw = d.switchDb["vlan"]
	}

	operEp := &OvsOperEndpointState{}
	operEp.StateDriver = d.oper.StateDriver
	err = operEp.Read(id)
	if core.ErrIfKeyExists(err) != nil {
		return err
	} else if err == nil {
		// check if oper state matches cfg state. In case of mismatch cleanup
		// up the EP and continue add new one. In case of match just return.
		if operEp.Matches(cfgEp) {
			log.Printf("Found matching oper state for ep %s, noop", id)

			// Ask the switch to update the port
			err = sw.UpdatePort(operEp.PortName, cfgEp, cfgEpGroup.PktTag)
			if err != nil {
				log.Errorf("Error creating port %s. Err: %v", intfName, err)
				return err
			}

			return nil
		}
		log.Printf("Found mismatching oper state for Ep, cleaning it. Config: %+v, Oper: %+v",
			cfgEp, operEp)
		d.DeleteEndpoint(operEp.ID)
	}

	// Get the interface name to use
	intfName, err = d.getIntfName()
	if err != nil {
		return err
	}

	// Ask the switch to create the port
	err = sw.CreatePort(intfName, cfgEp, cfgEpGroup.PktTag, cfgNw.PktTag)
	if err != nil {
		log.Errorf("Error creating port %s. Err: %v", intfName, err)
		return err
	}

	// Save the oper state
	operEp = &OvsOperEndpointState{
		NetID:       cfgEp.NetID,
		AttachUUID:  cfgEp.AttachUUID,
		ContName:    cfgEp.ContName,
		ServiceName: cfgEp.ServiceName,
		IPAddress:   cfgEp.IPAddress,
		MacAddress:  cfgEp.MacAddress,
		IntfName:    cfgEp.IntfName,
		PortName:    intfName,
		HomingHost:  cfgEp.HomingHost,
		VtepIP:      cfgEp.VtepIP}
	operEp.StateDriver = d.oper.StateDriver
	operEp.ID = id
	err = operEp.Write()
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			operEp.Clear()
		}
	}()

	return nil
}
示例#13
0
// CreateEndpoint creates an endpoint by named identifier
func (d *OvsDriver) CreateEndpoint(id string) error {
	var (
		err      error
		intfName string
		intfType string
	)

	cfgEp := &OvsCfgEndpointState{}
	cfgEp.StateDriver = d.oper.StateDriver
	err = cfgEp.Read(id)
	if err != nil {
		return err
	}

	// Ignore VTEP endpoints and uplink endpoints
	// FIXME: we need to stop publiching these from netmaster
	if cfgEp.VtepIP != "" {
		return nil
	}
	if cfgEp.IntfName != "" {
		return nil
	}

	cfgNw := OvsCfgNetworkState{}
	cfgNw.StateDriver = d.oper.StateDriver
	err = cfgNw.Read(cfgEp.NetID)
	if err != nil {
		return err
	}

	// Find the switch based on network type
	var sw *OvsSwitch
	if cfgNw.PktTagType == "vxlan" {
		sw = d.switchDb["vxlan"]
	} else {
		sw = d.switchDb["vlan"]
	}

	operEp := &OvsOperEndpointState{}
	operEp.StateDriver = d.oper.StateDriver
	err = operEp.Read(id)
	if core.ErrIfKeyExists(err) != nil {
		return err
	} else if err == nil {
		// check if oper state matches cfg state. In case of mismatch cleanup
		// up the EP and continue add new one. In case of match just return.
		if operEp.Matches(cfgEp) {
			log.Printf("Found matching oper state for ep %s, noop", id)

			// Ask the switch to update the port
			err = sw.UpdatePort(operEp.PortName, cfgEp, cfgNw.PktTag)
			if err != nil {
				log.Errorf("Error creating port %s. Err: %v", intfName, err)
				return err
			}

			return nil
		}
		log.Printf("Found mismatching oper state for Ep, cleaning it. Config: %+v, Oper: %+v",
			cfgEp, operEp)
		d.DeleteEndpoint(operEp.ID)
	}

	// add an internal ovs port with vlan-tag information from the state

	// XXX: revisit, the port name might need to come from user. Also revisit
	// the algorithm to take care of port being deleted and reuse unused port
	// numbers
	d.oper.CurrPortNum++
	err = d.oper.Write()
	if err != nil {
		return err
	}
	intfName = d.getIntfName()
	intfType = "internal"

	// Ask the switch to create the port
	err = sw.CreatePort(intfName, intfType, cfgEp, cfgNw.PktTag)
	if err != nil {
		log.Errorf("Error creating port %s. Err: %v", intfName, err)
		return err
	}

	// Save the oper state
	operEp = &OvsOperEndpointState{
		NetID:      cfgEp.NetID,
		AttachUUID: cfgEp.AttachUUID,
		ContName:   cfgEp.ContName,
		IPAddress:  cfgEp.IPAddress,
		MacAddress: cfgEp.MacAddress,
		IntfName:   cfgEp.IntfName,
		PortName:   intfName,
		HomingHost: cfgEp.HomingHost,
		VtepIP:     cfgEp.VtepIP}
	operEp.StateDriver = d.oper.StateDriver
	operEp.ID = id
	err = operEp.Write()
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			operEp.Clear()
		}
	}()

	return nil
}