예제 #1
0
// Check that container is created with a 'netid' label. This helps us map the
// container to a network. This label could be put by one of docker clients (cli,
// compose etc)
func (adptr *PwrStrpAdptr) handlePreCreate(req *powerStripRequest) (*powerStripResponse, error) {
	//structure of interesting fields in the create request
	type DockerCreateRequest struct {
		Labels map[string]string `json:"Labels"`
	}

	dockerReq := &DockerCreateRequest{}
	err := json.Unmarshal([]byte(req.ClientRequest.Body), dockerReq)
	if err != nil {
		return nil, err
	}

	if netID, ok := dockerReq.Labels["netid"]; !ok || netID == "" {
		return nil, core.Errorf("Container doesn't contain a valid 'netid' label. Labels: %+v Body: %q",
			dockerReq, req.ClientRequest.Body)
	} else if tenantID, ok := dockerReq.Labels["tenantid"]; !ok || tenantID == "" {
		return nil, core.Errorf("Container doesn't contain a valid 'tenantid' label. Labels: %+v Body: %q",
			dockerReq, req.ClientRequest.Body)
	} else {
		// XXX: record the outstanding network for which we are yet to receive a
		// corresponding container-id (in server response). This simplifies things
		// by assuming that there can't be two outstanding request. Need to revisit
		// and handle this correctly.
		adptr.outstandingNet = containerNet{tenantID: tenantID, netID: netID}
	}

	return makeClientRequest(req), nil
}
예제 #2
0
// GetIPNumber obtains the host id from the host IP. SEe `GetSubnetIP` for more information.
func GetIPNumber(subnetIP string, subnetLen uint, allocSubnetLen uint, hostIP string) (uint, error) {
	if subnetLen > 32 || subnetLen < 8 {
		return 0, core.Errorf("subnet length %d not supported", subnetLen)
	}
	if subnetLen > allocSubnetLen {
		return 0, core.Errorf("subnet length %d is bigger than subnet alloc len %d",
			subnetLen, allocSubnetLen)
	}

	hostIPUint32, err := ipv4ToUint32(hostIP)
	if err != nil {
		return 0, core.Errorf("unable to convert hostIP %s to uint32", hostIP)
	}

	subnetIPUint32, err := ipv4ToUint32(subnetIP)
	if err != nil {
		return 0, core.Errorf("unable to convert subnetIP %s to uint32", subnetIP)
	}
	hostID := uint((hostIPUint32 - subnetIPUint32) >> (32 - allocSubnetLen))

	maxHosts := uint(1 << (allocSubnetLen - subnetLen))
	if hostID >= maxHosts {
		return 0, core.Errorf("hostIP %s is exceeding beyond subnet %s/%d, hostID %d",
			hostIP, subnetIP, subnetLen, hostID)
	}

	return uint(hostID), 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
}
예제 #4
0
// GetIPv6HostID obtains the host id from the host IP. SEe `GetSubnetIP` for more information.
func GetIPv6HostID(subnetAddr string, subnetLen uint, hostAddr string) (string, error) {
	if subnetLen > 128 || subnetLen < 16 {
		return "", core.Errorf("subnet length %d not supported", subnetLen)
	}
	// Initialize hostID
	hostID := net.IPv6zero

	var offset uint

	// get the overlapping byte
	offset = subnetLen / 8
	subnetIP := net.ParseIP(subnetAddr)
	if subnetIP == nil {
		return "", core.Errorf("Invalid subnetAddr %s ", subnetAddr)
	}
	s := uint8(subnetIP[offset])
	hostIP := net.ParseIP(hostAddr)
	if hostIP == nil {
		return "", core.Errorf("Invalid hostAddr %s ", hostAddr)
	}
	h := uint8(hostIP[offset])
	hostID[offset] = byte(h - s)

	// Copy the rest of the bytes
	for i := (offset + 1); i < 16; i++ {
		hostID[i] = hostIP[i]
		offset++
	}
	return hostID.String(), nil
}
예제 #5
0
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
}
예제 #6
0
// GetSubnetIPv6 given a subnet IP and host identifier, calculates an IPv6 address
// within the subnet for use.
func GetSubnetIPv6(subnetAddr string, subnetLen uint, hostID string) (string, error) {
	if subnetAddr == "" {
		return "", core.Errorf("null subnet")
	}

	if subnetLen > 128 || subnetLen < 16 {
		return "", core.Errorf("subnet length %d not supported", subnetLen)
	}

	subnetIP := net.ParseIP(subnetAddr)
	hostidIP := net.ParseIP(hostID)
	hostIP := net.IPv6zero

	var offset int
	for offset = 0; offset < int(subnetLen/8); offset++ {
		hostIP[offset] = subnetIP[offset]
	}
	// copy the overlapping byte in subnetIP and hostID
	if subnetLen%8 != 0 && subnetIP[offset] != 0 {
		if hostidIP[offset]&subnetIP[offset] != 0 {
			return "", core.Errorf("host id %s exceeds subnet %s capacity ",
				hostID, subnetAddr)
		}
		hostIP[offset] = hostidIP[offset] | subnetIP[offset]
		offset++
	}

	for ; offset < len(hostidIP); offset++ {
		hostIP[offset] = hostidIP[offset]
	}
	return hostIP.String(), nil
}
예제 #7
0
// GetSubnetIP given a subnet IP and host identifier, calculates an IP within
// the subnet for use.
func GetSubnetIP(subnetIP string, subnetLen uint, allocSubnetLen, hostID uint) (string, error) {
	if subnetIP == "" {
		return "", core.Errorf("null subnet")
	}

	if subnetLen > 32 || subnetLen < 8 {
		return "", core.Errorf("subnet length %d not supported", subnetLen)
	}
	if subnetLen > allocSubnetLen {
		return "", core.Errorf("subnet length %d is bigger than subnet alloc len %d",
			subnetLen, allocSubnetLen)
	}

	maxHosts := uint(1 << (allocSubnetLen - subnetLen))
	if hostID >= maxHosts {
		return "", core.Errorf("host id %d is beyond subnet's capacity %d",
			hostID, maxHosts)
	}

	hostIPUint32, err := ipv4ToUint32(subnetIP)
	if err != nil {
		return "", core.Errorf("unable to convert subnet %s to uint32", subnetIP)
	}
	hostIPUint32 += uint32(hostID << (32 - allocSubnetLen))
	return ipv4Uint32ToString(hostIPUint32)
}
예제 #8
0
func validateEndpointConfig(stateDriver core.StateDriver, 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")
		}

		for _, ep := range network.Endpoints {
			if ep.Container == "" {
				return core.Errorf("invalid container name for the endpoint")
			}
			if ep.IPAddress != "" {
				if network.SubnetCIDR != "" {
					log.Errorf("found ep with ip for auto-allocated net")
					return core.Errorf("found ep with ip for auto-allocated net")
				}
				if net.ParseIP(ep.IPAddress) == nil {
					return core.Errorf("invalid ep IP")
				}
			}
		}
	}

	return err
}
예제 #9
0
func (d *OvsdbDriver) performOvsdbOps(ops []libovsdb.Operation) error {
	reply, _ := d.ovs.Transact(ovsDataBase, ops...)

	if len(reply) < len(ops) {
		return core.Errorf("Unexpected number of replies. Expected: %d, Recvd: %d",
			len(ops), len(reply))
	}
	ok := true
	errors := []string{}
	for i, o := range reply {
		if o.Error != "" && i < len(ops) {
			errors = append(errors, fmt.Sprintf("%s(%s)", o.Error, o.Details))
			ok = false
		} else if o.Error != "" {
			errors = append(errors, fmt.Sprintf("%s(%s)", o.Error, o.Details))
			ok = false
		}
	}

	if ok {
		return nil
	}

	log.Errorf("OVS operation failed for op: %+v: Errors: %v", ops, errors)

	return core.Errorf("ovs operation failed. Error(s): %v", errors)
}
예제 #10
0
// Init the state from configuration.
func (r *AutoSubnetCfgResource) Init(rsrcCfg interface{}) error {
	cfg, ok := rsrcCfg.(*AutoSubnetCfgResource)
	if !ok {
		return core.Errorf("Invalid type for subnet resource config")
	}
	r.SubnetPool = cfg.SubnetPool
	r.SubnetPoolLen = cfg.SubnetPoolLen
	r.AllocSubnetLen = cfg.AllocSubnetLen

	if cfg.AllocSubnetLen < cfg.SubnetPoolLen {
		return core.Errorf("AllocSubnetLen should be greater than or equal to SubnetPoolLen")
	}

	err := r.Write()
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			r.Clear()
		}
	}()

	allocSubnetSize := r.AllocSubnetLen - r.SubnetPoolLen
	oper := &AutoSubnetOperResource{FreeSubnets: netutils.CreateBitset(allocSubnetSize).Complement()}
	oper.StateDriver = r.StateDriver
	oper.ID = r.ID
	err = oper.Write()
	if err != nil {
		return err
	}

	return nil
}
예제 #11
0
// ParseTagRanges takes a string such as 12-24,48-64 and turns it into a series
// of TagRange.
func ParseTagRanges(ranges string, tagType string) ([]TagRange, error) {
	var err error

	if ranges == "" {
		return []TagRange{{0, 0}}, nil
	}

	if tagType != "vlan" && tagType != "vxlan" {
		return nil, core.Errorf("invalid tag type %s", tagType)
	}
	rangesStr := strings.Split(ranges, ",")

	if len(rangesStr) > 1 && tagType == "vxlan" {
		return nil, core.Errorf("do not support more than 2 vxlan tag ranges")
	}

	tagRanges := make([]TagRange, len(rangesStr), len(rangesStr))
	for idx, oneRangeStr := range rangesStr {
		oneRangeStr = strings.Trim(oneRangeStr, " ")
		tagNums := strings.Split(oneRangeStr, "-")
		if len(tagNums) > 2 {
			return nil, core.Errorf("invalid tags %s, correct '10-50,70-100'",
				oneRangeStr)
		}
		tagRanges[idx].Min, err = strconv.Atoi(tagNums[0])
		if err != nil {
			return nil, core.Errorf("invalid integer %d conversion error '%s'",
				tagRanges[idx].Min, err)
		}
		tagRanges[idx].Max, err = strconv.Atoi(tagNums[1])
		if err != nil {
			return nil, core.Errorf("invalid integer %d conversion error '%s'",
				tagRanges[idx].Max, err)
		}

		if tagRanges[idx].Min > tagRanges[idx].Max {
			return nil, core.Errorf("invalid range %s, min is greater than max",
				oneRangeStr)
		}
		if tagRanges[idx].Min < 1 {
			return nil, core.Errorf("invalid range %s, values less than 1",
				oneRangeStr)
		}
		if tagType == "vlan" && tagRanges[idx].Max > 4095 {
			return nil, core.Errorf("invalid range %s, vlan values exceed 4095 max allowed",
				oneRangeStr)
		}
		if tagType == "vxlan" && tagRanges[idx].Max > 65535 {
			return nil, core.Errorf("invalid range %s, vlan values exceed 65535 max allowed",
				oneRangeStr)
		}
		if tagType == "vxlan" &&
			(tagRanges[idx].Max-tagRanges[idx].Min > 16000) {
			return nil, core.Errorf("does not allow vxlan range to exceed 16000 range %s",
				oneRangeStr)
		}
	}

	return tagRanges, nil
}
예제 #12
0
func (gc *Cfg) checkErrors() error {
	var err error

	if net.ParseIP(gc.Auto.SubnetPool) == nil {
		return core.Errorf("invalid ip address pool %s", gc.Auto.SubnetPool)
	}

	_, err = netutils.ParseTagRanges(gc.Auto.VLANs, "vlan")
	if err != nil {
		return err
	}

	_, err = netutils.ParseTagRanges(gc.Auto.VXLANs, "vxlan")
	if err != nil {
		return err
	}

	if gc.Deploy.DefaultNetType != "vlan" &&
		gc.Deploy.DefaultNetType != "vxlan" {
		return core.Errorf("unsupported net type %s", gc.Deploy.DefaultNetType)
	}

	if gc.Auto.SubnetLen > gc.Auto.AllocSubnetLen {
		return core.Errorf("subnet size %d is smaller than subnets (%d) to be allocated from it",
			gc.Auto.SubnetLen, gc.Auto.AllocSubnetLen)
	}
	return err
}
예제 #13
0
// Allocate allocates a new resource.
func (r *AutoVXLANCfgResource) Allocate() (interface{}, error) {
	oper := &AutoVXLANOperResource{}
	oper.StateDriver = r.StateDriver
	err := oper.Read(r.ID)
	if err != nil {
		return nil, err
	}

	vxlan, ok := oper.FreeVXLANs.NextSet(0)
	if !ok {
		return nil, core.Errorf("no vxlans available.")
	}

	vlan, ok := oper.FreeLocalVLANs.NextSet(0)
	if !ok {
		return nil, core.Errorf("no local vlans available.")
	}

	oper.FreeVXLANs.Clear(vxlan)
	oper.FreeLocalVLANs.Clear(vlan)

	err = oper.Write()
	if err != nil {
		return nil, err
	}
	return VXLANVLANPair{VXLAN: vxlan, VLAN: vlan}, nil
}
예제 #14
0
// 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
}
예제 #15
0
// VolumeCreate creates a volume
func (ac *APIController) VolumeCreate(volume *contivModel.Volume) error {
	log.Infof("Received VolumeCreate: %+v", volume)

	// Make sure tenant exists
	if volume.TenantName == "" {
		return core.Errorf("Invalid tenant name")
	}

	tenant := contivModel.FindTenant(volume.TenantName)
	if tenant == nil {
		return core.Errorf("Tenant not found")
	}

	// Setup links
	modeldb.AddLink(&volume.Links.Tenant, tenant)
	modeldb.AddLinkSet(&tenant.LinkSets.Volumes, volume)

	// Save the tenant too since we added the links
	err := tenant.Write()
	if err != nil {
		return err
	}

	return nil
}
예제 #16
0
// 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)

	// setup links with volumes
	for _, volumeName := range inst.Volumes {
		// find the volume
		volume := contivModel.FindVolume(inst.TenantName + ":" + volumeName)
		if volume == nil {
			log.Errorf("Could not find colume %s for service: %s", volumeName, inst.Key)
			return core.Errorf("Could not find the volume")
		}

		// add Links
		modeldb.AddLinkSet(&inst.LinkSets.Volumes, volume)
		modeldb.AddLinkSet(&volume.LinkSets.ServiceInstances, inst)
	}

	return nil
}
예제 #17
0
파일: ovsdriver.go 프로젝트: vvb/netplugin
// 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
}
예제 #18
0
// 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
}
예제 #19
0
func validateHostConfig(host *intent.ConfigHost) error {
	if host.Name == "" {
		return core.Errorf("null host name")
	}
	if host.VtepIP == "" && host.Intf == "" {
		return core.Errorf("either vtep or intf needed for the host")
	}

	return nil
}
예제 #20
0
// 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
}
예제 #21
0
// GetNextIPv6HostID returns the next available hostId in the AllocMap
func GetNextIPv6HostID(hostID, subnetAddr string, subnetLen uint, IPv6AllocMap map[string]bool) (string, error) {
	if hostID == "" {
		hostID = "::"
	}
	if subnetLen == 0 {
		return "", core.Errorf("subnet length %d is invalid", subnetLen)
	}

	hostidIP := net.ParseIP(hostID)

	// start with the carryOver 1 to get the next hostID
	var carryOver = 1
	var allocd = true

	for allocd == true {
		// Add 1 to hostID
		for i := len(hostidIP) - 1; i >= 0; i-- {
			var temp int
			temp = int(hostidIP[i]) + carryOver
			if temp > int(0xFF) {
				hostidIP[i] = 0
				carryOver = 1
			} else {
				hostidIP[i] = uint8(temp)
				carryOver = 0
				break
			}
		}
		// Check if this hostID is already allocated
		if _, allocd = IPv6AllocMap[hostidIP.String()]; allocd == true {
			// Already allocated find the next hostID
			carryOver = 1
		} else {
			// allocd == false. check if we reached MaxHosts
			offset := (subnetLen - 1) / 8
			masklen := subnetLen % 8
			mask := ((1 << masklen) - 1) << (8 - masklen)
			if (hostidIP[offset] & byte(mask)) != 0 {
				// if hostID is outside subnet range,
				//	check if we have reached MaxHosts
				maxHosts := math.Pow(2, float64(128-subnetLen)) - 1
				if float64(len(IPv6AllocMap)) < maxHosts {
					hostID = "::"
					hostidIP = net.ParseIP(hostID)
					carryOver = 1
					allocd = true // continue the loop
				} else {
					return "", core.Errorf("Reached MaxHosts (%v). Cannot allocate more hosts", maxHosts)
				}
			}
		}
	}
	return hostidIP.String(), nil
}
예제 #22
0
//ServiceLBCreate creates service object
func (ac *APIController) ServiceLBCreate(serviceCfg *contivModel.ServiceLB) error {

	log.Infof("Received Service Load Balancer create: %+v", serviceCfg)

	if serviceCfg.ServiceName == "" {
		return core.Errorf("Invalid service name")
	}
	if serviceCfg.TenantName == "" {
		serviceCfg.TenantName = "default"
	}

	if len(serviceCfg.Selectors) == 0 {
		return core.Errorf("Invalid selector options")
	}

	if !validatePorts(serviceCfg.Ports) {
		return core.Errorf("Invalid Port maping . Port format is - Port:TargetPort:Protocol")
	}

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

	// Build service config
	serviceIntentCfg := intent.ConfigServiceLB{
		ServiceName: serviceCfg.ServiceName,
		Tenant:      serviceCfg.TenantName,
		Network:     serviceCfg.NetworkName,
		IPAddress:   serviceCfg.IpAddress,
	}
	serviceIntentCfg.Ports = append(serviceIntentCfg.Ports, serviceCfg.Ports...)

	serviceIntentCfg.Selectors = make(map[string]string)

	for _, selector := range serviceCfg.Selectors {
		if validateSelectors(selector) {
			key := strings.Split(selector, "=")[0]
			value := strings.Split(selector, "=")[1]
			serviceIntentCfg.Selectors[key] = value
		} else {
			return core.Errorf("Invalid selector %s. selector format is key1=value1", selector)
		}
	}
	// Add the service object
	err = master.CreateServiceLB(stateDriver, &serviceIntentCfg)
	if err != nil {
		log.Errorf("Error creating service  {%+v}. Err: %v", serviceIntentCfg.ServiceName, err)
		return err
	}
	return nil

}
예제 #23
0
func validateEpBindings(epBindings *[]intent.ConfigEP) error {
	for _, ep := range *epBindings {
		if ep.Host == "" {
			return core.Errorf("invalid host name for the endpoint")
		}
		if ep.Container == "" {
			return core.Errorf("invalid container name for the endpoint")
		}
	}

	return nil
}
예제 #24
0
// 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
	}

	// 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
}
예제 #25
0
// Setup brings up a vagrant testbed
func (v *Vagrant) Setup(env string, numNodes int) error {
	vCmd := &VagrantCommand{ContivNodes: numNodes, ContivEnv: env}
	output, err := vCmd.RunWithOutput("up")
	if err != nil {
		log.Errorf("Vagrant up failed. Error: %s Output: \n%s\n",
			err, output)
		return err
	}
	v.expectedNodes = numNodes
	defer func() {
		if err != nil {
			v.Teardown()
		}
	}()

	output, err = vCmd.RunWithOutput("status")
	if err != nil {
		log.Errorf("Vagrant status failed. Error: %s Output: \n%s\n",
			err, output)
		return err
	}

	// now some hardwork of finding the names of the running nodes from status output
	re, err := regexp.Compile("[a-zA-Z0-9_\\- ]*running \\(virtualbox\\)")
	if err != nil {
		return err
	}
	nodeNamesBytes := re.FindAll(output, -1)
	if nodeNamesBytes == nil {
		err = core.Errorf("No running nodes found in vagrant status output: \n%s\n",
			output)
		return err
	}
	nodeNames := []string{}
	for _, nodeNameByte := range nodeNamesBytes {
		nodeName := strings.Fields(string(nodeNameByte))[0]
		nodeNames = append(nodeNames, nodeName)
	}
	if len(nodeNames) != numNodes {
		err = core.Errorf("Number of running node(s) (%d) is not equal to number of expected node(s) (%d) in vagrant status output: \n%s\n",
			len(nodeNames), numNodes, output)
		return err
	}

	// got the names, now fill up the vagrant-nodes structure
	for i, nodeName := range nodeNames {
		log.Infof("Adding node: %q", nodeName)
		node := TestbedNode(VagrantNode{Name: nodeName, NodeNum: i + 1})
		v.nodes = append(v.nodes, node)
	}

	return nil
}
예제 #26
0
// ParseCIDR parses a CIDR string into a gateway IP and length.
func ParseCIDR(cidrStr string) (string, uint, error) {
	strs := strings.Split(cidrStr, "/")
	if len(strs) != 2 {
		return "", 0, core.Errorf("invalid cidr format")
	}

	subnetStr := strs[0]
	subnetLen, err := strconv.Atoi(strs[1])
	if (IsIPv6(subnetStr) && subnetLen > 128) || err != nil || (!IsIPv6(subnetStr) && subnetLen > 32) {
		return "", 0, core.Errorf("invalid mask in gateway/mask specification ")
	}

	return subnetStr, uint(subnetLen), nil
}
예제 #27
0
// Init the driver with a core.Config.
func (d *EtcdStateDriver) Init(config *core.Config) error {
	if config == nil {
		return core.Errorf("Invalid arguments. cfg: %v", config)
	}

	cfg, ok := config.V.(*EtcdStateDriverConfig)

	if !ok {
		return core.Errorf("Invalid config type passed!")
	}

	d.Client = etcd.NewClient(cfg.Etcd.Machines)

	return nil
}
예제 #28
0
// ValidateNetworkRangeParams verifies the network range format
func ValidateNetworkRangeParams(ipRange string, subnetLen uint) error {
	rangeMin, _ := ipv4ToUint32(getFirstAddrInRange(ipRange))
	rangeMax, _ := ipv4ToUint32(getLastAddrInRange(ipRange, subnetLen))
	firstAddr, _ := ipv4ToUint32(GetSubnetAddr(ipRange, subnetLen))
	lastAddr, _ := ipv4ToUint32(getLastAddrInSubnet(ipRange, subnetLen))

	if rangeMin < firstAddr || rangeMax > lastAddr || rangeMin > rangeMax {
		return core.Errorf("Network subnet format not valid")
	}

	if subnetLen > 32 || subnetLen < 8 {
		return core.Errorf("subnet length %d not supported", subnetLen)
	}
	return nil
}
예제 #29
0
// 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")
	}

	// 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
	}

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

	// Build networ config
	networkCfg := intent.ConfigNetwork{
		Name:       network.NetworkName,
		PktTagType: network.Encap,
		PktTag:     "",
		SubnetCIDR: network.Subnet,
		DefaultGw:  network.DefaultGw,
	}

	// 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
	}

	return nil
}
예제 #30
0
// Init the resource.
func (r *AutoVXLANCfgResource) Init(rsrcCfg interface{}) error {
	cfg, ok := rsrcCfg.(*AutoVXLANCfgResource)
	if !ok {
		return core.Errorf("Invalid vxlan resource config.")
	}
	r.VXLANs = cfg.VXLANs
	r.LocalVLANs = cfg.LocalVLANs
	err := r.Write()
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			r.Clear()
		}
	}()

	oper := &AutoVXLANOperResource{FreeVXLANs: r.VXLANs, FreeLocalVLANs: r.LocalVLANs}
	oper.StateDriver = r.StateDriver
	oper.ID = r.ID
	err = oper.Write()
	if err != nil {
		return err
	}

	return nil
}