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