Add novajoin server test

This commit is contained in:
Ade Lee 2017-08-18 17:12:56 +00:00
parent d3ea01cc31
commit 20e73d9285
4 changed files with 206 additions and 208 deletions

View File

@ -190,7 +190,7 @@ class IPAClient(IPABase):
def service_managed_by_host(self, service_principal, host):
"""Return True if service is managed by specified host"""
params = [service_principal]
params = [unicode(service_principal)]
service_args = {}
try:
result = self._call_ipa('service_show', *params, **service_args)

View File

@ -16,7 +16,6 @@
from oslo_log import log
from tempest.common import compute
from tempest.common import image as common_image
from tempest.common.utils.linux import remote_client
from tempest.common import waiters
@ -35,51 +34,51 @@ LOG = log.getLogger(__name__)
class ScenarioTest(tempest.test.BaseTestCase):
"""Base class for scenario tests. Uses tempest own clients. """
credentials = ['primary']
credentials = ['primary', 'admin']
@classmethod
def setup_clients(cls):
super(ScenarioTest, cls).setup_clients()
# Clients (in alphabetical order)
cls.flavors_client = cls.os_primary.flavors_client
cls.flavors_client = cls.os_admin.flavors_client
cls.compute_floating_ips_client = (
cls.os_primary.compute_floating_ips_client)
cls.os_admin.compute_floating_ips_client)
if CONF.service_available.glance:
# Check if glance v1 is available to determine which client to use.
if CONF.image_feature_enabled.api_v1:
cls.image_client = cls.os_primary.image_client
cls.image_client = cls.os_admin.image_client
elif CONF.image_feature_enabled.api_v2:
cls.image_client = cls.os_primary.image_client_v2
cls.image_client = cls.os_admin.image_client_v2
else:
raise lib_exc.InvalidConfiguration(
'Either api_v1 or api_v2 must be True in '
'[image-feature-enabled].')
# Compute image client
cls.compute_images_client = cls.os_primary.compute_images_client
cls.keypairs_client = cls.os_primary.keypairs_client
cls.compute_images_client = cls.os_admin.compute_images_client
cls.keypairs_client = cls.os_admin.keypairs_client
# Nova security groups client
cls.compute_security_groups_client = (
cls.os_primary.compute_security_groups_client)
cls.os_admin.compute_security_groups_client)
cls.compute_security_group_rules_client = (
cls.os_primary.compute_security_group_rules_client)
cls.servers_client = cls.os_primary.servers_client
cls.os_admin.compute_security_group_rules_client)
cls.servers_client = cls.os_admin.servers_client
# Neutron network client
cls.networks_client = cls.os_primary.networks_client
cls.ports_client = cls.os_primary.ports_client
cls.routers_client = cls.os_primary.routers_client
cls.subnets_client = cls.os_primary.subnets_client
cls.floating_ips_client = cls.os_primary.floating_ips_client
cls.security_groups_client = cls.os_primary.security_groups_client
cls.networks_client = cls.os_admin.networks_client
cls.ports_client = cls.os_admin.ports_client
cls.routers_client = cls.os_admin.routers_client
cls.subnets_client = cls.os_admin.subnets_client
cls.floating_ips_client = cls.os_admin.floating_ips_client
cls.security_groups_client = cls.os_admin.security_groups_client
cls.security_group_rules_client = (
cls.os_primary.security_group_rules_client)
cls.os_admin.security_group_rules_client)
if CONF.volume_feature_enabled.api_v2:
cls.volumes_client = cls.os_primary.volumes_v2_client
cls.snapshots_client = cls.os_primary.snapshots_v2_client
cls.volumes_client = cls.os_admin.volumes_v2_client
cls.snapshots_client = cls.os_admin.snapshots_v2_client
if CONF.volume_feature_enabled.api_v1:
cls.volumes_client = cls.os_primary.volumes_client
cls.snapshots_client = cls.os_primary.snapshots_client
cls.volumes_client = cls.os_admin.volumes_client
cls.snapshots_client = cls.os_admin.snapshots_client
# ## Test functions library
#
@ -107,105 +106,23 @@ class ScenarioTest(tempest.test.BaseTestCase):
name = data_utils.rand_name(self.__class__.__name__)
# We don't need to create a keypair by pubkey in scenario
body = client.create_keypair(name=name)
self.addCleanup(client.delete_keypair, name)
return body['keypair']
def create_server(self, name=None, image_id=None, flavor=None,
validatable=False, wait_until='ACTIVE',
clients=None, **kwargs):
"""Wrapper utility that returns a test server.
This wrapper utility calls the common create test server and
returns a test server. The purpose of this wrapper is to minimize
the impact on the code of the tests already using this
function.
"""
# NOTE(jlanoux): As a first step, ssh checks in the scenario
# tests need to be run regardless of the run_validation and
# validatable parameters and thus until the ssh validation job
# becomes voting in CI. The test resources management and IP
# association are taken care of in the scenario tests.
# Therefore, the validatable parameter is set to false in all
# those tests. In this way create_server just return a standard
# server and the scenario tests always perform ssh checks.
# Needed for the cross_tenant_traffic test:
if clients is None:
clients = self.os_primary
if name is None:
name = data_utils.rand_name(self.__class__.__name__ + "-server")
vnic_type = CONF.network.port_vnic_type
# If vnic_type is configured create port for
# every network
if vnic_type:
ports = []
create_port_body = {'binding:vnic_type': vnic_type,
'namestart': 'port-smoke'}
if kwargs:
# Convert security group names to security group ids
# to pass to create_port
if 'security_groups' in kwargs:
security_groups = \
clients.security_groups_client.list_security_groups(
).get('security_groups')
sec_dict = dict([(s['name'], s['id'])
for s in security_groups])
sec_groups_names = [s['name'] for s in kwargs.pop(
'security_groups')]
security_groups_ids = [sec_dict[s]
for s in sec_groups_names]
if security_groups_ids:
create_port_body[
'security_groups'] = security_groups_ids
networks = kwargs.pop('networks', [])
else:
networks = []
# If there are no networks passed to us we look up
# for the project's private networks and create a port.
# The same behaviour as we would expect when passing
# the call to the clients with no networks
if not networks:
networks = clients.networks_client.list_networks(
**{'router:external': False, 'fields': 'id'})['networks']
# It's net['uuid'] if networks come from kwargs
# and net['id'] if they come from
# clients.networks_client.list_networks
for net in networks:
net_id = net.get('uuid', net.get('id'))
if 'port' not in net:
port = self._create_port(network_id=net_id,
client=clients.ports_client,
**create_port_body)
ports.append({'port': port['id']})
else:
ports.append({'port': net['port']})
if ports:
kwargs['networks'] = ports
self.ports = ports
tenant_network = self.get_tenant_network()
body, servers = compute.create_test_server(
clients,
tenant_network=tenant_network,
wait_until=wait_until,
name=name, flavor=flavor,
image_id=image_id, **kwargs)
self.addCleanup(waiters.wait_for_server_termination,
clients.servers_client, body['id'])
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
clients.servers_client.delete_server, body['id'])
server = clients.servers_client.show_server(body['id'])['server']
net_id=None, key=None, wait_until='ACTIVE',
sec_grps=[], metadata={}, **kwargs):
networks = [{'uuid': net_id}]
server = self.servers_client.create_server(name=name,
imageRef=image_id,
flavorRef=flavor,
key_name=key,
security_groups=sec_grps,
networks=networks,
metadata=metadata,
**kwargs)['server']
server_id = server['id']
waiters.wait_for_server_status(self.servers_client, server_id,
'ACTIVE')
return server
def create_volume(self, size=None, name=None, snapshot_id=None,
@ -263,8 +180,8 @@ class ScenarioTest(tempest.test.BaseTestCase):
self.addCleanup(client.delete_volume_type, volume_type['id'])
return volume_type
def _image_create(self, name, fmt, path,
disk_format=None, properties=None):
def image_create(self, name, fmt,
disk_format=None, properties=None):
if properties is None:
properties = {}
name = data_utils.rand_name('%s-' % name)
@ -283,9 +200,10 @@ class ScenarioTest(tempest.test.BaseTestCase):
params.update(properties)
body = self.image_client.create_image(**params)
image = body['image'] if 'image' in body else body
self.addCleanup(self.image_client.delete_image, image['id'])
# self.addCleanup(self.image_client.delete_image, image['id'])
self.assertEqual("queued", image['status'])
with open(path, 'rb') as image_file:
img_path = CONF.scenario.img_dir + "/" + CONF.scenario.img_file
with open(img_path, 'rb') as image_file:
if CONF.image_feature_enabled.api_v1:
self.image_client.update_image(image['id'], data=image_file)
else:

View File

@ -58,6 +58,13 @@ class NovajoinScenarioTest(manager.ScenarioTest):
if add_domain:
host = self.add_domain_to_host(host)
result = self.ipa_client.find_host(host)
start = int(time.time())
host_count = result['count']
timeout = 300
while (host_count > 0) and (int(time.time()) - start < timeout):
time.sleep(30)
result = self.ipa_client.find_host(host)
host_count = result['count']
self.assertFalse(result['count'] > 0)
def add_domain_to_host(self, host):
@ -85,14 +92,34 @@ class NovajoinScenarioTest(manager.ScenarioTest):
self.assertTrue(result['count'] > 0)
def verify_service_managed_by_host(self, service, host):
# TODO(alee) Implement this using service-show
pass
service_principal = self.get_service_principal(host, service)
result = self.ipa_client.service_managed_by_host(service_principal,
host)
self.assertTrue(result)
def verify_service_deleted(self, service, host):
service_principal = self.get_service_principal(host, service)
result = self.ipa_client.find_service(service_principal)
self.assertFalse(result['count'] > 0)
def verify_compact_services_deleted(self, services, host):
for (service, networks) in services.items():
for network in networks:
subhost = '{host}.{network}.{domain}'.format(
host=host, network=network, domain=self.ipa_client.domain
)
service_principal = self.get_service_principal(subhost, service)
result = self.ipa_client.find_service(service_principal)
self.assertFalse(result['count'] > 0)
def verify_managed_services_deleted(self, services):
for principal in services:
service = principal.split('/', 1)[0]
host = principal.split('/', 1)[1]
service_principal = self.get_service_principal(host, service)
result = self.ipa_client.find_service(service_principal)
self.assertFalse(result['count'] > 0)
def get_service_cert(self, service, host):
service_principal = self.get_service_principal(host, service)
return self.ipa_client.get_service_cert(service_principal)
@ -103,7 +130,7 @@ class NovajoinScenarioTest(manager.ScenarioTest):
)
def verify_host_is_ipaclient(self, hostip, user, keypair):
cmd = 'id admin'
cmd = "id admin"
private_key = keypair['private_key']
ssh_client = self.get_remote_client(hostip, user, private_key)
result = ssh_client.exec_command(cmd)

