Skip to content

Conversation

@sandeeplocharla
Copy link
Collaborator

@sandeeplocharla sandeeplocharla commented Oct 21, 2025

Description

This PR...

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

How Has This Been Tested?

How did you try to break this feature and the system with this change?

//this method to get all svms and also filtered svms based on query params as a part of URL
@RequestMapping(method = RequestMethod.GET)
OntapResponse<Svm> getSvmResponse(URI baseURL, @RequestHeader("Authorization") String header);
OntapResponse<Svm> getSvms(URI baseURL, @RequestHeader("Authorization") String header);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we kept this naming convention for other feign client and this can return only one record also

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted it back

public static String Username;
public static String Password;
public static String ManagementLIF;
public static String Svm;
Copy link

@suryag1201 suryag1201 Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

svm is an object which can not be string use svmName instead

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, will rename it

public static String Password;
public static String ManagementLIF;
public static String Svm;
public static String Protocol;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have type as enum with supported protocols?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@SuppressWarnings("unchecked")
Map<String, String> details = (Map<String, String>)dsInfos.get("details");
// Validations
if (podId != null && clusterId == null) {
Copy link

@suryag1201 suryag1201 Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can combine this check into one check bcz both are required, also clusterId can be empty

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, in my previous review to this change i nanother PR, I gave comment to use trim command and then empty check. Please add them for each mandatory parameter

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taken care of it, done

}

PrimaryDataStoreParameters parameters = new PrimaryDataStoreParameters();
if (clusterId != null) {
Copy link

@suryag1201 suryag1201 Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this check is required again? it is already checked above

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Customer has an option to not send both cluster and pod ids, in case of creating a zone level primary storage pool.

details.put(Constants.MANAGEMENTLIF, url);

// Validate the ONTAP details
if(details.get(Constants.ISDISAGGREGATED) == null || details.get(Constants.ISDISAGGREGATED).isEmpty()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add _ for ISDISAGGREGATED constant like IS_DISAGGREGATED

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// Call the SVM API to check if the SVM exists
Svm svm = null;
URI url = URI.create(Constants.HTTPS + storage.getManagementLIF() + Constants.GETSVMs);
OntapResponse<Svm> svms = svmFeignClient.getSvms(url, authHeader);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a check for svms null check object

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

public class Constants {
public static final String NFS = "nfs";
public static final String ISCSI = "iscsi";
public static final String PROTOCOL = "protocol";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add _ where ever possible

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// Create URI for POST CreateVolume API
URI url = utils.generateURI(Constants.CREATEVOLUME);
// Call the VolumeFeignClient to create the volume
JobResponse jobResponse = volumeFeignClient.createVolumeWithJob(url, authHeader, volumeRequest);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add null checks

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, thanks

url = utils.generateURI(Constants.GETJOBBYUUID);
int jobRetryCount = 0, maxJobRetries = Constants.JOBMAXRETRIES;
Job createVolumeJob = null;
while(createVolumeJob == null || createVolumeJob.getState().equals(Constants.JOBRUNNING) || createVolumeJob.getState().equals(Constants.JOBQUEUE) || createVolumeJob.getState().equals(Constants.JOBPAUSED)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of checking for all state of job, check for not success

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems to be lost during rebase, thanks, done

Svm svm = null;
URI url = URI.create(Constants.HTTPS + storage.getManagementLIF() + Constants.GETSVMs);
OntapResponse<Svm> svms = svmFeignClient.getSvms(url, authHeader);
for (Svm storageVM : svms.getRecords()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of getting all svm and picking based on name, better to call getSVMByName. We may need to add this method in svmFeignClient

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this approach is not optimized. fetch the SVM using name as query parameter instead fetch all then find for desired name.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the necessary changes


@RequestMapping(method = RequestMethod.DELETE, value="/{uuid}")
void deleteVolume(@RequestHeader("Authorization") String authHeader, @PathVariable("uuid") String uuid);
void deleteVolume(URI baseURL, @RequestHeader("Authorization") String authHeader, @PathVariable("uuid") String uuid);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with this change, why do we need to add url parameter at class level annotation?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't pass it explicitly, we need to set a property statically in application.properties or somewhere like that, which in our case is not feasible. Also, user might ask us to deal with multiple filers, so, the IP wouldn't be static

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not seeing any significant changes here, better remove this class from the PR

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This came in as part of rebase. It just has some space changes. Sure, will try to revert it

@SuppressWarnings("unchecked")
Map<String, String> details = (Map<String, String>)dsInfos.get("details");
// Validations
if (podId != null && clusterId == null) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, in my previous review to this change i nanother PR, I gave comment to use trim command and then empty check. Please add them for each mandatory parameter

Svm svm = null;
URI url = URI.create(Constants.HTTPS + storage.getManagementLIF() + Constants.GETSVMs);
OntapResponse<Svm> svms = svmFeignClient.getSvms(url, authHeader);
for (Svm storageVM : svms.getRecords()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this approach is not optimized. fetch the SVM using name as query parameter instead fetch all then find for desired name.

ClusterVO clusterVO = _clusterDao.findById(clusterId);
Preconditions.checkNotNull(clusterVO, "Unable to locate the specified cluster");
if (clusterVO.getHypervisorType() != Hypervisor.HypervisorType.KVM) {
throw new CloudRuntimeException("ONTAP primary storage is not supported for KVM hypervisor");
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the message

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

import org.apache.cloudstack.storage.utils.Constants.ProtocolType;

public class OntapStorage {
public static String Username;
Copy link

@suryag1201 suryag1201 Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow naming convention for all fields

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why you added only inports in this class ?

public class OntapStorage {
public static String _username;
public static String _password;
public static String _managementLIF;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets use camel casing for the variable name

}
}

if (storagePoolName == null || storagePoolName.isEmpty()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty check on the sting parameters must use trim method as well

throw new CloudRuntimeException("iSCSI protocol is not enabled on SVM " + svmName);
}
List<Aggregate> aggrs = svm.getAggregates();
if (aggrs == null || aggrs.isEmpty()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One use case to validate here is that if the passed credentials belong to the cluster, then by default, all the aggregates are mapped to the underlying SVMs. However, if credentials belong to an SVM user, then aggregates must be assigned to the SVM to access them.

@suryag1201 can you help @sandeeplocharla to close on this use case implementation.

Copy link

@rajiv-jain-netapp rajiv-jain-netapp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are dependencies on these changes for other engineers, approving this PR for now. Ensure you are picking up the given comments in subsequent PR

@sandeeplocharla sandeeplocharla merged commit 25353c2 into main Oct 24, 2025
13 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants