Skip to content

Commit

Permalink
Merge pull request #4 from linkedin/master
Browse files Browse the repository at this point in the history
pulling from linkedin/zopkio
  • Loading branch information
jdehrlich committed Dec 16, 2015
2 parents d0542ed + 6c3091a commit 859ce9b
Show file tree
Hide file tree
Showing 36 changed files with 1,301 additions and 142 deletions.
11 changes: 8 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ before_install:
- cat /dev/zero | ssh-keygen -q -N ""
- cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
# install dependencies
install: "python setup.py install"
install:
- "python setup.py install"
- "pip install coverage"
- "pip install coveralls"
# run tests
script:
- python setup.py test
- zopkio examples/server_client/server_client.py --nopassword
- python setup.py test
- coverage run --source=zopkio setup.py test
after_success:
- coveralls
15 changes: 9 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ Zopkio - A Functional and Performance Test Framework for Distributed Systems
.. image:: https://travis-ci.org/linkedin/Zopkio.svg?branch=master
:target: https://travis-ci.org/linkedin/Zopkio

.. image:: https://coveralls.io/repos/linkedin/Zopkio/badge.svg?branch=master&service=github
:target: https://coveralls.io/github/linkedin/Zopkio?branch=master

Zopkio is a test framework built to support at scale performance and functional
testing.

Expand Down Expand Up @@ -87,7 +90,7 @@ Deployment
~~~~~~~~~~

The deployment file should be pointed to by an entry in the dictionary called
*deployemnet_code*. Deplyoment is one of the key features of Zopkio.
*deployment_code*. Deplyoment is one of the key features of Zopkio.
Developers can write test in
which they bring up arbtrary sets of services on multiple machines and then
within the tests exercise a considerable degree of control over these machines.
Expand Down Expand Up @@ -137,11 +140,11 @@ Test Files

Test files are specified by an entry in the test dictionary called *test_code*,
which should point to a list of test files.
Foreach test file, the framework will execute any function with *test* in the
name and track if the function executes successfully. In addition if there is a
function ``test_foo`` and a function ``validate_foo``, after all cleanup
and log collection is done, if ``test_foo`` executed successfully then
``validate_foo`` will be executed and tested for successful execution if
For each test file, the framework will execute any function with *test* in the
name (no matter the case) and track if the function executes successfully. In
addition if there is a function ``test_foo`` and a function ``validate_foo``,
after all cleanup and log collection is done, if ``test_foo`` executed successfully
then ``validate_foo`` will be executed and tested for successful execution if
it fails, the original test will fail and the logs from the post execution will
be displayed. Test can be run in either a parallel mode or a serial mode. By
default tests are run serially without any specified order. However each test file
Expand Down
12 changes: 6 additions & 6 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,11 @@ which behaves similarly.
Test Files
----------

Foreach test file, the framework will execute any function with *test* in the
name and track if the function executes successfully. In addition if there is a
function ``test_foo`` and a function ``validate_foo``, after all cleanup
and log collection is done, if ``test_foo`` executed successfully then
``validate_foo`` will be executed and tested for successful execution if
For each test file, the framework will execute any function with *test* in the
name (no matter the case) and track if the function executes successfully. In
addition if there is a function ``test_foo`` and a function ``validate_foo``,
after all cleanup and log collection is done, if ``test_foo`` executed successfully
then ``validate_foo`` will be executed and tested for successful execution if
it fails, the original test will fail and the logs from the post execution will
be displayed. Consider a simple test with our server client example::

Expand Down Expand Up @@ -384,7 +384,7 @@ Test configs are properties which affect how the tests are run. They are specifi
to the tests test writer and accessible from
``runtime.get_config(config_name)`` which will return the stored value or the
empty string if no property with that name is present. These are the properties
that can be overrode by the ``config-overrides`` command line flag.
that can be overridden by the ``config-overrides`` command line flag.

