]>
git.ipfire.org Git - nitsi.git/blob - src/nitsi/test.py
3ee793637223ac4793302a8986cdfb67a46816eb
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 need to catch exceptions here
81 if not (self
.recipe_file
or os
.path
.isfile(self
.recipe_file
)):
82 logger
.error("No such file: {}".format(self
.recipe_file
))
83 raise TestException("No recipe file found")
90 self
.log
= logger
.getChild(os
.path
.basename(self
.path
))
93 self
.log
= logger
.getChild(os
.path
.basename(self
.recipe_file
))
95 def read_settings(self
):
96 if self
.settings_file
:
97 self
.log
.debug("Going to read all settings from the ini file")
99 self
.config
= configparser
.ConfigParser()
100 self
.config
.read(self
.settings_file
)
101 except BaseException
as e
:
102 self
.log
.error("Failed to parse the config")
105 self
.settings
["name"] = self
.config
.get("GENERAL","name", fallback
="")
106 self
.settings
["description"] = self
.config
.get("GENERAL", "description", fallback
="")
107 self
.settings
["copy_to"] = self
.config
.get("GENERAL", "copy_to", fallback
=None)
108 self
.settings
["copy_from"] = self
.config
.get("GENERAL", "copy_from", fallback
=None)
109 self
.settings
["virtual_environ_path"] = self
.config
.get("VIRTUAL_ENVIRONMENT", "path", fallback
=None)
111 # We need to parse some settings here because they are loaded from a settings file
112 if not os
.path
.isabs(self
.settings
["virtual_environ_path"]):
113 self
.settings
["virtual_environ_path"] = os
.path
.normpath(os
.path
.dirname(
114 self
.settings_file
) + "/" + self
.settings
["virtual_environ_path"])
116 # Parse copy_from setting
117 if self
.settings
["copy_from"]:
118 self
.settings
["copy_from"] = settings
.settings_parse_copy_from(self
.settings
["copy_from"],
119 path
=os
.path
.dirname(self
.settings_file
))
121 # Update all settings from the cmd
122 self
.settings
.update(self
.cmd_settings
)
124 if not os
.path
.isabs(self
.settings
["virtual_environ_path"]):
125 self
.settings
["virtual_environ_path"] = os
.path
.abspath(self
.settings
["virtual_environ_path"])
128 # Check if we get at least a valid a valid path to virtual environ
129 if not self
.settings
["virtual_environ_path"]:
130 self
.log
.error("No path for virtual environment found.")
131 raise TestException("No path for virtual environment found.")
133 # Print all settings for debugging purpose
134 self
.log
.debug("Settings are:")
135 for key
in self
.settings
:
136 self
.log
.debug("{}: {}".format(key
, self
.settings
[key
]))
139 def virtual_environ_setup(self
):
140 self
.virtual_environ
= virtual_environ
.Virtual_environ(self
.settings
["virtual_environ_path"])
142 self
.virtual_networks
= self
.virtual_environ
.get_networks()
144 self
.virtual_machines
= self
.virtual_environ
.get_machines()
146 def virtual_environ_start(self
):
147 for name
in self
.virtual_environ
.network_names
:
148 self
.virtual_networks
[name
].define()
149 self
.virtual_networks
[name
].start()
151 for name
in self
.virtual_environ
.machine_names
:
152 self
.virtual_machines
[name
].define()
153 self
.virtual_machines
[name
].create_snapshot()
154 # We can only copy files when we know which and to which dir
155 if self
.settings
["copy_from"] and self
.settings
["copy_to"]:
156 self
.virtual_machines
[name
].copy_in(self
.settings
["copy_from"], self
.settings
["copy_to"])
157 self
.virtual_machines
[name
].start()
159 # Time to which all serial output log entries are relativ
160 log_start_time
= time
.time()
162 # Number of chars of the longest machine name
163 longest_machine_name
= self
.virtual_environ
.longest_machine_name
165 self
.log
.info("Try to login on all machines")
166 for name
in self
.virtual_environ
.machine_names
:
167 self
.log
.info("Try to login on {}".format(name
))
168 self
.virtual_machines
[name
].login("{}/test.log".format(self
.log_path
),
169 log_start_time
=log_start_time
,
170 longest_machine_name
=longest_machine_name
)
172 def load_recipe(self
):
173 self
.log
.info("Going to load the recipe")
175 self
.recipe
= recipe
.Recipe(self
.recipe_file
, machines
=self
.virtual_environ
.machine_names
)
176 for line
in self
.recipe
.recipe
:
179 self
.log
.debug("This was the recipe")
180 except BaseException
as e
:
181 self
.log
.error("Failed to load recipe")
184 def run_recipe(self
):
185 for line
in self
.recipe
.recipe
:
186 return_value
= self
.virtual_machines
[line
[0]].cmd(line
[2])
187 self
.log
.debug("Return value is: {}".format(return_value
))
188 if return_value
!= "0" and line
[1] == "":
189 raise TestException("Failed to execute command '{}' on {}, return code: {}".format(line
[2],line
[0], return_value
))
190 elif return_value
== "0" and line
[1] == "!":
191 raise TestException("Succeded to execute command '{}' on {}, return code: {}".format(line
[2],line
[0],return_value
))
193 self
.log
.debug("Command '{}' on {} returned with: {}".format(line
[2],line
[0],return_value
))
195 def virtual_environ_stop(self
):
196 for name
in self
.virtual_environ
.machine_names
:
197 # We just catch exception here to avoid
198 # that we stop the cleanup process if only one command fails
200 self
.virtual_machines
[name
].shutdown()
201 self
.virtual_machines
[name
].revert_snapshot()
202 self
.virtual_machines
[name
].undefine()
203 except BaseException
as e
:
204 self
.log
.exception(e
)
206 for name
in self
.virtual_environ
.network_names
:
208 self
.virtual_networks
[name
].undefine()
209 except BaseException
as e
:
210 self
.log
.exception(e
)