diff --git a/RedfishPkg/Include/Library/RedfishLib.h b/RedfishPkg/Include/Library/RedfishLib.h index b2488abbd4..28c2b290e6 100644 --- a/RedfishPkg/Include/Library/RedfishLib.h +++ b/RedfishPkg/Include/Library/RedfishLib.h @@ -380,6 +380,47 @@ RedfishPatchToPayload ( OUT REDFISH_RESPONSE *RedResponse ); +/** + Use HTTP POST to create new Redfish resource in the Resource Collection. + + The POST request should be submitted to the Resource Collection in which the new resource + is to belong. The Resource Collection is addressed by URI. The Redfish may + ignore any service controlled properties. The corresponding redfish response will returned, + including HTTP StatusCode, Headers and Payload which record any HTTP response messages. + + Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in + redfish response data. + + @param[in] RedfishService The Service to access the Redfish resources. + @param[in] Uri Relative path to address the resource. + @param[in] Content JSON represented properties to be update. + @param[in] ContentSize Size of the Content to be send to Redfish service + @param[in] ContentType Type of the Content to be send to Redfish service + @param[out] RedResponse Pointer to the Redfish response data. + + @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not + NULL and the value is 2XX. The Redfish resource will be returned + in Payload within RedResponse if server send it back in the HTTP + response message body. + @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or RedResponse is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get + more error info from returned HTTP StatusCode, Headers and Payload + within RedResponse: + 1. If the returned StatusCode is NULL, indicates any error happen. + 2. If the returned StatusCode is not NULL and the value is not 2XX, + indicates any error happen. +**/ +EFI_STATUS +EFIAPI +RedfishPostToUri ( + IN REDFISH_SERVICE RedfishService, + IN CONST CHAR8 *Uri, + IN CONST CHAR8 *Content, + IN UINTN ContentSize, + IN CONST CHAR8 *ContentType, + OUT REDFISH_RESPONSE *RedResponse + ); + /** Use HTTP POST to create a new resource in target payload. @@ -450,6 +491,43 @@ RedfishDeleteByUri ( OUT REDFISH_RESPONSE *RedResponse ); +/** + Use HTTP DELETE to remove a resource. + + This function uses the RedfishService to remove a Redfish resource which is addressed + by input Uri (only the relative path is required). The corresponding redfish response will + returned, including HTTP StatusCode, Headers and Payload which record any HTTP response + messages. + + Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in + redfish response data. + + @param[in] RedfishService The Service to access the Redfish resources. + @param[in] Uri Relative path to address the resource. + @param[in] Content JSON represented properties to be deleted. + @param[out] RedResponse Pointer to the Redfish response data. + + @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not + NULL and the value is 2XX, the Redfish resource has been removed. + If there is any message returned from server, it will be returned + in Payload within RedResponse. + @retval EFI_INVALID_PARAMETER RedfishService, Uri, or RedResponse is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get + more error info from returned HTTP StatusCode, Headers and Payload + within RedResponse: + 1. If the returned StatusCode is NULL, indicates any error happen. + 2. If the returned StatusCode is not NULL and the value is not 2XX, + indicates any error happen. +**/ +EFI_STATUS +EFIAPI +RedfishDeleteByUriEx ( + IN REDFISH_SERVICE RedfishService, + IN CONST CHAR8 *Uri, + IN CONST CHAR8 *Content, + OUT REDFISH_RESPONSE *RedResponse + ); + /** Dump text in fractions. diff --git a/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c b/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c index 9f9d37790e..51a85a7336 100644 --- a/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c +++ b/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c @@ -583,6 +583,102 @@ RedfishPatchToPayload ( return EFI_SUCCESS; } +/** + Use HTTP POST to create new Redfish resource in the Resource Collection. + + The POST request should be submitted to the Resource Collection in which the new resource + is to belong. The Resource Collection is addressed by URI. The Redfish may + ignore any service controlled properties. The corresponding redfish response will returned, + including HTTP StatusCode, Headers and Payload which record any HTTP response messages. + + Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in + redfish response data. + + @param[in] RedfishService The Service to access the Redfish resources. + @param[in] Uri Relative path to address the resource. + @param[in] Content JSON represented properties to be update. + @param[in] ContentSize Size of the Content to be send to Redfish service + @param[in] ContentType Type of the Content to be send to Redfish service + @param[out] RedResponse Pointer to the Redfish response data. + + @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not + NULL and the value is 2XX. The Redfish resource will be returned + in Payload within RedResponse if server send it back in the HTTP + response message body. + @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or RedResponse is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get + more error info from returned HTTP StatusCode, Headers and Payload + within RedResponse: + 1. If the returned StatusCode is NULL, indicates any error happen. + 2. If the returned StatusCode is not NULL and the value is not 2XX, + indicates any error happen. +**/ +EFI_STATUS +EFIAPI +RedfishPostToUri ( + IN REDFISH_SERVICE RedfishService, + IN CONST CHAR8 *Uri, + IN CONST CHAR8 *Content, + IN UINTN ContentSize, + IN CONST CHAR8 *ContentType, + OUT REDFISH_RESPONSE *RedResponse + ) +{ + EFI_STATUS Status; + EDKII_JSON_VALUE JsonValue; + + Status = EFI_SUCCESS; + JsonValue = NULL; + + if ((RedfishService == NULL) || (Uri == NULL) || (Content == NULL) || (RedResponse == NULL)) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE)); + + JsonValue = (EDKII_JSON_VALUE)postUriFromService ( + RedfishService, + Uri, + Content, + ContentSize, + ContentType, + &(RedResponse->StatusCode) + ); + + // + // 1. If the returned StatusCode is NULL, indicates any error happen. + // + if (RedResponse->StatusCode == NULL) { + Status = EFI_DEVICE_ERROR; + goto ON_EXIT; + } + + // + // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen. + // NOTE: If there is any error message returned from server, it will be returned in + // Payload within RedResponse. + // + if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \ + (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT)) + { + Status = EFI_DEVICE_ERROR; + } + +ON_EXIT: + if (JsonValue != NULL) { + RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService); + if (RedResponse->Payload == NULL) { + // + // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what + // we care about if the returned StatusCode is 2XX. + // + JsonValueFree (JsonValue); + } + } + + return Status; +} + /** Use HTTP POST to create a new resource in target payload. @@ -738,6 +834,96 @@ ON_EXIT: return Status; } +/** + Use HTTP DELETE to remove a resource. + + This function uses the RedfishService to remove a Redfish resource which is addressed + by input Uri (only the relative path is required). The corresponding redfish response will + returned, including HTTP StatusCode, Headers and Payload which record any HTTP response + messages. + + Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in + redfish response data. + + @param[in] RedfishService The Service to access the Redfish resources. + @param[in] Uri Relative path to address the resource. + @param[in] Content JSON represented properties to be deleted. + @param[out] RedResponse Pointer to the Redfish response data. + + @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not + NULL and the value is 2XX, the Redfish resource has been removed. + If there is any message returned from server, it will be returned + in Payload within RedResponse. + @retval EFI_INVALID_PARAMETER RedfishService, Uri, or RedResponse is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get + more error info from returned HTTP StatusCode, Headers and Payload + within RedResponse: + 1. If the returned StatusCode is NULL, indicates any error happen. + 2. If the returned StatusCode is not NULL and the value is not 2XX, + indicates any error happen. +**/ +EFI_STATUS +EFIAPI +RedfishDeleteByUriEx ( + IN REDFISH_SERVICE RedfishService, + IN CONST CHAR8 *Uri, + IN CONST CHAR8 *Content, + OUT REDFISH_RESPONSE *RedResponse + ) +{ + EFI_STATUS Status; + EDKII_JSON_VALUE JsonValue; + + Status = EFI_SUCCESS; + JsonValue = NULL; + + if ((RedfishService == NULL) || (Content == NULL) || (Uri == NULL) || (RedResponse == NULL)) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE)); + + JsonValue = (EDKII_JSON_VALUE)deleteUriFromServiceEx ( + RedfishService, + Uri, + Content, + &(RedResponse->StatusCode) + ); + + // + // 1. If the returned StatusCode is NULL, indicates any error happen. + // + if (RedResponse->StatusCode == NULL) { + Status = EFI_DEVICE_ERROR; + goto ON_EXIT; + } + + // + // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen. + // NOTE: If there is any error message returned from server, it will be returned in + // Payload within RedResponse. + // + if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \ + (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT)) + { + Status = EFI_DEVICE_ERROR; + } + +ON_EXIT: + if (JsonValue != NULL) { + RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService); + if (RedResponse->Payload == NULL) { + // + // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what + // we care about if the returned StatusCode is 2XX. + // + JsonValueFree (JsonValue); + } + } + + return Status; +} + /** Dump text in fractions. diff --git a/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h b/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h index 5c13b682a3..75afadc0ce 100644 --- a/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h +++ b/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h @@ -129,6 +129,14 @@ deleteUriFromService ( EFI_HTTP_STATUS_CODE **StatusCode ); +json_t * +deleteUriFromServiceEx ( + redfishService *service, + const char *uri, + const char *content, + EFI_HTTP_STATUS_CODE **StatusCode + ); + redfishPayload * getRedfishServiceRoot ( redfishService *service, diff --git a/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c b/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c index afa172b531..cbd4330a0e 100644 --- a/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c +++ b/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c @@ -924,9 +924,10 @@ ON_EXIT: } json_t * -deleteUriFromService ( +deleteUriFromServiceEx ( redfishService *service, const char *uri, + const char *content, EFI_HTTP_STATUS_CODE **StatusCode ) { @@ -937,6 +938,8 @@ deleteUriFromService ( EFI_HTTP_REQUEST_DATA *RequestData = NULL; EFI_HTTP_MESSAGE *RequestMsg = NULL; EFI_HTTP_MESSAGE ResponseMsg; + CHAR8 ContentLengthStr[80]; + size_t contentLength; ret = NULL; @@ -956,7 +959,7 @@ deleteUriFromService ( // // Step 1: Create HTTP request message with 4 headers: // - HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 5 : 4); + HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 8 : 7); if (HttpIoHeader == NULL) { ret = NULL; goto ON_EXIT; @@ -979,6 +982,23 @@ deleteUriFromService ( Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive"); ASSERT_EFI_ERROR (Status); + Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", "application/json"); + ASSERT_EFI_ERROR (Status); + + if (content != NULL) { + contentLength = strlen (content); + AsciiSPrint ( + ContentLengthStr, + sizeof (ContentLengthStr), + "%lu", + (UINT64)contentLength + ); + Status = HttpIoSetHeader (HttpIoHeader, "Content-Length", ContentLengthStr); + ASSERT_EFI_ERROR (Status); + Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0"); + ASSERT_EFI_ERROR (Status); + } + // // Step 2: build the rest of HTTP request info. // @@ -1004,6 +1024,11 @@ deleteUriFromService ( RequestMsg->HeaderCount = HttpIoHeader->HeaderCount; RequestMsg->Headers = HttpIoHeader->Headers; + if (content != NULL) { + RequestMsg->BodyLength = contentLength; + RequestMsg->Body = (VOID *)content; + } + ZeroMem (&ResponseMsg, sizeof (ResponseMsg)); // @@ -1057,6 +1082,16 @@ ON_EXIT: return ret; } +json_t * +deleteUriFromService ( + redfishService *service, + const char *uri, + EFI_HTTP_STATUS_CODE **StatusCode + ) +{ + return deleteUriFromServiceEx (service, uri, NULL, StatusCode); +} + redfishPayload * getRedfishServiceRoot ( redfishService *service,