CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
spec_builder.py
Go to the documentation of this file.
1 #
2 # This file is part of the CernVM File System.
3 #
4 
5 import argparse
6 import csv
7 import os.path
8 
9 from collections import namedtuple
10 
11 # POLICY pdir: Always include the entire (flat) parent directory
12 class SpecPoint:
13  def __init__(self, path, mode):
14  self.path = path
15  self.mode = mode
16  self.subfiles = []
17  def isParentOf(self, path):
18  return path[:len(self.path)+1] == self.path+"/"\
19  or path == self.path or self.path==""
20  def __str__(self):
21  if self.mode==1:
22  return "^" + self.path + "/*"
23  elif self.mode==0:
24  return "^" + (self.path if self.path != "" else "/")
25  def __eq__(self, other):
26  return self.path == other.path
27  def __ne__(self, other):
28  return self.path != other.path
29  def __lt__(self, other):
30  return self.path < other.path
31  def __gt__(self, other):
32  return self.path > other.path
33 
34 def peek(stack, pos = 1):
35  return stack[-pos] if len(stack)>0 else None
36 
37 def get_parent(path):
38  pos = path.rfind("/")
39  return path[:pos] if pos>0 else ""
40 
41 def exact_parser(pathsToInclude):
42  specsToInclude = []
43  for curPoint in pathsToInclude:
44  specPoint = None
45  if curPoint.action in exact_parser.dirFlat:
46  specPoint = SpecPoint(curPoint.path, 1)
47  else:
48  specPoint = SpecPoint(curPoint.path, 0)
49  specsToInclude.append(specPoint)
50  return specsToInclude
51 exact_parser.dirFlat = ["opendir()"]
52 
53 def parent_dir_parser(pathsToInclude):
54  specsToInclude = []
55  # Go through tracer points and build specs based on made calls
56  for curPoint in pathsToInclude:
57  specPoint = None
58  if curPoint.action in parent_dir_parser.parentDirFlat:
59  specPoint = SpecPoint(get_parent(curPoint.path), 1)
60  elif curPoint.action in parent_dir_parser.dirFlat:
61  specPoint = SpecPoint(curPoint.path, 1)
62  else:
63  specPoint = SpecPoint(curPoint.path, 0)
64  specsToInclude.append(specPoint)
65  return specsToInclude
66 
67 
68 parent_dir_parser.parentDirFlat = ["open()"]
69 parent_dir_parser.dirFlat = ["opendir()"]
70 
71 ParsingPolicies = {
72  "pdir": parent_dir_parser,
73  "exact": exact_parser
74 }
75 
76 class TracePoint(namedtuple("TracePoint", ["path", "action"])):
77  def __eq__(self, other):
78  return self.path == other.path
79  def __ne__(self, other):
80  return self.path != other.path
81  def __lt__(self, other):
82  return self.path < other.path
83  def __gt__(self, other):
84  return self.path > other.path
85 
87  def __init__(self, args):
88  print("Parsing file: " + args.infile)
89  print("Output file: " + args.outfile)
90  print("Policy: " + args.policy)
91  print("Filters: " + (",".join(args.filters) if len(args.filters) > 0 else "None"))
92  self.inputName = args.infile
93  self.outputName = args.outfile
94  self.policy = ParsingPolicies[args.policy]
95  self.filters = dict([(f+"()"), True] for f in args.filters)
96  def read_log(self):
97  pathsToInclude = []
98  with open(self.inputName, "r") as logFile:
99  csvLogReader = csv.reader(logFile, delimiter=',', quotechar='"')
100  for row in [r
101  for r in csvLogReader
102  if r[3] not in self.filters and int(r[1])>=0
103  and r[2] not in TraceParser.blacklist]:
104  if row[2] == "@UNKNOWN":
105  print("ERROR: An error occurred during tracing (event code 8)")
106  quit(-1)
107  pathsToInclude.append(TracePoint(row[2], row[3]))
108  specsToInclude = self.policy(pathsToInclude)
109  specsToInclude.sort()
110  rootEl = SpecPoint("", 0)
111  workStack = [rootEl]
112  self.pathSpec = []
113  for specPoint in specsToInclude:
114  while not peek(workStack).isParentOf(specPoint.path):
115  # Backtrack up to nearest parent
116  el = workStack.pop()
117  self.pathSpec.append(el)
118  topEl = peek(workStack)
119  if topEl.path == specPoint.path and topEl.mode < specPoint.mode:
120  # If stack top element is same path: Update if necessary
121  topEl.mode = specPoint.mode
122  elif topEl.path != specPoint.path:
123  # If stack top is some parent: Add if necessary
124  if topEl.mode==0\
125  or topEl.path != get_parent(specPoint.path)\
126  or specPoint.mode!=0:
127  workStack.append(specPoint)
128  self.pathSpec+=workStack
129 
130  def write_spec(self):
131  if not self.pathSpec:
132  print("No path specification created. Please call read_log first")
133  return
134  with open(self.outputName, "w") as specFile:
135  for p in self.pathSpec[:-1]:
136  specFile.write(str(p)+"\n")
137  specFile.write(str(self.pathSpec[-1]))
138 
139 TraceParser.blacklist = ["/.Trash","/.Trash-1000"]
140 
141 
143  argparser = argparse.ArgumentParser()
144  argparser.add_argument("--policy",
145  required=False,
146  default="pdir",
147  type=str,
148  help="What files should be included given a traced"
149  + " action on a certain file")
150 
151 
152  argparser.add_argument("infile",
153  type=str,
154  help="The trace log file")
155 
156  argparser.add_argument("outfile",
157  type=str,
158  help="The output file")
159 
160  argparser.add_argument("--filters",
161  required=False,
162  default="",
163  nargs="+",
164  choices=["open", "opendir", "lookup", "statfs", "getattr", "listxattr", "getxattr", "readlink"],
165  help="Calls which should be filtered")
166 
167  return argparser.parse_args()
168 
169 def main():
170  args = parse_args()
171  traceParser = TraceParser(args)
172  traceParser.read_log()
173  traceParser.write_spec()
174 
175 if __name__ == "__main__":
176  main()
def parent_dir_parser
Definition: spec_builder.py:53