Beispiel #1
0
func ensureContainersStarted(p DockerProvisioner, w io.Writer, relaunch bool, names []string, nodes ...cluster.Node) error {
	if w == nil {
		w = ioutil.Discard
	}
	var err error
	if len(names) == 0 {
		names, err = nodecontainer.AllNodeContainersNames()
		if err != nil {
			return err
		}
	}
	if len(nodes) == 0 {
		nodes, err = p.Cluster().UnfilteredNodes()
		if err != nil {
			return err
		}
	}
	errChan := make(chan error, len(nodes)*len(names))
	wg := sync.WaitGroup{}
	log.Debugf("[node containers] recreating %d containers", len(nodes)*len(names))
	recreateContainer := func(node *cluster.Node, confName string) {
		defer wg.Done()
		pool := node.Metadata["pool"]
		containerConfig, confErr := nodecontainer.LoadNodeContainer(pool, confName)
		if confErr != nil {
			errChan <- confErr
			return
		}
		if !containerConfig.Valid() {
			return
		}
		log.Debugf("[node containers] recreating container %q in %s [%s]", confName, node.Address, pool)
		fmt.Fprintf(w, "relaunching node container %q in the node %s [%s]\n", confName, node.Address, pool)
		confErr = create(containerConfig, node, pool, p, relaunch)
		if confErr != nil {
			confErr = errors.Wrapf(confErr, "[node containers] failed to create container in %s [%s]", node.Address, pool)
			errChan <- log.WrapError(confErr)
		}
	}
	for i := range nodes {
		wg.Add(1)
		go func(node *cluster.Node) {
			defer wg.Done()
			for j := range names {
				wg.Add(1)
				go recreateContainer(node, names[j])
			}
		}(&nodes[i])
	}
	wg.Wait()
	close(errChan)
	var allErrors []error
	for err = range errChan {
		allErrors = append(allErrors, err)
	}
	if len(allErrors) == 0 {
		return nil
	}
	return tsuruErrors.NewMultiError(allErrors...)
}
Beispiel #2
0
func (p *swarmProvisioner) Destroy(a provision.App) error {
	client, err := chooseDBSwarmNode()
	if err != nil {
		return err
	}
	multiErrors := tsuruErrors.NewMultiError()
	processes, err := allAppProcesses(a.GetName())
	if err != nil {
		multiErrors.Add(err)
	}
	for _, p := range processes {
		name := serviceNameForApp(a, p)
		err = client.RemoveService(docker.RemoveServiceOptions{
			ID: name,
		})
		if err != nil {
			if _, notFound := err.(*docker.NoSuchService); !notFound {
				multiErrors.Add(errors.WithStack(err))
			}
		}
	}
	err = client.RemoveNetwork(networkNameForApp(a))
	if err != nil {
		multiErrors.Add(errors.WithStack(err))
	}
	if multiErrors.Len() > 0 {
		return multiErrors
	}
	return nil
}
Beispiel #3
0
func RemoveNamedContainers(p DockerProvisioner, w io.Writer, name string, pool string) error {
	var nodes []cluster.Node
	var err error
	if pool == "" {
		nodes, err = p.Cluster().UnfilteredNodes()
	} else {
		nodes, err = p.Cluster().UnfilteredNodesForMetadata(map[string]string{"pool": pool})
	}
	if err != nil {
		return errors.WithStack(err)
	}
	errChan := make(chan error, len(nodes))
	wg := sync.WaitGroup{}
	removeContainer := func(node *cluster.Node) {
		pool := node.Metadata["pool"]
		client, err := node.Client()
		if err != nil {
			errChan <- err
			return
		}
		err = client.StopContainer(name, 10)
		if err != nil {
			if _, ok := err.(*docker.NoSuchContainer); ok {
				log.Debugf("[node containers] no such container %q in %s [%s]", name, node.Address, pool)
				fmt.Fprintf(w, "no such node container %q in the node %s [%s]\n", name, node.Address, pool)
				return
			}
			if _, ok := err.(*docker.ContainerNotRunning); !ok {
				err = errors.Wrapf(err, "[node containers] failed to stop container in %s [%s]", node.Address, pool)
				errChan <- err
				return
			}
		}
		log.Debugf("[node containers] removing container %q in %s [%s]", name, node.Address, pool)
		fmt.Fprintf(w, "removing node container %q in the node %s [%s]\n", name, node.Address, pool)
		err = client.RemoveContainer(docker.RemoveContainerOptions{ID: name, Force: true})
		if err != nil {
			err = errors.Wrapf(err, "[node containers] failed to remove container in %s [%s]", node.Address, pool)
			errChan <- err
		}
	}
	for i := range nodes {
		wg.Add(1)
		go func(node *cluster.Node) {
			removeContainer(node)
			wg.Done()
		}(&nodes[i])
	}
	wg.Wait()
	close(errChan)
	var allErrors []error
	for err := range errChan {
		allErrors = append(allErrors, err)
	}
	if len(allErrors) == 0 {
		return nil
	}
	return tsuruErrors.NewMultiError(allErrors...)
}
Beispiel #4
0
func (g MultiGuesser) GuessName(pathname string) (string, error) {
	var errors []error
	for _, guesser := range g.Guessers {
		app, err := guesser.GuessName(pathname)
		if err == nil {
			return app, nil
		}
		errors = append(errors, err)
	}
	return "", tsuruErrors.NewMultiError(errors...)
}
Beispiel #5
0
func create(c *nodecontainer.NodeContainerConfig, node *cluster.Node, poolName string, p DockerProvisioner, relaunch bool) error {
	client, err := node.Client()
	if err != nil {
		return err
	}
	c.Config.Image, err = pullImage(c, client, p, poolName)
	if err != nil {
		return err
	}
	c.Config.Env = append([]string{"DOCKER_ENDPOINT=" + node.Address}, c.Config.Env...)
	if c.Config.Labels == nil {
		c.Config.Labels = map[string]string{}
	}
	c.Config.Labels["tsuru.nodecontainer"] = strconv.FormatBool(true)
	c.Config.Labels["tsuru.node.pool"] = poolName
	c.Config.Labels["tsuru.node.address"] = node.Address
	c.Config.Labels["tsuru.node.provisioner"] = p.GetName()
	opts := docker.CreateContainerOptions{
		Name:       c.Name,
		HostConfig: &c.HostConfig,
		Config:     &c.Config,
	}
	_, err = client.CreateContainer(opts)
	if err != nil {
		if err != docker.ErrContainerAlreadyExists {
			return err
		}
		if relaunch {
			multiErr := tsuruErrors.NewMultiError()
			err = tryRemovingOld(client, opts.Name)
			if err != nil {
				multiErr.Add(errors.Wrapf(err, "unable to remove old node-container"))
			}
			_, err = client.CreateContainer(opts)
			if err != nil {
				multiErr.Add(errors.Wrapf(err, "unable to create new node-container"))
				return multiErr
			}
		}
	}
	err = client.StartContainer(c.Name, nil)
	if _, ok := err.(*docker.ContainerAlreadyRunning); !ok {
		return err
	}
	return nil
}
Beispiel #6
0
// PlatformAdd add a new platform to tsuru
func PlatformAdd(opts provision.PlatformOptions) error {
	if opts.Name == "" {
		return ErrPlatformNameMissing
	}
	provisioners, err := provision.Registry()
	if err != nil {
		return err
	}
	p := Platform{Name: opts.Name}
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	defer conn.Close()
	err = conn.Platforms().Insert(p)
	if err != nil {
		if mgo.IsDup(err) {
			return DuplicatePlatformError
		}
		return err
	}
	for _, p := range provisioners {
		if extensibleProv, ok := p.(provision.ExtensibleProvisioner); ok {
			err = extensibleProv.PlatformAdd(opts)
			if err != nil {
				break
			}
		}
	}
	if err != nil {
		dbErr := conn.Platforms().RemoveId(p.Name)
		if dbErr != nil {
			return tsuruErrors.NewMultiError(
				errors.Wrapf(dbErr, "unable to rollback platform add"),
				errors.Wrapf(err, "original platform add error"),
			)
		}
		return err
	}
	return nil
}
Beispiel #7
0
func (p *swarmProvisioner) UpgradeNodeContainer(name string, pool string, writer io.Writer) error {
	client, err := chooseDBSwarmNode()
	if err != nil {
		if errors.Cause(err) == errNoSwarmNode {
			return nil
		}
		return err
	}
	poolsToRun := []string{pool}
	if pool == "" {
		poolMap, errLoad := nodecontainer.LoadNodeContainersForPools(name)
		if errLoad != nil {
			return errors.WithStack(errLoad)
		}
		poolsToRun = make([]string, len(poolMap))
		i := 0
		for k, v := range poolMap {
			if !v.Valid() {
				continue
			}
			if k == "" {
				poolsToRun[len(poolMap)-1] = k
				continue
			}
			poolsToRun[i] = k
			i++
		}
	}
	var allErrors []error
	created := false
	for _, v := range poolsToRun {
		serviceSpec, errUpsert := serviceSpecForNodeContainer(name, v)
		if errUpsert != nil {
			errUpsert = errors.Wrapf(errUpsert, "[node containers] failed retrieve service spec for node container %q [%s]", name, v)
			allErrors = append(allErrors, errUpsert)
		}
		log.Debugf("[node containers] upserting service %q for node container %s [%s]", serviceSpec.Name, name, v)
		fmt.Fprintf(writer, "upserting service %q for node container %q [%s]\n", serviceSpec.Name, name, v)
		errUpsert, created = upsertService(serviceSpec, client)
		if errUpsert != nil {
			errUpsert = errors.Wrapf(errUpsert, "[node containers] failed upsert service %q for node container %q [%s]", serviceSpec.Name, name, v)
			allErrors = append(allErrors, errUpsert)
		}
	}
	if pool != "" && created {
		serviceName := nodeContainerServiceName(name, "")
		baseSpec, err := client.InspectService(serviceName)
		if err != nil {
			if _, ok := err.(*docker.NoSuchService); ok {
				return nil
			}
			err = errors.Wrapf(err, "[node containers] failed inspect base service %q for node container %q", serviceName, name)
			allErrors = append(allErrors, err)
		}
		newBaseSpec, err := serviceSpecForNodeContainer(name, "")
		if err != nil {
			err = errors.Wrapf(err, "[node containers] failed retrieve base service spec %q for node container %q", serviceName, name)
			allErrors = append(allErrors, err)
		}
		baseSpec.Spec.TaskTemplate.Placement = newBaseSpec.TaskTemplate.Placement
		log.Debugf("[node containers] updating base service %q for node container %s constraints", serviceName, name)
		fmt.Fprintf(writer, "updating base service %q for node container %s constraints\n", serviceName, name)
		err, _ = upsertService(&baseSpec.Spec, client)
		if err != nil {
			err = errors.Wrapf(err, "[node containers] failed update base service %q for node container %q", serviceName, name)
			allErrors = append(allErrors, err)
		}
	}
	if len(allErrors) == 0 {
		return nil
	}
	return tsuruErrors.NewMultiError(allErrors...)
}
Beispiel #8
0
func (i *dockerMachineIaaS) CreateMachine(params map[string]string) (*iaas.Machine, error) {
	caPath, _ := i.base.GetConfigString("ca-path")
	driverName, ok := params["driver"]
	if !ok {
		name, errConf := i.base.GetConfigString("driver:name")
		if errConf != nil {
			return nil, errDriverNotSet
		}
		driverName = name
		params["driver"] = driverName
	}
	dockerEngineInstallURL, _ := i.getParamOrConfigString("docker-install-url", params)
	insecureRegistry, _ := i.getParamOrConfigString("insecure-registry", params)
	var engineFlags []string
	if f, err := i.getParamOrConfigString("docker-flags", params); err == nil {
		engineFlags = strings.Split(f, ",")
	}
	machineName, ok := params["name"]
	if !ok {
		name, err := generateMachineName(params["pool"])
		if err != nil {
			return nil, err
		}
		machineName = name
	} else {
		delete(params, "name")
	}
	userDataFileParam, err := i.base.GetConfigString("driver:user-data-file-param")
	if err == nil {
		f, errTemp := ioutil.TempFile("", "")
		if errTemp != nil {
			return nil, errors.Wrap(errTemp, "failed to create userdata file")
		}
		defer os.RemoveAll(f.Name())
		userData, errData := i.base.ReadUserData()
		if errData != nil {
			return nil, errors.WithMessage(errData, "failed to read userdata")
		}
		_, errWrite := f.WriteString(userData)
		if errWrite != nil {
			return nil, errors.Wrap(errWrite, "failed to write local userdata file")
		}
		params[userDataFileParam] = f.Name()
	}
	driverOpts := i.buildDriverOpts(driverName, params)
	if userDataFileParam != "" {
		delete(params, userDataFileParam)
	}
	buf := &bytes.Buffer{}
	debugConf, _ := i.base.GetConfigString("debug")
	if debugConf == "" {
		debugConf = "false"
	}
	isDebug, err := strconv.ParseBool(debugConf)
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse debug config")
	}
	dockerMachine, err := i.apiFactory(DockerMachineConfig{
		CaPath:    caPath,
		OutWriter: buf,
		ErrWriter: buf,
		IsDebug:   isDebug,
	})
	if err != nil {
		return nil, err
	}
	defer func() {
		dockerMachine.Close()
		log.Debug(buf.String())
	}()
	m, err := dockerMachine.CreateMachine(CreateMachineOpts{
		Name:                   machineName,
		DriverName:             driverName,
		Params:                 driverOpts,
		InsecureRegistry:       insecureRegistry,
		DockerEngineInstallURL: dockerEngineInstallURL,
		ArbitraryFlags:         engineFlags,
	})
	if err != nil {
		if m != nil {
			errRem := dockerMachine.DeleteMachine(m.Base)
			if errRem != nil {
				err = tsuruErrors.NewMultiError(err, errors.WithMessage(errRem, "failed to remove machine after error"))
			}
		}
		return nil, err
	}
	m.Base.CreationParams = params
	return m.Base, nil
}