github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/lxd/storage_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package lxd_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/testing"
     9  	jc "github.com/juju/testing/checkers"
    10  	"github.com/lxc/lxd/shared/api"
    11  	gc "gopkg.in/check.v1"
    12  	"gopkg.in/juju/names.v2"
    13  
    14  	containerlxd "github.com/juju/juju/container/lxd"
    15  	"github.com/juju/juju/environs/context"
    16  	"github.com/juju/juju/provider/lxd"
    17  	"github.com/juju/juju/storage"
    18  )
    19  
    20  type storageSuite struct {
    21  	lxd.BaseSuite
    22  
    23  	provider storage.Provider
    24  
    25  	callCtx           context.ProviderCallContext
    26  	invalidCredential bool
    27  }
    28  
    29  var _ = gc.Suite(&storageSuite{})
    30  
    31  func (s *storageSuite) SetUpTest(c *gc.C) {
    32  	s.BaseSuite.SetUpTest(c)
    33  
    34  	provider, err := s.Env.StorageProvider("lxd")
    35  	c.Assert(err, jc.ErrorIsNil)
    36  	s.provider = provider
    37  	s.Stub.ResetCalls()
    38  	s.callCtx = &context.CloudCallContext{
    39  		InvalidateCredentialFunc: func(string) error {
    40  			s.invalidCredential = true
    41  			return nil
    42  		},
    43  	}
    44  }
    45  
    46  func (s *storageSuite) TearDownTest(c *gc.C) {
    47  	s.invalidCredential = false
    48  	s.BaseSuite.TearDownTest(c)
    49  }
    50  
    51  func (s *storageSuite) filesystemSource(c *gc.C, pool string) storage.FilesystemSource {
    52  	storageConfig, err := storage.NewConfig(pool, "lxd", nil)
    53  	c.Assert(err, jc.ErrorIsNil)
    54  	filesystemSource, err := s.provider.FilesystemSource(storageConfig)
    55  	c.Assert(err, jc.ErrorIsNil)
    56  	return filesystemSource
    57  }
    58  
    59  func (s *storageSuite) TestStorageProviderTypes(c *gc.C) {
    60  	s.Client.StorageIsSupported = false
    61  	types, err := s.Env.StorageProviderTypes()
    62  	c.Assert(err, jc.ErrorIsNil)
    63  	c.Assert(types, gc.HasLen, 0)
    64  
    65  	s.Client.StorageIsSupported = true
    66  	types, err = s.Env.StorageProviderTypes()
    67  	c.Assert(err, jc.ErrorIsNil)
    68  	c.Assert(types, jc.DeepEquals, []storage.ProviderType{"lxd"})
    69  }
    70  
    71  func (s *storageSuite) TestStorageDefaultPools(c *gc.C) {
    72  	pools := s.provider.DefaultPools()
    73  	c.Assert(pools, gc.HasLen, 2)
    74  	c.Assert(pools[0].Name(), gc.Equals, "lxd-zfs")
    75  	c.Assert(pools[1].Name(), gc.Equals, "lxd-btrfs")
    76  	s.Stub.CheckCallNames(c, "CreatePool", "CreatePool")
    77  }
    78  
    79  func (s *storageSuite) TestStorageDefaultPoolsDriverNotSupported(c *gc.C) {
    80  	s.Stub.SetErrors(
    81  		errors.New("no zfs for you"),
    82  		errors.NotFoundf("zfs storage pool"),
    83  	)
    84  	pools := s.provider.DefaultPools()
    85  	c.Assert(pools, gc.HasLen, 1)
    86  	c.Assert(pools[0].Name(), gc.Equals, "lxd-btrfs")
    87  	s.Stub.CheckCallNames(c, "CreatePool", "GetStoragePool", "CreatePool")
    88  }
    89  
    90  func (s *storageSuite) TestVolumeSource(c *gc.C) {
    91  	_, err := s.provider.VolumeSource(nil)
    92  	c.Assert(err, gc.ErrorMatches, "volumes not supported")
    93  	c.Assert(err, jc.Satisfies, errors.IsNotSupported)
    94  }
    95  
    96  func (s *storageSuite) TestFilesystemSource(c *gc.C) {
    97  	s.filesystemSource(c, "pool")
    98  }
    99  
   100  func (s *storageSuite) TestSupports(c *gc.C) {
   101  	c.Assert(s.provider.Supports(storage.StorageKindBlock), jc.IsFalse)
   102  	c.Assert(s.provider.Supports(storage.StorageKindFilesystem), jc.IsTrue)
   103  }
   104  
   105  func (s *storageSuite) TestDynamic(c *gc.C) {
   106  	c.Assert(s.provider.Dynamic(), jc.IsTrue)
   107  }
   108  
   109  func (s *storageSuite) TestScope(c *gc.C) {
   110  	c.Assert(s.provider.Scope(), gc.Equals, storage.ScopeEnviron)
   111  }
   112  
   113  func (s *storageSuite) TestCreateFilesystems(c *gc.C) {
   114  	source := s.filesystemSource(c, "source")
   115  	results, err := source.CreateFilesystems(s.callCtx, []storage.FilesystemParams{{
   116  		Tag:      names.NewFilesystemTag("0"),
   117  		Provider: "lxd",
   118  		Size:     1024,
   119  		ResourceTags: map[string]string{
   120  			"key": "value",
   121  		},
   122  		Attributes: map[string]interface{}{
   123  			"lxd-pool": "radiance",
   124  			"driver":   "btrfs",
   125  		},
   126  	}})
   127  	c.Assert(err, jc.ErrorIsNil)
   128  	c.Assert(results, gc.HasLen, 1)
   129  	c.Assert(results[0].Error, jc.ErrorIsNil)
   130  	c.Assert(results[0].Filesystem, jc.DeepEquals, &storage.Filesystem{
   131  		Tag: names.NewFilesystemTag("0"),
   132  		FilesystemInfo: storage.FilesystemInfo{
   133  			FilesystemId: "radiance:juju-f75cba-filesystem-0",
   134  			Size:         1024,
   135  		},
   136  	})
   137  
   138  	s.Stub.CheckCallNames(c, "CreatePool", "CreateVolume")
   139  	s.Stub.CheckCall(c, 0, "CreatePool", "radiance", "btrfs", map[string]string(nil))
   140  	s.Stub.CheckCall(c, 1, "CreateVolume", "radiance", "juju-f75cba-filesystem-0", map[string]string{
   141  		"user.key": "value",
   142  		"size":     "1024MiB",
   143  	})
   144  }
   145  
   146  func (s *storageSuite) TestCreateFilesystemsPoolExists(c *gc.C) {
   147  	s.Stub.SetErrors(errors.New("pool already exists"))
   148  	source := s.filesystemSource(c, "source")
   149  	results, err := source.CreateFilesystems(s.callCtx, []storage.FilesystemParams{{
   150  		Tag:      names.NewFilesystemTag("0"),
   151  		Provider: "lxd",
   152  		Size:     1024,
   153  		ResourceTags: map[string]string{
   154  			"key": "value",
   155  		},
   156  		Attributes: map[string]interface{}{
   157  			"lxd-pool": "radiance",
   158  			"driver":   "dir",
   159  		},
   160  	}})
   161  	c.Assert(err, jc.ErrorIsNil)
   162  	c.Assert(results, gc.HasLen, 1)
   163  	c.Assert(results[0].Error, jc.ErrorIsNil)
   164  	c.Assert(results[0].Filesystem, jc.DeepEquals, &storage.Filesystem{
   165  		names.NewFilesystemTag("0"),
   166  		names.VolumeTag{},
   167  		storage.FilesystemInfo{
   168  			FilesystemId: "radiance:juju-f75cba-filesystem-0",
   169  			Size:         1024,
   170  		},
   171  	})
   172  
   173  	s.Stub.CheckCallNames(c, "CreatePool", "GetStoragePool", "CreateVolume")
   174  	s.Stub.CheckCall(c, 0, "CreatePool", "radiance", "dir", map[string]string(nil))
   175  	s.Stub.CheckCall(c, 1, "GetStoragePool", "radiance")
   176  	s.Stub.CheckCall(c, 2, "CreateVolume", "radiance", "juju-f75cba-filesystem-0", map[string]string{
   177  		"user.key": "value",
   178  	})
   179  }
   180  
   181  func (s *storageSuite) TestCreateFilesystemsInvalidCredentials(c *gc.C) {
   182  	c.Assert(s.invalidCredential, jc.IsFalse)
   183  	source := s.filesystemSource(c, "source")
   184  	s.Client.Stub.SetErrors(nil, errTestUnAuth)
   185  	results, err := source.CreateFilesystems(s.callCtx, []storage.FilesystemParams{{
   186  		Tag:      names.NewFilesystemTag("0"),
   187  		Provider: "lxd",
   188  		Size:     1024,
   189  		ResourceTags: map[string]string{
   190  			"key": "value",
   191  		},
   192  		Attributes: map[string]interface{}{
   193  			"lxd-pool": "radiance",
   194  			"driver":   "btrfs",
   195  		},
   196  	}})
   197  	c.Assert(err, jc.ErrorIsNil)
   198  	c.Assert(s.invalidCredential, jc.IsTrue)
   199  	c.Assert(results, gc.HasLen, 1)
   200  	c.Assert(results[0].Error, gc.ErrorMatches, ".*not authorized")
   201  	c.Assert(results[0].Filesystem, jc.DeepEquals, (*storage.Filesystem)(nil))
   202  }
   203  
   204  func (s *storageSuite) TestDestroyFilesystems(c *gc.C) {
   205  	s.Stub.SetErrors(nil, errors.New("boom"))
   206  	source := s.filesystemSource(c, "source")
   207  	results, err := source.DestroyFilesystems(s.callCtx, []string{
   208  		"filesystem-0",
   209  		"pool0:filesystem-0",
   210  		"pool1:filesystem-1",
   211  	})
   212  	c.Assert(err, jc.ErrorIsNil)
   213  	c.Assert(results, gc.HasLen, 3)
   214  	c.Assert(results[0], gc.ErrorMatches, `invalid filesystem ID "filesystem-0"; expected ID in format <lxd-pool>:<volume-name>`)
   215  	c.Assert(results[1], jc.ErrorIsNil)
   216  	c.Assert(results[2], gc.ErrorMatches, "boom")
   217  
   218  	s.Stub.CheckCalls(c, []testing.StubCall{
   219  		{"DeleteStoragePoolVolume", []interface{}{"pool0", "custom", "filesystem-0"}},
   220  		{"DeleteStoragePoolVolume", []interface{}{"pool1", "custom", "filesystem-1"}},
   221  	})
   222  }
   223  
   224  func (s *storageSuite) TestDestroyFilesystemsInvalidCredentials(c *gc.C) {
   225  	c.Assert(s.invalidCredential, jc.IsFalse)
   226  	s.Client.Stub.SetErrors(errTestUnAuth)
   227  	source := s.filesystemSource(c, "source")
   228  	results, err := source.DestroyFilesystems(s.callCtx, []string{
   229  		"pool0:filesystem-0",
   230  	})
   231  	c.Assert(err, jc.ErrorIsNil)
   232  	c.Assert(s.invalidCredential, jc.IsTrue)
   233  	c.Assert(results, gc.HasLen, 1)
   234  	c.Assert(results[0], gc.ErrorMatches, "not authorized")
   235  }
   236  
   237  func (s *storageSuite) TestReleaseFilesystems(c *gc.C) {
   238  	s.Stub.SetErrors(nil, nil, nil, errors.New("boom"))
   239  	s.Client.Volumes = map[string][]api.StorageVolume{
   240  		"foo": {{
   241  			Name: "filesystem-0",
   242  			StorageVolumePut: api.StorageVolumePut{
   243  				Config: map[string]string{
   244  					"foo":                  "bar",
   245  					"user.juju-model-uuid": "baz",
   246  				},
   247  			},
   248  		}, {
   249  			Name: "filesystem-1",
   250  			StorageVolumePut: api.StorageVolumePut{
   251  				Config: map[string]string{
   252  					"user.juju-controller-uuid": "qux",
   253  					"user.juju-model-uuid":      "quux",
   254  				},
   255  			},
   256  		}},
   257  	}
   258  
   259  	source := s.filesystemSource(c, "source")
   260  	results, err := source.ReleaseFilesystems(s.callCtx, []string{
   261  		"filesystem-0",
   262  		"foo:filesystem-0",
   263  		"foo:filesystem-1",
   264  	})
   265  	c.Assert(err, jc.ErrorIsNil)
   266  	c.Assert(results, gc.HasLen, 3)
   267  	c.Assert(results[0], gc.ErrorMatches, `invalid filesystem ID "filesystem-0"; expected ID in format <lxd-pool>:<volume-name>`)
   268  	c.Assert(results[1], jc.ErrorIsNil)
   269  	c.Assert(results[2], gc.ErrorMatches, `removing tags from volume "filesystem-1" in pool "foo": boom`)
   270  
   271  	update0 := api.StorageVolumePut{
   272  		Config: map[string]string{
   273  			"foo": "bar",
   274  		},
   275  	}
   276  	update1 := api.StorageVolumePut{
   277  		Config: map[string]string{},
   278  	}
   279  
   280  	s.Stub.CheckCalls(c, []testing.StubCall{
   281  		{"GetStoragePoolVolume", []interface{}{"foo", "custom", "filesystem-0"}},
   282  		{"UpdateStoragePoolVolume", []interface{}{"foo", "custom", "filesystem-0", update0, "eTag"}},
   283  		{"GetStoragePoolVolume", []interface{}{"foo", "custom", "filesystem-1"}},
   284  		{"UpdateStoragePoolVolume", []interface{}{"foo", "custom", "filesystem-1", update1, "eTag"}},
   285  	})
   286  }
   287  
   288  func (s *storageSuite) TestReleaseFilesystemsInvalidCredentials(c *gc.C) {
   289  	c.Assert(s.invalidCredential, jc.IsFalse)
   290  	s.Stub.SetErrors(errTestUnAuth)
   291  
   292  	source := s.filesystemSource(c, "source")
   293  	results, err := source.ReleaseFilesystems(s.callCtx, []string{
   294  		"foo:filesystem-0",
   295  	})
   296  	c.Assert(err, jc.ErrorIsNil)
   297  	c.Assert(s.invalidCredential, jc.IsTrue)
   298  	c.Assert(results, gc.HasLen, 1)
   299  	c.Assert(results[0], gc.ErrorMatches, "not authorized")
   300  
   301  	s.Stub.CheckCalls(c, []testing.StubCall{
   302  		{"GetStoragePoolVolume", []interface{}{"foo", "custom", "filesystem-0"}},
   303  	})
   304  }
   305  
   306  func (s *storageSuite) TestAttachFilesystems(c *gc.C) {
   307  	container := s.NewContainer(c, "inst-0")
   308  	container.Devices = map[string]map[string]string{
   309  		"filesystem-1": {
   310  			"type":     "disk",
   311  			"source":   "filesystem-1",
   312  			"pool":     "pool",
   313  			"path":     "/mnt/path",
   314  			"readonly": "true",
   315  		},
   316  	}
   317  	s.Client.Containers = []containerlxd.Container{*container}
   318  
   319  	source := s.filesystemSource(c, "pool")
   320  	results, err := source.AttachFilesystems(s.callCtx, []storage.FilesystemAttachmentParams{{
   321  		AttachmentParams: storage.AttachmentParams{
   322  			Provider:   "lxd",
   323  			Machine:    names.NewMachineTag("123"),
   324  			InstanceId: "inst-0",
   325  			ReadOnly:   true,
   326  		},
   327  		Filesystem:   names.NewFilesystemTag("0"),
   328  		FilesystemId: "pool:filesystem-0",
   329  		Path:         "/mnt/path",
   330  	}, {
   331  		AttachmentParams: storage.AttachmentParams{
   332  			Provider:   "lxd",
   333  			Machine:    names.NewMachineTag("123"),
   334  			InstanceId: "inst-0",
   335  			ReadOnly:   true,
   336  		},
   337  		Filesystem:   names.NewFilesystemTag("1"),
   338  		FilesystemId: "pool:filesystem-1",
   339  		Path:         "/mnt/socio",
   340  	}, {
   341  		AttachmentParams: storage.AttachmentParams{
   342  			Provider:   "lxd",
   343  			Machine:    names.NewMachineTag("42"),
   344  			InstanceId: "inst-42",
   345  		},
   346  		Filesystem:   names.NewFilesystemTag("2"),
   347  		FilesystemId: "pool:filesystem-2",
   348  		Path:         "/mnt/psycho",
   349  	}})
   350  	c.Assert(err, jc.ErrorIsNil)
   351  	c.Assert(results, gc.HasLen, 3)
   352  	c.Assert(results[0].Error, jc.ErrorIsNil)
   353  	c.Assert(results[0].FilesystemAttachment, jc.DeepEquals, &storage.FilesystemAttachment{
   354  		names.NewFilesystemTag("0"),
   355  		names.NewMachineTag("123"),
   356  		storage.FilesystemAttachmentInfo{
   357  			Path:     "/mnt/path",
   358  			ReadOnly: true,
   359  		},
   360  	})
   361  	c.Assert(
   362  		results[1].Error,
   363  		gc.ErrorMatches,
   364  		`attaching filesystem 1 to machine 123: container "inst-0" already has a device "filesystem-1"`)
   365  	c.Assert(
   366  		results[2].Error, gc.ErrorMatches, `attaching filesystem 2 to machine 42: instance "inst-42" not found`,
   367  	)
   368  
   369  	// TODO (manadart 2018-06-25) We need to check the device written to the
   370  	// container as config.
   371  	s.Stub.CheckCalls(c, []testing.StubCall{{
   372  		"AliveContainers",
   373  		[]interface{}{"juju-f75cba-"},
   374  	}, {
   375  		"WriteContainer",
   376  		[]interface{}{&s.Client.Containers[0]},
   377  	}})
   378  }
   379  
   380  func (s *storageSuite) TestAttachFilesystemsInvalidCredentialsInstanceError(c *gc.C) {
   381  	c.Assert(s.invalidCredential, jc.IsFalse)
   382  	s.Client.Stub.SetErrors(errTestUnAuth)
   383  
   384  	container := s.NewContainer(c, "inst-0")
   385  	container.Devices = map[string]map[string]string{
   386  		"filesystem-1": {
   387  			"type":     "disk",
   388  			"source":   "filesystem-1",
   389  			"pool":     "pool",
   390  			"path":     "/mnt/path",
   391  			"readonly": "true",
   392  		},
   393  	}
   394  	s.Client.Containers = []containerlxd.Container{*container}
   395  
   396  	source := s.filesystemSource(c, "pool")
   397  	results, err := source.AttachFilesystems(s.callCtx, []storage.FilesystemAttachmentParams{{
   398  		AttachmentParams: storage.AttachmentParams{
   399  			Provider:   "lxd",
   400  			Machine:    names.NewMachineTag("123"),
   401  			InstanceId: "inst-0",
   402  			ReadOnly:   true,
   403  		},
   404  		Filesystem:   names.NewFilesystemTag("0"),
   405  		FilesystemId: "pool:filesystem-0",
   406  		Path:         "/mnt/path",
   407  	}})
   408  	c.Assert(err, gc.ErrorMatches, "not authorized")
   409  	c.Assert(s.invalidCredential, jc.IsTrue)
   410  	c.Assert(results, gc.HasLen, 0)
   411  }
   412  
   413  func (s *storageSuite) TestAttachFilesystemsInvalidCredentialsAttachingFilesystems(c *gc.C) {
   414  	c.Assert(s.invalidCredential, jc.IsFalse)
   415  	s.Client.Stub.SetErrors(nil, errTestUnAuth)
   416  
   417  	container := s.NewContainer(c, "inst-0")
   418  	container.Devices = map[string]map[string]string{
   419  		"filesystem-1": {
   420  			"type":     "disk",
   421  			"source":   "filesystem-1",
   422  			"pool":     "pool",
   423  			"path":     "/mnt/path",
   424  			"readonly": "true",
   425  		},
   426  	}
   427  	s.Client.Containers = []containerlxd.Container{*container}
   428  
   429  	source := s.filesystemSource(c, "pool")
   430  	results, err := source.AttachFilesystems(s.callCtx, []storage.FilesystemAttachmentParams{{
   431  		AttachmentParams: storage.AttachmentParams{
   432  			Provider:   "lxd",
   433  			Machine:    names.NewMachineTag("123"),
   434  			InstanceId: "inst-0",
   435  			ReadOnly:   true,
   436  		},
   437  		Filesystem:   names.NewFilesystemTag("0"),
   438  		FilesystemId: "pool:filesystem-0",
   439  		Path:         "/mnt/path",
   440  	}})
   441  	c.Assert(err, jc.ErrorIsNil)
   442  	c.Assert(s.invalidCredential, jc.IsTrue)
   443  	c.Assert(results, gc.HasLen, 1)
   444  	c.Assert(results[0].Error, gc.ErrorMatches, ".*not authorized")
   445  	c.Assert(results[0].FilesystemAttachment, jc.DeepEquals, (*storage.FilesystemAttachment)(nil))
   446  }
   447  
   448  func (s *storageSuite) TestDetachFilesystems(c *gc.C) {
   449  	container := s.NewContainer(c, "inst-0")
   450  	container.Devices = map[string]map[string]string{
   451  		"filesystem-0": {
   452  			"type":     "disk",
   453  			"source":   "filesystem-0",
   454  			"pool":     "pool",
   455  			"path":     "/mnt/path",
   456  			"readonly": "true",
   457  		},
   458  	}
   459  	s.Client.Containers = []containerlxd.Container{*container}
   460  
   461  	source := s.filesystemSource(c, "pool")
   462  	results, err := source.DetachFilesystems(s.callCtx, []storage.FilesystemAttachmentParams{{
   463  		AttachmentParams: storage.AttachmentParams{
   464  			Provider:   "lxd",
   465  			Machine:    names.NewMachineTag("123"),
   466  			InstanceId: "inst-0",
   467  		},
   468  		Filesystem:   names.NewFilesystemTag("0"),
   469  		FilesystemId: "pool:filesystem-0",
   470  	}, {
   471  		AttachmentParams: storage.AttachmentParams{
   472  			Provider:   "lxd",
   473  			Machine:    names.NewMachineTag("123"),
   474  			InstanceId: "inst-0",
   475  		},
   476  		Filesystem:   names.NewFilesystemTag("1"),
   477  		FilesystemId: "pool:filesystem-1",
   478  	}, {
   479  		AttachmentParams: storage.AttachmentParams{
   480  			Provider:   "lxd",
   481  			Machine:    names.NewMachineTag("42"),
   482  			InstanceId: "inst-42",
   483  		},
   484  		Filesystem:   names.NewFilesystemTag("2"),
   485  		FilesystemId: "pool:filesystem-2",
   486  	}})
   487  	c.Assert(err, jc.ErrorIsNil)
   488  	c.Assert(results, gc.HasLen, 3)
   489  	c.Assert(results[0], jc.ErrorIsNil)
   490  	c.Assert(results[1], jc.ErrorIsNil)
   491  	c.Assert(results[2], jc.ErrorIsNil)
   492  
   493  	// TODO (manadart 2018-06-25) We need to check the container config to
   494  	// ensure it represents the removed device.
   495  	s.Stub.CheckCalls(c, []testing.StubCall{{
   496  		"AliveContainers",
   497  		[]interface{}{"juju-f75cba-"},
   498  	}, {
   499  		"WriteContainer",
   500  		[]interface{}{&s.Client.Containers[0]},
   501  	}, {
   502  		"WriteContainer",
   503  		[]interface{}{&s.Client.Containers[0]},
   504  	}})
   505  }
   506  
   507  func (s *storageSuite) TestDetachFilesystemsInvalidCredentialsInstanceErrors(c *gc.C) {
   508  	c.Assert(s.invalidCredential, jc.IsFalse)
   509  	s.Client.Stub.SetErrors(errTestUnAuth)
   510  
   511  	source := s.filesystemSource(c, "pool")
   512  	results, err := source.DetachFilesystems(s.callCtx, []storage.FilesystemAttachmentParams{{
   513  		AttachmentParams: storage.AttachmentParams{
   514  			Provider:   "lxd",
   515  			Machine:    names.NewMachineTag("123"),
   516  			InstanceId: "inst-0",
   517  		},
   518  		Filesystem:   names.NewFilesystemTag("0"),
   519  		FilesystemId: "pool:filesystem-0",
   520  	}})
   521  	c.Assert(s.invalidCredential, jc.IsTrue)
   522  	c.Assert(err, gc.ErrorMatches, "not authorized")
   523  	c.Assert(results, gc.HasLen, 0)
   524  }
   525  
   526  func (s *storageSuite) TestDetachFilesystemsInvalidCredentialsDetachFilesystem(c *gc.C) {
   527  	c.Assert(s.invalidCredential, jc.IsFalse)
   528  	s.Client.Stub.SetErrors(nil, errTestUnAuth)
   529  
   530  	container := s.NewContainer(c, "inst-0")
   531  	container.Devices = map[string]map[string]string{
   532  		"filesystem-0": {
   533  			"type":     "disk",
   534  			"source":   "filesystem-0",
   535  			"pool":     "pool",
   536  			"path":     "/mnt/path",
   537  			"readonly": "true",
   538  		},
   539  	}
   540  	s.Client.Containers = []containerlxd.Container{*container}
   541  
   542  	source := s.filesystemSource(c, "pool")
   543  	results, err := source.DetachFilesystems(s.callCtx, []storage.FilesystemAttachmentParams{{
   544  		AttachmentParams: storage.AttachmentParams{
   545  			Provider:   "lxd",
   546  			Machine:    names.NewMachineTag("123"),
   547  			InstanceId: "inst-0",
   548  		},
   549  		Filesystem:   names.NewFilesystemTag("0"),
   550  		FilesystemId: "pool:filesystem-0",
   551  	}})
   552  	c.Assert(s.invalidCredential, jc.IsTrue)
   553  	c.Assert(err, jc.ErrorIsNil)
   554  	c.Assert(results, gc.HasLen, 1)
   555  	c.Assert(results[0], gc.ErrorMatches, ".*not authorized")
   556  }
   557  
   558  func (s *storageSuite) TestImportFilesystem(c *gc.C) {
   559  	source := s.filesystemSource(c, "pool")
   560  	c.Assert(source, gc.Implements, new(storage.FilesystemImporter))
   561  	importer := source.(storage.FilesystemImporter)
   562  
   563  	s.Client.Volumes = map[string][]api.StorageVolume{
   564  		"foo": {{
   565  			Name: "bar",
   566  			StorageVolumePut: api.StorageVolumePut{
   567  				Config: map[string]string{
   568  					"size": "10GiB",
   569  				},
   570  			},
   571  		}},
   572  	}
   573  
   574  	info, err := importer.ImportFilesystem(s.callCtx,
   575  		"foo:bar", map[string]string{
   576  			"baz": "qux",
   577  		})
   578  	c.Assert(err, jc.ErrorIsNil)
   579  	c.Assert(info, jc.DeepEquals, storage.FilesystemInfo{
   580  		FilesystemId: "foo:bar",
   581  		Size:         10 * 1024,
   582  	})
   583  
   584  	update := api.StorageVolumePut{
   585  		Config: map[string]string{
   586  			"size":     "10GiB",
   587  			"user.baz": "qux",
   588  		},
   589  	}
   590  	s.Stub.CheckCalls(c, []testing.StubCall{
   591  		{"GetStoragePoolVolume", []interface{}{"foo", "custom", "bar"}},
   592  		{"UpdateStoragePoolVolume", []interface{}{"foo", "custom", "bar", update, "eTag"}},
   593  	})
   594  }
   595  
   596  func (s *storageSuite) TestImportFilesystemInvalidCredentialsGetPool(c *gc.C) {
   597  	c.Assert(s.invalidCredential, jc.IsFalse)
   598  	s.Client.Stub.SetErrors(errTestUnAuth)
   599  	source := s.filesystemSource(c, "pool")
   600  
   601  	c.Assert(source, gc.Implements, new(storage.FilesystemImporter))
   602  	importer := source.(storage.FilesystemImporter)
   603  
   604  	info, err := importer.ImportFilesystem(s.callCtx,
   605  		"foo:bar", map[string]string{
   606  			"baz": "qux",
   607  		})
   608  	c.Assert(err, gc.ErrorMatches, ".*not authorized")
   609  	c.Assert(s.invalidCredential, jc.IsTrue)
   610  	c.Assert(info, jc.DeepEquals, storage.FilesystemInfo{})
   611  }
   612  
   613  func (s *storageSuite) TestImportFilesystemInvalidCredentialsUpdatePool(c *gc.C) {
   614  	c.Assert(s.invalidCredential, jc.IsFalse)
   615  	s.Client.Stub.SetErrors(nil, errTestUnAuth)
   616  	source := s.filesystemSource(c, "pool")
   617  
   618  	c.Assert(source, gc.Implements, new(storage.FilesystemImporter))
   619  	importer := source.(storage.FilesystemImporter)
   620  
   621  	s.Client.Volumes = map[string][]api.StorageVolume{
   622  		"foo": {{
   623  			Name: "bar",
   624  			StorageVolumePut: api.StorageVolumePut{
   625  				Config: map[string]string{
   626  					"size": "10GiB",
   627  				},
   628  			},
   629  		}},
   630  	}
   631  
   632  	info, err := importer.ImportFilesystem(s.callCtx,
   633  		"foo:bar", map[string]string{
   634  			"baz": "qux",
   635  		})
   636  	c.Assert(err, gc.ErrorMatches, ".*not authorized")
   637  	c.Assert(s.invalidCredential, jc.IsTrue)
   638  	c.Assert(info, jc.DeepEquals, storage.FilesystemInfo{})
   639  }