4 # Copyright (C) 2007, 2008, 2009, 2010, 2011 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """OS related QA tests.
29 from ganeti import utils
30 from ganeti import constants
36 from qa_utils import AssertCommand, AssertIn, AssertNotIn
39 _TEMP_OS_NAME = "TEMP-Ganeti-QA-OS"
40 _TEMP_OS_PATH = os.path.join(constants.OS_SEARCH_PATH[0], _TEMP_OS_NAME)
44 _PARTIALLY_VALID) = range(1, 4)
49 AssertCommand(["gnt-os", "list"])
54 AssertCommand(["gnt-os", "diagnose"])
57 def _TestOsModify(hvp_dict, fail=False):
59 cmd = ["gnt-os", "modify"]
61 for hv_name, hv_params in hvp_dict.items():
64 for key, value in hv_params.items():
65 options.append("%s=%s" % (key, value))
66 cmd.append("%s:%s" % (hv_name, ",".join(options)))
68 cmd.append(_TEMP_OS_NAME)
69 AssertCommand(cmd, fail=fail)
72 def _TestOsStates(os_name):
73 """gnt-os modify, more stuff"""
74 cmd = ["gnt-os", "modify"]
76 for param in ["hidden", "blacklisted"]:
77 for val in ["yes", "no"]:
78 new_cmd = cmd + ["--%s" % param, val, os_name]
79 AssertCommand(new_cmd)
80 # check that double-running the command is OK
81 AssertCommand(new_cmd)
84 def _SetupTempOs(node, dirname, variant, valid):
85 """Creates a temporary OS definition on the given node.
88 sq = utils.ShellQuoteArgs
90 sq(["rm", "-rf", dirname]),
91 sq(["mkdir", "-p", dirname]),
93 sq(["ln", "-fs", "/bin/true", "export"]),
94 sq(["ln", "-fs", "/bin/true", "import"]),
95 sq(["ln", "-fs", "/bin/true", "rename"]),
96 sq(["ln", "-fs", "/bin/true", "verify"]),
100 parts.append(sq(["ln", "-fs", "/bin/true", "create"]))
102 parts.append(sq(["echo", str(constants.OS_API_V20)]) +
103 " >ganeti_api_version")
105 parts.append(sq(["echo", variant]) + " >variants.list")
106 parts.append(sq(["echo", "funny this is funny"]) + " >parameters.list")
108 cmd = " && ".join(parts)
110 print qa_utils.FormatInfo("Setting up %s with %s OS definition" %
112 ["an invalid", "a valid"][int(valid)]))
114 AssertCommand(cmd, node=node)
117 def _RemoveTempOs(node, dirname):
118 """Removes a temporary OS definition.
121 AssertCommand(["rm", "-rf", dirname], node=node)
124 def _TestOs(mode, rapi_cb):
125 """Generic function for OS definition testing
128 master = qa_config.GetMasterNode()
132 fullname = "%s+%s" % (name, variant)
133 dirname = _TEMP_OS_PATH
135 # Ensure OS is usable
136 cmd = ["gnt-os", "modify", "--hidden=no", "--blacklisted=no", name]
141 for i, node in enumerate(qa_config.get("nodes")):
143 if mode == _ALL_INVALID:
145 elif mode == _ALL_VALID:
147 elif mode == _PARTIALLY_VALID:
150 raise AssertionError("Unknown mode %s" % mode)
151 _SetupTempOs(node, dirname, variant, valid)
153 # TODO: Use Python 2.6's itertools.permutations
154 for (hidden, blacklisted) in [(False, False), (True, False),
155 (False, True), (True, True)]:
156 # Change OS' visibility
157 cmd = ["gnt-os", "modify", "--hidden", ["no", "yes"][int(hidden)],
158 "--blacklisted", ["no", "yes"][int(blacklisted)], name]
161 # Diagnose, checking exit status
162 AssertCommand(["gnt-os", "diagnose"], fail=(mode != _ALL_VALID))
164 # Diagnose again, ignoring exit status
165 output = qa_utils.GetCommandOutput(master["primary"],
166 "gnt-os diagnose || :")
167 for line in output.splitlines():
168 if line.startswith("OS: %s [global status:" % name):
171 raise qa_error.Error("Didn't find OS '%s' in 'gnt-os diagnose'" % name)
174 cmd = ["gnt-os", "info"]
175 output = qa_utils.GetCommandOutput(master["primary"],
176 utils.ShellQuoteArgs(cmd))
177 AssertIn("%s:" % name, output.splitlines())
180 cmd = ["gnt-os", "info", name]
181 output = qa_utils.GetCommandOutput(master["primary"],
182 utils.ShellQuoteArgs(cmd)).splitlines()
183 AssertIn("%s:" % name, output)
184 for (field, value) in [("valid", mode == _ALL_VALID),
186 ("blacklisted", blacklisted)]:
187 AssertIn(" - %s: %s" % (field, value), output)
189 # Only valid OSes should be listed
190 cmd = ["gnt-os", "list", "--no-headers"]
191 output = qa_utils.GetCommandOutput(master["primary"],
192 utils.ShellQuoteArgs(cmd))
193 if mode == _ALL_VALID and not (hidden or blacklisted):
196 assert_fn = AssertNotIn
197 assert_fn(fullname, output.splitlines())
201 assert_fn(fullname, rapi_cb())
204 _RemoveTempOs(node, dirname)
207 def TestOsValid(rapi_cb):
208 """Testing valid OS definition"""
209 return _TestOs(_ALL_VALID, rapi_cb)
212 def TestOsInvalid(rapi_cb):
213 """Testing invalid OS definition"""
214 return _TestOs(_ALL_INVALID, rapi_cb)
217 def TestOsPartiallyValid(rapi_cb):
218 """Testing partially valid OS definition"""
219 return _TestOs(_PARTIALLY_VALID, rapi_cb)
222 def TestOsModifyValid():
223 """Testing a valid os modify invocation"""
225 constants.HT_XEN_PVM: {
226 constants.HV_ROOT_PATH: "/dev/sda5",
228 constants.HT_XEN_HVM: {
229 constants.HV_ACPI: False,
230 constants.HV_PAE: True,
234 return _TestOsModify(hv_dict)
237 def TestOsModifyInvalid():
238 """Testing an invalid os modify invocation"""
240 "blahblahblubb": {"bar": ""},
243 return _TestOsModify(hv_dict, fail=True)
246 def TestOsStatesNonExisting():
247 """Testing OS states with non-existing OS"""
248 AssertCommand(["test", "-e", _TEMP_OS_PATH], fail=True)
249 return _TestOsStates(_TEMP_OS_NAME)