func (s *rootfsSuite) TestCreateFilesystems(c *gc.C) { source := s.rootfsFilesystemSource(c) cmd := s.commands.expect("df", "--output=size", s.storageDir) cmd.respond("1K-blocks\n2048", nil) cmd = s.commands.expect("df", "--output=size", s.storageDir) cmd.respond("1K-blocks\n4096", nil) results, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("6"), Size: 2, }, { Tag: names.NewFilesystemTag("7"), Size: 4, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(results, jc.DeepEquals, []storage.CreateFilesystemsResult{{ Filesystem: &storage.Filesystem{ Tag: names.NewFilesystemTag("6"), FilesystemInfo: storage.FilesystemInfo{ FilesystemId: "6", Size: 2, }, }, }, { Filesystem: &storage.Filesystem{ Tag: names.NewFilesystemTag("7"), FilesystemInfo: storage.FilesystemInfo{ FilesystemId: "7", Size: 4, }, }, }}) }
func (s *tmpfsSuite) TestCreateFilesystemsHugePages(c *gc.C) { source := s.tmpfsFilesystemSource(c) // Set page size to 16MiB. s.PatchValue(provider.Getpagesize, func() int { return 16 * 1024 * 1024 }) results, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("1"), Size: 17, }, { Tag: names.NewFilesystemTag("2"), Size: 16, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(results, jc.DeepEquals, []storage.CreateFilesystemsResult{{ Filesystem: &storage.Filesystem{ Tag: names.NewFilesystemTag("1"), FilesystemInfo: storage.FilesystemInfo{ FilesystemId: "filesystem-1", Size: 32, }, }, }, { Filesystem: &storage.Filesystem{ Tag: names.NewFilesystemTag("2"), FilesystemInfo: storage.FilesystemInfo{ FilesystemId: "filesystem-2", Size: 16, }, }, }}) }
func (s *provisionerSuite) TestRemoveFilesystemsMachineAgent(c *gc.C) { s.setupFilesystems(c) s.authorizer.EnvironManager = false args := params.Entities{Entities: []params.Entity{ {"filesystem-0-0"}, {"filesystem-0-42"}, {"filesystem-42"}, {"filesystem-invalid"}, {"machine-0"}, }} err := s.State.DetachFilesystem(names.NewMachineTag("0"), names.NewFilesystemTag("0/0")) c.Assert(err, jc.ErrorIsNil) err = s.State.RemoveFilesystemAttachment(names.NewMachineTag("0"), names.NewFilesystemTag("0/0")) c.Assert(err, jc.ErrorIsNil) err = s.State.DestroyFilesystem(names.NewFilesystemTag("0/0")) c.Assert(err, jc.ErrorIsNil) result, err := s.api.Remove(args) c.Assert(err, jc.ErrorIsNil) c.Assert(result, gc.DeepEquals, params.ErrorResults{ Results: []params.ErrorResult{ {Error: nil}, {Error: nil}, {Error: ¶ms.Error{Message: "permission denied", Code: "unauthorized access"}}, {Error: ¶ms.Error{Message: `"filesystem-invalid" is not a valid filesystem tag`}}, {Error: ¶ms.Error{Message: "permission denied", Code: "unauthorized access"}}, }, }) }
func (s *tmpfsSuite) TestAttachFilesystemsMountReadOnly(c *gc.C) { source := s.tmpfsFilesystemSource(c) _, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("1"), Size: 1024, }}) c.Assert(err, jc.ErrorIsNil) cmd := s.commands.expect("df", "--output=source", "/var/lib/juju/storage/fs/foo") cmd.respond("header\nvalue", nil) s.commands.expect("mount", "-t", "tmpfs", "filesystem-1", "/var/lib/juju/storage/fs/foo", "-o", "size=1024m,ro") results, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{ Filesystem: names.NewFilesystemTag("1"), Path: "/var/lib/juju/storage/fs/foo", AttachmentParams: storage.AttachmentParams{ Machine: names.NewMachineTag("2"), ReadOnly: true, }, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(results, jc.DeepEquals, []storage.AttachFilesystemsResult{{ FilesystemAttachment: &storage.FilesystemAttachment{ Filesystem: names.NewFilesystemTag("1"), Machine: names.NewMachineTag("2"), FilesystemAttachmentInfo: storage.FilesystemAttachmentInfo{ Path: "/var/lib/juju/storage/fs/foo", ReadOnly: true, }, }, }}) }
func (s *rootfsSuite) TestAttachFilesystemsBindSameFSNonEmptyDirClaimed(c *gc.C) { source := s.rootfsFilesystemSource(c) cmd := s.commands.expect("df", "--output=source", "/srv/666") cmd.respond("headers\n/src/of/root", nil) cmd = s.commands.expect("mount", "--bind", filepath.Join(s.storageDir, "6"), "/srv/666") cmd.respond("", errors.New("mount --bind fails")) cmd = s.commands.expect("df", "--output=target", filepath.Join(s.storageDir, "6")) cmd.respond("headers\n/dev", nil) cmd = s.commands.expect("df", "--output=target", "/srv/666") cmd.respond("headers\n/dev", nil) s.mockDirFuncs.Dirs.Add(filepath.Join(s.storageDir, "6", "juju-target-claimed")) results, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{ Filesystem: names.NewFilesystemTag("6"), FilesystemId: "6", Path: "/srv/666", }}) c.Assert(err, jc.ErrorIsNil) c.Assert(results, jc.DeepEquals, []storage.AttachFilesystemsResult{{ FilesystemAttachment: &storage.FilesystemAttachment{ Filesystem: names.NewFilesystemTag("6"), FilesystemAttachmentInfo: storage.FilesystemAttachmentInfo{ Path: "/srv/666", }, }, }}) }
func (s *filesystemSuite) TestParseFilesystemTag(c *gc.C) { assertParseFilesystemTag(c, "filesystem-0", names.NewFilesystemTag("0")) assertParseFilesystemTag(c, "filesystem-88", names.NewFilesystemTag("88")) assertParseFilesystemTag(c, "filesystem-0-lxc-0-88", names.NewFilesystemTag("0/lxc/0/88")) assertParseFilesystemTagInvalid(c, "", names.InvalidTagError("", "")) assertParseFilesystemTagInvalid(c, "one", names.InvalidTagError("one", "")) assertParseFilesystemTagInvalid(c, "filesystem-", names.InvalidTagError("filesystem-", names.FilesystemTagKind)) assertParseFilesystemTagInvalid(c, "machine-0", names.InvalidTagError("machine-0", names.FilesystemTagKind)) }
func (s *FilesystemStateSuite) TestParseFilesystemAttachmentId(c *gc.C) { assertValid := func(id string, m names.MachineTag, v names.FilesystemTag) { machineTag, filesystemTag, err := state.ParseFilesystemAttachmentId(id) c.Assert(err, jc.ErrorIsNil) c.Assert(machineTag, gc.Equals, m) c.Assert(filesystemTag, gc.Equals, v) } assertValid("0:0", names.NewMachineTag("0"), names.NewFilesystemTag("0")) assertValid("0:0/1", names.NewMachineTag("0"), names.NewFilesystemTag("0/1")) assertValid("0/lxc/0:1", names.NewMachineTag("0/lxc/0"), names.NewFilesystemTag("1")) }
func (s *tmpfsSuite) TestCreateFilesystemsIsUse(c *gc.C) { source := s.tmpfsFilesystemSource(c) _, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("1"), Size: 1, }, { Tag: names.NewFilesystemTag("1"), Size: 2, }}) c.Assert(err, gc.ErrorMatches, "creating filesystem: filesystem 1 already exists") }
func (s *tmpfsSuite) TestAttachFilesystemsNoPathSpecified(c *gc.C) { source := s.tmpfsFilesystemSource(c) _, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("1"), Size: 1024, }}) c.Assert(err, jc.ErrorIsNil) _, err = source.AttachFilesystems([]storage.FilesystemAttachmentParams{{ Filesystem: names.NewFilesystemTag("6"), }}) c.Assert(err, gc.ErrorMatches, "attaching filesystem 6: filesystem mount point not specified") }
func (s *tmpfsSuite) TestAttachFilesystemsPathNotDir(c *gc.C) { source := s.tmpfsFilesystemSource(c) _, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("1"), Size: 1, }}) c.Assert(err, jc.ErrorIsNil) _, err = source.AttachFilesystems([]storage.FilesystemAttachmentParams{{ Filesystem: names.NewFilesystemTag("1"), Path: "file", }}) c.Assert(err, gc.ErrorMatches, `.* path "file" must be a directory`) }
func (s *managedfsSuite) TestCreateFilesystems(c *gc.C) { source := s.initSource(c) // sda is (re)partitioned and the filesystem created // on the partition. s.commands.expect("sgdisk", "--zap-all", "/dev/sda") s.commands.expect("sgdisk", "-n", "1:0:-1", "/dev/sda") s.commands.expect("mkfs.ext4", "/dev/sda1") // xvdf1 is assumed to not require a partition, on // account of ending with a digit. s.commands.expect("mkfs.ext4", "/dev/xvdf1") s.blockDevices[names.NewVolumeTag("0")] = storage.BlockDevice{ DeviceName: "sda", HardwareId: "capncrunch", Size: 2, } s.blockDevices[names.NewVolumeTag("1")] = storage.BlockDevice{ DeviceName: "xvdf1", HardwareId: "weetbix", Size: 3, } results, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("0/0"), Volume: names.NewVolumeTag("0"), Size: 2, }, { Tag: names.NewFilesystemTag("0/1"), Volume: names.NewVolumeTag("1"), Size: 3, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(results, jc.DeepEquals, []storage.CreateFilesystemsResult{{ Filesystem: &storage.Filesystem{ names.NewFilesystemTag("0/0"), names.NewVolumeTag("0"), storage.FilesystemInfo{ FilesystemId: "filesystem-0-0", Size: 2, }, }, }, { Filesystem: &storage.Filesystem{ names.NewFilesystemTag("0/1"), names.NewVolumeTag("1"), storage.FilesystemInfo{ FilesystemId: "filesystem-0-1", Size: 3, }, }, }}) }
func (s *managedfsSuite) testAttachFilesystems(c *gc.C, readOnly, reattach bool) { const testMountPoint = "/in/the/place" source := s.initSource(c) cmd := s.commands.expect("df", "--output=source", filepath.Dir(testMountPoint)) cmd.respond("headers\n/same/as/rootfs", nil) cmd = s.commands.expect("df", "--output=source", testMountPoint) if reattach { cmd.respond("headers\n/different/to/rootfs", nil) } else { cmd.respond("headers\n/same/as/rootfs", nil) var args []string if readOnly { args = append(args, "-o", "ro") } args = append(args, "/dev/sda1", testMountPoint) s.commands.expect("mount", args...) } s.blockDevices[names.NewVolumeTag("0")] = storage.BlockDevice{ DeviceName: "sda", HardwareId: "capncrunch", Size: 2, } s.filesystems[names.NewFilesystemTag("0/0")] = storage.Filesystem{ Tag: names.NewFilesystemTag("0/0"), Volume: names.NewVolumeTag("0"), } results, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{ Filesystem: names.NewFilesystemTag("0/0"), FilesystemId: "filesystem-0-0", AttachmentParams: storage.AttachmentParams{ Machine: names.NewMachineTag("0"), InstanceId: "inst-ance", ReadOnly: readOnly, }, Path: testMountPoint, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(results, jc.DeepEquals, []storage.AttachFilesystemsResult{{ FilesystemAttachment: &storage.FilesystemAttachment{ names.NewFilesystemTag("0/0"), names.NewMachineTag("0"), storage.FilesystemAttachmentInfo{ Path: testMountPoint, ReadOnly: readOnly, }, }, }}) }
func (s *FilesystemStateSuite) TestWatchMachineFilesystemAttachments(c *gc.C) { service := s.setupMixedScopeStorageService(c, "filesystem") addUnit := func(to *state.Machine) (u *state.Unit, m *state.Machine) { var err error u, err = service.AddUnit() c.Assert(err, jc.ErrorIsNil) if to != nil { err = u.AssignToMachine(to) c.Assert(err, jc.ErrorIsNil) return u, to } err = s.State.AssignUnit(u, state.AssignCleanEmpty) c.Assert(err, jc.ErrorIsNil) mid, err := u.AssignedMachineId() c.Assert(err, jc.ErrorIsNil) m, err = s.State.Machine(mid) c.Assert(err, jc.ErrorIsNil) return u, m } _, m0 := addUnit(nil) w := s.State.WatchMachineFilesystemAttachments(names.NewMachineTag("0")) defer testing.AssertStop(c, w) wc := testing.NewStringsWatcherC(c, s.State, w) wc.AssertChangeInSingleEvent("0:0/1", "0:0/2") // initial wc.AssertNoChange() addUnit(nil) // no change, since we're only interested in the one machine. wc.AssertNoChange() err := s.State.DetachFilesystem(names.NewMachineTag("0"), names.NewFilesystemTag("0")) c.Assert(err, jc.ErrorIsNil) // no change, since we're only interested in attachments of // machine-scoped volumes. wc.AssertNoChange() err = s.State.DetachFilesystem(names.NewMachineTag("0"), names.NewFilesystemTag("0/1")) c.Assert(err, jc.ErrorIsNil) wc.AssertChangeInSingleEvent("0:0/1") // dying wc.AssertNoChange() err = s.State.RemoveFilesystemAttachment(names.NewMachineTag("0"), names.NewFilesystemTag("0/1")) c.Assert(err, jc.ErrorIsNil) wc.AssertChangeInSingleEvent("0:0/1") // removed wc.AssertNoChange() addUnit(m0) wc.AssertChangeInSingleEvent("0:0/7", "0:0/8") wc.AssertNoChange() }
func (s *tmpfsSuite) TestCreateFilesystemsIsUse(c *gc.C) { source := s.tmpfsFilesystemSource(c) results, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("1"), Size: 1, }, { Tag: names.NewFilesystemTag("1"), Size: 2, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(results, gc.HasLen, 2) c.Assert(results[0].Error, jc.ErrorIsNil) c.Assert(results[1].Error, gc.ErrorMatches, "filesystem 1 already exists") }
func (s *storageProvisionerSuite) TestDestroyFilesystems(c *gc.C) { provisionedFilesystem := names.NewFilesystemTag("1") unprovisionedFilesystem := names.NewFilesystemTag("2") filesystemAccessor := newMockFilesystemAccessor() filesystemAccessor.provisionFilesystem(provisionedFilesystem) life := func(tags []names.Tag) ([]params.LifeResult, error) { results := make([]params.LifeResult, len(tags)) for i := range results { results[i].Life = params.Dead } return results, nil } removedChan := make(chan interface{}, 1) remove := func(tags []names.Tag) ([]params.ErrorResult, error) { removedChan <- tags return make([]params.ErrorResult, len(tags)), nil } args := &workerArgs{ filesystems: filesystemAccessor, life: &mockLifecycleManager{ life: life, remove: remove, }, } worker := newStorageProvisioner(c, args) defer func() { c.Assert(worker.Wait(), gc.IsNil) }() defer worker.Kill() filesystemAccessor.filesystemsWatcher.changes <- []string{ provisionedFilesystem.Id(), unprovisionedFilesystem.Id(), } args.environ.watcher.changes <- struct{}{} // Both filesystems should be removed; the provisioned one // *should* be deprovisioned first, but we don't currently // have the ability to do so via the storage provider API. var removed []names.Tag for len(removed) < 2 { tags := waitChannel(c, removedChan, "waiting for filesystems to be removed").([]names.Tag) removed = append(removed, tags...) } c.Assert(removed, jc.SameContents, []names.Tag{provisionedFilesystem, unprovisionedFilesystem}) assertNoEvent(c, removedChan, "filesystems removed") }
// assertMachineStorageRefs ensures that the specified machine's set of volume // and filesystem references corresponds exactly to the volume and filesystem // attachments that relate to the machine. func assertMachineStorageRefs(c *gc.C, st *state.State, m names.MachineTag) { machines, closer := state.GetRawCollection(st, state.MachinesC) defer closer() var doc struct { Volumes []string `bson:"volumes,omitempty"` Filesystems []string `bson:"filesystems,omitempty"` } err := machines.FindId(state.DocID(st, m.Id())).One(&doc) c.Assert(err, jc.ErrorIsNil) have := make(set.Tags) for _, v := range doc.Volumes { have.Add(names.NewVolumeTag(v)) } for _, f := range doc.Filesystems { have.Add(names.NewFilesystemTag(f)) } expect := make(set.Tags) volumeAttachments, err := st.MachineVolumeAttachments(m) c.Assert(err, jc.ErrorIsNil) for _, a := range volumeAttachments { expect.Add(a.Volume()) } filesystemAttachments, err := st.MachineFilesystemAttachments(m) c.Assert(err, jc.ErrorIsNil) for _, a := range filesystemAttachments { expect.Add(a.Filesystem()) } c.Assert(have, jc.DeepEquals, expect) }
func (s *tmpfsSuite) TestCreateFilesystems(c *gc.C) { source := s.tmpfsFilesystemSource(c) filesystems, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("6"), Size: 2, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(filesystems, jc.DeepEquals, []storage.Filesystem{{ Tag: names.NewFilesystemTag("6"), FilesystemInfo: storage.FilesystemInfo{ FilesystemId: "filesystem-6", Size: 2, }, }}) }
func (s *provisionerSuite) TestFilesystemParams(c *gc.C) { var callCount int apiCaller := testing.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error { c.Check(objType, gc.Equals, "StorageProvisioner") c.Check(version, gc.Equals, 0) c.Check(id, gc.Equals, "") c.Check(request, gc.Equals, "FilesystemParams") c.Check(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{"filesystem-100"}}}) c.Assert(result, gc.FitsTypeOf, ¶ms.FilesystemParamsResults{}) *(result.(*params.FilesystemParamsResults)) = params.FilesystemParamsResults{ Results: []params.FilesystemParamsResult{{ Result: params.FilesystemParams{ FilesystemTag: "filesystem-100", Size: 1024, Provider: "loop", }, }}, } callCount++ return nil }) st := storageprovisioner.NewState(apiCaller, names.NewMachineTag("123")) filesystemParams, err := st.FilesystemParams([]names.FilesystemTag{names.NewFilesystemTag("100")}) c.Check(err, jc.ErrorIsNil) c.Check(callCount, gc.Equals, 1) c.Assert(filesystemParams, jc.DeepEquals, []params.FilesystemParamsResult{{ Result: params.FilesystemParams{ FilesystemTag: "filesystem-100", Size: 1024, Provider: "loop", }, }}) }
// testDetachFilesystems is a test-case for detaching filesystems that use // the common "maybeUnmount" method. func testDetachFilesystems(c *gc.C, commands *mockRunCommand, source storage.FilesystemSource, mounted bool) { const testMountPoint = "/in/the/place" cmd := commands.expect("df", "--output=source", filepath.Dir(testMountPoint)) cmd.respond("headers\n/same/as/rootfs", nil) cmd = commands.expect("df", "--output=source", testMountPoint) if mounted { cmd.respond("headers\n/different/to/rootfs", nil) commands.expect("umount", testMountPoint) } else { cmd.respond("headers\n/same/as/rootfs", nil) } results, err := source.DetachFilesystems([]storage.FilesystemAttachmentParams{{ Filesystem: names.NewFilesystemTag("0/0"), FilesystemId: "filesystem-0-0", AttachmentParams: storage.AttachmentParams{ Machine: names.NewMachineTag("0"), InstanceId: "inst-id", }, Path: testMountPoint, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(results, gc.HasLen, 1) c.Assert(results[0], jc.ErrorIsNil) }
// addFilesystemOps returns txn.Ops to create a new filesystem with the // specified parameters. If the storage source cannot create filesystems // directly, a volume will be created and Juju will manage a filesystem // on it. func (st *State) addFilesystemOps(params FilesystemParams, machineId string) ([]txn.Op, names.FilesystemTag, names.VolumeTag, error) { if params.binding == nil { params.binding = names.NewMachineTag(machineId) } params, err := st.filesystemParamsWithDefaults(params) if err != nil { return nil, names.FilesystemTag{}, names.VolumeTag{}, errors.Trace(err) } machineId, err = st.validateFilesystemParams(params, machineId) if err != nil { return nil, names.FilesystemTag{}, names.VolumeTag{}, errors.Annotate(err, "validating filesystem params") } filesystemId, err := newFilesystemId(st, machineId) if err != nil { return nil, names.FilesystemTag{}, names.VolumeTag{}, errors.Annotate(err, "cannot generate filesystem name") } filesystemTag := names.NewFilesystemTag(filesystemId) // Check if the filesystem needs a volume. var volumeId string var volumeTag names.VolumeTag var ops []txn.Op _, provider, err := poolStorageProvider(st, params.Pool) if err != nil { return nil, names.FilesystemTag{}, names.VolumeTag{}, errors.Trace(err) } if !provider.Supports(storage.StorageKindFilesystem) { var volumeOp txn.Op volumeParams := VolumeParams{ params.storage, filesystemTag, // volume is bound to filesystem params.Pool, params.Size, } volumeOp, volumeTag, err = st.addVolumeOp(volumeParams, machineId) if err != nil { return nil, names.FilesystemTag{}, names.VolumeTag{}, errors.Annotate(err, "creating backing volume") } volumeId = volumeTag.Id() ops = append(ops, volumeOp) } filesystemOp := txn.Op{ C: filesystemsC, Id: filesystemId, Assert: txn.DocMissing, Insert: &filesystemDoc{ FilesystemId: filesystemId, VolumeId: volumeId, StorageId: params.storage.Id(), Binding: params.binding.String(), Params: ¶ms, // Every filesystem is created with one attachment. AttachmentCount: 1, }, } ops = append(ops, filesystemOp) return ops, filesystemTag, volumeTag, nil }
func (s *provisionerSuite) TestRemoveFilesystemAttachments(c *gc.C) { s.setupFilesystems(c) s.authorizer.EnvironManager = false err := s.State.DetachFilesystem(names.NewMachineTag("0"), names.NewFilesystemTag("1")) c.Assert(err, jc.ErrorIsNil) results, err := s.api.RemoveAttachment(params.MachineStorageIds{ Ids: []params.MachineStorageId{{ MachineTag: "machine-0", AttachmentTag: "filesystem-0-0", }, { MachineTag: "machine-0", AttachmentTag: "filesystem-1", }, { MachineTag: "machine-2", AttachmentTag: "filesystem-4", }, { MachineTag: "machine-0", AttachmentTag: "filesystem-42", }}, }) c.Assert(err, jc.ErrorIsNil) c.Assert(results, jc.DeepEquals, params.ErrorResults{ Results: []params.ErrorResult{ {Error: ¶ms.Error{Message: "removing attachment of filesystem 0/0 from machine 0: filesystem attachment is not dying"}}, {Error: nil}, {Error: ¶ms.Error{Message: "permission denied", Code: "unauthorized access"}}, {Error: ¶ms.Error{Message: `removing attachment of filesystem 42 from machine 0: filesystem "42" on machine "0" not found`, Code: "not found"}}, }, }) }
func (s *rootfsSuite) TestAttachFilesystemsNoPathSpecified(c *gc.C) { source := s.rootfsFilesystemSource(c) _, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{ Filesystem: names.NewFilesystemTag("6"), FilesystemId: "6", }}) c.Assert(err, gc.ErrorMatches, "attaching filesystem 6: filesystem mount point not specified") }
func (s *tmpfsSuite) TestAttachFilesystemsNoFilesystem(c *gc.C) { source := s.tmpfsFilesystemSource(c) _, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{ Filesystem: names.NewFilesystemTag("6"), Path: "/mnt", }}) c.Assert(err, gc.ErrorMatches, "attaching filesystem 6: reading filesystem info from disk: open .*/6.info: no such file or directory") }
func (s *rootfsSuite) TestCreateFilesystemsIsUse(c *gc.C) { source := s.rootfsFilesystemSource(c) _, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("666"), // magic; see mockDirFuncs Size: 1, }}) c.Assert(err, gc.ErrorMatches, "creating filesystem: \".*/666\" is not empty") }
// assertNoPersistentStorage ensures that there are no persistent volumes or // filesystems attached to the machine, and returns any mgo/txn assertions // required to ensure that remains true. func (m *Machine) assertNoPersistentStorage() (bson.D, error) { attachments := make(set.Tags) for _, v := range m.doc.Volumes { tag := names.NewVolumeTag(v) machineBound, err := isVolumeInherentlyMachineBound(m.st, tag) if err != nil { return nil, errors.Trace(err) } if !machineBound { attachments.Add(tag) } } for _, f := range m.doc.Filesystems { tag := names.NewFilesystemTag(f) machineBound, err := isFilesystemInherentlyMachineBound(m.st, tag) if err != nil { return nil, errors.Trace(err) } if !machineBound { attachments.Add(tag) } } if len(attachments) > 0 { return nil, &HasAttachmentsError{ MachineId: m.doc.Id, Attachments: attachments.SortedValues(), } } if m.doc.Life == Dying { return nil, nil } // A Dying machine cannot have attachments added to it, // but if we're advancing from Alive to Dead then we // must ensure no concurrent attachments are made. noNewVolumes := bson.DocElem{ "volumes", bson.D{{ "$not", bson.D{{ "$elemMatch", bson.D{{ "$nin", m.doc.Volumes, }}, }}, }}, // There are no volumes that are not in // the set of volumes we previously knew // about => the current set of volumes // is a subset of the previously known set. } noNewFilesystems := bson.DocElem{ "filesystems", bson.D{{ "$not", bson.D{{ "$elemMatch", bson.D{{ "$nin", m.doc.Filesystems, }}, }}, }}, } return bson.D{noNewVolumes, noNewFilesystems}, nil }
func (s *rootfsSuite) TestAttachFilesystemsPathNotDir(c *gc.C) { source := s.rootfsFilesystemSource(c) _, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{ Filesystem: names.NewFilesystemTag("6"), FilesystemId: "6", Path: "file", }}) c.Assert(err, gc.ErrorMatches, `.* path "file" must be a directory`) }
// ParseFilesystemAttachmentId parses a string as a filesystem attachment ID, // returning the machine and filesystem components. func ParseFilesystemAttachmentId(id string) (names.MachineTag, names.FilesystemTag, error) { fields := strings.SplitN(id, ":", 2) if len(fields) != 2 || !names.IsValidMachine(fields[0]) || !names.IsValidFilesystem(fields[1]) { return names.MachineTag{}, names.FilesystemTag{}, errors.Errorf("invalid filesystem attachment ID %q", id) } machineTag := names.NewMachineTag(fields[0]) filesystemTag := names.NewFilesystemTag(fields[1]) return machineTag, filesystemTag, nil }
func (s *managedfsSuite) TestCreateFilesystemsNoBlockDevice(c *gc.C) { source := s.initSource(c) _, err := source.CreateFilesystems([]storage.FilesystemParams{{ Tag: names.NewFilesystemTag("0/0"), Volume: names.NewVolumeTag("0"), Size: 2, }}) c.Assert(err, gc.ErrorMatches, "creating filesystem 0/0: backing-volume 0 is not yet attached") }
func (s *commonSuite) TestAuthFuncForTagKind(c *gc.C) { // TODO(dimitern): This list of all supported tags and kinds needs // to live in juju/names. uuid, err := utils.NewUUID() c.Assert(err, jc.ErrorIsNil) allTags := []names.Tag{ nil, // invalid tag names.NewActionTag(uuid.String()), names.NewCharmTag("cs:precise/missing"), names.NewModelTag(uuid.String()), names.NewFilesystemTag("20/20"), names.NewLocalUserTag("user"), names.NewMachineTag("42"), names.NewNetworkTag("public"), names.NewRelationTag("wordpress:mysql mysql:db"), names.NewServiceTag("wordpress"), names.NewSpaceTag("apps"), names.NewStorageTag("foo/42"), names.NewUnitTag("wordpress/5"), names.NewUserTag("joe"), names.NewVolumeTag("80/20"), } for i, allowedTag := range allTags { c.Logf("test #%d: allowedTag: %v", i, allowedTag) var allowedKind string if allowedTag != nil { allowedKind = allowedTag.Kind() } getAuthFunc := common.AuthFuncForTagKind(allowedKind) authFunc, err := getAuthFunc() if allowedKind == "" { c.Check(err, gc.ErrorMatches, "tag kind cannot be empty") c.Check(authFunc, gc.IsNil) continue } else if !c.Check(err, jc.ErrorIsNil) { continue } for j, givenTag := range allTags { c.Logf("test #%d.%d: givenTag: %v", i, j, givenTag) var givenKind string if givenTag != nil { givenKind = givenTag.Kind() } if allowedKind == givenKind { c.Check(authFunc(givenTag), jc.IsTrue) } else { c.Check(authFunc(givenTag), jc.IsFalse) } } } }
func (s *CleanupSuite) TestCleanupFilesystemAttachments(c *gc.C) { _, err := s.State.AddOneMachine(state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, Filesystems: []state.MachineFilesystemParams{{ Filesystem: state.FilesystemParams{Pool: "rootfs", Size: 1024}, }}, }) c.Assert(err, jc.ErrorIsNil) s.assertDoesNotNeedCleanup(c) err = s.State.DestroyFilesystem(names.NewFilesystemTag("0/0")) c.Assert(err, jc.ErrorIsNil) s.assertCleanupRuns(c) attachment, err := s.State.FilesystemAttachment(names.NewMachineTag("0"), names.NewFilesystemTag("0/0")) c.Assert(err, jc.ErrorIsNil) c.Assert(attachment.Life(), gc.Equals, state.Dying) }