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 }
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 }
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) } }
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() }
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 }
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 }
// Helper functions func containerPath(name string, isSnapshot bool) string { if isSnapshot { return shared.VarPath("snapshots", name) } return shared.VarPath("containers", name) }
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 }
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 }
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 }
func (c *lxdContainer) PathGet() string { if c.IsSnapshot() { return shared.VarPath("snapshots", c.NameGet()) } return shared.VarPath("containers", c.NameGet()) }
/* * 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 }
// 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 }
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 }
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 }
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()) }
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 }
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 }
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) }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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")) }
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") }