github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/uniter/runner/context/unitStorage_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package context_test
     5  
     6  import (
     7  	"github.com/juju/names"
     8  	jc "github.com/juju/testing/checkers"
     9  	"github.com/juju/utils"
    10  	"github.com/juju/utils/set"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/provider/ec2"
    15  	"github.com/juju/juju/state"
    16  	"github.com/juju/juju/storage/poolmanager"
    17  	"github.com/juju/juju/storage/provider"
    18  	"github.com/juju/juju/storage/provider/registry"
    19  	"github.com/juju/juju/worker/uniter/runner/context"
    20  )
    21  
    22  type unitStorageSuite struct {
    23  	HookContextSuite
    24  	expectedStorageNames         set.Strings
    25  	charmName                    string
    26  	initCons                     map[string]state.StorageConstraints
    27  	ch                           *state.Charm
    28  	initialStorageInstancesCount int
    29  }
    30  
    31  var _ = gc.Suite(&unitStorageSuite{})
    32  
    33  const (
    34  	testPool           = "block"
    35  	testPersistentPool = "block-persistent"
    36  )
    37  
    38  func (s *unitStorageSuite) SetUpTest(c *gc.C) {
    39  	s.HookContextSuite.SetUpTest(c)
    40  	setupTestStorageSupport(c, s.State)
    41  }
    42  
    43  func (s *unitStorageSuite) TestAddUnitStorage(c *gc.C) {
    44  	s.createStorageBlockUnit(c)
    45  	count := uint64(1)
    46  	s.assertUnitStorageAdded(c,
    47  		map[string]params.StorageConstraints{
    48  			"allecto": params.StorageConstraints{Count: &count}})
    49  }
    50  
    51  func (s *unitStorageSuite) TestAddUnitStorageIgnoresBlocks(c *gc.C) {
    52  	s.createStorageBlockUnit(c)
    53  	count := uint64(1)
    54  	s.BlockDestroyModel(c, "TestAddUnitStorageIgnoresBlocks")
    55  	s.BlockRemoveObject(c, "TestAddUnitStorageIgnoresBlocks")
    56  	s.BlockAllChanges(c, "TestAddUnitStorageIgnoresBlocks")
    57  	s.assertUnitStorageAdded(c,
    58  		map[string]params.StorageConstraints{
    59  			"allecto": params.StorageConstraints{Count: &count}})
    60  }
    61  
    62  func (s *unitStorageSuite) TestAddUnitStorageZeroCount(c *gc.C) {
    63  	s.createStorageBlockUnit(c)
    64  	cons := map[string]params.StorageConstraints{
    65  		"allecto": params.StorageConstraints{}}
    66  
    67  	ctx := s.addUnitStorage(c, cons)
    68  
    69  	// Flush the context with a success.
    70  	err := ctx.Flush("success", nil)
    71  	c.Assert(err, gc.ErrorMatches, `.*count must be specified.*`)
    72  
    73  	// Make sure no storage instances was added
    74  	after, err := s.State.AllStorageInstances()
    75  	c.Assert(err, jc.ErrorIsNil)
    76  	c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, 0)
    77  	s.assertExistingStorage(c, after)
    78  }
    79  
    80  func (s *unitStorageSuite) TestAddUnitStorageWithSize(c *gc.C) {
    81  	s.createStorageBlockUnit(c)
    82  	size := uint64(1)
    83  	cons := map[string]params.StorageConstraints{
    84  		"allecto": params.StorageConstraints{Size: &size}}
    85  
    86  	ctx := s.addUnitStorage(c, cons)
    87  
    88  	// Flush the context with a success.
    89  	err := ctx.Flush("success", nil)
    90  	c.Assert(err, gc.ErrorMatches, `.*only count can be specified.*`)
    91  
    92  	// Make sure no storage instances was added
    93  	after, err := s.State.AllStorageInstances()
    94  	c.Assert(err, jc.ErrorIsNil)
    95  	c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, 0)
    96  	s.assertExistingStorage(c, after)
    97  }
    98  
    99  func (s *unitStorageSuite) TestAddUnitStorageWithPool(c *gc.C) {
   100  	s.createStorageBlockUnit(c)
   101  	cons := map[string]params.StorageConstraints{
   102  		"allecto": params.StorageConstraints{Pool: "loop"}}
   103  
   104  	ctx := s.addUnitStorage(c, cons)
   105  
   106  	// Flush the context with a success.
   107  	err := ctx.Flush("success", nil)
   108  	c.Assert(err, gc.ErrorMatches, `.*only count can be specified.*`)
   109  
   110  	// Make sure no storage instances was added
   111  	after, err := s.State.AllStorageInstances()
   112  	c.Assert(err, jc.ErrorIsNil)
   113  	c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, 0)
   114  	s.assertExistingStorage(c, after)
   115  }
   116  
   117  func (s *unitStorageSuite) TestAddUnitStorageAccumulated(c *gc.C) {
   118  	s.createStorageBlock2Unit(c)
   119  	count := uint64(1)
   120  	s.assertUnitStorageAdded(c,
   121  		map[string]params.StorageConstraints{
   122  			"multi2up": params.StorageConstraints{Count: &count}},
   123  		map[string]params.StorageConstraints{
   124  			"multi1to10": params.StorageConstraints{Count: &count}})
   125  }
   126  
   127  func (s *unitStorageSuite) TestAddUnitStorageAccumulatedSame(c *gc.C) {
   128  	s.createStorageBlock2Unit(c)
   129  	count := uint64(1)
   130  	s.assertUnitStorageAdded(c,
   131  		map[string]params.StorageConstraints{
   132  			"multi2up": params.StorageConstraints{Count: &count}},
   133  		map[string]params.StorageConstraints{
   134  			"multi2up": params.StorageConstraints{Count: &count}})
   135  }
   136  
   137  func setupTestStorageSupport(c *gc.C, s *state.State) {
   138  	stsetts := state.NewStateSettings(s)
   139  	poolManager := poolmanager.New(stsetts)
   140  	_, err := poolManager.Create(testPool, provider.LoopProviderType, map[string]interface{}{"it": "works"})
   141  	c.Assert(err, jc.ErrorIsNil)
   142  	_, err = poolManager.Create(testPersistentPool, ec2.EBS_ProviderType, map[string]interface{}{"persistent": true})
   143  	c.Assert(err, jc.ErrorIsNil)
   144  
   145  	registry.RegisterEnvironStorageProviders("dummy", ec2.EBS_ProviderType)
   146  	registry.RegisterEnvironStorageProviders("admin", ec2.EBS_ProviderType)
   147  }
   148  
   149  func (s *unitStorageSuite) createStorageEnabledUnit(c *gc.C) {
   150  	s.ch = s.AddTestingCharm(c, s.charmName)
   151  	s.service = s.AddTestingServiceWithStorage(c, s.charmName, s.ch, s.initCons)
   152  	s.unit = s.AddUnit(c, s.service)
   153  
   154  	s.assertStorageCreated(c)
   155  	s.createHookSupport(c)
   156  }
   157  
   158  func (s *unitStorageSuite) createStorageBlockUnit(c *gc.C) {
   159  	s.charmName = "storage-block"
   160  	s.initCons = map[string]state.StorageConstraints{
   161  		"data": makeStorageCons("block", 1024, 1),
   162  	}
   163  	s.createStorageEnabledUnit(c)
   164  	s.assertStorageCreated(c)
   165  	s.createHookSupport(c)
   166  }
   167  
   168  func (s *unitStorageSuite) createStorageBlock2Unit(c *gc.C) {
   169  	s.charmName = "storage-block2"
   170  	s.initCons = map[string]state.StorageConstraints{
   171  		"multi1to10": makeStorageCons("loop", 0, 3),
   172  	}
   173  	s.createStorageEnabledUnit(c)
   174  	s.assertStorageCreated(c)
   175  	s.createHookSupport(c)
   176  }
   177  
   178  func (s *unitStorageSuite) assertStorageCreated(c *gc.C) {
   179  	all, err := s.State.AllStorageInstances()
   180  	c.Assert(err, jc.ErrorIsNil)
   181  	s.initialStorageInstancesCount = len(all)
   182  	s.expectedStorageNames = set.NewStrings()
   183  	for _, one := range all {
   184  		s.expectedStorageNames.Add(one.StorageName())
   185  	}
   186  }
   187  
   188  func (s *unitStorageSuite) createHookSupport(c *gc.C) {
   189  	password, err := utils.RandomPassword()
   190  	err = s.unit.SetPassword(password)
   191  	c.Assert(err, jc.ErrorIsNil)
   192  	s.st = s.OpenAPIAs(c, s.unit.Tag(), password)
   193  	s.uniter, err = s.st.Uniter()
   194  	c.Assert(err, jc.ErrorIsNil)
   195  	c.Assert(s.uniter, gc.NotNil)
   196  	s.apiUnit, err = s.uniter.Unit(s.unit.Tag().(names.UnitTag))
   197  	c.Assert(err, jc.ErrorIsNil)
   198  
   199  	err = s.unit.SetCharmURL(s.ch.URL())
   200  	c.Assert(err, jc.ErrorIsNil)
   201  }
   202  
   203  func makeStorageCons(pool string, size, count uint64) state.StorageConstraints {
   204  	return state.StorageConstraints{Pool: pool, Size: size, Count: count}
   205  }
   206  
   207  func (s *unitStorageSuite) addUnitStorage(c *gc.C, cons ...map[string]params.StorageConstraints) *context.HookContext {
   208  	// Get the context.
   209  	ctx := s.getHookContext(c, s.State.ModelUUID(), -1, "", noProxies)
   210  	c.Assert(ctx.UnitName(), gc.Equals, s.unit.Name())
   211  
   212  	for _, one := range cons {
   213  		for storage, _ := range one {
   214  			s.expectedStorageNames.Add(storage)
   215  		}
   216  		ctx.AddUnitStorage(one)
   217  	}
   218  	return ctx
   219  }
   220  
   221  func (s *unitStorageSuite) assertUnitStorageAdded(c *gc.C, cons ...map[string]params.StorageConstraints) {
   222  	ctx := s.addUnitStorage(c, cons...)
   223  
   224  	// Flush the context with a success.
   225  	err := ctx.Flush("success", nil)
   226  	c.Assert(err, jc.ErrorIsNil)
   227  
   228  	after, err := s.State.AllStorageInstances()
   229  	c.Assert(err, jc.ErrorIsNil)
   230  	c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, len(cons))
   231  	s.assertExistingStorage(c, after)
   232  }
   233  
   234  func (s *unitStorageSuite) assertExistingStorage(c *gc.C, all []state.StorageInstance) {
   235  	for _, one := range all {
   236  		c.Assert(s.expectedStorageNames.Contains(one.StorageName()), jc.IsTrue)
   237  	}
   238  }