]>
git.ipfire.org Git - nitsi.git/blob - src/nitsi/test.py
10 from . import virtual_environ
11 from . import settings
13 logger
= logging
.getLogger("nitsi.test")
16 class TestException(Exception):
17 def __init__(self
, message
):
18 self
.message
= message
21 def __init__(self
, log_path
, dir=None, recipe_file
=None, settings_file
=None, cmd_settings
=None):
25 # Set default values for the settings dict
26 self
.settings
["name"] = ""
27 self
.settings
["description"] = ""
28 self
.settings
["copy_from"] = None
29 self
.settings
["copy_to"] = None
30 self
.settings
["virtual_environ_path"] = None
32 self
.cmd_settings
= cmd_settings
33 self
.log_path
= log_path
35 # Init all vars with None
36 self
.settings_file
= None
37 self
.recipe_file
= None
40 # We need at least a path to a recipe file or a dir to a test
41 if not dir and not recipe
:
42 raise TestException("Did not get a path to a test or to a recipe file")
44 # We cannot decide which to use when we get both
45 if (dir and recipe_file
) or (dir and settings_file
):
46 raise TestException("Get dir and path to recipe or settings file")
50 if not os
.path
.isabs(dir):
51 self
.path
= os
.path
.abspath(dir)
52 except BaseException
as e
:
53 logger
.error("Could not get absolute path")
56 logger
.debug("Path of this test is: {}".format(self
.path
))
58 self
.recipe_file
= "{}/recipe".format(self
.path
)
59 self
.settings_file
= "{}/settings".format(self
.path
)
62 if not os
.path
.isabs(recipe_file
):
63 self
.recipe_file
= os
.path
.abspath(recipe_file
)
65 self
.recipe_file
= recipe_file
68 if not os
.path
.isabs(settings_file
):
69 self
.settings_file
= os
.path
.abspath(settings_file
)
71 self
.settings_file
= settings_file
73 # We can also go on without a settings file
74 if self
.settings_file
:
75 if not os
.path
.isfile(self
.settings_file
):
76 logger
.error("No such file: {}".format(self
.settings_file
))
77 raise TestException("No settings file found")
79 # os.path.isfile fails if self.recipe_file is None so we cannot use an and statement
81 if not os
.path
.isfile(self
.recipe_file
):
82 logger
.error("No such file: {}".format(self
.recipe_file
))
83 raise TestException("No recipe file found")
85 logger
.error("No such file: {}".format(self
.recipe_file
))
86 raise TestException("No recipe file found")
91 self
.log
= logger
.getChild(os
.path
.basename(self
.path
))
94 self
.log
= logger
.getChild(os
.path
.basename(self
.recipe_file
))
96 def read_settings(self
):
97 if self
.settings_file
:
98 self
.log
.debug("Going to read all settings from the ini file")
100 self
.config
= configparser
.ConfigParser()
101 self
.config
.read(self
.settings_file
)
102 except BaseException
as e
:
103 self
.log
.error("Failed to parse the config")
106 self
.settings
["name"] = self
.config
.get("GENERAL","name", fallback
="")
107 self
.settings
["description"] = self
.config
.get("GENERAL", "description", fallback
="")
108 self
.settings
["copy_to"] = self
.config
.get("GENERAL", "copy_to", fallback
=None)
109 self
.settings
["copy_from"] = self
.config
.get("GENERAL", "copy_from", fallback
=None)
110 self
.settings
["virtual_environ_path"] = self
.config
.get("VIRTUAL_ENVIRONMENT", "path", fallback
=None)
112 # We need to parse some settings here because they are loaded from a settings file
113 if not os
.path
.isabs(self
.settings
["virtual_environ_path"]):
114 self
.settings
["virtual_environ_path"] = os
.path
.normpath(os
.path
.dirname(
115 self
.settings_file
) + "/" + self
.settings
["virtual_environ_path"])
117 # Parse copy_from setting
118 if self
.settings
["copy_from"]:
119 self
.settings
["copy_from"] = settings
.settings_parse_copy_from(self
.settings
["copy_from"],
120 path
=os
.path
.dirname(self
.settings_file
))
122 # Update all settings from the cmd
123 self
.settings
.update(self
.cmd_settings
)
125 if not os
.path
.isabs(self
.settings
["virtual_environ_path"]):
126 self
.settings
["virtual_environ_path"] = os
.path
.abspath(self
.settings
["virtual_environ_path"])
129 # Check if we get at least a valid a valid path to virtual environ
130 if not self
.settings
["virtual_environ_path"]:
131 self
.log
.error("No path for virtual environment found.")
132 raise TestException("No path for virtual environment found.")
134 # Print all settings for debugging purpose
135 self
.log
.debug("Settings are:")
136 for key
in self
.settings
:
137 self
.log
.debug("{}: {}".format(key
, self
.settings
[key
]))
140 def virtual_environ_setup(self
):
141 self
.virtual_environ
= virtual_environ
.Virtual_environ(self
.settings
["virtual_environ_path"])
143 self
.virtual_networks
= self
.virtual_environ
.get_networks()
145 self
.virtual_machines
= self
.virtual_environ
.get_machines()
147 def virtual_environ_start(self
):
148 for name
in self
.virtual_environ
.network_names
:
149 self
.virtual_networks
[name
].define()
150 self
.virtual_networks
[name
].start()
152 for name
in self
.virtual_environ
.machine_names
:
153 self
.virtual_machines
[name
].define()
154 self
.virtual_machines
[name
].create_snapshot()
155 # We can only copy files when we know which and to which dir
156 if self
.settings
["copy_from"] and self
.settings
["copy_to"]:
157 self
.virtual_machines
[name
].copy_in(self
.settings
["copy_from"], self
.settings
["copy_to"])
158 self
.virtual_machines
[name
].start()
160 # Time to which all serial output log entries are relativ
161 log_start_time
= time
.time()
163 # Number of chars of the longest machine name
164 longest_machine_name
= self
.virtual_environ
.longest_machine_name
166 self
.log
.info("Try to login on all machines")
167 for name
in self
.virtual_environ
.machine_names
:
168 self
.log
.info("Try to login on {}".format(name
))
169 self
.virtual_machines
[name
].login("{}/test.log".format(self
.log_path
),
170 log_start_time
=log_start_time
,
171 longest_machine_name
=longest_machine_name
)
173 def load_recipe(self
):
174 self
.log
.info("Going to load the recipe")
176 self
.recipe
= recipe
.Recipe(self
.recipe_file
, machines
=self
.virtual_environ
.machine_names
)
177 for line
in self
.recipe
.recipe
:
180 self
.log
.debug("This was the recipe")
181 except BaseException
as e
:
182 self
.log
.error("Failed to load recipe")
185 def run_recipe(self
):
186 for line
in self
.recipe
.recipe
:
187 return_value
= self
.virtual_machines
[line
[0]].cmd(line
[2])
188 self
.log
.debug("Return value is: {}".format(return_value
))
189 if return_value
!= "0" and line
[1] == "":
190 raise TestException("Failed to execute command '{}' on {}, return code: {}".format(line
[2],line
[0], return_value
))
191 elif return_value
== "0" and line
[1] == "!":
192 raise TestException("Succeded to execute command '{}' on {}, return code: {}".format(line
[2],line
[0],return_value
))
194 self
.log
.debug("Command '{}' on {} returned with: {}".format(line
[2],line
[0],return_value
))
196 def virtual_environ_stop(self
):
197 for name
in self
.virtual_environ
.machine_names
:
198 # We just catch exception here to avoid
199 # that we stop the cleanup process if only one command fails
201 self
.virtual_machines
[name
].shutdown()
202 self
.virtual_machines
[name
].revert_snapshot()
203 self
.virtual_machines
[name
].undefine()
204 except BaseException
as e
:
205 self
.log
.exception(e
)
207 for name
in self
.virtual_environ
.network_names
:
209 self
.virtual_networks
[name
].undefine()
210 except BaseException
as e
:
211 self
.log
.exception(e
)