From e175f100247f74c0b714ba404b35258292cce050 Mon Sep 17 00:00:00 2001 From: Gabe Conradi Date: Tue, 7 Mar 2017 16:10:21 -0500 Subject: [PATCH] make lshw base_serial optional and omit dupes from overview drop duplicate BASE_SERIAL attrs add some docs and tooltips to attributes in show_overview fix some tooltips --- app/collins/models/LshwHelper.scala | 13 ++++++++----- app/collins/models/lshw/ServerBase.scala | 4 ++-- app/collins/util/parsers/LldpParser.scala | 1 + app/collins/util/parsers/LshwParser.scala | 5 +++-- app/views/asset/show_overview.scala.html | 21 ++++++++++++++------- 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/app/collins/models/LshwHelper.scala b/app/collins/models/LshwHelper.scala index 4a6f27bb2..72df84c8c 100644 --- a/app/collins/models/LshwHelper.scala +++ b/app/collins/models/LshwHelper.scala @@ -213,14 +213,14 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { val baseDescription = amfinder(seq, BaseDescription, _.toString, "") val baseProduct = amfinder(seq, BaseProduct, _.toString, "") val baseVendor = amfinder(seq, BaseVendor, _.toString, "") - val baseSerial = amfinder(seq, BaseSerial, _.toString, "") + val baseSerial = amfinder(seq, BaseSerial, x => if (x.isEmpty) { None } else { Some(x) }, None) Seq(ServerBase(baseDescription, baseProduct, baseVendor, baseSerial)) }.getOrElse(Nil) val filteredMeta = meta.map { case(groupId, metaSeq) => val newSeq = filterNot( metaSeq, - Set(BaseDescription.id, BaseProduct.id, BaseVendor.id) + Set(BaseDescription.id, BaseProduct.id, BaseVendor.id, BaseSerial.id) ) groupId -> newSeq } @@ -229,12 +229,15 @@ object LshwHelper extends CommonHelper[LshwRepresentation] { protected def collectBase(asset: Asset, lshw: LshwRepresentation): Seq[AssetMetaValue] = { val base = lshw.base - Seq( + val expectedAttrs = Seq( AssetMetaValue(asset, BaseDescription.id, base.description), AssetMetaValue(asset, BaseProduct.id, base.product), - AssetMetaValue(asset, BaseVendor.id, base.vendor), - AssetMetaValue(asset, BaseSerial.id, base.serial) + AssetMetaValue(asset, BaseVendor.id, base.vendor) ) + base.serial match { + case Some(x) => expectedAttrs ++ Seq(AssetMetaValue(asset, BaseSerial.id, base.serial.get)) + case None => expectedAttrs + } } } diff --git a/app/collins/models/lshw/ServerBase.scala b/app/collins/models/lshw/ServerBase.scala index eee1378cf..0400ed353 100644 --- a/app/collins/models/lshw/ServerBase.scala +++ b/app/collins/models/lshw/ServerBase.scala @@ -12,7 +12,7 @@ object ServerBase { (json \ "DESCRIPTION").as[String], (json \ "PRODUCT").as[String], (json \ "VENDOR").as[String], - (json \ "SERIAL").as[String])) + (json \ "SERIAL").asOpt[String])) override def writes(serverbase: ServerBase) = JsObject(Seq( "DESCRIPTION" -> Json.toJson(serverbase.description), "PRODUCT" -> Json.toJson(serverbase.product), @@ -22,7 +22,7 @@ object ServerBase { } case class ServerBase( - description: String = "", product: String = "", vendor: String = "", serial: String = "") extends LshwAsset { + description: String = "", product: String = "", vendor: String = "", serial: Option[String] = None) extends LshwAsset { import ServerBase._ override def toJsValue() = Json.toJson(this) diff --git a/app/collins/util/parsers/LldpParser.scala b/app/collins/util/parsers/LldpParser.scala index 433bea3dd..203ec3346 100644 --- a/app/collins/util/parsers/LldpParser.scala +++ b/app/collins/util/parsers/LldpParser.scala @@ -67,6 +67,7 @@ class LldpParser(txt: String) extends CommonParser[LldpRepresentation](txt) { } protected def findVlans(seq: NodeSeq): Seq[Vlan] = { + // TODO(gabe): make this less brittle and handle missing vlan-id (seq \\ "vlan").foldLeft(Seq[Vlan]()) { case (vseq, vlan) => val id = Option(vlan \ "@vlan-id" text).filter(_.nonEmpty).getOrElse("") diff --git a/app/collins/util/parsers/LshwParser.scala b/app/collins/util/parsers/LshwParser.scala index d1a12a778..97dbfa0d0 100644 --- a/app/collins/util/parsers/LshwParser.scala +++ b/app/collins/util/parsers/LshwParser.scala @@ -184,13 +184,14 @@ class LshwParser(txt: String) extends CommonParser[LshwRepresentation](txt) { // the correct element if ((elem \ "@class" text).toString == "system") { val asset = getAsset(elem) - val serial = (elem \ "serial" text) + // serial may be missing, so be flexible here and allow it to be absent + val serial = (elem \ "serial" headOption).map(_.text) ServerBase(asset.description, asset.product, asset.vendor, serial) } // To spice things up, sometimes we get $everything // instead of just $everything else if (((elem \ "node") \ "@class" text) == "system") { val asset = getAsset(elem \ "node") - val serial = (elem \ "serial" text) + val serial = (elem \ "serial" headOption).map(_.text) ServerBase(asset.description, asset.product, asset.vendor, serial) } else { throw MalformedAttributeException("Expected root class=system node attribute") diff --git a/app/views/asset/show_overview.scala.html b/app/views/asset/show_overview.scala.html index 03a9e50a5..42d611963 100644 --- a/app/views/asset/show_overview.scala.html +++ b/app/views/asset/show_overview.scala.html @@ -24,13 +24,15 @@

Asset Overview System and user attributes

} @if(aa.addresses.size > 0) { - Ip Addresses + IP Addresses @TagDecorator.decorate("IP_ADDRESS", aa.addresses.map(_.dottedAddress).toList, ", ") Primary IP Addresses } - Asset Tag + + Asset Tag + @if(SoftLayerConfig.enabled && SoftLayer.isSoftLayerAsset(aa.asset)) { @slLink(aa.asset, aa.asset.tag) } else { @@ -40,7 +42,7 @@

Asset Overview System and user attributes

@defining(aa.asset.nodeClass){ nodeclass => - Classification + Classification @nodeclass.map { nc => @@ -60,12 +62,12 @@

Asset Overview System and user attributes

} - Asset Type + Asset Type @aa.asset.assetType.label - Asset Status + Asset Status @aa.asset.getStatusName @if(aa.asset.isMaintenance) { See Notes @aa.asset.status.description @@ -76,7 +78,7 @@

Asset Overview System and user attributes

@if(aa.asset.stateId != 0) { @State.findById(aa.asset.stateId).map { state => - Asset State + Asset State @state.label @state.description @@ -94,7 +96,12 @@

Asset Overview System and user attributes

@MetaValueOrderer.order(aa.mvs.filter(_.getName() != "HOSTNAME")).map { case(size, mv) => - @mv.getLabel() @if(size > 1 || mv.getGroupId() != 0){(@mv.getGroupId())} + + @mv.getLabel() @if(size > 1 || mv.getGroupId() != 0){(@mv.getGroupId())} + + @{ mv.getName match {