"""provides all lax instances management commands into a single utility script:organization: Logilab:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"importsysimportosimportos.pathasospimporttimeimportreimporturllib2fromurllibimporturlencodefromCookieimportSimpleCookiefromlogilab.common.clcommandsimportCommand,register_commands,main_runfromcubicweb.common.uilibimportremove_html_tagsfromcubicweb.web.views.schemaimportSKIP_TYPESAPPLROOT=osp.abspath(osp.join(osp.dirname(osp.abspath(__file__)),'..'))definitialize_vregistry(applroot):# apply monkey patches firstfromcubicweb.goaimportdo_monkey_patchdo_monkey_patch()fromcubicweb.goa.goavregimportGAEVregistryfromcubicweb.goa.goaconfigimportGAEConfiguration#WebConfiguration.ext_resources['JAVASCRIPTS'].append('DATADIR/goa.js')config=GAEConfiguration('toto',applroot)vreg=GAEVregistry(config)vreg.set_schema(config.load_schema())returnvregdefalistdir(directory):return[osp.join(directory,f)forfinos.listdir(directory)]classLaxCommand(Command):"""base command class for all lax commands creates vreg, schema and calls """min_args=max_args=0defrun(self,args):self.vreg=initialize_vregistry(APPLROOT)self._run(args)classGenerateSchemaCommand(LaxCommand):"""generates the schema's png file"""name='genschema'def_run(self,args):assertnotargs,'no argument expected'fromyamsimportschema2dotschema=self.vreg.schemapath=osp.join(APPLROOT,'data','schema.png')schema2dot.schema2dot(schema,path,#size=size,skiptypes=SKIP_TYPES)print'generated',pathpath=osp.join(APPLROOT,'data','metaschema.png')schema2dot.schema2dot(schema,path)print'generated',pathclassPopulateDataDirCommand(LaxCommand):"""populate instance's data directory according to used cubes"""name='populatedata'def_run(self,args):assertnotargs,'no argument expected'# first clean everything which is a symlink from the data directorydatadir=osp.join(APPLROOT,'data')ifnotosp.exists(datadir):print'created data directory'os.mkdir(datadir)forfilepathinalistdir(datadir):ifosp.islink(filepath):print'removing',filepathos.remove(filepath)cubes=list(self.vreg.config.cubes())+['shared']fortemplincubes:templpath=self.vreg.config.cube_dir(templ)templdatadir=osp.join(templpath,'data')ifnotosp.exists(templdatadir):print'no data provided by',templcontinueforresourceinos.listdir(templdatadir):ifresource=='external_resources':continueifnotosp.exists(osp.join(datadir,resource)):print'symlinked %s from %s'%(resource,templ)os.symlink(osp.join(templdatadir,resource),osp.join(datadir,resource))classNoRedirectHandler(urllib2.HTTPRedirectHandler):defhttp_error_302(self,req,fp,code,msg,headers):raiseurllib2.HTTPError(req.get_full_url(),code,msg,headers,fp)http_error_301=http_error_303=http_error_307=http_error_302classGetSessionIdHandler(urllib2.HTTPRedirectHandler):def__init__(self,config):self.config=configdefhttp_error_303(self,req,fp,code,msg,headers):cookie=SimpleCookie(headers['Set-Cookie'])sessionid=cookie['__session'].valueprint'session id',sessionidsetattr(self.config,'cookie','__session='+sessionid)return1# on exception should be raisedclassURLCommand(LaxCommand):"""abstract class for commands doing stuff by accessing the web instance """min_args=max_args=1arguments='<site url>'options=(('cookie',{'short':'C','type':'string','metavar':'key=value','default':None,'help':'session/authentication cookie.'}),('user',{'short':'u','type':'string','metavar':'login','default':None,'help':'user login instead of giving raw cookie string (require lax ''based authentication).'}),('password',{'short':'p','type':'string','metavar':'password','default':None,'help':'user password instead of giving raw cookie string (require ''lax based authentication).'}),)def_run(self,args):baseurl=args[0]ifnotbaseurl.startswith('http'):baseurl='http://'+baseurlifnotbaseurl.endswith('/'):baseurl+='/'self.base_url=baseurlifnotself.config.cookieandself.config.user:# no cookie specified but a user is. Try to open a session using# given authentication infoprint'opening session for',self.config.useropener=urllib2.build_opener(GetSessionIdHandler(self.config))urllib2.install_opener(opener)data=urlencode(dict(__login=self.config.user,__password=self.config.password))self.open_url(urllib2.Request(baseurl,data))opener=urllib2.build_opener(NoRedirectHandler())urllib2.install_opener(opener)self.do_base_url(baseurl)defbuild_req(self,url):req=urllib2.Request(url)ifself.config.cookie:req.headers['Cookie']=self.config.cookiereturnreqdefopen_url(self,req):try:returnurllib2.urlopen(req)excepturllib2.HTTPError,ex:ifex.code==302:self.error_302(req,ex)elifex.code==500:self.error_500(req,ex)else:raisedeferror_302(self,req,ex):print'authentication required'print('visit %s?vid=authinfo with your browser to get ''authentication info'%self.base_url)sys.exit(1)deferror_500(self,req,ex):print'an unexpected error occured on the server'print('you may get more information by visiting ''%s'%req.get_full_url())sys.exit(1)defextract_message(self,data):match=re.search(r'<div class="message">(.*?)</div>',data.read(),re.M|re.S)ifmatch:msg=remove_html_tags(match.group(1))printmsgreturnmsgdefdo_base_url(self,baseurl):raiseNotImplementedError()classDSInitCommand(URLCommand):"""initialize the datastore"""name='db-init'options=URLCommand.options+(('sleep',{'short':'s','type':'int','metavar':'nb seconds','default':None,'help':'number of seconds to wait between each request to avoid ''going out of quota.'}),)defdo_base_url(self,baseurl):req=self.build_req(baseurl+'?vid=contentinit')whileTrue:try:data=self.open_url(req)excepturllib2.HTTPError,ex:ifex.code==303:# redirectprint'process completed'breakraisemsg=self.extract_message(data)ifmsgandmsg.startswith('error: '):print('you may to cleanup datastore by visiting ''%s?vid=contentclear (ALL ENTITIES WILL BE DELETED)'%baseurl)breakifself.config.sleep:time.sleep(self.config.sleep)classCleanSessionsCommand(URLCommand):"""cleanup sessions on the server. This command should usually be called regularly by a cron job or equivalent. """name="cleansessions"defdo_base_url(self,baseurl):req=self.build_req(baseurl+'?vid=cleansessions')data=self.open_url(req)self.extract_message(data)register_commands([GenerateSchemaCommand,PopulateDataDirCommand,DSInitCommand,CleanSessionsCommand,])defrun():main_run(sys.argv[1:])if__name__=='__main__':run()