From 34da274ad3c723cb6e6bc82463ab84381fa9476e Mon Sep 17 00:00:00 2001 From: Jacob Yundt Date: Fri, 14 Apr 2017 13:46:44 -0400 Subject: [PATCH 01/14] Adding initial GPU support Updating the lshw parser to capture GPU information, WIP --- app/collins/models/AssetMeta.scala | 4 ++ app/collins/models/LshwHelper.scala | 53 ++++++++++++++++++++++- app/collins/util/LshwRepresentation.scala | 10 ++++- app/collins/util/parsers/LshwParser.scala | 20 ++++++--- app/views/asset/show_hwdetails.scala.html | 17 ++++++++ app/views/asset/show_overview.scala.html | 8 ++++ conf/evolutions/collins/2.sql | 3 ++ conf/evolutions/collins/7.sql | 4 +- 8 files changed, 110 insertions(+), 9 deletions(-) diff --git a/app/collins/models/AssetMeta.scala b/app/collins/models/AssetMeta.scala index a8d13c6ae..ce2ac2fb9 100644 --- a/app/collins/models/AssetMeta.scala +++ b/app/collins/models/AssetMeta.scala @@ -198,6 +198,10 @@ object AssetMeta extends Schema with AnormAdapter[AssetMeta] with AssetMetaKeys val NicName = Value(32, "INTERFACE_NAME") // DO NOT USE - Deprecated val NicAddress = Value(33, "INTERFACE_ADDRESS") + + //I know this says Deprecated, but I'm unsure of where to define Gpu vars + val GpuCount = Value(34, "GPU_COUNT") + val GpuDescription = Value(35, "GPU_DESCRIPTION") } // Post enum fields, enum is not safe to extend with new values diff --git a/app/collins/models/LshwHelper.scala b/app/collins/models/LshwHelper.scala index 72df84c8c..75cac3ebc 100644 --- a/app/collins/models/LshwHelper.scala +++ b/app/collins/models/LshwHelper.scala @@ -3,6 +3,7 @@ package collins.models import collins.models.AssetMeta.DynamicEnum._ import collins.models.AssetMeta.Enum._ import collins.models.lshw.Cpu +import collins.models.lshw.Gpu import collins.models.lshw.Disk import collins.models.lshw.Memory import collins.models.lshw.Nic @@ -21,6 +22,8 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { CpuThreads, CpuSpeedGhz, CpuDescription, + GpuCount, + GpuDescription, MemorySizeBytes, MemoryDescription, MemorySizeTotal, @@ -36,6 +39,7 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { def construct(asset: Asset, lshw: LshwRepresentation): Seq[AssetMetaValue] = { collectCpus(asset, lshw) ++ + collectGpus(asset, lshw) ++ collectMemory(asset, lshw) ++ collectNics(asset, lshw) ++ collectDisks(asset, lshw) ++ @@ -45,11 +49,12 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { def reconstruct(asset: Asset, assetMeta: Seq[MetaWrapper]): Reconstruction = { val metaMap = assetMeta.groupBy { _.getGroupId } val (cpus,postCpuMap) = reconstructCpu(metaMap) + val (gpus,postGpuMap) = reconstructGpu(metaMap) val (memory,postMemoryMap) = reconstructMemory(postCpuMap) val (nics,postNicMap) = reconstructNics(postMemoryMap) val (disks,postDiskMap) = reconstructDisks(postNicMap) val (base,postBaseMap) = reconstructBase(postDiskMap) - (LshwRepresentation(cpus, memory, nics, disks, base.headOption.getOrElse(ServerBase())), postBaseMap.values.flatten.toSeq) + (LshwRepresentation(cpus, gpus, memory, nics, disks, base.headOption.getOrElse(ServerBase())), postBaseMap.values.flatten.toSeq) } protected def reconstructCpu(meta: Map[Int, Seq[MetaWrapper]]): FilteredSeq[Cpu] = { @@ -72,6 +77,7 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { } (cpuSeq, filteredMeta) } + protected def collectCpus(asset: Asset, lshw: LshwRepresentation): Seq[AssetMetaValue] = { if (lshw.cpuCount < 1) { return Seq() @@ -86,6 +92,51 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { ) } + + protected def reconstructGpu(meta: Map[Int, Seq[MetaWrapper]]): FilteredSeq[Gpu] = { + val gpuSeq = meta.get(0).map { seq => + val gpuCount = finder(seq, GpuCount, _.toInt, 0) + val gpuDescription = finder(seq, GpuDescription, _.toString, "") + (0 until gpuCount).map { id => + Gpu(gpuDescription, "", "") + }.toSeq + }.getOrElse(Nil) + val filteredMeta = meta.map { case(groupId, metaSeq) => + val newSeq = filterNot( + metaSeq, + Set(GpuCount.id, GpuDescription.id) + ) + groupId -> newSeq + } + (gpuSeq, filteredMeta) + } + + protected def collectGpus(asset: Asset, lshw: LshwRepresentation): Seq[AssetMetaValue] = { + if (lshw.gpuCount < 1) { + return Seq() + } + lshw.gpus.foldLeft((0,Seq[AssetMetaValue]())) { case (run,gpu) => + val groupId = run._1 + val total = run._2 + val res: Seq[AssetMetaValue] = Seq( + AssetMetaValue(asset, GpuDescription.id, groupId, "%s - %s".format(gpu.product, gpu.vendor)) + ) + (groupId + 1, total ++ res) + }._2 + } + +/* stashing + println("gpuCount") + println(lshw.gpuCount) + val gpu = lshw.gpus.find(gpu => gpu.description.nonEmpty).getOrElse(lshw.gpus.head) + println("gpu") + println(gpu) + Seq( + AssetMetaValue(asset, GpuDescription.id, "%s %s".format(gpu.product, gpu.vendor)) + ) + } +*/ + protected def reconstructMemory(meta: Map[Int, Seq[MetaWrapper]]): FilteredSeq[Memory] = { if (!meta.contains(0)) { return (Seq[Memory](), meta) diff --git a/app/collins/util/LshwRepresentation.scala b/app/collins/util/LshwRepresentation.scala index af8b91422..496423c75 100644 --- a/app/collins/util/LshwRepresentation.scala +++ b/app/collins/util/LshwRepresentation.scala @@ -8,6 +8,7 @@ import play.api.libs.json.Json import collins.models.lshw.Cpu import collins.models.lshw.Cpu.CpuFormat +import collins.models.lshw.Gpu import collins.models.lshw.Disk import collins.models.lshw.Disk.DiskFormat import collins.models.lshw.Memory @@ -19,10 +20,11 @@ import collins.models.lshw.ServerBase.ServerbaseFormat object LshwRepresentation { def empty(): LshwRepresentation = { - new LshwRepresentation(Seq(), Seq(), Seq(), Seq(), new ServerBase) + new LshwRepresentation(Seq(), Seq(), Seq(), Seq(), Seq(), new ServerBase) } implicit object LshwFormat extends Format[LshwRepresentation] { import Cpu._ + import Gpu._ import Disk._ import Memory._ import Nic._ @@ -30,12 +32,14 @@ object LshwRepresentation { import Json.toJson override def reads(json: JsValue) = JsSuccess(LshwRepresentation( (json \ "CPU").as[Seq[Cpu]], + (json \ "GPU").as[Seq[Gpu]], (json \ "MEMORY").as[Seq[Memory]], (json \ "NIC").as[Seq[Nic]], (json \ "DISK").as[Seq[Disk]], (json \ "BASE").as[ServerBase])) override def writes(lshw: LshwRepresentation) = JsObject(Seq( "CPU" -> Json.toJson(lshw.cpus), + "GPU" -> Json.toJson(lshw.gpus), "MEMORY" -> Json.toJson(lshw.memory), "NIC" -> Json.toJson(lshw.nics), "DISK" -> Json.toJson(lshw.disks), @@ -45,6 +49,7 @@ object LshwRepresentation { case class LshwRepresentation( cpus: Seq[Cpu], + gpus: Seq[Gpu], memory: Seq[Memory], nics: Seq[Nic], disks: Seq[Disk], @@ -61,6 +66,8 @@ case class LshwRepresentation( } def cpuSpeed: Double = cpus.sortBy(_.speedGhz).lastOption.map(_.speedGhz).getOrElse(0.0) + def gpuCount: Int = gpus.size + def totalMemory: ByteStorageUnit = memory.foldLeft(new ByteStorageUnit(0)) { case (total, mem) => new ByteStorageUnit(total.bytes + mem.size.bytes) @@ -105,6 +112,7 @@ case class LshwRepresentation( (cpuCoreCount == other.cpuCoreCount) && (cpuThreadCount == other.cpuThreadCount) && (cpuSpeed == other.cpuSpeed) && + (gpuCount == other.gpuCount) && (totalMemory.inBytes == other.totalMemory.inBytes) && (memoryBanksUsed == other.memoryBanksUsed) && (memoryBanksUnused == other.memoryBanksUnused) && diff --git a/app/collins/util/parsers/LshwParser.scala b/app/collins/util/parsers/LshwParser.scala index 97dbfa0d0..103922c53 100644 --- a/app/collins/util/parsers/LshwParser.scala +++ b/app/collins/util/parsers/LshwParser.scala @@ -2,6 +2,7 @@ package collins.util.parsers import collins.models.lshw.LshwAsset import collins.models.lshw.Cpu +import collins.models.lshw.Gpu import collins.models.lshw.Memory import collins.models.lshw.Disk import collins.models.lshw.Nic @@ -25,10 +26,11 @@ class LshwParser(txt: String) extends CommonParser[LshwRepresentation](txt) { val wildcard: PartialFunction[NodeSeq, LshwAsset] = { case _ => null } lazy val matcher = cpuMatcher.orElse( - memMatcher.orElse( - diskMatcher.orElse( - nicMatcher.orElse( - wildcard)))) + gpuMatcher.orElse( + memMatcher.orElse( + diskMatcher.orElse( + nicMatcher.orElse( + wildcard))))) override def parse(): Either[Throwable, LshwRepresentation] = { val xml = try { @@ -40,10 +42,11 @@ class LshwParser(txt: String) extends CommonParser[LshwRepresentation](txt) { } val rep = try { val base = getBaseInfo(xml) - getCoreNodes(xml).foldLeft(LshwRepresentation(Nil, Nil, Nil, Nil, base)) { + getCoreNodes(xml).foldLeft(LshwRepresentation(Nil, Nil, Nil, Nil, Nil, base)) { case (holder, node) => matcher(node) match { case c: Cpu => holder.copy(cpus = c +: holder.cpus) + case g: Gpu => holder.copy(gpus = g +: holder.gpus) case m: Memory => holder.copy(memory = m.copy(bank = holder.memory.size) +: holder.memory) case d: Disk => holder.copy(disks = d +: holder.disks) case n: Nic => holder.copy(nics = n +: holder.nics) @@ -79,6 +82,13 @@ class LshwParser(txt: String) extends CommonParser[LshwRepresentation](txt) { Cpu(cores, threads, speed, asset.description, asset.product, asset.vendor) } + val gpuMatcher: PartialFunction[NodeSeq, Gpu] = { + case n if ((n \ "@class" text) == "display") => { + val asset = getAsset(n) + Gpu(asset.description, asset.product, asset.vendor) + } + } + val memMatcher: PartialFunction[NodeSeq, Memory] = { case n if (n \ "@class" text) == "memory" && (n \ "@id" text).contains("bank:") => val asset = getAsset(n) diff --git a/app/views/asset/show_hwdetails.scala.html b/app/views/asset/show_hwdetails.scala.html index 135ff818f..83523a5b9 100644 --- a/app/views/asset/show_hwdetails.scala.html +++ b/app/views/asset/show_hwdetails.scala.html @@ -73,6 +73,23 @@

