Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
* .


### 0.1.0 - 27.02.2015

* Creates a config.ini if not found
* all threebot-worker relevant files are now located in `~/3bot/` or `<virtualenv>/3bot/`
* `threebot-worker` is a global available script
* Updated README


### 0.0.3 - 17.11.2014

* Raise exception only when in debug mode
Expand Down
62 changes: 48 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,73 @@ A worker is a computer program that runs as a background process on a machine. T

Jump to [3bot main repo](https://github.com/3bot/3bot/).

Use [this Gist](https://gist.github.com/walterrenner/4d8863043404bec01d0f) to install the 3bot-worker on your mashine.
## Setup/Installation

$ pip install threebot-worker
$ threebot-worker start



## Configuration

The configuration file contains all the configuration of your 3bot installation and/or components.
This section explains how this configuration work and which parameter are available.
The configuration file contains all the configuration of your threebot-worker installation.
This section explains which parameter are available.

* The configuration file is located under `/etc/3bot/config.ini`.
* There is a overall `3bot-settings` section.
* It's an ini-file.
The configuration file is located in `~/3bot/config.ini`. If you installed 3bot in an own virtualenv it
is located in `<path to virtualenv>/3bot/config.ini`

### The `3bot-settings` section
You don't need to create a configuration file by yourself. When you first run the threebot-worker, you will be asked to enter values for the required settings.

#### BOT_ENDPOINT
### Available settings

#### LOGFILE
#### BOT_ENDPOINT

* That file/path must be writable by the worker.
required: True

#### LOGLEVEL
default: *

* Valid values for `LOGLEVEL` could be taken from [here](https://docs.python.org/2/howto/logging.html).
List of hosts the worker should accept connections from (this is not well tested yet)

#### PORT

required: True

default: None

Port number the worker listens. This Port should be openend by your firewall. The port number from the 3bot application and threebot-worker settings must match.

#### SECRET_KEY

* Do never share your config.ini containing your `SECRET_KEY`!
required: True

default: None

The secret key is used to establish a secure connection from the 3bot application to the threebot-worker. The secret key from the 3bot application and threebot-worker settings must match.

**Never share your your secret key!**

#### LOGFILE

required: False

default: `~/3bot/3bot.log`

Path to the logfile. theebot-worker will log all incomming connections, performed workflows and errors.

#### LOGLEVEL

required: False

default: `CRITICAL`

Valid values for `LOGLEVEL` could be taken from [here](https://docs.python.org/2/howto/logging.html).

### Example
### Example for `confing.ini`

[3bot-settings]
BOT_ENDPOINT = *
PORT = 55556
SECRET_KEY = <YOUR SECRET KEY>
LOGFILE = /var/log/3bot-worker.log
LOGLEVEL = DEBUG

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ def long_description():
packages=find_packages(),
include_package_data=True,
install_requires=open('requirements.txt').read().split('\n'),
scripts=['threebot_worker/worker.py'],
scripts=['threebot_worker/threebot-worker'],
)
2 changes: 1 addition & 1 deletion threebot_worker/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

__version__ = '0.0.9'
__version__ = '0.1.0'
115 changes: 67 additions & 48 deletions threebot_worker/worker.py → threebot_worker/threebot-worker
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -11,83 +11,104 @@
import threebot_crypto
from threebot_worker.daemon import Daemon

configfile = '/etc/3bot/config.ini'
pidfile = '/tmp/3bot-worker.pid'
_default_logfile = '/etc/3bot/3bot.log'
_default_loglevel = 'ERROR'
PROTOCOL = 'tcp'

if os.environ['VIRTUAL_ENV']:
current_path = os.path.realpath(os.environ['VIRTUAL_ENV'])
local_configfile = os.path.join(current_path, 'config.ini')
pidfile = os.path.join(current_path, '3bot-worker.pid')
BASE_FOLDERNAME = '3bot'
BASEDIR = os.path.join(os.path.expanduser("~"), BASE_FOLDERNAME)

if os.environ.get('VIRTUAL_ENV', False): # in case worker runs in a virtualenv, set BASEDIR to path of virtualenv
BASEDIR = os.path.join(os.path.realpath(os.environ['VIRTUAL_ENV']), BASE_FOLDERNAME)

CONFIGFILE = os.path.join(BASEDIR, 'config.ini')
PIDFILE = os.path.join(BASEDIR, '3bot-worker.pid')
SCRIPTDIR = os.path.join(BASEDIR, 'logs')

LOGFILE = os.path.join(BASEDIR, '3bot.log')
LOGLEVEL = 'ERROR'

Config = ConfigParser.ConfigParser()

if local_configfile and os.path.isfile(local_configfile):
Config.read(local_configfile)
elif os.path.isfile(configfile):
Config.read(configfile)
if os.path.isfile(CONFIGFILE):
Config.read(CONFIGFILE)
else:
print "No configfile found in: '%s'" % configfile
print "You can find a basic configfile in the Documentation."
sys.exit(2)
print "No configfile found in: '%s'" % CONFIGFILE
print "----"
print "Creating basic configfile in '%s'" % CONFIGFILE
print "----"

os.makedirs(CONFIGFILE)
cfgfile = open(CONFIGFILE, 'w')

# add the settings to the structure of the file, and lets write it out...
Config.add_section('3bot-settings')
Config.set('3bot-settings', 'BOT_ENDPOINT', '*')

port = raw_input('Enter PORT: ')
Config.set('3bot-settings', 'PORT', port)

sec_key = raw_input('Enter SECRET_KEY: ')
Config.set('3bot-settings', 'SECRET_KEY', sec_key)

Config.write(cfgfile)
cfgfile.close()

FLAGS = 0

try:
BOT = Config.get('3bot-settings', 'BOT_ENDPOINT')
PORT = Config.get('3bot-settings', 'PORT')
except:
print "Invalid configfile in: '%s'. Could not find BOT or PORT declaration" % configfile
print "Invalid configfile in: '%s'. Could not find BOT or PORT declaration" % CONFIGFILE
print "You can find a basic configfile in the Documentation."
sys.exit(2)

try:
# Read secret key - never share yours!
SECRET_KEY = Config.get('3bot-settings', 'SECRET_KEY')
except:
print "Invalid configfile in: '%s'. Could not find SECRET_KEY declaration" % configfile
print "Invalid configfile in: '%s'. Could not find SECRET_KEY declaration" % CONFIGFILE
print "You can find a basic configfile in the Documentation."
sys.exit(2)


try:
LOGFILE = Config.get('3bot-settings', 'LOGFILE')
except ConfigParser.NoOptionError:
LOGFILE = _default_logfile
pass

try:
_LOGLEVEL = Config.get('3bot-settings', 'LOGLEVEL', _default_loglevel)
LOGLEVEL = Config.get('3bot-settings', 'LOGLEVEL')
except ConfigParser.NoOptionError:
_LOGLEVEL = _default_loglevel

if _LOGLEVEL == 'DEBUG':
LOGLEVEL = logging.DEBUG
elif _LOGLEVEL == 'INFO':
LOGLEVEL = logging.INFO
elif _LOGLEVEL == 'WARNING':
LOGLEVEL = logging.WARNING
elif _LOGLEVEL == 'ERROR':
LOGLEVEL = logging.ERROR
pass

if LOGLEVEL == 'DEBUG':
loglevel = logging.DEBUG
elif LOGLEVEL == 'INFO':
loglevel = logging.INFO
elif LOGLEVEL == 'WARNING':
loglevel = logging.WARNING
elif LOGLEVEL == 'ERROR':
loglevel = logging.ERROR
else:
LOGLEVEL = logging.CRITICAL

logging.basicConfig(filename=LOGFILE,
level=LOGLEVEL,
format='%(asctime)s %(message)s')
logging.basicConfig(
filename=LOGFILE,
level=loglevel,
format='%(asctime)s %(message)s',
)

if len(sys.argv) == 2:
if 'start' == sys.argv[1] or 'restart' == sys.argv[1]:
print '---'
print "Try Starting Worker with following settings found in '%s'" % configfile
print "Try Starting Worker with following settings found in '%s'" % CONFIGFILE
print 'ENDPOINT: %s' % str(BOT)
print 'PORT: %s' % str(PORT)
print 'LOGFILE: %s' % str(LOGFILE)
print 'LOGLEVEL: %s' % str(_LOGLEVEL)
print 'LOGLEVEL: %s' % str(LOGLEVEL)
print '---'


def writeScript(directory, script, body):
def write_script(directory, script, body):
# create and change to log directory
task_path = os.path.join(directory, script)

Expand All @@ -102,7 +123,7 @@ def writeScript(directory, script, body):
return task_path


def runCommand(request):
def run_command(request):
"""
Calls the action
"""
Expand All @@ -111,9 +132,8 @@ def runCommand(request):
log_time = request['workflow_log_time']
workflow_name = request['workflow']
foldername = "%s-%s-%s" % (log_time, str(log_id), workflow_name)
home = os.path.expanduser("~")

directory = os.path.join(home, '3bot', 'logs', foldername)
directory = os.path.join(SCRIPTDIR, foldername)

if not os.path.exists(directory):
os.makedirs(directory)
Expand All @@ -127,19 +147,19 @@ def runCommand(request):
if request.get('hooks', ) is not None:
if request['hooks'].get('pre_task', ) is not None:
task_filename = "pre_task_%i" % request['script']['id']
script_bits.append(writeScript(directory, task_filename, request['hooks']['pre_task']))
script_bits.append(write_script(directory, task_filename, request['hooks']['pre_task']))

# the main task
task_filename = "script_%i" % request['script']['id']
task_path = os.path.join(directory, task_filename)
task_body = request['script']['body']
script_bits.append(writeScript(directory, task_filename, task_body))
script_bits.append(write_script(directory, task_filename, task_body))

# add post task hook if available
if request.get('hooks', ) is not None:
if request['hooks'].get('post_task', ) is not None:
task_filename = "post_task_%i" % request['script']['id']
script_bits.append(writeScript(directory, task_filename, request['hooks']['post_task']))
script_bits.append(write_script(directory, task_filename, request['hooks']['post_task']))

callable = ''
if len(script_bits) > 1:
Expand Down Expand Up @@ -177,8 +197,7 @@ def run(self):

context = zmq.Context(1)
server = context.socket(zmq.REP)
logging.basicConfig(filename=LOGFILE, level=LOGLEVEL)
server.bind("tcp://%s:%s" % (BOT, PORT))
server.bind("%s://%s:%s" % (PROTOCOL, BOT, PORT))

while True:
request = server.recv(FLAGS)
Expand All @@ -191,25 +210,25 @@ def run(self):
response = {'type': 'ACK'}
else:
logging.info("Script request")
response = runCommand(request)
response = run_command(request)
response = threebot_crypto.encrypt(response, SECRET_KEY)
server.send(response, flags=FLAGS)
logging.info("Sending response")
else:
logging.error("Could not decrypt received message")
if self.debug_mode:
raise Exception("Could not decrypt message")
#server.send("", flags=FLAGS)
# server.send("", flags=FLAGS)


if __name__ == "__main__":
if len(sys.argv) == 3:
if 'start' == sys.argv[1] and 'debug' == sys.argv[2]:
daemon = WorkerDeamon(pidfile, debug_mode=True)
daemon = WorkerDeamon(PIDFILE, debug_mode=True)
daemon.start()

elif len(sys.argv) == 2:
daemon = WorkerDeamon(pidfile)
daemon = WorkerDeamon(PIDFILE)
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
Expand Down