From adad37c8ca6c45899b07da5ccb8a98762339a85e Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 8 Sep 2023 12:12:49 +0200 Subject: [PATCH] Add the GET /object handler And convert the "ls" command to use that. Also, * Fix the yaml properties stripped from their underscore. * Rename the drbd allocation ExpireAt to ExpiredAt --- core/commands/object_ls.go | 49 ++-- daemon/api/api.yaml | 167 +++++++++++- daemon/api/codegen_client_gen.go | 154 +++++++++++ daemon/api/codegen_server_gen.go | 268 +++++++++++-------- daemon/api/codegen_type_gen.go | 135 +++++++--- daemon/daemonapi/get_node_drbd_allocation.go | 6 +- daemon/daemonapi/get_object.go | 65 +++++ daemon/daemonapi/post_node_drbd_config.go | 2 +- drivers/resdiskdrbd/main.go | 2 +- 9 files changed, 663 insertions(+), 185 deletions(-) create mode 100644 daemon/daemonapi/get_object.go diff --git a/core/commands/object_ls.go b/core/commands/object_ls.go index 75997b3b1..e983b2273 100644 --- a/core/commands/object_ls.go +++ b/core/commands/object_ls.go @@ -1,11 +1,13 @@ package commands import ( - "sort" + "context" + "fmt" - "github.com/opensvc/om3/core/objectselector" + "github.com/opensvc/om3/core/client" "github.com/opensvc/om3/core/output" "github.com/opensvc/om3/core/rawconfig" + "github.com/opensvc/om3/daemon/api" ) type ( @@ -15,33 +17,40 @@ type ( ) func (t *CmdObjectLs) Run(selector, kind string) error { - selection := objectselector.NewSelection( - mergeSelector(selector, t.ObjectSelector, kind, "**"), - objectselector.SelectionWithLocal(t.Local), - objectselector.SelectionWithServer(t.Server), + var ( + data any + err error ) - data := make([]string, 0) - paths, err := selection.Expand() + mergedSelector := mergeSelector(selector, t.ObjectSelector, kind, "") + + c, err := client.New(client.WithURL(t.Server)) if err != nil { return err } - for _, path := range paths { - data = append(data, path.String()) + params := api.GetObjectParams{Path: &mergedSelector} + resp, err := c.GetObjectWithResponse(context.Background(), ¶ms) + if err != nil { + return fmt.Errorf("api: %w", err) } - sort.Strings(data) - human := func() string { - s := "" - for _, r := range data { - s += r + "\n" - } - return s + switch resp.StatusCode() { + case 200: + data = *resp.JSON200 + case 400: + data = *resp.JSON400 + case 401: + data = *resp.JSON401 + case 403: + data = *resp.JSON403 + case 500: + data = *resp.JSON500 } - output.Renderer{ + renderer := output.Renderer{ + DefaultOutput: "tab=OBJECT:meta.object,AVAIL:data.avail,OVERALL:data.overall", Output: t.Output, Color: t.Color, Data: data, - HumanRenderer: human, Colorize: rawconfig.Colorize, - }.Print() + } + renderer.Print() return nil } diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index d183e442d..1943c26ce 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -802,6 +802,33 @@ paths: $ref: '#/components/responses/403' 500: $ref: '#/components/responses/500' + /object: + get: + operationId: GetObject + tags: + - object + security: + - basicAuth: [] + - bearerAuth: [] + description: | + List all objects in the cluster. + parameters: + - $ref: '#/components/parameters/PathOptional' + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ObjectArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' /object/backlogs: get: operationId: GetObjectBacklogs @@ -1467,6 +1494,8 @@ components: - token properties: expired_at: + x-oapi-codegen-extra-tags: + yaml: expired_at type: string format: date-time token: @@ -1576,8 +1605,12 @@ components: - last_at properties: is_beating: + x-oapi-codegen-extra-tags: + yaml: is_beating type: boolean last_at: + x-oapi-codegen-extra-tags: + yaml: last_at type: string format: date-time DaemonListener: @@ -1616,6 +1649,8 @@ components: type: string format: date-time created_at: + x-oapi-codegen-extra-tags: + yaml: created_at type: string format: date-time id: @@ -1650,7 +1685,7 @@ components: required: - port - minor - - expire_at + - expired_at - id properties: id: @@ -1660,7 +1695,9 @@ components: type: integer minor: type: integer - expire_at: + expired_at: + x-oapi-codegen-extra-tags: + yaml: expired_at type: string format: date-time InstanceMeta: @@ -1734,7 +1771,7 @@ components: items: type: string placement_policy: - $ref: '#/components/schemas/Placement' + $ref: '#/components/schemas/PlacementPolicy' priority: type: integer resources: @@ -2156,7 +2193,24 @@ components: items: $ref: '#/components/schemas/NodeInfo' + # ======================================================================== + # object schemas + # ======================================================================== + ObjectArray: + type: array + items: + $ref: '#/components/schemas/ObjectItem' + ObjectItem: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/ObjectMeta' + data: + $ref: '#/components/schemas/ObjectData' ObjectConfig: type: object required: @@ -2180,10 +2234,83 @@ components: mtime: type: string format: date-time + ObjectMeta: + type: object + required: + - object + properties: + object: + type: string ObjectPaths: type: array items: type: string + ObjectData: + type: object + required: + - avail + - flex_max + - flex_min + - flex_target + - frozen + - instances + - orchestrate + - overall + - placement_policy + - placement_state + - priority + - provisioned + - scope + - topology + - up_instances_count + - updated_at + properties: + avail: + $ref: '#/components/schemas/Status' + flex_max: + x-oapi-codegen-extra-tags: + yaml: flex_max + type: integer + flex_min: + x-oapi-codegen-extra-tags: + yaml: flex_min + type: integer + flex_target: + x-oapi-codegen-extra-tags: + yaml: flex_target + type: integer + frozen: + type: string + instances: + type: object + additionalProperties: + $ref: '#/components/schemas/Instance' + orchestrate: + $ref: '#/components/schemas/Orchestrate' + overall: + $ref: '#/components/schemas/Status' + placement_policy: + $ref: '#/components/schemas/PlacementPolicy' + placement_state: + $ref: '#/components/schemas/PlacementState' + priority: + type: integer + provisioned: + $ref: '#/components/schemas/Provisioned' + scope: + type: array + items: + type: string + topology: + $ref: '#/components/schemas/Topology' + up_instances_count: + x-oapi-codegen-extra-tags: + yaml: up_instances_count + type: integer + updated_at: + x-oapi-codegen-extra-tags: + yaml: updated_at + type: string Orchestrate: type: string enum: @@ -2195,6 +2322,8 @@ components: type: object properties: orchestration_id: + x-oapi-codegen-extra-tags: + yaml: orchestration_id type: string format: uuid required: @@ -2267,7 +2396,9 @@ components: size: description: volume size in bytes type: number - Placement: + PlacementPolicy: + x-oapi-codegen-extra-tags: + yaml: placement_policy type: string default: none description: object placement policy @@ -2279,6 +2410,16 @@ components: - score - spread - shift + PlacementState: + x-oapi-codegen-extra-tags: + yaml: placement_state + type: string + description: object placement state + enum: + - optimal + - non-optimal + - n/a + - undef PostDaemonLogsControl: type: object required: @@ -2319,6 +2460,8 @@ components: - data properties: allocation_id: + x-oapi-codegen-extra-tags: + yaml: allocation_id type: string format: uuid data: @@ -2341,11 +2484,15 @@ components: path: type: string session_id: + x-oapi-codegen-extra-tags: + yaml: session_id type: string format: uuid state: type: string is_partial: + x-oapi-codegen-extra-tags: + yaml: is_partial type: boolean # ======================================================================== @@ -2456,8 +2603,12 @@ components: - nodename properties: cluster_id: + x-oapi-codegen-extra-tags: + yaml: cluster_id type: string cluster_name: + x-oapi-codegen-extra-tags: + yaml: cluster_name type: string nodename: type: string @@ -2508,14 +2659,20 @@ components: addr: type: string cluster_id: + x-oapi-codegen-extra-tags: + yaml: cluster_id type: string cluster_name: + x-oapi-codegen-extra-tags: + yaml: cluster_name type: string msg: type: string nodename: type: string updated_at: + x-oapi-codegen-extra-tags: + yaml: updated_at type: string format: date-time RelayMessageList: @@ -2635,6 +2792,8 @@ components: remaining: type: integer last_at: + x-oapi-codegen-extra-tags: + yaml: last_at type: string format: date-time ResourceId: diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index 611fe6151..dfa175bdf 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -190,6 +190,9 @@ type ClientInterface interface { // GetNodesInfo request GetNodesInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetObject request + GetObject(ctx context.Context, params *GetObjectParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // PostObjectActionAbort request with any body PostObjectActionAbortWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -705,6 +708,18 @@ func (c *Client) GetNodesInfo(ctx context.Context, reqEditors ...RequestEditorFn return c.Client.Do(req) } +func (c *Client) GetObject(ctx context.Context, params *GetObjectParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetObjectRequest(c.Server, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) PostObjectActionAbortWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewPostObjectActionAbortRequestWithBody(c.Server, contentType, body) if err != nil { @@ -2522,6 +2537,53 @@ func NewGetNodesInfoRequest(server string) (*http.Request, error) { return req, nil } +// NewGetObjectRequest generates requests for GetObject +func NewGetObjectRequest(server string, params *GetObjectParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/object") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + queryValues := queryURL.Query() + + if params.Path != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "path", runtime.ParamLocationQuery, *params.Path); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + queryURL.RawQuery = queryValues.Encode() + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewPostObjectActionAbortRequest calls the generic PostObjectActionAbort builder with application/json body func NewPostObjectActionAbortRequest(server string, body PostObjectActionAbortJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -3642,6 +3704,9 @@ type ClientWithResponsesInterface interface { // GetNodesInfo request GetNodesInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetNodesInfoResponse, error) + // GetObject request + GetObjectWithResponse(ctx context.Context, params *GetObjectParams, reqEditors ...RequestEditorFn) (*GetObjectResponse, error) + // PostObjectActionAbort request with any body PostObjectActionAbortWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostObjectActionAbortResponse, error) @@ -4526,6 +4591,32 @@ func (r GetNodesInfoResponse) StatusCode() int { return 0 } +type GetObjectResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ObjectArray + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetObjectResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetObjectResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type PostObjectActionAbortResponse struct { Body []byte HTTPResponse *http.Response @@ -5417,6 +5508,15 @@ func (c *ClientWithResponses) GetNodesInfoWithResponse(ctx context.Context, reqE return ParseGetNodesInfoResponse(rsp) } +// GetObjectWithResponse request returning *GetObjectResponse +func (c *ClientWithResponses) GetObjectWithResponse(ctx context.Context, params *GetObjectParams, reqEditors ...RequestEditorFn) (*GetObjectResponse, error) { + rsp, err := c.GetObject(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetObjectResponse(rsp) +} + // PostObjectActionAbortWithBodyWithResponse request with arbitrary body returning *PostObjectActionAbortResponse func (c *ClientWithResponses) PostObjectActionAbortWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostObjectActionAbortResponse, error) { rsp, err := c.PostObjectActionAbortWithBody(ctx, contentType, body, reqEditors...) @@ -7279,6 +7379,60 @@ func ParseGetNodesInfoResponse(rsp *http.Response) (*GetNodesInfoResponse, error return response, nil } +// ParseGetObjectResponse parses an HTTP response from a GetObjectWithResponse call +func ParseGetObjectResponse(rsp *http.Response) (*GetObjectResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetObjectResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ObjectArray + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + // ParsePostObjectActionAbortResponse parses an HTTP response from a PostObjectActionAbortWithResponse call func ParsePostObjectActionAbortResponse(rsp *http.Response) (*PostObjectActionAbortResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index 2d4a57b0e..7664bb9c8 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -114,6 +114,9 @@ type ServerInterface interface { // (GET /nodes/info) GetNodesInfo(ctx echo.Context) error + // (GET /object) + GetObject(ctx echo.Context, params GetObjectParams) error + // (POST /object/action/abort) PostObjectActionAbort(ctx echo.Context) error @@ -821,6 +824,28 @@ func (w *ServerInterfaceWrapper) GetNodesInfo(ctx echo.Context) error { return err } +// GetObject converts echo context to params. +func (w *ServerInterfaceWrapper) GetObject(ctx echo.Context) error { + var err error + + ctx.Set(BasicAuthScopes, []string{""}) + + ctx.Set(BearerAuthScopes, []string{""}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetObjectParams + // ------------- Optional query parameter "path" ------------- + + err = runtime.BindQueryParameter("form", true, false, "path", ctx.QueryParams(), ¶ms.Path) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter path: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetObject(ctx, params) + return err +} + // PostObjectActionAbort converts echo context to params. func (w *ServerInterfaceWrapper) PostObjectActionAbort(ctx echo.Context) error { var err error @@ -1260,6 +1285,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/node/monitor", wrapper.GetNodeMonitor) router.GET(baseURL+"/node/status", wrapper.GetNodeStatus) router.GET(baseURL+"/nodes/info", wrapper.GetNodesInfo) + router.GET(baseURL+"/object", wrapper.GetObject) router.POST(baseURL+"/object/action/abort", wrapper.PostObjectActionAbort) router.POST(baseURL+"/object/action/delete", wrapper.PostObjectActionDelete) router.POST(baseURL+"/object/action/freeze", wrapper.PostObjectActionFreeze) @@ -1288,124 +1314,130 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/daemon/api/codegen_type_gen.go b/daemon/api/codegen_type_gen.go index ae6a76ac5..4c2f4511f 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -23,15 +23,23 @@ const ( OrchestrateStart Orchestrate = "start" ) -// Defines values for Placement. +// Defines values for PlacementPolicy. const ( - PlacementLastStart Placement = "last start" - PlacementLoadAvg Placement = "load avg" - PlacementNodesOrder Placement = "nodes order" - PlacementNone Placement = "none" - PlacementScore Placement = "score" - PlacementShift Placement = "shift" - PlacementSpread Placement = "spread" + PlacementPolicyLastStart PlacementPolicy = "last start" + PlacementPolicyLoadAvg PlacementPolicy = "load avg" + PlacementPolicyNodesOrder PlacementPolicy = "nodes order" + PlacementPolicyNone PlacementPolicy = "none" + PlacementPolicyScore PlacementPolicy = "score" + PlacementPolicyShift PlacementPolicy = "shift" + PlacementPolicySpread PlacementPolicy = "spread" +) + +// Defines values for PlacementState. +const ( + PlacementStateNa PlacementState = "n/a" + PlacementStateNonOptimal PlacementState = "non-optimal" + PlacementStateOptimal PlacementState = "optimal" + PlacementStateUndef PlacementState = "undef" ) // Defines values for PostDaemonLogsControlLevel. @@ -73,13 +81,13 @@ const ( // Defines values for Status. const ( - StatusDown Status = "down" - StatusNa Status = "n/a" - StatusStdbyDown Status = "stdby down" - StatusStdbyUp Status = "stdby up" - StatusUndef Status = "undef" - StatusUp Status = "up" - StatusWarn Status = "warn" + Down Status = "down" + Na Status = "n/a" + StdbyDown Status = "stdby down" + StdbyUp Status = "stdby up" + Undef Status = "undef" + Up Status = "up" + Warn Status = "warn" ) // Defines values for Topology. @@ -96,7 +104,7 @@ type ArbitratorStatus struct { // AuthToken defines model for AuthToken. type AuthToken struct { - ExpiredAt time.Time `json:"expired_at"` + ExpiredAt time.Time `json:"expired_at" yaml:"expired_at"` Token string `json:"token"` } @@ -134,10 +142,10 @@ type DNSZone = []DNSRecord // DRBDAllocation defines model for DRBDAllocation. type DRBDAllocation struct { - ExpireAt time.Time `json:"expire_at"` - Id openapi_types.UUID `json:"id"` - Minor int `json:"minor"` - Port int `json:"port"` + ExpiredAt time.Time `json:"expired_at" yaml:"expired_at"` + Id openapi_types.UUID `json:"id"` + Minor int `json:"minor"` + Port int `json:"port"` } // DRBDConfig defines model for DRBDConfig. @@ -184,10 +192,10 @@ type DaemonHbMode struct { type DaemonHbStream struct { Alerts []DaemonSubsystemAlert `json:"alerts"` Configured time.Time `json:"configured"` - CreatedAt time.Time `json:"created_at"` + CreatedAt time.Time `json:"created_at" yaml:"created_at"` Id string `json:"id"` - IsBeating bool `json:"is_beating"` - LastAt time.Time `json:"last_at"` + IsBeating bool `json:"is_beating" yaml:"is_beating"` + LastAt time.Time `json:"last_at" yaml:"last_at"` State string `json:"state"` // Type hb stream type @@ -196,8 +204,8 @@ type DaemonHbStream struct { // DaemonHbStreamPeer defines model for DaemonHbStreamPeer. type DaemonHbStreamPeer struct { - IsBeating bool `json:"is_beating"` - LastAt time.Time `json:"last_at"` + IsBeating bool `json:"is_beating" yaml:"is_beating"` + LastAt time.Time `json:"last_at" yaml:"last_at"` } // DaemonHbStreamType defines model for DaemonHbStreamType. @@ -241,7 +249,7 @@ type DaemonSubsystemAlert struct { type DaemonSubsystemStatus struct { Alerts []DaemonSubsystemAlert `json:"alerts"` Configured time.Time `json:"configured"` - CreatedAt time.Time `json:"created_at"` + CreatedAt time.Time `json:"created_at" yaml:"created_at"` Id string `json:"id"` State string `json:"state"` } @@ -420,18 +428,60 @@ type NodeStatusItem struct { // NodesInfo defines model for NodesInfo. type NodesInfo = []NodeInfo +// ObjectArray defines model for ObjectArray. +type ObjectArray = []ObjectItem + // ObjectConfig defines model for ObjectConfig. type ObjectConfig struct { Data map[string]interface{} `json:"data"` Mtime time.Time `json:"mtime"` } +// ObjectData defines model for ObjectData. +type ObjectData struct { + Avail Status `json:"avail"` + FlexMax int `json:"flex_max" yaml:"flex_max"` + FlexMin int `json:"flex_min" yaml:"flex_min"` + FlexTarget int `json:"flex_target" yaml:"flex_target"` + Frozen string `json:"frozen"` + Instances map[string]Instance `json:"instances"` + Orchestrate Orchestrate `json:"orchestrate"` + Overall Status `json:"overall"` + + // PlacementPolicy object placement policy + PlacementPolicy PlacementPolicy `json:"placement_policy" yaml:"placement_policy"` + + // PlacementState object placement state + PlacementState PlacementState `json:"placement_state" yaml:"placement_state"` + Priority int `json:"priority"` + + // Provisioned service, instance or resource provisioned state + Provisioned Provisioned `json:"provisioned"` + Scope []string `json:"scope"` + + // Topology object topology + Topology Topology `json:"topology"` + UpInstancesCount int `json:"up_instances_count" yaml:"up_instances_count"` + UpdatedAt string `json:"updated_at" yaml:"updated_at"` +} + // ObjectFile defines model for ObjectFile. type ObjectFile struct { Data []byte `json:"data"` Mtime time.Time `json:"mtime"` } +// ObjectItem defines model for ObjectItem. +type ObjectItem struct { + Data ObjectData `json:"data"` + Meta ObjectMeta `json:"meta"` +} + +// ObjectMeta defines model for ObjectMeta. +type ObjectMeta struct { + Object string `json:"object"` +} + // ObjectPaths defines model for ObjectPaths. type ObjectPaths = []string @@ -440,11 +490,14 @@ type Orchestrate string // OrchestrationQueued defines model for OrchestrationQueued. type OrchestrationQueued struct { - OrchestrationId openapi_types.UUID `json:"orchestration_id"` + OrchestrationId openapi_types.UUID `json:"orchestration_id" yaml:"orchestration_id"` } -// Placement object placement policy -type Placement string +// PlacementPolicy object placement policy +type PlacementPolicy string + +// PlacementState object placement state +type PlacementState string // PoolStatus defines model for PoolStatus. type PoolStatus struct { @@ -501,7 +554,7 @@ type PostDaemonSubActionAction string // PostNodeDRBDConfigRequest defines model for PostNodeDRBDConfigRequest. type PostNodeDRBDConfigRequest struct { - AllocationId openapi_types.UUID `json:"allocation_id"` + AllocationId openapi_types.UUID `json:"allocation_id" yaml:"allocation_id"` Data []byte `json:"data"` } @@ -523,16 +576,16 @@ type PostObjectClear struct { // PostObjectProgress defines model for PostObjectProgress. type PostObjectProgress struct { - IsPartial *bool `json:"is_partial,omitempty"` + IsPartial *bool `json:"is_partial,omitempty" yaml:"is_partial"` Path string `json:"path"` - SessionId openapi_types.UUID `json:"session_id"` + SessionId openapi_types.UUID `json:"session_id" yaml:"session_id"` State string `json:"state"` } // PostRelayMessage defines model for PostRelayMessage. type PostRelayMessage struct { - ClusterId string `json:"cluster_id"` - ClusterName string `json:"cluster_name"` + ClusterId string `json:"cluster_id" yaml:"cluster_id"` + ClusterName string `json:"cluster_name" yaml:"cluster_name"` Msg string `json:"msg"` Nodename string `json:"nodename"` } @@ -560,11 +613,11 @@ type Provisioned string // RelayMessage defines model for RelayMessage. type RelayMessage struct { Addr string `json:"addr"` - ClusterId string `json:"cluster_id"` - ClusterName string `json:"cluster_name"` + ClusterId string `json:"cluster_id" yaml:"cluster_id"` + ClusterName string `json:"cluster_name" yaml:"cluster_name"` Msg string `json:"msg"` Nodename string `json:"nodename"` - UpdatedAt time.Time `json:"updated_at"` + UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` } // RelayMessageList defines model for RelayMessageList. @@ -592,7 +645,7 @@ type ResourceMonitor = instance.ResourceMonitor // ResourceMonitorRestart defines model for ResourceMonitorRestart. type ResourceMonitorRestart struct { - LastAt time.Time `json:"last_at"` + LastAt time.Time `json:"last_at" yaml:"last_at"` Remaining int `json:"remaining"` } @@ -888,6 +941,12 @@ type GetNodeStatusParams struct { Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` } +// GetObjectParams defines parameters for GetObject. +type GetObjectParams struct { + // Path object selector expression. + Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` +} + // GetObjectBacklogsParams defines parameters for GetObjectBacklogs. type GetObjectBacklogsParams struct { // Filter list of log filter diff --git a/daemon/daemonapi/get_node_drbd_allocation.go b/daemon/daemonapi/get_node_drbd_allocation.go index 643b03689..5f93509e9 100644 --- a/daemon/daemonapi/get_node_drbd_allocation.go +++ b/daemon/daemonapi/get_node_drbd_allocation.go @@ -58,7 +58,7 @@ func (t *pendingDRBDAllocationsMap) ports() []int { func (t *pendingDRBDAllocationsMap) expire() { now := time.Now() for id, a := range t.m { - if a.ExpireAt.After(now) { + if a.ExpiredAt.After(now) { delete(t.m, id) } } @@ -81,8 +81,8 @@ func (a *DaemonApi) GetNodeDRBDAllocation(ctx echo.Context) error { pendingDRBDAllocations.expire() resp := api.DRBDAllocation{ - Id: uuid.New(), - ExpireAt: time.Now().Add(5 * time.Second), + Id: uuid.New(), + ExpiredAt: time.Now().Add(5 * time.Second), } digest, err := drbd.GetDigest() diff --git a/daemon/daemonapi/get_object.go b/daemon/daemonapi/get_object.go new file mode 100644 index 000000000..cd134c01a --- /dev/null +++ b/daemon/daemonapi/get_object.go @@ -0,0 +1,65 @@ +package daemonapi + +import ( + "net/http" + + "github.com/labstack/echo/v4" + "github.com/rs/zerolog/log" + + "github.com/opensvc/om3/core/instance" + "github.com/opensvc/om3/core/object" + "github.com/opensvc/om3/daemon/api" +) + +func (a *DaemonApi) GetObject(ctx echo.Context, params api.GetObjectParams) error { + meta := Meta{ + Context: ctx, + Path: params.Path, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + ostats := object.StatusData.GetAll() + l := make(api.ObjectArray, 0) + for _, ostat := range ostats { + if !meta.HasPath(ostat.Path.String()) { + continue + } + + d := api.ObjectItem{ + Meta: api.ObjectMeta{ + Object: ostat.Path.String(), + }, + Data: api.ObjectData{ + Avail: api.Status(ostat.Value.Avail.String()), + FlexMax: ostat.Value.FlexMax, + FlexMin: ostat.Value.FlexMin, + FlexTarget: ostat.Value.FlexTarget, + Frozen: ostat.Value.Frozen, + Instances: make(map[string]api.Instance), + Orchestrate: api.Orchestrate(ostat.Value.Orchestrate), + Overall: api.Status(ostat.Value.Overall.String()), + PlacementPolicy: api.PlacementPolicy(ostat.Value.PlacementPolicy.String()), + PlacementState: api.PlacementState(ostat.Value.PlacementState.String()), + Priority: int(ostat.Value.Priority), + Provisioned: api.Provisioned(ostat.Value.Provisioned.String()), + Scope: append([]string{}, ostat.Value.Scope...), + Topology: api.Topology(ostat.Value.Topology.String()), + UpInstancesCount: ostat.Value.UpInstancesCount, + UpdatedAt: ostat.Value.UpdatedAt.String(), + }, + } + for nodename, config := range instance.ConfigData.GetByPath(ostat.Path) { + monitor := instance.MonitorData.Get(ostat.Path, nodename) + status := instance.StatusData.Get(ostat.Path, nodename) + d.Data.Instances[nodename] = api.Instance{ + Config: config, + Monitor: monitor, + Status: status, + } + } + l = append(l, d) + } + return ctx.JSON(http.StatusOK, l) +} diff --git a/daemon/daemonapi/post_node_drbd_config.go b/daemon/daemonapi/post_node_drbd_config.go index 07f4a518b..aa7a0a086 100644 --- a/daemon/daemonapi/post_node_drbd_config.go +++ b/daemon/daemonapi/post_node_drbd_config.go @@ -17,7 +17,7 @@ func (a *DaemonApi) PostNodeDRBDConfig(ctx echo.Context, params api.PostNodeDRBD if err := ctx.Bind(&payload); err != nil { return JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "%s", err) } - if a, ok := pendingDRBDAllocations.get(payload.AllocationId); !ok || time.Now().After(a.ExpireAt) { + if a, ok := pendingDRBDAllocations.get(payload.AllocationId); !ok || time.Now().After(a.ExpiredAt) { return JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "drbd allocation expired: %#v", a) } if strings.Contains(params.Name, "..") || strings.HasPrefix(params.Name, "/") { diff --git a/drivers/resdiskdrbd/main.go b/drivers/resdiskdrbd/main.go index a54b3c5ae..c90306757 100644 --- a/drivers/resdiskdrbd/main.go +++ b/drivers/resdiskdrbd/main.go @@ -446,7 +446,7 @@ func (t T) makeConfRes(allocations map[string]api.DRBDAllocation) (ConfRes, erro if !ok { return ConfRes{}, fmt.Errorf("drbd allocation for node %s not found", nodename) } - if time.Now().After(allocation.ExpireAt) { + if time.Now().After(allocation.ExpiredAt) { return ConfRes{}, fmt.Errorf("drbd allocation for node %s has expired", nodename) } device := fmt.Sprintf("/dev/drbd%d", allocation.Minor)