Example #1
0
//UpdateEndpointGroup updates the endpointgroups
func UpdateEndpointGroup(bandwidth, groupName, tenantName string, Dscp, burst int) error {

	// Get the state driver - get the etcd driver state
	stateDriver, err := utils.GetStateDriver()
	if err != nil {
		return err
	}

	key := mastercfg.GetEndpointGroupKey(groupName, tenantName)
	if key == "" {
		return errors.New("Error finding endpointGroup key ")
	}

	// Read etcd driver
	epCfg := mastercfg.EndpointGroupState{}
	epCfg.StateDriver = stateDriver

	err = epCfg.Read(key)
	if err != nil {
		log.Errorf("Error finding endpointgroup %s. Err: %v", key, err)
		return err
	}

	//update the epGroup state
	epCfg.DSCP = Dscp
	epCfg.Bandwidth = bandwidth
	epCfg.Burst = burst

	//Write to etcd
	err = epCfg.Write()
	if err != nil {
		return err
	}
	return nil
}
Example #2
0
// DeleteEndpointGroup handles endpoint group deletes
func DeleteEndpointGroup(tenantName, groupName string) error {
	// Get the state driver
	stateDriver, err := utils.GetStateDriver()
	if err != nil {
		return err
	}

	epgKey := mastercfg.GetEndpointGroupKey(groupName, tenantName)
	epgCfg := &mastercfg.EndpointGroupState{}
	epgCfg.StateDriver = stateDriver
	err = epgCfg.Read(epgKey)
	if err != nil {
		log.Errorf("error reading EPG key %s. Error: %s", epgKey, err)
		return err
	}

	if epgCfg.EpCount != 0 {
		return core.Errorf("Error: EPG %s has active endpoints", groupName)
	}

	// Delete the endpoint group state
	gstate.GlobalMutex.Lock()
	defer gstate.GlobalMutex.Unlock()
	gCfg := gstate.Cfg{}
	gCfg.StateDriver = stateDriver
	err = gCfg.Read(epgCfg.TenantName)
	if err != nil {
		log.Errorf("error reading tenant cfg state. Error: %s", err)
		return err
	}

	// if aci mode we allocate per-epg vlan. free it here.
	aciMode, aErr := IsAciConfigured()
	if aErr != nil {
		return aErr
	}

	if aciMode {
		if epgCfg.PktTagType == "vlan" {
			err = gCfg.FreeVLAN(uint(epgCfg.PktTag))
			if err != nil {
				return err
			}
			log.Debugf("Freed vlan %v\n", epgCfg.PktTag)
		}
	}

	// Delete endpoint group
	err = epgCfg.Clear()
	if err != nil {
		log.Errorf("error writing epGroup config. Error: %v", err)
		return err
	}

	if GetClusterMode() == "docker" {
		return docknet.DeleteDockNet(epgCfg.TenantName, epgCfg.NetworkName, epgCfg.GroupName)
	}
	return nil
}
Example #3
0
// CreateEndpoint creates an endpoint
func CreateEndpoint(stateDriver core.StateDriver, nwCfg *mastercfg.CfgNetworkState,
	ep *intent.ConfigEP) (*mastercfg.CfgEndpointState, error) {
	epCfg := &mastercfg.CfgEndpointState{}
	epCfg.StateDriver = stateDriver
	epCfg.ID = getEpName(nwCfg.ID, ep)
	err := epCfg.Read(epCfg.ID)
	if err == nil {
		// TODO: check for diffs and possible updates
		return epCfg, nil
	}

	epCfg.NetID = nwCfg.ID
	epCfg.ContName = ep.Container
	epCfg.AttachUUID = ep.AttachUUID
	epCfg.HomingHost = ep.Host
	epCfg.ServiceName = ep.ServiceName

	// Allocate addresses
	err = allocSetEpAddress(ep, epCfg, nwCfg)
	if err != nil {
		log.Errorf("error allocating and/or reserving IP. Error: %s", err)
		return nil, err
	}

	// Set endpoint group
	// Skip for infra nw
	if nwCfg.NwType != "infra" {
		epCfg.EndpointGroupKey = mastercfg.GetEndpointGroupKey(ep.ServiceName, nwCfg.Tenant)
		epCfg.EndpointGroupID, err = mastercfg.GetEndpointGroupID(stateDriver, ep.ServiceName, nwCfg.Tenant)
		if err != nil {
			log.Errorf("Error getting endpoint group for %s.%s. Err: %v", ep.ServiceName, nwCfg.ID, err)
			return nil, err
		}
	}

	err = nwCfg.IncrEpCount()
	if err != nil {
		log.Errorf("Error incrementing ep count. Err: %v", err)
		return nil, err
	}

	err = epCfg.Write()
	if err != nil {
		log.Errorf("error writing ep config. Error: %s", err)
		return nil, err
	}

	return epCfg, nil
}
Example #4
0
// CreateEndpointGroup handles creation of endpoint group
func CreateEndpointGroup(tenantName, networkName, groupName string) error {
	var epgID int

	// Get the state driver
	stateDriver, err := utils.GetStateDriver()
	if err != nil {
		return err
	}

	// Read global config
	gCfg := gstate.Cfg{}
	gCfg.StateDriver = stateDriver
	err = gCfg.Read(tenantName)
	if err != nil {
		log.Errorf("error reading tenant cfg state. Error: %s", err)
		return err
	}

	// read the network config
	networkID := networkName + "." + tenantName
	nwCfg := &mastercfg.CfgNetworkState{}
	nwCfg.StateDriver = stateDriver
	err = nwCfg.Read(networkID)
	if err != nil {
		log.Errorf("Could not find network %s. Err: %v", networkID, err)
		return err
	}

	// params for docker network
	if GetClusterMode() == "docker" {
		// Create each EPG as a docker network
		err = docknet.CreateDockNet(tenantName, networkName, groupName, nwCfg)
		if err != nil {
			log.Errorf("Error creating docker network for group %s.%s. Err: %v", networkName, groupName, err)
			return err
		}
	}

	// assign unique endpoint group ids
	// FIXME: This is a hack. need to add a epgID resource
	for i := 0; i < maxEpgID; i++ {
		epgID = globalEpgID
		globalEpgID = globalEpgID + 1
		if globalEpgID > maxEpgID {
			globalEpgID = 1
		}
		epgCfg := &mastercfg.EndpointGroupState{}
		epgCfg.StateDriver = stateDriver
		err = epgCfg.Read(strconv.Itoa(epgID))
		if err != nil {
			break
		}
	}

	// Create epGroup state
	epgCfg := &mastercfg.EndpointGroupState{
		GroupName:       groupName,
		TenantName:      tenantName,
		NetworkName:     networkName,
		EndpointGroupID: epgID,
		PktTagType:      nwCfg.PktTagType,
		PktTag:          nwCfg.PktTag,
		ExtPktTag:       nwCfg.ExtPktTag,
	}

	epgCfg.StateDriver = stateDriver
	epgCfg.ID = mastercfg.GetEndpointGroupKey(groupName, tenantName)
	log.Debugf("##Create EpGroup %v network %v tagtype %v", groupName, networkName, nwCfg.PktTagType)

	// if aci mode allocate per-epg vlan. otherwise, stick to per-network vlan
	aciMode, rErr := IsAciConfigured()
	if rErr != nil {
		return rErr
	}

	// Special handling for ACI mode
	if aciMode {
		if epgCfg.PktTagType != "vlan" {
			log.Errorf("Network type must be VLAN for ACI mode")
			return errors.New("Network type must be VLAN for ACI mode")
		}

		pktTag, err := gCfg.AllocVLAN(0)
		if err != nil {
			return err
		}
		epgCfg.PktTag = int(pktTag)
		log.Debugf("ACI -- Allocated vlan %v for epg %v", pktTag, groupName)

	}

	err = epgCfg.Write()
	if err != nil {
		return err
	}

	return nil
}
Example #5
0
// CreateEndpoint creates an endpoint
func CreateEndpoint(stateDriver core.StateDriver, nwCfg *mastercfg.CfgNetworkState,
	epReq *CreateEndpointRequest) (*mastercfg.CfgEndpointState, error) {

	ep := &epReq.ConfigEP
	epCfg := &mastercfg.CfgEndpointState{}
	epCfg.StateDriver = stateDriver
	epCfg.ID = getEpName(nwCfg.ID, ep)
	err := epCfg.Read(epCfg.ID)
	if err == nil {
		// TODO: check for diffs and possible updates
		return epCfg, nil
	}

	epCfg.NetID = nwCfg.ID
	epCfg.EndpointID = ep.Container
	epCfg.HomingHost = ep.Host
	epCfg.ServiceName = ep.ServiceName
	epCfg.EPCommonName = epReq.EPCommonName

	// Allocate addresses
	err = allocSetEpAddress(ep, epCfg, nwCfg)
	if err != nil {
		log.Errorf("error allocating and/or reserving IP. Error: %s", err)
		return nil, err
	}

	// cleanup relies on var err being used for all error checking
	defer freeAddrOnErr(nwCfg, epCfg.IPAddress, &err)

	// Set endpoint group
	// Skip for infra nw
	if nwCfg.NwType != "infra" {
		epCfg.EndpointGroupKey = mastercfg.GetEndpointGroupKey(ep.ServiceName, nwCfg.Tenant)
		epCfg.EndpointGroupID, err = mastercfg.GetEndpointGroupID(stateDriver, ep.ServiceName, nwCfg.Tenant)
		if err != nil {
			log.Errorf("Error getting endpoint group ID for %s.%s. Err: %v", ep.ServiceName, nwCfg.ID, err)
			return nil, err
		}

		if epCfg.EndpointGroupKey != "" {
			epgCfg := &mastercfg.EndpointGroupState{}
			epgCfg.StateDriver = stateDriver
			err = epgCfg.Read(epCfg.EndpointGroupKey)
			if err != nil {
				log.Errorf("Error reading Epg info for EP: %+v. Error: %v", ep, err)
				return nil, err
			}

			epgCfg.EpCount++

			err = epgCfg.Write()
			if err != nil {
				log.Errorf("Error saving epg state: %+v", epgCfg)
				return nil, err
			}
		}
	}

	err = nwCfg.IncrEpCount()
	if err != nil {
		log.Errorf("Error incrementing ep count. Err: %v", err)
		return nil, err
	}

	err = epCfg.Write()
	if err != nil {
		log.Errorf("error writing ep config. Error: %s", err)
		return nil, err
	}

	return epCfg, nil
}
Example #6
0
// Extract relevant info from epg obj and append to application nw spec
func appendEpgInfo(eMap *epgMap, epgObj *contivModel.EndpointGroup, stateDriver core.StateDriver) error {
	epg := epgSpec{}
	epg.Name = epgObj.GroupName

	log.Infof("Processing EPG: %+v", epgObj)
	// Get EPG key for the endpoint group
	epgKey := mastercfg.GetEndpointGroupKey(epgObj.GroupName, epgObj.TenantName)

	// update vlantag from EpGroupState
	epgCfg := &mastercfg.EndpointGroupState{}
	epgCfg.StateDriver = stateDriver
	eErr := epgCfg.Read(epgKey)
	if eErr != nil {
		log.Errorf("Error reading epg %v %v", epgKey, eErr)
		return eErr
	}

	// get the network name and gw cidr and update.
	epg.NwName = epgObj.NetworkName
	gwCIDR, nErr := getGwCIDR(epgObj, stateDriver)
	if nErr != nil {
		return nErr
	}
	epg.GwCIDR = gwCIDR

	epg.VlanTag = strconv.Itoa(epgCfg.PktTag)
	epg.epgID = epgCfg.EndpointGroupID

	// get all the policy details
	for _, policy := range epgObj.Policies {
		log.Debugf("==Processing policy %v", policy)
		policyKey := epgObj.TenantName + ":" + policy
		pObj := contivModel.FindPolicy(policyKey)
		if pObj == nil {
			errStr := fmt.Sprintf("Policy %v not found epg: %v", policy, epg.Name)
			return errors.New(errStr)
		}

		nErr = addPolicyContracts(eMap.Contracts, &epg, pObj)
		if nErr != nil {
			return nErr
		}
	}

	// Add linked contracts based on rules that refer this epg
	for _, ruleLink := range epgObj.LinkSets.MatchRules {
		rule := contivModel.FindRule(ruleLink.ObjKey)
		if rule == nil {
			errStr := fmt.Sprintf("Rule %s referring to epg %s not found",
				ruleLink.ObjKey, epg.Name)
			return errors.New(errStr)
		}
		cn := getContractName(rule.PolicyName, rule.FromEndpointGroup,
			rule.ToEndpointGroup)
		lKind := ""
		if rule.FromEndpointGroup != "" {
			lKind = cConsume
		} else {
			lKind = cProvide
		}

		cLink := contrLink{LinkKind: lKind,
			ContractName: cn,
			ContractKind: cInternal,
		}
		epg.ContractLinks = append(epg.ContractLinks, cLink)
	}

	// Append links for external contracts.
	tenant := epgObj.TenantName
	for _, contractsGrp := range epgObj.ExtContractsGrps {
		contractsGrpKey := tenant + ":" + contractsGrp
		contractsGrpObj := contivModel.FindExtContractsGroup(contractsGrpKey)

		if contractsGrpObj == nil {
			errStr := fmt.Sprintf("Contracts %v not found for epg: %v", contractsGrp, epg.Name)
			return errors.New(errStr)
		}

		lKind := ""
		if contractsGrpObj.ContractsType == "consumed" {
			lKind = cConsume
		} else if contractsGrpObj.ContractsType == "provided" {
			lKind = cProvide
		} else {
			// Should not be here.
			errStr := fmt.Sprintf("Invalid contracts type %v", contractsGrp)
			return errors.New(errStr)
		}

		for _, dn := range contractsGrpObj.Contracts {
			cLink := contrLink{LinkKind: lKind,
				ContractDN:   dn,
				ContractKind: cExternal,
			}
			epg.ContractLinks = append(epg.ContractLinks, cLink)
		}
	}

	eMap.Specs[epg.Name] = epg
	return nil
}
Example #7
0
// Extract relevant info from epg obj and append to application nw spec
func appendEpgInfo(eMap *epgMap, epgObj *contivModel.EndpointGroup, stateDriver core.StateDriver) error {
	epg := epgSpec{}
	epg.Name = epgObj.GroupName

	log.Infof("Processing EPG: %+v", epgObj)
	// Get EPG key for the endpoint group
	epgKey := mastercfg.GetEndpointGroupKey(epgObj.GroupName, epgObj.TenantName)

	// update vlantag from EpGroupState
	epgCfg := &mastercfg.EndpointGroupState{}
	epgCfg.StateDriver = stateDriver
	eErr := epgCfg.Read(epgKey)
	if eErr != nil {
		log.Errorf("Error reading epg %v %v", epgKey, eErr)
		return eErr
	}

	epg.VlanTag = strconv.Itoa(epgCfg.PktTag)

	// get all the service link details
	for _, policy := range epgObj.Policies {
		log.Debugf("==Processing policy %v", policy)
		policyKey := epgObj.TenantName + ":" + policy
		pObj := contivModel.FindPolicy(policyKey)
		if pObj == nil {
			errStr := fmt.Sprintf("Policy %v not found epg: %v", policy, epg.Name)
			return errors.New(errStr)
		}

		for ruleName := range pObj.LinkSets.Rules {
			log.Debugf("==Processing rule %v", ruleName)
			rule := contivModel.FindRule(ruleName)
			if rule == nil {
				errStr := fmt.Sprintf("rule %v not found", ruleName)
				return errors.New(errStr)
			}

			if rule.Action == "deny" {
				log.Debugf("==Ignoring deny rule %v", ruleName)
				continue
			}
			singleFilter := filterInfo{Protocol: rule.Protocol, ServPort: strconv.Itoa(rule.Port)}
			epg.Filters = append(epg.Filters, singleFilter)
			log.Debugf("Filter information: %v", singleFilter)

			if rule.FromEndpointGroup == "" {
				log.Debugf("User unspecified %v == exposed contract", ruleName)
				continue
			}

			// rule.FromEndpointGroup uses this epg
			uEpg, ok := eMap.Specs[rule.FromEndpointGroup]
			if ok {
				uEpg.Uses = append(uEpg.Uses, epg.Name)
				eMap.Specs[rule.FromEndpointGroup] = uEpg
			} else {
				//not in the map - need to add
				userEpg := epgSpec{}
				userEpg.Uses = append(userEpg.Uses, epg.Name)
				eMap.Specs[rule.FromEndpointGroup] = userEpg
			}
			log.Debugf("==Used by %v", rule.FromEndpointGroup)
		}

	}

	// Append external contracts.
	tenant := epgObj.TenantName
	for _, contractsGrp := range epgObj.ExtContractsGrps {
		contractsGrpKey := tenant + ":" + contractsGrp
		contractsGrpObj := contivModel.FindExtContractsGroup(contractsGrpKey)

		if contractsGrpObj == nil {
			errStr := fmt.Sprintf("Contracts %v not found for epg: %v", contractsGrp, epg.Name)
			return errors.New(errStr)
		}
		if contractsGrpObj.ContractsType == "consumed" {
			epg.ConsContracts = append(epg.ConsContracts, contractsGrpObj.Contracts...)
		} else if contractsGrpObj.ContractsType == "provided" {
			epg.ProvContracts = append(epg.ProvContracts, contractsGrpObj.Contracts...)
		} else {
			// Should not be here.
			errStr := fmt.Sprintf("Invalid contracts type %v", contractsGrp)
			return errors.New(errStr)
		}
	}

	log.Debugf("Copied over %d externally defined consumed contracts", len(epg.ConsContracts))
	log.Debugf("Copied over %d externally defined provided contracts", len(epg.ProvContracts))

	// add any saved uses info before overwriting
	savedEpg, ok := eMap.Specs[epg.Name]
	if ok {
		epg.Uses = append(epg.Uses, savedEpg.Uses...)
	}
	eMap.Specs[epg.Name] = epg
	return nil
}
Example #8
0
//UpdateEndpointHandler handles update event from netplugin
func UpdateEndpointHandler(w http.ResponseWriter, r *http.Request, vars map[string]string) (interface{}, error) {

	var epUpdReq UpdateEndpointRequest

	// Get object from the request
	err := json.NewDecoder(r.Body).Decode(&epUpdReq)

	if err != nil {
		log.Errorf("Error decoding EndpointUpdateRequest. Err %v", err)
		return nil, err
	}

	log.Infof("Received EndpointUpdateRequest {%+v}", epUpdReq)

	stateDriver, err := utils.GetStateDriver()
	if err != nil {
		return nil, err
	}

	if epUpdReq.Event == "start" {
		//Received container start event from netplugin. Check if the Provider
		//matches any service and perform service provider update if there is a matching
		//service.

		epCfg := &mastercfg.CfgEndpointState{}
		epCfg.StateDriver = stateDriver

		nwCfg := &mastercfg.CfgNetworkState{}
		nwCfg.StateDriver = stateDriver
		//check if networkname is epg name or network name
		key := mastercfg.GetNwCfgKey(epUpdReq.Network, epUpdReq.Tenant)
		err := nwCfg.Read(key)
		if err != nil {
			if !strings.Contains(err.Error(), "Key not found") {
				return nil, err
			}
			//If network is not found then networkname is epg
			epgCfg := &mastercfg.EndpointGroupState{}
			epgCfg.StateDriver = stateDriver
			key = mastercfg.GetEndpointGroupKey(epUpdReq.Network, epUpdReq.Tenant)
			err := epgCfg.Read(key)
			if err != nil {
				return nil, err
			}
			//get the network associated with the endpoint group
			key = mastercfg.GetNwCfgKey(epgCfg.NetworkName, epUpdReq.Tenant)
		}

		epCfg.ID = getEpName(key, &intent.ConfigEP{Container: epUpdReq.EndpointID})

		err = epCfg.Read(epCfg.ID)
		if err != nil {
			return nil, err
		}

		provider := &mastercfg.Provider{}
		provider.IPAddress = epUpdReq.IPAddress
		provider.Tenant = epUpdReq.Tenant
		provider.Network = epUpdReq.Network
		provider.ContainerID = epUpdReq.ContainerID
		provider.Labels = make(map[string]string)

		if epCfg.Labels == nil {
			//endpoint cfg doesnt have labels
			epCfg.Labels = make(map[string]string)
		}

		for k, v := range epUpdReq.Labels {
			provider.Labels[k] = v
			epCfg.Labels[k] = v
		}
		provider.EpIDKey = epCfg.ID
		//maintain the containerId in endpointstat for recovery
		epCfg.ContainerID = epUpdReq.ContainerID
		epCfg.EPCommonName = epUpdReq.EPCommonName

		err = epCfg.Write()
		if err != nil {
			log.Errorf("error writing ep config. Error: %s", err)
			return nil, err
		}

		providerID := getProviderID(provider)
		providerDbID := getProviderDbID(provider)
		if providerID == "" || providerDbID == "" {
			return nil, fmt.Errorf("Invalid ProviderID from providerInfo:{%v}", provider)
		}

		//update provider db
		mastercfg.SvcMutex.Lock()
		mastercfg.ProviderDb[providerDbID] = provider

		for serviceID, service := range mastercfg.ServiceLBDb {
			count := 0
			if service.Tenant == epUpdReq.Tenant {
				for key, value := range epUpdReq.Labels {
					if val := service.Selectors[key]; val == value {
						count++
					}

					if count == len(service.Selectors) {
						//Container corresponds to the service since it
						//matches all service Selectors
						mastercfg.ProviderDb[providerDbID].Services =
							append(mastercfg.ProviderDb[providerDbID].Services, serviceID)
							//Update ServiceDB
						mastercfg.ServiceLBDb[serviceID].Providers[providerID] = provider

						serviceLbState := &mastercfg.CfgServiceLBState{}
						serviceLbState.StateDriver = stateDriver
						err = serviceLbState.Read(serviceID)
						if err != nil {
							mastercfg.SvcMutex.Unlock()
							return nil, err
						}
						serviceLbState.Providers[providerID] = provider
						serviceLbState.Write()
						SvcProviderUpdate(serviceID, false)
						break
					}
				}
			}
		}
		mastercfg.SvcMutex.Unlock()

	} else if epUpdReq.Event == "die" {
		//Received a container die event. If it was a service provider -
		//clear the provider db and the service db and change the etcd state

		providerDbID := epUpdReq.ContainerID
		if providerDbID == "" {
			return nil, fmt.Errorf("Invalid containerID in UpdateEndpointRequest:(nil)")
		}

		mastercfg.SvcMutex.Lock()
		provider := mastercfg.ProviderDb[providerDbID]
		if provider == nil {
			mastercfg.SvcMutex.Unlock()
			// It is not a provider . Ignore event
			return nil, nil
		}

		for _, serviceID := range provider.Services {
			service := mastercfg.ServiceLBDb[serviceID]
			providerID := getProviderID(provider)
			if providerID == "" {
				mastercfg.SvcMutex.Unlock()
				return nil, fmt.Errorf("Invalid ProviderID from providerInfo:{%v}", provider)
			}
			if service.Providers[providerID] != nil {
				delete(service.Providers, providerID)

				serviceLbState := &mastercfg.CfgServiceLBState{}
				serviceLbState.StateDriver = stateDriver
				err = serviceLbState.Read(serviceID)
				if err != nil {
					mastercfg.SvcMutex.Unlock()
					return nil, err
				}
				delete(serviceLbState.Providers, providerID)
				serviceLbState.Write()
				delete(mastercfg.ProviderDb, providerDbID)
				SvcProviderUpdate(serviceID, false)

			}
		}
		mastercfg.SvcMutex.Unlock()

	}

	epUpdResp := &UpdateEndpointResponse{
		IPAddress: epUpdReq.IPAddress,
	}
	return epUpdResp, nil
}