summaryrefslogtreecommitdiffstats
path: root/Tasks/distribution/inventory/push-inventory.py
blob: 62153cc950a08a3888e50d2e2d3b87d3ccd6ac82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#!/usr/bin/python
# Copyright (c) 2006 Red Hat, Inc. All rights reserved. This copyrighted material 
# is made available to anyone wishing to use, modify, copy, or 
# redistribute it subject to the terms and conditions of the GNU General 
# Public License v.2.
# 
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Author: Bill Peck
#

import sys, getopt
import xmlrpclib
import string
import os
import commands
import pprint
import math
import re

sys.path.append('.')
sys.path.append("/usr/lib/anaconda")
import smolt
import anaconda_log
import partedUtils
import network

USAGE_TEXT = """
Usage:  push-inventory.py [-d] [[-h <HOSTNAME>] [-S server]]
"""

def push_inventory(hostname, inventory):
   client = xmlrpclib.Server(lab_server)
   #test_log = xmlrpclib.Binary(log)
   try:
      resp = client.machines.update(hostname, inventory)
      if(resp != 0) :
         raise NameError, "ERROR: Pushing Inventory for host %s." % hostname
   except:
      raise

# some machines just fail to boot with kernel-xen package.. but we need xen
# kernel to determine the hvm capability of the box correctly. We'll read
# hvm-capability in xen kernel and the rest in vanilla kernel. 
def read_inventory():
    # get the data from SMOLT but modify it for how RHTS expects to see it
    # Eventually we'll switch over to SMOLT properly.
    data = {}
    if ( os.uname()[2].find("xen") == -1 ):
       data['MODULE'] = []
       data['CPUFLAGS'] = []
       data['PCIID'] = []
       data['USBID'] = []
       data['DISK'] = []      # disk space for each disk
       data['BOOTDISK'] = []
       data['DISKSPACE'] = 0  # total combined diskspace
       data['NR_DISKS'] = 0   # number of spindles
       data['NR_ETH'] = 0       # number of ethX interfaces
       data['NR_IB'] = 0        # number of ibX interfaces

       cpu_info = smolt.read_cpuinfo()
       memory   = smolt.read_memory()
       profile  = smolt.Hardware()

       data['ARCH'] = cpu_info['platform']
       data['CPUSPEED'] = cpu_info['speed']
       try:
           data['CPUFAMILY'] = cpu_info['model_number']
       except:
           data['CPUFAMILY'] = cpu_info['model_rev']
       data['CPUVENDOR'] = cpu_info['type']
       data['CPUMODEL'] = cpu_info['model']
       data['CPUMODELNUMBER'] = cpu_info['model_ver']
       data['PROCESSORS'] = cpu_info['count']
       data['VENDOR'] = "%s" % profile.host.systemVendor
       data['MODEL'] = "%s" % profile.host.systemModel
       data['FORMFACTOR'] = "%s" % profile.host.formfactor

       # Round memory up to the next base 2
       n=0
       memory = int(memory['ram'])
       while memory > ( 2 << n):
           n=n+1
       data['MEMORY'] = 2 << n

       for cpuflag in cpu_info['other'].split(" "):
           data['CPUFLAGS'].append(cpuflag)

       for VendorID, DeviceID, SubsysVendorID, SubsysDeviceID, Bus, Driver, Type, Description in profile.deviceIter():
          if VendorID and DeviceID:
              if Bus == "pci":
                  data['PCIID'].append("%04x:%04x" % ( VendorID, DeviceID))
              if Bus == "usb":
                  data['USBID'].append("%04x:%04x" % ( VendorID, DeviceID))

       modules =  commands.getstatusoutput('/sbin/lsmod')[1].split('\n')[1:]
       for module in modules:
           data['MODULE'].append(module.split()[0])

       # Find Active Storage Driver(s)
       bootdisk = None
       bootregex = re.compile(r'/dev/([^ ]+) on /boot')
       disks = commands.getstatusoutput('/bin/mount')[1].split('\n')[1:]
       for disk in disks:
           if bootregex.search(disk):
               bootdisk = bootregex.search(disk).group(1)

       if bootdisk:
           drivers = commands.getstatusoutput('./getdriver.sh %s' % bootdisk)[1].split('\n')[1:]
           for driver in drivers:
               data['BOOTDISK'].append(driver)
       
       # Find Active Network interface
       iface = None
       for line in  commands.getstatusoutput('route -n')[1].split('\n'):
           if line.find('0.0.0.0') == 0:
               iface = line.split()[-1:][0] #eth0, eth1, etc..
       #Look in /etc/modprobe.conf for driver info..
       if iface and os.path.exists("/etc/modprobe.conf"):
           modprobe = open("/etc/modprobe.conf").read()
           for line in modprobe.split("\n"):
               if line.find(iface) != -1:
                   data['NETWORK'] = line.split()[-1:][0]
 
       # calculating available diskspace 
       diskset = partedUtils.DiskSet()
       diskset.openDevices()
       for diskname in diskset.disks.keys():
           disksize = int(math.ceil(partedUtils.getDeviceSizeMB(diskset.disks[diskname].dev)))
           data['DISK'].append("%d " % (disksize))
           data['DISKSPACE'] += disksize
           data['NR_DISKS'] += 1

       # finding out eth and ib interfaces...
       # TODO: this doesn't check whether or not the interfaces can be brought up on a network.
       #   it should probably check that too.
       eth_pat = re.compile ('^eth\d+$')
       ib_pat  = re.compile ('^ib\d+$')
       net = network.Network()
       for intname in net.available().keys():
           if eth_pat.match(intname):
              data['NR_ETH'] += 1
           elif ib_pat.match(intname):
              data['NR_IB'] += 1

    else:
       data['HVM'] = False
       # checking for whether or not the machine is hvm-enabled.
       caps = ""
       if os.path.exists("/sys/hypervisor/properties/capabilities"):
           caps = open("/sys/hypervisor/properties/capabilities").read()
           if caps.find("hvm") != -1:
              data['HVM'] = True

    return data
   
def usage():
    print USAGE_TEXT
    sys.exit(-1)
   
def main():
    global lab_server, hostname

    lab_server = ''
    hostname = ''
    debug = 0

    if ('LAB_SERVER' in os.environ.keys()):
        lab_server = "http://%s/cgi-bin/rhts/xmlrpc.cgi" % os.environ['LAB_SERVER']
    if ('HOSTNAME' in os.environ.keys()):
        hostname = os.environ['HOSTNAME']

    args = sys.argv[1:]
    try:
        opts, args = getopt.getopt(args, 'dh:S:', ['server=', 'debug', 'hostname='])
    except:
        usage()
    for opt, val in opts:
        if opt in ('-d', '--debug'):
            debug = 1
        if opt in ('-h', '--hostname'):
            hostname = val
        if opt in ('-S', '--server'):
            lab_server = "http://%s/cgi-bin/rhts/xmlrpc.cgi" % val

    inventory = read_inventory()
    if debug:
        print inventory
    else:
        if not hostname:
            print "You must specify a hostname with the -h switch"
            sys.exit(1)

        if not lab_server:
            print "You must specify a lab_server with the -S switch"
            sys.exit(1)

        push_inventory(hostname, inventory)


if __name__ == '__main__':
    main()
    sys.exit(0)