Add .gitignore
[nitsi.git] / recipe.py
1 #!/usr/bin/python3
2
3 import os
4
5 import logging
6
7 logger = logging.getLogger("nitsi.recipe")
8
9
10
11 class RecipeExeption(Exception):
12     pass
13
14
15
16 # Should read the test, check if the syntax are valid
17 # and return tuples with the ( host, command ) structure
18 class recipe():
19     def __init__(self, path, circle=[]):
20         self.recipe_file = path
21         try:
22             self.path = os.path.dirname(self.recipe_file)
23             self.name = os.path.basename(self.path)
24         except BaseException as e:
25             logger.error("Failed to get the name of the test to this recipe")
26             raise e
27
28         self.log = logger.getChild(self.name)
29         self.log.debug("Path of recipe is: {}".format(self.recipe_file))
30         self._recipe = None
31         self._machines = None
32
33         self.in_recursion = True
34         if len(circle) == 0:
35             self.in_recursion = False
36
37         self.circle = circle
38         self.log.debug("Tests we have already included: {}".format(self.circle))
39
40         if not os.path.isfile(self.recipe_file):
41             self.log.error("{} is not a file".format(self.recipe_file))
42             raise RecipeExeption
43
44         try:
45             with open(self.recipe_file) as fobj:
46                 self.raw_recipe = fobj.readlines()
47         except FileNotFoundError as error:
48             self.log.error("No such file: {}".format(vm_xml_file))
49
50     @property
51     def recipe(self):
52         if not self._recipe:
53             self.parse()
54
55         return self._recipe
56
57     @property
58     def machines(self):
59         if not self._machines:
60             self._machines = []
61             for line in self._recipe:
62                 if line[0] != "all" and line[0] not in self._machines:
63                     self._machines.append(line[0])
64
65         return self._machines
66
67     def parse(self):
68         self._recipe = []
69         i = 1
70         for line in self.raw_recipe:
71             raw_line = line.split(":", 1)
72             if len(raw_line) < 2:
73                 self.log.error("Error parsing the recipe in line {}".format(i))
74                 raise RecipeExeption
75             cmd = raw_line[1].strip()
76             raw_line = raw_line[0].strip().split(" ")
77             if len(raw_line) == 0:
78                 self.log.error("Failed to parse the recipe in line {}".format(i))
79                 raise RecipeExeption
80
81             if raw_line[0].strip() == "":
82                     self.log.error("Failed to parse the recipe in line {}".format(i))
83                     raise RecipeExeption
84
85             machine = raw_line[0].strip()
86
87             if len(raw_line) == 2:
88                 extra = raw_line[1].strip()
89             else:
90                 extra = ""
91
92             # We could get a machine here or a include statement
93             if machine == "include":
94                 path = cmd.strip()
95                 path = os.path.normpath(self.path + "/" + path)
96                 path = path + "/recipe"
97                 if path in self.circle:
98                     self.log.error("Detect import loop!")
99                     raise RecipeExeption
100                 self.circle.append(path)
101                 recipe_to_include = recipe(path, circle=self.circle)
102
103             if machine == "include":
104                 self._recipe.extend(recipe_to_include.recipe)
105             else:
106                 # Support also something like 'alice,bob: echo'
107                 machines = machine.split(",")
108                 for machine in machines:
109                     self._recipe.append((machine.strip(), extra.strip(), cmd.strip()))
110             i = i + 1
111
112             if not self.in_recursion:
113                 tmp_recipe = []
114                 for line in self._recipe:
115                     if line[0] != "all":
116                         tmp_recipe.append(line)
117                     else:
118                         for machine in self.machines:
119                             tmp_recipe.append((machine.strip(), line[1], line[2]))
120
121                 self._recipe = tmp_recipe