func unpackImage(d *Daemon, imagefname string, destpath string) error { err := unpack(d, imagefname, destpath) if err != nil { return err } rootfsPath := fmt.Sprintf("%s/rootfs", destpath) if shared.PathExists(imagefname + ".rootfs") { err = os.MkdirAll(rootfsPath, 0755) if err != nil { return fmt.Errorf("Error creating rootfs directory") } err = unpack(d, imagefname+".rootfs", rootfsPath) if err != nil { return err } } if !shared.PathExists(rootfsPath) { return fmt.Errorf("Image is missing a rootfs: %s", imagefname) } return nil }
// Copy imagefile and btrfs file out of the tmpdir func pullOutImagefiles(d *Daemon, builddir string, fingerprint string) error { imagefname := filepath.Join(builddir, fingerprint) imagerootfsfname := filepath.Join(builddir, fingerprint+".rootfs") finalName := shared.VarPath("images", fingerprint) finalrootfsName := shared.VarPath("images", fingerprint+".rootfs") if shared.PathExists(imagerootfsfname) { err := os.Rename(imagerootfsfname, finalrootfsName) if err != nil { return err } } err := os.Rename(imagefname, finalName) if err != nil { return err } lvsymlink := fmt.Sprintf("%s.lv", imagefname) if shared.PathExists(lvsymlink) { 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 storageForFilename(d *Daemon, filename string) (storage, error) { config := make(map[string]interface{}) storageType := storageTypeDir if d.IsMock { return newStorageWithConfig(d, storageTypeMock, config) } filesystem, err := filesystemDetect(filename) if err != nil { return nil, fmt.Errorf("couldn't detect filesystem for '%s': %v", filename, err) } if shared.PathExists(filename + ".lv") { storageType = storageTypeLvm lvPath, err := os.Readlink(filename + ".lv") if err != nil { return nil, fmt.Errorf("couldn't read link dest for '%s': %v", filename+".lv", err) } vgname := filepath.Base(filepath.Dir(lvPath)) config["vgName"] = vgname } else if shared.PathExists(filename + ".zfs") { storageType = storageTypeZfs } else if shared.PathExists(filename+".btrfs") || filesystem == "btrfs" { storageType = storageTypeBtrfs } return newStorageWithConfig(d, storageType, config) }
/* * Export the container to a unshifted tarfile containing: * dir/ * metadata.yaml * rootfs/ */ func (c *containerLXD) ExportToTar(snap string, w io.Writer) error { if snap == "" && c.IsRunning() { return fmt.Errorf("Cannot export a running container as image") } idmap, err := c.LastIdmapSetGet() if err != nil { return err } if idmap != nil { if err := idmap.UnshiftRootfs(c.RootfsPathGet()); err != nil { return err } defer idmap.ShiftRootfs(c.RootfsPathGet()) } tw := tar.NewWriter(w) // keep track of the first path we saw for each path with nlink>1 linkmap := map[uint64]string{} cDir := c.PathGet("") // Path inside the tar image is the pathname starting after cDir offset := len(cDir) + 1 writeToTar := func(path string, fi os.FileInfo, err error) error { if err := c.tarStoreFile(linkmap, offset, tw, path, fi); err != nil { shared.Debugf("Error tarring up %s: %s", path, err) return err } return nil } fnam := filepath.Join(cDir, "metadata.yaml") if shared.PathExists(fnam) { fi, err := os.Lstat(fnam) if err != nil { shared.Debugf("Error statting %s during exportToTar", fnam) tw.Close() return err } if err := c.tarStoreFile(linkmap, offset, tw, fnam, fi); err != nil { shared.Debugf("Error writing to tarfile: %s", err) tw.Close() return err } } fnam = filepath.Join(cDir, "rootfs") filepath.Walk(fnam, writeToTar) fnam = filepath.Join(cDir, "templates") if shared.PathExists(fnam) { filepath.Walk(fnam, writeToTar) } return tw.Close() }
func doNetworkGet(d *Daemon, name string) (shared.NetworkConfig, error) { // Get some information osInfo, _ := net.InterfaceByName(name) _, dbInfo, _ := dbNetworkGet(d.db, name) // Sanity check if osInfo == nil && dbInfo == nil { return shared.NetworkConfig{}, os.ErrNotExist } // Prepare the response n := shared.NetworkConfig{} n.Name = name n.UsedBy = []string{} n.Config = map[string]string{} // Look for containers using the interface cts, err := dbContainersList(d.db, cTypeRegular) if err != nil { return shared.NetworkConfig{}, err } for _, ct := range cts { c, err := containerLoadByName(d, ct) if err != nil { return shared.NetworkConfig{}, err } if networkIsInUse(c, n.Name) { n.UsedBy = append(n.UsedBy, fmt.Sprintf("/%s/containers/%s", shared.APIVersion, ct)) } } // Set the device type as needed if osInfo != nil && shared.IsLoopback(osInfo) { n.Type = "loopback" } else if dbInfo != nil || shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", n.Name)) { if dbInfo != nil { n.Managed = true n.Config = dbInfo.Config } n.Type = "bridge" } else if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/device", n.Name)) { n.Type = "physical" } else if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bonding", n.Name)) { n.Type = "bond" } else { _, err := exec.Command("ovs-vsctl", "br-exists", n.Name).CombinedOutput() if err == nil { n.Type = "bridge" } else { n.Type = "unknown" } } return n, nil }
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 providerConfigure(d *schema.ResourceData) (interface{}, error) { remote := d.Get("remote").(string) scheme := d.Get("scheme").(string) daemon_addr := "" switch scheme { case "unix": daemon_addr = fmt.Sprintf("unix:%s", d.Get("address")) case "https": daemon_addr = fmt.Sprintf("https://%s:%s", d.Get("address"), d.Get("port")) default: err := fmt.Errorf("Invalid scheme: %s", scheme) return nil, err } // build LXD config config := lxd.Config{ ConfigDir: os.ExpandEnv("$HOME/.config/lxc"), Remotes: make(map[string]lxd.RemoteConfig), } config.Remotes[remote] = lxd.RemoteConfig{Addr: daemon_addr} log.Printf("[DEBUG] LXD Config: %#v", config) if scheme == "https" { // validate certifictes exist certf := config.ConfigPath("client.crt") keyf := config.ConfigPath("client.key") if !shared.PathExists(certf) || !shared.PathExists(keyf) { err := fmt.Errorf("Certificate or key not found:\n\t%s\n\t%s", certf, keyf) return nil, err } serverCertf := config.ServerCertPath(remote) if !shared.PathExists(serverCertf) { err := fmt.Errorf("Server certificate not found:\n\t%s", serverCertf) return nil, err } } client, err := lxd.NewClient(&config, remote) if err != nil { err := fmt.Errorf("Could not create LXD client: %s", err) return nil, err } log.Printf("[DEBUG] LXD Client: %#v", client) if err := validateClient(client); err != nil { return nil, err } lxdProv := LxdProvider{ Remote: remote, Client: client, } return &lxdProv, nil }
func generateClientCertificate(config *lxd.Config) error { // Generate a client certificate if necessary. The default repositories are // either local or public, neither of which requires a client certificate. // Generation of the cert is delayed to avoid unnecessary overhead, e.g in // testing scenarios where only the default repositories are used. certf := config.ConfigPath("client.crt") keyf := config.ConfigPath("client.key") if !shared.PathExists(certf) || !shared.PathExists(keyf) { fmt.Fprintf(os.Stderr, i18n.G("Generating a client certificate. This may take a minute...")+"\n") return shared.FindOrGenCert(certf, keyf, true) } 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 }
/* * subvolSnapshot creates a snapshot of "source" to "dest" * the result will be readonly if "readonly" is True. */ func (s *storageBtrfs) subvolSnapshot( source string, dest string, readonly bool) error { parentDestPath := filepath.Dir(dest) if !shared.PathExists(parentDestPath) { if err := os.MkdirAll(parentDestPath, 0700); err != nil { return err } } if shared.PathExists(dest) { if err := os.Remove(dest); err != nil { return err } } var output []byte var err error if readonly { output, err = exec.Command( "btrfs", "subvolume", "snapshot", "-r", source, dest).CombinedOutput() } else { output, err = exec.Command( "btrfs", "subvolume", "snapshot", source, dest).CombinedOutput() } if err != nil { s.log.Error( "subvolume snapshot failed", log.Ctx{"source": source, "dest": dest, "output": string(output)}, ) return fmt.Errorf( "subvolume snapshot failed, source=%s, dest=%s, output=%s", source, dest, string(output), ) } return err }
/* * 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 }
func (s *storageDir) ContainerSnapshotRename( snapshotContainer container, newName string) error { oldPath := snapshotContainer.PathGet("") newPath := snapshotContainer.PathGet(newName) // Create the new parent. if strings.Contains(snapshotContainer.NameGet(), "/") { if !shared.PathExists(filepath.Dir(newPath)) { os.MkdirAll(filepath.Dir(newPath), 0700) } } // Now rename the snapshot. if err := os.Rename(oldPath, newPath); err != nil { return err } // Remove the old parent (on container rename) if its empty. if strings.Contains(snapshotContainer.NameGet(), "/") { if ok, _ := shared.PathIsEmpty(filepath.Dir(oldPath)); ok { os.Remove(filepath.Dir(oldPath)) } } return nil }
func (s *storageLvm) ContainerSnapshotStart(container container) error { srcName := containerNameToLVName(container.Name()) destName := containerNameToLVName(container.Name() + "/rw") shared.Log.Debug( "Creating snapshot", log.Ctx{"srcName": srcName, "destName": destName}) lvpath, err := s.createSnapshotLV(destName, srcName, false) if err != nil { return fmt.Errorf("Error creating snapshot LV: %v", err) } destPath := container.Path("") if !shared.PathExists(destPath) { if err := os.MkdirAll(destPath, 0755); err != nil { return fmt.Errorf("Error creating container directory: %v", err) } } output, err := exec.Command( "mount", "-o", "discard", lvpath, container.Path("")).CombinedOutput() if err != nil { return fmt.Errorf( "Error mounting snapshot LV path='%s': %v\noutput:'%s'", container.Path(""), err, string(output)) } return nil }
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 imageLoadStreamCache(d *Daemon) error { imageStreamCacheLock.Lock() defer imageStreamCacheLock.Unlock() if !shared.PathExists(shared.CachePath("simplestreams.yaml")) { return nil } content, err := ioutil.ReadFile(shared.CachePath("simplestreams.yaml")) if err != nil { return err } err = yaml.Unmarshal(content, imageStreamCache) if err != nil { return err } for url, entry := range imageStreamCache { if entry.ss == nil { ss, err := shared.SimpleStreamsClient(url, d.proxy) if err != nil { return err } entry.ss = ss } } return nil }
func loadModule(module string) error { if shared.PathExists(fmt.Sprintf("/sys/module/%s", module)) { return nil } return shared.RunCommand("modprobe", module) }
func snapshotPost(r *http.Request, c *lxdContainer, oldName string) Response { raw := shared.Jmap{} if err := json.NewDecoder(r.Body).Decode(&raw); err != nil { return BadRequest(err) } newName, err := raw.GetString("name") if err != nil { return BadRequest(err) } oldDir := snapshotDir(c, oldName) newDir := snapshotDir(c, newName) if shared.PathExists(newDir) { return Conflict } /* * TODO: do we need to do something more intelligent here? We probably * shouldn't do anything for stateful snapshots, since changing the fs * out from under criu will cause it to fail, but it may be useful to * do something for stateless ones. */ rename := func() error { return os.Rename(oldDir, newDir) } return AsyncResponse(shared.OperationWrap(rename), nil) }
func snapshotHandler(d *Daemon, r *http.Request) Response { containerName := mux.Vars(r)["name"] c, err := newLxdContainer(containerName, d) if err != nil { return SmartError(err) } snapshotName := mux.Vars(r)["snapshotName"] dir := snapshotDir(c, snapshotName) if !shared.PathExists(dir) { return NotFound } switch r.Method { case "GET": return snapshotGet(c, snapshotName) case "POST": return snapshotPost(r, c, snapshotName) case "DELETE": return snapshotDelete(d, c, snapshotName) default: return NotFound } }
func (s *storageBtrfs) ContainerCreate( container *lxdContainer, imageFingerprint string) error { imageSubvol := fmt.Sprintf( "%s.btrfs", shared.VarPath("images", imageFingerprint)) if !shared.PathExists(imageSubvol) { if err := s.ImageCreate(imageFingerprint); err != nil { return err } } err := s.subvolSnapshot(imageSubvol, container.PathGet(), false) if err != nil { return err } if !container.isPrivileged() { err = shiftRootfs(container, s.d) if err != nil { return err } } else { if err := os.Chmod(container.PathGet(), 0700); err != nil { return err } } return templateApply(container, "create") }
func (s *storageLvm) ContainerSnapshotStart(container container) error { srcName := containerNameToLVName(container.Name()) destName := containerNameToLVName(container.Name() + "/rw") shared.Log.Debug( "Creating snapshot", log.Ctx{"srcName": srcName, "destName": destName}) lvpath, err := s.createSnapshotLV(destName, srcName, false) if err != nil { return fmt.Errorf("Error creating snapshot LV: %v", err) } destPath := container.Path() if !shared.PathExists(destPath) { if err := os.MkdirAll(destPath, 0755); err != nil { return fmt.Errorf("Error creating container directory: %v", err) } } err = s.tryMount(lvpath, container.Path(), "ext4", 0, "discard") if err != nil { return fmt.Errorf( "Error mounting snapshot LV path='%s': %v", container.Path(), err) } return nil }
func (s *storageBtrfs) ContainerCreateFromImage( container container, imageFingerprint string) error { imageSubvol := fmt.Sprintf( "%s.btrfs", shared.VarPath("images", imageFingerprint)) // Create the btrfs subvol of the image first if it doesn exists. if !shared.PathExists(imageSubvol) { if err := s.ImageCreate(imageFingerprint); err != nil { return err } } // Now make a snapshot of the image subvol err := s.subvolsSnapshot(imageSubvol, container.Path(), false) if err != nil { return err } if !container.IsPrivileged() { if err = s.shiftRootfs(container); err != nil { s.ContainerDelete(container) return err } } else { if err := os.Chmod(container.Path(), 0700); err != nil { return err } } return container.TemplateApply("create") }
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 (s *storageBtrfs) subvolCreate(subvol string) error { parentDestPath := filepath.Dir(subvol) if !shared.PathExists(parentDestPath) { if err := os.MkdirAll(parentDestPath, 0700); err != nil { return err } } output, err := exec.Command( "btrfs", "subvolume", "create", subvol).CombinedOutput() if err != nil { s.log.Debug( "subvolume create failed", log.Ctx{"subvol": subvol, "output": string(output)}, ) return fmt.Errorf( "btrfs subvolume create failed, subvol=%s, output%s", subvol, string(output), ) } return nil }
// ContainerSnapshotRename renames a snapshot of a container. func (s *storageBtrfs) ContainerSnapshotRename( snapshotContainer container, newName string) error { oldPath := snapshotContainer.Path() newPath := containerPath(newName, true) // Create the new parent. if !shared.PathExists(filepath.Dir(newPath)) { os.MkdirAll(filepath.Dir(newPath), 0700) } // Now rename the snapshot. if !s.isSubvolume(oldPath) { if err := os.Rename(oldPath, newPath); err != nil { return err } } else { if err := s.subvolsSnapshot(oldPath, newPath, true); err != nil { return err } if err := s.subvolsDelete(oldPath); err != nil { return err } } // Remove the old parent (on container rename) if its empty. if ok, _ := shared.PathIsEmpty(filepath.Dir(oldPath)); ok { os.Remove(filepath.Dir(oldPath)) } return nil }
func (s *storageLvm) ContainerSnapshotRename( snapshotContainer container, newContainerName string) error { oldName := containerNameToLVName(snapshotContainer.NameGet()) newName := containerNameToLVName(newContainerName) output, err := s.renameLV(oldName, newName) if err != nil { s.log.Error("Failed to rename a snapshot LV", log.Ctx{"oldName": oldName, "newName": newName, "err": err, "output": string(output)}) return fmt.Errorf("Failed to rename a container LV, oldName='%s', newName='%s', err='%s'", oldName, newName, err) } oldPath := snapshotContainer.PathGet("") oldSymPath := fmt.Sprintf("%s.lv", oldPath) newPath := snapshotContainer.PathGet(newName) newSymPath := fmt.Sprintf("%s.lv", newPath) if err := os.Rename(oldSymPath, newSymPath); err != nil { s.log.Error("Failed to rename symlink", log.Ctx{"oldSymPath": oldSymPath, "newSymPath": newSymPath, "err": err}) return fmt.Errorf("Failed to rename symlink err='%s'", err) } if strings.Contains(snapshotContainer.NameGet(), "/") { if !shared.PathExists(filepath.Dir(newPath)) { os.MkdirAll(filepath.Dir(newPath), 0700) } } if strings.Contains(snapshotContainer.NameGet(), "/") { if ok, _ := shared.PathIsEmpty(filepath.Dir(oldPath)); ok { os.Remove(filepath.Dir(oldPath)) } } return nil }
func snapshotGet(sc container, name string) Response { body := shared.Jmap{ "name": name, "creation_date": sc.CreationDate().Unix(), "stateful": shared.PathExists(sc.StatePath())} return SyncResponse(true, body) }
/* * Export the container to a unshifted tarfile containing: * dir/ * metadata.yaml * rootfs/ */ func (d *lxdContainer) exportToTar(snap string, w io.Writer) error { if snap != "" && d.c.Running() { return fmt.Errorf("Cannot export a running container as image") } tw := tar.NewWriter(w) // keep track of the first path we saw for each path with nlink>1 linkmap := map[uint64]string{} cDir := shared.VarPath("lxc", d.name) // Path inside the tar image is the pathname starting after cDir offset := len(cDir) + 1 fnam := filepath.Join(cDir, "metadata.yaml") writeToTar := func(path string, fi os.FileInfo, err error) error { if err := d.tarStoreFile(linkmap, offset, tw, path, fi); err != nil { shared.Debugf("error tarring up %s: %s\n", path, err) return err } return nil } fnam = filepath.Join(cDir, "metadata.yaml") if shared.PathExists(fnam) { fi, err := os.Lstat(fnam) if err != nil { shared.Debugf("Error statting %s during exportToTar\n", fnam) tw.Close() return err } if err := d.tarStoreFile(linkmap, offset, tw, fnam, fi); err != nil { shared.Debugf("exportToTar: error writing to tarfile: %s\n", err) tw.Close() return err } } fnam = filepath.Join(cDir, "rootfs") filepath.Walk(fnam, writeToTar) fnam = filepath.Join(cDir, "templates") if shared.PathExists(fnam) { filepath.Walk(fnam, writeToTar) } return tw.Close() }
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 networkCreate(routers Routers) error { vethInterfaces, bridgeInterfaces, err := networkInterfaces(routers) if err != nil { return err } for _, veth := range vethInterfaces { if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s-1", veth)) && !shared.PathExists(fmt.Sprintf("/sys/class/net/%s-2", veth)) { out, err := exec.Command("ip", "link", "add", "dev", fmt.Sprintf("%s-1", veth), "type", "veth", "peer", "name", fmt.Sprintf("%s-2", veth)).CombinedOutput() if err != nil { return fmt.Errorf("Failed to create veth device: %s", out) } } if shared.PathExists(fmt.Sprintf("/sys/class/net/%s-1", veth)) { out, err := exec.Command("ip", "link", "set", "dev", fmt.Sprintf("%s-1", veth), "up").CombinedOutput() if err != nil { return fmt.Errorf("Failed to bring veth device up: %s", out) } } if shared.PathExists(fmt.Sprintf("/sys/class/net/%s-2", veth)) { out, err := exec.Command("ip", "link", "set", "dev", fmt.Sprintf("%s-2", veth), "up").CombinedOutput() if err != nil { return fmt.Errorf("Failed to bring veth device up: %s", out) } } } for _, bridge := range bridgeInterfaces { if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", bridge)) { out, err := exec.Command("ip", "link", "add", "dev", bridge, "type", "bridge").CombinedOutput() if err != nil { return fmt.Errorf("Failed to create bridge device: %s", out) } } out, err := exec.Command("ip", "link", "set", "dev", bridge, "up").CombinedOutput() if err != nil { return fmt.Errorf("Failed to bring bridge device up: %s", out) } } 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 }