-
Notifications
You must be signed in to change notification settings - Fork 491
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16135 from hpidcock/fullstatus-with-storage
#16135 Instead of `juju status --storage` making 3 seperate facade calls in addition to the FullStatus call, instead return the information in the FullStatus facade call. This also implements server side filtering on unit/application for storage entities. ## QA steps - Deploy multiple apps with storage. - Check `juju status` without storage - Check `juju status --storage` - Check `juju status --storage` works against old controller (Client facade <= 6) - Check `juju status --format yaml` (should have implicit --storage) - Check `juju status --storage <filter>` Example no filter: ``` juju status --storage Model Controller Cloud/Region Version SLA Timestamp a minikube minikube 3.2.3 unsupported 16:13:46+10:00 App Version Status Scale Charm Channel Rev Address Exposed Message b waiting 1 postgresql-k8s 14/stable 73 10.110.113.233 no installing agent postgresql-k8s waiting 1 postgresql-k8s 14/stable 73 10.104.229.135 no installing agent Unit Workload Agent Address Ports Message b/0* blocked idle 10.244.0.6 failed to create k8s resources postgresql-k8s/0* blocked idle 10.244.0.7 failed to create k8s resources Storage Unit Storage ID Type Pool Mountpoint Size Status Message b/0 pgdata/1 filesystem kubernetes /var/lib/postgresql/data 1.0 GiB attached Successfully provisioned volume pvc-f08518a7-20be-4184-bc50-e668baa7fa37 postgresql-k8s/0 pgdata/0 filesystem kubernetes /var/lib/postgresql/data 1.0 GiB attached Successfully provisioned volume pvc-48b7f0ea-b103-4d66-b21e-b69d107a072d ``` Example with filter: ``` juju status --storage b Model Controller Cloud/Region Version SLA Timestamp a minikube minikube 3.2.3 unsupported 16:16:27+10:00 App Version Status Scale Charm Channel Rev Address Exposed Message b 14.7 waiting 1 postgresql-k8s 14/stable 73 10.110.113.233 no installing agent Unit Workload Agent Address Ports Message b/0* blocked idle 10.244.0.6 failed to create k8s resources Storage Unit Storage ID Type Pool Mountpoint Size Status Message b/0 pgdata/1 filesystem kubernetes /var/lib/postgresql/data 1.0 GiB attached Successfully provisioned volume pvc-f08518a7-20be-4184-bc50-e668baa7fa37 ``` ## Documentation changes N/A ## Bug reference Partially mitigates https://bugs.launchpad.net/juju/+bug/2015371 JUJU-4538
- Loading branch information
Showing
35 changed files
with
1,110 additions
and
480 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// Copyright 2023 Canonical Ltd. | ||
// Licensed under the AGPLv3, see LICENCE file for details. | ||
|
||
package storagecommon | ||
|
||
import ( | ||
"github.com/juju/errors" | ||
"github.com/juju/names/v4" | ||
|
||
"github.com/juju/juju/apiserver/common" | ||
"github.com/juju/juju/core/life" | ||
"github.com/juju/juju/rpc/params" | ||
"github.com/juju/juju/state" | ||
) | ||
|
||
// FilesystemDetails returns the filesystem and its attachments as a params FilesystemDetails. | ||
func FilesystemDetails( | ||
sb DetailsBackend, | ||
unitToMachine UnitAssignedMachineFunc, | ||
f state.Filesystem, | ||
attachments []state.FilesystemAttachment, | ||
) (*params.FilesystemDetails, error) { | ||
details := ¶ms.FilesystemDetails{ | ||
FilesystemTag: f.FilesystemTag().String(), | ||
Life: life.Value(f.Life().String()), | ||
} | ||
|
||
if volumeTag, err := f.Volume(); err == nil { | ||
details.VolumeTag = volumeTag.String() | ||
} | ||
|
||
if info, err := f.Info(); err == nil { | ||
details.Info = FilesystemInfoFromState(info) | ||
} | ||
|
||
if len(attachments) > 0 { | ||
details.MachineAttachments = make(map[string]params.FilesystemAttachmentDetails, len(attachments)) | ||
details.UnitAttachments = make(map[string]params.FilesystemAttachmentDetails, len(attachments)) | ||
for _, attachment := range attachments { | ||
attDetails := params.FilesystemAttachmentDetails{ | ||
Life: life.Value(attachment.Life().String()), | ||
} | ||
if stateInfo, err := attachment.Info(); err == nil { | ||
attDetails.FilesystemAttachmentInfo = FilesystemAttachmentInfoFromState( | ||
stateInfo, | ||
) | ||
} | ||
if attachment.Host().Kind() == names.MachineTagKind { | ||
details.MachineAttachments[attachment.Host().String()] = attDetails | ||
} else { | ||
details.UnitAttachments[attachment.Host().String()] = attDetails | ||
} | ||
} | ||
} | ||
|
||
aStatus, err := f.Status() | ||
if err != nil { | ||
return nil, errors.Trace(err) | ||
} | ||
details.Status = common.EntityStatusFromState(aStatus) | ||
|
||
if storageTag, err := f.Storage(); err == nil { | ||
storageInstance, err := sb.StorageInstance(storageTag) | ||
if err != nil { | ||
return nil, errors.Trace(err) | ||
} | ||
storageDetails, err := StorageDetails(sb, unitToMachine, storageInstance) | ||
if err != nil { | ||
return nil, errors.Trace(err) | ||
} | ||
details.Storage = storageDetails | ||
} | ||
|
||
return details, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// Copyright 2023 Canonical Ltd. | ||
// Licensed under the AGPLv3, see LICENCE file for details. | ||
|
||
package storagecommon | ||
|
||
import ( | ||
"github.com/juju/errors" | ||
"github.com/juju/names/v4" | ||
|
||
"github.com/juju/juju/apiserver/common" | ||
"github.com/juju/juju/core/life" | ||
"github.com/juju/juju/core/status" | ||
"github.com/juju/juju/rpc/params" | ||
"github.com/juju/juju/state" | ||
) | ||
|
||
// DetailsBacked is used by StorageDetails, VolumeDetails and FilesystemDetails to access | ||
// state for collecting all the required information to send back over the wire. | ||
type DetailsBackend interface { | ||
StorageAccess | ||
VolumeAccess | ||
FilesystemAccess | ||
StorageAttachments(names.StorageTag) ([]state.StorageAttachment, error) | ||
} | ||
|
||
type UnitAssignedMachineFunc func(names.UnitTag) (names.MachineTag, error) | ||
|
||
// StorageDetails returns the storage instance as a params StorageDetails. | ||
func StorageDetails( | ||
sb DetailsBackend, | ||
unitToMachine UnitAssignedMachineFunc, | ||
si state.StorageInstance, | ||
) (*params.StorageDetails, error) { | ||
// Get information from underlying volume or filesystem. | ||
var persistent bool | ||
var statusEntity status.StatusGetter | ||
if si.Kind() == state.StorageKindFilesystem { | ||
// TODO(axw) when we support persistent filesystems, | ||
// e.g. CephFS, we'll need to do set "persistent" | ||
// here too. | ||
filesystem, err := sb.StorageInstanceFilesystem(si.StorageTag()) | ||
if err != nil { | ||
return nil, errors.Trace(err) | ||
} | ||
statusEntity = filesystem | ||
} else { | ||
volume, err := sb.StorageInstanceVolume(si.StorageTag()) | ||
if err != nil { | ||
return nil, errors.Trace(err) | ||
} | ||
if info, err := volume.Info(); err == nil { | ||
persistent = info.Persistent | ||
} | ||
statusEntity = volume | ||
} | ||
aStatus, err := statusEntity.Status() | ||
if err != nil { | ||
return nil, errors.Trace(err) | ||
} | ||
|
||
// Get unit storage attachments. | ||
var storageAttachmentDetails map[string]params.StorageAttachmentDetails | ||
storageAttachments, err := sb.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 { | ||
// TODO(caas) - handle attachments to units | ||
machineTag, location, err := storageAttachmentInfo(sb, a, unitToMachine) | ||
if err != nil { | ||
return nil, errors.Trace(err) | ||
} | ||
details := params.StorageAttachmentDetails{ | ||
StorageTag: a.StorageInstance().String(), | ||
UnitTag: a.Unit().String(), | ||
Location: location, | ||
Life: life.Value(a.Life().String()), | ||
} | ||
if machineTag.Id() != "" { | ||
details.MachineTag = machineTag.String() | ||
} | ||
storageAttachmentDetails[a.Unit().String()] = details | ||
} | ||
} | ||
|
||
var ownerTag string | ||
if owner, ok := si.Owner(); ok { | ||
ownerTag = owner.String() | ||
} | ||
|
||
return ¶ms.StorageDetails{ | ||
StorageTag: si.Tag().String(), | ||
OwnerTag: ownerTag, | ||
Kind: params.StorageKind(si.Kind()), | ||
Life: life.Value(si.Life().String()), | ||
Status: common.EntityStatusFromState(aStatus), | ||
Persistent: persistent, | ||
Attachments: storageAttachmentDetails, | ||
}, nil | ||
} | ||
|
||
func storageAttachmentInfo( | ||
sb DetailsBackend, | ||
a state.StorageAttachment, | ||
unitToMachine UnitAssignedMachineFunc, | ||
) (_ names.MachineTag, location string, _ error) { | ||
machineTag, err := unitToMachine(a.Unit()) | ||
if errors.Is(err, errors.NotAssigned) { | ||
return names.MachineTag{}, "", nil | ||
} else if err != nil { | ||
return names.MachineTag{}, "", errors.Trace(err) | ||
} | ||
info, err := StorageAttachmentInfo(sb, sb, sb, a, machineTag) | ||
if errors.Is(err, errors.NotProvisioned) { | ||
return machineTag, "", nil | ||
} else if err != nil { | ||
return names.MachineTag{}, "", errors.Trace(err) | ||
} | ||
return machineTag, info.Location, nil | ||
} |
Oops, something went wrong.