rbd: add functions to parse json in mirroring status description field

Add UnmarshalDescriptionJSON method to SiteMirrorImageStatus
Add DescriptionReplayStatus method to SiteMirrorImageStatus

Both these functions are meant to help extract the JSON object that is
some times appended to the Description field in the
SiteMirrorImageStatus struct. I have only seen the JSON appear after
"replaying, " but there's little docs for this and I skimmed to code to
even find out what fields the JSON might include.  As such, the
UnmarshalDescriptionJSON tries to unmarshal the appended JSON into an
object the caller provides in case skimming the code was insufficient or
the caller has other needs. For most cases, DescriptionReplayStatus can
be used to parse the JSON into a struct containing known fields.

Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
John Mulligan 2023-03-06 15:25:10 -05:00 committed by mergify[bot]
parent 5bb75604fa
commit f4f0d6dd9a
1 changed files with 71 additions and 0 deletions

71
rbd/mirror_desc_status.go Normal file
View File

@ -0,0 +1,71 @@
//go:build !nautilus && ceph_preview
// +build !nautilus,ceph_preview
package rbd
// #cgo LDFLAGS: -lrbd
// #include <stdlib.h>
// #include <rbd/librbd.h>
import "C"
import (
"encoding/json"
"strings"
)
// MirrorDescriptionReplayStatus contains information pertaining to the status
// of snapshot based RBD image mirroring.
type MirrorDescriptionReplayStatus struct {
ReplayState string `json:"replay_state"`
RemoteSnapshotTimestamp int64 `json:"remote_snapshot_timestamp"`
LocalSnapshotTimestamp int64 `json:"local_snapshot_timestamp"`
SyncingSnapshotTimestamp int64 `json:"syncing_snapshot_timestamp"`
SyncingPercent int `json:"syncing_percent"`
BytesPerSecond float64 `json:"bytes_per_second"`
BytesPerSnapshot float64 `json:"bytes_per_snapshot"`
LastSnapshotSyncSeconds int64 `json:"last_snapshot_sync_seconds"`
LastSnapshotBytes int64 `json:"last_snapshot_bytes"`
}
// extractDescriptionJSON will extract one string containing a JSON object from
// the description if one can be found.
func (s *SiteMirrorImageStatus) extractDescriptionJSON() (string, error) {
start := strings.Index(s.Description, "{")
if start == -1 {
return "", ErrNotExist
}
end := strings.LastIndex(s.Description, "}")
if end == -1 {
return "", ErrNotExist
}
if start >= end {
return "", ErrNotExist
}
return s.Description[start : end+1], nil
}
// UnmarshalDescriptionJSON parses an embedded JSON string that may be found in
// the description of the SiteMirrorImageStatus. It will store the result in
// the value pointed to by v. If no embedded JSON string is found an
// ErrNotExist error is returned. An error may also be returned if the contents
// can not be parsed.
func (s *SiteMirrorImageStatus) UnmarshalDescriptionJSON(v interface{}) error {
desc, err := s.extractDescriptionJSON()
if err != nil {
return err
}
return json.Unmarshal([]byte(desc), v)
}
// DescriptionReplayStatus parses a MirrorDescriptionReplayStatus result out of
// the image status description field if available. If the embedded status JSON
// is not found or fails to parse and error will be returned.
func (s *SiteMirrorImageStatus) DescriptionReplayStatus() (
*MirrorDescriptionReplayStatus, error) {
// ---
mdrs := MirrorDescriptionReplayStatus{}
if err := s.UnmarshalDescriptionJSON(&mdrs); err != nil {
return nil, err
}
return &mdrs, nil
}