- add "appmgr" script for managing apps and versions (from Gabor Gombas)

svn path=/trunk/boinc/; revision=18938
This commit is contained in:
David Anderson 2009-08-28 18:25:26 +00:00
parent 16c2d5addc
commit 3f9f76f5c2
6 changed files with 1229 additions and 131 deletions

View File

@ -7275,3 +7275,15 @@ David 28 Aug 2009
cs_cmdline.cpp
lib/
proxy_info.cpp,h
David 28 Aug 2009
- add "appmgr" script for managing apps and versions (from Gabor Gombas)
doc/manpages/
appmgr.xml
Makefile.xm
py/Boinc/
setup_project.py
tools/
appmgr (new)
pymw_setup (removed)

View File

@ -13,16 +13,19 @@ if ENABLE_MANAGER
endif
if ENABLE_SERVER
SERVER_MANS =
SERVER_MANS = appmgr.8
endif
man_MANS = $(CLIENT_MANS) $(CLIENTGUI_MANS) $(SERVER_MANS)
SUFFIXES = .xml .1
SUFFIXES = .xml .1 .8
.xml.1:
$(DOCBOOK2X_MAN) $<
.xml.8:
$(DOCBOOK2X_MAN) $<
all-local: $(man_MANS)
CLEANFILES = $(man_MANS)

640
doc/manpages/appmgr.xml Normal file
View File

