Sunday, January 31, 2010

OpenBSD and Python

Last time we covered FreeBSD's third party module, freebsd; this time we'll take a quick look at the equivalent openbsd package for the OpenBSD operating system.

$ python2.5
Python 2.5.4 (r254:67916, Jul  1 2009, 11:37:21)
[GCC 3.3.5 (propolice)] on openbsd4
Type "help", "copyright", "credits" or "license" for more information.
>>> import openbsd
>>> dir(openbsd)
['__builtins__', '__doc__', '__file__', '__name__', '__path__', '_ifconfig', '_netstat', '_packetDescriptors', '_pcap', '_sysvar', 'arc4random', 'ifconfig', 'netstat', 'packet', 'pcap', 'utils']

Let's see what all is hidden in that utils item:

>>> dir(openbsd.utils)
['DoubleAssociation', '__builtins__', '__doc__', '__file__', '__name__', 'cksum16', 'ethToBytes', 'ethToStr', 'findLongestSubsequence', 'getBlocks', 'ip6FromPrefix', 'ip6ToBytes', 'ip6ToStr', 'ipFromPrefix', 'ipToBytes', 'ipToStr', 'isIP6Addr', 'isIPAddr', 'isStringLike', 'multichar', 'multiord']

OK, a fair number of network addressing related functions.

help(openbsd.utils.ipFromPrefix)

ipFromPrefix(prefix)
    Produce an IPv4 address (netmask) from a prefix length.

That sounds handy.  Let's give it a shot:

>>> openbsd.utils.ipFromPrefix(24)
'255.255.255.0'

>>> help(openbsd.utils.DoubleAssociation)

Help on class DoubleAssociation in module openbsd.utils:

class DoubleAssociation(__builtin__.dict)
 |  A double-association is a broadminded dictionary - it goes both ways.
 |
 |  The rather simple implementation below requires the keys and values to
 |  be two disjoint sets. That is, if a given value is both a key and a
 |  value in a DoubleAssociation, you get unexpected behaviour.
 |
 |  Method resolution order:
 |      DoubleAssociation
 |      __builtin__.dict
 |      __builtin__.object
 |
 |  Methods defined here:
 |
 |  __init__(self, idict=None)
 |      # FIXME:
 |      #   While DoubleAssociation is adequate for our use, it is not entirely complete:
 |      #       - Deletion should delete both associations
 |      #       - Other dict methods that set values (eg. setdefault) will need to be over-ridden.



This one is kind of interesting - let's have a look:

>>> d = {1:'a', 2:'b', 3:'c'}
>>> d.get(1)
'a'
>>> print d.get('a')
None
>>> da = openbsd.utils.DoubleAssociation(d)
>>> da.get(1)
'a'
>>> da.get('a')
1

Just like the doc described it.  Both the keys and the values are keys, if that makes sense.

Back up to the main modules of the openbsd package:

>>> help(openbsd.arc4random)







NAME
    openbsd.arc4random

FILE
    /usr/local/lib/python2.5/site-packages/openbsd/arc4random.so

FUNCTIONS
    getbytes(...)
        Get some random bytes.






And the result -




>>> bytesx = openbsd.arc4random.getbytes(10)
>>> [bytex for bytex in bytesx]
['\xb4', '\xd1', '\x86', '\xb7', 'g', '8', '\x10', '}', '\x8b', '\xe5']



One last module on a more common theme:

NAME
    openbsd.ifconfig - A Python module for querying and manipulating network interfaces.

FILE
    /usr/local/lib/python2.5/site-packages/openbsd/ifconfig.py

CLASSES
    __builtin__.int(__builtin__.object)
        FlagVal
    __builtin__.object
        Flags
        IFConfig
        Interface
        MTU
        Media
        Metric
    exceptions.Exception(exceptions.BaseException)
        _ifconfig.IfConfigError

    class FlagVal(__builtin__.int)
     |  Method resolution order:
(etc.)
    

