CMS 3D CMS Logo

ExtractAppInfoFromXML.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 """Syntax:
3  ExtracAppInfoFromXML [-sapc] file
4 Parameters:
5  file file from where to read a RCMS configuration
6  -s list application servers found in the XML file
7  -p list the ports used found in the XML file
8  -a list the names of the applications configured in the XML file
9  -c list the cfg (eg dqmfu09-1_cfg.py) files
10 Notes:
11  The default behavior is to present a table organized in the following way
12  SERVER PORT CFG_FILE APP_NAME
13  which is equivalent to using -sapc
14 
15  The options selected and their order will affect teeh fields shown and their
16  respective sorting. eg.
17  -sa will only show SERVER and APP_NAME and will sort first by SERVER and
18  then by APP_NAME
19 
20  OUTPUT is always unique in a per row bases
21 """
22 from __future__ import print_function
23 
24 from builtins import range
25 import sys, os.path
26 from xml.dom import minidom
27 
29 xmldoc=""
30 
31 def printXMLtree(head,l=0,bn=0):
32  tabs=""
33  for a in range(l):
34  tabs+="\t"
35  try:
36  print("[%d-%d-%d]"%(l,bn,head.nodeType)+tabs+"+++++>"+head.tagName)
37  except AttributeError as e:
38  print("[%d-%d-%d]"%(l,bn,head.nodeType)+tabs+"+++++>"+str(e))
39  print("[%d-%d-%d-v]"%(l,bn,head.nodeType)+tabs+"."+ (head.nodeValue or "None"))
40  try:
41  for katt,vatt in head.attributes.items():
42  if katt!="environmentString":
43  print(tabs+"%s=%s"%(katt,vatt))
44  else:
45  print(tabs+"%s= 'Some Stuff'"%(katt,))
46  except:
47  pass
48  i=0
49  for node in head.childNodes:
50  printXMLtree(node,l+1,i)
51  i+=1
52 
53 def compactNodeValue(head):
54  firstborne=None
55  for item in head.childNodes:
56  if item.nodeType == 3:
57  firstborne = item
58  break
59  if not firstborne:
60  return
61  for item in head.childNodes[1:]:
62  if item.nodeType == 3:
63  firstborne.nodeValue+=item.nodeValue
64  item.nodeValue=None
65 
66 
67 def appendDataXML(head):
68  """Parses information that's XML format from value to the Docuemnt tree"""
69  compactNodeValue(head)
70  if head.firstChild.nodeValue:
71  newNode=minidom.parseString(head.firstChild.nodeValue)
72  for node in newNode.childNodes:
73  head.appendChild(node.cloneNode(True))
74  newNode.unlink()
75 
76 def getAppNameFromCfg(filename):
77  """it searches for the line containing the string consumerName, usually
78  found as a property of the process, and returns the set value found.
79  eg.
80  matches line:
81  process.EventStreamHttpReader.consumerName = 'EcalEndcap DQM Consumer'
82  returns:
83  EcalEndcap DQM Consumer
84  """
85  try:
86  f = open(filename)
87  consumer = f.readline()
88  name=""
89  while consumer :
90  consumer=consumer.strip()
91  if "consumerName" in consumer:
92  name=consumer[consumer.index("'")+1:consumer.index("'",consumer.index("'")+1)]
93  break
94  consumer = f.readline()
95  f.close()
96  except:
97  sys.stderr.write("WARNING: Unable to open file: " + filename + " from <configFile> section of XML\n")
98  name = "CONFIG FILE IS M.I.A"
99  return name
100 
101 def getProcNameFromCfg(filename):
102  """it searches for the line containing the string consumerName, usually
103  found as a property of the process, and returns the set value found.
104  eg.
105  matches line:
106  process = cms.Process ("ECALDQM")
107  returns:
108  ECALDQM
109  """
110  try:
111  f = open(filename)
112  except:
113  sys.stderr.write("Unable to open file: " + filename + " from <configFile> section of XML\n")
114  raise IOError
115  consumer = f.readline()
116  name=""
117  while consumer :
118  consumer=consumer.strip()
119  if "cms.Process(" in consumer:
120  name=consumer[consumer.index("(")+2:consumer.index(")")-1]
121  break
122  consumer = f.readline()
123  f.close()
124  return name
125 
126 def filterNodeList(branch1,nodeList):
127  if len(branch1) > 0:
128  branch=branch1[:len(branch1)]
129  idx=0
130  for item in range(len(nodeList)):
131  vals=[v for (k,v) in nodeList[idx].attributes.items()]
132  if branch[0] not in vals:
133  del nodeList[idx]
134  else:
135  idx=idx+1
136  del branch[0]
137  elif len(branch1)==0:
138  return nodeList
139  return filterNodeList(branch,nodeList)
140 
141 
142 def fillTable(order,branch=[]):
143  global xmldoc
144  table={}
145  if len(order)==0:
146  return table
147  key=min(order.keys())
148  k=order[key]
149  order.pop(key)
150  if k=="s":
151  lista=xmldoc.getElementsByTagName("XdaqExecutive")
152  lista=filterNodeList(branch,lista)
153  for item in lista:
154  table[item.attributes["hostname"].value]=""
155  for item in table.keys():
156  table[item]=fillTable(order.copy(),branch + [item])
157  elif k=="a":
158  lista=xmldoc.getElementsByTagName("XdaqExecutive")
159  lista=filterNodeList(branch,lista)
160  for item in lista:
161  pset=item.getElementsByTagName("parameterSet")
162  if len(pset):
163  arch=pset[0].firstChild.nodeValue[5:]
164  appname=getAppNameFromCfg(arch) or getProcNameFromCfg(arch)
165  table[appname]=""
166  else:
167  App=item.getElementsByTagName("xc:Application")
168  table[App[0].attributes["class"].value]=""
169  for item in table.keys():
170  table[item]=fillTable(order.copy(),branch)
171  elif k=="p":
172  lista=xmldoc.getElementsByTagName("XdaqExecutive")
173  lista=filterNodeList(branch,lista)
174  for item in lista:
175  table[item.attributes["port"].value]=""
176  for item in table.keys():
177  table[item]=fillTable(order.copy(),branch + [item])
178  elif k=="c":
179  lista=xmldoc.getElementsByTagName("XdaqExecutive")
180  lista=filterNodeList(branch,lista)
181  for item in lista:
182  pset=item.getElementsByTagName("parameterSet")
183  if not len(pset):
184  table["No additional file"]=""
185  else:
186  table[pset[0].firstChild.nodeValue]=""
187  for item in table.keys():
188  table[item]=fillTable(order.copy(),branch)
189  else:
190  pass
191  return table
192 
193 def SortAndGrid(table,order):
194  """table => {s:{p:{c:{a:{}}}}}"""
195  grid=[]
196  for (server,ports) in table.items():
197  for (port,configfiles) in ports.items():
198  for (configfile,appnames) in configfiles.items():
199  for appname in appnames.keys():
200  line=[]
201  for col in order.values():
202  if col=="s":
203  line.append(server)
204  if col=="p":
205  line.append(port)
206  if col=="c":
207  line.append(configfile)
208  if col=="a":
209  line.append(appname)
210  grid.append(line)
211  grid.sort()
212  return grid
213 
214 def printGrid(grid):
215  numcols=len(grid[0])
216  PPGrid=grid[:]
217  maxs=[]
218  for col in range(numcols):
219  maxs.append(0)
220  for line in grid:
221  for col in range(numcols):
222  if len(line[col])>maxs[col]:
223  maxs[col]=len(line[col])
224  for line in PPGrid:
225  pline=""
226  for col in range(numcols):
227  pline+=line[col].ljust(maxs[col]+2)
228  print(pline)
229 
230 
233 def getAppInfo(XMLf,s=0,a=2,p=1,c=3):
234  """ getAppInfo(XMLf,s=0,a=2,p=1,c=3) takes the file name of a valid RCMS
235  configuration and 4 variables that represent which fields are desired
236  and in which order.
237 
238  It returns a touple containing a directory that contains all the
239  relevant information in the XMLf file and a list of rows each row
240  containing the fiels specified by the other four variables in the r
241  espective order
242 
243  The fields are Servers (s) ports(p) Appnames a.k.a. consumer names(a)
244  and consumer config file. (Note: The consumerName is directly extracted
245  from the config file.) if one field is not desired it should be assigned
246  a value of -1 eg s=-1. other wise their value is mapped from smallest to
247  largest ==> left to right. Note the default values, they will take
248  precedence if not specifyed giving unexpected results
249  """
250  global xmldoc
251  try:
252  os.path.exists(XMLf)
253  except:
254  sys.stderr.write('File doesn\'t exist\n')
255  sys.exit(2)
256  try:
257  xmldoc = minidom.parse(XMLf)
258  except IOError:
259  sys.stderr.write('Unable to locate file ' +XMLf +'\n')
260  return ({},[])
261  except:
262  sys.stderr.write('Parser error\n')
263  return ({},[])
264 
265  configFileNodes=xmldoc.getElementsByTagName("configFile")
266  for node in configFileNodes:
267  appendDataXML(node)
268 
269  order={0:"s",1:"p",3:"a",2:"c"}
270  #try:
271  table=fillTable(order)
272  #except:
273  # return ({},[])
274  del order
275  order={}
276  if a != -1:
277  order[a]="a"
278  if c != -1:
279  order[c]="c"
280  if s != -1:
281  order[s]="s"
282  if p != -1:
283  order[p]="p"
284  grid=SortAndGrid(table,order)
285  #printXMLtree(xmldoc)
286  #Clean Up
287  xmldoc.unlink()
288  return (table,grid)
289 
290 
291 if __name__ == "__main__":
292  XMLfile=""
293  args=sys.argv
294  args.remove(args[0])
295  options=""
296  for arg in args:
297  if arg.startswith("-"):
298  options+=arg.strip("-")
299  else:
300  XMLfile=arg
301  if options.count("s")+options.count("a")+options.count("p")+options.count("c")!=len(options):
302  sys.stderr.write( "Sintax Error unrecognised option" )
303  sys.stderr.write( __doc__ )
304  sys.exit(2)
305  if options.count("s")+options.count("a")+options.count("p")+options.count("c")==0:
306  (apptable,appinfo)=getAppInfo(XMLfile)
307  else:
308  (apptable,appinfo)=getAppInfo(XMLfile,options.find("s"),options.find("a"),options.find("p"),options.find("c"))
309  if appinfo != []:
310  printGrid(appinfo)
311  apptable
def printXMLtree(head, l=0, bn=0)
def fillTable(order, branch=[])
def SortAndGrid(table, order)
def getAppInfo(XMLf, s=0, a=2, p=1, c=3)
getAppInfo #
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
def filterNodeList(branch1, nodeList)
#define str(s)