blob: 547d0d084608ae83e9e613385fd652e199e699f8 [file] [log] [blame]
Joe Gordonc97f5c72013-02-14 01:15:57 +00001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2013 OpenStack Foundation
4# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
Mikhail S Medvedev13168d02013-06-24 16:13:40 -050018import os
Pavel Sedláka2b757c2013-02-25 18:16:04 +010019import shlex
20import subprocess
Joe Gordonc97f5c72013-02-14 01:15:57 +000021
Matthew Treinish90aedd12013-02-25 17:56:49 -050022from oslo.config import cfg
23
Sean Daguef6825792013-05-08 13:51:26 -040024import tempest.cli.output_parser
Matthew Treinishf4a9b0f2013-07-26 16:58:26 -040025from tempest.openstack.common import log as logging
Pavel Sedláka2b757c2013-02-25 18:16:04 +010026import tempest.test
Joe Gordonc97f5c72013-02-14 01:15:57 +000027
Matthew Treinish90aedd12013-02-25 17:56:49 -050028
Joe Gordonc97f5c72013-02-14 01:15:57 +000029LOG = logging.getLogger(__name__)
30
31cli_opts = [
32 cfg.BoolOpt('enabled',
33 default=True,
34 help="enable cli tests"),
35 cfg.StrOpt('cli_dir',
Matthew Treinisheb724512013-10-25 15:12:59 +000036 default='/usr/local/bin',
Joe Gordonc97f5c72013-02-14 01:15:57 +000037 help="directory where python client binaries are located"),
Matt Riedemannab038c92013-08-06 06:56:48 -070038 cfg.IntOpt('timeout',
39 default=15,
40 help="Number of seconds to wait on a CLI timeout"),
Joe Gordonc97f5c72013-02-14 01:15:57 +000041]
42
43CONF = cfg.CONF
44cli_group = cfg.OptGroup(name='cli', title="cli Configuration Options")
45CONF.register_group(cli_group)
46CONF.register_opts(cli_opts, group=cli_group)
Pavel Sedláka2b757c2013-02-25 18:16:04 +010047
48
49class ClientTestBase(tempest.test.BaseTestCase):
50 @classmethod
51 def setUpClass(cls):
52 if not CONF.cli.enabled:
53 msg = "cli testing disabled"
54 raise cls.skipException(msg)
55 cls.identity = cls.config.identity
56 super(ClientTestBase, cls).setUpClass()
57
58 def __init__(self, *args, **kwargs):
Sean Daguef6825792013-05-08 13:51:26 -040059 self.parser = tempest.cli.output_parser
Pavel Sedláka2b757c2013-02-25 18:16:04 +010060 super(ClientTestBase, self).__init__(*args, **kwargs)
61
62 def nova(self, action, flags='', params='', admin=True, fail_ok=False):
63 """Executes nova command for the given action."""
64 return self.cmd_with_auth(
65 'nova', action, flags, params, admin, fail_ok)
66
Joe Gordone8b0e152013-03-25 13:37:15 -040067 def nova_manage(self, action, flags='', params='', fail_ok=False,
Joe Gordon0e7cbf82013-03-25 19:49:12 +000068 merge_stderr=False):
Joe Gordon4edb6452013-03-05 21:18:59 +000069 """Executes nova-manage command for the given action."""
70 return self.cmd(
Joe Gordone8b0e152013-03-25 13:37:15 -040071 'nova-manage', action, flags, params, fail_ok, merge_stderr)
Joe Gordon4edb6452013-03-05 21:18:59 +000072
Pavel Sedlák5ce5c032013-02-25 18:41:30 +010073 def keystone(self, action, flags='', params='', admin=True, fail_ok=False):
74 """Executes keystone command for the given action."""
75 return self.cmd_with_auth(
76 'keystone', action, flags, params, admin, fail_ok)
77
afazekasf35f9402013-03-25 14:51:13 +010078 def glance(self, action, flags='', params='', admin=True, fail_ok=False):
79 """Executes glance command for the given action."""
80 return self.cmd_with_auth(
81 'glance', action, flags, params, admin, fail_ok)
82
Mehdi Abaakouk8581c0b2013-10-04 10:45:42 +020083 def ceilometer(self, action, flags='', params='', admin=True,
84 fail_ok=False):
85 """Executes ceilometer command for the given action."""
86 return self.cmd_with_auth(
87 'ceilometer', action, flags, params, admin, fail_ok)
88
Steven Hardy5de54ee2013-12-31 15:58:30 +000089 def heat(self, action, flags='', params='', admin=True,
90 fail_ok=False):
91 """Executes heat command for the given action."""
92 return self.cmd_with_auth(
93 'heat', action, flags, params, admin, fail_ok)
94
saurabh467c4112013-07-08 17:08:31 +053095 def cinder(self, action, flags='', params='', admin=True, fail_ok=False):
96 """Executes cinder command for the given action."""
97 return self.cmd_with_auth(
98 'cinder', action, flags, params, admin, fail_ok)
99
saurabh55c29c72013-07-26 21:15:08 +0530100 def neutron(self, action, flags='', params='', admin=True, fail_ok=False):
101 """Executes neutron command for the given action."""
102 return self.cmd_with_auth(
103 'neutron', action, flags, params, admin, fail_ok)
104
Pavel Sedláka2b757c2013-02-25 18:16:04 +0100105 def cmd_with_auth(self, cmd, action, flags='', params='',
106 admin=True, fail_ok=False):
107 """Executes given command with auth attributes appended."""
Attila Fazekasc3a095b2013-08-17 09:15:44 +0200108 # TODO(jogo) make admin=False work
Pavel Sedláka2b757c2013-02-25 18:16:04 +0100109 creds = ('--os-username %s --os-tenant-name %s --os-password %s '
DennyZhangb432bac2013-09-17 16:24:12 +0000110 '--os-auth-url %s ' %
111 (self.identity.admin_username,
112 self.identity.admin_tenant_name,
113 self.identity.admin_password,
114 self.identity.uri))
Pavel Sedláka2b757c2013-02-25 18:16:04 +0100115 flags = creds + ' ' + flags
116 return self.cmd(cmd, action, flags, params, fail_ok)
117
Joe Gordone8b0e152013-03-25 13:37:15 -0400118 def cmd(self, cmd, action, flags='', params='', fail_ok=False,
Joe Gordon0e7cbf82013-03-25 19:49:12 +0000119 merge_stderr=False):
Pavel Sedláka2b757c2013-02-25 18:16:04 +0100120 """Executes specified command for the given action."""
Mikhail S Medvedev13168d02013-06-24 16:13:40 -0500121 cmd = ' '.join([os.path.join(CONF.cli.cli_dir, cmd),
Pavel Sedláka2b757c2013-02-25 18:16:04 +0100122 flags, action, params])
123 LOG.info("running: '%s'" % cmd)
Pavel Sedlák0d9a84f2013-08-27 19:09:26 +0200124 cmd_str = cmd
Pavel Sedláka2b757c2013-02-25 18:16:04 +0100125 cmd = shlex.split(cmd)
Pavel Sedlák0d9a84f2013-08-27 19:09:26 +0200126 result = ''
127 result_err = ''
Pavel Sedláka2b757c2013-02-25 18:16:04 +0100128 try:
Pavel Sedlák0d9a84f2013-08-27 19:09:26 +0200129 stdout = subprocess.PIPE
130 stderr = subprocess.STDOUT if merge_stderr else subprocess.PIPE
131 proc = subprocess.Popen(
132 cmd, stdout=stdout, stderr=stderr)
133 result, result_err = proc.communicate()
134 if not fail_ok and proc.returncode != 0:
135 raise CommandFailed(proc.returncode,
136 cmd,
Cyril Roelandtb18d5fb2013-10-09 20:23:39 +0000137 result,
138 stderr=result_err)
Pavel Sedlák0d9a84f2013-08-27 19:09:26 +0200139 finally:
140 LOG.debug('output of %s:\n%s' % (cmd_str, result))
141 if not merge_stderr and result_err:
142 LOG.debug('error output of %s:\n%s' % (cmd_str, result_err))
Pavel Sedláka2b757c2013-02-25 18:16:04 +0100143 return result
Pavel Sedlák5ce5c032013-02-25 18:41:30 +0100144
145 def assertTableStruct(self, items, field_names):
146 """Verify that all items has keys listed in field_names."""
147 for item in items:
148 for field in field_names:
149 self.assertIn(field, item)
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200150
Pavel Sedlák4c18fa12013-08-22 21:29:45 +0200151 def assertFirstLineStartsWith(self, lines, beginning):
152 self.assertTrue(lines[0].startswith(beginning),
153 msg=('Beginning of first line has invalid content: %s'
154 % lines[:3]))
155
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200156
157class CommandFailed(subprocess.CalledProcessError):
158 # adds output attribute for python2.6
Cyril Roelandtb18d5fb2013-10-09 20:23:39 +0000159 def __init__(self, returncode, cmd, output, stderr=""):
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200160 super(CommandFailed, self).__init__(returncode, cmd)
161 self.output = output
Cyril Roelandtb18d5fb2013-10-09 20:23:39 +0000162 self.stderr = stderr