Commit aa358bc8 authored by Łukasz Nowak's avatar Łukasz Nowak

Import toolbox codebase.

parent 8f3f960c
1.0-dev (unreleased)
--------------------
include CHANGES.txt
recursive-include src/slapos/tool/builder/templates *.in
include src/slapos/tool/builder/scripts/slapos
include src/slapos/tool/builder/scripts/slapos_firstboot
slapbuilder
===========
slapbuilder is a program to install a slapos image.
Mirror of files from http://susestudio.com/appliance/
#!/bin/bash
##############################################################################
#
# Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
#
# This script is executed at the end of appliance creation. Here you can do
# one-time actions to modify your appliance before it is ever used, like
# removing files and directories to make it smaller, creating symlinks,
# generating indexes, etc.
#
# The 'kiwi_type' variable will contain the format of the appliance (oem =
# disk image, vmx = VMware, iso = CD/DVD, xen = Xen).
#
# read in some variables
. /studio/profile
# Removing eth0 config file which became unecessary with the bridge creation
rm -f /etc/sysconfig/network/ifcfg-eth0
#!/bin/bash
### BEGIN INIT INFO
# Provides: suse_studio_custom
# Required-Start:
# Required-Stop:
# Default-Start:
# Default-Stop:
# Description: Script run whenever the appliance boots
### END INIT INFO
##############################################################################
#
# Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
#
# This script is executed whenever your appliance boots. Here you can add
# commands to be executed before the system enters the first runlevel. This
# could include loading kernel modules, starting daemons that aren't managed
# by init files, asking questions at the console, etc.
#
# The 'kiwi_type' variable will contain the format of the appliance (oem =
# disk image, vmx = VMware, iso = CD/DVD, xen = Xen).
#
#
# read in some variables
. /studio/profile
if [ -f /etc/init.d/suse_studio_firstboot ]
then
/etc/init.d/slapos_firstboot
elif [ -f /token_second_boot ]; then
/etc/init.d/slapos_secondboot
fi
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages
import os
name = 'slapos.tool.builder'
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
long_description=(
read('README.txt')
+ '\n' +
read('CHANGES.txt')
)
setup(
name = name,
version = '1.0-dev-2',
description = "slapos - partitioning tools for servers",
long_description=long_description,
license = "GPLv3",
keywords = "slapos server builder",
include_package_data = True,
packages = find_packages('src'),
package_dir = {'':'src'},
namespace_packages = ['slapos'],
# slapgos use this to create a clean ouput
install_requires = [
'setuptools', # namespace
],
entry_points = """
[console_scripts]
slapbuilder = %s:main
""" % name,
)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
This diff is collapsed.
#!/bin/sh
### BEGIN INIT INFO
# Provides: slapos
# Required-Start: $network $remote_fs
# Required-Stop: $network $remote_fs
# Default-Start: 3 5
# Default-Stop:
# Description: Run SlapOS
### END INIT INFO
##############################################################################
#
# Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
case "$1" in
start)
# clean the system
for service in rpcbind network-remotefs postfix ; do
chkconfig --del $service
/etc/init.d/$service stop
done
# set random root password
pwgen -sync 512 1 | passwd --stdin root
SLAP_INSTALL_LOG=/opt/slapos/slapos-install.log
if [ ! -f /opt/slapos/bin/slapformat ] ; then
while [ ! -f /opt/slapos/bin/slapformat ] ; do
echo -n "Installing SlapOS, log availble at ${SLAP_INSTALL_LOG}..."
# software not detected, force forever installation
mkdir -p /opt/slapos
(python -S -c \
'import urllib2;print urllib2.urlopen("http://svn.zope.org/*checkout*/zc.buildout/trunk/bootstrap/bootstrap.py").read()' \
| python -S - -c /etc/slapos/software.cfg buildout:directory=/opt/slapos \
>> ${SLAP_INSTALL_LOG} 2>&1 && /opt/slapos/bin/buildout -c \
/etc/slapos/software.cfg buildout:directory=/opt/slapos >> \
${SLAP_INSTALL_LOG} 2>&1 ) && (echo "done.") || (echo \
"failed, retrying, the last error was:." ; tail -n 20 ${SLAP_INSTALL_LOG} ; rm -f /opt/slapos/bin/slapformat)
done
fi
# software detected, ready to run
# Set up cron
echo """# BEWARE: This file will be automatically regenerated on each boot
SHELL=/bin/sh
PATH=/usr/bin:/usr/sbin:/sbin:/bin:/usr/lib/news/bin
MAILTO=root
0 0 * * * root /opt/slapos/bin/slapformat --verbose --log_file=/opt/slapos/slapformat.log /etc/slapos/slapos.cfg >> /opt/slapos/slapformat.log 2>&1
*/5 * * * * root /opt/slapos/bin/slapgrid-cp --verbose --logfile=/opt/slapos/slapgrid-cp.log --pidfile=/opt/slapos/slapgrid-cp.pid /etc/slapos/slapos.cfg >> /opt/slapos/slapgrid-cp.log 2>&1
*/5 * * * * root /opt/slapos/bin/slapgrid-sr --verbose --logfile=/opt/slapos/slapgrid-sr.log --pidfile=/opt/slapos/slapgrid-sr.pid /etc/slapos/slapos.cfg >> /opt/slapos/slapgrid-sr.log 2>&1
0 0 * * * root /opt/slapos/bin/slapgrid-ur --verbose --logfile=/opt/slapos/slapgrid-ur.log --pidfile=/opt/slapos/slapgrid-ur.pid /etc/slapos/slapos.cfg >> /opt/slapos/slapgrid-ur.log 2>&1
""" > /etc/cron.d/slapos
# Execute slapformat
echo -n "Running slapformat..."
/opt/slapos/bin/slapformat --verbose --console /etc/slapos/slapos.cfg
echo "done."
# Set kvm up
modprobe kvm_intel
chmod 666 /dev/kvm
# Enable noop scheduler for disk which have SLAPOS labeled partition
disk=`blkid -L SLAPOS | sed -r -e 's/(\/dev\/|[0-9]*$)//g'`
echo noop > /sys/block/$disk/queue/scheduler
;;
esac
#
# hosts This file describes a number of hostname-to-address
# mappings for the TCP/IP subsystem. It is mostly
# used at boot time, when no name servers are running.
# On small systems, this file can be used instead of a
# "named" name server.
# Syntax:
#
# IP-Address Full-Qualified-Hostname Short-Hostname
#
127.0.0.1 %(computer_id)s localhost
# special IPv6 addresses
::1 %(computer_id)s localhost ipv6-localhost ipv6-loopback
fe00::0 ipv6-localnet
ff00::0 ipv6-mcastprefix
ff02::1 ipv6-allnodes
ff02::2 ipv6-allrouters
ff02::3 ipv6-allhosts
BOOTPROTO='dhcp'
BRIDGE='yes'
BRIDGE_FORWARDDELAY='0'
BRIDGE_PORTS='eth0'
BRIDGE_STP='off'
BROADCAST=''
ETHTOOL_OPTIONS=''
IPADDR=''
MTU=''
NAME=''
NETMASK=''
NETWORK=''
REMOTE_IPADDR=''
STARTMODE='auto'
USERCONTROL='no'
[slapos]
software_root = /opt/slapgrid
instance_root = /srv/slapgrid
master_url = %(master_url)s
computer_id = %(computer_id)s
key_file = %(key_file)s
cert_file = %(cert_file)s
certificate_repository_path = %(certificate_repository_path)s
[slapformat]
computer_xml = /opt/slapos/slapos.xml
partition_amount = 200
bridge_name = br0
partition_base_name = slappart
user_base_name = slapuser
tap_base_name = slaptap
ipv4_local_network = 10.0.0.0/16
PermitRootLogin yes
AllowUsers root
AddressFamily inet6
RSAAuthentication yes
PubkeyAuthentication yes
#AuthorizedKeysFile %h/.ssh/authorized_keys
# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no
PasswordAuthentication no
X11Forwarding yes
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL
Subsystem sftp /usr/lib64/ssh/sftp-server
UsePAM yes
0.0.2 (unreleased)
------------------
0.0.1 (2010-10-22)
------------------
- working version
[Lukasz Nowak]
[egg_info]
tag_build = .dev
tag_svn_revision = 1
from setuptools import setup, find_packages
import os
name = "slapos.tool.cloudmgr"
version = '0.0.2'
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
long_description=(
read('README.txt')
+ '\n' +
read('CHANGES.txt')
)
setup(
name = name,
version = version,
author = 'Lukasz Nowak',
author_email = 'luke@nexedi.com',
description = "cloudmgr -- tools to manage clouds by using libcloud",
long_description=long_description,
license = "GPL",
keywords = "cloud libcloud manager",
classifiers=[
],
packages = find_packages('src'),
include_package_data = True,
package_dir = {'':'src'},
namespace_packages = [ 'slapos', 'slapos.tool' ],
install_requires = [
'setuptools', # namespaces
'paramiko',
'apache_libcloud>=0.4.0', #False name, 0.4.0 is not yet released on pypi
# and erpypi does not support names with "-"
],
url='https://svn.erp5.org/repos/vifib/trunk/utils/slapos.tool.cloudmgr/',
zip_safe=True,
entry_points = """
[console_scripts]
cloudmgr=slapos.tool.cloudmgr.cloudmgr:main
cloudlist=slapos.tool.cloudmgr.list:main
clouddestroy=slapos.tool.cloudmgr.destroy:main
cloudstart=slapos.tool.cloudmgr.start:main
cloudstop=slapos.tool.cloudmgr.stop:main
cloudgetprivatekey=slapos.tool.cloudmgr.getprivatekey:main
cloudgetpubliciplist=slapos.tool.cloudmgr.getpubliciplist:main
""" % dict(name=name),
)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
from update import update
from destroy import destroy
from start import start
from stop import stop
from list import uuidlist
from getpubliciplist import getpubliciplist
class NodeInterface:
def __init__(self, key, secret, service, location, node_uuid=None,
ssh_key=None):
self.key = key
self.location = location
self.node_uuid = node_uuid
self.ssh_key = ssh_key
self.secret = secret
self.service = service
def update(self, image, size, security_group):
result = update(self.key, self.secret, self.service, self.location,
self.node_uuid, self.ssh_key, image, size, security_group)
self.node_uuid = result['node_uuid']
self.ssh_key = result['ssh_key']
return result
def stop(self):
stop(self.key, self.secret, self.service, self.node_uuid, self.ssh_key)
def start(self):
start(self.key, self.secret, self.service, self.node_uuid)
def destroy(self):
destroy(self.key, self.secret, self.service, self.node_uuid)
def getPublicIpList(self):
return getpubliciplist(self.key, self.secret, self.service, self.node_uuid)
def getNodeUuidList(self):
return uuidlist(self.key, self.secret, self.service)
import sys
import time
from cloudinterface import NodeInterface
class CloudManager:
def __init__(self, configuration_file):
self.configuration_file = configuration_file
self.initialiseConfiguration()
def initialiseConfiguration(self):
self.configuration_dict = {}
try:
external_eval = file(self.configuration_file).read()
except IOError:
pass
else:
try:
self.configuration_dict = eval(external_eval)
except:
pass
if type(self.configuration_dict) != type({}):
self.configuration_dict = {}
for k in 'key', 'secret':
if k not in self.configuration_dict:
self.configuration_dict[k] = ''
elif type(self.configuration_dict[k]) != type(''):
self.configuration_dict[k] = ''
if 'node_list' not in self.configuration_dict:
self.configuration_dict['node_list'] = []
if type(self.configuration_dict['node_list']) != type([]):
self.configuration_dict['node_list'] = []
def run(self):
print 'Run begin...'
started = stopped = destroyed = unsupported = 0
self.key = self.configuration_dict['key']
self.secret = self.configuration_dict['secret']
for node in self.configuration_dict['node_list']:
node_object = NodeInterface(self.key, self.secret, node['service'],
node['location'], node['node_uuid'], node['ssh_key'])
if node['requested_state'] == 'started':
print 'Starting %r' % node['node_uuid']
if node_object.start():
started += 1
else:
unsupported += 1
elif node['requested_state'] == 'stopped':
print 'Stopping %r' % node['node_uuid']
if node_object.stop():
stopped += 1
else:
unsupported += 1
elif node['requested_state'] == 'destroyed':
print 'Destroying %r' % node['node_uuid']
if node_object.destroy():
destroyed +=1
else:
unsupported += 1
else:
print 'Unsupported state %r for node %r' % (node['requested_state'],
node['node_uuid'])
unsupported += 1
print 'Run finished', dict(started=started, stopped=stopped,
destroyed=destroyed, unsupported=unsupported)
def main():
while True:
CloudManager(sys.argv[1]).run()
time.sleep(5)
from slapos.tool.cloudmgr.lib import getDriverInstance, getNode
from libcloud.types import NodeState
import sys
def destroy(key, secret, service, node_uuid):
driver = getDriverInstance(service, key, secret)
node = getNode(driver, node_uuid)
if node is None:
return False
if node.state in [NodeState.RUNNING, NodeState.REBOOTING, NodeState.PENDING]:
return node.destroy()
else:
return False
def main():
print destroy(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
import sys
def getprivatekey(key, secret, service, node_uuid):
"""Fetches private key of node"""
raise NotImplementedError('Cedric implement')
return dict(
ssh_key = ssh_key,
)
def main():
getprivatekey(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
from slapos.tool.cloudmgr.lib import getDriverInstance, getNode
from libcloud.types import NodeState
import time
import sys
def getpubliciplist(key, secret, service, node_uuid):
"""Gets public ip(s), can wait for the first IP to appear"""
public_ip_list = []
for i in range(100):
driver = getDriverInstance(service, key, secret)
node = getNode(driver, node_uuid)
if node.state not in [NodeState.RUNNING, NodeState.REBOOTING,
NodeState.PENDING]:
break
if node.public_ip[0]:
public_ip_list = node.public_ip
break
else:
time.sleep(5)
return dict(
public_ip_list = public_ip_list
)
def main():
print getpubliciplist(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
from libcloud.types import Provider
from libcloud.providers import get_driver
import paramiko
import StringIO
driver_list = {
'DUMMY': get_driver(Provider.DUMMY),
'EC2_US_EAST': get_driver(Provider.EC2_US_EAST),
'EC2_US_WEST': get_driver(Provider.EC2_US_WEST),
'EC2_EU_WEST': get_driver(Provider.EC2_EU_WEST),
'RACKSPACE': get_driver(Provider.RACKSPACE),
'SLICEHOST': get_driver(Provider.SLICEHOST),
'GOGRID': get_driver(Provider.GOGRID),
'VPSNET': get_driver(Provider.VPSNET),
'LINODE': get_driver(Provider.LINODE),
'VCLOUD': get_driver(Provider.VCLOUD),
'RIMUHOSTING': get_driver(Provider.RIMUHOSTING),
'ECP': get_driver(Provider.ECP),
'IBM': get_driver(Provider.IBM),
'OPENNEBULA': get_driver(Provider.OPENNEBULA),
'DREAMHOST': get_driver(Provider.DREAMHOST),
}
def getDriverInstance(driverName, key, secret=None, secure=True, host=None,
port=None):
return driver_list.get(driverName)(key, secret, secure, host, port)
def getSSHConnection(driver, hostname, private_key):
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
#TODO if exception : try DSSKey
pkey = paramiko.RSAKey.from_private_key(StringIO.StringIO(private_key))
client.connect(hostname=hostname, username='root', pkey=pkey,
look_for_keys=False)
return client
def getNode(driver, node_uuid):
node_list = [node for node in driver.list_nodes() if node_uuid in node.uuid]
if len(node_list) == 0:
return None
if len(node_list) != 1:
raise IndexError('Several nodes with the uuid %r exist.' % node_uuid)
return node_list[0]
# Original work by Cedric de Saint Martin, adapted by Lukasz Nowak
import sys
from slapos.tool.cloudmgr.lib import getDriverInstance
def nodelist(key, secret, service):
driver = getDriverInstance(service, key, secret)
node_list = driver.list_nodes()
return node_list
def uuidlist(key, secret, service):
return [q.uuid for q in nodelist(key, secret, service)]
def main():
node_list = nodelist(*sys.argv[1:])
print 'Available nodes (%s):' % len(node_list)
for node in node_list:
print node
from slapos.tool.cloudmgr.lib import getDriverInstance, getNode
import sys
def start(key, secret, service, node_uuid):
"""Starts node"""
driver = getDriverInstance(service, key, secret)
node = getNode(driver, node_uuid)
if node is None:
return False
if node.state in [0, 1]:
return True
elif node.state == 3:
return node.reboot()
else:
return False
return True
def main():
print start(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
from getprivatekey import getprivatekey
from libcloud.types import NodeState
from slapos.tool.cloudmgr.lib import getDriverInstance, getSSHConnection, getNode
from paramiko import SSHException
import sys
def stop(key, secret, service, node_uuid, ssh_key=None):
"""Stops node"""
driver = getDriverInstance(service, key, secret)
node = getNode(driver, node_uuid)
# Checks state
if node.state not in [NodeState.RUNNING, NodeState.REBOOTING,
NodeState.PENDING]:
return False
# Good state : connects
if ssh_key is None:
ssh_key = getprivatekey(key, secret, service, node_uuid)
public_ip = node.public_ip[0]
if not public_ip:
raise Exception('Node is started but has no IP.')
try:
ssh = getSSHConnection(driver, public_ip, ssh_key)
print('Stopping instance...')
stdin, stdout, stderr = ssh.exec_command('halt')
except SSHException, e:
print('unable to stop')
raise e
error_log = stderr.read()
if error_log:
raise Exception('''Unable to stop : error log is :
%r
output is : %r''' % (error_log, stdout.read()))
return True
def main():
print stop(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
from slapos.tool.cloudmgr.lib import getDriverInstance
import sys
import uuid
from libcloud.types import NodeState
def update(key, secret, service, location, node_uuid=None, ssh_key=None,
image=None, size=None, security_group=None):
"""Update or create node"""
if node_uuid is not None:
driver = getDriverInstance(service, key, secret)
found_node_list = [node for node in driver.list_nodes() if node.uuid==node_uuid]
if len(found_node_list) == 0:
# node_uuid relates to not available one, recreate
node_uuid = None
elif len(found_node_list) == 1:
node = found_node_list[0]
if node.state not in [NodeState.RUNNING, NodeState.REBOOTING,
NodeState.PENDING]:
# node_uuid relates to destroyed one, recreate
node_uuid = None
if not node_uuid:
if not image or not size or not location:
raise Exception("Node can not be created because of lacking informations")
# XXX-Cedric : what exception?
# Creates node
return install(key, secret, service, image, size, location, security_group)
else:
return dict(
ssh_key = ssh_key,
node_uuid = node_uuid
)
def install(key, secret, service, image_id, size_id, location_id,
security_group):
driver = getDriverInstance(service, key, secret)
# Defines a dict that will be used to create our node(s)
argument_list = dict()
argument_list['image'] = [image for image in driver.list_images() if
image_id in image.id][0]
argument_list['size'] = [size for size in driver.list_sizes() if
size_id in size.id][0]
# We can create uour own images and sizes
#image = NodeImage(id=self.options['image_id'],
# name=self.options['image_name'],
# driver=driver)
#size = NodeSize(self.options['size_id'], self.options['size_name'], None,
# None, None, None, driver=driver)
argument_list['location'] = [location for location in
driver.list_locations() if location_id in location.id][0]
# If we are in ec2 : adding ssh key manually
if 'EC2' in service:
try:
unique_keyname = str(uuid.uuid1())
keypair = driver.ex_create_keypair(unique_keyname)
ssh_key = keypair['keyMaterial']
argument_list['ex_keyname'] = unique_keyname
except Exception, e:
# XX-Cedric : what to do here?
if e.args[0].find("InvalidKeyPair.Duplicate") == -1:
# XXX-Cedric : our unique key was not so unique...Do something
raise e
else:
raise e
# Prepares ssh key deployment and/or postflight script
# NOT IMPLEMENTED
#if self.options.get('ssh_key') or self.options.get('script'):
# deployment_argument_list = []
# if self.options.get('ssh_key'):
# deployment_argument_list.append(SSHKeyDeployment(
# self.options['ssh_key']))
# if self.options.get('script'):
# script_to_run = ScriptDeployment(self.options['script'])
# deployment_argument_list.append(script_to_run)
# argument_list['deploy'] = MultiStepDeployment(deployment_argument_list)
# If ec2, creates group, adds rules to it.
if 'EC2' in service:
try:
driver.ex_create_security_group(security_group, security_group)
except Exception, e:
if e.args[0].find("InvalidPermission.Duplicate") == -1:
pass #It's okay, don't worry.
driver.ex_authorize_security_group_permissive(security_group)
argument_list['ex_securitygroup'] = security_group
# Installs node
node = driver.create_node(**argument_list)#deploy_node(**argument_list)
node_uuid = node.uuid
return {'node_uuid': node_uuid, 'ssh_key': ssh_key}
def main():
try:
node_uuid = sys.argv[4]
except IndexError:
node_uuid = None
update(sys.argv[1], sys.argv[2], sys.argv[3], node_uuid)
0.0.6dev (unreleased)
---------------------
- Used psutil for evaluating cpu time
[Davide TAMMARO]
- New XML features
[Davide TAMMARO]
- New class for getting CPU informations
[Davide TAMMARO]
- New lib used ---> psutil
[Davide TAMMARO]
0.0.5 (2010-07-12)
------------------
- Invert - slap_monitor will run by subprocess.
[Lukasz Nowak]
0.0.4 (2010-07-12)
------------------
- Removed numpy as not needed.
[Lukasz Nowak]
0.0.3 (2010-07-12)
------------------
- Define dependencies.
[Lukasz Nowak]
0.0.2 (2010-07-12)
------------------
- Expose entry point accepting command line arguments.
[Lukasz Nowak]
0.0.1 (2010-07-05)
------------------
- Initial version.
[VILLETTE Charles]
slap.monitor
============
Monitoring for SLAP (Simple Language for Accounting and Provisioning) python library.
from setuptools import setup, find_packages
import os
name = "slapos.tool.monitor"
version = '0.0.6dev'
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
long_description=(
read('README.txt')
+ '\n' +
read('CHANGES.txt')
)
setup(
name = name,
version = version,
description = "Monitoring for SlapOS provided partitions",
long_description=long_description,
license = "GPLv3",
keywords = "slapos partition monitor",
classifiers=[
"Programming Language :: Python",
],
packages = find_packages('src'),
include_package_data = True,
package_dir = {'':'src'},
namespace_packages = [ 'slapos' ],
install_requires = [
'setuptools', # namespaces
'lxml',
'psutil',
],
zip_safe=True,
entry_points = """
[console_scripts]
slapmonitor = %(name)s.slapmonitor:run_slapmonitor
slapreport = %(name)s.slapmonitor:run_slapreport
""" % dict(name=name),
)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
##############################################################################
#
# Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import datetime
import os
import time
import resource
from time import strftime
import logging
import sys
from lxml import etree as ElementTree
import platform
import psutil
from optparse import OptionParser
import tempfile
import sqlite3.dbapi2 as sqlite3
#define global variable for log file
log_file = False
class MonitoringTool(object):
"""Provide functions to monitor CPU and Memory"""
def __init__(self):
pass
def get_cpu_and_memory_usage(self, proc):
"""Return CPU and Memory usage (percent) and
the specific moment used for the measure"""
return [proc.get_cpu_percent(), sum(proc.get_cpu_times()), proc.get_memory_percent(), proc.get_memory_info()[0], datetime.datetime.now()]
class GenerateXML(object):
"""Return a XML file upon request by reading from database"""
def __init__(self, element_tree, path_database, path_xml):
self.element_tree = element_tree
self.path_database = path_database
self.path_xml = path_xml
def dump_xml(self):
"""This func read data from database and through
_write_xml_output write result on xml file"""
consumption_infos = []
#This list hold the consuption infos in the following order
#[CPU % usage, CPU time usage (seconds), Memory % usage, Memory space usage (byte), date, time]
conn = sqlite3.connect(self.path_database)
cursor = conn.cursor()
cursor.execute("SELECT * FROM data")
for row in cursor:
consumption_infos.append(row)
consumption_summary = self._eval_consumption_summary (consumption_infos)
self._write_xml_output(consumption_summary, self.path_xml)
#Once we got infos we delete the table 'data'
cursor.execute("DELETE FROM data")
conn.commit()
cursor.close()
conn.close()
def _eval_consumption_summary(self, consumption_infos):
"""This function return a resources usage summary, for pricing purpose"""
cpu_percentage = []
memory_percentage = []
memory_space = []
#The total time that the cpu spent to work on it
cpu_time = consumption_infos[-1][1]
#start-end time and date
start_time = consumption_infos[0][5]
end_time = consumption_infos[-1][5]
start_date = consumption_infos[0][4]
end_date = consumption_infos[-1][4]
for item in consumption_infos:
cpu_percentage.append(item[0])
memory_percentage.append(item[2])
memory_space.append(item[3])
return [cpu_time, sum(memory_space) / float(len(memory_space)), end_date, end_time, end_time]
#return [scipy.mean(cpu_percentage), cpu_time, scipy.mean(memory_percentage),
# scipy.mean(memory_space), start_time, end_time, start_date, end_date]
def _write_xml_output(self, res_list, storage_path):
"""This function provide to dump on xml the consumption infos,
the res_list contains the following informations:
[CPU mean %, CPU whole usage (seconds), Memory mean %, Memory mean space usage (byte),
start_time, end_time, start_date, end_date]"""
#XXX- NOTE
"""The res_list has been recently changed, now it contains
[CPU whole usage (seconds), Memory mean space usage (byte)]"""
res_list = map(str, res_list)
cpu_list = ['Cpu consumption',
'Cpu consumption of the partition on %s at %s' % (res_list[2], res_list[3]),
res_list[0],
]
memory_list = ['Memory consumption',
'Memory consumption of the partition on %s at %s' % (res_list[2], res_list[3]),
res_list[1],
]
root = ElementTree.Element("consumption")
#Now we'll add two movement elements, one for cpu
tree = self._add_nodes(root, cpu_list )
tree.write(storage_path)
#one for memory
tree = self._add_nodes(root, memory_list)
tree.write(storage_path)
def _add_nodes(self, root, single_resource_list):
child_root = ElementTree.SubElement(root, "movement")
#child_root.set ('type', 'Sale Packing List')
child_data_start_date = ElementTree.SubElement(child_root, "resource")
child_data_start_date.text = single_resource_list[0]
child_data_end_date = ElementTree.SubElement(child_root, "title")
child_data_end_date.text = single_resource_list[1]
child_data_end_date = ElementTree.SubElement(child_root, "reference")
child_data_end_date.text = ''
child_data_end_date = ElementTree.SubElement(child_root, "quantity")
child_data_end_date.text = single_resource_list[2]
child_data_end_date = ElementTree.SubElement(child_root, "price")
child_data_end_date.text = ''
child_data_end_date = ElementTree.SubElement(child_root, "VAT")
child_data_end_date.text = ''
child_data_end_date = ElementTree.SubElement(child_root, "category")
child_data_end_date.text = ''
tree = self.element_tree.ElementTree(root)
return tree
def parse_opt():
usage="""usage: slapmonitor [options] PID_FILE_PATH DATABASE_PATH
Usage: slapreport [options] XML_PATH DATABASE_PATH """
parser = OptionParser(usage=usage)
parser.add_option('-t', '--update_time',type=int, dest='update_time', help='Specify the interval'\
'(in seconds) to check resources consumption [default 30 seconds]', default=3)
parser.add_option('-l', '--log_file', dest='path_log_file',help='Specify the logfile destination path',
metavar='FILE')
return parser
class SlapMonitor(object):
def __init__(self, proc, update_time, path_database):
self.proc = proc
self.update_time = update_time
self.path_database = path_database
self.start_monitor()
def start_monitor(self):
temporary_monitoring = MonitoringTool()
#check if the process is alive == None, instead zero value == proc is over
while self.proc.pid in psutil.get_pid_list():
conn = sqlite3.connect(self.path_database)
cursor = conn.cursor()
cursor.execute("create table if not exists data (cpu real, cpu_time real, memory real, rss real," \
"date text, time text)")
try:
res_list = temporary_monitoring.get_cpu_and_memory_usage(self.proc)
date_catched = "-".join([str(res_list[4].year), str(res_list[4].month), str(res_list[4].day)])
time_catched = ":".join([str(res_list[4].hour), str(res_list[4].minute), str(res_list[4].second)])
res_list[4] = date_catched
res_list.append(time_catched)
cursor.execute("insert into data values (?,?,?,?,?,?)" , res_list)
conn.commit()
cursor.close()
conn.close()
time.sleep(self.update_time)
except IOError:
if log_file:
logging.info("ERROR : process with pid : %s watched by slap monitor exited too quickly at %s"
% (self.proc.pid, strftime("%Y-%m-%d at %H:%m")))
sys.exit(1)
if log_file:
logging.info("EXIT 0: Process terminated normally!")
sys.exit(0)
def run_slapmonitor():
#This function require the pid file and the database path
parser = parse_opt()
opts, args = parser.parse_args()
if len(args) != 2:
parser.error("Incorrect number of arguments, 2 required but "+str(len(args))+" detected" )
if opts.path_log_file:
logging.basicConfig(filename=opts.path_log_file,level=logging.DEBUG)
global log_file
log_file = True
fed = open(args[0], 'r')
pid_read = fed.read()
fed.close()
proc = psutil.Process(int(pid_read))
SlapMonitor(proc, opts.update_time, args[1])
def run_slapreport():
#This function require the xml_path and database_path
parser = parse_opt()
opts, args = parser.parse_args()
if len(args) != 2:
parser.error("Incorrect number of arguments, 2 required but "+str(len(args))+" detected" )
if opts.path_log_file:
logging.basicConfig(filename=opts.path_log_file,level=logging.DEBUG)
global log_file
log_file = True
get_xml_hand = GenerateXML(ElementTree, args[1], args[0])
get_xml_hand.dump_xml()
0.0.2 (2011-04-14)
------------------
- Remove useless directory
[Romain Courteaud]
0.0.1 (2010-11-09)
------------------
- Add logging facility
- Add a secret key to validate upload
- Initial version.
[Romain Courteaud]
include CHANGES.txt
recursive-include src/slapos/tool/onetimeupload/templates *.html
recursive-include src/slapos/tool/onetimeupload/static *
onetimeupload
=============
onetimeupload is an HTTP application which only accepts one file to be
uploaded.
[egg_info]
tag_build = .dev
tag_svn_revision = 1
from setuptools import setup, find_packages
import os
name = "slapos.tool.onetimeupload"
version = '0.0.2'
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
long_description=(
read('README.txt')
+ '\n' +
read('CHANGES.txt')
)
setup(
name = name,
version = version,
description = "onetimeupload -- tools to upload a file",
long_description=long_description,
license = "GPLv3",
keywords = "upload web",
classifiers=[
"Programming Language :: Python",
],
packages = find_packages('src'),
include_package_data = True,
package_dir = {'':'src'},
namespace_packages = [ 'slapos', 'slapos.tool' ],
install_requires = [
'setuptools', # namespaces
'Flask',
],
url='https://svn.erp5.org/repos/vifib/trunk/utils/slapos.tool.onetimeupload/',
zip_safe=False,
entry_points = """
[console_scripts]
onetimeupload = slapos.tool.onetimeupload:main
""",
)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
##############################################################################
#
# Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import os
import sys
from flask import Flask, request, redirect
from optparse import OptionParser, Option
import logging
import logging.handlers
class Parser(OptionParser):
"""
Parse all arguments.
"""
def __init__(self, usage=None, version=None):
"""
Initialize all options possibles.
"""
OptionParser.__init__(self, usage=usage, version=version,
option_list=[
Option("-l", "--log_file",
help="The path of the log file",
type=str,
dest="log_file_path"),
])
def check_args(self):
"""
Check arguments
"""
(options, args) = self.parse_args()
if len(args) != 4:
self.error("Incorrect number of arguments")
host, port, upload_file, key = args
upload_file = os.path.abspath(upload_file)
return options, host, port, upload_file, key
class Config:
def setConfig(self, option_dict, host, port, upload_file, key):
"""
Set options given by parameters.
"""
# Set options parameters
for option, value in option_dict.__dict__.items():
setattr(self, option, value)
self.host = host
self.port = int(port)
self.upload_file = upload_file
self.key = key
def run(config):
app = Flask(__name__)
if config.log_file_path is not None:
file_handler = logging.handlers.RotatingFileHandler(
config.log_file_path, maxBytes=500000, backupCount=5)
file_handler.setLevel(logging.WARNING)
app.logger.addHandler(file_handler)
logging.getLogger('werkzeug').addHandler(file_handler)
@app.route('/', methods=['GET', 'POST'])
def upload_file():
if os.path.exists(config.upload_file):
template = app.open_resource('templates/done.html')
return template.read()
else:
if request.method == 'POST':
file = request.files['file']
key = "%s" % request.form.get('key')
if file and key:
if key == config.key:
file.save(config.upload_file)
return redirect('/')
template = app.open_resource('templates/index.html')
return template.read()
app.run(host=config.host, port=config.port, ssl_context='adhoc')
def main():
"Run default configuration."
usage = "usage: onetimeupload [options] HOST PORT UPLOAD_FILE KEY"
try:
# Parse arguments
config = Config()
config.setConfig(*Parser(usage=usage).check_args())
run(config)
return_code = 0
except SystemExit, err:
# Catch exception raise by optparse
return_code = err
sys.exit(return_code)
<!doctype html>
<title>File Uploaded</title>
<h1>File Uploaded</h1>
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form action="" method=post enctype=multipart/form-data>
<p>
<input type=file name=file><br/>
Secret Key <input type=text name=key><br/>
<input type=submit value=Upload>
</p>
</form>
recursive-include src/slapos/tool/runner/templates *.html
from setuptools import setup, find_packages
name = "slapos.tool.runner"
version = "1.0.dev-0"
def read(name):
return open(name).read()
long_description=( read('README.txt')
+ '\n' +
read('CHANGES.txt')
)
setup(
name=name,
version=version,
description="Web based runner for SlapOS",
classifiers=[
"Environment :: Web Environment",
"Intended Audience :: Developers",
"Intended Audience :: Education",
"Programming Language :: Python",
],
packages = find_packages('src'),
include_package_data = True,
package_dir = {'':'src'},
namespace_packages = ['slapos', 'slapos.tool'],
install_requires=[
'Flask', # based on Flask
'setuptools', # namespaces
'slapos.slap', # runner is using this to communicate with proxy
'xml_marshaller', # needed to dump information
],
entry_points = """
[console_scripts]
slaprunner = %(name)s:run
""" % dict(name=name),
)
[buildout]
extends = software.cfg
extensions +=
mr.developer
auto-checkout = *
[runner]
interpreter = python
[sources]
slapos.recipe.slaprunner = fs slapos.tool.slaprunner path=${buildout:directory}/recipe/slapos.recipe.slaprunner
import os
import shutil
def post_make_hook(options, buildout):
make_options_list = [q for q in options.get('make-options', '').split('\n') if q]
if os.system('make %s -f Makefile-libbz2_so' % ' '.join(make_options_list)) != 0:
raise ValueError('Generation of dynamic library failed')
original = 'libbz2.so.1.0.6'
link_list = ['libbz2.so.1.0', 'libbz2.so.1', 'libbz2.so']
destination = os.path.join(options['location'], 'lib')
for filename in [original] + link_list:
f = os.path.join(destination, filename)
if os.path.exists(f) or os.path.islink(f):
os.unlink(f)
shutil.copyfile(os.path.join(os.curdir, original), os.path.join(destination,
original))
for link in link_list:
os.symlink(original, os.path.join(destination,
link))
[buildout]
parts =
instance
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
[instance]
recipe = slapos.recipe.slaprunner
slaprunner = ${buildout:directory}/bin/slaprunner
slapgrid_sr = ${buildout:directory}/bin/slapgrid-sr
slapgrid_cp = ${buildout:directory}/bin/slapgrid-cp
slapproxy = ${buildout:directory}/bin/slapproxy
supervisor = ${buildout:directory}/bin/slapgrid-supervisor
--- Makefile.in 2002-10-08 16:09:12.000000000 +0000
+++ Makefile.in.nochange 2010-11-03 21:17:38.579435530 +0000
@@ -14,10 +14,6 @@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
-# File ownership and group
-BINOWN = bin
-BINGRP = bin
-
MAKEINFO = makeinfo
TEXI2DVI = texi2dvi
@@ -131,11 +127,11 @@
$(INSTALL_ROOT)$(includedir) $(INSTALL_ROOT)$(man3dir) \
$(INSTALL_ROOT)$(infodir)
$(LIBTOOL) $(INSTALL) -c libgdbm.la $(INSTALL_ROOT)$(libdir)/libgdbm.la
- $(INSTALL_DATA) -o $(BINOWN) -g $(BINGRP) gdbm.h \
+ $(INSTALL_DATA) gdbm.h \
$(INSTALL_ROOT)$(includedir)/gdbm.h
- $(INSTALL_DATA) -o $(BINOWN) -g $(BINGRP) $(srcdir)/gdbm.3 \
+ $(INSTALL_DATA) $(srcdir)/gdbm.3 \
$(INSTALL_ROOT)$(man3dir)/gdbm.3
- $(INSTALL_DATA) -o $(BINOWN) -g $(BINGRP) $(srcdir)/gdbm.info \
+ $(INSTALL_DATA) $(srcdir)/gdbm.info \
$(INSTALL_ROOT)$(infodir)/gdbm.info
install-compat:
@@ -143,9 +139,9 @@
$(INSTALL_ROOT)$(includedir)
$(LIBTOOL) $(INSTALL) -c libgdbm_compat.la \
$(INSTALL_ROOT)$(libdir)/libgdbm_compat.la
- $(INSTALL_DATA) -o $(BINOWN) -g $(BINGRP) $(srcdir)/dbm.h \
+ $(INSTALL_DATA) $(srcdir)/dbm.h \
$(INSTALL_ROOT)$(includedir)/dbm.h
- $(INSTALL_DATA) -o $(BINOWN) -g $(BINGRP) $(srcdir)/ndbm.h \
+ $(INSTALL_DATA) $(srcdir)/ndbm.h \
$(INSTALL_ROOT)$(includedir)/ndbm.h
#libgdbm.a: $(OBJS) gdbm.h
[buildout]
parts =
bzip2
[bzip2-hooks-download]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/../hook/bzip2.py
md5sum = 066c8355b7d726f30176ea5b6a35e1a2
download-only = true
filename = bzip2-hooks.py
[bzip2]
recipe = hexagonit.recipe.cmmi
url = http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz
md5sum = 00b516f4704d4a7cb50a1d97e6e8e15b
configure-command = true
make-options =
PREFIX=${buildout:parts-directory}/${:_buildout_section_name_}
CFLAGS="-fpic -fPIC -Wall -Winline -O2 -g -D_FILE_OFFSET_BITS=64"
post-make-hook = ${bzip2-hooks-download:location}/${bzip2-hooks-download:filename}:post_make_hook
[buildout]
parts =
gdbm
[gdbm-nochange-patch-download]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}../patch/gdbm-Makefile.in-nochange.patch
md5sum = fafa6cae0afbf2b5afb9ef3b8e3035a4
download-only = true
filename = gdbm-Makefile.in-nochange.patch
[gdbm]
recipe = hexagonit.recipe.cmmi
url = ftp://ftp.gnu.org/gnu/gdbm/gdbm-1.8.3.tar.gz
md5sum = 1d1b1d5c0245b1c00aff92da751e9aa1
patches = ${gdbm-nochange-patch-download:location}/${gdbm-nochange-patch-download:filename}
# install as parts/gdbm/include/gdbm/*.h etc. because some softwares
# (eg. python's dbmmodule.c extension) assume the location like this.
includedir = ${buildout:parts-directory}/${:_buildout_section_name_}/include
make-targets =
install install-compat includedir=${:includedir}/gdbm && rm -f ${:includedir}/*.h && ln -sf gdbm/gdbm.h ${:includedir}/gdbm.h
# it seems that parallel build sometimes fails for gdbm.
make-options =
-j1
[buildout]
parts =
gettext
extends =
ncurses.cfg
libxml2.cfg
zlib.cfg
[gettext]
recipe = hexagonit.recipe.cmmi
url = http://ftp.gnu.org/pub/gnu/gettext/gettext-0.18.1.1.tar.gz
md5sum = 3dd55b952826d2b32f51308f2f91aa89
configure-options =
--enable-shared
--disable-java
--disable-csharp
--with-libncurses-prefix=${ncurses:location}
--with-libxml2-prefix=${libxml2:location}
--with-included-gettext
--without-emacs
--disable-acl
--disable-openmp
environment =
CPPFLAGS=-I${libxml2:location}/include -I${zlib:location}/include -I${ncurses:location}/include
LDFLAGS=-L${libxml2:location}/lib -Wl,-rpath -Wl,${libxml2:location}/lib -L${zlib:location}/lib -Wl,-rpath -Wl,${zlib:location}/lib -L${ncurses:location}/lib -Wl,-rpath -Wl,${ncurses:location}/lib
[buildout]
extends =
gettext.cfg
zlib.cfg
[glib]
recipe = hexagonit.recipe.cmmi
url = http://ftp.gnome.org/pub/gnome/sources/glib/2.28/glib-2.28.6.tar.bz2
md5sum = 7d8fc15ae70d5111c0cf2a79d50ef717
configure-options =
--disable-selinux
--disable-fam
--disable-xattr
environment =
CPPFLAGS=-I${zlib:location}/include -I${gettext:location}/include
LDFLAGS=-L${zlib:location}/lib -Wl,-rpath -Wl,${zlib:location}/lib -L${gettext:location}/lib -Wl,-rpath -Wl,${gettext:location}/lib
PATH=${gettext:location}/bin:%(PATH)s
# libxml2 - the XML C parser and toolkit
# http://xmlsoft.org/
[buildout]
extends = zlib.cfg
parts =
libxml2
[libxml2]
recipe = hexagonit.recipe.cmmi
url = ftp://ftp.xmlsoft.org/libxml2/libxml2-2.7.8.tar.gz
md5sum = 8127a65e8c3b08856093099b52599c86
configure-options =
--without-python
--with-zlib=${zlib:location}
environment =
LDFLAGS = -Wl,-rpath -Wl,${zlib:location}/lib
[buildout]
extends =
libxml2.cfg
pkgconfig.cfg
zlib.cfg
parts =
libxslt
[libxslt]
url = ftp://xmlsoft.org/libxslt/libxslt-1.1.26.tar.gz
md5sum = e61d0364a30146aaa3001296f853b2b9
recipe = hexagonit.recipe.cmmi
configure-options =
--with-libxml-prefix=${libxml2:location}
--without-crypto
--without-python
environment =
PATH=${pkgconfig:location}/bin:%(PATH)s
CPPFLAGS=-I${zlib:location}/include
LDFLAGS=-Wl,-rpath -Wl,${zlib:location}/lib
PKG_CONFIG_PATH=${libxml2:location}/lib/pkgconfig:${zlib:location}/lib/pkgconfig
[buildout]
extends =
libxml2.cfg
libxslt.cfg
zlib.cfg
parts =
lxml-python
[lxml-python-env]
PATH = ${libxslt:location}/bin:%(PATH)s
[lxml-python]
recipe = zc.recipe.egg:custom
egg = lxml
rpath =
${libxml2:location}/lib/
${libxslt:location}/lib/
${zlib:location}/lib/
environment = lxml-python-env
[buildout]
parts =
ncurses
[ncurses]
recipe = hexagonit.recipe.cmmi
url = ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz
md5sum = 8cb9c412e5f2d96bc6f459aa8c6282a1
configure-options =
--prefix=${buildout:parts-directory}/${:_buildout_section_name_}
--with-shared
--with-normal
--without-debug
--enable-rpath
# tricky way to rerun with --enable-widec
make-targets =
install && (for i in curses unctrl eti form menu panel term; do ln -s ncurses/$i.h ${buildout:parts-directory}/${:_buildout_section_name_}/include/$i.h; done) && ./configure ${:configure-options} --enable-widec && make install
environment =
LDFLAGS =-Wl,--as-needed
# OpenSSL - a toolkit implementing SSL v2/v3 and TLS v1 protocols as
# well as a full-strength general purpose cryptography
# library.
# http://www.openssl.org/
[buildout]
extends =
zlib.cfg
parts =
openssl
[openssl]
recipe = hexagonit.recipe.cmmi
url = https://www.openssl.org/source/openssl-1.0.0d.tar.gz
md5sum = 40b6ea380cc8a5bf9734c2f8bf7e701e
configure-command = ./config
configure-options =
-I${zlib:location}/include
-L${zlib:location}/lib
--openssldir=${buildout:parts-directory}/${:_buildout_section_name_}/etc/ssl
--prefix=${buildout:parts-directory}/${:_buildout_section_name_}
--libdir=lib
shared
no-zlib
# it seems that parallel build sometimes fails for openssl.
make-options =
-j1
LDFLAGS="-Wl,-rpath -Wl,${zlib:location}/lib -Wl,-rpath -Wl,${buildout:parts-directory}/${:_buildout_section_name_}/lib"
SHARED_LDFLAGS="-Wl,-rpath -Wl,${zlib:location}/lib -Wl,-rpath -Wl,${buildout:parts-directory}/${:_buildout_section_name_}/lib"
# pkg-config - a helper tool used when compiling applications and libraries
# http://pkgconfig.freedesktop.org/
[buildout]
parts =
pkgconfig
extends =
gettext.cfg
glib.cfg
popt.cfg
[pkgconfig]
recipe = hexagonit.recipe.cmmi
url = http://pkgconfig.freedesktop.org/releases/pkg-config-0.25.tar.gz
md5sum = a3270bab3f4b69b7dc6dbdacbcae9745
location = ${buildout:parts-directory}/${:_buildout_section_name_}
# build pkg-config twice so that second configure can use pkg-config
# to compute GLIB_CFLAGS and GLIB_LIBS.
configure-command =
./configure --prefix=${:location} --with-installed-glib --with-installed-popt && make && make install && ./configure
configure-options =
--prefix=${:location}
--with-installed-glib
--with-installed-popt
environment =
PATH=${:location}/bin:%(PATH)s
PKG_CONFIG_PATH=${glib:location}/lib/pkgconfig
CPPFLAGS=-I${glib:location}/include -I${popt:location}/include
LDFLAGS=-L${gettext:location}/lib -Wl,-rpath -Wl,${gettext:location}/lib -L${glib:location}/lib -Wl,-rpath -Wl,${glib:location}/lib -L${popt:location}/lib -Wl,-rpath -Wl,${popt:location}/lib
[buildout]
parts =
popt
[popt]
recipe = hexagonit.recipe.cmmi
url = http://rpm5.org/files/popt/popt-1.16.tar.gz
md5sum = 3743beefa3dd6247a73f8f7a32c14c33
[buildout]
extends =
bzip2.cfg
gdbm.cfg
gettext.cfg
ncurses.cfg
openssl.cfg
readline.cfg
sqlite3.cfg
zlib.cfg
parts =
python2.7
[python2.7]
<= python2.7.1
[python2.7.0]
<= python2.7common
package_version = 2.7
md5sum = 35f56b092ecf39a6bd59d64f142aae0f
package_version_suffix =
[python2.7.1]
<= python2.7common
package_version = 2.7.1
md5sum = 15ed56733655e3fab785e49a7278d2fb
package_version_suffix =
[bootstrap2.7]
recipe = zc.recipe.egg
eggs = zc.buildout
suffix =
scripts =
buildout=bootstrap2.7
arguments = sys.argv[1:] + ["bootstrap"]
python = python2.7
[python2.7common]
recipe = hexagonit.recipe.cmmi
# This is actually the default setting for prefix, but we can't use it in
# other settings in this part if we don't set it explicitly here.
prefix = ${buildout:parts-directory}/${:_buildout_section_name_}
version = 2.7
executable = ${:prefix}/bin/python${:version}
url =
http://python.org/ftp/python/${:package_version}/Python-${:package_version}${:package_version_suffix}.tgz
configure-options =
--enable-unicode=ucs4
--with-threads
environment =
CPPFLAGS=-I${zlib:location}/include -I${readline:location}/include -I${ncurses:location}/include/ -I${ncurses:location}/include/ncursesw/ -I${bzip2:location}/include -I${gdbm:location}/include -I${openssl:location}/include -I${sqlite3:location}/include -I${gettext:location}/include
LDFLAGS=-L${zlib:location}/lib -L${readline:location}/lib -L${ncurses:location}/lib -L${bzip2:location}/lib -L${gdbm:location}/lib -L${openssl:location}/lib -L${sqlite3:location}/lib -Wl,-rpath -Wl,${zlib:location}/lib -Wl,-rpath -Wl,${readline:location}/lib -Wl,-rpath -Wl,${ncurses:location}/lib -Wl,-rpath -Wl,${bzip2:location}/lib -Wl,-rpath -Wl,${gdbm:location}/lib -Wl,-rpath -Wl,${openssl:location}/lib -Wl,-rpath -Wl,${sqlite3:location}/lib -L${gettext:location}/lib -Wl,-rpath -Wl,${gettext:location}/lib
[buildout]
parts =
readline
extends =
ncurses.cfg
[readline]
recipe = hexagonit.recipe.cmmi
url = http://ftp.gnu.org/gnu/readline/readline-6.1.tar.gz
md5sum = fc2f7e714fe792db1ce6ddc4c9fb4ef3
configure-options =
--with-ncurses=${ncurses:location}
environment =
LDFLAGS =-Wl,-rpath ${ncurses:location}/lib
[buildout]
extends = readline.cfg
parts =
sqlite3
[sqlite3]
recipe = hexagonit.recipe.cmmi
url = http://www.sqlite.org/sqlite-autoconf-3070500.tar.gz
md5sum = a9604a82613ade2e7f4c303f233e477f
configure-options =
--enable-readline
environment =
CPPFLAGS=-I${readline:location}/include -I${ncurses:location}/include
LDFLAGS=-L${buildout:parts-directory}/${:_buildout_section_name_} -Wl,-rpath -Wl,${readline:location}/lib -Wl,-rpath -Wl,${ncurses:location}/lib -L${readline:location}/lib -L${ncurses:location}/lib
[buildout]
parts =
zlib
[zlib]
recipe = hexagonit.recipe.cmmi
url = http://prdownloads.sourceforge.net/libpng/zlib-1.2.5.tar.gz?download
md5sum = c735eab2d659a96e5a594c9e8541ad63
Changelog
=========
1.2 (unreleased)
----------------
1.1 (2011-04-22)
----------------
include CHANGES.txt
recursive-include src/slapos/recipe/slaprunner/ *.in
from setuptools import setup, find_packages
name = "slapos.recipe.slaprunner"
version = '1.2-dev'
def read(name):
return open(name).read()
long_description = (read('README.txt') + '\n' + read('CHANGES.txt'))
setup(
name=name,
version=version,
description="ZC Buildout recipe for OSOE SlapOS training",
long_description=long_description,
license="GPLv3",
keywords="buildout slapos recipe runner",
classifiers=[
"Framework :: Buildout :: Recipe",
"Programming Language :: Python",
],
packages=find_packages('src'),
package_dir={'': 'src'},
include_package_data=True,
install_requires=[
'setuptools', # for namespacing
'slapos.lib.recipe', # uses internally
'zc.recipe.egg',
'zc.buildout', # it is recipe
],
namespace_packages=['slapos', 'slapos.recipe'],
entry_points={'zc.buildout': ['default = %s:Recipe' % name]},
)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
##############################################################################
#
# Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from slapos.lib.recipe.BaseSlapRecipe import BaseSlapRecipe
import os
import pkg_resources
import sys
import zc.buildout
import zc.recipe.egg
class Recipe(BaseSlapRecipe):
def __init__(self, buildout, name, options):
BaseSlapRecipe.__init__(self, buildout, name, options)
options['eggs'] = 'slapos.recipe.slaprunner'
self.egg = zc.recipe.egg.Scripts(buildout, name, options)
def _install(self):
self.path_list = []
self.requirements, self.ws = self.egg.working_set()
ipv4 = self.getLocalIPv4Address()
ipv6 = self.getGlobalIPv6Address()
proxy_port = '50000'
runner_port = '50000'
workdir = self.createDataDirectory('runner')
software_root = os.path.join(workdir, 'software')
instance_root = os.path.join(workdir, 'instance')
configuration = dict(
software_root=software_root,
instance_root=instance_root,
master_url='http://%s:%s/' % (ipv4, proxy_port),
computer_id='slaprunner',
partition_amount=2,
slapgrid_sr=self.options['slapgrid_sr'],
slapgrid_cp=self.options['slapgrid_cp'],
slapproxy=self.options['slapproxy'],
supervisor=self.options['supervisor'],
supervisord_config=os.path.join(instance_root, 'etc',
'supervisord.conf'),
runner_workdir=workdir,
runner_host=ipv6,
runner_port=runner_port,
ipv4_address=ipv4,
ipv6_address=ipv6,
proxy_host=ipv4,
proxy_port=proxy_port,
proxy_database=os.path.join(workdir, 'proxy.db')
)
config_file = self.createConfigurationFile('slapos.cfg',
self.substituteTemplate(pkg_resources.resource_filename(__name__,
'template/slapos.cfg.in'), configuration))
self.path_list.append(config_file)
self.path_list.extend(zc.buildout.easy_install.scripts([('slaprunner',
'slapos.recipe.slaprunner.execute', 'execute')], self.ws, sys.executable,
self.wrapper_directory, arguments=[self.options['slaprunner'].strip(),
config_file]))
self.setConnectionDict(dict(url='http://[%s]:%s' % (ipv6, runner_port)))
return self.path_list
import os
def execute(args):
"""Portable execution with process replacement"""
os.execv(args[0], args)
[slapos]
software_root = %(software_root)s
instance_root = %(instance_root)s
master_url = %(master_url)s
computer_id = %(computer_id)s
[slapformat]
partition_amount = %(partition_amount)s
[slaprunner]
slapgrid_sr = %(slapgrid_sr)s
slapgrid_cp = %(slapgrid_cp)s
slapproxy = %(slapproxy)s
supervisor = %(supervisor)s
supervisord_config = %(supervisord_config)s
runner_workdir = %(runner_workdir)s
runner_host = %(runner_host)s
runner_port = %(runner_port)s
ipv4_address = %(ipv4_address)s
ipv6_address = %(ipv6_address)s
[slapproxy]
host = %(proxy_host)s
port = %(proxy_port)s
database_uri = %(proxy_database)s
[buildout]
extends =
profile/python-2.7.cfg
profile/lxml-python.cfg
extensions =
slapos.tool.rebootstrap
parts =
runner
template
# Unzip, as Flask used by proxy can have a lot of troubles with zipped eggs
unzip = true
find-links +=
http://www.nexedi.org/static/packages/source/slapos.buildout/
versions = versions
[template]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance.cfg
output = ${buildout:directory}/template.cfg
mode = 0644
md5sum = 51ed347aafb12528382d0d0e2b324dd0
[rebootstrap]
version = 1
section = python2.7
[runner]
recipe = zc.recipe.egg
eggs =
${lxml-python:egg}
slapos.tool.grid
slapos.tool.proxy
slapos.tool.runner
slapos.recipe.slaprunner
[versions]
zc.buildout = 1.5.3-dev-SlapOS-001
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
from optparse import OptionParser, Option
import ConfigParser
import logging
import logging.handlers
import os
import sys
class Parser(OptionParser):
"""
Parse all arguments.
"""
def __init__(self, usage=None, version=None):
"""
Initialize all options possibles.
"""
OptionParser.__init__(self, usage=usage, version=version,
option_list=[
Option("-l", "--log_file",
help="The path to the log file used by the script.",
type=str),
Option("-v", "--verbose",
default=False,
action="store_true",
help="Verbose output."),
Option("-c", "--console",
default=False,
action="store_true",
help="Console output."),
Option("-d", "--debug",
default=False,
action="store_true",
help="Debug mode."),
])
def check_args(self):
"""
Check arguments
"""
(options, args) = self.parse_args()
if len(args) != 1:
self.error("Incorrect number of arguments")
return options, args[0]
class Config:
def setConfig(self, option_dict, configuration_file_path):
"""
Set options given by parameters.
"""
self.configuration_file_path = os.path.abspath(configuration_file_path)
# Set options parameters
for option, value in option_dict.__dict__.items():
setattr(self, option, value)
# Load configuration file
configuration_parser = ConfigParser.SafeConfigParser()
configuration_parser.read(configuration_file_path)
# Merges the arguments and configuration
for section in ("slaprunner", "slapos", "slapproxy", "slapformat"):
configuration_dict = dict(configuration_parser.items(section))
for key in configuration_dict:
if not getattr(self, key, None):
setattr(self, key, configuration_dict[key])
# set up logging
self.logger = logging.getLogger("slaprunner")
self.logger.setLevel(logging.INFO)
if self.console:
self.logger.addHandler(logging.StreamHandler())
if self.log_file:
if not os.path.isdir(os.path.dirname(self.log_file)):
# fallback to console only if directory for logs does not exists and
# continue to run
raise ValueError('Please create directory %r to store %r log file' % (
os.path.dirname(self.log_file), self.log_file))
else:
file_handler = logging.FileHandler(self.log_file)
file_handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
self.logger.addHandler(file_handler)
self.logger.info('Configured logging to file %r' % self.log_file)
self.logger.info("Started.")
if self.verbose:
self.logger.setLevel(logging.DEBUG)
self.logger.debug("Verbose mode enabled.")
def run():
"Run default configuration."
usage = "usage: %s [options] CONFIGURATION_FILE" % sys.argv[0]
try:
# Parse arguments
config = Config()
config.setConfig(*Parser(usage=usage).check_args())
serve(config)
return_code = 0
except SystemExit, err:
# Catch exception raise by optparse
return_code = err
sys.exit(return_code)
def serve(config):
from views import app
app.config.update(**config.__dict__)
app.config.update(
software_log=config.software_root.rstrip('/') + '.log',
instance_log=config.instance_root.rstrip('/') + '.log',
instance_profile=os.path.join(config.runner_workdir, 'instance.cfg'),
software_profile=os.path.join(config.runner_workdir, 'software.cfg'),
SECRET_KEY='123',
)
app.run(host=config.runner_host, port=int(config.runner_port),
debug=config.debug, threaded=True)
{% extends "layout.html" %}
{% block body %}
Welcome!<br>
This is SlapOS buildout web based runner.
{% endblock %}
{% extends "layout.html" %}
{% block body %}
Instance inspection<br>
Supervisor:<br>
<textarea cols=100 rows=10 readonly>{{ supervisor }}</textarea><br>
SLAP:<br>
{% for item in slap_status %}
<b>{{ item[0 ]}}</b><br>
<textarea cols=100 rows=5 readonly>{{ item[1] }}</textarea><br>
{% endfor %}
File content:<br>
<textarea cols=100 rows=40 readonly>{{ file_content }}</textarea><br>
{% endblock %}
<!doctype html>
<title>Buildout runner</title>
<div class=menu>
<a href="{{ url_for('home') }}">Home</a> |
Software:
<a href="{{ url_for('editSoftwareProfile') }}">Edit</a>
<a href="{{ url_for('runSoftwareProfile') }}">Run</a>
<a href="{{ url_for('viewSoftwareLog') }}">Build log</a>
<a href="{{ url_for('inspectSoftware') }}">Inspect</a>
<a href="{{ url_for('removeSoftware') }}">Remove</a>
|
Instance
<a href="{{ url_for('editInstanceProfile') }}">Edit</a>
<a href="{{ url_for('runInstanceProfile') }}">Run</a>
<a href="{{ url_for('viewInstanceLog') }}">Build log</a>
<a href="{{ url_for('inspectInstance') }}">Inspect</a>
<a href="{{ url_for('stopAllPartition') }}">Stop all</a>
<a href="{{ url_for('removeInstance') }}">Remove</a>
</div>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<div class=page>
{% block body %}{% endblock %}
</div>
{% extends "layout.html" %}
{% block body %}
Result for {{ type }}<br>
<textarea cols=100 rows=40 readonly>{{ result }}</textarea>
{% endblock %}
{% extends "layout.html" %}
{% block body %}
<form action="{{ url_for('updateInstanceProfile') }}" method=post class=add-entry>
<dl>
<dt>Instance Profile:
<dd><textarea name=content rows=20 cols=100>{{ profile }}</textarea>
<dd><input type=submit value=Update>
</dl>
</form>
{% endblock %}
{% extends "layout.html" %}
{% block body %}
<form action="{{ url_for('updateSoftwareProfile') }}" method=post class=add-entry>
<dl>
<dt>Note: Url of instance.cfg is <tt>{{ instance_url }}</tt>
<dt>Software Profile:
<dd><textarea name=content rows=20 cols=100>{{ profile }}</textarea>
<dd><input type=submit value=Update>
</dl>
</form>
{% endblock %}
{% extends "layout.html" %}
{% block body %}
Currently running: {{ running }}<br>
Notre: You can refresh this page from time to time to have updates.<br>
Result for {{ type }}<br>
<textarea cols=100 rows=40 readonly>{{ result }}</textarea>
{% endblock %}
import slapos.slap
import time
import subprocess
import os
from xml_marshaller import xml_marshaller
class Popen(subprocess.Popen):
def __init__(self, *args, **kwargs):
kwargs['stdin'] = subprocess.PIPE
kwargs['stderr'] = subprocess.STDOUT
kwargs.setdefault('stdout', subprocess.PIPE)
kwargs.setdefault('close_fds', True)
subprocess.Popen.__init__(self, *args, **kwargs)
self.stdin.flush()
self.stdin.close()
self.stdin = None
def updateProxy(config):
if not os.path.exists(config['instance_root']):
os.mkdir(config['instance_root'])
slap = slapos.slap.slap()
slap.initializeConnection(config['master_url'])
slap.registerSupply().supply(config['software_profile'], computer_guid=config['computer_id'])
computer = slap.registerComputer(config['computer_id'])
prefix = 'slappart'
slap_config = {
'address': config['ipv4_address'],
'instance_root': config['instance_root'],
'netmask': '255.255.255.255',
'partition_list': [
],
'reference': config['computer_id'],
'software_root': config['software_root']}
for i in xrange(0, int(config['partition_amount'])):
partition_reference = '%s%s' % (prefix, i)
partition_path = os.path.join(config['instance_root'], partition_reference)
if not os.path.exists(partition_path):
os.mkdir(partition_path)
os.chmod(partition_path, 0750)
slap_config['partition_list'].append({'address_list': [{'addr': config['ipv4_address'],
'netmask': '255.255.255.255'},
{'addr': config['ipv6_address'],
'netmask': 'ffff:ffff:ffff::'},
],
'path': partition_path,
'reference': partition_reference,
'tap': {'name': partition_reference},
})
computer.updateConfiguration(xml_marshaller.dumps(slap_config))
slap.registerOpenOrder().request(config['software_profile'],
partition_reference=partition_reference)
def readPid(file):
if os.path.exists(file):
data = open(file).read().strip()
try:
return int(data)
except Exception:
return 0
return 0
def writePid(file, pid):
open(file, 'w').write(str(pid))
def startProxy(config):
proxy_pid = os.path.join(config['runner_workdir'], 'proxy.pid')
pid = readPid(proxy_pid)
running = False
if pid:
try:
os.kill(pid, 0)
except Exception:
pass
else:
running = True
if not running:
proxy = Popen([config['slapproxy'], config['configuration_file_path']])
proxy_pid = os.path.join(config['runner_workdir'], 'proxy.pid')
writePid(proxy_pid, proxy.pid)
time.sleep(5)
def stopProxy(config):
pid = readPid(os.path.join(config['runner_workdir'], 'proxy.pid'))
if pid:
try:
os.kill(pid)
except:
pass
def removeProxyDb(config):
if os.path.exists(config['database_uri']):
os.unlink(config['database_uri'])
def isSoftwareRunning(config):
slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-sr.pid')
pid = readPid(slapgrid_pid)
if pid:
try:
os.kill(pid, 0)
except Exception:
running = False
else:
running = True
else:
running = False
return running
def runSoftwareWithLock(config):
slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-sr.pid')
if not isSoftwareRunning(config):
if not os.path.exists(config['software_root']):
os.mkdir(config['software_root'])
stopProxy(config)
removeProxyDb(config)
startProxy(config)
logfile = open(config['software_log'], 'w')
updateProxy(config)
slapgrid = Popen([config['slapgrid_sr'], '-vc', config['configuration_file_path']], stdout=logfile)
writePid(slapgrid_pid, slapgrid.pid)
slapgrid.wait()
return True
return False
def isInstanceRunning(config):
slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-cp.pid')
pid = readPid(slapgrid_pid)
if pid:
try:
os.kill(pid, 0)
except Exception:
running = False
else:
running = True
else:
running = False
return running
def runInstanceWithLock(config):
slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-cp.pid')
if not isInstanceRunning(config):
startProxy(config)
logfile = open(config['instance_log'], 'w')
updateProxy(config)
slapgrid = Popen([config['slapgrid_cp'], '-vc', config['configuration_file_path']], stdout=logfile)
writePid(slapgrid_pid, slapgrid.pid)
slapgrid.wait()
return True
return False
def getProfile(profile):
if os.path.exists(profile):
return open(profile).read()
else:
return ''
def getSlapStatus(config):
slap = slapos.slap.slap()
slap.initializeConnection(config['master_url'])
partition_list = []
computer = slap.registerComputer(config['computer_id'])
try:
for partition in computer.getComputerPartitionList():
# Note: Internal use of API, as there is no reflexion interface in SLAP
partition_list.append((partition.getId(), partition._connection_dict.copy()))
except Exception:
pass
return partition_list
def svcStopAll(config):
return Popen([config['supervisor'], '-c', config['supervisord_config'], 'shutdown']).communicate()[0]
def getSvcStatus(config):
return Popen([config['supervisor'], '-c', config['supervisord_config'], 'status']).communicate()[0]
from flask import Flask, request, redirect, url_for, \
render_template, flash
from utils import getProfile, runInstanceWithLock, runSoftwareWithLock, Popen, isInstanceRunning, isSoftwareRunning, getSvcStatus, getSlapStatus, svcStopAll
import os
import shutil
app = Flask(__name__)
# general views
@app.route('/')
def home():
return render_template('index.html')
# software views
@app.route('/editSoftwareProfile')
def editSoftwareProfile():
return render_template('updateSoftwareProfile.html',
profile=getProfile(app.config['software_profile']), instance_url=url_for('getInstance', _external=True))
@app.route('/software.cfg', methods=['GET', 'POST'])
def getSoftware():
return getProfile(app.config['software_profile'])
@app.route('/inspectSoftware', methods=['GET'])
def inspectSoftware():
if not os.path.exists(app.config['software_root']):
result = "Does not exists yet"
else:
process = Popen(['find'], cwd=app.config['software_root'])
result = process.communicate()[0]
return render_template('runResult.html', type='Software',
result=result)
@app.route('/removeSoftware')
def removeSoftware():
if isSoftwareRunning(app.config) or isInstanceRunning(app.config):
flash('Software installation or instantiation in progress, cannot remove')
elif os.path.exists(app.config['software_root']):
svcStopAll(app.config)
shutil.rmtree(app.config['software_root'])
flash('Software removed')
return redirect(url_for('inspectSoftware'))
@app.route('/runSoftwareProfile', methods=['GET'])
def runSoftwareProfile():
if runSoftwareWithLock(app.config):
flash('Started.')
else:
flash('Already running.')
return redirect(url_for('viewSoftwareLog'))
@app.route('/viewSoftwareLog', methods=['GET'])
def viewSoftwareLog():
if os.path.exists(app.config['software_log']):
result = open(app.config['software_log'], 'r').read()
else:
result = 'Not found yet'
return render_template('viewLog.html', type='Software',
result=result, running=isSoftwareRunning(app.config))
@app.route('/updateSoftwareProfile', methods=['POST'])
def updateSoftwareProfile():
open(app.config['software_profile'], 'w').write(request.form['content'])
return redirect(url_for('editSoftwareProfile'))
# instance views
@app.route('/editInstanceProfile')
def editInstanceProfile():
return render_template('updateInstanceProfile.html',
profile=getProfile(app.config['instance_profile']))
@app.route('/instance.cfg', methods=['GET', 'POST'])
def getInstance():
return getProfile(app.config['instance_profile'])
@app.route('/inspectInstance', methods=['GET'])
def inspectInstance():
file_content = 'Does not exists yet.'
if os.path.exists(app.config['instance_root']):
process = Popen(['find'], cwd=app.config['instance_root'])
file_content = process.communicate()[0]
return render_template('instanceInspect.html',
file_content=file_content, supervisor=getSvcStatus(app.config), slap_status=getSlapStatus(app.config))
@app.route('/removeInstance')
def removeInstance():
if isInstanceRunning(app.config):
flash('Instantiation in progress, cannot remove')
elif os.path.exists(app.config['instance_root']):
svcStopAll(app.config)
shutil.rmtree(app.config['instance_root'])
flash('Instance removed')
return redirect(url_for('inspectInstance'))
@app.route('/runInstanceProfile', methods=['GET'])
def runInstanceProfile():
if not os.path.exists(app.config['instance_root']):
os.mkdir(app.config['instance_root'])
if runInstanceWithLock(app.config):
flash('Started.')
else:
flash('Already running.')
return redirect(url_for('viewInstanceLog'))
@app.route('/viewInstanceLog', methods=['GET'])
def viewInstanceLog():
if os.path.exists(app.config['instance_log']):
result = open(app.config['instance_log'], 'r').read()
else:
result = 'Not found yet'
return render_template('viewLog.html', type='Instance',
result=result, running=isInstanceRunning(app.config))
@app.route('/updateInstanceProfile', methods=['POST'])
def updateInstanceProfile():
open(app.config['instance_profile'], 'w').write(request.form['content'])
return redirect(url_for('editInstanceProfile'))
@app.route('/stopAllPartition', methods=['GET'])
def stopAllPartition():
svcStopAll(app.config)
return redirect(url_for('inspectInstance'))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment