Tuesday, November 24, 2015

Listing software versions in SCCM

And here is another windows-related posting. So I needed to look for which Windows computers had a given program and which version they had installed. Since over here they use SCCM, I thought it might be something right up its alley. And it was.. after a fashion.

So, under \Monitoring\Overview\Queries it has a query called "All Systems with Specified Product Name and Version,"


which when you run it asks for the, well, product name and version and then returns the hosts that match that. So, when you click it, it pops a window

Where you enter the product name. Once you press "OK" then it asks for the product version. After that it should run and spit out the hosts matching the criteria and some other info, which we do not know what yet since we are good kids and did not look under the skirt.

Thing is, it returned nothing.

Hmmm, maybe I did not enter the proper data. So how about if we pick a program that we know to be installed in at least some of the machines? First we need to see what it looks like under SCCM:

What we are interested on are

  • Product Name = Mozila Firefox 41.0.1 US(x86 en US)
  • Product Version = 41.0.1

Don't ask me why Mozilla decided to put the Product Version in the Product Name; I've asked them before and never had an answer. Just between you and me, it really does annoy me because it caused some issues deploying packages using puppet. That said, I think we should save that conversation for another time.

I think we have been good children for long enough. Time for some skirt pulling! And here is how the query looks like (I did some pretty formatting so we can see what is going on):

select distinct 
   sys.Name, 
   sys.SMSAssignedSites, 
   sys.OperatingSystemNameandVersion, 
   sys.ResourceDomainORWorkgroup, 
   sys.LastLogonUserName, 
   sys.IPAddresses, 
   sys.IPSubnets, 
   sys.ResourceId, 
   sys.ResourceType 
from
   SMS_G_System_SoftwareProduct as prod 
   inner join SMS_R_System as sys 
on 
   sys.ResourceId = prod.ResourceID 
where 
   prod.ProductName like ##PRM:SMS_G_System_SoftwareProduct.ProductName## 
and 
   prod.ProductVersion like ##PRM:SMS_G_System_SoftwareProduct.ProductVersion##

The ##PRM:SMS_G_System_SoftwareProduct.ProductName## means that it will stop and ask for the SMS_G_System_SoftwareProduct.ProductVersion, which means we can have someone run the query and enter the search data without needing to mess with the code. So, we can see what they were trying to accomplish even though it does not work. So, let's do some thinking with our fingers try something else:

select 
distinct 
   SMS_R_System.Name 
from  
   SMS_R_System 
   inner join SMS_G_System_INSTALLED_SOFTWARE 
on 
   SMS_G_System_INSTALLED_SOFTWARE.ResourceId = SMS_R_System.ResourceId 
where 
   SMS_G_System_INSTALLED_SOFTWARE.ARPDisplayName like "Mozila Firefox%"

And that works! It prints out a list of hostnames which have that product. I will not be able to show the screen capture since it would show the name of production machines instead of my lab. So you will have to have some faith. While we are at it, how about if we add more useful info? I don't know about you, but I would like to know which version of the software is installed and when that installation (or upgrade) took place. I will not not comment on the extra attributes we are getting back because I think you can figure out

select 
distinct 
   SMS_R_System.Name,
   SMS_G_System_INSTALLED_SOFTWARE.ProductVersion,
   SMS_G_System_INSTALLED_SOFTWARE.InstallDate
from  
   SMS_R_System 
   inner join SMS_G_System_INSTALLED_SOFTWARE 
on 
   SMS_G_System_INSTALLED_SOFTWARE.ResourceId = SMS_R_System.ResourceId 
where 
   SMS_G_System_INSTALLED_SOFTWARE.ARPDisplayName like "Mozila Firefox%"

We could make this interactive by changing

   SMS_G_System_INSTALLED_SOFTWARE.ARPDisplayName like "Mozila Firefox%"
to
   ##SMS_G_System_INSTALLED_SOFTWARE.ARPDisplayName##
Incidentally, it seems that SMS_G_System_INSTALLED_SOFTWARE.ARPDisplayName gave the same result as SMS_G_System_INSTALLED_SOFTWARE.ProductName, but that does not mean that will always be the case.

Tuesday, November 10, 2015

Memory size and Memory location in Linux

Quick easy post: I right now need to find (I am tying this as I am solving the problem, so this will be a rough post) how many memory slots the motherboard of a machine running Linux (actually Xenserver, but close enough for our needs) has, which ones are being occupied, and which kind of SIMM cards it is using. This machine is in a server room about a mil from me am I do not want to go face the rain to get there. So, how to do the deed?

The Xencenter interface does not seem to be helpful with that, so we will don our battle moustaches (ladies, it is ok to buy a nice handlebar moustache to use in this occasions; the look of your coworkers should be reason enough to do it) and go to command line.

The command in question is dmidecode, which can be found in most Linux distros to probulate the system management BIOS. Some of you have used it before, so let's rush through it a bit. This is how it starts:

# dmidecode 2.11
SMBIOS 2.7 present.
77 structures occupying 4848 bytes.
Table at 0xCF42C000.

Handle 0xDA00, DMI type 218, 11 bytes
OEM-specific Type
        Header and Data:
                DA 0B 00 DA B2 00 17 20 0E 10 01