Application configs are properties which affect how the remote services are
configured, there is not currently a decision as to how we will install these
Expand Down
19 changes: 19 additions & 0 deletions examples/zookeeper/config/zookeeper1_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"zookeeper1_host": "localhost",
"zookeeper1_install_path" : "/tmp/zookeeper_test1",
"zookeeper1_logs": [
"zookeeper.out"
],
"zookeeper1_post_install_cmds": [
"cp zookeeper-3.4.6/conf/zoo_sample.cfg zookeeper-3.4.6/conf/zoo.cfg",
"sed -i.bak 's/.*dataDir=.*/dataDir=dataDir1/g' zookeeper-3.4.6/conf/zoo.cfg",
"sed -i.bak 's/.*clientPort=.*/clientPort=2181/g' zookeeper-3.4.6/conf/zoo.cfg",
"echo 'server.1=localhost:2888:3888' >> zookeeper-3.4.6/conf/zoo.cfg",
"echo 'server.2=localhost:2889:3889' >> zookeeper-3.4.6/conf/zoo.cfg",
"echo 'server.3=localhost:2890:3890' >> zookeeper-3.4.6/conf/zoo.cfg",
"rm -rf dataDir1",
"mkdir dataDir1",
"echo '1' > dataDir1/myid"
],
"zookeeper1_pid_file": "/tmp/zookeeper_test1/dataDir1/zookeeper_server.pid"
}
19 changes: 19 additions & 0 deletions examples/zookeeper/config/zookeeper2_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"zookeeper2_host":"localhost",
"zookeeper2_install_path" : "/tmp/zookeeper_test2",
"zookeeper2_logs": [
"zookeeper.out"
],
"zookeeper2_post_install_cmds": [
"cp zookeeper-3.4.6/conf/zoo_sample.cfg zookeeper-3.4.6/conf/zoo.cfg",
"sed -i.bak 's/.*dataDir=.*/dataDir=dataDir2/g' zookeeper-3.4.6/conf/zoo.cfg",
"sed -i.bak 's/.*clientPort=.*/clientPort=2182/g' zookeeper-3.4.6/conf/zoo.cfg",
"echo 'server.1=localhost:2888:3888' >> zookeeper-3.4.6/conf/zoo.cfg",
"echo 'server.2=localhost:2889:3889' >> zookeeper-3.4.6/conf/zoo.cfg",
"echo 'server.3=localhost:2890:3890' >> zookeeper-3.4.6/conf/zoo.cfg",
"rm -rf dataDir2",
"mkdir dataDir2",
"echo '2' > dataDir2/myid"
],
"zookeeper2_pid_file": "/tmp/zookeeper_test2/dataDir2/zookeeper_server.pid"
}
19 changes: 19 additions & 0 deletions examples/zookeeper/config/zookeeper3_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"zookeeper3_host":"localhost",
"zookeeper3_install_path" : "/tmp/zookeeper_test3",
"zookeeper3_logs": [
"zookeeper.out"
],
"zookeeper3_post_install_cmds": [
"cp zookeeper-3.4.6/conf/zoo_sample.cfg zookeeper-3.4.6/conf/zoo.cfg",
"sed -i.bak 's/.*dataDir=.*/dataDir=dataDir3/g' zookeeper-3.4.6/conf/zoo.cfg",
"sed -i.bak 's/.*clientPort=.*/clientPort=2183/g' zookeeper-3.4.6/conf/zoo.cfg",
"echo 'server.1=localhost:2888:3888' >> zookeeper-3.4.6/conf/zoo.cfg",
"echo 'server.2=localhost:2889:3889' >> zookeeper-3.4.6/conf/zoo.cfg",
"echo 'server.3=localhost:2890:3890' >> zookeeper-3.4.6/conf/zoo.cfg",
"rm -rf dataDir3",
"mkdir dataDir3",
"echo '3' > dataDir3/myid"
],
"zookeeper3_pid_file": "/tmp/zookeeper_test3/dataDir3/zookeeper_server.pid"
}
6 changes: 4 additions & 2 deletions examples/zookeeper/config/zookeeper_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
"zookeeper_host":"localhost",
"zookeeper_exec_location":"http://apache.mirrors.pair.com/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz",
"zookeeper_stop_command": "zookeeper-3.4.6/bin/zkServer.sh stop",
"zookeeper_start_command": "zookeeper-3.4.6/bin/zkServer.sh start zookeeper-3.4.6/conf/zoo.cfg",
"zookeeper_start_command": "zookeeper-3.4.6/bin/zkServer.sh start zookeeper-3.4.6/conf/zoo.cfg",
"cleanup_pending_process" : false,
"verify_after_each_test": true,
"zookeeper_logs": [
"zookeeper.out"
],
"zookeeper_post_install_cmds": [
"cp zookeeper-3.4.6/conf/zoo_sample.cfg zookeeper-3.4.6/conf/zoo.cfg",
"sed -i.bak 's/.*dataDir=.*/dataDir=data/g' zookeeper-3.4.6/conf/zoo.cfg"
"sed -i.bak 's/.*dataDir=.*/dataDir=dataDir1/g' zookeeper-3.4.6/conf/zoo.cfg",
"sed -i.bak 's/.*clientPort=.*/clientPort=2181/g' zookeeper-3.4.6/conf/zoo.cfg"
]
}
81 changes: 81 additions & 0 deletions examples/zookeeper/deploy_zookeepers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Copyright 2015 LinkedIn Corp.
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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

import zopkio.adhoc_deployer as adhoc_deployer
import zopkio.runtime as runtime

zookeper_deployer = None


def setup_suite():
print "Starting zookeeper quorum"
global zookeper_deployer
env_dict = {}

if "localhost" not in runtime.get_active_config('zookeeper_host'):
env_dict = {'JAVA_HOME':'/export/apps/jdk/current'}

zookeper_deployer = adhoc_deployer.SSHDeployer("zookeeper",
{'pid_keyword': "zookeeper",
'executable': runtime.get_active_config('zookeeper_exec_location'),
'env':env_dict,
'extract': True,
'stop_command':runtime.get_active_config('zookeeper_stop_command'),
'start_command': runtime.get_active_config('zookeeper_start_command')})
runtime.set_deployer("zookeeper", zookeper_deployer)

