From 82b3c5aa33c8db219d15a0acaf994661e4b5d81b Mon Sep 17 00:00:00 2001 From: Rahul Bhalla Date: Wed, 15 Nov 2023 12:36:53 +0530 Subject: [PATCH 1/2] Add Zeroize Support --- pkg/zhmcclient/fakes/lpar.go | 81 ++++++++++++++++++++++++++++++++++++ pkg/zhmcclient/fakes/zhmc.go | 81 ++++++++++++++++++++++++++++++++++++ pkg/zhmcclient/lpar.go | 45 +++++++++++++++++--- pkg/zhmcclient/lpar_test.go | 50 +++++++++++++++++++++- pkg/zhmcclient/model.go | 5 +++ pkg/zhmcclient/zhmc.go | 5 ++- 6 files changed, 259 insertions(+), 8 deletions(-) diff --git a/pkg/zhmcclient/fakes/lpar.go b/pkg/zhmcclient/fakes/lpar.go index 3d3c9b5..bbf3d86 100644 --- a/pkg/zhmcclient/fakes/lpar.go +++ b/pkg/zhmcclient/fakes/lpar.go @@ -215,6 +215,20 @@ type LparAPI struct { result1 int result2 *zhmcclient.HmcError } + ZeroizeCryptoDomainStub func(string, *zhmcclient.CryptoAdapterDetails) (int, *zhmcclient.HmcError) + zeroizeCryptoDomainMutex sync.RWMutex + zeroizeCryptoDomainArgsForCall []struct { + arg1 string + arg2 *zhmcclient.CryptoAdapterDetails + } + zeroizeCryptoDomainReturns struct { + result1 int + result2 *zhmcclient.HmcError + } + zeroizeCryptoDomainReturnsOnCall map[int]struct { + result1 int + result2 *zhmcclient.HmcError + } invocations map[string][][]interface{} invocationsMutex sync.RWMutex } @@ -1148,6 +1162,71 @@ func (fake *LparAPI) UpdateLparPropertiesReturnsOnCall(i int, result1 int, resul }{result1, result2} } +func (fake *LparAPI) ZeroizeCryptoDomain(arg1 string, arg2 *zhmcclient.CryptoAdapterDetails) (int, *zhmcclient.HmcError) { + fake.zeroizeCryptoDomainMutex.Lock() + ret, specificReturn := fake.zeroizeCryptoDomainReturnsOnCall[len(fake.zeroizeCryptoDomainArgsForCall)] + fake.zeroizeCryptoDomainArgsForCall = append(fake.zeroizeCryptoDomainArgsForCall, struct { + arg1 string + arg2 *zhmcclient.CryptoAdapterDetails + }{arg1, arg2}) + stub := fake.ZeroizeCryptoDomainStub + fakeReturns := fake.zeroizeCryptoDomainReturns + fake.recordInvocation("ZeroizeCryptoDomain", []interface{}{arg1, arg2}) + fake.zeroizeCryptoDomainMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *LparAPI) ZeroizeCryptoDomainCallCount() int { + fake.zeroizeCryptoDomainMutex.RLock() + defer fake.zeroizeCryptoDomainMutex.RUnlock() + return len(fake.zeroizeCryptoDomainArgsForCall) +} + +func (fake *LparAPI) ZeroizeCryptoDomainCalls(stub func(string, *zhmcclient.CryptoAdapterDetails) (int, *zhmcclient.HmcError)) { + fake.zeroizeCryptoDomainMutex.Lock() + defer fake.zeroizeCryptoDomainMutex.Unlock() + fake.ZeroizeCryptoDomainStub = stub +} + +func (fake *LparAPI) ZeroizeCryptoDomainArgsForCall(i int) (string, *zhmcclient.CryptoAdapterDetails) { + fake.zeroizeCryptoDomainMutex.RLock() + defer fake.zeroizeCryptoDomainMutex.RUnlock() + argsForCall := fake.zeroizeCryptoDomainArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *LparAPI) ZeroizeCryptoDomainReturns(result1 int, result2 *zhmcclient.HmcError) { + fake.zeroizeCryptoDomainMutex.Lock() + defer fake.zeroizeCryptoDomainMutex.Unlock() + fake.ZeroizeCryptoDomainStub = nil + fake.zeroizeCryptoDomainReturns = struct { + result1 int + result2 *zhmcclient.HmcError + }{result1, result2} +} + +func (fake *LparAPI) ZeroizeCryptoDomainReturnsOnCall(i int, result1 int, result2 *zhmcclient.HmcError) { + fake.zeroizeCryptoDomainMutex.Lock() + defer fake.zeroizeCryptoDomainMutex.Unlock() + fake.ZeroizeCryptoDomainStub = nil + if fake.zeroizeCryptoDomainReturnsOnCall == nil { + fake.zeroizeCryptoDomainReturnsOnCall = make(map[int]struct { + result1 int + result2 *zhmcclient.HmcError + }) + } + fake.zeroizeCryptoDomainReturnsOnCall[i] = struct { + result1 int + result2 *zhmcclient.HmcError + }{result1, result2} +} + func (fake *LparAPI) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() @@ -1179,6 +1258,8 @@ func (fake *LparAPI) Invocations() map[string][][]interface{} { defer fake.unmountIsoImageMutex.RUnlock() fake.updateLparPropertiesMutex.RLock() defer fake.updateLparPropertiesMutex.RUnlock() + fake.zeroizeCryptoDomainMutex.RLock() + defer fake.zeroizeCryptoDomainMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/pkg/zhmcclient/fakes/zhmc.go b/pkg/zhmcclient/fakes/zhmc.go index eaeb5bc..aced0a9 100644 --- a/pkg/zhmcclient/fakes/zhmc.go +++ b/pkg/zhmcclient/fakes/zhmc.go @@ -614,6 +614,20 @@ type ZhmcAPI struct { result1 int result2 *zhmcclient.HmcError } + ZeroizeCryptoDomainStub func(string, *zhmcclient.CryptoAdapterDetails) (int, *zhmcclient.HmcError) + zeroizeCryptoDomainMutex sync.RWMutex + zeroizeCryptoDomainArgsForCall []struct { + arg1 string + arg2 *zhmcclient.CryptoAdapterDetails + } + zeroizeCryptoDomainReturns struct { + result1 int + result2 *zhmcclient.HmcError + } + zeroizeCryptoDomainReturnsOnCall map[int]struct { + result1 int + result2 *zhmcclient.HmcError + } invocations map[string][][]interface{} invocationsMutex sync.RWMutex } @@ -3342,6 +3356,71 @@ func (fake *ZhmcAPI) UpdateStorageGroupPropertiesReturnsOnCall(i int, result1 in }{result1, result2} } +func (fake *ZhmcAPI) ZeroizeCryptoDomain(arg1 string, arg2 *zhmcclient.CryptoAdapterDetails) (int, *zhmcclient.HmcError) { + fake.zeroizeCryptoDomainMutex.Lock() + ret, specificReturn := fake.zeroizeCryptoDomainReturnsOnCall[len(fake.zeroizeCryptoDomainArgsForCall)] + fake.zeroizeCryptoDomainArgsForCall = append(fake.zeroizeCryptoDomainArgsForCall, struct { + arg1 string + arg2 *zhmcclient.CryptoAdapterDetails + }{arg1, arg2}) + stub := fake.ZeroizeCryptoDomainStub + fakeReturns := fake.zeroizeCryptoDomainReturns + fake.recordInvocation("ZeroizeCryptoDomain", []interface{}{arg1, arg2}) + fake.zeroizeCryptoDomainMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *ZhmcAPI) ZeroizeCryptoDomainCallCount() int { + fake.zeroizeCryptoDomainMutex.RLock() + defer fake.zeroizeCryptoDomainMutex.RUnlock() + return len(fake.zeroizeCryptoDomainArgsForCall) +} + +func (fake *ZhmcAPI) ZeroizeCryptoDomainCalls(stub func(string, *zhmcclient.CryptoAdapterDetails) (int, *zhmcclient.HmcError)) { + fake.zeroizeCryptoDomainMutex.Lock() + defer fake.zeroizeCryptoDomainMutex.Unlock() + fake.ZeroizeCryptoDomainStub = stub +} + +func (fake *ZhmcAPI) ZeroizeCryptoDomainArgsForCall(i int) (string, *zhmcclient.CryptoAdapterDetails) { + fake.zeroizeCryptoDomainMutex.RLock() + defer fake.zeroizeCryptoDomainMutex.RUnlock() + argsForCall := fake.zeroizeCryptoDomainArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *ZhmcAPI) ZeroizeCryptoDomainReturns(result1 int, result2 *zhmcclient.HmcError) { + fake.zeroizeCryptoDomainMutex.Lock() + defer fake.zeroizeCryptoDomainMutex.Unlock() + fake.ZeroizeCryptoDomainStub = nil + fake.zeroizeCryptoDomainReturns = struct { + result1 int + result2 *zhmcclient.HmcError + }{result1, result2} +} + +func (fake *ZhmcAPI) ZeroizeCryptoDomainReturnsOnCall(i int, result1 int, result2 *zhmcclient.HmcError) { + fake.zeroizeCryptoDomainMutex.Lock() + defer fake.zeroizeCryptoDomainMutex.Unlock() + fake.ZeroizeCryptoDomainStub = nil + if fake.zeroizeCryptoDomainReturnsOnCall == nil { + fake.zeroizeCryptoDomainReturnsOnCall = make(map[int]struct { + result1 int + result2 *zhmcclient.HmcError + }) + } + fake.zeroizeCryptoDomainReturnsOnCall[i] = struct { + result1 int + result2 *zhmcclient.HmcError + }{result1, result2} +} + func (fake *ZhmcAPI) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() @@ -3427,6 +3506,8 @@ func (fake *ZhmcAPI) Invocations() map[string][][]interface{} { defer fake.updateNicPropertiesMutex.RUnlock() fake.updateStorageGroupPropertiesMutex.RLock() defer fake.updateStorageGroupPropertiesMutex.RUnlock() + fake.zeroizeCryptoDomainMutex.RLock() + defer fake.zeroizeCryptoDomainMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/pkg/zhmcclient/lpar.go b/pkg/zhmcclient/lpar.go index 8612d4a..2f76ced 100644 --- a/pkg/zhmcclient/lpar.go +++ b/pkg/zhmcclient/lpar.go @@ -39,10 +39,9 @@ type LparAPI interface { DetachStorageGroupToPartition(storageGroupURI string, request *StorageGroupPayload) (int, *HmcError) MountIsoImage(lparURI string, isoFile string, insFile string) (int, *HmcError) UnmountIsoImage(lparURI string) (int, *HmcError) - ListNics(lparURI string) ([]string, int, *HmcError) FetchAsciiConsoleURI(lparURI string, request *AsciiConsoleURIPayload) (*AsciiConsoleURIResponse, int, *HmcError) - + ZeroizeCryptoDomain(lparURI string, adapterDetails *CryptoAdapterDetails) (int, *HmcError) GetEnergyDetailsforLPAR(lparURI string, props *EnergyRequestPayload) (uint64, int, *HmcError) } @@ -625,13 +624,13 @@ func (m *LparManager) FetchAsciiConsoleURI(lparURI string, request *AsciiConsole "timestamp": 1680408593302 }] } - - */ + +*/ func (m *LparManager) GetEnergyDetailsforLPAR(lparURI string, props *EnergyRequestPayload) (uint64, int, *HmcError) { requestUrl := m.client.CloneEndpointURL() requestUrl.Path = path.Join(requestUrl.Path, lparURI, "/operations", "/get-historical-sustainability-data") - logger.Info("Request URL:" + string(requestUrl.Path) + " Method:" + http.MethodPost + " props" + fmt.Sprint(props)) + logger.Info("Request URL:" + string(requestUrl.Path) + " Method:" + http.MethodPost + " props" + fmt.Sprint(props)) status, responseBody, err := m.client.ExecuteRequest(http.MethodPost, requestUrl, props, "") if err != nil { @@ -657,3 +656,39 @@ func (m *LparManager) GetEnergyDetailsforLPAR(lparURI string, props *EnergyReque errorResponseBody := GenerateErrorFromResponse(responseBody) return 0, status, errorResponseBody } + +/** +* POST /api/partitions/{partition-id}/operations/zeroize-crypto-domain +* +* Return: 204 (No Content) is returned and no response body +* or: 400, 404, 409, 500, 503 + */ + +func (m *LparManager) ZeroizeCryptoDomain(lparURI string, adapterDetails *CryptoAdapterDetails) (int, *HmcError) { + requestUrl := m.client.CloneEndpointURL() + requestUrl.Path = path.Join(requestUrl.Path, lparURI) + logger.Info("Request URL:" + string(requestUrl.Path) + " Method:" + http.MethodPost + " adapterDetails" + fmt.Sprint(adapterDetails)) + status, responseBody, err := m.client.ExecuteRequest(http.MethodPost, requestUrl, adapterDetails, "") + if err != nil { + logger.Error("error on getting lpar's energy", + zap.String("request url", fmt.Sprint(requestUrl)), + zap.String("method", http.MethodGet), + zap.String("status", fmt.Sprint(status)), + zap.Error(fmt.Errorf("%v", err))) + return status, err + } + + logger.Info("Response : " + string(responseBody)) + + if status == http.StatusNoContent { + var wd WattageData + err := json.Unmarshal(responseBody, &wd) + if err != nil { + return status, getHmcErrorFromErr(ERR_CODE_HMC_UNMARSHAL_FAIL, err) + } + logger.Info("Response: get on lpars successfully, status:" + fmt.Sprint(status)) + return status, nil + } + errorResponseBody := GenerateErrorFromResponse(responseBody) + return status, errorResponseBody +} diff --git a/pkg/zhmcclient/lpar_test.go b/pkg/zhmcclient/lpar_test.go index b1869a8..440bda7 100644 --- a/pkg/zhmcclient/lpar_test.go +++ b/pkg/zhmcclient/lpar_test.go @@ -131,7 +131,7 @@ var _ = Describe("LPAR", func() { Describe("GetEnergyDetailsforLPAR", func() { var ( - bytes []byte + bytes []byte ) BeforeEach(func() { @@ -149,7 +149,7 @@ var _ = Describe("LPAR", func() { fakeClient.CloneEndpointURLReturns(url) fakeClient.ExecuteRequestReturns(http.StatusOK, bytes, nil) props := &EnergyRequestPayload{ - Range: "last-day", + Range: "last-day", Resolution: "fifteen-minutes", } rets, _, err := manager.GetEnergyDetailsforLPAR(lparid, props) @@ -296,6 +296,52 @@ var _ = Describe("LPAR", func() { }) }) + Describe("Zeroize Crypto Domain", func() { + var ( + payload *CryptoAdapterDetails + bytesResponse []byte + ) + + BeforeEach(func() { + payload = &CryptoAdapterDetails{ + CryptoAdapterUri: "/api/adapters/196a234", + DomainIdx: 0, + } + + bytesResponse, _ = json.Marshal(payload) + }) + + Context("When ZeroizeCryptoDomain and returns correctly", func() { + It("check the results succeed", func() { + fakeClient.CloneEndpointURLReturns(url) + fakeClient.ExecuteRequestReturns(http.StatusNoContent, bytesResponse, nil) + _, err := manager.ZeroizeCryptoDomain(lparid, payload) + + Expect(err).To(BeNil()) + }) + }) + + Context("When ZeroizeCryptoDomain returns error due to unmarshalErr", func() { + It("check the error happened", func() { + fakeClient.CloneEndpointURLReturns(url) + fakeClient.ExecuteRequestReturns(http.StatusBadRequest, []byte("incorrect json bytes"), hmcErr) + _, err := manager.ZeroizeCryptoDomain(lparid, payload) + + Expect(err.Error()).ToNot(BeNil()) + }) + }) + + Context("When ZeroizeCryptoDomain returns error due to hmcErr", func() { + It("check the error happened", func() { + fakeClient.CloneEndpointURLReturns(url) + fakeClient.ExecuteRequestReturns(http.StatusBadRequest, bytesResponse, hmcErr) + _, err := manager.ZeroizeCryptoDomain(lparid, payload) + + Expect(*err).To(Equal(*hmcErr)) + }) + }) + }) + Describe("UpdateLparProperties", func() { var ( payload *LparProperties diff --git a/pkg/zhmcclient/model.go b/pkg/zhmcclient/model.go index d55090d..6afb8f4 100644 --- a/pkg/zhmcclient/model.go +++ b/pkg/zhmcclient/model.go @@ -1084,6 +1084,11 @@ type CryptoConfig struct { CryptoDomainConfigurations []DomainInfo `json:"crypto-domain-configurations,omitempty"` } +type CryptoAdapterDetails struct { + CryptoAdapterUri string `json:"crypto-adapter-uri,omitempty"` + DomainIdx int `json:"domain-index,omitempty"` +} + type EnergyRequestPayload struct { Timescale string `json:"timescale,omitempty"` Type string `json:"type,omitempty"` diff --git a/pkg/zhmcclient/zhmc.go b/pkg/zhmcclient/zhmc.go index 733dee0..a19768f 100644 --- a/pkg/zhmcclient/zhmc.go +++ b/pkg/zhmcclient/zhmc.go @@ -101,6 +101,9 @@ func (m *ZhmcManager) UnmountIsoImage(lparURI string) (int, *HmcError) { func (m *ZhmcManager) ListNics(lparURI string) ([]string, int, *HmcError) { return m.lparManager.ListNics(lparURI) } +func (m *ZhmcManager) ZeroizeCryptoDomain(lparURI string, adapterDetails *CryptoAdapterDetails) (int, *HmcError) { + return m.lparManager.ZeroizeCryptoDomain(lparURI, adapterDetails) +} func (m *ZhmcManager) AttachStorageGroupToPartition(lparURI string, request *StorageGroupPayload) (int, *HmcError) { return m.lparManager.AttachStorageGroupToPartition(lparURI, request) @@ -119,7 +122,7 @@ func (m *ZhmcManager) GetEnergyDetailsforLPAR(lparURI string, props *EnergyReque } func (m *ZhmcManager) GetLiveEnergyDetailsforLPAR(lparURI string) (uint64, int, *HmcError) { - return m.metricsManager.GetLiveEnergyDetailsforLPAR(lparURI) + return m.metricsManager.GetLiveEnergyDetailsforLPAR(lparURI) } // Adapter From 4988056b00f9b2d850dd5b1c2d222883cb237715 Mon Sep 17 00:00:00 2001 From: Rahul Bhalla Date: Wed, 15 Nov 2023 12:58:17 +0530 Subject: [PATCH 2/2] Updated response for zeroize support --- pkg/zhmcclient/lpar.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pkg/zhmcclient/lpar.go b/pkg/zhmcclient/lpar.go index 8b8d645..efa0d3a 100644 --- a/pkg/zhmcclient/lpar.go +++ b/pkg/zhmcclient/lpar.go @@ -659,7 +659,6 @@ func (m *LparManager) GetEnergyDetailsforLPAR(lparURI string, props *EnergyReque return 0, status, errorResponseBody } - /** * POST /api/partitions/{partition-id}/operations/zeroize-crypto-domain * @@ -684,18 +683,20 @@ func (m *LparManager) ZeroizeCryptoDomain(lparURI string, adapterDetails *Crypto logger.Info("Response : " + string(responseBody)) if status == http.StatusNoContent { - var wd WattageData - err := json.Unmarshal(responseBody, &wd) - if err != nil { - return status, getHmcErrorFromErr(ERR_CODE_HMC_UNMARSHAL_FAIL, err) - } - logger.Info("Response: get on lpars successfully, status:" + fmt.Sprint(status)) + logger.Info(fmt.Sprintf("Response: zeroize partition crypto domains successfull, request url: %v, method: %v, status: %v", lparURI, http.MethodPost, status)) return status, nil } errorResponseBody := GenerateErrorFromResponse(responseBody) return status, errorResponseBody } +/** +* POST /api/partitions/{partition-id}/operations/increase-crypto-configuration +* +* Return: 204 (No Content) is returned and no response body +* or: 400, 404, 409, 500, 503 + */ + func (m *LparManager) AttachCryptoToPartition(lparURI string, request *CryptoConfig) (int, *HmcError) { requestUrl := m.client.CloneEndpointURL() requestUrl.Path = path.Join(requestUrl.Path, lparURI, "/operations/increase-crypto-configuration")