...

Source file src/k8s.io/kubernetes/pkg/volume/fc/fc_test.go

Documentation: k8s.io/kubernetes/pkg/volume/fc

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package fc
    18  
    19  import (
    20  	"os"
    21  	"path/filepath"
    22  	"runtime"
    23  	"strconv"
    24  	"strings"
    25  	"testing"
    26  
    27  	"k8s.io/mount-utils"
    28  	testingexec "k8s.io/utils/exec/testing"
    29  
    30  	v1 "k8s.io/api/core/v1"
    31  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    32  	"k8s.io/apimachinery/pkg/types"
    33  	"k8s.io/client-go/kubernetes/fake"
    34  	utiltesting "k8s.io/client-go/util/testing"
    35  	"k8s.io/kubernetes/pkg/volume"
    36  	volumetest "k8s.io/kubernetes/pkg/volume/testing"
    37  )
    38  
    39  func TestCanSupport(t *testing.T) {
    40  	tmpDir, err := utiltesting.MkTmpdir("fc_test")
    41  	if err != nil {
    42  		t.Fatalf("error creating temp dir: %v", err)
    43  	}
    44  	defer os.RemoveAll(tmpDir)
    45  
    46  	plugMgr := volume.VolumePluginMgr{}
    47  	plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
    48  
    49  	plug, err := plugMgr.FindPluginByName("kubernetes.io/fc")
    50  	if err != nil {
    51  		t.Fatal("Can't find the plugin by name")
    52  	}
    53  	if plug.GetPluginName() != "kubernetes.io/fc" {
    54  		t.Errorf("Wrong name: %s", plug.GetPluginName())
    55  	}
    56  	if plug.CanSupport(&volume.Spec{}) {
    57  		t.Errorf("Expected false")
    58  	}
    59  	if plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{}}}) {
    60  		t.Errorf("Expected false")
    61  	}
    62  	if !plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{FC: &v1.FCVolumeSource{}}}}) {
    63  		t.Errorf("Expected true")
    64  	}
    65  	if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{}}}) {
    66  		t.Errorf("Expected false")
    67  	}
    68  	if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{}}}}) {
    69  		t.Errorf("Expected false")
    70  	}
    71  	if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{FC: &v1.FCVolumeSource{}}}}}) {
    72  		t.Errorf("Expected true")
    73  	}
    74  }
    75  
    76  func TestGetAccessModes(t *testing.T) {
    77  	tmpDir, err := utiltesting.MkTmpdir("fc_test")
    78  	if err != nil {
    79  		t.Fatalf("error creating temp dir: %v", err)
    80  	}
    81  	defer os.RemoveAll(tmpDir)
    82  
    83  	plugMgr := volume.VolumePluginMgr{}
    84  	plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
    85  
    86  	plug, err := plugMgr.FindPersistentPluginByName("kubernetes.io/fc")
    87  	if err != nil {
    88  		t.Errorf("Can't find the plugin by name")
    89  	}
    90  	if !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteOnce) || !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadOnlyMany) {
    91  		t.Errorf("Expected two AccessModeTypes:  %s and %s", v1.ReadWriteOnce, v1.ReadOnlyMany)
    92  	}
    93  }
    94  
    95  type fakeDiskManager struct {
    96  	tmpDir       string
    97  	attachCalled bool
    98  	detachCalled bool
    99  }
   100  
   101  func newFakeDiskManager() *fakeDiskManager {
   102  	return &fakeDiskManager{
   103  		tmpDir: utiltesting.MkTmpdirOrDie("fc_test"),
   104  	}
   105  }
   106  
   107  func (fake *fakeDiskManager) Cleanup() {
   108  	os.RemoveAll(fake.tmpDir)
   109  }
   110  
   111  func (fake *fakeDiskManager) MakeGlobalPDName(disk fcDisk) string {
   112  	return fake.tmpDir
   113  }
   114  
   115  func (fake *fakeDiskManager) MakeGlobalVDPDName(disk fcDisk) string {
   116  	return fake.tmpDir
   117  }
   118  
   119  func (fake *fakeDiskManager) AttachDisk(b fcDiskMounter) (string, error) {
   120  	globalPath := b.manager.MakeGlobalPDName(*b.fcDisk)
   121  	err := os.MkdirAll(globalPath, 0750)
   122  	if err != nil {
   123  		return "", err
   124  	}
   125  	fake.attachCalled = true
   126  	return "", nil
   127  }
   128  
   129  func (fake *fakeDiskManager) DetachDisk(c fcDiskUnmounter, mntPath string) error {
   130  	globalPath := c.manager.MakeGlobalPDName(*c.fcDisk)
   131  	err := os.RemoveAll(globalPath)
   132  	if err != nil {
   133  		return err
   134  	}
   135  	fake.detachCalled = true
   136  	return nil
   137  }
   138  
   139  func (fake *fakeDiskManager) DetachBlockFCDisk(c fcDiskUnmapper, mapPath, devicePath string) error {
   140  	err := os.RemoveAll(mapPath)
   141  	if err != nil {
   142  		return err
   143  	}
   144  	fake.detachCalled = true
   145  	return nil
   146  }
   147  
   148  func doTestPlugin(t *testing.T, spec *volume.Spec) {
   149  	tmpDir, err := utiltesting.MkTmpdir("fc_test")
   150  	if err != nil {
   151  		t.Fatalf("error creating temp dir: %v", err)
   152  	}
   153  	defer os.RemoveAll(tmpDir)
   154  
   155  	plugMgr := volume.VolumePluginMgr{}
   156  	plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
   157  
   158  	plug, err := plugMgr.FindPluginByName("kubernetes.io/fc")
   159  	if err != nil {
   160  		t.Errorf("Can't find the plugin by name")
   161  	}
   162  	fakeManager := newFakeDiskManager()
   163  	defer fakeManager.Cleanup()
   164  	fakeMounter := mount.NewFakeMounter(nil)
   165  	fakeExec := &testingexec.FakeExec{}
   166  	mounter, err := plug.(*fcPlugin).newMounterInternal(spec, types.UID("poduid"), fakeManager, fakeMounter, fakeExec)
   167  	if err != nil {
   168  		t.Errorf("Failed to make a new Mounter: %v", err)
   169  	}
   170  	if mounter == nil {
   171  		t.Errorf("Got a nil Mounter: %v", err)
   172  	}
   173  
   174  	path := mounter.GetPath()
   175  	expectedPath := filepath.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~fc/vol1")
   176  	if path != expectedPath {
   177  		t.Errorf("Unexpected path, expected %q, got: %q", expectedPath, path)
   178  	}
   179  
   180  	if err := mounter.SetUp(volume.MounterArgs{}); err != nil {
   181  		t.Errorf("Expected success, got: %v", err)
   182  	}
   183  	if _, err := os.Stat(path); err != nil {
   184  		if os.IsNotExist(err) {
   185  			t.Errorf("SetUp() failed, volume path not created: %s", path)
   186  		} else {
   187  			t.Errorf("SetUp() failed: %v", err)
   188  		}
   189  	}
   190  
   191  	fakeManager2 := newFakeDiskManager()
   192  	defer fakeManager2.Cleanup()
   193  	unmounter, err := plug.(*fcPlugin).newUnmounterInternal("vol1", types.UID("poduid"), fakeManager2, fakeMounter, fakeExec)
   194  	if err != nil {
   195  		t.Errorf("Failed to make a new Unmounter: %v", err)
   196  	}
   197  	if unmounter == nil {
   198  		t.Errorf("Got a nil Unmounter: %v", err)
   199  	}
   200  
   201  	if err := unmounter.TearDown(); err != nil {
   202  		t.Errorf("Expected success, got: %v", err)
   203  	}
   204  	if _, err := os.Stat(path); err == nil {
   205  		t.Errorf("TearDown() failed, volume path still exists: %s", path)
   206  	} else if !os.IsNotExist(err) {
   207  		t.Errorf("TearDown() failed: %v", err)
   208  	}
   209  }
   210  
   211  func doTestPluginNilMounter(t *testing.T, spec *volume.Spec) {
   212  	tmpDir, err := utiltesting.MkTmpdir("fc_test")
   213  	if err != nil {
   214  		t.Fatalf("error creating temp dir: %v", err)
   215  	}
   216  	defer os.RemoveAll(tmpDir)
   217  
   218  	plugMgr := volume.VolumePluginMgr{}
   219  	plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
   220  
   221  	plug, err := plugMgr.FindPluginByName("kubernetes.io/fc")
   222  	if err != nil {
   223  		t.Errorf("Can't find the plugin by name")
   224  	}
   225  	fakeManager := newFakeDiskManager()
   226  	defer fakeManager.Cleanup()
   227  	fakeMounter := mount.NewFakeMounter(nil)
   228  	fakeExec := &testingexec.FakeExec{}
   229  	mounter, err := plug.(*fcPlugin).newMounterInternal(spec, types.UID("poduid"), fakeManager, fakeMounter, fakeExec)
   230  	if err == nil {
   231  		t.Errorf("Error failed to make a new Mounter is expected: %v", err)
   232  	}
   233  	if mounter != nil {
   234  		t.Errorf("A nil Mounter is expected: %v", err)
   235  	}
   236  }
   237  
   238  func TestPluginVolume(t *testing.T) {
   239  	lun := int32(0)
   240  	vol := &v1.Volume{
   241  		Name: "vol1",
   242  		VolumeSource: v1.VolumeSource{
   243  			FC: &v1.FCVolumeSource{
   244  				TargetWWNs: []string{"500a0981891b8dc5"},
   245  				FSType:     "ext4",
   246  				Lun:        &lun,
   247  			},
   248  		},
   249  	}
   250  	doTestPlugin(t, volume.NewSpecFromVolume(vol))
   251  }
   252  
   253  func TestPluginPersistentVolume(t *testing.T) {
   254  	lun := int32(0)
   255  	fs := v1.PersistentVolumeFilesystem
   256  	vol := &v1.PersistentVolume{
   257  		ObjectMeta: metav1.ObjectMeta{
   258  			Name: "vol1",
   259  		},
   260  		Spec: v1.PersistentVolumeSpec{
   261  			PersistentVolumeSource: v1.PersistentVolumeSource{
   262  				FC: &v1.FCVolumeSource{
   263  					TargetWWNs: []string{"500a0981891b8dc5"},
   264  					FSType:     "ext4",
   265  					Lun:        &lun,
   266  				},
   267  			},
   268  			VolumeMode: &fs,
   269  		},
   270  	}
   271  	doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
   272  }
   273  
   274  func TestPluginVolumeWWIDs(t *testing.T) {
   275  	vol := &v1.Volume{
   276  		Name: "vol1",
   277  		VolumeSource: v1.VolumeSource{
   278  			FC: &v1.FCVolumeSource{
   279  				WWIDs:  []string{"3600508b400105e210000900000490000"},
   280  				FSType: "ext4",
   281  			},
   282  		},
   283  	}
   284  	doTestPlugin(t, volume.NewSpecFromVolume(vol))
   285  }
   286  
   287  func TestPluginPersistentVolumeWWIDs(t *testing.T) {
   288  	fs := v1.PersistentVolumeFilesystem
   289  	vol := &v1.PersistentVolume{
   290  		ObjectMeta: metav1.ObjectMeta{
   291  			Name: "vol1",
   292  		},
   293  		Spec: v1.PersistentVolumeSpec{
   294  			PersistentVolumeSource: v1.PersistentVolumeSource{
   295  				FC: &v1.FCVolumeSource{
   296  					WWIDs:  []string{"3600508b400105e21 000900000490000"},
   297  					FSType: "ext4",
   298  				},
   299  			},
   300  			VolumeMode: &fs,
   301  		},
   302  	}
   303  	doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
   304  }
   305  
   306  func TestPluginVolumeNoDiskInfo(t *testing.T) {
   307  	vol := &v1.Volume{
   308  		Name: "vol1",
   309  		VolumeSource: v1.VolumeSource{
   310  			FC: &v1.FCVolumeSource{
   311  				FSType: "ext4",
   312  			},
   313  		},
   314  	}
   315  	doTestPluginNilMounter(t, volume.NewSpecFromVolume(vol))
   316  }
   317  
   318  func TestPluginPersistentVolumeNoDiskInfo(t *testing.T) {
   319  	fs := v1.PersistentVolumeFilesystem
   320  	vol := &v1.PersistentVolume{
   321  		ObjectMeta: metav1.ObjectMeta{
   322  			Name: "vol1",
   323  		},
   324  		Spec: v1.PersistentVolumeSpec{
   325  			PersistentVolumeSource: v1.PersistentVolumeSource{
   326  				FC: &v1.FCVolumeSource{
   327  					FSType: "ext4",
   328  				},
   329  			},
   330  			VolumeMode: &fs,
   331  		},
   332  	}
   333  	doTestPluginNilMounter(t, volume.NewSpecFromPersistentVolume(vol, false))
   334  }
   335  
   336  func TestPersistentClaimReadOnlyFlag(t *testing.T) {
   337  	tmpDir, err := utiltesting.MkTmpdir("fc_test")
   338  	if err != nil {
   339  		t.Fatalf("error creating temp dir: %v", err)
   340  	}
   341  	defer os.RemoveAll(tmpDir)
   342  
   343  	lun := int32(0)
   344  	fs := v1.PersistentVolumeFilesystem
   345  	pv := &v1.PersistentVolume{
   346  		ObjectMeta: metav1.ObjectMeta{
   347  			Name: "pvA",
   348  		},
   349  		Spec: v1.PersistentVolumeSpec{
   350  			PersistentVolumeSource: v1.PersistentVolumeSource{
   351  				FC: &v1.FCVolumeSource{
   352  					TargetWWNs: []string{"some_wwn"},
   353  					FSType:     "ext4",
   354  					Lun:        &lun,
   355  				},
   356  			},
   357  			ClaimRef: &v1.ObjectReference{
   358  				Name: "claimA",
   359  			},
   360  			VolumeMode: &fs,
   361  		},
   362  	}
   363  
   364  	claim := &v1.PersistentVolumeClaim{
   365  		ObjectMeta: metav1.ObjectMeta{
   366  			Name:      "claimA",
   367  			Namespace: "nsA",
   368  		},
   369  		Spec: v1.PersistentVolumeClaimSpec{
   370  			VolumeName: "pvA",
   371  			VolumeMode: &fs,
   372  		},
   373  		Status: v1.PersistentVolumeClaimStatus{
   374  			Phase: v1.ClaimBound,
   375  		},
   376  	}
   377  
   378  	client := fake.NewSimpleClientset(pv, claim)
   379  
   380  	plugMgr := volume.VolumePluginMgr{}
   381  	plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, client, nil))
   382  	plug, _ := plugMgr.FindPluginByName(fcPluginName)
   383  
   384  	// readOnly bool is supplied by persistent-claim volume source when its mounter creates other volumes
   385  	spec := volume.NewSpecFromPersistentVolume(pv, true)
   386  	pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
   387  	mounter, _ := plug.NewMounter(spec, pod, volume.VolumeOptions{})
   388  	if mounter == nil {
   389  		t.Fatalf("Got a nil Mounter")
   390  	}
   391  
   392  	if !mounter.GetAttributes().ReadOnly {
   393  		t.Errorf("Expected true for mounter.IsReadOnly")
   394  	}
   395  }
   396  
   397  func Test_getWwnsLun(t *testing.T) {
   398  	num := int32(0)
   399  	fc := &v1.FCVolumeSource{
   400  		TargetWWNs: []string{"500a0981891b8dc5"},
   401  		FSType:     "ext4",
   402  		Lun:        &num,
   403  	}
   404  	wwn, lun, _, err := getWwnsLunWwids(fc)
   405  	// if no wwn and lun, exit
   406  	if (len(wwn) == 0 && lun != "0") || err != nil {
   407  		t.Errorf("no fc disk found")
   408  	}
   409  }
   410  
   411  func Test_getWwids(t *testing.T) {
   412  	fc := &v1.FCVolumeSource{
   413  		FSType: "ext4",
   414  		WWIDs:  []string{"3600508b400105e210000900000490000"},
   415  	}
   416  	_, _, wwid, err := getWwnsLunWwids(fc)
   417  	// if no wwn and lun, exit
   418  	if len(wwid) == 0 || err != nil {
   419  		t.Errorf("no fc disk found")
   420  	}
   421  }
   422  
   423  func Test_getWwnsLunWwidsError(t *testing.T) {
   424  	fc := &v1.FCVolumeSource{
   425  		FSType: "ext4",
   426  	}
   427  	wwn, lun, wwid, err := getWwnsLunWwids(fc)
   428  	// expected no wwn and lun and wwid
   429  	if (len(wwn) != 0 && lun != "" && len(wwid) != 0) || err == nil {
   430  		t.Errorf("unexpected fc disk found")
   431  	}
   432  }
   433  
   434  func Test_ConstructVolumeSpec(t *testing.T) {
   435  	if runtime.GOOS == "darwin" {
   436  		t.Skipf("Test_ConstructVolumeSpec is not supported on GOOS=%s", runtime.GOOS)
   437  	}
   438  	fm := mount.NewFakeMounter(
   439  		[]mount.MountPoint{
   440  			{Device: "/dev/sdb", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod1"},
   441  			{Device: "/dev/sdb", Path: "/var/lib/kubelet/plugins/kubernetes.io/fc/50060e801049cfd1-lun-0"},
   442  			{Device: "/dev/sdc", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod2"},
   443  			{Device: "/dev/sdc", Path: "/var/lib/kubelet/plugins/kubernetes.io/fc/volumeDevices/3600508b400105e210000900000490000"},
   444  		})
   445  	mountPaths := []string{
   446  		"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod1",
   447  		"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod2",
   448  	}
   449  	for _, path := range mountPaths {
   450  		refs, err := fm.GetMountRefs(path)
   451  		if err != nil {
   452  			t.Errorf("couldn't get mountrefs. err: %v", err)
   453  		}
   454  		var globalPDPath string
   455  		for _, ref := range refs {
   456  			if strings.Contains(ref, "kubernetes.io/fc") {
   457  				globalPDPath = ref
   458  				break
   459  			}
   460  		}
   461  		if len(globalPDPath) == 0 {
   462  			t.Errorf("couldn't fetch mountrefs")
   463  		}
   464  		arr := strings.Split(globalPDPath, "/")
   465  		if len(arr) < 1 {
   466  			t.Errorf("failed to retrieve volume plugin information from globalPDPath: %v", globalPDPath)
   467  		}
   468  		volumeInfo := arr[len(arr)-1]
   469  		if strings.Contains(volumeInfo, "-lun-") {
   470  			wwnLun := strings.Split(volumeInfo, "-lun-")
   471  			if len(wwnLun) < 2 {
   472  				t.Errorf("failed to retrieve TargetWWN and Lun. volumeInfo is invalid: %v", volumeInfo)
   473  			}
   474  			lun, _ := strconv.Atoi(wwnLun[1])
   475  			lun32 := int32(lun)
   476  			if wwnLun[0] != "50060e801049cfd1" || lun32 != 0 {
   477  				t.Errorf("failed to retrieve TargetWWN and Lun")
   478  			}
   479  		} else {
   480  			if volumeInfo != "3600508b400105e210000900000490000" {
   481  				t.Errorf("failed to retrieve WWIDs")
   482  			}
   483  		}
   484  	}
   485  }
   486  
   487  func Test_ConstructVolumeSpecNoRefs(t *testing.T) {
   488  	fm := mount.NewFakeMounter(
   489  		[]mount.MountPoint{
   490  			{Device: "/dev/sdd", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod1"},
   491  		})
   492  	mountPaths := []string{
   493  		"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod1",
   494  	}
   495  	for _, path := range mountPaths {
   496  		refs, _ := fm.GetMountRefs(path)
   497  		var globalPDPath string
   498  		for _, ref := range refs {
   499  			if strings.Contains(ref, "kubernetes.io/fc") {
   500  				globalPDPath = ref
   501  				break
   502  			}
   503  		}
   504  		if len(globalPDPath) != 0 {
   505  			t.Errorf("invalid globalPDPath")
   506  		}
   507  	}
   508  }
   509  

View as plain text