Package gavo :: Package web :: Module adminrender
[frames] | no frames]

Source Code for Module gavo.web.adminrender

  1  """ 
  2  A renderer to do RD-based maintainance. 
  3  """ 
  4   
  5  #c Copyright 2008-2019, the GAVO project 
  6  #c 
  7  #c This program is free software, covered by the GNU GPL.  See the 
  8  #c COPYING file in the source distribution. 
  9   
 10   
 11  import sys 
 12  import traceback 
 13   
 14  from nevow import tags as T 
 15   
 16  from gavo import base 
 17  from gavo import stc 
 18  from gavo import svcs 
 19  from gavo.imp import formal 
 20  from gavo.web import common 
 21  from gavo.web import grend 
 22   
 23   
24 -class AdminRenderer(formal.ResourceMixin, 25 grend.CustomTemplateMixin, 26 grend.ServiceBasedPage):
27 """A renderer allowing to block and/or reload services. 28 29 This renderer could really be attached to any service since 30 it does not call it, but it usually lives on //services/overview. 31 It will always require authentication. 32 33 It takes the id of the RD to administer from the path segments 34 following the renderer name. 35 36 By virtue of builtin vanity, you can reach the admin renderer 37 at /seffe, and thus you can access /seffe/foo/q to administer 38 the foo/q RD. 39 """ 40 name = "admin" 41 customTemplate = svcs.loadSystemTemplate("admin.html") 42 clientRD = None 43 # set below when RD loading failed. 44 reloadExc = None 45 reloadTB = None 46
47 - def form_setDowntime(self, ctx):
48 form = formal.Form() 49 form.addField("scheduled", formal.String(), 50 label="Schedule downtime for", 51 description="Note that this is purely informative. The server" 52 " will not take down the services at this point in time." 53 " Leave empty to cancel. This will also be cleared on a" 54 " reload.") 55 form.addAction(self.setDowntime, label="Ok") 56 form.data = { 57 "scheduled": base.getMetaText(self.clientRD, "_scheduledDowntime")} 58 return form
59
60 - def setDowntime(self, ctx, form, data):
61 scheduleFor = data.get("scheduled") 62 if scheduleFor is None: 63 self.clientRD.delMeta("_scheduledDowntime") 64 else: 65 try: 66 stc.parseISODT(scheduleFor) # check syntax 67 self.clientRD.setMeta("_scheduledDowntime", scheduleFor) 68 except stc.STCLiteralError: # bad date syntax 69 raise base.ui.logOldExc( 70 formal.FieldError("Doesn't look like ISO", "scheduleFor"))
71
72 - def form_adminOps(self, ctx):
73 form = formal.Form() 74 if hasattr(self.clientRD, "currently_blocked"): 75 label = "Unblock" 76 else: 77 label = "Block" 78 form.addAction(self.toggleBlock, label=label, name="block") 79 form.addAction(self.reloadRD, label="Reload RD", name="submit") 80 return form
81
82 - def toggleBlock(self, ctx, form, data):
83 if hasattr(self.clientRD, "currently_blocked"): 84 delattr(self.clientRD, "currently_blocked") 85 else: 86 self.clientRD.currently_blocked = True
87
88 - def reloadRD(self, ctx, form, data):
89 # XXX TODO: load the supposedly changed RD here and raise errors before 90 # booting out the old stuff. 91 base.caches.clearForName(self.clientRD.sourceId)
92
93 - def data_blockstatus(self, ctx, data):
94 if hasattr(self.clientRD, "currently_blocked"): 95 return "blocked" 96 return "not blocked"
97
98 - def data_services(self, ctx, data):
99 """returns a sequence of service items belonging to clientRD, sorted 100 by id. 101 """ 102 return sorted(self.clientRD.services)
103 110
111 - def render_rdId(self, ctx, data):
112 return ctx.tag[self.clientRD.sourceId]
113
114 - def render_ifexc(self, ctx, data):
115 """render children if there was an exception during RD load. 116 """ 117 if self.reloadExc is None: 118 return "" 119 else: 120 return ctx.tag
121
122 - def render_exc(self, ctx, data):
123 return ctx.tag[repr(self.reloadExc)]
124
125 - def render_traceback(self, ctx, data):
126 return ctx.tag[self.reloadTB]
127
128 - def renderHTTP(self, ctx):
129 # naked renderer means admin services itself 130 if self.clientRD is None: 131 self.clientRD = base.caches.getRD("__system__/services") 132 return common.runAuthenticated(ctx, "admin", 133 super(AdminRenderer, self).renderHTTP, ctx)
134
135 - def _extractDamageInfo(self):
136 """called when reload of RD failed; leaves exc. info in some attributes. 137 """ 138 type, value = sys.exc_info()[:2] 139 self.reloadExc = value 140 self.reloadTB = traceback.format_exc()
141 142 # the locateChild here is actually the constructor, as it were -- 143 # each request gets a new AdminRender by web.root
144 - def locateChild(self, ctx, segments):
145 rdId = "/".join(segments) 146 try: 147 self.clientRD = base.caches.getRD(rdId) 148 if hasattr(self.clientRD, "getRealRD"): 149 self.clientRD = self.clientRD.getRealRD() 150 151 self.metaCarrier = self.clientRD 152 self.macroPackage = self.clientRD 153 except base.RDNotFound: 154 raise base.ui.logOldExc( 155 svcs.UnknownURI("No such resource descriptor: %s"%rdId)) 156 except Exception: # RD is botched. Clear cache and give an error 157 base.caches.clearForName(rdId) 158 self._extractDamageInfo() 159 return self, ()
160 161 defaultDocFactory = common.doctypedStan( 162 T.html[ 163 T.head[ 164 T.title["Missing Template"]], 165 T.body[ 166 T.p["Admin services are only available with a admin.html template"]] 167 ])
168