house keeping .. these are not used anymore
Change-Id: I7460cb1fa4a666b18610eeac51a4c639952c97ed
This commit is contained in:
parent
1614a1e63b
commit
8916e8ebab
|
@ -1,368 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# 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.
|
||||
import sys
|
||||
import argparse
|
||||
from textwrap import dedent
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from refstack.models import *
|
||||
from refstack.common.tempest_config import TempestConfig
|
||||
from refstack.common.tester import Tester
|
||||
|
||||
|
||||
def add(args):
|
||||
"""adds a cloud
|
||||
|
||||
refstack add --endpoint='http://127.0.0.1:5000/v3/' --test-user='demo' \
|
||||
--test-key='pass' --admin-endpoint='http://127.0.0.1:5000/v3/' \
|
||||
--admin-user='admin' --admin-key='pass'
|
||||
|
||||
outputs confirmation along with the id of the cloud that was just added.
|
||||
endpoint is a unique key so you only get to add one record per end point"""
|
||||
try:
|
||||
cloud = Cloud()
|
||||
|
||||
cloud.endpoint = args.endpoint
|
||||
cloud.test_user = args.test_user
|
||||
cloud.test_key = args.test_key
|
||||
cloud.admin_endpoint = args.admin_endpoint
|
||||
cloud.admin_user = args.admin_user
|
||||
cloud.admin_key = args.admin_key
|
||||
|
||||
db.add(cloud)
|
||||
db.commit()
|
||||
|
||||
print 'New cloud added with id: %s ' % (cloud.id)
|
||||
clouds(args)
|
||||
|
||||
except IntegrityError:
|
||||
print 'A Cloud with %s as its endpoint has already been added. ' % args.endpoint
|
||||
|
||||
|
||||
def config(args):
|
||||
"""returns a raw output of the config for specified cloud"""
|
||||
cloud = db.query(Cloud).get(args.cloud_id)
|
||||
|
||||
if cloud is None:
|
||||
print 'Invalid cloud-id, Please use one from this list.'
|
||||
clouds(args)
|
||||
sys.exit(1)
|
||||
|
||||
t = TempestConfig(args.cloud_id)
|
||||
|
||||
print t.build_config_from_keystone()
|
||||
|
||||
|
||||
def remove(args):
|
||||
"""removes a cloud
|
||||
refstack remove {cloud_id}
|
||||
|
||||
confirms that cloud-id 123 has been removed from the database as well as
|
||||
all tests assosiateed with it."""
|
||||
cloud = db.query(Cloud).get(args.cloud_id)
|
||||
|
||||
if cloud is None:
|
||||
print 'Invalid cloud-id, Please use one from this list.'
|
||||
clouds(args)
|
||||
|
||||
else:
|
||||
db.delete(cloud)
|
||||
db.commit()
|
||||
print 'cloud %s has been deleted.' % args.cloud_id
|
||||
|
||||
|
||||
def clouds(args):
|
||||
"""returns a list of your clouds"""
|
||||
print 'Your clouds:\n'
|
||||
print 'id | endpoint | test-user | admin-user '
|
||||
print '---------------------------------------'
|
||||
for row in db.query(Cloud).all():
|
||||
print "%s | %s | %s | %s " % (row.id, row.endpoint, row.test_user, row.admin_user)
|
||||
print ''
|
||||
|
||||
|
||||
def start(args):
|
||||
"""start test command
|
||||
|
||||
refstack start {cloud_id} --sha {sha}
|
||||
|
||||
triggers local run of tempest with specified cloud_id returns a
|
||||
test_id so that the user can check status or cancel the test"""
|
||||
#load the cloud from the specified id
|
||||
cloud = db.query(Cloud).get(args.cloud_id)
|
||||
|
||||
if cloud is None:
|
||||
print 'Invalid cloud-id, Please use one from this list.'
|
||||
clouds(args)
|
||||
sys.exit(1)
|
||||
|
||||
# run the damn test
|
||||
t = Tester(args.cloud_id)
|
||||
results = t.run_local()
|
||||
|
||||
# store the results
|
||||
test = db.query(Test).filter_by(cloud_id=args.cloud_id).first()
|
||||
|
||||
# creat a new test
|
||||
print 'Adding a new test.'
|
||||
test = Test(args.cloud_id)
|
||||
test.config = t.config
|
||||
db.add(test)
|
||||
db.commit()
|
||||
print 'test added with id: %s' % test.id
|
||||
|
||||
|
||||
'''
|
||||
# do cleanup and then mark the last status to 'canceled'
|
||||
test_result = TestResults()
|
||||
test_result.test_id = test.id
|
||||
test_result.subunit = result
|
||||
|
||||
|
||||
db.add(test_result)
|
||||
db.commit()
|
||||
'''
|
||||
|
||||
|
||||
def status(args):
|
||||
"""get the status of a running test
|
||||
|
||||
refstack status {test-id}
|
||||
"""
|
||||
test = db.query(Test).get(args.test_id)
|
||||
|
||||
if test is None:
|
||||
# This isn't a valid test id
|
||||
print '%s is not a valid test-id.' % args.test_id
|
||||
sys.exit(1)
|
||||
else:
|
||||
|
||||
test_status = db.query(TestStatus).filter_by(test_id=test.id).order_by(TestStatus.id.desc()).all()
|
||||
|
||||
print 'Status Log for test-id %s (top is most recent)' % args.test_id
|
||||
print 'id | timestamp | message'
|
||||
for row in test_status:
|
||||
print '%s | %s | %s ' % (row.id, row.timestamp, row.message)
|
||||
|
||||
|
||||
def cancel(args):
|
||||
"""cancels a running test
|
||||
|
||||
refstack cancel --test-id {test_id}
|
||||
|
||||
stops the running test if it is running and displays output to user"""
|
||||
print 'cancel triggered'
|
||||
test = db.query(Test).get(args.test_id)
|
||||
|
||||
if test is None:
|
||||
# This isn't a valid test id
|
||||
print '%s is not a valid test-id.' % args.test_id
|
||||
sys.exit(1)
|
||||
|
||||
else:
|
||||
test_status = db.query(TestStatus).filter_by(test_id=test.id).order_by(TestStatus.id.desc()).first()
|
||||
|
||||
if test_status.message in ('running') :
|
||||
# do cleanup and then mark the last status to 'canceled'
|
||||
test_status = TestStatus(test.id, 'canceled')
|
||||
db.add(test_status)
|
||||
db.commit()
|
||||
|
||||
else:
|
||||
print 'test %s does not apear to be running' % args.test_id
|
||||
|
||||
status(args)
|
||||
|
||||
|
||||
def result(args):
|
||||
"""outputs the results of a test
|
||||
|
||||
refstack results --test_id --format {screen|subunit}
|
||||
|
||||
if the test isn't finished it will say in progress otherwise will return
|
||||
subunit|screen output"""
|
||||
print 'result triggered'
|
||||
|
||||
|
||||
def tests(args):
|
||||
"""returns either a list of tests for the specified cloud-id"""
|
||||
#load the cloud from the specified id
|
||||
cloud = db.query(Cloud).get(args.cloud_id)
|
||||
|
||||
if cloud is None:
|
||||
print 'Invalid cloud-id, Please use one from this list.'
|
||||
|
||||
clouds(args)
|
||||
sys.exit(1)
|
||||
|
||||
print 'tests for cloud with id: %s \n' % args.cloud_id
|
||||
|
||||
print 'id | status '
|
||||
print '---------------------------------------'
|
||||
for row in db.query(Test).filter_by(cloud_id=args.cloud_id).all():
|
||||
_status = db.query(TestStatus).filter_by(test_id=row.id).order_by(TestStatus.id.desc()).first()
|
||||
print "%s | %s " % (row.id, _status.message)
|
||||
print ''
|
||||
|
||||
|
||||
def subcommands(subparsers):
|
||||
"""argparse options for the clouds command """
|
||||
clouds_parser = subparsers.add_parser('clouds', help='list clouds')
|
||||
|
||||
"""argparse subparsers with """
|
||||
add_cloud_parser = subparsers.add_parser('add', help='Add a new Cloud')
|
||||
|
||||
add_cloud_parser.add_argument('--endpoint',
|
||||
required=True,
|
||||
action='store',
|
||||
dest='endpoint',
|
||||
help='Non-admin keystone endpoint')
|
||||
|
||||
add_cloud_parser.add_argument('--test-user',
|
||||
required=True,
|
||||
action='store',
|
||||
dest='test_user',
|
||||
help='Non-admin keystone user')
|
||||
|
||||
add_cloud_parser.add_argument('--test-key',
|
||||
required=True,
|
||||
action='store',
|
||||
dest='test_key',
|
||||
help='Non-admin keystone password or key')
|
||||
|
||||
add_cloud_parser.add_argument('--admin-endpoint',
|
||||
required=True,
|
||||
action='store',
|
||||
dest='admin_endpoint',
|
||||
help='Admin keystone endpoint')
|
||||
|
||||
add_cloud_parser.add_argument('--admin-user',
|
||||
required=True,
|
||||
action='store',
|
||||
dest='admin_user',
|
||||
help='Admin keystone user')
|
||||
|
||||
add_cloud_parser.add_argument('--admin-key',
|
||||
required=True,
|
||||
action='store',
|
||||
dest='admin_key',
|
||||
help='Admin keystone key or password')
|
||||
|
||||
"""argparse options for the remove command """
|
||||
remove_parser = subparsers.add_parser('remove', help='remove a Cloud')
|
||||
|
||||
remove_parser.add_argument(action='store',
|
||||
dest='cloud_id',
|
||||
help='The id of the cloud you want to remove')
|
||||
|
||||
"""argparse options for the start command """
|
||||
start_parser = subparsers.add_parser('start', help='start tests on cloud')
|
||||
|
||||
start_parser.add_argument(action='store',
|
||||
dest='cloud_id',
|
||||
help='The id of the cloud you want to test')
|
||||
|
||||
start_parser.add_argument('--sha',
|
||||
required=False,
|
||||
action='store',
|
||||
dest='sha',
|
||||
help='optionally specify a sha for the tempest version to use')
|
||||
|
||||
"""argparse options for the status command """
|
||||
status_parser = subparsers.add_parser('status', help='returns status of test')
|
||||
status_parser.add_argument(action='store',
|
||||
dest='test_id',
|
||||
help='The id of the test you want status of.')
|
||||
|
||||
status_parser.add_argument('--list',
|
||||
'-l',
|
||||
action='store_true',
|
||||
help='list status history')
|
||||
|
||||
|
||||
"""argparse options for the cancel command """
|
||||
cancel_parser = subparsers.add_parser('cancel', help='cancel a test')
|
||||
|
||||
cancel_parser.add_argument(action='store',
|
||||
dest='test_id',
|
||||
help='The id of the test you want to cancel')
|
||||
|
||||
|
||||
|
||||
"""argparse options for the result command """
|
||||
result_parser = subparsers.add_parser('result', help='provides results')
|
||||
result_parser.add_argument(action='store',
|
||||
dest='test_id',
|
||||
help='The id of the test you want to cancel')
|
||||
|
||||
"""argparse options for the tests command """
|
||||
tests_parser = subparsers.add_parser('tests', help='list tests')
|
||||
|
||||
tests_parser.add_argument(action='store',
|
||||
dest='cloud_id',
|
||||
help='The id of the cloud you want to test')
|
||||
|
||||
"""argparse options for the tests command """
|
||||
tests_parser = subparsers.add_parser('config', help='output tempest config for cloud')
|
||||
|
||||
tests_parser.add_argument(action='store',
|
||||
dest='cloud_id',
|
||||
help='The id of the cloud you want a config for')
|
||||
|
||||
|
||||
def main():
|
||||
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')
|
||||
|
||||
subparsers = parser.add_subparsers(help='Sub commands', dest='command')
|
||||
|
||||
subcommands(subparsers)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# action function mapping
|
||||
actions = { 'add': add,
|
||||
'remove': remove,
|
||||
'start': start,
|
||||
'cancel': cancel,
|
||||
'status': status,
|
||||
'result': result,
|
||||
'tests': tests,
|
||||
'config': config,
|
||||
'clouds': clouds}
|
||||
|
||||
if args.command in actions:
|
||||
actions[args.command](args)
|
||||
else:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,249 +0,0 @@
|
|||
#
|
||||
# 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 keystoneclient.v2_0 import client
|
||||
from refstack.models import db, Cloud
|
||||
|
||||
|
||||
class TempestConfig(object):
|
||||
"""temptest config options. gets converted to a tempest config file"""
|
||||
config = {}
|
||||
|
||||
def output(self):
|
||||
"""outputs config in propper format"""
|
||||
output = ''
|
||||
for k, v in self.config.items():
|
||||
output += '[%s] \n' % k
|
||||
for sk, sv in v.items():
|
||||
output += '%s = %s \n' % (sk, sv)
|
||||
output += '\n'
|
||||
return output
|
||||
|
||||
def build_config_from_keystone(self):
|
||||
"""uses the keystoneclient libs to query a clouds endpoint and
|
||||
retrive a service catelog. that it then uses to populate the
|
||||
values for our specific tempest config"""
|
||||
# load an existing cloud
|
||||
self._cloud = db.query(Cloud).filter_by(id=self.cloud_id).first()
|
||||
|
||||
if not self._cloud:
|
||||
# cloud not found.. invalid id
|
||||
# maybe I should do someting about this ..
|
||||
return None
|
||||
|
||||
# This stuff we know before hitting up keystone
|
||||
self.config['identity']['uri'] = self._cloud.admin_endpoint
|
||||
self.config['identity']['admin_username'] = self._cloud.admin_user
|
||||
self.config['identity']['admin_password'] = self._cloud.admin_key
|
||||
self.config['identity']['username'] = self._cloud.test_user
|
||||
self.config['identity']['password'] = self._cloud.test_key
|
||||
self.config['identity']['tenant_name'] = self._cloud.admin_user
|
||||
|
||||
# keystone client object
|
||||
self._keystone = client.Client(username=self._cloud.admin_user,
|
||||
password=self._cloud.admin_key,
|
||||
tenant_name=self._cloud.admin_user,
|
||||
auth_url=self._cloud.admin_endpoint)
|
||||
|
||||
if self._keystone is None:
|
||||
"""TODO.. this should cause a fail"""
|
||||
print "keystone didnt connect for some reason"
|
||||
return None
|
||||
|
||||
self._keystone.management_url = self._cloud.admin_endpoint
|
||||
|
||||
# make sure this keystone server can list services
|
||||
# using has_service_catalog
|
||||
if not self._keystone.has_service_catalog():
|
||||
# we have no service catelog all tests are fail
|
||||
# because we can't build a config
|
||||
print "fail "
|
||||
#else:
|
||||
# print "has service catalog"
|
||||
|
||||
self.service_catalog = {}
|
||||
|
||||
# make a local dict of the service catalog
|
||||
for item in self._keystone.service_catalog.catalog['serviceCatalog']:
|
||||
self.service_catalog[item['name']] = \
|
||||
item['endpoints'][0]['publicURL']
|
||||
|
||||
# setup output service_available
|
||||
for service in self.config['service_available'].keys():
|
||||
if service in self.service_catalog:
|
||||
self.config['service_available'][service] = True
|
||||
|
||||
# boto settings
|
||||
self.config['boto']['ec2_url'] = self.service_catalog['ec2']
|
||||
self.config['boto']['s3_url'] = self.service_catalog['s3']
|
||||
|
||||
# return the actual config
|
||||
return self.output()
|
||||
|
||||
def __init__(self, cloud_id):
|
||||
""" sets up the default configs"""
|
||||
self.cloud_id = cloud_id
|
||||
|
||||
self.config['DEFAULT'] = {
|
||||
'debug': True,
|
||||
'use_stderr': False,
|
||||
'log_file': 'output',
|
||||
'lock_path': '/tmp/' + str(cloud_id) + '/',
|
||||
'default_log_levels': """tempest.stress=INFO,amqplib=WARN,
|
||||
sqlalchemy=WARN,boto=WARN,suds=INFO,keystone=INFO,
|
||||
eventlet.wsgi.server=WARN"""}
|
||||
|
||||
self.config['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.config['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': '1',
|
||||
'build_timeout': '400',
|
||||
'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.config['compute-admin'] = {
|
||||
'username': '',
|
||||
'password': '',
|
||||
'tenant_name': ''}
|
||||
|
||||
self.config['image'] = {
|
||||
'catalog_type': 'image',
|
||||
'api_version': 1,
|
||||
'http_image': ''}
|
||||
|
||||
self.config['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.config['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.config['object-storage'] = {
|
||||
'catalog_type': 'object-store',
|
||||
'container_sync_timeout': 120,
|
||||
'container_sync_interval': 5,
|
||||
'accounts_quotas_available': True,
|
||||
'operator_role': 'Member'}
|
||||
|
||||
self.config['boto'] = {
|
||||
'ssh_user': 'cirros',
|
||||
'ec2_url': '',
|
||||
's3_url': '',
|
||||
'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.config['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.config['dashboard'] = {
|
||||
'dashboard_url': '',
|
||||
'login_url': ''}
|
||||
|
||||
self.config['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.config['cli'] = {
|
||||
'enabled': True,
|
||||
'cli_dir': '/usr/local/bin',
|
||||
'timeout': 15}
|
||||
|
||||
self.config['service_available'] = {
|
||||
'cinder': False,
|
||||
'neutron': False,
|
||||
'glance': False,
|
||||
'swift': False,
|
||||
'nova': False,
|
||||
'heat': False,
|
||||
'horizon': False}
|
||||
|
||||
self.config['stress'] = {
|
||||
'max_instances': 32,
|
||||
'log_check_interval': 60,
|
||||
'default_thread_number_per_action': 4}
|
|
@ -1,218 +0,0 @@
|
|||
#
|
||||
# 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.
|
||||
import os
|
||||
from subprocess import call
|
||||
from refstack.common.tempest_config import TempestConfig
|
||||
import testrepository.repository.file
|
||||
from testrepository import ui
|
||||
from testrepository.commands import run
|
||||
from testrepository.commands import init
|
||||
|
||||
import gear
|
||||
|
||||
|
||||
class TesterWorker(object):
|
||||
"""gearman worker code"""
|
||||
def __init__(self, app):
|
||||
self.worker = gear.Worker('run_remote_test')
|
||||
|
||||
self.worker.addServer(app.gearman_server)
|
||||
self.worker.registerFunction('run_remote_test')
|
||||
|
||||
def run_remote_test(self):
|
||||
pass
|
||||
|
||||
def run_job(self):
|
||||
while True:
|
||||
job = self.worker.getJob()
|
||||
job.sendWorkComplete(job.arguments.reverse())
|
||||
|
||||
|
||||
class TestRepositoryUI(ui.AbstractUI):
|
||||
"""nothing"""
|
||||
def __init__(self, here):
|
||||
"""Create a UI to run a TestRepository command
|
||||
|
||||
:param here: What should the 'here' be for the UI.
|
||||
"""
|
||||
self.here = here
|
||||
|
||||
|
||||
class TestRepositorySource(object):
|
||||
"""Get test results from a testrepository.
|
||||
|
||||
Reloading asks testr to re-run (and implicitly record) a new
|
||||
test result.
|
||||
|
||||
:ivar testr_directory: path to directory containing .testr repository
|
||||
"""
|
||||
|
||||
def __init__(self, testr_directory):
|
||||
self.testr_directory = os.path.expanduser(testr_directory)
|
||||
self._ui = TestRepositoryUI(self.testr_directory)
|
||||
|
||||
self.init_repo()
|
||||
|
||||
def get_subunit_stream(self):
|
||||
try:
|
||||
return self.testrepository_last_stream()
|
||||
except KeyError:
|
||||
pass # raise NoStreamPresent()
|
||||
|
||||
def init_repo(self):
|
||||
"""inits a new testrepository repo in the supplied path"""
|
||||
#os.chdir(self.testr_directory)
|
||||
try:
|
||||
cmd = init.init(self._ui)
|
||||
cmd.run()
|
||||
except OSError:
|
||||
# if this happens its fine .. just means the repo is already there
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
os.getcwd()
|
||||
os.chdir(self.testr_directory)
|
||||
self._ui.c = self.testr_directory + 'tempest.conf'
|
||||
|
||||
cmd = run.run(self._ui)
|
||||
|
||||
return cmd.execute()
|
||||
|
||||
def testrepository_last_stream(self):
|
||||
factory = testrepository.repository.file.RepositoryFactory()
|
||||
repo = factory.open(self.testr_directory)
|
||||
# this is poor because it just returns a stringio for the whole
|
||||
# thing; we should instead try to read from it as a file so we can
|
||||
# get nonblocking io
|
||||
return repo.get_test_run(repo.latest_id()).get_subunit_stream()
|
||||
|
||||
|
||||
class Tester(object):
|
||||
""" Test functions"""
|
||||
test_id = None
|
||||
sha = None
|
||||
cloud_id = None
|
||||
_status = None
|
||||
|
||||
def __init__(self, cloud_id=None, test_id=None, sha=None):
|
||||
""" init method loads specified id or fails"""
|
||||
if not test_id:
|
||||
#create a new test id
|
||||
self.test_id = 10
|
||||
else:
|
||||
# set test id
|
||||
self.test_id = id
|
||||
|
||||
self.tempest_config = TempestConfig(cloud_id)
|
||||
self.cloud_id = cloud_id
|
||||
self.sha = sha
|
||||
self.test_path = "/tmp/%s/" % cloud_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(self):
|
||||
"""triggers local run"""
|
||||
# make sure we have a folder to put a repo in..
|
||||
if not os.path.exists(self.test_path):
|
||||
os.makedirs(self.test_path)
|
||||
|
||||
# write the tempest config to that folder
|
||||
self.write_config(self.test_path)
|
||||
|
||||
# setup the repo wrapper..
|
||||
# this creates the repo if its not already there
|
||||
tr = TestRepositorySource(self.test_path)
|
||||
|
||||
"""TODO: So this is supposed to use the testr wrapper to trigger a run.
|
||||
however.. I am completly blocked on how to make it work the right way..
|
||||
so I am moving on for now once the congigs are setup and repo initiated
|
||||
it will call a subprocess run the command .. THEN query the repo for
|
||||
the last set of results and store the subunit stream.
|
||||
|
||||
# run tests
|
||||
#tr.run()
|
||||
"""
|
||||
|
||||
print "starting test"
|
||||
call([self.test_path + 'runtests.sh']) # replace this
|
||||
print "finished with tests"
|
||||
|
||||
# get back the results
|
||||
result = tr.testrepository_last_stream()
|
||||
|
||||
# write results to database maybe ..
|
||||
return result.read()
|
||||
#return None
|
||||
|
||||
def write_config(self, path):
|
||||
"""writes config to path specified"""
|
||||
# get the config
|
||||
print "writing configs %s" % path
|
||||
|
||||
self._config = self.tempest_config.build_config_from_keystone()
|
||||
|
||||
runtests_script = """#!/bin/bash
|
||||
cd %s
|
||||
testr run
|
||||
exit $?""" % path
|
||||
|
||||
"""TODO make this cleaner"""
|
||||
testr_output = """[DEFAULT]
|
||||
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
|
||||
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
|
||||
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-500} \
|
||||
${PYTHON:-python} -m subunit.run discover \
|
||||
tempest.api $LISTOPT $IDOPTION
|
||||
test_id_option=--load-list $IDFILE
|
||||
test_list_option=--list
|
||||
group_regex=([^\.]*\.)*"""
|
||||
|
||||
with open(path + "runtests.sh", "w") as runtests_script_file:
|
||||
runtests_script_file.write(runtests_script)
|
||||
|
||||
os.chmod(path + "runtests.sh", 0744)
|
||||
|
||||
with open(path + "tempest.conf", "w") as config_file:
|
||||
config_file.write(self._config)
|
||||
|
||||
with open(path + ".testr.conf", "w") as testr_config_file:
|
||||
testr_config_file.write(testr_output)
|
||||
|
||||
def cancel(self):
|
||||
""" cancels a running test"""
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
"""The status property."""
|
||||
def fget(self):
|
||||
return self._status
|
||||
|
||||
def fset(self, value):
|
||||
self._status = value
|
||||
|
||||
def fdel(self):
|
||||
del self._status
|
||||
|
||||
return locals()
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
"""The config property. outputs a tempest config based on settings"""
|
||||
return self.tempest_config.output()
|
|
@ -1,47 +0,0 @@
|
|||
#
|
||||
# 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.
|
||||
import os
|
||||
|
||||
###############################################################
|
||||
#
|
||||
#
|
||||
# THIS FILE IS NOT USED
|
||||
# (leaveing it around briefly for reference)
|
||||
#
|
||||
#
|
||||
###############################################################
|
||||
|
||||
db_path = '/tmp'
|
||||
|
||||
|
||||
class Default(object):
|
||||
MAILGUN_KEY = '#@#@#@#@'
|
||||
MAILGUN_DOMAIN = 'refstack.org'
|
||||
SECRET_KEY = '#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@'
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get(
|
||||
'DATABASE_URL', 'sqlite:///%s/refstack.db' % (db_path))
|
||||
DEBUG = True
|
||||
SECURITY_PASSWORD_HASH = 'sha512_crypt'
|
||||
SECURITY_PASSWORD_SALT = SECRET_KEY
|
||||
SECURITY_POST_LOGIN_VIEW = 'dashboard'
|
||||
SECURITY_RECOVERABLE = True
|
||||
SECURITY_REGISTERABLE = True
|
||||
SECURITY_EMAIL_SENDER = "refstack.org"
|
||||
MAIL_SERVER = 'smtp.refstack.org'
|
||||
MAIL_PORT = 465
|
||||
MAIL_USE_SSL = True
|
||||
MAIL_USERNAME = 'postmaster@refstack.org'
|
||||
MAIL_PASSWORD = '1234'
|
Loading…
Reference in New Issue