2222import com .cloud .agent .api .to .DataObjectType ;
2323import com .cloud .agent .api .to .DataStoreTO ;
2424import com .cloud .agent .api .to .DataTO ;
25+ import org .apache .cloudstack .engine .subsystem .api .storage .EndPoint ;
2526import org .apache .cloudstack .engine .subsystem .api .storage .EndPointSelector ;
2627import com .cloud .exception .InvalidParameterValueException ;
2728import com .cloud .host .Host ;
4344import org .apache .cloudstack .engine .subsystem .api .storage .VolumeInfo ;
4445import org .apache .cloudstack .framework .async .AsyncCompletionCallback ;
4546import org .apache .cloudstack .storage .command .CommandResult ;
47+ import org .apache .cloudstack .storage .command .CreateObjectCommand ;
4648import org .apache .cloudstack .storage .datastore .db .PrimaryDataStoreDao ;
4749import org .apache .cloudstack .storage .datastore .db .StoragePoolDetailsDao ;
4850import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
@@ -138,42 +140,34 @@ public void createAsync(DataStore dataStore, DataObject dataObject, AsyncComplet
138140 * @param volumeInfo Volume information with size, format, uuid
139141 * @return Answer from KVM agent indicating success/failure
140142 */
141- // private Answer createVolumeOnKVMHost(VolumeInfo volumeInfo) {
142- // try {
143- // s_logger.info("createVolumeOnKVMHost: Sending CreateObjectCommand to KVM agent for volume: {}", volumeInfo.getUuid());
144- //
145- // // Create command with volume TO (Transfer Object)
146- // CreateObjectCommand cmd = new CreateObjectCommand(volumeInfo.getTO());
147- //
148- // // Select endpoint (KVM agent) to send command
149- // // epSelector will find an appropriate KVM host in the cluster/pod
150- // EndPoint ep = epSelector.select(volumeInfo);
151- //
152- // if (ep == null) {
153- // String errMsg = "No remote endpoint to send CreateObjectCommand, check if host is up";
154- // s_logger.error(errMsg);
155- // return new Answer(cmd, false, errMsg);
156- // }
157- //
158- // s_logger.info("createVolumeOnKVMHost: Sending command to endpoint: {}", ep.getHostAddr());
159- //
160- // // Send command to KVM agent and wait for response
161- // Answer answer = ep.sendMessage(cmd);
162- //
163- // if (answer != null && answer.getResult()) {
164- // s_logger.info("createVolumeOnKVMHost: Successfully created qcow2 file on KVM host");
165- // } else {
166- // s_logger.error("createVolumeOnKVMHost: Failed to create qcow2 file: {}",
167- // answer != null ? answer.getDetails() : "null answer");
168- // }
169- //
170- // return answer;
171- //
172- // } catch (Exception e) {
173- // s_logger.error("createVolumeOnKVMHost: Exception sending CreateObjectCommand", e);
174- // return new Answer(null, false, e.toString());
175- // }
176- // }
143+ private Answer createVolumeOnKVMHost (VolumeInfo volumeInfo ) {
144+ try {
145+ s_logger .info ("createVolumeOnKVMHost: Sending CreateObjectCommand to KVM agent for volume: {}" , volumeInfo .getUuid ());
146+ // Create command with volume TO (Transfer Object)
147+ CreateObjectCommand cmd = new CreateObjectCommand (volumeInfo .getTO ());
148+ // Select endpoint (KVM agent) to send command
149+ // epSelector will find an appropriate KVM host in the cluster/pod
150+ EndPoint ep = epSelector .select (volumeInfo );
151+ if (ep == null ) {
152+ String errMsg = "No remote endpoint to send CreateObjectCommand, check if host is up" ;
153+ s_logger .error (errMsg );
154+ return new Answer (cmd , false , errMsg );
155+ }
156+ s_logger .info ("createVolumeOnKVMHost: Sending command to endpoint: {}" , ep .getHostAddr ());
157+ // Send command to KVM agent and wait for response
158+ Answer answer = ep .sendMessage (cmd );
159+ if (answer != null && answer .getResult ()) {
160+ s_logger .info ("createVolumeOnKVMHost: Successfully created qcow2 file on KVM host" );
161+ } else {
162+ s_logger .error ("createVolumeOnKVMHost: Failed to create qcow2 file: {}" ,
163+ answer != null ? answer .getDetails () : "null answer" );
164+ }
165+ return answer ;
166+ } catch (Exception e ) {
167+ s_logger .error ("createVolumeOnKVMHost: Exception sending CreateObjectCommand" , e );
168+ return new Answer (null , false , e .toString ());
169+ }
170+ }
177171
178172 /**
179173 * Creates CloudStack volume based on storage protocol type (NFS or iSCSI).
@@ -201,17 +195,7 @@ private String createCloudStackVolumeForTypeVolume(DataStore dataStore, DataObje
201195 // Step 1: Create ONTAP volume and set metadata
202196 String volumeUuid = createManagedNfsVolume (dataStore , dataObject , storagePool );
203197
204- // Step 2: Send command to KVM host to create qcow2 file using qemu-img
205- // VolumeInfo volumeInfo = (VolumeInfo) dataObject;
206- // Answer answer = createVolumeOnKVMHost(volumeInfo);
207-
208- // if (answer == null || !answer.getResult()) {
209- // String errMsg = answer != null ? answer.getDetails() : "Failed to create qcow2 on KVM host";
210- // s_logger.error("createCloudStackVolumeForTypeVolume: " + errMsg);
211- // throw new CloudRuntimeException(errMsg);
212- // }
213-
214- // create export olicy and attach it to new volume created
198+ // Step 2: Create export policy and attach it to new volume (MUST be before KVM mount)
215199 VolumeInfo volumeInfo = (VolumeInfo ) dataObject ;
216200 Map <String , String > volumeDetails = new HashMap <>();
217201 volumeDetails .put (Constants .VOLUME_UUID , volumeInfo .getUuid ());
@@ -223,6 +207,13 @@ private String createCloudStackVolumeForTypeVolume(DataStore dataStore, DataObje
223207 accessGroup .setVolumedetails (volumeDetails );
224208 storageStrategy .createAccessGroup (accessGroup );
225209
210+ // Step 3: Send command to KVM host to create qcow2 file using qemu-img
211+ Answer answer = createVolumeOnKVMHost (volumeInfo );
212+ if (answer == null || !answer .getResult ()) {
213+ String errMsg = answer != null ? answer .getDetails () : "Failed to create qcow2 on KVM host" ;
214+ s_logger .error ("createCloudStackVolumeForTypeVolume: " + errMsg );
215+ throw new CloudRuntimeException (errMsg );
216+ }
226217 // create export policy
227218// VolumeInfo volumeInfo = (VolumeInfo) dataObject;
228219// String svmName = details.get(Constants.SVM_NAME);
0 commit comments