From 48273195509ab8cfa1e806bb85e55b21010907e7 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 1 Sep 2023 16:30:40 +0200 Subject: [PATCH 01/30] Implement more api handlers * GET /instance/monitor * GET /instance/config Use x-go-type openapi syntax to avoid a lot of transtyping code. --- daemon/api/api.yaml | 262 +++++++++++++++-- daemon/api/codegen_client_gen.go | 340 +++++++++++++++++++++++ daemon/api/codegen_server_gen.go | 274 +++++++++++------- daemon/api/codegen_type_gen.go | 123 ++++++-- daemon/daemonapi/get_instance_config.go | 42 +++ daemon/daemonapi/get_instance_monitor.go | 43 +++ daemon/daemonapi/get_instance_status.go | 56 +--- daemon/daemonapi/post_instance_status.go | 75 +---- 8 files changed, 944 insertions(+), 271 deletions(-) create mode 100644 daemon/daemonapi/get_instance_config.go create mode 100644 daemon/daemonapi/get_instance_monitor.go diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index 22dd1857a..1fa8e4d75 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -265,11 +265,63 @@ paths: $ref: '#/components/responses/403' 500: $ref: '#/components/responses/500' + /instance/config: + get: + operationId: GetInstanceConfig + tags: + - instance + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/PathOptional' + - $ref: '#/components/parameters/NodeOptional' + responses: + 200: + description: get instance config + content: + application/json: + schema: + $ref: '#/components/schemas/GetInstanceConfigArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + /instance/monitor: + get: + operationId: GetInstanceMonitor + tags: + - instance + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/PathOptional' + - $ref: '#/components/parameters/NodeOptional' + responses: + 200: + description: get instance monitor + content: + application/json: + schema: + $ref: '#/components/schemas/GetInstanceMonitorArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' /instance/status: get: operationId: GetInstanceStatus tags: - - object + - instance security: - basicAuth: [] - bearerAuth: [] @@ -294,7 +346,7 @@ paths: post: operationId: PostInstanceStatus tags: - - object + - instance security: - basicAuth: [] - bearerAuth: [] @@ -1460,45 +1512,154 @@ components: node: type: string InstanceConfig: + x-go-type: instance.Config + x-go-type-import: + path: github.com/opensvc/om3/core/config type: object required: - app + - checksum + - children - drp - env + - flex_max + - flex_min + - flex_target + - monitor_action + - pre_monitor_action + - nodename - orchestrate - - placement + - path + - parents + - placement_policy - priority + - resources + - scope - subsets - topology + - updated_at properties: app: type: string + checksum: + type: string + children: + type: array + items: + type: string drp: type: boolean env: type: string + flex_max: + type: integer + flex_min: + type: integer + flex_target: + type: integer + monitor_action: + type: string + pre_monitor_action: + type: string + nodename: + type: string orchestrate: $ref: '#/components/schemas/Orchestrate' - placement: + path: + type: string + parents: + type: array + items: + type: string + placement_policy: $ref: '#/components/schemas/Placement' priority: type: integer - description: scheduling priority of an object instance on a its node - default: 50 + resources: + $ref: '#/components/schemas/ResourcesConfig' + scope: + type: array + items: + type: string subsets: - type: object - description: subset properties - additionalProperties: - type: object - required: - - parallel - properties: - parallel: - type: boolean - default: false + $ref: '#/components/schemas/SubsetsConfig' topology: $ref: '#/components/schemas/Topology' + updated_at: + type: string + format: date-time + InstanceMonitor: + x-go-type: instance.Monitor + x-go-type-import: + path: github.com/opensvc/om3/core/instance + type: object + required: + - global_expect + - global_expect_updated_at + - global_expect_options + - is_leader + - is_ha_leader + - local_expect + - local_expect_updated_at + - orchestration_id + - orchestration_is_done + - session_id + - state + - state_updated_at + - monitor_action_executed_at + - preserved + - resources + - updated_at + - parents + - children + properties: + global_expect: + type: string + global_expect_updated_at: + type: string + format: date-time + global_expect_options: + type: object + is_leader: + type: boolean + is_ha_leader: + type: boolean + local_expect: + type: string + local_expect_updated_at: + type: string + format: date-time + orchestration_id: + type: string + orchestration_is_done: + type: boolean + session_id: + type: string + state: + type: string + state_updated_at: + type: string + format: date-time + monitor_action_executed_at: + type: string + format: date-time + preserved: + type: boolean + resources: + type: array + items: + type: object + updated_at: + type: string + format: date-time + parents: + type: object + children: + type: object InstanceStatus: + x-go-type: instance.Status + x-go-type-import: + path: github.com/opensvc/om3/core/status type: object required: - avail @@ -1865,6 +2026,34 @@ components: type: string is_partial: type: boolean + GetInstanceConfigArray: + type: array + items: + $ref: '#/components/schemas/GetInstanceConfigElement' + GetInstanceConfigElement: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/InstanceMeta' + data: + $ref: '#/components/schemas/InstanceConfig' + GetInstanceMonitorArray: + type: array + items: + $ref: '#/components/schemas/GetInstanceMonitorElement' + GetInstanceMonitorElement: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/InstanceMeta' + data: + $ref: '#/components/schemas/InstanceMonitor' GetInstanceStatusArray: type: array items: @@ -1991,6 +2180,33 @@ components: properties: messages: $ref: '#/components/schemas/RelayMessageList' + ResourcesConfig: + type: array + items: + $ref: '#/components/schemas/ResourceConfig' + ResourceConfig: + x-go-type: instance.ResourceConfig + x-go-type-import: + path: github.com/opensvc/om3/core/instance + type: object + required: + - is_disabled + - is_monitored + - is_standby + - restart + - restart_delay + properties: + is_disabled: + type: boolean + is_monitored: + type: boolean + is_standby: + type: boolean + restart: + type: integer + restart_delay: + type: string + format: duration ResourceExposedStatus: type: object required: @@ -2167,6 +2383,20 @@ components: - undef - stdby up - stdby down + SubsetsConfig: + type: array + items: + $ref: '#/components/schemas/SubsetConfig' + SubsetConfig: + x-go-type: instance.SubsetConfig + x-go-type-import: + path: github.com/opensvc/om3/core/instance + type: object + required: + - parallel + properties: + parallel: + type: boolean Topology: type: string description: "object topology" diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index 35df8a3c4..8c8c10f11 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -123,6 +123,12 @@ type ClientInterface interface { PostDaemonSubAction(ctx context.Context, body PostDaemonSubActionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetInstanceConfig request + GetInstanceConfig(ctx context.Context, params *GetInstanceConfigParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetInstanceMonitor request + GetInstanceMonitor(ctx context.Context, params *GetInstanceMonitorParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetInstanceStatus request GetInstanceStatus(ctx context.Context, params *GetInstanceStatusParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -411,6 +417,30 @@ func (c *Client) PostDaemonSubAction(ctx context.Context, body PostDaemonSubActi return c.Client.Do(req) } +func (c *Client) GetInstanceConfig(ctx context.Context, params *GetInstanceConfigParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetInstanceConfigRequest(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) GetInstanceMonitor(ctx context.Context, params *GetInstanceMonitorParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetInstanceMonitorRequest(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) GetInstanceStatus(ctx context.Context, params *GetInstanceStatusParams, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetInstanceStatusRequest(c.Server, params) if err != nil { @@ -1511,6 +1541,132 @@ func NewPostDaemonSubActionRequestWithBody(server string, contentType string, bo return req, nil } +// NewGetInstanceConfigRequest generates requests for GetInstanceConfig +func NewGetInstanceConfigRequest(server string, params *GetInstanceConfigParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/instance/config") + 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) + } + } + } + + } + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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 +} + +// NewGetInstanceMonitorRequest generates requests for GetInstanceMonitor +func NewGetInstanceMonitorRequest(server string, params *GetInstanceMonitorParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/instance/monitor") + 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) + } + } + } + + } + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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 +} + // NewGetInstanceStatusRequest generates requests for GetInstanceStatus func NewGetInstanceStatusRequest(server string, params *GetInstanceStatusParams) (*http.Request, error) { var err error @@ -3132,6 +3288,12 @@ type ClientWithResponsesInterface interface { PostDaemonSubActionWithResponse(ctx context.Context, body PostDaemonSubActionJSONRequestBody, reqEditors ...RequestEditorFn) (*PostDaemonSubActionResponse, error) + // GetInstanceConfig request + GetInstanceConfigWithResponse(ctx context.Context, params *GetInstanceConfigParams, reqEditors ...RequestEditorFn) (*GetInstanceConfigResponse, error) + + // GetInstanceMonitor request + GetInstanceMonitorWithResponse(ctx context.Context, params *GetInstanceMonitorParams, reqEditors ...RequestEditorFn) (*GetInstanceMonitorResponse, error) + // GetInstanceStatus request GetInstanceStatusWithResponse(ctx context.Context, params *GetInstanceStatusParams, reqEditors ...RequestEditorFn) (*GetInstanceStatusResponse, error) @@ -3521,6 +3683,58 @@ func (r PostDaemonSubActionResponse) StatusCode() int { return 0 } +type GetInstanceConfigResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *GetInstanceConfigArray + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetInstanceConfigResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetInstanceConfigResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetInstanceMonitorResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *GetInstanceMonitorArray + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetInstanceMonitorResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetInstanceMonitorResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type GetInstanceStatusResponse struct { Body []byte HTTPResponse *http.Response @@ -4537,6 +4751,24 @@ func (c *ClientWithResponses) PostDaemonSubActionWithResponse(ctx context.Contex return ParsePostDaemonSubActionResponse(rsp) } +// GetInstanceConfigWithResponse request returning *GetInstanceConfigResponse +func (c *ClientWithResponses) GetInstanceConfigWithResponse(ctx context.Context, params *GetInstanceConfigParams, reqEditors ...RequestEditorFn) (*GetInstanceConfigResponse, error) { + rsp, err := c.GetInstanceConfig(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetInstanceConfigResponse(rsp) +} + +// GetInstanceMonitorWithResponse request returning *GetInstanceMonitorResponse +func (c *ClientWithResponses) GetInstanceMonitorWithResponse(ctx context.Context, params *GetInstanceMonitorParams, reqEditors ...RequestEditorFn) (*GetInstanceMonitorResponse, error) { + rsp, err := c.GetInstanceMonitor(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetInstanceMonitorResponse(rsp) +} + // GetInstanceStatusWithResponse request returning *GetInstanceStatusResponse func (c *ClientWithResponses) GetInstanceStatusWithResponse(ctx context.Context, params *GetInstanceStatusParams, reqEditors ...RequestEditorFn) (*GetInstanceStatusResponse, error) { rsp, err := c.GetInstanceStatus(ctx, params, reqEditors...) @@ -5436,6 +5668,114 @@ func ParsePostDaemonSubActionResponse(rsp *http.Response) (*PostDaemonSubActionR return response, nil } +// ParseGetInstanceConfigResponse parses an HTTP response from a GetInstanceConfigWithResponse call +func ParseGetInstanceConfigResponse(rsp *http.Response) (*GetInstanceConfigResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetInstanceConfigResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest GetInstanceConfigArray + 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 +} + +// ParseGetInstanceMonitorResponse parses an HTTP response from a GetInstanceMonitorWithResponse call +func ParseGetInstanceMonitorResponse(rsp *http.Response) (*GetInstanceMonitorResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetInstanceMonitorResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest GetInstanceMonitorArray + 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 +} + // ParseGetInstanceStatusResponse parses an HTTP response from a GetInstanceStatusWithResponse call func ParseGetInstanceStatusResponse(rsp *http.Response) (*GetInstanceStatusResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index 1b91c9562..a8ed98911 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -51,6 +51,12 @@ type ServerInterface interface { // (POST /daemon/sub/action) PostDaemonSubAction(ctx echo.Context) error + // (GET /instance/config) + GetInstanceConfig(ctx echo.Context, params GetInstanceConfigParams) error + + // (GET /instance/monitor) + GetInstanceMonitor(ctx echo.Context, params GetInstanceMonitorParams) error + // (GET /instance/status) GetInstanceStatus(ctx echo.Context, params GetInstanceStatusParams) error @@ -365,6 +371,64 @@ func (w *ServerInterfaceWrapper) PostDaemonSubAction(ctx echo.Context) error { return err } +// GetInstanceConfig converts echo context to params. +func (w *ServerInterfaceWrapper) GetInstanceConfig(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 GetInstanceConfigParams + // ------------- 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)) + } + + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetInstanceConfig(ctx, params) + return err +} + +// GetInstanceMonitor converts echo context to params. +func (w *ServerInterfaceWrapper) GetInstanceMonitor(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 GetInstanceMonitorParams + // ------------- 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)) + } + + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetInstanceMonitor(ctx, params) + return err +} + // GetInstanceStatus converts echo context to params. func (w *ServerInterfaceWrapper) GetInstanceStatus(ctx echo.Context) error { var err error @@ -1027,6 +1091,8 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/daemon/status", wrapper.GetDaemonStatus) router.POST(baseURL+"/daemon/stop", wrapper.PostDaemonStop) router.POST(baseURL+"/daemon/sub/action", wrapper.PostDaemonSubAction) + router.GET(baseURL+"/instance/config", wrapper.GetInstanceConfig) + router.GET(baseURL+"/instance/monitor", wrapper.GetInstanceMonitor) router.GET(baseURL+"/instance/status", wrapper.GetInstanceStatus) router.POST(baseURL+"/instance/status", wrapper.PostInstanceStatus) router.GET(baseURL+"/networks", wrapper.GetNetworks) @@ -1068,104 +1134,116 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+w9f3PbtpJfBaN3M23fyLIdp3mtb/pHmqSvfuc4udi5m7nYkwHJlYSGBBgAlK28yXe/", - "wQLgDxGkKNty3dh/JRZBYLG72N9Y/nsUiywXHLhWo8N/j3IqaQYaJP718t2vL18IPmWzE5qB+SUBFUuW", - "ayb46HCk50CmRZqSnOo5EVOCP7AUCFMkgaSIISFTKTJ8wM0c4xEzb34uQC5H4xH+djhyjyR8LpiEZHSo", - "ZQHjkYrnkFGzrl7mZpzSkvHZ6OvX8ehlIakFYxWqjF6RxD8Nr1d7XK0BVzTLU/P4RzUaB5Z8tQCuf2Op", - "BtleNWVKGxSAGWSQYEaFVy8fVmszDZlqT2pHErjKJSjFBD8kHz4xnlx8GKc0gvSXBU0LuPj7udlJBf+b", - "6A+I9ammulDv84RqSMaGRL9MhWjvrPyBSkmXuNNjljEd2mPGNEFYSSwKrjs2iOPCuN0fj6ZCZlSPDkeM", - "62dPK3gY1zADaQEQs3WITsXsttBMSQDRNQQ3sT2ZTBrYViz55Wf6E+w9hWc7Ubz/ZOfpATzb+ekg2d+Z", - "wv5e8uPBswOg/xiEeXPQVE5jeIPA0bQNLfdDeg6Tf953gk5E0rOKQB4ilCeEcaUpj4EoSCHWoo6nSRcQ", - "IoGO08WfjOmXX6DYDx4yy7tvqZ53wmRYuWNZ92gTQdK71AY7Xrt0hYEk2h9fQvT3IAIMPGvJsjlc14JD", - "dR+/Gi0U0YIo4Ik5k4pMhewBRfXiqOOANgm/paP3DlK6fJEWSoM8SsLaLraPCUtIqTi94lOp0OaB4Pin", - "NNN1IMJN85Ela84owmQOKu9UwNw9vRFAfpJ14IgUeniC5oxIkXYJJvcoQO3/kDAdHY7+tltZI7t2mNo1", - "awbpderOQPdh8aekA57a4+5NfzXsqnLBld35k709808suAaOOpLmecpitCd2/1DWIqnm69vaWymiFDK7", - "ShP0N/9V8azlfoODp3ez+K80Ie/gcwFKh6HYvwso3nNa6LmQ7AskYTAO7gUyfroLKBwE5IxlIIoOSH6+", - "C0iMQ5CyOAjCj3fDn0dcg+Q0JacgFyDJKynxFAfguRMWMWCwGMh7TheUpTRCObcCzVcvZVCMPC/0/Ex8", - "AgQglyIHqZmVMHCVG+X4kSLApbVszPgdzTIIKjM/VVtmV8r2Q31q/85FAG1OCbZBi9EZXIcp97r1HM18", - "aAwOe8noOvOKA2bYS29KyBX6PANfsw5SC0luk2NvwzpQysl7MPaixE/XiBOHiq7nb8p9d404LbfYGvHy", - "5PQdxEImAcqlVKkAg4wNX9HgA29ytJlNp7XfS7fNo2UdEzo7AweNHWB2UgdMCMEvT07/T3AYbDVUqGiZ", - "DmOMazxPUxGXEYTQCdzoALKkMbYoWBIaljEuZBh5uZA69GQFezjMTzSugYowBFFXRnHaO/XELwGPlhqC", - "7kAdhm4qUchCCI1F6kytdWTDCV6Uww1/cjXsrZcnp2b8PBo2/PfIjDamK3AYCNixH21IKTgbvKPXbrBB", - "pCg046DCXGBeS4p0KECn5fC2FEtL69agEBFT22+1gRpI9fW76fuiTk2apm+mo8MPg6AtIrVUGjIveS/K", - "OQ3xbm+236M2D2Yisf8ZJj/cPK+dPloVIUpLoNnm853ie0F/pk49P/3Ygd1NDAdicLthh9FMZLy1eUQy", - "UIrOgBQKEhIt0ZckcBVDrsnlHDg5M2OZMp53PDc/SSBMm1/MTPbXzwUUQFLgM/TO23okCAktfWmnZjsc", - "9NAO5kCljoDqcgO4p/ou1sowNyirje1DsqPbTVl0vAmXGORv+MpbMKLgogU4/t7iEaY+Giwa9FTCKBIi", - "BcpROFKlN9CCKxiuzV5NtR7HZ47sTVDDzDCPiD0pxFkT/RCtofJxTRfckiB6XSmJW5rxtK4gbmvO0qRc", - "NRpLP2CAOW2NSW8ArAeorbLcPOU03aQqN/M8BWs2rUg/KxeC5quCBUiml+stVT9L7Z0BIHVhkxpQN9UY", - "KxsNaCLrrhQI8lBrNZZA9YYuprVw29jUVA8w+t3mG+A24MAF/HQhLGP2zRzRthjwAbpyiFFQlPiwpFJm", - "Q5WJyzjFMGBrL/8EfeRyHZaIzxHJQynWev1VChnwINU6x3aa6H0rN6dC6xSGv/XajG3zvqZ9Dlnj5RbQ", - "vOnmVigWq/5tB7+UTjfO1AdA53FbUJauQ0GFsFhwpSVlLhHeVoaxKrLglqZSfAG+0VlCbag0lZseQlGL", - "dQ/bl1iApOkGL+QSFMgFuAzIlBapHh1OaapgNe7lh6I9KAsgbEr0nCliIyVkThXhQpMIgJPCJqJJUgDR", - "glByzis7LhGX3OyZxAZea8ZRkhlyAMfcYw6SiWRyztEuNVZg+ykBnqixzX1YCNRcFGlCIiAFj+eUzyAZ", - "k3NOeUJK4C9ZmpoRCrQBDHc6wYx6mwlyKRZMMcEtetbEC8uhNokgChlv4IK8c2+8usqFgqSi0KoskQXn", - "zoYrJ16T7jKOHk0h7IM6Sl3f8rNHr3mm3AGqH5f2OagxeMW5dZZsUqCO1QoNjQ34jTZ+DImTYzHrVy5u", - "wDVVizMEbTXGfxuPKRCkEzKeg8GYWfrjoJDSqthcnSG01RPQl0J+6hKcIKWQajNuYvlwvm4sf5SHpusM", - "PXL7bg9MgQeFNwUHQ/Ue3/j6dR3yjvKAU5WHIe/SiLmrP2g9kEGLa9XJyqtAta9AGEJ2z+ubUyxErwDy", - "WniZSuiQN3nDIOBFFrlYGPvSJaEUJANipbikG+2ms6sF0SMSOOJT0YYci39CaW/83QdDvEjAGIp9hCUZ", - "gxAsEjg2rwQPQ2f6v0z9OxDw/y75j2DYgA1CZ2FFxYclG1RixQDjM6zQm4SEVh4uAbEThLatBVFaSDoD", - "guATRbldbzAqTp+fYEXOugiZI8q4Xrpg4e0irkVw21QNo7aGVlwKkRvEElaFtWfAn5tT4E+T9aEpuxs7", - "b9dulOfVwQyGLwT4y6ac1mUIWkBkaApcz0DASf0UoR1amH5jKVw7Z3EnEJZFUsNV5Vsh0s6AC81pxFJW", - "6pLBs15Hac+BJhtm/m6kYqudO/06Hi1EWmQb2MTVFP+DbwbFRItW1Vsbqb0apXrp2KHw4jlLE2nT8sOJ", - "ImQ+p4GqZsqJfWQNUIs4kki2AG6D3kQtYuIN4rD30mVqeE27IsHsGuYhYWYRDbXCaK+nV4N4ftflVkrD", - "BFe56KWPo+pfx6h6K5R20WMxUy8E11IElEwKC0gbDvWIGXE8HgEvMhQ4EBUzLFTDny+pxJpuV9kypRp9", - "opxyFiNwvI7Kjn3YVfvBPi2i53E4DU7L3z2Q6KphlE7kgeXHI1VEAYPBhnNrBYrGaKgbBFVF5zz62/5E", - "Xg0q2Gy4nLGv5zcQdG15Xcyo+4AMqitZDcOtpu7dMeguIzEwGlVdpex95VkgmuzrFz4OrD24Xq6/uU5P", - "QNDDXkt5NCGepSKi6Ue4ysMRwPHIrNQ7oCfYHITHKunnkQjlCDqIHSLaRf/8Hefnlhc4vWQ6ngfsIVCa", - "8bKUpVvVZIwf2Yf7bb2zAbDjxpL9oL9Igcotomab3NYrDeBWwH8rxUyCUsHcbE6lZjQNh6O7gbPXAYZK", - "hU320pi8L1djNoil66+rPFwwtfixI6vkH3daopmadVoEHS+Fs412K4317Oy1uYJbdOWggeOoXeKhqQSf", - "k3mRUb4jgSY0SoHAVZ5Se4iIyiFmUxYbDxoj6CKOCymBx96hP+e5XbERmg5pqOayZ3Mgv5+dvfUR8dj4", - "6d9/ePfbi388Odi/GJNTQOlCnv1AZsBBYpA+Wto1hWQzxomydbZTITugIyHg6pWBTKcQwomaC6nHq6hR", - "RZZRuVyZHJP8E0KONDn9/c3745fn/OTNGbFxfXvPsAaYFt1gjl2Ryzk3W8oLmQsFyt4qi2nKvliqfA+T", - "2WRMCsX4zLxqjIwFEFdOfM45zIRmOPY/iQIgAbQeTJ7+ECTZqsNp2aYkpMdZB+/VsxCrlx6wGHlcXdsS", - "snQLSC18Tuz5LU1Ql+LJ2BWGy/guHY21LCBk5/UfbpoksvdY3+Gpv410htnOeBOBsTbbUMffRj5pA/EB", - "97H+XHXWRWy0DMLXURqhOnYXyly1JSVTWCrfLuthXCt3Z8nxLZtxIUERmqaWb4mWlCuGZ8wa/yro8wKP", - "ad5egvGExVSDWYbqlbUUmVOepKUcJDiJKlKUjXRmUOXTiBawhLhJ5svcnD8lJEHvqyOPyFzwrgnUJ1ju", - "2LBhTplU9rAmRvgYUSrR6DL/tzxsdq4FcYWe5NxgA3YuWQKERqLQVlT7XdUBqSiV+phowDqaDU1QHovZ", - "SkHsSskepKklp3ME2ZQw7XOzWrLZDCShxE3gyEnKRO85r5OGC02KvAOvovMuWA0VXhXS2UzCDGnKuBbk", - "jU04ouAEmhh18HxBWVq7AIsvTs453jhRhHHiV6xmTwT/ThPjIhPaxas3Ty975Je6oIpUGUah4WLyMgAy", - "ZOqjxBkWPImWwcSoQ6clJE0v6VJhrj0f4z14QqcaKYvI2AwVwzzuatPG7wfdcUWylhex45pnA0NqSrGZ", - "0Yo6fEWezjaMrg67DOFloBdUZQDInkx7Duu12rUEeSsV7qIzEjWU9DY6Uq9mVzhMuT311L7W+CC04frx", - "37Sm4VjMXnEtl2EVtjKmO5rWNhA66/6CobHqhb79rx6xtlbdJNFQc7kGl4+0qsOt4dadncBLs7XAHU0y", - "Zs5ZlNL4U8qU9j/M3L3GshRnNB79IfBRCnSBXTmEwJjf54Jq3bgYUG3JZ+3abixnxkJef0/CzXBUjsdD", - "J2egB755Zge3YrnlhOV8IYS1lg9YDO6Rz+nNhdJEGXXrs5wEeJILxvXEns7BWUZKLoVME9TdBWef0QKo", - "zUdYAlyzKQPZ7D3BPvPJk729pzv7e5NYZJMiKrguDvf2D+FZlDylB9GPPz7doLjelftbm8etjV5Xc1UV", - "KxY0m7vwelZScmVB/N0vuZI7vheo/Xlnfx9RK3LgahFPlFwcJrB4wvcnDt6J3cVkf3NE09tEdSmd/Kkv", - "jD5JxCWvEgro1Y0KnsAUdUISLQkOs//FwcG8goK4kEwvT82ps4iPqGLx88IeezyNqMPNrxXEc62xxCcC", - "KkH60fav37y4/Nf/nvlL+DgFPl2d42vNbnbxhJEjirXJCc0NqhYglcXyweTnyb41C4Gbh+anvcneqFba", - "sEsLPd8t78/mwjpjhsHQxDbKD+NZ1Y3dcaNNUkfxfTVk13ZN+DoONSrChct2RWOS0SuWFZktFSBPns6v", - "18Fofy8LMM3FFnsZVOgJdzOo+gaEZinB2jWDqsv968Ye1G6d9481g6ob4evGHjR4Holc4/YPF4aYdY7+", - "cGGQa43EDyPDUqMLM8Ou9Xh2E652kyJDRzQoCF8WWU7qHUZenpySL4KX0SYbQ2qy5T9Bl7fnzASjLdLX", - "X8C9x9S9AcXchRN7VbJBOeznpTrpZu8MecfWDu6j1Cs73aYipOx21nUdrDbWNu8aMLDez2yAbNBwpS06", - "dlR5G24Y81R3N75p9mkwDlrRNY2y2s9jxpR1js1AIl1/Dy0ITRJCCYfLxg1JkkEWgZyc87M5ECNhjNkS", - "Y/QiTplRf87sVYRqkgJVmswk5Zp8Zyz474iQ5Lt/Cca/m5zzc/5WihgURradZ9yAgymSGOlD1ZLHcym4", - "KFS6JMZEwO2NiVHKxKPQjFcYEy+jNo3p5lTZWwB5EaVMzSEhl0zPbV3cIW7wl/Nib+8gpjkzf+EfYAA9", - "E2Qq0lRckrwX5DFZioLM6QJD/5d4NdW+aF6wJ/PwnO8Qg4PTIjZTjbsWHtMkgcQ9qX4m32M4AS4tScpd", - "4WgMxtUopn7wqx3ZGGH3amYfO7WnnSteUkVoKoEmS9K8QVsuhqGp6y1FOcGCE5s4MVaJQZ0NZTeZ0biQ", - "PwTkXFVX8i/rRK6IuXZuyteNGq5fRWB/b7khndY4XPqLvowf2yvKh08GW0YPQlBZP3+IpMKRdVElIRML", - "WOHE25FUx2atLlHVBOTmsqo535aEVWORwdIK8bBWXFlChARWU1C5cWFRhUutlVW4jS4Jgqu5IH1APuEK", - "awRU7/y3KaGOXXxrrYgyEJllVhoW3FQ0iQR2LrXYsTS5PRF12+JBzNRuXCts7PSQ23WQFhOg9K8iWd5e", - "J67gWgHLUoH2lnkqZsTHfJvU6Wjw1y+Hn1hv8pvTBbWrhM7d6fBj3pWX7W7kca7mfR6Md1Clt/rxfOqz", - "Npv5i+02wgP8wVZDza0GjBr7e0iEF/kQMXpqxj2Kphriimi3qkhfi76yrH3bOqhaKcDErpRBlBEiVUSk", - "1nL/URmFKO7rLQZIyZWS+03lZKPZ9gAR2eiZvlXx2NGLJMBjmEBrVqjUegWvI/Ffn3VcBuwCeyh2SYUW", - "n2xLKLTugLToZYD07dNVHZy1YiCsIB8amY2EcH0AekXDiR+zxsWrVwhVPmtE40/AE+I7DvR+uKS7ffg2", - "RUT7Qv+3aUZ5EjjSiwR2DXWMY9qZl8HO0ERCjNfNxKwjKWPk+a9+rk2VR/WRkgGaw94U3io/+BYm3ygX", - "YCOoigXi8mZRMGyJF4+UjRYp8v0Uv5WBsZcxmVKWQvIDYbxqleCLT7G2ahIMGxlmsfeZbmSlPRB5vUqv", - "REbJLm10Xe6U3O4KZK1H8zYd0eZKnafnz8Na1XZ9HcZe+N7lG6aXmx/62q7fX4HZI6ge1iHps1y3Qdrt", - "mL7hm8sBItc6Tz+avRsKhAFWD4fLNSbP8f0xd25QVfKw7J3a9Zp+YfG6cbq2ddDLjvY3Pt63Alaov969", - "Vi/uu0Hrxv5U+7LPurE//1m8qXZ9XW6ffWI7Vm3THy4X+eYlgg2G7NKys0WnRKi3wNieRKivEkA+PiCN", - "5pTEXs3W6ZK4pCMRnFD3ZUMMmvuPDGLzuBtYCt9K0MsTHdGzAe1x/B1xQGcm5AXlMaS2xNlSvskPk0d1", - "8c2qix4uTiAFDcPZ+KUd/+fx8ZuSaW1jTRfILxMwdkOP3PwguXkqAb5swM2/2fH3l5vthh65+UFy84wt", - "IKLxp+H8/E//xv3laL+pR55+kDxd9kwYztTlTfx7zNXlth7Z+mGydSFnG9gdb3H4/WXngpcMjS3rH43q", - "B8zbZTOjYbx96rvg3FPexu08svIDZeV1xd9NTnYl4PeVkUX+yMcPk4+rVtTDONmOvxtedotdh6PxzUee", - "fpA8XfBNo3fv/Rv32ZB+jOA9aJ6+Rrzjfe2lv4SL+MjcD4u5b6v437LgY/n/X7YSonUFoEuwVVX72xRm", - "dpVQ7UPPXQQMB6zeSGhcRlD2YtJjYcxadlhbJt/41OGm57364l+glyMsaFrYrryhe2K1xz3ND1qzsiwH", - "qQT3StBNg2FR1deHpPbin3Y9rYHshyOUpu6jlf08iJ+2vAkHbp9yCOLDoduNC+st1h5L6/+a5B9UXt/8", - "5ti27YnHEvtHx6fBo2XT6n7dYgXEdVph3IVaceLrwQiWvP6JvzWSpfwc4LZFS7lQyFux31Mz9mYZbWk4", - "JLbz4xS/OuQ+qoaToZ9iP8VU/9pPwhLsB4ieDiSPPgtyRy5E2nuW3+KAjXpX+J4V/jsKZo372Lhi5Xvc", - "36YscETw5C6ilMW75YcIuul+eklnM5C31FnPfx7iXqPYo8wiyWFMQkqXu7UP+nQhrPFJvI2/zWBePvHf", - "7RtgfeMLL2yTmKNkuwqz+TG/b7xHXt8d+BUSb0s3Nj+u2NG5idp+IQnVVIG2nx2lBLmV1L+i9NjYbaWx", - "29ev/x8AAP//7z/eJG6uAAA=", + "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", + "Ja+v/z8AAP//SZLHr9XDAAA=", } // 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 26adcac03..8e63ebfb2 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -7,6 +7,7 @@ import ( "time" openapi_types "github.com/deepmap/oapi-codegen/pkg/types" + "github.com/opensvc/om3/core/instance" ) const ( @@ -14,6 +15,24 @@ const ( BearerAuthScopes = "bearerAuth.Scopes" ) +// Defines values for Orchestrate. +const ( + OrchestrateHa Orchestrate = "ha" + OrchestrateNo Orchestrate = "no" + OrchestrateStart Orchestrate = "start" +) + +// Defines values for Placement. +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" +) + // Defines values for PostDaemonLogsControlLevel. const ( PostDaemonLogsControlLevelDebug PostDaemonLogsControlLevel = "debug" @@ -27,16 +46,16 @@ const ( // Defines values for PostDaemonSubActionAction. const ( - Start PostDaemonSubActionAction = "start" - Stop PostDaemonSubActionAction = "stop" + PostDaemonSubActionActionStart PostDaemonSubActionAction = "start" + PostDaemonSubActionActionStop PostDaemonSubActionAction = "stop" ) // Defines values for Provisioned. const ( - False Provisioned = "false" - Mixed Provisioned = "mixed" - Na Provisioned = "n/a" - True Provisioned = "true" + ProvisionedFalse Provisioned = "false" + ProvisionedMixed Provisioned = "mixed" + ProvisionedNa Provisioned = "n/a" + ProvisionedTrue Provisioned = "true" ) // Defines values for Role. @@ -62,6 +81,12 @@ const ( StatusWarn Status = "warn" ) +// Defines values for Topology. +const ( + Failover Topology = "failover" + Flex Topology = "flex" +) + // AuthToken defines model for AuthToken. type AuthToken struct { ExpiredAt time.Time `json:"expired_at"` @@ -207,6 +232,24 @@ type DaemonSubsystemStatus struct { // EventList responseEventList is a list of sse type EventList = openapi_types.File +// GetInstanceConfigArray defines model for GetInstanceConfigArray. +type GetInstanceConfigArray = []GetInstanceConfigElement + +// GetInstanceConfigElement defines model for GetInstanceConfigElement. +type GetInstanceConfigElement struct { + Data InstanceConfig `json:"data"` + Meta InstanceMeta `json:"meta"` +} + +// GetInstanceMonitorArray defines model for GetInstanceMonitorArray. +type GetInstanceMonitorArray = []GetInstanceMonitorElement + +// GetInstanceMonitorElement defines model for GetInstanceMonitorElement. +type GetInstanceMonitorElement struct { + Data InstanceMonitor `json:"data"` + Meta InstanceMeta `json:"meta"` +} + // GetInstanceStatusArray defines model for GetInstanceStatusArray. type GetInstanceStatusArray = []GetInstanceStatusElement @@ -216,35 +259,20 @@ type GetInstanceStatusElement struct { Meta InstanceMeta `json:"meta"` } +// InstanceConfig defines model for InstanceConfig. +type InstanceConfig = instance.Config + // InstanceMeta defines model for InstanceMeta. type InstanceMeta struct { Node string `json:"node"` Object string `json:"object"` } +// InstanceMonitor defines model for InstanceMonitor. +type InstanceMonitor = instance.Monitor + // InstanceStatus defines model for InstanceStatus. -type InstanceStatus struct { - Avail Status `json:"avail"` - Constraints bool `json:"constraints"` - Csum string `json:"csum"` - FrozenAt time.Time `json:"frozen_at"` - LastStartedAt time.Time `json:"last_started_at"` - Optional Status `json:"optional"` - Overall Status `json:"overall"` - - // Preserved preserve is true if this status has not been updated due to a - // heartbeat downtime covered by a maintenance period. - // when the maintenance period ends, the status should be unchanged, - // and preserve will be set to false. - Preserved bool `json:"preserved"` - - // Provisioned service, instance or resource provisioned state - Provisioned Provisioned `json:"provisioned"` - Resources []ResourceExposedStatus `json:"resources"` - Running []string `json:"running"` - Scale int `json:"scale"` - UpdatedAt time.Time `json:"updated_at"` -} +type InstanceStatus = instance.Status // LogList responseLogList is a list of sse type LogList = openapi_types.File @@ -322,6 +350,12 @@ type ObjectFile struct { // ObjectPaths defines model for ObjectPaths. type ObjectPaths = []string +// Orchestrate defines model for Orchestrate. +type Orchestrate string + +// Placement object placement policy +type Placement string + // PoolStatus defines model for PoolStatus. type PoolStatus struct { Capabilities *[]string `json:"capabilities,omitempty"` @@ -477,6 +511,9 @@ type RelayMessages struct { Messages RelayMessageList `json:"messages"` } +// ResourceConfig defines model for ResourceConfig. +type ResourceConfig = instance.ResourceConfig + // ResourceExposedStatus defines model for ResourceExposedStatus. type ResourceExposedStatus struct { // Disable hints the resource ignores all state transition actions @@ -533,6 +570,9 @@ type ResourceProvisionStatus struct { State Provisioned `json:"state"` } +// ResourcesConfig defines model for ResourcesConfig. +type ResourcesConfig = []ResourceConfig + // Role defines model for Role. type Role string @@ -566,6 +606,15 @@ type SANPathTarget struct { // Status defines model for Status. type Status string +// SubsetConfig defines model for SubsetConfig. +type SubsetConfig = instance.SubsetConfig + +// SubsetsConfig defines model for SubsetsConfig. +type SubsetsConfig = []SubsetConfig + +// Topology object topology +type Topology string + // DRBDConfigName defines model for DRBDConfigName. type DRBDConfigName = string @@ -677,6 +726,24 @@ type GetDaemonStatusParams struct { Selector *SelectorOptional `form:"selector,omitempty" json:"selector,omitempty"` } +// GetInstanceConfigParams defines parameters for GetInstanceConfig. +type GetInstanceConfigParams struct { + // Path object selector expression. + Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` + + // Node object and instance selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` +} + +// GetInstanceMonitorParams defines parameters for GetInstanceMonitor. +type GetInstanceMonitorParams struct { + // Path object selector expression. + Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` + + // Node object and instance selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` +} + // GetInstanceStatusParams defines parameters for GetInstanceStatus. type GetInstanceStatusParams struct { // Path object selector expression. diff --git a/daemon/daemonapi/get_instance_config.go b/daemon/daemonapi/get_instance_config.go new file mode 100644 index 000000000..ce91e893a --- /dev/null +++ b/daemon/daemonapi/get_instance_config.go @@ -0,0 +1,42 @@ +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/daemon/api" +) + +func (a *DaemonApi) GetInstanceConfig(ctx echo.Context, params api.GetInstanceConfigParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + Path: params.Path, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + data := instance.ConfigData.GetAll() + l := make(api.GetInstanceConfigArray, 0) + for _, e := range data { + if !meta.HasPath(e.Path.String()) { + continue + } + if !meta.HasNode(e.Node) { + continue + } + d := api.GetInstanceConfigElement{ + Meta: api.InstanceMeta{ + Node: e.Node, + Object: e.Path.String(), + }, + Data: api.InstanceConfig(*e.Value), + } + l = append(l, d) + } + return ctx.JSON(http.StatusOK, l) +} diff --git a/daemon/daemonapi/get_instance_monitor.go b/daemon/daemonapi/get_instance_monitor.go new file mode 100644 index 000000000..29a05a5c8 --- /dev/null +++ b/daemon/daemonapi/get_instance_monitor.go @@ -0,0 +1,43 @@ +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/daemon/api" +) + +// GetNetworks returns network status list. +func (a *DaemonApi) GetInstanceMonitor(ctx echo.Context, params api.GetInstanceMonitorParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + Path: params.Path, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + data := instance.MonitorData.GetAll() + l := make(api.GetInstanceMonitorArray, 0) + for _, e := range data { + if !meta.HasPath(e.Path.String()) { + continue + } + if !meta.HasNode(e.Node) { + continue + } + d := api.GetInstanceMonitorElement{ + Meta: api.InstanceMeta{ + Node: e.Node, + Object: e.Path.String(), + }, + Data: api.InstanceMonitor(*e.Value), + } + l = append(l, d) + } + return ctx.JSON(http.StatusOK, l) +} diff --git a/daemon/daemonapi/get_instance_status.go b/daemon/daemonapi/get_instance_status.go index 256186ce0..5088b2f73 100644 --- a/daemon/daemonapi/get_instance_status.go +++ b/daemon/daemonapi/get_instance_status.go @@ -35,62 +35,8 @@ func (a *DaemonApi) GetInstanceStatus(ctx echo.Context, params api.GetInstanceSt Node: e.Node, Object: e.Path.String(), }, - Data: api.InstanceStatus{ - Avail: api.Status(e.Value.Avail.String()), - Constraints: e.Value.Constraints, - FrozenAt: e.Value.FrozenAt, - LastStartedAt: e.Value.LastStartedAt, - Optional: api.Status(e.Value.Optional.String()), - Overall: api.Status(e.Value.Overall.String()), - Provisioned: api.Provisioned(e.Value.Provisioned.String()), - }, - } - - running := make([]string, len(e.Value.Running)) - for i, d := range e.Value.Running { - running[i] = d - } - d.Data.Running = running - - resources := make([]api.ResourceExposedStatus, len(e.Value.Resources)) - for i, d := range e.Value.Resources { - info := make(map[string]any) - for i, d := range d.Info { - info[i] = d - } - log := make(api.ResourceLog, 0) - for _, d := range d.Log { - if d == nil { - continue - } - log = append(log, api.ResourceLogEntry{ - Level: string(d.Level), - Message: d.Message, - }) - } - nd := api.ResourceExposedStatus{ - Disable: bool(d.Disable), - Encap: bool(d.Encap), - Info: info, - Label: d.Label, - Log: log, - Monitor: bool(d.Monitor), - Optional: bool(d.Optional), - Provisioned: api.ResourceProvisionStatus{ - State: api.Provisioned(d.Provisioned.State.String()), - Mtime: d.Provisioned.Mtime, - }, - Restart: int(d.Restart), - Rid: d.Rid, - Standby: bool(d.Standby), - Status: api.Status(d.Status.String()), - Subset: d.Subset, - Tags: append([]string{}, d.Tags...), - Type: d.Type, - } - resources[i] = nd + Data: api.InstanceStatus(*e.Value), } - d.Data.Resources = resources l = append(l, d) } return ctx.JSON(http.StatusOK, l) diff --git a/daemon/daemonapi/post_instance_status.go b/daemon/daemonapi/post_instance_status.go index f120b088b..288664294 100644 --- a/daemon/daemonapi/post_instance_status.go +++ b/daemon/daemonapi/post_instance_status.go @@ -5,12 +5,7 @@ import ( "github.com/labstack/echo/v4" - "github.com/opensvc/om3/core/instance" "github.com/opensvc/om3/core/path" - "github.com/opensvc/om3/core/provisioned" - "github.com/opensvc/om3/core/resource" - "github.com/opensvc/om3/core/resourceid" - "github.com/opensvc/om3/core/status" "github.com/opensvc/om3/daemon/api" "github.com/opensvc/om3/daemon/msgbus" "github.com/opensvc/om3/util/hostname" @@ -34,78 +29,10 @@ func (a *DaemonApi) PostInstanceStatus(ctx echo.Context) error { log.Warn().Err(err).Msgf("can't parse path: %s", payload.Path) return JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "Error parsing path '%s': %s", payload.Path, err) } - instanceStatus, err := postInstanceStatusToInstanceStatus(payload) - if err != nil { - log.Warn().Err(err).Msgf("Error transtyping instance status: %#v", payload) - return JSONProblemf(ctx, http.StatusBadRequest, "Error transtyping instance status", "%s", err) - } localhost := hostname.Hostname() - a.EventBus.Pub(&msgbus.InstanceStatusPost{Path: p, Node: localhost, Value: *instanceStatus}, + a.EventBus.Pub(&msgbus.InstanceStatusPost{Path: p, Node: localhost, Value: payload.Status}, pubsub.Label{"path", payload.Path}, pubsub.Label{"node", localhost}, ) return ctx.JSON(http.StatusOK, nil) } - -func postInstanceStatusToInstanceStatus(payload api.PostInstanceStatus) (*instance.Status, error) { - payloadStatus := payload.Status - instanceStatus := instance.Status{ - Avail: status.Parse(string(payloadStatus.Avail)), - FrozenAt: payloadStatus.FrozenAt, - Overall: status.Parse(string(payloadStatus.Overall)), - UpdatedAt: payloadStatus.UpdatedAt, - LastStartedAt: payloadStatus.LastStartedAt, - } - instanceStatus.Constraints = payloadStatus.Constraints - instanceStatus.Optional = status.Parse(string(payloadStatus.Optional)) - if prov, err := provisioned.NewFromString(string(payloadStatus.Provisioned)); err != nil { - return nil, err - } else { - instanceStatus.Provisioned = prov - } - resources := make([]resource.ExposedStatus, 0) - for _, v := range payloadStatus.Resources { - exposed := resource.ExposedStatus{ - Rid: v.Rid, - Label: v.Label, - Status: status.Parse(string(v.Status)), - Type: v.Type, - } - exposed.Disable = resource.DisableFlag(v.Disable) - exposed.Encap = resource.EncapFlag(v.Encap) - info := make(map[string]interface{}) - for n, value := range v.Info { - info[n] = value - } - exposed.Info = info - l := make([]*resource.StatusLogEntry, 0) - for _, logEntry := range v.Log { - l = append(l, &resource.StatusLogEntry{ - Level: resource.Level(logEntry.Level), - Message: logEntry.Message, - }) - } - exposed.Log = l - exposed.Monitor = resource.MonitorFlag(v.Monitor) - exposed.Optional = resource.OptionalFlag(v.Optional) - resProv := resource.ProvisionStatus{} - if provState, err := provisioned.NewFromString(string(v.Provisioned.State)); err != nil { - return nil, err - } else { - resProv.State = provState - } - resProv.Mtime = v.Provisioned.Mtime - exposed.Provisioned = resProv - exposed.Restart = resource.RestartFlag(v.Restart) - if rid, err := resourceid.Parse(v.Rid); err == nil { - exposed.ResourceID = rid - } - exposed.Standby = resource.StandbyFlag(v.Standby) - exposed.Subset = v.Subset - exposed.Tags = append([]string{}, v.Tags...) - resources = append(resources, exposed) - } - instanceStatus.Resources = resources - instanceStatus.Running = append([]string{}, payloadStatus.Running...) - return &instanceStatus, nil -} From 30590d72d2de1a1913b3de5d605baf5c683b0abe Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 1 Sep 2023 19:58:06 +0200 Subject: [PATCH 02/30] api tidying * Rename api.GetInstance*Element to api.Instance*Item * Use api.InstanceStatusItem in the PostInstanceStatus handler, so the POST and GET /instance/status use the same body format * Make PostInstanceStatus verify the emitter node is the localhost --- core/object/core_status.go | 10 +- daemon/api/api.yaml | 26 +-- daemon/api/codegen_client_gen.go | 12 +- daemon/api/codegen_server_gen.go | 219 +++++++++++------------ daemon/api/codegen_type_gen.go | 58 +++--- daemon/daemonapi/get_instance_config.go | 4 +- daemon/daemonapi/get_instance_monitor.go | 4 +- daemon/daemonapi/get_instance_status.go | 4 +- daemon/daemonapi/post_instance_status.go | 24 ++- 9 files changed, 183 insertions(+), 178 deletions(-) diff --git a/core/object/core_status.go b/core/object/core_status.go index 3c345fa1d..7f0ce9996 100644 --- a/core/object/core_status.go +++ b/core/object/core_status.go @@ -15,6 +15,7 @@ import ( "github.com/opensvc/om3/core/status" "github.com/opensvc/om3/daemon/api" "github.com/opensvc/om3/util/file" + "github.com/opensvc/om3/util/hostname" ) func (t *core) statusFile() string { @@ -124,9 +125,12 @@ func (t *core) postInstanceStatus(data instance.Status) error { if c, err := client.New(); err != nil { return err } else { - body := api.PostInstanceStatus{ - Path: t.path.String(), - Status: instanceStatus, + body := api.InstanceStatusItem{ + Meta: api.InstanceMeta{ + Object: t.path.String(), + Node: hostname.Hostname(), + }, + Data: instanceStatus, } resp, err := c.PostInstanceStatusWithResponse(context.Background(), body) if err != nil { diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index 1fa8e4d75..e3bfe05fa 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -282,7 +282,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/GetInstanceConfigArray' + $ref: '#/components/schemas/InstanceConfigArray' 400: $ref: '#/components/responses/400' 401: @@ -308,7 +308,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/GetInstanceMonitorArray' + $ref: '#/components/schemas/InstanceMonitorArray' 400: $ref: '#/components/responses/400' 401: @@ -334,7 +334,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/GetInstanceStatusArray' + $ref: '#/components/schemas/InstanceStatusArray' 400: $ref: '#/components/responses/400' 401: @@ -356,7 +356,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PostInstanceStatus' + $ref: '#/components/schemas/InstanceStatusItem' responses: 200: description: OK @@ -2026,11 +2026,11 @@ components: type: string is_partial: type: boolean - GetInstanceConfigArray: + InstanceConfigArray: type: array items: - $ref: '#/components/schemas/GetInstanceConfigElement' - GetInstanceConfigElement: + $ref: '#/components/schemas/InstanceConfigItem' + InstanceConfigItem: type: object required: - meta @@ -2040,11 +2040,11 @@ components: $ref: '#/components/schemas/InstanceMeta' data: $ref: '#/components/schemas/InstanceConfig' - GetInstanceMonitorArray: + InstanceMonitorArray: type: array items: - $ref: '#/components/schemas/GetInstanceMonitorElement' - GetInstanceMonitorElement: + $ref: '#/components/schemas/InstanceMonitorItem' + InstanceMonitorItem: type: object required: - meta @@ -2054,11 +2054,11 @@ components: $ref: '#/components/schemas/InstanceMeta' data: $ref: '#/components/schemas/InstanceMonitor' - GetInstanceStatusArray: + InstanceStatusArray: type: array items: - $ref: '#/components/schemas/GetInstanceStatusElement' - GetInstanceStatusElement: + $ref: '#/components/schemas/InstanceStatusItem' + InstanceStatusItem: type: object required: - meta diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index 8c8c10f11..84ed08eb3 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -3686,7 +3686,7 @@ func (r PostDaemonSubActionResponse) StatusCode() int { type GetInstanceConfigResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *GetInstanceConfigArray + JSON200 *InstanceConfigArray JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -3712,7 +3712,7 @@ func (r GetInstanceConfigResponse) StatusCode() int { type GetInstanceMonitorResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *GetInstanceMonitorArray + JSON200 *InstanceMonitorArray JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -3738,7 +3738,7 @@ func (r GetInstanceMonitorResponse) StatusCode() int { type GetInstanceStatusResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *GetInstanceStatusArray + JSON200 *InstanceStatusArray JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -5683,7 +5683,7 @@ func ParseGetInstanceConfigResponse(rsp *http.Response) (*GetInstanceConfigRespo switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest GetInstanceConfigArray + var dest InstanceConfigArray if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -5737,7 +5737,7 @@ func ParseGetInstanceMonitorResponse(rsp *http.Response) (*GetInstanceMonitorRes switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest GetInstanceMonitorArray + var dest InstanceMonitorArray if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -5791,7 +5791,7 @@ func ParseGetInstanceStatusResponse(rsp *http.Response) (*GetInstanceStatusRespo switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest GetInstanceStatusArray + var dest InstanceStatusArray if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index a8ed98911..4916f2bb4 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -1134,116 +1134,115 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "Ja+v/z8AAP//SZLHr9XDAAA=", + "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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 8e63ebfb2..676513506 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -232,36 +232,18 @@ type DaemonSubsystemStatus struct { // EventList responseEventList is a list of sse type EventList = openapi_types.File -// GetInstanceConfigArray defines model for GetInstanceConfigArray. -type GetInstanceConfigArray = []GetInstanceConfigElement - -// GetInstanceConfigElement defines model for GetInstanceConfigElement. -type GetInstanceConfigElement struct { - Data InstanceConfig `json:"data"` - Meta InstanceMeta `json:"meta"` -} - -// GetInstanceMonitorArray defines model for GetInstanceMonitorArray. -type GetInstanceMonitorArray = []GetInstanceMonitorElement - -// GetInstanceMonitorElement defines model for GetInstanceMonitorElement. -type GetInstanceMonitorElement struct { - Data InstanceMonitor `json:"data"` - Meta InstanceMeta `json:"meta"` -} +// InstanceConfig defines model for InstanceConfig. +type InstanceConfig = instance.Config -// GetInstanceStatusArray defines model for GetInstanceStatusArray. -type GetInstanceStatusArray = []GetInstanceStatusElement +// InstanceConfigArray defines model for InstanceConfigArray. +type InstanceConfigArray = []InstanceConfigItem -// GetInstanceStatusElement defines model for GetInstanceStatusElement. -type GetInstanceStatusElement struct { - Data InstanceStatus `json:"data"` +// InstanceConfigItem defines model for InstanceConfigItem. +type InstanceConfigItem struct { + Data InstanceConfig `json:"data"` Meta InstanceMeta `json:"meta"` } -// InstanceConfig defines model for InstanceConfig. -type InstanceConfig = instance.Config - // InstanceMeta defines model for InstanceMeta. type InstanceMeta struct { Node string `json:"node"` @@ -271,9 +253,27 @@ type InstanceMeta struct { // InstanceMonitor defines model for InstanceMonitor. type InstanceMonitor = instance.Monitor +// InstanceMonitorArray defines model for InstanceMonitorArray. +type InstanceMonitorArray = []InstanceMonitorItem + +// InstanceMonitorItem defines model for InstanceMonitorItem. +type InstanceMonitorItem struct { + Data InstanceMonitor `json:"data"` + Meta InstanceMeta `json:"meta"` +} + // InstanceStatus defines model for InstanceStatus. type InstanceStatus = instance.Status +// InstanceStatusArray defines model for InstanceStatusArray. +type InstanceStatusArray = []InstanceStatusItem + +// InstanceStatusItem defines model for InstanceStatusItem. +type InstanceStatusItem struct { + Data InstanceStatus `json:"data"` + Meta InstanceMeta `json:"meta"` +} + // LogList responseLogList is a list of sse type LogList = openapi_types.File @@ -409,12 +409,6 @@ type PostDaemonSubAction struct { // PostDaemonSubActionAction defines model for PostDaemonSubAction.Action. type PostDaemonSubActionAction string -// PostInstanceStatus defines model for PostInstanceStatus. -type PostInstanceStatus struct { - Path string `json:"path"` - Status InstanceStatus `json:"status"` -} - // PostNodeDRBDConfigRequest defines model for PostNodeDRBDConfigRequest. type PostNodeDRBDConfigRequest struct { AllocationId openapi_types.UUID `json:"allocation_id"` @@ -853,7 +847,7 @@ type PostDaemonLogsControlJSONRequestBody = PostDaemonLogsControl type PostDaemonSubActionJSONRequestBody = PostDaemonSubAction // PostInstanceStatusJSONRequestBody defines body for PostInstanceStatus for application/json ContentType. -type PostInstanceStatusJSONRequestBody = PostInstanceStatus +type PostInstanceStatusJSONRequestBody = InstanceStatusItem // PostNodeDRBDConfigJSONRequestBody defines body for PostNodeDRBDConfig for application/json ContentType. type PostNodeDRBDConfigJSONRequestBody = PostNodeDRBDConfigRequest diff --git a/daemon/daemonapi/get_instance_config.go b/daemon/daemonapi/get_instance_config.go index ce91e893a..e35300b01 100644 --- a/daemon/daemonapi/get_instance_config.go +++ b/daemon/daemonapi/get_instance_config.go @@ -21,7 +21,7 @@ func (a *DaemonApi) GetInstanceConfig(ctx echo.Context, params api.GetInstanceCo return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") } data := instance.ConfigData.GetAll() - l := make(api.GetInstanceConfigArray, 0) + l := make(api.InstanceConfigArray, 0) for _, e := range data { if !meta.HasPath(e.Path.String()) { continue @@ -29,7 +29,7 @@ func (a *DaemonApi) GetInstanceConfig(ctx echo.Context, params api.GetInstanceCo if !meta.HasNode(e.Node) { continue } - d := api.GetInstanceConfigElement{ + d := api.InstanceConfigItem{ Meta: api.InstanceMeta{ Node: e.Node, Object: e.Path.String(), diff --git a/daemon/daemonapi/get_instance_monitor.go b/daemon/daemonapi/get_instance_monitor.go index 29a05a5c8..7d7027ca0 100644 --- a/daemon/daemonapi/get_instance_monitor.go +++ b/daemon/daemonapi/get_instance_monitor.go @@ -22,7 +22,7 @@ func (a *DaemonApi) GetInstanceMonitor(ctx echo.Context, params api.GetInstanceM return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") } data := instance.MonitorData.GetAll() - l := make(api.GetInstanceMonitorArray, 0) + l := make(api.InstanceMonitorArray, 0) for _, e := range data { if !meta.HasPath(e.Path.String()) { continue @@ -30,7 +30,7 @@ func (a *DaemonApi) GetInstanceMonitor(ctx echo.Context, params api.GetInstanceM if !meta.HasNode(e.Node) { continue } - d := api.GetInstanceMonitorElement{ + d := api.InstanceMonitorItem{ Meta: api.InstanceMeta{ Node: e.Node, Object: e.Path.String(), diff --git a/daemon/daemonapi/get_instance_status.go b/daemon/daemonapi/get_instance_status.go index 5088b2f73..19f11d162 100644 --- a/daemon/daemonapi/get_instance_status.go +++ b/daemon/daemonapi/get_instance_status.go @@ -22,7 +22,7 @@ func (a *DaemonApi) GetInstanceStatus(ctx echo.Context, params api.GetInstanceSt return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") } data := instance.StatusData.GetAll() - l := make(api.GetInstanceStatusArray, 0) + l := make(api.InstanceStatusArray, 0) for _, e := range data { if !meta.HasPath(e.Path.String()) { continue @@ -30,7 +30,7 @@ func (a *DaemonApi) GetInstanceStatus(ctx echo.Context, params api.GetInstanceSt if !meta.HasNode(e.Node) { continue } - d := api.GetInstanceStatusElement{ + d := api.InstanceStatusItem{ Meta: api.InstanceMeta{ Node: e.Node, Object: e.Path.String(), diff --git a/daemon/daemonapi/post_instance_status.go b/daemon/daemonapi/post_instance_status.go index 288664294..f45e4fda4 100644 --- a/daemon/daemonapi/post_instance_status.go +++ b/daemon/daemonapi/post_instance_status.go @@ -1,6 +1,7 @@ package daemonapi import ( + "fmt" "net/http" "github.com/labstack/echo/v4" @@ -16,23 +17,30 @@ func (a *DaemonApi) PostInstanceStatus(ctx echo.Context) error { var ( err error p path.T - payload api.PostInstanceStatus + payload api.InstanceStatusItem ) log := LogHandler(ctx, "PostInstanceStatus") log.Debug().Msgf("starting") if err := ctx.Bind(&payload); err != nil { log.Warn().Err(err).Msgf("decode body") - return JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "%s", err) + _ = JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "%s", err) + return err } - p, err = path.Parse(payload.Path) + p, err = path.Parse(payload.Meta.Object) if err != nil { - log.Warn().Err(err).Msgf("can't parse path: %s", payload.Path) - return JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "Error parsing path '%s': %s", payload.Path, err) + log.Warn().Err(err).Msgf("can't parse path: %s", payload.Meta.Object) + _ = JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "Error parsing path '%s': %s", payload.Meta.Object, err) + return err } localhost := hostname.Hostname() - a.EventBus.Pub(&msgbus.InstanceStatusPost{Path: p, Node: localhost, Value: payload.Status}, - pubsub.Label{"path", payload.Path}, - pubsub.Label{"node", localhost}, + if payload.Meta.Node != localhost { + err := fmt.Errorf("meta node is %s: expecting %s", payload.Meta.Node, localhost) + _ = JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "%s", err) + return err + } + a.EventBus.Pub(&msgbus.InstanceStatusPost{Path: p, Node: payload.Meta.Node, Value: payload.Data}, + pubsub.Label{"path", payload.Meta.Object}, + pubsub.Label{"node", payload.Meta.Node}, ) return ctx.JSON(http.StatusOK, nil) } From a67daf133cf21f1aae14261eddbfeb804a040e50 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 1 Sep 2023 20:52:55 +0200 Subject: [PATCH 03/30] Rename Preserved to IsPreserved --- core/cluster/frame_instance.go | 2 +- core/instance/monitor.go | 2 +- daemon/api/api.yaml | 8 +- daemon/api/codegen_server_gen.go | 154 +++++++++++++++---------------- 4 files changed, 83 insertions(+), 83 deletions(-) diff --git a/core/cluster/frame_instance.go b/core/cluster/frame_instance.go index e9d928dc5..e6616fe96 100644 --- a/core/cluster/frame_instance.go +++ b/core/cluster/frame_instance.go @@ -40,7 +40,7 @@ func (f Frame) sObjectInstance(path string, node string, scope []string) string } func sObjectInstanceAvail(objectAvail status.T, instance instance.Status, mon instance.Monitor) string { - if mon.Preserved { + if mon.IsPreserved { return iconPreserved } switch instance.Avail { diff --git a/core/instance/monitor.go b/core/instance/monitor.go index a2a2ef2c5..8d67f15e0 100644 --- a/core/instance/monitor.go +++ b/core/instance/monitor.go @@ -43,7 +43,7 @@ type ( State MonitorState `json:"state" yaml:"state"` StateUpdatedAt time.Time `json:"state_updated_at" yaml:"state_updated_at"` MonitorActionExecutedAt time.Time `json:"monitor_action_executed_at" yaml:"monitor_action_executed_at"` - Preserved bool `json:"preserved" yaml:"preserved"` + IsPreserved bool `json:"preserved" yaml:"preserved"` Resources ResourceMonitorMap `json:"resources,omitempty" yaml:"resources,omitempty"` UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index e3bfe05fa..84d9c373d 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -1607,7 +1607,7 @@ components: - state - state_updated_at - monitor_action_executed_at - - preserved + - is_preserved - resources - updated_at - parents @@ -1643,7 +1643,7 @@ components: monitor_action_executed_at: type: string format: date-time - preserved: + is_preserved: type: boolean resources: type: array @@ -1669,7 +1669,7 @@ components: - last_started_at - optional - overall - - preserved + - is_preserved - provisioned - resources - running @@ -1693,7 +1693,7 @@ components: $ref: '#/components/schemas/Status' overall: $ref: '#/components/schemas/Status' - preserved: + is_preserved: type: boolean description: | preserve is true if this status has not been updated due to a diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index 4916f2bb4..65a683cc3 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -1166,83 +1166,83 @@ var swaggerSpec = []string{ "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", } // GetSwagger returns the content of the embedded swagger specification file From a8e805ff911f07bb051e8857a19066ff07a0ea3b Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Sat, 2 Sep 2023 10:57:05 +0200 Subject: [PATCH 04/30] Add the GET /instance api handler Example: $ curl -X GET 'https://localhost:1215/instance?path=foo001' -H 'accept: application/json' -H 'Authorization: Basic ..' -k -s |jq [ { "data": { "config": { "app": "default", "csum": "80e572a36f85f34823211913bce56059", "children": [ "foo010", "foo011", "foo012", "foo013", "foo014@dev2n1", "notexist" ], "orchestrate": "ha", "placement_policy": "last start", "priority": 50, "resources": { "fs#1": { "is_disabled": false, "is_monitored": false, "is_standby": false, "restart": 0, "restart_delay": 500000000 }, "volume#1": { "is_disabled": false, "is_monitored": false, "is_standby": false, "restart": 0, "restart_delay": 500000000 }, "volume#2": { "is_disabled": false, "is_monitored": false, "is_standby": false, "restart": 0, "restart_delay": 500000000 }, "volume#3": { "is_disabled": false, "is_monitored": false, "is_standby": false, "restart": 0, "restart_delay": 500000000 } }, "scope": [ "dev2n1", "dev2n2", "dev2n3" ], "subsets": {}, "topology": "failover", "updated_at": "2023-08-23T08:20:50.605710559+02:00" }, "monitor": { "global_expect": "none", "global_expect_updated_at": "0001-01-01T00:00:00Z", "global_expect_options": null, "is_leader": false, "is_ha_leader": false, "local_expect": "started", "local_expect_updated_at": "2023-09-02T10:55:54.246600548+02:00", "orchestration_id": "00000000-0000-0000-0000-000000000000", "orchestration_is_done": false, "session_id": "00000000-0000-0000-0000-000000000000", "state": "idle", "state_updated_at": "2023-09-02T10:55:51.397889345+02:00", "monitor_action_executed_at": "0001-01-01T00:00:00Z", "preserved": false, "resources": { "fs#1": { "restart": { "remaining": 0, "last_at": "0001-01-01T00:00:00Z" } }, "volume#1": { "restart": { "remaining": 0, "last_at": "0001-01-01T00:00:00Z" } }, "volume#2": { "restart": { "remaining": 0, "last_at": "0001-01-01T00:00:00Z" } }, "volume#3": { "restart": { "remaining": 0, "last_at": "0001-01-01T00:00:00Z" } } }, "updated_at": "2023-09-02T10:55:54.246628287+02:00", "children": { "foo010": "up", "foo011": "up", "foo012": "undef", "foo013": "up", "foo014@dev2n1": "up", "notexist": "undef" } }, "status": { "avail": "up", "frozen_at": "0001-01-01T00:00:00Z", "last_started_at": "2023-08-25T19:35:47.633870082+02:00", "overall": "up", "provisioned": "true", "resources": [ { "rid": "volume#1", "label": "foo001-vol-1", "status": "up", "type": "volume", "provisioned": { "mtime": "2023-07-06T10:03:25.231284828+02:00", "state": "true" } }, { "rid": "volume#2", "label": "foo001-vol-2", "status": "up", "type": "volume", "provisioned": { "mtime": "2023-07-06T10:03:30.127315837+02:00", "state": "true" } }, { "rid": "volume#3", "label": "foo001-vol-3", "status": "up", "type": "volume", "provisioned": { "mtime": "2023-07-06T10:03:35.211348039+02:00", "state": "true" } }, { "rid": "fs#1", "label": "flag /dev/shm/opensvc/svc/foo001/fs#1.flag", "status": "up", "type": "fs.flag", "provisioned": { "mtime": "2023-07-06T10:03:35.543350141+02:00", "state": "true" } } ], "updated_at": "2023-09-02T10:55:51.574173407+02:00" } }, "meta": { "node": "dev2n1", "object": "foo001" } }, ... --- daemon/api/api.yaml | 49 ++++++ daemon/api/codegen_client_gen.go | 170 +++++++++++++++++++++ daemon/api/codegen_server_gen.go | 252 ++++++++++++++++++------------- daemon/api/codegen_type_gen.go | 25 +++ daemon/daemonapi/get_instance.go | 48 ++++++ 5 files changed, 435 insertions(+), 109 deletions(-) create mode 100644 daemon/daemonapi/get_instance.go diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index 84d9c373d..6e43b2896 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -265,6 +265,32 @@ paths: $ref: '#/components/responses/403' 500: $ref: '#/components/responses/500' + /instance: + get: + operationId: GetInstance + tags: + - instance + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/PathOptional' + - $ref: '#/components/parameters/NodeOptional' + responses: + 200: + description: get instance config, monitor and status + content: + application/json: + schema: + $ref: '#/components/schemas/InstanceArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' /instance/config: get: operationId: GetInstanceConfig @@ -2026,6 +2052,29 @@ components: type: string is_partial: type: boolean + Instance: + type: object + properties: + config: + $ref: '#/components/schemas/InstanceConfig' + monitor: + $ref: '#/components/schemas/InstanceMonitor' + status: + $ref: '#/components/schemas/InstanceStatus' + InstanceArray: + type: array + items: + $ref: '#/components/schemas/InstanceItem' + InstanceItem: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/InstanceMeta' + data: + $ref: '#/components/schemas/Instance' InstanceConfigArray: type: array items: diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index 84ed08eb3..04b051a16 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -123,6 +123,9 @@ type ClientInterface interface { PostDaemonSubAction(ctx context.Context, body PostDaemonSubActionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetInstance request + GetInstance(ctx context.Context, params *GetInstanceParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetInstanceConfig request GetInstanceConfig(ctx context.Context, params *GetInstanceConfigParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -417,6 +420,18 @@ func (c *Client) PostDaemonSubAction(ctx context.Context, body PostDaemonSubActi return c.Client.Do(req) } +func (c *Client) GetInstance(ctx context.Context, params *GetInstanceParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetInstanceRequest(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) GetInstanceConfig(ctx context.Context, params *GetInstanceConfigParams, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetInstanceConfigRequest(c.Server, params) if err != nil { @@ -1541,6 +1556,69 @@ func NewPostDaemonSubActionRequestWithBody(server string, contentType string, bo return req, nil } +// NewGetInstanceRequest generates requests for GetInstance +func NewGetInstanceRequest(server string, params *GetInstanceParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/instance") + 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) + } + } + } + + } + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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 +} + // NewGetInstanceConfigRequest generates requests for GetInstanceConfig func NewGetInstanceConfigRequest(server string, params *GetInstanceConfigParams) (*http.Request, error) { var err error @@ -3288,6 +3366,9 @@ type ClientWithResponsesInterface interface { PostDaemonSubActionWithResponse(ctx context.Context, body PostDaemonSubActionJSONRequestBody, reqEditors ...RequestEditorFn) (*PostDaemonSubActionResponse, error) + // GetInstance request + GetInstanceWithResponse(ctx context.Context, params *GetInstanceParams, reqEditors ...RequestEditorFn) (*GetInstanceResponse, error) + // GetInstanceConfig request GetInstanceConfigWithResponse(ctx context.Context, params *GetInstanceConfigParams, reqEditors ...RequestEditorFn) (*GetInstanceConfigResponse, error) @@ -3683,6 +3764,32 @@ func (r PostDaemonSubActionResponse) StatusCode() int { return 0 } +type GetInstanceResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *InstanceArray + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetInstanceResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetInstanceResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type GetInstanceConfigResponse struct { Body []byte HTTPResponse *http.Response @@ -4751,6 +4858,15 @@ func (c *ClientWithResponses) PostDaemonSubActionWithResponse(ctx context.Contex return ParsePostDaemonSubActionResponse(rsp) } +// GetInstanceWithResponse request returning *GetInstanceResponse +func (c *ClientWithResponses) GetInstanceWithResponse(ctx context.Context, params *GetInstanceParams, reqEditors ...RequestEditorFn) (*GetInstanceResponse, error) { + rsp, err := c.GetInstance(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetInstanceResponse(rsp) +} + // GetInstanceConfigWithResponse request returning *GetInstanceConfigResponse func (c *ClientWithResponses) GetInstanceConfigWithResponse(ctx context.Context, params *GetInstanceConfigParams, reqEditors ...RequestEditorFn) (*GetInstanceConfigResponse, error) { rsp, err := c.GetInstanceConfig(ctx, params, reqEditors...) @@ -5668,6 +5784,60 @@ func ParsePostDaemonSubActionResponse(rsp *http.Response) (*PostDaemonSubActionR return response, nil } +// ParseGetInstanceResponse parses an HTTP response from a GetInstanceWithResponse call +func ParseGetInstanceResponse(rsp *http.Response) (*GetInstanceResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetInstanceResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest InstanceArray + 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 +} + // ParseGetInstanceConfigResponse parses an HTTP response from a GetInstanceConfigWithResponse call func ParseGetInstanceConfigResponse(rsp *http.Response) (*GetInstanceConfigResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index 65a683cc3..19d053beb 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -51,6 +51,9 @@ type ServerInterface interface { // (POST /daemon/sub/action) PostDaemonSubAction(ctx echo.Context) error + // (GET /instance) + GetInstance(ctx echo.Context, params GetInstanceParams) error + // (GET /instance/config) GetInstanceConfig(ctx echo.Context, params GetInstanceConfigParams) error @@ -371,6 +374,35 @@ func (w *ServerInterfaceWrapper) PostDaemonSubAction(ctx echo.Context) error { return err } +// GetInstance converts echo context to params. +func (w *ServerInterfaceWrapper) GetInstance(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 GetInstanceParams + // ------------- 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)) + } + + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetInstance(ctx, params) + return err +} + // GetInstanceConfig converts echo context to params. func (w *ServerInterfaceWrapper) GetInstanceConfig(ctx echo.Context) error { var err error @@ -1091,6 +1123,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/daemon/status", wrapper.GetDaemonStatus) router.POST(baseURL+"/daemon/stop", wrapper.PostDaemonStop) router.POST(baseURL+"/daemon/sub/action", wrapper.PostDaemonSubAction) + router.GET(baseURL+"/instance", wrapper.GetInstance) router.GET(baseURL+"/instance/config", wrapper.GetInstanceConfig) router.GET(baseURL+"/instance/monitor", wrapper.GetInstanceMonitor) router.GET(baseURL+"/instance/status", wrapper.GetInstanceStatus) @@ -1134,115 +1167,116 @@ 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 676513506..4367a4d94 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -232,6 +232,16 @@ type DaemonSubsystemStatus struct { // EventList responseEventList is a list of sse type EventList = openapi_types.File +// Instance defines model for Instance. +type Instance struct { + Config *InstanceConfig `json:"config,omitempty"` + Monitor *InstanceMonitor `json:"monitor,omitempty"` + Status *InstanceStatus `json:"status,omitempty"` +} + +// InstanceArray defines model for InstanceArray. +type InstanceArray = []InstanceItem + // InstanceConfig defines model for InstanceConfig. type InstanceConfig = instance.Config @@ -244,6 +254,12 @@ type InstanceConfigItem struct { Meta InstanceMeta `json:"meta"` } +// InstanceItem defines model for InstanceItem. +type InstanceItem struct { + Data Instance `json:"data"` + Meta InstanceMeta `json:"meta"` +} + // InstanceMeta defines model for InstanceMeta. type InstanceMeta struct { Node string `json:"node"` @@ -720,6 +736,15 @@ type GetDaemonStatusParams struct { Selector *SelectorOptional `form:"selector,omitempty" json:"selector,omitempty"` } +// GetInstanceParams defines parameters for GetInstance. +type GetInstanceParams struct { + // Path object selector expression. + Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` + + // Node object and instance selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` +} + // GetInstanceConfigParams defines parameters for GetInstanceConfig. type GetInstanceConfigParams struct { // Path object selector expression. diff --git a/daemon/daemonapi/get_instance.go b/daemon/daemonapi/get_instance.go new file mode 100644 index 000000000..b08ff125c --- /dev/null +++ b/daemon/daemonapi/get_instance.go @@ -0,0 +1,48 @@ +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/daemon/api" +) + +func (a *DaemonApi) GetInstance(ctx echo.Context, params api.GetInstanceParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + Path: params.Path, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + configs := instance.ConfigData.GetAll() + l := make(api.InstanceArray, 0) + for _, config := range configs { + if !meta.HasPath(config.Path.String()) { + continue + } + if !meta.HasNode(config.Node) { + continue + } + monitor := instance.MonitorData.Get(config.Path, config.Node) + status := instance.StatusData.Get(config.Path, config.Node) + d := api.InstanceItem{ + Meta: api.InstanceMeta{ + Node: config.Node, + Object: config.Path.String(), + }, + Data: api.Instance{ + Config: config.Value, + Monitor: monitor, + Status: status, + }, + } + l = append(l, d) + } + return ctx.JSON(http.StatusOK, l) +} From 92026522bec4516a032823ac49dafed50174a0dd Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 4 Sep 2023 09:29:31 +0200 Subject: [PATCH 05/30] Stop using POST /object/monitor Use POST /objet/action/ instead, in the objectaction package. --- core/objectaction/object.go | 261 +++++++++++++++++++++++++++++++----- 1 file changed, 231 insertions(+), 30 deletions(-) diff --git a/core/objectaction/object.go b/core/objectaction/object.go index f563158c1..f82f59ebd 100644 --- a/core/objectaction/object.go +++ b/core/objectaction/object.go @@ -348,6 +348,10 @@ func (t T) DoLocal() error { // DoAsync uses the agent API to submit a target state to reach via an // orchestration. func (t T) DoAsync() error { + target, ok := instance.MonitorGlobalExpectValues[t.Target] + if !ok { + return fmt.Errorf("unexpected action: %s", t.Target) + } c, err := client.New(client.WithURL(t.Server), client.WithTimeout(0)) if err != nil { return err @@ -386,6 +390,7 @@ func (t T) DoAsync() error { if t.Wait { waitC = make(chan error, len(paths)) } + for _, p := range paths { var ( err error @@ -394,39 +399,235 @@ func (t T) DoAsync() error { if t.Wait { t.waitExpectation(ctx, c, t.Target, p, waitC) } - switch t.Target { - case instance.MonitorGlobalExpectPlacedAt.String(): - params := api.PostObjectActionSwitch{} - params.Path = p.String() - options := t.TargetOptions.(instance.MonitorGlobalExpectOptionsPlacedAt) - params.Destination = options.Destination - resp, e := c.PostObjectActionSwitchWithResponse(ctx, params) - if e != nil { + switch target { + case instance.MonitorGlobalExpectAborted: + params := api.PostObjectAction{Path: p.String()} + if resp, e := c.PostObjectActionAbortWithResponse(ctx, params); e != nil { err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } } - switch resp.StatusCode() { - case http.StatusOK: - b = resp.Body - case 400: - err = fmt.Errorf("%s", resp.JSON400) - case 401: - err = fmt.Errorf("%s", resp.JSON401) - case 403: - err = fmt.Errorf("%s", resp.JSON403) - case 408: - err = fmt.Errorf("%s", resp.JSON408) - case 409: - err = fmt.Errorf("%s", resp.JSON409) - case 500: - err = fmt.Errorf("%s", resp.JSON500) + case instance.MonitorGlobalExpectDeleted: + params := api.PostObjectAction{Path: p.String()} + if resp, e := c.PostObjectActionDeleteWithResponse(ctx, params); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } } - - default: - params := api.PostObjectMonitor{} - params.Path = p.String() - params.GlobalExpect = &t.Target - resp, e := c.PostObjectMonitorWithResponse(ctx, params) - if e != nil { + case instance.MonitorGlobalExpectFrozen: + params := api.PostObjectAction{Path: p.String()} + if resp, e := c.PostObjectActionFreezeWithResponse(ctx, params); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } + } + case instance.MonitorGlobalExpectProvisioned: + params := api.PostObjectAction{Path: p.String()} + if resp, e := c.PostObjectActionProvisionWithResponse(ctx, params); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } + } + case instance.MonitorGlobalExpectPurged: + params := api.PostObjectAction{Path: p.String()} + if resp, e := c.PostObjectActionPurgeWithResponse(ctx, params); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } + } + case instance.MonitorGlobalExpectStarted: + params := api.PostObjectAction{Path: p.String()} + if resp, e := c.PostObjectActionStartWithResponse(ctx, params); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } + } + case instance.MonitorGlobalExpectStopped: + params := api.PostObjectAction{Path: p.String()} + if resp, e := c.PostObjectActionStopWithResponse(ctx, params); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } + } + case instance.MonitorGlobalExpectThawed: + params := api.PostObjectAction{Path: p.String()} + if resp, e := c.PostObjectActionUnfreezeWithResponse(ctx, params); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } + } + case instance.MonitorGlobalExpectUnprovisioned: + params := api.PostObjectAction{Path: p.String()} + if resp, e := c.PostObjectActionUnprovisionWithResponse(ctx, params); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } + } + case instance.MonitorGlobalExpectPlaced: + params := api.PostObjectActionSwitch{Path: p.String()} + if resp, e := c.PostObjectActionSwitchWithResponse(ctx, params); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } + } + case instance.MonitorGlobalExpectPlacedAt: + params := api.PostObjectActionSwitch{Path: p.String()} + if options, ok := t.TargetOptions.(instance.MonitorGlobalExpectOptionsPlacedAt); !ok { + return fmt.Errorf("unexpected orchestration options: %#v", t.TargetOptions) + } else { + params.Destination = options.Destination + } + if resp, e := c.PostObjectActionSwitchWithResponse(ctx, params); e != nil { err = e } else { switch resp.StatusCode() { From e8b7d4393adfb115601fa52cd9f182a676d49419 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 4 Sep 2023 09:44:53 +0200 Subject: [PATCH 06/30] Use POST /object/action/abort instead of /object/abort And drop the POST /object/abort handler. --- core/commands/object_abort.go | 62 ++------ daemon/api/api.yaml | 31 ---- daemon/api/codegen_client_gen.go | 155 ------------------- daemon/api/codegen_server_gen.go | 215 ++++++++++++-------------- daemon/api/codegen_type_gen.go | 8 - daemon/daemonapi/post_object_abort.go | 36 ----- 6 files changed, 112 insertions(+), 395 deletions(-) delete mode 100644 daemon/daemonapi/post_object_abort.go diff --git a/core/commands/object_abort.go b/core/commands/object_abort.go index 2b70cfc3c..abb06f39b 100644 --- a/core/commands/object_abort.go +++ b/core/commands/object_abort.go @@ -1,61 +1,25 @@ package commands -import ( - "context" - "errors" - "fmt" - "net/http" - "os" - - "github.com/opensvc/om3/core/client" - "github.com/opensvc/om3/core/monitor" - "github.com/opensvc/om3/core/objectselector" - "github.com/opensvc/om3/daemon/api" -) +import "github.com/opensvc/om3/core/objectaction" type ( CmdObjectAbort struct { - OptsAsync OptsGlobal + OptsAsync } ) func (t *CmdObjectAbort) Run(selector, kind string) error { mergedSelector := mergeSelector(selector, t.ObjectSelector, kind, "") - sel := objectselector.NewSelection(mergedSelector) - paths, err := sel.Expand() - if err != nil { - return err - } - var errs error - c, err := client.New(client.WithURL(t.Server)) - if err != nil { - return err - } - params := api.PostObjectAbort{} - for _, p := range paths { - params.Path = p.String() - if resp, err := c.PostObjectAbort(context.Background(), params); err != nil { - errs = errors.Join(errs, err) - } else if resp.StatusCode != http.StatusOK { - errs = errors.Join(errs, fmt.Errorf("unexpected post object abort status code %s", resp.Status)) - } - } - if t.Watch { - m := monitor.New() - m.SetColor(t.Color) - m.SetFormat(t.Output) - m.SetSelector(mergedSelector) - cli, e := client.New(client.WithURL(t.Server), client.WithTimeout(0)) - if e != nil { - _, _ = fmt.Fprintln(os.Stderr, e) - return e - } - statusGetter := cli.NewGetDaemonStatus().SetSelector(mergedSelector) - evReader, err := cli.NewGetEvents().SetSelector(mergedSelector).GetReader() - errs = errors.Join(errs, err) - err = m.DoWatch(statusGetter, evReader, os.Stdout) - errs = errors.Join(errs, err) - } - return errs + return objectaction.New( + objectaction.WithObjectSelector(mergedSelector), + objectaction.WithLocal(t.Local), + objectaction.WithFormat(t.Output), + objectaction.WithColor(t.Color), + objectaction.WithAsyncTarget("aborted"), + objectaction.WithAsyncTime(t.Time), + objectaction.WithAsyncWait(t.Wait), + objectaction.WithAsyncWatch(t.Watch), + objectaction.WithProgress(!t.Quiet && t.Log == ""), + ).Do() } diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index 6e43b2896..8c42ad555 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -618,30 +618,6 @@ paths: $ref: '#/components/responses/403' 500: $ref: '#/components/responses/500' - /object/abort: - post: - operationId: PostObjectAbort - tags: - - object - security: - - basicAuth: [] - - bearerAuth: [] - requestBody: - description: Abort orchestration currently running on a selection of objects. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PostObjectAbort' - responses: - 200: - description: OK - 401: - $ref: '#/components/responses/401' - 403: - $ref: '#/components/responses/403' - 500: - $ref: '#/components/responses/500' /object/backlogs: get: operationId: GetObjectBacklogs @@ -2009,13 +1985,6 @@ components: type: string state: type: string - PostObjectAbort: - type: object - required: - - path - properties: - path: - type: string PostObjectClear: type: object required: diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index 04b051a16..d02812598 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -171,11 +171,6 @@ type ClientInterface interface { // GetNodesInfo request GetNodesInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - // PostObjectAbort request with any body - PostObjectAbortWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostObjectAbort(ctx context.Context, body PostObjectAbortJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // PostObjectActionAbort request with any body PostObjectActionAbortWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -624,30 +619,6 @@ func (c *Client) GetNodesInfo(ctx context.Context, reqEditors ...RequestEditorFn return c.Client.Do(req) } -func (c *Client) PostObjectAbortWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostObjectAbortRequestWithBody(c.Server, contentType, body) - 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) PostObjectAbort(ctx context.Context, body PostObjectAbortJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostObjectAbortRequest(c.Server, body) - 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 { @@ -2233,46 +2204,6 @@ func NewGetNodesInfoRequest(server string) (*http.Request, error) { return req, nil } -// NewPostObjectAbortRequest calls the generic PostObjectAbort builder with application/json body -func NewPostObjectAbortRequest(server string, body PostObjectAbortJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostObjectAbortRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostObjectAbortRequestWithBody generates requests for PostObjectAbort with any type of body -func NewPostObjectAbortRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/object/abort") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - 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 @@ -3414,11 +3345,6 @@ type ClientWithResponsesInterface interface { // GetNodesInfo request GetNodesInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetNodesInfoResponse, error) - // PostObjectAbort request with any body - PostObjectAbortWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostObjectAbortResponse, error) - - PostObjectAbortWithResponse(ctx context.Context, body PostObjectAbortJSONRequestBody, reqEditors ...RequestEditorFn) (*PostObjectAbortResponse, error) - // PostObjectActionAbort request with any body PostObjectActionAbortWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostObjectActionAbortResponse, error) @@ -4120,30 +4046,6 @@ func (r GetNodesInfoResponse) StatusCode() int { return 0 } -type PostObjectAbortResponse struct { - Body []byte - HTTPResponse *http.Response - JSON401 *Problem - JSON403 *Problem - JSON500 *Problem -} - -// Status returns HTTPResponse.Status -func (r PostObjectAbortResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostObjectAbortResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - type PostObjectActionAbortResponse struct { Body []byte HTTPResponse *http.Response @@ -5008,23 +4910,6 @@ func (c *ClientWithResponses) GetNodesInfoWithResponse(ctx context.Context, reqE return ParseGetNodesInfoResponse(rsp) } -// PostObjectAbortWithBodyWithResponse request with arbitrary body returning *PostObjectAbortResponse -func (c *ClientWithResponses) PostObjectAbortWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostObjectAbortResponse, error) { - rsp, err := c.PostObjectAbortWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostObjectAbortResponse(rsp) -} - -func (c *ClientWithResponses) PostObjectAbortWithResponse(ctx context.Context, body PostObjectAbortJSONRequestBody, reqEditors ...RequestEditorFn) (*PostObjectAbortResponse, error) { - rsp, err := c.PostObjectAbort(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostObjectAbortResponse(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...) @@ -6484,46 +6369,6 @@ func ParseGetNodesInfoResponse(rsp *http.Response) (*GetNodesInfoResponse, error return response, nil } -// ParsePostObjectAbortResponse parses an HTTP response from a PostObjectAbortWithResponse call -func ParsePostObjectAbortResponse(rsp *http.Response) (*PostObjectAbortResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostObjectAbortResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - 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 19d053beb..2daf4323e 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -93,9 +93,6 @@ type ServerInterface interface { // (GET /nodes/info) GetNodesInfo(ctx echo.Context) error - // (POST /object/abort) - PostObjectAbort(ctx echo.Context) error - // (POST /object/action/abort) PostObjectActionAbort(ctx echo.Context) error @@ -679,19 +676,6 @@ func (w *ServerInterfaceWrapper) GetNodesInfo(ctx echo.Context) error { return err } -// PostObjectAbort converts echo context to params. -func (w *ServerInterfaceWrapper) PostObjectAbort(ctx echo.Context) error { - var err error - - ctx.Set(BasicAuthScopes, []string{""}) - - ctx.Set(BearerAuthScopes, []string{""}) - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.PostObjectAbort(ctx) - return err -} - // PostObjectActionAbort converts echo context to params. func (w *ServerInterfaceWrapper) PostObjectActionAbort(ctx echo.Context) error { var err error @@ -1137,7 +1121,6 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/node/logs", wrapper.GetNodeLogs) router.POST(baseURL+"/node/monitor", wrapper.PostNodeMonitor) router.GET(baseURL+"/nodes/info", wrapper.GetNodesInfo) - router.POST(baseURL+"/object/abort", wrapper.PostObjectAbort) router.POST(baseURL+"/object/action/abort", wrapper.PostObjectActionAbort) router.POST(baseURL+"/object/action/delete", wrapper.PostObjectActionDelete) router.POST(baseURL+"/object/action/freeze", wrapper.PostObjectActionFreeze) @@ -1168,7 +1151,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL var swaggerSpec = []string{ "H4sIAAAAAAAC/+w9/XPbtpL/CkbvZtq+kSU7Tvta3/SHNGlf8y5xcrFzN3OxxwORKwkNBTAAKFt5k//9", - "Bl8kSAIkZVuuG/unxCI+FruL/cJi8e9RwlY5o0ClGB39e5Rjjlcggeu/Xrz75cVzRudkcYxXoH5JQSSc", + "Bl8kSAIkZVupa/unxCI+FruL/cJi8e9RwlY5o0ClGB39e5Rjjlcggeu/Xrz75cVzRudkcYxXoH5JQSSc", "5JIwOjoaySWgeZFlKMdyidgc6R9IBogIlEJaJJCiOWcr/YGqMcYjonp+KoBvRuOR/u1oZD9x+FQQDuno", "SPICxiORLGGF1bxyk6t2QnJCF6MvX8ajFwXHBowmVCt8hVL3NTyf97maA67wKs/U5+/FaByY8tc1UPkb", "ySTw9qwZEVKhAFQjhQTVKjx7+bGam0hYifagpiWCq5yDEITRI/ThI6Hp+YdxhmeQ/bzGWQHnfz9TK6ng", @@ -1179,104 +1162,104 @@ var swaggerSpec = []string{ "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", + "77EuZaMu5Zcv/x8AAP//ErY4isjEAAA=", } // 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 4367a4d94..6a14e03a4 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -438,11 +438,6 @@ type PostNodeMonitor struct { State *string `json:"state,omitempty"` } -// PostObjectAbort defines model for PostObjectAbort. -type PostObjectAbort struct { - Path string `json:"path"` -} - // PostObjectAction defines model for PostObjectAction. type PostObjectAction struct { Path string `json:"path"` @@ -880,9 +875,6 @@ type PostNodeDRBDConfigJSONRequestBody = PostNodeDRBDConfigRequest // PostNodeMonitorJSONRequestBody defines body for PostNodeMonitor for application/json ContentType. type PostNodeMonitorJSONRequestBody = PostNodeMonitor -// PostObjectAbortJSONRequestBody defines body for PostObjectAbort for application/json ContentType. -type PostObjectAbortJSONRequestBody = PostObjectAbort - // PostObjectActionAbortJSONRequestBody defines body for PostObjectActionAbort for application/json ContentType. type PostObjectActionAbortJSONRequestBody = PostObjectAction diff --git a/daemon/daemonapi/post_object_abort.go b/daemon/daemonapi/post_object_abort.go deleted file mode 100644 index dd557feae..000000000 --- a/daemon/daemonapi/post_object_abort.go +++ /dev/null @@ -1,36 +0,0 @@ -package daemonapi - -import ( - "net/http" - - "github.com/labstack/echo/v4" - - "github.com/opensvc/om3/core/instance" - "github.com/opensvc/om3/core/path" - "github.com/opensvc/om3/daemon/api" - "github.com/opensvc/om3/daemon/msgbus" - "github.com/opensvc/om3/util/hostname" - "github.com/opensvc/om3/util/pubsub" -) - -func (a *DaemonApi) PostObjectAbort(ctx echo.Context) error { - var ( - payload = api.PostObjectAbort{} - p path.T - err error - ) - if err := ctx.Bind(&payload); err != nil { - return JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "%s", err) - } - p, err = path.Parse(payload.Path) - if err != nil { - return JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "Error parsing path '%s': %s", payload.Path, err) - } - globalExpect := instance.MonitorGlobalExpectAborted - instMonitor := instance.MonitorUpdate{ - GlobalExpect: &globalExpect, - } - a.EventBus.Pub(&msgbus.SetInstanceMonitor{Path: p, Node: hostname.Hostname(), Value: instMonitor}, - pubsub.Label{"path", p.String()}, labelApi) - return ctx.JSON(http.StatusOK, nil) -} From 36d3ee9990f99a887f002dc0d6094a4d648ddca0 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 4 Sep 2023 11:13:17 +0200 Subject: [PATCH 07/30] Remove the POST /object/monitor handler --- daemon/api/api.yaml | 47 ----- daemon/api/codegen_client_gen.go | 187 ------------------- daemon/api/codegen_server_gen.go | 236 +++++++++++------------- daemon/api/codegen_type_gen.go | 11 -- daemon/daemonapi/post_object_monitor.go | 77 -------- 5 files changed, 109 insertions(+), 449 deletions(-) delete mode 100644 daemon/daemonapi/post_object_monitor.go diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index 8c42ad555..b270b400d 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -750,40 +750,6 @@ paths: $ref: '#/components/responses/403' 500: $ref: '#/components/responses/500' - /object/monitor: - post: - operationId: PostObjectMonitor - tags: - - object - security: - - basicAuth: [] - - bearerAuth: [] - requestBody: - description: monitor - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PostObjectMonitor' - responses: - 200: - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/MonitorUpdateQueued' - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 403: - $ref: '#/components/responses/403' - 408: - $ref: '#/components/responses/408' - 409: - $ref: '#/components/responses/409' - 500: - $ref: '#/components/responses/500' /object/progress: post: operationId: PostObjectProgress @@ -1992,19 +1958,6 @@ components: properties: path: type: string - PostObjectMonitor: - type: object - required: - - path - properties: - local_expect: - type: string - global_expect: - type: string - path: - type: string - state: - type: string PostObjectProgress: type: object required: diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index d02812598..34f0bb6e2 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -243,11 +243,6 @@ type ClientInterface interface { // GetObjectLogs request GetObjectLogs(ctx context.Context, params *GetObjectLogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - // PostObjectMonitor request with any body - PostObjectMonitorWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostObjectMonitor(ctx context.Context, body PostObjectMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // GetObjectPaths request GetObjectPaths(ctx context.Context, params *GetObjectPathsParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -955,30 +950,6 @@ func (c *Client) GetObjectLogs(ctx context.Context, params *GetObjectLogsParams, return c.Client.Do(req) } -func (c *Client) PostObjectMonitorWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostObjectMonitorRequestWithBody(c.Server, contentType, body) - 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) PostObjectMonitor(ctx context.Context, body PostObjectMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostObjectMonitorRequest(c.Server, body) - 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) GetObjectPaths(ctx context.Context, params *GetObjectPathsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetObjectPathsRequest(c.Server, params) if err != nil { @@ -2920,46 +2891,6 @@ func NewGetObjectLogsRequest(server string, params *GetObjectLogsParams) (*http. return req, nil } -// NewPostObjectMonitorRequest calls the generic PostObjectMonitor builder with application/json body -func NewPostObjectMonitorRequest(server string, body PostObjectMonitorJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostObjectMonitorRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostObjectMonitorRequestWithBody generates requests for PostObjectMonitor with any type of body -func NewPostObjectMonitorRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/object/monitor") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - // NewGetObjectPathsRequest generates requests for GetObjectPaths func NewGetObjectPathsRequest(server string, params *GetObjectPathsParams) (*http.Request, error) { var err error @@ -3417,11 +3348,6 @@ type ClientWithResponsesInterface interface { // GetObjectLogs request GetObjectLogsWithResponse(ctx context.Context, params *GetObjectLogsParams, reqEditors ...RequestEditorFn) (*GetObjectLogsResponse, error) - // PostObjectMonitor request with any body - PostObjectMonitorWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostObjectMonitorResponse, error) - - PostObjectMonitorWithResponse(ctx context.Context, body PostObjectMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*PostObjectMonitorResponse, error) - // GetObjectPaths request GetObjectPathsWithResponse(ctx context.Context, params *GetObjectPathsParams, reqEditors ...RequestEditorFn) (*GetObjectPathsResponse, error) @@ -4477,34 +4403,6 @@ func (r GetObjectLogsResponse) StatusCode() int { return 0 } -type PostObjectMonitorResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued - JSON400 *Problem - JSON401 *Problem - JSON403 *Problem - JSON408 *Problem - JSON409 *Problem - JSON500 *Problem -} - -// Status returns HTTPResponse.Status -func (r PostObjectMonitorResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostObjectMonitorResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - type GetObjectPathsResponse struct { Body []byte HTTPResponse *http.Response @@ -5150,23 +5048,6 @@ func (c *ClientWithResponses) GetObjectLogsWithResponse(ctx context.Context, par return ParseGetObjectLogsResponse(rsp) } -// PostObjectMonitorWithBodyWithResponse request with arbitrary body returning *PostObjectMonitorResponse -func (c *ClientWithResponses) PostObjectMonitorWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostObjectMonitorResponse, error) { - rsp, err := c.PostObjectMonitorWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostObjectMonitorResponse(rsp) -} - -func (c *ClientWithResponses) PostObjectMonitorWithResponse(ctx context.Context, body PostObjectMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*PostObjectMonitorResponse, error) { - rsp, err := c.PostObjectMonitor(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostObjectMonitorResponse(rsp) -} - // GetObjectPathsWithResponse request returning *GetObjectPathsResponse func (c *ClientWithResponses) GetObjectPathsWithResponse(ctx context.Context, params *GetObjectPathsParams, reqEditors ...RequestEditorFn) (*GetObjectPathsResponse, error) { rsp, err := c.GetObjectPaths(ctx, params, reqEditors...) @@ -7338,74 +7219,6 @@ func ParseGetObjectLogsResponse(rsp *http.Response) (*GetObjectLogsResponse, err return response, nil } -// ParsePostObjectMonitorResponse parses an HTTP response from a PostObjectMonitorWithResponse call -func ParsePostObjectMonitorResponse(rsp *http.Response) (*PostObjectMonitorResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostObjectMonitorResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued - 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 == 408: - var dest Problem - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON408 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: - var dest Problem - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON409 = &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 -} - // ParseGetObjectPathsResponse parses an HTTP response from a GetObjectPathsWithResponse call func ParseGetObjectPathsResponse(rsp *http.Response) (*GetObjectPathsResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index 2daf4323e..350aa6b2e 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -141,9 +141,6 @@ type ServerInterface interface { // (GET /object/logs) GetObjectLogs(ctx echo.Context, params GetObjectLogsParams) error - // (POST /object/monitor) - PostObjectMonitor(ctx echo.Context) error - // (GET /object/paths) GetObjectPaths(ctx echo.Context, params GetObjectPathsParams) error @@ -948,19 +945,6 @@ func (w *ServerInterfaceWrapper) GetObjectLogs(ctx echo.Context) error { return err } -// PostObjectMonitor converts echo context to params. -func (w *ServerInterfaceWrapper) PostObjectMonitor(ctx echo.Context) error { - var err error - - ctx.Set(BasicAuthScopes, []string{""}) - - ctx.Set(BearerAuthScopes, []string{""}) - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.PostObjectMonitor(ctx) - return err -} - // GetObjectPaths converts echo context to params. func (w *ServerInterfaceWrapper) GetObjectPaths(ctx echo.Context) error { var err error @@ -1137,7 +1121,6 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/object/config", wrapper.GetObjectConfig) router.GET(baseURL+"/object/file", wrapper.GetObjectFile) router.GET(baseURL+"/object/logs", wrapper.GetObjectLogs) - router.POST(baseURL+"/object/monitor", wrapper.PostObjectMonitor) router.GET(baseURL+"/object/paths", wrapper.GetObjectPaths) router.POST(baseURL+"/object/progress", wrapper.PostObjectProgress) router.GET(baseURL+"/pools", wrapper.GetPools) @@ -1150,116 +1133,115 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "77EuZaMu5Zcv/x8AAP//ErY4isjEAAA=", + "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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 6a14e03a4..5e48fe645 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -454,14 +454,6 @@ type PostObjectClear struct { Path string `json:"path"` } -// PostObjectMonitor defines model for PostObjectMonitor. -type PostObjectMonitor struct { - GlobalExpect *string `json:"global_expect,omitempty"` - LocalExpect *string `json:"local_expect,omitempty"` - Path string `json:"path"` - State *string `json:"state,omitempty"` -} - // PostObjectProgress defines model for PostObjectProgress. type PostObjectProgress struct { IsPartial *bool `json:"is_partial,omitempty"` @@ -911,9 +903,6 @@ type PostObjectActionUnprovisionJSONRequestBody = PostObjectAction // PostObjectClearJSONRequestBody defines body for PostObjectClear for application/json ContentType. type PostObjectClearJSONRequestBody = PostObjectClear -// PostObjectMonitorJSONRequestBody defines body for PostObjectMonitor for application/json ContentType. -type PostObjectMonitorJSONRequestBody = PostObjectMonitor - // PostObjectProgressJSONRequestBody defines body for PostObjectProgress for application/json ContentType. type PostObjectProgressJSONRequestBody = PostObjectProgress diff --git a/daemon/daemonapi/post_object_monitor.go b/daemon/daemonapi/post_object_monitor.go deleted file mode 100644 index 60e29c7e7..000000000 --- a/daemon/daemonapi/post_object_monitor.go +++ /dev/null @@ -1,77 +0,0 @@ -package daemonapi - -import ( - "errors" - "net/http" - "time" - - "github.com/google/uuid" - "github.com/labstack/echo/v4" - - "github.com/opensvc/om3/core/instance" - "github.com/opensvc/om3/core/path" - "github.com/opensvc/om3/daemon/api" - "github.com/opensvc/om3/daemon/msgbus" - "github.com/opensvc/om3/util/hostname" - "github.com/opensvc/om3/util/pubsub" -) - -func (a *DaemonApi) PostObjectMonitor(ctx echo.Context) error { - var ( - payload api.PostObjectMonitor - update instance.MonitorUpdate - p path.T - err error - ) - if err := ctx.Bind(&payload); err != nil { - return JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "%s", err) - } - p, err = path.Parse(payload.Path) - if err != nil { - return JSONProblemf(ctx, http.StatusBadRequest, "Invalid body", "Error parsing path %s: %s", payload.Path, err) - } - if instMon := instance.MonitorData.Get(p, hostname.Hostname()); instMon == nil { - return JSONProblemf(ctx, http.StatusNotFound, "Not found", "Object does not exist: %s", payload.Path) - } - if payload.GlobalExpect != nil { - i := instance.MonitorGlobalExpectValues[*payload.GlobalExpect] - update.GlobalExpect = &i - } - if payload.LocalExpect != nil { - i := instance.MonitorLocalExpectValues[*payload.LocalExpect] - update.LocalExpect = &i - } - if payload.State != nil { - i := instance.MonitorStateValues[*payload.State] - update.State = &i - } - update.CandidateOrchestrationId = uuid.New() - msg := msgbus.SetInstanceMonitor{ - Path: p, - Node: hostname.Hostname(), - Value: update, - Err: make(chan error), - } - a.EventBus.Pub(&msg, pubsub.Label{"path", p.String()}, labelApi) - ticker := time.NewTicker(300 * time.Millisecond) - defer ticker.Stop() - var errs error - for { - select { - case <-ticker.C: - return JSONProblemf(ctx, http.StatusRequestTimeout, "set monitor", "timeout waiting for monitor commit") - case err := <-msg.Err: - if err != nil { - errs = errors.Join(errs, err) - } else if errs != nil { - return JSONProblemf(ctx, http.StatusConflict, "set monitor", "%s", errs) - } else { - return ctx.JSON(http.StatusOK, api.MonitorUpdateQueued{ - OrchestrationId: update.CandidateOrchestrationId, - }) - } - case <-ctx.Request().Context().Done(): - return JSONProblemf(ctx, http.StatusGone, "set monitor", "") - } - } -} From 167dbbf9ab0b96bee422748b617687a4d3ef7e1f Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 4 Sep 2023 18:50:47 +0200 Subject: [PATCH 08/30] Add /node handlers GET /node GET /node/config GET /node/status GET /node/monitor These handlers return list of meta+data items, suited for filtered by meta tabular outputs. --- core/node/labels.go | 14 + core/node/monitor.go | 18 +- core/node/status.go | 33 +- core/nodeselector/nodeselector.go | 7 +- core/nodesinfo/main.go | 48 +- daemon/api/api.yaml | 382 ++++++++++++++-- daemon/api/codegen_client_gen.go | 652 ++++++++++++++++++++++++++- daemon/api/codegen_server_gen.go | 329 +++++++++----- daemon/api/codegen_type_gen.go | 88 ++++ daemon/daemonapi/get_node.go | 43 ++ daemon/daemonapi/get_node_config.go | 37 ++ daemon/daemonapi/get_node_monitor.go | 38 ++ daemon/daemonapi/get_node_status.go | 38 ++ daemon/daemondata/data_init.go | 3 +- daemon/msgbus/messages.go | 17 +- daemon/nmon/main.go | 6 +- 16 files changed, 1520 insertions(+), 233 deletions(-) create mode 100644 core/node/labels.go create mode 100644 daemon/daemonapi/get_node.go create mode 100644 daemon/daemonapi/get_node_config.go create mode 100644 daemon/daemonapi/get_node_monitor.go create mode 100644 daemon/daemonapi/get_node_status.go diff --git a/core/node/labels.go b/core/node/labels.go new file mode 100644 index 000000000..9f6bad2c9 --- /dev/null +++ b/core/node/labels.go @@ -0,0 +1,14 @@ +package node + +type ( + // Labels holds the key/value pairs defined in the labels section of the node.conf + Labels map[string]string +) + +func (t Labels) DeepCopy() Labels { + labels := make(Labels) + for k, v := range t { + labels[k] = v + } + return labels +} diff --git a/core/node/monitor.go b/core/node/monitor.go index e16c1770b..f4b0508b8 100644 --- a/core/node/monitor.go +++ b/core/node/monitor.go @@ -12,12 +12,18 @@ import ( type ( // Monitor describes the in-daemon states of a node Monitor struct { - State MonitorState `json:"state" yaml:"state"` - LocalExpect MonitorLocalExpect `json:"local_expect" yaml:"local_expect"` - GlobalExpect MonitorGlobalExpect `json:"global_expect" yaml:"global_expect"` - StateUpdatedAt time.Time `json:"state_updated_at" yaml:"state_updated_at"` - GlobalExpectUpdatedAt time.Time `json:"global_expect_updated_at" yaml:"global_expect_updated_at"` - LocalExpectUpdatedAt time.Time `json:"local_expect_updated_at" yaml:"local_expect_updated_at"` + GlobalExpect MonitorGlobalExpect `json:"global_expect" yaml:"global_expect"` + LocalExpect MonitorLocalExpect `json:"local_expect" yaml:"local_expect"` + State MonitorState `json:"state" yaml:"state"` + + GlobalExpectUpdatedAt time.Time `json:"global_expect_updated_at" yaml:"global_expect_updated_at"` + LocalExpectUpdatedAt time.Time `json:"local_expect_updated_at" yaml:"local_expect_updated_at"` + StateUpdatedAt time.Time `json:"state_updated_at" yaml:"state_updated_at"` + UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` + + OrchestrationId uuid.UUID `json:"orchestration_id" yaml:"orchestration_id"` + OrchestrationIsDone bool `json:"orchestration_is_done" yaml:"orchestration_is_done"` + SessionId uuid.UUID `json:"session_id" yaml:"session_id"` } // MonitorUpdate is embedded in the SetNodeMonitor message to diff --git a/core/node/status.go b/core/node/status.go index 81954aedc..8d4c778bb 100644 --- a/core/node/status.go +++ b/core/node/status.go @@ -4,8 +4,8 @@ import ( "time" "github.com/opensvc/om3/core/instance" - "github.com/opensvc/om3/core/nodesinfo" "github.com/opensvc/om3/core/status" + "github.com/opensvc/om3/util/san" ) type ( @@ -19,7 +19,7 @@ type ( MinAvailMemPct uint64 `json:"min_avail_mem" yaml:"min_avail_mem"` MinAvailSwapPct uint64 `json:"min_avail_swap" yaml:"min_avail_swap"` IsSpeaker bool `json:"is_speaker" yaml:"is_speaker"` - Labels nodesinfo.Labels `json:"labels" yaml:"labels"` + Labels Labels `json:"labels" yaml:"labels"` } // Instances groups instances configuration digest and status @@ -35,6 +35,18 @@ type ( Url string `json:"url" yaml:"url"` Status status.T `json:"status" yaml:"status"` } + + // NodesInfo is the dataset exposed via the GET /nodes_info handler, + // used by nodes to: + // * expand node selector expressions based on labels + // * setup clusterwide lun mapping from pools backed by san arrays + NodesInfo map[string]NodeInfo + + NodeInfo struct { + Env string `json:"env" yaml:"env"` + Labels Labels `json:"labels" yaml:"labels"` + Paths san.Paths `json:"paths" yaml:"paths"` + } ) func (t Status) IsFrozen() bool { @@ -65,11 +77,11 @@ func (t *Status) DeepCopy() *Status { // GetNodesInfo returns a NodesInfo struct, ie a map of // a subset of information from the data cache -func GetNodesInfo() *nodesinfo.NodesInfo { - result := make(nodesinfo.NodesInfo) +func GetNodesInfo() *NodesInfo { + result := make(NodesInfo) for _, nodeConfig := range ConfigData.GetAll() { name := nodeConfig.Node - nodeInfo := nodesinfo.NodeInfo{Env: nodeConfig.Value.Env} + nodeInfo := NodeInfo{Env: nodeConfig.Value.Env} if nodeStatus := StatusData.Get(name); nodeStatus != nil { nodeInfo.Labels = nodeStatus.Labels.DeepCopy() } @@ -80,3 +92,14 @@ func GetNodesInfo() *nodesinfo.NodesInfo { } return &result } + +// GetNodesWithAnyPaths return the list of nodes having any of the given paths. +func (t NodesInfo) GetNodesWithAnyPaths(paths san.Paths) []string { + l := make([]string, 0) + for nodename, node := range t { + if paths.HasAnyOf(node.Paths) { + l = append(l, nodename) + } + } + return l +} diff --git a/core/nodeselector/nodeselector.go b/core/nodeselector/nodeselector.go index ef21498c5..8900e82a1 100644 --- a/core/nodeselector/nodeselector.go +++ b/core/nodeselector/nodeselector.go @@ -14,6 +14,7 @@ import ( "github.com/opensvc/om3/core/client" "github.com/opensvc/om3/core/clientcontext" "github.com/opensvc/om3/core/clusternode" + "github.com/opensvc/om3/core/node" "github.com/opensvc/om3/core/nodesinfo" "github.com/opensvc/om3/util/funcopt" "github.com/opensvc/om3/util/hostname" @@ -30,7 +31,7 @@ type ( server string knownNodes []string knownNodesSet *orderedset.OrderedSet - info nodesinfo.NodesInfo + info node.NodesInfo log zerolog.Logger } @@ -88,7 +89,7 @@ func WithLocal(v bool) funcopt.O { // WithNodesInfo allow in-daemon callers to bypass nodesinfo.Load and nodesinfo.Req // as they can access the NodesInfo faster from the data bus. -func WithNodesInfo(v nodesinfo.NodesInfo) funcopt.O { +func WithNodesInfo(v node.NodesInfo) funcopt.O { return funcopt.F(func(i any) error { t := i.(*T) t.info = v @@ -309,7 +310,7 @@ func (t T) daemonKnownNodes() ([]string, error) { } } -func (t *T) getNodesInfo() (nodesinfo.NodesInfo, error) { +func (t *T) getNodesInfo() (node.NodesInfo, error) { var err error if t.info != nil { return t.info, nil diff --git a/core/nodesinfo/main.go b/core/nodesinfo/main.go index 586aa40dc..b88a251d7 100644 --- a/core/nodesinfo/main.go +++ b/core/nodesinfo/main.go @@ -8,36 +8,11 @@ import ( "os" "path/filepath" + "github.com/opensvc/om3/core/node" "github.com/opensvc/om3/core/rawconfig" "github.com/opensvc/om3/daemon/api" - "github.com/opensvc/om3/util/san" ) -type ( - // NodesInfo is the dataset exposed via the GET /nodes_info handler, - // used by nodes to: - // * expand node selector expressions based on labels - // * setup clusterwide lun mapping from pools backed by san arrays - NodesInfo map[string]NodeInfo - - NodeInfo struct { - Env string `json:"env" yaml:"env"` - Labels Labels `json:"labels" yaml:"labels"` - Paths san.Paths `json:"paths" yaml:"paths"` - } - - // Labels holds the key/value pairs defined in the labels section of the node.conf - Labels map[string]string -) - -func (t Labels) DeepCopy() Labels { - labels := make(Labels) - for k, v := range t { - labels[k] = v - } - return labels -} - func cacheFile() string { return filepath.Join(rawconfig.Paths.Var, "nodes_info.json") } @@ -48,7 +23,7 @@ func cacheFilePair() (final, tmp string) { return } -func Save(data NodesInfo) error { +func Save(data node.NodesInfo) error { p, tmp := cacheFilePair() jsonFile, err := os.Create(tmp) if err != nil { @@ -67,8 +42,8 @@ func Save(data NodesInfo) error { return nil } -func Load() (NodesInfo, error) { - data := NodesInfo{} +func Load() (node.NodesInfo, error) { + data := node.NodesInfo{} p := cacheFile() jsonFile, err := os.Open(p) if err != nil { @@ -80,7 +55,7 @@ func Load() (NodesInfo, error) { return data, err } -func ReqWithClient(c api.ClientInterface) (NodesInfo, error) { +func ReqWithClient(c api.ClientInterface) (node.NodesInfo, error) { if c == nil { panic("nodesinfo.ReqWithClient(nil): no client") } @@ -90,19 +65,8 @@ func ReqWithClient(c api.ClientInterface) (NodesInfo, error) { } else if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("unexpected get nodes info status code %s", resp.Status) } - var data NodesInfo + var data node.NodesInfo defer resp.Body.Close() err = json.NewDecoder(resp.Body).Decode(&data) return data, err } - -// GetNodesWithAnyPaths return the list of nodes having any of the given paths. -func (t NodesInfo) GetNodesWithAnyPaths(paths san.Paths) []string { - l := make([]string, 0) - for nodename, node := range t { - if paths.HasAnyOf(node.Paths) { - l = append(l, nodename) - } - } - return l -} diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index b270b400d..490a90a49 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -265,6 +265,11 @@ paths: $ref: '#/components/responses/403' 500: $ref: '#/components/responses/500' + + # ======================================================================== + # instance paths + # ======================================================================== + /instance: get: operationId: GetInstance @@ -422,6 +427,144 @@ paths: $ref: '#/components/responses/403' 500: $ref: '#/components/responses/500' + + # ======================================================================== + # node paths + # ======================================================================== + + /node: + get: + operationId: GetNode + tags: + - node + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/NodeOptional' + responses: + 200: + description: get node config, monitor and status + content: + application/json: + schema: + $ref: '#/components/schemas/NodeArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + /node/config: + get: + operationId: GetNodeConfig + tags: + - node + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/NodeOptional' + responses: + 200: + description: get node config + content: + application/json: + schema: + $ref: '#/components/schemas/NodeConfigArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + /node/monitor: + get: + operationId: GetNodeMonitor + tags: + - node + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/NodeOptional' + responses: + 200: + description: get node monitor + content: + application/json: + schema: + $ref: '#/components/schemas/NodeMonitorArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + post: + operationId: PostNodeMonitor + tags: + - node + security: + - basicAuth: [] + - bearerAuth: [] + requestBody: + description: monitor + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PostNodeMonitor' + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/MonitorUpdateQueued' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 408: + $ref: '#/components/responses/408' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + /node/status: + get: + operationId: GetNodeStatus + tags: + - node + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/NodeOptional' + responses: + 200: + description: get node status + content: + application/json: + schema: + $ref: '#/components/schemas/NodeStatusArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' /node/drbd/allocation: get: operationId: GetNodeDRBDAllocation @@ -563,40 +706,6 @@ paths: $ref: '#/components/responses/403' 500: $ref: '#/components/responses/500' - /node/monitor: - post: - operationId: PostNodeMonitor - tags: - - node - security: - - basicAuth: [] - - bearerAuth: [] - requestBody: - description: monitor - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PostNodeMonitor' - responses: - 200: - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/MonitorUpdateQueued' - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 403: - $ref: '#/components/responses/403' - 408: - $ref: '#/components/responses/408' - 409: - $ref: '#/components/responses/409' - 500: - $ref: '#/components/responses/500' /nodes/info: get: operationId: GetNodesInfo @@ -1266,6 +1375,16 @@ paths: $ref: '#/components/responses/500' components: schemas: + ArbitratorStatus: + type: object + required: + - url + - status + properties: + url: + type: string + status: + $ref: '#/components/schemas/Status' AuthToken: type: object required: @@ -1482,7 +1601,7 @@ components: InstanceConfig: x-go-type: instance.Config x-go-type-import: - path: github.com/opensvc/om3/core/config + path: github.com/opensvc/om3/core/instance type: object required: - app @@ -1627,7 +1746,7 @@ components: InstanceStatus: x-go-type: instance.Status x-go-type-import: - path: github.com/opensvc/om3/core/status + path: github.com/opensvc/om3/core/instance type: object required: - avail @@ -1739,6 +1858,183 @@ components: type: integer pct: type: number + + # ======================================================================== + # node schemas + # ======================================================================== + + Node: + type: object + properties: + config: + $ref: '#/components/schemas/NodeConfig' + monitor: + $ref: '#/components/schemas/NodeMonitor' + status: + $ref: '#/components/schemas/NodeStatus' + NodeArray: + type: array + items: + $ref: '#/components/schemas/NodeItem' + NodeItem: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/NodeMeta' + data: + $ref: '#/components/schemas/Node' + NodeConfig: + x-go-type: node.Config + x-go-type-import: + path: github.com/opensvc/om3/core/node + type: object + required: + - env + - maintenance_grace_period + - ready_period + - rejoin_grace_period + - split_action + properties: + env: + type: string + maintenance_grace_period: + type: string + format: duration + ready_period: + type: string + format: duration + rejoin_grace_period: + type: string + format: duration + split_action: + type: string + NodeConfigArray: + type: array + items: + $ref: '#/components/schemas/NodeConfigItem' + NodeConfigItem: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/NodeMeta' + data: + $ref: '#/components/schemas/NodeConfig' + NodeMonitor: + x-go-type: node.Monitor + x-go-type-import: + path: github.com/opensvc/om3/core/node + type: object + required: + - global_expect + - global_expect_updated_at + - local_expect + - local_expect_updated_at + - orchestration_id + - orchestration_is_done + - session_id + - state + - state_updated_at + - updated_at + properties: + global_expect: + type: string + global_expect_updated_at: + type: string + format: date-time + local_expect: + type: string + local_expect_updated_at: + type: string + format: date-time + orchestration_id: + type: string + orchestration_is_done: + type: boolean + session_id: + type: string + state: + type: string + state_updated_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + NodeMonitorArray: + type: array + items: + $ref: '#/components/schemas/NodeMonitorItem' + NodeMonitorItem: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/NodeMeta' + data: + $ref: '#/components/schemas/NodeMonitor' + NodeStatus: + x-go-type: node.Status + x-go-type-import: + path: github.com/opensvc/om3/core/node + type: object + required: + - agent + - api + - arbitrators + - compat + - frozen_at + - gen + - min_avail_mem + - min_avail_swap + - is_speaker + - labels + properties: + agent: + type: string + api: + type: string + arbitrators: + type: object + additionalProperties: + $ref: '#/components/schemas/ArbitratorStatus' + compat: + type: boolean + frozen_at: + type: string + format: date-time + gen: + additionalProperties: + type: integer + min_avail_mem: + type: integer + min_avail_swap: + type: integer + is_speaker: + type: boolean + labels: + type: object + NodeStatusArray: + type: array + items: + $ref: '#/components/schemas/NodeStatusItem' + NodeStatusItem: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/NodeMeta' + data: + $ref: '#/components/schemas/NodeStatus' NodeInfo: type: object required: @@ -1771,10 +2067,19 @@ components: value: type: string description: value is the label value. + NodeMeta: + type: object + required: + - node + properties: + node: + type: string NodesInfo: type: array items: $ref: '#/components/schemas/NodeInfo' + + ObjectConfig: type: object required: @@ -1974,6 +2279,11 @@ components: type: string is_partial: type: boolean + + # ======================================================================== + # instance schemas + # ======================================================================== + Instance: type: object properties: diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index 34f0bb6e2..116a03ddc 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -143,12 +143,18 @@ type ClientInterface interface { // GetNetworks request GetNetworks(ctx context.Context, params *GetNetworksParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetNode request + GetNode(ctx context.Context, params *GetNodeParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetNodeBacklogs request GetNodeBacklogs(ctx context.Context, params *GetNodeBacklogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) // PostNodeClear request PostNodeClear(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetNodeConfig request + GetNodeConfig(ctx context.Context, params *GetNodeConfigParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetNodeDRBDAllocation request GetNodeDRBDAllocation(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -163,11 +169,17 @@ type ClientInterface interface { // GetNodeLogs request GetNodeLogs(ctx context.Context, params *GetNodeLogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetNodeMonitor request + GetNodeMonitor(ctx context.Context, params *GetNodeMonitorParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // PostNodeMonitor request with any body PostNodeMonitorWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) PostNodeMonitor(ctx context.Context, body PostNodeMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetNodeStatus request + GetNodeStatus(ctx context.Context, params *GetNodeStatusParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetNodesInfo request GetNodesInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -494,6 +506,18 @@ func (c *Client) GetNetworks(ctx context.Context, params *GetNetworksParams, req return c.Client.Do(req) } +func (c *Client) GetNode(ctx context.Context, params *GetNodeParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetNodeRequest(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) GetNodeBacklogs(ctx context.Context, params *GetNodeBacklogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetNodeBacklogsRequest(c.Server, params) if err != nil { @@ -518,6 +542,18 @@ func (c *Client) PostNodeClear(ctx context.Context, reqEditors ...RequestEditorF return c.Client.Do(req) } +func (c *Client) GetNodeConfig(ctx context.Context, params *GetNodeConfigParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetNodeConfigRequest(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) GetNodeDRBDAllocation(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetNodeDRBDAllocationRequest(c.Server) if err != nil { @@ -578,6 +614,18 @@ func (c *Client) GetNodeLogs(ctx context.Context, params *GetNodeLogsParams, req return c.Client.Do(req) } +func (c *Client) GetNodeMonitor(ctx context.Context, params *GetNodeMonitorParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetNodeMonitorRequest(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) PostNodeMonitorWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewPostNodeMonitorRequestWithBody(c.Server, contentType, body) if err != nil { @@ -602,6 +650,18 @@ func (c *Client) PostNodeMonitor(ctx context.Context, body PostNodeMonitorJSONRe return c.Client.Do(req) } +func (c *Client) GetNodeStatus(ctx context.Context, params *GetNodeStatusParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetNodeStatusRequest(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) GetNodesInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetNodesInfoRequest(c.Server) if err != nil { @@ -1837,6 +1897,53 @@ func NewGetNetworksRequest(server string, params *GetNetworksParams) (*http.Requ return req, nil } +// NewGetNodeRequest generates requests for GetNode +func NewGetNodeRequest(server string, params *GetNodeParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/node") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + queryValues := queryURL.Query() + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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 +} + // NewGetNodeBacklogsRequest generates requests for GetNodeBacklogs func NewGetNodeBacklogsRequest(server string, params *GetNodeBacklogsParams) (*http.Request, error) { var err error @@ -1923,6 +2030,53 @@ func NewPostNodeClearRequest(server string) (*http.Request, error) { return req, nil } +// NewGetNodeConfigRequest generates requests for GetNodeConfig +func NewGetNodeConfigRequest(server string, params *GetNodeConfigParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/node/config") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + queryValues := queryURL.Query() + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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 +} + // NewGetNodeDRBDAllocationRequest generates requests for GetNodeDRBDAllocation func NewGetNodeDRBDAllocationRequest(server string) (*http.Request, error) { var err error @@ -2108,6 +2262,53 @@ func NewGetNodeLogsRequest(server string, params *GetNodeLogsParams) (*http.Requ return req, nil } +// NewGetNodeMonitorRequest generates requests for GetNodeMonitor +func NewGetNodeMonitorRequest(server string, params *GetNodeMonitorParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/node/monitor") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + queryValues := queryURL.Query() + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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 +} + // NewPostNodeMonitorRequest calls the generic PostNodeMonitor builder with application/json body func NewPostNodeMonitorRequest(server string, body PostNodeMonitorJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -2148,6 +2349,53 @@ func NewPostNodeMonitorRequestWithBody(server string, contentType string, body i return req, nil } +// NewGetNodeStatusRequest generates requests for GetNodeStatus +func NewGetNodeStatusRequest(server string, params *GetNodeStatusParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/node/status") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + queryValues := queryURL.Query() + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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 +} + // NewGetNodesInfoRequest generates requests for GetNodesInfo func NewGetNodesInfoRequest(server string) (*http.Request, error) { var err error @@ -3248,12 +3496,18 @@ type ClientWithResponsesInterface interface { // GetNetworks request GetNetworksWithResponse(ctx context.Context, params *GetNetworksParams, reqEditors ...RequestEditorFn) (*GetNetworksResponse, error) + // GetNode request + GetNodeWithResponse(ctx context.Context, params *GetNodeParams, reqEditors ...RequestEditorFn) (*GetNodeResponse, error) + // GetNodeBacklogs request GetNodeBacklogsWithResponse(ctx context.Context, params *GetNodeBacklogsParams, reqEditors ...RequestEditorFn) (*GetNodeBacklogsResponse, error) // PostNodeClear request PostNodeClearWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostNodeClearResponse, error) + // GetNodeConfig request + GetNodeConfigWithResponse(ctx context.Context, params *GetNodeConfigParams, reqEditors ...RequestEditorFn) (*GetNodeConfigResponse, error) + // GetNodeDRBDAllocation request GetNodeDRBDAllocationWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetNodeDRBDAllocationResponse, error) @@ -3268,11 +3522,17 @@ type ClientWithResponsesInterface interface { // GetNodeLogs request GetNodeLogsWithResponse(ctx context.Context, params *GetNodeLogsParams, reqEditors ...RequestEditorFn) (*GetNodeLogsResponse, error) + // GetNodeMonitor request + GetNodeMonitorWithResponse(ctx context.Context, params *GetNodeMonitorParams, reqEditors ...RequestEditorFn) (*GetNodeMonitorResponse, error) + // PostNodeMonitor request with any body PostNodeMonitorWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostNodeMonitorResponse, error) PostNodeMonitorWithResponse(ctx context.Context, body PostNodeMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*PostNodeMonitorResponse, error) + // GetNodeStatus request + GetNodeStatusWithResponse(ctx context.Context, params *GetNodeStatusParams, reqEditors ...RequestEditorFn) (*GetNodeStatusResponse, error) + // GetNodesInfo request GetNodesInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetNodesInfoResponse, error) @@ -3770,17 +4030,18 @@ func (r GetNetworksResponse) StatusCode() int { return 0 } -type GetNodeBacklogsResponse struct { +type GetNodeResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *LogList + JSON200 *NodeArray + JSON400 *Problem JSON401 *Problem JSON403 *Problem JSON500 *Problem } // Status returns HTTPResponse.Status -func (r GetNodeBacklogsResponse) Status() string { +func (r GetNodeResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -3788,25 +4049,24 @@ func (r GetNodeBacklogsResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetNodeBacklogsResponse) StatusCode() int { +func (r GetNodeResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type PostNodeClearResponse struct { +type GetNodeBacklogsResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *Problem - JSON400 *Problem + JSON200 *LogList JSON401 *Problem JSON403 *Problem JSON500 *Problem } // Status returns HTTPResponse.Status -func (r PostNodeClearResponse) Status() string { +func (r GetNodeBacklogsResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -3814,22 +4074,25 @@ func (r PostNodeClearResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r PostNodeClearResponse) StatusCode() int { +func (r GetNodeBacklogsResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type GetNodeDRBDAllocationResponse struct { +type PostNodeClearResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *DRBDAllocation + JSON200 *Problem + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem JSON500 *Problem } // Status returns HTTPResponse.Status -func (r GetNodeDRBDAllocationResponse) Status() string { +func (r PostNodeClearResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -3837,17 +4100,17 @@ func (r GetNodeDRBDAllocationResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetNodeDRBDAllocationResponse) StatusCode() int { +func (r PostNodeClearResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type GetNodeDRBDConfigResponse struct { +type GetNodeConfigResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *DRBDConfig + JSON200 *NodeConfigArray JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -3855,7 +4118,7 @@ type GetNodeDRBDConfigResponse struct { } // Status returns HTTPResponse.Status -func (r GetNodeDRBDConfigResponse) Status() string { +func (r GetNodeConfigResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -3863,14 +4126,63 @@ func (r GetNodeDRBDConfigResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetNodeDRBDConfigResponse) StatusCode() int { +func (r GetNodeConfigResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type PostNodeDRBDConfigResponse struct { +type GetNodeDRBDAllocationResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *DRBDAllocation + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetNodeDRBDAllocationResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetNodeDRBDAllocationResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetNodeDRBDConfigResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *DRBDConfig + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetNodeDRBDConfigResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetNodeDRBDConfigResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type PostNodeDRBDConfigResponse struct { Body []byte HTTPResponse *http.Response JSON400 *Problem @@ -3919,6 +4231,32 @@ func (r GetNodeLogsResponse) StatusCode() int { return 0 } +type GetNodeMonitorResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *NodeMonitorArray + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetNodeMonitorResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetNodeMonitorResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type PostNodeMonitorResponse struct { Body []byte HTTPResponse *http.Response @@ -3947,6 +4285,32 @@ func (r PostNodeMonitorResponse) StatusCode() int { return 0 } +type GetNodeStatusResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *NodeStatusArray + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetNodeStatusResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetNodeStatusResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type GetNodesInfoResponse struct { Body []byte HTTPResponse *http.Response @@ -4720,6 +5084,15 @@ func (c *ClientWithResponses) GetNetworksWithResponse(ctx context.Context, param return ParseGetNetworksResponse(rsp) } +// GetNodeWithResponse request returning *GetNodeResponse +func (c *ClientWithResponses) GetNodeWithResponse(ctx context.Context, params *GetNodeParams, reqEditors ...RequestEditorFn) (*GetNodeResponse, error) { + rsp, err := c.GetNode(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetNodeResponse(rsp) +} + // GetNodeBacklogsWithResponse request returning *GetNodeBacklogsResponse func (c *ClientWithResponses) GetNodeBacklogsWithResponse(ctx context.Context, params *GetNodeBacklogsParams, reqEditors ...RequestEditorFn) (*GetNodeBacklogsResponse, error) { rsp, err := c.GetNodeBacklogs(ctx, params, reqEditors...) @@ -4738,6 +5111,15 @@ func (c *ClientWithResponses) PostNodeClearWithResponse(ctx context.Context, req return ParsePostNodeClearResponse(rsp) } +// GetNodeConfigWithResponse request returning *GetNodeConfigResponse +func (c *ClientWithResponses) GetNodeConfigWithResponse(ctx context.Context, params *GetNodeConfigParams, reqEditors ...RequestEditorFn) (*GetNodeConfigResponse, error) { + rsp, err := c.GetNodeConfig(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetNodeConfigResponse(rsp) +} + // GetNodeDRBDAllocationWithResponse request returning *GetNodeDRBDAllocationResponse func (c *ClientWithResponses) GetNodeDRBDAllocationWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetNodeDRBDAllocationResponse, error) { rsp, err := c.GetNodeDRBDAllocation(ctx, reqEditors...) @@ -4782,6 +5164,15 @@ func (c *ClientWithResponses) GetNodeLogsWithResponse(ctx context.Context, param return ParseGetNodeLogsResponse(rsp) } +// GetNodeMonitorWithResponse request returning *GetNodeMonitorResponse +func (c *ClientWithResponses) GetNodeMonitorWithResponse(ctx context.Context, params *GetNodeMonitorParams, reqEditors ...RequestEditorFn) (*GetNodeMonitorResponse, error) { + rsp, err := c.GetNodeMonitor(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetNodeMonitorResponse(rsp) +} + // PostNodeMonitorWithBodyWithResponse request with arbitrary body returning *PostNodeMonitorResponse func (c *ClientWithResponses) PostNodeMonitorWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostNodeMonitorResponse, error) { rsp, err := c.PostNodeMonitorWithBody(ctx, contentType, body, reqEditors...) @@ -4799,6 +5190,15 @@ func (c *ClientWithResponses) PostNodeMonitorWithResponse(ctx context.Context, b return ParsePostNodeMonitorResponse(rsp) } +// GetNodeStatusWithResponse request returning *GetNodeStatusResponse +func (c *ClientWithResponses) GetNodeStatusWithResponse(ctx context.Context, params *GetNodeStatusParams, reqEditors ...RequestEditorFn) (*GetNodeStatusResponse, error) { + rsp, err := c.GetNodeStatus(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetNodeStatusResponse(rsp) +} + // GetNodesInfoWithResponse request returning *GetNodesInfoResponse func (c *ClientWithResponses) GetNodesInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetNodesInfoResponse, error) { rsp, err := c.GetNodesInfo(ctx, reqEditors...) @@ -5860,6 +6260,60 @@ func ParseGetNetworksResponse(rsp *http.Response) (*GetNetworksResponse, error) return response, nil } +// ParseGetNodeResponse parses an HTTP response from a GetNodeWithResponse call +func ParseGetNodeResponse(rsp *http.Response) (*GetNodeResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetNodeResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest NodeArray + 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 +} + // ParseGetNodeBacklogsResponse parses an HTTP response from a GetNodeBacklogsWithResponse call func ParseGetNodeBacklogsResponse(rsp *http.Response) (*GetNodeBacklogsResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -5961,6 +6415,60 @@ func ParsePostNodeClearResponse(rsp *http.Response) (*PostNodeClearResponse, err return response, nil } +// ParseGetNodeConfigResponse parses an HTTP response from a GetNodeConfigWithResponse call +func ParseGetNodeConfigResponse(rsp *http.Response) (*GetNodeConfigResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetNodeConfigResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest NodeConfigArray + 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 +} + // ParseGetNodeDRBDAllocationResponse parses an HTTP response from a GetNodeDRBDAllocationWithResponse call func ParseGetNodeDRBDAllocationResponse(rsp *http.Response) (*GetNodeDRBDAllocationResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -6135,6 +6643,60 @@ func ParseGetNodeLogsResponse(rsp *http.Response) (*GetNodeLogsResponse, error) return response, nil } +// ParseGetNodeMonitorResponse parses an HTTP response from a GetNodeMonitorWithResponse call +func ParseGetNodeMonitorResponse(rsp *http.Response) (*GetNodeMonitorResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetNodeMonitorResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest NodeMonitorArray + 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 +} + // ParsePostNodeMonitorResponse parses an HTTP response from a PostNodeMonitorWithResponse call func ParsePostNodeMonitorResponse(rsp *http.Response) (*PostNodeMonitorResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -6203,6 +6765,60 @@ func ParsePostNodeMonitorResponse(rsp *http.Response) (*PostNodeMonitorResponse, return response, nil } +// ParseGetNodeStatusResponse parses an HTTP response from a GetNodeStatusWithResponse call +func ParseGetNodeStatusResponse(rsp *http.Response) (*GetNodeStatusResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetNodeStatusResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest NodeStatusArray + 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 +} + // ParseGetNodesInfoResponse parses an HTTP response from a GetNodesInfoWithResponse call func ParseGetNodesInfoResponse(rsp *http.Response) (*GetNodesInfoResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index 350aa6b2e..845b240ea 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -69,12 +69,18 @@ type ServerInterface interface { // (GET /networks) GetNetworks(ctx echo.Context, params GetNetworksParams) error + // (GET /node) + GetNode(ctx echo.Context, params GetNodeParams) error + // (GET /node/backlogs) GetNodeBacklogs(ctx echo.Context, params GetNodeBacklogsParams) error // (POST /node/clear) PostNodeClear(ctx echo.Context) error + // (GET /node/config) + GetNodeConfig(ctx echo.Context, params GetNodeConfigParams) error + // (GET /node/drbd/allocation) GetNodeDRBDAllocation(ctx echo.Context) error @@ -87,9 +93,15 @@ type ServerInterface interface { // (GET /node/logs) GetNodeLogs(ctx echo.Context, params GetNodeLogsParams) error + // (GET /node/monitor) + GetNodeMonitor(ctx echo.Context, params GetNodeMonitorParams) error + // (POST /node/monitor) PostNodeMonitor(ctx echo.Context) error + // (GET /node/status) + GetNodeStatus(ctx echo.Context, params GetNodeStatusParams) error + // (GET /nodes/info) GetNodesInfo(ctx echo.Context) error @@ -519,6 +531,28 @@ func (w *ServerInterfaceWrapper) GetNetworks(ctx echo.Context) error { return err } +// GetNode converts echo context to params. +func (w *ServerInterfaceWrapper) GetNode(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 GetNodeParams + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetNode(ctx, params) + return err +} + // GetNodeBacklogs converts echo context to params. func (w *ServerInterfaceWrapper) GetNodeBacklogs(ctx echo.Context) error { var err error @@ -561,6 +595,28 @@ func (w *ServerInterfaceWrapper) PostNodeClear(ctx echo.Context) error { return err } +// GetNodeConfig converts echo context to params. +func (w *ServerInterfaceWrapper) GetNodeConfig(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 GetNodeConfigParams + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetNodeConfig(ctx, params) + return err +} + // GetNodeDRBDAllocation converts echo context to params. func (w *ServerInterfaceWrapper) GetNodeDRBDAllocation(ctx echo.Context) error { var err error @@ -647,6 +703,28 @@ func (w *ServerInterfaceWrapper) GetNodeLogs(ctx echo.Context) error { return err } +// GetNodeMonitor converts echo context to params. +func (w *ServerInterfaceWrapper) GetNodeMonitor(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 GetNodeMonitorParams + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetNodeMonitor(ctx, params) + return err +} + // PostNodeMonitor converts echo context to params. func (w *ServerInterfaceWrapper) PostNodeMonitor(ctx echo.Context) error { var err error @@ -660,6 +738,28 @@ func (w *ServerInterfaceWrapper) PostNodeMonitor(ctx echo.Context) error { return err } +// GetNodeStatus converts echo context to params. +func (w *ServerInterfaceWrapper) GetNodeStatus(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 GetNodeStatusParams + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetNodeStatus(ctx, params) + return err +} + // GetNodesInfo converts echo context to params. func (w *ServerInterfaceWrapper) GetNodesInfo(ctx echo.Context) error { var err error @@ -1097,13 +1197,17 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/instance/status", wrapper.GetInstanceStatus) router.POST(baseURL+"/instance/status", wrapper.PostInstanceStatus) router.GET(baseURL+"/networks", wrapper.GetNetworks) + router.GET(baseURL+"/node", wrapper.GetNode) router.GET(baseURL+"/node/backlogs", wrapper.GetNodeBacklogs) router.POST(baseURL+"/node/clear", wrapper.PostNodeClear) + router.GET(baseURL+"/node/config", wrapper.GetNodeConfig) router.GET(baseURL+"/node/drbd/allocation", wrapper.GetNodeDRBDAllocation) router.GET(baseURL+"/node/drbd/config", wrapper.GetNodeDRBDConfig) router.POST(baseURL+"/node/drbd/config", wrapper.PostNodeDRBDConfig) router.GET(baseURL+"/node/logs", wrapper.GetNodeLogs) + router.GET(baseURL+"/node/monitor", wrapper.GetNodeMonitor) router.POST(baseURL+"/node/monitor", wrapper.PostNodeMonitor) + router.GET(baseURL+"/node/status", wrapper.GetNodeStatus) router.GET(baseURL+"/nodes/info", wrapper.GetNodesInfo) router.POST(baseURL+"/object/action/abort", wrapper.PostObjectActionAbort) router.POST(baseURL+"/object/action/delete", wrapper.PostObjectActionDelete) @@ -1133,115 +1237,122 @@ 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 5e48fe645..0e1ee6359 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -8,6 +8,7 @@ import ( openapi_types "github.com/deepmap/oapi-codegen/pkg/types" "github.com/opensvc/om3/core/instance" + "github.com/opensvc/om3/core/node" ) const ( @@ -87,6 +88,12 @@ const ( Flex Topology = "flex" ) +// ArbitratorStatus defines model for ArbitratorStatus. +type ArbitratorStatus struct { + Status Status `json:"status"` + Url string `json:"url"` +} + // AuthToken defines model for AuthToken. type AuthToken struct { ExpiredAt time.Time `json:"expired_at"` @@ -327,6 +334,28 @@ type NetworkStatusUsage struct { Used int `json:"used"` } +// Node defines model for Node. +type Node struct { + Config *NodeConfig `json:"config,omitempty"` + Monitor *NodeMonitor `json:"monitor,omitempty"` + Status *NodeStatus `json:"status,omitempty"` +} + +// NodeArray defines model for NodeArray. +type NodeArray = []NodeItem + +// NodeConfig defines model for NodeConfig. +type NodeConfig = node.Config + +// NodeConfigArray defines model for NodeConfigArray. +type NodeConfigArray = []NodeConfigItem + +// NodeConfigItem defines model for NodeConfigItem. +type NodeConfigItem struct { + Data NodeConfig `json:"data"` + Meta NodeMeta `json:"meta"` +} + // NodeInfo defines model for NodeInfo. type NodeInfo struct { // Labels labels is the list of node labels. @@ -339,6 +368,12 @@ type NodeInfo struct { Paths []SANPath `json:"paths"` } +// NodeItem defines model for NodeItem. +type NodeItem struct { + Data Node `json:"data"` + Meta NodeMeta `json:"meta"` +} + // NodeLabel defines model for NodeLabel. type NodeLabel struct { // Name name is the label name. @@ -348,6 +383,35 @@ type NodeLabel struct { Value string `json:"value"` } +// NodeMeta defines model for NodeMeta. +type NodeMeta struct { + Node string `json:"node"` +} + +// NodeMonitor defines model for NodeMonitor. +type NodeMonitor = node.Monitor + +// NodeMonitorArray defines model for NodeMonitorArray. +type NodeMonitorArray = []NodeMonitorItem + +// NodeMonitorItem defines model for NodeMonitorItem. +type NodeMonitorItem struct { + Data NodeMonitor `json:"data"` + Meta NodeMeta `json:"meta"` +} + +// NodeStatus defines model for NodeStatus. +type NodeStatus = node.Status + +// NodeStatusArray defines model for NodeStatusArray. +type NodeStatusArray = []NodeStatusItem + +// NodeStatusItem defines model for NodeStatusItem. +type NodeStatusItem struct { + Data NodeStatus `json:"data"` + Meta NodeMeta `json:"meta"` +} + // NodesInfo defines model for NodesInfo. type NodesInfo = []NodeInfo @@ -765,6 +829,12 @@ type GetNetworksParams struct { Name *string `form:"name,omitempty" json:"name,omitempty"` } +// GetNodeParams defines parameters for GetNode. +type GetNodeParams struct { + // Node object and instance selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` +} + // GetNodeBacklogsParams defines parameters for GetNodeBacklogs. type GetNodeBacklogsParams struct { // Filter list of log filter @@ -774,6 +844,12 @@ type GetNodeBacklogsParams struct { Paths Paths `form:"paths" json:"paths"` } +// GetNodeConfigParams defines parameters for GetNodeConfig. +type GetNodeConfigParams struct { + // Node object and instance selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` +} + // GetNodeDRBDConfigParams defines parameters for GetNodeDRBDConfig. type GetNodeDRBDConfigParams struct { // Name the full path of the file is deduced from the name @@ -795,6 +871,18 @@ type GetNodeLogsParams struct { Paths Paths `form:"paths" json:"paths"` } +// GetNodeMonitorParams defines parameters for GetNodeMonitor. +type GetNodeMonitorParams struct { + // Node object and instance selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` +} + +// GetNodeStatusParams defines parameters for GetNodeStatus. +type GetNodeStatusParams struct { + // Node object and instance selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` +} + // GetObjectBacklogsParams defines parameters for GetObjectBacklogs. type GetObjectBacklogsParams struct { // Filter list of log filter diff --git a/daemon/daemonapi/get_node.go b/daemon/daemonapi/get_node.go new file mode 100644 index 000000000..5f72c323b --- /dev/null +++ b/daemon/daemonapi/get_node.go @@ -0,0 +1,43 @@ +package daemonapi + +import ( + "net/http" + + "github.com/labstack/echo/v4" + "github.com/rs/zerolog/log" + + "github.com/opensvc/om3/core/node" + "github.com/opensvc/om3/daemon/api" +) + +func (a *DaemonApi) GetNode(ctx echo.Context, params api.GetNodeParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + configs := node.ConfigData.GetAll() + l := make(api.NodeArray, 0) + for _, config := range configs { + if !meta.HasNode(config.Node) { + continue + } + monitor := node.MonitorData.Get(config.Node) + status := node.StatusData.Get(config.Node) + d := api.NodeItem{ + Meta: api.NodeMeta{ + Node: config.Node, + }, + Data: api.Node{ + Config: config.Value, + Monitor: monitor, + Status: status, + }, + } + l = append(l, d) + } + return ctx.JSON(http.StatusOK, l) +} diff --git a/daemon/daemonapi/get_node_config.go b/daemon/daemonapi/get_node_config.go new file mode 100644 index 000000000..c1436b648 --- /dev/null +++ b/daemon/daemonapi/get_node_config.go @@ -0,0 +1,37 @@ +package daemonapi + +import ( + "net/http" + + "github.com/labstack/echo/v4" + "github.com/rs/zerolog/log" + + "github.com/opensvc/om3/core/node" + "github.com/opensvc/om3/daemon/api" +) + +func (a *DaemonApi) GetNodeConfig(ctx echo.Context, params api.GetNodeConfigParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + data := node.ConfigData.GetAll() + l := make(api.NodeConfigArray, 0) + for _, e := range data { + if !meta.HasNode(e.Node) { + continue + } + d := api.NodeConfigItem{ + Meta: api.NodeMeta{ + Node: e.Node, + }, + Data: api.NodeConfig(*e.Value), + } + l = append(l, d) + } + return ctx.JSON(http.StatusOK, l) +} diff --git a/daemon/daemonapi/get_node_monitor.go b/daemon/daemonapi/get_node_monitor.go new file mode 100644 index 000000000..6c666bdde --- /dev/null +++ b/daemon/daemonapi/get_node_monitor.go @@ -0,0 +1,38 @@ +package daemonapi + +import ( + "net/http" + + "github.com/labstack/echo/v4" + "github.com/rs/zerolog/log" + + "github.com/opensvc/om3/core/node" + "github.com/opensvc/om3/daemon/api" +) + +// GetNetworks returns network status list. +func (a *DaemonApi) GetNodeMonitor(ctx echo.Context, params api.GetNodeMonitorParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + data := node.MonitorData.GetAll() + l := make(api.NodeMonitorArray, 0) + for _, e := range data { + if !meta.HasNode(e.Node) { + continue + } + d := api.NodeMonitorItem{ + Meta: api.NodeMeta{ + Node: e.Node, + }, + Data: api.NodeMonitor(*e.Value), + } + l = append(l, d) + } + return ctx.JSON(http.StatusOK, l) +} diff --git a/daemon/daemonapi/get_node_status.go b/daemon/daemonapi/get_node_status.go new file mode 100644 index 000000000..c57dc13a8 --- /dev/null +++ b/daemon/daemonapi/get_node_status.go @@ -0,0 +1,38 @@ +package daemonapi + +import ( + "net/http" + + "github.com/labstack/echo/v4" + "github.com/rs/zerolog/log" + + "github.com/opensvc/om3/core/node" + "github.com/opensvc/om3/daemon/api" +) + +// GetNetworks returns network status list. +func (a *DaemonApi) GetNodeStatus(ctx echo.Context, params api.GetNodeStatusParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + data := node.StatusData.GetAll() + l := make(api.NodeStatusArray, 0) + for _, e := range data { + if !meta.HasNode(e.Node) { + continue + } + d := api.NodeStatusItem{ + Meta: api.NodeMeta{ + Node: e.Node, + }, + Data: api.NodeStatus(*e.Value), + } + l = append(l, d) + } + return ctx.JSON(http.StatusOK, l) +} diff --git a/daemon/daemondata/data_init.go b/daemon/daemondata/data_init.go index 6975fd2df..7e40d3c00 100644 --- a/daemon/daemondata/data_init.go +++ b/daemon/daemondata/data_init.go @@ -7,7 +7,6 @@ import ( "github.com/opensvc/om3/core/cluster" "github.com/opensvc/om3/core/instance" "github.com/opensvc/om3/core/node" - "github.com/opensvc/om3/core/nodesinfo" "github.com/opensvc/om3/core/object" "github.com/opensvc/om3/core/rawconfig" "github.com/opensvc/om3/daemon/msgbus" @@ -88,7 +87,7 @@ func newNodeData(localNode string) node.Node { Compat: 12, FrozenAt: frozen, Gen: map[string]uint64{localNode: 1}, - Labels: nodesinfo.Labels{}, + Labels: node.Labels{}, MinAvailMemPct: 0, MinAvailSwapPct: 0, IsSpeaker: false, diff --git a/daemon/msgbus/messages.go b/daemon/msgbus/messages.go index 05d12bfed..ed808658a 100644 --- a/daemon/msgbus/messages.go +++ b/daemon/msgbus/messages.go @@ -13,7 +13,6 @@ import ( "github.com/opensvc/om3/core/event" "github.com/opensvc/om3/core/instance" "github.com/opensvc/om3/core/node" - "github.com/opensvc/om3/core/nodesinfo" "github.com/opensvc/om3/core/object" "github.com/opensvc/om3/core/path" "github.com/opensvc/om3/util/pubsub" @@ -255,7 +254,7 @@ type ( // Exec message describes an exec call Exec struct { pubsub.Msg `yaml:",inline"` - Command string `json:"command" yaml:"command"` + Command string `json:"command" yaml:"command"` // Node is the nodename that will call exec Node string `json:"node" yaml:"node"` // Origin describes the exec caller: example: imon, nmon, scheduler... @@ -266,9 +265,9 @@ type ( // ExecFailed message describes failed exec call ExecFailed struct { pubsub.Msg `yaml:",inline"` - Command string `json:"command" yaml:"command"` - Duration time.Duration `json:"duration" yaml:"duration"` - ErrS string `json:"error" yaml:"error"` + Command string `json:"command" yaml:"command"` + Duration time.Duration `json:"duration" yaml:"duration"` + ErrS string `json:"error" yaml:"error"` // Node is the nodename that called exec Node string `json:"node" yaml:"node"` // Origin describes the exec caller: example: imon, nmon, scheduler... @@ -279,8 +278,8 @@ type ( // ExecSuccess message describes successfully exec call ExecSuccess struct { pubsub.Msg `yaml:",inline"` - Command string `json:"command" yaml:"command"` - Duration time.Duration `json:"duration" yaml:"duration"` + Command string `json:"command" yaml:"command"` + Duration time.Duration `json:"duration" yaml:"duration"` // Node is the nodename that called exec Node string `json:"node" yaml:"node"` // Origin describes the exec caller: example: imon, nmon, scheduler... @@ -563,8 +562,8 @@ type ( NodeStatusLabelsUpdated struct { pubsub.Msg `yaml:",inline"` - Node string `json:"node" yaml:"node"` - Value nodesinfo.Labels `json:"node_labels" yaml:"node_labels"` + Node string `json:"node" yaml:"node"` + Value node.Labels `json:"node_labels" yaml:"node_labels"` } // NodeStatusUpdated is the message that nmon publish when node status is modified. diff --git a/daemon/nmon/main.go b/daemon/nmon/main.go index c0d7a4250..4e706de02 100644 --- a/daemon/nmon/main.go +++ b/daemon/nmon/main.go @@ -101,12 +101,12 @@ type ( labelLocalhost pubsub.Label - // cacheNodesInfo is a map of nodes to nodesinfo.NodeInfo, it is used to + // cacheNodesInfo is a map of nodes to node.NodeInfo, it is used to // maintain the nodesinfo.json file. // local values are computed by nmon. // peer values are updated from msgbus events NodeStatusLabelsUpdated, NodeConfigUpdated, NodeOsPathsUpdated // and ForgetPeer. - cacheNodesInfo map[string]nodesinfo.NodeInfo + cacheNodesInfo map[string]node.NodeInfo // nodeStatus is the node.Status for localhost that is the source of publication of msgbus.NodeStatusUpdated for // localhost. @@ -173,7 +173,7 @@ func Start(parent context.Context, drainDuration time.Duration) (context.CancelF frozen: true, // ensure initial frozen livePeers: map[string]bool{localhost: true}, - cacheNodesInfo: map[string]nodesinfo.NodeInfo{localhost: {}}, + cacheNodesInfo: map[string]node.NodeInfo{localhost: {}}, labelLocalhost: pubsub.Label{"node", localhost}, } From 919f18b26a74d764377308171a1cfaf03181f4f4 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Tue, 5 Sep 2023 09:33:11 +0200 Subject: [PATCH 09/30] Add /cluster handlers * POST /cluster/action/abort * POST /cluster/action/freeze * POST /cluster/action/unfreeze --- core/objectaction/object.go | 31 +- daemon/api/api.yaml | 107 +++- daemon/api/codegen_client_gen.go | 498 +++++++++++++++++- daemon/api/codegen_server_gen.go | 285 ++++++---- daemon/api/codegen_type_gen.go | 10 +- daemon/api/main.go | 2 +- daemon/daemonapi/post_cluster_action.go | 66 +++ daemon/daemonapi/post_node_monitor.go | 2 +- daemon/daemonapi/post_object_action.go | 2 +- daemon/daemonapi/post_object_action_switch.go | 2 +- 10 files changed, 815 insertions(+), 190 deletions(-) create mode 100644 daemon/daemonapi/post_cluster_action.go diff --git a/core/objectaction/object.go b/core/objectaction/object.go index f82f59ebd..a61c6a57b 100644 --- a/core/objectaction/object.go +++ b/core/objectaction/object.go @@ -656,10 +656,10 @@ func (t T) DoAsync() error { } } else { toWait++ - var monitorUpdateQueued api.MonitorUpdateQueued - if err := json.Unmarshal(b, &monitorUpdateQueued); err == nil { + var orchestrationQueued api.OrchestrationQueued + if err := json.Unmarshal(b, &orchestrationQueued); err == nil { r = result{ - OrchestrationId: monitorUpdateQueued.OrchestrationId, + OrchestrationId: orchestrationQueued.OrchestrationId, Path: p.String(), } } else { @@ -708,31 +708,6 @@ func (t T) DoAsync() error { // DoRemote posts the action to a peer node agent API, for synchronous // execution. func (t T) DoRemote() error { - /* - c, err := client.New(client.WithURL(t.Server)) - if err != nil { - return err - } - req := c.NewPostObjectAction() - req.ObjectSelector = t.ObjectSelector - req.NodeSelector = t.NodeSelector - req.Action = t.Action - req.Options = t.PostFlags - b, err := req.Do() - if err != nil { - return err - } - human := func() string { - s := fmt.Sprintln(string(b)) - return s - } - output.Renderer{ - Format: t.Format, - Color: t.Color, - Data: b, - HumanRenderer: human, - }.Print() - */ return fmt.Errorf("todo") } diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index 490a90a49..a7e4ea395 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -36,6 +36,87 @@ paths: $ref: '#/components/responses/500' 503: $ref: '#/components/responses/503' + /cluster/action/abort: + post: + operationId: PostClusterActionAbort + tags: + - cluster + security: + - basicAuth: [] + - bearerAuth: [] + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/OrchestrationQueued' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 408: + $ref: '#/components/responses/408' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + /cluster/action/freeze: + post: + operationId: PostClusterActionFreeze + tags: + - cluster + security: + - basicAuth: [] + - bearerAuth: [] + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/OrchestrationQueued' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 408: + $ref: '#/components/responses/408' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + /cluster/action/unfreeze: + post: + operationId: PostClusterActionUnfreeze + tags: + - cluster + security: + - basicAuth: [] + - bearerAuth: [] + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/OrchestrationQueued' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 408: + $ref: '#/components/responses/408' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' /daemon/dns/dump: get: operationId: GetDaemonDNSDump @@ -527,7 +608,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -927,7 +1008,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -961,7 +1042,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -995,7 +1076,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -1029,7 +1110,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -1063,7 +1144,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -1097,7 +1178,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -1131,7 +1212,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -1165,7 +1246,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -1199,7 +1280,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -1233,7 +1314,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -1267,7 +1348,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MonitorUpdateQueued' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: @@ -2114,7 +2195,7 @@ components: - no - start default: no - MonitorUpdateQueued: + OrchestrationQueued: type: object properties: orchestration_id: diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index 116a03ddc..5e14ea88e 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -92,6 +92,15 @@ type ClientInterface interface { // PostAuthToken request PostAuthToken(ctx context.Context, params *PostAuthTokenParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // PostClusterActionAbort request + PostClusterActionAbort(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + + // PostClusterActionFreeze request + PostClusterActionFreeze(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + + // PostClusterActionUnfreeze request + PostClusterActionUnfreeze(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetDaemonDNSDump request GetDaemonDNSDump(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -290,6 +299,42 @@ func (c *Client) PostAuthToken(ctx context.Context, params *PostAuthTokenParams, return c.Client.Do(req) } +func (c *Client) PostClusterActionAbort(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostClusterActionAbortRequest(c.Server) + 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) PostClusterActionFreeze(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostClusterActionFreezeRequest(c.Server) + 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) PostClusterActionUnfreeze(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostClusterActionUnfreezeRequest(c.Server) + 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) GetDaemonDNSDump(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetDaemonDNSDumpRequest(c.Server) if err != nil { @@ -1169,6 +1214,87 @@ func NewPostAuthTokenRequest(server string, params *PostAuthTokenParams) (*http. return req, nil } +// NewPostClusterActionAbortRequest generates requests for PostClusterActionAbort +func NewPostClusterActionAbortRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/cluster/action/abort") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewPostClusterActionFreezeRequest generates requests for PostClusterActionFreeze +func NewPostClusterActionFreezeRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/cluster/action/freeze") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewPostClusterActionUnfreezeRequest generates requests for PostClusterActionUnfreeze +func NewPostClusterActionUnfreezeRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/cluster/action/unfreeze") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewGetDaemonDNSDumpRequest generates requests for GetDaemonDNSDump func NewGetDaemonDNSDumpRequest(server string) (*http.Request, error) { var err error @@ -3445,6 +3571,15 @@ type ClientWithResponsesInterface interface { // PostAuthToken request PostAuthTokenWithResponse(ctx context.Context, params *PostAuthTokenParams, reqEditors ...RequestEditorFn) (*PostAuthTokenResponse, error) + // PostClusterActionAbort request + PostClusterActionAbortWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostClusterActionAbortResponse, error) + + // PostClusterActionFreeze request + PostClusterActionFreezeWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostClusterActionFreezeResponse, error) + + // PostClusterActionUnfreeze request + PostClusterActionUnfreezeWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostClusterActionUnfreezeResponse, error) + // GetDaemonDNSDump request GetDaemonDNSDumpWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetDaemonDNSDumpResponse, error) @@ -3657,6 +3792,90 @@ func (r PostAuthTokenResponse) StatusCode() int { return 0 } +type PostClusterActionAbortResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *OrchestrationQueued + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON408 *Problem + JSON409 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r PostClusterActionAbortResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r PostClusterActionAbortResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type PostClusterActionFreezeResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *OrchestrationQueued + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON408 *Problem + JSON409 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r PostClusterActionFreezeResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r PostClusterActionFreezeResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type PostClusterActionUnfreezeResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *OrchestrationQueued + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON408 *Problem + JSON409 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r PostClusterActionUnfreezeResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r PostClusterActionUnfreezeResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type GetDaemonDNSDumpResponse struct { Body []byte HTTPResponse *http.Response @@ -4260,7 +4479,7 @@ func (r GetNodeMonitorResponse) StatusCode() int { type PostNodeMonitorResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4339,7 +4558,7 @@ func (r GetNodesInfoResponse) StatusCode() int { type PostObjectActionAbortResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4367,7 +4586,7 @@ func (r PostObjectActionAbortResponse) StatusCode() int { type PostObjectActionDeleteResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4395,7 +4614,7 @@ func (r PostObjectActionDeleteResponse) StatusCode() int { type PostObjectActionFreezeResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4423,7 +4642,7 @@ func (r PostObjectActionFreezeResponse) StatusCode() int { type PostObjectActionGivebackResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4451,7 +4670,7 @@ func (r PostObjectActionGivebackResponse) StatusCode() int { type PostObjectActionProvisionResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4479,7 +4698,7 @@ func (r PostObjectActionProvisionResponse) StatusCode() int { type PostObjectActionPurgeResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4507,7 +4726,7 @@ func (r PostObjectActionPurgeResponse) StatusCode() int { type PostObjectActionStartResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4535,7 +4754,7 @@ func (r PostObjectActionStartResponse) StatusCode() int { type PostObjectActionStopResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4563,7 +4782,7 @@ func (r PostObjectActionStopResponse) StatusCode() int { type PostObjectActionSwitchResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4591,7 +4810,7 @@ func (r PostObjectActionSwitchResponse) StatusCode() int { type PostObjectActionUnfreezeResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4619,7 +4838,7 @@ func (r PostObjectActionUnfreezeResponse) StatusCode() int { type PostObjectActionUnprovisionResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *MonitorUpdateQueued + JSON200 *OrchestrationQueued JSON400 *Problem JSON401 *Problem JSON403 *Problem @@ -4925,6 +5144,33 @@ func (c *ClientWithResponses) PostAuthTokenWithResponse(ctx context.Context, par return ParsePostAuthTokenResponse(rsp) } +// PostClusterActionAbortWithResponse request returning *PostClusterActionAbortResponse +func (c *ClientWithResponses) PostClusterActionAbortWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostClusterActionAbortResponse, error) { + rsp, err := c.PostClusterActionAbort(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParsePostClusterActionAbortResponse(rsp) +} + +// PostClusterActionFreezeWithResponse request returning *PostClusterActionFreezeResponse +func (c *ClientWithResponses) PostClusterActionFreezeWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostClusterActionFreezeResponse, error) { + rsp, err := c.PostClusterActionFreeze(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParsePostClusterActionFreezeResponse(rsp) +} + +// PostClusterActionUnfreezeWithResponse request returning *PostClusterActionUnfreezeResponse +func (c *ClientWithResponses) PostClusterActionUnfreezeWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostClusterActionUnfreezeResponse, error) { + rsp, err := c.PostClusterActionUnfreeze(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParsePostClusterActionUnfreezeResponse(rsp) +} + // GetDaemonDNSDumpWithResponse request returning *GetDaemonDNSDumpResponse func (c *ClientWithResponses) GetDaemonDNSDumpWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetDaemonDNSDumpResponse, error) { rsp, err := c.GetDaemonDNSDump(ctx, reqEditors...) @@ -5572,6 +5818,210 @@ func ParsePostAuthTokenResponse(rsp *http.Response) (*PostAuthTokenResponse, err return response, nil } +// ParsePostClusterActionAbortResponse parses an HTTP response from a PostClusterActionAbortWithResponse call +func ParsePostClusterActionAbortResponse(rsp *http.Response) (*PostClusterActionAbortResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &PostClusterActionAbortResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest OrchestrationQueued + 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 == 408: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON408 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &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 +} + +// ParsePostClusterActionFreezeResponse parses an HTTP response from a PostClusterActionFreezeWithResponse call +func ParsePostClusterActionFreezeResponse(rsp *http.Response) (*PostClusterActionFreezeResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &PostClusterActionFreezeResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest OrchestrationQueued + 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 == 408: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON408 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &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 +} + +// ParsePostClusterActionUnfreezeResponse parses an HTTP response from a PostClusterActionUnfreezeWithResponse call +func ParsePostClusterActionUnfreezeResponse(rsp *http.Response) (*PostClusterActionUnfreezeResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &PostClusterActionUnfreezeResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest OrchestrationQueued + 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 == 408: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON408 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &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 +} + // ParseGetDaemonDNSDumpResponse parses an HTTP response from a GetDaemonDNSDumpWithResponse call func ParseGetDaemonDNSDumpResponse(rsp *http.Response) (*GetDaemonDNSDumpResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -6712,7 +7162,7 @@ func ParsePostNodeMonitorResponse(rsp *http.Response) (*PostNodeMonitorResponse, switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -6881,7 +7331,7 @@ func ParsePostObjectActionAbortResponse(rsp *http.Response) (*PostObjectActionAb switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -6949,7 +7399,7 @@ func ParsePostObjectActionDeleteResponse(rsp *http.Response) (*PostObjectActionD switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -7017,7 +7467,7 @@ func ParsePostObjectActionFreezeResponse(rsp *http.Response) (*PostObjectActionF switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -7085,7 +7535,7 @@ func ParsePostObjectActionGivebackResponse(rsp *http.Response) (*PostObjectActio switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -7153,7 +7603,7 @@ func ParsePostObjectActionProvisionResponse(rsp *http.Response) (*PostObjectActi switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -7221,7 +7671,7 @@ func ParsePostObjectActionPurgeResponse(rsp *http.Response) (*PostObjectActionPu switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -7289,7 +7739,7 @@ func ParsePostObjectActionStartResponse(rsp *http.Response) (*PostObjectActionSt switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -7357,7 +7807,7 @@ func ParsePostObjectActionStopResponse(rsp *http.Response) (*PostObjectActionSto switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -7425,7 +7875,7 @@ func ParsePostObjectActionSwitchResponse(rsp *http.Response) (*PostObjectActionS switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -7493,7 +7943,7 @@ func ParsePostObjectActionUnfreezeResponse(rsp *http.Response) (*PostObjectActio switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -7561,7 +8011,7 @@ func ParsePostObjectActionUnprovisionResponse(rsp *http.Response) (*PostObjectAc switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MonitorUpdateQueued + var dest OrchestrationQueued if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index 845b240ea..afbdc2b45 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -24,6 +24,15 @@ type ServerInterface interface { // (POST /auth/token) PostAuthToken(ctx echo.Context, params PostAuthTokenParams) error + // (POST /cluster/action/abort) + PostClusterActionAbort(ctx echo.Context) error + + // (POST /cluster/action/freeze) + PostClusterActionFreeze(ctx echo.Context) error + + // (POST /cluster/action/unfreeze) + PostClusterActionUnfreeze(ctx echo.Context) error + // (GET /daemon/dns/dump) GetDaemonDNSDump(ctx echo.Context) error @@ -206,6 +215,45 @@ func (w *ServerInterfaceWrapper) PostAuthToken(ctx echo.Context) error { return err } +// PostClusterActionAbort converts echo context to params. +func (w *ServerInterfaceWrapper) PostClusterActionAbort(ctx echo.Context) error { + var err error + + ctx.Set(BasicAuthScopes, []string{""}) + + ctx.Set(BearerAuthScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.PostClusterActionAbort(ctx) + return err +} + +// PostClusterActionFreeze converts echo context to params. +func (w *ServerInterfaceWrapper) PostClusterActionFreeze(ctx echo.Context) error { + var err error + + ctx.Set(BasicAuthScopes, []string{""}) + + ctx.Set(BearerAuthScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.PostClusterActionFreeze(ctx) + return err +} + +// PostClusterActionUnfreeze converts echo context to params. +func (w *ServerInterfaceWrapper) PostClusterActionUnfreeze(ctx echo.Context) error { + var err error + + ctx.Set(BasicAuthScopes, []string{""}) + + ctx.Set(BearerAuthScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.PostClusterActionUnfreeze(ctx) + return err +} + // GetDaemonDNSDump converts echo context to params. func (w *ServerInterfaceWrapper) GetDaemonDNSDump(ctx echo.Context) error { var err error @@ -1182,6 +1230,9 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL } router.POST(baseURL+"/auth/token", wrapper.PostAuthToken) + router.POST(baseURL+"/cluster/action/abort", wrapper.PostClusterActionAbort) + router.POST(baseURL+"/cluster/action/freeze", wrapper.PostClusterActionFreeze) + router.POST(baseURL+"/cluster/action/unfreeze", wrapper.PostClusterActionUnfreeze) router.GET(baseURL+"/daemon/dns/dump", wrapper.GetDaemonDNSDump) router.GET(baseURL+"/daemon/events", wrapper.GetDaemonEvents) router.POST(baseURL+"/daemon/join", wrapper.PostDaemonJoin) @@ -1237,122 +1288,124 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", + "3AAA", } // 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 0e1ee6359..1a67ccc81 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -300,11 +300,6 @@ type InstanceStatusItem struct { // LogList responseLogList is a list of sse type LogList = openapi_types.File -// MonitorUpdateQueued defines model for MonitorUpdateQueued. -type MonitorUpdateQueued struct { - OrchestrationId openapi_types.UUID `json:"orchestration_id"` -} - // NetworkStatus defines model for NetworkStatus. type NetworkStatus struct { Errors *[]string `json:"errors,omitempty"` @@ -433,6 +428,11 @@ type ObjectPaths = []string // Orchestrate defines model for Orchestrate. type Orchestrate string +// OrchestrationQueued defines model for OrchestrationQueued. +type OrchestrationQueued struct { + OrchestrationId openapi_types.UUID `json:"orchestration_id"` +} + // Placement object placement policy type Placement string diff --git a/daemon/api/main.go b/daemon/api/main.go index 93f2172af..c0516ed73 100644 --- a/daemon/api/main.go +++ b/daemon/api/main.go @@ -6,7 +6,7 @@ package api import "fmt" -func (t MonitorUpdateQueued) String() (out string) { +func (t OrchestrationQueued) String() (out string) { return fmt.Sprint(t.OrchestrationId) } diff --git a/daemon/daemonapi/post_cluster_action.go b/daemon/daemonapi/post_cluster_action.go new file mode 100644 index 000000000..9138eae20 --- /dev/null +++ b/daemon/daemonapi/post_cluster_action.go @@ -0,0 +1,66 @@ +package daemonapi + +import ( + "errors" + "net/http" + "time" + + "github.com/google/uuid" + "github.com/labstack/echo/v4" + "github.com/opensvc/om3/core/node" + "github.com/opensvc/om3/daemon/api" + "github.com/opensvc/om3/daemon/msgbus" + "github.com/opensvc/om3/util/hostname" +) + +func (a *DaemonApi) PostClusterActionAbort(ctx echo.Context) error { + return a.PostClusterAction(ctx, node.MonitorGlobalExpectAborted) +} + +func (a *DaemonApi) PostClusterActionFreeze(ctx echo.Context) error { + return a.PostClusterAction(ctx, node.MonitorGlobalExpectFrozen) +} + +func (a *DaemonApi) PostClusterActionUnfreeze(ctx echo.Context) error { + return a.PostClusterAction(ctx, node.MonitorGlobalExpectThawed) +} + +func (a *DaemonApi) PostClusterAction(ctx echo.Context, globalExpect node.MonitorGlobalExpect) error { + var ( + value = node.MonitorUpdate{} + ) + if mon := node.MonitorData.Get(hostname.Hostname()); mon == nil { + return JSONProblemf(ctx, http.StatusNotFound, "Not found", "node monitor not found: %s", hostname.Hostname()) + } + value = node.MonitorUpdate{ + GlobalExpect: &globalExpect, + CandidateOrchestrationId: uuid.New(), + } + msg := msgbus.SetNodeMonitor{ + Node: hostname.Hostname(), + Value: value, + Err: make(chan error), + } + a.EventBus.Pub(&msg, labelNode, labelApi) + ticker := time.NewTicker(300 * time.Millisecond) + defer ticker.Stop() + var errs error + for { + select { + case <-ticker.C: + return JSONProblemf(ctx, http.StatusRequestTimeout, "set monitor", "timeout waiting for monitor commit") + case err := <-msg.Err: + if err != nil { + errs = errors.Join(errs, err) + } else if errs != nil { + return JSONProblemf(ctx, http.StatusConflict, "set monitor", "%s", errs) + } else { + return ctx.JSON(http.StatusOK, api.OrchestrationQueued{ + OrchestrationId: value.CandidateOrchestrationId, + }) + } + case <-ctx.Request().Context().Done(): + return JSONProblemf(ctx, http.StatusGone, "set monitor", "") + } + } +} diff --git a/daemon/daemonapi/post_node_monitor.go b/daemon/daemonapi/post_node_monitor.go index a09339fd7..24717d2b5 100644 --- a/daemon/daemonapi/post_node_monitor.go +++ b/daemon/daemonapi/post_node_monitor.go @@ -56,7 +56,7 @@ func (a *DaemonApi) PostNodeMonitor(ctx echo.Context) error { } else if errs != nil { return JSONProblemf(ctx, http.StatusConflict, "set monitor", "%s", errs) } else { - return ctx.JSON(http.StatusOK, api.MonitorUpdateQueued{ + return ctx.JSON(http.StatusOK, api.OrchestrationQueued{ OrchestrationId: update.CandidateOrchestrationId, }) } diff --git a/daemon/daemonapi/post_object_action.go b/daemon/daemonapi/post_object_action.go index 6d29f5369..2f52ee0b2 100644 --- a/daemon/daemonapi/post_object_action.go +++ b/daemon/daemonapi/post_object_action.go @@ -97,7 +97,7 @@ func (a *DaemonApi) PostObjectAction(ctx echo.Context, globalExpect instance.Mon } else if errs != nil { return JSONProblemf(ctx, http.StatusConflict, "set monitor", "%s", errs) } else { - return ctx.JSON(http.StatusOK, api.MonitorUpdateQueued{ + return ctx.JSON(http.StatusOK, api.OrchestrationQueued{ OrchestrationId: value.CandidateOrchestrationId, }) } diff --git a/daemon/daemonapi/post_object_action_switch.go b/daemon/daemonapi/post_object_action_switch.go index ccc099967..fb6b1ddd1 100644 --- a/daemon/daemonapi/post_object_action_switch.go +++ b/daemon/daemonapi/post_object_action_switch.go @@ -61,7 +61,7 @@ func (a *DaemonApi) PostObjectActionSwitch(ctx echo.Context) error { } else if errs != nil { return JSONProblemf(ctx, http.StatusConflict, "set monitor", "%s", errs) } else { - return ctx.JSON(http.StatusOK, api.MonitorUpdateQueued{ + return ctx.JSON(http.StatusOK, api.OrchestrationQueued{ OrchestrationId: value.CandidateOrchestrationId, }) } From 6c21dbc2927d2bcadedd53fb7f498cd793ea3622 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Tue, 5 Sep 2023 10:37:42 +0200 Subject: [PATCH 10/30] Use POST /cluster/action/* and POST /node/action/drain from cmd --- core/nodeaction/node.go | 133 ++++++---- daemon/api/api.yaml | 47 ++-- daemon/api/codegen_client_gen.go | 337 ++++++++++++-------------- daemon/api/codegen_server_gen.go | 269 ++++++++++---------- daemon/api/codegen_type_gen.go | 10 - daemon/daemonapi/post_node_drain.go | 55 +++++ daemon/daemonapi/post_node_monitor.go | 67 ----- 7 files changed, 444 insertions(+), 474 deletions(-) create mode 100644 daemon/daemonapi/post_node_drain.go delete mode 100644 daemon/daemonapi/post_node_monitor.go diff --git a/core/nodeaction/node.go b/core/nodeaction/node.go index ceb965c67..c642f51ae 100644 --- a/core/nodeaction/node.go +++ b/core/nodeaction/node.go @@ -225,6 +225,7 @@ func (t T) DoAsync() error { cancel context.CancelFunc expectation any waitC = make(chan error) + b []byte ) c, err := client.New(client.WithURL(t.Server), client.WithTimeout(0)) if err != nil { @@ -237,59 +238,103 @@ func (t T) DoAsync() error { ctx, cancel = context.WithCancel(context.Background()) defer cancel() } - params := api.PostNodeMonitor{} switch t.Target { - case "": case node.MonitorStateDrained.String(): - s := t.Target - params.LocalExpect = &s - expectation = node.MonitorStateDrained - default: - if globalExpect, ok := node.MonitorGlobalExpectValues[t.Target]; ok { - s := t.Target - params.GlobalExpect = &s - expectation = globalExpect + if resp, e := c.PostNodeActionDrainWithResponse(ctx); e != nil { + err = e } else { - return fmt.Errorf("unexpected global expect value %s", t.Target) + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } } - } - if t.Wait { - go t.waitExpectation(ctx, c, expectation, waitC) - } - resp, err := c.PostNodeMonitorWithResponse(ctx, params) - if err != nil { - return err - } - switch resp.StatusCode() { - case http.StatusOK: - human := func() string { - s := fmt.Sprintln(resp.JSON200) - return s + case node.MonitorGlobalExpectAborted.String(): + if resp, e := c.PostClusterActionAbortWithResponse(ctx); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } + } + case node.MonitorGlobalExpectFrozen.String(): + if resp, e := c.PostClusterActionFreezeWithResponse(ctx); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } + } + case node.MonitorGlobalExpectThawed.String(): + if resp, e := c.PostClusterActionUnfreezeWithResponse(ctx); e != nil { + err = e + } else { + switch resp.StatusCode() { + case http.StatusOK: + b = resp.Body + case 400: + err = fmt.Errorf("%s", resp.JSON400) + case 401: + err = fmt.Errorf("%s", resp.JSON401) + case 403: + err = fmt.Errorf("%s", resp.JSON403) + case 408: + err = fmt.Errorf("%s", resp.JSON408) + case 409: + err = fmt.Errorf("%s", resp.JSON409) + case 500: + err = fmt.Errorf("%s", resp.JSON500) + } } - output.Renderer{ - Format: t.Format, - Color: t.Color, - Data: resp.JSON200, - HumanRenderer: human, - Colorize: rawconfig.Colorize, - }.Print() - case 400: - return fmt.Errorf("%s", resp.JSON400) - case 401: - return fmt.Errorf("%s", resp.JSON401) - case 403: - return fmt.Errorf("%s", resp.JSON403) - case 408: - return fmt.Errorf("%s", resp.JSON408) - case 409: - return fmt.Errorf("%s", resp.JSON409) - case 500: - return fmt.Errorf("%s", resp.JSON500) default: - return fmt.Errorf("unexpected status code %s", resp.Status()) + return fmt.Errorf("unexpected target: %s", t.Target) + } + var orchestrationQueued api.OrchestrationQueued + if err := json.Unmarshal(b, &orchestrationQueued); err == nil { + fmt.Println(orchestrationQueued.OrchestrationId) + } else { + fmt.Fprintln(os.Stderr, err) } if t.Wait { + go t.waitExpectation(ctx, c, expectation, waitC) select { case <-ctx.Done(): return ctx.Err() diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index a7e4ea395..c6060ea58 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -563,62 +563,56 @@ paths: $ref: '#/components/responses/403' 500: $ref: '#/components/responses/500' - /node/monitor: - get: - operationId: GetNodeMonitor + /node/action/drain: + post: + operationId: PostNodeActionDrain tags: - node security: - basicAuth: [] - bearerAuth: [] - parameters: - - $ref: '#/components/parameters/NodeOptional' responses: 200: - description: get node monitor + description: OK content: application/json: schema: - $ref: '#/components/schemas/NodeMonitorArray' + $ref: '#/components/schemas/OrchestrationQueued' 400: $ref: '#/components/responses/400' 401: $ref: '#/components/responses/401' 403: $ref: '#/components/responses/403' + 408: + $ref: '#/components/responses/408' + 409: + $ref: '#/components/responses/409' 500: $ref: '#/components/responses/500' - post: - operationId: PostNodeMonitor + /node/monitor: + get: + operationId: GetNodeMonitor tags: - node security: - basicAuth: [] - bearerAuth: [] - requestBody: - description: monitor - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PostNodeMonitor' + parameters: + - $ref: '#/components/parameters/NodeOptional' responses: 200: - description: OK + description: get node monitor content: application/json: schema: - $ref: '#/components/schemas/OrchestrationQueued' + $ref: '#/components/schemas/NodeMonitorArray' 400: $ref: '#/components/responses/400' 401: $ref: '#/components/responses/401' 403: $ref: '#/components/responses/403' - 408: - $ref: '#/components/responses/408' - 409: - $ref: '#/components/responses/409' 500: $ref: '#/components/responses/500' /node/status: @@ -2328,15 +2322,6 @@ components: data: type: string format: byte - PostNodeMonitor: - type: object - properties: - local_expect: - type: string - global_expect: - type: string - state: - type: string PostObjectClear: type: object required: diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index 5e14ea88e..7082ed94d 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -155,6 +155,9 @@ type ClientInterface interface { // GetNode request GetNode(ctx context.Context, params *GetNodeParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // PostNodeActionDrain request + PostNodeActionDrain(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetNodeBacklogs request GetNodeBacklogs(ctx context.Context, params *GetNodeBacklogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -181,11 +184,6 @@ type ClientInterface interface { // GetNodeMonitor request GetNodeMonitor(ctx context.Context, params *GetNodeMonitorParams, reqEditors ...RequestEditorFn) (*http.Response, error) - // PostNodeMonitor request with any body - PostNodeMonitorWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostNodeMonitor(ctx context.Context, body PostNodeMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // GetNodeStatus request GetNodeStatus(ctx context.Context, params *GetNodeStatusParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -563,6 +561,18 @@ func (c *Client) GetNode(ctx context.Context, params *GetNodeParams, reqEditors return c.Client.Do(req) } +func (c *Client) PostNodeActionDrain(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostNodeActionDrainRequest(c.Server) + 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) GetNodeBacklogs(ctx context.Context, params *GetNodeBacklogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetNodeBacklogsRequest(c.Server, params) if err != nil { @@ -671,30 +681,6 @@ func (c *Client) GetNodeMonitor(ctx context.Context, params *GetNodeMonitorParam return c.Client.Do(req) } -func (c *Client) PostNodeMonitorWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostNodeMonitorRequestWithBody(c.Server, contentType, body) - 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) PostNodeMonitor(ctx context.Context, body PostNodeMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostNodeMonitorRequest(c.Server, body) - 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) GetNodeStatus(ctx context.Context, params *GetNodeStatusParams, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetNodeStatusRequest(c.Server, params) if err != nil { @@ -2070,6 +2056,33 @@ func NewGetNodeRequest(server string, params *GetNodeParams) (*http.Request, err return req, nil } +// NewPostNodeActionDrainRequest generates requests for PostNodeActionDrain +func NewPostNodeActionDrainRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/node/action/drain") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewGetNodeBacklogsRequest generates requests for GetNodeBacklogs func NewGetNodeBacklogsRequest(server string, params *GetNodeBacklogsParams) (*http.Request, error) { var err error @@ -2435,46 +2448,6 @@ func NewGetNodeMonitorRequest(server string, params *GetNodeMonitorParams) (*htt return req, nil } -// NewPostNodeMonitorRequest calls the generic PostNodeMonitor builder with application/json body -func NewPostNodeMonitorRequest(server string, body PostNodeMonitorJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostNodeMonitorRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostNodeMonitorRequestWithBody generates requests for PostNodeMonitor with any type of body -func NewPostNodeMonitorRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/node/monitor") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - // NewGetNodeStatusRequest generates requests for GetNodeStatus func NewGetNodeStatusRequest(server string, params *GetNodeStatusParams) (*http.Request, error) { var err error @@ -3634,6 +3607,9 @@ type ClientWithResponsesInterface interface { // GetNode request GetNodeWithResponse(ctx context.Context, params *GetNodeParams, reqEditors ...RequestEditorFn) (*GetNodeResponse, error) + // PostNodeActionDrain request + PostNodeActionDrainWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostNodeActionDrainResponse, error) + // GetNodeBacklogs request GetNodeBacklogsWithResponse(ctx context.Context, params *GetNodeBacklogsParams, reqEditors ...RequestEditorFn) (*GetNodeBacklogsResponse, error) @@ -3660,11 +3636,6 @@ type ClientWithResponsesInterface interface { // GetNodeMonitor request GetNodeMonitorWithResponse(ctx context.Context, params *GetNodeMonitorParams, reqEditors ...RequestEditorFn) (*GetNodeMonitorResponse, error) - // PostNodeMonitor request with any body - PostNodeMonitorWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostNodeMonitorResponse, error) - - PostNodeMonitorWithResponse(ctx context.Context, body PostNodeMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*PostNodeMonitorResponse, error) - // GetNodeStatus request GetNodeStatusWithResponse(ctx context.Context, params *GetNodeStatusParams, reqEditors ...RequestEditorFn) (*GetNodeStatusResponse, error) @@ -4275,6 +4246,34 @@ func (r GetNodeResponse) StatusCode() int { return 0 } +type PostNodeActionDrainResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *OrchestrationQueued + JSON400 *Problem + JSON401 *Problem + JSON403 *Problem + JSON408 *Problem + JSON409 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r PostNodeActionDrainResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r PostNodeActionDrainResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type GetNodeBacklogsResponse struct { Body []byte HTTPResponse *http.Response @@ -4476,34 +4475,6 @@ func (r GetNodeMonitorResponse) StatusCode() int { return 0 } -type PostNodeMonitorResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *OrchestrationQueued - JSON400 *Problem - JSON401 *Problem - JSON403 *Problem - JSON408 *Problem - JSON409 *Problem - JSON500 *Problem -} - -// Status returns HTTPResponse.Status -func (r PostNodeMonitorResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostNodeMonitorResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - type GetNodeStatusResponse struct { Body []byte HTTPResponse *http.Response @@ -5339,6 +5310,15 @@ func (c *ClientWithResponses) GetNodeWithResponse(ctx context.Context, params *G return ParseGetNodeResponse(rsp) } +// PostNodeActionDrainWithResponse request returning *PostNodeActionDrainResponse +func (c *ClientWithResponses) PostNodeActionDrainWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostNodeActionDrainResponse, error) { + rsp, err := c.PostNodeActionDrain(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParsePostNodeActionDrainResponse(rsp) +} + // GetNodeBacklogsWithResponse request returning *GetNodeBacklogsResponse func (c *ClientWithResponses) GetNodeBacklogsWithResponse(ctx context.Context, params *GetNodeBacklogsParams, reqEditors ...RequestEditorFn) (*GetNodeBacklogsResponse, error) { rsp, err := c.GetNodeBacklogs(ctx, params, reqEditors...) @@ -5419,23 +5399,6 @@ func (c *ClientWithResponses) GetNodeMonitorWithResponse(ctx context.Context, pa return ParseGetNodeMonitorResponse(rsp) } -// PostNodeMonitorWithBodyWithResponse request with arbitrary body returning *PostNodeMonitorResponse -func (c *ClientWithResponses) PostNodeMonitorWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostNodeMonitorResponse, error) { - rsp, err := c.PostNodeMonitorWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostNodeMonitorResponse(rsp) -} - -func (c *ClientWithResponses) PostNodeMonitorWithResponse(ctx context.Context, body PostNodeMonitorJSONRequestBody, reqEditors ...RequestEditorFn) (*PostNodeMonitorResponse, error) { - rsp, err := c.PostNodeMonitor(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostNodeMonitorResponse(rsp) -} - // GetNodeStatusWithResponse request returning *GetNodeStatusResponse func (c *ClientWithResponses) GetNodeStatusWithResponse(ctx context.Context, params *GetNodeStatusParams, reqEditors ...RequestEditorFn) (*GetNodeStatusResponse, error) { rsp, err := c.GetNodeStatus(ctx, params, reqEditors...) @@ -6764,6 +6727,74 @@ func ParseGetNodeResponse(rsp *http.Response) (*GetNodeResponse, error) { return response, nil } +// ParsePostNodeActionDrainResponse parses an HTTP response from a PostNodeActionDrainWithResponse call +func ParsePostNodeActionDrainResponse(rsp *http.Response) (*PostNodeActionDrainResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &PostNodeActionDrainResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest OrchestrationQueued + 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 == 408: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON408 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest Problem + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &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 +} + // ParseGetNodeBacklogsResponse parses an HTTP response from a GetNodeBacklogsWithResponse call func ParseGetNodeBacklogsResponse(rsp *http.Response) (*GetNodeBacklogsResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -7147,74 +7178,6 @@ func ParseGetNodeMonitorResponse(rsp *http.Response) (*GetNodeMonitorResponse, e return response, nil } -// ParsePostNodeMonitorResponse parses an HTTP response from a PostNodeMonitorWithResponse call -func ParsePostNodeMonitorResponse(rsp *http.Response) (*PostNodeMonitorResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostNodeMonitorResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest OrchestrationQueued - 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 == 408: - var dest Problem - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON408 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: - var dest Problem - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON409 = &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 -} - // ParseGetNodeStatusResponse parses an HTTP response from a GetNodeStatusWithResponse call func ParseGetNodeStatusResponse(rsp *http.Response) (*GetNodeStatusResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index afbdc2b45..1fa76bbb4 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -81,6 +81,9 @@ type ServerInterface interface { // (GET /node) GetNode(ctx echo.Context, params GetNodeParams) error + // (POST /node/action/drain) + PostNodeActionDrain(ctx echo.Context) error + // (GET /node/backlogs) GetNodeBacklogs(ctx echo.Context, params GetNodeBacklogsParams) error @@ -105,9 +108,6 @@ type ServerInterface interface { // (GET /node/monitor) GetNodeMonitor(ctx echo.Context, params GetNodeMonitorParams) error - // (POST /node/monitor) - PostNodeMonitor(ctx echo.Context) error - // (GET /node/status) GetNodeStatus(ctx echo.Context, params GetNodeStatusParams) error @@ -601,6 +601,19 @@ func (w *ServerInterfaceWrapper) GetNode(ctx echo.Context) error { return err } +// PostNodeActionDrain converts echo context to params. +func (w *ServerInterfaceWrapper) PostNodeActionDrain(ctx echo.Context) error { + var err error + + ctx.Set(BasicAuthScopes, []string{""}) + + ctx.Set(BearerAuthScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.PostNodeActionDrain(ctx) + return err +} + // GetNodeBacklogs converts echo context to params. func (w *ServerInterfaceWrapper) GetNodeBacklogs(ctx echo.Context) error { var err error @@ -773,19 +786,6 @@ func (w *ServerInterfaceWrapper) GetNodeMonitor(ctx echo.Context) error { return err } -// PostNodeMonitor converts echo context to params. -func (w *ServerInterfaceWrapper) PostNodeMonitor(ctx echo.Context) error { - var err error - - ctx.Set(BasicAuthScopes, []string{""}) - - ctx.Set(BearerAuthScopes, []string{""}) - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.PostNodeMonitor(ctx) - return err -} - // GetNodeStatus converts echo context to params. func (w *ServerInterfaceWrapper) GetNodeStatus(ctx echo.Context) error { var err error @@ -1249,6 +1249,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.POST(baseURL+"/instance/status", wrapper.PostInstanceStatus) router.GET(baseURL+"/networks", wrapper.GetNetworks) router.GET(baseURL+"/node", wrapper.GetNode) + router.POST(baseURL+"/node/action/drain", wrapper.PostNodeActionDrain) router.GET(baseURL+"/node/backlogs", wrapper.GetNodeBacklogs) router.POST(baseURL+"/node/clear", wrapper.PostNodeClear) router.GET(baseURL+"/node/config", wrapper.GetNodeConfig) @@ -1257,7 +1258,6 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.POST(baseURL+"/node/drbd/config", wrapper.PostNodeDRBDConfig) router.GET(baseURL+"/node/logs", wrapper.GetNodeLogs) router.GET(baseURL+"/node/monitor", wrapper.GetNodeMonitor) - router.POST(baseURL+"/node/monitor", wrapper.PostNodeMonitor) router.GET(baseURL+"/node/status", wrapper.GetNodeStatus) router.GET(baseURL+"/nodes/info", wrapper.GetNodesInfo) router.POST(baseURL+"/object/action/abort", wrapper.PostObjectActionAbort) @@ -1288,124 +1288,123 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "3AAA", + "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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 1a67ccc81..f9eaf6eea 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -495,13 +495,6 @@ type PostNodeDRBDConfigRequest struct { Data []byte `json:"data"` } -// PostNodeMonitor defines model for PostNodeMonitor. -type PostNodeMonitor struct { - GlobalExpect *string `json:"global_expect,omitempty"` - LocalExpect *string `json:"local_expect,omitempty"` - State *string `json:"state,omitempty"` -} - // PostObjectAction defines model for PostObjectAction. type PostObjectAction struct { Path string `json:"path"` @@ -952,9 +945,6 @@ type PostInstanceStatusJSONRequestBody = InstanceStatusItem // PostNodeDRBDConfigJSONRequestBody defines body for PostNodeDRBDConfig for application/json ContentType. type PostNodeDRBDConfigJSONRequestBody = PostNodeDRBDConfigRequest -// PostNodeMonitorJSONRequestBody defines body for PostNodeMonitor for application/json ContentType. -type PostNodeMonitorJSONRequestBody = PostNodeMonitor - // PostObjectActionAbortJSONRequestBody defines body for PostObjectActionAbort for application/json ContentType. type PostObjectActionAbortJSONRequestBody = PostObjectAction diff --git a/daemon/daemonapi/post_node_drain.go b/daemon/daemonapi/post_node_drain.go new file mode 100644 index 000000000..f12d3a32d --- /dev/null +++ b/daemon/daemonapi/post_node_drain.go @@ -0,0 +1,55 @@ +package daemonapi + +import ( + "errors" + "net/http" + "time" + + "github.com/google/uuid" + "github.com/labstack/echo/v4" + "github.com/opensvc/om3/core/node" + "github.com/opensvc/om3/daemon/api" + "github.com/opensvc/om3/daemon/msgbus" + "github.com/opensvc/om3/util/hostname" +) + +func (a *DaemonApi) PostNodeActionDrain(ctx echo.Context) error { + var ( + value = node.MonitorUpdate{} + ) + if mon := node.MonitorData.Get(hostname.Hostname()); mon == nil { + return JSONProblemf(ctx, http.StatusNotFound, "Not found", "node monitor not found: %s", hostname.Hostname()) + } + state := node.MonitorStateDrained + value = node.MonitorUpdate{ + State: &state, + CandidateOrchestrationId: uuid.New(), + } + msg := msgbus.SetNodeMonitor{ + Node: hostname.Hostname(), + Value: value, + Err: make(chan error), + } + a.EventBus.Pub(&msg, labelNode, labelApi) + ticker := time.NewTicker(300 * time.Millisecond) + defer ticker.Stop() + var errs error + for { + select { + case <-ticker.C: + return JSONProblemf(ctx, http.StatusRequestTimeout, "set monitor", "timeout waiting for monitor commit") + case err := <-msg.Err: + if err != nil { + errs = errors.Join(errs, err) + } else if errs != nil { + return JSONProblemf(ctx, http.StatusConflict, "set monitor", "%s", errs) + } else { + return ctx.JSON(http.StatusOK, api.OrchestrationQueued{ + OrchestrationId: value.CandidateOrchestrationId, + }) + } + case <-ctx.Request().Context().Done(): + return JSONProblemf(ctx, http.StatusGone, "set monitor", "") + } + } +} diff --git a/daemon/daemonapi/post_node_monitor.go b/daemon/daemonapi/post_node_monitor.go deleted file mode 100644 index 24717d2b5..000000000 --- a/daemon/daemonapi/post_node_monitor.go +++ /dev/null @@ -1,67 +0,0 @@ -package daemonapi - -import ( - "errors" - "net/http" - - "github.com/google/uuid" - "github.com/labstack/echo/v4" - - "github.com/opensvc/om3/core/node" - "github.com/opensvc/om3/daemon/api" - "github.com/opensvc/om3/daemon/msgbus" - "github.com/opensvc/om3/util/hostname" -) - -func (a *DaemonApi) PostNodeMonitor(ctx echo.Context) error { - var ( - payload api.PostNodeMonitor - validRequest bool - update node.MonitorUpdate - ) - if err := ctx.Bind(&payload); err != nil { - return JSONProblem(ctx, http.StatusBadRequest, "Invalid Body", err.Error()) - } - if payload.LocalExpect != nil { - validRequest = true - i := node.MonitorLocalExpectValues[*payload.LocalExpect] - update.LocalExpect = &i - } - if payload.GlobalExpect != nil { - validRequest = true - i := node.MonitorGlobalExpectValues[*payload.GlobalExpect] - update.GlobalExpect = &i - } - if payload.State != nil { - validRequest = true - i := node.MonitorStateValues[*payload.State] - update.State = &i - } - update.CandidateOrchestrationId = uuid.New() - if !validRequest { - return JSONProblem(ctx, http.StatusBadRequest, "Invalid Body", "Need at least 'state', 'local_expect' or 'global_expect'") - } - msg := msgbus.SetNodeMonitor{ - Node: hostname.Hostname(), - Value: update, - Err: make(chan error), - } - a.EventBus.Pub(&msg, labelApi) - var errs error - for { - select { - case err := <-msg.Err: - if err != nil { - errs = errors.Join(errs, err) - } else if errs != nil { - return JSONProblemf(ctx, http.StatusConflict, "set monitor", "%s", errs) - } else { - return ctx.JSON(http.StatusOK, api.OrchestrationQueued{ - OrchestrationId: update.CandidateOrchestrationId, - }) - } - case <-ctx.Request().Context().Done(): - return JSONProblemf(ctx, http.StatusGone, "set monitor", "") - } - } -} From 977ce60330faaffc17717f137b533eac2a0f4435 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Tue, 5 Sep 2023 10:44:46 +0200 Subject: [PATCH 11/30] Rename "node abort" cmd as "cluster abort" As "cluster freeze" and "cluster unfreeze" are the command to submit an orchestration, the orchestration abort must be in the same command subsystem. --- CHANGELOG.md | 2 ++ cmd/ccfg.go | 1 + cmd/factory.go | 30 +++++++++---------- cmd/node.go | 1 - .../{node_abort.go => cluster_abort.go} | 4 +-- 5 files changed, 20 insertions(+), 18 deletions(-) rename core/commands/{node_abort.go => cluster_abort.go} (85%) diff --git a/CHANGELOG.md b/CHANGELOG.md index d64dfcc1f..94d8741be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -116,6 +116,8 @@ * **breaking change:** "om node freeze" is now local only. Use "om cluster freeze" for the orchestrated freeze of all nodes. Same applies to "unfreeze" and its hidden alias "thaw". +* **breaking change:** "om cluster abort" replaces "om node abort" to abort the pending cluster action orchestration. + * **breaking change:** "om ... set|unset" no longer accept --param and --value. Use --kw instead, which was also supported in v2. * "om monitor" instance availability icons changes: diff --git a/cmd/ccfg.go b/cmd/ccfg.go index 8db9443fc..eaa86c6f5 100644 --- a/cmd/ccfg.go +++ b/cmd/ccfg.go @@ -18,6 +18,7 @@ func init() { cmdObjectSet, cmdObjectPrint, cmdObjectValidate, + newCmdClusterAbort(), newCmdClusterFreeze(), newCmdClusterThaw(), newCmdClusterUnfreeze(), diff --git a/cmd/factory.go b/cmd/factory.go index 7bde3d1a9..1014237f1 100644 --- a/cmd/factory.go +++ b/cmd/factory.go @@ -135,6 +135,21 @@ func newCmdArrayLs() *cobra.Command { return cmd } +func newCmdClusterAbort() *cobra.Command { + var options commands.CmdClusterAbort + cmd := &cobra.Command{ + Use: "abort", + Short: "abort the running orchestration", + RunE: func(cmd *cobra.Command, args []string) error { + return options.Run() + }, + } + flags := cmd.Flags() + addFlagsAsync(flags, &options.OptsAsync) + addFlagsGlobal(flags, &options.OptsGlobal) + return cmd +} + func newCmdClusterFreeze() *cobra.Command { var options commands.CmdClusterFreeze cmd := &cobra.Command{ @@ -525,21 +540,6 @@ func newCmdNetworkStatus() *cobra.Command { return cmd } -func newCmdNodeAbort() *cobra.Command { - var options commands.CmdNodeAbort - cmd := &cobra.Command{ - Use: "abort", - Short: "abort the running orchestration", - RunE: func(cmd *cobra.Command, args []string) error { - return options.Run() - }, - } - flags := cmd.Flags() - addFlagsAsync(flags, &options.OptsAsync) - addFlagsGlobal(flags, &options.OptsGlobal) - return cmd -} - func newCmdNodeCapabilitiesList() *cobra.Command { var options commands.CmdNodeCapabilitiesList cmd := &cobra.Command{ diff --git a/cmd/node.go b/cmd/node.go index f253c37ab..3e9191423 100644 --- a/cmd/node.go +++ b/cmd/node.go @@ -120,7 +120,6 @@ func init() { cmdNodePush, cmdNodeRelay, cmdNodeValidate, - newCmdNodeAbort(), newCmdNodeChecks(), newCmdNodeClear(), newCmdNodeDoc(), diff --git a/core/commands/node_abort.go b/core/commands/cluster_abort.go similarity index 85% rename from core/commands/node_abort.go rename to core/commands/cluster_abort.go index 90607af7f..575af2d03 100644 --- a/core/commands/node_abort.go +++ b/core/commands/cluster_abort.go @@ -4,12 +4,12 @@ import ( "github.com/opensvc/om3/core/nodeaction" ) -type CmdNodeAbort struct { +type CmdClusterAbort struct { OptsGlobal OptsAsync } -func (t *CmdNodeAbort) Run() error { +func (t *CmdClusterAbort) Run() error { return nodeaction.New( nodeaction.WithRemoteNodes(t.NodeSelector), nodeaction.WithRemoteAction("abort"), From f5861288c53bb286559ca01bc6f9aa8ce57aecf4 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Tue, 5 Sep 2023 12:10:06 +0200 Subject: [PATCH 12/30] Fix the "om3 node drain" command Set LocalExpect instead of State to "drained". --- daemon/daemonapi/post_node_drain.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon/daemonapi/post_node_drain.go b/daemon/daemonapi/post_node_drain.go index f12d3a32d..b1172e317 100644 --- a/daemon/daemonapi/post_node_drain.go +++ b/daemon/daemonapi/post_node_drain.go @@ -20,9 +20,9 @@ func (a *DaemonApi) PostNodeActionDrain(ctx echo.Context) error { if mon := node.MonitorData.Get(hostname.Hostname()); mon == nil { return JSONProblemf(ctx, http.StatusNotFound, "Not found", "node monitor not found: %s", hostname.Hostname()) } - state := node.MonitorStateDrained + localExpect := node.MonitorLocalExpectDrained value = node.MonitorUpdate{ - State: &state, + LocalExpect: &localExpect, CandidateOrchestrationId: uuid.New(), } msg := msgbus.SetNodeMonitor{ From 6a26c219fe276390d0b39f7a34ec4c3db00ae760 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Tue, 5 Sep 2023 15:25:00 +0200 Subject: [PATCH 13/30] Add the "om instance ls" command Example: root@dev2n1:~/dev/om3# ./om3 "test/**" instance ls OBJ NODE AVAIL test/svc/svc1 dev2n1 n/a test/cfg/cfg1 dev2n1 n/a test/cfg/cfg1 dev2n3 n/a test/cfg/cfg1 dev2n2 n/a Also add support for adding columns to a default columning. Example: root@dev2n1:~/dev/om3# ./om3 "test/**" instance ls -o "+OVERALL:.data.status.overall" OBJ NODE AVAIL OVERALL test/cfg/cfg1 dev2n2 n/a n/a test/cfg/cfg1 dev2n1 n/a n/a test/svc/svc1 dev2n1 n/a n/a test/cfg/cfg1 dev2n3 n/a n/a This patch also rename the output.Renderer.Format field to output.Renderer.Output for alignment with the commandline --output. --- cmd/all.go | 5 +++ cmd/factory.go | 23 ++++++++++ core/commands/array_ls.go | 2 +- core/commands/daemon_dns_dump.go | 2 +- core/commands/daemon_relay_status.go | 2 +- core/commands/network_ls.go | 2 +- core/commands/network_status.go | 2 +- core/commands/node_events.go | 2 +- core/commands/node_ls.go | 2 +- core/commands/node_print_schedule.go | 2 +- core/commands/node_relay_status.go | 2 +- core/commands/object_instance_ls.go | 59 ++++++++++++++++++++++++++ core/commands/object_ls.go | 2 +- core/commands/object_print_config.go | 4 +- core/commands/object_print_devices.go | 2 +- core/commands/object_print_schedule.go | 2 +- core/commands/object_print_status.go | 2 +- core/commands/pool_ls.go | 2 +- core/commands/pool_status.go | 2 +- core/monitor/main.go | 2 +- core/nodeaction/node.go | 2 +- core/objectaction/object.go | 4 +- core/output/renderer.go | 19 ++++++--- 23 files changed, 122 insertions(+), 26 deletions(-) create mode 100644 core/commands/object_instance_ls.go diff --git a/cmd/all.go b/cmd/all.go index a28d67e9f..132ef4e4e 100644 --- a/cmd/all.go +++ b/cmd/all.go @@ -11,6 +11,7 @@ func init() { cmdObjectComplianceShow := newCmdObjectComplianceShow(kind) cmdObjectComplianceList := newCmdObjectComplianceList(kind) cmdObjectEdit := newCmdObjectEdit(kind) + cmdObjectInstance := newCmdObjectInstance(kind) cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) @@ -25,6 +26,7 @@ func init() { cmdObjectCollector, cmdObjectCompliance, cmdObjectEdit, + cmdObjectInstance, cmdObjectPrint, cmdObjectPush, cmdObjectSet, @@ -60,6 +62,9 @@ func init() { newCmdObjectUnprovision(kind), newCmdObjectUnset(kind), ) + cmdObjectInstance.AddCommand( + newCmdObjectInstanceLs(kind), + ) cmdObjectEdit.AddCommand( newCmdObjectEditConfig(kind), ) diff --git a/cmd/factory.go b/cmd/factory.go index 1014237f1..365857ca6 100644 --- a/cmd/factory.go +++ b/cmd/factory.go @@ -1632,6 +1632,14 @@ func newCmdObjectComplianceList(kind string) *cobra.Command { } } +func newCmdObjectInstance(kind string) *cobra.Command { + return &cobra.Command{ + Use: "instance", + Short: "config, status, monitor, ls", + Aliases: []string{"inst", "in"}, + } +} + func newCmdObjectComplianceShow(kind string) *cobra.Command { return &cobra.Command{ Use: "show", @@ -2179,6 +2187,21 @@ func newCmdObjectPrintSchedule(kind string) *cobra.Command { return cmd } +func newCmdObjectInstanceLs(kind string) *cobra.Command { + var options commands.CmdObjectInstanceLs + cmd := &cobra.Command{ + Use: "ls", + Aliases: []string{"list"}, + Short: "object instances list", + RunE: func(cmd *cobra.Command, args []string) error { + return options.Run(selectorFlag, kind) + }, + } + flags := cmd.Flags() + addFlagsGlobal(flags, &options.OptsGlobal) + return cmd +} + func newCmdObjectPrintStatus(kind string) *cobra.Command { var options commands.CmdObjectPrintStatus cmd := &cobra.Command{ diff --git a/core/commands/array_ls.go b/core/commands/array_ls.go index f99144a5f..fc990f6b2 100644 --- a/core/commands/array_ls.go +++ b/core/commands/array_ls.go @@ -27,7 +27,7 @@ func (t *CmdArrayLs) Run() error { data, err = t.extractDaemon() } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, HumanRenderer: func() string { diff --git a/core/commands/daemon_dns_dump.go b/core/commands/daemon_dns_dump.go index 008f929d8..2f319582f 100644 --- a/core/commands/daemon_dns_dump.go +++ b/core/commands/daemon_dns_dump.go @@ -38,7 +38,7 @@ func (t *CmdDaemonDNSDump) Run() error { return err } renderer := output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: parsed, Colorize: rawconfig.Colorize, diff --git a/core/commands/daemon_relay_status.go b/core/commands/daemon_relay_status.go index 21ef3dd4b..7b5ce1dba 100644 --- a/core/commands/daemon_relay_status.go +++ b/core/commands/daemon_relay_status.go @@ -43,7 +43,7 @@ func (t *CmdDaemonRelayStatus) Run() error { }) } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: messages, Colorize: rawconfig.Colorize, diff --git a/core/commands/network_ls.go b/core/commands/network_ls.go index 591ca4625..920465ca1 100644 --- a/core/commands/network_ls.go +++ b/core/commands/network_ls.go @@ -28,7 +28,7 @@ func (t *CmdNetworkLs) Run() error { data, err = t.extractDaemon() } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, HumanRenderer: func() string { diff --git a/core/commands/network_status.go b/core/commands/network_status.go index 196a6ff6b..556057ace 100644 --- a/core/commands/network_status.go +++ b/core/commands/network_status.go @@ -37,7 +37,7 @@ func (t *CmdNetworkStatus) Run() error { return err } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, Colorize: rawconfig.Colorize, diff --git a/core/commands/node_events.go b/core/commands/node_events.go index c6448e0da..289d21601 100644 --- a/core/commands/node_events.go +++ b/core/commands/node_events.go @@ -290,7 +290,7 @@ func (t *CmdNodeEvents) doEvent(e event.Event) { t.Output = output.JSONLine.String() } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: ce, Colorize: rawconfig.Colorize, diff --git a/core/commands/node_ls.go b/core/commands/node_ls.go index 7b60e5e7a..1950974a6 100644 --- a/core/commands/node_ls.go +++ b/core/commands/node_ls.go @@ -39,7 +39,7 @@ func (t *CmdNodeLs) Run() error { return err } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: nodes, HumanRenderer: func() string { diff --git a/core/commands/node_print_schedule.go b/core/commands/node_print_schedule.go index 0b5e037fd..cc13da4f1 100644 --- a/core/commands/node_print_schedule.go +++ b/core/commands/node_print_schedule.go @@ -71,7 +71,7 @@ func (t *CmdNodePrintSchedule) Run() error { data := t.extract(c) output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, Colorize: rawconfig.Colorize, diff --git a/core/commands/node_relay_status.go b/core/commands/node_relay_status.go index dffa654d3..037bde924 100644 --- a/core/commands/node_relay_status.go +++ b/core/commands/node_relay_status.go @@ -89,7 +89,7 @@ func (t *CmdNodeRelayStatus) Run() error { } } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: messages, Colorize: rawconfig.Colorize, diff --git a/core/commands/object_instance_ls.go b/core/commands/object_instance_ls.go new file mode 100644 index 000000000..94a03f15f --- /dev/null +++ b/core/commands/object_instance_ls.go @@ -0,0 +1,59 @@ +package commands + +import ( + "context" + "fmt" + + "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 ( + CmdObjectInstanceLs struct { + OptsGlobal + } +) + +func (t *CmdObjectInstanceLs) Run(selector, kind string) error { + var ( + data any + err error + ) + mergedSelector := mergeSelector(selector, t.ObjectSelector, kind, "") + + c, err := client.New(client.WithURL(t.Server)) + if err != nil { + return err + } + params := api.GetInstanceParams{Path: &mergedSelector} + if t.NodeSelector != "" { + params.Node = &t.NodeSelector + } + resp, err := c.GetInstanceWithResponse(context.Background(), ¶ms) + if err != nil { + return fmt.Errorf("api: %w", err) + } + 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 + } + renderer := output.Renderer{ + DefaultOutput: "tab=OBJ:meta.object,NODE:meta.node,AVAIL:data.status.avail", + Output: t.Output, + Color: t.Color, + Data: data, + Colorize: rawconfig.Colorize, + } + renderer.Print() + return nil +} diff --git a/core/commands/object_ls.go b/core/commands/object_ls.go index 01582e34f..75997b3b1 100644 --- a/core/commands/object_ls.go +++ b/core/commands/object_ls.go @@ -37,7 +37,7 @@ func (t *CmdObjectLs) Run(selector, kind string) error { return s } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, HumanRenderer: human, diff --git a/core/commands/object_print_config.go b/core/commands/object_print_config.go index f961c6dc9..a9058b54a 100644 --- a/core/commands/object_print_config.go +++ b/core/commands/object_print_config.go @@ -135,7 +135,7 @@ func (t *CmdObjectPrintConfig) Run(selector, kind string) error { return d.Render() } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data[selector].Data, HumanRenderer: render, @@ -154,7 +154,7 @@ func (t *CmdObjectPrintConfig) Run(selector, kind string) error { return s } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, HumanRenderer: render, diff --git a/core/commands/object_print_devices.go b/core/commands/object_print_devices.go index 69c862c5a..4e89817df 100644 --- a/core/commands/object_print_devices.go +++ b/core/commands/object_print_devices.go @@ -92,7 +92,7 @@ func (t *CmdObjectPrintDevices) Run(selector, kind string) error { } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, Colorize: rawconfig.Colorize, diff --git a/core/commands/object_print_schedule.go b/core/commands/object_print_schedule.go index 2047eccbb..bf484a10f 100644 --- a/core/commands/object_print_schedule.go +++ b/core/commands/object_print_schedule.go @@ -94,7 +94,7 @@ func (t *CmdObjectPrintSchedule) Run(selector, kind string) error { data := t.extract(mergedSelector, c) output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, Colorize: rawconfig.Colorize, diff --git a/core/commands/object_print_status.go b/core/commands/object_print_status.go index a231223c6..d38d5c4a8 100644 --- a/core/commands/object_print_status.go +++ b/core/commands/object_print_status.go @@ -159,7 +159,7 @@ func (t *CmdObjectPrintStatus) Run(selector, kind string) error { } data, _ = t.extract(mergedSelector, c) renderer := output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, HumanRenderer: func() string { diff --git a/core/commands/pool_ls.go b/core/commands/pool_ls.go index f64678f5e..3d8a25d1d 100644 --- a/core/commands/pool_ls.go +++ b/core/commands/pool_ls.go @@ -27,7 +27,7 @@ func (t *CmdPoolLs) Run() error { data, err = t.extractDaemon() } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, HumanRenderer: func() string { diff --git a/core/commands/pool_status.go b/core/commands/pool_status.go index 4c5597f1c..4f62b00e5 100644 --- a/core/commands/pool_status.go +++ b/core/commands/pool_status.go @@ -37,7 +37,7 @@ func (t *CmdPoolStatus) Run() error { return err } output.Renderer{ - Format: t.Output, + Output: t.Output, Color: t.Color, Data: data, Colorize: rawconfig.Colorize, diff --git a/core/monitor/main.go b/core/monitor/main.go index 94ab02c3e..5f8548c5c 100644 --- a/core/monitor/main.go +++ b/core/monitor/main.go @@ -138,7 +138,7 @@ func (m *T) doOneShot(data cluster.Data, clear bool, out io.Writer) { } s, err := output.Renderer{ - Format: m.format, + Output: m.format, Color: m.color, Data: data.WithSelector(m.selector), HumanRenderer: human, diff --git a/core/nodeaction/node.go b/core/nodeaction/node.go index c642f51ae..7799d34f6 100644 --- a/core/nodeaction/node.go +++ b/core/nodeaction/node.go @@ -201,7 +201,7 @@ func (t T) DoLocal() error { return s } output.Renderer{ - Format: t.Format, + Output: t.Format, Color: t.Color, Data: []actionrouter.Result{r}, HumanRenderer: human, diff --git a/core/objectaction/object.go b/core/objectaction/object.go index a61c6a57b..36b1e30c9 100644 --- a/core/objectaction/object.go +++ b/core/objectaction/object.go @@ -327,7 +327,7 @@ func (t T) DoLocal() error { return s } output.Renderer{ - Format: t.Format, + Output: t.Format, Color: t.Color, Data: rs, HumanRenderer: human, @@ -683,7 +683,7 @@ func (t T) DoAsync() error { return s } output.Renderer{ - Format: t.Format, + Output: t.Format, Color: t.Color, Data: rs, HumanRenderer: human, diff --git a/core/output/renderer.go b/core/output/renderer.go index e01debdfa..7e8c0de11 100644 --- a/core/output/renderer.go +++ b/core/output/renderer.go @@ -25,7 +25,8 @@ type ( // Renderer hosts the renderer options and data, and exposes the rendering // method. Renderer struct { - Format string + DefaultOutput string + Output string Color string Data interface{} HumanRenderer RenderFunc @@ -57,11 +58,19 @@ func (t Renderer) Sprint() (string, error) { var ( options, format string ) - if i := strings.Index(t.Format, "="); i > 0 { - options = t.Format[i+1:] - format = t.Format[:i] + if t.DefaultOutput != "" { + if t.Output == "auto" { + t.Output = t.DefaultOutput + } + if strings.HasPrefix(t.Output, "+") { + t.Output = t.DefaultOutput + "," + t.Output[1:] + } + } + if i := strings.Index(t.Output, "="); i > 0 { + options = t.Output[i+1:] + format = t.Output[:i] } else { - format = t.Format + format = t.Output } formatID := toID[format] From c145732637c34d2e9e0bf786d1adeb2025fac887 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Tue, 5 Sep 2023 15:59:34 +0200 Subject: [PATCH 14/30] Make "instance ls" command available on mono-object selectors --- cmd/cfg.go | 5 +++++ cmd/sec.go | 5 +++++ cmd/svc.go | 5 +++++ cmd/usr.go | 5 +++++ cmd/vol.go | 5 +++++ 5 files changed, 25 insertions(+) diff --git a/cmd/cfg.go b/cmd/cfg.go index 8c1a2325f..65c427eed 100644 --- a/cmd/cfg.go +++ b/cmd/cfg.go @@ -5,6 +5,7 @@ func init() { cmdObject := newCmdCfg() cmdObjectEdit := newCmdObjectEdit(kind) + cmdObjectInstance := newCmdObjectInstance(kind) cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) @@ -15,6 +16,7 @@ func init() { ) cmdObject.AddCommand( cmdObjectEdit, + cmdObjectInstance, cmdObjectPrint, cmdObjectSet, cmdObjectValidate, @@ -39,6 +41,9 @@ func init() { cmdObjectEdit.AddCommand( newCmdObjectEditConfig(kind), ) + cmdObjectInstance.AddCommand( + newCmdObjectInstanceLs(kind), + ) cmdObjectPrint.AddCommand( cmdObjectPrintConfig, newCmdObjectPrintStatus(kind), diff --git a/cmd/sec.go b/cmd/sec.go index 5ab0cb90e..286d589d6 100644 --- a/cmd/sec.go +++ b/cmd/sec.go @@ -5,6 +5,7 @@ func init() { cmdObject := newCmdSec() cmdObjectEdit := newCmdObjectEdit(kind) + cmdObjectInstance := newCmdObjectInstance(kind) cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) @@ -15,6 +16,7 @@ func init() { ) cmdObject.AddCommand( cmdObjectEdit, + cmdObjectInstance, cmdObjectPrint, cmdObjectSet, cmdObjectValidate, @@ -41,6 +43,9 @@ func init() { cmdObjectEdit.AddCommand( newCmdObjectEditConfig(kind), ) + cmdObjectInstance.AddCommand( + newCmdObjectInstanceLs(kind), + ) cmdObjectPrint.AddCommand( cmdObjectPrintConfig, newCmdObjectPrintStatus(kind), diff --git a/cmd/svc.go b/cmd/svc.go index a4301ecf7..e092795ed 100644 --- a/cmd/svc.go +++ b/cmd/svc.go @@ -12,6 +12,7 @@ func init() { cmdObjectComplianceShow := newCmdObjectComplianceShow(kind) cmdObjectComplianceList := newCmdObjectComplianceList(kind) cmdObjectEdit := newCmdObjectEdit(kind) + cmdObjectInstance := newCmdObjectInstance(kind) cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) @@ -26,6 +27,7 @@ func init() { cmdObjectCollector, cmdObjectCompliance, cmdObjectEdit, + cmdObjectInstance, cmdObjectPrint, cmdObjectPush, cmdObjectSet, @@ -66,6 +68,9 @@ func init() { cmdObjectEdit.AddCommand( newCmdObjectEditConfig(kind), ) + cmdObjectInstance.AddCommand( + newCmdObjectInstanceLs(kind), + ) cmdObjectSet.AddCommand( newCmdObjectSetProvisioned(kind), newCmdObjectSetUnprovisioned(kind), diff --git a/cmd/usr.go b/cmd/usr.go index 2610fc4e2..6e311063a 100644 --- a/cmd/usr.go +++ b/cmd/usr.go @@ -5,6 +5,7 @@ func init() { cmdObject := newCmdUsr() cmdObjectEdit := newCmdObjectEdit(kind) + cmdObjectInstance := newCmdObjectInstance(kind) cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) @@ -15,6 +16,7 @@ func init() { ) cmdObject.AddCommand( cmdObjectEdit, + cmdObjectInstance, cmdObjectPrint, cmdObjectSet, cmdObjectValidate, @@ -40,6 +42,9 @@ func init() { cmdObjectEdit.AddCommand( newCmdObjectEditConfig(kind), ) + cmdObjectInstance.AddCommand( + newCmdObjectInstanceLs(kind), + ) cmdObjectPrint.AddCommand( cmdObjectPrintConfig, newCmdObjectPrintStatus(kind), diff --git a/cmd/vol.go b/cmd/vol.go index 0430ff552..bbbf76c9c 100644 --- a/cmd/vol.go +++ b/cmd/vol.go @@ -7,6 +7,7 @@ func init() { cmdObjectCollector := newCmdObjectCollector(kind) cmdObjectCollectorTag := newCmdObjectCollectorTag(kind) cmdObjectEdit := newCmdObjectEdit(kind) + cmdObjectInstance := newCmdObjectInstance(kind) cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) @@ -20,6 +21,7 @@ func init() { cmdObject.AddCommand( cmdObjectCollector, cmdObjectEdit, + cmdObjectInstance, cmdObjectPrint, cmdObjectPush, cmdObjectSet, @@ -70,6 +72,9 @@ func init() { cmdObjectEdit.AddCommand( newCmdObjectEditConfig(kind), ) + cmdObjectInstance.AddCommand( + newCmdObjectInstanceLs(kind), + ) cmdObjectSet.AddCommand( newCmdObjectSetProvisioned(kind), newCmdObjectSetUnprovisioned(kind), From 9c77ad51b555fcce176c6fa689d05942d0321c92 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Wed, 6 Sep 2023 15:43:05 +0200 Subject: [PATCH 15/30] Use []instance.ResourceMonitor as instance.Monitor.Resources type Instead of a map. --- core/instance/config.go | 61 ++--- core/instance/monitor.go | 98 ++++---- core/instance/status.go | 8 +- daemon/api/api.yaml | 29 ++- daemon/api/codegen_server_gen.go | 219 +++++++++--------- daemon/api/codegen_type_gen.go | 9 + daemon/icfg/main.go | 9 +- daemon/imon/main.go | 2 +- daemon/imon/main_cmd.go | 9 +- daemon/imon/orchestration_resource_restart.go | 137 ++++++----- 10 files changed, 317 insertions(+), 264 deletions(-) diff --git a/core/instance/config.go b/core/instance/config.go index c17f26d41..50de42658 100644 --- a/core/instance/config.go +++ b/core/instance/config.go @@ -14,29 +14,31 @@ type ( // Config describes a configuration file content checksum, // timestamp of last change and the nodes it should be installed on. Config struct { - App string `json:"app,omitempty" yaml:"app,omitempty"` - Checksum string `json:"csum" yaml:"csum"` - Children []path.Relation `json:"children,omitempty" yaml:"children,omitempty"` - DRP bool `json:"drp,omitempty" yaml:"drp,omitempty"` - Env string `json:"env,omitempty" yaml:"env,omitempty"` - FlexMax int `json:"flex_max,omitempty" yaml:"flex_max,omitempty"` - FlexMin int `json:"flex_min,omitempty" yaml:"flex_min,omitempty"` - FlexTarget int `json:"flex_target,omitempty" yaml:"flex_target,omitempty"` - MonitorAction MonitorAction `json:"monitor_action,omitempty" yaml:"monitor_action,omitempty"` - PreMonitorAction string `json:"pre_monitor_action,omitempty" yaml:"pre_monitor_action,omitempty"` - Nodename string `json:"-" yaml:"-"` - Orchestrate string `json:"orchestrate" yaml:"orchestrate"` - Path path.T `json:"-" yaml:"-"` - Parents []path.Relation `json:"parents,omitempty" yaml:"parents,omitempty"` - PlacementPolicy placement.Policy `json:"placement_policy" yaml:"placement_policy"` - Priority priority.T `json:"priority,omitempty" yaml:"priority,omitempty"` - Resources map[string]ResourceConfig `json:"resources" yaml:"resources"` - Scope []string `json:"scope" yaml:"scope"` - Subsets map[string]SubsetConfig `json:"subsets" yaml:"subsets"` - Topology topology.T `json:"topology" yaml:"topology"` - UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` + App string `json:"app,omitempty" yaml:"app,omitempty"` + Checksum string `json:"csum" yaml:"csum"` + Children []path.Relation `json:"children,omitempty" yaml:"children,omitempty"` + DRP bool `json:"drp,omitempty" yaml:"drp,omitempty"` + Env string `json:"env,omitempty" yaml:"env,omitempty"` + FlexMax int `json:"flex_max,omitempty" yaml:"flex_max,omitempty"` + FlexMin int `json:"flex_min,omitempty" yaml:"flex_min,omitempty"` + FlexTarget int `json:"flex_target,omitempty" yaml:"flex_target,omitempty"` + MonitorAction MonitorAction `json:"monitor_action,omitempty" yaml:"monitor_action,omitempty"` + PreMonitorAction string `json:"pre_monitor_action,omitempty" yaml:"pre_monitor_action,omitempty"` + Nodename string `json:"-" yaml:"-"` + Orchestrate string `json:"orchestrate" yaml:"orchestrate"` + Path path.T `json:"-" yaml:"-"` + Parents []path.Relation `json:"parents,omitempty" yaml:"parents,omitempty"` + PlacementPolicy placement.Policy `json:"placement_policy" yaml:"placement_policy"` + Priority priority.T `json:"priority,omitempty" yaml:"priority,omitempty"` + Resources ResourceConfigs `json:"resources" yaml:"resources"` + Scope []string `json:"scope" yaml:"scope"` + Subsets map[string]SubsetConfig `json:"subsets" yaml:"subsets"` + Topology topology.T `json:"topology" yaml:"topology"` + UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` } - ResourceConfig struct { + ResourceConfigs []ResourceConfig + ResourceConfig struct { + Rid string `json:"rid,omitempty" yaml:"rid,omitempty"` IsDisabled bool `json:"is_disabled" yaml:"is_disabled"` IsMonitored bool `json:"is_monitored" yaml:"is_monitored"` IsStandby bool `json:"is_standby" yaml:"is_standby"` @@ -49,12 +51,8 @@ type ( ) func (cfg Config) DeepCopy() *Config { - resources := make(map[string]ResourceConfig) subSets := make(map[string]SubsetConfig) - for id, v := range cfg.Resources { - resources[id] = v - } for id, v := range cfg.Subsets { subSets[id] = v } @@ -62,7 +60,7 @@ func (cfg Config) DeepCopy() *Config { newCfg := cfg newCfg.Scope = append([]string{}, cfg.Scope...) newCfg.Subsets = subSets - newCfg.Resources = resources + newCfg.Resources = append(ResourceConfigs{}, cfg.Resources...) return &newCfg } @@ -82,3 +80,12 @@ func ConfigEqual(a, b *Config) bool { } return true } + +func (rcfgs ResourceConfigs) Get(rid string) *ResourceConfig { + for _, rcfg := range rcfgs { + if rcfg.Rid == rid { + return &rcfg + } + } + return nil +} diff --git a/core/instance/monitor.go b/core/instance/monitor.go index 8d67f15e0..0cd2438c2 100644 --- a/core/instance/monitor.go +++ b/core/instance/monitor.go @@ -39,18 +39,19 @@ type ( // A orchestration is cleaned up when all instance monitors have OrchestrationIsDone set. OrchestrationIsDone bool `json:"orchestration_is_done" yaml:"orchestration_is_done"` - SessionId uuid.UUID `json:"session_id" yaml:"session_id"` - State MonitorState `json:"state" yaml:"state"` - StateUpdatedAt time.Time `json:"state_updated_at" yaml:"state_updated_at"` - MonitorActionExecutedAt time.Time `json:"monitor_action_executed_at" yaml:"monitor_action_executed_at"` - IsPreserved bool `json:"preserved" yaml:"preserved"` - Resources ResourceMonitorMap `json:"resources,omitempty" yaml:"resources,omitempty"` - UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` + SessionId uuid.UUID `json:"session_id" yaml:"session_id"` + State MonitorState `json:"state" yaml:"state"` + StateUpdatedAt time.Time `json:"state_updated_at" yaml:"state_updated_at"` + MonitorActionExecutedAt time.Time `json:"monitor_action_executed_at" yaml:"monitor_action_executed_at"` + IsPreserved bool `json:"preserved" yaml:"preserved"` + Resources ResourceMonitors `json:"resources,omitempty" yaml:"resources,omitempty"` + UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` Parents map[string]status.T `json:"parents,omitempty" yaml:"parents,omitempty"` Children map[string]status.T `json:"children,omitempty" yaml:"children,omitempty"` } + ResourceMonitors []ResourceMonitor ResourceMonitorMap map[string]ResourceMonitor // MonitorUpdate is embedded in the SetInstanceMonitor message to @@ -69,6 +70,7 @@ type ( // ResourceMonitor describes the restart states maintained by the daemon // for an object instance. ResourceMonitor struct { + Rid string `json:"rid,omitempty" yaml:"rid,omitempty"` Restart ResourceMonitorRestart `json:"restart" yaml:"restart"` } ResourceMonitorRestart struct { @@ -264,6 +266,7 @@ var ( ErrSameLocalExpect = errors.New("instance monitor local expect is already set to the same value") ErrSameState = errors.New("instance monitor state is already set to the same value") + MonitorActionNone MonitorAction = "" MonitorActionCrash MonitorAction = "crash" MonitorActionFreezeStop MonitorAction = "freeze_stop" MonitorActionReboot MonitorAction = "reboot" @@ -361,33 +364,33 @@ func (t *MonitorGlobalExpect) UnmarshalText(b []byte) error { } } -func (m ResourceMonitorMap) DecRestartRemaining(rid string) { - if rmon, ok := m[rid]; ok && rmon.Restart.Remaining > 0 { - rmon.Restart.Remaining -= 1 - m[rid] = rmon +func (t ResourceMonitors) AsMap() ResourceMonitorMap { + m := make(ResourceMonitorMap) + for _, d := range t { + m[d.Rid] = d } + return m } -func (m ResourceMonitorMap) GetRestartRemaining(rid string) (int, bool) { - if rmon, ok := m[rid]; ok { - return rmon.Restart.Remaining, true - } else { - return 0, false +func (t ResourceMonitorMap) AsList() []ResourceMonitor { + l := make([]ResourceMonitor, len(t)) + i := 0 + for rid, d := range t { + d.Rid = rid + l[i] = d + i += 1 } + return l } -func (m ResourceMonitorMap) GetRestart(rid string) (ResourceMonitorRestart, bool) { - if rmon, ok := m[rid]; ok { - return rmon.Restart, true - } else { - return ResourceMonitorRestart{}, false +func (rmon *ResourceMonitor) DecRestartRemaining() { + if rmon.Restart.Remaining > 0 { + rmon.Restart.Remaining -= 1 } } -func (m ResourceMonitorMap) StopRestartTimer(rid string) bool { - if rmon, ok := m[rid]; !ok { - return false - } else if rmon.Restart.Timer == nil { +func (rmon *ResourceMonitor) StopRestartTimer() bool { + if rmon.Restart.Timer == nil { return false } else { rmon.Restart.Timer.Stop() @@ -396,39 +399,22 @@ func (m ResourceMonitorMap) StopRestartTimer(rid string) bool { } } -func (m ResourceMonitorMap) GetRestartTimer(rid string) (*time.Timer, bool) { - if rmon, ok := m[rid]; ok { - return rmon.Restart.Timer, true - } else { - return nil, false - } -} - -func (m ResourceMonitorMap) HasRestartTimer(rid string) bool { - if rmon, ok := m[rid]; ok { - return rmon.Restart.Timer != nil - } else { - return false - } -} - -func (m ResourceMonitorMap) SetRestartLastAt(rid string, v time.Time) { - if rmon, ok := m[rid]; ok { - rmon.Restart.LastAt = v - m[rid] = rmon - } -} - -func (m ResourceMonitorMap) SetRestartRemaining(rid string, v int) { - if rmon, ok := m[rid]; ok { - rmon.Restart.Remaining = v - m[rid] = rmon +func (l ResourceMonitors) Set(m ResourceMonitor) { + for i, rmon := range l { + if m.Rid == rmon.Rid { + l[i] = m + return + } } + l = append(l, m) } -func (m ResourceMonitorMap) SetRestartTimer(rid string, v *time.Timer) { - if rmon, ok := m[rid]; ok { - rmon.Restart.Timer = v - m[rid] = rmon +func (l ResourceMonitors) Get(rid string) *ResourceMonitor { + for _, rmon := range l { + if rmon.Rid != rid { + continue + } + return &rmon } + return nil } diff --git a/core/instance/status.go b/core/instance/status.go index a70b00277..fea1840d7 100644 --- a/core/instance/status.go +++ b/core/instance/status.go @@ -134,7 +134,7 @@ func (t Status) ResourceFlagsString(rid resourceid.T, r resource.ExposedStatus) func (mon Monitor) ResourceFlagRestartString(rid resourceid.T, r resource.ExposedStatus) string { // Restart and retries retries := 0 - if rmon, ok := mon.Resources[rid.Name]; ok { + if rmon, ok := mon.Resources.AsMap()[rid.Name]; ok { retries = rmon.Restart.Remaining } return r.Restart.FlagString(retries) @@ -142,11 +142,7 @@ func (mon Monitor) ResourceFlagRestartString(rid resourceid.T, r resource.Expose func (mon Monitor) DeepCopy() *Monitor { v := mon - restart := make(map[string]ResourceMonitor) - for s, val := range v.Resources { - restart[s] = val - } - v.Resources = restart + v.Resources = append(ResourceMonitors{}, v.Resources...) if mon.GlobalExpectOptions != nil { switch mon.GlobalExpect { case MonitorGlobalExpectPlacedAt: diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index c6060ea58..84eeebee3 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -1810,7 +1810,7 @@ components: resources: type: array items: - type: object + $ref: '#/components/schemas/ResourceMonitor' updated_at: type: string format: date-time @@ -2537,12 +2537,15 @@ components: path: github.com/opensvc/om3/core/instance type: object required: + - rid - is_disabled - is_monitored - is_standby - restart - restart_delay properties: + rid: + type: string is_disabled: type: boolean is_monitored: @@ -2622,6 +2625,30 @@ components: type: string type: type: string + ResourceMonitor: + x-go-type: instance.ResourceMonitor + x-go-type-import: + path: github.com/opensvc/om3/core/instance + type: object + required: + - rid + - restart + properties: + rid: + type: string + restart: + $ref: '#/components/schemas/ResourceMonitorRestart' + ResourceMonitorRestart: + type: object + required: + - remaining + - last_at + properties: + remaining: + type: integer + last_at: + type: string + format: date-time ResourceId: type: string ResourceLog: diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index 1fa76bbb4..1e32e312e 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -1289,7 +1289,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL var swaggerSpec = []string{ "H4sIAAAAAAAC/+w9a3PcNpJ/BTV7VUm2RiPJcrKJrvLBsZON92zZZyl3VWe5VBiyZwYxCdAAOJKy5f9+", - "hRcJkgAfekWx9MnWsAE0uhvdjUaj8e9ZwvKCUaBSzA7/PSswxzlI4PqvF+9+evGc0RVZH+Ec1C8piIST", + "hRcJkgAfekWx9MnWsAE0uhuNRqO78e9ZwvKCUaBSzA7/PSswxzlI4PqvF+9+evGc0RVZH+Ec1C8piIST", "QhJGZ4czuQG0KrMMFVhuEFsh/QPJABGBUkjLBFK04izXH6jqYz4jquWnEvjlbD7Tvx3O7CcOn0rCIZ0d", "Sl7CfCaSDeRYjSsvCwUnJCd0Pfv8eT57UXJs0GhjleMLlLqv4fG8z/UYcIHzIlOfvxWzeWDIn7dA5S8k", "k8C7o2ZESEUCUECKCAoqPHr1sR6bSMhFt1MDieCi4CAEYfQQvf9IaPrh/TzDS8h+3OKshA9/P1UzqfF/", @@ -1297,114 +1297,115 @@ 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 f9eaf6eea..62c75b461 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -616,6 +616,15 @@ type ResourceLogEntry struct { Message string `json:"message"` } +// ResourceMonitor defines model for ResourceMonitor. +type ResourceMonitor = instance.ResourceMonitor + +// ResourceMonitorRestart defines model for ResourceMonitorRestart. +type ResourceMonitorRestart struct { + LastAt time.Time `json:"last_at"` + Remaining int `json:"remaining"` +} + // ResourceProvisionStatus defines model for ResourceProvisionStatus. type ResourceProvisionStatus struct { Mtime time.Time `json:"mtime"` diff --git a/daemon/icfg/main.go b/daemon/icfg/main.go index 5b79c7534..770fa2781 100644 --- a/daemon/icfg/main.go +++ b/daemon/icfg/main.go @@ -380,20 +380,21 @@ func (o *T) getSubsets(cf *xconfig.T) map[string]instance.SubsetConfig { return m } -func (o *T) getResources(cf *xconfig.T) map[string]instance.ResourceConfig { - m := make(map[string]instance.ResourceConfig) +func (o *T) getResources(cf *xconfig.T) instance.ResourceConfigs { + m := make(instance.ResourceConfigs, 0) for _, section := range cf.SectionStrings() { switch section { case "env", "DEFAULT": continue } - m[section] = instance.ResourceConfig{ + m = append(m, instance.ResourceConfig{ + Rid: section, RestartDelay: cf.GetDuration(key.New(section, "restart_delay")), Restart: cf.GetInt(key.New(section, "restart")), IsDisabled: cf.GetBool(key.New(section, "disable")), IsMonitored: cf.GetBool(key.New(section, "monitor")), IsStandby: cf.GetBool(key.New(section, "standby")), - } + }) } return m } diff --git a/daemon/imon/main.go b/daemon/imon/main.go index ccdba07fa..914eab8ca 100644 --- a/daemon/imon/main.go +++ b/daemon/imon/main.go @@ -131,7 +131,7 @@ func start(parent context.Context, p path.T, nodes []string, drainDuration time. LocalExpect: instance.MonitorLocalExpectNone, GlobalExpect: instance.MonitorGlobalExpectNone, State: instance.MonitorStateIdle, - Resources: make(map[string]instance.ResourceMonitor), + Resources: make(instance.ResourceMonitors, 0), Children: make(map[string]status.T), Parents: make(map[string]status.T), StateUpdatedAt: time.Now(), diff --git a/daemon/imon/main_cmd.go b/daemon/imon/main_cmd.go index d8564f9f0..7d5968953 100644 --- a/daemon/imon/main_cmd.go +++ b/daemon/imon/main_cmd.go @@ -1014,13 +1014,14 @@ func (o *imon) doAction(action func() error, newState, successState, errorState } func (o *imon) initResourceMonitor() { - m := make(map[string]instance.ResourceMonitor) - for rid, res := range o.instConfig.Resources { - m[rid] = instance.ResourceMonitor{ + m := make(instance.ResourceMonitors, 0) + for _, res := range o.instConfig.Resources { + m = append(m, instance.ResourceMonitor{ + Rid: res.Rid, Restart: instance.ResourceMonitorRestart{ Remaining: res.Restart, }, - } + }) } o.state.Resources = m o.change = true diff --git a/daemon/imon/orchestration_resource_restart.go b/daemon/imon/orchestration_resource_restart.go index bd7bd8e91..2b4d89e16 100644 --- a/daemon/imon/orchestration_resource_restart.go +++ b/daemon/imon/orchestration_resource_restart.go @@ -84,8 +84,11 @@ func (o *imon) orchestrateResourceRestart() { case instance.MonitorActionFreezeStop: case instance.MonitorActionReboot: case instance.MonitorActionSwitch: + case instance.MonitorActionNone: + o.log.Error().Msgf("skip monitor action: not configured") + return default: - o.log.Error().Msgf("skip monitor action: unsupported: %s", o.instConfig.MonitorAction) + o.log.Error().Msgf("skip monitor action: not supported: %s", o.instConfig.MonitorAction) return } @@ -114,77 +117,73 @@ func (o *imon) orchestrateResourceRestart() { } } - resetTimer := func(rid string) { - todoRestart.Del(rid) - todoStandby.Del(rid) - if timer, ok := o.state.Resources.GetRestartTimer(rid); ok && timer != nil { - o.log.Info().Msgf("resource %s is up, reset delayed restart", rid) - timer.Stop() - o.state.Resources.SetRestartTimer(rid, nil) - o.change = true + resetTimer := func(rmon *instance.ResourceMonitor) { + todoRestart.Del(rmon.Rid) + todoStandby.Del(rmon.Rid) + if rmon.Restart.Timer != nil { + o.log.Info().Msgf("resource %s is up, reset delayed restart", rmon.Rid) + o.change = rmon.StopRestartTimer() + o.state.Resources.Set(*rmon) } } - resetRemaining := func(rid string) { - rcfg, ok := o.instConfig.Resources[rid] - if !ok { - return - } - if remaining, ok := o.state.Resources.GetRestartRemaining(rid); ok && remaining != rcfg.Restart { - o.log.Info().Msgf("resource %s is up, reset restart count to the max (%d -> %d)", rid, remaining, rcfg.Restart) + resetRemaining := func(rcfg *instance.ResourceConfig, rmon *instance.ResourceMonitor) { + if rmon.Restart.Remaining != rcfg.Restart { + o.log.Info().Msgf("resource %s is up, reset restart count to the max (%d -> %d)", rcfg.Rid, rmon.Restart.Remaining, rcfg.Restart) o.state.MonitorActionExecutedAt = time.Time{} - o.state.Resources.SetRestartRemaining(rid, rcfg.Restart) + rmon.Restart.Remaining = rcfg.Restart + o.state.Resources.Set(*rmon) o.change = true } } - resetRemainingAndTimer := func(rid string) { - resetRemaining(rid) - resetTimer(rid) + resetRemainingAndTimer := func(rcfg *instance.ResourceConfig, rmon *instance.ResourceMonitor) { + resetRemaining(rcfg, rmon) + resetTimer(rmon) } resetTimers := func() { - for _, res := range o.instStatus[o.localhost].Resources { - resetTimer(res.Rid) + for _, rmon := range o.state.Resources { + resetTimer(&rmon) } } planFor := func(rid string, resStatus status.T, started bool) { - rcfg, ok := o.instConfig.Resources[rid] + rcfg := o.instConfig.Resources.Get(rid) + rmon := o.state.Resources.Get(rid) switch { - case !ok: + case rcfg == nil: + return + case rmon == nil: return case rcfg.IsDisabled: o.log.Debug().Msgf("resource %s restart skip: disable=%v", rid, rcfg.IsDisabled) - resetRemainingAndTimer(rid) + resetRemainingAndTimer(rcfg, rmon) case resStatus.Is(status.NotApplicable, status.Undef): o.log.Debug().Msgf("resource %s restart skip: status=%s", rid, resStatus) - resetRemainingAndTimer(rid) + resetRemainingAndTimer(rcfg, rmon) case resStatus.Is(status.Up, status.StandbyUp): o.log.Debug().Msgf("resource %s restart skip: status=%s", rid, resStatus) - resetRemainingAndTimer(rid) - case o.state.Resources.HasRestartTimer(rid): + resetRemainingAndTimer(rcfg, rmon) + case rmon.Restart.Timer != nil: o.log.Debug().Msgf("resource %s restart skip: already has a delay timer", rid) case !o.state.MonitorActionExecutedAt.IsZero(): o.log.Debug().Msgf("resource %s restart skip: already ran the monitor action", rid) - default: - rmon := o.state.Resources[rid] - if started { - o.log.Info().Msgf("resource %s status %s, restart remaining %d out of %d", rid, resStatus, rmon.Restart.Remaining, rcfg.Restart) - if rmon.Restart.Remaining == 0 { - o.state.MonitorActionExecutedAt = time.Now() - o.change = true - doMonitorAction(rid) - } else { - todoRestart.Add(rid) - } - } else if rcfg.IsStandby { - o.log.Info().Msgf("resource %s status %s, standby restart remaining %d out of %d", rid, resStatus, rmon.Restart.Remaining, rcfg.Restart) - todoStandby.Add(rid) + case started: + o.log.Info().Msgf("resource %s status %s, restart remaining %d out of %d", rid, resStatus, rmon.Restart.Remaining, rcfg.Restart) + if rmon.Restart.Remaining == 0 { + o.state.MonitorActionExecutedAt = time.Now() + o.change = true + doMonitorAction(rid) } else { - o.log.Debug().Msgf("resource %s restart skip: instance not started", rid) - resetTimer(rid) + todoRestart.Add(rid) } + case rcfg.IsStandby: + o.log.Info().Msgf("resource %s status %s, standby restart remaining %d out of %d", rid, resStatus, rmon.Restart.Remaining, rcfg.Restart) + todoStandby.Add(rid) + default: + o.log.Debug().Msgf("resource %s restart skip: instance not started", rid) + resetTimer(rmon) } } @@ -193,8 +192,14 @@ func (o *imon) orchestrateResourceRestart() { rids := make([]string, 0) now := time.Now() for rid, _ := range todo { - rcfg := o.instConfig.Resources[rid] - rmon := o.state.Resources[rid] + rcfg := o.instConfig.Resources.Get(rid) + if rcfg == nil { + continue + } + rmon := o.state.Resources.Get(rid) + if rmon == nil { + continue + } if rcfg.RestartDelay != nil { notBefore := rmon.Restart.LastAt.Add(*rcfg.RestartDelay) if now.Before(notBefore) { @@ -217,8 +222,13 @@ func (o *imon) orchestrateResourceRestart() { timer := time.AfterFunc(delay, func() { now := time.Now() for _, rid := range rids { - o.state.Resources.SetRestartLastAt(rid, now) - o.state.Resources.SetRestartTimer(rid, nil) + rmon := o.state.Resources.Get(rid) + if rmon == nil { + continue + } + rmon.Restart.LastAt = now + rmon.Restart.Timer = nil + o.state.Resources.Set(*rmon) o.change = true } action := func() error { @@ -227,8 +237,13 @@ func (o *imon) orchestrateResourceRestart() { o.doTransitionAction(action, instance.MonitorStateStarting, instance.MonitorStateIdle, instance.MonitorStateStartFailed) }) for _, rid := range rids { - o.state.Resources.DecRestartRemaining(rid) - o.state.Resources.SetRestartTimer(rid, timer) + rmon := o.state.Resources.Get(rid) + if rmon == nil { + continue + } + rmon.DecRestartRemaining() + rmon.Restart.Timer = timer + o.state.Resources.Set(*rmon) o.change = true } } @@ -241,8 +256,13 @@ func (o *imon) orchestrateResourceRestart() { timer := time.AfterFunc(delay, func() { now := time.Now() for _, rid := range rids { - o.state.Resources.SetRestartLastAt(rid, now) - o.state.Resources.SetRestartTimer(rid, nil) + rmon := o.state.Resources.Get(rid) + if rmon == nil { + continue + } + rmon.Restart.LastAt = now + rmon.Restart.Timer = nil + o.state.Resources.Set(*rmon) o.change = true } action := func() error { @@ -251,8 +271,13 @@ func (o *imon) orchestrateResourceRestart() { o.doTransitionAction(action, instance.MonitorStateStarting, instance.MonitorStateIdle, instance.MonitorStateStartFailed) }) for _, rid := range rids { - o.state.Resources.DecRestartRemaining(rid) - o.state.Resources.SetRestartTimer(rid, timer) + rmon := o.state.Resources.Get(rid) + if rmon == nil { + continue + } + rmon.DecRestartRemaining() + rmon.Restart.Timer = timer + o.state.Resources.Set(*rmon) o.change = true } } @@ -319,8 +344,8 @@ func (o *imon) orchestrateResourceRestart() { started := instMonitor.LocalExpect == instance.MonitorLocalExpectStarted - for _, res := range o.instStatus[o.localhost].Resources { - planFor(res.Rid, res.Status, started) + for _, rstat := range o.instStatus[o.localhost].Resources { + planFor(rstat.Rid, rstat.Status, started) } doStandby() doRestart() From 1347870f3e431a414e1f88c9ca2a2e0a82ef739b Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Wed, 6 Sep 2023 16:04:34 +0200 Subject: [PATCH 16/30] Add fine-grained "instance * ls" commands * instance config ls * instance monitor ls * instance status ls In addition to instance ls that reports all of the above info. --- cmd/all.go | 15 +++++ cmd/factory.go | 66 +++++++++++++++++++++ cmd/svc.go | 15 +++++ cmd/vol.go | 15 +++++ core/commands/object_instance_config_ls.go | 59 ++++++++++++++++++ core/commands/object_instance_ls.go | 2 +- core/commands/object_instance_monitor_ls.go | 59 ++++++++++++++++++ core/commands/object_instance_status_ls.go | 59 ++++++++++++++++++ 8 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 core/commands/object_instance_config_ls.go create mode 100644 core/commands/object_instance_monitor_ls.go create mode 100644 core/commands/object_instance_status_ls.go diff --git a/cmd/all.go b/cmd/all.go index 132ef4e4e..f256ae2be 100644 --- a/cmd/all.go +++ b/cmd/all.go @@ -12,6 +12,9 @@ func init() { cmdObjectComplianceList := newCmdObjectComplianceList(kind) cmdObjectEdit := newCmdObjectEdit(kind) cmdObjectInstance := newCmdObjectInstance(kind) + cmdObjectInstanceConfig := newCmdObjectInstanceConfig(kind) + cmdObjectInstanceMonitor := newCmdObjectInstanceMonitor(kind) + cmdObjectInstanceStatus := newCmdObjectInstanceStatus(kind) cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) @@ -62,7 +65,19 @@ func init() { newCmdObjectUnprovision(kind), newCmdObjectUnset(kind), ) + cmdObjectInstanceConfig.AddCommand( + newCmdObjectInstanceConfigLs(kind), + ) + cmdObjectInstanceMonitor.AddCommand( + newCmdObjectInstanceMonitorLs(kind), + ) + cmdObjectInstanceStatus.AddCommand( + newCmdObjectInstanceStatusLs(kind), + ) cmdObjectInstance.AddCommand( + cmdObjectInstanceConfig, + cmdObjectInstanceMonitor, + cmdObjectInstanceStatus, newCmdObjectInstanceLs(kind), ) cmdObjectEdit.AddCommand( diff --git a/cmd/factory.go b/cmd/factory.go index 365857ca6..86cee162e 100644 --- a/cmd/factory.go +++ b/cmd/factory.go @@ -1640,6 +1640,27 @@ func newCmdObjectInstance(kind string) *cobra.Command { } } +func newCmdObjectInstanceConfig(kind string) *cobra.Command { + return &cobra.Command{ + Use: "config", + Aliases: []string{"conf", "cf"}, + } +} + +func newCmdObjectInstanceMonitor(kind string) *cobra.Command { + return &cobra.Command{ + Use: "monitor", + Aliases: []string{"mon"}, + } +} + +func newCmdObjectInstanceStatus(kind string) *cobra.Command { + return &cobra.Command{ + Use: "status", + Aliases: []string{"stat", "st"}, + } +} + func newCmdObjectComplianceShow(kind string) *cobra.Command { return &cobra.Command{ Use: "show", @@ -2202,6 +2223,51 @@ func newCmdObjectInstanceLs(kind string) *cobra.Command { return cmd } +func newCmdObjectInstanceConfigLs(kind string) *cobra.Command { + var options commands.CmdObjectInstanceConfigLs + cmd := &cobra.Command{ + Use: "ls", + Aliases: []string{"list"}, + Short: "object instance configs list", + RunE: func(cmd *cobra.Command, args []string) error { + return options.Run(selectorFlag, kind) + }, + } + flags := cmd.Flags() + addFlagsGlobal(flags, &options.OptsGlobal) + return cmd +} + +func newCmdObjectInstanceStatusLs(kind string) *cobra.Command { + var options commands.CmdObjectInstanceStatusLs + cmd := &cobra.Command{ + Use: "ls", + Aliases: []string{"list"}, + Short: "object instance statuses list", + RunE: func(cmd *cobra.Command, args []string) error { + return options.Run(selectorFlag, kind) + }, + } + flags := cmd.Flags() + addFlagsGlobal(flags, &options.OptsGlobal) + return cmd +} + +func newCmdObjectInstanceMonitorLs(kind string) *cobra.Command { + var options commands.CmdObjectInstanceMonitorLs + cmd := &cobra.Command{ + Use: "ls", + Aliases: []string{"list"}, + Short: "object instances monitors list", + RunE: func(cmd *cobra.Command, args []string) error { + return options.Run(selectorFlag, kind) + }, + } + flags := cmd.Flags() + addFlagsGlobal(flags, &options.OptsGlobal) + return cmd +} + func newCmdObjectPrintStatus(kind string) *cobra.Command { var options commands.CmdObjectPrintStatus cmd := &cobra.Command{ diff --git a/cmd/svc.go b/cmd/svc.go index e092795ed..4ceed8a97 100644 --- a/cmd/svc.go +++ b/cmd/svc.go @@ -13,6 +13,9 @@ func init() { cmdObjectComplianceList := newCmdObjectComplianceList(kind) cmdObjectEdit := newCmdObjectEdit(kind) cmdObjectInstance := newCmdObjectInstance(kind) + cmdObjectInstanceConfig := newCmdObjectInstanceConfig(kind) + cmdObjectInstanceMonitor := newCmdObjectInstanceMonitor(kind) + cmdObjectInstanceStatus := newCmdObjectInstanceStatus(kind) cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) @@ -68,7 +71,19 @@ func init() { cmdObjectEdit.AddCommand( newCmdObjectEditConfig(kind), ) + cmdObjectInstanceConfig.AddCommand( + newCmdObjectInstanceConfigLs(kind), + ) + cmdObjectInstanceMonitor.AddCommand( + newCmdObjectInstanceMonitorLs(kind), + ) + cmdObjectInstanceStatus.AddCommand( + newCmdObjectInstanceStatusLs(kind), + ) cmdObjectInstance.AddCommand( + cmdObjectInstanceConfig, + cmdObjectInstanceMonitor, + cmdObjectInstanceStatus, newCmdObjectInstanceLs(kind), ) cmdObjectSet.AddCommand( diff --git a/cmd/vol.go b/cmd/vol.go index bbbf76c9c..21b69441b 100644 --- a/cmd/vol.go +++ b/cmd/vol.go @@ -8,6 +8,9 @@ func init() { cmdObjectCollectorTag := newCmdObjectCollectorTag(kind) cmdObjectEdit := newCmdObjectEdit(kind) cmdObjectInstance := newCmdObjectInstance(kind) + cmdObjectInstanceConfig := newCmdObjectInstanceConfig(kind) + cmdObjectInstanceMonitor := newCmdObjectInstanceMonitor(kind) + cmdObjectInstanceStatus := newCmdObjectInstanceStatus(kind) cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) @@ -72,7 +75,19 @@ func init() { cmdObjectEdit.AddCommand( newCmdObjectEditConfig(kind), ) + cmdObjectInstanceConfig.AddCommand( + newCmdObjectInstanceConfigLs(kind), + ) + cmdObjectInstanceMonitor.AddCommand( + newCmdObjectInstanceMonitorLs(kind), + ) + cmdObjectInstanceStatus.AddCommand( + newCmdObjectInstanceStatusLs(kind), + ) cmdObjectInstance.AddCommand( + cmdObjectInstanceConfig, + cmdObjectInstanceMonitor, + cmdObjectInstanceStatus, newCmdObjectInstanceLs(kind), ) cmdObjectSet.AddCommand( diff --git a/core/commands/object_instance_config_ls.go b/core/commands/object_instance_config_ls.go new file mode 100644 index 000000000..4551acae8 --- /dev/null +++ b/core/commands/object_instance_config_ls.go @@ -0,0 +1,59 @@ +package commands + +import ( + "context" + "fmt" + + "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 ( + CmdObjectInstanceConfigLs struct { + OptsGlobal + } +) + +func (t *CmdObjectInstanceConfigLs) Run(selector, kind string) error { + var ( + data any + err error + ) + mergedSelector := mergeSelector(selector, t.ObjectSelector, kind, "") + + c, err := client.New(client.WithURL(t.Server)) + if err != nil { + return err + } + params := api.GetInstanceConfigParams{Path: &mergedSelector} + if t.NodeSelector != "" { + params.Node = &t.NodeSelector + } + resp, err := c.GetInstanceConfigWithResponse(context.Background(), ¶ms) + if err != nil { + return fmt.Errorf("api: %w", err) + } + 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 + } + renderer := output.Renderer{ + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,ORCHESTRATE:data.orchestrate,TOPOLOGY:data.topology", + Output: t.Output, + Color: t.Color, + Data: data, + Colorize: rawconfig.Colorize, + } + renderer.Print() + return nil +} diff --git a/core/commands/object_instance_ls.go b/core/commands/object_instance_ls.go index 94a03f15f..3bf904af8 100644 --- a/core/commands/object_instance_ls.go +++ b/core/commands/object_instance_ls.go @@ -48,7 +48,7 @@ func (t *CmdObjectInstanceLs) Run(selector, kind string) error { data = *resp.JSON500 } renderer := output.Renderer{ - DefaultOutput: "tab=OBJ:meta.object,NODE:meta.node,AVAIL:data.status.avail", + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,AVAIL:data.status.avail", Output: t.Output, Color: t.Color, Data: data, diff --git a/core/commands/object_instance_monitor_ls.go b/core/commands/object_instance_monitor_ls.go new file mode 100644 index 000000000..d94295f28 --- /dev/null +++ b/core/commands/object_instance_monitor_ls.go @@ -0,0 +1,59 @@ +package commands + +import ( + "context" + "fmt" + + "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 ( + CmdObjectInstanceMonitorLs struct { + OptsGlobal + } +) + +func (t *CmdObjectInstanceMonitorLs) Run(selector, kind string) error { + var ( + data any + err error + ) + mergedSelector := mergeSelector(selector, t.ObjectSelector, kind, "") + + c, err := client.New(client.WithURL(t.Server)) + if err != nil { + return err + } + params := api.GetInstanceMonitorParams{Path: &mergedSelector} + if t.NodeSelector != "" { + params.Node = &t.NodeSelector + } + resp, err := c.GetInstanceMonitorWithResponse(context.Background(), ¶ms) + if err != nil { + return fmt.Errorf("api: %w", err) + } + 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 + } + renderer := output.Renderer{ + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,STATE:data.state", + Output: t.Output, + Color: t.Color, + Data: data, + Colorize: rawconfig.Colorize, + } + renderer.Print() + return nil +} diff --git a/core/commands/object_instance_status_ls.go b/core/commands/object_instance_status_ls.go new file mode 100644 index 000000000..88c481b96 --- /dev/null +++ b/core/commands/object_instance_status_ls.go @@ -0,0 +1,59 @@ +package commands + +import ( + "context" + "fmt" + + "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 ( + CmdObjectInstanceStatusLs struct { + OptsGlobal + } +) + +func (t *CmdObjectInstanceStatusLs) Run(selector, kind string) error { + var ( + data any + err error + ) + mergedSelector := mergeSelector(selector, t.ObjectSelector, kind, "") + + c, err := client.New(client.WithURL(t.Server)) + if err != nil { + return err + } + params := api.GetInstanceStatusParams{Path: &mergedSelector} + if t.NodeSelector != "" { + params.Node = &t.NodeSelector + } + resp, err := c.GetInstanceStatusWithResponse(context.Background(), ¶ms) + if err != nil { + return fmt.Errorf("api: %w", err) + } + 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 + } + renderer := output.Renderer{ + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,AVAIL:data.avail", + Output: t.Output, + Color: t.Color, + Data: data, + Colorize: rawconfig.Colorize, + } + renderer.Print() + return nil +} From 5d8f610b37b7242ca5885c6118555d7dde6b361b Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Thu, 7 Sep 2023 10:48:14 +0200 Subject: [PATCH 17/30] Revert to maps to repr res config monitor and status in instance So the rid is not embeded in rcfg, rstat and rmon --- core/clusterip/main.go | 5 +- core/instance/config.go | 68 ++--- core/instance/monitor.go | 78 +++--- core/instance/status.go | 82 +++--- core/object/actor_status.go | 5 +- core/resource/resource.go | 2 - daemon/api/api.yaml | 30 +-- daemon/api/codegen_server_gen.go | 236 +++++++++--------- daemon/api/codegen_type_gen.go | 63 +++-- daemon/dns/main_cmd.go | 12 +- daemon/icfg/main.go | 5 +- daemon/imon/main_cmd.go | 9 +- daemon/imon/orchestration_resource_restart.go | 46 ++-- util/xmap/main.go | 8 + 14 files changed, 308 insertions(+), 341 deletions(-) diff --git a/core/clusterip/main.go b/core/clusterip/main.go index e9ebdbbc6..533cc3d75 100644 --- a/core/clusterip/main.go +++ b/core/clusterip/main.go @@ -86,9 +86,8 @@ func (t L) Load(clusterStatus cluster.Data) L { if inst.Status == nil { continue } - for _, resourceData := range inst.Status.Resources { - rid := resourceData.Rid - if ipIntf, ok := resourceData.Info["ipaddr"]; ok { + for rid, rstat := range inst.Status.Resources { + if ipIntf, ok := rstat.Info["ipaddr"]; ok { p, err := path.Parse(ps) if err != nil { log.Debug().Err(err).Str("path", ps).Send() diff --git a/core/instance/config.go b/core/instance/config.go index 50de42658..7d643888a 100644 --- a/core/instance/config.go +++ b/core/instance/config.go @@ -8,37 +8,37 @@ import ( "github.com/opensvc/om3/core/priority" "github.com/opensvc/om3/core/topology" "github.com/opensvc/om3/util/stringslice" + "github.com/opensvc/om3/util/xmap" ) type ( // Config describes a configuration file content checksum, // timestamp of last change and the nodes it should be installed on. Config struct { - App string `json:"app,omitempty" yaml:"app,omitempty"` - Checksum string `json:"csum" yaml:"csum"` - Children []path.Relation `json:"children,omitempty" yaml:"children,omitempty"` - DRP bool `json:"drp,omitempty" yaml:"drp,omitempty"` - Env string `json:"env,omitempty" yaml:"env,omitempty"` - FlexMax int `json:"flex_max,omitempty" yaml:"flex_max,omitempty"` - FlexMin int `json:"flex_min,omitempty" yaml:"flex_min,omitempty"` - FlexTarget int `json:"flex_target,omitempty" yaml:"flex_target,omitempty"` - MonitorAction MonitorAction `json:"monitor_action,omitempty" yaml:"monitor_action,omitempty"` - PreMonitorAction string `json:"pre_monitor_action,omitempty" yaml:"pre_monitor_action,omitempty"` - Nodename string `json:"-" yaml:"-"` - Orchestrate string `json:"orchestrate" yaml:"orchestrate"` - Path path.T `json:"-" yaml:"-"` - Parents []path.Relation `json:"parents,omitempty" yaml:"parents,omitempty"` - PlacementPolicy placement.Policy `json:"placement_policy" yaml:"placement_policy"` - Priority priority.T `json:"priority,omitempty" yaml:"priority,omitempty"` - Resources ResourceConfigs `json:"resources" yaml:"resources"` - Scope []string `json:"scope" yaml:"scope"` - Subsets map[string]SubsetConfig `json:"subsets" yaml:"subsets"` - Topology topology.T `json:"topology" yaml:"topology"` - UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` + App string `json:"app,omitempty" yaml:"app,omitempty"` + Checksum string `json:"csum" yaml:"csum"` + Children []path.Relation `json:"children,omitempty" yaml:"children,omitempty"` + DRP bool `json:"drp,omitempty" yaml:"drp,omitempty"` + Env string `json:"env,omitempty" yaml:"env,omitempty"` + FlexMax int `json:"flex_max,omitempty" yaml:"flex_max,omitempty"` + FlexMin int `json:"flex_min,omitempty" yaml:"flex_min,omitempty"` + FlexTarget int `json:"flex_target,omitempty" yaml:"flex_target,omitempty"` + MonitorAction MonitorAction `json:"monitor_action,omitempty" yaml:"monitor_action,omitempty"` + PreMonitorAction string `json:"pre_monitor_action,omitempty" yaml:"pre_monitor_action,omitempty"` + Nodename string `json:"-" yaml:"-"` + Orchestrate string `json:"orchestrate" yaml:"orchestrate"` + Path path.T `json:"-" yaml:"-"` + Parents []path.Relation `json:"parents,omitempty" yaml:"parents,omitempty"` + PlacementPolicy placement.Policy `json:"placement_policy" yaml:"placement_policy"` + Priority priority.T `json:"priority,omitempty" yaml:"priority,omitempty"` + Resources ResourceConfigs `json:"resources" yaml:"resources"` + Scope []string `json:"scope" yaml:"scope"` + Subsets SubsetConfigs `json:"subsets" yaml:"subsets"` + Topology topology.T `json:"topology" yaml:"topology"` + UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` } - ResourceConfigs []ResourceConfig + ResourceConfigs map[string]ResourceConfig ResourceConfig struct { - Rid string `json:"rid,omitempty" yaml:"rid,omitempty"` IsDisabled bool `json:"is_disabled" yaml:"is_disabled"` IsMonitored bool `json:"is_monitored" yaml:"is_monitored"` IsStandby bool `json:"is_standby" yaml:"is_standby"` @@ -48,20 +48,22 @@ type ( SubsetConfig struct { Parallel bool `json:"parallel,omitempty" yaml:"parallel,omitempty"` } + SubsetConfigs map[string]SubsetConfig ) -func (cfg Config) DeepCopy() *Config { - subSets := make(map[string]SubsetConfig) +func (m ResourceConfigs) DeepCopy() ResourceConfigs { + return xmap.Copy(m) +} - for id, v := range cfg.Subsets { - subSets[id] = v - } +func (m SubsetConfigs) DeepCopy() SubsetConfigs { + return xmap.Copy(m) +} +func (cfg Config) DeepCopy() *Config { newCfg := cfg newCfg.Scope = append([]string{}, cfg.Scope...) - newCfg.Subsets = subSets - newCfg.Resources = append(ResourceConfigs{}, cfg.Resources...) - + newCfg.Subsets = cfg.Subsets.DeepCopy() + newCfg.Resources = cfg.Resources.DeepCopy() return &newCfg } @@ -82,8 +84,8 @@ func ConfigEqual(a, b *Config) bool { } func (rcfgs ResourceConfigs) Get(rid string) *ResourceConfig { - for _, rcfg := range rcfgs { - if rcfg.Rid == rid { + for rrid, rcfg := range rcfgs { + if rrid == rid { return &rcfg } } diff --git a/core/instance/monitor.go b/core/instance/monitor.go index 0cd2438c2..37b24dd97 100644 --- a/core/instance/monitor.go +++ b/core/instance/monitor.go @@ -8,7 +8,10 @@ import ( "time" "github.com/google/uuid" + "github.com/opensvc/om3/core/resource" + "github.com/opensvc/om3/core/resourceid" "github.com/opensvc/om3/core/status" + "github.com/opensvc/om3/util/xmap" ) type ( @@ -51,8 +54,7 @@ type ( Children map[string]status.T `json:"children,omitempty" yaml:"children,omitempty"` } - ResourceMonitors []ResourceMonitor - ResourceMonitorMap map[string]ResourceMonitor + ResourceMonitors map[string]ResourceMonitor // MonitorUpdate is embedded in the SetInstanceMonitor message to // change some Monitor values. A nil value does not change the @@ -70,7 +72,6 @@ type ( // ResourceMonitor describes the restart states maintained by the daemon // for an object instance. ResourceMonitor struct { - Rid string `json:"rid,omitempty" yaml:"rid,omitempty"` Restart ResourceMonitorRestart `json:"restart" yaml:"restart"` } ResourceMonitorRestart struct { @@ -364,25 +365,6 @@ func (t *MonitorGlobalExpect) UnmarshalText(b []byte) error { } } -func (t ResourceMonitors) AsMap() ResourceMonitorMap { - m := make(ResourceMonitorMap) - for _, d := range t { - m[d.Rid] = d - } - return m -} - -func (t ResourceMonitorMap) AsList() []ResourceMonitor { - l := make([]ResourceMonitor, len(t)) - i := 0 - for rid, d := range t { - d.Rid = rid - l[i] = d - i += 1 - } - return l -} - func (rmon *ResourceMonitor) DecRestartRemaining() { if rmon.Restart.Remaining > 0 { rmon.Restart.Remaining -= 1 @@ -399,22 +381,48 @@ func (rmon *ResourceMonitor) StopRestartTimer() bool { } } -func (l ResourceMonitors) Set(m ResourceMonitor) { - for i, rmon := range l { - if m.Rid == rmon.Rid { - l[i] = m - return - } +func (m ResourceMonitors) Set(rid string, rmon ResourceMonitor) { + m[rid] = rmon +} + +func (m ResourceMonitors) Get(rid string) *ResourceMonitor { + if rmon, ok := m[rid]; ok { + return &rmon + } else { + return nil } - l = append(l, m) } -func (l ResourceMonitors) Get(rid string) *ResourceMonitor { - for _, rmon := range l { - if rmon.Rid != rid { - continue +func (m ResourceMonitors) DeepCopy() ResourceMonitors { + return xmap.Copy(m) +} + +func (mon Monitor) ResourceFlagRestartString(rid resourceid.T, r resource.ExposedStatus) string { + // Restart and retries + retries := 0 + if rmon := mon.Resources.Get(rid.Name); rmon != nil { + retries = rmon.Restart.Remaining + } + return r.Restart.FlagString(retries) +} + +func (mon Monitor) DeepCopy() *Monitor { + v := mon + v.Resources = v.Resources.DeepCopy() + if mon.GlobalExpectOptions != nil { + switch mon.GlobalExpect { + case MonitorGlobalExpectPlacedAt: + b, _ := json.Marshal(mon.GlobalExpectOptions) + var placedAt MonitorGlobalExpectOptionsPlacedAt + // TODO Don't ignore following error + _ = json.Unmarshal(b, &placedAt) + v.GlobalExpectOptions = placedAt + // TODO add other cases for globalExpect values that requires GlobalExpectOptions + default: + b, _ := json.Marshal(mon.GlobalExpectOptions) + // TODO Don't ignore following error + _ = json.Unmarshal(b, &v.GlobalExpectOptions) } - return &rmon } - return nil + return &v } diff --git a/core/instance/status.go b/core/instance/status.go index fea1840d7..d2c307600 100644 --- a/core/instance/status.go +++ b/core/instance/status.go @@ -1,7 +1,6 @@ package instance import ( - "encoding/json" "sort" "time" @@ -16,18 +15,20 @@ type ( // Status describes the instance status. Status struct { - Avail status.T `json:"avail" yaml:"avail"` - Constraints bool `json:"constraints,omitempty" yaml:"constraints,omitempty"` - FrozenAt time.Time `json:"frozen_at,omitempty" yaml:"frozen_at,omitempty"` - LastStartedAt time.Time `json:"last_started_at" yaml:"last_started_at"` - Optional status.T `json:"optional,omitempty" yaml:"optional,omitempty"` - Overall status.T `json:"overall" yaml:"overall"` - Provisioned provisioned.T `json:"provisioned" yaml:"provisioned"` - Resources []resource.ExposedStatus `json:"resources,omitempty" yaml:"resources,omitempty"` - Running ResourceRunningSet `json:"running,omitempty" yaml:"running,omitempty"` - UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` + Avail status.T `json:"avail" yaml:"avail"` + Constraints bool `json:"constraints,omitempty" yaml:"constraints,omitempty"` + FrozenAt time.Time `json:"frozen_at,omitempty" yaml:"frozen_at,omitempty"` + LastStartedAt time.Time `json:"last_started_at" yaml:"last_started_at"` + Optional status.T `json:"optional,omitempty" yaml:"optional,omitempty"` + Overall status.T `json:"overall" yaml:"overall"` + Provisioned provisioned.T `json:"provisioned" yaml:"provisioned"` + Resources ResourceStatuses `json:"resources,omitempty" yaml:"resources,omitempty"` + Running ResourceRunningSet `json:"running,omitempty" yaml:"running,omitempty"` + UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` } + ResourceStatuses map[string]resource.ExposedStatus + // ResourceRunningSet is the list of resource currently running (sync and task). ResourceRunningSet []string @@ -36,6 +37,14 @@ type ( ResourceOrder []resource.ExposedStatus ) +func (m ResourceStatuses) DeepCopy() ResourceStatuses { + n := make(ResourceStatuses) + for k, v := range m { + n[k] = *v.DeepCopy() + } + return n +} + // Has is true if the rid is found running in the Instance Monitor data sent by the daemon. func (t ResourceRunningSet) Has(rid string) bool { for _, r := range t { @@ -52,13 +61,13 @@ func (t ResourceRunningSet) Has(rid string) bool { // 3/ resource name func (t *Status) SortedResources() []resource.ExposedStatus { l := make([]resource.ExposedStatus, 0) - for _, v := range t.Resources { - rid, err := resourceid.Parse(v.Rid) + for rid, rstat := range t.Resources { + id, err := resourceid.Parse(rid) if err != nil { continue } - v.ResourceID = rid - l = append(l, v) + rstat.ResourceID = id + l = append(l, rstat) } sort.Sort(ResourceOrder(l)) return l @@ -73,15 +82,10 @@ func (t Status) IsThawed() bool { } func (t Status) DeepCopy() *Status { - t.Running = append(ResourceRunningSet{}, t.Running...) - - resources := make([]resource.ExposedStatus, 0) - for _, v := range t.Resources { - resources = append(resources, *v.DeepCopy()) - } - t.Resources = resources - - return &t + n := t + n.Running = append(ResourceRunningSet{}, t.Running...) + n.Resources = t.Resources.DeepCopy() + return &n } func (a ResourceOrder) Len() int { return len(a) } @@ -130,33 +134,3 @@ func (t Status) ResourceFlagsString(rid resourceid.T, r resource.ExposedStatus) flags += r.Standby.FlagString() return flags } - -func (mon Monitor) ResourceFlagRestartString(rid resourceid.T, r resource.ExposedStatus) string { - // Restart and retries - retries := 0 - if rmon, ok := mon.Resources.AsMap()[rid.Name]; ok { - retries = rmon.Restart.Remaining - } - return r.Restart.FlagString(retries) -} - -func (mon Monitor) DeepCopy() *Monitor { - v := mon - v.Resources = append(ResourceMonitors{}, v.Resources...) - if mon.GlobalExpectOptions != nil { - switch mon.GlobalExpect { - case MonitorGlobalExpectPlacedAt: - b, _ := json.Marshal(mon.GlobalExpectOptions) - var placedAt MonitorGlobalExpectOptionsPlacedAt - // TODO Don't ignore following error - _ = json.Unmarshal(b, &placedAt) - v.GlobalExpectOptions = placedAt - // TODO add other cases for globalExpect values that requires GlobalExpectOptions - default: - b, _ := json.Marshal(mon.GlobalExpectOptions) - // TODO Don't ignore following error - _ = json.Unmarshal(b, &v.GlobalExpectOptions) - } - } - return &v -} diff --git a/core/object/actor_status.go b/core/object/actor_status.go index 970bca775..206c5fef9 100644 --- a/core/object/actor_status.go +++ b/core/object/actor_status.go @@ -102,7 +102,7 @@ func runningRIDList(t interface{}) []string { } func (t *actor) resourceStatusEval(ctx context.Context, data *instance.Status) error { - resources := make([]resource.ExposedStatus, 0) + data.Resources = make(instance.ResourceStatuses) var mu sync.Mutex err := t.ResourceSets().Do(ctx, t, "", "status", func(ctx context.Context, r resource.Driver) error { xd := resource.GetExposedStatus(ctx, r) @@ -118,8 +118,7 @@ func (t *actor) resourceStatusEval(ctx context.Context, data *instance.Status) e } mu.Lock() - resources = append(resources, xd) - data.Resources = resources + data.Resources[r.RID()] = xd data.Overall.Add(xd.Status) if !xd.Optional { data.Avail.Add(xd.Status) diff --git a/core/resource/resource.go b/core/resource/resource.go index 5a9f47dd6..7ae7078e5 100644 --- a/core/resource/resource.go +++ b/core/resource/resource.go @@ -207,7 +207,6 @@ type ( // which is embedded in the instance status. ExposedStatus struct { ResourceID *resourceid.T `json:"-" yaml:"-"` - Rid string `json:"rid" yaml:"rid"` Label string `json:"label" yaml:"label"` Log []*StatusLogEntry `json:"log,omitempty" yaml:"log,omitempty"` Status status.T `json:"status" yaml:"status"` @@ -1138,7 +1137,6 @@ func SCSIPersistentReservationStatus(r Driver) status.T { // GetExposedStatus returns the resource exposed status data for embedding into the instance status data. func GetExposedStatus(ctx context.Context, r Driver) ExposedStatus { return ExposedStatus{ - Rid: r.RID(), Label: formatResourceLabel(r), Type: r.Manifest().DriverID.String(), Status: Status(ctx, r), diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index 84eeebee3..a1681bb1f 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -1738,7 +1738,9 @@ components: priority: type: integer resources: - $ref: '#/components/schemas/ResourcesConfig' + type: object + additionalProperties: + $ref: '#/components/schemas/ResourceConfig' scope: type: array items: @@ -1808,8 +1810,8 @@ components: is_preserved: type: boolean resources: - type: array - items: + type: object + additionalProperties: $ref: '#/components/schemas/ResourceMonitor' updated_at: type: string @@ -1866,9 +1868,9 @@ components: provisioned: $ref: '#/components/schemas/Provisioned' resources: - type: array - items: - $ref: '#/components/schemas/ResourceExposedStatus' + type: object + additionalProperties: + $ref: '#/components/schemas/ResourceStatus' running: type: array items: @@ -2527,25 +2529,18 @@ components: properties: messages: $ref: '#/components/schemas/RelayMessageList' - ResourcesConfig: - type: array - items: - $ref: '#/components/schemas/ResourceConfig' ResourceConfig: x-go-type: instance.ResourceConfig x-go-type-import: path: github.com/opensvc/om3/core/instance type: object required: - - rid - is_disabled - is_monitored - is_standby - restart - restart_delay properties: - rid: - type: string is_disabled: type: boolean is_monitored: @@ -2557,7 +2552,7 @@ components: restart_delay: type: string format: duration - ResourceExposedStatus: + ResourceStatus: type: object required: - disable @@ -2569,8 +2564,6 @@ components: - optional - provisioned - restart - - rid - - rid - standby - status - subset @@ -2608,8 +2601,6 @@ components: $ref: '#/components/schemas/ResourceProvisionStatus' restart: type: integer - rid: - $ref: '#/components/schemas/ResourceId' standby: type: boolean description: | @@ -2631,11 +2622,8 @@ components: path: github.com/opensvc/om3/core/instance type: object required: - - rid - restart properties: - rid: - type: string restart: $ref: '#/components/schemas/ResourceMonitorRestart' ResourceMonitorRestart: diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index 1e32e312e..765fa0068 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -1288,124 +1288,124 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", + "AA==", } // 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 62c75b461..97e696b47 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -568,8 +568,34 @@ type RelayMessages struct { // ResourceConfig defines model for ResourceConfig. type ResourceConfig = instance.ResourceConfig -// ResourceExposedStatus defines model for ResourceExposedStatus. -type ResourceExposedStatus struct { +// ResourceLog defines model for ResourceLog. +type ResourceLog = []ResourceLogEntry + +// ResourceLogEntry defines model for ResourceLogEntry. +type ResourceLogEntry struct { + Level string `json:"level"` + Message string `json:"message"` +} + +// ResourceMonitor defines model for ResourceMonitor. +type ResourceMonitor = instance.ResourceMonitor + +// ResourceMonitorRestart defines model for ResourceMonitorRestart. +type ResourceMonitorRestart struct { + LastAt time.Time `json:"last_at"` + Remaining int `json:"remaining"` +} + +// ResourceProvisionStatus defines model for ResourceProvisionStatus. +type ResourceProvisionStatus struct { + Mtime time.Time `json:"mtime"` + + // State service, instance or resource provisioned state + State Provisioned `json:"state"` +} + +// ResourceStatus defines model for ResourceStatus. +type ResourceStatus struct { // Disable hints the resource ignores all state transition actions Disable bool `json:"disable"` @@ -592,7 +618,6 @@ type ResourceExposedStatus struct { Optional bool `json:"optional"` Provisioned ResourceProvisionStatus `json:"provisioned"` Restart int `json:"restart"` - Rid ResourceId `json:"rid"` // Standby resource should always be up, even after a stop state transition action Standby bool `json:"standby"` @@ -604,38 +629,6 @@ type ResourceExposedStatus struct { Type string `json:"type"` } -// ResourceId defines model for ResourceId. -type ResourceId = string - -// ResourceLog defines model for ResourceLog. -type ResourceLog = []ResourceLogEntry - -// ResourceLogEntry defines model for ResourceLogEntry. -type ResourceLogEntry struct { - Level string `json:"level"` - Message string `json:"message"` -} - -// ResourceMonitor defines model for ResourceMonitor. -type ResourceMonitor = instance.ResourceMonitor - -// ResourceMonitorRestart defines model for ResourceMonitorRestart. -type ResourceMonitorRestart struct { - LastAt time.Time `json:"last_at"` - Remaining int `json:"remaining"` -} - -// ResourceProvisionStatus defines model for ResourceProvisionStatus. -type ResourceProvisionStatus struct { - Mtime time.Time `json:"mtime"` - - // State service, instance or resource provisioned state - State Provisioned `json:"state"` -} - -// ResourcesConfig defines model for ResourcesConfig. -type ResourcesConfig = []ResourceConfig - // Role defines model for Role. type Role string diff --git a/daemon/dns/main_cmd.go b/daemon/dns/main_cmd.go index d0123cf57..d432730e5 100644 --- a/daemon/dns/main_cmd.go +++ b/daemon/dns/main_cmd.go @@ -141,8 +141,8 @@ func (t *dns) onInstanceStatusUpdated(c *msgbus.InstanceStatusUpdated) { } } } - for _, r := range c.Value.Resources { - i, ok := r.Info[ipAddrInfoKey] + for rid, rstat := range c.Value.Resources { + i, ok := rstat.Info[ipAddrInfoKey] if !ok { continue } @@ -197,9 +197,9 @@ func (t *dns) onInstanceStatusUpdated(c *msgbus.InstanceStatusUpdated) { Content: nameOnNode, }) - if rid, err := resourceid.Parse(r.Rid); err == nil { - nameWithResourceName := rid.Index() + "." + name - nameOnNodeWithResourceName := rid.Index() + "." + nameOnNode + if id, err := resourceid.Parse(rid); err == nil { + nameWithResourceName := id.Index() + "." + name + nameOnNodeWithResourceName := id.Index() + "." + nameOnNode // Add a resource direct record (node agnostic) stage(Record{ @@ -237,7 +237,7 @@ func (t *dns) onInstanceStatusUpdated(c *msgbus.InstanceStatusUpdated) { Content: nameOnNodeWithResourceName, }) } - stageSRVs(r) + stageSRVs(rstat) } for key, record := range existingRecords { diff --git a/daemon/icfg/main.go b/daemon/icfg/main.go index 770fa2781..0903adc07 100644 --- a/daemon/icfg/main.go +++ b/daemon/icfg/main.go @@ -387,14 +387,13 @@ func (o *T) getResources(cf *xconfig.T) instance.ResourceConfigs { case "env", "DEFAULT": continue } - m = append(m, instance.ResourceConfig{ - Rid: section, + m[section] = instance.ResourceConfig{ RestartDelay: cf.GetDuration(key.New(section, "restart_delay")), Restart: cf.GetInt(key.New(section, "restart")), IsDisabled: cf.GetBool(key.New(section, "disable")), IsMonitored: cf.GetBool(key.New(section, "monitor")), IsStandby: cf.GetBool(key.New(section, "standby")), - }) + } } return m } diff --git a/daemon/imon/main_cmd.go b/daemon/imon/main_cmd.go index 7d5968953..8592417c0 100644 --- a/daemon/imon/main_cmd.go +++ b/daemon/imon/main_cmd.go @@ -1015,13 +1015,12 @@ func (o *imon) doAction(action func() error, newState, successState, errorState func (o *imon) initResourceMonitor() { m := make(instance.ResourceMonitors, 0) - for _, res := range o.instConfig.Resources { - m = append(m, instance.ResourceMonitor{ - Rid: res.Rid, + for rid, rcfg := range o.instConfig.Resources { + m[rid] = instance.ResourceMonitor{ Restart: instance.ResourceMonitorRestart{ - Remaining: res.Restart, + Remaining: rcfg.Restart, }, - }) + } } o.state.Resources = m o.change = true diff --git a/daemon/imon/orchestration_resource_restart.go b/daemon/imon/orchestration_resource_restart.go index 2b4d89e16..95633bf55 100644 --- a/daemon/imon/orchestration_resource_restart.go +++ b/daemon/imon/orchestration_resource_restart.go @@ -117,34 +117,34 @@ func (o *imon) orchestrateResourceRestart() { } } - resetTimer := func(rmon *instance.ResourceMonitor) { - todoRestart.Del(rmon.Rid) - todoStandby.Del(rmon.Rid) + resetTimer := func(rid string, rmon *instance.ResourceMonitor) { + todoRestart.Del(rid) + todoStandby.Del(rid) if rmon.Restart.Timer != nil { - o.log.Info().Msgf("resource %s is up, reset delayed restart", rmon.Rid) + o.log.Info().Msgf("resource %s is up, reset delayed restart", rid) o.change = rmon.StopRestartTimer() - o.state.Resources.Set(*rmon) + o.state.Resources.Set(rid, *rmon) } } - resetRemaining := func(rcfg *instance.ResourceConfig, rmon *instance.ResourceMonitor) { + resetRemaining := func(rid string, rcfg *instance.ResourceConfig, rmon *instance.ResourceMonitor) { if rmon.Restart.Remaining != rcfg.Restart { - o.log.Info().Msgf("resource %s is up, reset restart count to the max (%d -> %d)", rcfg.Rid, rmon.Restart.Remaining, rcfg.Restart) + o.log.Info().Msgf("resource %s is up, reset restart count to the max (%d -> %d)", rid, rmon.Restart.Remaining, rcfg.Restart) o.state.MonitorActionExecutedAt = time.Time{} rmon.Restart.Remaining = rcfg.Restart - o.state.Resources.Set(*rmon) + o.state.Resources.Set(rid, *rmon) o.change = true } } - resetRemainingAndTimer := func(rcfg *instance.ResourceConfig, rmon *instance.ResourceMonitor) { - resetRemaining(rcfg, rmon) - resetTimer(rmon) + resetRemainingAndTimer := func(rid string, rcfg *instance.ResourceConfig, rmon *instance.ResourceMonitor) { + resetRemaining(rid, rcfg, rmon) + resetTimer(rid, rmon) } resetTimers := func() { - for _, rmon := range o.state.Resources { - resetTimer(&rmon) + for rid, rmon := range o.state.Resources { + resetTimer(rid, &rmon) } } @@ -158,13 +158,13 @@ func (o *imon) orchestrateResourceRestart() { return case rcfg.IsDisabled: o.log.Debug().Msgf("resource %s restart skip: disable=%v", rid, rcfg.IsDisabled) - resetRemainingAndTimer(rcfg, rmon) + resetRemainingAndTimer(rid, rcfg, rmon) case resStatus.Is(status.NotApplicable, status.Undef): o.log.Debug().Msgf("resource %s restart skip: status=%s", rid, resStatus) - resetRemainingAndTimer(rcfg, rmon) + resetRemainingAndTimer(rid, rcfg, rmon) case resStatus.Is(status.Up, status.StandbyUp): o.log.Debug().Msgf("resource %s restart skip: status=%s", rid, resStatus) - resetRemainingAndTimer(rcfg, rmon) + resetRemainingAndTimer(rid, rcfg, rmon) case rmon.Restart.Timer != nil: o.log.Debug().Msgf("resource %s restart skip: already has a delay timer", rid) case !o.state.MonitorActionExecutedAt.IsZero(): @@ -183,7 +183,7 @@ func (o *imon) orchestrateResourceRestart() { todoStandby.Add(rid) default: o.log.Debug().Msgf("resource %s restart skip: instance not started", rid) - resetTimer(rmon) + resetTimer(rid, rmon) } } @@ -228,7 +228,7 @@ func (o *imon) orchestrateResourceRestart() { } rmon.Restart.LastAt = now rmon.Restart.Timer = nil - o.state.Resources.Set(*rmon) + o.state.Resources.Set(rid, *rmon) o.change = true } action := func() error { @@ -243,7 +243,7 @@ func (o *imon) orchestrateResourceRestart() { } rmon.DecRestartRemaining() rmon.Restart.Timer = timer - o.state.Resources.Set(*rmon) + o.state.Resources.Set(rid, *rmon) o.change = true } } @@ -262,7 +262,7 @@ func (o *imon) orchestrateResourceRestart() { } rmon.Restart.LastAt = now rmon.Restart.Timer = nil - o.state.Resources.Set(*rmon) + o.state.Resources.Set(rid, *rmon) o.change = true } action := func() error { @@ -277,7 +277,7 @@ func (o *imon) orchestrateResourceRestart() { } rmon.DecRestartRemaining() rmon.Restart.Timer = timer - o.state.Resources.Set(*rmon) + o.state.Resources.Set(rid, *rmon) o.change = true } } @@ -344,8 +344,8 @@ func (o *imon) orchestrateResourceRestart() { started := instMonitor.LocalExpect == instance.MonitorLocalExpectStarted - for _, rstat := range o.instStatus[o.localhost].Resources { - planFor(rstat.Rid, rstat.Status, started) + for rid, rstat := range o.instStatus[o.localhost].Resources { + planFor(rid, rstat.Status, started) } doStandby() doRestart() diff --git a/util/xmap/main.go b/util/xmap/main.go index f8bac0460..ba9cddc08 100644 --- a/util/xmap/main.go +++ b/util/xmap/main.go @@ -11,3 +11,11 @@ func Keys(i interface{}) []string { } return l } + +func Copy[K, V comparable](m map[K]V) map[K]V { + result := make(map[K]V) + for k, v := range m { + result[k] = v + } + return result +} From 6f5c76f1f9856af7cb1f5c43fbec74fd7ebf3150 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Thu, 7 Sep 2023 10:59:47 +0200 Subject: [PATCH 18/30] Rename resource.Status() to EvalStatus() So the Status word is free to be used as a type. --- core/object/core_action.go | 2 +- core/resource/resource.go | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/object/core_action.go b/core/object/core_action.go index 8f6dda317..3f7ae017b 100644 --- a/core/object/core_action.go +++ b/core/object/core_action.go @@ -384,7 +384,7 @@ func (t *actor) action(ctx context.Context, fn resourceset.DoFunc) error { } t.ResourceSets().Do(ctx, l, b, "pre-"+action.Name+" status", func(ctx context.Context, r resource.Driver) error { sb := statusbus.FromContext(ctx) - sb.Post(r.RID(), resource.Status(ctx, r), false) + sb.Post(r.RID(), resource.EvalStatus(ctx, r), false) return nil }) if err := t.abortStart(ctx, l); err != nil { diff --git a/core/resource/resource.go b/core/resource/resource.go index 7ae7078e5..8b5f9eb5a 100644 --- a/core/resource/resource.go +++ b/core/resource/resource.go @@ -714,7 +714,7 @@ func checkRequires(ctx context.Context, r Driver) error { // Boot deactivates a resource when the node is rebooted func Boot(ctx context.Context, r Driver) error { - defer Status(ctx, r) + defer EvalStatus(ctx, r) return boot(ctx, r) } @@ -724,7 +724,7 @@ func Run(ctx context.Context, r Driver) error { if !ok { return ErrActionNotSupported } - defer Status(ctx, r) + defer EvalStatus(ctx, r) if r.IsDisabled() { return ErrDisabled } @@ -753,7 +753,7 @@ func Run(ctx context.Context, r Driver) error { // PRStop deactivates a resource interfacer S3GPR func PRStop(ctx context.Context, r Driver) error { - defer Status(ctx, r) + defer EvalStatus(ctx, r) if r.IsDisabled() { return ErrDisabled } @@ -769,7 +769,7 @@ func PRStop(ctx context.Context, r Driver) error { // PRStart activates a resource interfacer S3GPR func PRStart(ctx context.Context, r Driver) error { - defer Status(ctx, r) + defer EvalStatus(ctx, r) if r.IsDisabled() { return ErrDisabled } @@ -799,7 +799,7 @@ func StartStandby(ctx context.Context, r Driver) error { if !r.IsStandby() { return nil } - defer Status(ctx, r) + defer EvalStatus(ctx, r) if r.IsDisabled() { return ErrDisabled } @@ -836,7 +836,7 @@ func Start(ctx context.Context, r Driver) error { if !ok { return ErrActionNotSupported } - defer Status(ctx, r) + defer EvalStatus(ctx, r) if r.IsDisabled() { return ErrDisabled } @@ -873,7 +873,7 @@ func Resync(ctx context.Context, r Driver) error { if !ok { return ErrActionNotSupported } - defer Status(ctx, r) + defer EvalStatus(ctx, r) if r.IsDisabled() { return ErrDisabled } @@ -892,7 +892,7 @@ func Full(ctx context.Context, r Driver) error { if !ok { return ErrActionNotSupported } - defer Status(ctx, r) + defer EvalStatus(ctx, r) if r.IsDisabled() { return ErrDisabled } @@ -911,7 +911,7 @@ func Update(ctx context.Context, r Driver) error { if !ok { return ErrActionNotSupported } - defer Status(ctx, r) + defer EvalStatus(ctx, r) if r.IsDisabled() { return ErrDisabled } @@ -925,13 +925,13 @@ func Update(ctx context.Context, r Driver) error { // Shutdown deactivates a resource even if standby is true func Shutdown(ctx context.Context, r Driver) error { - defer Status(ctx, r) + defer EvalStatus(ctx, r) return shutdown(ctx, r) } // Stop deactivates a resource func Stop(ctx context.Context, r Driver) error { - defer Status(ctx, r) + defer EvalStatus(ctx, r) return stop(ctx, r) } @@ -1058,8 +1058,8 @@ func stop(ctx context.Context, r Driver) error { return nil } -// Status evaluates the status of a resource interfacer -func Status(ctx context.Context, r Driver) status.T { +// EvalStatus evaluates the status of a resource interfacer +func EvalStatus(ctx context.Context, r Driver) status.T { r.StatusLog().Reset() if r.IsStatusDisabled() { r.StatusLog().Info("nostatus") @@ -1139,7 +1139,7 @@ func GetExposedStatus(ctx context.Context, r Driver) ExposedStatus { return ExposedStatus{ Label: formatResourceLabel(r), Type: r.Manifest().DriverID.String(), - Status: Status(ctx, r), + Status: EvalStatus(ctx, r), Subset: r.RSubset(), Tags: r.TagSet(), Log: r.StatusLog().Entries(), From a22c35a6dfe60493c6e52b20aa4e0f5805daeb9b Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Thu, 7 Sep 2023 11:54:58 +0200 Subject: [PATCH 19/30] Renames in the resource package * ExposedStatus => Status * GetExposedStatus => GetStatus * exposedStatusInfo => getStatusInfo * exposedStatusInfoSched => getStatusInfoSched --- core/instance/instance_test.go | 2 +- core/instance/monitor.go | 2 +- core/instance/status.go | 10 ++++---- core/object/actor_status.go | 2 +- core/resource/resource.go | 42 +++++++++++++++++----------------- daemon/dns/main_cmd.go | 2 +- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/core/instance/instance_test.go b/core/instance/instance_test.go index e6dfd05d2..cbc0136de 100644 --- a/core/instance/instance_test.go +++ b/core/instance/instance_test.go @@ -29,7 +29,7 @@ func Test_Status_Unmarshal(t *testing.T) { Overall: status.Down, Provisioned: provisioned.Mixed, UpdatedAt: time.Date(2022, time.December, 28, 11, 21, 45, 800780633, time.UTC), - Resources: []resource.ExposedStatus{ + Resources: []resource.Status{ { ResourceID: (*resourceid.T)(nil), Rid: "volume#1", diff --git a/core/instance/monitor.go b/core/instance/monitor.go index 37b24dd97..3dc9984a4 100644 --- a/core/instance/monitor.go +++ b/core/instance/monitor.go @@ -397,7 +397,7 @@ func (m ResourceMonitors) DeepCopy() ResourceMonitors { return xmap.Copy(m) } -func (mon Monitor) ResourceFlagRestartString(rid resourceid.T, r resource.ExposedStatus) string { +func (mon Monitor) ResourceFlagRestartString(rid resourceid.T, r resource.Status) string { // Restart and retries retries := 0 if rmon := mon.Resources.Get(rid.Name); rmon != nil { diff --git a/core/instance/status.go b/core/instance/status.go index d2c307600..1ce2d21e8 100644 --- a/core/instance/status.go +++ b/core/instance/status.go @@ -27,14 +27,14 @@ type ( UpdatedAt time.Time `json:"updated_at" yaml:"updated_at"` } - ResourceStatuses map[string]resource.ExposedStatus + ResourceStatuses map[string]resource.Status // ResourceRunningSet is the list of resource currently running (sync and task). ResourceRunningSet []string // ResourceOrder is a sortable list representation of the // instance status resources map. - ResourceOrder []resource.ExposedStatus + ResourceOrder []resource.Status ) func (m ResourceStatuses) DeepCopy() ResourceStatuses { @@ -59,8 +59,8 @@ func (t ResourceRunningSet) Has(rid string) bool { // 1/ driver group // 2/ subset // 3/ resource name -func (t *Status) SortedResources() []resource.ExposedStatus { - l := make([]resource.ExposedStatus, 0) +func (t *Status) SortedResources() []resource.Status { + l := make([]resource.Status, 0) for rid, rstat := range t.Resources { id, err := resourceid.Parse(rid) if err != nil { @@ -116,7 +116,7 @@ func (a ResourceOrder) Less(i, j int) bool { // E Encap // P Provisioned // S Standby -func (t Status) ResourceFlagsString(rid resourceid.T, r resource.ExposedStatus) string { +func (t Status) ResourceFlagsString(rid resourceid.T, r resource.Status) string { flags := "" // Running task or sync diff --git a/core/object/actor_status.go b/core/object/actor_status.go index 206c5fef9..f827a0837 100644 --- a/core/object/actor_status.go +++ b/core/object/actor_status.go @@ -105,7 +105,7 @@ func (t *actor) resourceStatusEval(ctx context.Context, data *instance.Status) e data.Resources = make(instance.ResourceStatuses) var mu sync.Mutex err := t.ResourceSets().Do(ctx, t, "", "status", func(ctx context.Context, r resource.Driver) error { - xd := resource.GetExposedStatus(ctx, r) + xd := resource.GetStatus(ctx, r) // If the resource is up but the provisioned flag is unset, set // the provisioned flag. diff --git a/core/resource/resource.go b/core/resource/resource.go index 8b5f9eb5a..f302a8366 100644 --- a/core/resource/resource.go +++ b/core/resource/resource.go @@ -203,9 +203,9 @@ type ( // TagSet is the list of unique tag names found in the resource definition. TagSet []string - // ExposedStatus is the structure representing the resource status, + // Status is the structure representing the resource status, // which is embedded in the instance status. - ExposedStatus struct { + Status struct { ResourceID *resourceid.T `json:"-" yaml:"-"` Label string `json:"label" yaml:"label"` Log []*StatusLogEntry `json:"log,omitempty" yaml:"log,omitempty"` @@ -234,7 +234,7 @@ type ( Hook int - ExposedStatusInfoSchedAction struct { + StatusInfoSchedAction struct { Last time.Time `json:"last" yaml:"last"` } @@ -866,7 +866,7 @@ func Start(ctx context.Context, r Driver) error { return nil } -// Resync execute the resource Resync function, if exposed. +// Resync execute the resource Resync function, if implemented by the driver. func Resync(ctx context.Context, r Driver) error { var i any = r s, ok := i.(resyncer) @@ -885,7 +885,7 @@ func Resync(ctx context.Context, r Driver) error { return nil } -// Full execute the resource Update function, if exposed. +// Full execute the resource Update function, if implemented by the driver. func Full(ctx context.Context, r Driver) error { var i any = r s, ok := i.(fuller) @@ -904,7 +904,7 @@ func Full(ctx context.Context, r Driver) error { return nil } -// Update execute the resource Update function, if exposed. +// Update execute the resource Update function, if implemented by the driver. func Update(ctx context.Context, r Driver) error { var i any = r s, ok := i.(updater) @@ -1134,9 +1134,9 @@ func SCSIPersistentReservationStatus(r Driver) status.T { } } -// GetExposedStatus returns the resource exposed status data for embedding into the instance status data. -func GetExposedStatus(ctx context.Context, r Driver) ExposedStatus { - return ExposedStatus{ +// GetStatus returns the resource Status for embedding into the instance.Status. +func GetStatus(ctx context.Context, r Driver) Status { + return Status{ Label: formatResourceLabel(r), Type: r.Manifest().DriverID.String(), Status: EvalStatus(ctx, r), @@ -1144,7 +1144,7 @@ func GetExposedStatus(ctx context.Context, r Driver) ExposedStatus { Tags: r.TagSet(), Log: r.StatusLog().Entries(), Provisioned: getProvisionStatus(r), - Info: exposedStatusInfo(r), + Info: getStatusInfo(r), Restart: RestartFlag(r.RestartCount()), Optional: OptionalFlag(r.IsOptional()), Standby: StandbyFlag(r.IsStandby()), @@ -1154,7 +1154,7 @@ func GetExposedStatus(ctx context.Context, r Driver) ExposedStatus { } func printStatus(ctx context.Context, r Driver) error { - data := GetExposedStatus(ctx, r) + data := GetStatus(ctx, r) enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") return enc.Encode(data) @@ -1214,22 +1214,22 @@ func (t *T) DoWithLock(disable bool, timeout time.Duration, intent string, f fun return f() } -func exposedStatusInfo(t Driver) (data map[string]any) { +func getStatusInfo(t Driver) (data map[string]any) { if i, ok := t.(StatusInfoer); ok { data = i.StatusInfo() } else { data = make(map[string]any) } if i, ok := t.(Scheduler); ok { - data["sched"] = exposedStatusInfoSched(i) + data["sched"] = getStatusInfoSched(i) } return data } -func exposedStatusInfoSched(t Scheduler) map[string]ExposedStatusInfoSchedAction { - data := make(map[string]ExposedStatusInfoSchedAction) +func getStatusInfoSched(t Scheduler) map[string]StatusInfoSchedAction { + data := make(map[string]StatusInfoSchedAction) for _, e := range t.Schedules() { - ad := ExposedStatusInfoSchedAction{ + ad := StatusInfoSchedAction{ Last: e.LastRunAt, } data[e.Action] = ad @@ -1237,14 +1237,14 @@ func exposedStatusInfoSched(t Scheduler) map[string]ExposedStatusInfoSchedAction return data } -func (exposedStatus ExposedStatus) DeepCopy() *ExposedStatus { - newValue := ExposedStatus{} - if b, err := json.Marshal(exposedStatus); err != nil { - return &ExposedStatus{} +func (rstat Status) DeepCopy() *Status { + newValue := Status{} + if b, err := json.Marshal(rstat); err != nil { + return &Status{} } else if err := json.Unmarshal(b, &newValue); err == nil { return &newValue } - return &ExposedStatus{} + return &Status{} } func (t SCSIPersistentReservation) IsSCSIPersistentReservationPreemptAbortDisabled() bool { diff --git a/daemon/dns/main_cmd.go b/daemon/dns/main_cmd.go index d432730e5..cbb5b0641 100644 --- a/daemon/dns/main_cmd.go +++ b/daemon/dns/main_cmd.go @@ -127,7 +127,7 @@ func (t *dns) onInstanceStatusUpdated(c *msgbus.InstanceStatusUpdated) { }) } - stageSRVs := func(r resource.ExposedStatus) { + stageSRVs := func(r resource.Status) { i, ok := r.Info[exposeInfoKey] if !ok { return From c6791bf8538677d8d767ae55f9949f487416e980 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 8 Sep 2023 12:12:49 +0200 Subject: [PATCH 20/30] 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 | 267 +++++++++++-------- 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, 662 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 a1681bb1f..455fb8d37 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 7082ed94d..7a1843b42 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 765fa0068..b8a3afa17 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,129 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "AA==", + "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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 97e696b47..50978d253 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. @@ -231,7 +239,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"` } @@ -410,18 +418,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 @@ -430,11 +480,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 { @@ -491,7 +544,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"` } @@ -513,16 +566,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"` } @@ -550,11 +603,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. @@ -582,7 +635,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"` } @@ -878,6 +931,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) From 04e5cc62e605846ace0b9376d9037380d9ac3f9c Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 8 Sep 2023 17:36:11 +0200 Subject: [PATCH 21/30] Add GET /resource handlers * GET /resource * GET /resource/config * GET /resource/monitor * GET /resource/status --- daemon/api/api.yaml | 312 +++++++-- daemon/api/codegen_client_gen.go | 790 ++++++++++++++++++++++- daemon/api/codegen_server_gen.go | 411 ++++++++---- daemon/api/codegen_type_gen.go | 146 +++-- daemon/daemonapi/get_resource.go | 58 ++ daemon/daemonapi/get_resource_config.go | 48 ++ daemon/daemonapi/get_resource_monitor.go | 48 ++ daemon/daemonapi/get_resource_status.go | 48 ++ 8 files changed, 1609 insertions(+), 252 deletions(-) create mode 100644 daemon/daemonapi/get_resource.go create mode 100644 daemon/daemonapi/get_resource_config.go create mode 100644 daemon/daemonapi/get_resource_monitor.go create mode 100644 daemon/daemonapi/get_resource_status.go diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index 455fb8d37..adbc64cb1 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -1475,6 +1475,114 @@ paths: $ref: '#/components/responses/403' 500: $ref: '#/components/responses/500' + /resource: + get: + operationId: GetResource + tags: + - resource + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/PathOptional' + - $ref: '#/components/parameters/NodeOptional' + - $ref: '#/components/parameters/RidOptional' + responses: + 200: + description: get resource config, monitor and status + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + /resource/config: + get: + operationId: GetResourceConfig + tags: + - resource + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/PathOptional' + - $ref: '#/components/parameters/NodeOptional' + - $ref: '#/components/parameters/RidOptional' + responses: + 200: + description: get resource config + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceConfigArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + /resource/monitor: + get: + operationId: GetResourceMonitor + tags: + - resource + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/PathOptional' + - $ref: '#/components/parameters/NodeOptional' + - $ref: '#/components/parameters/RidOptional' + responses: + 200: + description: get resource monitor + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceMonitorArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + /resource/status: + get: + operationId: GetResourceStatus + tags: + - resource + security: + - basicAuth: [] + - bearerAuth: [] + parameters: + - $ref: '#/components/parameters/PathOptional' + - $ref: '#/components/parameters/NodeOptional' + - $ref: '#/components/parameters/RidOptional' + responses: + 200: + description: get resource status + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceStatusArray' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' components: schemas: ArbitratorStatus: @@ -1874,7 +1982,6 @@ components: - provisioned - resources - running - - updated_at - scale - updated_at properties: @@ -2686,6 +2793,34 @@ components: properties: messages: $ref: '#/components/schemas/RelayMessageList' + + # ======================================================================== + # resource schemas + # ======================================================================== + + Resource: + type: object + properties: + config: + $ref: '#/components/schemas/ResourceConfig' + monitor: + $ref: '#/components/schemas/ResourceMonitor' + status: + $ref: '#/components/schemas/ResourceStatus' + ResourceArray: + type: array + items: + $ref: '#/components/schemas/ResourceItem' + ResourceItem: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/ResourceMeta' + data: + $ref: '#/components/schemas/Resource' ResourceConfig: x-go-type: instance.ResourceConfig x-go-type-import: @@ -2709,7 +2844,101 @@ components: restart_delay: type: string format: duration + ResourceConfigArray: + type: array + items: + $ref: '#/components/schemas/ResourceConfigItem' + ResourceConfigItem: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/ResourceMeta' + data: + $ref: '#/components/schemas/ResourceConfig' + ResourceId: + type: string + ResourceLog: + type: array + items: + $ref: '#/components/schemas/ResourceLogEntry' + ResourceLogEntry: + type: object + required: + - level + - message + properties: + level: + type: string + message: + type: string + ResourceProvisionStatus: + type: object + required: + - state + - mtime + properties: + mtime: + type: string + format: date-time + state: + $ref: '#/components/schemas/Provisioned' + ResourceMeta: + type: object + required: + - node + - object + - rid + properties: + node: + type: string + object: + type: string + rid: + type: string + ResourceMonitor: + x-go-type: instance.ResourceMonitor + x-go-type-import: + path: github.com/opensvc/om3/core/instance + type: object + required: + - restart + properties: + restart: + $ref: '#/components/schemas/ResourceMonitorRestart' + ResourceMonitorArray: + type: array + items: + $ref: '#/components/schemas/ResourceMonitorItem' + ResourceMonitorItem: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/ResourceMeta' + data: + $ref: '#/components/schemas/ResourceMonitor' + ResourceMonitorRestart: + type: object + required: + - remaining + - last_at + properties: + remaining: + type: integer + last_at: + x-oapi-codegen-extra-tags: + yaml: last_at + type: string + format: date-time ResourceStatus: + x-go-type: resource.Status + x-go-type-import: + path: github.com/opensvc/om3/core/resource type: object required: - disable @@ -2773,56 +3002,20 @@ components: type: string type: type: string - ResourceMonitor: - x-go-type: instance.ResourceMonitor - x-go-type-import: - path: github.com/opensvc/om3/core/instance - type: object - required: - - restart - properties: - restart: - $ref: '#/components/schemas/ResourceMonitorRestart' - ResourceMonitorRestart: - type: object - required: - - remaining - - last_at - properties: - remaining: - type: integer - last_at: - x-oapi-codegen-extra-tags: - yaml: last_at - type: string - format: date-time - ResourceId: - type: string - ResourceLog: + ResourceStatusArray: type: array items: - $ref: '#/components/schemas/ResourceLogEntry' - ResourceLogEntry: - type: object - required: - - level - - message - properties: - level: - type: string - message: - type: string - ResourceProvisionStatus: - type: object - required: - - state - - mtime - properties: - mtime: - type: string - format: date-time - state: - $ref: '#/components/schemas/Provisioned' + $ref: '#/components/schemas/ResourceStatusItem' + ResourceStatusItem: + type: object + required: + - meta + - data + properties: + meta: + $ref: '#/components/schemas/ResourceMeta' + data: + $ref: '#/components/schemas/ResourceStatus' DaemonStatus: type: object required: @@ -3027,19 +3220,11 @@ components: NodeOptional: name: node in: query - description: object and instance selector expression. + description: node selector expression. schema: type: string example: n2,az=eu1 - Resource: - name: resource - in: query - description: resource selector expression. - required: true - schema: - type: string - example: fs#1,ip - ResourceOptional: + RidOptional: name: resource in: query description: resource selector expression. @@ -3074,7 +3259,6 @@ components: bearerFormat: JWT responses: '200': - type: object description: OK content: application/json: @@ -3083,56 +3267,48 @@ components: '204': description: No Content '400': - type: object description: Bad Request content: application/json: schema: $ref: "#/components/schemas/Problem" '401': - type: object description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/Problem" '403': - type: object description: Bad Request content: application/json: schema: $ref: "#/components/schemas/Problem" '404': - type: object description: Not Found content: application/json: schema: $ref: "#/components/schemas/Problem" '408': - type: object description: Request Timeout content: application/json: schema: $ref: "#/components/schemas/Problem" '409': - type: object description: Conflict content: application/json: schema: $ref: "#/components/schemas/Problem" '500': - type: object description: Internal Server Error content: application/json: schema: $ref: "#/components/schemas/Problem" '503': - type: object description: Service Unavailable content: application/json: diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index 7a1843b42..5c10e9d3c 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -286,6 +286,18 @@ type ClientInterface interface { PostRelayMessageWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) PostRelayMessage(ctx context.Context, body PostRelayMessageJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetResource request + GetResource(ctx context.Context, params *GetResourceParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetResourceConfig request + GetResourceConfig(ctx context.Context, params *GetResourceConfigParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetResourceMonitor request + GetResourceMonitor(ctx context.Context, params *GetResourceMonitorParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetResourceStatus request + GetResourceStatus(ctx context.Context, params *GetResourceStatusParams, reqEditors ...RequestEditorFn) (*http.Response, error) } func (c *Client) PostAuthToken(ctx context.Context, params *PostAuthTokenParams, reqEditors ...RequestEditorFn) (*http.Response, error) { @@ -1152,6 +1164,54 @@ func (c *Client) PostRelayMessage(ctx context.Context, body PostRelayMessageJSON return c.Client.Do(req) } +func (c *Client) GetResource(ctx context.Context, params *GetResourceParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetResourceRequest(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) GetResourceConfig(ctx context.Context, params *GetResourceConfigParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetResourceConfigRequest(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) GetResourceMonitor(ctx context.Context, params *GetResourceMonitorParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetResourceMonitorRequest(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) GetResourceStatus(ctx context.Context, params *GetResourceStatusParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetResourceStatusRequest(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) +} + // NewPostAuthTokenRequest generates requests for PostAuthToken func NewPostAuthTokenRequest(server string, params *PostAuthTokenParams) (*http.Request, error) { var err error @@ -3560,6 +3620,322 @@ func NewPostRelayMessageRequestWithBody(server string, contentType string, body return req, nil } +// NewGetResourceRequest generates requests for GetResource +func NewGetResourceRequest(server string, params *GetResourceParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/resource") + 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) + } + } + } + + } + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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) + } + } + } + + } + + if params.Resource != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "resource", runtime.ParamLocationQuery, *params.Resource); 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 +} + +// NewGetResourceConfigRequest generates requests for GetResourceConfig +func NewGetResourceConfigRequest(server string, params *GetResourceConfigParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/resource/config") + 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) + } + } + } + + } + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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) + } + } + } + + } + + if params.Resource != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "resource", runtime.ParamLocationQuery, *params.Resource); 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 +} + +// NewGetResourceMonitorRequest generates requests for GetResourceMonitor +func NewGetResourceMonitorRequest(server string, params *GetResourceMonitorParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/resource/monitor") + 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) + } + } + } + + } + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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) + } + } + } + + } + + if params.Resource != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "resource", runtime.ParamLocationQuery, *params.Resource); 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 +} + +// NewGetResourceStatusRequest generates requests for GetResourceStatus +func NewGetResourceStatusRequest(server string, params *GetResourceStatusParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/resource/status") + 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) + } + } + } + + } + + if params.Node != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "node", runtime.ParamLocationQuery, *params.Node); 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) + } + } + } + + } + + if params.Resource != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "resource", runtime.ParamLocationQuery, *params.Resource); 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 +} + func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { for _, r := range c.RequestEditors { if err := r(ctx, req); err != nil { @@ -3800,6 +4176,18 @@ type ClientWithResponsesInterface interface { PostRelayMessageWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostRelayMessageResponse, error) PostRelayMessageWithResponse(ctx context.Context, body PostRelayMessageJSONRequestBody, reqEditors ...RequestEditorFn) (*PostRelayMessageResponse, error) + + // GetResource request + GetResourceWithResponse(ctx context.Context, params *GetResourceParams, reqEditors ...RequestEditorFn) (*GetResourceResponse, error) + + // GetResourceConfig request + GetResourceConfigWithResponse(ctx context.Context, params *GetResourceConfigParams, reqEditors ...RequestEditorFn) (*GetResourceConfigResponse, error) + + // GetResourceMonitor request + GetResourceMonitorWithResponse(ctx context.Context, params *GetResourceMonitorParams, reqEditors ...RequestEditorFn) (*GetResourceMonitorResponse, error) + + // GetResourceStatus request + GetResourceStatusWithResponse(ctx context.Context, params *GetResourceStatusParams, reqEditors ...RequestEditorFn) (*GetResourceStatusResponse, error) } type PostAuthTokenResponse struct { @@ -5048,17 +5436,116 @@ func (r GetObjectLogsResponse) StatusCode() int { return 0 } -type GetObjectPathsResponse struct { +type GetObjectPathsResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ObjectPaths + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetObjectPathsResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetObjectPathsResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type PostObjectProgressResponse struct { + Body []byte + HTTPResponse *http.Response + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r PostObjectProgressResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r PostObjectProgressResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetPoolsResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *PoolStatusList + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetPoolsResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetPoolsResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetSwaggerResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *map[string]interface{} + JSON401 *Problem + JSON403 *Problem + JSON500 *Problem +} + +// Status returns HTTPResponse.Status +func (r GetSwaggerResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetSwaggerResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetRelayMessageResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *ObjectPaths + JSON200 *RelayMessages JSON401 *Problem JSON403 *Problem JSON500 *Problem } // Status returns HTTPResponse.Status -func (r GetObjectPathsResponse) Status() string { +func (r GetRelayMessageResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -5066,23 +5553,24 @@ func (r GetObjectPathsResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetObjectPathsResponse) StatusCode() int { +func (r GetRelayMessageResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type PostObjectProgressResponse struct { +type PostRelayMessageResponse struct { Body []byte HTTPResponse *http.Response + JSON200 *Problem JSON401 *Problem JSON403 *Problem JSON500 *Problem } // Status returns HTTPResponse.Status -func (r PostObjectProgressResponse) Status() string { +func (r PostRelayMessageResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -5090,24 +5578,25 @@ func (r PostObjectProgressResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r PostObjectProgressResponse) StatusCode() int { +func (r PostRelayMessageResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type GetPoolsResponse struct { +type GetResourceResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *PoolStatusList + JSON200 *ResourceArray + JSON400 *Problem JSON401 *Problem JSON403 *Problem JSON500 *Problem } // Status returns HTTPResponse.Status -func (r GetPoolsResponse) Status() string { +func (r GetResourceResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -5115,24 +5604,25 @@ func (r GetPoolsResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetPoolsResponse) StatusCode() int { +func (r GetResourceResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type GetSwaggerResponse struct { +type GetResourceConfigResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *map[string]interface{} + JSON200 *ResourceConfigArray + JSON400 *Problem JSON401 *Problem JSON403 *Problem JSON500 *Problem } // Status returns HTTPResponse.Status -func (r GetSwaggerResponse) Status() string { +func (r GetResourceConfigResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -5140,24 +5630,25 @@ func (r GetSwaggerResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetSwaggerResponse) StatusCode() int { +func (r GetResourceConfigResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type GetRelayMessageResponse struct { +type GetResourceMonitorResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *RelayMessages + JSON200 *ResourceMonitorArray + JSON400 *Problem JSON401 *Problem JSON403 *Problem JSON500 *Problem } // Status returns HTTPResponse.Status -func (r GetRelayMessageResponse) Status() string { +func (r GetResourceMonitorResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -5165,24 +5656,25 @@ func (r GetRelayMessageResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetRelayMessageResponse) StatusCode() int { +func (r GetResourceMonitorResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type PostRelayMessageResponse struct { +type GetResourceStatusResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *Problem + JSON200 *ResourceStatusArray + JSON400 *Problem JSON401 *Problem JSON403 *Problem JSON500 *Problem } // Status returns HTTPResponse.Status -func (r PostRelayMessageResponse) Status() string { +func (r GetResourceStatusResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -5190,7 +5682,7 @@ func (r PostRelayMessageResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r PostRelayMessageResponse) StatusCode() int { +func (r GetResourceStatusResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } @@ -5827,6 +6319,42 @@ func (c *ClientWithResponses) PostRelayMessageWithResponse(ctx context.Context, return ParsePostRelayMessageResponse(rsp) } +// GetResourceWithResponse request returning *GetResourceResponse +func (c *ClientWithResponses) GetResourceWithResponse(ctx context.Context, params *GetResourceParams, reqEditors ...RequestEditorFn) (*GetResourceResponse, error) { + rsp, err := c.GetResource(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetResourceResponse(rsp) +} + +// GetResourceConfigWithResponse request returning *GetResourceConfigResponse +func (c *ClientWithResponses) GetResourceConfigWithResponse(ctx context.Context, params *GetResourceConfigParams, reqEditors ...RequestEditorFn) (*GetResourceConfigResponse, error) { + rsp, err := c.GetResourceConfig(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetResourceConfigResponse(rsp) +} + +// GetResourceMonitorWithResponse request returning *GetResourceMonitorResponse +func (c *ClientWithResponses) GetResourceMonitorWithResponse(ctx context.Context, params *GetResourceMonitorParams, reqEditors ...RequestEditorFn) (*GetResourceMonitorResponse, error) { + rsp, err := c.GetResourceMonitor(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetResourceMonitorResponse(rsp) +} + +// GetResourceStatusWithResponse request returning *GetResourceStatusResponse +func (c *ClientWithResponses) GetResourceStatusWithResponse(ctx context.Context, params *GetResourceStatusParams, reqEditors ...RequestEditorFn) (*GetResourceStatusResponse, error) { + rsp, err := c.GetResourceStatus(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetResourceStatusResponse(rsp) +} + // ParsePostAuthTokenResponse parses an HTTP response from a PostAuthTokenWithResponse call func ParsePostAuthTokenResponse(rsp *http.Response) (*PostAuthTokenResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -8676,3 +9204,219 @@ func ParsePostRelayMessageResponse(rsp *http.Response) (*PostRelayMessageRespons return response, nil } + +// ParseGetResourceResponse parses an HTTP response from a GetResourceWithResponse call +func ParseGetResourceResponse(rsp *http.Response) (*GetResourceResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetResourceResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ResourceArray + 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 +} + +// ParseGetResourceConfigResponse parses an HTTP response from a GetResourceConfigWithResponse call +func ParseGetResourceConfigResponse(rsp *http.Response) (*GetResourceConfigResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetResourceConfigResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ResourceConfigArray + 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 +} + +// ParseGetResourceMonitorResponse parses an HTTP response from a GetResourceMonitorWithResponse call +func ParseGetResourceMonitorResponse(rsp *http.Response) (*GetResourceMonitorResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetResourceMonitorResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ResourceMonitorArray + 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 +} + +// ParseGetResourceStatusResponse parses an HTTP response from a GetResourceStatusWithResponse call +func ParseGetResourceStatusResponse(rsp *http.Response) (*GetResourceStatusResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetResourceStatusResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ResourceStatusArray + 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 +} diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index b8a3afa17..4be0094d2 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -182,6 +182,18 @@ type ServerInterface interface { // (POST /relay/message) PostRelayMessage(ctx echo.Context) error + + // (GET /resource) + GetResource(ctx echo.Context, params GetResourceParams) error + + // (GET /resource/config) + GetResourceConfig(ctx echo.Context, params GetResourceConfigParams) error + + // (GET /resource/monitor) + GetResourceMonitor(ctx echo.Context, params GetResourceMonitorParams) error + + // (GET /resource/status) + GetResourceStatus(ctx echo.Context, params GetResourceStatusParams) error } // ServerInterfaceWrapper converts echo contexts to parameters. @@ -1226,6 +1238,150 @@ func (w *ServerInterfaceWrapper) PostRelayMessage(ctx echo.Context) error { return err } +// GetResource converts echo context to params. +func (w *ServerInterfaceWrapper) GetResource(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 GetResourceParams + // ------------- 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)) + } + + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // ------------- Optional query parameter "resource" ------------- + + err = runtime.BindQueryParameter("form", true, false, "resource", ctx.QueryParams(), ¶ms.Resource) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter resource: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetResource(ctx, params) + return err +} + +// GetResourceConfig converts echo context to params. +func (w *ServerInterfaceWrapper) GetResourceConfig(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 GetResourceConfigParams + // ------------- 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)) + } + + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // ------------- Optional query parameter "resource" ------------- + + err = runtime.BindQueryParameter("form", true, false, "resource", ctx.QueryParams(), ¶ms.Resource) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter resource: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetResourceConfig(ctx, params) + return err +} + +// GetResourceMonitor converts echo context to params. +func (w *ServerInterfaceWrapper) GetResourceMonitor(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 GetResourceMonitorParams + // ------------- 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)) + } + + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // ------------- Optional query parameter "resource" ------------- + + err = runtime.BindQueryParameter("form", true, false, "resource", ctx.QueryParams(), ¶ms.Resource) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter resource: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetResourceMonitor(ctx, params) + return err +} + +// GetResourceStatus converts echo context to params. +func (w *ServerInterfaceWrapper) GetResourceStatus(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 GetResourceStatusParams + // ------------- 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)) + } + + // ------------- Optional query parameter "node" ------------- + + err = runtime.BindQueryParameter("form", true, false, "node", ctx.QueryParams(), ¶ms.Node) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node: %s", err)) + } + + // ------------- Optional query parameter "resource" ------------- + + err = runtime.BindQueryParameter("form", true, false, "resource", ctx.QueryParams(), ¶ms.Resource) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter resource: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetResourceStatus(ctx, params) + return err +} + // This is a simple interface which specifies echo.Route addition functions which // are present on both echo.Echo and echo.Group, since we want to allow using // either of them for path registration @@ -1308,135 +1464,144 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/public/openapi", wrapper.GetSwagger) router.GET(baseURL+"/relay/message", wrapper.GetRelayMessage) router.POST(baseURL+"/relay/message", wrapper.PostRelayMessage) + router.GET(baseURL+"/resource", wrapper.GetResource) + router.GET(baseURL+"/resource/config", wrapper.GetResourceConfig) + router.GET(baseURL+"/resource/monitor", wrapper.GetResourceMonitor) + router.GET(baseURL+"/resource/status", wrapper.GetResourceStatus) } // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", + "AAA=", } // 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 50978d253..74316bae6 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -9,6 +9,7 @@ import ( openapi_types "github.com/deepmap/oapi-codegen/pkg/types" "github.com/opensvc/om3/core/instance" "github.com/opensvc/om3/core/node" + "github.com/opensvc/om3/core/resource" ) const ( @@ -618,9 +619,34 @@ type RelayMessages struct { Messages RelayMessageList `json:"messages"` } +// Resource defines model for Resource. +type Resource struct { + Config *ResourceConfig `json:"config,omitempty"` + Monitor *ResourceMonitor `json:"monitor,omitempty"` + Status *ResourceStatus `json:"status,omitempty"` +} + +// ResourceArray defines model for ResourceArray. +type ResourceArray = []ResourceItem + // ResourceConfig defines model for ResourceConfig. type ResourceConfig = instance.ResourceConfig +// ResourceConfigArray defines model for ResourceConfigArray. +type ResourceConfigArray = []ResourceConfigItem + +// ResourceConfigItem defines model for ResourceConfigItem. +type ResourceConfigItem struct { + Data ResourceConfig `json:"data"` + Meta ResourceMeta `json:"meta"` +} + +// ResourceItem defines model for ResourceItem. +type ResourceItem struct { + Data Resource `json:"data"` + Meta ResourceMeta `json:"meta"` +} + // ResourceLog defines model for ResourceLog. type ResourceLog = []ResourceLogEntry @@ -630,9 +656,25 @@ type ResourceLogEntry struct { Message string `json:"message"` } +// ResourceMeta defines model for ResourceMeta. +type ResourceMeta struct { + Node string `json:"node"` + Object string `json:"object"` + Rid string `json:"rid"` +} + // ResourceMonitor defines model for ResourceMonitor. type ResourceMonitor = instance.ResourceMonitor +// ResourceMonitorArray defines model for ResourceMonitorArray. +type ResourceMonitorArray = []ResourceMonitorItem + +// ResourceMonitorItem defines model for ResourceMonitorItem. +type ResourceMonitorItem struct { + Data ResourceMonitor `json:"data"` + Meta ResourceMeta `json:"meta"` +} + // ResourceMonitorRestart defines model for ResourceMonitorRestart. type ResourceMonitorRestart struct { LastAt time.Time `json:"last_at" yaml:"last_at"` @@ -648,38 +690,15 @@ type ResourceProvisionStatus struct { } // ResourceStatus defines model for ResourceStatus. -type ResourceStatus struct { - // Disable hints the resource ignores all state transition actions - Disable bool `json:"disable"` - - // Encap indicates that the resource is handled by the encapsulated agents, - // and ignored at the hypervisor level - Encap bool `json:"encap"` - - // Info key-value pairs providing interesting information to collect - // site-wide about this resource - Info map[string]interface{} `json:"info"` - Label string `json:"label"` - Log ResourceLog `json:"log"` - - // Monitor tells the daemon if it should trigger a monitor action when the - // resource is not up - Monitor bool `json:"monitor"` +type ResourceStatus = resource.Status - // Optional is resource status aggregated into Overall instead of Avail instance status. - // Errors in optional resource don't stop a state transition action - Optional bool `json:"optional"` - Provisioned ResourceProvisionStatus `json:"provisioned"` - Restart int `json:"restart"` +// ResourceStatusArray defines model for ResourceStatusArray. +type ResourceStatusArray = []ResourceStatusItem - // Standby resource should always be up, even after a stop state transition action - Standby bool `json:"standby"` - Status Status `json:"status"` - - // Subset the name of the subset this resource is assigned to - Subset string `json:"subset"` - Tags []string `json:"tags"` - Type string `json:"type"` +// ResourceStatusItem defines model for ResourceStatusItem. +type ResourceStatusItem struct { + Data ResourceStatus `json:"data"` + Meta ResourceMeta `json:"meta"` } // Role defines model for Role. @@ -763,6 +782,9 @@ type RelayClusterId = string // RelayNodename defines model for RelayNodename. type RelayNodename = string +// RidOptional defines model for RidOptional. +type RidOptional = string + // Roles defines model for Roles. type Roles = []Role @@ -840,7 +862,7 @@ type GetInstanceParams struct { // Path object selector expression. Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` - // Node object and instance selector expression. + // Node node selector expression. Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` } @@ -849,7 +871,7 @@ type GetInstanceConfigParams struct { // Path object selector expression. Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` - // Node object and instance selector expression. + // Node node selector expression. Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` } @@ -858,7 +880,7 @@ type GetInstanceMonitorParams struct { // Path object selector expression. Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` - // Node object and instance selector expression. + // Node node selector expression. Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` } @@ -867,7 +889,7 @@ type GetInstanceStatusParams struct { // Path object selector expression. Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` - // Node object and instance selector expression. + // Node node selector expression. Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` } @@ -879,7 +901,7 @@ type GetNetworksParams struct { // GetNodeParams defines parameters for GetNode. type GetNodeParams struct { - // Node object and instance selector expression. + // Node node selector expression. Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` } @@ -894,7 +916,7 @@ type GetNodeBacklogsParams struct { // GetNodeConfigParams defines parameters for GetNodeConfig. type GetNodeConfigParams struct { - // Node object and instance selector expression. + // Node node selector expression. Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` } @@ -921,13 +943,13 @@ type GetNodeLogsParams struct { // GetNodeMonitorParams defines parameters for GetNodeMonitor. type GetNodeMonitorParams struct { - // Node object and instance selector expression. + // Node node selector expression. Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` } // GetNodeStatusParams defines parameters for GetNodeStatus. type GetNodeStatusParams struct { - // Node object and instance selector expression. + // Node node selector expression. Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` } @@ -994,6 +1016,54 @@ type GetRelayMessageParams struct { ClusterId *RelayClusterId `form:"cluster_id,omitempty" json:"cluster_id,omitempty"` } +// GetResourceParams defines parameters for GetResource. +type GetResourceParams struct { + // Path object selector expression. + Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` + + // Node node selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` + + // Resource resource selector expression. + Resource *RidOptional `form:"resource,omitempty" json:"resource,omitempty"` +} + +// GetResourceConfigParams defines parameters for GetResourceConfig. +type GetResourceConfigParams struct { + // Path object selector expression. + Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` + + // Node node selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` + + // Resource resource selector expression. + Resource *RidOptional `form:"resource,omitempty" json:"resource,omitempty"` +} + +// GetResourceMonitorParams defines parameters for GetResourceMonitor. +type GetResourceMonitorParams struct { + // Path object selector expression. + Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` + + // Node node selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` + + // Resource resource selector expression. + Resource *RidOptional `form:"resource,omitempty" json:"resource,omitempty"` +} + +// GetResourceStatusParams defines parameters for GetResourceStatus. +type GetResourceStatusParams struct { + // Path object selector expression. + Path *PathOptional `form:"path,omitempty" json:"path,omitempty"` + + // Node node selector expression. + Node *NodeOptional `form:"node,omitempty" json:"node,omitempty"` + + // Resource resource selector expression. + Resource *RidOptional `form:"resource,omitempty" json:"resource,omitempty"` +} + // PostDaemonLogsControlJSONRequestBody defines body for PostDaemonLogsControl for application/json ContentType. type PostDaemonLogsControlJSONRequestBody = PostDaemonLogsControl diff --git a/daemon/daemonapi/get_resource.go b/daemon/daemonapi/get_resource.go new file mode 100644 index 000000000..3a610f580 --- /dev/null +++ b/daemon/daemonapi/get_resource.go @@ -0,0 +1,58 @@ +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/daemon/api" +) + +func (a *DaemonApi) GetResource(ctx echo.Context, params api.GetResourceParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + Path: params.Path, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + configs := instance.ConfigData.GetAll() + l := make(api.ResourceArray, 0) + for _, config := range configs { + if !meta.HasPath(config.Path.String()) { + continue + } + if !meta.HasNode(config.Node) { + continue + } + monitor := instance.MonitorData.Get(config.Path, config.Node) + status := instance.StatusData.Get(config.Path, config.Node) + for rid, resourceConfig := range config.Value.Resources { + if params.Resource != nil && rid != *params.Resource { + continue + } + d := api.ResourceItem{ + Meta: api.ResourceMeta{ + Node: config.Node, + Object: config.Path.String(), + Rid: rid, + }, + Data: api.Resource{ + Config: &resourceConfig, + }, + } + if e, ok := monitor.Resources[rid]; ok { + d.Data.Monitor = &e + } + if e, ok := status.Resources[rid]; ok { + d.Data.Status = &e + } + l = append(l, d) + } + } + return ctx.JSON(http.StatusOK, l) +} diff --git a/daemon/daemonapi/get_resource_config.go b/daemon/daemonapi/get_resource_config.go new file mode 100644 index 000000000..79ae6edf3 --- /dev/null +++ b/daemon/daemonapi/get_resource_config.go @@ -0,0 +1,48 @@ +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/daemon/api" +) + +func (a *DaemonApi) GetResourceConfig(ctx echo.Context, params api.GetResourceConfigParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + Path: params.Path, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + configs := instance.ConfigData.GetAll() + l := make(api.ResourceConfigArray, 0) + for _, config := range configs { + if !meta.HasPath(config.Path.String()) { + continue + } + if !meta.HasNode(config.Node) { + continue + } + for rid, resourceConfig := range config.Value.Resources { + if params.Resource != nil && rid != *params.Resource { + continue + } + d := api.ResourceConfigItem{ + Meta: api.ResourceMeta{ + Node: config.Node, + Object: config.Path.String(), + Rid: rid, + }, + Data: resourceConfig, + } + l = append(l, d) + } + } + return ctx.JSON(http.StatusOK, l) +} diff --git a/daemon/daemonapi/get_resource_monitor.go b/daemon/daemonapi/get_resource_monitor.go new file mode 100644 index 000000000..2fc3b19b8 --- /dev/null +++ b/daemon/daemonapi/get_resource_monitor.go @@ -0,0 +1,48 @@ +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/daemon/api" +) + +func (a *DaemonApi) GetResourceMonitor(ctx echo.Context, params api.GetResourceMonitorParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + Path: params.Path, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + monitors := instance.MonitorData.GetAll() + l := make(api.ResourceMonitorArray, 0) + for _, monitor := range monitors { + if !meta.HasPath(monitor.Path.String()) { + continue + } + if !meta.HasNode(monitor.Node) { + continue + } + for rid, resourceMonitor := range monitor.Value.Resources { + if params.Resource != nil && rid != *params.Resource { + continue + } + d := api.ResourceMonitorItem{ + Meta: api.ResourceMeta{ + Node: monitor.Node, + Object: monitor.Path.String(), + Rid: rid, + }, + Data: resourceMonitor, + } + l = append(l, d) + } + } + return ctx.JSON(http.StatusOK, l) +} diff --git a/daemon/daemonapi/get_resource_status.go b/daemon/daemonapi/get_resource_status.go new file mode 100644 index 000000000..da436c575 --- /dev/null +++ b/daemon/daemonapi/get_resource_status.go @@ -0,0 +1,48 @@ +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/daemon/api" +) + +func (a *DaemonApi) GetResourceStatus(ctx echo.Context, params api.GetResourceStatusParams) error { + meta := Meta{ + Context: ctx, + Node: params.Node, + Path: params.Path, + } + if err := meta.Expand(); err != nil { + log.Error().Err(err).Send() + return JSONProblem(ctx, http.StatusInternalServerError, "Server error", "expand selection") + } + statuses := instance.StatusData.GetAll() + l := make(api.ResourceStatusArray, 0) + for _, status := range statuses { + if !meta.HasPath(status.Path.String()) { + continue + } + if !meta.HasNode(status.Node) { + continue + } + for rid, resourceStatus := range status.Value.Resources { + if params.Resource != nil && rid != *params.Resource { + continue + } + d := api.ResourceStatusItem{ + Meta: api.ResourceMeta{ + Node: status.Node, + Object: status.Path.String(), + Rid: rid, + }, + Data: resourceStatus, + } + l = append(l, d) + } + } + return ctx.JSON(http.StatusOK, l) +} From 4c4917dfaac19a77ea72bbbdd50c48d5049220bb Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Sun, 10 Sep 2023 17:43:56 +0200 Subject: [PATCH 22/30] Fix the daemondata test --- daemon/daemondata/testdata/full-node2-t1.json | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/daemon/daemondata/testdata/full-node2-t1.json b/daemon/daemondata/testdata/full-node2-t1.json index 57627fd34..94a0a6adc 100644 --- a/daemon/daemondata/testdata/full-node2-t1.json +++ b/daemon/daemondata/testdata/full-node2-t1.json @@ -33,9 +33,8 @@ "kind": "svc", "provisioned": "true", "updated_at": "2022-12-29T13:45:06.978675685+01:00", - "resources": [ - { - "rid": "fs#1", + "resources": { + "fs#1": { "label": "flag /dev/shm/opensvc/svc/foo/fs#1.flag", "status": "down", "type": "fs.flag", @@ -44,8 +43,7 @@ "state": "true" } }, - { - "rid": "fs#2", + "fs#2": { "label": "flag /dev/shm/opensvc/svc/foo/fs#2.flag", "status": "down", "type": "fs.flag", @@ -55,8 +53,7 @@ }, "optional": true }, - { - "rid": "fs#3", + "fs#3": { "label": "flag /dev/shm/opensvc/svc/foo/fs#3.flag", "status": "down", "type": "fs.flag", @@ -65,8 +62,7 @@ "state": "true" } }, - { - "rid": "fs#4", + "fs#4": { "label": "flag /dev/shm/opensvc/svc/foo/fs#4.flag", "status": "down", "type": "fs.flag", @@ -75,7 +71,7 @@ "state": "true" } } - ] + } } } }, From 1e2c73552787c7972370be28c50366ad3ecf2b53 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Sun, 10 Sep 2023 23:35:45 +0200 Subject: [PATCH 23/30] Fix the cmd/svcapp... go test --- cmd/svcapp_print_status_test.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/cmd/svcapp_print_status_test.go b/cmd/svcapp_print_status_test.go index 86ccab46f..e6ad10d5e 100644 --- a/cmd/svcapp_print_status_test.go +++ b/cmd/svcapp_print_status_test.go @@ -18,16 +18,15 @@ func TestAppPrintStatusFlatJson(t *testing.T) { Level string Message string } - cases := [][]logT{ - { + cases := map[string][]logT{ + "app#0": { {"info", "FOO"}, }, - {}, - - { + "app#1": {}, + "app#2": { {"warn", "DeadlineExceeded"}, }, - { + "app#3": { {"warn", "line1"}, {"warn", "line2"}, }, @@ -43,16 +42,16 @@ func TestAppPrintStatusFlatJson(t *testing.T) { outS := string(out) for rid, c := range cases { - t.Logf("check rid %d, expected %v", rid, c) + t.Logf("check rid %s, expected %v", rid, c) for i, log := range c { - prefix := fmt.Sprintf("instances[0].status.resources[%d].log[%d]", rid, i) + prefix := fmt.Sprintf("instances[0].status.resources.'%s'.log[%d]", rid, i) searched := fmt.Sprintf("%s.message = %s%s%s", prefix, string('"'), log.Message, string('"')) assert.Containsf(t, outS, searched, "%s not found in \n%s", searched, string(outS)) searched = fmt.Sprintf("%s.level = %s%s%s", prefix, string('"'), log.Level, string('"')) assert.Containsf(t, outS, searched, "%s not found in \n%s", searched, string(outS)) } - mustNotExist := fmt.Sprintf("instances[0].status.resources[%d].log[%d]", rid, len(c)+1) + mustNotExist := fmt.Sprintf("instances[0].status.resources.'%s'.log[%d]", rid, len(c)+1) assert.NotContainsf(t, outS, mustNotExist, "extra log has been found: '%s' in \n'%s'", mustNotExist, outS) } } From 823ae9e64e0959fb0f37935385c7e936f145d8b7 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 11 Sep 2023 07:51:08 +0200 Subject: [PATCH 24/30] Fix core/instance tests --- core/instance/instance_test.go | 11 ++++------- core/instance/monitor_test.go | 4 ++-- core/instance/testdata/status.json | 13 +++++-------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/core/instance/instance_test.go b/core/instance/instance_test.go index cbc0136de..2b85adc3e 100644 --- a/core/instance/instance_test.go +++ b/core/instance/instance_test.go @@ -29,10 +29,9 @@ func Test_Status_Unmarshal(t *testing.T) { Overall: status.Down, Provisioned: provisioned.Mixed, UpdatedAt: time.Date(2022, time.December, 28, 11, 21, 45, 800780633, time.UTC), - Resources: []resource.Status{ - { + Resources: ResourceStatuses{ + "volume#1": { ResourceID: (*resourceid.T)(nil), - Rid: "volume#1", Label: "data2", Log: []*resource.StatusLogEntry{ { @@ -47,9 +46,8 @@ func Test_Status_Unmarshal(t *testing.T) { State: provisioned.True, }, }, - { + "fs#1": { ResourceID: (*resourceid.T)(nil), - Rid: "fs#1", Label: "flag /dev/shm/opensvc/svc/svc2/fs#1.flag", Status: status.Down, Type: "fs.flag", @@ -58,9 +56,8 @@ func Test_Status_Unmarshal(t *testing.T) { State: provisioned.False, }, }, - { + "app#1": { ResourceID: (*resourceid.T)(nil), - Rid: "app#1", Label: "forking app.forking", Log: []*resource.StatusLogEntry{ { diff --git a/core/instance/monitor_test.go b/core/instance/monitor_test.go index 4fc9fe5b0..61e5e0fd5 100644 --- a/core/instance/monitor_test.go +++ b/core/instance/monitor_test.go @@ -34,7 +34,7 @@ func Test_Monitor_Unmarshal(t *testing.T) { LocalExpectUpdatedAt: t0, State: MonitorStateIdle, StateUpdatedAt: t0, - Resources: ResourceMonitorMap{ + Resources: ResourceMonitors{ "fs#1": ResourceMonitor{ Restart: ResourceMonitorRestart{ Remaining: 1, @@ -61,7 +61,7 @@ func Test_Monitor_DeepCopy(t *testing.T) { mon1 := Monitor{ LocalExpectUpdatedAt: time.Now(), GlobalExpectUpdatedAt: time.Now(), - Resources: ResourceMonitorMap{ + Resources: ResourceMonitors{ "a": ResourceMonitor{Restart: ResourceMonitorRestart{Remaining: 1, LastAt: time.Now()}}, "b": ResourceMonitor{Restart: ResourceMonitorRestart{Remaining: 8, LastAt: time.Now()}}, }, diff --git a/core/instance/testdata/status.json b/core/instance/testdata/status.json index a74f78ef5..06fa81506 100644 --- a/core/instance/testdata/status.json +++ b/core/instance/testdata/status.json @@ -7,9 +7,8 @@ "kind": "svc", "provisioned": "mixed", "updated_at": "2022-12-28T11:21:45.800780633Z", - "resources": [ - { - "rid": "volume#1", + "resources": { + "volume#1": { "label": "data2", "log": [ { @@ -24,8 +23,7 @@ "state": "true" } }, - { - "rid": "fs#1", + "fs#1": { "label": "flag /dev/shm/opensvc/svc/svc2/fs#1.flag", "status": "down", "type": "fs.flag", @@ -34,8 +32,7 @@ "state": "false" } }, - { - "rid": "app#1", + "app#1": { "label": "forking app.forking", "log": [ { @@ -51,5 +48,5 @@ }, "restart": 2 } - ] + } } From df292849191db9bce6a266bdff2840dee6487b9b Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 11 Sep 2023 08:13:40 +0200 Subject: [PATCH 25/30] Fix the core/object go tests --- core/object/testdata/instanceStatus.json | 27 ++++-------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/core/object/testdata/instanceStatus.json b/core/object/testdata/instanceStatus.json index 4e41fb27a..0e9ab78a2 100644 --- a/core/object/testdata/instanceStatus.json +++ b/core/object/testdata/instanceStatus.json @@ -21,8 +21,8 @@ "overall": "warn", "placement": "nodes order", "provisioned": "true", - "resources": [ - {"rid": "fs#1", + "resources": { + "fs#1": { "label": "fs.flag", "provisioned": { "mtime": "2020-03-04T16:33:23.16700383+01:00", @@ -31,7 +31,7 @@ "status": "up", "type": "fs.flag" }, - { "rid": "fs#2", + "fs#2": { "label": "fs.flag", "log": [ "info: info msg", @@ -45,8 +45,7 @@ "status": "up", "type": "fs.flag" }, - { - "rid": "sync#i0", + "sync#i0": { "label": "rsync svc config to nodes", "log": [ "warn: need update" @@ -55,24 +54,6 @@ "status": "down", "type": "sync.rsync" } - ], - "status_group": { - "DEFAULT": "n/a", - "app": "n/a", - "certificate": "n/a", - "container": "n/a", - "disk": "n/a", - "expose": "n/a", - "fs": "up", - "hashpolicy": "n/a", - "ip": "n/a", - "route": "n/a", - "share": "n/a", - "subset": "n/a", - "sync": "warn", - "task": "n/a", - "vhost": "n/a", - "volume": "n/a" }, "subsets": {}, "topology": "failover", From e21b55a5e27b75a474ae1a338cad007e06f41f12 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 11 Sep 2023 15:55:30 +0200 Subject: [PATCH 26/30] Add the "resource * ls" commandset * resource ls * resource config ls * resource monitor ls * resource status ls --- cmd/all.go | 20 +++++ cmd/factory.go | 89 +++++++++++++++++++++ cmd/svc.go | 20 +++++ cmd/vol.go | 20 +++++ core/commands/object_resource_config_ls.go | 64 +++++++++++++++ core/commands/object_resource_ls.go | 64 +++++++++++++++ core/commands/object_resource_monitor_ls.go | 64 +++++++++++++++ core/commands/object_resource_status_ls.go | 64 +++++++++++++++ 8 files changed, 405 insertions(+) create mode 100644 core/commands/object_resource_config_ls.go create mode 100644 core/commands/object_resource_ls.go create mode 100644 core/commands/object_resource_monitor_ls.go create mode 100644 core/commands/object_resource_status_ls.go diff --git a/cmd/all.go b/cmd/all.go index f256ae2be..aa021852b 100644 --- a/cmd/all.go +++ b/cmd/all.go @@ -18,6 +18,10 @@ func init() { cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) + cmdObjectResource := newCmdObjectResource(kind) + cmdObjectResourceConfig := newCmdObjectResourceConfig(kind) + cmdObjectResourceMonitor := newCmdObjectResourceMonitor(kind) + cmdObjectResourceStatus := newCmdObjectResourceStatus(kind) cmdObjectPush := newCmdObjectPush(kind) cmdObjectSync := newCmdObjectSync(kind) cmdObjectValidate := newCmdObjectValidate(kind) @@ -32,6 +36,7 @@ func init() { cmdObjectInstance, cmdObjectPrint, cmdObjectPush, + cmdObjectResource, cmdObjectSet, cmdObjectSync, cmdObjectValidate, @@ -80,6 +85,21 @@ func init() { cmdObjectInstanceStatus, newCmdObjectInstanceLs(kind), ) + cmdObjectResourceConfig.AddCommand( + newCmdObjectResourceConfigLs(kind), + ) + cmdObjectResourceMonitor.AddCommand( + newCmdObjectResourceMonitorLs(kind), + ) + cmdObjectResourceStatus.AddCommand( + newCmdObjectResourceStatusLs(kind), + ) + cmdObjectResource.AddCommand( + cmdObjectResourceConfig, + cmdObjectResourceMonitor, + cmdObjectResourceStatus, + newCmdObjectResourceLs(kind), + ) cmdObjectEdit.AddCommand( newCmdObjectEditConfig(kind), ) diff --git a/cmd/factory.go b/cmd/factory.go index 86cee162e..b9af4e333 100644 --- a/cmd/factory.go +++ b/cmd/factory.go @@ -2470,6 +2470,95 @@ func newCmdObjectSyncUpdate(kind string) *cobra.Command { return cmd } +func newCmdObjectResource(kind string) *cobra.Command { + return &cobra.Command{ + Use: "resource", + Short: "config, status, monitor, ls", + Aliases: []string{"res"}, + } +} + +func newCmdObjectResourceConfig(kind string) *cobra.Command { + return &cobra.Command{ + Use: "config", + Aliases: []string{"conf", "cf"}, + } +} + +func newCmdObjectResourceMonitor(kind string) *cobra.Command { + return &cobra.Command{ + Use: "monitor", + Aliases: []string{"mon"}, + } +} + +func newCmdObjectResourceStatus(kind string) *cobra.Command { + return &cobra.Command{ + Use: "status", + Aliases: []string{"stat", "st"}, + } +} + +func newCmdObjectResourceLs(kind string) *cobra.Command { + var options commands.CmdObjectResourceLs + cmd := &cobra.Command{ + Use: "ls", + Short: "list the selected resource (config, monitor, status)", + RunE: func(cmd *cobra.Command, args []string) error { + return options.Run(selectorFlag, kind) + }, + } + flags := cmd.Flags() + addFlagsGlobal(flags, &options.OptsGlobal) + addFlagRID(flags, &options.RID) + return cmd +} + +func newCmdObjectResourceConfigLs(kind string) *cobra.Command { + var options commands.CmdObjectResourceConfigLs + cmd := &cobra.Command{ + Use: "ls", + Short: "list the selected resource config", + RunE: func(cmd *cobra.Command, args []string) error { + return options.Run(selectorFlag, kind) + }, + } + flags := cmd.Flags() + addFlagsGlobal(flags, &options.OptsGlobal) + addFlagRID(flags, &options.RID) + return cmd +} + +func newCmdObjectResourceMonitorLs(kind string) *cobra.Command { + var options commands.CmdObjectResourceMonitorLs + cmd := &cobra.Command{ + Use: "ls", + Short: "list the selected resource monitor", + RunE: func(cmd *cobra.Command, args []string) error { + return options.Run(selectorFlag, kind) + }, + } + flags := cmd.Flags() + addFlagsGlobal(flags, &options.OptsGlobal) + addFlagRID(flags, &options.RID) + return cmd +} + +func newCmdObjectResourceStatusLs(kind string) *cobra.Command { + var options commands.CmdObjectResourceStatusLs + cmd := &cobra.Command{ + Use: "ls", + Short: "list the selected resource status", + RunE: func(cmd *cobra.Command, args []string) error { + return options.Run(selectorFlag, kind) + }, + } + flags := cmd.Flags() + addFlagsGlobal(flags, &options.OptsGlobal) + addFlagRID(flags, &options.RID) + return cmd +} + func newCmdObjectRun(kind string) *cobra.Command { var options commands.CmdObjectRun cmd := &cobra.Command{ diff --git a/cmd/svc.go b/cmd/svc.go index 4ceed8a97..5f472de2a 100644 --- a/cmd/svc.go +++ b/cmd/svc.go @@ -16,6 +16,10 @@ func init() { cmdObjectInstanceConfig := newCmdObjectInstanceConfig(kind) cmdObjectInstanceMonitor := newCmdObjectInstanceMonitor(kind) cmdObjectInstanceStatus := newCmdObjectInstanceStatus(kind) + cmdObjectResource := newCmdObjectResource(kind) + cmdObjectResourceConfig := newCmdObjectResourceConfig(kind) + cmdObjectResourceMonitor := newCmdObjectResourceMonitor(kind) + cmdObjectResourceStatus := newCmdObjectResourceStatus(kind) cmdObjectSet := newCmdObjectSet(kind) cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) @@ -33,6 +37,7 @@ func init() { cmdObjectInstance, cmdObjectPrint, cmdObjectPush, + cmdObjectResource, cmdObjectSet, cmdObjectSync, cmdObjectValidate, @@ -80,6 +85,21 @@ func init() { cmdObjectInstanceStatus.AddCommand( newCmdObjectInstanceStatusLs(kind), ) + cmdObjectResourceConfig.AddCommand( + newCmdObjectResourceConfigLs(kind), + ) + cmdObjectResourceMonitor.AddCommand( + newCmdObjectResourceMonitorLs(kind), + ) + cmdObjectResourceStatus.AddCommand( + newCmdObjectResourceStatusLs(kind), + ) + cmdObjectResource.AddCommand( + cmdObjectResourceConfig, + cmdObjectResourceMonitor, + cmdObjectResourceStatus, + newCmdObjectResourceLs(kind), + ) cmdObjectInstance.AddCommand( cmdObjectInstanceConfig, cmdObjectInstanceMonitor, diff --git a/cmd/vol.go b/cmd/vol.go index 21b69441b..db282b82f 100644 --- a/cmd/vol.go +++ b/cmd/vol.go @@ -15,6 +15,10 @@ func init() { cmdObjectPrint := newCmdObjectPrint(kind) cmdObjectPrintConfig := newCmdObjectPrintConfig(kind) cmdObjectPush := newCmdObjectPush(kind) + cmdObjectResource := newCmdObjectResource(kind) + cmdObjectResourceConfig := newCmdObjectResourceConfig(kind) + cmdObjectResourceMonitor := newCmdObjectResourceMonitor(kind) + cmdObjectResourceStatus := newCmdObjectResourceStatus(kind) cmdObjectSync := newCmdObjectSync(kind) cmdObjectValidate := newCmdObjectValidate(kind) @@ -27,6 +31,7 @@ func init() { cmdObjectInstance, cmdObjectPrint, cmdObjectPush, + cmdObjectResource, cmdObjectSet, cmdObjectSync, cmdObjectValidate, @@ -90,6 +95,21 @@ func init() { cmdObjectInstanceStatus, newCmdObjectInstanceLs(kind), ) + cmdObjectResourceConfig.AddCommand( + newCmdObjectResourceConfigLs(kind), + ) + cmdObjectResourceMonitor.AddCommand( + newCmdObjectResourceMonitorLs(kind), + ) + cmdObjectResourceStatus.AddCommand( + newCmdObjectResourceStatusLs(kind), + ) + cmdObjectResource.AddCommand( + cmdObjectResourceConfig, + cmdObjectResourceMonitor, + cmdObjectResourceStatus, + newCmdObjectResourceLs(kind), + ) cmdObjectSet.AddCommand( newCmdObjectSetProvisioned(kind), newCmdObjectSetUnprovisioned(kind), diff --git a/core/commands/object_resource_config_ls.go b/core/commands/object_resource_config_ls.go new file mode 100644 index 000000000..94abc7925 --- /dev/null +++ b/core/commands/object_resource_config_ls.go @@ -0,0 +1,64 @@ +package commands + +import ( + "context" + "fmt" + + "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 ( + CmdObjectResourceConfigLs struct { + OptsGlobal + OptsResourceSelector + } +) + +func (t *CmdObjectResourceConfigLs) Run(selector, kind string) error { + var ( + data any + err error + ) + mergedSelector := mergeSelector(selector, t.ObjectSelector, kind, "") + + c, err := client.New(client.WithURL(t.Server)) + if err != nil { + return err + } + params := api.GetResourceConfigParams{Path: &mergedSelector} + if t.NodeSelector != "" { + params.Node = &t.NodeSelector + } + if t.RID != "" { + params.Resource = &t.RID + } + // TODO: add subset and tag params + resp, err := c.GetResourceConfigWithResponse(context.Background(), ¶ms) + if err != nil { + return fmt.Errorf("api: %w", err) + } + 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 + } + renderer := output.Renderer{ + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,IS_MONITORED:data.is_monitored,IS_DISABLED:data.is_disabled,IS_STANDBY:data.is_standby,RESTART:data.restart,RESTART_DELAY:data.restart_delay", + Output: t.Output, + Color: t.Color, + Data: data, + Colorize: rawconfig.Colorize, + } + renderer.Print() + return nil +} diff --git a/core/commands/object_resource_ls.go b/core/commands/object_resource_ls.go new file mode 100644 index 000000000..befd3e8e2 --- /dev/null +++ b/core/commands/object_resource_ls.go @@ -0,0 +1,64 @@ +package commands + +import ( + "context" + "fmt" + + "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 ( + CmdObjectResourceLs struct { + OptsGlobal + OptsResourceSelector + } +) + +func (t *CmdObjectResourceLs) Run(selector, kind string) error { + var ( + data any + err error + ) + mergedSelector := mergeSelector(selector, t.ObjectSelector, kind, "") + + c, err := client.New(client.WithURL(t.Server)) + if err != nil { + return err + } + params := api.GetResourceParams{Path: &mergedSelector} + if t.NodeSelector != "" { + params.Node = &t.NodeSelector + } + if t.RID != "" { + params.Resource = &t.RID + } + // TODO: add subset and tag params + resp, err := c.GetResourceWithResponse(context.Background(), ¶ms) + if err != nil { + return fmt.Errorf("api: %w", err) + } + 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 + } + renderer := output.Renderer{ + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,STATUS:data.status.status", + Output: t.Output, + Color: t.Color, + Data: data, + Colorize: rawconfig.Colorize, + } + renderer.Print() + return nil +} diff --git a/core/commands/object_resource_monitor_ls.go b/core/commands/object_resource_monitor_ls.go new file mode 100644 index 000000000..bbb8b407f --- /dev/null +++ b/core/commands/object_resource_monitor_ls.go @@ -0,0 +1,64 @@ +package commands + +import ( + "context" + "fmt" + + "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 ( + CmdObjectResourceMonitorLs struct { + OptsGlobal + OptsResourceSelector + } +) + +func (t *CmdObjectResourceMonitorLs) Run(selector, kind string) error { + var ( + data any + err error + ) + mergedSelector := mergeSelector(selector, t.ObjectSelector, kind, "") + + c, err := client.New(client.WithURL(t.Server)) + if err != nil { + return err + } + params := api.GetResourceMonitorParams{Path: &mergedSelector} + if t.NodeSelector != "" { + params.Node = &t.NodeSelector + } + if t.RID != "" { + params.Resource = &t.RID + } + // TODO: add subset and tag params + resp, err := c.GetResourceMonitorWithResponse(context.Background(), ¶ms) + if err != nil { + return fmt.Errorf("api: %w", err) + } + 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 + } + renderer := output.Renderer{ + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,RESTART_REMAINING:data.restart.remaining,RESTART_LAST_AT:restart.last_at", + Output: t.Output, + Color: t.Color, + Data: data, + Colorize: rawconfig.Colorize, + } + renderer.Print() + return nil +} diff --git a/core/commands/object_resource_status_ls.go b/core/commands/object_resource_status_ls.go new file mode 100644 index 000000000..101c42035 --- /dev/null +++ b/core/commands/object_resource_status_ls.go @@ -0,0 +1,64 @@ +package commands + +import ( + "context" + "fmt" + + "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 ( + CmdObjectResourceStatusLs struct { + OptsGlobal + OptsResourceSelector + } +) + +func (t *CmdObjectResourceStatusLs) Run(selector, kind string) error { + var ( + data any + err error + ) + mergedSelector := mergeSelector(selector, t.ObjectSelector, kind, "") + + c, err := client.New(client.WithURL(t.Server)) + if err != nil { + return err + } + params := api.GetResourceStatusParams{Path: &mergedSelector} + if t.NodeSelector != "" { + params.Node = &t.NodeSelector + } + if t.RID != "" { + params.Resource = &t.RID + } + // TODO: add subset and tag params + resp, err := c.GetResourceStatusWithResponse(context.Background(), ¶ms) + if err != nil { + return fmt.Errorf("api: %w", err) + } + 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 + } + renderer := output.Renderer{ + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,STATUS:data.status.avail", + Output: t.Output, + Color: t.Color, + Data: data, + Colorize: rawconfig.Colorize, + } + renderer.Print() + return nil +} From d1d7b516aa9824636b06af649ae881d5f6400f0e Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 11 Sep 2023 15:59:44 +0200 Subject: [PATCH 27/30] Fix resource commands default columns in outputs --- core/commands/object_resource_monitor_ls.go | 2 +- core/commands/object_resource_status_ls.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/commands/object_resource_monitor_ls.go b/core/commands/object_resource_monitor_ls.go index bbb8b407f..0cb0baffb 100644 --- a/core/commands/object_resource_monitor_ls.go +++ b/core/commands/object_resource_monitor_ls.go @@ -53,7 +53,7 @@ func (t *CmdObjectResourceMonitorLs) Run(selector, kind string) error { data = *resp.JSON500 } renderer := output.Renderer{ - DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,RESTART_REMAINING:data.restart.remaining,RESTART_LAST_AT:restart.last_at", + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,RESTART_REMAINING:data.restart.remaining,RESTART_LAST_AT:data.restart.last_at", Output: t.Output, Color: t.Color, Data: data, diff --git a/core/commands/object_resource_status_ls.go b/core/commands/object_resource_status_ls.go index 101c42035..bb43dbb7d 100644 --- a/core/commands/object_resource_status_ls.go +++ b/core/commands/object_resource_status_ls.go @@ -53,7 +53,7 @@ func (t *CmdObjectResourceStatusLs) Run(selector, kind string) error { data = *resp.JSON500 } renderer := output.Renderer{ - DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,STATUS:data.status.avail", + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,STATUS:data.status", Output: t.Output, Color: t.Color, Data: data, From 515f6ab2c7852744c7e538027b634bebbcc67048 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 11 Sep 2023 16:38:34 +0200 Subject: [PATCH 28/30] Don't exit from tab renderer on jsonpath find error Report the error in the table cell and continue, so the user can easily see which part of the columning syntax is wrong. --- core/output/renderer.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/output/renderer.go b/core/output/renderer.go index 7e8c0de11..053463736 100644 --- a/core/output/renderer.go +++ b/core/output/renderer.go @@ -251,11 +251,13 @@ func (t Renderer) renderTab(options string) (string, error) { for _, jsonPath := range jsonPaths { values, err := jsonPath.FindResults(line) if err != nil { - return "", err + fmt.Fprintf(w, "<%s>\t", err) + continue } valueStrings := []string{} if len(values) == 0 || len(values[0]) == 0 { - valueStrings = append(valueStrings, "") + fmt.Fprintf(w, "\t", err) + continue } for arrIx := range values { for valIx := range values[arrIx] { From 53d1162d8590c83369a6132a22e63293f1624e06 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 11 Sep 2023 16:39:56 +0200 Subject: [PATCH 29/30] Add more columns to the default "resource ls" renderer --- core/commands/object_resource_ls.go | 2 +- core/commands/object_resource_status_ls.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/commands/object_resource_ls.go b/core/commands/object_resource_ls.go index befd3e8e2..67e1032b1 100644 --- a/core/commands/object_resource_ls.go +++ b/core/commands/object_resource_ls.go @@ -53,7 +53,7 @@ func (t *CmdObjectResourceLs) Run(selector, kind string) error { data = *resp.JSON500 } renderer := output.Renderer{ - DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,STATUS:data.status.status", + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,TYPE:data.status.type,STATUS:data.status.status,IS_MONITORED:data.config.is_monitored,IS_DISABLED:data.config.is_disabled,IS_STANDBY:data.config.is_standby,RESTART:data.config.restart,RESTART_REMAINING:data.monitor.restart.remaining", Output: t.Output, Color: t.Color, Data: data, diff --git a/core/commands/object_resource_status_ls.go b/core/commands/object_resource_status_ls.go index bb43dbb7d..e4f577c09 100644 --- a/core/commands/object_resource_status_ls.go +++ b/core/commands/object_resource_status_ls.go @@ -53,7 +53,7 @@ func (t *CmdObjectResourceStatusLs) Run(selector, kind string) error { data = *resp.JSON500 } renderer := output.Renderer{ - DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,STATUS:data.status", + DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,RID:meta.rid,TYPE:data.type,STATUS:data.status", Output: t.Output, Color: t.Color, Data: data, From 9fae4e3f36c3520fe258ce8176c6be4cdebbc5eb Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Mon, 11 Sep 2023 17:28:42 +0200 Subject: [PATCH 30/30] Fix a core/output error format --- core/output/renderer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/output/renderer.go b/core/output/renderer.go index 053463736..06dcbebda 100644 --- a/core/output/renderer.go +++ b/core/output/renderer.go @@ -256,7 +256,7 @@ func (t Renderer) renderTab(options string) (string, error) { } valueStrings := []string{} if len(values) == 0 || len(values[0]) == 0 { - fmt.Fprintf(w, "\t", err) + fmt.Fprintf(w, "\t") continue } for arrIx := range values {