volumes.go 5.3 KB
Newer Older
M
Medya Gh 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
Copyright 2020 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package oci

import (
20 21
	"bufio"
	"bytes"
M
Medya Gh 已提交
22
	"context"
M
Medya Gh 已提交
23
	"fmt"
M
Medya Gh 已提交
24
	"os/exec"
25
	"strings"
M
Medya Gh 已提交
26
	"time"
M
Medya Gh 已提交
27

M
Medya Gh 已提交
28
	"github.com/golang/glog"
M
Medya Gh 已提交
29 30 31
	"github.com/pkg/errors"
)

M
Medya Gh 已提交
32 33
// DeleteAllVolumesByLabel deletes all volumes that have a specific label
// if there is no volume to delete it will return nil
34 35
func DeleteAllVolumesByLabel(ociBin string, label string) []error {
	var deleteErrs []error
36
	glog.Infof("trying to delete all %s volumes with label %s", ociBin, label)
M
Medya Gh 已提交
37 38
	if ociBin == Docker {
		if err := PointToHostDockerDaemon(); err != nil {
M
Medya Gh 已提交
39
			return []error{errors.Wrap(err, "point host docker daemon")}
M
Medya Gh 已提交
40 41
		}
	}
42 43 44

	vs, err := allVolumesByLabel(ociBin, label)
	if err != nil {
45
		return []error{fmt.Errorf("listing volumes by label %q: %v", label, err)}
46
	}
M
lint  
Medya Gh 已提交
47
	for _, v := range vs {
M
Medya Gh 已提交
48 49 50 51 52 53 54 55
		// allow no more than 3 seconds for this. when this takes long this means deadline passed
		ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
		defer cancel()
		cmd := exec.CommandContext(ctx, ociBin, "volume", "rm", "--force", v)
		if ctx.Err() == context.DeadlineExceeded {
			glog.Warningf("removing volume with label %s took longer than normal. Restarting your %s daemon might fix this issue.", label, ociBin)
			deleteErrs = append(deleteErrs, fmt.Errorf("delete deadline exceeded for %s", label))
		}
M
Medya Gh 已提交
56
		if out, err := cmd.CombinedOutput(); err != nil {
57 58 59 60 61 62 63 64 65 66 67 68 69 70
			deleteErrs = append(deleteErrs, fmt.Errorf("deleting volume %s: output: %s", v, string(out)))
		}
	}
	return deleteErrs
}

// PruneAllVolumesByLabel deletes all volumes that have a specific label
// if there is no volume to delete it will return nil
// example: docker volume prune -f --filter label=name.minikube.sigs.k8s.io=minikube
func PruneAllVolumesByLabel(ociBin string, label string) []error {
	var deleteErrs []error
	glog.Infof("trying to prune all %s volumes with label %s", ociBin, label)
	if ociBin == Docker {
		if err := PointToHostDockerDaemon(); err != nil {
M
Medya Gh 已提交
71
			return []error{errors.Wrap(err, "point host docker daemon")}
72 73
		}
	}
M
Medya Gh 已提交
74 75
	// allow no more than 3 seconds for this. when this takes long this means deadline passed
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
M
Medya Gh 已提交
76
	defer cancel()
77 78

	// try to prune afterwards just in case delete didn't go through
M
Medya Gh 已提交
79
	cmd := exec.CommandContext(ctx, ociBin, "volume", "prune", "-f", "--filter", "label="+label)
M
Medya Gh 已提交
80 81 82
	if out, err := cmd.CombinedOutput(); err != nil {
		deleteErrs = append(deleteErrs, errors.Wrapf(err, "prune volume by label %s: %s", label, string(out)))
	}
M
Medya Gh 已提交
83 84 85 86
	if ctx.Err() == context.DeadlineExceeded {
		glog.Warningf("pruning volume with label %s took longer than normal. Restarting your %s daemon might fix this issue.", label, ociBin)
		deleteErrs = append(deleteErrs, fmt.Errorf("prune deadline exceeded for %s", label))
	}
87 88 89 90 91 92 93 94
	return deleteErrs
}

// allVolumesByLabel returns name of all docker volumes by a specific label
// will not return error if there is no volume found.
func allVolumesByLabel(ociBin string, label string) ([]string, error) {
	cmd := exec.Command(ociBin, "volume", "ls", "--filter", "label="+label, "--format", "{{.Name}}")
	stdout, err := cmd.Output()
95
	s := bufio.NewScanner(bytes.NewReader(stdout))
M
Medya Gh 已提交
96
	var vols []string
97 98 99 100
	for s.Scan() {
		v := strings.TrimSpace(s.Text())
		if v != "" {
			vols = append(vols, v)
M
Medya Gh 已提交
101
		}
102
	}
M
Medya Gh 已提交
103
	return vols, err
M
Medya Gh 已提交
104 105
}

106 107 108 109 110 111 112 113 114 115 116 117 118
// ExtractTarballToVolume runs a docker image imageName which extracts the tarball at tarballPath
// to the volume named volumeName
func ExtractTarballToVolume(tarballPath, volumeName, imageName string) error {
	if err := PointToHostDockerDaemon(); err != nil {
		return errors.Wrap(err, "point host docker-daemon")
	}
	cmd := exec.Command(Docker, "run", "--rm", "--entrypoint", "/usr/bin/tar", "-v", fmt.Sprintf("%s:/preloaded.tar:ro", tarballPath), "-v", fmt.Sprintf("%s:/extractDir", volumeName), imageName, "-I", "lz4", "-xvf", "/preloaded.tar", "-C", "/extractDir")
	if out, err := cmd.CombinedOutput(); err != nil {
		return errors.Wrapf(err, "output %s", string(out))
	}
	return nil
}

M
Medya Gh 已提交
119 120 121
// createDockerVolume creates a docker volume to be attached to the container with correct labels and prefixes based on profile name
// Caution ! if volume already exists does NOT return an error and will not apply the minikube labels on it.
// TODO: this should be fixed as a part of https://github.com/kubernetes/minikube/issues/6530
S
Sharif Elgamal 已提交
122
func createDockerVolume(profile string, nodeName string) error {
M
Medya Gh 已提交
123
	if err := PointToHostDockerDaemon(); err != nil {
M
Medya Gh 已提交
124
		return errors.Wrap(err, "point host docker daemon")
M
Medya Gh 已提交
125
	}
S
Sharif Elgamal 已提交
126
	cmd := exec.Command(Docker, "volume", "create", nodeName, "--label", fmt.Sprintf("%s=%s", ProfileLabelKey, profile), "--label", fmt.Sprintf("%s=%s", CreatedByLabelKey, "true"))
M
Medya Gh 已提交
127 128 129 130 131
	if out, err := cmd.CombinedOutput(); err != nil {
		return errors.Wrapf(err, "output %s", string(out))
	}
	return nil
}