Log all messages for a machine using the name of this machine
[nitsi.git] / 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):
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
18class recipe():
19 def __init__(self, path, circle=[]):
3a4eb2c7 20 self.recipe_file = path
1ed8ca9f 21 self.log = logger.getChild(os.path.basename(self.recipe_file))
3a4eb2c7
JS
22 self.path = os.path.dirname(self.recipe_file)
23 self.log.debug("Path of recipe is: {}".format(self.recipe_file))
24 self._recipe = None
25 self._machines = None
26
27 self.in_recursion = True
28 if len(circle) == 0:
29 self.in_recursion = False
30
31 self.circle = circle
32 self.log.debug(circle)
33 self.log.debug(self.circle)
34
35 if not os.path.isfile(self.recipe_file):
36 self.log.error("No such file: {}".format(self.recipe_file))
37
38 try:
39 with open(self.recipe_file) as fobj:
40 self.raw_recipe = fobj.readlines()
41 except FileNotFoundError as error:
42 self.log.error("No such file: {}".format(vm_xml_file))
43
44 @property
45 def recipe(self):
46 if not self._recipe:
47 self.parse()
48
49 return self._recipe
50
51 @property
52 def machines(self):
53 if not self._machines:
54 self._machines = []
55 for line in self._recipe:
56 if line[0] != "all" and line[0] not in self._machines:
57 self._machines.append(line[0])
58
59 return self._machines
60
61 def parse(self):
62 self._recipe = []
63 i = 1
64 for line in self.raw_recipe:
65 raw_line = line.split(":")
66 if len(raw_line) < 2:
67 self.log.error("Error parsing the recipe in line {}".format(i))
68 raise RecipeExeption
69 cmd = raw_line[1].strip()
70 raw_line = raw_line[0].strip().split(" ")
71 if len(raw_line) == 0:
72 self.log.error("Failed to parse the recipe in line {}".format(i))
73 raise RecipeExeption
74
75 if raw_line[0].strip() == "":
76 self.log.error("Failed to parse the recipe in line {}".format(i))
77 raise RecipeExeption
78
79 machine = raw_line[0].strip()
80
81 if len(raw_line) == 2:
82 extra = raw_line[1].strip()
83 else:
84 extra = ""
85
86 # We could get a machine here or a include statement
87 if machine == "include":
88 path = cmd.strip()
89 path = os.path.normpath(self.path + "/" + path)
90 path = path + "/recipe"
91 if path in self.circle:
92 self.log.error("Detect import loop!")
93 raise RecipeExeption
94 self.circle.append(path)
95 recipe_to_include = recipe(path, circle=self.circle)
96
97 if machine == "include":
98 self._recipe.extend(recipe_to_include.recipe)
99 else:
100 # Support also something like 'alice,bob: echo'
101 machines = machine.split(",")
102 for machine in machines:
103 self._recipe.append((machine.strip(), extra.strip(), cmd.strip()))
104 i = i + 1
105
106 if not self.in_recursion:
107 tmp_recipe = []
108 for line in self._recipe:
109 if line[0] != "all":
110 tmp_recipe.append(line)
111 else:
112 for machine in self.machines:
113 tmp_recipe.append((machine.strip(), line[1], line[2]))
114
115 self._recipe = tmp_recipe