winterhazel commented on code in PR #13053:
URL: https://github.com/apache/cloudstack/pull/13053#discussion_r3191253147
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/UnifiedNASStrategy.java:
##########
@@ -77,7 +72,22 @@ public void setOntapStorage(OntapStorage ontapStorage) {
@Override
public CloudStackVolume createCloudStackVolume(CloudStackVolume
cloudstackVolume) {
- return null;
+ logger.info("createCloudStackVolume: Create cloudstack volume " +
cloudstackVolume);
+ try {
+ // Step 1: set cloudstack volume metadata
+ String volumeUuid =
updateCloudStackVolumeMetadata(cloudstackVolume.getDatastoreId(),
cloudstackVolume.getVolumeInfo());
Review Comment:
`volumeUuid` is not used
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/UnifiedNASStrategy.java:
##########
@@ -96,24 +119,40 @@ public void copyCloudStackVolume(CloudStackVolume
cloudstackVolume) {
@Override
public CloudStackVolume getCloudStackVolume(Map<String, String>
cloudStackVolumeMap) {
- return null;
+ logger.info("getCloudStackVolume: Get cloudstack volume " +
cloudStackVolumeMap);
+ CloudStackVolume cloudStackVolume = null;
+ FileInfo fileInfo =
getFile(cloudStackVolumeMap.get(OntapStorageConstants.VOLUME_UUID),cloudStackVolumeMap.get(OntapStorageConstants.FILE_PATH));
+
+ if(fileInfo != null){
Review Comment:
```suggestion
if (fileInfo != null) {
```
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/UnifiedNASStrategy.java:
##########
@@ -300,4 +402,153 @@ private ExportPolicy
createExportPolicyRequest(AccessGroup accessGroup,String sv
return exportPolicy;
}
+
+ private String updateCloudStackVolumeMetadata(String dataStoreId,
DataObject volumeInfo) {
+ logger.info("updateCloudStackVolumeMetadata called with datastoreID:
{} volumeInfo: {} ", dataStoreId, volumeInfo );
+ try {
+ VolumeObject volumeObject = (VolumeObject) volumeInfo;
+ long volumeId = volumeObject.getId();
+ logger.info("updateCloudStackVolumeMetadata: VolumeInfo ID from
VolumeObject: {}", volumeId);
+ VolumeVO volume = volumeDao.findById(volumeId);
+ if (volume == null) {
+ throw new CloudRuntimeException("Volume not found with id: " +
volumeId);
+ }
+ String volumeUuid = volumeInfo.getUuid();
+ volume.setPoolType(Storage.StoragePoolType.NetworkFilesystem);
+ volume.setPoolId(Long.parseLong(dataStoreId));
+ volume.setPath(volumeUuid); // Filename for qcow2 file
+ volumeDao.update(volume.getId(), volume);
+ logger.info("Updated volume path to {} for volume ID {}",
volumeUuid, volumeId);
+ return volumeUuid;
+ }catch (Exception e){
+ logger.error("updateCloudStackVolumeMetadata: Exception while
updating volumeInfo: {} in volume: {}", dataStoreId, volumeInfo.getUuid(), e);
+ throw new CloudRuntimeException("Exception while updating
volumeInfo: " + e.getMessage());
+ }
Review Comment:
Adjust the indentation of this try block. All lines are missing a space
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/UnifiedNASStrategy.java:
##########
@@ -252,19 +285,88 @@ private void assignExportPolicyToVolume(String
volumeUuid, String policyName) {
Thread.sleep(OntapStorageConstants.CREATE_VOLUME_CHECK_SLEEP_TIME);
}
} catch (Exception e) {
- logger.error("Exception while updating volume: ", e);
+ logger.error("assignExportPolicyToVolume: Exception while
updating volume: ", e);
throw new CloudRuntimeException("Failed to update volume: " +
e.getMessage());
}
- logger.info("Export policy successfully assigned to volume: {}",
volumeUuid);
+ logger.info("assignExportPolicyToVolume: Export policy
successfully assigned to volume: {}", volumeUuid);
} catch (FeignException e) {
- logger.error("Failed to assign export policy to volume: {}",
volumeUuid, e);
+ logger.error("assignExportPolicyToVolume: Failed to assign export
policy to volume: {}", volumeUuid, e);
throw new CloudRuntimeException("Failed to assign export policy: "
+ e.getMessage());
} catch (Exception e) {
- logger.error("Exception while assigning export policy to volume:
{}", volumeUuid, e);
+ logger.error("assignExportPolicyToVolume: Exception while
assigning export policy to volume: {}", volumeUuid, e);
throw new CloudRuntimeException("Failed to assign export policy: "
+ e.getMessage());
}
}
+ private boolean createFile(String volumeUuid, String filePath, FileInfo
fileInfo) {
+ logger.info("createFile: Creating file: {} in volume: {}", filePath,
volumeUuid);
+ try {
+ String authHeader =
OntapStorageUtils.generateAuthHeader(storage.getUsername(),
storage.getPassword());
+ nasFeignClient.createFile(authHeader, volumeUuid, filePath,
fileInfo);
+ logger.info("createFile: File created successfully: {} in volume:
{}", filePath, volumeUuid);
+ return true;
+ } catch (FeignException e) {
+ logger.error("createFile: Failed to create file: {} in volume:
{}", filePath, volumeUuid, e);
+ return false;
+ } catch (Exception e) {
+ logger.error("createFile: Exception while creating file: {} in
volume: {}", filePath, volumeUuid, e);
+ return false;
+ }
+ }
+
+ private boolean deleteFile(String volumeUuid, String filePath) {
+ logger.info("deleteFile: Deleting file: {} from volume: {}", filePath,
volumeUuid);
+ try {
+ String authHeader =
OntapStorageUtils.generateAuthHeader(storage.getUsername(),
storage.getPassword());
+ nasFeignClient.deleteFile(authHeader, volumeUuid, filePath);
+ logger.info("deleteFile: File deleted successfully: {} from
volume: {}", filePath, volumeUuid);
+ return true;
+ } catch (FeignException e) {
+ logger.error("deleteFile: Failed to delete file: {} from volume:
{}", filePath, volumeUuid, e);
+ return false;
+ } catch (Exception e) {
+ logger.error("deleteFile: Exception while deleting file: {} from
volume: {}", filePath, volumeUuid, e);
+ return false;
+ }
+ }
+
+ private OntapResponse<FileInfo> getFileInfo(String volumeUuid, String
filePath) {
+ logger.debug("getFileInfo: Getting file info for: {} in volume: {}",
filePath, volumeUuid);
+ try {
+ String authHeader =
OntapStorageUtils.generateAuthHeader(storage.getUsername(),
storage.getPassword());
+ OntapResponse<FileInfo> response =
nasFeignClient.getFileResponse(authHeader, volumeUuid, filePath);
+ logger.debug("getFileInfo: Retrieved file info for: {} in volume:
{}", filePath, volumeUuid);
+ return response;
+ } catch (FeignException e){
+ if (e.status() == 404) {
+ logger.debug("getFileInfo: File not found: {} in volume: {}",
filePath, volumeUuid);
+ return null;
+ }
+ logger.error("getFileInfo: Failed to get file info: {} in volume:
{}", filePath, volumeUuid, e);
+ throw new CloudRuntimeException("Failed to get file info: " +
e.getMessage());
+ } catch (Exception e){
+ logger.error("getFileInfo: Exception while getting file info: {}
in volume: {}", filePath, volumeUuid, e);
+ throw new CloudRuntimeException("Failed to get file info: " +
e.getMessage());
+ }
+ }
+
+ private boolean updateFile(String volumeUuid, String filePath, FileInfo
fileInfo) {
+ logger.info("updateFile: Updating file: {} in volume: {}", filePath,
volumeUuid);
+ try {
+ String authHeader =
OntapStorageUtils.generateAuthHeader(storage.getUsername(),
storage.getPassword());
+ nasFeignClient.updateFile( authHeader, volumeUuid, filePath,
fileInfo);
+ logger.info("updateFile: File updated successfully: {} in volume:
{}", filePath, volumeUuid);
+ return true;
+ } catch (FeignException e) {
+ logger.error("updateFile: Failed to update file: {} in volume:
{}", filePath, volumeUuid, e);
+ return false;
+ } catch (Exception e){
+ logger.error("updateFile: Exception while updating file: {} in
volume: {}", filePath, volumeUuid, e);
+ return false;
+ }
+ }
+
+
Review Comment:
Methods from line 301-367 are not used. Is this expected?
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/UnifiedNASStrategy.java:
##########
@@ -180,11 +212,11 @@ public void disableLogicalAccess(Map<String, String>
values) {
@Override
public Map<String, String> getLogicalAccess(Map<String, String> values) {
Review Comment:
This method does not seem to be used outside the tests. Is this expected?
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/utils/OntapStorageUtils.java:
##########
@@ -36,41 +42,116 @@
public class OntapStorageUtils {
private static final Logger logger =
LogManager.getLogger(OntapStorageUtils.class);
-
private static final String BASIC = "Basic";
private static final String AUTH_HEADER_COLON = ":";
+ /**
+ * Method generates authentication headers using storage backend
credentials passed as normal string
+ *
+ * @param username -->> username of the storage backend
+ * @param password -->> normal decoded password of the storage backend
+ * @return
+ */
public static String generateAuthHeader (String username, String password)
{
byte[] encodedBytes = Base64Utils.encode((username + AUTH_HEADER_COLON
+ password).getBytes(StandardCharsets.UTF_8));
return BASIC + StringUtils.SPACE + new String(encodedBytes);
}
+ public static CloudStackVolume
createCloudStackVolumeRequestByProtocol(StoragePoolVO storagePool, Map<String,
String> details, DataObject volumeObject) {
+ CloudStackVolume cloudStackVolumeRequest = null;
+
+ String protocol = details.get(OntapStorageConstants.PROTOCOL);
+ ProtocolType protocolType = ProtocolType.valueOf(protocol);
+ switch (protocolType) {
+ case NFS3:
+ cloudStackVolumeRequest = new CloudStackVolume();
+
cloudStackVolumeRequest.setDatastoreId(String.valueOf(storagePool.getId()));
+ cloudStackVolumeRequest.setVolumeInfo(volumeObject);
+ break;
+ case ISCSI:
+ Svm svm = new Svm();
+ svm.setName(details.get(OntapStorageConstants.SVM_NAME));
+ cloudStackVolumeRequest = new CloudStackVolume();
+ Lun lunRequest = new Lun();
+ lunRequest.setSvm(svm);
+
+ LunSpace lunSpace = new LunSpace();
+ lunSpace.setSize(volumeObject.getSize());
+ lunRequest.setSpace(lunSpace);
+ //Lun name is full path like in unified
"/vol/VolumeName/LunName"
+ String lunName =
volumeObject.getName().replace(OntapStorageConstants.HYPHEN,
OntapStorageConstants.UNDERSCORE);
+ if(!isValidName(lunName)) {
+ String errMsg = "createAsync: Invalid dataObject name [" +
lunName + "]. It must start with a letter and can only contain letters, digits,
and underscores, and be up to 200 characters long.";
+ throw new InvalidParameterValueException(errMsg);
+ }
+ String lunFullName = getLunName(storagePool.getName(),
lunName);
+ lunRequest.setName(lunFullName);
+
+ String osType =
getOSTypeFromHypervisor(storagePool.getHypervisor().name());
+ lunRequest.setOsType(Lun.OsTypeEnum.valueOf(osType));
+
+ cloudStackVolumeRequest.setLun(lunRequest);
+ break;
+ default:
+ throw new CloudRuntimeException("Unsupported protocol " +
protocol);
+
+ }
+ return cloudStackVolumeRequest;
+ }
+
+ public static boolean isValidName(String name) {
+ // Check for null and length constraint first
+ if (name == null || name.length() > 200) {
+ return false;
+ }
+ // Regex: Starts with a letter, followed by letters, digits, or
underscores
+ return name.matches(OntapStorageConstants.ONTAP_NAME_REGEX);
+ }
+
+ public static String getOSTypeFromHypervisor(String hypervisorType){
Review Comment:
```suggestion
public static String getOSTypeFromHypervisor(String hypervisorType) {
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]