Changeset 13789 for fact/tools/PyDimCtrl/fpydim.py
- Timestamp:
- 05/18/12 23:16:43 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
fact/tools/PyDimCtrl/fpydim.py
r13770 r13789 1 1 #!/usr/bin/python -tti 2 3 # for tab completion 2 4 import rlcompleter 3 5 import readline 4 6 readline.parse_and_bind('tab: complete') 5 7 6 import sys 7 import pydim 8 import types 9 import time # for sleep 10 from pprint import pprint 11 from keyword import iskeyword 8 import sys # for sys.exit() during bebugging mostly :-) 9 import types # for dynamic class construction 10 import time # for time.sleep 11 from pprint import pprint # for nice printing 12 13 from keyword import iskeyword # in case dynamic methods are equal to keywords 14 15 import pydim # for the C-API Dim Call Wrappers 16 17 # using this line makes 'export DIM_DNS_NODE=daq' obsolete 12 18 pydim.dic_set_dns_node('daq') 13 19 14 # making server list15 rawlist = pydim.dic_sync_info_service('DIS_DNS/SERVER_LIST','C')16 # the output needs to be treated a bit .. it is a tuple with only one long string in it17 # the string contains | and the strange character \x0018 # I use both to cut the list apart19 rawlist = rawlist[0].split('\x00')20 servers_n_hosts = rawlist[0].split('|')21 server_ids = rawlist[1].split('|')22 23 servers = {}24 for i,snh in enumerate(servers_n_hosts):25 snh = snh.split('@')26 s = snh[0]27 h = snh[1]28 sid = server_ids[i]29 servers[s] = (sid, h)30 31 # delete unneeded vars32 del servers_n_hosts33 del rawlist34 del server_ids35 36 # print servers37 38 # make service list39 services = {}40 dd = {}41 for serv in servers.keys():42 # print serv+'/SERVICE_LIST'43 sl_raw = pydim.dic_sync_info_service(serv+'/SERVICE_LIST','C')[0]44 if serv+'/SERVICE_DESC' in sl_raw:45 sd_raw = pydim.dic_sync_info_service(serv+'/SERVICE_DESC','C')[0]46 else:47 # print "Warning:", serv+'/SERVICE_DESC' , "not in SERVICE_LIST of", serv48 sd_raw = ''49 sl_raw = sl_raw.rstrip('\x00\n')50 sl_raw = sl_raw.replace('\x00','')51 sd_raw = sd_raw.rstrip('\x00\n')52 sl = sl_raw.split('\n')53 sd = sd_raw.split('\n')54 55 # create descripton dict dd from service_desc list sd56 for d_str in sd:57 service,equalsign,desc = d_str.partition('=')58 #if '=' != equalsign:59 # print "Error: server:", serv, "desc:", d_str60 dd[service] = desc61 62 63 services[serv] = {}64 for service in sl:65 service = service.split('|')66 if service[0] in dd:67 services[serv][service[0]] = (68 service[1], service[2], dd[service[0]])69 # else:70 # print service[0], 'has no DESC in SERVICE_DESC'71 72 # pprint( services )73 74 20 class FactDimServer( object ): 75 21 76 def __init__(self, name): 77 self.name = name 78 79 def cmd(self, cmdstr, *args): 80 #args = cmdstr.split(' ') 81 #for i in range(len(args)): 82 # i = len(args)-1-i 83 # if not args[i]: 84 # del args[i] 85 cmdstr=self.name+'/'+cmdstr.upper() 86 # args = tuple(args[1:]) 87 desc = services[self.name][cmdstr.upper()][0] 88 # there is a bug in the pydim library ... 89 # even if a command need no argument 90 # one has to give one ... need to tell Niko about it. 91 if len(desc) == 0: 92 desc = 'I' 93 args=(1,) 94 # print 'cmd: cmdstr:', cmdstr, 95 # print '-args:', args, 96 # print '-desc:', desc 97 pydim.dic_sync_cmnd_service(cmdstr, args, desc, timeout=None) 98 def get(self, service): 99 full_srv_name = self.name+'/'+service.upper() 100 desc = services[self.name][full_srv_name][0] 101 return pydim.dic_sync_info_service(full_srv_name, desc) 102 103 def __call__(self): 104 """ get Server State as numeric code 105 for convenience 106 """ 107 if hasattr(self, 'state'): 108 s = self.state()[0] 109 return int(s[ s.find('[')+1 : s.find(']') ]) 110 else: 111 raise TypeError(self.name+' has no CMD called STATE') 112 113 def wait(self, state_num, timeout=None): 114 """ waits for a certain state 115 BLOCKING 116 returns True if state was reached 117 returns False if timeout occured 118 raises TypeError if Server has no method state 119 """ 120 121 if not hasattr(self, 'state'): 122 raise TypeError(self.name+' has no CMD called STATE') 123 if timeout == None: 124 timeout = float('inf') 125 else: 126 timeout = float(timeout) 127 start = time.time() 128 while not self() == state_num: 129 time.sleep(0.1) 130 if time.time() >= start+timeout: 131 return False 132 return True 22 def __init__(self, name): 23 """ sets name of instance to name of server, all uppercase 24 """ 25 self.name = name.upper() 26 27 def _cmd(self, cmdstr, *args): 28 """ used by all dynamicly created methods, which call a Dim CMD 29 """ 30 cmdstr=self.name+'/'+cmdstr.upper() 31 desc = services[self.name][cmdstr.upper()][0] 32 33 # there is a work around for a bug in pydim 34 # even if a command needs no argument, and desc is also empty string 35 # one has to give one ... need to tell Niko about it. 36 if not desc: 37 desc = 'I' 38 args=(1,) 39 pydim.dic_sync_cmnd_service(cmdstr, args, desc, timeout=None) 40 41 42 def _get(self, service): 43 """ used by all dynamicly created methods, which get a service 44 """ 45 full_srv_name = self.name+'/'+service.upper() 46 desc = services[self.name][full_srv_name][0] 47 return pydim.dic_sync_info_service(full_srv_name, desc) 48 49 50 def __call__(self): 51 """ Wrapper / For Convenience 52 self.state() returns a string (if it exists) 53 *returns* numeric state code, parsed from return of self.state() 54 """ 55 if hasattr(self, 'state'): 56 s = self.state()[0] 57 return int(s[ s.find('[')+1 : s.find(']') ]) 58 else: 59 raise TypeError(self.name+' has no CMD called STATE') 60 61 def wait(self, state_num, timeout=None): 62 """ waits for a certain state 63 BLOCKING 64 returns True if state was reached 65 returns False if timeout occured 66 raises TypeError if Server has no method state 67 """ 68 69 if not hasattr(self, 'state'): 70 raise TypeError(self.name+' has no CMD called STATE') 71 if timeout == None: 72 timeout = float('inf') 73 else: 74 timeout = float(timeout) 75 start = time.time() 76 while not self() == state_num: 77 time.sleep(0.1) 78 if time.time() >= start+timeout: 79 return False 80 return True 81 82 83 84 # utility functions for dynamic addid of methods to classes 85 def add_command(cls, name): 86 meth_name = name.split('/')[1].lower() 87 if iskeyword(meth_name): 88 meth_name += '_cmd' 89 90 # this is the new command, it simple calls the _cmd() method 91 def new_command(self, *args): 92 self._cmd(meth_name, *args) 93 94 new_command.__name__ = meth_name 95 96 # from this line on, the docstring of the method is created 97 if name in dd: 98 if not dd[name]: 99 new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!" 100 else: 101 new_command.__doc__ = dd[name] 102 else: 103 new_command.__doc__ = "-- no DESC found in SERVICE_DESC --" 104 new_command.__doc__ += '\n' 105 new_command.__doc__ += services[name.split('/')[0]][name][0] 106 107 # this line make the new_command() method, a method of the class cls 108 # giving it the name new_command.__name__ 109 setattr( cls, new_command.__name__, new_command) 110 111 # add_getter is very similar to add_command, 112 # the only difference is, that it calls _get() instead of _cmd() 113 # and since _get() has a return value, this return value is vorwarded to the user 114 def add_getter(cls, name): 115 meth_name = name.split('/')[1].lower() 116 if iskeyword(meth_name): 117 meth_name += '_cmd' 118 def new_command(self): 119 return self._get(meth_name) 120 new_command.__name__ = meth_name 121 if name in dd: 122 if not dd[name]: 123 new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!" 124 else: 125 new_command.__doc__ = dd[name] 126 else: 127 new_command.__doc__ = "-- no DESC found in SERVICE_DESC --" 128 new_command.__doc__ += '\n' 129 new_command.__doc__ += services[name.split('/')[0]][name][0] 130 setattr( cls, new_command.__name__, new_command) 131 132 133 134 135 136 # In order to create classes according to the Dim-Servers, currently connected 137 # to the DIS_DNS I have to parse DIS_DNS/SERVER_LIST 138 # This is done in two steps, first I get the list of Server Names from DIS_DNS 139 # and the I get the list of each servers services and cmds, 140 # from each servers SERVICE_LIST and the service/command description 141 # from each servers SERVICE_DESC 142 # I get quite a lot of information, which I store in python dicts, or 143 # even nested dicts, if necessary. 144 145 def ParseDnsServerList(): 146 # making server list 147 rawlist = pydim.dic_sync_info_service('DIS_DNS/SERVER_LIST','C') 148 # the output needs to be treated a bit .. it is a tuple with only one long string in it 149 # the string contains | and the strange character \x00 150 # I use both to cut the list apart 151 rawlist = rawlist[0].split('\x00') 152 servers_n_hosts = rawlist[0].split('|') 153 server_ids = rawlist[1].split('|') 154 155 servers = {} 156 for i,snh in enumerate(servers_n_hosts): 157 snh = snh.split('@') 158 s = snh[0] 159 h = snh[1] 160 sid = server_ids[i] 161 servers[s] = (sid, h) 162 163 return servers 164 165 166 167 # servers should be a dict containing uppercase server names as keys, 168 # the values are not needed, so it might be any iteratable python listlike type 169 # to be precise 170 def ParseServersServiceList( servers ) 171 172 services = {} 173 dd = {} 174 for server in servers: 175 # sl_raw is a tuple, with an really long string, which needs to be parsed 176 sl_raw = pydim.dic_sync_info_service(server+'/SERVICE_LIST','C')[0] 177 178 # even without parsing, I can find out, if this server also gives me a 179 # service description list. In case it does not, this is fine as well 180 # the doc string of the dynamicly created methods, will then contain 181 # a note, that therer was no SERVICE_DESC ... 182 if server+'/SERVICE_DESC' in sl_raw: 183 sd_raw = pydim.dic_sync_info_service(server+'/SERVICE_DESC','C')[0] 184 else: 185 sd_raw = '' 186 187 # now before parsing, I strip off all ASCII zeroes '\x00' and all 188 # line breaks off the *end* of the long string of both 189 # the service list sl 190 # and service description sd 191 # 192 # I think in sl_raw were alse some '\x00' in the middle .. these 193 # are replaced by nothing, in case they are there. 194 sl_raw = sl_raw.rstrip('\x00\n') 195 sl_raw = sl_raw.replace('\x00','') 196 sd_raw = sd_raw.rstrip('\x00\n') 197 198 # The lists are seperated by line breaks, so I split them using this 199 sl = sl_raw.split('\n') 200 sd = sd_raw.split('\n') 201 202 # First I parse the service descriptons, so I have them available, 203 # when I create the dict full of services. 204 # All desciptions look like this 205 # 'SERVER/SERVICE=some descriptive text' or 206 # 'SERVER/SERVICE=' 207 # this I use to create the dictionary. 208 # create descripton dict dd from service_desc list sd 209 for d_str in sd: 210 service,equalsign,desc = d_str.partition('=') 211 #if '=' != equalsign: 212 # print "Error: server:", server, "desc:", d_str 213 dd[service] = desc 214 215 # Now I fill ther services dict. Each server gets a nested dict 216 # inside services. 217 # Each service is explained in a string with a '|' in between. 218 # I use this for spliting. 219 # The string look like this 220 # SERVER/SERVICE|format-desc-str(e.g. I:2;C)|-empty- or CMD or RPC| 221 services[server] = {} 222 for service in sl: 223 service = service.split('|') 224 if service[0] in dd: 225 services[server][service[0]] = ( 226 service[1], service[2], dd[service[0]]) 227 return services 228 229 230 servers = ParseDnsServerList() 231 services = ParseServersServiceList( servers ) 232 133 233 # create one class for each Fact Dim Server 134 234 FactDimServerClasses = [] 135 235 for server_name in servers: 136 137 236 FactDimServerClasses.append( 237 types.ClassType( server_name, (FactDimServer,), {}) ) 138 238 139 239 # create an instace of each of the classes … … 143 243 all_dims = [] 144 244 for i,server_name in enumerate(servers): 145 146 245 new_instance = FactDimServerClasses[i](server_name) 246 all_dims.append( new_instance ) 147 247 del new_instance 148 248 … … 150 250 #print "connecting to Dim Servers... " 151 251 for dim in all_dims: 152 # print dim.name.lower() 153 if dim.name == 'DIS_DNS': 154 continue 155 globals()[dim.name.lower()] = dim 156 dims.append(dim) 157 158 # utility class for dynamic addid of methods to classes 159 def add_command(cls, name): 160 meth_name = name.split('/')[1].lower() 161 if iskeyword(meth_name): 162 meth_name += '_cmd' 163 def new_command(self, *args): 164 self.cmd(meth_name, *args) 165 new_command.__name__ = meth_name 166 if name in dd: 167 if not dd[name]: 168 new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!" 169 else: 170 new_command.__doc__ = dd[name] 171 else: 172 new_command.__doc__ = "-- no DESC found in SERVICE_DESC --" 173 new_command.__doc__ += '\n' 174 new_command.__doc__ += services[name.split('/')[0]][name][0] 175 setattr( cls, new_command.__name__, new_command) 176 177 def add_getter(cls, name): 178 meth_name = name.split('/')[1].lower() 179 if iskeyword(meth_name): 180 meth_name += '_cmd' 181 def new_command(self): 182 return self.get(meth_name) 183 new_command.__name__ = meth_name 184 if name in dd: 185 if not dd[name]: 186 new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!" 187 else: 188 new_command.__doc__ = dd[name] 189 else: 190 new_command.__doc__ = "-- no DESC found in SERVICE_DESC --" 191 new_command.__doc__ += '\n' 192 new_command.__doc__ += services[name.split('/')[0]][name][0] 193 setattr( cls, new_command.__name__, new_command) 252 # print dim.name.lower() 253 if dim.name == 'DIS_DNS': 254 continue 255 globals()[dim.name.lower()] = dim 256 dims.append(dim) 194 257 195 258 for i,dim in enumerate(all_dims): 196 for cmd in services[dim.name]: 197 if 'CMD' in services[dim.name][cmd][1]: 198 cmdname = cmd.split('/')[1] 199 add_command(FactDimServerClasses[i], cmd) 200 elif not services[dim.name][cmd][1]: 201 cmdname = cmd.split('/')[1] 202 add_getter(FactDimServerClasses[i], cmd) 203 259 for cmd in services[dim.name]: 260 if 'CMD' in services[dim.name][cmd][1]: 261 cmdname = cmd.split('/')[1] 262 add_command(FactDimServerClasses[i], cmd) 263 elif not services[dim.name][cmd][1]: 264 cmdname = cmd.split('/')[1] 265 add_getter(FactDimServerClasses[i], cmd) 266 267 ############################################################################## 268 # class for colored printing 204 269 205 270 class bcolors: 206 HEADER = '\033[95m' 207 OKBLUE = '\033[94m' 208 OKGREEN = '\033[92m' 209 WARNING = '\033[93m' 210 FAIL = '\033[91m' 211 ENDC = '\033[0m' 212 213 def disable(self): 214 self.HEADER = '' 215 self.OKBLUE = '' 216 self.OKGREEN = '' 217 self.WARNING = '' 218 self.FAIL = '' 219 self.ENDC = '' 271 HEADER = '\033[95m' 272 OKBLUE = '\033[94m' 273 OKGREEN = '\033[92m' 274 WARNING = '\033[93m' 275 FAIL = '\033[91m' 276 ENDC = '\033[0m' 277 278 def disable(self): 279 self.HEADER = '' 280 self.OKBLUE = '' 281 self.OKGREEN = '' 282 self.WARNING = '' 283 self.FAIL = '' 284 self.ENDC = '' 285 286 ############################################################################## 287 # class which implements colored printing 288 # method calls can be used instead of Python print calls 289 # for conveniently printing colored output. 290 291 220 292 class MSG( bcolors): 221 def __init__(self, verbose = True): 222 self.output = verbose 223 224 def fail(self, text ): 225 text = str(text) 226 if self.output: 227 print bcolors.FAIL + "ERROR:" + bcolors.ENDC, 228 print bcolors.FAIL + text + bcolors.ENDC 229 230 def warn(self, text ): 231 text = str(text) 232 if self.output: 233 print bcolors.WARNING + text + bcolors.ENDC 234 235 def ok(self, text ): 236 text = str(text) 237 if self.output: 238 print bcolors.OKGREEN + text + bcolors.ENDC 239 240 def __call__(self, *args): 241 if self.output: 242 for arg in args: 243 print arg, 244 print 245 293 def __init__(self, verbose = True): 294 """ create MSG instance, 295 default is verbose, 296 sets self.output 297 298 if: 299 self.*output* = True, object behaves as expeted 300 if False, no call return anything 301 """ 302 self.output = verbose 303 304 def fail(self, text ): 305 """ print in RED 306 """ 307 text = str(text) 308 if self.output: 309 print bcolors.FAIL + "ERROR:" + bcolors.ENDC, 310 print bcolors.FAIL + text + bcolors.ENDC 311 312 def warn(self, text ): 313 """ print in YELLOW 314 """ 315 text = str(text) 316 if self.output: 317 print bcolors.WARNING + text + bcolors.ENDC 318 319 def ok(self, text ): 320 """ print in GREEN 321 """ 322 text = str(text) 323 if self.output: 324 print bcolors.OKGREEN + text + bcolors.ENDC 325 326 def __call__(self, *args): 327 """ print as Python print would do 328 """ 329 if self.output: 330 for arg in args: 331 print arg, 332 print 333
Note:
See TracChangeset
for help on using the changeset viewer.