From febd1e01b53a703f1a7c45620c537d6b30ba5eaf Mon Sep 17 00:00:00 2001 From: David Lenwell Date: Thu, 19 Sep 2013 21:52:31 -0700 Subject: [PATCH] lots of new stuff .. start of tempest config generator --- refstack/cli/refstack | 118 ++++++++++++++++++++++ refstack/common/__init__.py | 15 +++ refstack/common/client.py | 0 refstack/common/cloud.py | 44 +++++++++ refstack/common/tempest-config.py | 157 ++++++++++++++++++++++++++++++ refstack/common/test.py | 82 ++++++++++++++++ refstack/common/user.py | 33 +++++++ refstack/common/vendor.py | 31 ++++++ 8 files changed, 480 insertions(+) create mode 100755 refstack/common/__init__.py create mode 100755 refstack/common/client.py create mode 100755 refstack/common/cloud.py create mode 100755 refstack/common/tempest-config.py create mode 100755 refstack/common/test.py create mode 100755 refstack/common/user.py create mode 100755 refstack/common/vendor.py diff --git a/refstack/cli/refstack b/refstack/cli/refstack index 5b6a451b..370ec969 100755 --- a/refstack/cli/refstack +++ b/refstack/cli/refstack @@ -14,3 +14,121 @@ # 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 os.path +import sys +import subprocess +import argparse +from textwrap import dedent +from refstack.common import test + +basedir = os.path.dirname(__file__) + +def call(*args, **kwargs): + """subprocess.call with error checking.""" + assert not subprocess.call(*args, **kwargs) + +class actions(argparse.Action): + """ david please comment this """ + test_id = None + params = {} + + def __call__(self, parser, params, values, option_string=None, **kwargs): + """Triggered by -c command line argument """ + self.params = params + setattr(self.params, self.dest, values) + + self._print(self.params, verbose=True) + + # action function mapping + actions = { 'run' : self.run, + 'status' : self.status, + 'cancel' : self.cancel, + 'result' : self.result, + 'export' : self.export, + 'list' : self.list } + + if len(self.params.command) > 1: + print "Please only use one command at a time!\n\n" + parser.print_help() + sys.exit(1) + + for command in self.params.command: + if command in actions: + actions[command]() + + def _print(self, output, verbose=False): + """ print wrapper so -v and -s can be respected """ + if not self.params.silent: + if verbose is False: + print(output) + elif verbose is True and self.params.verbose > 0: + print(output) + + def run(self): + """ run test command""" + self._print('run command called',True) + + def status(self): + """ get the status of a running test""" + self._print('status command called',True) + + def cancel(self): + """ cancels a running test""" + self._print('cancel command called',True) + + def result(self): + """ outputs the results of a test""" + self._print('result command called',True) + + def export(self): + """ export something forgot why I adddedd this""" + self._print('export command called',True) + + def list(self): + """ returns a list of cached test results""" + self._print('list command called',True) + + +def main(): + """ command line hook """ + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=dedent("""\ + This is a CLI utility for refstack + + """), + epilog=dedent("""\ + Usage: + + Refstack CLI: + \n\n\n """)) + + + # output options + parser.add_argument('--verbose', '-v', action='count') + parser.add_argument('--silent', '-s', action='store_true') + + + # all paramaters can be overridden + parser.add_argument('--test-id', nargs='?', type=int, + default=None, + help="""id of the test you want to interact with.. if you are starting + a new test you can leave this blank and it will + return a new test_id""") + + parser.add_argument('command', nargs='+', action=actions, + help="Command to execute. ", + choices=['run','status','cancel','result','export','list'] ) + + args = parser.parse_args() + # validate input + #option_given = not (args.c == None) + + #if not option_given: + # parser.print_help() + # sys.exit(1) + + + +if __name__ == '__main__': + main() diff --git a/refstack/common/__init__.py b/refstack/common/__init__.py new file mode 100755 index 00000000..0fe048dc --- /dev/null +++ b/refstack/common/__init__.py @@ -0,0 +1,15 @@ +# +# Copyright (c) 2013 Piston Cloud Computing, Inc. +# 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. \ No newline at end of file diff --git a/refstack/common/client.py b/refstack/common/client.py new file mode 100755 index 00000000..e69de29b diff --git a/refstack/common/cloud.py b/refstack/common/cloud.py new file mode 100755 index 00000000..4253f01d --- /dev/null +++ b/refstack/common/cloud.py @@ -0,0 +1,44 @@ +# +# Copyright (c) 2013 Piston Cloud Computing, Inc. +# 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. +from refstack.common import * + + +class Cloud: + """ Vendor functions""" + id = None + + def __init__(self, id): + """ init method loads specified id or fails""" + self.id = id + + @def end_point(): + doc = "The end_point property." + def fget(self): + return self._end_point + def fset(self, value): + self._end_point = value + def fdel(self): + del self._end_point + return locals() + + foo = property(**foo()) + + def tests(self, cloud_ + id = None): + """ returns object populated with test objects that belong to + this user and filter + ed by cloud_id if specified """ + diff --git a/refstack/common/tempest-config.py b/refstack/common/tempest-config.py new file mode 100755 index 00000000..bfcca2d7 --- /dev/null +++ b/refstack/common/tempest-config.py @@ -0,0 +1,157 @@ + +class TempestConf(dict): + """temptest config options. gets converted to a tempest config file""" + def __init__(self): + """ sets up the default configs""" + self['DEFAULT'] = { + 'debug':True, + 'use_stderr':False, + 'log_file':'', + 'lock_path':'', + 'default_log_levels':"""tempest.stress=INFO,amqplib=WARN, + sqlalchemy=WARN,boto=WARN,suds=INFO,keystone=INFO, + eventlet.wsgi.server=WARN"""} + + self['identity'] = { + 'catalog_type': 'identity', + 'disable_ssl_certificate_validation': False, + 'uri': '', + 'uri_v3': '', + 'region': 'RegionOne', + 'username': '', + 'password': '', + 'tenant_name': '', + 'alt_username': '', + 'alt_password': '', + 'alt_tenant_name': '', + 'admin_username': '', + 'admin_password': '', + 'admin_tenant_name': '', + 'admin_role': ''} + + + self['compute'] = { + 'catalog_type': 'compute', + 'allow_tenant_isolation': True, + 'allow_tenant_reuse': True, + 'image_ref': '', + 'image_ref_alt': '', + 'flavor_ref': '', + 'flavor_ref_alt': '', + 'image_ssh_user': '', + 'image_ssh_password': '', + 'image_alt_ssh_user': '', + 'image_alt_ssh_password': '', + 'build_interval': '', + 'build_timeout': '', + 'run_ssh': False, + 'ssh_user': '', + 'fixed_network_name': '', + 'network_for_ssh': '', + 'ip_version_for_ssh': '', + 'ping_timeout': '', + 'ssh_timeout': '', + 'ready_wait': 0, + 'ssh_channel_timeout': 60, + 'use_floatingip_for_ssh': True, + 'create_image_enabled': True, + 'resize_available': True, + 'change_password_available': False, + 'live_migration_available': False, + 'use_block_migration_for_live_migration': False, + 'block_migrate_supports_cinder_iscsi': False, + 'disk_config_enabled': True, + 'flavor_extra_enabled': True, + 'volume_device_name': ''} + + self['compute-admin'] = { + 'username': '', + 'password': '', + 'tenant_name': ''} + + self['image'] = { + 'catalog_type': 'image', + 'api_version': 1, + 'http_image': ''} + + self['network'] = { + 'catalog_type': 'network', + 'api_version': '2.0', + 'tenant_network_cidr': '10.100.0.0/16', + 'tenant_network_mask_bits': 28, + 'tenant_networks_reachable': False, + 'public_network_id': '', + 'public_router_id': ''} + + self['volume'] = { + 'catalog_type': 'volume', + 'disk_format': 'raw', + 'build_interval': 1, + 'build_timeout': 400, + 'multi_backend_enabled': False, + 'backend1_name': 'BACKEND_1', + 'backend2_name': 'BACKEND_2', + 'storage_protocol': 'iSCSI', + 'vendor_name': 'Open Source'} + + self['object-storage'] = { + 'catalog_type': 'object-store', + 'container_sync_timeout': 120, + 'container_sync_interval': 5, + 'accounts_quotas_available': True, + 'operator_role': 'Member'} + + self['boto'] = { + 'ssh_user': 'cirros', + 'ec2_url': 'http://172.16.200.130:8773/services/Cloud', + 's3_url': 'http://172.16.200.130:3333', + 'aws_access': '', + 'aws_secret': '', + 's3_materials_path': '', + 'ari_manifest': 'cirros-0.3.1-x86_64-initrd.manifest.xml', + 'ami_manifest': 'cirros-0.3.1-x86_64-blank.img.manifest.xml', + 'aki_manifest': 'cirros-0.3.1-x86_64-vmlinuz.manifest.xml', + 'instance_type': 'm1.nano', + 'http_socket_timeout': 30, + 'num_retries': 1, + 'build_timeout': 400, + 'build_interval': 1} + + self['orchestration'] = { + 'catalog_type': 'orchestration', + 'build_interval': 1, + 'build_timeout': 300, + 'instance_type': 'm1.micro', + '#image_ref': 'ubuntu-vm-heat-cfntools', + '#keypair_name': 'heat_key'} + + self['dashboard'] = { + 'dashboard_url = http://172.16.200.130/', + 'login_url = http://172.16.200.130/auth/login/', + + self['scenario'] = { + 'img_dir': '', + 'ami_img_file': 'cirros-0.3.1-x86_64-blank.img', + 'ari_img_file': 'cirros-0.3.1-x86_64-initrd', + 'aki_img_file': 'cirros-0.3.1-x86_64-vmlinuz', + 'ssh_user': 'cirros', + 'large_ops_number': '0', + + self['cli'] = { + 'enabled': True, + 'cli_dir': '/usr/local/bin', + 'timeout': 15 } + + self['service_available'] = { + 'cinder': True, + 'neutron': False, + 'glance': True, + 'swift': False, + 'nova': True, + 'heat': False, + 'horizon': True} + + self['stress'] = { + 'max_instances': 32, + 'log_check_interval': 60, + 'default_thread_number_per_action': 4 } diff --git a/refstack/common/test.py b/refstack/common/test.py new file mode 100755 index 00000000..dbbb135f --- /dev/null +++ b/refstack/common/test.py @@ -0,0 +1,82 @@ +# +# Copyright (c) 2013 Piston Cloud Computing, Inc. +# 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. +from refstack.common import * + +class Tests(dict): + """ behaves like a dictionary of test objects """ + user_id = None + vendor_id = None + + def __init__(self,user_id=None,vendor_id=None): + """ accepts either a vendor or a user id then sets its self up + an object full of test objects filtered by the passed in id""" + + +class Test(object): + """ Test functions""" + id = None + sha = None + cloud_id = None + _status = None + + def __init__(self,cloud_id,test_id=None,sha=None): + """ init method loads specified id or fails""" + if not id: + #create a new test id + self.id = 10 + else: + # set test id + self.id = id + + self.cloud_id = cloud_id + self.sha = sha + + return self.id + + + def run_remote(self): + """triggers remote run""" + # install tempest in virt env + # start tests against cloud_id using sha of tempest + # no sha indicates trunk + + + def run_local(): + """ triggers local run""" + # spawns + return "run_local called" + + + def cancel(self): + """ cancels a running test""" + + @def status(): + doc = "The status property." + def fget(self): + return self._status + def fset(self, value): + self._status = value + def fdel(self): + del self._status + return locals() + + @def config(): + doc = "The config property." + def fget(self): + return self.config + + return locals() + diff --git a/refstack/common/user.py b/refstack/common/user.py new file mode 100755 index 00000000..d8776cdb --- /dev/null +++ b/refstack/common/user.py @@ -0,0 +1,33 @@ +# +# Copyright (c) 2013 Piston Cloud Computing, Inc. +# 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. +from refstack.common import * + + +class User: + """ Vendor functions""" + id = None + + def __init__(self, id): + """ init method loads specified id or fails""" + self.id = id + + def clouds(self): + """ returns clouds object filtered to specified user""" + + def tests(self, cloud_id = None): + """ returns object populated with test objects that belong to + this user and filtered by cloud_id if specified """ + \ No newline at end of file diff --git a/refstack/common/vendor.py b/refstack/common/vendor.py new file mode 100755 index 00000000..d97a78c4 --- /dev/null +++ b/refstack/common/vendor.py @@ -0,0 +1,31 @@ +# +# Copyright (c) 2013 Piston Cloud Computing, Inc. +# 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. +from refstack.common import * + + +class Vendor: + """ Vendor functions""" + def __init__(self, id): + """ init method loads specified id or fails""" + + def users(self): + """ returns users object filtered to the specified vendor""" + + def clouds(self): + """ returns clouds object filtered to specified vendor""" + + def tests(self): + """ returns tests object filtered to specified vendor"""