@@ -200,6 +200,202 @@ private void testCreateContainer() throws StorageContainerException {
200200 "DB does not exist" );
201201 }
202202
203+ @ ContainerTestVersionInfo .ContainerTest
204+ public void testCreateContainerWithStorageTypeFiltering (
205+ ContainerTestVersionInfo versionInfo ) throws Exception {
206+ init (versionInfo );
207+
208+ // Create two volumes: one SSD, one DISK
209+ File ssdDir = new File (folder , "ssd" );
210+ File diskDir = new File (folder , "disk" );
211+ assertTrue (ssdDir .mkdirs ());
212+ assertTrue (diskDir .mkdirs ());
213+
214+ HddsVolume ssdVolume = new HddsVolume .Builder (ssdDir .toString ())
215+ .conf (CONF )
216+ .datanodeUuid (datanodeId .toString ())
217+ .storageType (org .apache .hadoop .fs .StorageType .SSD )
218+ .build ();
219+ HddsVolume diskVolume = new HddsVolume .Builder (diskDir .toString ())
220+ .conf (CONF )
221+ .datanodeUuid (datanodeId .toString ())
222+ .storageType (org .apache .hadoop .fs .StorageType .DISK )
223+ .build ();
224+
225+ StorageVolumeUtil .checkVolume (ssdVolume , scmId , scmId , CONF , null , null );
226+ StorageVolumeUtil .checkVolume (diskVolume , scmId , scmId , CONF , null , null );
227+
228+ List <HddsVolume > mixedVolumes = new ArrayList <>();
229+ mixedVolumes .add (ssdVolume );
230+ mixedVolumes .add (diskVolume );
231+
232+ VolumeSet mixedVolumeSet = mock (MutableVolumeSet .class );
233+ when (mixedVolumeSet .getVolumesList ())
234+ .thenAnswer (i -> mixedVolumes .stream ()
235+ .map (v -> (StorageVolume ) v )
236+ .collect (Collectors .toList ()));
237+
238+ // volumeChoosingPolicy returns the first volume from the filtered list
239+ RoundRobinVolumeChoosingPolicy policy =
240+ mock (RoundRobinVolumeChoosingPolicy .class );
241+ when (policy .chooseVolume (anyList (), anyLong ())).thenAnswer (
242+ invocation -> {
243+ List <HddsVolume > volumes = invocation .getArgument (0 );
244+ return volumes .get (0 );
245+ });
246+
247+ // Request SSD storage type - should only see ssdVolume
248+ KeyValueContainerData ssdContainerData = new KeyValueContainerData (100L ,
249+ layout ,
250+ (long ) StorageUnit .GB .toBytes (5 ), UUID .randomUUID ().toString (),
251+ datanodeId .toString ());
252+ KeyValueContainer ssdContainer =
253+ new KeyValueContainer (ssdContainerData , CONF );
254+ ssdContainer .create (mixedVolumeSet , policy , scmId ,
255+ org .apache .hadoop .hdds .protocol .StorageType .SSD );
256+
257+ assertEquals (ssdVolume , ssdContainerData .getVolume ());
258+
259+ // Request DISK storage type - should only see diskVolume
260+ KeyValueContainerData diskContainerData = new KeyValueContainerData (101L ,
261+ layout ,
262+ (long ) StorageUnit .GB .toBytes (5 ), UUID .randomUUID ().toString (),
263+ datanodeId .toString ());
264+ KeyValueContainer diskContainer =
265+ new KeyValueContainer (diskContainerData , CONF );
266+ diskContainer .create (mixedVolumeSet , policy , scmId ,
267+ org .apache .hadoop .hdds .protocol .StorageType .DISK );
268+
269+ assertEquals (diskVolume , diskContainerData .getVolume ());
270+ }
271+
272+ @ ContainerTestVersionInfo .ContainerTest
273+ public void testCreateContainerWithStorageTypeFallback (
274+ ContainerTestVersionInfo versionInfo ) throws Exception {
275+ init (versionInfo );
276+
277+ // Create only DISK volumes - no SSD available
278+ File diskDir = new File (folder , "diskonly" );
279+ assertTrue (diskDir .mkdirs ());
280+
281+ HddsVolume diskVolume = new HddsVolume .Builder (diskDir .toString ())
282+ .conf (CONF )
283+ .datanodeUuid (datanodeId .toString ())
284+ .storageType (org .apache .hadoop .fs .StorageType .DISK )
285+ .build ();
286+ StorageVolumeUtil .checkVolume (diskVolume , scmId , scmId , CONF , null , null );
287+
288+ List <HddsVolume > diskOnlyVolumes = new ArrayList <>();
289+ diskOnlyVolumes .add (diskVolume );
290+
291+ VolumeSet diskOnlyVolumeSet = mock (MutableVolumeSet .class );
292+ when (diskOnlyVolumeSet .getVolumesList ())
293+ .thenAnswer (i -> diskOnlyVolumes .stream ()
294+ .map (v -> (StorageVolume ) v )
295+ .collect (Collectors .toList ()));
296+
297+ RoundRobinVolumeChoosingPolicy policy =
298+ mock (RoundRobinVolumeChoosingPolicy .class );
299+ when (policy .chooseVolume (anyList (), anyLong ())).thenAnswer (
300+ invocation -> {
301+ List <HddsVolume > volumes = invocation .getArgument (0 );
302+ return volumes .get (0 );
303+ });
304+
305+ // Request SSD but only DISK is available - should fall back to DISK
306+ KeyValueContainerData fallbackData = new KeyValueContainerData (102L ,
307+ layout ,
308+ (long ) StorageUnit .GB .toBytes (5 ), UUID .randomUUID ().toString (),
309+ datanodeId .toString ());
310+ KeyValueContainer fallbackContainer =
311+ new KeyValueContainer (fallbackData , CONF );
312+ fallbackContainer .create (diskOnlyVolumeSet , policy , scmId ,
313+ org .apache .hadoop .hdds .protocol .StorageType .SSD );
314+
315+ // Should succeed and use the DISK volume as fallback
316+ assertEquals (diskVolume , fallbackData .getVolume ());
317+ }
318+
319+ @ ContainerTestVersionInfo .ContainerTest
320+ public void testCreateContainerWithNullStorageType (
321+ ContainerTestVersionInfo versionInfo ) throws Exception {
322+ init (versionInfo );
323+ // Null storageType should behave identically to the original create()
324+ keyValueContainer .create (volumeSet , volumeChoosingPolicy , scmId , null );
325+ keyValueContainerData = keyValueContainer .getContainerData ();
326+
327+ assertNotNull (keyValueContainerData .getMetadataPath ());
328+ assertNotNull (keyValueContainerData .getChunksPath ());
329+ assertTrue (keyValueContainer .getContainerFile ().exists ());
330+ assertTrue (keyValueContainer .getContainerDBFile ().exists ());
331+ }
332+
333+ @ ContainerTestVersionInfo .ContainerTest
334+ public void testCreateContainerFilteringPassesOnlyMatchingVolumes (
335+ ContainerTestVersionInfo versionInfo ) throws Exception {
336+ init (versionInfo );
337+
338+ // Create 2 SSD + 1 DISK volumes
339+ File ssd1Dir = new File (folder , "ssd1" );
340+ File ssd2Dir = new File (folder , "ssd2" );
341+ File diskDir = new File (folder , "disk2" );
342+ assertTrue (ssd1Dir .mkdirs ());
343+ assertTrue (ssd2Dir .mkdirs ());
344+ assertTrue (diskDir .mkdirs ());
345+
346+ HddsVolume ssd1 = new HddsVolume .Builder (ssd1Dir .toString ())
347+ .conf (CONF ).datanodeUuid (datanodeId .toString ())
348+ .storageType (org .apache .hadoop .fs .StorageType .SSD ).build ();
349+ HddsVolume ssd2 = new HddsVolume .Builder (ssd2Dir .toString ())
350+ .conf (CONF ).datanodeUuid (datanodeId .toString ())
351+ .storageType (org .apache .hadoop .fs .StorageType .SSD ).build ();
352+ HddsVolume disk = new HddsVolume .Builder (diskDir .toString ())
353+ .conf (CONF ).datanodeUuid (datanodeId .toString ())
354+ .storageType (org .apache .hadoop .fs .StorageType .DISK ).build ();
355+
356+ StorageVolumeUtil .checkVolume (ssd1 , scmId , scmId , CONF , null , null );
357+ StorageVolumeUtil .checkVolume (ssd2 , scmId , scmId , CONF , null , null );
358+ StorageVolumeUtil .checkVolume (disk , scmId , scmId , CONF , null , null );
359+
360+ List <HddsVolume > allVolumes = new ArrayList <>();
361+ allVolumes .add (ssd1 );
362+ allVolumes .add (ssd2 );
363+ allVolumes .add (disk );
364+
365+ VolumeSet vs = mock (MutableVolumeSet .class );
366+ when (vs .getVolumesList ())
367+ .thenAnswer (i -> allVolumes .stream ()
368+ .map (v -> (StorageVolume ) v )
369+ .collect (Collectors .toList ()));
370+
371+ // Capture which volumes the policy actually sees
372+ List <List <HddsVolume >> capturedVolumeLists = new ArrayList <>();
373+ RoundRobinVolumeChoosingPolicy policy =
374+ mock (RoundRobinVolumeChoosingPolicy .class );
375+ when (policy .chooseVolume (anyList (), anyLong ())).thenAnswer (
376+ invocation -> {
377+ List <HddsVolume > volumes = invocation .getArgument (0 );
378+ capturedVolumeLists .add (new ArrayList <>(volumes ));
379+ return volumes .get (0 );
380+ });
381+
382+ KeyValueContainerData data = new KeyValueContainerData (200L ,
383+ layout ,
384+ (long ) StorageUnit .GB .toBytes (5 ), UUID .randomUUID ().toString (),
385+ datanodeId .toString ());
386+ KeyValueContainer container = new KeyValueContainer (data , CONF );
387+ container .create (vs , policy , scmId ,
388+ org .apache .hadoop .hdds .protocol .StorageType .SSD );
389+
390+ // Policy should have received only the 2 SSD volumes, not the DISK one
391+ assertEquals (1 , capturedVolumeLists .size ());
392+ List <HddsVolume > receivedVolumes = capturedVolumeLists .get (0 );
393+ assertEquals (2 , receivedVolumes .size ());
394+ assertTrue (receivedVolumes .contains (ssd1 ));
395+ assertTrue (receivedVolumes .contains (ssd2 ));
396+ assertFalse (receivedVolumes .contains (disk ));
397+ }
398+
203399 /**
204400 * Tests repair of containers affected by the bug reported in HDDS-6235.
205401 */
0 commit comments