summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Callaghan <dcallagh@redhat.com>2012-06-15 17:48:36 +1000
committerDan Callaghan <dcallagh@redhat.com>2012-06-15 18:13:28 +1000
commit8d8477fb5fd6f53f4a5b9191f12f925b7f926d7e (patch)
treeb85416068b3fc04d74d7fc25d9459f7266883890
parentc1dc232e059eee512ed856c907be995bd05f5700 (diff)
/distribution/beaker/fake_systems: initial version of taskbeaker-distribution-beaker-fake_systems-1_0-2
-rw-r--r--IntegrationTests/src/bkr/inttest/beah_dummy.py76
-rw-r--r--Tasks/distribution/beaker/fake_systems/Makefile59
-rw-r--r--Tasks/distribution/beaker/fake_systems/PURPOSE1
-rwxr-xr-xTasks/distribution/beaker/fake_systems/beah_dummy.py108
-rwxr-xr-xTasks/distribution/beaker/fake_systems/dummy_fast5
-rwxr-xr-xTasks/distribution/beaker/fake_systems/dummy_flakey17
-rwxr-xr-xTasks/distribution/beaker/fake_systems/dummy_medium8
-rwxr-xr-xTasks/distribution/beaker/fake_systems/dummy_slow8
-rwxr-xr-xTasks/distribution/beaker/fake_systems/hosts.sh9
-rwxr-xr-xTasks/distribution/beaker/fake_systems/power-csv.sh19
-rwxr-xr-xTasks/distribution/beaker/fake_systems/runtest.sh76
-rwxr-xr-xTasks/distribution/beaker/fake_systems/system-csv.sh13
12 files changed, 323 insertions, 76 deletions
diff --git a/IntegrationTests/src/bkr/inttest/beah_dummy.py b/IntegrationTests/src/bkr/inttest/beah_dummy.py
deleted file mode 100644
index 3c4caf0..0000000
--- a/IntegrationTests/src/bkr/inttest/beah_dummy.py
+++ /dev/null
@@ -1,76 +0,0 @@
-import hashlib
-import base64
-import xmlrpclib
-import time
-import threading
-import logging
-from lxml import etree
-from StringIO import StringIO
-from socket import gethostname
-
-log = logging.getLogger(__name__)
-
-
-class BeahDummy(threading.Thread):
-
- _dummy_string = 'thisisdummydata'
-
- _file_size = 512000 # bytes
- _install_time = 30 #seconds
- _task_duration = 120 # seconds
-
- def __init__(self, machine_name, proxy_addr=None, *args, **kw):
- super(BeahDummy,self).__init__(*args, **kw)
- self.machine_name = machine_name
- if not proxy_addr:
- proxy_addr = gethostname()
- self.rpc2 = xmlrpclib.ServerProxy('http://%s:8000/RPC2' % proxy_addr)
-
- def run(self):
- self.rpc2.install_start(self.machine_name)
- log.info('Seeping for %s seconds' % self._install_time)
- time.sleep(self._install_time) #install time
- recipe = self.rpc2.get_recipe(self.machine_name)
- tree = etree.parse(StringIO(recipe))
- for task in tree.findall('//task'):
- task_id = task.get('id')
- task_name = task.get('name')
- self.run_task(task_id, task_name)
-
- def run_task(self, task_id, task_name):
- """
- Start the task, send some logs, sleep a bit for the runtime, the send pass result
- and stop the task
-
- """
- string_to_send = self._dummy_string * 66 # testing with this chunk size
- chunk_size = len(string_to_send)
- total_size_sent_task_log = 0
- offset_task_log = 0
- self.rpc2.task_start(task_id)
- _md5 = hashlib.md5()
- _md5.update(string_to_send)
- while total_size_sent_task_log < self._file_size:
- data = base64.encodestring(string_to_send)
- self.rpc2.task_upload_file(task_id, 'load_test',
- 'name_%s' % task_id, chunk_size, _md5.hexdigest(),
- offset_task_log, data)
- offset_task_log += 1
- total_size_sent_task_log += chunk_size
-
- #final chunk
- self.rpc2.task_upload_file(task_id, 'load_test', 'name_%s' % task_id,
- chunk_size, _md5.hexdigest(), -1, data)
- #Simulate some run time
- time.sleep(self._task_duration)
- #send result
- result_id = self.rpc2.task_result(task_id, 'pass_', task_name, '1079',
- '(Pass)')
- offset_result_log = 0
- total_size_sent_result_log = 0
- string_to_send_result = self._dummy_string * 326
- result_data = base64.encodestring(string_to_send_result)
- #no chunking
- self.rpc2.result_upload_file(result_id, '/',
- 'load_test--result', len(string_to_send_result), '', '0', result_data)
- self.rpc2.task_stop(task_id, 'stop', 'OK')
diff --git a/Tasks/distribution/beaker/fake_systems/Makefile b/Tasks/distribution/beaker/fake_systems/Makefile
new file mode 100644
index 0000000..1342c9d
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/Makefile
@@ -0,0 +1,59 @@
+# Copyright (c) 2012 Red Hat, Inc. All rights reserved. This copyrighted material
+# is made available to anyone wishing to use, modify, copy, or
+# redistribute it subject to the terms and conditions of the GNU General
+# Public License v.2.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Author: Dan Callaghan <dcallagh@redhat.com>
+
+TOPLEVEL_NAMESPACE=distribution
+PACKAGE_NAME=beaker
+RELATIVE_PATH=fake_systems
+export TESTVERSION=1.0
+export TEST=/$(TOPLEVEL_NAMESPACE)/$(PACKAGE_NAME)/$(RELATIVE_PATH)
+
+# executables to be built should be added here, they will be generated on the system under test.
+BUILT_FILES=
+
+# data files, .c files, scripts anything needed to either compile the test and/or run it.
+FILES=$(METADATA) runtest.sh Makefile PURPOSE hosts.sh system-csv.sh power-csv.sh \
+ dummy_fast dummy_medium dummy_slow dummy_flakey
+
+.PHONY: run
+run: $(FILES) build
+ ./runtest.sh
+
+.PHONY: build
+build: $(BUILT_FILES)
+
+.PHONY: clean
+clean:
+ rm -f *~ *.rpm $(BUILT_FILES)
+
+# Include Common Makefile
+include /usr/share/rhts/lib/rhts-make.include
+
+# Generate the testinfo.desc here:
+$(METADATA): Makefile
+ @touch $(METADATA)
+ @echo "Owner: Dan Callaghan <dcallagh@redhat.com>" > $(METADATA)
+ @echo "Name: $(TEST)" >> $(METADATA)
+ @echo "Path: $(TEST_DIR)" >> $(METADATA)
+ @echo "License: GPL-2" >> $(METADATA)
+ @echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
+ @echo "Description: Adds fake systems to Beaker" >> $(METADATA)
+ @echo "TestTime: 10m" >> $(METADATA)
+ @echo "Requires: beakerlib" >> $(METADATA)
+ @echo "Requires: curl" >> $(METADATA)
+ @echo "Requires: python-daemon" >> $(METADATA)
+ @echo "Requires: python-lxml" >> $(METADATA)
+ @echo "Requires: python-gevent" >> $(METADATA)
+
+ rhts-lint $(METADATA)
diff --git a/Tasks/distribution/beaker/fake_systems/PURPOSE b/Tasks/distribution/beaker/fake_systems/PURPOSE
new file mode 100644
index 0000000..f83341c
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/PURPOSE
@@ -0,0 +1 @@
+Add fake systems to Beaker. Intended for load testing.
diff --git a/Tasks/distribution/beaker/fake_systems/beah_dummy.py b/Tasks/distribution/beaker/fake_systems/beah_dummy.py
new file mode 100755
index 0000000..efddb08
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/beah_dummy.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+
+import hashlib
+import base64
+import xmlrpclib
+import time
+from lxml import etree
+from socket import gethostname
+
+
+class BeahDummy(object):
+
+ install_time = 600 #seconds
+ task_duration = 120 # seconds
+ task_log_chunk = 'thisisdummydata' * 66
+ task_log_chunk_enc = base64.encodestring(task_log_chunk)
+ task_log_chunk_md5 = hashlib.md5(task_log_chunk).hexdigest()
+ task_log_chunk_count = 128
+ recipe_log = 'thisisdummydata' * 326
+ recipe_log_enc = base64.encodestring(recipe_log)
+ recipe_log_md5 = hashlib.md5(recipe_log).hexdigest()
+
+ def __init__(self, machine_name, proxy_hostname='localhost'):
+ self.machine_name = machine_name
+ self.rpc2 = xmlrpclib.ServerProxy('http://%s:8000/RPC2' % proxy_hostname)
+
+ def run(self):
+ print '%s install_start' % self.machine_name
+ self.rpc2.install_start(self.machine_name)
+ time.sleep(self.install_time) #install time
+ recipe = self.rpc2.get_recipe(self.machine_name)
+ tree = etree.fromstring(recipe)
+ for task in tree.findall('.//task'):
+ task_id = task.get('id')
+ task_name = task.get('name')
+ self.run_task(task_id, task_name)
+
+ def run_task(self, task_id, task_name):
+ """
+ Start the task, send some logs, sleep a bit for the runtime, the send pass result
+ and stop the task
+
+ """
+ offset_task_log = 0
+ print '%s T:%s task_start' % (self.machine_name, task_id)
+ self.rpc2.task_start(task_id)
+ for i in xrange(self.task_log_chunk_count):
+ print '%s T:%s task_upload_file' % (self.machine_name, task_id)
+ self.rpc2.task_upload_file(task_id, 'load_test',
+ 'name_%s' % task_id, len(self.task_log_chunk), self.task_log_chunk_md5,
+ offset_task_log, self.task_log_chunk_enc)
+ offset_task_log += len(self.task_log_chunk)
+
+ #final chunk
+ print '%s T:%s task_upload_file' % (self.machine_name, task_id)
+ self.rpc2.task_upload_file(task_id, 'load_test', 'name_%s' % task_id,
+ len(self.task_log_chunk), self.task_log_chunk_md5, -1, self.task_log_chunk_enc)
+ #Simulate some run time
+ time.sleep(self.task_duration)
+ #send result
+ print '%s T:%s task_result' % (self.machine_name, task_id)
+ result_id = self.rpc2.task_result(task_id, 'pass_', task_name, '1079',
+ '(Pass)')
+ #no chunking
+ print '%s T:%s TR:%s result_upload_file' % (self.machine_name, task_id, result_id)
+ self.rpc2.result_upload_file(result_id, '/',
+ 'load_test--result', len(self.recipe_log), self.recipe_log_md5, 0, self.recipe_log_enc)
+ print '%s T:%s task_stop' % (self.machine_name, task_id)
+ self.rpc2.task_stop(task_id, 'stop', 'OK')
+
+class BeahDummyManager(object):
+
+ """
+ It's too expensive to create a separate beah_dummy process for potentially
+ thousands of dummy systems at the same time. So this is a tiny server
+ process which runs multiple beah_dummies in their own greenlet.
+
+ To start a new beah_dummy:
+ PUT /beah_dummy/fqdn.example.com
+ """
+
+ # TODO we could also implement DELETE to terminate a running beah_dummy
+
+ def wsgi(self, environ, start_response):
+ if not environ['PATH_INFO'].startswith('/beah_dummy/'):
+ start_response('404 Not Found', [('Content-Type', 'text/plain')])
+ return ['Path %s does not exist' % environ['PATH_INFO']]
+ if environ['REQUEST_METHOD'] != 'PUT':
+ start_response('405 Method Not Allowed', [('Content-Type', 'text/plain')])
+ return ['Method %s is not allowed' % environ['REQUEST_METHOD']]
+ hostname = environ['PATH_INFO'][len('/beah_dummy/'):]
+ gevent.spawn(BeahDummy(hostname).run)
+ start_response('204 No Content', [])
+ return []
+
+if __name__ == '__main__':
+ from optparse import OptionParser
+ parser = OptionParser()
+ parser.add_option("-f", "--foreground", default=False, action="store_true",
+ help="run in foreground (do not spawn a daemon)")
+ opts, args = parser.parse_args()
+ if not opts.foreground:
+ import daemon
+ daemon.DaemonContext().open()
+ import gevent.monkey
+ gevent.monkey.patch_all(thread=False)
+ from gevent.pywsgi import WSGIServer
+ WSGIServer(('', 8001), BeahDummyManager().wsgi).serve_forever()
diff --git a/Tasks/distribution/beaker/fake_systems/dummy_fast b/Tasks/distribution/beaker/fake_systems/dummy_fast
new file mode 100755
index 0000000..7ae66d2
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/dummy_fast
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -e
+if [ "$power_mode" == "on" ] ; then
+ curl -f -X PUT "http://localhost:8001/beah_dummy/$power_id"
+fi
diff --git a/Tasks/distribution/beaker/fake_systems/dummy_flakey b/Tasks/distribution/beaker/fake_systems/dummy_flakey
new file mode 100755
index 0000000..ef54063
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/dummy_flakey
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+
+# Takes a random amount of time between 0-60 seconds,
+# and randomly fails 1/10 times.
+
+delay=$(($RANDOM % 60))
+echo -n "dummy_flakey: sleeping for $delay seconds... "
+sleep $delay
+if [ $(($RANDOM % 10)) == 0 ] ; then
+ echo "done, now failing"
+ exit 1
+fi
+echo "done"
+if [ "$power_mode" == "on" ] ; then
+ curl -f -X PUT "http://localhost:8001/beah_dummy/$power_id"
+fi
diff --git a/Tasks/distribution/beaker/fake_systems/dummy_medium b/Tasks/distribution/beaker/fake_systems/dummy_medium
new file mode 100755
index 0000000..f9be83b
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/dummy_medium
@@ -0,0 +1,8 @@
+#!/bin/bash
+set -e
+echo -n "dummy_medium: sleeping for 5 seconds... "
+sleep 5
+echo "done"
+if [ "$power_mode" == "on" ] ; then
+ curl -f -X PUT "http://localhost:8001/beah_dummy/$power_id"
+fi
diff --git a/Tasks/distribution/beaker/fake_systems/dummy_slow b/Tasks/distribution/beaker/fake_systems/dummy_slow
new file mode 100755
index 0000000..f358f79
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/dummy_slow
@@ -0,0 +1,8 @@
+#!/bin/bash
+set -e
+echo -n "dummy_slow: sleeping for 60 seconds... "
+sleep 60
+echo "done"
+if [ "$power_mode" == "on" ] ; then
+ curl -f -X PUT "http://localhost:8001/beah_dummy/$power_id"
+fi
diff --git a/Tasks/distribution/beaker/fake_systems/hosts.sh b/Tasks/distribution/beaker/fake_systems/hosts.sh
new file mode 100755
index 0000000..1f9613b
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/hosts.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+set -e
+
+: ${TEST_SYSTEM_COUNT:=0}
+: ${TEST_SYSTEM_PREFIX:=test-}
+
+seq $TEST_SYSTEM_COUNT | while read n ; do
+ echo "127.1.$(($n / 256)).$(($n % 256)) $TEST_SYSTEM_PREFIX$n.invalid"
+done
diff --git a/Tasks/distribution/beaker/fake_systems/power-csv.sh b/Tasks/distribution/beaker/fake_systems/power-csv.sh
new file mode 100755
index 0000000..8093728
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/power-csv.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+set -e
+
+: ${TEST_SYSTEM_COUNT:=0}
+: ${TEST_SYSTEM_PREFIX:=test-}
+
+# Put quotes around the header fields to work around bz802842
+echo '"csv_type","fqdn","power_address","power_type","power_id"'
+seq $TEST_SYSTEM_COUNT | while read n ; do
+ # This distribution of the different dummy power types is completely
+ # unscientific and made-up. We don't want *too* many slow ones, otherwise
+ # the load tests will just cause an exploding backlog.
+ power_type=
+ [ $(($n % 10)) -ge 9 ] && : ${power_type:=dummy_flakey}
+ [ $(($n % 10)) -ge 8 ] && : ${power_type:=dummy_slow}
+ [ $(($n % 10)) -ge 5 ] && : ${power_type:=dummy_medium}
+ : ${power_type:=dummy_fast}
+ echo "power,$TEST_SYSTEM_PREFIX$n.invalid,localhost,$power_type,$TEST_SYSTEM_PREFIX$n.invalid"
+done
diff --git a/Tasks/distribution/beaker/fake_systems/runtest.sh b/Tasks/distribution/beaker/fake_systems/runtest.sh
new file mode 100755
index 0000000..94df24c
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/runtest.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+# Copyright (c) 2012 Red Hat, Inc. All rights reserved. This copyrighted material
+# is made available to anyone wishing to use, modify, copy, or
+# redistribute it subject to the terms and conditions of the GNU General
+# Public License v.2.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Author: Dan Callaghan <dcallagh@redhat.com>
+
+. /usr/share/beakerlib/beakerlib.sh
+
+function LabController()
+{
+ rlJournalStart
+ rlPhaseStartSetup
+ rlRun "yum install -y curl python-daemon python-lxml python-gevent"
+ rlRun "cp dummy_* /etc/beaker/power-scripts/" 0 "Installing dummy power scripts"
+ rlRun "./beah_dummy.py" 0 "Starting beah_dummy.py daemon"
+ rlLog "Adding fake entries to /etc/hosts"
+ ./hosts.sh >>/etc/hosts
+ rlLog "Generating fake system CSV files"
+ ./system-csv.sh >systems.csv
+ ./power-csv.sh >power.csv
+ rlRun "curl -f -s -o /dev/null -c cookie -d user_name=admin -d password=testing -d login=1 http://$SERVER/bkr/login" 0 "Logging in to Beaker server"
+ rlRun "curl -f -s -o /dev/null -b cookie --form csv_file=@systems.csv http://$SERVER/bkr/csv/action_import" 0 "Uploading systems CSV"
+ rlRun "curl -f -s -o /dev/null -b cookie --form csv_file=@power.csv http://$SERVER/bkr/csv/action_import" 0 "Uploading power CSV"
+ rlPhaseEnd
+ rlJournalEnd
+}
+
+function Inventory()
+{
+ rlJournalStart
+ rlPhaseStartSetup
+ rlRun "curl -f -s -o /dev/null -c cookie -d user_name=admin -d password=testing -d login=1 http://localhost/bkr/login" 0 "Logging in to Beaker server"
+ for powertype in dummy_* ; do
+ rlRun "curl -f -s -o /dev/null -b cookie -d name=$powertype -d id= http://localhost/bkr/powertypes/save" 0 "Adding dummy power type $powertype in Beaker"
+ done
+ rlPhaseEnd
+ rlJournalEnd
+}
+
+if grep -q $HOSTNAME <<<"$CLIENTS" ; then
+ rlLog "Running as Lab Controller using Inventory: ${SERVERS}"
+ TEST="$TEST/lab_controller"
+ SERVER=$(echo $SERVERS | awk '{print $1}')
+ LabController
+ exit 0
+fi
+
+if grep -q $HOSTNAME <<<"$SERVERS" ; then
+ rlLog "Running as Inventory using Lab Controllers: ${CLIENTS}"
+ TEST="$TEST/inventory"
+ Inventory
+ exit 0
+fi
+
+if [ -z "$SERVERS" -o -z "$CLIENTS" ]; then
+ rlLog "Inventory=${SERVERS} LabController=${CLIENTS} Assuming Single Host Mode."
+ CLIENTS=$STANDALONE
+ SERVERS=$STANDALONE
+ SERVER=$(echo $SERVERS | awk '{print $1}')
+ TEST="$TEST/lab_controller" LabController
+ TEST="$TEST/inventory" Inventory
+ exit 0
+fi
+
+rlDie "not reached"
diff --git a/Tasks/distribution/beaker/fake_systems/system-csv.sh b/Tasks/distribution/beaker/fake_systems/system-csv.sh
new file mode 100755
index 0000000..d5420ef
--- /dev/null
+++ b/Tasks/distribution/beaker/fake_systems/system-csv.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -e
+
+: ${TEST_SYSTEM_COUNT:=0}
+: ${TEST_SYSTEM_COUNT_AUTOMATED:=0}
+: ${TEST_SYSTEM_PREFIX:=test-}
+
+# Put quotes around the header fields to work around bz802842
+echo '"csv_type","fqdn","arch","type","lab_controller","vendor","model","location","status"'
+seq $TEST_SYSTEM_COUNT | while read n ; do
+ [ $n -lt $TEST_SYSTEM_COUNT_AUTOMATED ] && status=Automated || status=Manual
+ echo "system,$TEST_SYSTEM_PREFIX$n.invalid,x86_64,Machine,$HOSTNAME,Fake,Fake,Non-existent,$status"
+done