Esempio n. 1
0
func (n *Network) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *apinet.EndpointSettings) error {
	vc := cache.ContainerCache().GetContainer(containerName)
	if vc != nil {
		containerName = vc.ContainerID
	}

	client := PortLayerClient()
	getRes, err := client.Containers.Get(containers.NewGetParamsWithContext(ctx).WithID(containerName))
	if err != nil {
		switch err := err.(type) {
		case *containers.GetNotFound:
			return derr.NewRequestNotFoundError(fmt.Errorf(err.Payload.Message))

		case *containers.GetDefault:
			return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError)

		default:
			return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError)
		}
	}

	h := getRes.Payload
	nc := &models.NetworkConfig{NetworkName: networkName}
	if endpointConfig != nil {
		if endpointConfig.IPAMConfig != nil && endpointConfig.IPAMConfig.IPv4Address != "" {
			nc.Address = &endpointConfig.IPAMConfig.IPv4Address

		}

		// Pass Links and Aliases to PL
		nc.Aliases = vicendpoint.Alias(endpointConfig)
	}

	addConRes, err := client.Scopes.AddContainer(scopes.NewAddContainerParamsWithContext(ctx).
		WithScope(nc.NetworkName).
		WithConfig(&models.ScopesAddContainerConfig{
			Handle:        h,
			NetworkConfig: nc,
		}))
	if err != nil {
		switch err := err.(type) {
		case *scopes.AddContainerNotFound:
			return derr.NewRequestNotFoundError(fmt.Errorf(err.Payload.Message))

		case *scopes.AddContainerInternalServerError:
			return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError)

		default:
			return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError)
		}
	}

	h = addConRes.Payload

	// only bind if the container is running
	// get the state of the container
	getStateRes, err := client.Containers.GetState(containers.NewGetStateParamsWithContext(ctx).WithHandle(h))
	if err != nil {
		switch err := err.(type) {
		case *containers.GetStateNotFound:
			return derr.NewRequestNotFoundError(fmt.Errorf(err.Payload.Message))

		case *containers.GetStateDefault:
			return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError)

		default:
			return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError)
		}
	}

	h = getStateRes.Payload.Handle
	if getStateRes.Payload.State == "RUNNING" {
		bindRes, err := client.Scopes.BindContainer(scopes.NewBindContainerParamsWithContext(ctx).WithHandle(h))
		if err != nil {
			switch err := err.(type) {
			case *scopes.BindContainerNotFound:
				return derr.NewRequestNotFoundError(fmt.Errorf(err.Payload.Message))

			case *scopes.BindContainerInternalServerError:
				return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError)

			default:
				return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError)
			}
		}

		defer func() {
			if err == nil {
				return
			}
			if _, err2 := client.Scopes.UnbindContainer(scopes.NewUnbindContainerParamsWithContext(ctx).WithHandle(h)); err2 != nil {
				log.Warnf("failed bind container rollback: %s", err2)
			}
		}()

		h = bindRes.Payload.Handle
	}

	// commit handle
	_, err = client.Containers.Commit(containers.NewCommitParamsWithContext(ctx).WithHandle(h))
	if err != nil {
		switch err := err.(type) {
		case *containers.CommitNotFound:
			return derr.NewRequestNotFoundError(fmt.Errorf(err.Payload.Message))

		case *containers.CommitDefault:
			return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError)

		default:
			return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError)
		}
	}

	return nil
}
Esempio n. 2
0
func (c *Container) containerStart(name string, hostConfig *containertypes.HostConfig, bind bool) error {
	var err error

	// Get an API client to the portlayer
	client := c.containerProxy.Client()

	// Look up the container name in the metadata cache to get long ID
	vc := cache.ContainerCache().GetContainer(name)
	if vc == nil {
		return NotFoundError(name)
	}
	id := vc.ContainerID

	// handle legacy hostConfig
	if hostConfig != nil {
		// hostConfig exist for backwards compatibility.  TODO: Figure out which parameters we
		// need to look at in hostConfig
	} else if vc != nil {
		hostConfig = vc.HostConfig
	}

	if vc != nil && hostConfig.NetworkMode.NetworkName() == "" {
		hostConfig.NetworkMode = vc.HostConfig.NetworkMode
	}

	// get a handle to the container
	handle, err := c.Handle(id, name)
	if err != nil {
		return err
	}

	var endpoints []*models.EndpointConfig
	// bind network
	if bind {
		var bindRes *scopes.BindContainerOK
		bindRes, err = client.Scopes.BindContainer(scopes.NewBindContainerParamsWithContext(ctx).WithHandle(handle))
		if err != nil {
			switch err := err.(type) {
			case *scopes.BindContainerNotFound:
				cache.ContainerCache().DeleteContainer(id)
				return NotFoundError(name)
			case *scopes.BindContainerInternalServerError:
				return InternalServerError(err.Payload.Message)
			default:
				return InternalServerError(err.Error())
			}
		}

		handle = bindRes.Payload.Handle
		endpoints = bindRes.Payload.Endpoints

		// unbind in case we fail later
		defer func() {
			if err != nil {
				client.Scopes.UnbindContainer(scopes.NewUnbindContainerParamsWithContext(ctx).WithHandle(handle))
			}
		}()

		// unmap ports that vc needs if they're not being used by previously mapped container
		err = c.cleanupPortBindings(vc)
		if err != nil {
			return err
		}
	}

	// change the state of the container
	// TODO: We need a resolved ID from the name
	var stateChangeRes *containers.StateChangeOK
	stateChangeRes, err = client.Containers.StateChange(containers.NewStateChangeParamsWithContext(ctx).WithHandle(handle).WithState("RUNNING"))
	if err != nil {
		switch err := err.(type) {
		case *containers.StateChangeNotFound:
			cache.ContainerCache().DeleteContainer(id)
			return NotFoundError(name)
		case *containers.StateChangeDefault:
			return InternalServerError(err.Payload.Message)
		default:
			return InternalServerError(err.Error())
		}
	}

	handle = stateChangeRes.Payload

	// map ports
	if bind {
		e := c.findPortBoundNetworkEndpoint(hostConfig, endpoints)
		if err = MapPorts(hostConfig, e, id); err != nil {
			return InternalServerError(fmt.Sprintf("error mapping ports: %s", err))
		}

		defer func() {
			if err != nil {
				UnmapPorts(hostConfig)
			}
		}()
	}

	// commit the handle; this will reconfigure and start the vm
	_, err = client.Containers.Commit(containers.NewCommitParamsWithContext(ctx).WithHandle(handle))
	if err != nil {
		switch err := err.(type) {
		case *containers.CommitNotFound:
			cache.ContainerCache().DeleteContainer(id)
			return NotFoundError(name)
		case *containers.CommitConflict:
			return ConflictError(err.Error())
		case *containers.CommitDefault:
			return InternalServerError(err.Payload.Message)
		default:
			return InternalServerError(err.Error())
		}
	}

	return nil
}