Re: [HTCondor-devel] Ring in the New Year with new python bindings!


Date: Sat, 29 Dec 2012 12:04:33 -0600
From: Brian Bockelman <bbockelm@xxxxxxxxxxx>
Subject: Re: [HTCondor-devel] Ring in the New Year with new python bindings!
Proposal and design document for inclusion into base Condor:

https://htcondor-wiki.cs.wisc.edu/index.cgi/tktview?tn=3407

Brian

On Dec 28, 2012, at 8:32 PM, Brian Bockelman <bbockelm@xxxxxxxxxxx> wrote:

> Ok, based on input from Burt, I rounded out the functionality a bit - 
> 
> The python-condor module now has much more functionality.  It can submit jobs, remove/hold/release/suspend/continue, and edit jobs.  It can advertise ads into the collector.  It also exposes the parameter subsystem as a dictionary-like object (anyone want to write a configuration validator in python?).
> 
> Submitting via a raw ClassAd interface is a touch "fun" as you get to figure out which magic attributes are required in the job (see https://htcondor-wiki.cs.wisc.edu/index.cgi/tktview?tn=3406).  However, I don't plan on re-implementing condor_submit, so this interface will likely remain developers-only.
> 
> I took the time to refactor a bit to make the API more natural - schedd actions utilize the "Schedd" object and collector actions utilize the "Collector" object.  This seems to be the correct direction to go.
> 
> Enjoy!
> 
> Brian
> 
> PS - Food for thought: Dan noted over IM that utilizing these bindings be a pleasant way to write unit tests.
> 
> [bbockelm@example python-condor]$ python
> Python 2.6.6 (r266:84292, Jun 18 2012, 09:57:52) 
> [GCC 4.4.6 20110731 (Red Hat 4.4.6-3)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> import condor
>>>> import classad
>>>> coll = condor.Collector("red-condor.unl.edu")
>>>> results = coll.query(condor.AdTypes.Startd, "true", ["Name"])
>>>> len(results)
> 3812
>>>> results[0]
> [ Name = "slot1@red-d20n35"; MyType = "Machine"; TargetType = "Job"; CurrentTime = time() ]
>>>> scheddAd = coll.locate(condor.DaemonTypes.Schedd, "red-gw1.unl.edu")
>>>> scheddAd["ScheddIpAddr"]
> '<129.93.239.132:53020>'
>>>> schedd = condor.Schedd(scheddAd)
>>>> results = schedd.query('Owner =?= "cmsprod088"', ["ClusterId", "ProcId"])
>>>> len(results)
> 63
>>>> results[0]
> [ MyType = "Job"; TargetType = "Machine"; ServerTime = 1356722353; ClusterId = 674143; ProcId = 0; CurrentTime = time() ]
>>>> condor.param["COLLECTOR_HOST"]
> 'hcc-briantest.unl.edu'
>>>> schedd = condor.Schedd() # Defaults to the local schedd.
>>>> results = schedd.query()
>>>> results[0]["RequestMemory"]
> ifthenelse(MemoryUsage isnt undefined,MemoryUsage,( ImageSize + 1023 ) / 1024)
>>>> results[0]["RequestMemory"].eval()
> 1L
>>>> ad=classad.parse(open("test.submit.ad"))
>>>> print schedd.submit(ad, 2) # Submits two jobs in the cluster; edit test.submit.ad to preference.
> 110
>>>> print schedd.act(condor.JobAction.Remove, ["111.0", "110.0"])'
> 
>    [
>        TotalNotFound = 0; 
>        TotalPermissionDenied = 0; 
>        TotalAlreadyDone = 0; 
>        TotalJobAds = 2; 
>        TotalSuccess = 2; 
>        TotalChangedAds = 1; 
>        TotalBadStatus = 0; 
>        TotalError = 0
>    ]
>>>> print schedd.act(condor.JobAction.Hold, "Owner =?= \"bbockelm\"")'
> 
>    [
>        TotalNotFound = 0; 
>        TotalPermissionDenied = 0; 
>        TotalAlreadyDone = 0; 
>        TotalJobAds = 2; 
>        TotalSuccess = 2; 
>        TotalChangedAds = 1; 
>        TotalBadStatus = 0; 
>        TotalError = 0
>    ]
>>>> schedd.edit('Owner =?= "bbockelm"', "Foo", classad.ExprTree('"baz"'))
>>>> schedd.edit(["110.0"], "Foo", '"bar"')
>>>> 
> 
> On Dec 28, 2012, at 9:44 AM, Brian Bockelman <bbockelm@xxxxxxxxxxx> wrote:
> 
>> Hi all,
>> 
>> Over Christmas break, I decided to tackle a small project that had been sitting in the back of my mind for awhile - python bindings for ClassAds and HTCondor.
>> 
>> This resulted in two new projects:
>> https://github.com/bbockelm/python-classad
>> https://github.com/bbockelm/python-condor
>> 
>> It utilizes boost.python to do the majority of the lifting.  I try to wrap the "90%" features - things that are needed 90% of the time.  Some of the remaining features are going to take some amount of clever thinking to expose (a gold star to someone who will write the "Why ClassAd::SetParentScope is an unusable interface" rant for me).
>> 
>> The end-result is quite nice for ClassAds.  It can be built on the system based only on the condor-classad-devel, boost-devel, and boost-python RPMs.
>> 
>> The end-result for HTCondor wrappers leaves a bit to be desired.  It requires the source code of HTCondor to be present - and, because some important things are defined in the g++ invocation for HTCondor instead of the config.h header, you may need to twiddle with platfrom-specific defines.  The correct abstractions and API to expose is also not clear; I might be fiddling more in the future.
>> 
>> Having in-process bindings is incredibly useful:
>> - It prevents developers from re-implementing, poorly, bits and pieces of the ClassAd language in order to parse output of Condor tools.
>> - One reason I tackled this project is I'm afraid no sysadmin has sufficient skills to write JobHooks without it (see https://htcondor-wiki.cs.wisc.edu/index.cgi/tktview?tn=3380).
>> - It allows tools to re-use established security sessions.
>> - It allows errors to be handled more cleanly.
>> 
>> I'd really like to make these into a Condor contrib module.  While python-classads is fine stand-alone, the build limitations outlined above makes a strong case for a contrib python-condor.
>> 
>> Anyhow - enjoy the python bindings!  If I missed your favorite ClassAd/Condor feature, patches are accepted!
>> 
>> Brian
>> 
>> [bbockelm@hcc-briantest python-classads]$ python
>> Python 2.6.6 (r266:84292, Jun 18 2012, 09:57:52) 
>> [GCC 4.4.6 20110731 (Red Hat 4.4.6-3)] on linux2
>> Type "help", "copyright", "credits" or "license" for more information.
>>>>> import classad
>>>>> ad = classad.ClassAd()
>>>>> expr = classad.ExprTree("2+2")
>>>>> ad["foo"] = expr
>>>>> print ad["foo"].eval()
>> 4
>>>>> ad["bar"] = 2.1
>>>>> ad["baz"] = classad.ExprTree("time() + 4")
>>>>> print list(ad)
>> ['bar', 'foo', 'baz']
>>>>> print dict(ad.items())
>> {'baz': time() + 4, 'foo': 2 + 2, 'bar': 2.100000000000000E+00}
>>>>> print ad
>> 
>>   [
>>       bar = 2.100000000000000E+00; 
>>       foo = 2 + 2; 
>>       baz = time() + 4
>>   ]
>>>>> ad2=classad.parse(open("test_ad", "r"));
>>>>> ad2["error"] = classad.Value.Error
>>>>> ad2["undefined"] = classad.Value.Undefined
>>>>> print ad2
>> 
>>   [
>>       error = error; 
>>       bar = 2.100000000000000E+00; 
>>       foo = 2 + 2; 
>>       undefined = undefined; 
>>       baz = time() + 4
>>   ]
>>>>> ad2["undefined"]
>> classad.Value.Undefined
>>>>> 
>> 
>> [bbockelm@example python-condor]$ python
>> Python 2.6.6 (r266:84292, Jun 18 2012, 09:57:52) 
>> [GCC 4.4.6 20110731 (Red Hat 4.4.6-3)] on linux2
>> Type "help", "copyright", "credits" or "license" for more information.
>>>>> import condor
>>>>> results = condor.query_collector("red-condor.unl.edu", "true", ["Name"])
>>>>> print len(results)
>> 4130
>>>>> print results[0]
>> 
>>   [
>>       Name = "Nebraska T2@xxxxxxxxxxxxxxxxxx"; 
>>       MyType = "Collector"; 
>>       CurrentTime = time()
>>   ]
>>>>> results = condor.query_collector("red-condor.unl.edu", 'MyType =?= "Scheduler"', ["Name"])
>>>>> print results[0]
>> 
>>   [
>>       Name = "red-gw1.unl.edu"; 
>>       MyType = "Scheduler"; 
>>       NumUsers = 21; 
>>       CurrentTime = time()
>>   ]
>>>>> query = condor.JobQuery()
>>>>> schedd = query.locate("red-condor.unl.edu", "red-gw1.unl.edu")
>>>>> schedd["ScheddIpAddr"]
>> '<129.93.239.132:53020>'
>>>>> results = query.run(schedd, 'Owner =?= "cmsprod088"', ["ClusterId", "ProcID"])
>>>>> len(results)
>> 439
>>>>> results[0]
>> [ MyType = "Job"; TargetType = "Machine"; ServerTime = 1356662680; ClusterId = 670932; ProcID = 0; CurrentTime = time() ]
>>>>> 
>> 
>> 
>> _______________________________________________
>> HTCondor-devel mailing list
>> HTCondor-devel@xxxxxxxxxxx
>> https://lists.cs.wisc.edu/mailman/listinfo/htcondor-devel
> 
> _______________________________________________
> HTCondor-devel mailing list
> HTCondor-devel@xxxxxxxxxxx
> https://lists.cs.wisc.edu/mailman/listinfo/htcondor-devel

Attachment: smime.p7s
Description: S/MIME cryptographic signature

[← Prev in Thread] Current Thread [Next in Thread→]