]>
Commit | Line | Data |
---|---|---|
5e7f6db7 JS |
1 | #!/usr/bin/python3 |
2 | ||
6632e137 | 3 | import configparser |
5e7f6db7 | 4 | import libvirt |
6632e137 | 5 | import logging |
5e7f6db7 | 6 | import os |
6c352a80 JS |
7 | import time |
8 | ||
b560f31a JS |
9 | from . import recipe |
10 | from . import virtual_environ | |
5e7f6db7 | 11 | |
1ed8ca9f | 12 | logger = logging.getLogger("nitsi.test") |
5e7f6db7 | 13 | |
61b44c10 JS |
14 | |
15 | class TestException(Exception): | |
16 | def __init__(self, message): | |
17 | self.message = message | |
18 | ||
ee227ea1 | 19 | class Test(): |
978854bf JS |
20 | def __init__(self, path, log_path, settings=None): |
21 | # init settings var | |
22 | self.settings = {} | |
23 | ||
5e7f6db7 JS |
24 | try: |
25 | self.path = os.path.abspath(path) | |
1ed8ca9f | 26 | self.log = logger.getChild(os.path.basename(self.path)) |
5e7f6db7 | 27 | except BaseException as e: |
1ed8ca9f | 28 | logger.error("Could not get absolute path") |
5addee87 | 29 | raise e |
5e7f6db7 | 30 | |
2fa4467d | 31 | self.log.debug("Path of this test is: {}".format(self.path)) |
5e7f6db7 | 32 | |
b4936764 JS |
33 | self.log_path = log_path |
34 | ||
5e7f6db7 JS |
35 | self.settings_file = "{}/settings".format(self.path) |
36 | if not os.path.isfile(self.settings_file): | |
37 | self.log.error("No such file: {}".format(self.settings_file)) | |
250db3b1 | 38 | raise TestException("No settings file found") |
5e7f6db7 JS |
39 | |
40 | self.recipe_file = "{}/recipe".format(self.path) | |
41 | if not os.path.isfile(self.recipe_file): | |
42 | self.log.error("No such file: {}".format(self.recipe_file)) | |
250db3b1 | 43 | raise TestException("No recipe file found") |
5e7f6db7 | 44 | |
978854bf JS |
45 | self.cmd_settings = settings |
46 | ||
5e7f6db7 | 47 | def read_settings(self): |
8428a452 | 48 | self.log.debug("Going to read all settings from the ini file") |
c02dd9a9 JS |
49 | try: |
50 | self.config = configparser.ConfigParser() | |
51 | self.config.read(self.settings_file) | |
52 | except BaseException as e: | |
53 | self.log.error("Failed to parse the config") | |
54 | raise e | |
55 | ||
978854bf JS |
56 | self.settings["name"] = self.config.get("GENERAL","name", fallback="") |
57 | self.settings["description"] = self.config.get("GENERAL", "description", fallback="") | |
58 | self.settings["copy_to"] = self.config.get("GENERAL", "copy_to", fallback=None) | |
59 | self.settings["copy_from"] = self.config.get("GENERAL", "copy_from", fallback=None) | |
60 | self.settings["virtual_environ_path"] = self.config.get("VIRTUAL_ENVIRONMENT", "path", fallback=None) | |
8428a452 | 61 | |
978854bf | 62 | if not self.settings["virtual_environ_path"]: |
8428a452 JS |
63 | self.log.error("No path for virtual environment found.") |
64 | raise TestException("No path for virtual environment found.") | |
65 | ||
978854bf | 66 | self.settings["virtual_environ_path"] = os.path.normpath(self.path + "/" + self.settings["virtual_environ_path"]) |
129c0b0f JS |
67 | |
68 | # Parse copy_from setting | |
978854bf | 69 | if self.settings["copy_from"]: |
8428a452 | 70 | self.log.debug("Going to parse the copy_from setting.") |
978854bf | 71 | self.settings["copy_from"] = self.settings["copy_from"].split(",") |
14cd493f | 72 | |
8428a452 | 73 | tmp = [] |
978854bf | 74 | for file in self.settings["copy_from"]: |
8428a452 JS |
75 | file = file.strip() |
76 | # If file is empty we do not want to add it to the list | |
77 | if not file == "": | |
78 | # If we get an absolut path we do nothing | |
79 | # If not we add self.path to get an absolut path | |
80 | if not os.path.isabs(file): | |
81 | file = os.path.normpath(self.path + "/" + file) | |
f010720b | 82 | |
8428a452 JS |
83 | # We need to check if file is a valid file or dir |
84 | if not (os.path.isdir(file) or os.path.isfile(file)): | |
85 | raise TestException("'{}' is not a valid file nor a valid directory".format(file)) | |
f010720b | 86 | |
8428a452 JS |
87 | self.log.debug("'{}' will be copied into all images".format(file)) |
88 | tmp.append(file) | |
14cd493f | 89 | |
978854bf | 90 | self.settings["copy_from"] = tmp |
5e7f6db7 | 91 | |
129c0b0f | 92 | |
5e7f6db7 JS |
93 | |
94 | def virtual_environ_setup(self): | |
978854bf | 95 | self.virtual_environ = virtual_environ.Virtual_environ(self.settings["virtual_environ_path"]) |
5e7f6db7 JS |
96 | |
97 | self.virtual_networks = self.virtual_environ.get_networks() | |
98 | ||
99 | self.virtual_machines = self.virtual_environ.get_machines() | |
100 | ||
101 | def virtual_environ_start(self): | |
3fa89b7c JS |
102 | for name in self.virtual_environ.network_names: |
103 | self.virtual_networks[name].define() | |
104 | self.virtual_networks[name].start() | |
5e7f6db7 | 105 | |
3fa89b7c JS |
106 | for name in self.virtual_environ.machine_names: |
107 | self.virtual_machines[name].define() | |
108 | self.virtual_machines[name].create_snapshot() | |
8428a452 | 109 | # We can only copy files when we know which and to which dir |
978854bf JS |
110 | if self.settings["copy_from"] and self.settings["copy_to"]: |
111 | self.virtual_machines[name].copy_in(self.settings["copy_from"], self.settings["copy_to"]) | |
3fa89b7c | 112 | self.virtual_machines[name].start() |
5e7f6db7 | 113 | |
6c352a80 JS |
114 | # Time to which all serial output log entries are relativ |
115 | log_start_time = time.time() | |
116 | ||
fc35cba1 JS |
117 | # Number of chars of the longest machine name |
118 | longest_machine_name = self.virtual_environ.longest_machine_name | |
119 | ||
5ff14f2d | 120 | self.log.info("Try to login on all machines") |
3fa89b7c | 121 | for name in self.virtual_environ.machine_names: |
5ff14f2d | 122 | self.log.info("Try to login on {}".format(name)) |
fc35cba1 JS |
123 | self.virtual_machines[name].login("{}/test.log".format(self.log_path), |
124 | log_start_time=log_start_time, | |
125 | longest_machine_name=longest_machine_name) | |
5e7f6db7 | 126 | |
3fa89b7c | 127 | def load_recipe(self): |
2fa4467d | 128 | self.log.info("Going to load the recipe") |
3fa89b7c | 129 | try: |
ee227ea1 | 130 | self.recipe = recipe.Recipe(self.recipe_file, machines=self.virtual_environ.machine_names) |
4bc54b45 JS |
131 | for line in self.recipe.recipe: |
132 | self.log.debug(line) | |
2fa4467d JS |
133 | |
134 | self.log.debug("This was the recipe") | |
4bc54b45 | 135 | except BaseException as e: |
3fa89b7c | 136 | self.log.error("Failed to load recipe") |
4bc54b45 | 137 | raise e |
3fa89b7c JS |
138 | |
139 | def run_recipe(self): | |
140 | for line in self.recipe.recipe: | |
141 | return_value = self.virtual_machines[line[0]].cmd(line[2]) | |
bce7d520 JS |
142 | self.log.debug("Return value is: {}".format(return_value)) |
143 | if return_value != "0" and line[1] == "": | |
61b44c10 | 144 | raise TestException("Failed to execute command '{}' on {}, return code: {}".format(line[2],line[0], return_value)) |
bce7d520 | 145 | elif return_value == "0" and line[1] == "!": |
61b44c10 | 146 | raise TestException("Succeded to execute command '{}' on {}, return code: {}".format(line[2],line[0],return_value)) |
bce7d520 JS |
147 | else: |
148 | self.log.debug("Command '{}' on {} returned with: {}".format(line[2],line[0],return_value)) | |
3fa89b7c JS |
149 | |
150 | def virtual_environ_stop(self): | |
151 | for name in self.virtual_environ.machine_names: | |
f9178ad3 JS |
152 | # We just catch exception here to avoid |
153 | # that we stop the cleanup process if only one command fails | |
154 | try: | |
155 | self.virtual_machines[name].shutdown() | |
156 | self.virtual_machines[name].revert_snapshot() | |
157 | self.virtual_machines[name].undefine() | |
158 | except BaseException as e: | |
159 | self.log.exception(e) | |
3fa89b7c JS |
160 | |
161 | for name in self.virtual_environ.network_names: | |
f9178ad3 JS |
162 | try: |
163 | self.virtual_networks[name].undefine() | |
164 | except BaseException as e: | |
165 | self.log.exception(e) | |
166 |