blob: 8e91a6d744b6de662c0064b108f0852301510575 [file] [log] [blame]
Julie Pichond1017642013-07-24 16:37:23 +01001# All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
Matthew Treinish89128142015-04-23 10:44:30 -040015from six.moves import html_parser as HTMLParser
16from six.moves.urllib import parse
17from six.moves.urllib import request
Julie Pichond1017642013-07-24 16:37:23 +010018
Matthew Treinish6c072292014-01-29 19:15:52 +000019from tempest import config
Julie Pichond1017642013-07-24 16:37:23 +010020from tempest.scenario import manager
Masayuki Igawa4ded9f02014-02-17 15:05:59 +090021from tempest import test
Julie Pichond1017642013-07-24 16:37:23 +010022
Matthew Treinish6c072292014-01-29 19:15:52 +000023CONF = config.CONF
24
Julie Pichond1017642013-07-24 16:37:23 +010025
Sean Dague8fa6c032014-11-25 10:54:38 -050026class HorizonHTMLParser(HTMLParser.HTMLParser):
27 csrf_token = None
28 region = None
David Lylef0b070c2015-08-12 19:27:18 -060029 login = None
Sean Dague8fa6c032014-11-25 10:54:38 -050030
31 def _find_name(self, attrs, name):
32 for attrpair in attrs:
33 if attrpair[0] == 'name' and attrpair[1] == name:
34 return True
35 return False
36
37 def _find_value(self, attrs):
38 for attrpair in attrs:
39 if attrpair[0] == 'value':
40 return attrpair[1]
41 return None
42
David Lylef0b070c2015-08-12 19:27:18 -060043 def _find_attr_value(self, attrs, attr_name):
44 for attrpair in attrs:
45 if attrpair[0] == attr_name:
46 return attrpair[1]
47 return None
48
Sean Dague8fa6c032014-11-25 10:54:38 -050049 def handle_starttag(self, tag, attrs):
50 if tag == 'input':
51 if self._find_name(attrs, 'csrfmiddlewaretoken'):
52 self.csrf_token = self._find_value(attrs)
53 if self._find_name(attrs, 'region'):
54 self.region = self._find_value(attrs)
David Lylef0b070c2015-08-12 19:27:18 -060055 if tag == 'form':
56 self.login = self._find_attr_value(attrs, 'action')
Sean Dague8fa6c032014-11-25 10:54:38 -050057
58
Masayuki Igawa2675f8f2014-07-17 13:46:26 +020059class TestDashboardBasicOps(manager.ScenarioTest):
Julie Pichond1017642013-07-24 16:37:23 +010060
61 """
62 This is a basic scenario test:
63 * checks that the login page is available
64 * logs in as a regular user
65 * checks that the user home page loads without error
66 """
67
68 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000069 def skip_checks(cls):
70 super(TestDashboardBasicOps, cls).skip_checks()
Matthew Treinish6c072292014-01-29 19:15:52 +000071 if not CONF.service_available.horizon:
Julie Pichond1017642013-07-24 16:37:23 +010072 raise cls.skipException("Horizon support is required")
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000073
74 @classmethod
75 def setup_credentials(cls):
Masayuki Igawa60ea6c52014-10-15 17:32:14 +090076 cls.set_network_resources()
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000077 super(TestDashboardBasicOps, cls).setup_credentials()
Julie Pichond1017642013-07-24 16:37:23 +010078
79 def check_login_page(self):
Matthew Treinish89128142015-04-23 10:44:30 -040080 response = request.urlopen(CONF.dashboard.dashboard_url)
Thomas Bechtold44587492015-02-09 10:04:03 +010081 self.assertIn("id_username", response.read())
Julie Pichond1017642013-07-24 16:37:23 +010082
Matthew Treinish643f4c62014-12-12 19:54:34 -050083 def user_login(self, username, password):
Matthew Treinish89128142015-04-23 10:44:30 -040084 self.opener = request.build_opener(request.HTTPCookieProcessor())
Matthew Treinish6c072292014-01-29 19:15:52 +000085 response = self.opener.open(CONF.dashboard.dashboard_url).read()
Julie Pichond1017642013-07-24 16:37:23 +010086
87 # Grab the CSRF token and default region
Sean Dague8fa6c032014-11-25 10:54:38 -050088 parser = HorizonHTMLParser()
89 parser.feed(response)
Julie Pichond1017642013-07-24 16:37:23 +010090
David Lylef0b070c2015-08-12 19:27:18 -060091 # construct login url for dashboard, discovery accomodates non-/ web
92 # root for dashboard
93 login_url = CONF.dashboard.dashboard_url + parser.login[1:]
94
Julie Pichond1017642013-07-24 16:37:23 +010095 # Prepare login form request
David Lylef0b070c2015-08-12 19:27:18 -060096 req = request.Request(login_url)
Julie Pichond1017642013-07-24 16:37:23 +010097 req.add_header('Content-type', 'application/x-www-form-urlencoded')
Matthew Treinish6c072292014-01-29 19:15:52 +000098 req.add_header('Referer', CONF.dashboard.dashboard_url)
Matthew Treinish643f4c62014-12-12 19:54:34 -050099 params = {'username': username,
100 'password': password,
Sean Dague8fa6c032014-11-25 10:54:38 -0500101 'region': parser.region,
102 'csrfmiddlewaretoken': parser.csrf_token}
Matthew Treinish89128142015-04-23 10:44:30 -0400103 self.opener.open(req, parse.urlencode(params))
Julie Pichond1017642013-07-24 16:37:23 +0100104
105 def check_home_page(self):
Matthew Treinish6c072292014-01-29 19:15:52 +0000106 response = self.opener.open(CONF.dashboard.dashboard_url)
Julie Pichond1017642013-07-24 16:37:23 +0100107 self.assertIn('Overview', response.read())
108
Chris Hoge7579c1a2015-02-26 14:12:15 -0800109 @test.idempotent_id('4f8851b1-0e69-482b-b63b-84c6e76f6c80')
Masayuki Igawa4ded9f02014-02-17 15:05:59 +0900110 @test.services('dashboard')
Julie Pichond1017642013-07-24 16:37:23 +0100111 def test_basic_scenario(self):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000112 creds = self.os.credentials
Julie Pichond1017642013-07-24 16:37:23 +0100113 self.check_login_page()
Matthew Treinish643f4c62014-12-12 19:54:34 -0500114 self.user_login(creds.username, creds.password)
Julie Pichond1017642013-07-24 16:37:23 +0100115 self.check_home_page()