karbor/karbor/tests/fullstack/karbor_objects.py

473 lines
15 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from functools import partial
from oslo_utils import uuidutils
from karbor.common import constants
from karbor.tests.fullstack import karbor_base as base
from karbor.tests.fullstack import utils
SHORT_TIMEOUT = 150
MEDIUM_TIMEOUT = 450
LONG_TIMEOUT = 900
SHORT_SLEEP = 3
MEDIUM_SLEEP = 15
LONG_SLEEP = 30
HUGE_SLEEP = 100
DEFAULT_FLAVOR = "cirros256"
DEFAULT_NETWORK = "private"
class Checkpoint(object):
def __init__(self):
super(Checkpoint, self).__init__()
self.id = None
self._provider_id = None
self.karbor_client = base._get_karbor_client()
def _checkpoint_status(self, status=None):
try:
cp = self.karbor_client.checkpoints.get(self._provider_id, self.id)
except Exception:
return False
if status is None or cp.status == status:
return True
else:
return False
def create(self, provider_id, plan_id, timeout=LONG_TIMEOUT):
self._provider_id = provider_id
checkpoint = self.karbor_client.checkpoints.create(provider_id,
plan_id)
self.id = checkpoint.id
utils.wait_until_true(partial(self._checkpoint_status,
constants.CHECKPOINT_STATUS_AVAILABLE),
timeout=timeout, sleep=HUGE_SLEEP)
return self.id
def close(self, timeout=MEDIUM_TIMEOUT):
try:
self.karbor_client.checkpoints.delete(self._provider_id, self.id)
except Exception:
return
utils.wait_until_true(partial(self._checkpoint_status,
constants.CHECKPOINT_STATUS_DELETED),
timeout=timeout, sleep=LONG_SLEEP)
class Plan(object):
_name_id = 0
def __init__(self):
super(Plan, self).__init__()
self.id = None
self.karbor_client = base._get_karbor_client()
def create(self, provider_id, resources,
parameters={}, name=None):
def _transform_resource(resource):
if isinstance(resource, dict):
return resource
if hasattr(resource, 'to_dict') and callable(resource.to_dict):
return resource.to_dict()
if name is None:
name = "KarborFullstack-Plan-{id}".format(
id=self.__class__._name_id
)
self.__class__._name_id += 1
resources = map(_transform_resource, resources)
plan = self.karbor_client.plans.create(name, provider_id, resources,
parameters)
self.id = plan.id
return self.id
def update(self, data):
return self.karbor_client.plans.update(self.id, data)
def close(self):
try:
self.karbor_client.plans.delete(self.id)
except Exception:
return
class Restore(object):
def __init__(self):
super(Restore, self).__init__()
self.id = None
self.karbor_client = base._get_karbor_client()
def _restore_status(self, status=None):
try:
restore = self.karbor_client.restores.get(self.id)
except Exception:
return False
if status is None or restore.status == status:
return True
else:
return False
def create(self, provider_id, checkpoint_id, target, parameters,
restore_auth, timeout=LONG_TIMEOUT):
restore = self.karbor_client.restores.create(provider_id,
checkpoint_id,
target,
parameters,
restore_auth)
self.id = restore.id
utils.wait_until_true(partial(self._restore_status, 'success'),
timeout=timeout, sleep=HUGE_SLEEP)
return self.id
def close(self):
pass
class Trigger(object):
_name_id = 0
def __init__(self):
super(Trigger, self).__init__()
self.id = None
self.karbor_client = base._get_karbor_client()
def create(self, type, properties, name=None):
if name is None:
name = "KarborFullstack-Trigger-{id}".format(
id=self.__class__._name_id
)
self.__class__._name_id += 1
trigger = self.karbor_client.triggers.create(name, type, properties)
self.id = trigger.id
return self.id
def close(self):
try:
self.karbor_client.triggers.delete(self.id)
except Exception:
return
class ScheduledOperation(object):
_name_id = 0
def __init__(self):
super(ScheduledOperation, self).__init__()
self.id = None
self.karbor_client = base._get_karbor_client()
def create(self, operation_type, trigger_id,
operation_definition, name=None):
if name is None:
name = "KarborFullstack-Scheduled-Operation-{id}".format(
id=self.__class__._name_id
)
self.__class__._name_id += 1
scheduled_operation = self.karbor_client.scheduled_operations.create(
name,
operation_type,
trigger_id,
operation_definition
)
self.id = scheduled_operation.id
return self.id
def close(self):
try:
self.karbor_client.scheduled_operations.delete(self.id)
except Exception:
return
class Server(object):
_name_id = 0
def __init__(self):
super(Server, self).__init__()
self.id = None
self._name = None
self.nova_client = base._get_nova_client()
self.neutron_client = base._get_neutron_client()
self.cinder_client = base._get_cinder_client()
self.glance_client = base._get_glance_client()
def _server_status(self, status=None):
try:
server = self.nova_client.servers.get(self.id)
except Exception:
return False
if status is None or status == server.status:
return True
else:
return False
def to_dict(self):
return {
"id": self.id,
"type": constants.SERVER_RESOURCE_TYPE,
"name": self._name,
}
def create(self, name=None, image=None, volume=None, flavor=DEFAULT_FLAVOR,
network=DEFAULT_NETWORK, timeout=LONG_TIMEOUT):
block_device_mapping_v2 = None
if volume:
block_device_mapping_v2 = [{
'uuid': volume,
'source_type': 'volume',
'destination_type': 'volume',
'boot_index': 0,
'delete_on_termination': False}]
else:
if not image:
images = self.glance_client.images.list()
for image_iter in images:
if image_iter['disk_format'] not in ('aki', 'ari') and (
image_iter['name'].startswith('cirros')):
image = image_iter['id']
break
assert image
flavor = self.nova_client.flavors.find(name=flavor)
if name is None:
name = "KarborFullstack-Server-{id}".format(
id=self.__class__._name_id
)
self.__class__._name_id += 1
self._name = name
networks = self.neutron_client.list_networks(name=network)
assert len(networks['networks']) > 0
network_id = networks['networks'][0]['id']
server = self.nova_client.servers.create(
name=name,
image=image,
block_device_mapping_v2=block_device_mapping_v2,
flavor=flavor,
nics=[{"net-id": network_id}],
)
self.id = server.id
utils.wait_until_true(partial(self._server_status, 'ACTIVE'),
timeout=timeout, sleep=MEDIUM_SLEEP)
return self.id
def _volume_attached(self, volume_id):
volume_item = self.cinder_client.volumes.get(volume_id)
server_attachments = list(filter(lambda x: x['server_id'] == self.id,
volume_item.attachments))
if len(server_attachments) > 0:
return True
else:
return False
def attach_volume(self, volume_id, timeout=MEDIUM_TIMEOUT):
self.nova_client.volumes.create_server_volume(self.id, volume_id)
utils.wait_until_true(partial(self._volume_attached, volume_id),
timeout=timeout, sleep=SHORT_SLEEP)
def _volume_detached(self, volume_id):
volume_item = self.cinder_client.volumes.get(volume_id)
server_attachments = list(filter(lambda x: x['server_id'] == self.id,
volume_item.attachments))
if len(server_attachments) > 0:
return False
else:
return True
def detach_volume(self, volume_id, timeout=MEDIUM_TIMEOUT):
self.nova_client.volumes.delete_server_volume(self.id, volume_id)
utils.wait_until_true(partial(self._volume_detached, volume_id),
timeout=timeout, sleep=SHORT_SLEEP)
def close(self, timeout=MEDIUM_TIMEOUT):
try:
self.nova_client.servers.delete(self.id)
except Exception:
return
utils.wait_until_none(self._server_status, timeout=timeout,
sleep=MEDIUM_SLEEP)
class Volume(object):
_name_id = 0
def __init__(self):
super(Volume, self).__init__()
self.id = None
self._name = None
self.cinder_client = base._get_cinder_client()
self.glance_client = base._get_glance_client()
def _volume_status(self, status=None):
try:
volume = self.cinder_client.volumes.get(self.id)
except Exception:
return False
if status is None or status == volume.status:
return True
else:
return False
def to_dict(self):
return {
"id": self.id,
"type": constants.VOLUME_RESOURCE_TYPE,
"name": self._name,
"extra_info": {'availability_zone': 'az1'},
}
def create(self, size, name=None, create_from_image=False,
timeout=LONG_TIMEOUT):
if name is None:
name = "KarborFullstack-Volume-{id}".format(
id=self.__class__._name_id
)
self.__class__._name_id += 1
self._name = name
image = None
if create_from_image:
images = self.glance_client.images.list()
for image_iter in images:
if image_iter['disk_format'] not in ('aki', 'ari') and (
image_iter['name'].startswith('cirros')):
image = image_iter['id']
break
assert image
volume = self.cinder_client.volumes.create(size, name=name,
imageRef=image)
self.id = volume.id
utils.wait_until_true(partial(self._volume_status, 'available'),
timeout=timeout, sleep=MEDIUM_SLEEP)
return self.id
def close(self, timeout=LONG_TIMEOUT):
try:
self.cinder_client.volumes.delete(self.id)
except Exception:
return
utils.wait_until_none(self._volume_status, timeout=timeout,
sleep=MEDIUM_SLEEP)
class Share(object):
_name_id = 0
def __init__(self):
super(Share, self).__init__()
self.id = None
self._name = None
self.manila_client = base._get_manila_client()
self.neutron_client = base._get_neutron_client()
def _share_status(self, status=None):
try:
share = self.manila_client.shares.get(self.id)
except Exception:
return False
if status is None or status == share.status:
return True
else:
return False
def to_dict(self):
return {
"id": self.id,
"type": constants.SHARE_RESOURCE_TYPE,
"name": self._name,
}
def create(self, share_proto, size, name=None, timeout=LONG_TIMEOUT):
if name is None:
name = "KarborFullstack-Share-{id}".format(id=self._name_id)
self._name_id += 1
self._name = name
share = self.manila_client.shares.create(share_proto, size, name=name)
self.id = share.id
utils.wait_until_true(partial(self._share_status, 'available'),
timeout=timeout, sleep=MEDIUM_SLEEP)
return self.id
def close(self, timeout=MEDIUM_TIMEOUT):
try:
self.manila_client.shares.delete(self.id)
except Exception:
return
utils.wait_until_none(self._share_status, timeout=timeout,
sleep=MEDIUM_SLEEP)
class Network(object):
def __init__(self):
super(Network, self).__init__()
self.id = None
self.project_id = None
self._name = "private-net-%s" % uuidutils.generate_uuid()
self.neutron_client = base._get_neutron_client()
def _network_status(self, status=None):
try:
networks = self.neutron_client.list_networks(name=self._name)
assert len(networks['networks']) > 0
network = networks['networks'][0]
except Exception:
return False
if status is None or status == network['status']:
return True
else:
return False
def to_dict(self):
return {
"id": self.id,
"type": constants.NETWORK_RESOURCE_TYPE,
"name": self._name,
}
def create(self, timeout=MEDIUM_TIMEOUT):
network = {'name': self._name, 'admin_state_up': True}
self.neutron_client.create_network({'network': network})
networks = self.neutron_client.list_networks(name=self._name)
assert len(networks['networks']) > 0
network_id = networks['networks'][0]['id']
self.id = network_id
self.project_id = networks['networks'][0]['tenant_id']
utils.wait_until_true(partial(self._network_status, 'ACTIVE'),
timeout=timeout, sleep=MEDIUM_SLEEP)
return self.id
def close(self, timeout=LONG_TIMEOUT):
try:
self.neutron_client.delete_network(self.id)
except Exception:
return
utils.wait_until_none(self._network_status, timeout=timeout,
sleep=MEDIUM_SLEEP)