// Setup external contracts for an epg. func setupExternalContracts(endpointGroup *contivModel.EndpointGroup, extContractsGrps []string) error { // Validate presence and register consumed external contracts tenant := endpointGroup.TenantName for _, contractsGrp := range extContractsGrps { contractsGrpKey := tenant + ":" + contractsGrp contractsGrpObj := contivModel.FindExtContractsGroup(contractsGrpKey) if contractsGrpObj == nil { errStr := fmt.Sprintf("External contracts group %s not found", contractsGrp) log.Errorf(errStr) return core.Errorf(errStr) } // Establish the necessary links. modeldb.AddLinkSet(&contractsGrpObj.LinkSets.EndpointGroups, endpointGroup) modeldb.AddLinkSet(&endpointGroup.LinkSets.ExtContractsGrps, contractsGrpObj) // Links made, write the policy set object. err := contractsGrpObj.Write() if err != nil { return err } } return nil }
// RuleCreate Creates the rule within a policy func (ac *APIController) RuleCreate(rule *contivModel.Rule) error { log.Infof("Received RuleCreate: %+v", rule) policyKey := rule.TenantName + ":" + rule.PolicyName // find the policy policy := contivModel.FindPolicy(policyKey) if policy == nil { log.Errorf("Error finding policy %s", policyKey) return core.Errorf("Policy not found") } // link the rule to policy modeldb.AddLinkSet(&rule.LinkSets.Policies, policy) modeldb.AddLinkSet(&policy.LinkSets.Rules, rule) err := policy.Write() if err != nil { return err } // Trigger policyDB Update err = master.PolicyAddRule(policy, rule) if err != nil { log.Errorf("Error adding rule %s to policy %s. Err: %v", rule.Key, policy.Key, err) return err } return nil }
// AppProfileUpdate updates app func (ac *APIController) AppProfileUpdate(oldProf, newProf *contivModel.AppProfile) error { log.Infof("Received AppProfileUpdate: %+v, newProf: %+v", oldProf, newProf) // handle any epg addition for _, epg := range newProf.EndpointGroups { epgKey := newProf.TenantName + ":" + epg log.Infof("Add %s to %s", epgKey, newProf.AppProfileName) epgObj := contivModel.FindEndpointGroup(epgKey) if epgObj == nil { return core.Errorf("EndpointGroup %s not found", epgKey) } modeldb.AddLinkSet(&newProf.LinkSets.EndpointGroups, epgObj) // workaround for objdb update problem modeldb.AddLinkSet(&oldProf.LinkSets.EndpointGroups, epgObj) modeldb.AddLink(&epgObj.Links.AppProfile, newProf) err := epgObj.Write() if err != nil { log.Errorf("Error updating epg state(%+v). Err: %v", epgObj, err) return err } } // handle any epg removal for _, epg := range oldProf.EndpointGroups { if !stringInSlice(epg, newProf.EndpointGroups) { epgKey := newProf.TenantName + ":" + epg log.Infof("Remove %s from %s", epgKey, newProf.AppProfileName) epgObj := contivModel.FindEndpointGroup(epgKey) if epgObj == nil { return core.Errorf("EndpointGroup %s not found", epgKey) } modeldb.RemoveLink(&epgObj.Links.AppProfile, oldProf) err := epgObj.Write() if err != nil { log.Errorf("Error updating epg state(%+v). Err: %v", epgObj, err) return err } // workaround for objdb update problem modeldb.RemoveLinkSet(&oldProf.LinkSets.EndpointGroups, epgObj) } } // workaround for objdb update problem -- should fix model oldProf.EndpointGroups = newProf.EndpointGroups // update the app nw DeleteAppNw(oldProf) CreateAppNw(oldProf) return nil }
// RuleCreate Creates the rule within a policy func (ac *APIController) RuleCreate(rule *contivModel.Rule) error { log.Infof("Received RuleCreate: %+v", rule) // verify parameter values if rule.Direction == "in" { if rule.ToNetwork != "" || rule.ToEndpointGroup != "" || rule.ToIpAddress != "" { return errors.New("Can not specify 'to' parameters in incoming rule") } if rule.FromNetwork != "" && rule.FromIpAddress != "" { return errors.New("Can not specify both from network and from ip address") } } else if rule.Direction == "out" { if rule.FromNetwork != "" || rule.FromEndpointGroup != "" || rule.FromIpAddress != "" { return errors.New("Can not specify 'from' parameters in outgoing rule") } if rule.ToNetwork != "" && rule.ToIpAddress != "" { return errors.New("Can not specify both to-network and to-ip address") } } else { return errors.New("Invalid direction for the rule") } policyKey := rule.TenantName + ":" + rule.PolicyName // find the policy policy := contivModel.FindPolicy(policyKey) if policy == nil { log.Errorf("Error finding policy %s", policyKey) return core.Errorf("Policy not found") } // Trigger policyDB Update err := master.PolicyAddRule(policy, rule) if err != nil { log.Errorf("Error adding rule %s to policy %s. Err: %v", rule.Key, policy.Key, err) return err } // link the rule to policy modeldb.AddLinkSet(&rule.LinkSets.Policies, policy) modeldb.AddLinkSet(&policy.LinkSets.Rules, rule) err = policy.Write() if err != nil { return err } return nil }
// AppCreate creates app state func (ac *APIController) AppCreate(app *contivModel.App) error { log.Infof("Received AppCreate: %+v", app) // Make sure tenant exists if app.TenantName == "" { return core.Errorf("Invalid tenant name") } tenant := contivModel.FindTenant(app.TenantName) if tenant == nil { return core.Errorf("Tenant not found") } // Setup links modeldb.AddLink(&app.Links.Tenant, tenant) modeldb.AddLinkSet(&tenant.LinkSets.Apps, app) // Save the tenant too since we added the links err := tenant.Write() if err != nil { log.Errorf("Error updating tenant state(%+v). Err: %v", tenant, err) return err } CreateAppNw(app) return nil }
// PolicyCreate creates policy func (ac *APIController) PolicyCreate(policy *contivModel.Policy) error { log.Infof("Received PolicyCreate: %+v", policy) // Make sure tenant exists if policy.TenantName == "" { return core.Errorf("Invalid tenant name") } tenant := contivModel.FindTenant(policy.TenantName) if tenant == nil { return core.Errorf("Tenant not found") } // Setup links modeldb.AddLink(&policy.Links.Tenant, tenant) modeldb.AddLinkSet(&tenant.LinkSets.Policies, policy) // Save the tenant too since we added the links err := tenant.Write() if err != nil { log.Errorf("Error updating tenant state(%+v). Err: %v", tenant, err) return err } return nil }
// NetworkCreate creates network func (ac *APIController) NetworkCreate(network *contivModel.Network) error { log.Infof("Received NetworkCreate: %+v", network) // Make sure tenant exists if network.TenantName == "" { return core.Errorf("Invalid tenant name") } tenant := contivModel.FindTenant(network.TenantName) if tenant == nil { return core.Errorf("Tenant not found") } // If there is an EndpointGroup with the same name as this network, reject. nameClash := contivModel.FindEndpointGroup(network.Key) if nameClash != nil { return core.Errorf("EndpointGroup %s conflicts with the network name", nameClash.GroupName) } // Get the state driver stateDriver, err := utils.GetStateDriver() if err != nil { return err } // Build network config networkCfg := intent.ConfigNetwork{ Name: network.NetworkName, NwType: network.NwType, PktTagType: network.Encap, PktTag: network.PktTag, SubnetCIDR: network.Subnet, Gateway: network.Gateway, } // Create the network err = master.CreateNetwork(networkCfg, stateDriver, network.TenantName) if err != nil { log.Errorf("Error creating network {%+v}. Err: %v", network, err) return err } // Setup links modeldb.AddLink(&network.Links.Tenant, tenant) modeldb.AddLinkSet(&tenant.LinkSets.Networks, network) // Save the tenant too since we added the links err = tenant.Write() if err != nil { log.Errorf("Error updating tenant state(%+v). Err: %v", tenant, err) return err } return nil }
// AppProfileCreate creates app profile state func (ac *APIController) AppProfileCreate(prof *contivModel.AppProfile) error { log.Infof("Received AppProfileCreate: %+v", prof) // Make sure tenant exists if prof.TenantName == "" { return core.Errorf("Invalid tenant name") } tenant := contivModel.FindTenant(prof.TenantName) if tenant == nil { return core.Errorf("Tenant %s not found", prof.TenantName) } // Setup links modeldb.AddLink(&prof.Links.Tenant, tenant) modeldb.AddLinkSet(&tenant.LinkSets.AppProfiles, prof) for _, epg := range prof.EndpointGroups { epgKey := prof.TenantName + ":" + epg epgObj := contivModel.FindEndpointGroup(epgKey) if epgObj == nil { return core.Errorf("EndpointGroup %s not found", epgKey) } modeldb.AddLinkSet(&prof.LinkSets.EndpointGroups, epgObj) modeldb.AddLink(&epgObj.Links.AppProfile, prof) err := epgObj.Write() if err != nil { log.Errorf("Error updating epg state(%+v). Err: %v", epgObj, err) return err } } err := tenant.Write() if err != nil { log.Errorf("Error updating tenant state(%+v). Err: %v", tenant, err) return err } CreateAppNw(prof) return nil }
// ServiceInstanceCreate creates a service instance func (ac *APIController) ServiceInstanceCreate(serviceInstance *contivModel.ServiceInstance) error { log.Infof("Received ServiceInstanceCreate: %+v", serviceInstance) inst := serviceInstance // Find the service serviceKey := inst.TenantName + ":" + inst.AppName + ":" + inst.ServiceName service := contivModel.FindService(serviceKey) if service == nil { log.Errorf("Service %s not found for instance: %+v", serviceKey, inst) return core.Errorf("Service not found") } // Add links modeldb.AddLinkSet(&service.LinkSets.Instances, inst) modeldb.AddLink(&inst.Links.Service, service) return nil }
// ServiceCreate creates service func (ac *APIController) ServiceCreate(service *contivModel.Service) error { log.Infof("Received ServiceCreate: %+v", service) // check params if (service.TenantName == "") || (service.AppName == "") { return core.Errorf("Invalid parameters") } // Make sure tenant exists tenant := contivModel.FindTenant(service.TenantName) if tenant == nil { return core.Errorf("Tenant not found") } // Find the app this service belongs to app := contivModel.FindApp(service.TenantName + ":" + service.AppName) if app == nil { return core.Errorf("App not found") } // Setup links modeldb.AddLink(&service.Links.App, app) modeldb.AddLinkSet(&app.LinkSets.Services, service) // Save the app too since we added the links err := app.Write() if err != nil { return err } // Check if user specified any networks if len(service.Networks) == 0 { service.Networks = append(service.Networks, "private") } // link service with network for _, netName := range service.Networks { netKey := service.TenantName + ":" + netName network := contivModel.FindNetwork(netKey) if network == nil { log.Errorf("Service: %s could not find network %s", service.Key, netKey) return core.Errorf("Network not found") } // Link the network modeldb.AddLinkSet(&service.LinkSets.Networks, network) modeldb.AddLinkSet(&network.LinkSets.Services, service) // save the network err := network.Write() if err != nil { return err } } // Check if user specified any endpoint group for the service if len(service.EndpointGroups) == 0 { // Create one default endpointGroup per network for _, netName := range service.Networks { // params for default endpoint group dfltEpgName := service.AppName + "." + service.ServiceName + "." + netName endpointGroup := contivModel.EndpointGroup{ Key: service.TenantName + ":" + dfltEpgName, TenantName: service.TenantName, NetworkName: netName, GroupName: dfltEpgName, } // Create default endpoint group for the service err = contivModel.CreateEndpointGroup(&endpointGroup) if err != nil { log.Errorf("Error creating endpoint group: %+v, Err: %v", endpointGroup, err) return err } // Add the endpoint group to the list service.EndpointGroups = append(service.EndpointGroups, dfltEpgName) } } // Link the service and endpoint group for _, epgName := range service.EndpointGroups { endpointGroup := contivModel.FindEndpointGroup(service.TenantName + ":" + epgName) if endpointGroup == nil { log.Errorf("Error: could not find endpoint group: %s", epgName) return core.Errorf("could not find endpointGroup") } // setup links modeldb.AddLinkSet(&service.LinkSets.EndpointGroups, endpointGroup) modeldb.AddLinkSet(&endpointGroup.LinkSets.Services, service) // save the endpointGroup err = endpointGroup.Write() if err != nil { return err } } return nil }
// EndpointGroupUpdate updates endpoint group func (ac *APIController) EndpointGroupUpdate(endpointGroup, params *contivModel.EndpointGroup) error { log.Infof("Received EndpointGroupUpdate: %+v, params: %+v", endpointGroup, params) // Only update policy attachments // Look for policy adds for _, policyName := range params.Policies { if !stringInSlice(policyName, endpointGroup.Policies) { policyKey := endpointGroup.TenantName + ":" + policyName // find the policy policy := contivModel.FindPolicy(policyKey) if policy == nil { log.Errorf("Could not find policy %s", policyName) return core.Errorf("Policy not found") } // attach policy to epg err := master.PolicyAttach(endpointGroup, policy) if err != nil && err != master.EpgPolicyExists { log.Errorf("Error attaching policy %s to epg %s", policyName, endpointGroup.Key) return err } // Setup links modeldb.AddLinkSet(&policy.LinkSets.EndpointGroups, endpointGroup) modeldb.AddLinkSet(&endpointGroup.LinkSets.Policies, policy) err = policy.Write() if err != nil { return err } } } // now look for policy removals for _, policyName := range endpointGroup.Policies { if !stringInSlice(policyName, params.Policies) { policyKey := endpointGroup.TenantName + ":" + policyName // find the policy policy := contivModel.FindPolicy(policyKey) if policy == nil { log.Errorf("Could not find policy %s", policyName) return core.Errorf("Policy not found") } // detach policy to epg err := master.PolicyDetach(endpointGroup, policy) if err != nil && err != master.EpgPolicyExists { log.Errorf("Error detaching policy %s from epg %s", policyName, endpointGroup.Key) return err } // Remove links modeldb.RemoveLinkSet(&policy.LinkSets.EndpointGroups, endpointGroup) modeldb.RemoveLinkSet(&endpointGroup.LinkSets.Policies, policy) err = policy.Write() if err != nil { return err } } } // Update the policy list endpointGroup.Policies = params.Policies return nil }
// EndpointGroupCreate creates end point group func (ac *APIController) EndpointGroupCreate(endpointGroup *contivModel.EndpointGroup) error { log.Infof("Received EndpointGroupCreate: %+v", endpointGroup) // assign unique endpoint group ids endpointGroup.EndpointGroupID = globalEpgID globalEpgID = globalEpgID + 1 // Find the tenant tenant := contivModel.FindTenant(endpointGroup.TenantName) if tenant == nil { return core.Errorf("Tenant not found") } // Setup links modeldb.AddLink(&endpointGroup.Links.Tenant, tenant) modeldb.AddLinkSet(&tenant.LinkSets.EndpointGroups, endpointGroup) // Save the tenant too since we added the links err := tenant.Write() if err != nil { return err } // create the endpoint group state err = master.CreateEndpointGroup(endpointGroup.TenantName, endpointGroup.NetworkName, endpointGroup.GroupName, endpointGroup.EndpointGroupID) if err != nil { log.Errorf("Error creating endpoing group %+v. Err: %v", endpointGroup, err) return err } // for each policy create an epg policy Instance for _, policyName := range endpointGroup.Policies { policyKey := endpointGroup.TenantName + ":" + policyName // find the policy policy := contivModel.FindPolicy(policyKey) if policy == nil { log.Errorf("Could not find policy %s", policyName) return core.Errorf("Policy not found") } // attach policy to epg err = master.PolicyAttach(endpointGroup, policy) if err != nil { log.Errorf("Error attaching policy %s to epg %s", policyName, endpointGroup.Key) return err } // establish Links modeldb.AddLinkSet(&policy.LinkSets.EndpointGroups, endpointGroup) modeldb.AddLinkSet(&endpointGroup.LinkSets.Policies, policy) // Write the policy err = policy.Write() if err != nil { return err } } return nil }
// RuleCreate Creates the rule within a policy func (ac *APIController) RuleCreate(rule *contivModel.Rule) error { log.Infof("Received RuleCreate: %+v", rule) // verify parameter values if rule.Direction == "in" { if rule.ToNetwork != "" || rule.ToEndpointGroup != "" || rule.ToIpAddress != "" { return errors.New("Can not specify 'to' parameters in incoming rule") } if rule.FromNetwork != "" && rule.FromIpAddress != "" { return errors.New("Can not specify both from network and from ip address") } if rule.FromNetwork != "" && rule.FromEndpointGroup != "" { return errors.New("Can not specify both from network and from EndpointGroup") } } else if rule.Direction == "out" { if rule.FromNetwork != "" || rule.FromEndpointGroup != "" || rule.FromIpAddress != "" { return errors.New("Can not specify 'from' parameters in outgoing rule") } if rule.ToNetwork != "" && rule.ToIpAddress != "" { return errors.New("Can not specify both to-network and to-ip address") } if rule.ToNetwork != "" && rule.ToEndpointGroup != "" { return errors.New("Can not specify both to-network and to-EndpointGroup") } } else { return errors.New("Invalid direction for the rule") } // Make sure endpoint groups and networks referred exists. if rule.FromEndpointGroup != "" { epgKey := rule.TenantName + ":" + rule.FromEndpointGroup // find the endpoint group epg := contivModel.FindEndpointGroup(epgKey) if epg == nil { log.Errorf("Error finding endpoint group %s", epgKey) return errors.New("endpoint group not found") } } else if rule.ToEndpointGroup != "" { epgKey := rule.TenantName + ":" + rule.ToEndpointGroup // find the endpoint group epg := contivModel.FindEndpointGroup(epgKey) if epg == nil { log.Errorf("Error finding endpoint group %s", epgKey) return errors.New("endpoint group not found") } } else if rule.FromNetwork != "" { netKey := rule.TenantName + ":" + rule.FromNetwork net := contivModel.FindNetwork(netKey) if net == nil { log.Errorf("Network %s not found", netKey) return errors.New("FromNetwork not found") } } else if rule.ToNetwork != "" { netKey := rule.TenantName + ":" + rule.ToNetwork net := contivModel.FindNetwork(netKey) if net == nil { log.Errorf("Network %s not found", netKey) return errors.New("ToNetwork not found") } } policyKey := rule.TenantName + ":" + rule.PolicyName // find the policy policy := contivModel.FindPolicy(policyKey) if policy == nil { log.Errorf("Error finding policy %s", policyKey) return core.Errorf("Policy not found") } // Trigger policyDB Update err := master.PolicyAddRule(policy, rule) if err != nil { log.Errorf("Error adding rule %s to policy %s. Err: %v", rule.Key, policy.Key, err) return err } // link the rule to policy modeldb.AddLinkSet(&rule.LinkSets.Policies, policy) modeldb.AddLinkSet(&policy.LinkSets.Rules, rule) err = policy.Write() if err != nil { return err } // Update any affected app profiles syncAppProfile(policy) return nil }
// EndpointGroupUpdate updates endpoint group func (ac *APIController) EndpointGroupUpdate(endpointGroup, params *contivModel.EndpointGroup) error { log.Infof("Received EndpointGroupUpdate: %+v, params: %+v", endpointGroup, params) // if the network association was changed, reject the update. if endpointGroup.NetworkName != params.NetworkName { return core.Errorf("Cannot change network association after epg is created.") } // Only update policy attachments // Look for policy adds for _, policyName := range params.Policies { if !stringInSlice(policyName, endpointGroup.Policies) { policyKey := endpointGroup.TenantName + ":" + policyName // find the policy policy := contivModel.FindPolicy(policyKey) if policy == nil { log.Errorf("Could not find policy %s", policyName) return core.Errorf("Policy not found") } // attach policy to epg err := master.PolicyAttach(endpointGroup, policy) if err != nil && err != master.EpgPolicyExists { log.Errorf("Error attaching policy %s to epg %s", policyName, endpointGroup.Key) return err } // Setup links modeldb.AddLinkSet(&policy.LinkSets.EndpointGroups, endpointGroup) modeldb.AddLinkSet(&endpointGroup.LinkSets.Policies, policy) err = policy.Write() if err != nil { return err } } } // now look for policy removals for _, policyName := range endpointGroup.Policies { if !stringInSlice(policyName, params.Policies) { policyKey := endpointGroup.TenantName + ":" + policyName // find the policy policy := contivModel.FindPolicy(policyKey) if policy == nil { log.Errorf("Could not find policy %s", policyName) return core.Errorf("Policy not found") } // detach policy to epg err := master.PolicyDetach(endpointGroup, policy) if err != nil && err != master.EpgPolicyExists { log.Errorf("Error detaching policy %s from epg %s", policyName, endpointGroup.Key) return err } // Remove links modeldb.RemoveLinkSet(&policy.LinkSets.EndpointGroups, endpointGroup) modeldb.RemoveLinkSet(&endpointGroup.LinkSets.Policies, policy) err = policy.Write() if err != nil { return err } } } // Update the policy list endpointGroup.Policies = params.Policies // For the external contracts, we can keep the update simple. Remove // all that we have now, and update the epg with the new list. // Step 1: Cleanup existing external contracts. err := cleanupExternalContracts(endpointGroup) if err != nil { return err } // Step 2: Add contracts from the update. // Consumed contracts err = setupExternalContracts(endpointGroup, params.ExtContractsGrps) if err != nil { return err } // Update the epg itself with the new contracts groups. endpointGroup.ExtContractsGrps = params.ExtContractsGrps // if there is an associated app profiles, update that as well profKey := endpointGroup.Links.AppProfile.ObjKey profObj := contivModel.FindAppProfile(profKey) if profObj == nil { log.Warnf("EndpointGroupUpdate prof %s not found", profKey) } else { log.Infof("EndpointGroupUpdate sync prof %s", profKey) DeleteAppNw(profObj) CreateAppNw(profObj) } return nil }
// EndpointGroupCreate creates end point group func (ac *APIController) EndpointGroupCreate(endpointGroup *contivModel.EndpointGroup) error { log.Infof("Received EndpointGroupCreate: %+v", endpointGroup) // Find the tenant tenant := contivModel.FindTenant(endpointGroup.TenantName) if tenant == nil { return core.Errorf("Tenant not found") } // Find the network nwObjKey := endpointGroup.TenantName + ":" + endpointGroup.NetworkName network := contivModel.FindNetwork(nwObjKey) if network == nil { return core.Errorf("Network %s not found", endpointGroup.NetworkName) } // If there is a Network with the same name as this endpointGroup, reject. nameClash := contivModel.FindNetwork(endpointGroup.Key) if nameClash != nil { return core.Errorf("Network %s conflicts with the endpointGroup name", nameClash.NetworkName) } // create the endpoint group state err := master.CreateEndpointGroup(endpointGroup.TenantName, endpointGroup.NetworkName, endpointGroup.GroupName) if err != nil { log.Errorf("Error creating endpoing group %+v. Err: %v", endpointGroup, err) return err } // for each policy create an epg policy Instance for _, policyName := range endpointGroup.Policies { policyKey := endpointGroup.TenantName + ":" + policyName // find the policy policy := contivModel.FindPolicy(policyKey) if policy == nil { log.Errorf("Could not find policy %s", policyName) endpointGroupCleanup(endpointGroup) return core.Errorf("Policy not found") } // attach policy to epg err = master.PolicyAttach(endpointGroup, policy) if err != nil { log.Errorf("Error attaching policy %s to epg %s", policyName, endpointGroup.Key) endpointGroupCleanup(endpointGroup) return err } // establish Links modeldb.AddLinkSet(&policy.LinkSets.EndpointGroups, endpointGroup) modeldb.AddLinkSet(&endpointGroup.LinkSets.Policies, policy) // Write the policy err = policy.Write() if err != nil { endpointGroupCleanup(endpointGroup) return err } } // Setup external contracts this EPG might have. err = setupExternalContracts(endpointGroup, endpointGroup.ExtContractsGrps) if err != nil { log.Errorf("Error setting up external contracts for epg %s", endpointGroup.Key) endpointGroupCleanup(endpointGroup) return err } // Setup links modeldb.AddLink(&endpointGroup.Links.Network, network) modeldb.AddLink(&endpointGroup.Links.Tenant, tenant) modeldb.AddLinkSet(&network.LinkSets.EndpointGroups, endpointGroup) modeldb.AddLinkSet(&tenant.LinkSets.EndpointGroups, endpointGroup) // Save the tenant and network since we added the links err = network.Write() if err != nil { endpointGroupCleanup(endpointGroup) return err } err = tenant.Write() if err != nil { endpointGroupCleanup(endpointGroup) return err } return nil }