]>
git.ipfire.org Git - nitsi.git/blob - src/nitsi/recipe.py
6 logger
= logging
.getLogger("nitsi.recipe")
10 class RecipeExeption(Exception):
11 def __init__(self
, message
):
12 self
.message
= message
16 # Should read the test, check if the syntax are valid
17 # and return tuples with the ( host, command ) structure
19 def __init__(self
, path
, circle
=[], machines
=[], fallback_machines
=[], include_path
=None):
20 self
.recipe_file
= path
22 self
.path
= os
.path
.dirname(self
.recipe_file
)
23 self
.path
= os
.path
.abspath(self
.path
)
24 self
.name
= os
.path
.basename(self
.path
)
25 except BaseException
as e
:
26 logger
.error("Failed to get the path to this recipe")
29 self
.log
= logger
.getChild(self
.name
)
30 self
.log
.debug("Path of recipe is: {}".format(self
.recipe_file
))
32 # This path must be absolut
33 self
.include_path
= include_path
35 if self
.include_path
and not os
.path
.isabs(self
.include_path
):
36 raise RecipeExeption("Include path must be absolut.")
38 self
.log
.debug("Include path is: {}".format(self
.include_path
))
41 self
._machines
= machines
42 self
._fallback
_machines
= fallback_machines
44 self
.log
.debug("Machine names we use when we substitute the all statement: {}".format(self
._machines
))
46 self
.log
.debug("Length of the cirle list {}".format(len(circle
)))
47 self
.in_recursion
= True
49 self
.in_recursion
= False
51 self
.log
.debug("We are in a recursion: {}".format(self
.in_recursion
))
54 self
.log
.debug("Recipes we have already included: {}".format(self
.circle
))
56 if not os
.path
.isfile(self
.recipe_file
):
57 self
.log
.error("{} is not a file".format(self
.recipe_file
))
58 raise RecipeExeption("{} is not a file".format(self
.recipe_file
))
61 with
open(self
.recipe_file
) as fobj
:
62 self
.raw_recipe
= fobj
.readlines()
63 except FileNotFoundError
as error
:
64 self
.log
.error("No such file: {}".format(self
.recipe_file
))
81 for line
in self
.raw_recipe
:
82 # Check if the line is empty
83 if line
.strip() == "":
84 self
.log
.debug("Skipping empty line {}".format(i
))
88 # Check if the line is a comment
89 if line
.strip().startswith("#"):
90 self
.log
.debug("Skipping comment in line {}".format(i
))
94 raw_line
= line
.split(":", 1)
96 self
.log
.error("Error parsing the recipe in line {}".format(i
))
97 raise RecipeExeption("Error parsing the recipe in line {}".format(i
))
98 cmd
= raw_line
[1].strip()
100 raw_line
= raw_line
[0].strip().split(" ")
101 if len(raw_line
) == 0:
102 self
.log
.error("Failed to parse the recipe in line {}".format(i
))
103 raise RecipeExeption("Failed to parse the recipe in line {}".format(i
))
105 if raw_line
[0].strip() == "":
106 self
.log
.error("Failed to parse the recipe in line {}".format(i
))
107 raise RecipeExeption("Failed to parse the recipe in line {}".format(i
))
109 machine
= raw_line
[0].strip()
111 if len(raw_line
) == 2:
112 extra
= raw_line
[1].strip()
116 # We could get a machine here or a include statement
117 if machine
== "include":
119 if self
.include_path
:
120 path
= os
.path
.normpath(self
.include_path
+ "/" + path
)
122 path
= os
.path
.normpath(self
.path
+ "/" + path
)
124 # If we did not get a valid file we asume that we get a valid path to a test.
125 if os
.path
.isdir(path
):
126 path
= path
+ "/recipe"
128 self
.log
.debug("Path of recipe to include is: {}".format(path
))
130 if path
in self
.circle
:
131 self
.log
.error("Detect import loop!")
132 raise RecipeExeption("Detect import loop!")
133 self
.circle
.append(path
)
134 recipe_to_include
= Recipe(path
, circle
=self
.circle
, include_path
=self
.include_path
)
136 if machine
== "include":
137 self
._recipe
.extend(recipe_to_include
.recipe
)
139 # Support also something like 'alice,bob: echo'
140 machines
= machine
.split(",")
141 for machine
in machines
:
142 self
._recipe
.append((machine
.strip(), extra
.strip(), cmd
.strip()))
144 # Increase the line number by one
147 # Substitue the all statement
148 if not self
.in_recursion
:
149 self
.log
.debug("We are not in a recursion")
150 # We will store the machine names we use to substitute the all statement
151 # in tmp_machines to keep the code which actually does the substitution clear
154 # Check if we get a setting to substitute the all statement
155 if len(self
.machines
) != 0:
156 tmp_machines
= self
.machines
158 # Second try to fill tmp_machines
160 # dertermine machines we use in this recipe
162 for line
in self
.recipe
:
164 if not line
[0] in tmp
and line
[0] != "all":
167 self
.log
.debug("Machines except all in the recipe: {}".format(tmp
))
169 # Check if we got anything else then all: in th recipe
173 # If we get here we are using all machines in the virtual environment as fallback value
175 tmp_machines
= self
._fallback
_machines
178 for line
in self
._recipe
:
180 tmp_recipe
.append(line
)
182 for machine
in tmp_machines
:
183 tmp_recipe
.append((machine
.strip(), line
[1], line
[2]))
185 self
._recipe
= tmp_recipe