I was demoing Spacewalk and I realized that it would be a very interesting way to keep inventory and monitor all my systems, not just the *nix based ones. So on a whim I decided to break out my limited Python skills and try to write a simple client that would register a Windows machine. I realize this could be potentially blasphemous, but I thought it might be useful. I am by no means a Windows administrator, but my department has been looking for something that could potentially handle all our machines and something that was, preferably Open Source.

Anyway, I thought I would post the simple python script here and see if you guys thought it might be something that one day could fit into Spacewalk/RHN. I've attached the script to this email. It's probably a bit crude due to my limited Python experience, but surprisingly, I've tested it on XP and Windows 7 and it seems to register a system just fine with an activation key. I've done some of the basic Network Monitoring tests with it too and they seem to work just fine. Thoughts? And please feel free to tell me I'm probably barking up the wrong tree if you do think I am.

--
Jason
# rhn-win-stub-client
#
# this is almost, but not quite, entirely unlike a stipped down,
# proof of concept windows stub client.  It's purpose is
# to daze and confuse the spacewalk server by registering
# a windows machine.  Mostly for inventory and monitoring
# purposes, for those with mixed OS environments, but future
# development could prove interesting if no one shoots the
# idea down entirely.

# PRE-REQUISITS:
#  - Python 2.6 for windows ( http://www.python.org/download/releases/2.6.5/ )
#  - pyOpenSSL 0.9 for windows ( 
http://sourceforge.net/projects/pyopenssl/files/pyopenssl-win/0.9/pyOpenSSL-0.9.win32-py2.6.exe/download
 )
#  - You'll also may need the RHNS-CA-CERT file from a machine with the
#    rhn client installed, but possibly not.  

import os
import sys
import getopt
import socket
import string
import platform
import xmlrpclib

server_url = ""
pretend = 0
def os_info():
    # This may look a bit klugy but it should suffice.
    # only do this on windows nt machines
    if os.name=='nt':
        ver_info = sys.getwindowsversion()
        # This is probably in an incomplete list, but for proof of concept....
        ver_format = ver_info[3], ver_info[0], ver_info[1]
        win_version = {
            (1, 4, 0): '95',
            (1, 4, 10): '98',
            (1, 4, 90): 'ME',
            (2, 4, 0): 'NT',
            (2, 5, 0): '2000',
            (2, 5, 1): 'XP',
            (2, 5, 2): '2003',
            (2, 6, 1): '7'
        } # List is missing all Windows Server identifiers, Vista and any 
mobile verisons.  Possibly
        # more...

        # now attempt to detect the processor arch
        processor_info = platform.processor()
        arch_info = string.split(processor_info)
        arch = arch_info[0]
        if arch == "Intel64":
            arch = "x86_64"
        else:
            # assume, probably wrongly, i386 for now for anything else.
            arch == "i386"

        # then return the version info and arch to the caller.
        if win_version.has_key(ver_format):
            return ["Microsoft Windows", win_version[ver_format], ver_info[4], 
arch]
        else:
            return ["Microsoft Windows", "Unknown", "Unknown", arch]

def reg_system(server):

    print "\n\nRHN Windows Client attempting to register system... "
    # get the os info
    os_version = os_info()
    # this is the bare minimum of what we have to send to register a system.
    auth_dict = { "profile_name": 
string.lower(socket.getfqdn(socket.gethostname())),
              "os_release": os_version[1]+ " " + os_version[2],
              "release_name": os_version[0],
              "architecture": os_version[3],
              "token": "1-winxpkey" }
    # if we are in pretend mode, then  only print the data
    if pretend == 1:
        print "DONE!\n\n"
        print "I would have sent this to the server to register myself:"
        print "\tServer: " + server_url + "\n"
        print "\tInfo: " + str(auth_dict) + "\n\n"
    else:
        # call the remote routine to register the system
        info = server.registration.new_system(auth_dict)
        sysid_file = open(os.path.expanduser("~/rhn_sysid"), "w")
        sysid_file.write(str(info))
        sysid_file.close()

        print "DONE!\n"
    
    update_sys_prof(server)
    

def update_sys_prof(server):

    print "Attempting to update system profile... "
    # get some of our default net info.  There's probably
    # a better way of doing this, but this should be sane enough
    # for P.O.C.
    hostname = string.lower(socket.getfqdn(socket.gethostname()))
    ip_addr= socket.gethostbyname(hostname)

    # XXX: Right now we only know how to update the netinfo
    # more to come...
    net_dict = {}
    net_dict['class'] = "NETINFO"
    net_dict['hostname'] = hostname
    net_dict['ipaddr'] = ip_addr
    
    hw_prof = []
    hw_prof.append(net_dict)


    
    system_id =""
    try:
        # we need a valid local rhn_sysid file.  For now, it's kept in the 
user's
        # home directory, for certainty that we can write to it.
        sysid_file = open(os.path.expanduser("~/rhn_sysid"), "r")
        system_id = sysid_file.read()
        sysid_file.close()
    except IOError, err:
        print "Unable to run update properly, system seems to not be 
registered.\n\n"
        # if we are in pretend mode, try to continue...
        if pretend != 1:
            sys.exit(1)
        else:
            system_id = "<Unknown>"
    
    if pretend == 1:
        # print what we would have sent if we are only pretending
        print "DONE!\n\n"
        print "I would have sent this to the server to update my profile:\n"
        print "\tServer: " + server_url + "\n"
        print "\tHW Profile: " + str(hw_prof) + "\n\n"
    else:
        # call the remote routines to update the system profile
        server.registration.refresh_hw_profile(system_id, hw_prof)
        print "DONE!\n"


# some initial values.
update=0
register=0
activation_key=""
position=0

# now let's parse the command line opts.
try:
    opts, args = getopt.getopt(sys.argv[1:], "", ["update",
                                                  "register",
                                                  "verifyOS",
                                                  "pretend",
                                                  "server=",
                                                  "key="])
except getopt.GetoptError, err:
    #print error on unrecognized option.
    print "Option Error: " + str(err)
    sys.exit(2)
for o, a in opts:
    if o == "--update":
        update=1
    elif o == "--register":
        register=1
    elif o == "--verifyOS":
        print os_info()
        sys.exit(0)
    elif o == "--key":
        activation_key = a
    elif o == "--pretend":
        pretend=1
    elif o == "--server":
        server_url = a
    else:
        print "\nError: Option " + o + " not recognized!\n\n"
        sys.exit(1)
# if we are not pretending, we should have a server URL
# the only option that doesn't require it is --verifyOS
# which prints and exits above.
if pretend != 1 and server_url == "":
    print "\nError: --server option is needed."
    sys.exit(1)

# if no activation key is specified but the user wants to register
# error out for now, because I haven't yet implemented login
# based registering.
if register == 1 and activation_key == "":
    print "\nError: activation key needed to register"
    sys.exit(1)

if update == 1 and register == 1:
    # no need to print an error, because register will
    # run an update. so set update to 0 so it doesn't
    # run twice
    update = 0

# if we are pretending, don't set up the xmlrpc server connection
if pretend == 1:
    server = None
else:
    server = xmlrpclib.ServerProxy(server_url)

# run just the update stuff if that's what the user
# wants or run the full registration and such if
# that's what they specify
if update == 1:
    update_sys_prof(server)
elif register == 1:
    reg_system(server)



_______________________________________________
Spacewalk-devel mailing list
Spacewalk-devel@redhat.com
https://www.redhat.com/mailman/listinfo/spacewalk-devel

Reply via email to