예제 #1
0
파일: storage_lvm.go 프로젝트: rockstar/lxd
func (s *storageLvm) ContainerCreateFromImage(
	container container, imageFingerprint string) error {

	imageLVFilename := shared.VarPath(
		"images", fmt.Sprintf("%s.lv", imageFingerprint))

	if !shared.PathExists(imageLVFilename) {
		if err := s.ImageCreate(imageLVFilename); err != nil {
			return err
		}
	}

	containerName := containerNameToLVName(container.Name())

	lvpath, err := s.createSnapshotLV(containerName, imageFingerprint, false)
	if err != nil {
		return err
	}

	destPath := container.Path("")
	if err := os.MkdirAll(destPath, 0755); err != nil {
		return fmt.Errorf("Error creating container directory: %v", err)
	}

	dst := shared.VarPath("containers", fmt.Sprintf("%s.lv", container.Name()))
	err = os.Symlink(lvpath, dst)
	if err != nil {
		return err
	}

	output, err := exec.Command("mount", "-o", "discard", lvpath, destPath).CombinedOutput()
	if err != nil {
		s.ContainerDelete(container)
		return fmt.Errorf("Error mounting snapshot LV: %v\noutput:'%s'", err, string(output))
	}

	if !container.IsPrivileged() {
		if err = s.shiftRootfs(container); err != nil {
			output, err2 := exec.Command("umount", destPath).CombinedOutput()
			if err2 != nil {
				return fmt.Errorf("Error in umount: '%s' while cleaning up after error in shiftRootfs: '%s'\n umount output: '%s'", err2, err, output)
			}
			s.ContainerDelete(container)
			return fmt.Errorf("Error in shiftRootfs: %v", err)
		}
	}

	err = container.TemplateApply("create")
	if err != nil {
		s.log.Error("Error in create template during ContainerCreateFromImage, continuing to unmount",
			log.Ctx{"err": err})
	}

	output, umounterr := exec.Command("umount", destPath).CombinedOutput()
	if umounterr != nil {
		return fmt.Errorf("Error unmounting '%s' after shiftRootfs: %v", destPath, umounterr)
	}

	return err
}
예제 #2
0
파일: db_update.go 프로젝트: ccsblueboy/lxd
func dbUpdateFromV30(currentVersion int, version int, d *Daemon) error {
	if d.MockMode {
		return nil
	}

	entries, err := ioutil.ReadDir(shared.VarPath("containers"))
	if err != nil {
		return err
	}

	for _, entry := range entries {
		if !shared.IsDir(shared.VarPath("containers", entry.Name(), "rootfs")) {
			continue
		}

		info, err := os.Stat(shared.VarPath("containers", entry.Name(), "rootfs"))
		if err != nil {
			return err
		}

		if int(info.Sys().(*syscall.Stat_t).Uid) == 0 {
			err := os.Chmod(shared.VarPath("containers", entry.Name()), 0700)
			if err != nil {
				return err
			}

			err = os.Chown(shared.VarPath("containers", entry.Name()), 0, 0)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
예제 #3
0
func containerPost(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]
	c, err := newLxdContainer(name, d)
	if err != nil {
		return SmartError(err)
	}

	buf, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return InternalError(err)
	}

	body := containerPostBody{}
	if err := json.Unmarshal(buf, &body); err != nil {
		return BadRequest(err)
	}

	if body.Migration {
		ws, err := migration.NewMigrationSource(c.c)
		if err != nil {
			return InternalError(err)
		}

		return AsyncResponseWithWs(ws, nil)
	} else {
		if c.c.Running() {
			return BadRequest(fmt.Errorf("renaming of running container not allowed"))
		}

		args := DbCreateContainerArgs{
			d:            d,
			name:         body.Name,
			ctype:        cTypeRegular,
			config:       c.config,
			profiles:     c.profiles,
			ephem:        c.ephemeral,
			baseImage:    c.config["volatile.baseImage"],
			architecture: c.architecture,
		}

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

		run := func() error {
			oldPath := fmt.Sprintf("%s/", shared.VarPath("lxc", c.name))
			newPath := fmt.Sprintf("%s/", shared.VarPath("lxc", body.Name))

			if err := os.Rename(oldPath, newPath); err != nil {
				return err
			}

			removeContainer(d, c.name)
			return nil
		}

		return AsyncResponse(shared.OperationWrap(run), nil)
	}
}
예제 #4
0
func btrfsCopyImage(hash string, name string, d *Daemon) error {
	dpath := shared.VarPath("lxc", name)
	imagefile := shared.VarPath("images", hash)
	subvol := fmt.Sprintf("%s.btrfs", imagefile)

	return exec.Command("btrfs", "subvolume", "snapshot", subvol, dpath).Run()
}
예제 #5
0
파일: images.go 프로젝트: vahe/lxd
func imageBuildFromInfo(d *Daemon, info shared.ImageInfo) (metadata map[string]string, err error) {
	err = d.Storage.ImageCreate(info.Fingerprint)
	if err != nil {
		os.Remove(shared.VarPath("images", info.Fingerprint))
		os.Remove(shared.VarPath("images", info.Fingerprint) + ".rootfs")

		return metadata, err
	}

	err = dbImageInsert(
		d.db,
		info.Fingerprint,
		info.Filename,
		info.Size,
		info.Public,
		info.AutoUpdate,
		info.Architecture,
		info.CreationDate,
		info.ExpiryDate,
		info.Properties)
	if err != nil {
		return metadata, err
	}

	metadata = make(map[string]string)
	metadata["fingerprint"] = info.Fingerprint
	metadata["size"] = strconv.FormatInt(info.Size, 10)

	return metadata, nil
}
예제 #6
0
파일: storage_zfs.go 프로젝트: ralic/lxd
func (s *storageZfs) ContainerSnapshotDelete(snapshotContainer container) error {
	fields := strings.SplitN(snapshotContainer.Name(), shared.SnapshotDelimiter, 2)
	cName := fields[0]
	snapName := fmt.Sprintf("snapshot-%s", fields[1])

	removable, err := s.zfsSnapshotRemovable(fmt.Sprintf("containers/%s", cName), snapName)
	if removable {
		err = s.zfsSnapshotDestroy(fmt.Sprintf("containers/%s", cName), snapName)
		if err != nil {
			return err
		}
	} else {
		err = s.zfsSnapshotRename(fmt.Sprintf("containers/%s", cName), snapName, fmt.Sprintf("copy-%s", uuid.NewV4().String()))
		if err != nil {
			return err
		}
	}

	err = os.Remove(shared.VarPath(fmt.Sprintf("snapshots/%s/%s.zfs", cName, fields[1])))
	if err != nil {
		return err
	}

	parent := shared.VarPath(fmt.Sprintf("snapshots/%s", cName))
	if ok, _ := shared.PathIsEmpty(parent); ok {
		err = os.Remove(parent)
		if err != nil {
			return err
		}
	}

	return nil
}
예제 #7
0
파일: container.go 프로젝트: vahe/lxd
// Helper functions
func containerPath(name string, isSnapshot bool) string {
	if isSnapshot {
		return shared.VarPath("snapshots", name)
	}

	return shared.VarPath("containers", name)
}
예제 #8
0
파일: storage_zfs.go 프로젝트: ralic/lxd
func (s *storageZfs) ContainerRename(container container, newName string) error {
	oldName := container.Name()

	err := s.zfsRename(fmt.Sprintf("containers/%s", oldName), fmt.Sprintf("containers/%s", newName))
	if err != nil {
		return err
	}

	err = s.zfsSet(fmt.Sprintf("containers/%s", newName), "mountpoint", shared.VarPath(fmt.Sprintf("containers/%s", newName)))
	if err != nil {
		return err
	}

	err = os.Rename(shared.VarPath(fmt.Sprintf("containers/%s.zfs", oldName)), shared.VarPath(fmt.Sprintf("containers/%s.zfs", newName)))
	if err != nil {
		return err
	}

	err = os.Remove(shared.VarPath(fmt.Sprintf("containers/%s", oldName)))
	if err != nil {
		return err
	}

	return nil
}
예제 #9
0
파일: db_update.go 프로젝트: vahe/lxd
func dbUpdatesApplyAll(d *Daemon) error {
	currentVersion := dbGetSchema(d.db)

	backup := false
	for _, update := range dbUpdates {
		if update.version <= currentVersion {
			continue
		}

		if !d.MockMode && !backup {
			shared.LogInfof("Updating the LXD database schema. Backup made as \"lxd.db.bak\"")
			err := shared.FileCopy(shared.VarPath("lxd.db"), shared.VarPath("lxd.db.bak"))
			if err != nil {
				return err
			}

			backup = true
		}

		err := update.apply(currentVersion, d)
		if err != nil {
			return err
		}

		currentVersion = update.version
	}

	return nil
}
예제 #10
0
파일: storage_zfs.go 프로젝트: ralic/lxd
func (s *storageZfs) ImageDelete(fingerprint string) error {
	fs := fmt.Sprintf("images/%s", fingerprint)

	removable, err := s.zfsSnapshotRemovable(fs, "readonly")

	if err != nil {
		return err
	}

	if removable {
		err := s.zfsDestroy(fs)
		if err != nil {
			return err
		}
	} else {
		err := s.zfsSet(fs, "mountpoint", "none")
		if err != nil {
			return err
		}

		err = s.zfsRename(fs, fmt.Sprintf("deleted/%s", fs))
		if err != nil {
			return err
		}
	}

	if shared.PathExists(shared.VarPath(fs + ".zfs")) {
		os.Remove(shared.VarPath(fs + ".zfs"))
	}
	return nil
}
예제 #11
0
파일: container_new.go 프로젝트: RuneTM/lxd
func (c *lxdContainer) PathGet() string {
	if c.IsSnapshot() {
		return shared.VarPath("snapshots", c.NameGet())
	}

	return shared.VarPath("containers", c.NameGet())
}
예제 #12
0
파일: containers.go 프로젝트: Ramzec/lxd
/*
 * Export the container under @dir.  It will look like:
 * dir/
 *     metadata.yaml
 *     rootfs/
 */
func (d *lxdContainer) exportToDir(snap, dir string) error {
	if snap != "" && d.c.Running() {
		return fmt.Errorf("Cannot export a running container as image")
	}

	source := shared.VarPath("lxc", d.name, "metadata.yaml")
	dest := fmt.Sprintf("%s/metadata.yaml", dir)
	if shared.PathExists(source) {
		if err := shared.CopyFile(dest, source); err != nil {
			return err
		}
	}

	if snap != "" {
		source = snapshotRootfsDir(d, snap)
	} else {
		source = shared.VarPath("lxc", d.name, "rootfs")
	}

	// rsync the rootfs
	err := exec.Command("rsync", "-a", "--devices", source, dir).Run()
	if err != nil {
		return err
	}

	// unshift
	if !d.isPrivileged() {
		rootfs := fmt.Sprintf("%s/rootfs", dir)
		err = d.idmapset.UnshiftRootfs(rootfs)
	}
	return err
}
예제 #13
0
파일: images.go 프로젝트: Ramzec/lxd
// Copy imagefile and btrfs file out of the tmpdir
func pullOutImagefiles(d *Daemon, builddir string, fingerprint string) error {
	imagefname := filepath.Join(builddir, fingerprint)
	finalName := shared.VarPath("images", fingerprint)

	err := os.Rename(imagefname, finalName)
	if err != nil {
		return err
	}

	lvsymlink := fmt.Sprintf("%s.lv", imagefname)
	if _, err := os.Stat(lvsymlink); err == nil {
		dst := shared.VarPath("images", fmt.Sprintf("%s.lv", fingerprint))
		return os.Rename(lvsymlink, dst)
	}

	switch d.BackingFs {
	case "btrfs":
		subvol := fmt.Sprintf("%s.btrfs", imagefname)
		dst := shared.VarPath("images", fmt.Sprintf("%s.btrfs", fingerprint))
		if err := os.Rename(subvol, dst); err != nil {
			return err
		}
	}

	return nil
}
예제 #14
0
func (s *storageLvm) ImageCreate(fingerprint string) error {
	finalName := shared.VarPath("images", fingerprint)

	lvpath, err := s.createThinLV(fingerprint)
	if err != nil {
		s.log.Error("LVMCreateThinLV", log.Ctx{"err": err})
		return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
	}

	dst := shared.VarPath("images", fmt.Sprintf("%s.lv", fingerprint))
	err = os.Symlink(lvpath, dst)
	if err != nil {
		return err
	}

	tempLVMountPoint, err := ioutil.TempDir(shared.VarPath("images"), "tmp_lv_mnt")
	if err != nil {
		return err
	}
	defer func() {
		if err := os.RemoveAll(tempLVMountPoint); err != nil {
			s.log.Error("Deleting temporary LVM mount point", log.Ctx{"err": err})
		}
	}()

	var fstype string
	fstype, err = s.d.ConfigValueGet("storage.lvm_fstype")
	if err != nil {
		return fmt.Errorf("Error checking server config, err=%v", err)
	}

	if fstype == "" {
		fstype = "ext4"
	}

	err = s.tryMount(lvpath, tempLVMountPoint, fstype, 0, "discard")
	if err != nil {
		shared.Logf("Error mounting image LV for untarring: %v", err)
		return fmt.Errorf("Error mounting image LV: %v", err)

	}

	untarErr := untarImage(finalName, tempLVMountPoint)

	err = s.tryUnmount(tempLVMountPoint, 0)
	if err != nil {
		s.log.Warn("could not unmount LV. Will not remove",
			log.Ctx{"lvpath": lvpath, "mountpoint": tempLVMountPoint, "err": err})
		if untarErr == nil {
			return err
		}

		return fmt.Errorf(
			"Error unmounting '%s' during cleanup of error %v",
			tempLVMountPoint, untarErr)
	}

	return untarErr
}
예제 #15
0
파일: daemon.go 프로젝트: akshaykarle/lxd
func readMyCert() (string, string, error) {
	certf := shared.VarPath("server.crt")
	keyf := shared.VarPath("server.key")
	shared.LogDebug("Looking for existing certificates", log.Ctx{"cert": certf, "key": keyf})
	err := shared.FindOrGenCert(certf, keyf, false)

	return certf, keyf, err
}
예제 #16
0
func (c *lxdContainer) PathGet() string {
	if c.IsSnapshot() {
		snappieces := strings.SplitN(c.NameGet(), containerSnapshotDelimiter, 2)
		return shared.VarPath("lxc", snappieces[0], "snapshots", snappieces[1])
	}

	return shared.VarPath("lxc", c.NameGet())
}
예제 #17
0
파일: images.go 프로젝트: joker042/lxd
func imageDelete(d *Daemon, r *http.Request) Response {
	fingerprint := mux.Vars(r)["fingerprint"]

	imgInfo, err := dbImageGet(d.db, fingerprint, false)
	if err != nil {
		return SmartError(err)
	}

	fname := shared.VarPath("images", imgInfo.Fingerprint)
	err = os.Remove(fname)
	if err != nil {
		shared.Debugf("Error deleting image file %s: %s\n", fname, err)
	}

	fmetaname := shared.VarPath("images", imgInfo.Fingerprint+".rootfs")
	if shared.PathExists(fmetaname) {
		err = os.Remove(fmetaname)
		if err != nil {
			shared.Debugf("Error deleting image file %s: %s\n", fmetaname, err)
		}
	}

	vgname, vgnameIsSet, err := getServerConfigValue(d, "core.lvm_vg_name")
	if err != nil {
		return InternalError(fmt.Errorf("Error checking server config: %v", err))
	}

	if vgnameIsSet {
		err = shared.LVMRemoveLV(vgname, imgInfo.Fingerprint)
		if err != nil {
			return InternalError(fmt.Errorf("Failed to remove deleted image LV: %v", err))
		}

		lvsymlink := fmt.Sprintf("%s.lv", fname)
		err = os.Remove(lvsymlink)
		if err != nil {
			return InternalError(fmt.Errorf("Failed to remove symlink to deleted image LV: '%s': %v", lvsymlink, err))
		}
	} else if d.BackingFs == "btrfs" {
		subvol := fmt.Sprintf("%s.btrfs", fname)
		btrfsDeleteSubvol(subvol)
	}

	tx, err := dbBegin(d.db)
	if err != nil {
		return InternalError(err)
	}

	_, _ = tx.Exec("DELETE FROM images_aliases WHERE image_id=?", imgInfo.Id)
	_, _ = tx.Exec("DELETE FROM images_properties WHERE image_id?", imgInfo.Id)
	_, _ = tx.Exec("DELETE FROM images WHERE id=?", imgInfo.Id)

	if err := txCommit(tx); err != nil {
		return InternalError(err)
	}

	return EmptySyncResponse
}
예제 #18
0
파일: daemon.go 프로젝트: Ramzec/lxd
func readMyCert() (string, string, error) {
	certf := shared.VarPath("server.crt")
	keyf := shared.VarPath("server.key")
	shared.Debugf("looking for existing certificates: %s %s", certf, keyf)

	err := shared.FindOrGenCert(certf, keyf)

	return certf, keyf, err
}
예제 #19
0
파일: storage.go 프로젝트: RuneTM/lxd
func storageForContainer(d *Daemon, container *lxdContainer) (storage, error) {
	var cpath string
	if container.IsSnapshot() {
		cpath = shared.VarPath("snapshots", container.name)
	} else {
		cpath = shared.VarPath("containers", container.name)
	}
	return storageForFilename(d, cpath)
}
예제 #20
0
func (s *storageZfs) zfsClone(source string, name string, dest string, dotZfs bool) error {
	var mountpoint string

	mountpoint = shared.VarPath(dest)
	if dotZfs {
		mountpoint += ".zfs"
	}

	output, err := exec.Command(
		"zfs",
		"clone",
		"-p",
		"-o", fmt.Sprintf("mountpoint=%s", mountpoint),
		fmt.Sprintf("%s/%s@%s", s.zfsPool, source, name),
		fmt.Sprintf("%s/%s", s.zfsPool, dest)).CombinedOutput()
	if err != nil {
		s.log.Error("zfs clone failed", log.Ctx{"output": string(output)})
		return fmt.Errorf("Failed to clone the filesystem: %s", output)
	}

	subvols, err := s.zfsListSubvolumes(source)
	if err != nil {
		return err
	}

	for _, sub := range subvols {
		snaps, err := s.zfsListSnapshots(sub)
		if err != nil {
			return err
		}

		if !shared.StringInSlice(name, snaps) {
			continue
		}

		destSubvol := dest + strings.TrimPrefix(sub, source)
		mountpoint = shared.VarPath(destSubvol)
		if dotZfs {
			mountpoint += ".zfs"
		}

		output, err := exec.Command(
			"zfs",
			"clone",
			"-p",
			"-o", fmt.Sprintf("mountpoint=%s", mountpoint),
			fmt.Sprintf("%s/%s@%s", s.zfsPool, sub, name),
			fmt.Sprintf("%s/%s", s.zfsPool, destSubvol)).CombinedOutput()
		if err != nil {
			s.log.Error("zfs clone failed", log.Ctx{"output": string(output)})
			return fmt.Errorf("Failed to clone the sub-volume: %s", output)
		}
	}

	return nil
}
예제 #21
0
func (s *storageZfs) Init(config map[string]interface{}) (storage, error) {
	s.sType = storageTypeZfs
	s.sTypeName = storageTypeToString(s.sType)

	err := s.initShared()
	if err != nil {
		return s, err
	}

	if config["zfsPool"] == nil {
		zfsPool, err := s.d.ConfigValueGet("storage.zfs_pool_name")
		if err != nil {
			return s, fmt.Errorf("Error checking server config: %v", err)
		}

		if zfsPool == "" {
			return s, fmt.Errorf("ZFS isn't enabled")
		}

		s.zfsPool = zfsPool
	} else {
		s.zfsPool = config["zfsPool"].(string)
	}

	out, err := exec.LookPath("zfs")
	if err != nil || len(out) == 0 {
		return s, fmt.Errorf("The 'zfs' tool isn't available")
	}

	err = s.zfsCheckPool(s.zfsPool)
	if err != nil {
		if shared.PathExists(shared.VarPath("zfs.img")) {
			_, _ = exec.Command("modprobe", "zfs").CombinedOutput()

			output, err := exec.Command("zpool", "import",
				"-d", shared.VarPath(), s.zfsPool).CombinedOutput()
			if err != nil {
				return s, fmt.Errorf("Unable to import the ZFS pool: %s", output)
			}
		} else {
			return s, err
		}
	}

	output, err := exec.Command("zfs", "get", "version", "-H", "-o", "value", s.zfsPool).CombinedOutput()
	if err != nil {
		return s, fmt.Errorf("The 'zfs' tool isn't working properly")
	}

	count, err := fmt.Sscanf(string(output), "%s\n", &s.sTypeVersion)
	if err != nil || count != 1 {
		return s, fmt.Errorf("The 'zfs' tool isn't working properly")
	}

	return s, nil
}
예제 #22
0
파일: storage_lvm.go 프로젝트: vahe/lxd
func (s *storageLvm) ImageCreate(fingerprint string) error {
	finalName := shared.VarPath("images", fingerprint)

	lvpath, err := s.createThinLV(fingerprint)
	if err != nil {
		s.log.Error("LVMCreateThinLV", log.Ctx{"err": err})
		return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
	}

	dst := shared.VarPath("images", fmt.Sprintf("%s.lv", fingerprint))
	err = os.Symlink(lvpath, dst)
	if err != nil {
		return err
	}

	tempLVMountPoint, err := ioutil.TempDir(shared.VarPath("images"), "tmp_lv_mnt")
	if err != nil {
		return err
	}
	defer func() {
		if err := os.RemoveAll(tempLVMountPoint); err != nil {
			s.log.Error("Deleting temporary LVM mount point", log.Ctx{"err": err})
		}
	}()

	fstype := daemonConfig["storage.lvm_fstype"].Get()
	mountOptions := daemonConfig["storage.lvm_mount_options"].Get()
	err = tryMount(lvpath, tempLVMountPoint, fstype, 0, mountOptions)
	if err != nil {
		shared.LogInfof("Error mounting image LV for unpacking: %v", err)
		return fmt.Errorf("Error mounting image LV: %v", err)
	}

	unpackErr := unpackImage(s.d, finalName, tempLVMountPoint)

	err = tryUnmount(tempLVMountPoint, 0)
	if err != nil {
		s.log.Warn("could not unmount LV. Will not remove",
			log.Ctx{"lvpath": lvpath, "mountpoint": tempLVMountPoint, "err": err})
		if unpackErr == nil {
			return err
		}

		return fmt.Errorf(
			"Error unmounting '%s' during cleanup of error %v",
			tempLVMountPoint, unpackErr)
	}

	if unpackErr != nil {
		s.removeLV(fingerprint)
		return unpackErr
	}

	return nil
}
예제 #23
0
파일: db_update.go 프로젝트: vahe/lxd
func dbUpdateFromV15(currentVersion int, version int, d *Daemon) error {
	// munge all LVM-backed containers' LV names to match what is
	// required for snapshot support

	cNames, err := dbContainersList(d.db, cTypeRegular)
	if err != nil {
		return err
	}

	err = daemonConfigInit(d.db)
	if err != nil {
		return err
	}

	vgName := daemonConfig["storage.lvm_vg_name"].Get()

	for _, cName := range cNames {
		var lvLinkPath string
		if strings.Contains(cName, shared.SnapshotDelimiter) {
			lvLinkPath = shared.VarPath("snapshots", fmt.Sprintf("%s.lv", cName))
		} else {
			lvLinkPath = shared.VarPath("containers", fmt.Sprintf("%s.lv", cName))
		}

		if !shared.PathExists(lvLinkPath) {
			continue
		}

		newLVName := strings.Replace(cName, "-", "--", -1)
		newLVName = strings.Replace(newLVName, shared.SnapshotDelimiter, "-", -1)

		if cName == newLVName {
			shared.LogDebug("No need to rename, skipping", log.Ctx{"cName": cName, "newLVName": newLVName})
			continue
		}

		shared.LogDebug("About to rename cName in lv upgrade", log.Ctx{"lvLinkPath": lvLinkPath, "cName": cName, "newLVName": newLVName})

		output, err := exec.Command("lvrename", vgName, cName, newLVName).CombinedOutput()
		if err != nil {
			return fmt.Errorf("Could not rename LV '%s' to '%s': %v\noutput:%s", cName, newLVName, err, string(output))
		}

		if err := os.Remove(lvLinkPath); err != nil {
			return fmt.Errorf("Couldn't remove lvLinkPath '%s'", lvLinkPath)
		}
		newLinkDest := fmt.Sprintf("/dev/%s/%s", vgName, newLVName)
		if err := os.Symlink(newLinkDest, lvLinkPath); err != nil {
			return fmt.Errorf("Couldn't recreate symlink '%s'->'%s'", lvLinkPath, newLinkDest)
		}
	}

	return nil
}
예제 #24
0
func dbUpdateFromV15(d *Daemon) error {
	// munge all LVM-backed containers' LV names to match what is
	// required for snapshot support

	cNames, err := dbContainersList(d.db, cTypeRegular)
	if err != nil {
		return err
	}

	vgName, err := d.ConfigValueGet("storage.lvm_vg_name")
	if err != nil {
		return fmt.Errorf("Error checking server config: %v", err)
	}

	for _, cName := range cNames {
		var lvLinkPath string
		if strings.Contains(cName, shared.SnapshotDelimiter) {
			lvLinkPath = shared.VarPath("snapshots", fmt.Sprintf("%s.lv", cName))
		} else {
			lvLinkPath = shared.VarPath("containers", fmt.Sprintf("%s.lv", cName))
		}

		if !shared.PathExists(lvLinkPath) {
			continue
		}

		newLVName := strings.Replace(cName, "-", "--", -1)
		newLVName = strings.Replace(newLVName, shared.SnapshotDelimiter, "-", -1)

		if cName == newLVName {
			shared.Log.Debug("No need to rename, skipping", log.Ctx{"cName": cName, "newLVName": newLVName})
			continue
		}

		shared.Log.Debug("About to rename cName in lv upgrade", log.Ctx{"lvLinkPath": lvLinkPath, "cName": cName, "newLVName": newLVName})

		output, err := exec.Command("lvrename", vgName, cName, newLVName).CombinedOutput()
		if err != nil {
			return fmt.Errorf("Could not rename LV '%s' to '%s': %v\noutput:%s", cName, newLVName, err, string(output))
		}

		if err := os.Remove(lvLinkPath); err != nil {
			return fmt.Errorf("Couldn't remove lvLinkPath '%s'", lvLinkPath)
		}
		newLinkDest := fmt.Sprintf("/dev/%s/%s", vgName, newLVName)
		if err := os.Symlink(newLinkDest, lvLinkPath); err != nil {
			return fmt.Errorf("Couldn't recreate symlink '%s'->'%s'", lvLinkPath, newLinkDest)
		}
	}
	stmt := `
INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));`
	_, err = d.db.Exec(stmt, 16)
	return err
}
예제 #25
0
func (s *storageLvm) ImageCreate(fingerprint string) error {
	finalName := shared.VarPath("images", fingerprint)

	lvpath, err := s.createThinLV(fingerprint)
	if err != nil {
		s.log.Error("LVMCreateThinLV", log.Ctx{"err": err})
		return fmt.Errorf("Error Creating LVM LV for new image: %v", err)
	}

	dst := shared.VarPath("images", fmt.Sprintf("%s.lv", fingerprint))
	err = os.Symlink(lvpath, dst)
	if err != nil {
		return err
	}

	tempLVMountPoint, err := ioutil.TempDir(shared.VarPath("images"), "tmp_lv_mnt")
	if err != nil {
		return err
	}
	defer func() {
		if err := os.RemoveAll(tempLVMountPoint); err != nil {
			s.log.Error("Deleting temporary LVM mount point", log.Ctx{"err": err})
		}
	}()

	output, err := exec.Command(
		"mount",
		"-o", "discard",
		lvpath,
		tempLVMountPoint).CombinedOutput()

	if err != nil {
		shared.Logf("Error mounting image LV for untarring: '%s'", string(output))
		return fmt.Errorf("Error mounting image LV: %v", err)

	}

	untarErr := untarImage(finalName, tempLVMountPoint)

	output, err = exec.Command("umount", tempLVMountPoint).CombinedOutput()
	if err != nil {
		s.log.Warn("could not unmount LV. Will not remove",
			log.Ctx{"lvpath": lvpath, "mountpoint": tempLVMountPoint, "err": err})
		if untarErr == nil {
			return err
		}

		return fmt.Errorf(
			"Error unmounting '%s' during cleanup of error %v",
			tempLVMountPoint, untarErr)
	}

	return untarErr
}
예제 #26
0
func (s *storageZfs) ContainerRename(container container, newName string) error {
	oldName := container.Name()

	// Unmount the filesystem
	err := s.zfsUnmount(fmt.Sprintf("containers/%s", oldName))
	if err != nil {
		return err
	}

	// Rename the filesystem
	err = s.zfsRename(fmt.Sprintf("containers/%s", oldName), fmt.Sprintf("containers/%s", newName))
	if err != nil {
		return err
	}

	// Update to the new mountpoint
	err = s.zfsSet(fmt.Sprintf("containers/%s", newName), "mountpoint", shared.VarPath(fmt.Sprintf("containers/%s.zfs", newName)))
	if err != nil {
		return err
	}

	// In case ZFS didn't mount the filesystem, do it ourselves
	err = s.zfsMount(fmt.Sprintf("containers/%s", newName))
	if err != nil {
		return err
	}

	// In case the change of mountpoint didn't remove the old path, do it ourselves
	if shared.PathExists(shared.VarPath(fmt.Sprintf("containers/%s.zfs", oldName))) {
		err = os.Remove(shared.VarPath(fmt.Sprintf("containers/%s.zfs", oldName)))
		if err != nil {
			return err
		}
	}

	// Remove the old symlink
	err = os.Remove(shared.VarPath(fmt.Sprintf("containers/%s", oldName)))
	if err != nil {
		return err
	}

	// Create a new symlink
	err = os.Symlink(shared.VarPath(fmt.Sprintf("containers/%s.zfs", newName)), shared.VarPath(fmt.Sprintf("containers/%s", newName)))
	if err != nil {
		return err
	}

	// Rename the snapshot path
	if shared.PathExists(shared.VarPath(fmt.Sprintf("snapshots/%s", oldName))) {
		err = os.Rename(shared.VarPath(fmt.Sprintf("snapshots/%s", oldName)), shared.VarPath(fmt.Sprintf("snapshots/%s", newName)))
		if err != nil {
			return err
		}
	}

	return nil
}
예제 #27
0
파일: db_update.go 프로젝트: vahe/lxd
func dbUpdateFromV29(currentVersion int, version int, d *Daemon) error {
	if d.MockMode {
		return nil
	}

	if shared.PathExists(shared.VarPath("zfs.img")) {
		err := os.Chmod(shared.VarPath("zfs.img"), 0600)
		if err != nil {
			return err
		}
	}

	return nil
}
예제 #28
0
func storageLVMGetThinPoolUsers(d *Daemon) ([]string, error) {
	results := []string{}
	vgname, err := d.ConfigValueGet("storage.lvm_vg_name")
	if err != nil {
		return results, fmt.Errorf("Error getting lvm_vg_name config")
	}
	if vgname == "" {
		return results, nil
	}
	poolname, err := d.ConfigValueGet("storage.lvm_thinpool_name")
	if err != nil {
		return results, fmt.Errorf("Error getting lvm_thinpool_name config")
	}
	if poolname == "" {
		return results, nil
	}

	cNames, err := dbContainersList(d.db, cTypeRegular)
	if err != nil {
		return results, err
	}
	for _, cName := range cNames {
		var lvLinkPath string
		if strings.Contains(cName, shared.SnapshotDelimiter) {
			lvLinkPath = shared.VarPath("snapshots", fmt.Sprintf("%s.lv", cName))
		} else {
			lvLinkPath = shared.VarPath("containers", fmt.Sprintf("%s.lv", cName))
		}

		if shared.PathExists(lvLinkPath) {
			results = append(results, cName)
		}
	}

	imageNames, err := dbImagesGet(d.db, false)
	if err != nil {
		return results, err
	}

	for _, imageName := range imageNames {
		imageLinkPath := shared.VarPath("images", fmt.Sprintf("%s.lv", imageName))
		if shared.PathExists(imageLinkPath) {
			results = append(results, imageName)
		}
	}

	return results, nil

}
예제 #29
0
func (suite *lxdTestSuite) TestContainer_Path_Regular() {
	// Regular
	args := containerLXDArgs{
		Ctype:     cTypeRegular,
		Ephemeral: false,
	}

	c, err := containerLXDCreateInternal(suite.d, "testFoo", args)
	suite.Req.Nil(err)
	defer c.Delete()

	suite.Req.False(c.IsSnapshot(), "Shouldn't be a snapshot.")
	suite.Req.Equal(shared.VarPath("containers", "testFoo"), c.Path(""))
	suite.Req.Equal(shared.VarPath("containers", "testFoo2"), c.Path("testFoo2"))
}
예제 #30
0
파일: storage_lvm.go 프로젝트: rcj4747/lxd
func (s *storageLvm) ContainerCreateFromImage(
	container container, imageFingerprint string) error {

	imageLVFilename := shared.VarPath(
		"images", fmt.Sprintf("%s.lv", imageFingerprint))

	if !shared.PathExists(imageLVFilename) {
		if err := s.ImageCreate(imageLVFilename); err != nil {
			return err
		}
	}

	lvpath, err := s.createSnapshotLV(container.NameGet(), imageFingerprint)
	if err != nil {
		return err
	}

	destPath := container.PathGet("")
	if err := os.MkdirAll(destPath, 0755); err != nil {
		return fmt.Errorf("Error creating container directory: %v", err)
	}

	dst := shared.VarPath("containers", fmt.Sprintf("%s.lv", container.NameGet()))
	err = os.Symlink(lvpath, dst)
	if err != nil {
		return err
	}

	if !container.IsPrivileged() {
		output, err := exec.Command("mount", "-o", "discard", lvpath, destPath).CombinedOutput()
		if err != nil {
			s.ContainerDelete(container)
			return fmt.Errorf("Error mounting snapshot LV: %v\noutput:'%s'", err, output)
		}

		if err = s.shiftRootfs(container); err != nil {
			s.ContainerDelete(container)
			return fmt.Errorf("Error in shiftRootfs: %v", err)
		}

		output, err = exec.Command("umount", destPath).CombinedOutput()
		if err != nil {
			return fmt.Errorf("Error unmounting '%s' after shiftRootfs: %v", destPath, err)
		}
	}

	return container.TemplateApply("create")
}