github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/worker/diskformatter/diskformatter_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package diskformatter_test
     5  
     6  import (
     7  	"errors"
     8  	"time"
     9  
    10  	"github.com/juju/names"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/api/watcher"
    14  	"github.com/juju/juju/apiserver/params"
    15  	"github.com/juju/juju/storage"
    16  	coretesting "github.com/juju/juju/testing"
    17  	"github.com/juju/juju/worker/diskformatter"
    18  	"github.com/juju/testing"
    19  )
    20  
    21  var _ = gc.Suite(&DiskFormatterWorkerSuite{})
    22  
    23  type DiskFormatterWorkerSuite struct {
    24  	coretesting.BaseSuite
    25  }
    26  
    27  func (s *DiskFormatterWorkerSuite) TestWorker(c *gc.C) {
    28  	ids := []string{
    29  		"0", "1", "2", "3", "4", "5",
    30  	}
    31  
    32  	blockDeviceResults := []params.BlockDeviceResult{{
    33  		Result: storage.BlockDevice{
    34  			Name:       "0",
    35  			DeviceName: "sda",
    36  			Label:      "dev0-label",
    37  			UUID:       "9aade75c-6528-4acf-ab69-258b8dc51798",
    38  		},
    39  	}, {
    40  		Result: storage.BlockDevice{
    41  			Name:           "1",
    42  			DeviceName:     "sdb",
    43  			UUID:           "edc2348a-a2bc-4b15-b7f3-cb951b3489ad",
    44  			FilesystemType: "btrfs",
    45  		},
    46  	}, {
    47  		Result: storage.BlockDevice{
    48  			Name:       "2",
    49  			DeviceName: "sdc",
    50  		},
    51  	}, {
    52  		Result: storage.BlockDevice{
    53  			Name:       "3",
    54  			DeviceName: "sdd",
    55  		},
    56  	}, {
    57  		Result: storage.BlockDevice{
    58  			Name:       "4",
    59  			DeviceName: "sde",
    60  		},
    61  	}, {
    62  		Error: &params.Error{
    63  			Code:    params.CodeNotFound,
    64  			Message: "block device 5 not found",
    65  		},
    66  	}}
    67  
    68  	blockDeviceStorageInstanceResults := []params.StorageInstanceResult{{
    69  		Result: storage.StorageInstance{
    70  			Id:   "needs-a-filesystem",
    71  			Kind: storage.StorageKindFilesystem,
    72  		},
    73  	}, {
    74  		Result: storage.StorageInstance{
    75  			Id:   "already-has-a-filesystem",
    76  			Kind: storage.StorageKindFilesystem,
    77  		},
    78  	}, {
    79  		Result: storage.StorageInstance{
    80  			Id:   "doesnt-need-a-filesystem",
    81  			Kind: storage.StorageKindBlock,
    82  		},
    83  	}, {
    84  		Error: &params.Error{
    85  			Code:    params.CodeNotAssigned,
    86  			Message: "3 is not assigned to a storage instance",
    87  		},
    88  	}}
    89  
    90  	accessor := &mockBlockDeviceAccessor{
    91  		changes: make(chan []string),
    92  		blockDevices: func(tags []names.DiskTag) (params.BlockDeviceResults, error) {
    93  			expect := make([]names.DiskTag, len(ids))
    94  			for i, id := range ids {
    95  				expect[i] = names.NewDiskTag(id)
    96  			}
    97  			c.Assert(tags, gc.DeepEquals, expect)
    98  			return params.BlockDeviceResults{blockDeviceResults}, nil
    99  		},
   100  		blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
   101  			expect := make([]names.DiskTag, 0, len(blockDeviceResults))
   102  			for i, result := range blockDeviceResults {
   103  				if result.Error != nil {
   104  					continue
   105  				}
   106  				expect = append(expect, names.NewDiskTag(ids[i]))
   107  			}
   108  			c.Assert(tags, gc.DeepEquals, expect)
   109  			return params.StorageInstanceResults{blockDeviceStorageInstanceResults}, nil
   110  		},
   111  	}
   112  
   113  	testing.PatchExecutableAsEchoArgs(c, s, "mkfs.ext4")
   114  
   115  	w := diskformatter.NewWorker(accessor)
   116  	accessor.changes <- ids
   117  	done := make(chan struct{})
   118  	go func() {
   119  		w.Kill()
   120  		w.Wait()
   121  		close(done)
   122  	}()
   123  
   124  	select {
   125  	case <-done:
   126  		testing.AssertEchoArgs(c, "mkfs.ext4", "/dev/disk/by-label/dev0-label")
   127  	case <-time.After(coretesting.LongWait):
   128  		c.Fatalf("timed out waiting for diskformatter to update")
   129  	}
   130  }
   131  
   132  func (s *DiskFormatterWorkerSuite) TestMakeDefaultFilesystem(c *gc.C) {
   133  	accessor := &mockBlockDeviceAccessor{
   134  		blockDevices: func([]names.DiskTag) (params.BlockDeviceResults, error) {
   135  			return params.BlockDeviceResults{[]params.BlockDeviceResult{{
   136  				Result: storage.BlockDevice{
   137  					Name:       "0",
   138  					DeviceName: "sda",
   139  					Label:      "dev0-label",
   140  					UUID:       "9aade75c-6528-4acf-ab69-258b8dc51798",
   141  				},
   142  			}}}, nil
   143  		},
   144  		blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
   145  			return params.StorageInstanceResults{[]params.StorageInstanceResult{{
   146  				Result: storage.StorageInstance{
   147  					Id:   "needs-a-filesystem",
   148  					Kind: storage.StorageKindFilesystem,
   149  				},
   150  			}}}, nil
   151  		},
   152  	}
   153  
   154  	testing.PatchExecutableAsEchoArgs(c, s, "mkfs.ext4")
   155  	formatter := diskformatter.NewDiskFormatter(accessor)
   156  	err := formatter.Handle([]string{"0"})
   157  	c.Assert(err, gc.IsNil)
   158  	testing.AssertEchoArgs(c, "mkfs.ext4", "/dev/disk/by-label/dev0-label")
   159  }
   160  
   161  func (s *DiskFormatterWorkerSuite) TestBlockDeviceError(c *gc.C) {
   162  	accessor := &mockBlockDeviceAccessor{
   163  		blockDevices: func(tags []names.DiskTag) (params.BlockDeviceResults, error) {
   164  			return params.BlockDeviceResults{}, errors.New("BlockDevice failed")
   165  		},
   166  	}
   167  	formatter := diskformatter.NewDiskFormatter(accessor)
   168  	err := formatter.Handle([]string{"0"})
   169  	c.Assert(err, gc.ErrorMatches, "cannot get block devices: BlockDevice failed")
   170  }
   171  
   172  func (s *DiskFormatterWorkerSuite) TestBlockDeviceStorageInstanceError(c *gc.C) {
   173  	accessor := &mockBlockDeviceAccessor{
   174  		blockDevices: func([]names.DiskTag) (params.BlockDeviceResults, error) {
   175  			return params.BlockDeviceResults{[]params.BlockDeviceResult{{
   176  				Result: storage.BlockDevice{Name: "0", DeviceName: "sda"},
   177  			}}}, nil
   178  		},
   179  		blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
   180  			return params.StorageInstanceResults{}, errors.New("BlockDeviceStorageInstance failed")
   181  		},
   182  	}
   183  	formatter := diskformatter.NewDiskFormatter(accessor)
   184  	err := formatter.Handle([]string{"0"})
   185  	c.Assert(err, gc.ErrorMatches, "cannot get assigned storage instances: BlockDeviceStorageInstance failed")
   186  }
   187  
   188  func (s *DiskFormatterWorkerSuite) TestCannotMakeFilesystem(c *gc.C) {
   189  	accessor := &mockBlockDeviceAccessor{
   190  		blockDevices: func(tags []names.DiskTag) (params.BlockDeviceResults, error) {
   191  			return params.BlockDeviceResults{[]params.BlockDeviceResult{{
   192  				Result: storage.BlockDevice{Name: "0", DeviceName: "sda"},
   193  			}}}, nil
   194  		},
   195  		blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) {
   196  			return params.StorageInstanceResults{[]params.StorageInstanceResult{{
   197  				Result: storage.StorageInstance{
   198  					Id:   "needs-a-filesystem",
   199  					Kind: storage.StorageKindFilesystem,
   200  				},
   201  			}}}, nil
   202  		},
   203  	}
   204  	// Failure to create a filesystem should not cause the handler to error.
   205  	testing.PatchExecutableThrowError(c, s, "mkfs.ext4", 1)
   206  	formatter := diskformatter.NewDiskFormatter(accessor)
   207  	err := formatter.Handle([]string{"0"})
   208  	c.Assert(err, gc.IsNil)
   209  }
   210  
   211  type mockBlockDeviceAccessor struct {
   212  	changes                     chan []string
   213  	blockDevices                func([]names.DiskTag) (params.BlockDeviceResults, error)
   214  	blockDeviceStorageInstances func([]names.DiskTag) (params.StorageInstanceResults, error)
   215  }
   216  
   217  func (m *mockBlockDeviceAccessor) Changes() <-chan []string {
   218  	return m.changes
   219  }
   220  
   221  func (m *mockBlockDeviceAccessor) Stop() error {
   222  	return nil
   223  }
   224  
   225  func (m *mockBlockDeviceAccessor) Err() error {
   226  	return nil
   227  }
   228  
   229  func (m *mockBlockDeviceAccessor) WatchBlockDevices() (watcher.StringsWatcher, error) {
   230  	return m, nil
   231  }
   232  
   233  func (m *mockBlockDeviceAccessor) BlockDevices(tags []names.DiskTag) (params.BlockDeviceResults, error) {
   234  	return m.blockDevices(tags)
   235  }
   236  
   237  func (m *mockBlockDeviceAccessor) BlockDeviceStorageInstances(tags []names.DiskTag) (params.StorageInstanceResults, error) {
   238  	return m.blockDeviceStorageInstances(tags)
   239  }