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
31 from ganeti import pathutils
37 from qa_utils import AssertCommand, AssertIn, AssertNotIn
40 _TEMP_OS_NAME = "TEMP-Ganeti-QA-OS"
41 _TEMP_OS_PATH = os.path.join(pathutils.OS_SEARCH_PATH[0], _TEMP_OS_NAME)
45 _PARTIALLY_VALID) = range(1, 4)
50 AssertCommand(["gnt-os", "list"])
55 AssertCommand(["gnt-os", "diagnose"])
58 def _TestOsModify(hvp_dict, fail=False):
60 cmd = ["gnt-os", "modify"]
62 for hv_name, hv_params in hvp_dict.items():
65 for key, value in hv_params.items():
66 options.append("%s=%s" % (key, value))
67 cmd.append("%s:%s" % (hv_name, ",".join(options)))
69 cmd.append(_TEMP_OS_NAME)
70 AssertCommand(cmd, fail=fail)
73 def _TestOsStates(os_name):
74 """gnt-os modify, more stuff"""
75 cmd = ["gnt-os", "modify"]
77 for param in ["hidden", "blacklisted"]:
78 for val in ["yes", "no"]:
79 new_cmd = cmd + ["--%s" % param, val, os_name]
80 AssertCommand(new_cmd)
81 # check that double-running the command is OK
82 AssertCommand(new_cmd)
85 def _SetupTempOs(node, dirname, variant, valid):
86 """Creates a temporary OS definition on the given node.
89 sq = utils.ShellQuoteArgs
91 sq(["rm", "-rf", dirname]),
92 sq(["mkdir", "-p", dirname]),
94 sq(["ln", "-fs", "/bin/true", "export"]),
95 sq(["ln", "-fs", "/bin/true", "import"]),
96 sq(["ln", "-fs", "/bin/true", "rename"]),
97 sq(["ln", "-fs", "/bin/true", "verify"]),
101 parts.append(sq(["ln", "-fs", "/bin/true", "create"]))
103 parts.append(sq(["echo", str(constants.OS_API_V20)]) +
104 " >ganeti_api_version")
106 parts.append(sq(["echo", variant]) + " >variants.list")
107 parts.append(sq(["echo", "funny this is funny"]) + " >parameters.list")
109 cmd = " && ".join(parts)
111 print qa_utils.FormatInfo("Setting up %s with %s OS definition" %
113 ["an invalid", "a valid"][int(valid)]))
115 AssertCommand(cmd, node=node)
118 def _RemoveTempOs(node, dirname):
119 """Removes a temporary OS definition.
122 AssertCommand(["rm", "-rf", dirname], node=node)
125 def _TestOs(mode, rapi_cb):
126 """Generic function for OS definition testing
129 master = qa_config.GetMasterNode()
133 fullname = "%s+%s" % (name, variant)
134 dirname = _TEMP_OS_PATH
136 # Ensure OS is usable
137 cmd = ["gnt-os", "modify", "--hidden=no", "--blacklisted=no", name]
142 for i, node in enumerate(qa_config.get("nodes")):
144 if mode == _ALL_INVALID:
146 elif mode == _ALL_VALID:
148 elif mode == _PARTIALLY_VALID:
151 raise AssertionError("Unknown mode %s" % mode)
152 _SetupTempOs(node, dirname, variant, valid)
154 # TODO: Use Python 2.6's itertools.permutations
155 for (hidden, blacklisted) in [(False, False), (True, False),
156 (False, True), (True, True)]:
157 # Change OS' visibility
158 cmd = ["gnt-os", "modify", "--hidden", ["no", "yes"][int(hidden)],
159 "--blacklisted", ["no", "yes"][int(blacklisted)], name]
162 # Diagnose, checking exit status
163 AssertCommand(["gnt-os", "diagnose"], fail=(mode != _ALL_VALID))
165 # Diagnose again, ignoring exit status
166 output = qa_utils.GetCommandOutput(master.primary,
167 "gnt-os diagnose || :")
168 for line in output.splitlines():
169 if line.startswith("OS: %s [global status:" % name):
172 raise qa_error.Error("Didn't find OS '%s' in 'gnt-os diagnose'" % name)
175 cmd = ["gnt-os", "info"]
176 output = qa_utils.GetCommandOutput(master.primary,
177 utils.ShellQuoteArgs(cmd))
178 AssertIn("%s:" % name, output.splitlines())
181 cmd = ["gnt-os", "info", name]
182 output = qa_utils.GetCommandOutput(master.primary,
183 utils.ShellQuoteArgs(cmd)).splitlines()
184 AssertIn("%s:" % name, output)
185 for (field, value) in [("valid", mode == _ALL_VALID),
187 ("blacklisted", blacklisted)]:
188 AssertIn(" - %s: %s" % (field, value), output)
190 # Only valid OSes should be listed
191 cmd = ["gnt-os", "list", "--no-headers"]
192 output = qa_utils.GetCommandOutput(master.primary,
193 utils.ShellQuoteArgs(cmd))
194 if mode == _ALL_VALID and not (hidden or blacklisted):
197 assert_fn = AssertNotIn
198 assert_fn(fullname, output.splitlines())
202 assert_fn(fullname, rapi_cb())
205 _RemoveTempOs(node, dirname)
208 def TestOsValid(rapi_cb):
209 """Testing valid OS definition"""
210 return _TestOs(_ALL_VALID, rapi_cb)
213 def TestOsInvalid(rapi_cb):
214 """Testing invalid OS definition"""
215 return _TestOs(_ALL_INVALID, rapi_cb)
218 def TestOsPartiallyValid(rapi_cb):
219 """Testing partially valid OS definition"""
220 return _TestOs(_PARTIALLY_VALID, rapi_cb)
223 def TestOsModifyValid():
224 """Testing a valid os modify invocation"""
226 constants.HT_XEN_PVM: {
227 constants.HV_ROOT_PATH: "/dev/sda5",
229 constants.HT_XEN_HVM: {
230 constants.HV_ACPI: False,
231 constants.HV_PAE: True,
235 return _TestOsModify(hv_dict)
238 def TestOsModifyInvalid():
239 """Testing an invalid os modify invocation"""
241 "blahblahblubb": {"bar": ""},
244 return _TestOsModify(hv_dict, fail=True)
247 def TestOsStatesNonExisting():
248 """Testing OS states with non-existing OS"""
249 AssertCommand(["test", "-e", _TEMP_OS_PATH], fail=True)
250 return _TestOsStates(_TEMP_OS_NAME)