# Deploy Zookeeper1
print "Deploy Zookeeper1"
zookeper_deployer.install("zookeeper1",
{"hostname": "localhost",
"install_path": runtime.get_active_config('zookeeper1_install_path'),
"pid_file": runtime.get_active_config('zookeeper1_pid_file'),
'post_install_cmds':runtime.get_active_config('zookeeper1_post_install_cmds')})

zookeper_deployer.start("zookeeper1",configs={"sync": True})

# Deploy Zookeeper2
print "Deploy Zookeeper2"
zookeper_deployer.install("zookeeper2",
{"hostname": "localhost",
"install_path": runtime.get_active_config('zookeeper2_install_path'),
"pid_file": runtime.get_active_config('zookeeper2_pid_file'),
'post_install_cmds':runtime.get_active_config('zookeeper2_post_install_cmds')})

zookeper_deployer.start("zookeeper2",configs={"sync": True})

# Deploy Zookeeper3
print "Deploy Zookeeper3"
zookeper_deployer.install("zookeeper3",
{"hostname": "localhost",
"install_path": runtime.get_active_config('zookeeper3_install_path'),
"pid_file": runtime.get_active_config('zookeeper3_pid_file'),
'post_install_cmds':runtime.get_active_config('zookeeper3_post_install_cmds')})

zookeper_deployer.start("zookeeper3",configs={"sync": True})

def teardown_suite():
#Terminate Zookeeper
global zookeper_deployer
zookeper_deployer.undeploy("zookeeper1")
zookeper_deployer.undeploy("zookeeper2")
zookeper_deployer.undeploy("zookeeper3")
print "zookeepers terminated"
5 changes: 3 additions & 2 deletions examples/zookeeper/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@ def setup_suite():
'executable': runtime.get_active_config('zookeeper_exec_location'),
'env':env_dict,
'extract': True,
'post_install_cmds':runtime.get_active_config('zookeeper_post_install_cmds'),
'stop_command':runtime.get_active_config('zookeeper_stop_command'),
'start_command': runtime.get_active_config('zookeeper_start_command')})
runtime.set_deployer("zookeeper", zookeper_deployer)

zookeper_deployer.install("zookeeper",
{"hostname": runtime.get_active_config('zookeeper_host'),
"install_path": "/tmp/zookeeper_test"})
"install_path": "/tmp/zookeeper_test",
'post_install_cmds':runtime.get_active_config('zookeeper_post_install_cmds')})

zookeper_deployer.start("zookeeper",configs={"sync": True})


Expand Down
37 changes: 37 additions & 0 deletions examples/zookeeper/log_naarad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2015 LinkedIn Corp.
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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

LOGS_DIRECTORY = "/tmp/zopkio_zookeeper/logs/"
OUTPUT_DIRECTORY = "/tmp/zopkio_zookeeper/results/"

def machine_logs():
return {
"zookeeper": [os.path.join("/tmp/zookeeper_test", "zookeeper.out")],
}

def naarad_logs():
return {
'zookeeper': [],
}


def naarad_config():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), "naarad.cfg")
75 changes: 75 additions & 0 deletions examples/zookeeper/test_suites/zookeeper_cluster_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Copyright 2015 LinkedIn Corp.
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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 kazoo.client import KazooClient
from multiprocessing import Process
import time

import zopkio.runtime as runtime
import zopkio.test_utils as testutilities
import zopkio.adhoc_deployer as adhoc_deployer


zookeper_deployer = None
test_phase = 1

def zookeeper_ephemeral_node(name):
zk = KazooClient(hosts=str(runtime.get_active_config('zookeeper_host') + ':2181'))
zk.start()
zk.create("/my/zookeeper_test/node1", b"process1 running", ephemeral=True)
#At 10 validate that ephemeral node exist that is the process is still running
time.sleep(10)
assert zk.exists("/my/zookeeper_test/node1"), "process node is not found at 10 s when it is still running"

time.sleep(20)
zk.stop()

def test_zookeeper_process_tracking():
"""
Tests if process register node correctly with zookeeper and zookeeper deletes it when process terminates
"""
#Wait for zookeeper to start so that kazoo client can connect correctly
time.sleep(5)
#"connecting to esnure /my/zookeeper_test"

kazoo_connection_url = str(runtime.get_active_config('zookeeper_host') + ':2181')
zkclient = KazooClient(hosts=kazoo_connection_url)

zkclient.start()

zkclient.ensure_path("/my/zookeeper_test")
#spawn a python multiprocess which creates an ephermeral node
#once the process ends the node will be deleted.
p = Process(target=zookeeper_ephemeral_node, args=("process1",))
p.start()
zkclient.stop()

def validate_zookeeper_process_tracking():
"""
Verify if process register node correctly with zookeeper and zookeeper deletes it when process terminates
"""
zk = KazooClient(hosts=str(runtime.get_active_config('zookeeper_host') + ':2181'))
zk.start()

#At 60 validate that process has terminated by looking at the ephemeral node
time.sleep(60)
assert not zk.exists("/my/zookeeper_test/node1"), "process node not found at 60 s when it should have terminated"

zk.stop()
Loading

0 comments on commit 859ce9b

Please sign in to comment.