Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/flexvolume_driver/flexvolume_driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ import (

func main() {
rand.Seed(time.Now().UnixNano())
driver := flexvolume.NewFlexVolumeDriver(utils.NewUUID, flexvolume.NewLinuxMounter())
driver := flexvolume.NewFlexVolumeDriver(utils.NewUUID, utils.NewMounter())
os.Stdout.WriteString(driver.Run(os.Args[1:]))
}
2 changes: 1 addition & 1 deletion cmd/virtlet/virtlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func runTapManager(config *v1.VirtletConfig) {
glog.Errorf("FD server returned error: %v", err)
os.Exit(1)
}
if err := libvirttools.ChownForEmulator(*config.FDServerSocketPath); err != nil {
if err := libvirttools.ChownForEmulator(*config.FDServerSocketPath, false); err != nil {
glog.Warningf("Couldn't set tapmanager socket permissions: %v", err)
}
for {
Expand Down
5 changes: 5 additions & 0 deletions deploy/data/virtlet-ds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ spec:
mountPath: /dev
- mountPath: /var/lib/virtlet
name: virtlet
mountPropagation: Bidirectional
- mountPath: /var/lib/libvirt
name: libvirt
- mountPath: /var/run/libvirt
Expand Down Expand Up @@ -222,10 +223,14 @@ spec:
volumeMounts:
- mountPath: /var/lib/virtlet
name: virtlet
mountPropagation: HostToContainer
- mountPath: /var/lib/libvirt
name: libvirt
- name: vms-log
mountPath: /var/log/vms
- mountPath: /var/lib/kubelet/pods
name: k8s-pods-dir
mountPropagation: HostToContainer
- name: dev
mountPath: /dev
- name: modules
Expand Down
24 changes: 12 additions & 12 deletions pkg/flexvolume/flexvolume.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,13 @@ func init() {
}
}

type Mounter interface {
Mount(source string, target string, fstype string) error
Unmount(target string) error
}

type nullMounter struct{}

func (m *nullMounter) Mount(source string, target string, fstype string) error {
func (m *nullMounter) Mount(source string, target string, fstype string, flags uintptr) error {
return nil
}

func (m *nullMounter) Unmount(target string) error {
func (m *nullMounter) Unmount(target string, flags int) error {
return nil
}

Expand All @@ -67,10 +62,11 @@ type UuidGen func() string

type FlexVolumeDriver struct {
uuidGen UuidGen
mounter Mounter
mounter utils.Mounter
}

func NewFlexVolumeDriver(uuidGen UuidGen, mounter Mounter) *FlexVolumeDriver {
// NewFlexVolumeDriver creates a FlexVolumeDriver struct
func NewFlexVolumeDriver(uuidGen UuidGen, mounter utils.Mounter) *FlexVolumeDriver {
return &FlexVolumeDriver{uuidGen: uuidGen, mounter: mounter}
}

Expand Down Expand Up @@ -132,15 +128,15 @@ func (d *FlexVolumeDriver) mount(targetMountDir, jsonOptions string) (map[string
return nil, err
}

if err := d.mounter.Mount("tmpfs", targetMountDir, "tmpfs"); err != nil {
if err := d.mounter.Mount("tmpfs", targetMountDir, "tmpfs", 0); err != nil {
return nil, fmt.Errorf("error mounting tmpfs at %q: %v", targetMountDir, err)
}

done := false
defer func() {
// try to unmount upon error or panic
if !done {
d.mounter.Unmount(targetMountDir)
d.mounter.Unmount(targetMountDir, 0)
}
}()

Expand All @@ -154,7 +150,7 @@ func (d *FlexVolumeDriver) mount(targetMountDir, jsonOptions string) (map[string

// Invocation: <driver executable> unmount <mount dir>
func (d *FlexVolumeDriver) unmount(targetMountDir string) (map[string]interface{}, error) {
if err := d.mounter.Unmount(targetMountDir); err != nil {
if err := d.mounter.Unmount(targetMountDir, 0); err != nil {
return nil, fmt.Errorf("unmount %q: %v", targetMountDir, err.Error())
}

Expand Down Expand Up @@ -274,6 +270,10 @@ func formatResult(fields map[string]interface{}, err error) string {
// means that no partition number was specified.
func GetFlexvolumeInfo(dir string) (string, int, error) {
dataFile := filepath.Join(dir, flexvolumeDataFile)
if _, err := os.Stat(dataFile); os.IsNotExist(err) {
return "", 0, err
}

var opts map[string]interface{}
if err := utils.ReadJSON(dataFile, &opts); err != nil {
return "", 0, fmt.Errorf("can't read flexvolume data file %q: %v", dataFile, err)
Expand Down
6 changes: 3 additions & 3 deletions pkg/flexvolume/flexvolume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type fakeMounter struct {
journal []string
}

var _ Mounter = &fakeMounter{}
var _ utils.Mounter = &fakeMounter{}

func newFakeMounter(t *testing.T, tmpDir string) *fakeMounter {
return &fakeMounter{t: t, tmpDir: tmpDir}
Expand All @@ -53,7 +53,7 @@ func (mounter *fakeMounter) validatePath(target string) {
}
}

func (mounter *fakeMounter) Mount(source string, target string, fstype string) error {
func (mounter *fakeMounter) Mount(source string, target string, fstype string, flags uintptr) error {
mounter.validatePath(target)
mounter.journal = append(mounter.journal, fmt.Sprintf("mount: %s %s %s", source, target, fstype))

Expand Down Expand Up @@ -81,7 +81,7 @@ func (mounter *fakeMounter) Mount(source string, target string, fstype string) e
return nil
}

func (mounter *fakeMounter) Unmount(target string) error {
func (mounter *fakeMounter) Unmount(target string, flags int) error {
// we make sure that path is under our tmpdir before wiping it
mounter.validatePath(target)
mounter.journal = append(mounter.journal, fmt.Sprintf("unmount: %s", target))
Expand Down
3 changes: 3 additions & 0 deletions pkg/libvirttools/TestContainerLifecycle.out.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
UserDataOverwrite: false
UserDataScript: ""
VCPUCount: 1
VirtletChown9pfsMounts: false
PodAnnotations:
hello: world
virt: let
Expand Down Expand Up @@ -176,6 +177,7 @@
UserDataOverwrite: false
UserDataScript: ""
VCPUCount: 1
VirtletChown9pfsMounts: false
PodAnnotations:
hello: world
virt: let
Expand Down Expand Up @@ -225,6 +227,7 @@
UserDataOverwrite: false
UserDataScript: ""
VCPUCount: 1
VirtletChown9pfsMounts: false
PodAnnotations:
hello: world
virt: let
Expand Down
1 change: 1 addition & 0 deletions pkg/libvirttools/TestDomainForcedShutdown.out.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
UserDataOverwrite: false
UserDataScript: ""
VCPUCount: 1
VirtletChown9pfsMounts: false
PodAnnotations:
hello: world
virt: let
Expand Down
12 changes: 6 additions & 6 deletions pkg/libvirttools/ceph_flexvolume.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,24 +93,24 @@ func (v *cephVolume) UUID() string {
return v.opts.UUID
}

func (v *cephVolume) Setup() (*libvirtxml.DomainDisk, error) {
func (v *cephVolume) Setup() (*libvirtxml.DomainDisk, *libvirtxml.DomainFilesystem, error) {
ipPortPair := strings.Split(v.opts.Monitor, ":")
if len(ipPortPair) != 2 {
return nil, fmt.Errorf("invalid format of ceph monitor setting: %s. Expected ip:port", v.opts.Monitor)
return nil, nil, fmt.Errorf("invalid format of ceph monitor setting: %s. Expected ip:port", v.opts.Monitor)
}

secret, err := v.owner.DomainConnection().DefineSecret(v.secretDef())
if err != nil {
return nil, fmt.Errorf("error defining ceph secret: %v", err)
return nil, nil, fmt.Errorf("error defining ceph secret: %v", err)
}

key, err := base64.StdEncoding.DecodeString(v.opts.Secret)
if err != nil {
return nil, fmt.Errorf("error decoding ceph secret: %v", err)
return nil, nil, fmt.Errorf("error decoding ceph secret: %v", err)
}

if err := secret.SetValue([]byte(key)); err != nil {
return nil, fmt.Errorf("error setting value of secret %q: %v", v.secretUsageName(), err)
return nil, nil, fmt.Errorf("error setting value of secret %q: %v", v.secretUsageName(), err)
}

return &libvirtxml.DomainDisk{
Expand All @@ -135,7 +135,7 @@ func (v *cephVolume) Setup() (*libvirtxml.DomainDisk, error) {
},
},
},
}, nil
}, nil, nil
}

func (v *cephVolume) Teardown() error {
Expand Down
81 changes: 57 additions & 24 deletions pkg/libvirttools/cloudinit.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,43 +467,76 @@ func (g *CloudInitGenerator) generateMounts(volumeMap diskPathMap) ([]interface{
var mountScriptLines []string
for _, m := range g.config.Mounts {
// Skip file based mounts (including secrets and config maps).
if isRegularFile(m.HostPath) {
if isRegularFile(m.HostPath) ||
strings.Contains(m.HostPath, "kubernetes.io~secret") ||
strings.Contains(m.HostPath, "kubernetes.io~configmap") {
continue
}

uuid, part, err := flexvolume.GetFlexvolumeInfo(m.HostPath)
mountInfo, mountScriptLine, err := generateFlexvolumeMounts(volumeMap, m)
if err != nil {
glog.Errorf("Can't mount directory %q to %q inside the VM: can't get flexvolume uuid: %v", m.HostPath, m.ContainerPath, err)
continue
}
dpath, found := volumeMap[uuid]
if !found {
glog.Errorf("Can't mount directory %q to %q inside the VM: no device found for flexvolume uuid %q", m.HostPath, m.ContainerPath, uuid)
continue
}
if part < 0 {
part = 1
}
devPath := dpath.devPath
mountDevSuffix := ""
if part != 0 {
devPath += fmt.Sprintf("-part%d", part)
mountDevSuffix += strconv.Itoa(part)
if !os.IsNotExist(err) {
glog.Errorf("Can't mount directory %q to %q inside the VM: %v", m.HostPath, m.ContainerPath, err)
continue
}

// Fs based volume
mountInfo, mountScriptLine, err = generateFsBasedVolumeMounts(m)
if err != nil {
glog.Errorf("Can't mount directory %q to %q inside the VM: %v", m.HostPath, m.ContainerPath, err)
continue
}
}
r = append(r, []interface{}{devPath, m.ContainerPath})
mountScriptLines = append(
mountScriptLines,
// TODO: do better job at escaping m.ContainerPath
fmt.Sprintf("if ! mountpoint '%s'; then mkdir -p '%s' && mount /dev/`ls %s`%s '%s'; fi",
m.ContainerPath, m.ContainerPath, dpath.sysfsPath, mountDevSuffix, m.ContainerPath))

r = append(r, mountInfo)
mountScriptLines = append(mountScriptLines, mountScriptLine)
}

mountScript := ""
if len(mountScriptLines) != 0 {
mountScript = fmt.Sprintf("#!/bin/sh\n%s\n", strings.Join(mountScriptLines, "\n"))
}
return r, mountScript
}

func generateFlexvolumeMounts(volumeMap diskPathMap, mount types.VMMount) ([]interface{}, string, error) {
uuid, part, err := flexvolume.GetFlexvolumeInfo(mount.HostPath)
if err != nil {
// If the error is NotExist, return the original error
if os.IsNotExist(err) {
return nil, "", err
}
err = fmt.Errorf("can't get flexvolume uuid: %v", err)
return nil, "", err
}
dpath, found := volumeMap[uuid]
if !found {
err = fmt.Errorf("no device found for flexvolume uuid %q", uuid)
return nil, "", err
}
if part < 0 {
part = 1
}
devPath := dpath.devPath
mountDevSuffix := ""
if part != 0 {
devPath += fmt.Sprintf("-part%d", part)
mountDevSuffix += strconv.Itoa(part)
}
// TODO: do better job at escaping mount.ContainerPath
mountScriptLine := fmt.Sprintf("if ! mountpoint '%s'; then mkdir -p '%s' && mount /dev/`ls %s`%s '%s'; fi",
mount.ContainerPath, mount.ContainerPath, dpath.sysfsPath, mountDevSuffix, mount.ContainerPath)
return []interface{}{devPath, mount.ContainerPath}, mountScriptLine, nil
}

func generateFsBasedVolumeMounts(mount types.VMMount) ([]interface{}, string, error) {
mountTag := path.Base(mount.ContainerPath)
fsMountScript := fmt.Sprintf("if ! mountpoint '%s'; then mkdir -p '%s' && mount -t 9p -o trans=virtio %s '%s'; fi",
mount.ContainerPath, mount.ContainerPath, mountTag, mount.ContainerPath)
r := []interface{}{mountTag, mount.ContainerPath, "9p", "trans=virtio"}
return r, fsMountScript, nil
}

type writeFilesUpdater struct {
entries []interface{}
mounts []types.VMMount
Expand Down
4 changes: 2 additions & 2 deletions pkg/libvirttools/config_volumesource.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ func (v *configVolume) cloudInitGenerator() *CloudInitGenerator {
return NewCloudInitGenerator(v.config, configIsoDir)
}

func (v *configVolume) Setup() (*libvirtxml.DomainDisk, error) {
return v.cloudInitGenerator().DiskDef(), nil
func (v *configVolume) Setup() (*libvirtxml.DomainDisk, *libvirtxml.DomainFilesystem, error) {
return v.cloudInitGenerator().DiskDef(), nil, nil
}

func (v *configVolume) WriteImage(volumeMap diskPathMap) error {
Expand Down
1 change: 1 addition & 0 deletions pkg/libvirttools/defaultvolumesrc.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func GetDefaultVolumeSource() VMVolumeSource {
return CombineVMVolumeSources(
GetRootVolume,
ScanFlexVolumes,
GetFileSystemVolumes,
// XXX: GetConfigVolume must go last because it
// doesn't produce correct name for cdrom devices
GetConfigVolume)
Expand Down
32 changes: 20 additions & 12 deletions pkg/libvirttools/disklist.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ type diskItem struct {
volume VMVolume
}

func (di *diskItem) setup(config *types.VMConfig) (*libvirtxml.DomainDisk, error) {
diskDef, err := di.volume.Setup()
func (di *diskItem) setup(config *types.VMConfig) (*libvirtxml.DomainDisk, *libvirtxml.DomainFilesystem, error) {
diskDef, fsDef, err := di.volume.Setup()
if err != nil {
return nil, err
return nil, nil, err
}
if diskDef != nil {
diskDef.Target = di.driver.target()
diskDef.Address = di.driver.address()
}
diskDef.Target = di.driver.target()
diskDef.Address = di.driver.address()
return diskDef, nil
return diskDef, fsDef, nil
}

type diskList struct {
Expand Down Expand Up @@ -72,23 +74,29 @@ func newDiskList(config *types.VMConfig, source VMVolumeSource, owner volumeOwne
}

// setup performs the setup procedure on each volume in the diskList
// and returns a list of libvirtxml DomainDisk structs
func (dl *diskList) setup() ([]libvirtxml.DomainDisk, error) {
// and returns a list of libvirtxml DomainDisk and domainFileSystems structs
func (dl *diskList) setup() ([]libvirtxml.DomainDisk, []libvirtxml.DomainFilesystem, error) {
var domainDisks []libvirtxml.DomainDisk
var domainFileSystems []libvirtxml.DomainFilesystem
for n, item := range dl.items {
diskDef, err := item.setup(dl.config)
diskDef, fsDef, err := item.setup(dl.config)
if err != nil {
// try to tear down volumes that were already set up
for _, item := range dl.items[:n] {
if err := item.volume.Teardown(); err != nil {
glog.Warningf("Failed to tear down a volume on error: %v", err)
}
}
return nil, err
return nil, nil, err
}
if diskDef != nil {
domainDisks = append(domainDisks, *diskDef)
}
if fsDef != nil {
domainFileSystems = append(domainFileSystems, *fsDef)
}
domainDisks = append(domainDisks, *diskDef)
}
return domainDisks, nil
return domainDisks, domainFileSystems, nil
}

// writeImages writes images for volumes that are based on generated
Expand Down
Loading