@ -0,0 +1,640 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
<!ENTITY appmgr "<command>appmgr</command>">
]>
<refentry>
<refentryinfo>
<author>
<firstname>Gábor</firstname>
<surname>Gombás</surname>
<email>gombasg@sztaki.hu</email>
</author>
<date>August 27, 2009</date>
</refentryinfo>
<refmeta>
<refentrytitle>&appmgr;</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>&appmgr;</refname>
<refpurpose>Tool to manage applications and platforms</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
&appmgr;
<arg choice="plain">list</arg>
<arg><option>--no-versions</option></arg>
</cmdsynopsis>
<cmdsynopsis>
&appmgr;
<arg choice="plain">add</arg>
<arg choice="plain"><replaceable>NAME</replaceable></arg>
<arg choice="plain"><replaceable>DESC</replaceable></arg>
<group>
<arg><option>--hr=no</option></arg>
<arg><option>--hr=fine</option></arg>
<arg><option>--hr=coarse</option></arg>
</group>
<arg><option>--beta</option></arg>
<arg><option>--weight=<replaceable>NUM</replaceable></option></arg>
<arg><option>--target_nresults=<replaceable>NUM</replaceable></option></arg>
</cmdsynopsis>
<cmdsynopsis>
&appmgr;
<arg choice="plain">delete</arg>
<arg choice="plain"><replaceable>NAME</replaceable></arg>
<arg><option>--version=<replaceable>VER</replaceable></option></arg>
<arg><option>--platform=<replaceable>NAME</replaceable></option></arg>
<arg><option>--plan_class=<replaceable>NAME</replaceable></option></arg>
</cmdsynopsis>
<cmdsynopsis>
&appmgr;
<arg choice="plain">update</arg>
<arg choice="plain"><replaceable>NAME</replaceable></arg>
<group>
<arg><option>--hr=no</option></arg>
<arg><option>--hr=fine</option></arg>
<arg><option>--hr=coarse</option></arg>
</group>
<group>
<arg><option>--beta</option></arg>
<arg><option>--no-beta</option></arg>
</group>
<arg><option>--weight=<replaceable>NUM</replaceable></option></arg>
<arg><option>--target_nresults=<replaceable>NUM</replaceable></option></arg>
<arg><option>--user_friendly_name=<replaceable>DESC</replaceable></option></arg>
<arg><option>--min_version=<replaceable>VER</replaceable></option></arg>
<group>
<arg><option>--deprecated</option></arg>
<arg><option>--no-deprecated</option></arg>
</group>
</cmdsynopsis>
<cmdsynopsis>
&appmgr;
<arg choice="plain">update_appver</arg>
<arg choice="plain"><replaceable>NAME</replaceable></arg>
<arg><option>--version=<replaceable>VER</replaceable></option></arg>
<arg><option>--platform=<replaceable>NAME</replaceable></option></arg>
<arg><option>--plan_class=<replaceable>NAME</replaceable></option></arg>
<group>
<arg><option>--deprecated</option></arg>
<arg><option>--no-deprecated</option></arg>
</group>
<arg><option>--min_core_version=<replaceable>VER</replaceable></option></arg>
<arg><option>--max_core_version=<replaceable>VER</replaceable></option></arg>
</cmdsynopsis>
<cmdsynopsis>
&appmgr;
<arg choice="plain">list_platform</arg>
<arg><option>--short</option></arg>
</cmdsynopsis>
<cmdsynopsis>
&appmgr;
<arg choice="plain">add_platform</arg>
<arg choice="plain"><replaceable>NAME</replaceable></arg>
<arg choice="plain"><replaceable>DESC</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
&appmgr;
<arg choice="plain">delete_platform</arg>
<arg choice="plain"><replaceable>NAME</replaceable></arg>
<arg><option>--force</option></arg>
</cmdsynopsis>
<cmdsynopsis>
&appmgr;
<arg choice="plain">update_platform</arg>
<arg choice="plain"><replaceable>NAME</replaceable></arg>
<arg><option>--user_friendly_name=<replaceable>DESC</replaceable></option></arg>
<group>
<arg><option>--deprecated</option></arg>
<arg><option>--no-deprecated</option></arg>
</group>
</cmdsynopsis>
<cmdsynopsis>
&appmgr;
<arg choice="plain">add_standard_platforms</arg>
</cmdsynopsis>
<cmdsynopsis>
&appmgr;
<group choice="req">
<arg choice="plain"><option>-h</option></arg>
<arg choice="plain"><option>--help</option></arg>
</group>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>
&appmgr; is a tool to manage platforms, applications and application
versions from the command-line.
</para>
<para>
Note: <firstterm>application</firstterm> refers to data in the
<literal>app</literal> table; <firstterm>application version</firstterm>
refers to data in the <literal>app_version</literal> table and in the
file system.
</para>
</refsect1>
<refsect1>
<title>COMMANDS</title>
<para>
The generic syntax is:
</para>
<para>
<cmdsynopsis>
&appmgr;
<arg choice="plain">COMMAND</arg>
<arg><replaceable>command arguments</replaceable></arg>
</cmdsynopsis>
</para>
<para>
Note that command-specific options must came after the command, never before.
Here is a short list of the available commands. The following sections describe
the commands in detail.
</para>
<variablelist>
<varlistentry>
<term>list</term>
<listitem>
<para>
List the installed applications and application versions.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>add</term>
<listitem>
<para>
Add a new application.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>delete</term>
<listitem>
<para>
Delete an application or application version.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>update</term>
<listitem>
<para>
Update the properties of an application.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>update_appver</term>
<listitem>
<para>
Update the properties of an application version.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>list_platform</term>
<listitem>
<para>
List the platforms known to the project.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>add_platform</term>
<listitem>
<para>
Add a new platform.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>delete_platform</term>
<listitem>
<para>
Delete a platform.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>update_platform</term>
<listitem>
<para>
Update the properties of a platform.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>add_standard_platforms</term>
<listitem>
<para>
Add all standard platforms to the project.
</para>
</listitem>
</varlistentry>
</variablelist>
<refsect2>
<title>LIST</title>
<para>
List the installed applications and application versions, together with
any non-default properties (beta, deprecated, min. core version etc.). If the
<option>--no-versions</option> option is specified, then the
list of application versions is omitted and just the application definitions
are listed.
</para>
</refsect2>
<refsect2>
<title>ADD</title>
<para>
Add a new application. <replaceable>NAME</replaceable> is
the short name of the application as used in the file system.
<replaceable>DESC</replaceable> is the user-friendly name that is
displayed to users.
</para>
<para>
The following options can also be specified:
</para>
<variablelist>
<varlistentry>
<term>
<option>--hr=no</option>,
<option>--hr=fine</option>,
<option>--hr=coarse</option>
</term>
<listitem>
<para>
Set the homogeneous redundancy class. <literal>no</literal> means
all hosts are equivalent, <literal>fine</literal> means
fine-grained classification of 80 classes,
<literal>coarse</literal> means coarse classification of 4
classes.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--beta</option>
</term>
<listitem>
<para>
Indicate that this is application is in beta testing. Users can select
if they are willing to test applications marked as beta in their
preferences; see the wiki section "Beta-test applications" about
how to enable this on the web interface.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--weight=<replaceable>NUM</replaceable></option>
</term>
<listitem>
<para>
Specify the weight of this application if the feeder is run with
the <option>-allapps</option> option. <replaceable>NUM</replaceable>
is a floating-point value, the default is 1.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--target_nresults=<replaceable>NUM</replaceable></option>
</term>
<listitem>
<para>
Set the number of replicas when an otherwise unreplicated work
unit is sent to a host that is not trusted. See the wiki section
"Adaptive replication" for details.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect2>
<refsect2>
<title>DELETE</title>
<para>
Delete applications or application versions. This command deletes both the
database records and the files under the <filename>download</filename> and
<filename>apps</filename> directories, so use with care.
</para>
<para>
The following options can be specified:
</para>
<variablelist>
<varlistentry>
<term>
<option>--version=<replaceable>VER</replaceable></option>
</term>
<listitem>
<para>
Select only application versions with the version number
<replaceable>VER</replaceable>.
The version number must be
specified as <literal>major.minor</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--platform=<replaceable>NAME</replaceable></option>
</term>
<listitem>
<para>
Select only application versions for the platform
<replaceable>NAME</replaceable>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--plan_class=<replaceable>NAME</replaceable></option>
</term>
<listitem>
<para>
Select only application versions having the plan class
<replaceable>NAME</replaceable>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
If more than one of the options <option>--version</option>,
<option>--platform</option> and <option>--plan_class</option> are
specified, then only application versions matching all the criteria
are deleted. If none of these options are specified, then the
application is also deleted. Note that if one or more of
these options are specified then the application is not
deleted even if there are no more application versions remaining.
</para>
</refsect2>
<refsect2>
<title>UPDATE</title>
<para>
Update the properties of an application. The following properties can
be modified:
</para>
<variablelist>
<varlistentry>
<term>
<option>--hr=no</option>,
<option>--hr=fine</option>,
<option>--hr=coarse</option>
</term>
<listitem>
<para>
Set the homogeneous redundancy class. <literal>no</literal> means
all hosts are equivalent, <literal>fine</literal> means
fine-grained classification of 80 classes,
<literal>coarse</literal> means coarse classification of 4
classes.
</para>
<warning>
Do not change the homogeneous redundancy class while there are jobs
in progress!
</warning>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--beta</option>
</term>
<listitem>
<para>
Indicate that this is application is in beta testing. Users can select
if they are willing to test applications marked as beta in their
preferences; see the wiki about how to enable this on the web interface.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--no-beta</option>
</term>
<listitem>
<para>
Indicate that the application is no more in beta testing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--weight=<replaceable>NUM</replaceable></option>
</term>
<listitem>
<para>
Specify the weight of this application if the feeder is run with
the <option>-allapps</option> option. <replaceable>NUM</replaceable>
is a floating-point value, the default is 1.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--target_nresults=<replaceable>NUM</replaceable></option>
</term>
<listitem>
<para>
Set the number of replicas when an otherwise unreplicated work
unit is sent to a host that is not trusted. See the wiki article
on "Adaptive replication" for details.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--user_friendly_name=<replaceable>DESC</replaceable></option>
</term>
<listitem>
<para>
Update the user-friendly description of the application.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--min_version=<replaceable>VER</replaceable></option>
</term>
<listitem>
<para>
Set the min. version of the application that the scheduler accepts.
This is checked only if the client uses the <literal>anonymous</literal>
platform.
The version number must be
specified as <literal>major.minor</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--deprecated</option>
</term>
<listitem>
<para>
Indicate that the application is deprecated. The feeder will then
ignore this application when looking for new work.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--no-deprecated</option>
</term>
<listitem>
<para>
Remove the deprecation mark from the application.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect2>
<refsect2>
<title>UPDATE_APPVER</title>
<para>
Update the properties of an application version. The version(s) to operate
on can be specified with the <option>--version</option>, <option>--platform</option>
and <option>--plan_class</option> options, as described at the <literal>DELETE</literal>
command.
</para>
<para>
The following properties can be modified:
</para>
<variablelist>
<varlistentry>
<term>
<option>--min_core_version=<replaceable>VER</replaceable></option>
</term>
<listitem>
<para>
Set the min. version of the core client that is required to run
this application version.
The version number must be specified as
<literal>major.minor</literal>. The 3rd component (the patch
level) of the core client version is ignored.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--max_core_version=<replaceable>VER</replaceable></option>
</term>
<listitem>
<para>
Set the max. version of the core client that is allowed to run
this application. Note that the scheduler ignores this setting currently.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--deprecated</option>
</term>
<listitem>
<para>
Indicate that the application version is deprecated. The feeder will then
ignore this version when looking for new work.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--no-deprecated</option>
</term>
<listitem>
<para>
Remove the deprecation mark from the application version.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect2>
<refsect2>
<title>LIST_PLATFORM</title>
<para>
List the platforms known to the project. If the <option>--short</option> option
is specified, then only the short names of the platforms are listed.
</para>
</refsect2>
<refsect2>
<title>ADD_PLATFORM</title>
<para>
Add a new platform. <replaceable>NAME</replaceable> is the short name
of the platform that is used in the scheduler requests.
<replaceable>DESC</replaceable> is the user-friendly name that is
displayed to users.
</para>
</refsect2>
<refsect2>
<title>DELETE_PLATFORM</title>
<para>
Delete a platform. If the <option>--force</option> option is specified, the
command deletes all application versions for this platform. Otherwise, if there
are such application versions, the command will fail.
</para>
</refsect2>
<refsect2>
<title>UPDATE_PLATFORM</title>
<para>
Update the properties of a platform. The following properties can be modified:
</para>
<variablelist>
<varlistentry>
<term>
<option>--user_friendly_name=<replaceable>DESC</replaceable></option>
</term>
<listitem>
<para>
Update the user-friendly description of the platform.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--deprecated</option>
</term>
<listitem>
<para>
Indicate that the platform is deprecated. The feeder will then
ignore this platform when looking for new work.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--no-deprecated</option>
</term>
<listitem>
<para>
Remove the deprecation mark from the platform.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect2>
<refsect2>
<title>ADD_STANDARD_PLATFORMS</title>
<para>
Add all the standard platform definitions to the database that do not
exist yet.
</para>
</refsect2>
</refsect1>
</refentry>

