func validateNetworkConfig(tenant *intent.ConfigTenant) error { var err error if tenant.Name == "" { return core.Errorf("null tenant name") } for _, network := range tenant.Networks { if network.Name == "" { core.Errorf("null network name") } err = checkPktTagType(network.PktTagType) if err != nil { return err } if network.SubnetCIDR != "" { _, _, err = netutils.ParseCIDR(network.SubnetCIDR) if err != nil { return err } } if network.Gateway != "" { if net.ParseIP(network.Gateway) == nil { return core.Errorf("invalid IP") } } } return err }
// 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 err = gCfg.Write() if err != nil { log.Errorf("error updating tenant '%s'.Error: %s", tenant.Name, err) return err } tempRm, err := resources.GetStateResourceManager() if err != nil { return err } err = gCfg.Process(core.ResourceManager(tempRm)) if err != nil { log.Errorf("Error updating the config %+v. Error: %s", gCfg, err) return err } err = startServiceContainer(tenant.Name) if err != nil { log.Errorf("Error starting service container. Err: %v", err) 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 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 }
func validateOpts(opts *cliOpts) error { var err error if flagSet.NArg() != 1 || opts.help { usage() return nil } if opts.debug { log.SetLevel(log.DebugLevel) } if opts.oper.Get() == "" { log.Fatalf("An operation must be specified") } if opts.construct.Get() == "" { log.Fatalf("A construct must be specified") } if opts.pktTagType != "vxlan" && opts.pktTagType != "vlan" { log.Fatalf("error '%s' packet tag type not supported", opts.pktTagType) } // global create params validation if opts.oper.Get() == cliOperCreate && opts.construct.Get() == cliConstructGlobal { if opts.vlans != "" { _, err = netutils.ParseTagRanges(opts.vlans, "vlan") if err != nil { log.Fatalf("error '%s' parsing vlan range '%s' \n", err, opts.vlans) } } if opts.vxlans != "" { _, err = netutils.ParseTagRanges(opts.vxlans, "vxlan") if err != nil { log.Fatalf("error '%s' parsing vxlan range '%s' \n", err, opts.vxlans) } } } if opts.pktTag == "auto" { if opts.oper.Get() == cliOperCreate && opts.construct.Get() == cliConstructNetwork { log.Infof(" auto allocating network subnet from global pool") } } else if opts.pktTag != "" { _, err = strconv.Atoi(opts.pktTag) if err != nil { log.Fatalf("Error convertinng tag %s to integer \n", opts.pktTag) } } // network create params validation if opts.oper.Get() == cliOperCreate && opts.construct.Get() == cliConstructNetwork { } if opts.homingHost == "" { opts.homingHost, err = os.Hostname() if err != nil { log.Fatalf("error obtaining the hostname, error %s \n", err) } } // default gw and mask parsing if opts.subnetCidr == "" { opts.subnetLen = 0 opts.subnetIP = "auto" } else { _, _, err = net.ParseCIDR(opts.subnetCidr) if err != nil { log.Fatalf("error '%s' parsing cidr ip %s \n", err, opts.subnetCidr) } opts.subnetIP, opts.subnetLen, err = netutils.ParseCIDR(opts.subnetCidr) if err != nil { logFatalSubnetAndMaskFormatError() } } if opts.vtepIP != "" && net.ParseIP(opts.vtepIP) == nil { log.Fatalf("error '%s' parsing vtep ip %s \n", err, opts.vtepIP) } // endpoint parameters validation if opts.oper.Get() == cliOperCreate && opts.construct.Get() == cliConstructEndpoint && opts.vtepIP != "" && (opts.netID == "" || opts.ipAddr == "") { if opts.ipAddr == "auto" { log.Debugf("doing auto ip address assignemt for the ep... \n") } else { log.Fatalf("Endpoint creation requires a valid net-id, vlan tag, " + "and ip address") } } // attach detach parameters validation if (opts.oper.Get() == cliOperAttach || opts.oper.Get() == cliOperDetach) && opts.construct.Get() == cliConstructEndpoint && opts.contName == "" { log.Fatalf("A valid container-id is needed to attach/detach a container to an ep") } 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 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" { nwCfg.ExtPktTag = network.PktTag nwCfg.PktTag = network.PktTag } else if network.PktTagType == "vlan" { nwCfg.PktTag = network.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.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 } // Create the network in docker subnetCIDR := fmt.Sprintf("%s/%d", nwCfg.SubnetIP, nwCfg.SubnetLen) err = createDockNet(nwCfg.ID, 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, networkID, stateDriver) if err != nil { log.Errorf("Error attaching service container to network: %s. Err: %v", networkID, err) } return nil }