212 lines
9.0 KiB
Python
212 lines
9.0 KiB
Python
# Copyright 2012 OpenStack Foundation
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
|
|
import ConfigParser
|
|
import contextlib
|
|
import types
|
|
import urlparse
|
|
|
|
from tempest import config
|
|
from tempest import exceptions
|
|
|
|
import boto
|
|
import boto.ec2
|
|
import boto.s3.connection
|
|
|
|
CONF = config.CONF
|
|
|
|
|
|
class BotoClientBase(object):
|
|
|
|
ALLOWED_METHODS = set()
|
|
|
|
def __init__(self, username=None, password=None,
|
|
auth_url=None, tenant_name=None,
|
|
*args, **kwargs):
|
|
# FIXME(andreaf) replace credentials and auth_url with auth_provider
|
|
|
|
self.connection_timeout = str(CONF.boto.http_socket_timeout)
|
|
self.num_retries = str(CONF.boto.num_retries)
|
|
self.build_timeout = CONF.boto.build_timeout
|
|
self.ks_cred = {"username": username,
|
|
"password": password,
|
|
"auth_url": auth_url,
|
|
"tenant_name": tenant_name}
|
|
|
|
def _keystone_aws_get(self):
|
|
# FIXME(andreaf) Move EC2 credentials to AuthProvider
|
|
import keystoneclient.v2_0.client
|
|
|
|
keystone = keystoneclient.v2_0.client.Client(**self.ks_cred)
|
|
ec2_cred_list = keystone.ec2.list(keystone.auth_user_id)
|
|
ec2_cred = None
|
|
for cred in ec2_cred_list:
|
|
if cred.tenant_id == keystone.auth_tenant_id:
|
|
ec2_cred = cred
|
|
break
|
|
else:
|
|
ec2_cred = keystone.ec2.create(keystone.auth_user_id,
|
|
keystone.auth_tenant_id)
|
|
if not all((ec2_cred, ec2_cred.access, ec2_cred.secret)):
|
|
raise exceptions.NotFound("Unable to get access and secret keys")
|
|
return ec2_cred
|
|
|
|
def _config_boto_timeout(self, timeout, retries):
|
|
try:
|
|
boto.config.add_section("Boto")
|
|
except ConfigParser.DuplicateSectionError:
|
|
pass
|
|
boto.config.set("Boto", "http_socket_timeout", timeout)
|
|
boto.config.set("Boto", "num_retries", retries)
|
|
|
|
def __getattr__(self, name):
|
|
"""Automatically creates methods for the allowed methods set."""
|
|
if name in self.ALLOWED_METHODS:
|
|
def func(self, *args, **kwargs):
|
|
with contextlib.closing(self.get_connection()) as conn:
|
|
return getattr(conn, name)(*args, **kwargs)
|
|
|
|
func.__name__ = name
|
|
setattr(self, name, types.MethodType(func, self, self.__class__))
|
|
setattr(self.__class__, name,
|
|
types.MethodType(func, None, self.__class__))
|
|
return getattr(self, name)
|
|
else:
|
|
raise AttributeError(name)
|
|
|
|
def get_connection(self):
|
|
self._config_boto_timeout(self.connection_timeout, self.num_retries)
|
|
if not all((self.connection_data["aws_access_key_id"],
|
|
self.connection_data["aws_secret_access_key"])):
|
|
if all(self.ks_cred.itervalues()):
|
|
ec2_cred = self._keystone_aws_get()
|
|
self.connection_data["aws_access_key_id"] = \
|
|
ec2_cred.access
|
|
self.connection_data["aws_secret_access_key"] = \
|
|
ec2_cred.secret
|
|
else:
|
|
raise exceptions.InvalidConfiguration(
|
|
"Unable to get access and secret keys")
|
|
return self.connect_method(**self.connection_data)
|
|
|
|
|
|
class APIClientEC2(BotoClientBase):
|
|
|
|
def connect_method(self, *args, **kwargs):
|
|
return boto.connect_ec2(*args, **kwargs)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(APIClientEC2, self).__init__(*args, **kwargs)
|
|
aws_access = CONF.boto.aws_access
|
|
aws_secret = CONF.boto.aws_secret
|
|
purl = urlparse.urlparse(CONF.boto.ec2_url)
|
|
|
|
region_name = CONF.compute.region
|
|
if not region_name:
|
|
region_name = CONF.identity.region
|
|
region = boto.ec2.regioninfo.RegionInfo(name=region_name,
|
|
endpoint=purl.hostname)
|
|
port = purl.port
|
|
if port is None:
|
|
if purl.scheme is not "https":
|
|
port = 80
|
|
else:
|
|
port = 443
|
|
else:
|
|
port = int(port)
|
|
self.connection_data = {"aws_access_key_id": aws_access,
|
|
"aws_secret_access_key": aws_secret,
|
|
"is_secure": purl.scheme == "https",
|
|
"region": region,
|
|
"host": purl.hostname,
|
|
"port": port,
|
|
"path": purl.path}
|
|
|
|
ALLOWED_METHODS = set(('create_key_pair', 'get_key_pair',
|
|
'delete_key_pair', 'import_key_pair',
|
|
'get_all_key_pairs',
|
|
'get_all_tags',
|
|
'create_image', 'get_image',
|
|
'register_image', 'deregister_image',
|
|
'get_all_images', 'get_image_attribute',
|
|
'modify_image_attribute', 'reset_image_attribute',
|
|
'get_all_kernels',
|
|
'create_volume', 'delete_volume',
|
|
'get_all_volume_status', 'get_all_volumes',
|
|
'get_volume_attribute', 'modify_volume_attribute'
|
|
'bundle_instance', 'cancel_spot_instance_requests',
|
|
'confirm_product_instanc',
|
|
'get_all_instance_status', 'get_all_instances',
|
|
'get_all_reserved_instances',
|
|
'get_all_spot_instance_requests',
|
|
'get_instance_attribute', 'monitor_instance',
|
|
'monitor_instances', 'unmonitor_instance',
|
|
'unmonitor_instances',
|
|
'purchase_reserved_instance_offering',
|
|
'reboot_instances', 'request_spot_instances',
|
|
'reset_instance_attribute', 'run_instances',
|
|
'start_instances', 'stop_instances',
|
|
'terminate_instances',
|
|
'attach_network_interface', 'attach_volume',
|
|
'detach_network_interface', 'detach_volume',
|
|
'get_console_output',
|
|
'delete_network_interface', 'create_subnet',
|
|
'create_network_interface', 'delete_subnet',
|
|
'get_all_network_interfaces',
|
|
'allocate_address', 'associate_address',
|
|
'disassociate_address', 'get_all_addresses',
|
|
'release_address',
|
|
'create_snapshot', 'delete_snapshot',
|
|
'get_all_snapshots', 'get_snapshot_attribute',
|
|
'modify_snapshot_attribute',
|
|
'reset_snapshot_attribute', 'trim_snapshots',
|
|
'get_all_regions', 'get_all_zones',
|
|
'get_all_security_groups', 'create_security_group',
|
|
'delete_security_group', 'authorize_security_group',
|
|
'authorize_security_group_egress',
|
|
'revoke_security_group',
|
|
'revoke_security_group_egress'))
|
|
|
|
|
|
class ObjectClientS3(BotoClientBase):
|
|
|
|
def connect_method(self, *args, **kwargs):
|
|
return boto.connect_s3(*args, **kwargs)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(ObjectClientS3, self).__init__(*args, **kwargs)
|
|
aws_access = CONF.boto.aws_access
|
|
aws_secret = CONF.boto.aws_secret
|
|
purl = urlparse.urlparse(CONF.boto.s3_url)
|
|
port = purl.port
|
|
if port is None:
|
|
if purl.scheme is not "https":
|
|
port = 80
|
|
else:
|
|
port = 443
|
|
else:
|
|
port = int(port)
|
|
self.connection_data = {"aws_access_key_id": aws_access,
|
|
"aws_secret_access_key": aws_secret,
|
|
"is_secure": purl.scheme == "https",
|
|
"host": purl.hostname,
|
|
"port": port,
|
|
"calling_format": boto.s3.connection.
|
|
OrdinaryCallingFormat()}
|
|
|
|
ALLOWED_METHODS = set(('create_bucket', 'delete_bucket', 'generate_url',
|
|
'get_all_buckets', 'get_bucket', 'delete_key',
|
|
'lookup'))
|