Project

General

Profile

« Previous | Next » 

Revision 3f50c558

Added by François ARMAND about 6 years ago

Fixes #11918: Incorrect detection of architecture on Ubuntu 14.04 32 bits

View differences:

inventory-fusion/src/main/scala/com/normation/inventory/provisioning/fusion/FusionReportParsingExtension.scala
package com.normation.inventory.provisioning.fusion
import scala.xml.{Node,NodeSeq}
import scala.xml.Node
import com.normation.inventory.domain.InventoryReport
/**
......
*/
abstract class FusionReportParsingExtension extends PartialFunction[(Node,InventoryReport) , InventoryReport] {
}
}
inventory-fusion/src/main/scala/com/normation/inventory/provisioning/fusion/FusionReportUnmarshaller.scala
package fusion
import com.normation.inventory.domain._
import com.normation.inventory.provisioning.fusion._
import java.io.InputStream
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import java.util.Locale
import com.normation.utils.StringUuidGenerator
import com.normation.utils.Utils._
import java.net.InetAddress
import scala.xml._
import org.xml.sax.SAXParseException
import net.liftweb.common._
import com.normation.inventory.domain.InventoryConstants._
import com.normation.inventory.services.provisioning._
import org.joda.time.format.DateTimeFormatter
import com.normation.utils.Control.sequence
import com.normation.inventory.domain.NodeTimezone
class FusionReportUnmarshaller(
......
//same as above, but handle conversion to int
private[this] def optInt (n:NodeSeq, tag: String): Option[Int] = convert(optText(n \ tag), tag, "Int" , java.lang.Integer.parseInt)
private[this] def optLong (n:NodeSeq, tag: String): Option[Long] = convert(optText(n \ tag), tag, "Long" , java.lang.Long.parseLong)
private[this] def optFloat (n:NodeSeq, tag: String): Option[Float] = convert(optText(n \ tag), tag, "Float" , java.lang.Float.parseFloat)
private[this] def optDouble(n:NodeSeq, tag: String): Option[Double] = convert(optText(n \ tag), tag, "Double", java.lang.Double.parseDouble)
......
)
}
/**
/*
* Insert bios, manufacturer and system serial in the inventory
* If Manufacturer or System Serial Number is already defined, skip them and write
* a warn log
......
report.copy(node = report.node.copy(networks = nets))
}
/*
* Try to normalize ARCH. We want to provide to the user something common: i686, x86_64, ppc64, etc.
* We are going to use https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures
* as reference names.
* Fusion provides // we change to:
* - amd64 => x86_64
* - if OS == AIX => ppc64
* - PowerPC => ppc (AIX already taken care of, and AFAIK we don't have any mean to be more precise, even with CPU info)
* - PowerPC (other cases) => ppc
* - 32-bit / 64-bit (windows) => x86 / x86_64
* - things with x86_64 / x86 / i*86 in their name => x86_64 / x86 / i*86
* - IA-64, i[3-9]86, x86, x86_64, arm.*, other => identical [lower case]
*/
private[this] def normalizeArch(os: OsDetails)(s: String): String = {
val ix86 = """.*(i[3-9]86).*""".r
val x86 = """.*(x86|32-bit).*""".r
val x86_64 = """.*(x86_64|amd64|64-bit).*""".r
val aix = """.*(aix).*""".r
if(os.os == AixOS) {
"ppc64"
} else {
s.toLowerCase() match {
case "powerpc" => "ppc"
// x64_64 must be check before x86 regex
case x86_64(_) => "x86_64"
case x86(_) => "x86"
case ix86(x) => x
case aix(_) => "ppc64"
case x => x
}
}
}
// ******************************************** //
// parsing implementation details for each tags //
// ******************************************** //
......
*
* *** Operating System infos ***
* ARCHNAME : architecture type.
* Ex: "x86_64-linux-gnu-thread-multi"
* We want i686, x86_64, armv7l, etc
* VMSYSTEM : The virtualization technologie used if the machine is a virtual machine.
* Can be: Physical (default), Xen, VirtualBox, Virtual Machine, VMware, QEMU, SolarisZone, Aix LPAR, Hyper-V
*
......
, name = optText(xml\\"NAME")
, ram = optText(xml\\"MEMORY").map(m => MemorySize(m + ramUnit))
, swap = optText(xml\\"SWAP").map(m=> MemorySize(m + swapUnit))
, archDescription = optText(xml\\"ARCHNAME")
// update arch ONLY if it is not yet defined
, archDescription = report.node.archDescription.orElse(optText(xml\\"ARCHNAME").map(normalizeArch(report.node.main.osDetails)))
, lastLoggedUser = optText(xml\\"LASTLOGGEDUSER")
, lastLoggedUserTime = try {
optText(xml\\"DATELASTLOGGEDUSER").map(date => userLoginDateTimeFormat.parseDateTime(date) )
......
def processOsDetails(xml:NodeSeq, report:InventoryReport, contentNode:NodeSeq) : InventoryReport = {
/*
* ARCH : operating system arch (i686, x86_64...)
*
* FULL_NAME : full os description string
* SUSE Linux Enterprise Server 11 (x86_64)
* KERNEL_NAME : the type of OS
......
case _ => None
}
report.copy( node = report.node.copyWithMain(m => m.copy (osDetails = osDetail) ).copy(timezone = timezone) )
// for arch, we want to keep the value only in the case where OPERATINGSYSTEM/ARCH is missing
val arch = optText(xml\\"ARCH").map(normalizeArch(report.node.main.osDetails)).orElse(report.node.archDescription)
report.copy( node = report.node.copyWithMain(m => m.copy (osDetails = osDetail) ).copy(timezone = timezone, archDescription = arch ) )
}
inventory-fusion/src/main/scala/com/normation/inventory/provisioning/fusion/PostUnmarshallCheckConsistency.scala
package com.normation.inventory.provisioning
package fusion
import com.normation.inventory.domain.InventoryReport
import net.liftweb.common._
import scala.xml.NodeSeq
import com.normation.utils.Control.{pipeline, bestEffort}
import com.normation.utils.Control.pipeline
import com.normation.inventory.services.provisioning._
import scala.xml.Elem
inventory-fusion/src/test/scala/com/normation/inventory/provisioning/fusion/TestReportParsing.scala
import org.specs2.runner._
import com.normation.utils.StringUuidGeneratorImpl
import net.liftweb.common._
import scala.xml.XML
import java.io.File
import com.normation.inventory.domain._
......
private[this] implicit class TestParser(parser: FusionReportUnmarshaller) {
def parse(reportRelativePath: String): InventoryReport = {
import java.net.URL
val url = this.getClass.getClassLoader.getResource(reportRelativePath)
if(null == url) throw new NullPointerException(s"Resource with relative path '${reportRelativePath}' is null (missing resource? Spelling? Permissions?)")
val is = url.openStream()
......
"correctly parse the timezone" in {
report.node.timezone must beEqualTo(Some(NodeTimezone("CEST", "+0200")))
}
}
"Arch in Inventory" should {
"be defined for windows 2012" in {
val arch = parser.parse("fusion-report/WIN-AI8CLNPLOV5-2014-06-20-18-15-49.ocs").node.archDescription
arch must beEqualTo(Some("x86_64"))
}
"correctly get the arch when OPERATINGSYSTEM/ARCH is defined" in {
val arch = parser.parse("fusion-report/signed_inventory.ocs").node.archDescription
arch must beEqualTo(Some("x86_64"))
}
"correctly get the arch even if OPERATINGSYSTEM/ARCH is missing" in {
val arch = parser.parse("fusion-report/sles-10-64-sp3-2011-08-23-16-06-17.ocs").node.archDescription
arch must beEqualTo(Some("x86_64"))
}
"be 'ppc64' on AIX" in {
val arch = parser.parse("fusion-report/sovma136-2014-02-10-07-13-43.ocs").node.archDescription
arch must beEqualTo(Some("ppc64"))
}
}
"Agent in Inventory" should {
"should be empty when there is no agent" in {
"be empty when there is no agent" in {
val agents = parser.parse("fusion-report/rudder-tag/minimal-zero-agent.ocs").node.agents.map(_.name).toList
agents must be empty
}
"should have one agent when using community" in {
"have one agent when using community" in {
val agents = parser.parse("fusion-report/rudder-tag/minimal-one-agent.ocs").node.agents.map(_.name).toList
agents == (COMMUNITY_AGENT :: Nil)
}
"should have two agent when using community and nova" in {
"have two agent when using community and nova" in {
val agents = parser.parse("fusion-report/rudder-tag/minimal-two-agents.ocs").node.agents.map(_.name).toList
agents == (COMMUNITY_AGENT :: NOVA_AGENT :: Nil)
}
"should be empty when there is two agents, using two different policy servers" in {
"be empty when there is two agents, using two different policy servers" in {
val agents = parser.parse("fusion-report/rudder-tag/minimal-two-agents-fails.ocs").node.agents.map(_.name).toList
agents must be empty
}

Also available in: Unified diff