Example #1
0
func (d *Dispatcher) InspectVCH(vch *vm.VirtualMachine, conf *config.VirtualContainerHostConfigSpec) error {
	defer trace.End(trace.Begin(conf.Name))

	state, err := vch.PowerState(d.ctx)
	if err != nil {
		log.Errorf("Failed to get VM power state, service might not be available at this moment.")
	}
	if state != types.VirtualMachinePowerStatePoweredOn {
		err = errors.Errorf("VCH is not powered on, state %s", state)
		log.Errorf("%s", err)
		return err
	}

	clientIP := conf.ExecutorConfig.Networks["client"].Assigned.IP
	externalIP := conf.ExecutorConfig.Networks["external"].Assigned.IP

	if ip.IsUnspecifiedIP(clientIP) {
		err = errors.Errorf("No client IP address assigned")
		log.Errorf("%s", err)
		return err
	}

	if ip.IsUnspecifiedIP(externalIP) {
		err = errors.Errorf("No external IP address assigned")
		log.Errorf("%s", err)
		return err
	}

	d.HostIP = clientIP.String()
	log.Debugf("IP address for client interface: %s", d.HostIP)
	if !conf.HostCertificate.IsNil() {
		d.VICAdminProto = "https"
		d.DockerPort = fmt.Sprintf("%d", opts.DefaultTLSHTTPPort)
	} else {
		d.VICAdminProto = "http"
		d.DockerPort = fmt.Sprintf("%d", opts.DefaultHTTPPort)
	}

	// try looking up preferred name, irrespective of CAs
	if cert, err := conf.HostCertificate.X509Certificate(); err == nil {
		name, _ := viableHostAddress([]net.IP{clientIP}, cert, conf.CertificateAuthorities)
		if name != "" {
			log.Debugf("Retrieved proposed name from host certificate: %q", name)
			log.Debugf("Assigning first name from set: %s", name)

			if name != d.HostIP {
				log.Infof("Using address from host certificate over allocated IP: %s", d.HostIP)
				// reassign
				d.HostIP = name
			}
		} else {
			log.Warnf("Unable to identify address acceptable to host certificate")
		}
	} else {
		log.Debugf("Failed to load host cert: %s", err)
	}

	d.ShowVCH(conf, "", "", "", "")
	return nil
}
Example #2
0
File: client.go Project: vmware/vic
func (c *client) isCompletePacket(p *dhcp.Packet) bool {
	complete := !ip.IsUnspecifiedIP(p.YourIP()) &&
		!ip.IsUnspecifiedIP(p.ServerIP())

	if !complete {
		return false
	}

	for _, param := range c.params {
		switch dhcp4.OptionCode(param) {
		case dhcp4.OptionSubnetMask:
			ones, bits := p.SubnetMask().Size()
			if ones == 0 || bits == 0 {
				return false
			}
		case dhcp4.OptionRouter:
			if ip.IsUnspecifiedIP(p.Gateway()) {
				return false
			}
		case dhcp4.OptionDomainNameServer:
			if len(p.DNS()) == 0 {
				return false
			}
		}
	}

	if p.LeaseTime().Seconds() == 0 {
		return false
	}

	return true
}
Example #3
0
func (d *Dispatcher) InspectVCH(vch *vm.VirtualMachine, conf *config.VirtualContainerHostConfigSpec) error {
	defer trace.End(trace.Begin(conf.Name))

	state, err := vch.PowerState(d.ctx)
	if err != nil {
		log.Errorf("Failed to get VM power state, service might not be avaialble at this moment.")
	}
	if state != types.VirtualMachinePowerStatePoweredOn {
		err = errors.Errorf("VCH is not powered on, state %s", state)
		log.Errorf("%s", err)
		return err
	}
	if ip.IsUnspecifiedIP(conf.ExecutorConfig.Networks["client"].Assigned.IP) {
		err = errors.Errorf("No client IP address assigned")
		log.Errorf("%s", err)
		return err
	}

	d.HostIP = conf.ExecutorConfig.Networks["client"].Assigned.IP.String()
	log.Debug("IP address for client interface: %s", d.HostIP)
	if !conf.HostCertificate.IsNil() {
		d.VICAdminProto = "https"
		d.DockerPort = fmt.Sprintf("%d", opts.DefaultTLSHTTPPort)
	} else {
		d.VICAdminProto = "http"
		d.DockerPort = fmt.Sprintf("%d", opts.DefaultHTTPPort)
	}
	d.ShowVCH(conf, "", "")
	return nil
}
Example #4
0
func updateDefaultRoute(t Netlink, link netlink.Link, endpoint *NetworkEndpoint) error {
	// Add routes
	if !endpoint.Network.Default || ip.IsUnspecifiedIP(endpoint.Network.Gateway.IP) {
		log.Debugf("not setting route for network: default=%v gateway=%s", endpoint.Network.Default, endpoint.Network.Gateway.IP)
		return nil
	}

	_, defaultNet, _ := net.ParseCIDR("0.0.0.0/0")
	// delete default route first
	if err := t.RouteDel(&netlink.Route{LinkIndex: link.Attrs().Index, Dst: defaultNet}); err != nil {
		if errno, ok := err.(syscall.Errno); !ok || errno != syscall.ESRCH {
			return fmt.Errorf("could not update default route: %s", err)
		}
	}

	log.Infof("Setting default gateway to %s", endpoint.Network.Gateway.IP)
	route := &netlink.Route{LinkIndex: link.Attrs().Index, Dst: defaultNet, Gw: endpoint.Network.Gateway.IP}
	if err := t.RouteAdd(route); err != nil {
		detail := fmt.Sprintf("failed to add gateway route for endpoint %s: %s", endpoint.Network.Name, err)
		return errors.New(detail)
	}

	log.Infof("updated default route to %s interface, gateway: %s", endpoint.Network.Name, endpoint.Network.Gateway.IP)
	return nil
}
Example #5
0
func toScopeConfig(scope *network.Scope) *models.ScopeConfig {
	subnet := ""
	if !ip.IsUnspecifiedIP(scope.Subnet().IP) {
		subnet = scope.Subnet().String()
	}

	gateway := ""
	if !scope.Gateway().IsUnspecified() {
		gateway = scope.Gateway().String()
	}

	id := scope.ID().String()
	sc := &models.ScopeConfig{
		ID:        &id,
		Name:      scope.Name(),
		ScopeType: scope.Type(),
		IPAM:      scope.IPAM().Pools(),
		Subnet:    &subnet,
		Gateway:   &gateway,
	}

	if len(sc.IPAM) == 0 && len(subnet) != 0 {
		// use subnet as pool
		sc.IPAM = []string{subnet}
	}

	eps := scope.Endpoints()
	sc.Endpoints = make([]*models.EndpointConfig, len(eps))
	for i, e := range eps {
		sc.Endpoints[i] = toEndpointConfig(e)
	}

	return sc
}
Example #6
0
func isCompletePacket(p *dhcp.Packet) bool {
	complete := !ip.IsUnspecifiedIP(p.Gateway()) &&
		!ip.IsUnspecifiedIP(p.YourIP()) &&
		!ip.IsUnspecifiedIP(p.ServerIP())

	if !complete {
		return false
	}

	ones, bits := p.SubnetMask().Size()
	if ones == 0 || bits == 0 {
		return false
	}

	if p.LeaseTime().Seconds() == 0 {
		return false
	}

	return true
}
Example #7
0
func newEndpoint(container *Container, scope *Scope, eip *net.IP, pciSlot *int32) *Endpoint {
	e := &Endpoint{
		container: container,
		scope:     scope,
		ip:        net.IPv4(0, 0, 0, 0),
		static:    false,
		ports:     make(map[Port]interface{}),
		aliases:   make(map[string][]alias),
	}

	if eip != nil && !ip.IsUnspecifiedIP(*eip) {
		e.ip = *eip
		e.static = true
	}

	return e
}
Example #8
0
func (t *BaseOperations) updateNameservers(endpoint *NetworkEndpoint) error {
	// Add nameservers
	// This is incredibly trivial for now - should be updated to a less messy approach
	if len(endpoint.Network.Nameservers) > 0 {
		Sys.ResolvConf.AddNameservers(endpoint.Network.Nameservers...)
		log.Infof("Added nameservers: %+v", endpoint.Network.Nameservers)
	} else if !ip.IsUnspecifiedIP(endpoint.Network.Gateway.IP) {
		Sys.ResolvConf.AddNameservers(endpoint.Network.Gateway.IP)
		log.Infof("Added nameserver: %s", endpoint.Network.Gateway.IP)
	}

	if err := Sys.ResolvConf.Save(); err != nil {
		return err
	}

	return nil
}
Example #9
0
func getDynamicIP(t Netlink, link netlink.Link, endpoint *NetworkEndpoint) (client.Client, error) {
	var ack *dhcp.Packet
	var err error

	// use dhcp to acquire address
	dc, err := client.NewClient(link.Attrs().Index, link.Attrs().HardwareAddr)
	if err != nil {
		return nil, err
	}

	params := []byte{byte(dhcp4.OptionSubnetMask)}
	if ip.IsUnspecifiedIP(endpoint.Network.Gateway.IP) {
		params = append(params, byte(dhcp4.OptionRouter))
	}
	if len(endpoint.Network.Nameservers) == 0 {
		params = append(params, byte(dhcp4.OptionDomainNameServer))
	}

	dc.SetParameterRequestList(params...)

	err = dc.Request()
	if err != nil {
		log.Errorf("error sending dhcp request: %s", err)
		return nil, err
	}

	ack = dc.LastAck()
	if ack.YourIP() == nil || ack.SubnetMask() == nil {
		err = fmt.Errorf("dhcp assigned nil ip or subnet mask")
		log.Error(err)
		return nil, err
	}

	log.Infof("DHCP response: IP=%s, SubnetMask=%s, Gateway=%s, DNS=%s, Lease Time=%s", ack.YourIP(), ack.SubnetMask(), ack.Gateway(), ack.DNS(), ack.LeaseTime())
	defer func() {
		if err != nil && ack != nil {
			dc.Release()
		}
	}()

	return dc, nil
}
Example #10
0
func toEndpointConfig(e *network.Endpoint) *models.EndpointConfig {
	addr := ""
	if !ip.IsUnspecifiedIP(e.IP()) {
		addr = e.IP().String()
	}

	ports := e.Ports()
	ecports := make([]string, len(ports))
	for i, p := range e.Ports() {
		ecports[i] = p.String()
	}

	return &models.EndpointConfig{
		Address:   addr,
		Container: e.ID().String(),
		ID:        e.ID().String(),
		Name:      e.Name(),
		Scope:     e.Scope().Name(),
		Ports:     ecports,
	}
}
Example #11
0
func reserveGateway(gateway net.IP, subnet *net.IPNet, spaces []*AddressSpace) (net.IP, error) {
	defer trace.End(trace.Begin(""))
	if ip.IsUnspecifiedSubnet(subnet) {
		return nil, fmt.Errorf("cannot reserve gateway for nil subnet")
	}

	if !ip.IsUnspecifiedIP(gateway) {
		// verify gateway is routable address
		if !ip.IsRoutableIP(gateway, subnet) {
			return nil, fmt.Errorf("gateway address %s is not routable on network %s", gateway, subnet)
		}

		// optionally reserve it in one of the pools
		for _, p := range spaces {
			if err := p.ReserveIP4(gateway); err == nil {
				break
			}
		}

		return gateway, nil
	}

	// gateway is not specified, pick one from the available pools
	if len(spaces) > 0 {
		var err error
		if gateway, err = spaces[0].ReserveNextIP4(); err != nil {
			return nil, err
		}

		if !ip.IsRoutableIP(gateway, subnet) {
			return nil, fmt.Errorf("gateway address %s is not routable on network %s", gateway, subnet)
		}

		return gateway, nil
	}

	return nil, fmt.Errorf("could not reserve gateway address for network %s", subnet)
}
Example #12
0
func toScopeConfig(scope *network.Scope) *models.ScopeConfig {
	subnet := ""
	if !ip.IsUnspecifiedIP(scope.Subnet().IP) {
		subnet = scope.Subnet().String()
	}

	gateway := ""
	if !scope.Gateway().IsUnspecified() {
		gateway = scope.Gateway().String()
	}

	id := scope.ID().String()
	sc := &models.ScopeConfig{
		ID:        &id,
		Name:      scope.Name(),
		ScopeType: scope.Type(),
		Subnet:    &subnet,
		Gateway:   &gateway,
	}

	var pools []string
	for _, p := range scope.Pools() {
		pools = append(pools, p.String())
	}

	sc.IPAM = pools
	if len(sc.IPAM) == 0 {
		sc.IPAM = []string{subnet}
	}

	eps := scope.Endpoints()
	sc.Endpoints = make([]*models.EndpointConfig, len(eps))
	for i, e := range eps {
		sc.Endpoints[i] = toEndpointConfig(e)
	}

	return sc
}
Example #13
0
File: scope.go Project: vmware/vic
func (s *Scope) reserveEndpointIP(e *Endpoint) error {
	if s.isDynamic() {
		return nil
	}

	// reserve an ip address
	var err error
	for _, p := range s.spaces {
		if !ip.IsUnspecifiedIP(e.ip) {
			if err = p.ReserveIP4(e.ip); err == nil {
				return nil
			}
		} else {
			var eip net.IP
			if eip, err = p.ReserveNextIP4(); err == nil {
				e.ip = eip
				return nil
			}
		}
	}

	return err
}
Example #14
0
// AddContainer add a container to the specified scope, optionally specifying an ip address
// for the container in the scope
func (c *Context) AddContainer(h *exec.Handle, options *AddContainerOptions) error {
	defer trace.End(trace.Begin(""))
	c.Lock()
	defer c.Unlock()

	if h == nil {
		return fmt.Errorf("handle is required")
	}

	var err error
	s, err := c.resolveScope(options.Scope)
	if err != nil {
		return err
	}

	if h.ExecConfig.Networks != nil {
		if _, ok := h.ExecConfig.Networks[s.Name()]; ok {
			// already part of this scope
			return nil
		}

		// check if container is already part of an "external" scope;
		// only one "external" scope per container is allowed
		if s.Type() == constants.ExternalScopeType {
			for name := range h.ExecConfig.Networks {
				sc, _ := c.resolveScope(name)
				if sc.Type() == constants.ExternalScopeType {
					return fmt.Errorf("container can only be added to at most one mapped network")
				}
			}
		}
	}

	// figure out if we need to add a new NIC
	// if there is already a NIC connected to a
	// bridge network and we are adding the container
	// to a bridge network, we just reuse that
	// NIC
	var pciSlot int32
	if s.Type() == constants.BridgeScopeType {
		for _, ne := range h.ExecConfig.Networks {
			sc, err := c.resolveScope(ne.Network.Name)
			if err != nil {
				return err
			}

			if sc.Type() != constants.BridgeScopeType {
				continue
			}

			if ne.ID != "" {
				pciSlot = atoiOrZero(ne.ID)
				if pciSlot != 0 {
					break
				}
			}
		}
	}

	if pciSlot == 0 {
		d, err := addEthernetCard(h, s)
		if err != nil {
			return err
		}

		pciSlot = spec.VirtualDeviceSlotNumber(d)
	}

	if h.ExecConfig.Networks == nil {
		h.ExecConfig.Networks = make(map[string]*executor.NetworkEndpoint)
	}

	ne := &executor.NetworkEndpoint{
		Common: executor.Common{
			ID: strconv.Itoa(int(pciSlot)),
			// Name: this would cause NIC renaming if uncommented
		},
		Network: executor.ContainerNetwork{
			Common: executor.Common{
				Name: s.Name(),
			},
			Aliases: options.Aliases,
			Type:    s.Type(),
		},
		Ports: options.Ports,
	}
	pools := s.Pools()
	ne.Network.Pools = make([]ip.Range, len(pools))
	for i, p := range pools {
		ne.Network.Pools[i] = *p
	}

	ne.Static = false
	if options.IP != nil && !ip.IsUnspecifiedIP(*options.IP) {
		ne.Static = true
		ne.IP = &net.IPNet{
			IP:   *options.IP,
			Mask: s.Subnet().Mask,
		}
	}

	h.ExecConfig.Networks[s.Name()] = ne
	return nil
}
Example #15
0
func (c *Context) bindContainer(h *exec.Handle) ([]*Endpoint, error) {
	con, err := c.container(h)
	if con != nil {
		return con.Endpoints(), nil // already bound
	}

	if _, ok := err.(ResourceNotFoundError); !ok {
		return nil, err
	}

	con = &Container{
		id:   uid.Parse(h.ExecConfig.ID),
		name: h.ExecConfig.Name,
	}

	defaultMarked := false
	aliases := make(map[string]*Container)
	var endpoints []*Endpoint
	for _, ne := range h.ExecConfig.Networks {
		var s *Scope
		s, ok := c.scopes[ne.Network.Name]
		if !ok {
			return nil, &ResourceNotFoundError{}
		}

		defer func() {
			if err == nil {
				return
			}

			s.RemoveContainer(con)
		}()

		var eip *net.IP
		if ne.Static {
			eip = &ne.IP.IP
		} else if !ip.IsUnspecifiedIP(ne.Assigned.IP) {
			// for VCH restart, we need to reserve
			// the IP of the running container
			//
			// this may be a DHCP assigned IP, however, the
			// addContainer call below will ignore reserving
			// an IP if the scope is "dynamic"
			eip = &ne.Assigned.IP
		}

		e := newEndpoint(con, s, eip, nil)
		e.static = ne.Static
		if err = s.AddContainer(con, e); err != nil {
			return nil, err
		}

		ports, _, err := nat.ParsePortSpecs(ne.Ports)
		if err != nil {
			return nil, err
		}
		for p := range ports {
			var port Port
			if port, err = ParsePort(string(p)); err != nil {
				return nil, err
			}

			if err = e.addPort(port); err != nil {
				return nil, err
			}
		}

		if !ip.IsUnspecifiedIP(e.IP()) {
			ne.IP = &net.IPNet{
				IP:   e.IP(),
				Mask: e.Scope().Subnet().Mask,
			}
		}
		ne.Network.Gateway = net.IPNet{IP: e.Gateway(), Mask: e.Subnet().Mask}
		ne.Network.Nameservers = make([]net.IP, len(s.dns))
		copy(ne.Network.Nameservers, s.dns)

		// mark the external network as default
		if !defaultMarked && e.Scope().Type() == constants.ExternalScopeType {
			defaultMarked = true
			ne.Network.Default = true
		}

		// dns lookup aliases
		aliases[fmt.Sprintf("%s:%s", s.Name(), con.name)] = con
		aliases[fmt.Sprintf("%s:%s", s.Name(), con.id.Truncate())] = con

		// container specific aliases
		for _, a := range ne.Network.Aliases {
			log.Debugf("adding alias %s", a)
			l := strings.Split(a, ":")
			if len(l) != 2 {
				err = fmt.Errorf("Parsing network alias %s failed", a)
				return nil, err
			}

			who, what := l[0], l[1]
			if who == "" {
				who = con.name
			}
			if a, exists := e.addAlias(who, what); a != badAlias && !exists {
				whoc := con
				// if the alias is not for this container, then
				// find it in the container collection
				if who != con.name {
					whoc = c.containers[who]
				}

				// whoc may be nil here, which means that the aliased
				// container is not bound yet; this is OK, and will be
				// fixed up when "who" is bound
				if whoc != nil {
					aliases[a.scopedName()] = whoc
				}
			}
		}

		// fix up the aliases to this container
		// from other containers
		for _, e := range s.Endpoints() {
			if e.Container() == con {
				continue
			}

			for _, a := range e.getAliases(con.name) {
				aliases[a.scopedName()] = con
			}
		}

		endpoints = append(endpoints, e)
	}

	// verify all the aliases to be added do not conflict with
	// existing container keys
	for a := range aliases {
		if _, ok := c.containers[a]; ok {
			return nil, fmt.Errorf("duplicate alias %s for container %s", a, con.ID())
		}
	}

	// FIXME: if there was no external network to mark as default,
	// then just pick the first network to mark as default
	if !defaultMarked {
		defaultMarked = true
		for _, ne := range h.ExecConfig.Networks {
			ne.Network.Default = true
			break
		}
	}

	// long id
	c.containers[con.id.String()] = con
	// short id
	c.containers[con.id.Truncate().String()] = con
	// name
	c.containers[con.name] = con
	// aliases
	for k, v := range aliases {
		log.Debugf("adding alias %s -> %s", k, v.Name())
		c.containers[k] = v
	}

	return endpoints, nil
}
Example #16
0
func (c *Context) addScope(s *Scope) error {
	defer trace.End(trace.Begin(""))

	if _, ok := c.scopes[s.name]; ok {
		return DuplicateResourceError{}
	}

	var err error
	var defaultPool bool
	var allzeros, allones net.IP
	var space *AddressSpace
	spaces := s.spaces
	subnet := s.subnet
	gateway := s.gateway

	// cleanup
	defer func() {
		if err == nil || space == nil || !defaultPool {
			return
		}

		for _, p := range spaces {
			// release DNS IPs
			for _, d := range s.dns {
				p.ReleaseIP4(d)
			}

			// release gateway
			if !ip.IsUnspecifiedIP(gateway) {
				p.ReleaseIP4(gateway)
			}

			// release all-ones and all-zeros addresses
			if !ip.IsUnspecifiedIP(allzeros) {
				p.ReleaseIP4(allzeros)
			}
			if !ip.IsUnspecifiedIP(allones) {
				p.ReleaseIP4(allones)
			}
		}

		c.defaultBridgePool.ReleaseIP4Range(space)
	}()

	// subnet may not be specified, e.g. for "external" networks
	if !ip.IsUnspecifiedSubnet(subnet) {
		// allocate the subnet
		space, defaultPool, err = c.reserveSubnet(subnet)
		if err != nil {
			return err
		}

		subnet = space.Network

		spaces, err = reservePools(space, spaces)
		if err != nil {
			return err
		}

		// reserve all-ones and all-zeros addresses, which are not routable and so
		// should not be handed out
		allones = ip.AllOnesAddr(subnet)
		allzeros = ip.AllZerosAddr(subnet)
		for _, p := range spaces {
			p.ReserveIP4(allones)
			p.ReserveIP4(allzeros)

			// reserve DNS IPs
			for _, d := range s.dns {
				if d.Equal(gateway) {
					continue // gateway will be reserved later
				}

				p.ReserveIP4(d)
			}
		}

		if gateway, err = reserveGateway(gateway, subnet, spaces); err != nil {
			return err
		}

		s.gateway = gateway
		s.spaces = spaces
		s.subnet = subnet
	}

	c.scopes[s.name] = s

	return nil
}
Example #17
0
// ensureApplianceInitializes checks if the appliance component processes are launched correctly
func (d *Dispatcher) ensureApplianceInitializes(conf *config.VirtualContainerHostConfigSpec) error {
	defer trace.End(trace.Begin(""))

	if d.appliance == nil {
		return errors.New("cannot validate appliance due to missing VM reference")
	}

	log.Infof("Waiting for IP information")
	d.waitForKey("guestinfo..init.networks|client.ip.IP")
	ctxerr := d.ctx.Err()

	if ctxerr == nil {
		log.Info("Waiting for major appliance components to launch")
		log.Debug("waiting for vicadmin to start")
		d.waitForKey("guestinfo..init.sessions|vicadmin.started")
		log.Debug("waiting for docker personality to start")
		d.waitForKey("guestinfo..init.sessions|docker-personality.started")
		log.Debug("waiting for port layer to start")
		d.waitForKey("guestinfo..init.sessions|port-layer.started")
	}

	// at this point either everything has succeeded or we're going into diagnostics, ignore error
	// as we're only using it for IP in the success case
	updateErr := d.applianceConfiguration(conf)

	// TODO: we should call to the general vic-machine inspect implementation here for more detail
	// but instead...
	if !ip.IsUnspecifiedIP(conf.ExecutorConfig.Networks["client"].Assigned.IP) {
		d.HostIP = conf.ExecutorConfig.Networks["client"].Assigned.IP.String()
		log.Debug("Obtained IP address for client interface: %q", d.HostIP)
		return nil
	}

	// it's possible we timed out... get updated info having adjusted context to allow it
	// keeping it short
	ctxerr = d.ctx.Err()

	d.ctx, _ = context.WithTimeout(context.Background(), 10*time.Second)
	err := d.applianceConfiguration(conf)
	if err != nil {
		return fmt.Errorf("unable to retrieve updated configuration from appliance for diagnostics: %s", err)
	}

	if ctxerr == context.DeadlineExceeded {
		log.Info("Failed to retrieve IP for client interface")
		log.Info("  State of all interfaces:")

		// if we timed out, then report status - if cancelled this doesn't need reporting
		for name, net := range conf.ExecutorConfig.Networks {
			addr := net.Assigned.String()
			if ip.IsUnspecifiedIP(net.Assigned.IP) {
				addr = "waiting for IP"
			}
			log.Infof("    %q IP: %q", name, addr)
		}

		// if we timed out, then report status - if cancelled this doesn't need reporting
		log.Info("  State of components:")
		for name, session := range conf.ExecutorConfig.Sessions {
			status := "waiting to launch"
			if session.Started == "true" {
				status = "started successfully"
			} else if session.Started != "" {
				status = session.Started
			}
			log.Infof("    %q: %q", name, status)
		}

		return errors.New("timed out waiting for IP address information from appliance")
	}

	return fmt.Errorf("could not obtain IP address information from appliance: %s", updateErr)
}
Example #18
0
func (c *Context) newScopeCommon(id uid.UID, name, scopeType string, subnet *net.IPNet, gateway net.IP, dns []net.IP, ipam *IPAM, network object.NetworkReference) (*Scope, error) {

	var err error
	var space *AddressSpace
	var defaultPool bool
	var allzeros, allones net.IP

	// cleanup
	defer func() {
		if err == nil || space == nil || !defaultPool {
			return
		}

		for _, p := range ipam.spaces {
			// release DNS IPs
			for _, d := range dns {
				p.ReleaseIP4(d)
			}

			// release gateway
			if !ip.IsUnspecifiedIP(gateway) {
				p.ReleaseIP4(gateway)
			}

			// release all-ones and all-zeros addresses
			if !ip.IsUnspecifiedIP(allzeros) {
				p.ReleaseIP4(allzeros)
			}
			if !ip.IsUnspecifiedIP(allones) {
				p.ReleaseIP4(allones)
			}
		}

		c.defaultBridgePool.ReleaseIP4Range(space)
	}()

	// subnet may not be specified, e.g. for "external" networks
	if !ip.IsUnspecifiedSubnet(subnet) {
		// allocate the subnet
		space, defaultPool, err = c.reserveSubnet(subnet)
		if err != nil {
			return nil, err
		}

		subnet = space.Network

		ipam.spaces, err = reservePools(space, ipam)
		if err != nil {
			return nil, err
		}

		// reserve all-ones and all-zeros addresses, which are not routable and so
		// should not be handed out
		allones = ip.AllOnesAddr(subnet)
		allzeros = ip.AllZerosAddr(subnet)
		for _, p := range ipam.spaces {
			p.ReserveIP4(allones)
			p.ReserveIP4(allzeros)

			// reserve DNS IPs
			for _, d := range dns {
				if d.Equal(gateway) {
					continue // gateway will be reserved later
				}

				p.ReserveIP4(d)
			}
		}

		if gateway, err = reserveGateway(gateway, subnet, ipam); err != nil {
			return nil, err
		}

	}

	newScope := &Scope{
		id:         id,
		name:       name,
		subnet:     *subnet,
		gateway:    gateway,
		ipam:       ipam,
		containers: make(map[uid.UID]*Container),
		scopeType:  scopeType,
		space:      space,
		dns:        dns,
		builtin:    false,
		network:    network,
	}

	c.scopes[name] = newScope

	return newScope, nil
}
Example #19
0
func apply(nl Netlink, t *BaseOperations, endpoint *NetworkEndpoint) error {
	if endpoint.applied {
		log.Infof("skipping applying config for network %s as it has been applied already", endpoint.Network.Name)
		return nil // already applied
	}

	// Locate interface
	slot, err := strconv.Atoi(endpoint.ID)
	if err != nil {
		return fmt.Errorf("endpoint ID must be a base10 numeric pci slot identifier: %s", err)
	}

	defer func() {
		if err == nil {
			log.Infof("successfully applied config for network %s", endpoint.Network.Name)
			endpoint.applied = true
		}
	}()

	var link netlink.Link
	link, err = nl.LinkBySlot(int32(slot))
	if err != nil {
		return fmt.Errorf("unable to acquire reference to link %s: %s", endpoint.ID, err)
	}

	// rename the link if needed
	link, err = renameLink(nl, link, int32(slot), endpoint)
	if err != nil {
		return fmt.Errorf("unable to reacquire link %s after rename pass: %s", endpoint.ID, err)
	}

	var dc client.Client
	defer func() {
		if err != nil && dc != nil {
			dc.Release()
		}
	}()

	var newIP *net.IPNet

	if endpoint.IsDynamic() && endpoint.DHCP == nil {
		if e, ok := t.dynEndpoints[endpoint.ID]; ok {
			// endpoint shares NIC, copy over DHCP
			endpoint.DHCP = e[0].DHCP
		}
	}

	log.Debugf("%+v", endpoint)
	if endpoint.IsDynamic() {
		if endpoint.DHCP == nil {
			dc, err = getDynamicIP(nl, link, endpoint)
			if err != nil {
				return err
			}

			ack := dc.LastAck()
			endpoint.DHCP = &DHCPInfo{
				Assigned:    net.IPNet{IP: ack.YourIP(), Mask: ack.SubnetMask()},
				Nameservers: ack.DNS(),
				Gateway:     net.IPNet{IP: ack.Gateway(), Mask: ack.SubnetMask()},
			}
		}
		newIP = &endpoint.DHCP.Assigned
	} else {
		newIP = endpoint.IP
		if newIP.IP.Equal(net.IPv4zero) {
			// managed externally
			return nil
		}
	}

	var old *net.IPNet
	if !ip.IsUnspecifiedIP(endpoint.Assigned.IP) {
		old = &endpoint.Assigned
	}

	if err = linkAddrUpdate(old, newIP, nl, link); err != nil {
		return err
	}

	updateEndpoint(newIP, endpoint)

	if err = updateDefaultRoute(nl, link, endpoint); err != nil {
		return err
	}

	if err = t.updateHosts(endpoint); err != nil {
		return err
	}

	Sys.ResolvConf.RemoveNameservers(endpoint.Network.Nameservers...)
	if err = t.updateNameservers(endpoint); err != nil {
		return err
	}

	if endpoint.IsDynamic() {
		eps := t.dynEndpoints[endpoint.ID]
		found := false
		for _, e := range eps {
			if e == endpoint {
				found = true
				break
			}
		}

		if !found {
			eps = append(eps, endpoint)
			t.dynEndpoints[endpoint.ID] = eps
		}
	}

	// add renew/release loop if necessary
	if dc != nil {
		if _, ok := t.dhcpLoops[endpoint.ID]; !ok {
			stop := make(chan struct{})
			if err != nil {
				log.Errorf("could not make DHCP client id for link %s: %s", link.Attrs().Name, err)
			} else {
				t.dhcpLoops[endpoint.ID] = stop
				go t.dhcpLoop(stop, endpoint, dc)
			}
		}
	}

	return nil
}
Example #20
0
func apply(nl Netlink, t *BaseOperations, endpoint *NetworkEndpoint) error {
	// Locate interface
	slot, err := strconv.Atoi(endpoint.ID)
	if err != nil {
		detail := fmt.Sprintf("endpoint ID must be a base10 numeric pci slot identifier: %s", err)
		return errors.New(detail)
	}
	link, err := nl.LinkBySlot(int32(slot))
	if err != nil {
		detail := fmt.Sprintf("unable to acquire reference to link %s: %s", endpoint.ID, err)
		return errors.New(detail)
	}

	// rename the link if needed
	link, err = renameLink(nl, link, int32(slot), endpoint)
	if err != nil {
		detail := fmt.Sprintf("unable to reacquire link %s after rename pass: %s", endpoint.ID, err)
		return errors.New(detail)
	}

	var ack *dhcp.Packet
	defer func() {
		if err != nil && ack != nil {
			t.dhcpClient.Release(ack)
		}
	}()

	var newIP *net.IPNet

	if endpoint.IsDynamic() && endpoint.DHCP == nil {
		if e, ok := t.dynEndpoints[endpoint.ID]; ok {
			// endpoint shares NIC, copy over DHCP
			endpoint.DHCP = e[0].DHCP
		}
	}

	log.Debugf("%+v", endpoint)
	if endpoint.IsDynamic() {
		if endpoint.DHCP == nil {
			ack, err = getDynamicIP(nl, link, t.dhcpClient)
			if err != nil {
				return err
			}

			endpoint.DHCP = &DHCPInfo{
				Assigned:    net.IPNet{IP: ack.YourIP(), Mask: ack.SubnetMask()},
				Nameservers: ack.DNS(),
				Gateway:     net.IPNet{IP: ack.Gateway(), Mask: ack.SubnetMask()},
			}
		}
		newIP = &endpoint.DHCP.Assigned
	} else {
		newIP = endpoint.Static
		if newIP.IP.IsUnspecified() {
			// managed externally
			return nil
		}
	}

	var old *net.IPNet
	if !ip.IsUnspecifiedIP(endpoint.Assigned.IP) {
		old = &endpoint.Assigned
	}

	if err = linkAddrUpdate(old, newIP, nl, link); err != nil {
		return err
	}

	updateEndpoint(newIP, endpoint)

	if err = updateDefaultRoute(nl, link, endpoint); err != nil {
		return err
	}

	if err = t.updateHosts(endpoint); err != nil {
		return err
	}

	t.resolvConf.RemoveNameservers(endpoint.Network.Nameservers...)
	if err = t.updateNameservers(endpoint); err != nil {
		return err
	}

	if endpoint.IsDynamic() {
		eps := t.dynEndpoints[endpoint.ID]
		found := false
		for _, e := range eps {
			if e == endpoint {
				found = true
				break
			}
		}

		if !found {
			eps = append(eps, endpoint)
			t.dynEndpoints[endpoint.ID] = eps
		}
	}

	// add renew/release loop if necessary
	if ack != nil {
		if _, ok := t.dhcpLoops[endpoint.ID]; !ok {
			stop := make(chan bool)
			id, err := client.NewID(link.Attrs().Index, link.Attrs().HardwareAddr)
			if err != nil {
				log.Errorf("could not make DHCP client id for link %s: %s", link.Attrs().Name, err)
			} else {
				go t.dhcpLoop(stop, endpoint, ack, id)
				t.dhcpLoops[endpoint.ID] = stop
			}
		}
	}

	return nil
}
Example #21
0
File: config.go Project: vmware/vic
func (e *NetworkEndpoint) IsDynamic() bool {
	return !e.Static && (e.IP == nil || ip.IsUnspecifiedIP(e.IP.IP))
}
Example #22
0
func TestMapExternalNetworks(t *testing.T) {
	ctx, err := NewContext(net.IPNet{IP: net.IPv4(172, 16, 0, 0), Mask: net.CIDRMask(12, 32)}, net.CIDRMask(16, 32))
	if err != nil {
		t.Fatalf("NewContext() => (nil, %s), want (ctx, nil)", err)
	}

	// check if external networks were loaded
	for n, nn := range Config.ContainerNetworks {
		scopes, err := ctx.Scopes(&n)
		if err != nil || len(scopes) != 1 {
			t.Fatalf("external network %s was not loaded", n)
		}

		s := scopes[0]
		pools := s.IPAM().Pools()
		if !ip.IsUnspecifiedIP(nn.Gateway.IP) {
			subnet := &net.IPNet{IP: nn.Gateway.IP.Mask(nn.Gateway.Mask), Mask: nn.Gateway.Mask}
			if ip.IsUnspecifiedSubnet(s.Subnet()) || !s.Subnet().IP.Equal(subnet.IP) || !bytes.Equal(s.Subnet().Mask, subnet.Mask) {
				t.Fatalf("external network %s was loaded with wrong subnet, got: %s, want: %s", n, s.Subnet(), subnet)
			}

			if ip.IsUnspecifiedIP(s.Gateway()) || !s.Gateway().Equal(nn.Gateway.IP) {
				t.Fatalf("external network %s was loaded with wrong gateway, got: %s, want: %s", n, s.Gateway(), nn.Gateway.IP)
			}

			if len(nn.Pools) == 0 {
				// only one pool corresponding to the subnet
				if len(pools) != 1 || pools[0] != subnet.String() {
					t.Fatalf("external network %s was loaded with wrong pool, got: %+v, want %+v", n, pools, []*net.IPNet{subnet})
				}
			}
		}

		for _, d := range nn.Nameservers {
			found := false
			for _, d2 := range s.DNS() {
				if d2.Equal(d) {
					found = true
					break
				}
			}

			if !found {
				t.Fatalf("external network %s was loaded with wrong nameservers, got: %+v, want: %+v", n, s.DNS(), nn.Nameservers)
			}
		}

		for _, p := range nn.Pools {
			found := false
			for _, p2 := range pools {
				if p2 == p.String() {
					found = true
					break
				}
			}

			if !found {
				t.Fatalf("external network %s was loaded with wrong pools, got: %+v, want: %+v", n, s.IPAM().Pools(), nn.Pools)
			}
		}
	}
}