>>> intx = openbsd.ifconfig.Interface('rl0')
>>> print intx
rl0: flags=8843 mtu 1500
         media: Ethernet autoselect
         link: 00:30:bd:72:6a:a0
         inet6: fe80:2::230:bdff:fe72:6aa0
         inet: 192.168.100.100
>>> dir(intx)
['Iftype', 'Name', '__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', '_addrToStr', '_addrTypeLookup', '_getAddresses', '_getinfo', '_setflags', '_setmetric', '_setmtu', 'addAddress', 'addresses', 'delAddress', 'flags', 'media', 'metric', 'mtu', 'setAddress']
>>> intx.media
media: Ethernet autoselect
>>> intx.addresses
[{'address': {'sa_family': 18L, 'iftype': 'ETHER', 'address': '00:30:bd:72:6a:a0'}}, {'netmask': {'sa_family': 24L, 'address': 'ffff:ffff:ffff:ffff::'}, 'address': {'sa_family': 24L, 'address': 'fe80:2::230:bdff:fe72:6aa0'}}, {'netmask': {'sa_family': 0L, 'address': None}, 'dstaddr': {'sa_family': 2L, 'address': '192.168.100.255'}, 'address': {'sa_family': 2L, 'address': '192.168.100.100'}}]
>>>   


ifconfig available within Python - sweet.  rl0 is the ethernet device on my old Dell tower.

Examination of the openbsd package shows that it has quite a bit to offer.  If you're using OpenBSD, there's nothing stopping you from doing routine sysadmin tasks with Python.  If not, now you've got a reason to check it out.

Python Modules for the BSD's

Well, for FreeBSD and OpenBSD, at least.  I can't yet vouch for NetBSD and Dragonfly BSD.

First, FreeBSD - the port is named py-freebsd.  Once built, the module can be imported with "import freebsd".

[carl@pcbsd]/usr/local/lib/python2.6/site-packages(158)% python
Python 2.6.2 (r262:71600, Jun 24 2009, 23:31:28)
[GCC 4.2.1 20070719 [FreeBSD]] on freebsd7
Type "help", "copyright", "credits" or "license" for more information.
>>> import freebsd
>>> dir(freebsd)
['__doc__', '__file__', '__name__', '__package__', '__version__', 'chflags', 'const', 'fchflags', 'fstatfs', 'geom_getxml', 'getfsent', 'getfsfile', 'getfsspec', 'getfsstat', 'gethostname', 'getloadavg', 'getlogin', 'getosreldate', 'getpriority', 'getprogname', 'getpwent', 'getpwnam', 'getpwuid', 'getquota', 'getrlimit', 'getrusage', 'ifstats', 'ipstats', 'jail', 'kevent', 'kqueue', 'ktrace', 'lchflags', 'quotaoff', 'quotaon', 'quotasync', 'reboot', 'sendfile', 'sethostname', 'setlogin', 'setpriority', 'setproctitle', 'setprogname', 'setquota', 'setrlimit', 'statfs', 'sysctl', 'sysctldescr', 'sysctlmibtoname', 'sysctlnametomib', 'tcpstats', 'udpstats']



Not a bad collection of utilities.  Let's take a couple for a test drive:

>>> freebsd.gethostname()
'pcbsd'

>>> freebsd.getprogname()
'python'
>>> help(freebsd.jail)  
Help on built-in function jail in module freebsd:

jail(...)
jail(path, hostname, ip_number):
The jail() system call sets up a jail and locks the current process
in it. The ``path'' should be set to the directory which is to be
the root of the prison. The ``hostname'' can be set to the hostname
of the prison. This can be changed from the inside of the prison.
The ``ip_number'' can be set to the IP number assigned to the prison.

>>> # wow, you can set up a jail with python