Handle 0x0000, DMI type 0, 24 bytes
BIOS Information
        Vendor: Dell Inc.
        Version: 2.3.3
        Release Date: 07/10/2014
        Address: 0xF0000
        Runtime Size: 64 kB
        ROM Size: 8192 kB
        Characteristics:
                ISA is supported
                PCI is supported
                PNP is supported
                BIOS is upgradeable
                BIOS shadowing is allowed
                Boot from CD is supported
                Selectable boot is supported
                EDD is supported
                Japanese floppy for Toshiba 1.2 MB is supported (int 13h)
                5.25"/360 kB floppy services are supported (int 13h)
                5.25"/1.2 MB floppy services are supported (int 13h)
                3.5"/720 kB floppy services are supported (int 13h)
                8042 keyboard services are supported (int 9h)
                Serial services are supported (int 14h)
                CGA/mono video services are supported (int 10h)
                ACPI is supported
                USB legacy is supported
                BIOS boot specification is supported
                Function key-initiated network boot is supported
                Targeted content distribution is supported
                UEFI is supported
        BIOS Revision: 2.3

As you can see, the machine in question is a Dell (they do make servers you know; this one is a 1U) and we can see some of its specs. Next would be stuff like CPU specs (cache, features, speed), which we don't care right now. What we care about is the memory:

Memory Device
        Array Handle: 0x1000
        Error Information Handle: Not Provided
        Total Width: 72 bits
        Data Width: 64 bits
        Size: 16384 MB
        Form Factor: DIMM
        Set: 1
        Locator: DIMM_A1
        Bank Locator: Not Specified
        Type: DDR3
        Type Detail: Synchronous Registered (Buffered)
        Speed: 1600 MHz
        Manufacturer: 00CE00B300CE
        Serial Number: 0296F2E0
        Asset Tag: 01150664
        Part Number: M393B2G70EB0-YK0
        Rank: 2
        Configured Clock Speed: 1333 MHz

Handle 0x1101, DMI type 17, 34 bytes
Memory Device
        Array Handle: 0x1000
        Error Information Handle: Not Provided
        Total Width: 72 bits
        Data Width: 64 bits
        Size: 16384 MB
        Form Factor: DIMM
        Set: 1
        Locator: DIMM_A2
        Bank Locator: Not Specified
        Type: DDR3
        Type Detail: Synchronous Registered (Buffered)
        Speed: 1600 MHz
        Manufacturer: 00CE00B300CE
        Serial Number: 0296F43E
        Asset Tag: 01150664
        Part Number: M393B2G70EB0-YK0
        Rank: 2
        Configured Clock Speed: 1333 MHz

Handle 0x1102, DMI type 17, 34 bytes
Memory Device
        Array Handle: 0x1000
        Error Information Handle: Not Provided
        Total Width: 72 bits
        Data Width: 64 bits
        Size: No Module Installed
        Form Factor: DIMM
        Set: 2
        Locator: DIMM_A3
        Bank Locator: Not Specified
        Type: DDR3
        Type Detail: Synchronous
        Speed: Unknown
        Manufacturer:
        Serial Number:
        Asset Tag:
        Part Number:
        Rank: Unknown
        Configured Clock Speed: Unknown

Handle 0x1103, DMI type 17, 34 bytes
Memory Device
[...]

As you can see, we have a 16GB SIMM (fine, be grammar police and call it a DIMM) on DIMM_A1 amd DIMM_A2 slots, but nobody on DIMM_A3; just between us, this machine only has those 2 SIMMs. So, how about we find out how many SIMM slots this machine have?

[root@vmhost3 ~]# dmidecode | grep 'Locator: DIMM_'
        Locator: DIMM_A1
        Locator: DIMM_A2
        Locator: DIMM_A3
        Locator: DIMM_A4
        Locator: DIMM_A5
        Locator: DIMM_A6
[root@vmhost3 ~]#

Hmm, we can do better; let's be lazy and let the script do the count. And, just to show we are good, we will use sed instead of grep because the name is shorter

[root@vmhost3 ~]# dmidecode | sed -n '/Locator: DIMM_/p'|wc -l
6
[root@vmhost3 ~]#

Six slots. Not bad. So, how many of those are being populated? We know that an empty slot is flagged by Size: No Module Installed. Let's then look for the entries without that pattern, which is easy to do using grep:

[root@vmhost3 ~]# dmidecode | grep -A5 'Memory Device' | grep -c 'MB'
2
[root@vmhost3 ~]#

Note we dropped the wc since grep can count how many times we got successful matches. Also, the -A5 means that we are printing the first 5 lines after the matched pattern; this way the second grep has something to bite. How about if we spit out the name of which memory slots have memory and how big they are? And maybe the type and model number while we are at it. Here's how to do the deed using grep:

[root@vmhost3 ~]# dmidecode |  grep -A18  'Memory Device' | grep -B4 -A13 -e 'Size:.* MB' | grep -e 'Locator: D' -e 'Size' -e 'Part Number'
        Size: 16384 MB
        Locator: DIMM_A1
        Part Number: M393B2G70EB0-YK0
        Size: 16384 MB
        Locator: DIMM_A2
        Part Number: M393B2G70EB0-YK0
[root@vmhost3 ~]# 

I used 3 greps here to make it easier to see what is going on:

  1. Fist grep finds from the dmidecode output the entries related to memories and feed the complete entry (each is 18 lines long) to the next grep.
  2. This one then only looks for entries that have memories being reported in megabytes (MB); the fragile assumption here is that if there is a SIMM in the slot, its Size: will be reported as X MB, otherwise as we found out above it will be Size: No Module Installed. The cleverest way to do this is to test for Size: No Module Installed; if it is not there use it. But, I never claimed to be that clever.

    Now, if a matching pattern is found, we print the entire entry for this memory device, hence the -A13 (after) and -B4 (before); they print the lines before and after the one which contains the pattern.

  3. Finally we print only the lines we want to use, namely Part Number, Size, and Locator(which SIMM slot memory is sitting on).

Now, I know how many memory slots are available, which ones are being occupied, and which memory card models are installed. I can now decide if I want to buy more matching ones or lookup the specs and find the largest cards that will work in this device. Not bad for a rainy day.