Example #1
0
func createFromMigration(d *Daemon, req *containerPostReq) Response {
	if req.Source.Mode != "pull" {
		return NotImplemented
	}

	createArgs := DbCreateContainerArgs{
		d:         d,
		name:      req.Name,
		ctype:     cTypeRegular,
		config:    req.Config,
		profiles:  req.Profiles,
		ephem:     req.Ephemeral,
		baseImage: req.Source.BaseImage,
	}

	_, err := dbCreateContainer(createArgs)
	if err != nil {
		return SmartError(err)
	}

	c, err := newLxdContainer(req.Name, d)
	if err != nil {
		removeContainer(d, req.Name)
		return SmartError(err)
	}

	// rsync complaisn if the parent directory for the rootfs sync doesn't
	// exist
	dpath := shared.VarPath("lxc", req.Name)
	if err := os.MkdirAll(dpath, 0700); err != nil {
		removeContainer(d, req.Name)
		return InternalError(err)
	}

	if err := extractShiftIfExists(d, c, req.Source.BaseImage, req.Name); err != nil {
		removeContainer(d, req.Name)
		return InternalError(err)
	}

	config, err := shared.GetTLSConfig(d.certf, d.keyf)
	if err != nil {
		removeContainer(d, req.Name)
		return InternalError(err)
	}

	args := migration.MigrationSinkArgs{
		Url: req.Source.Operation,
		Dialer: websocket.Dialer{
			TLSClientConfig: config,
			NetDial:         shared.RFC3493Dialer},
		Container: c.c,
		Secrets:   req.Source.Websockets,
		IdMapSet:  c.idmapset,
	}

	sink, err := migration.NewMigrationSink(&args)
	if err != nil {
		removeContainer(d, req.Name)
		return BadRequest(err)
	}

	run := func() shared.OperationResult {
		err := sink()
		if err != nil {
			removeContainer(d, req.Name)
			return shared.OperationError(err)
		}

		c, err := newLxdContainer(req.Name, d)
		if err != nil {
			return shared.OperationError(err)
		}

		err = templateApply(c, "copy")
		if err != nil {
			return shared.OperationError(err)
		}

		return shared.OperationError(nil)
	}

	resources := make(map[string][]string)
	resources["containers"] = []string{req.Name}

	return &asyncResponse{run: run, resources: resources}
}
Example #2
0
func createFromMigration(d *Daemon, req *containerPostReq) Response {
	if req.Source.Mode != "pull" {
		return NotImplemented
	}

	run := func() shared.OperationResult {
		createArgs := containerLXDArgs{
			Ctype:     cTypeRegular,
			Config:    req.Config,
			Profiles:  req.Profiles,
			Ephemeral: req.Ephemeral,
			BaseImage: req.Source.BaseImage,
		}

		var c container
		if _, err := dbImageGet(d.db, req.Source.BaseImage, false, true); err == nil {
			c, err = containerLXDCreateFromImage(
				d, req.Name, createArgs, req.Source.BaseImage)

			if err != nil {
				return shared.OperationError(err)
			}
		} else {
			c, err = containerLXDCreateAsEmpty(d, req.Name, createArgs)
			if err != nil {
				return shared.OperationError(err)
			}
		}

		config, err := shared.GetTLSConfig(d.certf, d.keyf)
		if err != nil {
			c.Delete()
			return shared.OperationError(err)
		}

		lxContainer, err := c.LXContainerGet()
		if err != nil {
			c.Delete()
			return shared.OperationError(err)
		}
		idmapset, err := c.IdmapSetGet()
		if err != nil {
			c.Delete()
			return shared.OperationError(err)
		}
		args := migration.MigrationSinkArgs{
			Url: req.Source.Operation,
			Dialer: websocket.Dialer{
				TLSClientConfig: config,
				NetDial:         shared.RFC3493Dialer},
			Container: lxContainer,
			Secrets:   req.Source.Websockets,
			IdMapSet:  idmapset,
		}

		sink, err := migration.NewMigrationSink(&args)
		if err != nil {
			c.Delete()
			return shared.OperationError(err)
		}

		// Start the storage for this container (LVM mount/umount)
		c.StorageStart()
		defer c.StorageStop()

		// And finaly run the migration.
		err = sink()
		if err != nil {
			c.Delete()
			return shared.OperationError(err)
		}

		err = c.TemplateApply("copy")
		if err != nil {
			return shared.OperationError(err)
		}

		return shared.OperationError(nil)
	}

	resources := make(map[string][]string)
	resources["containers"] = []string{req.Name}

	return &asyncResponse{run: run, resources: resources}
}