func freeNetworkResources(stateDriver core.StateDriver, nwMasterCfg *NwConfig, nwCfg *drivers.OvsCfgNetworkState, gCfg *gstate.Cfg) (err error) { tempRm, err := resources.GetStateResourceManager() if err != nil { return err } rm := core.ResourceManager(tempRm) if nwCfg.PktTagType == "vlan" { err = gCfg.FreeVLAN(rm, uint(nwCfg.PktTag)) if err != nil { return err } } else if nwCfg.PktTagType == "vxlan" { log.Infof("freeing vlan %d vxlan %d", nwCfg.PktTag, nwCfg.ExtPktTag) err = gCfg.FreeVXLAN(rm, uint(nwCfg.ExtPktTag), uint(nwCfg.PktTag)) if err != nil { return err } } if nwMasterCfg.SubnetIP == "" { log.Infof("freeing subnet %s/%s", nwCfg.SubnetIP, nwCfg.SubnetLen) err = gCfg.FreeSubnet(rm, nwCfg.SubnetIP) if err != nil { return err } } return err }
// AllocVXLAN allocates a new vxlan; ids for both the vxlan and vlan are returned. func (gc *Cfg) AllocVXLAN(reqVxlan uint) (vxlan uint, localVLAN uint, err error) { tempRm, err := resources.GetStateResourceManager() if err != nil { return 0, 0, err } ra := core.ResourceManager(tempRm) g := &Oper{} g.StateDriver = gc.StateDriver err = g.Read("") if err != nil { return 0, 0, err } if reqVxlan != 0 && reqVxlan <= g.FreeVXLANsStart { return 0, 0, errors.New("Requested vxlan is out of range") } if (reqVxlan != 0) && (reqVxlan >= g.FreeVXLANsStart) { reqVxlan = reqVxlan - g.FreeVXLANsStart } pair, err1 := ra.AllocateResourceVal("global", resources.AutoVXLANResource, reqVxlan) if err1 != nil { return 0, 0, err1 } vxlan = pair.(resources.VXLANVLANPair).VXLAN + g.FreeVXLANsStart localVLAN = pair.(resources.VXLANVLANPair).VLAN return }
func freeNetworkResources(stateDriver core.StateDriver, nwCfg *mastercfg.CfgNetworkState, gCfg *gstate.Cfg) (err error) { tempRm, err := resources.GetStateResourceManager() if err != nil { return err } rm := core.ResourceManager(tempRm) if nwCfg.PktTagType == "vlan" { err = gCfg.FreeVLAN(rm, uint(nwCfg.PktTag)) if err != nil { return err } } else if nwCfg.PktTagType == "vxlan" { log.Infof("freeing vlan %d vxlan %d", nwCfg.PktTag, nwCfg.ExtPktTag) err = gCfg.FreeVXLAN(rm, uint(nwCfg.ExtPktTag), uint(nwCfg.PktTag)) if err != nil { return err } } if nwCfg.SubnetIsAllocated { log.Infof("freeing subnet %s/%d", nwCfg.SubnetIP, nwCfg.SubnetLen) err = gCfg.FreeSubnet(rm, nwCfg.SubnetIP) if err != nil { return err } } if err := gCfg.UnassignNetwork(nwCfg.ID); err != nil { return err } return err }
// FreeVLAN releases a VLAN for a given ID. func (gc *Cfg) FreeVLAN(vlan uint) error { tempRm, err := resources.GetStateResourceManager() if err != nil { return err } ra := core.ResourceManager(tempRm) return ra.DeallocateResourceVal("global", resources.AutoVLANResource, vlan) }
// Process validates, implements, and writes the state. func (gc *Cfg) Process(res string) error { var err error tempRm, err := resources.GetStateResourceManager() if err != nil { return err } ra := core.ResourceManager(tempRm) err = gc.checkErrors(res) if err != nil { return core.Errorf("process failed on error checks %s", err) } // Only define a vlan resource if a valid range was specified if res == "vlan" { if gc.Auto.VLANs != "" { var vlanRsrcCfg *bitset.BitSet vlanRsrcCfg, err = gc.initVLANBitset(gc.Auto.VLANs) if err != nil { return err } err = ra.DefineResource("global", resources.AutoVLANResource, vlanRsrcCfg) if err != nil { return err } } } // Only define a vxlan resource if a valid range was specified var freeVXLANsStart uint if res == "vxlan" { if gc.Auto.VXLANs != "" { var vxlanRsrcCfg *resources.AutoVXLANCfgResource vxlanRsrcCfg, freeVXLANsStart, err = gc.initVXLANBitset(gc.Auto.VXLANs) if err != nil { return err } err = ra.DefineResource("global", resources.AutoVXLANResource, vxlanRsrcCfg) if err != nil { return err } } g := &Oper{FreeVXLANsStart: freeVXLANsStart} g.StateDriver = gc.StateDriver err = g.Write() if err != nil { log.Errorf("error '%s' updating global oper state %v \n", err, g) return err } } log.Debugf("updating the global config to new state %v \n", gc) return nil }
// GetVlansInUse gets the vlans that are currently in use func (gc *Cfg) GetVlansInUse() (uint, string) { tempRm, err := resources.GetStateResourceManager() if err != nil { log.Errorf("error getting resource manager: %s", err) return 0, "" } ra := core.ResourceManager(tempRm) return ra.GetResourceList("global", resources.AutoVLANResource) }
// DeleteEndpointGroup handles endpoint group deletes func DeleteEndpointGroup(epgID int) error { // Get the state driver stateDriver, err := utils.GetStateDriver() if err != nil { return err } epgCfg := &mastercfg.EndpointGroupState{} epgCfg.StateDriver = stateDriver err = epgCfg.Read(strconv.Itoa(epgID)) if err != nil { log.Errorf("EpGroup %v is not configured", epgID) return err } gCfg := gstate.Cfg{} gCfg.StateDriver = stateDriver err = gCfg.Read(epgCfg.Tenant) 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 { tempRm, rErr := resources.GetStateResourceManager() if rErr != nil { return rErr } rm := core.ResourceManager(tempRm) if epgCfg.PktTagType == "vlan" { err = gCfg.FreeVLAN(rm, uint(epgCfg.PktTag)) if err != nil { return err } log.Debugf("Freed vlan %v\n", epgCfg.PktTag) } } epgNet := epgCfg.Name + "." + epgCfg.NetworkName + "." + epgCfg.Tenant err = epgCfg.Clear() if err != nil { log.Errorf("error writing epGroup config. Error: %v", err) return err } return deleteDockNet(epgNet) }
// CreateTenant sets the tenant's state according to the passed ConfigTenant. func CreateTenant(stateDriver core.StateDriver, tenant *intent.ConfigTenant) error { gOper := &gstate.Oper{} gOper.StateDriver = stateDriver err := gOper.Read(tenant.Name) if err == nil { return err } err = validateTenantConfig(tenant) if err != nil { return err } gCfg := &gstate.Cfg{} gCfg.StateDriver = stateDriver gCfg.Version = gstate.VersionBeta1 gCfg.Tenant = tenant.Name gCfg.Deploy.DefaultNetType = tenant.DefaultNetType gCfg.Deploy.DefaultNetwork = tenant.DefaultNetwork gCfg.Auto.SubnetPool, gCfg.Auto.SubnetLen, _ = netutils.ParseCIDR(tenant.SubnetPool) gCfg.Auto.VLANs = tenant.VLANs gCfg.Auto.VXLANs = tenant.VXLANs gCfg.Auto.AllocSubnetLen = tenant.AllocSubnetLen tempRm, err := resources.GetStateResourceManager() if err != nil { return err } // setup resources err = gCfg.Process(core.ResourceManager(tempRm)) if err != nil { log.Errorf("Error updating the config %+v. Error: %s", gCfg, err) return err } // start skydns container err = startServiceContainer(tenant.Name) if err != nil { log.Errorf("Error starting service container. Err: %v", err) return err } err = gCfg.Write() if err != nil { log.Errorf("error updating tenant '%s'.Error: %s", tenant.Name, err) return err } return nil }
// AllocVLAN allocates a new VLAN resource. Returns an ID. func (gc *Cfg) AllocVLAN(reqVlan uint) (uint, error) { tempRm, err := resources.GetStateResourceManager() if err != nil { return 0, err } ra := core.ResourceManager(tempRm) vlan, err := ra.AllocateResourceVal("global", resources.AutoVLANResource, reqVlan) if err != nil { log.Errorf("alloc vlan failed: %q", err) return 0, err } return vlan.(uint), err }
// UpdateResources deletes associated resources func (gc *Cfg) UpdateResources(res string) error { log.Infof("Received update resource for res %s", res) tempRm, err := resources.GetStateResourceManager() if err != nil { return err } ra := core.ResourceManager(tempRm) err = gc.checkErrors(res) if err != nil { return core.Errorf("process failed on error checks %s", err) } if res == "vlan" { var vlanRsrcCfg *bitset.BitSet vlanRsrcCfg, err = gc.initVLANBitset(gc.Auto.VLANs) if err != nil { return err } err = ra.RedefineResource("global", resources.AutoVLANResource, vlanRsrcCfg) if err != nil { log.Errorf("Error deleting vlan resource. Err: %v", err) } } else if res == "vxlan" { var vxlanRsrcCfg *resources.AutoVXLANCfgResource vxlanRsrcCfg, err = gc.initVXLANBitset(gc.Auto.VXLANs) if err != nil { return err } err = ra.RedefineResource("global", resources.AutoVXLANResource, vxlanRsrcCfg) if err != nil { log.Errorf("Error deleting vxlan resource. Err: %v", err) } g := &Oper{FreeVXLANsStart: vxlanRsrcCfg.FreeVXLANsStart} g.StateDriver = gc.StateDriver err = g.Write() if err != nil { log.Errorf("error '%s' updating global oper state %v \n", err, g) return err } } return err }
// DeleteTenantID deletes a tenant from the state store, by ID. func DeleteTenantID(stateDriver core.StateDriver, tenantID string) error { gOper := &gstate.Oper{} gOper.StateDriver = stateDriver err := gOper.Read(tenantID) if err != nil { log.Errorf("error reading tenant info '%s'. Error: %s", tenantID, err) return err } err = stopAndRemoveServiceContainer(tenantID) if err != nil { log.Errorf("Error in stopping service container for tenant: %+v", tenantID) return err } gCfg := &gstate.Cfg{} gCfg.StateDriver = stateDriver err = gCfg.Read(tenantID) if err != nil { log.Errorf("error reading tenant config '%s'. Error: %s", tenantID, err) return err } tempRm, err := resources.GetStateResourceManager() if err == nil { err = gCfg.DeleteResources(core.ResourceManager(tempRm)) if err != nil { log.Errorf("Error deleting the config %+v. Error: %s", gCfg, err) } } // delete tenant config err = gCfg.Clear() if err != nil { log.Errorf("error deleting cfg for tenant %q: Error: %s", tenantID, err) } err = gOper.Clear() if err != nil { log.Errorf("error deleting oper for tenant %q: Error: %s", tenantID, err) } return err }
// FreeVXLAN returns a VXLAN id to the pool. func (gc *Cfg) FreeVXLAN(vxlan uint, localVLAN uint) error { tempRm, err := resources.GetStateResourceManager() if err != nil { return err } ra := core.ResourceManager(tempRm) g := &Oper{} g.StateDriver = gc.StateDriver err = g.Read("") if err != nil { return nil } return ra.DeallocateResourceVal("global", resources.AutoVXLANResource, resources.VXLANVLANPair{ VXLAN: vxlan - g.FreeVXLANsStart, VLAN: localVLAN}) }
// DeleteResources deletes associated resources func (gc *Cfg) DeleteResources() error { tempRm, err := resources.GetStateResourceManager() if err != nil { return err } ra := core.ResourceManager(tempRm) err = ra.UndefineResource("global", resources.AutoVLANResource) if err != nil { log.Errorf("Error deleting vlan resource. Err: %v", err) } err = ra.UndefineResource("global", resources.AutoVXLANResource) if err != nil { log.Errorf("Error deleting vxlan resource. Err: %v", err) } return err }
// CreateNetwork creates a network from intent func CreateNetwork(network intent.ConfigNetwork, stateDriver core.StateDriver, tenantName string) error { var extPktTag, pktTag uint 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 } tempRm, err := resources.GetStateResourceManager() if err != nil { return err } rm := core.ResourceManager(tempRm) // Create network state nwCfg := &drivers.OvsCfgNetworkState{} nwCfg.StateDriver = stateDriver if nwCfg.Read(network.Name) == nil { // TODO: check if parameters changed and apply an update if needed return nil } // construct and update network state nwMasterCfg := &NwConfig{} nwMasterCfg.StateDriver = stateDriver nwMasterCfg.Tenant = tenantName nwMasterCfg.ID = network.Name nwMasterCfg.PktTagType = network.PktTagType nwMasterCfg.PktTag = network.PktTag nwMasterCfg.SubnetIP, nwMasterCfg.SubnetLen, _ = netutils.ParseCIDR(network.SubnetCIDR) nwMasterCfg.DefaultGw = network.DefaultGw nwCfg = &drivers.OvsCfgNetworkState{ Tenant: nwMasterCfg.Tenant, PktTagType: nwMasterCfg.PktTagType, SubnetIP: nwMasterCfg.SubnetIP, SubnetLen: nwMasterCfg.SubnetLen, } nwCfg.StateDriver = stateDriver nwCfg.ID = nwMasterCfg.ID if nwMasterCfg.PktTagType == "" { nwCfg.PktTagType = gCfg.Deploy.DefaultNetType } if nwMasterCfg.PktTag == "" { if nwCfg.PktTagType == "vlan" { pktTag, err = gCfg.AllocVLAN(rm) if err != nil { return err } } else if nwCfg.PktTagType == "vxlan" { extPktTag, pktTag, err = gCfg.AllocVXLAN(rm) if err != nil { return err } } nwCfg.ExtPktTag = int(extPktTag) nwCfg.PktTag = int(pktTag) } else if nwMasterCfg.PktTagType == "vxlan" { // XXX: take local vlan as config, instead of allocating it // independently. Return erro for now, if user tries this config return core.Errorf("Not handled. Need to introduce local-vlan config") } else if nwMasterCfg.PktTagType == "vlan" { nwCfg.PktTag, _ = strconv.Atoi(nwMasterCfg.PktTag) // XXX: do configuration check, to make sure it is allowed } if nwCfg.SubnetIP == "" { nwCfg.SubnetLen = gCfg.Auto.AllocSubnetLen nwCfg.SubnetIP, err = gCfg.AllocSubnet(rm) if err != nil { return err } } nwCfg.DefaultGw = network.DefaultGw if nwCfg.DefaultGw == "" { // TBD: allocate per global policy } netutils.InitSubnetBitset(&nwCfg.IPAllocMap, nwCfg.SubnetLen) err = nwCfg.Write() if err != nil { return err } err = nwMasterCfg.Write() if err != nil { log.Errorf("error writing nw config. Error: %s", err) return err } if nwCfg.PktTagType == "vxlan" { readHost := &HostConfig{} readHost.StateDriver = stateDriver hostCfgs, err := readHost.ReadAll() if err != nil { if !strings.Contains(err.Error(), "Key not found") { log.Errorf("error reading hosts during net add. Error: %s", err) } } for _, hostCfg := range hostCfgs { host := hostCfg.(*HostConfig) err = createVtep(stateDriver, host, nwCfg.ID) if err != nil { log.Errorf("error creating vtep. Error: %s", err) } } } return nil }
// CreateEndpointGroup handles creation of endpoint group func CreateEndpointGroup(tenantName, networkName, groupName string, epgID int) error { // 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" { subnetCIDR := fmt.Sprintf("%s/%d", nwCfg.SubnetIP, nwCfg.SubnetLen) // Create each EPG as a docker network err = createDockNet(tenantName, networkName, groupName, subnetCIDR, nwCfg.Gateway) if err != nil { log.Errorf("Error creating docker network for group %s.%s. Err: %v", networkName, groupName, err) return err } } // Get resource manager tempRm, err := resources.GetStateResourceManager() if err != nil { return err } rm := core.ResourceManager(tempRm) // Create epGroup state epgCfg := &mastercfg.EndpointGroupState{ Name: groupName, Tenant: tenantName, NetworkName: networkName, PktTagType: nwCfg.PktTagType, PktTag: nwCfg.PktTag, ExtPktTag: nwCfg.ExtPktTag, } epgCfg.StateDriver = stateDriver epgCfg.ID = strconv.Itoa(epgID) 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(rm) 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 }
// CreateNetwork creates a network from intent func CreateNetwork(network intent.ConfigNetwork, stateDriver core.StateDriver, tenantName string) error { var extPktTag, pktTag uint 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 } tempRm, err := resources.GetStateResourceManager() if err != nil { return err } rm := core.ResourceManager(tempRm) // Create network state networkID := network.Name + "." + tenantName nwCfg := &mastercfg.CfgNetworkState{} nwCfg.StateDriver = stateDriver if nwCfg.Read(networkID) == nil { // TODO: check if parameters changed and apply an update if needed return nil } subnetIP, subnetLen, _ := netutils.ParseCIDR(network.SubnetCIDR) // construct and update network state nwCfg = &mastercfg.CfgNetworkState{ Tenant: tenantName, NetworkName: network.Name, PktTagType: network.PktTagType, SubnetIP: subnetIP, SubnetLen: subnetLen, Gateway: network.Gateway, } nwCfg.ID = networkID nwCfg.StateDriver = stateDriver if network.PktTagType == "" { nwCfg.PktTagType = gCfg.Deploy.DefaultNetType } if network.PktTag == 0 { if nwCfg.PktTagType == "vlan" { pktTag, err = gCfg.AllocVLAN(rm) if err != nil { return err } } else if nwCfg.PktTagType == "vxlan" { extPktTag, pktTag, err = gCfg.AllocVXLAN(rm) if err != nil { return err } } nwCfg.ExtPktTag = int(extPktTag) nwCfg.PktTag = int(pktTag) } else if network.PktTagType == "vxlan" { if !isTagInRange(uint(network.PktTag), "vxlan", gCfg.Auto.VXLANs, stateDriver, tenantName) { return fmt.Errorf("vxlan %d does not adhere to tenant's vxlan range %s", network.PktTag, gCfg.Auto.VXLANs) } nwCfg.ExtPktTag = network.PktTag nwCfg.PktTag = network.PktTag } else if network.PktTagType == "vlan" { if !isTagInRange(uint(network.PktTag), "vlan", gCfg.Auto.VLANs, stateDriver, tenantName) { return fmt.Errorf("vlan %d does not adhere to tenant's vlan range %s", network.PktTag, gCfg.Auto.VLANs) } nwCfg.PktTag = network.PktTag } if nwCfg.SubnetIP == "" { nwCfg.SubnetLen = gCfg.Auto.AllocSubnetLen nwCfg.SubnetIP, err = gCfg.AllocSubnet(rm) if err != nil { return err } nwCfg.SubnetIsAllocated = true } defaultNwName, err := gCfg.AssignDefaultNetwork(network.Name) if err != nil { log.Errorf("error assigning the default network. Error: %s", err) return err } if network.Name == defaultNwName { // For auto derived subnets assign gateway ip be the last valid unicast ip the subnet if nwCfg.Gateway == "" && nwCfg.SubnetIsAllocated { var ipAddrValue uint ipAddrValue = (1 << (32 - nwCfg.SubnetLen)) - 2 nwCfg.Gateway, err = netutils.GetSubnetIP(nwCfg.SubnetIP, nwCfg.SubnetLen, 32, ipAddrValue) if err != nil { return err } nwCfg.IPAllocMap.Set(ipAddrValue) } } netutils.InitSubnetBitset(&nwCfg.IPAllocMap, nwCfg.SubnetLen) err = nwCfg.Write() if err != nil { return err } if GetClusterMode() == "docker" { // Create the network in docker subnetCIDR := fmt.Sprintf("%s/%d", nwCfg.SubnetIP, nwCfg.SubnetLen) err = createDockNet(tenantName, network.Name, "", subnetCIDR, nwCfg.Gateway) if err != nil { log.Errorf("Error creating network %s in docker. Err: %v", nwCfg.ID, err) return err } // Attach service container endpoint to the network err = attachServiceContainer(tenantName, network.Name, stateDriver) if err != nil { log.Errorf("Error attaching service container to network: %s. Err: %v", networkID, err) return err } } return nil }