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 .storage .command .CreateObjectCommand ;
26+ import org .apache .cloudstack .engine .subsystem .api .storage .EndPoint ;
27+ import org .apache .cloudstack .engine .subsystem .api .storage .EndPointSelector ;
2528import com .cloud .exception .InvalidParameterValueException ;
2629import com .cloud .host .Host ;
2730import com .cloud .storage .Storage ;
@@ -68,6 +71,8 @@ public class OntapPrimaryDatastoreDriver implements PrimaryDataStoreDriver {
6871 @ Inject private StoragePoolDetailsDao storagePoolDetailsDao ;
6972 @ Inject private PrimaryDataStoreDao storagePoolDao ;
7073 @ Inject private com .cloud .storage .dao .VolumeDao volumeDao ;
74+ @ Inject private EndPointSelector epSelector ;
75+
7176 @ Override
7277 public Map <String , String > getCapabilities () {
7378 s_logger .trace ("OntapPrimaryDatastoreDriver: getCapabilities: Called" );
@@ -161,12 +166,60 @@ public void createAsync(DataStore dataStore, DataObject dataObject, AsyncComplet
161166 }
162167 }
163168
169+ /**
170+ * Sends CreateObjectCommand to KVM agent to create qcow2 file using qemu-img.
171+ * The KVM agent will call:
172+ * - KVMStorageProcessor.createVolume()
173+ * - primaryPool.createPhysicalDisk()
174+ * - LibvirtStorageAdaptor.createPhysicalDiskByQemuImg()
175+ * Which executes: qemu-img create -f qcow2 /mnt/<uuid>/<volumeUuid> <size>
176+ *
177+ * @param volumeInfo Volume information with size, format, uuid
178+ * @return Answer from KVM agent indicating success/failure
179+ */
180+ private Answer createVolumeOnKVMHost (VolumeInfo volumeInfo ) {
181+ try {
182+ s_logger .info ("createVolumeOnKVMHost: Sending CreateObjectCommand to KVM agent for volume: {}" , volumeInfo .getUuid ());
183+
184+ // Create command with volume TO (Transfer Object)
185+ CreateObjectCommand cmd = new CreateObjectCommand (volumeInfo .getTO ());
186+
187+ // Select endpoint (KVM agent) to send command
188+ // epSelector will find an appropriate KVM host in the cluster/pod
189+ EndPoint ep = epSelector .select (volumeInfo );
190+
191+ if (ep == null ) {
192+ String errMsg = "No remote endpoint to send CreateObjectCommand, check if host is up" ;
193+ s_logger .error (errMsg );
194+ return new Answer (cmd , false , errMsg );
195+ }
196+
197+ s_logger .info ("createVolumeOnKVMHost: Sending command to endpoint: {}" , ep .getHostAddr ());
198+
199+ // Send command to KVM agent and wait for response
200+ Answer answer = ep .sendMessage (cmd );
201+
202+ if (answer != null && answer .getResult ()) {
203+ s_logger .info ("createVolumeOnKVMHost: Successfully created qcow2 file on KVM host" );
204+ } else {
205+ s_logger .error ("createVolumeOnKVMHost: Failed to create qcow2 file: {}" ,
206+ answer != null ? answer .getDetails () : "null answer" );
207+ }
208+
209+ return answer ;
210+
211+ } catch (Exception e ) {
212+ s_logger .error ("createVolumeOnKVMHost: Exception sending CreateObjectCommand" , e );
213+ return new Answer (null , false , e .toString ());
214+ }
215+ }
216+
164217 /**
165218 * Creates CloudStack volume based on storage protocol type (NFS or iSCSI).
166219 *
167220 * For Managed NFS (Option 2 Implementation):
168- * - Returns only UUID without creating qcow2 file
169- * - KVM hypervisor creates qcow2 file automatically during VM deployment
221+ * - Creates ONTAP volume and sets metadata in CloudStack DB
222+ * - Sends CreateObjectCommand to KVM host to create qcow2 file using qemu-img
170223 * - ONTAP volume provides the backing NFS storage
171224 *
172225 * For iSCSI/Block Storage:
@@ -184,7 +237,20 @@ private String createCloudStackVolumeForTypeVolume(DataStore dataStore, DataObje
184237 String protocol = details .get (Constants .PROTOCOL );
185238
186239 if (ProtocolType .NFS .name ().equalsIgnoreCase (protocol )) {
187- return createManagedNfsVolume (dataStore , dataObject , storagePool );
240+ // Step 1: Create ONTAP volume and set metadata
241+ String volumeUuid = createManagedNfsVolume (dataStore , dataObject , storagePool );
242+
243+ // Step 2: Send command to KVM host to create qcow2 file using qemu-img
244+ VolumeInfo volumeInfo = (VolumeInfo ) dataObject ;
245+ Answer answer = createVolumeOnKVMHost (volumeInfo );
246+
247+ if (answer == null || !answer .getResult ()) {
248+ String errMsg = answer != null ? answer .getDetails () : "Failed to create qcow2 on KVM host" ;
249+ s_logger .error ("createCloudStackVolumeForTypeVolume: " + errMsg );
250+ throw new CloudRuntimeException (errMsg );
251+ }
252+
253+ return volumeUuid ;
188254 } else if (ProtocolType .ISCSI .name ().equalsIgnoreCase (protocol )) {
189255 return createManagedBlockVolume (dataStore , dataObject , storagePool , details );
190256 } else {
0 commit comments