// TODO(axw) move this and createParamsStorageInstance to // apiserver/common/storage.go, alongside StorageAttachmentInfo. func (api *API) isPersistent(si state.StorageInstance) (bool, error) { if si.Kind() != state.StorageKindBlock { // TODO(axw) when we support persistent filesystems, // e.g. CephFS, we'll need to do the same thing as // we do for volumes for filesystems. return false, nil } volume, err := api.storage.StorageInstanceVolume(si.StorageTag()) if err != nil { return false, err } // If the volume is not provisioned, we read its config attributes. if params, ok := volume.Params(); ok { _, cfg, err := common.StoragePoolConfig(params.Pool, api.poolManager) if err != nil { return false, err } return cfg.IsPersistent(), nil } // If the volume is provisioned, we look at its provisioning info. info, err := volume.Info() if err != nil { return false, err } return info.Persistent, nil }
func volumeStorageAttachmentInfo( st StorageInterface, storageInstance state.StorageInstance, machineTag names.MachineTag, ) (*storage.StorageAttachmentInfo, error) { storageTag := storageInstance.StorageTag() volume, err := st.StorageInstanceVolume(storageTag) if err != nil { return nil, errors.Annotate(err, "getting volume") } volumeInfo, err := volume.Info() if err != nil { return nil, errors.Annotate(err, "getting volume info") } volumeAttachment, err := st.VolumeAttachment(machineTag, volume.VolumeTag()) if err != nil { return nil, errors.Annotate(err, "getting volume attachment") } volumeAttachmentInfo, err := volumeAttachment.Info() if err != nil { return nil, errors.Annotate(err, "getting volume attachment info") } devicePath, err := volumeAttachmentDevicePath( volumeInfo, volumeAttachmentInfo, ) if err != nil { return nil, errors.Trace(err) } return &storage.StorageAttachmentInfo{ storage.StorageKindBlock, devicePath, }, nil }
func volumeStorageAttachmentInfo( st StorageInterface, storageInstance state.StorageInstance, machineTag names.MachineTag, ) (*storage.StorageAttachmentInfo, error) { storageTag := storageInstance.StorageTag() volume, err := st.StorageInstanceVolume(storageTag) if err != nil { return nil, errors.Annotate(err, "getting volume") } volumeInfo, err := volume.Info() if err != nil { return nil, errors.Annotate(err, "getting volume info") } volumeAttachment, err := st.VolumeAttachment(machineTag, volume.VolumeTag()) if err != nil { return nil, errors.Annotate(err, "getting volume attachment") } volumeAttachmentInfo, err := volumeAttachment.Info() if err != nil { return nil, errors.Annotate(err, "getting volume attachment info") } blockDevices, err := st.BlockDevices(machineTag) if err != nil { return nil, errors.Annotate(err, "getting block devices") } blockDevice, ok := MatchingBlockDevice( blockDevices, volumeInfo, volumeAttachmentInfo, ) if !ok { // We must not say that a block-kind storage attachment is // provisioned until its block device has shown up on the // machine, otherwise the charm may attempt to use it and // fail. return nil, errors.NotProvisionedf("%v", names.ReadableString(storageTag)) } devicePath, err := volumeAttachmentDevicePath( volumeInfo, volumeAttachmentInfo, *blockDevice, ) if err != nil { return nil, errors.Trace(err) } return &storage.StorageAttachmentInfo{ storage.StorageKindBlock, devicePath, }, nil }
func createStorageDetails(st storageAccess, si state.StorageInstance) (*params.StorageDetails, error) { // Get information from underlying volume or filesystem. var persistent bool var statusEntity status.StatusGetter if si.Kind() != state.StorageKindBlock { // TODO(axw) when we support persistent filesystems, // e.g. CephFS, we'll need to do set "persistent" // here too. filesystem, err := st.StorageInstanceFilesystem(si.StorageTag()) if err != nil { return nil, errors.Trace(err) } statusEntity = filesystem } else { volume, err := st.StorageInstanceVolume(si.StorageTag()) if err != nil { return nil, errors.Trace(err) } if info, err := volume.Info(); err == nil { persistent = info.Persistent } statusEntity = volume } status, err := statusEntity.Status() if err != nil { return nil, errors.Trace(err) } // Get unit storage attachments. var storageAttachmentDetails map[string]params.StorageAttachmentDetails storageAttachments, err := st.StorageAttachments(si.StorageTag()) if err != nil { return nil, errors.Trace(err) } if len(storageAttachments) > 0 { storageAttachmentDetails = make(map[string]params.StorageAttachmentDetails) for _, a := range storageAttachments { machineTag, location, err := storageAttachmentInfo(st, a) if err != nil { return nil, errors.Trace(err) } details := params.StorageAttachmentDetails{ a.StorageInstance().String(), a.Unit().String(), machineTag.String(), location, } storageAttachmentDetails[a.Unit().String()] = details } } return ¶ms.StorageDetails{ StorageTag: si.Tag().String(), OwnerTag: si.Owner().String(), Kind: params.StorageKind(si.Kind()), Status: common.EntityStatusFromState(status), Persistent: persistent, Attachments: storageAttachmentDetails, }, nil }
func filesystemStorageAttachmentInfo( st StorageInterface, storageInstance state.StorageInstance, machineTag names.MachineTag, ) (*storage.StorageAttachmentInfo, error) { storageTag := storageInstance.StorageTag() filesystem, err := st.StorageInstanceFilesystem(storageTag) if err != nil { return nil, errors.Annotate(err, "getting filesystem") } filesystemAttachment, err := st.FilesystemAttachment(machineTag, filesystem.FilesystemTag()) if err != nil { return nil, errors.Annotate(err, "getting filesystem attachment") } filesystemAttachmentInfo, err := filesystemAttachment.Info() if err != nil { return nil, errors.Annotate(err, "getting filesystem attachment info") } return &storage.StorageAttachmentInfo{ storage.StorageKindFilesystem, filesystemAttachmentInfo.MountPoint, }, nil }