Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SMHE-2011 Save firmware file to file system #1324

Merged
merged 29 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
959d6df
Moved firmwareFileIdentification to requestData and added HashType an…
harrymiddelburgetall May 13, 2024
4ea7570
Removed unreachable code
jboon May 14, 2024
469be86
dlms protocol adapter reads fwfile and imageidentifier from s3 bucket
harrymiddelburgetall May 14, 2024
f0dddeb
Removed image_identifier from firmwarefile in core database (smartmet…
harrymiddelburgetall May 16, 2024
2795ddd
restore ws-smartmetering request. Removed hash(type)
harrymiddelburgetall May 17, 2024
23e1a81
cucumber tests
harrymiddelburgetall May 17, 2024
5b155cb
Renamed S3BucketService to implementation neutral FirmwareFileStoreSe…
harrymiddelburgetall May 21, 2024
33641a5
Merge branch 'feature/SMHE-2011_firmware-s3-bucket' of github.com:OSG…
jboon May 21, 2024
f80bbbb
Write firmware to local storage and calculate digest
jboon May 22, 2024
d2d2242
Write firmware to local storage and calculate digest
jboon May 23, 2024
e983482
Merge branch 'development' into feature/SMHE-2011_firmware-s3-bucket
jboon May 23, 2024
bc84897
Write firmware to local storage and calculate digest
jboon May 23, 2024
b81a03c
Write firmware to local storage and calculate digest
jboon May 23, 2024
0a7c7e7
Added modified cucumber tests for AddOrChangeFirmware request
harrymiddelburgetall May 23, 2024
5f44c89
Restored AcceptanceTests.java and removed Tags
harrymiddelburgetall May 23, 2024
5ec9251
Unit tests and additional logic from that process
jboon May 23, 2024
be212d4
Merge branch 'feature/SMHE-2011_firmware-s3-bucket' of github.com:OSG…
jboon May 23, 2024
a9af96d
Removed obsolete code
jboon May 27, 2024
09a81b3
Merge branch 'development' into feature/SMHE-2011_firmware-s3-bucket
jboon May 27, 2024
a5f7846
Use UploadFW request is given condition for Update FW request test
harrymiddelburgetall May 27, 2024
7237027
Merge branch 'feature/SMHE-2011_firmware-s3-bucket' of https://github…
harrymiddelburgetall May 27, 2024
befc4b9
Merge branch 'feature/SMHE-2011_firmware-s3-bucket' of github.com:OSG…
jboon May 27, 2024
f03c756
Solved sonar issues
harrymiddelburgetall May 27, 2024
e1c7fa4
Hash type mapping corrected
jboon May 27, 2024
eb33335
Merge branch 'feature/SMHE-2011_firmware-s3-bucket' of github.com:OSG…
jboon May 27, 2024
4097950
Sonar issues
jboon May 27, 2024
c671022
Solved sonar issue
harrymiddelburgetall May 28, 2024
ab6597d
Copyright and removal of InboundOsgpCoreFirmwareFileResponsesMessagin…
harrymiddelburgetall May 28, 2024
545ad72
Processed review comments
harrymiddelburgetall May 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import static org.opensmartgridplatform.cucumber.core.ReadSettingsHelper.getString;
import static org.opensmartgridplatform.cucumber.core.ReadSettingsHelper.getStringList;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
Expand All @@ -37,6 +40,8 @@ public class FirmwareSteps {
public static final String ACTIVE_FIRMWARE = "active_firmware";
public static final String M_BUS_DRIVER_ACTIVE_FIRMWARE = "m_bus_driver_active_firmware";
public static final String SIMPLE_VERSION_INFO = "simple_version_info";
public static final String DATABASE = "database";
public static final String FILE_STORAGE = "file_storage";

@Autowired private FirmwareFileRepository firmwareFileRepository;

Expand All @@ -46,15 +51,23 @@ protected Firmware createAndGetFirmware(final Map<String, String> requestParamet
getString(requestParameters, PlatformKeys.FIRMWARE_FILE_IDENTIFICATION, null));
firmware.setFilename(getString(requestParameters, PlatformKeys.FIRMWARE_FILE_FILENAME, null));
firmware.setDescription(getString(requestParameters, PlatformKeys.FIRMWARE_DESCRIPTION, null));
if (requestParameters.containsKey(PlatformKeys.FIRMWARE_FILE)) {
if (requestParameters.containsKey(PlatformKeys.FIRMWARE_FILE)
&& requestParameters.get(PlatformKeys.FIRMWARE_FILE) != null) {
firmware.setFile(getHexDecoded(requestParameters, PlatformKeys.FIRMWARE_FILE, null));
}
if (requestParameters.containsKey(PlatformKeys.FIRMWARE_FILE_IMAGE_IDENTIFIER)
&& requestParameters.get(PlatformKeys.FIRMWARE_FILE_IMAGE_IDENTIFIER) != null) {
firmware.setImageIdentifier(
getHexDecoded(requestParameters, PlatformKeys.FIRMWARE_FILE_IMAGE_IDENTIFIER, null));
}
firmware.setPushToNewDevices(
getBoolean(
requestParameters,
PlatformKeys.FIRMWARE_PUSH_TO_NEW_DEVICES,
PlatformDefaults.FIRMWARE_PUSH_TO_NEW_DEVICE));

firmware.setHashType(getString(requestParameters, PlatformKeys.FIRMWARE_HASH_TYPE, null));

firmware.setFirmwareModuleData(new FirmwareModuleData());
if (requestParameters.containsKey(PlatformKeys.FIRMWARE_MODULE_VERSION_COMM)) {
firmware
Expand Down Expand Up @@ -170,7 +183,8 @@ protected ChangeableFirmware createAndGetChangeableFirmware(
}

protected void assertFirmwareFileExists(
final String identification, final Map<String, String> firmwareFileProperties) {
final String identification, final Map<String, String> firmwareFileProperties)
throws NoSuchAlgorithmException {
final Firmware expectedFirmware = this.createAndGetFirmware(firmwareFileProperties);
final FirmwareFile databaseFirmwareFile =
this.firmwareFileRepository.findByIdentification(identification);
Expand All @@ -180,8 +194,40 @@ protected void assertFirmwareFileExists(
.as("Firmware File {} should exist", identification);

assertThat(databaseFirmwareFile.getDescription()).isEqualTo(expectedFirmware.getDescription());
assertThat(databaseFirmwareFile.getFile()).isEqualTo(expectedFirmware.getFile());
assertThat(databaseFirmwareFile.getFilename()).isEqualTo(expectedFirmware.getFilename());

if (expectedFirmware.getFile() == null) {
return;
}

final String fileStoreLocation =
getString(firmwareFileProperties, PlatformKeys.FIRMWARE_FILE_STORE_LOCATION, DATABASE);

if (fileStoreLocation == DATABASE) {
assertThat(databaseFirmwareFile.getFile()).isEqualTo(expectedFirmware.getFile());
}
if (fileStoreLocation == FILE_STORAGE) {
// There is no check here whether the file is actually on the file storage. Since the cucumber
// test is running outside the container in which the gxf common mudule runs there is no way
// to check the existence of the file on file storage inside the container. We can check that
// the file is NOT stored in the database and the hash for the file content is in the database
// as expected.
// Other cucumber tests that use the uploaded firmware file like UpdateFirmwareRequest test
// the existence of the file on storage by using the upload request as given condition for
// their test
assertThat(databaseFirmwareFile.getFile()).isNull();
assertThat(databaseFirmwareFile.getHashType()).isEqualTo(expectedFirmware.getHashType());
assertThat(databaseFirmwareFile.getHash())
.isEqualTo(
this.calculateHash(expectedFirmware.getHashType(), expectedFirmware.getFile()));
}
}

private String calculateHash(final String hashType, final byte[] firmwareFile)
throws NoSuchAlgorithmException {
final MessageDigest messageDigest = MessageDigest.getInstance(hashType);
final byte[] digest = messageDigest.digest(firmwareFile);
return new BigInteger(1, digest).toString(16);
}

protected void assertFirmwareFileHasModuleVersions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,36 @@ Feature: FirmwareManagement add or change firmware
I want to add a new or change an existing firmware
In order to ...

Scenario: Add firmware with File Contents
Scenario Outline: Add firmware <content> File Contents and <identifier> Image Identifier
Given a device model
| ModelCode | DeviceModelDBStorageModel_test |
| DeviceModelFileStorage | false |
When receiving an add or change firmware request
| FirmwareFileIdentification | 1234567890ABCBEF |
| FirmwareFile | 57696520646974206c656573742069732067656b |
| FirmwareFilename | NewFirmware_test1 |
| ManufacturerName | Test |
| ModelCode | DeviceModelDBStorageModel_test |
| FirmwareDescription | Add 1 - Firmware is newly created with File Contents |
| FirmwareModuleVersionComm | comm_1.2 |
| FirmwareFileIdentification | 1234567890ABCBEF |
| FirmwareFile | <file> |
| FirmwareFilename | NewFirmware_test1 |
| ManufacturerName | Test |
| ModelCode | DeviceModelDBStorageModel_test |
| FirmwareDescription | some description |
| FirmwareModuleVersionComm | comm_1.2 |
| FirmwareFileImageIdentifier | <imageidentifier> |
Then the add or change firmware response contains
| Result | OK |
And the firmware file '1234567890ABCBEF' exists
| FirmwareFile | 57696520646974206c656573742069732067656b |
| FirmwareFilename | NewFirmware_test1 |
| FirmwareDescription | Add 1 - Firmware is newly created with File Contents |
| FirmwareModuleVersionComm | comm_1.2 |
| FirmwareFile | <file> |
| FirmwareFilename | NewFirmware_test1 |
| FirmwareDescription | some description |
| FirmwareModuleVersionComm | comm_1.2 |
# Firmware files uploaded with AddOrChangeFirmwareRequest always are store on file storage and
# hash of type SHA256
| FirmwareFileStoreLocation | FILE_STORAGE |
| FirmwareHashType | SHA256 |
Examples:
| imageidentifier | file | content | identifier |
| FEDCBA0987654321 | 57696520646974206c656573742069732067656b | with | with |
| | 57696520646974206c656573742069732067656b | with | without |
| FEDCBA0987654321 | | without | with |
| | | without | without |

Scenario: Add firmware without File Content
Given a device model
Expand Down Expand Up @@ -68,6 +79,8 @@ Feature: FirmwareManagement add or change firmware
| FirmwareFile | 57696520646974206c656573742069732067656b |
| FirmwareFilename | NewFirmware_test3 |
| FirmwareDescription | Add 3 - Firmware is newly created with related FirmwareModules |
| FirmwareFileStoreLocation | FILE_STORAGE |
| FirmwareHashType | SHA256 |
And the firmware file '1234567890ABCBEF' has module versions
| FirmwareModuleVersionComm | comm_1.2 |
| FirmwareModuleVersionFunc | func_1.3 |
Expand Down Expand Up @@ -101,6 +114,8 @@ Feature: FirmwareManagement add or change firmware
| FirmwareFile | 57696520646974206c656573742069732067656b |
| FirmwareFilename | NewFirmware_test4 |
| FirmwareDescription | Add 4 - Firmware is newly created with multiple related DeviceModels |
| FirmwareFileStoreLocation | FILE_STORAGE |
| FirmwareHashType | SHA256 |
And the firmware file '1234567890ABCBEF' has device models
| ModelCode | DeviceModelDBStorageModel_test1;DeviceModelDBStorageModel_test2;DeviceModelDBStorageModel_test3 |

Expand All @@ -120,7 +135,9 @@ Feature: FirmwareManagement add or change firmware
| FirmwareFile | 57696520646974206c656573742069732067656b |
| FirmwareFilename | NewFirmware_test5 |
| FirmwareDescription | Add 5 - Firmware is newly created with File Contents and without related DeviceModels |

| FirmwareFileStoreLocation | FILE_STORAGE |
| FirmwareHashType | SHA256 |

Scenario: Change firmware with File Content - Change Description
Given a device model
| ModelCode | DeviceModelDBStorageModel_test |
Expand Down Expand Up @@ -149,6 +166,8 @@ Feature: FirmwareManagement add or change firmware
| ManufacturerName | Test |
| ModelCode | DeviceModelDBStorageModel_test |
| FirmwareDescription | Change 1 - Firmware is changed - Added Description |
| FirmwareFileStoreLocation | FILE_STORAGE |
| FirmwareHashType | SHA256 |

Scenario: Change firmware without File Content - Add File Content
Given a device model
Expand Down Expand Up @@ -176,6 +195,8 @@ Feature: FirmwareManagement add or change firmware
| FirmwareFilename | NewFirmware_test4 |
| FirmwarePushToNewDevices | true |
| FirmwareDescription | Change 2 - Firmware is changed - Added File Content |
| FirmwareFileStoreLocation | FILE_STORAGE |
| FirmwareHashType | SHA256 |

Scenario: Change firmware without related DeviceModels- Add related DeviceModels
Given a device model
Expand Down Expand Up @@ -205,7 +226,7 @@ Feature: FirmwareManagement add or change firmware
And the firmware file '1234567890ABCBEF' exists
| FirmwarePushToNewDevices | true |
| FirmwareDescription | Change 3 - Firmware is changed - Added related DeviceModels |

Scenario: Change firmware without related DeviceModels- Add related DeviceModels
Given a device model
| ModelCode | DeviceModelDBStorageModel_test1 |
Expand Down Expand Up @@ -242,4 +263,4 @@ Feature: FirmwareManagement add or change firmware
| FirmwareModuleVersionMa | ma_2.4 |
| FirmwareModuleVersionMbus | mbus_2.5 |
| FirmwareModuleVersionSec | sec_2.6 |
| FirmwareModuleVersionMbda | mbda_2.7 |
| FirmwareModuleVersionMbda | mbda_2.7 |
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@
package org.opensmartgridplatform.cucumber.platform.smartmetering.glue.steps.ws.smartmetering.smartmeteringconfiguration;

import static org.assertj.core.api.Assertions.assertThat;
import static org.opensmartgridplatform.cucumber.core.ReadSettingsHelper.getHexDecoded;
import static org.opensmartgridplatform.cucumber.core.ReadSettingsHelper.getString;

import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.opensmartgridplatform.adapter.ws.schema.smartmetering.common.OsgpResultType;
import org.opensmartgridplatform.adapter.ws.schema.smartmetering.configuration.UpdateFirmwareAsyncRequest;
Expand All @@ -27,15 +37,27 @@
import org.opensmartgridplatform.domain.core.entities.Device;
import org.opensmartgridplatform.domain.core.entities.FirmwareFile;
import org.opensmartgridplatform.domain.core.repositories.DeviceRepository;
import org.opensmartgridplatform.domain.core.repositories.FirmwareFileRepository;
import org.opensmartgridplatform.dto.valueobjects.HashTypeDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ws.soap.client.SoapFaultClientException;

@Slf4j
@Transactional(value = "txMgrCore")
public class UpdateFirmware {

@Value("${smartmetering.firmware.path}")
private String firmwarePath;

@Value("${smartmetering.firmware.imageidentifier.extention}")
private String imageIdentifierExtension;

@Autowired private DeviceRepository deviceRepository;

@Autowired private FirmwareFileRepository firmwareFileRepository;

@Autowired private SmartMeteringConfigurationClient client;

@Autowired private DeviceFirmwareModuleSteps deviceFirmwareModuleSteps;
Expand Down Expand Up @@ -111,4 +133,65 @@ public void theDatabaseShouldNotBeUpdatedWithTheNewDeviceFirmware(
+ " should not have firmware versions from the scenario after an unsuccessful update.")
.isFalse();
}

@Given(
"a firmware file and image identifier in a firmware file store and corresponding hash in database")
public void aFirmwareFileAndImageIdentifierInAFirmwareFileStoreAndCorrespondingHashInDatabase(
final Map<String, String> settings) throws Throwable {
final String firmwareIdentification =
getString(settings, PlatformKeys.FIRMWARE_FILE_IDENTIFICATION, null);

final FirmwareFile firmwareFile =
this.firmwareFileRepository.findByIdentificationOnly(firmwareIdentification);
byte[] fileContent = null;
if (settings.containsKey(PlatformKeys.FIRMWARE_FILE)) {
fileContent = getHexDecoded(settings, PlatformKeys.FIRMWARE_FILE, null);
}
final String imageIdentifier =
getString(settings, PlatformKeys.FIRMWARE_FILE_IMAGE_IDENTIFIER, null);
final String hashType = getString(settings, PlatformKeys.FIRMWARE_HASH_TYPE, null);
final HashTypeDto hashTypeDto = HashTypeDto.valueOf(hashType);
this.storeFileContentAndHash(firmwareFile, fileContent, imageIdentifier, hashTypeDto);
}

private void storeFileContentAndHash(
final FirmwareFile firmwareFile,
final byte[] fileContent,
final String imageIdentifier,
final HashTypeDto hashTypeDto)
throws IOException {
final Path path = Paths.get(this.firmwarePath);
if (!Files.exists(path)) {
Files.createDirectories(path);
}
if (fileContent != null) {
final Path pathFirmware = Paths.get(this.firmwarePath, firmwareFile.getIdentification());
if (!Files.exists(pathFirmware)) {
Files.write(pathFirmware, fileContent);
}
}
if (imageIdentifier != null) {
final Path pathImageIdentifier =
Paths.get(
this.firmwarePath,
firmwareFile.getIdentification() + "." + this.imageIdentifierExtension);
if (!Files.exists(pathImageIdentifier)) {
Files.write(pathImageIdentifier, imageIdentifier.getBytes());
}
}
firmwareFile.setHash(this.calcHash(fileContent, hashTypeDto.getAlgorithmName()));
firmwareFile.setHashType(hashTypeDto.name());
this.firmwareFileRepository.save(firmwareFile);
}

private String calcHash(final byte[] filecontent, final String algorithm) {
try {
final MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
final byte[] digest = messageDigest.digest(filecontent);
return new BigInteger(1, digest).toString(16);
} catch (final NoSuchAlgorithmException e) {
log.error("Error calculating digest", e);
return "";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,6 @@ web.service.smartmetering.notification.port=8189
jre.encryption.key.resource=classpath:osgp-secret-management-jre.key

simulator.max.logicalids.per.port=100

smartmetering.firmware.path=/etc/osp/firmwarefiles
smartmetering.firmware.imageidentifier.extention=imgid
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: Apache-2.0

@SmartMetering @Platform @NightlyBuildOnly
@SmartMetering @Platform @NightlyBuildOnly @SmartMeteringFirmware
Feature: SmartMetering functional exceptions regarding firmware

Scenario: firmware upgrade with unknown firmware
Expand All @@ -27,7 +27,6 @@ Feature: SmartMetering functional exceptions regarding firmware
| FirmwareModuleVersionSec | |
| FirmwareFilename | KFPP_V060100FF.bin |
| ModelCode | MA105 |
| FirmwareFileImageIdentifier | 496d6167654964656e746966696572 |
| FirmwareIsForSmartMeters | true |
When the request for a firmware upgrade is received
| DeviceIdentification | TEST1024000000002 |
Expand Down Expand Up @@ -55,7 +54,6 @@ Feature: SmartMetering functional exceptions regarding firmware
| FirmwareModuleVersionSec | |
| FirmwareFilename | KFPP_V060100FF.bin |
| ModelCode | MA105 |
| FirmwareFileImageIdentifier | 496d6167654964656e746966696572 |
| FirmwareIsForSmartMeters | true |
When the request for a firmware upgrade is received
| DeviceIdentification | TEST1024000000002 |
Expand Down
Loading
Loading