Beispiel #1
0
    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")
Beispiel #2
0
    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')
Beispiel #3
0
    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')
Beispiel #6
0
    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
Beispiel #7
0
    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
Beispiel #8
0
 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)
Beispiel #9
0
    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.")
Beispiel #10
0
    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))
Beispiel #11
0
 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)
Beispiel #12
0
    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
Beispiel #13
0
    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'
Beispiel #14
0
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()
Beispiel #15
0
    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() != [])
Beispiel #16
0
    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')
Beispiel #17
0
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)
Beispiel #19
0
    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)
Beispiel #20
0
    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()
Beispiel #21
0
    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)
Beispiel #23
0
    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,
        )
Beispiel #25
0
    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
Beispiel #26
0
    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)
Beispiel #27
0
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