QA: Stop using "in" operator for node
[ganeti-local] / qa / qa_os.py
1 #
2 #
3
4 # Copyright (C) 2007, 2008, 2009, 2010, 2011 Google Inc.
5 #
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.
10 #
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.
15 #
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
19 # 02110-1301, USA.
20
21
22 """OS related QA tests.
23
24 """
25
26 import os
27 import os.path
28
29 from ganeti import utils
30 from ganeti import constants
31 from ganeti import pathutils
32
33 import qa_config
34 import qa_utils
35 import qa_error
36
37 from qa_utils import AssertCommand, AssertIn, AssertNotIn
38
39
40 _TEMP_OS_NAME = "TEMP-Ganeti-QA-OS"
41 _TEMP_OS_PATH = os.path.join(pathutils.OS_SEARCH_PATH[0], _TEMP_OS_NAME)
42
43 (_ALL_VALID,
44  _ALL_INVALID,
45  _PARTIALLY_VALID) = range(1, 4)
46
47
48 def TestOsList():
49   """gnt-os list"""
50   AssertCommand(["gnt-os", "list"])
51
52
53 def TestOsDiagnose():
54   """gnt-os diagnose"""
55   AssertCommand(["gnt-os", "diagnose"])
56
57
58 def _TestOsModify(hvp_dict, fail=False):
59   """gnt-os modify"""
60   cmd = ["gnt-os", "modify"]
61
62   for hv_name, hv_params in hvp_dict.items():
63     cmd.append("-H")
64     options = []
65     for key, value in hv_params.items():
66       options.append("%s=%s" % (key, value))
67     cmd.append("%s:%s" % (hv_name, ",".join(options)))
68
69   cmd.append(_TEMP_OS_NAME)
70   AssertCommand(cmd, fail=fail)
71
72
73 def _TestOsStates(os_name):
74   """gnt-os modify, more stuff"""
75   cmd = ["gnt-os", "modify"]
76
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)
83
84
85 def _SetupTempOs(node, dirname, variant, valid):
86   """Creates a temporary OS definition on the given node.
87
88   """
89   sq = utils.ShellQuoteArgs
90   parts = [
91     sq(["rm", "-rf", dirname]),
92     sq(["mkdir", "-p", dirname]),
93     sq(["cd", 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"]),
98     ]
99
100   if valid:
101     parts.append(sq(["ln", "-fs", "/bin/true", "create"]))
102
103   parts.append(sq(["echo", str(constants.OS_API_V20)]) +
104                " >ganeti_api_version")
105
106   parts.append(sq(["echo", variant]) + " >variants.list")
107   parts.append(sq(["echo", "funny this is funny"]) + " >parameters.list")
108
109   cmd = " && ".join(parts)
110
111   print qa_utils.FormatInfo("Setting up %s with %s OS definition" %
112                             (node["primary"],
113                              ["an invalid", "a valid"][int(valid)]))
114
115   AssertCommand(cmd, node=node)
116
117
118 def _RemoveTempOs(node, dirname):
119   """Removes a temporary OS definition.
120
121   """
122   AssertCommand(["rm", "-rf", dirname], node=node)
123
124
125 def _TestOs(mode, rapi_cb):
126   """Generic function for OS definition testing
127
128   """
129   master = qa_config.GetMasterNode()
130
131   name = _TEMP_OS_NAME
132   variant = "default"
133   fullname = "%s+%s" % (name, variant)
134   dirname = _TEMP_OS_PATH
135
136   # Ensure OS is usable
137   cmd = ["gnt-os", "modify", "--hidden=no", "--blacklisted=no", name]
138   AssertCommand(cmd)
139
140   nodes = []
141   try:
142     for i, node in enumerate(qa_config.get("nodes")):
143       nodes.append(node)
144       if mode == _ALL_INVALID:
145         valid = False
146       elif mode == _ALL_VALID:
147         valid = True
148       elif mode == _PARTIALLY_VALID:
149         valid = bool(i % 2)
150       else:
151         raise AssertionError("Unknown mode %s" % mode)
152       _SetupTempOs(node, dirname, variant, valid)
153
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]
160       AssertCommand(cmd)
161
162       # Diagnose, checking exit status
163       AssertCommand(["gnt-os", "diagnose"], fail=(mode != _ALL_VALID))
164
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):
170           break
171       else:
172         raise qa_error.Error("Didn't find OS '%s' in 'gnt-os diagnose'" % name)
173
174       # Check info for all
175       cmd = ["gnt-os", "info"]
176       output = qa_utils.GetCommandOutput(master["primary"],
177                                          utils.ShellQuoteArgs(cmd))
178       AssertIn("%s:" % name, output.splitlines())
179
180       # Check info for OS
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),
186                              ("hidden", hidden),
187                              ("blacklisted", blacklisted)]:
188         AssertIn("  - %s: %s" % (field, value), output)
189
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):
195         assert_fn = AssertIn
196       else:
197         assert_fn = AssertNotIn
198       assert_fn(fullname, output.splitlines())
199
200       # Check via RAPI
201       if rapi_cb:
202         assert_fn(fullname, rapi_cb())
203   finally:
204     for node in nodes:
205       _RemoveTempOs(node, dirname)
206
207
208 def TestOsValid(rapi_cb):
209   """Testing valid OS definition"""
210   return _TestOs(_ALL_VALID, rapi_cb)
211
212
213 def TestOsInvalid(rapi_cb):
214   """Testing invalid OS definition"""
215   return _TestOs(_ALL_INVALID, rapi_cb)
216
217
218 def TestOsPartiallyValid(rapi_cb):
219   """Testing partially valid OS definition"""
220   return _TestOs(_PARTIALLY_VALID, rapi_cb)
221
222
223 def TestOsModifyValid():
224   """Testing a valid os modify invocation"""
225   hv_dict = {
226     constants.HT_XEN_PVM: {
227       constants.HV_ROOT_PATH: "/dev/sda5",
228       },
229     constants.HT_XEN_HVM: {
230       constants.HV_ACPI: False,
231       constants.HV_PAE: True,
232       },
233     }
234
235   return _TestOsModify(hv_dict)
236
237
238 def TestOsModifyInvalid():
239   """Testing an invalid os modify invocation"""
240   hv_dict = {
241     "blahblahblubb": {"bar": ""},
242     }
243
244   return _TestOsModify(hv_dict, fail=True)
245
246
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)