View File

@ -363,7 +363,7 @@ sys.path.insert(0, os.path.join('%s', 'py'))
'update_stats', 'db_dump', 'db_purge', 'show_shmem', 'census',
'delete_file', 'request_file_list', 'get_file', 'send_file' ])
map(lambda (s): install(srcdir('tools',s), dir('bin',s)),
[ 'create_work', 'xadd', 'dbcheck_files_exist', 'run_in_ops',
[ 'appmgr', 'create_work', 'xadd', 'dbcheck_files_exist', 'run_in_ops',
'update_versions', 'parse_config', 'grep_logs', 'db_query',
'watch_tcp', 'sign_executable', 'dir_hier_move',
'dir_hier_path' ])

571
tools/appmgr Executable file
View File

@ -0,0 +1,571 @@
#! /usr/bin/env python
#
# Written by Gabor Gombas <gombasg@sztaki.hu>
# Licensed under the same terms as the rest of BOINC.
"""
Manage applications and platforms from the command line.
Run "appmgr --help" to list the available commands.
Run "appmgr <command> --help" to get the description of a command.
"""
import time, os, re, string
from optparse import OptionParser
from xml.dom.minidom import parseString
import boinc_path_config
from Boinc import database, db_mid, configxml
# The list of standard platforms
standard_platforms = {
'windows_intelx86': 'Microsoft Windows (98 or later) running on an Intel x86-compatible CPU',
'windows_x86_64': 'Microsoft Windows running on an AMD x86_64 or Intel EM64T CPU',
'i686-pc-linux-gnu': 'Linux running on an Intel x86-compatible CPU',
'x86_64-pc-linux-gnu': 'Linux running on an AMD x86_64 or Intel EM64T CPU',
'powerpc-apple-darwin': 'Mac OS X 10.3 or later running on Motorola PowerPC',
'i686-apple-darwin': 'Mac OS 10.4 or later running on Intel',
'x86_64-apple-darwin': 'Intel 64-bit Mac OS 10.5 or later',
'sparc-sun-solaris2.7': 'Solaris 2.7 running on a SPARC-compatible CPU',
'sparc-sun-solaris': 'Solaris 2.8 or later running on a SPARC-compatible CPU',
'sparc64-sun-solaris': 'Solaris 2.8 or later running on a SPARC 64-bit CPU',
'powerpc64-ps3-linux-gnu': 'Sony Playstation 3 running Linux',
'anonymous': 'anonymous'}
def remove_directory(dir):
"""Remove a directory and all files inside it."""
for file in os.listdir(dir):
os.unlink(os.path.join(dir, file))
os.rmdir(dir)
def remove_app_directory(appver, config):
"""Remove files for an app version under <projectroot>/apps"""
appdir = os.path.join(config.app_dir, appver.app.name)
for path in map(lambda file: os.path.join(appdir, file), os.listdir(appdir)):
match = re.match('^[^.]+_([0-9]+)[.]([0-9]+)_([^.]+?(?:[0-9][0-9.]*[0-9])?)(?:__([^.])+)?(?:[.][a-zA-Z0-9\_\-]*)?$', os.path.basename(path))
if not match:
continue
major, minor, platform_name, plan_class = match.groups()
version_num = int(major) * 100 + int(minor)
if plan_class is None:
plan_class = ''
if platform_name != appver.platform.name:
continue
if appver.version_num != version_num:
continue
if appver.plan_class != plan_class:
continue
if os.path.isdir(path):
remove_directory(path)
else:
os.unlink(path)
# If all versions are gone, remove the parent directory as well
try:
os.rmdir(appdir)
except:
pass
def do_delete_app_version(appver):
"""Delete both the files and the database entry for an app version."""
config = configxml.default_config().config
# Remove files/directories under app_dir
appdir = os.path.join(config.app_dir, appver.app.name)
if os.path.isdir(appdir):
remove_app_directory(appver, config)
# Remove files under download_dir
# appver.xml_doc does not have a parent node, so we have to add one
xml = parseString('<xml>' + appver.xml_doc + '</xml>')
for file in xml.getElementsByTagName('file_info'):
name = ''
for node in file.getElementsByTagName('name')[0].childNodes:
if node.nodeType == node.TEXT_NODE:
name += node.data
if not name:
continue
os.unlink(os.path.join(config.download_dir, name))
tmp = str(appver)
appver.remove()
print "Removed " + tmp
def add_platform(args):
usage = """%prog add_platform <name> <user-friendly name>
Add a new platform definition to the database."""
parser = OptionParser(usage = usage)
options, extra_args = parser.parse_args(args)
if len(extra_args) != 2:
parser.error("Wrong number of arguments")
platform = database.Platform(create_time = time.time(),
name = extra_args[0],
user_friendly_name = extra_args[1],
deprecated = 0)
platform.commit()
print "Added " + str(platform)
def del_platform(args):
usage = """%prog delete_platform <name>
Deletes a platform from the database. If the --force flag is specified, it also
deletes all application versions for this platform. Otherwise, if there is an
application version available for this platform, the command will fail."""
parser = OptionParser(usage = usage)
parser.add_option("-f", "--force",
dest = "force",
action = "store_true",
default = False,
help = "remove any app versions that still exist for this platform")
options, extra_args = parser.parse_args(args)
if len(extra_args) != 1:
parser.error("Wrong number of arguments")
platforms = database.Platforms.find(name = extra_args[0])
if len(platforms) < 1:
raise SystemExit("Unknown platform name")
platform = platforms[0]
# If there are still application versions defined for this platform, then
# either bail out, or if --force was given, blow those application versions
# first
for appver in database.AppVersions.find(platform = platform):
if not options.force:
raise SystemExit("There are still application versions for this "
"platform, bailing out")
do_delete_app_version(appver)
# The id is gone after .remove(), so we have to save the stringified form
tmp = str(platform)
platform.remove()
print "Deleted " + tmp
def update_platform(args):
usage = """%prog update_platform <name> [options]
Update platform data."""
parser = OptionParser(usage = usage)
parser.add_option("--deprecated",
action = "store_const",
const = 1,
help = "mark the platform as deprecated")
parser.add_option("--no-deprecated",
dest = "deprecated",
action = "store_const",
const = 0,
help = "remove the deprecation mark")
parser.add_option("--user_friendly_name",
metavar = "DESC",
help = "set the user-friendly name of the platform")
options, extra_args = parser.parse_args(args)
if len(extra_args) != 1:
parser.error("Wrong number of arguments")
platforms = database.Platforms.find(name = extra_args[0])
if not platforms:
raise SystemExit("Unknown platform name")
platform = platforms[0]
if options.deprecated is not None:
platform.deprecated = options.deprecated
if options.user_friendly_name:
platform.user_friendly_name = options.user_friendly_name
platform.commit()
print "Updated " + str(platform)
def list_platform(args):
usage = """%prog list_platform
List all defined platforms."""
parser = OptionParser(usage = usage)
parser.add_option("--short",
action = "store_true",
help = "show the short names only")
options, extra_args = parser.parse_args(args)
if extra_args:
parser.error("Extra arguments on the command line")
# Ensure consistent ordering
database.Platforms.select_args = 'ORDER BY name'
for platform in database.Platforms.find():
if options.short:
print platform.name
else:
desc = platform.name + ": " + platform.user_friendly_name
if platform.deprecated:
desc += " (Deprecated)"
print desc
def add_standard_platforms(args):
usage = """%prog add_standard_platforms
Add all standard platform definitions to the database. If some of them
already exist they will not be modified."""
parser = OptionParser(usage = usage)
options, extra_args = parser.parse_args(args)
if extra_args:
parser.error("Extra arguments on the command line")
for name in standard_platforms.keys():
if database.Platforms.find(name = name):
continue
platform = database.Platform(create_time = time.time(),
name = name,
user_friendly_name = standard_platforms[name],
deprecated = 0)
platform.commit()
print "Added " + str(platform)
def add_app(args):
usage = """%prog add <name> <user-friendly name> [options]
Register a new application in the database."""
hr_types = { 'no': 0, 'fine': 1, 'coarse': 2}
parser = OptionParser(usage = usage)
parser.add_option("--hr",
choices = hr_types.keys(),
default = "no",
metavar = "(no|fine|coarse)",
help = "set the homogeneous redundancy type")
parser.add_option("--beta",
action = "store_const",
default = 0,
const = 1,
help = "the application is still in beta testing, and only "
"users participating in the test program will run it")
parser.add_option("--weight",
type = "float",
default = 1,
metavar = "NUM",
help = "set the weight of the application when application "
"interleaving is enabled in the feeder")
parser.add_option("--target_nresults",
type = "int",
default = 0,
metavar = "NUM",
help = "default number of replicas for adaptive replication")
options, extra_args = parser.parse_args(args)
if len(extra_args) != 2:
parser.error("Wrong number of arguments")
app = database.App(create_time = time.time(),
name = extra_args[0],
min_version = 0,
deprecated = 0,
user_friendly_name = extra_args[1],
homogeneous_redundancy = hr_types[options.hr],
weight = options.weight,
beta = options.beta,
target_nresults = options.target_nresults)
try:
app.commit()
except Exception, e:
print "Failed to add application"
return
print "Added " + str(app)
def del_app(args):
usage = """%prog delete <name> [options]
Delete application versions. This command deletes the matching database
entries and all corresponding files under <projectroot>/apps and
<projectroot>/download. If more than one of the --version, --platform and
--plan_class options are specified, they are AND'ed together. If no
version/platform/plan class options are given, all versions of the application
are deleted and the application is removed from the 'app' table as well."""
parser = OptionParser(usage = usage)
parser.add_option("--version",
type = "float",
metavar = "VER",
help = "delete versions with the given version number")
parser.add_option("--platform",
metavar = "NAME",
help = "delete versions for the given platform")
parser.add_option("--plan_class",
metavar = "NAME",
help = "delete versions for the given plan class")
options, extra_args = parser.parse_args(args)
if len(extra_args) != 1:
parser.error("Wrong number of arguments")
apps = database.Apps.find(name = extra_args[0])
if not apps:
raise SystemExit("No such application")
app = apps[0]
kwargs = { 'app': app }
if options.version:
kwargs['version_num'] = int(options.version * 100)
if options.platform:
platforms = database.Platforms.find(name = options.platform)
if not platforms:
raise SystemExit("Unknown platform name")
kwargs['platform'] = platforms[0]
if options.plan_class:
kwargs['plan_class'] = options.plan_class
for appver in database.AppVersions.find(**kwargs):
do_delete_app_version(appver)
# If the user requested to remove all versions, then remove the entry
# from the 'app' table as well
if not options.version and not options.platform and not options.plan_class:
tmp = str(app)
app.remove()
print "Removed " + tmp
def update_app(args):
usage = """%prog update <name> [options]
Update the properties of the given application."""
hr_types = { 'no': 0, 'fine': 1, 'coarse': 2}
parser = OptionParser(usage = usage)
parser.add_option("--hr",
choices = hr_types.keys(),
default = "no",
metavar = "(no|fine|coarse)",
help = "set the homogeneous redundancy type")
parser.add_option("--beta",
action = "store_const",
const = 1,
help = "the application is still in beta testing, and only "
"users participating in the test program will run it")
parser.add_option("--no-beta",
action = "store_const",
dest = "beta",
const = 0,
help = "the application is no more in beta testing")
parser.add_option("--weight",
type = "float",
metavar = "NUM",
help = "set the weight of the application when application "
"interleaving is enabled in the feeder")
parser.add_option("--target_nresults",
type = "int",
metavar = "NUM",
help = "default number of replicas for adaptive replication")
parser.add_option("--user_friendly_name",
metavar = "DESC",
help = "set the user-friendly description of the application")
parser.add_option("--min_version",
type = "float",
metavar = "VER",
help = "set the minimum app version clients allowed to use")
parser.add_option("--deprecated",
action = "store_const",
const = 1,
help = "mark the application as deprecated")
parser.add_option("--no-deprecated",
dest = "deprecated",
action = "store_const",
const = 0,
help = "remove the deprecation mark")
options, extra_args = parser.parse_args(args)
if len(extra_args) != 1:
parser.error("Wrong number of arguments")
apps = database.Apps.find(name = extra_args[0])
if not apps:
raise SystemExit("No such application")
app = apps[0]
if options.hr is not None:
app.homogeneous_redundancy = hr_types[options.hr]
if options.beta is not None:
app.beta = options.beta
if options.weight is not None:
app.weight = options.weight
if options.target_nresults is not None:
app.target_nresults = options.target_nresults
if options.user_friendly_name:
app.user_friendly_name = options.user_friendly_name
if options.min_version is not None:
app.min_version = int(options.min_version * 100)
if options.deprecated is not None:
app.deprecated = options.deprecated
app.commit()
print "Updated " + str(app)
def list_app(args):
usage = """%prog list
List all applications and application versions."""
parser = OptionParser(usage = usage)
parser.add_option("--no-versions",
action = "store_true",
default = False,
help = "do not list application versions")
options, extra_args = parser.parse_args(args)
if extra_args:
parser.error("Extra arguments on the command line")
# Ensure consistent ordering for the output
database.Apps.select_args = 'ORDER BY name'
# It would be nice to order by platform name...
database.AppVersions.select_args = 'ORDER BY version_num, platformid, plan_class'
hr_classes = {0: 'No', 1: 'Fine-grained', 2: 'Coarse'}
for app in database.Apps.find():
title = app.name + ": " + app.user_friendly_name
print title
print "-" * len(title)
props = []
if app.deprecated:
props.append("Deprecated.")
if app.beta:
props.append("Beta.")
if app.min_version:
props.append("Min. version: %.2f." % (float(app.min_version) / 100))
props.append(hr_classes[app.homogeneous_redundancy] +
' homogeneous redundancy.')
props.append("Weight %g." % app.weight)
if app.target_nresults:
props.append(str(app.target_nresults) + " adaptive replicas.")
print string.join(props, ' ')
if options.no_versions:
print
continue
print "Versions:\n"
for appver in database.AppVersions.find(app = app):
desc = "\t%5.2f" % (float(appver.version_num) / 100)
desc += " " + appver.platform.name
props = []
if appver.plan_class:
props.append("Plan: " + appver.plan_class + ".")
if appver.deprecated:
props.append("Deprecated.")
if appver.min_core_version:
props.append("Min. core version: %g." % \
(float(appver.min_core_version) / 100))
if appver.max_core_version:
props.append("Max. core version: %g." % \
(float(appver.max_core_version) / 100))
if props:
desc += " (" + string.join(props, ' ') + ')'
print desc
print
def update_appver(args):
usage = """%prog update_appver <name> [options]
Update the properties of the given application version(s). If none
of the --version, --platform, --plan_class options are specified,
then all versions for the given application are updated."""
parser = OptionParser(usage = usage)
parser.add_option("--version",
type = "float",
metavar = "VER",
help = "update just the given version number")
parser.add_option("--platform",
metavar = "NAME",
help = "update just the given platform")
parser.add_option("--plan_class",
metavar = "NAME",
help = "update just the given plan class")
parser.add_option("--min_core_version",
type = "float",
metavar = "VER",
help = "set the minimum usable core client version")
parser.add_option("--max_core_version",
type = "float",
metavar = "VER",
help = "set the maximum usable core client version")
parser.add_option("--deprecated",
action = "store_const",
const = 1,
help = "mark this version as deprecated")
parser.add_option("--no-deprecated",
dest = "deprecated",
action = "store_const",
const = 0,
help = "remove the deprecation mark")
options, extra_args = parser.parse_args(args)
if len(extra_args) != 1:
parser.error("Wrong number of arguments")
apps = database.Apps.find(name = extra_args[0])
if not apps:
raise SystemExit("No such application")
app = apps[0]
kwargs = { 'app': app }
if options.version:
kwargs['version_num'] = int(options.version * 100)
if options.platform:
platforms = database.Platforms.find(name = options.platform)
if not platforms:
raise SystemExit("Unknown platform name")
kwargs['platform'] = platforms[0]
if options.plan_class:
kwargs['plan_class'] = options.plan_class
for appver in database.AppVersions.find(**kwargs):
if options.deprecated is not None:
appver.deprecated = options.deprecated
if options.min_core_version is not None:
appver.min_core_version = int(options.min_core_version * 100)
if options.max_core_version is not None:
appver.max_core_version = int(options.max_core_version * 100)
appver.commit()
print "Updated " + str(appver)
command_table = {
'add': add_app,
'delete': del_app,
'update': update_app,
'list': list_app,
'update_appver': update_appver,
'add_platform': add_platform,
'delete_platform': del_platform,
'update_platform': update_platform,
'list_platform': list_platform,
'add_standard_platforms': add_standard_platforms}
usage = """%%prog [global options] <command> [command arguments]
Available commands:
%s
Use "%%prog <command> --help" to get a description of the command.""" % \
string.join(map(lambda x: "\t" + x, sorted(command_table.keys())), "\n")
parser = OptionParser(usage=usage)
parser.disable_interspersed_args()
global_options, args = parser.parse_args()
if not args:
parser.error("Command is not provided")
if not args[0] in command_table:
parser.error("Unknown command " + args[0])
database.connect()
command_table[args[0]](args[1:])

View File

@ -1,128 +0,0 @@
#!/usr/bin/env python
try:
import boinc_path_config
from Boinc import configxml, projectxml
except:
import configxml, projectxml
from optparse import OptionParser
import os, logging, sys, stat
LINUX_WORKER = """\
#!/bin/sh
`python $1 $2 $3`
`touch boinc_finish_called`
"""
WINDOWS_WORKER = """\
@echo off
set _path=%path%
set _python=%_path:*python=python%
set _python=%_python:~0,6%
if %_python% neq python set PATH=%path%;C:\python25
python %1 %2 %s3
type nul > boinc_finish_called
"""
PYMW_APP = """\
import sys
import cPickle
def pymw_get_input():
infile = open(sys.argv[1], 'r')
obj = cPickle.Unpickler(infile).load()
infile.close()
return obj
def pymw_return_output(output):
outfile = open(sys.argv[2], 'w')
cPickle.Pickler(outfile).dump(output)
outfile.close()
"""
FILE_REF = """\
<copy_file/>
"""
parser = OptionParser(usage="usage: %prog")
parser.add_option("-p", "--pymw_dir", dest="pymw_dir", default="", help="specify the working directory of pymw", metavar="<ABSOLUTE_PATH>")
options, args = parser.parse_args()
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
pymw_dir = options.pymw_dir
if pymw_dir == "":
logging.error("py_mw working directory have to be provided (-p switch)")
sys.exit(0)
elif not os.path.exists(pymw_dir):
logging.error(pymw_dir + " does not exist")
sys.exit(0)
logging.info("pymw working directory set to " + pymw_dir)
logging.info("writing pymw_assimilator in config.xml")
config = configxml.ConfigFile().read()
# Remove old instances of pymw_assimilator
for daemon in config.daemons:
if daemon.cmd[0:16] == 'pymw_assimilator':
config.daemons.remove_node(daemon)
# Append new instance of pymw_assimilator to config.xml
config.daemons.make_node_and_append("daemon").cmd = "pymw_assimilator -d 3 -app pymw -pymw_dir " + pymw_dir
config.write()
# Append new instance of pymw worker to project.xml
project = projectxml.ProjectFile().read()
found = False
for element in project.elements:
if element.name == 'pymw':
logging.info("PyMW client applications are already installed")
sys.exit(0)
project.elements.make_node_and_append("app").name = "pymw"
project.write()
for element in project.elements:
if element.name == "pymw":
element.user_friendly_name = "PyMW - Master Worker Computing in Python"
project.write()
# Install worker applications
app_dir = os.path.join(config.config.app_dir, "pymw")
print app_dir
if os.path.isdir(app_dir):
logging.info("PyMW client applications are already installed")
else:
os.mkdir(app_dir)
# Linux
logging.info("setting up client application for Linux platform")
linux_dir = os.path.join(app_dir, "pymw_1.00_i686-pc-linux-gnu")
linux_exe = os.path.join(linux_dir, "pymw_1.00_i686-pc-linux-gnu")
os.mkdir(linux_dir)
open(linux_exe, "w").writelines(LINUX_WORKER)
open(os.path.join(linux_dir, "pymw_1.00_i686-pc-linux-gnu.file_ref_info"), "w").writelines(FILE_REF)
open(os.path.join(linux_dir, "pymw_app.py"), "w").writelines(PYMW_APP)
open(os.path.join(linux_dir, "pymw_app.py.file_ref_info"), "w").writelines(FILE_REF)
os.chmod(linux_exe, stat.S_IRWXU)
logging.info("client application for Linux platform set up successfully")
# Windows
logging.info("setting up client application for Windows platform")
win_dir = os.path.join(app_dir, "pymw_1.00_windows_intelx86")
win_exe = os.path.join(win_dir, "pymw_1.00_windows_intelx86.exe")
os.mkdir(win_dir)
open(win_exe, "w").writelines(WINDOWS_WORKER)
open(os.path.join(win_dir, "pymw_1.00_windows_intelx86.exe.file_ref_info"), "w").writelines(FILE_REF)
open(os.path.join(win_dir, "pymw_app.py"), "w").writelines(PYMW_APP)
open(os.path.join(win_dir, "pymw_app.py.file_ref_info"), "w").writelines(FILE_REF)
os.chmod(win_exe, stat.S_IRWXU)
logging.info("client application for Windows platform set up successfully")
# Call update_versions
project_home = config.config.app_dir.rpartition('/')[0]
os.chdir(project_home)
os.system("xadd")
os.system("update_versions")
logging.info("---------------------")
logging.info("PyMW setup successful")
logging.info("---------------------")