>>> freebsd.ifstats()
>>> >>> import pprint
>>> pprint.pprint(_)
{'bge0': {'addrlen': 6,
'baudrate': 100000000L,
'collisions': 0L,
'flags': 34883,
'hdrlen': 14,
'hwassist': 7L,
'ibytes': 19222590L,
'ierrors': 0L,
'imcasts': 577L,
'ipackets': 19728L,
'iqdrops': 0L,
'metric': 0L,
'mtu': 1500L,
'name': 'bge0',
'noproto': 0L,
'obytes': 2009038L,
'oerrors': 0L,
'omcasts': 0L,
'opackets': 13285L,
'pcount': 0,
'physical': 0,
'snd_drops': 0,
'snd_len': 0,
'snd_maxlen': 511,
'type': 6},


bge0 is the ethernet device on my Thinkpad.


>>> freebsd.getlogin()
'carl'
>>> freebsd.tcpstats()
>>> pprint.pprint(_)
{'accepts': 0L,
'badsyn': 0L,
'cachedrtt': 147L,
'cachedrttvar': 150L,
'cachedssthresh': 4L,
'closed': 495L,
'connattempt': 360L,
'conndrops': 20L,
'connects': 340L,
'delack': 277L,
'drops': 22L,
'keepdrops': 0L,
'keepprobe': 0L,
'keeptimeo': 0L,
'listendrop': 0L,
'mturesent': 0L,
'pawsdrop': 0L,
'persistdrop': 0L,
'persisttimeo': 0L,
'predack': 0L,
'preddat': 15226L,
'rcvackbyte': 1093284L,
'rcvackpack': 1848L,
'rcvacktoomuch': 0L,
'rcvafterclose': 7L,
'rcvbadoff': 0L,
'rcvbadsum': 0L,
'rcvbyte': 16595286L,
'rcvbyteafterwin': 0L,
'rcvdupack': 232L,
'rcvdupbyte': 88723L,
'rcvduppack': 77L,
'rcvoobyte': 1015050L,
'rcvoopack': 919L,
'rcvpack': 15882L,
'rcvpackafterwin': 0L,
'rcvpartdupbyte': 525L,
'rcvpartduppack': 2L,
'rcvshort': 0L,
'rcvtotal': 18489L,
'rcvwinprobe': 0L,
'rcvwinupd': 3L,
'rexmttimeo': 118L,
'rttupdated': 1817L,
'sc_aborted': 0L,
'sc_added': 0L,
'sc_badack': 0L,
'sc_bucketoverflow': 0L,
'sc_cacheoverflow': 0L,
'sc_completed': 0L,
'sc_dropped': 0L,
'sc_dupsyn': 0L,
'sc_recvcookie': 0L,
'sc_reset': 0L,
'sc_retransmitted': 0L,
'sc_sendcookie': 0L,
'sc_stale': 0L,
'sc_unreach': 0L,
'sc_zonefail': 0L,
'segstimed': 1688L,
'sndacks': 9261L,
'sndbyte': 1098259L,
'sndctrl': 697L,
'sndpack': 1252L,
'sndprobe': 0L,
'sndrexmitbyte': 2252L,
'sndrexmitpack': 2L,
'sndtotal': 12381L,
'sndurg': 0L,
'sndwinup': 1169L,
'timeoutdrop': 9L}

 
22 drops, 9 of them timeouts, and a bunch of other stuff too.

Enough for today.  Next time we'll take a quick look at the Python module for OpenBSD.












Thursday, January 28, 2010

Python Logos III: Pycon India 2009 contest

Just received an e-mail from Noufal this morning (actually it was a comment on one of the previous two logo posts) about the Indian Pycon logo contest last year.  I've already shown the winner in a previous post, but the entries are worth seeing in their own right.  Hats off to the contributors:

** SPECIAL NOTE:  Some of the following logos do not comply with the Python Software Foundation's trademark rules for the use of the logo.  Although there was no harm intended through use in such manner, it's always good to keep the full logo intact (don't split the snakes or take one away!).  My very basic, and perhaps inaccurate understanding is that it's OK to use the logo and even change it's colors, but the shape should remain intact.