def get_client_and_attempt_operation(self, ip): """Attempt to list users on the openstack-dashboard service. This is slightly complicated in that the client is actually a web-site. Thus, the test has to login first and then attempt the operation. This makes the test a little more complicated. :param ip: the IP address to get the session against. :type ip: str :raises: PolicydOperationFailedException if operation fails. """ unit = zaza_model.get_unit_from_name( zaza_model.get_lead_unit_name(self.application_name)) logging.info("Dashboard is at {}".format(unit.public_address)) overcloud_auth = openstack_utils.get_overcloud_auth() password = overcloud_auth['OS_PASSWORD'], logging.info("admin password is {}".format(password)) # try to get the url which will either pass or fail with a 403 overcloud_auth = openstack_utils.get_overcloud_auth() domain = 'admin_domain', username = '******', password = overcloud_auth['OS_PASSWORD'], client, response = _login(self.get_horizon_url(), domain, username, password) # now attempt to get the domains page _url = self.url.format(unit.public_address) result = client.get(_url) if result.status_code == 403: raise policyd.PolicydOperationFailedException("Not authenticated")
def test_401_authenticate(self): """Validate that authentication succeeds for client log in.""" logging.info('Checking authentication through dashboard...') dashboard_ip = _get_dashboard_ip() overcloud_auth = openstack_utils.get_overcloud_auth() password = overcloud_auth['OS_PASSWORD'], logging.info("admin password is {}".format(password)) # try to get the url which will either pass or fail with a 403 overcloud_auth = openstack_utils.get_overcloud_auth() domain = 'admin_domain', username = '******', password = overcloud_auth['OS_PASSWORD'], _login(dashboard_ip, domain, username, password) logging.info('OK')
def _find_keystone_v3_user(self, username, domain, group=None): """Find a user within a specified keystone v3 domain. :param str username: Username to search for in keystone :param str domain: username selected from which domain :param str group: group to search for in keystone for group membership :return: return username if found :rtype: Optional[str] """ for ip in self.keystone_ips: logging.info('Keystone IP {}'.format(ip)) session = openstack_utils.get_keystone_session( openstack_utils.get_overcloud_auth(address=ip)) client = openstack_utils.get_keystone_session_client(session) if group is None: domain_users = client.users.list( domain=client.domains.find(name=domain).id, ) else: domain_users = client.users.list( domain=client.domains.find(name=domain).id, group=self._find_keystone_v3_group(group, domain).id, ) usernames = [u.name.lower() for u in domain_users] if username.lower() in usernames: return username logging.debug( "User {} was not found. Returning None.".format(username) ) return None
def main(argv): cli_utils.setup_logging() overcloud_novarc = openstack_utils.get_overcloud_auth() user_file = mojo_utils.get_mojo_file('keystone_users.yaml') user_config = generic_utils.get_yaml_config(user_file) try: cacert = os.path.join(os.environ.get('MOJO_LOCAL_DIR'), 'cacert.pem') os.stat(cacert) except FileNotFoundError: cacert = None keystone_session = openstack_utils.get_overcloud_keystone_session( verify=cacert) keystone_client = openstack_utils.get_keystone_session_client( keystone_session) if overcloud_novarc.get('API_VERSION', 2) == 2: projects = [user['project'] for user in user_config] mojo_os_utils.project_create(keystone_client, projects) mojo_os_utils.user_create_v2(keystone_client, user_config) # TODO validate this works without adding roles # mojo_os_utils.add_users_to_roles(keystone_client, user_config) else: for user in user_config: mojo_os_utils.domain_create(keystone_client, [user['domain']]) mojo_os_utils.project_create(keystone_client, [user['project']], user['domain']) mojo_os_utils.user_create_v3(keystone_client, user_config)
def test_401_authenticate(self): """Validate that authentication succeeds for client log in.""" logging.info('Checking authentication through dashboard...') unit = zaza_model.get_unit_from_name( zaza_model.get_lead_unit_name(self.application_name)) overcloud_auth = openstack_utils.get_overcloud_auth() password = overcloud_auth['OS_PASSWORD'], logging.info("admin password is {}".format(password)) # try to get the url which will either pass or fail with a 403 overcloud_auth = openstack_utils.get_overcloud_auth() domain = 'admin_domain', username = '******', password = overcloud_auth['OS_PASSWORD'], _login(unit.public_address, domain, username, password) logging.info('OK')
def _find_keystone_v3_group(self, group, domain): """Find a group within a specified keystone v3 domain. :param str group: Group to search for in keystone :param str domain: group selected from which domain :return: return group if found :rtype: Optional[str] """ for ip in self.keystone_ips: logging.info('Keystone IP {}'.format(ip)) session = openstack_utils.get_keystone_session( openstack_utils.get_overcloud_auth(address=ip)) client = openstack_utils.get_keystone_session_client(session) domain_groups = client.groups.list( domain=client.domains.find(name=domain).id ) for searched_group in domain_groups: if searched_group.name.lower() == group.lower(): return searched_group logging.debug( "Group {} was not found. Returning None.".format(group) ) return None
def setUpClass(cls, application_name=None, model_alias=None): """Run class setup for running Designate charm operation tests.""" application_name = application_name or "designate" model_alias = model_alias or "" super(BaseDesignateTest, cls).setUpClass(application_name, model_alias) os_release = openstack_utils.get_os_release if os_release() >= os_release('bionic_rocky'): cls.designate_svcs = [ 'designate-agent', 'designate-api', 'designate-central', 'designate-mdns', 'designate-worker', 'designate-sink', 'designate-producer', ] else: cls.designate_svcs = [ 'designate-agent', 'designate-api', 'designate-central', 'designate-mdns', 'designate-pool-manager', 'designate-sink', 'designate-zone-manager', ] # Get keystone session cls.post_xenial_queens = os_release() >= os_release('xenial_queens') overcloud_auth = openstack_utils.get_overcloud_auth() keystone = openstack_utils.get_keystone_client(overcloud_auth) keystone_session = openstack_utils.get_overcloud_keystone_session() if cls.post_xenial_queens: cls.designate = openstack_utils.get_designate_session_client( session=keystone_session) cls.domain_list = cls.designate.zones.list cls.domain_delete = cls.designate.zones.delete cls.domain_create = cls.designate.zones.create else: # Authenticate admin with designate endpoint designate_ep = keystone.service_catalog.url_for( service_type='dns', interface='publicURL') keystone_ep = keystone.service_catalog.url_for( service_type='identity', interface='publicURL') cls.designate = openstack_utils.get_designate_session_client( version=1, auth_url=keystone_ep, token=keystone_session.get_token(), tenant_name="admin", endpoint=designate_ep) cls.domain_list = cls.designate.domains.list cls.domain_delete = cls.designate.domains.delete cls.domain_create = cls.designate.domains.create cls.server_list = cls.designate.servers.list cls.server_create = cls.designate.servers.create cls.server_delete = cls.designate.servers.delete
def setUpClass(cls): """Run class setup for running glance simple streams sync tests.""" super(GlanceSimpleStreamsSyncTest, cls).setUpClass() # dict of OS_* env vars overcloud_auth = openstack_utils.get_overcloud_auth() cls.keystone_client = openstack_utils.get_keystone_client( overcloud_auth) cls.glance_client = openstack_utils.get_glance_session_client( cls.keystone_session)
def setup_for_attempt_operation(self, ip): """Create a loadbalancer. This is necessary so that the attempt is to show the load-balancer and this is an operator that the policy can stop. Unfortunately, octavia, whilst it has a policy for just listing load-balancers, unfortunately, it doesn't work; whereas showing the load-balancer can be stopped. NB this only works if the setup phase of the octavia tests have been completed. :param ip: the ip of for keystone. :type ip: str """ logging.info("Setting up loadbalancer.") auth = openstack_utils.get_overcloud_auth(address=ip) sess = openstack_utils.get_keystone_session(auth) octavia_client = openstack_utils.get_octavia_session_client(sess) neutron_client = openstack_utils.get_neutron_session_client(sess) if openstack_utils.dvr_enabled(): network_name = 'private_lb_fip_network' else: network_name = 'private' resp = neutron_client.list_networks(name=network_name) vip_subnet_id = resp['networks'][0]['subnets'][0] res = octavia_client.load_balancer_create( json={ 'loadbalancer': { 'description': 'Created by Zaza', 'admin_state_up': True, 'vip_subnet_id': vip_subnet_id, 'name': 'zaza-lb-0', }}) self.lb_id = res['loadbalancer']['id'] # now wait for it to get to the active state @tenacity.retry(wait=tenacity.wait_fixed(1), reraise=True, stop=tenacity.stop_after_delay(900)) def wait_for_lb_resource(client, resource_id): resp = client.load_balancer_show(resource_id) logging.info(resp['provisioning_status']) assert resp['provisioning_status'] == 'ACTIVE', ( 'load balancer resource has not reached ' 'expected provisioning status: {}' .format(resp)) return resp logging.info('Awaiting loadbalancer to reach provisioning_status ' '"ACTIVE"') resp = wait_for_lb_resource(octavia_client, self.lb_id) logging.info(resp) logging.info("Setup loadbalancer complete.")
def get_keystone_session_admin_user(self, ip): """Return the keystone session admin user. :param ip: the IP address to get the session against. :type ip: str :returns: a keystone session to the IP address :rtype: keystoneauth1.session.Session """ return openstack_utils.get_keystone_session( openstack_utils.get_overcloud_auth(address=ip))
def test_110_catalog_endpoints(self): """Verify that the endpoints are present in the catalog.""" overcloud_auth = openstack_utils.get_overcloud_auth() keystone_client = openstack_utils.get_keystone_client( overcloud_auth) actual_endpoints = keystone_client.service_catalog.get_endpoints() actual_interfaces = [endpoint['interface'] for endpoint in actual_endpoints["baremetal"]] for expected_interface in ('internal', 'admin', 'public'): assert(expected_interface in actual_interfaces)
def test_rotate_admin_password(self): """Verify action used to rotate admin user's password.""" ADMIN_PASSWD = 'admin_passwd' old_passwd = juju_utils.leader_get(self.application_name, ADMIN_PASSWD) # test access using the old password with self.v3_keystone_preferred(): for ip in self.keystone_ips: try: ks_session = openstack_utils.get_keystone_session( openstack_utils.get_overcloud_auth(address=ip)) ks_client = openstack_utils.get_keystone_session_client( ks_session) ks_client.users.list() except keystoneauth1.exceptions.http.Forbidden: raise zaza_exceptions.KeystoneAuthorizationStrict( 'Keystone auth with old password FAILED.') # run the action to rotate the password zaza.model.run_action_on_leader( self.application_name, 'rotate-admin-password', ) # test access using the new password with self.v3_keystone_preferred(): for ip in self.keystone_ips: try: ks_session = openstack_utils.get_keystone_session( openstack_utils.get_overcloud_auth(address=ip)) ks_client = openstack_utils.get_keystone_session_client( ks_session) ks_client.users.list() except keystoneauth1.exceptions.http.Forbidden: raise zaza_exceptions.KeystoneAuthorizationStrict( 'Keystone auth with new password FAILED.') # make sure the password was actually changed new_passwd = juju_utils.leader_get(self.application_name, ADMIN_PASSWD) assert old_passwd != new_passwd
def test_backward_compatible_uuid_for_default_domain(self): """Check domain named ``default`` literally has ``default`` as ID. Some third party software chooses to hard code this value for some inexplicable reason. """ with self.v3_keystone_preferred(): ks_session = openstack_utils.get_keystone_session( openstack_utils.get_overcloud_auth()) ks_client = openstack_utils.get_keystone_session_client(ks_session) domain = ks_client.domains.get('default') logging.info(pprint.pformat(domain)) assert domain.id == 'default'
def configure_external_s3_backend(): """Set up Ceph-radosgw as an external S3 backend for Glance.""" logging.info("Creating a test S3 user and credentials for Glance") username, displayname = "zaza-glance-test", "Zaza Glance Test User" cmd = "radosgw-admin user create --uid='{}' --display-name='{}'".format( username, displayname) results = model.run_on_leader("ceph-mon", cmd) stdout = json.loads(results["stdout"]) keys = stdout["keys"][0] access_key, secret_key = keys["access_key"], keys["secret_key"] logging.info("Getting S3 endpoint URL of Radosgw from Keystone") keystone_auth = openstack_utils.get_overcloud_auth() keystone_client = openstack_utils.get_keystone_client(keystone_auth) endpoint_url = keystone_client.session.get_endpoint( service_type="s3", interface="public", region="RegionOne", ) logging.info("Creating a test S3 bucket for Glance") bucket_name = "zaza-glance-s3-test" s3_client = boto3.client( "s3", endpoint_url=endpoint_url, aws_access_key_id=access_key, aws_secret_access_key=secret_key, ) s3_client.create_bucket(Bucket=bucket_name) logging.info("Updating Glance configs with S3 endpoint information") model.set_application_config( "glance", { "s3-store-host": endpoint_url, "s3-store-access-key": access_key, "s3-store-secret-key": secret_key, "s3-store-bucket": bucket_name, }, ) model.wait_for_agent_status() logging.info("Waiting for units to reach target states") model.wait_for_application_states( states={ "glance": { "workload-status": "active", "workload-status-message": "Unit is ready", } }) model.block_until_all_units_idle()
def test_200_api_connection(self): """Simple api calls to check service is up and responding.""" logging.info('Instantiating gnocchi client...') overcloud_auth = openstack_utils.get_overcloud_auth() keystone = openstack_utils.get_keystone_client(overcloud_auth) gnocchi_ep = keystone.service_catalog.url_for(service_type='metric', interface='publicURL') gnocchi = gnocchi_client.Client( session=openstack_utils.get_overcloud_keystone_session(), adapter_options={ 'endpoint_override': gnocchi_ep, }) logging.info('Checking api functionality...') assert (gnocchi.status.get() != [])
def test_admin_project_scoped_access(self): """Verify cloud admin access using project scoped token. `admin` user in `admin_domain` should be able to access API methods guarded by `rule:cloud_admin` policy using a token scoped to `admin` project in `admin_domain`. We implement a policy that enables domain segregation and administration delegation [0]. It is important to understand that this differs from the default policy. In the initial implementation it was necessary to switch between using a `domain` scoped and `project` scoped token to successfully manage a cloud, but since the introduction of `is_admin` functionality in Keystone [1][2][3] and our subsequent adoption of it in Keystone charm [4], this is no longer necessary. This test here to validate this behaviour. 0: https://github.com/openstack/keystone/commit/c7a5c6c 1: https://github.com/openstack/keystone/commit/e702369 2: https://github.com/openstack/keystone/commit/e923a14 3: https://github.com/openstack/keystone/commit/9804081 4: https://github.com/openstack/charm-keystone/commit/10e3d84 """ if (openstack_utils.get_os_release() < openstack_utils.get_os_release('trusty_mitaka')): logging.info('skipping test < trusty_mitaka') return with self.config_change( {'preferred-api-version': self.default_api_version}, {'preferred-api-version': '3'}, application_name="keystone"): for ip in self.keystone_ips: try: logging.info('keystone IP {}'.format(ip)) ks_session = openstack_utils.get_keystone_session( openstack_utils.get_overcloud_auth(address=ip)) ks_client = openstack_utils.get_keystone_session_client( ks_session) result = ks_client.domains.list() logging.info('.domains.list: "{}"'.format( pprint.pformat(result))) except keystoneauth1.exceptions.http.Forbidden as e: raise zaza_exceptions.KeystoneAuthorizationStrict( 'Retrieve domain list as admin with project scoped ' 'token FAILED. ({})'.format(e)) logging.info('OK')
def add_auth_config(ctxt): """Add authorization config to context. :param ctxt: Context dictionary :type ctxt: dict :returns: None :rtype: None """ overcloud_auth = openstack_utils.get_overcloud_auth() ctxt['proto'] = urllib.parse.urlparse(overcloud_auth['OS_AUTH_URL']).scheme ctxt['admin_username'] = overcloud_auth['OS_USERNAME'] ctxt['admin_password'] = overcloud_auth['OS_PASSWORD'] if overcloud_auth['API_VERSION'] == 3: ctxt['admin_project_name'] = overcloud_auth['OS_PROJECT_NAME'] ctxt['admin_domain_name'] = overcloud_auth['OS_DOMAIN_NAME'] ctxt['default_credentials_domain_name'] = ( overcloud_auth['OS_PROJECT_DOMAIN_NAME'])
def test_106_compute_catalog_endpoints(self): """Verify that the compute endpoints are present in the catalog.""" overcloud_auth = openstack_utils.get_overcloud_auth() keystone_client = openstack_utils.get_keystone_client( overcloud_auth) actual_endpoints = keystone_client.service_catalog.get_endpoints() logging.info('Checking compute endpoints...') if self.current_release < self.XENIAL_QUEENS: actual_compute_endpoints = actual_endpoints['compute'][0] for expected_url in ('internalURL', 'adminURL', 'publicURL'): assert(expected_url in actual_compute_endpoints) else: actual_compute_interfaces = [endpoint['interface'] for endpoint in actual_endpoints['compute']] for expected_interface in ('internal', 'admin', 'public'): assert(expected_interface in actual_compute_interfaces)
def _auth_arguments(cls, keystone_client): """Generate workloadmgrcli arguments for cloud authentication. :returns: string of required cli arguments for authentication :rtype: str """ overcloud_auth = openstack_utils.get_overcloud_auth() overcloud_auth.update({ "OS_DOMAIN_ID": openstack_utils.get_domain_id(keystone_client, domain_name="admin_domain"), "OS_TENANT_ID": openstack_utils.get_project_id( keystone_client, project_name="admin", domain_name="admin_domain", ), "OS_TENANT_NAME": "admin", }) _required_keys = [ "OS_AUTH_URL", "OS_USERNAME", "OS_PASSWORD", "OS_REGION_NAME", "OS_DOMAIN_ID", "OS_TENANT_ID", "OS_TENANT_NAME", ] params = [] for os_key in _required_keys: params.append("--{}={}".format( os_key.lower().replace("_", "-"), overcloud_auth[os_key], )) return " ".join(params)
def test_400_api_connection(self): """Simple api calls to check service is up and responding.""" logging.info('Authenticating with the barbican endpoint') overcloud_auth = openstack_utils.get_overcloud_auth() keystone_client = openstack_utils.get_keystone_client( overcloud_auth) keystone_session = openstack_utils.get_overcloud_keystone_session() barbican_endpoint = keystone_client.service_catalog.url_for( service_type='key-manager', interface='publicURL') barbican = barbican_client.Client(session=keystone_session, endpoint=barbican_endpoint) logging.info('Creating a secret') my_secret = barbican.secrets.create() my_secret.name = u'Random plain text password' my_secret.payload = u'password' logging.info('Storing the secret') my_secret_ref = my_secret.store() assert(my_secret_ref is not None) logging.info('Deleting the secret') my_secret.delete()
def cleanup_for_attempt_operation(self, ip): """Remove the loadbalancer. :param ip: the ip of for keystone. :type ip: str """ logging.info("Deleting loadbalancer {}.".format(self.lb_id)) auth = openstack_utils.get_overcloud_auth(address=ip) sess = openstack_utils.get_keystone_session(auth) octavia_client = openstack_utils.get_octavia_session_client(sess) octavia_client.load_balancer_delete(self.lb_id) logging.info("Deleting loadbalancer in progress ...") @tenacity.retry(wait=tenacity.wait_fixed(1), reraise=True, stop=tenacity.stop_after_delay(900)) def wait_til_deleted(client, lb_id): lb_list = client.load_balancer_list() ids = [lb['id'] for lb in lb_list['loadbalancers']] assert lb_id not in ids, 'load balancer still deleting' wait_til_deleted(octavia_client, self.lb_id) logging.info("Deleted loadbalancer.")
def keystone_v3_domain_setup(): overcloud_novarc = openstack_utils.get_overcloud_auth() if overcloud_novarc.get('API_VERSION', 2) == 3: try: cacert = os.path.join(os.environ.get('MOJO_LOCAL_DIR'), 'cacert.pem') os.stat(cacert) except FileNotFoundError: cacert = None keystone_session = openstack_utils.get_overcloud_keystone_session( verify=cacert) keystone_client = openstack_utils.get_keystone_session_client( keystone_session) mojo_os_utils.project_create(keystone_client, ['admin'], 'admin_domain') admin_project_id = openstack_utils.get_project_id( keystone_client, 'admin', api_version=3, domain_name='admin_domain') role = keystone_client.roles.find(name='admin') user = keystone_client.users.find(name='admin') keystone_client.roles.grant(role, user=user, project=admin_project_id)
def test_400_gnocchi_metrics(self): """Verify that ceilometer-agent publishes metrics to gnocchi.""" current_os_release = openstack_utils.get_os_release() openstack_pike_or_older = ( current_os_release <= openstack_utils.get_os_release('xenial_pike')) if openstack_pike_or_older: # Both the charm and Ceilometer itself had different behaviors in # terms of which metrics were published and how fast, which would # lead to a combinatorial explosion if we had to maintain test # expectations for these old releases. logging.info('OpenStack Pike or older, skipping') return # ceilometer-agent-compute reports metrics for each existing VM, so at # least one VM is needed: self.RESOURCE_PREFIX = 'zaza-ceilometer-agent' self.launch_guest('ubuntu', instance_key=glance_setup.LTS_IMAGE_NAME) logging.info('Instantiating gnocchi client...') overcloud_auth = openstack_utils.get_overcloud_auth() keystone = openstack_utils.get_keystone_client(overcloud_auth) gnocchi_ep = keystone.service_catalog.url_for(service_type='metric', interface='publicURL') gnocchi = gnocchi_client.Client( session=openstack_utils.get_overcloud_keystone_session(), adapter_options={ 'endpoint_override': gnocchi_ep, }) expected_metric_names = self.__get_expected_metric_names( current_os_release) min_timeout_seconds = 500 polling_interval_seconds = ( openstack_utils.get_application_config_option( self.application_name, 'polling-interval')) timeout_seconds = max(10 * polling_interval_seconds, min_timeout_seconds) logging.info('Giving ceilometer-agent {}s to publish all metrics to ' 'gnocchi...'.format(timeout_seconds)) max_time = time.time() + timeout_seconds while time.time() < max_time: found_metric_names = { metric['name'] for metric in gnocchi.metric.list() } missing_metric_names = expected_metric_names - found_metric_names if len(missing_metric_names) == 0: logging.info('All expected metrics found.') break time.sleep(polling_interval_seconds) unexpected_found_metric_names = (found_metric_names - expected_metric_names) if len(unexpected_found_metric_names) > 0: logging.info('Unexpected metrics ' 'published: ' + ', '.join(unexpected_found_metric_names)) if len(missing_metric_names) > 0: self.fail('These metrics should have been published but ' "weren't: " + ', '.join(missing_metric_names))
def main(argv): cli_utils.setup_logging() parser = argparse.ArgumentParser() default_machines = ["cirros:m1.tiny:1"] parser.add_argument("machines", default=default_machines, nargs="*") parser.add_argument("--active_wait", default=600) parser.add_argument("--cloudinit_wait", default=600) parser.add_argument("--ping_wait", default=600) options = parser.parse_args() machines = cli_utils.parse_arg(options, 'machines', multiargs=True) active_wait = int(cli_utils.parse_arg(options, 'active_wait')) cloudinit_wait = int(cli_utils.parse_arg(options, 'cloudinit_wait')) ping_wait = int(cli_utils.parse_arg(options, 'ping_wait')) overcloud_novarc = openstack_utils.get_overcloud_auth() try: cacert = os.path.join(os.environ.get('MOJO_LOCAL_DIR'), 'cacert.pem') os.stat(cacert) logging.info("Using cacert file: {}".format(cacert)) except FileNotFoundError: logging.info("Not using a cacert pem file") cacert = None logging.info("Initializing client sessions") keystone_session = openstack_utils.get_overcloud_keystone_session( verify=cacert) keystonec = openstack_utils.get_keystone_session_client(keystone_session) domain = overcloud_novarc.get('OS_PROJECT_DOMAIN_NAME') project_id = openstack_utils.get_project_id( keystonec, 'admin', api_version=overcloud_novarc['API_VERSION'], domain_name=domain) novac = openstack_utils.get_nova_session_client(keystone_session) neutronc = openstack_utils.get_neutron_session_client(keystone_session) init_flavors(novac) priv_key = mojo_os_utils.create_keypair(novac, 'mojo') openstack_utils.add_neutron_secgroup_rules(neutronc, project_id) for server in novac.servers.list(search_opts={'all_tenants': 1}): if server.name.startswith('mojo'): logging.info("Deleting nova instance {}".format(server.id)) novac.servers.delete(server.id) for instanceset in machines: image_name, flavor_name, count = instanceset.split(":") # when instance count allows boot instances off both regular instance # storage and volume storage # # account for count=1 and odd numbers # NOTE(fnordahl) temporarilly disable test while tests settle # regular_boot_count = int(int(count) / 2) + (int(count) % 2) # volume_boot_count = int(int(count) / 2) regular_boot_count = int(count) volume_boot_count = 0 mojo_os_utils.boot_and_test( novac, neutronc, image_name=image_name, flavor_name=flavor_name, number=regular_boot_count, privkey=priv_key, active_wait=active_wait, cloudinit_wait=cloudinit_wait, ping_wait=ping_wait, ) mojo_os_utils.boot_and_test( novac, neutronc, image_name=image_name, flavor_name=flavor_name, number=volume_boot_count, privkey=priv_key, active_wait=active_wait, cloudinit_wait=cloudinit_wait, ping_wait=ping_wait, boot_from_volume=True, )
def test_401_authenticate(self): """Validate that authentication succeeds for client log in. Ported from amulet tests. """ logging.info('Checking authentication through dashboard...') unit_name = zaza_model.get_lead_unit_name('openstack-dashboard') keystone_unit = zaza_model.get_lead_unit_name('keystone') dashboard_relation = openstack_juju.get_relation_from_unit( keystone_unit, unit_name, 'identity-service') dashboard_ip = dashboard_relation['private-address'] logging.debug("... dashboard_ip is:{}".format(dashboard_ip)) url = 'http://{}/horizon/auth/login/'.format(dashboard_ip) overcloud_auth = openstack_utils.get_overcloud_auth() if overcloud_auth['OS_AUTH_URL'].endswith("v2.0"): api_version = 2 else: api_version = 3 keystone_client = openstack_utils.get_keystone_client(overcloud_auth) catalog = keystone_client.service_catalog.get_endpoints() logging.info(catalog) if api_version == 2: region = catalog['identity'][0]['publicURL'] else: region = [ i['url'] for i in catalog['identity'] if i['interface'] == 'public' ][0] # NOTE(ajkavanagh) there used to be a trusty/icehouse test in the # amulet test, but as the zaza tests only test from trusty/mitaka # onwards, the test has been dropped if (openstack_utils.get_os_release() >= openstack_utils.get_os_release('bionic_stein')): expect = "Sign Out" # update the in dashboard seems to require region to be default in # this test configuration region = 'default' else: expect = 'Projects - OpenStack Dashboard' # NOTE(thedac) Similar to the connection test above we get occasional # intermittent authentication fails. Wrap in a retry loop. @tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, min=5, max=10), retry=tenacity.retry_unless_exception_type( self.AuthExceptions), reraise=True) def _do_auth_check(expect): # start session, get csrftoken client = requests.session() client.get(url) if 'csrftoken' in client.cookies: csrftoken = client.cookies['csrftoken'] else: raise Exception("Missing csrftoken") # build and send post request auth = { 'domain': 'admin_domain', 'username': '******', 'password': overcloud_auth['OS_PASSWORD'], 'csrfmiddlewaretoken': csrftoken, 'next': '/horizon/', 'region': region, } # In the minimal test deployment /horizon/project/ is unauthorized, # this does not occur in a full deployment and is probably due to # services/information missing that horizon wants to display data # for. # Redirect to /horizon/identity/ instead. if (openstack_utils.get_os_release() >= openstack_utils.get_os_release('xenial_queens')): auth['next'] = '/horizon/identity/' if (openstack_utils.get_os_release() >= openstack_utils.get_os_release('bionic_stein')): auth['region'] = 'default' if api_version == 2: del auth['domain'] logging.info('POST data: "{}"'.format(auth)) response = client.post(url, data=auth, headers={'Referer': url}) if expect not in response.text: msg = 'FAILURE code={} text="{}"'.format( response, response.text) # NOTE(thedac) amulet.raise_status exits on exception. # Raise a custom exception. logging.info("Yeah, wen't wrong: {}".format(msg)) raise self.FailedAuth(msg) raise self.PassedAuth() try: _do_auth_check(expect) except self.FailedAuth as e: assert False, str(e) except self.PassedAuth: pass
def _test_get_overcloud_auth(self, tls_relation=False, ssl_cert=False, v2_api=False): self.patch_object(openstack_utils.model, 'get_relation_id') self.patch_object(openstack_utils, 'get_application_config_option') self.patch_object(openstack_utils, 'get_keystone_ip') self.patch_object(openstack_utils, "get_current_os_versions") self.patch_object(openstack_utils.juju_utils, 'leader_get') if tls_relation: self.patch_object(openstack_utils.model, "scp_from_unit") self.patch_object(openstack_utils.model, "get_first_unit_name") self.get_first_unit_name.return_value = "keystone/4" self.patch_object(openstack_utils.os, "chmod") self.patch_object(openstack_utils.os, "path") self.path.return_value = True self.get_keystone_ip.return_value = '127.0.0.1' self.get_relation_id.return_value = None self.get_application_config_option.return_value = None self.leader_get.return_value = 'openstack' if tls_relation or ssl_cert: port = 35357 transport = 'https' if tls_relation: self.get_relation_id.return_value = 'tls-certificates:1' if ssl_cert: self.get_application_config_option.side_effect = [ 'FAKECRTDATA', None, ] else: port = 5000 transport = 'http' if v2_api: str_api = 'v2.0' self.get_current_os_versions.return_value = {"keystone": "mitaka"} expect = { 'OS_AUTH_URL': '{}://127.0.0.1:{}/{}'.format(transport, port, str_api), 'OS_TENANT_NAME': 'admin', 'OS_USERNAME': '******', 'OS_PASSWORD': '******', 'OS_REGION_NAME': 'RegionOne', 'API_VERSION': 2, } else: str_api = 'v3' self.get_current_os_versions.return_value = {"keystone": "queens"} expect = { 'OS_AUTH_URL': '{}://127.0.0.1:{}/{}'.format(transport, port, str_api), 'OS_USERNAME': '******', 'OS_PASSWORD': '******', 'OS_REGION_NAME': 'RegionOne', 'OS_DOMAIN_NAME': 'admin_domain', 'OS_USER_DOMAIN_NAME': 'admin_domain', 'OS_PROJECT_NAME': 'admin', 'OS_PROJECT_DOMAIN_NAME': 'admin_domain', 'API_VERSION': 3, } if tls_relation: expect['OS_CACERT'] = openstack_utils.KEYSTONE_LOCAL_CACERT self.assertEqual(openstack_utils.get_overcloud_auth(), expect)
def _login(dashboard_url, domain, username, password, cafile=None): """Login to the website to get a session. :param dashboard_url: The URL of the dashboard to log in to. :type dashboard_url: str :param domain: the domain to login into :type domain: str :param username: the username to login as :type username: str :param password: the password to use to login :type password: str :returns: tuple of (client, response) where response is the page after logging in. :rtype: (requests.sessions.Session, requests.models.Response) :raises: FailedAuth if the authorisation doesn't work """ auth_url = '{}/auth/login/'.format(dashboard_url) # start session, get csrftoken client = requests.session() client.get(auth_url, verify=cafile) if 'csrftoken' in client.cookies: csrftoken = client.cookies['csrftoken'] else: raise Exception("Missing csrftoken") # build and send post request overcloud_auth = openstack_utils.get_overcloud_auth() if overcloud_auth['OS_AUTH_URL'].endswith("v2.0"): api_version = 2 else: api_version = 3 keystone_client = openstack_utils.get_keystone_client(overcloud_auth) catalog = keystone_client.service_catalog.get_endpoints() logging.info(catalog) if api_version == 2: region = catalog['identity'][0]['publicURL'] else: region = [ i['url'] for i in catalog['identity'] if i['interface'] == 'public' ][0] auth = { 'domain': domain, 'username': username, 'password': password, 'csrfmiddlewaretoken': csrftoken, 'next': '/horizon/', 'region': region, } # In the minimal test deployment /horizon/project/ is unauthorized, # this does not occur in a full deployment and is probably due to # services/information missing that horizon wants to display data # for. # Redirect to /horizon/identity/ instead. if (openstack_utils.get_os_release() >= openstack_utils.get_os_release('xenial_queens')): auth['next'] = '/horizon/identity/' if (openstack_utils.get_os_release() >= openstack_utils.get_os_release('bionic_stein')): auth['region'] = 'default' if api_version == 2: del auth['domain'] logging.info('POST data: "{}"'.format(auth)) response = client.post(auth_url, data=auth, headers={'Referer': auth_url}, verify=cafile) # NOTE(ajkavanagh) there used to be a trusty/icehouse test in the # amulet test, but as the zaza tests only test from trusty/mitaka # onwards, the test has been dropped if (openstack_utils.get_os_release() >= openstack_utils.get_os_release('bionic_stein')): expect = "Sign Out" # update the in dashboard seems to require region to be default in # this test configuration region = 'default' else: expect = 'Projects - OpenStack Dashboard' if expect not in response.text: msg = 'FAILURE code={} text="{}"'.format(response, response.text) logging.info("Yeah, wen't wrong: {}".format(msg)) raise FailedAuth(msg) logging.info("Logged into okay") return client, response