CPU Collected CPU Information

+

GPU Collected GPU Information

+ + + + + + + + @aa.lshw.gpus.zipWithIndex.map { case(cpu,id) => + + + + + } + +
IdDescription
@id@cpu.description
+

Memory Collected Memory Information

diff --git a/app/views/asset/show_overview.scala.html b/app/views/asset/show_overview.scala.html index 42d611963..56e7a72d0 100644 --- a/app/views/asset/show_overview.scala.html +++ b/app/views/asset/show_overview.scala.html @@ -204,6 +204,14 @@

Hardware Summary Summary of system components reported by LSHW@{if (aa.lshw.hasHyperthreadingEnabled) "Yes" else "No"} +

+ + + + + + + diff --git a/conf/evolutions/collins/2.sql b/conf/evolutions/collins/2.sql index 5439a2b38..4392cad71 100644 --- a/conf/evolutions/collins/2.sql +++ b/conf/evolutions/collins/2.sql @@ -58,6 +58,9 @@ INSERT INTO asset_meta VALUES (31, 'LLDP_VLAN_NAME', -1, 'LLDP VLANE Name', 'VLA INSERT INTO asset_meta VALUES (32, 'INTERFACE_NAME', -1, 'Interface Name', 'Name of physical interface, e.g. eth0'); INSERT INTO asset_meta VALUES (33, 'INTERFACE_ADDRESS', 0, 'IP Address', 'Address on interface, e.g. 10.0.0.1'); +INSERT INTO asset_meta VALUES (34, 'GPU_COUNT', -1, 'GPU Count', 'Number of physical GPUs in asset'); +INSERT INTO asset_meta VALUES (35, 'GPU_DESCRIPTION', -1, 'GPU Description', 'GPU description, vendor labels'); + INSERT INTO asset VALUES (1, 'tumblrtag1', 7, 1, CURRENT_TIMESTAMP, null, null); -- gateway 10.0.0.1, ip address 10.0.0.2, netmask /19 = 255.255.224.0 diff --git a/conf/evolutions/collins/7.sql b/conf/evolutions/collins/7.sql index 08f1eb73f..51505b4ec 100644 --- a/conf/evolutions/collins/7.sql +++ b/conf/evolutions/collins/7.sql @@ -2,9 +2,9 @@ # --- !Ups -UPDATE asset_meta SET priority = -1 WHERE id=33; +UPDATE asset_meta SET priority = -1 WHERE id=35; # --- !Downs -UPDATE asset_meta SET priority = 0 WHERE id=33; +UPDATE asset_meta SET priority = 0 WHERE id=35; From f9fbecab747bce5a61e0d39412ca7341f54d5044 Mon Sep 17 00:00:00 2001 From: Jacob Yundt Date: Fri, 14 Apr 2017 13:59:02 -0400 Subject: [PATCH 02/14] Adding (missing) Gpu.scala file --- app/collins/models/lshw/Gpu.scala | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 app/collins/models/lshw/Gpu.scala diff --git a/app/collins/models/lshw/Gpu.scala b/app/collins/models/lshw/Gpu.scala new file mode 100644 index 000000000..732d6c98a --- /dev/null +++ b/app/collins/models/lshw/Gpu.scala @@ -0,0 +1,27 @@ +package collins.models.lshw + +import play.api.libs.json.Format +import play.api.libs.json.JsObject +import play.api.libs.json.JsSuccess +import play.api.libs.json.JsValue +import play.api.libs.json.Json + +object Gpu { + + implicit object GpuFormat extends Format[Gpu] { + override def reads(json: JsValue) = JsSuccess(Gpu( + (json \ "DESCRIPTION").as[String], + (json \ "PRODUCT").as[String], + (json \ "VENDOR").as[String])) + override def writes(gpu: Gpu) = JsObject(Seq( + "DESCRIPTION" -> Json.toJson(gpu.description), + "PRODUCT" -> Json.toJson(gpu.product), + "VENDOR" -> Json.toJson(gpu.vendor))) + } +} + +case class Gpu( + description: String, product: String, vendor: String) extends LshwAsset { + import Gpu._ + override def toJsValue() = Json.toJson(this) +} From 50a520f63b20436cecd72c1e452772301dd1235e Mon Sep 17 00:00:00 2001 From: Michael Schuett Date: Fri, 14 Apr 2017 16:25:28 -0400 Subject: [PATCH 03/14] Render All GPUs (#1) This renders the proper number of GPUs and also correctly shows the description if the Server has multiple types or an onboard graphics card. --- app/collins/models/LshwHelper.scala | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/app/collins/models/LshwHelper.scala b/app/collins/models/LshwHelper.scala index 75cac3ebc..5464c923e 100644 --- a/app/collins/models/LshwHelper.scala +++ b/app/collins/models/LshwHelper.scala @@ -94,13 +94,16 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { protected def reconstructGpu(meta: Map[Int, Seq[MetaWrapper]]): FilteredSeq[Gpu] = { - val gpuSeq = meta.get(0).map { seq => - val gpuCount = finder(seq, GpuCount, _.toInt, 0) - val gpuDescription = finder(seq, GpuDescription, _.toString, "") - (0 until gpuCount).map { id => - Gpu(gpuDescription, "", "") - }.toSeq - }.getOrElse(Nil) + val gpuSeq = meta.foldLeft(Seq[Gpu]()) { case (seq, map) => + val groupId = map._1 + val wrapSeq = map._2 + val descr = finder(wrapSeq, GpuDescription, _.toString, "") + if (descr.isEmpty) { + seq + } else { + Gpu(descr, "", "") +: seq + } + } val filteredMeta = meta.map { case(groupId, metaSeq) => val newSeq = filterNot( metaSeq, @@ -119,6 +122,7 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { val groupId = run._1 val total = run._2 val res: Seq[AssetMetaValue] = Seq( + AssetMetaValue(asset, GpuCount.id, groupId, lshw.gpuCount.toString), AssetMetaValue(asset, GpuDescription.id, groupId, "%s - %s".format(gpu.product, gpu.vendor)) ) (groupId + 1, total ++ res) From 9e3e60035ea5c7d1a6450c5d6ab0b4f71186b62b Mon Sep 17 00:00:00 2001 From: Jacob Yundt Date: Mon, 17 Apr 2017 10:15:59 -0400 Subject: [PATCH 04/14] Filter NVIDIA GPUs Only add NVIDIA GPUs to asset list. Previously all display adapters (including the onboard VGA adapters) were listed as GPUs. --- app/collins/models/LshwHelper.scala | 1 - app/collins/util/parsers/LshwParser.scala | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/collins/models/LshwHelper.scala b/app/collins/models/LshwHelper.scala index 5464c923e..1a3924598 100644 --- a/app/collins/models/LshwHelper.scala +++ b/app/collins/models/LshwHelper.scala @@ -122,7 +122,6 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { val groupId = run._1 val total = run._2 val res: Seq[AssetMetaValue] = Seq( - AssetMetaValue(asset, GpuCount.id, groupId, lshw.gpuCount.toString), AssetMetaValue(asset, GpuDescription.id, groupId, "%s - %s".format(gpu.product, gpu.vendor)) ) (groupId + 1, total ++ res) diff --git a/app/collins/util/parsers/LshwParser.scala b/app/collins/util/parsers/LshwParser.scala index 103922c53..abd516af0 100644 --- a/app/collins/util/parsers/LshwParser.scala +++ b/app/collins/util/parsers/LshwParser.scala @@ -83,7 +83,7 @@ class LshwParser(txt: String) extends CommonParser[LshwRepresentation](txt) { } val gpuMatcher: PartialFunction[NodeSeq, Gpu] = { - case n if ((n \ "@class" text) == "display") => { + case n if ((n \ "@class" text) == "display" && (n \\ "vendor" text).contains("NVIDIA Corporation")) => { val asset = getAsset(n) Gpu(asset.description, asset.product, asset.vendor) } From 7b3a82627c1f8904008bec21396f43d5f22e89d6 Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 19 Apr 2017 09:19:28 -0400 Subject: [PATCH 05/14] Add gpu support tests (#3) Create two new tests to verify GPU functionality works as expected. --- app/collins/models/LshwHelper.scala | 19 +- app/collins/util/LshwRepresentation.scala | 1 + test/collins/models/LshwHelperSpec.scala | 7 + .../collins/util/parsers/LshwParserSpec.scala | 13 + test/resources/lshw-gpu.xml | 1564 +++++++++++++++++ 5 files changed, 1588 insertions(+), 16 deletions(-) create mode 100644 test/resources/lshw-gpu.xml diff --git a/app/collins/models/LshwHelper.scala b/app/collins/models/LshwHelper.scala index 1a3924598..cacc5aefb 100644 --- a/app/collins/models/LshwHelper.scala +++ b/app/collins/models/LshwHelper.scala @@ -49,8 +49,8 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { def reconstruct(asset: Asset, assetMeta: Seq[MetaWrapper]): Reconstruction = { val metaMap = assetMeta.groupBy { _.getGroupId } val (cpus,postCpuMap) = reconstructCpu(metaMap) - val (gpus,postGpuMap) = reconstructGpu(metaMap) - val (memory,postMemoryMap) = reconstructMemory(postCpuMap) + val (gpus,postGpuMap) = reconstructGpu(postCpuMap) + val (memory,postMemoryMap) = reconstructMemory(postGpuMap) val (nics,postNicMap) = reconstructNics(postMemoryMap) val (disks,postDiskMap) = reconstructDisks(postNicMap) val (base,postBaseMap) = reconstructBase(postDiskMap) @@ -92,7 +92,6 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { ) } - protected def reconstructGpu(meta: Map[Int, Seq[MetaWrapper]]): FilteredSeq[Gpu] = { val gpuSeq = meta.foldLeft(Seq[Gpu]()) { case (seq, map) => val groupId = map._1 @@ -107,7 +106,7 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { val filteredMeta = meta.map { case(groupId, metaSeq) => val newSeq = filterNot( metaSeq, - Set(GpuCount.id, GpuDescription.id) + Set(GpuDescription.id) ) groupId -> newSeq } @@ -128,18 +127,6 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { }._2 } -/* stashing - println("gpuCount") - println(lshw.gpuCount) - val gpu = lshw.gpus.find(gpu => gpu.description.nonEmpty).getOrElse(lshw.gpus.head) - println("gpu") - println(gpu) - Seq( - AssetMetaValue(asset, GpuDescription.id, "%s %s".format(gpu.product, gpu.vendor)) - ) - } -*/ - protected def reconstructMemory(meta: Map[Int, Seq[MetaWrapper]]): FilteredSeq[Memory] = { if (!meta.contains(0)) { return (Seq[Memory](), meta) diff --git a/app/collins/util/LshwRepresentation.scala b/app/collins/util/LshwRepresentation.scala index 496423c75..d56823d4e 100644 --- a/app/collins/util/LshwRepresentation.scala +++ b/app/collins/util/LshwRepresentation.scala @@ -9,6 +9,7 @@ import play.api.libs.json.Json import collins.models.lshw.Cpu import collins.models.lshw.Cpu.CpuFormat import collins.models.lshw.Gpu +import collins.models.lshw.Gpu.GpuFormat import collins.models.lshw.Disk import collins.models.lshw.Disk.DiskFormat import collins.models.lshw.Memory diff --git a/test/collins/models/LshwHelperSpec.scala b/test/collins/models/LshwHelperSpec.scala index 2ae5e1356..e394354e4 100644 --- a/test/collins/models/LshwHelperSpec.scala +++ b/test/collins/models/LshwHelperSpec.scala @@ -88,6 +88,13 @@ class LshwHelperSpec extends mutable.Specification { LshwHelper.updateAsset(asset, parsed()) asset.getMetaAttribute(AssetMeta.Enum.DiskType.toString) must beNone } + "with an NVIDIA GPU" in new LshwCommonHelper("lshw-gpu.xml") { + val lshw = parsed() + val stub = getStub() + val constructed: Seq[AssetMetaValue] = LshwHelper.construct(stub, lshw) + val reconstructed = LshwHelper.reconstruct(stub, metaValue2metaWrapper(constructed))._1 + lshw mustEqual reconstructed + } } } diff --git a/test/collins/util/parsers/LshwParserSpec.scala b/test/collins/util/parsers/LshwParserSpec.scala index 71d59d571..e856526d7 100644 --- a/test/collins/util/parsers/LshwParserSpec.scala +++ b/test/collins/util/parsers/LshwParserSpec.scala @@ -492,5 +492,18 @@ class LshwParserSpec extends mutable.Specification { } } // wonky opterons + "Parse GPU server" in { + "quad nvidia GPU server" in new LshwParserHelper("lshw-gpu.xml"){ + val parseResults = parsed() + parseResults must beRight + parseResults.right.toOption must beSome.which { rep => + rep.cpuCount mustEqual 2 + rep.cpuCoreCount mustEqual 12 + + rep.gpuCount mustEqual 2 + } + } + } + } // The LSHW parser should } diff --git a/test/resources/lshw-gpu.xml b/test/resources/lshw-gpu.xml new file mode 100644 index 000000000..ff25685b8 --- /dev/null +++ b/test/resources/lshw-gpu.xml @@ -0,0 +1,1564 @@ + + + + + + + Rack Mount Chassis + PowerEdge C6105 (N/A) + Winbond Electronics + N/A + FZ22YQ1 + 64 + + + + + + + + + SMBIOS version 2.6 + DMI version 2.6 + 64-bit processes + 32-bit processes + + + Motherboard + 001V46 + Winbond Electronics + 0 + A01 + .FZ22YQ1.CN7170315N0004. + N/A + + BIOS + Winbond Electronics + 1 + 1.7.6 + 04/21/2011 + 65536 + 4128768 + + ISA bus + PCI bus + Plug-and-Play + BIOS EEPROM can be upgraded + BIOS shadowing + ESCD + Booting from CD-ROM/DVD + Selectable boot path + BIOS ROM is socketed + Enhanced Disk Drive extensions + Print Screen key + INT14 serial line control + INT17 printer control + INT10 CGA/Mono video + ACPI + USB legacy emulation + Booting from LS-120 + Booting from ATAPI ZIP + BIOS boot specification + + + + CPU + AMD Opteron(tm) Processor 4174 HE + Hynix Semiconductor (Hyundai Electronics) + 5 + cpu@0 + D1 + To Be Filled By O.E.M. + CPU 0 + 2300000000 + 2300000000 + 64 + 200000000 + + + + + + + 64bits extensions (x86-64) + mathematical co-processor + FPU exceptions reporting + + virtual mode extensions + debugging extensions + page size extensions + time stamp counter + model-specific registers + 4GB+ memory addressing (Physical Address Extension) + machine check exceptions + compare and exchange 8-byte + on-chip advanced programmable interrupt controller (APIC) + memory type range registers + page global enable + machine check architecture + conditional move instruction + page attribute table + 36-bit page size extensions + + multimedia extensions (MMX) + fast floating point save/restore + streaming SIMD extensions (SSE) + streaming SIMD extensions (SSE2) + HyperThreading + fast system calls + no-execute bit (NX) + multimedia extensions (MMXExt) + + + + multimedia extensions (3DNow!Ext) + multimedia extensions (3DNow!) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + L1 cache + 6 + L1-Cache + 786432 + 786432 + 1000000000 + + Pipeline burst + Internal + Write-back + Unified cache + + + + L2 cache + 7 + L2-Cache + 3145728 + 3145728 + 1000000000 + + Pipeline burst + Internal + Write-back + Unified cache + + + + L3 cache + 8 + L3-Cache + 6291456 + 6291456 + 1000000000 + + Pipeline burst + Internal + Write-back + Unified cache + + + + + CPU + AMD Opteron(tm) Processor 4174 HE + Hynix Semiconductor (Hyundai Electronics) + 9 + cpu@1 + D1 + To Be Filled By O.E.M. + CPU 1 + 2300000000 + 2300000000 + 64 + 200000000 + + + + + + + 64bits extensions (x86-64) + mathematical co-processor + FPU exceptions reporting + + virtual mode extensions + debugging extensions + page size extensions + time stamp counter + model-specific registers + 4GB+ memory addressing (Physical Address Extension) + machine check exceptions + compare and exchange 8-byte + on-chip advanced programmable interrupt controller (APIC) + memory type range registers + page global enable + machine check architecture + conditional move instruction + page attribute table + 36-bit page size extensions + + multimedia extensions (MMX) + fast floating point save/restore + streaming SIMD extensions (SSE) + streaming SIMD extensions (SSE2) + HyperThreading + fast system calls + no-execute bit (NX) + multimedia extensions (MMXExt) + + + + multimedia extensions (3DNow!Ext) + multimedia extensions (3DNow!) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + L1 cache + a + L1-Cache + 786432 + 786432 + 1000000000 + + Pipeline burst + Internal + Write-back + Unified cache + + + + L2 cache + b + L2-Cache + 3145728 + 3145728 + 1000000000 + + Pipeline burst + Internal + Write-back + Unified cache + + + + L3 cache + c + L3-Cache + 6291456 + 6291456 + 1000000000 + + Pipeline burst + Internal + Write-back + Unified cache + + + + + System Memory + 28 + System board or motherboard + 34359738368 + + DIMM DDR3 Synchronous [empty] + ModulePartNumber00 + Manufacturer00 + 0 + SerNum00 + CPU0 DIMM A0 + + + DIMM DDR3 Synchronous [empty] + ModulePartNumber01 + Manufacturer01 + 1 + SerNum01 + CPU0 DIMM A1 + + + DIMM DDR3 Synchronous 1333 MHz (0.8 ns) + HMT31GR7BFR4A-H9 + Hyundai + 2 + 8AF9A71E + CPU0 DIMM A2 + 8589934592 + 64 + 1333000000 + + + DIMM DDR3 Synchronous [empty] + ModulePartNumber03 + Manufacturer03 + 3 + SerNum03 + CPU0 DIMM B0 + + + DIMM DDR3 Synchronous [empty] + ModulePartNumber04 + Manufacturer04 + 4 + SerNum04 + CPU0 DIMM B1 + + + DIMM DDR3 Synchronous 1333 MHz (0.8 ns) + HMT31GR7BFR4A-H9 + Hyundai + 5 + 8BF9171E + CPU0 DIMM B2 + 8589934592 + 64 + 1333000000 + + + DIMM DDR3 Synchronous [empty] + ModulePartNumber06 + Manufacturer06 + 6 + SerNum06 + CPU1 DIMM C0 + + + DIMM DDR3 Synchronous [empty] + ModulePartNumber07 + Manufacturer07 + 7 + SerNum07 + CPU1 DIMM C1 + + + DIMM DDR3 Synchronous 1333 MHz (0.8 ns) + HMT31GR7BFR4A-H9 + Hyundai + 8 + 95F9871E + CPU1 DIMM C2 + 8589934592 + 64 + 1333000000 + + + DIMM DDR3 Synchronous [empty] + ModulePartNumber09 + Manufacturer09 + 9 + SerNum09 + CPU1 DIMM D0 + + + DIMM DDR3 Synchronous [empty] + ModulePartNumber10 + Manufacturer10 + a + SerNum10 + CPU1 DIMM D1 + + + DIMM DDR3 Synchronous 1333 MHz (0.8 ns) + HMT31GR7BFR4A-H9 + Hyundai + b + A2F9B71E + CPU1 DIMM D2 + 8589934592 + 64 + 1333000000 + + + + Host bridge + Xeon E7 v3/Xeon E5 v3/Core i7 DMI2 + Intel Corporation + 100 + pci@0000:00:00.0 + 02 + 32 + 33000000 + + PCI bridge + Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 1 + Intel Corporation + 1 + pci@0000:00:01.0 + 02 + 32 + 33000000 + + + + + + Message Signalled Interrupts + PCI Express + Power Management + + bus mastering + PCI capabilities listing + + + + + + + PCI bridge + Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 + Intel Corporation + 2 + pci@0000:00:02.0 + 02 + 32 + 33000000 + + + + + + Message Signalled Interrupts + PCI Express + Power Management + + bus mastering + PCI capabilities listing + + + + + + + + + VGA compatible controller + GM200GL [Quadro M6000] + NVIDIA Corporation + 0 + pci@0000:02:00.0 + a1 + 64 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + PCI Express + + bus mastering + PCI capabilities listing + extension ROM + + + + + + + + + + + + + + Audio device + NVIDIA Corporation + NVIDIA Corporation + 0.1 + pci@0000:02:00.1 + a1 + 32 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + PCI Express + bus mastering + PCI capabilities listing + + + + + + + + + PCI bridge + Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 + Intel Corporation + 3 + pci@0000:00:03.0 + 02 + 32 + 33000000 + + + + + + Message Signalled Interrupts + PCI Express + Power Management + + bus mastering + PCI capabilities listing + + + + + + + + + VGA compatible controller + GM200GL [Quadro M6000] + NVIDIA Corporation + 0 + pci@0000:03:00.0 + a1 + 64 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + PCI Express + + bus mastering + PCI capabilities listing + extension ROM + + + + + + + + + + + + + + Audio device + NVIDIA Corporation + NVIDIA Corporation + 0.1 + pci@0000:03:00.1 + a1 + 32 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + PCI Express + bus mastering + PCI capabilities listing + + + + + + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 0 + Intel Corporation + 4 + pci@0000:00:04.0 + 02 + 64 + 33000000 + + + + + + MSI-X + PCI Express + Power Management + bus mastering + PCI capabilities listing + + + + + + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 1 + Intel Corporation + 4.1 + pci@0000:00:04.1 + 02 + 64 + 33000000 + + + + + + MSI-X + PCI Express + Power Management + bus mastering + PCI capabilities listing + + + + + + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 2 + Intel Corporation + 4.2 + pci@0000:00:04.2 + 02 + 64 + 33000000 + + + + + + MSI-X + PCI Express + Power Management + bus mastering + PCI capabilities listing + + + + + + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 3 + Intel Corporation + 4.3 + pci@0000:00:04.3 + 02 + 64 + 33000000 + + + + + + MSI-X + PCI Express + Power Management + bus mastering + PCI capabilities listing + + + + + + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 4 + Intel Corporation + 4.4 + pci@0000:00:04.4 + 02 + 64 + 33000000 + + + + + + MSI-X + PCI Express + Power Management + bus mastering + PCI capabilities listing + + + + + + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 5 + Intel Corporation + 4.5 + pci@0000:00:04.5 + 02 + 64 + 33000000 + + + + + + MSI-X + PCI Express + Power Management + bus mastering + PCI capabilities listing + + + + + + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 6 + Intel Corporation + 4.6 + pci@0000:00:04.6 + 02 + 64 + 33000000 + + + + + + MSI-X + PCI Express + Power Management + bus mastering + PCI capabilities listing + + + + + + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 7 + Intel Corporation + 4.7 + pci@0000:00:04.7 + 02 + 64 + 33000000 + + + + + + MSI-X + PCI Express + Power Management + bus mastering + PCI capabilities listing + + + + + + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 Address Map, VTd_Misc, System Management + Intel Corporation + 5 + pci@0000:00:05.0 + 02 + 32 + 33000000 + + + + + PCI Express + PCI capabilities listing + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 Hot Plug + Intel Corporation + 5.1 + pci@0000:00:05.1 + 02 + 32 + 33000000 + + + + + PCI Express + Message Signalled Interrupts + PCI capabilities listing + + + + System peripheral + Xeon E7 v3/Xeon E5 v3/Core i7 RAS, Control Status and Global Errors + Intel Corporation + 5.2 + pci@0000:00:05.2 + 02 + 32 + 33000000 + + + + + PCI Express + PCI capabilities listing + + + + PIC + Xeon E7 v3/Xeon E5 v3/Core i7 I/O APIC + Intel Corporation + 5.4 + pci@0000:00:05.4 + 02 + 32 + 33000000 + + + + + PCI Express + Power Management + + bus mastering + PCI capabilities listing + + + + + + + Unassigned class + C610/X99 series chipset SPSR + Intel Corporation + 11 + pci@0000:00:11.0 + 05 + 32 + 33000000 + + + + + PCI Express + Power Management + bus mastering + PCI capabilities listing + + + + SATA controller + C610/X99 series chipset sSATA Controller [AHCI mode] + Intel Corporation + 11.4 + pci@0000:00:11.4 + 05 + 32 + 66000000 + + + + + + + Message Signalled Interrupts + Power Management + + bus mastering + PCI capabilities listing + + + + + + + + + + + + + USB controller + C610/X99 series chipset USB xHCI Host Controller + Intel Corporation + 14 + pci@0000:00:14.0 + 05 + 64 + 33000000 + + + + + + Power Management + + bus mastering + PCI capabilities listing + + + + + + + + + Communication controller + C610/X99 series chipset MEI Controller #1 + Intel Corporation + 16 + pci@0000:00:16.0 + 05 + 64 + 33000000 + + + + + Power Management + Message Signalled Interrupts + bus mastering + PCI capabilities listing + + + + + + + Communication controller + C610/X99 series chipset MEI Controller #2 + Intel Corporation + 16.1 + pci@0000:00:16.1 + 05 + 64 + 33000000 + + + + + Power Management + Message Signalled Interrupts + bus mastering + PCI capabilities listing + + + + + + + USB controller + C610/X99 series chipset USB Enhanced Host Controller #2 + Intel Corporation + 1a + pci@0000:00:1a.0 + 05 + 32 + 33000000 + + + + + + Power Management + Debug port + Enhanced Host Controller Interface (USB2) + bus mastering + PCI capabilities listing + + + + + + + + Audio device + C610/X99 series chipset HD Audio Controller + Intel Corporation + 1b + pci@0000:00:1b.0 + 05 + 64 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + PCI Express + bus mastering + PCI capabilities listing + + + + + + + + + PCI bridge + C610/X99 series chipset PCI Express Root Port #1 + Intel Corporation + 1c + pci@0000:00:1c.0 + d5 + 32 + 33000000 + + + + + + PCI Express + Message Signalled Interrupts + Power Management + + bus mastering + PCI capabilities listing + + + + + + + PCI bridge + C610/X99 series chipset PCI Express Root Port #4 + Intel Corporation + 1c.3 + pci@0000:00:1c.3 + d5 + 32 + 33000000 + + + + + + PCI Express + Message Signalled Interrupts + Power Management + + bus mastering + PCI capabilities listing + + + + + + + + PCI bridge + AST1150 PCI-to-PCI Bridge + ASPEED Technology, Inc. + 0 + pci@0000:05:00.0 + 03 + 32 + 33000000 + + + Message Signalled Interrupts + Power Management + PCI Express + + bus mastering + PCI capabilities listing + + + + + + + VGA compatible controller + ASPEED Graphics Family + ASPEED Technology, Inc. + 0 + pci@0000:06:00.0 + 30 + 32 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + + bus mastering + PCI capabilities listing + extension ROM + + + + + + + + + + + + PCI bridge + C610/X99 series chipset PCI Express Root Port #5 + Intel Corporation + 1c.4 + pci@0000:00:1c.4 + d5 + 32 + 33000000 + + + + + + PCI Express + Message Signalled Interrupts + Power Management + + bus mastering + PCI capabilities listing + + + + + + + + + + USB controller + C610/X99 series chipset USB Enhanced Host Controller #1 + Intel Corporation + 1d + pci@0000:00:1d.0 + 05 + 32 + 33000000 + + + + + + Power Management + Debug port + Enhanced Host Controller Interface (USB2) + bus mastering + PCI capabilities listing + + + + + + + + ISA bridge + C610/X99 series chipset LPC Controller + Intel Corporation + 1f + pci@0000:00:1f.0 + 05 + 32 + 33000000 + + + + + + + bus mastering + PCI capabilities listing + + + + + + + SATA controller + C610/X99 series chipset 6-Port SATA Controller [AHCI mode] + Intel Corporation + 1f.2 + pci@0000:00:1f.2 + 05 + 32 + 66000000 + + + + + + + Message Signalled Interrupts + Power Management + + bus mastering + PCI capabilities listing + + + + + + + + + + + + + SMBus + C610/X99 series chipset SMBus Controller + Intel Corporation + 1f.3 + pci@0000:00:1f.3 + 05 + 64 + 33000000 + + + + + + + + + + + Signal processing controller + C610/X99 series chipset Thermal Subsystem + Intel Corporation + 1f.6 + pci@0000:00:1f.6 + 05 + 64 + 33000000 + + + + + Power Management + Message Signalled Interrupts + bus mastering + PCI capabilities listing + + + + + + + + + Host bridge + Family 10h Processor HyperTransport Configuration + Hynix Semiconductor (Hyundai Electronics) + 101 + pci@0000:00:18.0 + 00 + 32 + 33000000 + + + Host bridge + Family 10h Processor Address Map + Hynix Semiconductor (Hyundai Electronics) + 102 + pci@0000:00:18.1 + 00 + 32 + 33000000 + + + Host bridge + Family 10h Processor DRAM Controller + Hynix Semiconductor (Hyundai Electronics) + 103 + pci@0000:00:18.2 + 00 + 32 + 33000000 + + + + + + + + + Host bridge + Family 10h Processor Miscellaneous Control + Hynix Semiconductor (Hyundai Electronics) + 104 + pci@0000:00:18.3 + 00 + 32 + 33000000 + + + Host bridge + Family 10h Processor Link Control + Hynix Semiconductor (Hyundai Electronics) + 105 + pci@0000:00:18.4 + 00 + 32 + 33000000 + + + Host bridge + Family 10h Processor HyperTransport Configuration + Hynix Semiconductor (Hyundai Electronics) + 106 + pci@0000:00:19.0 + 00 + 32 + 33000000 + + + Host bridge + Family 10h Processor Address Map + Hynix Semiconductor (Hyundai Electronics) + 107 + pci@0000:00:19.1 + 00 + 32 + 33000000 + + + Host bridge + Family 10h Processor DRAM Controller + Hynix Semiconductor (Hyundai Electronics) + 108 + pci@0000:00:19.2 + 00 + 32 + 33000000 + + + + + + + + + Host bridge + Family 10h Processor Miscellaneous Control + Hynix Semiconductor (Hyundai Electronics) + 109 + pci@0000:00:19.3 + 00 + 32 + 33000000 + + + Host bridge + Family 10h Processor Link Control + Hynix Semiconductor (Hyundai Electronics) + 10a + pci@0000:00:19.4 + 00 + 32 + 33000000 + + + + Ethernet interface + 1 + bond0 + e8:9a:8f:23:15:72 + + + + + + + + + + + + Physical interface + + + + Ethernet interface + 2 + bond0.100 + e8:9a:8f:23:15:72 + + + + + + + + + + + + Physical interface + + + + Ethernet interface + 3 + bond0.101 + e8:9a:8f:23:15:72 + + + + + + + + + + + + Physical interface + + + + Ethernet interface + 4 + bond0.103 + e8:9a:8f:23:15:72 + + + + + + + + + + + + Physical interface + + + + Ethernet interface + 5 + bond0.105 + e8:9a:8f:23:15:72 + + + + + + + + + + + + + Physical interface + + + + Ethernet interface + 6 + vnet0 + fe:54:00:52:1a:d7 + 10000000 + + + + + + + + + + + + + + + Physical interface + + + From a3cc729083fc285b2c23475653e3c427ef72cf05 Mon Sep 17 00:00:00 2001 From: Jacob Yundt Date: Thu, 20 Apr 2017 16:33:15 -0400 Subject: [PATCH 06/14] Cleanup of DB migration scripts. --- conf/evolutions/collins/14.sql | 10 ++++++++++ conf/evolutions/collins/2.sql | 3 --- conf/evolutions/collins/7.sql | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 conf/evolutions/collins/14.sql diff --git a/conf/evolutions/collins/14.sql b/conf/evolutions/collins/14.sql new file mode 100644 index 000000000..f9552a072 --- /dev/null +++ b/conf/evolutions/collins/14.sql @@ -0,0 +1,10 @@ +# --- Add GPU information to asset_meta + +# --- !Ups + +INSERT INTO asset_meta VALUES (34, 'GPU_COUNT', -1, 'GPU Count', 'Number of physical GPUs in asset'); +INSERT INTO asset_meta VALUES (35, 'GPU_DESCRIPTION', -1, 'GPU Description', 'GPU description, vendor labels'); + +# --- !Downs + +DELETE FROM asset_meta WHERE id in (34,35); diff --git a/conf/evolutions/collins/2.sql b/conf/evolutions/collins/2.sql index 4392cad71..5439a2b38 100644 --- a/conf/evolutions/collins/2.sql +++ b/conf/evolutions/collins/2.sql @@ -58,9 +58,6 @@ INSERT INTO asset_meta VALUES (31, 'LLDP_VLAN_NAME', -1, 'LLDP VLANE Name', 'VLA INSERT INTO asset_meta VALUES (32, 'INTERFACE_NAME', -1, 'Interface Name', 'Name of physical interface, e.g. eth0'); INSERT INTO asset_meta VALUES (33, 'INTERFACE_ADDRESS', 0, 'IP Address', 'Address on interface, e.g. 10.0.0.1'); -INSERT INTO asset_meta VALUES (34, 'GPU_COUNT', -1, 'GPU Count', 'Number of physical GPUs in asset'); -INSERT INTO asset_meta VALUES (35, 'GPU_DESCRIPTION', -1, 'GPU Description', 'GPU description, vendor labels'); - INSERT INTO asset VALUES (1, 'tumblrtag1', 7, 1, CURRENT_TIMESTAMP, null, null); -- gateway 10.0.0.1, ip address 10.0.0.2, netmask /19 = 255.255.224.0 diff --git a/conf/evolutions/collins/7.sql b/conf/evolutions/collins/7.sql index 51505b4ec..08f1eb73f 100644 --- a/conf/evolutions/collins/7.sql +++ b/conf/evolutions/collins/7.sql @@ -2,9 +2,9 @@ # --- !Ups -UPDATE asset_meta SET priority = -1 WHERE id=35; +UPDATE asset_meta SET priority = -1 WHERE id=33; # --- !Downs -UPDATE asset_meta SET priority = 0 WHERE id=35; +UPDATE asset_meta SET priority = 0 WHERE id=33; From 148b990190a07e67a593f4c12f45a81601fa7071 Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 26 Apr 2017 13:22:37 -0400 Subject: [PATCH 07/14] Add gpu support fixup * Update evolutions migration to avoid hardcoding index values. * Remove additional hardcoded GPU AssetMeta references. * Add initial gpu whitelist config file functionality. --- app/collins/models/AssetMeta.scala | 8 +++----- app/collins/models/LshwHelper.scala | 4 +--- app/collins/util/config/GpuConfig.scala | 12 ++++++++++++ app/collins/util/parsers/LshwParser.scala | 3 ++- conf/evolutions/collins/14.sql | 7 ++++--- conf/reference/gpu_reference.conf | 5 +++++ conf/test_base.conf | 4 ++++ conf/validations.conf | 1 + 8 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 app/collins/util/config/GpuConfig.scala create mode 100644 conf/reference/gpu_reference.conf diff --git a/app/collins/models/AssetMeta.scala b/app/collins/models/AssetMeta.scala index ce2ac2fb9..43d5c9ace 100644 --- a/app/collins/models/AssetMeta.scala +++ b/app/collins/models/AssetMeta.scala @@ -198,10 +198,6 @@ object AssetMeta extends Schema with AnormAdapter[AssetMeta] with AssetMetaKeys val NicName = Value(32, "INTERFACE_NAME") // DO NOT USE - Deprecated val NicAddress = Value(33, "INTERFACE_ADDRESS") - - //I know this says Deprecated, but I'm unsure of where to define Gpu vars - val GpuCount = Value(34, "GPU_COUNT") - val GpuDescription = Value(35, "GPU_DESCRIPTION") } // Post enum fields, enum is not safe to extend with new values @@ -210,9 +206,11 @@ object AssetMeta extends Schema with AnormAdapter[AssetMeta] with AssetMetaKeys val BaseProduct = findOrCreateFromName("BASE_PRODUCT") val BaseVendor = findOrCreateFromName("BASE_VENDOR") val BaseSerial = findOrCreateFromName("BASE_SERIAL") + val GpuCount = findOrCreateFromName("GPU_COUNT") + val GpuDescription = findOrCreateFromName("GPU_DESCRIPTION") def getValues(): Seq[AssetMeta] = { - Seq(BaseDescription, BaseProduct, BaseVendor, BaseSerial) + Seq(BaseDescription, BaseProduct, BaseVendor, BaseSerial, GpuCount, GpuDescription) } } } diff --git a/app/collins/models/LshwHelper.scala b/app/collins/models/LshwHelper.scala index cacc5aefb..11c5ef471 100644 --- a/app/collins/models/LshwHelper.scala +++ b/app/collins/models/LshwHelper.scala @@ -22,8 +22,6 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { CpuThreads, CpuSpeedGhz, CpuDescription, - GpuCount, - GpuDescription, MemorySizeBytes, MemoryDescription, MemorySizeTotal, @@ -96,7 +94,7 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { val gpuSeq = meta.foldLeft(Seq[Gpu]()) { case (seq, map) => val groupId = map._1 val wrapSeq = map._2 - val descr = finder(wrapSeq, GpuDescription, _.toString, "") + val descr = amfinder(wrapSeq, GpuDescription, _.toString, "") if (descr.isEmpty) { seq } else { diff --git a/app/collins/util/config/GpuConfig.scala b/app/collins/util/config/GpuConfig.scala new file mode 100644 index 000000000..f88aeb9fc --- /dev/null +++ b/app/collins/util/config/GpuConfig.scala @@ -0,0 +1,12 @@ +package collins.util.config + +object GpuConfig extends Configurable { + override val namespace = "gpu" + override val referenceConfigFilename = "gpu_reference.conf" + + def gpuVendors= getStringSet("gpuVendors") + + override protected def validateConfig() { + gpuVendors + } +} diff --git a/app/collins/util/parsers/LshwParser.scala b/app/collins/util/parsers/LshwParser.scala index abd516af0..c3c5fc122 100644 --- a/app/collins/util/parsers/LshwParser.scala +++ b/app/collins/util/parsers/LshwParser.scala @@ -9,6 +9,7 @@ import collins.models.lshw.Nic import collins.models.lshw.ServerBase import collins.util.config.LshwConfig +import collins.util.config.GpuConfig import collins.util.LshwRepresentation import collins.util.ByteStorageUnit import collins.util.BitStorageUnit @@ -83,7 +84,7 @@ class LshwParser(txt: String) extends CommonParser[LshwRepresentation](txt) { } val gpuMatcher: PartialFunction[NodeSeq, Gpu] = { - case n if ((n \ "@class" text) == "display" && (n \\ "vendor" text).contains("NVIDIA Corporation")) => { + case n if ((n \ "@class" text) == "display" && GpuConfig.gpuVendors.exists(s => (n \\ "vendor" text).contains(s))) => { val asset = getAsset(n) Gpu(asset.description, asset.product, asset.vendor) } diff --git a/conf/evolutions/collins/14.sql b/conf/evolutions/collins/14.sql index f9552a072..7acd7ddc0 100644 --- a/conf/evolutions/collins/14.sql +++ b/conf/evolutions/collins/14.sql @@ -2,9 +2,10 @@ # --- !Ups -INSERT INTO asset_meta VALUES (34, 'GPU_COUNT', -1, 'GPU Count', 'Number of physical GPUs in asset'); -INSERT INTO asset_meta VALUES (35, 'GPU_DESCRIPTION', -1, 'GPU Description', 'GPU description, vendor labels'); +INSERT INTO asset_meta (name, priority, label, description) VALUES ('GPU_COUNT', -1, 'GPU Count', 'Number of physical GPUs in asset'); +INSERT INTO asset_meta (name, priority, label, description) VALUES ('GPU_DESCRIPTION', -1, 'GPU Description', 'GPU description, vendor labels'); # --- !Downs -DELETE FROM asset_meta WHERE id in (34,35); +DELETE FROM asset_meta WHERE name ='GPU_COUNT' +DELETE FROM asset_meta WHERE name ='GPU_DESCRIPTION' diff --git a/conf/reference/gpu_reference.conf b/conf/reference/gpu_reference.conf new file mode 100644 index 000000000..fc4f09517 --- /dev/null +++ b/conf/reference/gpu_reference.conf @@ -0,0 +1,5 @@ +gpu { + # A list of hardware vendors that should be parsed by lshw as "gpu vendors" + gpuVendors = [] + +} diff --git a/conf/test_base.conf b/conf/test_base.conf index ba6aaaabe..687afaa27 100644 --- a/conf/test_base.conf +++ b/conf/test_base.conf @@ -282,6 +282,10 @@ lshw { lshw.defaultNicCapacity=10000000000 } +gpu { + gpuVendors = ["NVIDIA Corporation"] +} + include "authentication.conf" # Set logging properties in logger.xml or dev_logger.xml diff --git a/conf/validations.conf b/conf/validations.conf index 63d931ffc..366723a0c 100644 --- a/conf/validations.conf +++ b/conf/validations.conf @@ -18,6 +18,7 @@ config.validations = [ collins.util.config.LshwConfig, collins.util.config.LldpConfig, collins.util.config.NodeclassifierConfig, + collins.util.config.GpuConfig, collins.util.power.PowerConfiguration, collins.util.security.AuthenticationProviderConfig, collins.util.security.FileAuthenticationProviderConfig, From ea915fc335d34f6cecbe9abfac5ccdb8eca0f89e Mon Sep 17 00:00:00 2001 From: Jacob Yundt Date: Wed, 26 Apr 2017 13:35:34 -0400 Subject: [PATCH 08/14] Minor typo fix for hwdetails view. --- app/views/asset/show_hwdetails.scala.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/asset/show_hwdetails.scala.html b/app/views/asset/show_hwdetails.scala.html index 83523a5b9..575c0eab2 100644 --- a/app/views/asset/show_hwdetails.scala.html +++ b/app/views/asset/show_hwdetails.scala.html @@ -81,10 +81,10 @@

GPU Collected GPU Information

- @aa.lshw.gpus.zipWithIndex.map { case(cpu,id) => + @aa.lshw.gpus.zipWithIndex.map { case(gpu,id) => - + } From 0412dacdb16ac4d0d663ea746c27f03330f09509 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 27 Apr 2017 15:54:24 -0400 Subject: [PATCH 09/14] Update ruby collins-client with GPU functionality --- support/ruby/collins-client/lib/collins/asset.rb | 9 +++++++++ support/ruby/collins-client/spec/collins/asset_spec.rb | 8 ++++++++ .../spec/fixtures/full_asset_with_gpu.json | 1 + .../ruby/collins-client/spec/support/collins_fixture.rb | 3 +++ 4 files changed, 21 insertions(+) create mode 100644 support/ruby/collins-client/spec/fixtures/full_asset_with_gpu.json diff --git a/support/ruby/collins-client/lib/collins/asset.rb b/support/ruby/collins-client/lib/collins/asset.rb index 495de8584..898e910f2 100644 --- a/support/ruby/collins-client/lib/collins/asset.rb +++ b/support/ruby/collins-client/lib/collins/asset.rb @@ -193,6 +193,15 @@ def cpus extract(extras, "HARDWARE", "CPU") || [] end + # @return [Fixnum] Number of GPU's found + def gpu_count + (extract(extras, "HARDWARE", "GPU") || []).length + end + # @return [Array] GPU information + def gpus + extract(extras, "HARDWARE", "GPU") || [] + end + # @return [Array] Disk information def disks extract(extras, "HARDWARE", "DISK") || [] diff --git a/support/ruby/collins-client/spec/collins/asset_spec.rb b/support/ruby/collins-client/spec/collins/asset_spec.rb index ca58dbeac..1567abc5f 100644 --- a/support/ruby/collins-client/spec/collins/asset_spec.rb +++ b/support/ruby/collins-client/spec/collins/asset_spec.rb @@ -96,6 +96,14 @@ end end + context "assets with GPUs should have" do + subject { Collins::Asset.from_json(CollinsFixture.full_asset_with_gpu(true)) } + + it "#gpu_count" do + subject.gpu_count.should == 2 + end + end + context "Update" do it "lshw is not an attribute" do ["lshw","LSHW"].each do |name| diff --git a/support/ruby/collins-client/spec/fixtures/full_asset_with_gpu.json b/support/ruby/collins-client/spec/fixtures/full_asset_with_gpu.json new file mode 100644 index 000000000..332c0fc9a --- /dev/null +++ b/support/ruby/collins-client/spec/fixtures/full_asset_with_gpu.json @@ -0,0 +1 @@ +{"status":"success:ok","data":{"ASSET":{"ID":2,"TAG":"U000006","STATE":{"ID":1,"STATUS":null,"NAME":"NEW","LABEL":"New","DESCRIPTION":"A service in this state is inactive. It does minimal work and consumes minimal resources."},"STATUS":"New","TYPE":"SERVER_NODE","CREATED":"2017-04-26T16:52:36","UPDATED":"2017-04-26T16:52:38","DELETED":null},"HARDWARE":{"CPU":[{"CORES":6,"THREADS":6,"SPEED_GHZ":2.3,"DESCRIPTION":"AMD Opteron(tm) Processor 4174 HE Hynix Semiconductor (Hyundai Electronics)","PRODUCT":"","VENDOR":""},{"CORES":6,"THREADS":6,"SPEED_GHZ":2.3,"DESCRIPTION":"AMD Opteron(tm) Processor 4174 HE Hynix Semiconductor (Hyundai Electronics)","PRODUCT":"","VENDOR":""}],"GPU":[{"DESCRIPTION":"GM200GL [Quadro M6000] - NVIDIA Corporation","PRODUCT":"","VENDOR":""},{"DESCRIPTION":"GM200GL [Quadro M6000] - NVIDIA Corporation","PRODUCT":"","VENDOR":""}],"MEMORY":[{"SIZE":0,"SIZE_S":"0","SIZE_HUMAN":"0 Bytes","BANK":0,"DESCRIPTION":"Empty Memory Bank","PRODUCT":"","VENDOR":""},{"SIZE":0,"SIZE_S":"0","SIZE_HUMAN":"0 Bytes","BANK":1,"DESCRIPTION":"Empty Memory Bank","PRODUCT":"","VENDOR":""},{"SIZE":8589934592,"SIZE_S":"8589934592","SIZE_HUMAN":"8.00 GB","BANK":2,"DESCRIPTION":"DIMM DDR3 Synchronous 1333 MHz (0.8 ns) - Hyundai HMT31GR7BFR4A-H9","PRODUCT":"","VENDOR":""},{"SIZE":0,"SIZE_S":"0","SIZE_HUMAN":"0 Bytes","BANK":3,"DESCRIPTION":"Empty Memory Bank","PRODUCT":"","VENDOR":""},{"SIZE":0,"SIZE_S":"0","SIZE_HUMAN":"0 Bytes","BANK":4,"DESCRIPTION":"Empty Memory Bank","PRODUCT":"","VENDOR":""},{"SIZE":8589934592,"SIZE_S":"8589934592","SIZE_HUMAN":"8.00 GB","BANK":5,"DESCRIPTION":"DIMM DDR3 Synchronous 1333 MHz (0.8 ns) - Hyundai HMT31GR7BFR4A-H9","PRODUCT":"","VENDOR":""},{"SIZE":0,"SIZE_S":"0","SIZE_HUMAN":"0 Bytes","BANK":6,"DESCRIPTION":"Empty Memory Bank","PRODUCT":"","VENDOR":""},{"SIZE":0,"SIZE_S":"0","SIZE_HUMAN":"0 Bytes","BANK":7,"DESCRIPTION":"Empty Memory Bank","PRODUCT":"","VENDOR":""},{"SIZE":8589934592,"SIZE_S":"8589934592","SIZE_HUMAN":"8.00 GB","BANK":8,"DESCRIPTION":"DIMM DDR3 Synchronous 1333 MHz (0.8 ns) - Hyundai HMT31GR7BFR4A-H9","PRODUCT":"","VENDOR":""},{"SIZE":0,"SIZE_S":"0","SIZE_HUMAN":"0 Bytes","BANK":9,"DESCRIPTION":"Empty Memory Bank","PRODUCT":"","VENDOR":""},{"SIZE":0,"SIZE_S":"0","SIZE_HUMAN":"0 Bytes","BANK":10,"DESCRIPTION":"Empty Memory Bank","PRODUCT":"","VENDOR":""},{"SIZE":8589934592,"SIZE_S":"8589934592","SIZE_HUMAN":"8.00 GB","BANK":11,"DESCRIPTION":"DIMM DDR3 Synchronous 1333 MHz (0.8 ns) - Hyundai HMT31GR7BFR4A-H9","PRODUCT":"","VENDOR":""}],"NIC":[],"DISK":[],"BASE":{"DESCRIPTION":"Rack Mount Chassis","PRODUCT":"PowerEdge C6105 (N/A)","VENDOR":"Winbond Electronics","SERIAL":"FZ22YQ1"}},"LLDP":{"INTERFACES":[{"NAME":"eth0","CHASSIS":{"NAME":"accessB07.corp.uhq.ua.tc","ID":{"TYPE":"mac","VALUE":"ec:3e:f7:1e:77:c0"},"DESCRIPTION":"Juniper Networks, Inc. ex4300-48p Ethernet Switch, kernel JUNOS 14.1X53-D30.3, Build date: 2015-10-02 12:40:24 UTC Copyright (c) 1996-2015 Juniper Networks, Inc."},"PORT":{"ID":{"TYPE":"local","VALUE":"529"},"DESCRIPTION":"ge-0/0/12"},"VLANS":[{"ID":40,"NAME":"vlan-40"}]}]},"IPMI":{"ASSET_ID":2,"ASSET_TAG":"U000006","IPMI_USERNAME":"root","IPMI_PASSWORD":"YCM0PCt6y37uJsHb","IPMI_GATEWAY":"172.16.32.1","IPMI_ADDRESS":"172.16.32.20","IPMI_NETMASK":"255.255.240.0","ID":2},"ADDRESSES":[],"POWER":[],"ATTRIBS":{"0":{"CHASSIS_TAG":"U000006"}}}} diff --git a/support/ruby/collins-client/spec/support/collins_fixture.rb b/support/ruby/collins-client/spec/support/collins_fixture.rb index e29e5e716..a5630ef6b 100644 --- a/support/ruby/collins-client/spec/support/collins_fixture.rb +++ b/support/ruby/collins-client/spec/support/collins_fixture.rb @@ -30,6 +30,9 @@ def partial_asset_no_state json = false def basic_log json=false get_fixture_data 'basic_log.json', json end + def full_asset_with_gpu json=false + get_fixture_data 'full_asset_with_gpu.json', json + end def data name File.read(fixture_file(name)) From 63a25f17529c5996eed66125120c5e2be4fe3578 Mon Sep 17 00:00:00 2001 From: Jacob Yundt Date: Fri, 5 May 2017 12:12:52 -0400 Subject: [PATCH 10/14] Update docker/validations.conf to include GpuConfg --- conf/docker/validations.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/docker/validations.conf b/conf/docker/validations.conf index a46e7bc4a..3e7c250ad 100644 --- a/conf/docker/validations.conf +++ b/conf/docker/validations.conf @@ -15,6 +15,7 @@ config.validations = [ collins.util.config.CryptoConfig, collins.util.config.IpmiConfig, collins.util.config.LshwConfig, + collins.util.config.GpuConfig, collins.util.config.LldpConfig, collins.util.config.NodeclassifierConfig, collins.util.power.PowerConfiguration, From f301fd99f9f703ab51b302ccb44ce79d828403ce Mon Sep 17 00:00:00 2001 From: Jacob Yundt Date: Tue, 16 May 2017 15:58:31 -0400 Subject: [PATCH 11/14] Incorporate Dynamic Enum fix Related to tumblr/collins#547 --- app/collins/models/AssetMeta.scala | 4 ++++ app/collins/models/LshwHelper.scala | 2 ++ app/collins/models/shared/CommonHelper.scala | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/collins/models/AssetMeta.scala b/app/collins/models/AssetMeta.scala index 43d5c9ace..595810439 100644 --- a/app/collins/models/AssetMeta.scala +++ b/app/collins/models/AssetMeta.scala @@ -212,5 +212,9 @@ object AssetMeta extends Schema with AnormAdapter[AssetMeta] with AssetMetaKeys def getValues(): Seq[AssetMeta] = { Seq(BaseDescription, BaseProduct, BaseVendor, BaseSerial, GpuCount, GpuDescription) } + + def getLshwValues(): Set[AssetMeta] = { + Set(BaseDescription, BaseProduct, BaseVendor, BaseSerial, GpuCount, GpuDescription) + } } } diff --git a/app/collins/models/LshwHelper.scala b/app/collins/models/LshwHelper.scala index 11c5ef471..521eee46c 100644 --- a/app/collins/models/LshwHelper.scala +++ b/app/collins/models/LshwHelper.scala @@ -35,6 +35,8 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { DiskStorageTotal ) + override val managedDynamicTags = AssetMeta.DynamicEnum.getLshwValues() + def construct(asset: Asset, lshw: LshwRepresentation): Seq[AssetMetaValue] = { collectCpus(asset, lshw) ++ collectGpus(asset, lshw) ++ diff --git a/app/collins/models/shared/CommonHelper.scala b/app/collins/models/shared/CommonHelper.scala index 142b2341f..dde068d3b 100644 --- a/app/collins/models/shared/CommonHelper.scala +++ b/app/collins/models/shared/CommonHelper.scala @@ -10,6 +10,7 @@ trait CommonHelper[T] { type FilteredSeq[T1] = Tuple2[Seq[T1], Map[Int, Seq[MetaWrapper]]] val managedTags: Set[AssetMeta.Enum] + val managedDynamicTags: Set[AssetMeta] = Set() /** * Construct an appropriate AssetMetaValue sequence from the representation @@ -27,7 +28,7 @@ trait CommonHelper[T] { def updateAsset(asset: Asset, rep: T): Boolean = { val mvs = construct(asset, rep) if (!managedTags.isEmpty) { - AssetMetaValue.deleteByAssetAndMetaId(asset, managedTags.map(_.id.toLong)) + AssetMetaValue.deleteByAssetAndMetaId(asset, ((managedTags.map(_.id.toLong) ++ managedDynamicTags.map(_.id)))) } mvs.size == AssetMetaValue.create(mvs) From d019c27fb30c1541dbb31de075a834283154060a Mon Sep 17 00:00:00 2001 From: Jacob Yundt Date: Fri, 19 May 2017 09:37:22 -0400 Subject: [PATCH 12/14] Additional gpu support fixup - Split 'description' -> 'product' and 'vendor' based on PCI enumeration - Remove static GPU_COUNT - Cleanup hwdetails view to include GPU product, GPU vendor - Modify hwdetails view to only display GPUs info if GPUs are present - Whitelist NVIDIA GPUs by default - Rename GPU whitelist config param to avoid stutter --- app/collins/models/AssetMeta.scala | 8 ++++---- app/collins/models/LshwHelper.scala | 12 +++++++----- app/collins/util/config/GpuConfig.scala | 4 ++-- app/collins/util/parsers/LshwParser.scala | 2 +- app/views/asset/show_hwdetails.scala.html | 7 +++++-- app/views/asset/show_overview.scala.html | 1 + conf/evolutions/collins/14.sql | 8 ++++---- conf/test_base.conf | 4 ---- 8 files changed, 24 insertions(+), 22 deletions(-) diff --git a/app/collins/models/AssetMeta.scala b/app/collins/models/AssetMeta.scala index 595810439..8ccd6921e 100644 --- a/app/collins/models/AssetMeta.scala +++ b/app/collins/models/AssetMeta.scala @@ -206,15 +206,15 @@ object AssetMeta extends Schema with AnormAdapter[AssetMeta] with AssetMetaKeys val BaseProduct = findOrCreateFromName("BASE_PRODUCT") val BaseVendor = findOrCreateFromName("BASE_VENDOR") val BaseSerial = findOrCreateFromName("BASE_SERIAL") - val GpuCount = findOrCreateFromName("GPU_COUNT") - val GpuDescription = findOrCreateFromName("GPU_DESCRIPTION") + val GpuProduct= findOrCreateFromName("GPU_PRODUCT") + val GpuVendor = findOrCreateFromName("GPU_VENDOR") def getValues(): Seq[AssetMeta] = { - Seq(BaseDescription, BaseProduct, BaseVendor, BaseSerial, GpuCount, GpuDescription) + Seq(BaseDescription, BaseProduct, BaseVendor, BaseSerial, GpuProduct, GpuVendor) } def getLshwValues(): Set[AssetMeta] = { - Set(BaseDescription, BaseProduct, BaseVendor, BaseSerial, GpuCount, GpuDescription) + Set(BaseDescription, BaseProduct, BaseVendor, BaseSerial, GpuProduct, GpuVendor) } } } diff --git a/app/collins/models/LshwHelper.scala b/app/collins/models/LshwHelper.scala index 521eee46c..770db0861 100644 --- a/app/collins/models/LshwHelper.scala +++ b/app/collins/models/LshwHelper.scala @@ -96,17 +96,18 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { val gpuSeq = meta.foldLeft(Seq[Gpu]()) { case (seq, map) => val groupId = map._1 val wrapSeq = map._2 - val descr = amfinder(wrapSeq, GpuDescription, _.toString, "") - if (descr.isEmpty) { + val product = amfinder(wrapSeq, GpuProduct, _.toString, "") + val vendor= amfinder(wrapSeq, GpuVendor, _.toString, "") + if (product.isEmpty || vendor.isEmpty) { seq } else { - Gpu(descr, "", "") +: seq + Gpu("", product, vendor) +: seq } } val filteredMeta = meta.map { case(groupId, metaSeq) => val newSeq = filterNot( metaSeq, - Set(GpuDescription.id) + Set(GpuProduct.id, GpuVendor.id) ) groupId -> newSeq } @@ -121,7 +122,8 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { val groupId = run._1 val total = run._2 val res: Seq[AssetMetaValue] = Seq( - AssetMetaValue(asset, GpuDescription.id, groupId, "%s - %s".format(gpu.product, gpu.vendor)) + AssetMetaValue(asset, GpuProduct.id, groupId, gpu.product.toString), + AssetMetaValue(asset, GpuVendor.id, groupId, gpu.vendor.toString) ) (groupId + 1, total ++ res) }._2 diff --git a/app/collins/util/config/GpuConfig.scala b/app/collins/util/config/GpuConfig.scala index f88aeb9fc..934c9508d 100644 --- a/app/collins/util/config/GpuConfig.scala +++ b/app/collins/util/config/GpuConfig.scala @@ -4,9 +4,9 @@ object GpuConfig extends Configurable { override val namespace = "gpu" override val referenceConfigFilename = "gpu_reference.conf" - def gpuVendors= getStringSet("gpuVendors") + def supportedVendorStrings= getStringSet("supportedVendorStrings", Set("NVIDIA Corporation")) override protected def validateConfig() { - gpuVendors + supportedVendorStrings } } diff --git a/app/collins/util/parsers/LshwParser.scala b/app/collins/util/parsers/LshwParser.scala index c3c5fc122..dbe61db47 100644 --- a/app/collins/util/parsers/LshwParser.scala +++ b/app/collins/util/parsers/LshwParser.scala @@ -84,7 +84,7 @@ class LshwParser(txt: String) extends CommonParser[LshwRepresentation](txt) { } val gpuMatcher: PartialFunction[NodeSeq, Gpu] = { - case n if ((n \ "@class" text) == "display" && GpuConfig.gpuVendors.exists(s => (n \\ "vendor" text).contains(s))) => { + case n if ((n \ "@class" text) == "display" && GpuConfig.supportedVendorStrings.exists(s => (n \\ "vendor" text).contains(s))) => { val asset = getAsset(n) Gpu(asset.description, asset.product, asset.vendor) } diff --git a/app/views/asset/show_hwdetails.scala.html b/app/views/asset/show_hwdetails.scala.html index 575c0eab2..837a6d59e 100644 --- a/app/views/asset/show_hwdetails.scala.html +++ b/app/views/asset/show_hwdetails.scala.html @@ -73,22 +73,25 @@

CPU Collected CPU Information

GPU
Total GPUs@aa.lshw.gpuCount
Memory
@id@cpu.description @gpu.description
+ @if(aa.lshw.gpuCount > 0) {

GPU Collected GPU Information

- + @aa.lshw.gpus.zipWithIndex.map { case(gpu,id) => - + + }
IdDescriptionIdDescriptionVendor
@id@gpu.description@gpu.product@gpu.vendor
+ }

Memory Collected Memory Information

diff --git a/app/views/asset/show_overview.scala.html b/app/views/asset/show_overview.scala.html index 56e7a72d0..aeb67c899 100644 --- a/app/views/asset/show_overview.scala.html +++ b/app/views/asset/show_overview.scala.html @@ -204,6 +204,7 @@

Hardware Summary Summary of system components reported by LSHW@{if (aa.lshw.hasHyperthreadingEnabled) "Yes" else "No"} +

diff --git a/conf/evolutions/collins/14.sql b/conf/evolutions/collins/14.sql index 7acd7ddc0..77688c71a 100644 --- a/conf/evolutions/collins/14.sql +++ b/conf/evolutions/collins/14.sql @@ -2,10 +2,10 @@ # --- !Ups -INSERT INTO asset_meta (name, priority, label, description) VALUES ('GPU_COUNT', -1, 'GPU Count', 'Number of physical GPUs in asset'); -INSERT INTO asset_meta (name, priority, label, description) VALUES ('GPU_DESCRIPTION', -1, 'GPU Description', 'GPU description, vendor labels'); +INSERT INTO asset_meta (name, priority, label, description) VALUES ('GPU_PRODUCT', -1, 'GPU Product', 'GPU product (description of GPU)'); +INSERT INTO asset_meta (name, priority, label, description) VALUES ('GPU_VENDOR', -1, 'GPU Vendor', 'GPU vendor'); # --- !Downs -DELETE FROM asset_meta WHERE name ='GPU_COUNT' -DELETE FROM asset_meta WHERE name ='GPU_DESCRIPTION' +DELETE FROM asset_meta WHERE name ='GPU_VENDOR' +DELETE FROM asset_meta WHERE name ='GPU_PRODUCT' diff --git a/conf/test_base.conf b/conf/test_base.conf index 687afaa27..ba6aaaabe 100644 --- a/conf/test_base.conf +++ b/conf/test_base.conf @@ -282,10 +282,6 @@ lshw { lshw.defaultNicCapacity=10000000000 } -gpu { - gpuVendors = ["NVIDIA Corporation"] -} - include "authentication.conf" # Set logging properties in logger.xml or dev_logger.xml From 7212e38df521774b6aa584a96529d5efadf4fec8 Mon Sep 17 00:00:00 2001 From: Jacob Yundt Date: Fri, 19 May 2017 10:11:01 -0400 Subject: [PATCH 13/14] Add two additional GPU tests New lshw output provided from a Dell device with one GPU. --- test/collins/models/LshwHelperSpec.scala | 9 +- .../collins/util/parsers/LshwParserSpec.scala | 12 +- test/resources/lshw-dell.xml | 837 ++++++++++++++++++ 3 files changed, 856 insertions(+), 2 deletions(-) create mode 100644 test/resources/lshw-dell.xml diff --git a/test/collins/models/LshwHelperSpec.scala b/test/collins/models/LshwHelperSpec.scala index e394354e4..9704d0108 100644 --- a/test/collins/models/LshwHelperSpec.scala +++ b/test/collins/models/LshwHelperSpec.scala @@ -88,7 +88,14 @@ class LshwHelperSpec extends mutable.Specification { LshwHelper.updateAsset(asset, parsed()) asset.getMetaAttribute(AssetMeta.Enum.DiskType.toString) must beNone } - "with an NVIDIA GPU" in new LshwCommonHelper("lshw-gpu.xml") { + "with a dual NVIDIA GPU" in new LshwCommonHelper("lshw-gpu.xml") { + val lshw = parsed() + val stub = getStub() + val constructed: Seq[AssetMetaValue] = LshwHelper.construct(stub, lshw) + val reconstructed = LshwHelper.reconstruct(stub, metaValue2metaWrapper(constructed))._1 + lshw mustEqual reconstructed + } + "with a single NVIDIA GPU" in new LshwCommonHelper("lshw-dell.xml") { val lshw = parsed() val stub = getStub() val constructed: Seq[AssetMetaValue] = LshwHelper.construct(stub, lshw) diff --git a/test/collins/util/parsers/LshwParserSpec.scala b/test/collins/util/parsers/LshwParserSpec.scala index e856526d7..3c0d225b0 100644 --- a/test/collins/util/parsers/LshwParserSpec.scala +++ b/test/collins/util/parsers/LshwParserSpec.scala @@ -493,7 +493,7 @@ class LshwParserSpec extends mutable.Specification { } // wonky opterons "Parse GPU server" in { - "quad nvidia GPU server" in new LshwParserHelper("lshw-gpu.xml"){ + "dual nvidia GPU server" in new LshwParserHelper("lshw-gpu.xml"){ val parseResults = parsed() parseResults must beRight parseResults.right.toOption must beSome.which { rep => @@ -503,6 +503,16 @@ class LshwParserSpec extends mutable.Specification { rep.gpuCount mustEqual 2 } } + "Dell single nvidia GPU server" in new LshwParserHelper("lshw-dell.xml"){ + val parseResults = parsed() + parseResults must beRight + parseResults.right.toOption must beSome.which { rep => + rep.cpuCount mustEqual 1 + rep.cpuCoreCount mustEqual 4 + + rep.gpuCount mustEqual 1 + } + } } } // The LSHW parser should diff --git a/test/resources/lshw-dell.xml b/test/resources/lshw-dell.xml new file mode 100644 index 000000000..553cb91ee --- /dev/null +++ b/test/resources/lshw-dell.xml @@ -0,0 +1,837 @@ + + + + + + + + Laptop + Precision 7510 (06D9) + Dell Inc. + [REMOVED] + 64 + + + + + + + + + SMBIOS version 2.8 + DMI version 2.8 + 32-bit processes + + + Motherboard + 0M91XC + Dell Inc. + 0 + A00 + [REMOVED] + + BIOS + Dell Inc. + 0 + 1.9.5 + 12/22/2016 + 65536 + 16711680 + + PCI bus + Plug-and-Play + BIOS EEPROM can be upgraded + BIOS shadowing + Booting from CD-ROM/DVD + Selectable boot path + Enhanced Disk Drive extensions + 5.25" 1.2MB floppy + 3.5" 720KB floppy + 3.5" 2.88MB floppy + Print Screen key + i8042 keyboard controller + INT14 serial line control + INT17 printer control + ACPI + USB legacy emulation + Smart battery + BIOS boot specification + Function-key initiated network service boot + UEFI specification is supported + + + + L1 cache + 43 + L1 Cache + 131072 + 131072 + + Synchronous + Internal + Write-back + Data cache + + + + L1 cache + 44 + L1 Cache + 131072 + 131072 + + Synchronous + Internal + Write-back + Instruction cache + + + + L2 cache + 45 + L2 Cache + 1048576 + 1048576 + + Synchronous + Internal + Write-back + Unified cache + + + + L3 cache + 46 + L3 Cache + 8388608 + 8388608 + + Synchronous + Internal + Write-back + Unified cache + + + + CPU + Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz + Intel Corp. + 47 + cpu@0 + Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz + [REMOVED] + U3E1 + 3371203000 + 3371203000 + 64 + 100000000 + + + + + + + 64bits extensions (x86-64) + mathematical co-processor + FPU exceptions reporting + + virtual mode extensions + debugging extensions + page size extensions + time stamp counter + model-specific registers + 4GB+ memory addressing (Physical Address Extension) + machine check exceptions + compare and exchange 8-byte + on-chip advanced programmable interrupt controller (APIC) + fast system calls + memory type range registers + page global enable + machine check architecture + conditional move instruction + page attribute table + 36-bit page size extensions + + debug trace and EMON store MSRs + thermal control (ACPI) + multimedia extensions (MMX) + fast floating point save/restore + streaming SIMD extensions (SSE) + streaming SIMD extensions (SSE2) + self-snoop + HyperThreading + thermal interrupt and status + pending break event + fast system calls + no-execute bit (NX) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CPU Frequency scaling + + + + System Memory + 48 + System board or motherboard + 34359738368 + + SODIMM Synchronous 2133 MHz (0.5 ns) + HMA82GS6MFR8N-TF + SK Hynix + 0 + [REMOVED] + ChannelA-DIMM0 + 17179869184 + 64 + 2133000000 + + + DIMM [empty] + 1 + ChannelB-DIMM0 + + + SODIMM Synchronous 2133 MHz (0.5 ns) + HMA82GS6MFR8N-TF + SK Hynix + 2 + [REMOVED] + ChannelB-DIMM1 + 17179869184 + 64 + 2133000000 + + + DIMM [empty] + 3 + ChannelA-DIMM1 + + + + Host bridge + Sky Lake Host Bridge/DRAM Registers + Intel Corporation + 100 + pci@0000:00:00.0 + 07 + 32 + 33000000 + + PCI bridge + Sky Lake PCIe Controller (x16) + Intel Corporation + 1 + pci@0000:00:01.0 + 07 + 32 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + PCI Express + + bus mastering + PCI capabilities listing + + + + + + + + + VGA compatible controller + GM107GLM [Quadro M2000M] + NVIDIA Corporation + 0 + pci@0000:01:00.0 + a2 + 64 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + PCI Express + + bus mastering + PCI capabilities listing + extension ROM + + + + + + + + + + + + Audio device + NVIDIA Corporation + NVIDIA Corporation + 0.1 + pci@0000:01:00.1 + a1 + 32 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + PCI Express + bus mastering + PCI capabilities listing + + + + + + + + + Signal processing controller + Intel Corporation + Intel Corporation + 4 + pci@0000:00:04.0 + 07 + 64 + 33000000 + + + + + + Message Signalled Interrupts + Power Management + PCI capabilities listing + + + + + + + + USB controller + Sunrise Point-H USB 3.0 xHCI Controller + Intel Corporation + 14 + pci@0000:00:14.0 + 31 + 64 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + + bus mastering + PCI capabilities listing + + + + + + + + Signal processing controller + Sunrise Point-H Thermal subsystem + Intel Corporation + 14.2 + pci@0000:00:14.2 + 31 + 64 + 33000000 + + + + + Power Management + Message Signalled Interrupts + bus mastering + PCI capabilities listing + + + + + + + Communication controller + Sunrise Point-H CSME HECI #1 + Intel Corporation + 16 + pci@0000:00:16.0 + 31 + 64 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + bus mastering + PCI capabilities listing + + + + + + + + RAID bus controller + SATA Controller [RAID mode] + Intel Corporation + 17 + pci@0000:00:17.0 + 31 + 32 + 66000000 + + + + + + + Message Signalled Interrupts + Power Management + bus mastering + PCI capabilities listing + + + + + + + + + + + + + PCI bridge + Sunrise Point-H PCI Express Root Port #2 + Intel Corporation + 1c + pci@0000:00:1c.0 + f1 + 32 + 33000000 + + + + + + PCI Express + Message Signalled Interrupts + Power Management + + bus mastering + PCI capabilities listing + + + + + + + + PCI bridge + Sunrise Point-H PCI Express Root Port #3 + Intel Corporation + 1c.2 + pci@0000:00:1c.2 + f1 + 32 + 33000000 + + + + + + PCI Express + Message Signalled Interrupts + Power Management + + bus mastering + PCI capabilities listing + + + + + + + Unassigned class + Realtek Semiconductor Co., Ltd. + Realtek Semiconductor Co., Ltd. + 0 + pci@0000:03:00.0 + 01 + 32 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + PCI Express + bus mastering + PCI capabilities listing + + + + + + + + + PCI bridge + Sunrise Point-H PCI Express Root Port #5 + Intel Corporation + 1c.4 + pci@0000:00:1c.4 + f1 + 32 + 33000000 + + + + + + PCI Express + Message Signalled Interrupts + Power Management + + bus mastering + PCI capabilities listing + + + + + + + + + + ISA bridge + Sunrise Point-H LPC Controller + Intel Corporation + 1f + pci@0000:00:1f.0 + 31 + 32 + 33000000 + + + + + + bus mastering + + + + Memory controller + Sunrise Point-H PMC + Intel Corporation + 1f.2 + pci@0000:00:1f.2 + 31 + 32 + 33000000 + + + + + bus mastering + + + + + + + Audio device + Sunrise Point-H HD Audio + Intel Corporation + 1f.3 + pci@0000:00:1f.3 + 31 + 64 + 33000000 + + + + + + Power Management + Message Signalled Interrupts + bus mastering + PCI capabilities listing + + + + + + + + + SMBus + Sunrise Point-H SMBus + Intel Corporation + 1f.4 + pci@0000:00:1f.4 + 31 + 64 + 33000000 + + + + + + + + + + Ethernet interface + Ethernet Connection (2) I219-LM + Intel Corporation + 1f.6 + pci@0000:00:1f.6 + eth0 + 31 + [REMOVED] + 1000000000 + 1000000000 + 32 + 33000000 + + + + + + + + + + + + + + + + Power Management + Message Signalled Interrupts + bus mastering + PCI capabilities listing + + Physical interface + twisted pair + 10Mbit/s + 10Mbit/s (full duplex) + 100Mbit/s + 100Mbit/s (full duplex) + 1Gbit/s (full duplex) + Auto-negotiation + + + + + + + + + 1 + scsi3 + + Emulated device + + + ATA Disk + Samsung SSD 850 + 0.0.0 + scsi@3:0.0.0 + /dev/sda + 8:0 + 2B6Q + [REMOVED] + 1024209543168 + + + + + + + Partitioned disk + MS-DOS partition table + + + EXT4 volume + Linux + 1 + scsi@3:0.0.0,1 + /dev/sda1 + / + /var/lib/docker/aufs + 8:1 + 1.0 + [REMOVED] + 990118936576 + 990118936576 + + + + + + + + + + + + Primary partition + Bootable partition (active) + + Extended Attributes + 4GB+ files + 16TB+ files + directories with 65000+ subdirs + needs recovery + extent-based allocation + + EXT2/EXT3 + initialized volume + + + + Extended partition + 2 + scsi@3:0.0.0,2 + /dev/sda2 + 8:2 + 34088158208 + 34088158208 + + Primary partition + Extended partition + Partitioned disk + Extended partition + + + Linux swap / Solaris partition + 5 + /dev/sda5 + 8:5 + 34088157184 + + No filesystem + + + + + + + + DELL RDYCT71 + LG + 1 + 12/29/2016 + [REMOVED] + Sys. Battery Bay + 90990 + + + + + + From 262c2ea01392b3189c0c853e82d7c52af4bda61b Mon Sep 17 00:00:00 2001 From: Jacob Yundt Date: Mon, 22 May 2017 11:04:36 -0400 Subject: [PATCH 14/14] Remove unnecessary gpuCount. --- app/collins/util/LshwRepresentation.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/app/collins/util/LshwRepresentation.scala b/app/collins/util/LshwRepresentation.scala index d56823d4e..fc03bc59f 100644 --- a/app/collins/util/LshwRepresentation.scala +++ b/app/collins/util/LshwRepresentation.scala @@ -113,7 +113,6 @@ case class LshwRepresentation( (cpuCoreCount == other.cpuCoreCount) && (cpuThreadCount == other.cpuThreadCount) && (cpuSpeed == other.cpuSpeed) && - (gpuCount == other.gpuCount) && (totalMemory.inBytes == other.totalMemory.inBytes) && (memoryBanksUsed == other.memoryBanksUsed) && (memoryBanksUnused == other.memoryBanksUnused) &&
GPU