Repository: hadoop Updated Branches: refs/heads/trunk 5304698dc -> 7225ec0ce
http://git-wip-us.apache.org/repos/asf/hadoop/blob/7225ec0c/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/fpga/TestFpgaResourceHandler.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/fpga/TestFpgaResourceHandler.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/fpga/TestFpgaResourceHandler.java new file mode 100644 index 0000000..d3d55fa --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/fpga/TestFpgaResourceHandler.java @@ -0,0 +1,458 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.fpga; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.util.StringUtils; +import org.apache.hadoop.yarn.api.records.*; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.server.nodemanager.Context; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.ResourceMappings; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationException; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationExecutor; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.CGroupsHandler; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.ResourceHandlerException; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.ResourceSet; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.resourceplugin.fpga.FpgaDiscoverer; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.resourceplugin.fpga.IntelFpgaOpenclPlugin; +import org.apache.hadoop.yarn.server.nodemanager.recovery.NMStateStoreService; +import org.apache.hadoop.yarn.util.resource.TestResourceUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +import static org.mockito.Mockito.*; + + +public class TestFpgaResourceHandler { + private Context mockContext; + private FpgaResourceHandlerImpl fpgaResourceHandler; + private Configuration configuration; + private CGroupsHandler mockCGroupsHandler; + private PrivilegedOperationExecutor mockPrivilegedExecutor; + private NMStateStoreService mockNMStateStore; + private ConcurrentHashMap<ContainerId, Container> runningContainersMap; + private IntelFpgaOpenclPlugin mockVendorPlugin; + private static final String vendorType = "IntelOpenCL"; + + @Before + public void setup() { + TestResourceUtils.addNewTypesToResources(ResourceInformation.FPGA_URI); + configuration = new YarnConfiguration(); + + mockCGroupsHandler = mock(CGroupsHandler.class); + mockPrivilegedExecutor = mock(PrivilegedOperationExecutor.class); + mockNMStateStore = mock(NMStateStoreService.class); + mockContext = mock(Context.class); + // Assumed devices parsed from output + List<FpgaResourceAllocator.FpgaDevice> list = new ArrayList<>(); + list.add(new FpgaResourceAllocator.FpgaDevice(vendorType, 247, 0, null)); + list.add(new FpgaResourceAllocator.FpgaDevice(vendorType, 247, 1, null)); + list.add(new FpgaResourceAllocator.FpgaDevice(vendorType, 247, 2, null)); + list.add(new FpgaResourceAllocator.FpgaDevice(vendorType, 247, 3, null)); + list.add(new FpgaResourceAllocator.FpgaDevice(vendorType, 247, 4, null)); + mockVendorPlugin = mockPlugin(vendorType, list); + FpgaDiscoverer.getInstance().setConf(configuration); + when(mockContext.getNMStateStore()).thenReturn(mockNMStateStore); + runningContainersMap = new ConcurrentHashMap<>(); + when(mockContext.getContainers()).thenReturn(runningContainersMap); + + fpgaResourceHandler = new FpgaResourceHandlerImpl(mockContext, + mockCGroupsHandler, mockPrivilegedExecutor, mockVendorPlugin); + } + + @Test + public void testBootstrap() throws ResourceHandlerException { + // Case 1. auto + String allowed = "auto"; + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, allowed); + fpgaResourceHandler.bootstrap(configuration); + verify(mockVendorPlugin, times(1)).initPlugin(configuration); + verify(mockCGroupsHandler, times(1)).initializeCGroupController( + CGroupsHandler.CGroupController.DEVICES); + Assert.assertEquals(5, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + Assert.assertEquals(5, fpgaResourceHandler.getFpgaAllocator().getAllowedFpga().size()); + // Case 2. subset of devices + fpgaResourceHandler = new FpgaResourceHandlerImpl(mockContext, + mockCGroupsHandler, mockPrivilegedExecutor, mockVendorPlugin); + allowed = "0,1,2"; + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, allowed); + fpgaResourceHandler.bootstrap(configuration); + Assert.assertEquals(3, fpgaResourceHandler.getFpgaAllocator().getAllowedFpga().size()); + List<FpgaResourceAllocator.FpgaDevice> allowedDevices = fpgaResourceHandler.getFpgaAllocator().getAllowedFpga(); + for (String s : allowed.split(",")) { + boolean check = false; + for (FpgaResourceAllocator.FpgaDevice device : allowedDevices) { + if (device.getMinor().toString().equals(s)) { + check = true; + } + } + Assert.assertTrue("Minor:" + s +"found", check); + } + Assert.assertEquals(3, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + + // Case 3. User configuration contains invalid minor device number + fpgaResourceHandler = new FpgaResourceHandlerImpl(mockContext, + mockCGroupsHandler, mockPrivilegedExecutor, mockVendorPlugin); + allowed = "0,1,7"; + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, allowed); + fpgaResourceHandler.bootstrap(configuration); + Assert.assertEquals(2, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + Assert.assertEquals(2, fpgaResourceHandler.getFpgaAllocator().getAllowedFpga().size()); + } + + @Test + public void testBootstrapWithInvalidUserConfiguration() throws ResourceHandlerException { + // User configuration contains invalid minor device number + String allowed = "0,1,7"; + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, allowed); + fpgaResourceHandler.bootstrap(configuration); + Assert.assertEquals(2, fpgaResourceHandler.getFpgaAllocator().getAllowedFpga().size()); + Assert.assertEquals(2, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + + String[] invalidAllowedStrings = {"a,1,2,", "a,1,2", "0,1,2,#", "a", "1,"}; + for (String s : invalidAllowedStrings) { + boolean invalidConfiguration = false; + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, s); + try { + fpgaResourceHandler.bootstrap(configuration); + } catch (ResourceHandlerException e) { + invalidConfiguration = true; + } + Assert.assertTrue(invalidConfiguration); + } + + String[] allowedStrings = {"1,2", "1"}; + for (String s : allowedStrings) { + boolean invalidConfiguration = false; + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, s); + try { + fpgaResourceHandler.bootstrap(configuration); + } catch (ResourceHandlerException e) { + invalidConfiguration = true; + } + Assert.assertFalse(invalidConfiguration); + } + } + + @Test + public void testBootStrapWithEmptyUserConfiguration() throws ResourceHandlerException { + // User configuration contains invalid minor device number + String allowed = ""; + boolean invalidConfiguration = false; + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, allowed); + try { + fpgaResourceHandler.bootstrap(configuration); + } catch (ResourceHandlerException e) { + invalidConfiguration = true; + } + Assert.assertTrue(invalidConfiguration); + } + + @Test + public void testAllocationWithPreference() throws ResourceHandlerException, PrivilegedOperationException { + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, "0,1,2"); + fpgaResourceHandler.bootstrap(configuration); + // Case 1. The id-0 container request 1 FPGA of IntelOpenCL type and GEMM IP + fpgaResourceHandler.preStart(mockContainer(0, 1, "GEMM")); + Assert.assertEquals(1, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + verifyDeniedDevices(getContainerId(0), Arrays.asList(1, 2)); + List<FpgaResourceAllocator.FpgaDevice> list = fpgaResourceHandler.getFpgaAllocator() + .getUsedFpga().get(getContainerId(0).toString()); + for (FpgaResourceAllocator.FpgaDevice device : list) { + Assert.assertEquals("IP should be updated to GEMM", "GEMM", device.getIPID()); + } + // Case 2. The id-1 container request 3 FPGA of IntelOpenCL and GEMM IP. this should fail + boolean flag = false; + try { + fpgaResourceHandler.preStart(mockContainer(1, 3, "GZIP")); + } catch (ResourceHandlerException e) { + flag = true; + } + Assert.assertTrue(flag); + // Case 3. Release the id-0 container + fpgaResourceHandler.postComplete(getContainerId(0)); + Assert.assertEquals(0, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + Assert.assertEquals(3, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + // Now we have enough devices, re-allocate for the id-1 container + fpgaResourceHandler.preStart(mockContainer(1, 3, "GEMM")); + // Id-1 container should have 0 denied devices + verifyDeniedDevices(getContainerId(1), new ArrayList<>()); + Assert.assertEquals(3, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + Assert.assertEquals(0, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + // Release container id-1 + fpgaResourceHandler.postComplete(getContainerId(1)); + Assert.assertEquals(0, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + Assert.assertEquals(3, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + // Case 4. Now all 3 devices should have IPID GEMM + // Try container id-2 and id-3 + fpgaResourceHandler.preStart(mockContainer(2, 1, "GZIP")); + fpgaResourceHandler.postComplete(getContainerId(2)); + fpgaResourceHandler.preStart(mockContainer(3, 2, "GEMM")); + + // IPID should be GEMM for id-3 container + list = fpgaResourceHandler.getFpgaAllocator() + .getUsedFpga().get(getContainerId(3).toString()); + for (FpgaResourceAllocator.FpgaDevice device : list) { + Assert.assertEquals("IPID should be GEMM", "GEMM", device.getIPID()); + } + Assert.assertEquals(2, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + Assert.assertEquals(1, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + fpgaResourceHandler.postComplete(getContainerId(3)); + Assert.assertEquals(0, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + Assert.assertEquals(3, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + + // Case 5. id-4 request 0 FPGA device + fpgaResourceHandler.preStart(mockContainer(4, 0, "")); + // Deny all devices for id-4 + verifyDeniedDevices(getContainerId(4), Arrays.asList(0, 1, 2)); + Assert.assertEquals(0, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + Assert.assertEquals(3, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + + // Case 6. id-5 with invalid FPGA device + try { + fpgaResourceHandler.preStart(mockContainer(5, -2, "")); + } catch (ResourceHandlerException e) { + Assert.assertTrue(true); + } + } + + @Test + public void testsAllocationWithExistingIPIDDevices() throws ResourceHandlerException, PrivilegedOperationException { + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, "0,1,2"); + fpgaResourceHandler.bootstrap(configuration); + // The id-0 container request 3 FPGA of IntelOpenCL type and GEMM IP + fpgaResourceHandler.preStart(mockContainer(0, 3, "GEMM")); + Assert.assertEquals(3, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + List<FpgaResourceAllocator.FpgaDevice> list = fpgaResourceHandler.getFpgaAllocator() + .getUsedFpga().get(getContainerId(0).toString()); + fpgaResourceHandler.postComplete(getContainerId(0)); + for (FpgaResourceAllocator.FpgaDevice device : list) { + Assert.assertEquals("IP should be updated to GEMM", "GEMM", device.getIPID()); + } + + // Case 1. id-1 container request preStart, with no plugin.configureIP called + fpgaResourceHandler.preStart(mockContainer(1, 1, "GEMM")); + fpgaResourceHandler.preStart(mockContainer(2, 1, "GEMM")); + // we should have 3 times due to id-1 skip 1 invocation + verify(mockVendorPlugin, times(3)).configureIP(anyString(),anyString()); + fpgaResourceHandler.postComplete(getContainerId(1)); + fpgaResourceHandler.postComplete(getContainerId(2)); + + // Case 2. id-2 container request preStart, with 1 plugin.configureIP called + fpgaResourceHandler.preStart(mockContainer(1, 1, "GZIP")); + // we should have 4 times invocation + verify(mockVendorPlugin, times(4)).configureIP(anyString(),anyString()); + } + + @Test + public void testAllocationWithZeroDevices() throws ResourceHandlerException, PrivilegedOperationException { + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, "0,1,2"); + fpgaResourceHandler.bootstrap(configuration); + // The id-0 container request 0 FPGA + fpgaResourceHandler.preStart(mockContainer(0, 0, null)); + verifyDeniedDevices(getContainerId(0), Arrays.asList(0, 1, 2)); + verify(mockVendorPlugin, times(0)).downloadIP(anyString(), anyString(), anyMap()); + verify(mockVendorPlugin, times(0)).configureIP(anyString(), anyString()); + } + + @Test + public void testStateStore() throws ResourceHandlerException, IOException { + // Case 1. store 3 devices + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, "0,1,2"); + fpgaResourceHandler.bootstrap(configuration); + Container container0 = mockContainer(0, 3, "GEMM"); + fpgaResourceHandler.preStart(container0); + List<FpgaResourceAllocator.FpgaDevice> assigned = + fpgaResourceHandler.getFpgaAllocator().getUsedFpga().get(getContainerId(0).toString()); + verify(mockNMStateStore).storeAssignedResources(container0, + ResourceInformation.FPGA_URI, + new ArrayList<>(assigned)); + fpgaResourceHandler.postComplete(getContainerId(0)); + // Case 2. ask 0, no store api called + Container container1 = mockContainer(1, 0, ""); + fpgaResourceHandler.preStart(container1); + verify(mockNMStateStore, never()).storeAssignedResources( + eq(container1), eq(ResourceInformation.FPGA_URI), anyList()); + } + + @Test + public void testReacquireContainer() throws ResourceHandlerException { + + Container c0 = mockContainer(0, 2, "GEMM"); + List<FpgaResourceAllocator.FpgaDevice> assigned = new ArrayList<>(); + assigned.add(new FpgaResourceAllocator.FpgaDevice(vendorType, 247, 0, null)); + assigned.add(new FpgaResourceAllocator.FpgaDevice(vendorType, 247, 1, null)); + // Mock we've stored the c0 states + mockStateStoreForContainer(c0, assigned); + // NM start + configuration.set(YarnConfiguration.NM_FPGA_ALLOWED_DEVICES, "0,1,2"); + fpgaResourceHandler.bootstrap(configuration); + Assert.assertEquals(0, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + Assert.assertEquals(3, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + // Case 1. try recover state for id-0 container + fpgaResourceHandler.reacquireContainer(getContainerId(0)); + // minor number matches + List<FpgaResourceAllocator.FpgaDevice> used = fpgaResourceHandler.getFpgaAllocator(). + getUsedFpga().get(getContainerId(0).toString()); + int count = 0; + for (FpgaResourceAllocator.FpgaDevice device : used) { + if (device.getMinor().equals(0)){ + count++; + } + if (device.getMinor().equals(1)) { + count++; + } + } + Assert.assertEquals("Unexpected used minor number in allocator",2, count); + List<FpgaResourceAllocator.FpgaDevice> available = fpgaResourceHandler.getFpgaAllocator(). + getAvailableFpga().get(vendorType); + count = 0; + for (FpgaResourceAllocator.FpgaDevice device : available) { + if (device.getMinor().equals(2)) { + count++; + } + } + Assert.assertEquals("Unexpected available minor number in allocator", 1, count); + + + // Case 2. Recover a not allowed device with minor number 5 + Container c1 = mockContainer(1, 1, "GEMM"); + assigned = new ArrayList<>(); + assigned.add(new FpgaResourceAllocator.FpgaDevice(vendorType, 247, 5, null)); + // Mock we've stored the c1 states + mockStateStoreForContainer(c1, assigned); + boolean flag = false; + try { + fpgaResourceHandler.reacquireContainer(getContainerId(1)); + } catch (ResourceHandlerException e) { + flag = true; + } + Assert.assertTrue(flag); + Assert.assertEquals(2, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + Assert.assertEquals(1, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + + // Case 3. recover a already used device by other container + Container c2 = mockContainer(2, 1, "GEMM"); + assigned = new ArrayList<>(); + assigned.add(new FpgaResourceAllocator.FpgaDevice(vendorType, 247, 1, null)); + // Mock we've stored the c2 states + mockStateStoreForContainer(c2, assigned); + flag = false; + try { + fpgaResourceHandler.reacquireContainer(getContainerId(2)); + } catch (ResourceHandlerException e) { + flag = true; + } + Assert.assertTrue(flag); + Assert.assertEquals(2, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + Assert.assertEquals(1, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + + // Case 4. recover a normal container c3 with remaining minor device number 2 + Container c3 = mockContainer(3, 1, "GEMM"); + assigned = new ArrayList<>(); + assigned.add(new FpgaResourceAllocator.FpgaDevice(vendorType, 247, 2, null)); + // Mock we've stored the c2 states + mockStateStoreForContainer(c3, assigned); + fpgaResourceHandler.reacquireContainer(getContainerId(3)); + Assert.assertEquals(3, fpgaResourceHandler.getFpgaAllocator().getUsedFpgaCount()); + Assert.assertEquals(0, fpgaResourceHandler.getFpgaAllocator().getAvailableFpgaCount()); + } + + private void verifyDeniedDevices(ContainerId containerId, + List<Integer> deniedDevices) + throws ResourceHandlerException, PrivilegedOperationException { + verify(mockCGroupsHandler, atLeastOnce()).createCGroup( + CGroupsHandler.CGroupController.DEVICES, containerId.toString()); + + if (null != deniedDevices && !deniedDevices.isEmpty()) { + verify(mockPrivilegedExecutor, times(1)).executePrivilegedOperation( + new PrivilegedOperation(PrivilegedOperation.OperationType.FPGA, Arrays + .asList(FpgaResourceHandlerImpl.CONTAINER_ID_CLI_OPTION, + containerId.toString(), + FpgaResourceHandlerImpl.EXCLUDED_FPGAS_CLI_OPTION, + StringUtils.join(",", deniedDevices))), true); + } else if (deniedDevices.isEmpty()) { + verify(mockPrivilegedExecutor, times(1)).executePrivilegedOperation( + new PrivilegedOperation(PrivilegedOperation.OperationType.FPGA, Arrays + .asList(FpgaResourceHandlerImpl.CONTAINER_ID_CLI_OPTION, + containerId.toString())), true); + } + } + + private static IntelFpgaOpenclPlugin mockPlugin(String type, List<FpgaResourceAllocator.FpgaDevice> list) { + IntelFpgaOpenclPlugin plugin = mock(IntelFpgaOpenclPlugin.class); + when(plugin.initPlugin(Mockito.anyObject())).thenReturn(true); + when(plugin.getFpgaType()).thenReturn(type); + when(plugin.downloadIP(Mockito.anyString(), Mockito.anyString(), Mockito.anyMap())).thenReturn("/tmp"); + when(plugin.configureIP(Mockito.anyString(), Mockito.anyObject())).thenReturn(true); + when(plugin.discover(Mockito.anyInt())).thenReturn(list); + return plugin; + } + + + private static Container mockContainer(int id, int numFpga, String IPID) { + Container c = mock(Container.class); + + Resource res = Resource.newInstance(1024, 1); + ResourceMappings resMapping = new ResourceMappings(); + res.setResourceValue(ResourceInformation.FPGA_URI, numFpga); + when(c.getResource()).thenReturn(res); + when(c.getResourceMappings()).thenReturn(resMapping); + + when(c.getContainerId()).thenReturn(getContainerId(id)); + + ContainerLaunchContext clc = mock(ContainerLaunchContext.class); + Map<String, String> envs = new HashMap<>(); + if (numFpga > 0) { + envs.put("REQUESTED_FPGA_IP_ID", IPID); + } + when(c.getLaunchContext()).thenReturn(clc); + when(clc.getEnvironment()).thenReturn(envs); + when(c.getWorkDir()).thenReturn("/tmp"); + ResourceSet resourceSet = new ResourceSet(); + when(c.getResourceSet()).thenReturn(resourceSet); + + return c; + } + + private void mockStateStoreForContainer(Container container, + List<FpgaResourceAllocator.FpgaDevice> assigned) { + ResourceMappings rmap = new ResourceMappings(); + ResourceMappings.AssignedResources ar = + new ResourceMappings.AssignedResources(); + ar.updateAssignedResources(new ArrayList<>(assigned)); + rmap.addAssignedResources(ResourceInformation.FPGA_URI, ar); + when(container.getResourceMappings()).thenReturn(rmap); + runningContainersMap.put(container.getContainerId(), container); + } + + private static ContainerId getContainerId(int id) { + return ContainerId.newContainerId(ApplicationAttemptId + .newInstance(ApplicationId.newInstance(1234L, 1), 1), id); + } +} http://git-wip-us.apache.org/repos/asf/hadoop/blob/7225ec0c/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/resourceplugin/fpga/TestFpgaDiscoverer.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/resourceplugin/fpga/TestFpgaDiscoverer.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/resourceplugin/fpga/TestFpgaDiscoverer.java new file mode 100644 index 0000000..87fb4e9 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/resourceplugin/fpga/TestFpgaDiscoverer.java @@ -0,0 +1,187 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.hadoop.yarn.server.nodemanager.containermanager.resourceplugin.fpga; + + +import org.apache.commons.io.FileUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.exceptions.YarnException; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.fpga.FpgaResourceAllocator; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class TestFpgaDiscoverer { + + private String getTestParentFolder() { + File f = new File("target/temp/" + TestFpgaDiscoverer.class.getName()); + return f.getAbsolutePath(); + } + + private void touchFile(File f) throws IOException { + new FileOutputStream(f).close(); + } + + @Before + public void before() throws IOException { + String folder = getTestParentFolder(); + File f = new File(folder); + FileUtils.deleteDirectory(f); + f.mkdirs(); + } + + @Test + public void testLinuxFpgaResourceDiscoverPluginConfig() throws YarnException, IOException { + Configuration conf = new Configuration(false); + FpgaDiscoverer discoverer = FpgaDiscoverer.getInstance(); + + IntelFpgaOpenclPlugin openclPlugin = new IntelFpgaOpenclPlugin(); + // because FPGA discoverer is a singleton, we use setPlugin to make + // FpgaDiscoverer.getInstance().diagnose() work in openclPlugin.initPlugin() + discoverer.setResourceHanderPlugin(openclPlugin); + openclPlugin.initPlugin(conf); + openclPlugin.setShell(mockPuginShell()); + + discoverer.initialize(conf); + // Case 1. No configuration set for binary + Assert.assertEquals("No configuration should return just a single binary name", + "aocl", openclPlugin.getPathToExecutable()); + + // Case 2. With correct configuration and file exists + File fakeBinary = new File(getTestParentFolder() + "/aocl"); + conf.set(YarnConfiguration.NM_FPGA_PATH_TO_EXEC, getTestParentFolder() + "/aocl"); + touchFile(fakeBinary); + discoverer.initialize(conf); + Assert.assertEquals("Correct configuration should return user setting", + getTestParentFolder() + "/aocl", openclPlugin.getPathToExecutable()); + + // Case 3. With correct configuration but file doesn't exists. Use default + fakeBinary.delete(); + discoverer.initialize(conf); + Assert.assertEquals("Correct configuration but file doesn't exists should return just a single binary name", + "aocl", openclPlugin.getPathToExecutable()); + + } + + @Test + public void testDiscoverPluginParser() throws YarnException { + String output = "------------------------- acl0 -------------------------\n" + + "Vendor: Nallatech ltd\n" + + "Phys Dev Name Status Information\n" + + "aclnalla_pcie0Passed nalla_pcie (aclnalla_pcie0)\n" + + " PCIe dev_id = 2494, bus:slot.func = 02:00.00, Gen3 x8\n" + + " FPGA temperature = 53.1 degrees C.\n" + + " Total Card Power Usage = 31.7 Watts.\n" + + " Device Power Usage = 0.0 Watts.\n" + + "DIAGNOSTIC_PASSED" + + "---------------------------------------------------------\n"; + output = output + + "------------------------- acl1 -------------------------\n" + + "Vendor: Nallatech ltd\n" + + "Phys Dev Name Status Information\n" + + "aclnalla_pcie1Passed nalla_pcie (aclnalla_pcie1)\n" + + " PCIe dev_id = 2495, bus:slot.func = 03:00.00, Gen3 x8\n" + + " FPGA temperature = 43.1 degrees C.\n" + + " Total Card Power Usage = 11.7 Watts.\n" + + " Device Power Usage = 0.0 Watts.\n" + + "DIAGNOSTIC_PASSED" + + "---------------------------------------------------------\n"; + output = output + + "------------------------- acl2 -------------------------\n" + + "Vendor: Intel(R) Corporation\n" + + "\n" + + "Phys Dev Name Status Information\n" + + "\n" + + "acla10_ref0 Passed Arria 10 Reference Platform (acla10_ref0)\n" + + " PCIe dev_id = 2494, bus:slot.func = 09:00.00, Gen2 x8\n" + + " FPGA temperature = 50.5781 degrees C.\n" + + "\n" + + "DIAGNOSTIC_PASSED\n" + + "---------------------------------------------------------\n"; + Configuration conf = new Configuration(false); + IntelFpgaOpenclPlugin openclPlugin = new IntelFpgaOpenclPlugin(); + FpgaDiscoverer.getInstance().setResourceHanderPlugin(openclPlugin); + + openclPlugin.initPlugin(conf); + openclPlugin.setShell(mockPuginShell()); + + FpgaDiscoverer.getInstance().initialize(conf); + + List<FpgaResourceAllocator.FpgaDevice> list = new LinkedList<>(); + + // Case 1. core parsing + openclPlugin.parseDiagnoseInfo(output, list); + Assert.assertEquals(3, list.size()); + Assert.assertEquals("IntelOpenCL", list.get(0).getType()); + Assert.assertEquals("247", list.get(0).getMajor().toString()); + Assert.assertEquals("0", list.get(0).getMinor().toString()); + Assert.assertEquals("acl0", list.get(0).getAliasDevName()); + Assert.assertEquals("aclnalla_pcie0", list.get(0).getDevName()); + Assert.assertEquals("02:00.00", list.get(0).getBusNum()); + Assert.assertEquals("53.1 degrees C", list.get(0).getTemperature()); + Assert.assertEquals("31.7 Watts", list.get(0).getCardPowerUsage()); + + Assert.assertEquals("IntelOpenCL", list.get(1).getType()); + Assert.assertEquals("247", list.get(1).getMajor().toString()); + Assert.assertEquals("1", list.get(1).getMinor().toString()); + Assert.assertEquals("acl1", list.get(1).getAliasDevName()); + Assert.assertEquals("aclnalla_pcie1", list.get(1).getDevName()); + Assert.assertEquals("03:00.00", list.get(1).getBusNum()); + Assert.assertEquals("43.1 degrees C", list.get(1).getTemperature()); + Assert.assertEquals("11.7 Watts", list.get(1).getCardPowerUsage()); + + Assert.assertEquals("IntelOpenCL", list.get(2).getType()); + Assert.assertEquals("246", list.get(2).getMajor().toString()); + Assert.assertEquals("0", list.get(2).getMinor().toString()); + Assert.assertEquals("acl2", list.get(2).getAliasDevName()); + Assert.assertEquals("acla10_ref0", list.get(2).getDevName()); + Assert.assertEquals("09:00.00", list.get(2).getBusNum()); + Assert.assertEquals("50.5781 degrees C", list.get(2).getTemperature()); + Assert.assertEquals("", list.get(2).getCardPowerUsage()); + + // Case 2. check alias map + Map<String, String> aliasMap = openclPlugin.getAliasMap(); + Assert.assertEquals("acl0", aliasMap.get("247:0")); + Assert.assertEquals("acl1", aliasMap.get("247:1")); + Assert.assertEquals("acl2", aliasMap.get("246:0")); + } + + private IntelFpgaOpenclPlugin.InnerShellExecutor mockPuginShell() { + IntelFpgaOpenclPlugin.InnerShellExecutor shell = mock(IntelFpgaOpenclPlugin.InnerShellExecutor.class); + when(shell.runDiagnose(anyString(),anyInt())).thenReturn(""); + when(shell.getMajorAndMinorNumber("aclnalla_pcie0")).thenReturn("247:0"); + when(shell.getMajorAndMinorNumber("aclnalla_pcie1")).thenReturn("247:1"); + when(shell.getMajorAndMinorNumber("acla10_ref0")).thenReturn("246:0"); + return shell; + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org For additional commands, e-mail: common-commits-h...@hadoop.apache.org