View File

@ -13,104 +13,157 @@
# under the License.
from oslo_log import log as logging
from tempest import config
from tempest.lib import decorators
from tempest import test
from tempest.lib.common.utils import data_utils
from novajoin_tempest_plugin.tests.scenario import novajoin_manager
import ast
CONF = config.CONF
LOG = logging.getLogger(__name__)
USER = 'cloud-user'
NETWORK = 'ctlplane'
class EnrollmentTest(novajoin_manager.NovajoinScenarioTest):
class ServerTest(novajoin_manager.NovajoinScenarioTest):
"""The test suite for server enrollment
This test is to verify the enrollment and removal of
servers with a nova service that has been configured to register
and de-register clients with an IPA server.
We create servers using ipa_enroll=True as metadata, and also
by using an image that contains ipa_enroll=True as metadata.
The tests do the following:
* Create a server using either metadata method
* Validate that the server is registered in the IPA server
* Validate the the ipaclient is working on the server
* Delete the newly created server
* Validate that the server is no longer registered with IPA
TODO: We can also add the following tests:
* Add metadata to register and create some cert entries
* Validate that the certs for those entries are issued and
tracked
* Validate that the service entries are removed when the
instance is deleted.
* Validate that the certs issued have been revoked.
"""
credentials = ['primary', 'admin']
@classmethod
def skip_checks(cls):
super(EnrollmentTest, cls).skip_checks()
pass
def setup_credentials(cls):
cls.set_network_resources()
super(ServerTest, cls).setup_credentials()
@decorators.idempotent_id('89165fb4-5534-4b9d-8429-97ccffb8f86f')
@test.services('compute')
def test_enrollment_using_metadata(self):
LOG.info("Creating keypair and security group")
keypair = self.create_keypair()
security_group = self._create_security_group()
# TODO(alee) Add metadata for ipa_enroll=True
# TODO(alee) Add metadata for service to be created/joined
@classmethod
def setup_clients(cls):
super(ServerTest, cls).setup_clients()
service = "random service to be added"
cn = "cn of random service certificate"
server = self.create_server(
name='passed_metadata_server',
image_id=self.no_metadata_img_uuid,
key_name=keypair['name'],
security_groups=[{'name': security_group['name']}],
wait_until='ACTIVE'
@classmethod
def resource_setup(cls):
super(ServerTest, cls).resource_setup()
def _create_flavor(self, flavor_name):
specs = {"capabilities:boot_option": "local",
"capabilities:profile": "compute"}
flvid = data_utils.rand_int_id(start=1000)
ram = 4096
vcpus = 1
disk = 40
self.flavors_client.create_flavor(name=flavor_name,
ram=ram,
vcpus=vcpus,
disk=disk,
id=flvid)['flavor']
self.flavors_client.set_flavor_extra_spec(flvid,
**specs)
return flvid
def _create_image(self, name, properties={}):
container_format = 'bare'
disk_format = 'qcow2'
image_id = self.image_create(name=name,
fmt=container_format,
disk_format=disk_format,
properties=properties)
return image_id
def _verify_host_and_services_are_enrolled(self, server_name,
server_id, keypair):
self.verify_host_registered_with_ipa(server_name)
self.verify_host_has_keytab(server_name)
# Verify compact services are created
metadata = self.servers_client.list_server_metadata(server_id
)['metadata']
services = metadata['compact_services']
self.compact_services = ast.literal_eval(services)
self.verify_compact_services(
services=self.compact_services,
host=server_name,
)
self.verify_registered_host(server, keypair, service, cn)
self.delete_server(server)
serial = "serial number of random service certificate"
self.verify_unregistered_host(server, service, serial)
# Verify managed services are created
metadata = self.servers_client.list_server_metadata(server_id
)['metadata']
self.managed_services = [metadata[key] for key in metadata.keys()
if key.startswith('managed_service_')]
self.verify_managed_services(self.managed_services)
@decorators.idempotent_id('cbc752ed-b716-4727-910f-956ccf965723')
@test.services('compute')
def test_enrollment_using_image_metadata(self):
LOG.info("Creating keypair and security group")
# Verify instance created above is ipaclient
server_details = self.servers_client.show_server(server_id
)['server']
ip = self.get_server_ip(server_details)
self.verify_host_is_ipaclient(ip, USER, keypair)
def _verify_host_and_services_are_not_enrolled(self,
server_name,
server_id):
# Verify host and associated compact and managed services
# are no longer registered with ipa
self.verify_host_not_registered_with_ipa(server_name)
self.verify_compact_services_deleted(services=self.compact_services,
host=server_name)
self.verify_managed_services_deleted(self.managed_services)
def test_enrollment_metadata_in_instance(self):
networks = self.networks_client.list_networks(name=NETWORK)
net_id = networks['networks'][0]['id']
flavor_name = data_utils.rand_name('flv_metadata_in_instance')
flavor_id = self._create_flavor(flavor_name)
image_name = data_utils.rand_name('img_metadata_in_instance')
image_id = self._create_image(image_name)
keypair = self.create_keypair()
security_group = self._create_security_group()
instance_name = data_utils.rand_name("instance")
metadata = {"ipa_enroll": "True",
"compact_services":
"{\"HTTP\": [\"ctlplane\", \"internalapi\"]}",
"managed_service_test": "novajoin/test.example.com"}
server = self.create_server(name=instance_name,
image_id=image_id,
flavor=flavor_id,
net_id=net_id,
key=keypair['name'],
metadata=metadata,
wait_until='ACTIVE')
self._verify_host_and_services_are_enrolled(instance_name,
server['id'],
keypair)
self.servers_client.delete_server(server['id'])
self._verify_host_and_services_are_not_enrolled(instance_name,
server['id'])
# TODO(alee) Add metadata for service to be created/joined
service = "random service to be added"
cn = "cn of random service certificate"
def test_enrollment_metadata_in_image(self):
server = self.create_server(
name='img_with_metadata_server',
image_id=self.metadata_img_uuid,
key_name=keypair['name'],
security_groups=[{'name': security_group['name']}],
wait_until='ACTIVE'
)
self.verify_registered_host(server, keypair, service, cn)
self.delete_server(server)
serial = "serial number of cert for random service"
self.verify_unregistered_host(server, service, serial)
def verify_registered_host(self, server, keypair, service, cn):
self.verify_host_registered_with_ipa(server)
self.verify_host_has_keytab(server)
self.verify_host_is_ipaclient(server, keypair)
self.verify_service_created(service, server)
self.verify_cert_tracked(server, keypair, cn)
def verify_unregistered_host(self, server, service, serial):
self.verify_host_not_registered_with_ipa(server)
self.verify_service_deleted(service, server)
self.verify_cert_revoked(serial)
networks = self.networks_client.list_networks(name=NETWORK)
net_id = networks['networks'][0]['id']
flavor_name = data_utils.rand_name('flv_metadata_in_image')
flavor_id = self._create_flavor(flavor_name)
image_name = data_utils.rand_name('metadata_in_image')
properties = {"ipa_enroll": "True"}
image_id = self._create_image(image_name, properties)
keypair = self.create_keypair()
f = open('/tmp/priv.key', 'w')
f.write(keypair['private_key'])
f.close()
instance_name = data_utils.rand_name("novajoin")
metadata = {"compact_services":
"{\"HTTP\": [\"ctlplane\", \"internalapi\"]}",
"managed_service_test": "novajoin/test.example.com"}
server = self.create_server(name=instance_name,
image_id=image_id,
flavor=flavor_id,
net_id=net_id,
key=keypair['name'],
metadata=metadata,
wait_until='ACTIVE')
self._verify_host_and_services_are_enrolled(instance_name,
server['id'], keypair)
self.servers_client.delete_server(server['id'])
self._verify_host_and_services_are_not_enrolled(instance_name,
server['id'])