From: Nicolas Turro Date: Fri, 25 Nov 2011 09:43:36 +0000 (+0100) Subject: Merge branch 'master' into senslab2 X-Git-Tag: sfa-2.1-24~3^2~269 X-Git-Url: http://git.onelab.eu/?p=sfa.git;a=commitdiff_plain;h=bb57cb30c7cfdddcf8e55fd7084e3cdaf67eaac4;hp=43a30d5e8fe5e5a0b9c70b2ec5232d853355e165 Merge branch 'master' into senslab2 --- diff --git a/INSTALL.txt b/INSTALL.txt index cc59cebd..b93abaef 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -30,8 +30,8 @@ These four configuration parameters are required for SFA server configuration set SFA_PLC_USER to PLC_ROOT_USER set SFA_PLC_PASSWORD to PLC_ROOT_PASSWORD - set SFA_PLC_DB_USER to PLC_DB_USER - set SFA_PLC_DB_PASSWORD to PLC_DB_PASSWORD + set SFA_DB_USER to PLC_DB_USER + set SFA_DB_PASSWORD to PLC_DB_PASSWORD write and quit *NOTE* at this point you get a warning b/c the authorities hierarchy has not been created yet; ignore diff --git a/config/default_config.xml b/config/default_config.xml index 670d6f26..10471bc3 100644 --- a/config/default_config.xml +++ b/config/default_config.xml @@ -18,14 +18,14 @@ Thierry Parmentelat Basic system variables. - - Generic Flavour - pl - This string refers to a class located in sfa.generic that describes - which specific implementation needs to be used for api, manager and driver objects. - PlanetLab users do not need to change this setting. - - + + Generic Flavour + pl + This string refers to a class located in sfa.generic that describes + which specific implementation needs to be used for api, manager and driver objects. + PlanetLab users do not need to change this setting. + + Human readable name @@ -33,6 +33,12 @@ Thierry Parmentelat The human readable name for this interface. + + Aggregate Manager API Version + 1 + The Aggregate API version + + Credential Schema /etc/sfa/credential.xsd @@ -109,6 +115,42 @@ Thierry Parmentelat + + + Slice Manager + The settings that affect the slice manager that will run + as part of this SFA instance. + + + + Enable Slice Manager + true + Allows this local SFA instance to run as a + slice manager. + + + + Slice Manager type + pl + The type of backend server for this + slice manager. Not all slice managers are myplc. + + + + Hostname + localhost + The hostname where the slice manager is expected to + be found. + + + + Port number + 12347 + The port where the slice manager is to be found. + + + + Aggregate @@ -153,38 +195,48 @@ Thierry Parmentelat - - Slice Manager - The settings that affect the slice manager that will run - as part of this SFA instance. + + + The settings that tell this SFA instance where to find its database. You can essentially leave this as-is unless you plan on hosting your data on some other box. - Enable Slice Manager + Enabled true - Allows this local SFA instance to run as a - slice manager. - - - - Slice Manager type - pl - The type of backend server for this - slice manager. Not all slice managers are myplc. + Enable the database server on this machine. - Hostname + Database host localhost - The hostname where the slice manager is expected to - be found. + The host where the SFA database can be reached. - Port number - 12347 - The port where the slice manager is to be found. + Database port + 5432 + The port where the SFA database can be reached. + + + + Database user + sfadbuser + When SFA gets co-hosted with a myplc, this should match the PLC config. + + + Database password + + When SFA gets co-hosted with a myplc, this should match the PLC config. + + + + Database name + sfa + SFA database name. + + + @@ -212,39 +264,11 @@ Thierry Parmentelat Full URL of PLC interface. - - Database name - planetlab5 - Planetlab database name. - - - - Datbase host - localhost - The host where the PLC database can be reached. - - - - Database port - 5432 - The port where the PLC database can be reached. - - - - Database user - pgsqluser - - - - - Database password - - The password for PLC_DB_USER. - - + + SFA Flash Policy The settings that affect the flash policy server that will run diff --git a/config/sfa-config-tty b/config/sfa-config-tty index 9b2c439e..9fef0f9c 100755 --- a/config/sfa-config-tty +++ b/config/sfa-config-tty @@ -18,12 +18,10 @@ usual_variables = [ "SFA_REGISTRY_HOST", "SFA_AGGREGATE_HOST", "SFA_SM_HOST", + "SFA_PLC_URL", "SFA_PLC_USER", "SFA_PLC_PASSWORD", - "SFA_PLC_DB_HOST", - "SFA_PLC_DB_USER", - "SFA_PLC_DB_PASSWORD", - "SFA_PLC_URL", + "SFA_DB_HOST", ] configuration={ \ diff --git a/flashpolicy/__init__.py b/flashpolicy/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/setup.py b/setup.py index c3285ebd..98d07a8c 100755 --- a/setup.py +++ b/setup.py @@ -53,7 +53,6 @@ package_dirs = [ 'sfatables', 'sfatables/commands', 'sfatables/processors', - 'flashpolicy', ] diff --git a/sfa.spec b/sfa.spec index 1fad71d4..57cebecc 100644 --- a/sfa.spec +++ b/sfa.spec @@ -1,6 +1,6 @@ %define name sfa %define version 1.1 -%define taglevel 4 +%define taglevel 5 %define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}} %global python_sitearch %( python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)" ) @@ -18,19 +18,28 @@ Vendor: PlanetLab Packager: PlanetLab Central Distribution: PlanetLab %{plrelease} URL: %{SCMURL} + Summary: the SFA python libraries Group: Applications/System - BuildRequires: make Requires: python >= 2.5 Requires: m2crypto Requires: xmlsec1-openssl-devel Requires: libxslt-python Requires: python-ZSI +# for uuidgen - used in db password generation +# on f8 this actually comes with e2fsprogs, go figure +Requires: util-linux-ng # xmlbuilder depends on lxml Requires: python-lxml Requires: python-setuptools Requires: python-dateutil +# for the registry +Requires: postgresql >= 8.2, postgresql-server >= 8.2 +Requires: postgresql-python +Requires: python-psycopg2 +Requires: pyOpenSSL >= 0.7 +Requires: myplc-config # python 2.5 has uuid module added, for python 2.4 we still need it. # we can't really check for if we can load uuid as a python module, @@ -45,19 +54,11 @@ Requires: python-dateutil #Requires: python-uuid #%endif -%package cm -Summary: the SFA layer around MyPLC NodeManager -Group: Applications/System -Requires: sfa -Requires: pyOpenSSL >= 0.6 - %package plc Summary: the SFA layer around MyPLC Group: Applications/System Requires: sfa Requires: python-psycopg2 -Requires: myplc-config -Requires: pyOpenSSL >= 0.7 %package client Summary: the SFA experimenter-side CLI @@ -70,6 +71,12 @@ Summary: sfatables policy tool for SFA Group: Applications/System Requires: sfa +%package cm +Summary: the SFA layer around MyPLC NodeManager +Group: Applications/System +Requires: sfa +Requires: pyOpenSSL >= 0.6 + %package flashpolicy Summary: SFA support for flash clients Group: Applications/System @@ -83,10 +90,6 @@ Requires: sfa %description This package provides the python libraries for the PlanetLab implementation of SFA -%description cm -This package implements the SFA interface which serves as a layer -between the existing PlanetLab NodeManager interfaces and the SFA API. - %description plc This package implements the SFA interface which serves as a layer between the existing PlanetLab interfaces and the SFA API. @@ -100,6 +103,10 @@ sfatables is a tool for defining access and admission control policies in an SFA network, in much the same way as iptables is for ip networks. This is the command line interface to manage sfatables +%description cm +This package implements the SFA interface which serves as a layer +between the existing PlanetLab NodeManager interfaces and the SFA API. + %description flashpolicy This package provides support for adobe flash client applications. @@ -115,29 +122,26 @@ make VERSIONTAG="%{version}-%{taglevel}" SCMURL="%{SCMURL}" %install rm -rf $RPM_BUILD_ROOT make VERSIONTAG="%{version}-%{taglevel}" SCMURL="%{SCMURL}" install DESTDIR="$RPM_BUILD_ROOT" +rm -rf $RPM_BUILD_ROOT/%{python_sitelib}/*egg-info %clean rm -rf $RPM_BUILD_ROOT %files -# sfa and sfatables depend each other. +# sfa and sfatables depend on each other. +%{python_sitelib}/sfa +%{python_sitelib}/xmlbuilder +/etc/init.d/sfa %{_bindir}/sfa-start.py* -/etc/sfatables/* -%{python_sitelib}/* %{_bindir}/keyconvert.py* +%{_bindir}/sfa-config-tty +%config /etc/sfa/default_config.xml +%config (noreplace) /etc/sfa/aggregates.xml +%config (noreplace) /etc/sfa/registries.xml /var/www/html/wsdl/*.wsdl -%files cm -/etc/init.d/sfa-cm -%{_bindir}/sfa_component_setup.py* -# cron jobs here - %files plc %defattr(-,root,root) -%config /etc/sfa/default_config.xml -%config (noreplace) /etc/sfa/aggregates.xml -%config (noreplace) /etc/sfa/registries.xml -/etc/init.d/sfa /etc/sfa/pl.rng /etc/sfa/credential.xsd /etc/sfa/top.xsd @@ -145,10 +149,9 @@ rm -rf $RPM_BUILD_ROOT /etc/sfa/xml.xsd /etc/sfa/protogeni-rspec-common.xsd /etc/sfa/topology -%{_bindir}/sfa-config-tty %{_bindir}/sfa-import-plc.py* -%{_bindir}/sfa-clean-peer-records.py* %{_bindir}/sfa-nuke-plc.py* +%{_bindir}/sfa-clean-peer-records.py* %{_bindir}/gen-sfa-cm-config.py* %{_bindir}/sfa-ca.py* @@ -161,7 +164,14 @@ rm -rf $RPM_BUILD_ROOT %{_bindir}/sfadump.py* %files sfatables +/etc/sfatables/* %{_bindir}/sfatables +%{python_sitelib}/sfatables + +%files cm +/etc/init.d/sfa-cm +%{_bindir}/sfa_component_setup.py* +# cron jobs here %files flashpolicy %{_bindir}/sfa_flashpolicy.py* @@ -197,6 +207,14 @@ fi [ "$1" -ge "1" ] && service sfa-cm restart || : %changelog +* Thu Nov 24 2011 Thierry Parmentelat - sfa-1.1-5 +- sfa should now be started *before* the initial import +- sfa to use its own database (default sfa) - can run without myplc +- server calls support optional 'options' +- client sends options in argument when needed +- fix infinite getattr recursion in elements/element.py +- error codes in line with geni + * Fri Nov 18 2011 Thierry Parmentelat - sfa-1.1-4 - fixed links and attributes in rspecs - minor cleanup in the API methods, and more consistent names in manager methods diff --git a/sfa/client/sfi.py b/sfa/client/sfi.py index fc6a7b48..9ed3c848 100755 --- a/sfa/client/sfi.py +++ b/sfa/client/sfi.py @@ -429,7 +429,7 @@ class Sfi: return version - def server_supports_call_id_arg(self, server): + def server_supports_options_arg(self, server): """ Returns true if server support the optional call_id arg, false otherwise. """ @@ -441,11 +441,11 @@ class Sfi: version_parts = code_tag_parts[0].split(".") major, minor = version_parts[0], version_parts[1] rev = code_tag_parts[1] - if int(major) > 1: - if int(minor) > 0 or int(rev) > 20: + if int(major) >= 1: + if int(minor) >= 2: return True return False - + # # Get various credential and spec files # @@ -929,8 +929,11 @@ class Sfi: delegated_cred = self.delegate_cred(user_cred, get_authority(self.authority)) creds.append(delegated_cred) server = self.server_proxy_from_opts(opts) - #results = server.ListSlices(creds, unique_call_id()) - results = server.ListSlices(creds) + call_args = [creds] + if self.server_supports_options_arg(server): + options = {'call_id': unique_call_id()} + call_args.append(options) + results = server.ListSlices(*call_args) display_list(results) return @@ -938,16 +941,19 @@ class Sfi: def resources(self, opts, args): user_cred = self.get_user_cred().save_to_string(save_parents=True) server = self.slicemgr - call_options = {} server = self.server_proxy_from_opts(opts) + + options = {'call_id': unique_call_id()} + #panos add info options + if opts.info: + options['info'] = opts.info if args: cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True) hrn = args[0] - call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')} + options['geni_slice_urn'] = hrn_to_urn(hrn, 'slice') else: cred = user_cred - hrn = None creds = [cred] if opts.delegate: @@ -958,18 +964,13 @@ class Sfi: server_version = self.get_cached_server_version(server) if 'sfa' in server_version: # just request the version the client wants - call_options['rspec_version'] = version_manager.get_version(opts.rspec_version).to_dict() + options['rspec_version'] = version_manager.get_version(opts.rspec_version).to_dict() else: # this must be a protogeni aggregate. We should request a v2 ad rspec # regardless of what the client user requested - call_options['rspec_version'] = version_manager.get_version('ProtoGENI 2').to_dict() - #panos add info options - if opts.info: - call_options['info'] = opts.info + options['rspec_version'] = version_manager.get_version('ProtoGENI 2').to_dict() - call_args = [creds, call_options] - if self.server_supports_call_id_arg(server): - call_args.append(unique_call_id()) + call_args = [creds, options] result = server.ListResources(*call_args) if opts.file is None: display_rspec(result, opts.format) @@ -1022,9 +1023,9 @@ class Sfi: if delegated_cred: creds.append(delegated_cred) call_args = [slice_urn, creds, rspec, users] - if self.server_supports_call_id_arg(server): - call_args.append(unique_call_id()) - + if self.server_supports_options_arg(server): + options = {'call_id': unique_call_id()} + call_args.append(options) result = server.CreateSliver(*call_args) if opts.file is None: print result @@ -1095,10 +1096,10 @@ class Sfi: delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) creds.append(delegated_cred) server = self.server_proxy_from_opts(opts) - call_args = [slice_urn, creds] - if self.server_supports_call_id_arg(server): - call_args.append(unique_call_id()) + if self.server_supports_options_arg(server): + options = {'call_id': unique_call_id()} + call_args.append(options) return server.DeleteSliver(*call_args) # start named slice @@ -1149,8 +1150,9 @@ class Sfi: time = args[1] call_args = [slice_urn, creds, time] - if self.server_supports_call_id_arg(server): - call_args.append(unique_call_id()) + if self.server_supports_options_arg(server): + options = {'call_id': unique_call_id()} + call_args.append(options) return server.RenewSliver(*call_args) @@ -1164,8 +1166,9 @@ class Sfi: creds.append(delegated_cred) server = self.server_proxy_from_opts(opts) call_args = [slice_urn, creds] - if self.server_supports_call_id_arg(server): - call_args.append(unique_call_id()) + if self.server_supports_options_arg(server): + options = {'call_id': unique_call_id()} + call_args.append(options) result = server.SliverStatus(*call_args) print result if opts.file: diff --git a/sfa/importer/sfa-import-plc.py b/sfa/importer/sfa-import-plc.py index 6873f48a..15a5bc6d 100755 --- a/sfa/importer/sfa-import-plc.py +++ b/sfa/importer/sfa-import-plc.py @@ -80,9 +80,7 @@ def main(): table.create() # create root authority - sfaImporter.create_top_level_auth_records(root_auth) - if not root_auth == interface_hrn: - sfaImporter.create_top_level_auth_records(interface_hrn) + sfaImporter.create_top_level_auth_records(interface_hrn) # create s user record for the slice manager sfaImporter.create_sm_client_record() diff --git a/sfa/importer/sfaImport.py b/sfa/importer/sfaImport.py index 4de6e1bd..568fce84 100644 --- a/sfa/importer/sfaImport.py +++ b/sfa/importer/sfaImport.py @@ -66,9 +66,8 @@ class sfaImport: def create_top_level_auth_records(self, hrn): """ - Create top level records (includes root and sub authorities (local/remote) + Create top level db records (includes root and sub authorities (local/remote) """ - urn = hrn_to_urn(hrn, 'authority') # make sure parent exists parent_hrn = get_authority(hrn) if not parent_hrn: @@ -76,11 +75,8 @@ class sfaImport: if not parent_hrn == hrn: self.create_top_level_auth_records(parent_hrn) - # create the authority if it doesnt already exist - if not self.AuthHierarchy.auth_exists(urn): - self.logger.info("Import: creating top level authorities") - self.AuthHierarchy.create_auth(urn) - + # enxure key and cert exists: + self.AuthHierarchy.create_top_level_auth(hrn) # create the db record if it doesnt already exist auth_info = self.AuthHierarchy.get_auth_info(hrn) table = SfaTable() diff --git a/sfa/init.d/sfa b/sfa/init.d/sfa index 08975dc7..7247339d 100755 --- a/sfa/init.d/sfa +++ b/sfa/init.d/sfa @@ -8,31 +8,73 @@ # description: Wraps PLCAPI into the SFA compliant API # -# Source config -[ -f /etc/sfa/sfa_config ] && . /etc/sfa/sfa_config - # source function library . /etc/init.d/functions -# Regenerate configuration files - almost verbatim from plc.init -reload () +# Default locations +PGDATA=/var/lib/pgsql/data +postgresql_conf=$PGDATA/postgresql.conf +pghba_conf=$PGDATA/pg_hba.conf +postgresql_sysconfig=/etc/sysconfig/pgsql + +# PLC consolidated (merged) config file +plc_whole_config=/etc/planetlab/plc_config.xml +# SFA consolidated (merged) config file +sfa_whole_config=/etc/sfa/sfa_config.xml +# SFA default config (read-only template) +sfa_default_config=/etc/sfa/default_config.xml +# SFA local (site-dependent) file +sfa_local_config=/etc/sfa/configs/site.xml + +# Source sfa shell config if present +[ -f /etc/sfa/sfa_config ] && . /etc/sfa/sfa_config + +# Export so that we do not have to specify -p to psql invocations +export PGPORT=$SFA_DB_PORT + +########## +# Total number of errors +ERRORS=0 + +# Count the exit status of the last command +check () { + ERRORS=$(($ERRORS+$?)) +} + +# can't trust the return of service postgresql start / nor status +function postgresql_check () { + + # wait until postmaster is up and running - or 10s max + if status postmaster >& /dev/null && [ -f /var/lock/subsys/postgresql ] ; then + # The only way we can be sure is if we can access it + for i in $(seq 1 10) ; do + # Must do this as the postgres user initially (before we + # fix pg_hba.conf to passwordless localhost access). + su -c 'psql -U postgres -c "" template1' postgres && return 0 + sleep 1 + done + fi + + return 1 +} + + +# Regenerate configuration files - almost verbatim from plc.init +function reload () { force=$1 # Regenerate the main configuration file from default values # overlaid with site-specific and current values. # Thierry -- 2007-07-05 : values in plc_config.xml are *not* taken into account here - files=( - /etc/sfa/default_config.xml - /etc/sfa/configs/site.xml - ) + files=( $sfa_default_config $sfa_local_config ) for file in "${files[@]}" ; do - if [ -n "$force" -o $file -nt /etc/sfa/sfa_config.xml ] ; then + if [ -n "$force" -o $file -nt $sfa_whole_config ] ; then tmp=$(mktemp /tmp/sfa_config.xml.XXXXXX) plc-config --xml "${files[@]}" >$tmp if [ $? -eq 0 ] ; then - mv $tmp /etc/sfa/sfa_config.xml - chmod 444 /etc/sfa/sfa_config.xml + mv $tmp $sfa_whole_config + chmod 444 $sfa_whole_config else echo "SFA: Warning: Invalid configuration file(s) detected" rm -f $tmp @@ -42,25 +84,162 @@ reload () done # Convert configuration to various formats - if [ -n "$force" -o /etc/sfa/sfa_config.xml -nt /etc/sfa/sfa_config ] ; then - plc-config --shell /etc/sfa/sfa_config.xml >/etc/sfa/sfa_config + if [ -n "$force" -o $sfa_whole_config -nt /etc/sfa/sfa_config ] ; then + plc-config --shell $sfa_whole_config >/etc/sfa/sfa_config fi - if [ -n "$force" -o /etc/sfa/sfa_config.xml -nt /etc/sfa/sfa_config.py ] ; then - plc-config --python /etc/sfa/sfa_config.xml >/etc/sfa/sfa_config.py + if [ -n "$force" -o $sfa_whole_config -nt /etc/sfa/sfa_config.py ] ; then + plc-config --python $sfa_whole_config >/etc/sfa/sfa_config.py fi -# if [ -n "$force" -o /etc/sfa/sfa_config.xml -nt /etc/sfa/php/sfa_config.php ] ; then +# if [ -n "$force" -o $sfa_whole_config -nt /etc/sfa/php/sfa_config.php ] ; then # mkdir -p /etc/sfa/php -# plc-config --php /etc/sfa/sfa_config.xml >/etc/sfa/php/sfa_config.php +# plc-config --php $sfa_whole_config >/etc/sfa/php/sfa_config.php # fi # [re]generate the sfa_component_config - gen-sfa-cm-config.py + # this is a server-side thing but produces a file that somehow needs to be pushed + # on the planetlab nodes; in the case where sfa and myplc run on different boxes + # (or there is no myplc at all) this should be turned off + # as the component manager is not operational yet we skip this for now + #gen-sfa-cm-config.py } -start() { +### initialize DB (don't chkconfig postgresql on) +function db_start () { + + # only if enabled + [ "$SFA_DB_ENABLED" == 1 ] || return + + if ! rpm -q myplc >& /dev/null; then + + ######## standalone deployment - no colocated myplc + + ######## sysconfig + # Set data directory and redirect startup output to /var/log/pgsql + mkdir -p $(dirname $postgresql_sysconfig) + # remove previous definitions + touch $postgresql_sysconfig + tmp=${postgresql_sysconfig}.new + ( egrep -v '^(PGDATA=|PGLOG=|PGPORT=)' $postgresql_sysconfig + echo "PGDATA=$PGDATA" + echo "PGLOG=/var/log/pgsql" + echo "PGPORT=$PLC_DB_PORT" + ) >> $tmp ; mv -f $tmp $postgresql_sysconfig + + ######## /var/lib/pgsql/data + # Fix ownership (rpm installation may have changed it) + chown -R -H postgres:postgres $(dirname $PGDATA) + + # PostgreSQL must be started at least once to bootstrap + # /var/lib/pgsql/data + if [ ! -f $postgresql_conf ] ; then + service postgresql initdb &> /dev/null || : + check + fi + + ######## /var/lib/pgsql/data/postgresql.conf + registry_ip="" + foo=$(python -c "import socket; print socket.gethostbyname(\"$SFA_REGISTRY_HOST\")") && registry_ip="$foo" + # Enable DB server. drop Postgresql<=7.x + # PostgreSQL >=8.0 defines listen_addresses + # listen on a specific IP + localhost, more robust when run within a vserver + sed -i -e '/^listen_addresses/d' $postgresql_conf + if [ -z "$registry_ip" ] ; then + echo "listen_addresses = 'localhost'" >> $postgresql_conf + else + echo "listen_addresses = '${registry_ip},localhost'" >> $postgresql_conf + fi + # tweak timezone to be 'UTC' + sed -i -e '/^timezone=/d' $postgresql_conf + echo "timezone='UTC'" >> $postgresql_conf + + ######## /var/lib/pgsql/data/pg_hba.conf + # Disable access to all DBs from all hosts + sed -i -e '/^\(host\|local\)/d' $pghba_conf + + # Enable passwordless localhost access + echo "local all all trust" >>$pghba_conf + # grant access + ( + echo "host $SFA_DB_NAME $SFA_DB_USER 127.0.0.1/32 password" + [ -n "$registry_ip" ] && echo "host $SFA_DB_NAME $SFA_DB_USER ${registry_ip}/32 password" + ) >>$pghba_conf + + # Fix ownership (sed -i changes it) + chown postgres:postgres $postgresql_conf $pghba_conf + + ######## compute a password if needed + if [ -z "$SFA_DB_PASSWORD" ] ; then + SFA_DB_PASSWORD=$(uuidgen) + plc-config --category=sfa_db --variable=password --value="$SFA_DB_PASSWORD" --save=$sfa_local_config $sfa_local_config + reload force + fi + + else + + ######## we are colocated with a myplc + # no need to worry about the pgsql setup (see /etc/plc.d/postgresql) + # myplc enforces the password for its user + PLC_DB_USER=$(plc-config --category=plc_db --variable=user) + PLC_DB_PASSWORD=$(plc-config --category=plc_db --variable=password) + # store this as the SFA user/password + plc-config --category=sfa_db --variable=user --value=$PLC_DB_USER --save=$sfa_local_config $sfa_local_config + plc-config --category=sfa_db --variable=password --value=$PLC_DB_PASSWORD --save=$sfa_local_config $sfa_local_config + reload force + fi + + ######## Start up the server + # not too nice, but.. when co-located with myplc we'll let it start/stop postgresql + if ! rpm -q myplc >& /dev/null ; then + echo STARTING... + service postgresql start >& /dev/null + fi + postgresql_check + check + + ######## make sure we have the user and db created + # user + if ! psql -U $SFA_DB_USER -c "" template1 >/dev/null 2>&1 ; then + psql -U postgres -c "CREATE USER $SFA_DB_USER PASSWORD '$SFA_DB_PASSWORD'" template1 + else + psql -U postgres -c "ALTER USER $SFA_DB_USER WITH PASSWORD '$SFA_DB_PASSWORD'" template1 + fi + check + + # db + if ! psql -U $SFA_DB_USER -c "" $SFA_DB_NAME >/dev/null 2>&1 ; then + createdb -U postgres --template=template0 --encoding=UNICODE --owner=$SFA_DB_USER $SFA_DB_NAME + # xxx in case we'd like to ship the db schema separately + #psql -U $SFA_DB_USER -f /etc/sfa/or/someplace/else/sfa.sql $SFA_DB_NAME + fi + check + + MESSAGE=$"Checking for PostgreSQL server" + echo -n "$MESSAGE" + [ "$ERRORS" == 0 ] && success "$MESSAGE" || failure "$MESSAGE" ; echo +} + +# shutdown DB +function db_stop () { + + # only if enabled + [ "$SFA_DB_ENABLED" == 1 ] || return + + # not too nice, but.. when co-located with myplc we'll let it start/stop postgresql + if ! rpm -q myplc >& /dev/null ; then + service postgresql stop >& /dev/null + check + MESSAGE=$"Stopping PostgreSQL server" + echo -n "$MESSAGE" + [ "$ERRORS" == 0 ] && success "$MESSAGE" || failure "$MESSAGE" ; echo + fi +} + +function start() { reload + db_start + # install peer certs action $"SFA installing peer certs" daemon /usr/bin/sfa-start.py -t -d $OPTIONS @@ -80,16 +259,16 @@ start() { action "Flash Policy Server" daemon /usr/bin/sfa_flashpolicy.py --file="$SFA_FLASHPOLICY_CONFIG_FILE" --port=$SFA_FLASHPOLICY_PORT -d fi - RETVAL=$? - [ $RETVAL -eq 0 ] && touch /var/lock/subsys/sfa-start.py + touch /var/lock/subsys/sfa-start.py } -stop() { +function stop() { action $"Shutting down SFA" killproc sfa-start.py - RETVAL=$? - [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sfa-start.py + db_stop + + rm -f /var/lock/subsys/sfa-start.py } diff --git a/sfa/managers/aggregate_manager.py b/sfa/managers/aggregate_manager.py index 1b069f7a..56d60086 100644 --- a/sfa/managers/aggregate_manager.py +++ b/sfa/managers/aggregate_manager.py @@ -28,7 +28,7 @@ class AggregateManager: #self.caching=True self.caching=False - def GetVersion(self, api): + def GetVersion(self, api, options={}): version_manager = VersionManager() ad_rspec_versions = [] @@ -38,14 +38,14 @@ class AggregateManager: ad_rspec_versions.append(rspec_version.to_dict()) if rspec_version.content_type in ['*', 'request']: request_rspec_versions.append(rspec_version.to_dict()) - default_rspec_version = version_manager.get_version("sfa 1").to_dict() xrn=Xrn(api.hrn) version_more = {'interface':'aggregate', + 'sfa': 1, + 'geni_api': api.config.SFA_AGGREGATE_API_VERSION, 'testbed':'myplc', 'hrn':xrn.get_hrn(), - 'request_rspec_versions': request_rspec_versions, - 'ad_rspec_versions': ad_rspec_versions, - 'default_ad_rspec': default_rspec_version + 'geni_request_rspec_versions': request_rspec_versions, + 'geni_ad_rspec_versions': ad_rspec_versions, } return version_core(version_more) @@ -108,7 +108,8 @@ class AggregateManager: return reg_objects - def SliverStatus(self, api, slice_xrn, creds, call_id): + def SliverStatus(self, api, slice_xrn, creds, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return {} (hrn, _) = urn_to_hrn(slice_xrn) @@ -158,11 +159,12 @@ class AggregateManager: result['geni_resources'] = resources return result - def CreateSliver(self, api, slice_xrn, creds, rspec_string, users, call_id): + def CreateSliver(self, api, slice_xrn, creds, rspec_string, users, options={}): """ Create the sliver[s] (slice) at this aggregate. Verify HRN and initialize the slice record in PLC if necessary. """ + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" aggregate = Aggregate(api) @@ -201,7 +203,8 @@ class AggregateManager: return aggregate.get_rspec(slice_xrn=slice_xrn, version=rspec.version) - def RenewSliver(self, api, xrn, creds, expiration_time, call_id): + def RenewSliver(self, api, xrn, creds, expiration_time, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return True (hrn, _) = urn_to_hrn(xrn) slicename = hrn_to_pl_slicename(hrn) @@ -250,7 +253,8 @@ class AggregateManager: # XX not implemented at this interface return 1 - def DeleteSliver(self, api, xrn, creds, call_id): + def DeleteSliver(self, api, xrn, creds, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" (hrn, _) = urn_to_hrn(xrn) slicename = hrn_to_pl_slicename(hrn) @@ -270,7 +274,8 @@ class AggregateManager: api.driver.BindObjectToPeer('slice', slice['slice_id'], peer, slice['peer_slice_id']) return 1 - def ListSlices(self, api, creds, call_id): + def ListSlices(self, api, creds, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return [] # look in cache first if self.caching and api.cache: @@ -289,10 +294,12 @@ class AggregateManager: return slice_urns - def ListResources(self, api, creds, options, call_id): + def ListResources(self, api, creds, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" # get slice's hrn from options xrn = options.get('geni_slice_urn', None) + cached = options.get('cached', True) (hrn, _) = urn_to_hrn(xrn) version_manager = VersionManager() @@ -305,7 +312,7 @@ class AggregateManager: version_string = version_string + "_"+options.get('info', 'default') # look in cache first - if self.caching and api.cache and not xrn: + if self.caching and api.cache and not xrn and cached: rspec = api.cache.get(version_string) if rspec: api.logger.info("aggregate.ListResources: returning cached value for hrn %s"%hrn) @@ -313,8 +320,8 @@ class AggregateManager: #panos: passing user-defined options #print "manager options = ",options - aggregate = Aggregate(api, options) - rspec = aggregate.get_rspec(slice_xrn=xrn, version=rspec_version) + aggregate = Aggregate(api) + rspec = aggregate.get_rspec(slice_xrn=xrn, version=rspec_version, options=options) # cache the result if self.caching and api.cache and not xrn: @@ -323,7 +330,7 @@ class AggregateManager: return rspec - def GetTicket(self, api, xrn, creds, rspec, users): + def GetTicket(self, api, xrn, creds, rspec, users, options={}): (slice_hrn, _) = urn_to_hrn(xrn) slices = Slices(api) diff --git a/sfa/managers/aggregate_manager_eucalyptus.py b/sfa/managers/aggregate_manager_eucalyptus.py index 3f2d512c..55e14ce6 100644 --- a/sfa/managers/aggregate_manager_eucalyptus.py +++ b/sfa/managers/aggregate_manager_eucalyptus.py @@ -444,7 +444,8 @@ class AggregateManagerEucalyptus: port=eucaPort, path=srvPath) - def ListResources(api, creds, options, call_id): + def ListResources(api, creds, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" # get slice's hrn from options xrn = options.get('geni_slice_urn', '') @@ -540,7 +541,8 @@ class AggregateManagerEucalyptus: """ Hook called via 'sfi.py create' """ - def CreateSliver(api, slice_xrn, creds, xml, users, call_id): + def CreateSliver(api, slice_xrn, creds, xml, users, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" logger = logging.getLogger('EucaAggregate') @@ -677,7 +679,7 @@ class AggregateManagerEucalyptus: f.write("%s %s %s\n" % (instId, ipaddr, hrn)) f.close() - def GetVersion(api): + def GetVersion(api, options={}): version_manager = VersionManager() ad_rspec_versions = [] @@ -687,13 +689,13 @@ class AggregateManagerEucalyptus: ad_rspec_versions.append(rspec_version.to_dict()) if rspec_version.content_type in ['*', 'request']: request_rspec_versions.append(rspec_version.to_dict()) - default_rspec_version = version_manager.get_version("sfa 1").to_dict() xrn=Xrn(api.hrn) version_more = {'interface':'aggregate', + 'sfa': 1, + 'geni_api': api.config.SFA_AGGREGATE_API_VERSION, 'testbed':'myplc', 'hrn':xrn.get_hrn(), - 'request_rspec_versions': request_rspec_versions, - 'ad_rspec_versions': ad_rspec_versions, - 'default_ad_rspec': default_rspec_version + 'geni_request_rspec_versions': request_rspec_versions, + 'geni_ad_rspec_versions': ad_rspec_versions, } return version_core(version_more) diff --git a/sfa/managers/aggregate_manager_max.py b/sfa/managers/aggregate_manager_max.py index 09e56b77..91130bc4 100644 --- a/sfa/managers/aggregate_manager_max.py +++ b/sfa/managers/aggregate_manager_max.py @@ -214,11 +214,13 @@ class AggregateManagerMax (AggregateManager): ### GENI AM API Methods - def SliverStatus(self, api, slice_xrn, creds, call_id): + def SliverStatus(self, api, slice_xrn, creds, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return {} return self.slice_status(api, slice_xrn, creds) - def CreateSliver(self, api, slice_xrn, creds, rspec_string, users, call_id): + def CreateSliver(self, api, slice_xrn, creds, rspec_string, users, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" #TODO: create real CreateSliver response rspec ret = self.create_slice(api, slice_xrn, creds, rspec_string, users) @@ -227,12 +229,14 @@ class AggregateManagerMax (AggregateManager): else: return " Error! " - def DeleteSliver(self, api, xrn, creds, call_id): + def DeleteSliver(self, api, xrn, creds, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" return self.delete_slice(api, xrn, creds) # no caching - def ListResources(self, api, creds, options,call_id): + def ListResources(self, api, creds, options={}): + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" # version_string = "rspec_%s" % (rspec_version.get_version_name()) slice_urn = options.get('geni_slice_urn') diff --git a/sfa/managers/slice_manager.py b/sfa/managers/slice_manager.py index 50edb9a3..7c58a688 100644 --- a/sfa/managers/slice_manager.py +++ b/sfa/managers/slice_manager.py @@ -26,7 +26,7 @@ class SliceManager: self.caching=True - def _call_id_supported(self, api, server): + def _options_supported(self, api, server): """ Returns true if server support the optional call_id arg, false otherwise. """ @@ -39,8 +39,8 @@ class SliceManager: version_parts = code_tag_parts[0].split(".") major, minor = version_parts[0:2] rev = code_tag_parts[1] - if int(major) > 1: - if int(minor) > 0 or int(rev) > 20: + if int(major) >= 1: + if int(minor) >= 2: return True return False @@ -53,7 +53,7 @@ class SliceManager: logger.warning("GetVersion, falling back to xmlrpclib.ServerProxy internals") return server._ServerProxy__host + server._ServerProxy__handler - def GetVersion(self, api): + def GetVersion(self, api, options={}): # peers explicitly in aggregates.xml peers =dict ([ (peername,self.get_serverproxy_url(v)) for (peername,v) in api.aggregates.iteritems() if peername != api.hrn]) @@ -65,15 +65,15 @@ class SliceManager: ad_rspec_versions.append(rspec_version.to_dict()) if rspec_version.content_type in ['*', 'request']: request_rspec_versions.append(rspec_version.to_dict()) - default_rspec_version = version_manager.get_version("sfa 1").to_dict() xrn=Xrn(api.hrn, 'authority+sa') version_more = {'interface':'slicemgr', + 'sfa': 1, + 'geni_api': api.config.SFA_AGGREGATE_API_VERSION, 'hrn' : xrn.get_hrn(), 'urn' : xrn.get_urn(), 'peers': peers, - 'request_rspec_versions': request_rspec_versions, - 'ad_rspec_versions': ad_rspec_versions, - 'default_ad_rspec': default_rspec_version + 'geni_request_rspec_versions': request_rspec_versions, + 'geni_ad_rspec_versions': ad_rspec_versions, } sm_version=version_core(version_more) # local aggregate if present needs to have localhost resolved @@ -114,16 +114,14 @@ class SliceManager: except Exception, e: logger.warn("add_slicemgr_stat failed on %s: %s" %(aggname, str(e))) - def ListResources(self, api, creds, options, call_id): + def ListResources(self, api, creds, options={}): version_manager = VersionManager() - def _ListResources(aggregate, server, credential, opts, call_id): + def _ListResources(aggregate, server, credential, opts={}): my_opts = copy(opts) args = [credential, my_opts] tStart = time.time() try: - if self._call_id_supported(api, server): - args.append(call_id) version = api.get_cached_server_version(server) # force ProtoGENI aggregates to give us a v2 RSpec if 'sfa' not in version.keys(): @@ -133,7 +131,7 @@ class SliceManager: except Exception, e: api.logger.log_exc("ListResources failed at %s" %(server.url)) return {"aggregate": aggregate, "elapsed": time.time()-tStart, "status": "exception", "exc_info": sys.exc_info()} - + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" # get slice's hrn from options @@ -170,7 +168,7 @@ class SliceManager: # get the rspec from the aggregate interface = api.aggregates[aggregate] server = api.server_proxy(interface, cred) - threads.run(_ListResources, aggregate, server, [cred], options, call_id) + threads.run(_ListResources, aggregate, server, [cred], options) results = threads.get_results() @@ -195,10 +193,10 @@ class SliceManager: return rspec.toxml() - def CreateSliver(self, api, xrn, creds, rspec_str, users, call_id): + def CreateSliver(self, api, xrn, creds, rspec_str, users, options={}): version_manager = VersionManager() - def _CreateSliver(aggregate, server, xrn, credential, rspec, users, call_id): + def _CreateSliver(aggregate, server, xrn, credential, rspec, users, options={}): tStart = time.time() try: # Need to call GetVersion at an aggregate to determine the supported @@ -214,14 +212,15 @@ class SliceManager: rspec = rspec.toxml() requested_users = sfa_to_pg_users_arg(users) args = [xrn, credential, rspec, requested_users] - if self._call_id_supported(api, server): - args.append(call_id) + if self._options_supported(api, server): + args.append(options) rspec = server.CreateSliver(*args) return {"aggregate": aggregate, "rspec": rspec, "elapsed": time.time()-tStart, "status": "success"} except: logger.log_exc('Something wrong in _CreateSliver with URL %s'%server.url) return {"aggregate": aggregate, "elapsed": time.time()-tStart, "status": "exception", "exc_info": sys.exc_info()} - + + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" # Validate the RSpec against PlanetLab's schema --disabled for now # The schema used here needs to aggregate the PL and VINI schemas @@ -267,14 +266,15 @@ class SliceManager: api.logger.log_exc("SM.CreateSliver: Failed to merge aggregate rspec") return result_rspec.toxml() - def RenewSliver(self, api, xrn, creds, expiration_time, call_id): - def _RenewSliver(server, xrn, creds, expiration_time, call_id): + def RenewSliver(self, api, xrn, creds, expiration_time, options={}): + def _RenewSliver(server, xrn, creds, expiration_time, options={}): server_version = api.get_cached_server_version(server) - args = [xrn, creds, expiration_time, call_id] - if self._call_id_supported(api, server): - args.append(call_id) + args = [xrn, creds, expiration_time] + if self._options_supported(api, server): + args.append(options) return server.RenewSliver(*args) + call_id = options.get('call_id') if Callids().already_handled(call_id): return True (hrn, type) = urn_to_hrn(xrn) @@ -298,14 +298,15 @@ class SliceManager: # 'and' the results return reduce (lambda x,y: x and y, threads.get_results() , True) - def DeleteSliver(self, api, xrn, creds, call_id): - def _DeleteSliver(server, xrn, creds, call_id): + def DeleteSliver(self, api, xrn, creds, options={}): + def _DeleteSliver(server, xrn, creds, options={}): server_version = api.get_cached_server_version(server) args = [xrn, creds] - if self._call_id_supported(api, server): - args.append(call_id) + if self._options_supported(api, server): + args.append(options) return server.DeleteSliver(*args) - + + call_id = options.get('call_id') if Callids().already_handled(call_id): return "" (hrn, type) = urn_to_hrn(xrn) # get the callers hrn @@ -330,14 +331,15 @@ class SliceManager: # first draft at a merging SliverStatus - def SliverStatus(self, api, slice_xrn, creds, call_id): - def _SliverStatus(server, xrn, creds, call_id): + def SliverStatus(self, api, slice_xrn, creds, options={}): + def _SliverStatus(server, xrn, creds, options={}): server_version = api.get_cached_server_version(server) args = [xrn, creds] - if self._call_id_supported(api, server): - args.append(call_id) + if self._options_supported(api, server): + args.append(options) return server.SliverStatus(*args) - + + call_id = options.get('call_id') if Callids().already_handled(call_id): return {} # attempt to use delegated credential first cred = api.getDelegatedCredential(creds) @@ -371,14 +373,15 @@ class SliceManager: return overall - def ListSlices(self, api, creds, call_id): - def _ListSlices(server, creds, call_id): + def ListSlices(self, api, creds, options={}): + def _ListSlices(server, creds, options={}): server_version = api.get_cached_server_version(server) args = [creds] - if self._call_id_supported(api, server): - args.append(call_id) + if self._options_supported(api, server): + args.append(options) return server.ListSlices(*args) - + + call_id = options.get('call_id') if Callids().already_handled(call_id): return [] # look in cache first @@ -404,7 +407,7 @@ class SliceManager: continue interface = api.aggregates[aggregate] server = api.server_proxy(interface, cred) - threads.run(_ListSlices, server, [cred], call_id) + threads.run(_ListSlices, server, [cred], options) # combime results results = threads.get_results() @@ -419,7 +422,7 @@ class SliceManager: return slices - def GetTicket(self, api, xrn, creds, rspec, users): + def GetTicket(self, api, xrn, creds, rspec, users, options={}): slice_hrn, type = urn_to_hrn(xrn) # get the netspecs contained within the clients rspec aggregate_rspecs = {} @@ -446,7 +449,7 @@ class SliceManager: interface = api.aggregates[aggregate] server = api.server_proxy(interface, cred) - threads.run(server.GetTicket, xrn, [cred], aggregate_rspec, users) + threads.run(server.GetTicket, xrn, [cred], aggregate_rspec, users, options) results = threads.get_results() diff --git a/sfa/methods/CreateSliver.py b/sfa/methods/CreateSliver.py index dd76d9ba..218986eb 100644 --- a/sfa/methods/CreateSliver.py +++ b/sfa/methods/CreateSliver.py @@ -25,11 +25,11 @@ class CreateSliver(Method): Parameter(type([str]), "List of credentials")), Parameter(str, "RSpec"), Parameter(type([]), "List of user information"), - Parameter(str, "call_id"), + Parameter(dict, "options"), ] returns = Parameter(str, "Allocated RSpec") - def call(self, slice_xrn, creds, rspec, users, call_id=""): + def call(self, slice_xrn, creds, rspec, users, options={}): hrn, type = urn_to_hrn(slice_xrn) self.api.logger.info("interface: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, hrn, self.name)) @@ -52,7 +52,7 @@ class CreateSliver(Method): rspec = run_sfatables(chain_name, hrn, origin_hrn, rspec) slivers = RSpec(rspec).version.get_nodes_with_slivers() if slivers: - result = self.api.manager.CreateSliver(self.api, slice_xrn, creds, rspec, users, call_id) + result = self.api.manager.CreateSliver(self.api, slice_xrn, creds, rspec, users, options) else: result = rspec return result diff --git a/sfa/methods/DeleteSliver.py b/sfa/methods/DeleteSliver.py index 58b88466..fe07b6ad 100644 --- a/sfa/methods/DeleteSliver.py +++ b/sfa/methods/DeleteSliver.py @@ -19,12 +19,12 @@ class DeleteSliver(Method): Parameter(str, "Human readable name of slice to delete (hrn or urn)"), Mixed(Parameter(str, "Credential string"), Parameter(type([str]), "List of credentials")), - Parameter(str, "call_id"), + Parameter(dict, "options"), ] returns = Parameter(int, "1 if successful") - def call(self, xrn, creds, call_id=""): + def call(self, xrn, creds, options={}): (hrn, type) = urn_to_hrn(xrn) valid_creds = self.api.auth.checkCredentials(creds, 'deletesliver', hrn) @@ -32,6 +32,6 @@ class DeleteSliver(Method): origin_hrn = Credential(string=valid_creds[0]).get_gid_caller().get_hrn() self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, hrn, self.name)) - self.api.manager.DeleteSliver(self.api, xrn, creds, call_id) + self.api.manager.DeleteSliver(self.api, xrn, creds, options) return 1 diff --git a/sfa/methods/GetTicket.py b/sfa/methods/GetTicket.py index 174bd4c6..b1d8f872 100644 --- a/sfa/methods/GetTicket.py +++ b/sfa/methods/GetTicket.py @@ -29,12 +29,13 @@ class GetTicket(Method): Mixed(Parameter(str, "Credential string"), Parameter(type([str]), "List of credentials")), Parameter(str, "Resource specification (rspec)"), - Parameter(type([]), "List of user information") + Parameter(type([]), "List of user information"), + Parameter(dict, "Options") ] returns = Parameter(str, "String representation of a ticket object") - def call(self, xrn, creds, rspec, users): + def call(self, xrn, creds, rspec, users, options={}): hrn, type = urn_to_hrn(xrn) # Find the valid credentials valid_creds = self.api.auth.checkCredentials(creds, 'getticket', hrn) @@ -51,5 +52,5 @@ class GetTicket(Method): rspec = run_sfatables(chain_name, hrn, origin_hrn, rspec) # remove nodes that are not available at this interface from the rspec - return self.api.manager.GetTicket(self.api, xrn, creds, rspec, users) + return self.api.manager.GetTicket(self.api, xrn, creds, rspec, users, options) diff --git a/sfa/methods/GetVersion.py b/sfa/methods/GetVersion.py index 8c215c45..801b3392 100644 --- a/sfa/methods/GetVersion.py +++ b/sfa/methods/GetVersion.py @@ -8,9 +8,9 @@ class GetVersion(Method): @return version """ interfaces = ['registry','aggregate', 'slicemgr', 'component'] - accepts = [] + accepts = [Parameter(dict, "Options")] returns = Parameter(dict, "Version information") - def call(self): + def call(self, options={}): self.api.logger.info("interface: %s\tmethod-name: %s" % (self.api.interface, self.name)) - return self.api.manager.GetVersion(self.api) + return self.api.manager.GetVersion(self.api, options) diff --git a/sfa/methods/ListResources.py b/sfa/methods/ListResources.py index a12447f6..6b1e7850 100644 --- a/sfa/methods/ListResources.py +++ b/sfa/methods/ListResources.py @@ -17,12 +17,11 @@ class ListResources(Method): accepts = [ Mixed(Parameter(str, "Credential string"), Parameter(type([str]), "List of credentials")), - Parameter(dict, "Options"), - Parameter(str, "call_id"), + Parameter(dict, "Options") ] returns = Parameter(str, "List of resources") - def call(self, creds, options, call_id=""): + def call(self, creds, options={}): self.api.logger.info("interface: %s\tmethod-name: %s" % (self.api.interface, self.name)) # get slice's hrn from options @@ -36,7 +35,7 @@ class ListResources(Method): origin_hrn = options.get('origin_hrn', None) if not origin_hrn: origin_hrn = Credential(string=valid_creds[0]).get_gid_caller().get_hrn() - rspec = self.api.manager.ListResources(self.api, creds, options, call_id) + rspec = self.api.manager.ListResources(self.api, creds, options) # filter rspec through sfatables if self.api.interface in ['aggregate']: diff --git a/sfa/methods/ListSlices.py b/sfa/methods/ListSlices.py index e8521c1a..eed408f2 100644 --- a/sfa/methods/ListSlices.py +++ b/sfa/methods/ListSlices.py @@ -15,17 +15,17 @@ class ListSlices(Method): accepts = [ Mixed(Parameter(str, "Credential string"), Parameter(type([str]), "List of credentials")), - Parameter(str, "call_id"), + Parameter(dict, "options"), ] returns = Parameter(list, "List of slice names") - def call(self, creds, call_id=""): + def call(self, creds, options={}): valid_creds = self.api.auth.checkCredentials(creds, 'listslices') #log the call origin_hrn = Credential(string=valid_creds[0]).get_gid_caller().get_hrn() self.api.logger.info("interface: %s\tcaller-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, self.name)) - return self.api.manager.ListSlices(self.api, creds, call_id) + return self.api.manager.ListSlices(self.api, creds, options) diff --git a/sfa/methods/RenewSliver.py b/sfa/methods/RenewSliver.py index b34d424a..48d64931 100644 --- a/sfa/methods/RenewSliver.py +++ b/sfa/methods/RenewSliver.py @@ -20,11 +20,11 @@ class RenewSliver(Method): Parameter(str, "Slice URN"), Parameter(type([str]), "List of credentials"), Parameter(str, "Expiration time in RFC 3339 format"), - Parameter(str, "call_id"), + Parameter(dict, "Options"), ] returns = Parameter(bool, "Success or Failure") - def call(self, slice_xrn, creds, expiration_time, call_id=""): + def call(self, slice_xrn, creds, expiration_time, options={}): (hrn, type) = urn_to_hrn(slice_xrn) @@ -40,5 +40,5 @@ class RenewSliver(Method): raise InsufficientRights('Renewsliver: Credential expires before requested expiration time') if requested_time > datetime.datetime.utcnow() + datetime.timedelta(days=max_renew_days): raise Exception('Cannot renew > %s days from now' % max_renew_days) - return self.api.manager.RenewSliver(self.api, slice_xrn, valid_creds, expiration_time, call_id) + return self.api.manager.RenewSliver(self.api, slice_xrn, valid_creds, expiration_time, options) diff --git a/sfa/methods/SliverStatus.py b/sfa/methods/SliverStatus.py index 2f4bc0c7..2a0ac5dc 100644 --- a/sfa/methods/SliverStatus.py +++ b/sfa/methods/SliverStatus.py @@ -14,17 +14,17 @@ class SliverStatus(Method): Parameter(str, "Slice URN"), Mixed(Parameter(str, "Credential string"), Parameter(type([str]), "List of credentials")), - Parameter(str, "call_id"), + Parameter(dict, "Options") ] returns = Parameter(dict, "Status details") - def call(self, slice_xrn, creds, call_id=""): + def call(self, slice_xrn, creds, options={}): hrn, type = urn_to_hrn(slice_xrn) valid_creds = self.api.auth.checkCredentials(creds, 'sliverstatus', hrn) self.api.logger.info("interface: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, hrn, self.name)) - status = self.api.manager.SliverStatus(self.api, hrn, valid_creds, call_id) + status = self.api.manager.SliverStatus(self.api, hrn, valid_creds, options) return status diff --git a/sfa/methods/UpdateSliver.py b/sfa/methods/UpdateSliver.py index f9baae4a..245b2077 100644 --- a/sfa/methods/UpdateSliver.py +++ b/sfa/methods/UpdateSliver.py @@ -20,13 +20,13 @@ class UpdateSliver(CreateSliver): Parameter(type([str]), "List of credentials")), Parameter(str, "RSpec"), Parameter(type([]), "List of user information"), - Parameter(str, "call_id"), + Parameter(dict, "options"), ] returns = Parameter(str, "Allocated RSpec") - def call(self, slice_xrn, creds, rspec, users, call_id=""): + def call(self, slice_xrn, creds, rspec, users, options={}): - return CreateSliver.call(self, slice_xrn, creds, rspec, users, call_id) + return CreateSliver.call(self, slice_xrn, creds, rspec, users, options) diff --git a/sfa/plc/aggregate.py b/sfa/plc/aggregate.py index 3ec538ad..0eff6cca 100644 --- a/sfa/plc/aggregate.py +++ b/sfa/plc/aggregate.py @@ -23,10 +23,9 @@ class Aggregate: #panos new user options variable user_options = {} - def __init__(self, api, user_options={}): + def __init__(self, api): self.api = api - self.user_options = user_options - + def get_sites(self, filter={}): sites = {} for site in self.api.driver.GetSites(filter): @@ -60,6 +59,8 @@ class Aggregate: for s1_node_id in site1['node_ids']: for s2_node_id in site2['node_ids']: + if s1_node_id not in nodes or s2_node_id not in nodes: + continue node1 = nodes[s1_node_id] node2 = nodes[s2_node_id] # set interfaces @@ -134,12 +135,16 @@ class Aggregate: return (slice, slivers) - def get_nodes_and_links(self, slice=None,slivers=[]): + def get_nodes_and_links(self, slice=None,slivers=[], options={}): filter = {} tags_filter = {} if slice and 'node_ids' in slice and slice['node_ids']: filter['node_id'] = slice['node_ids'] tags_filter=filter.copy() + + geni_available = options.get('geni_available') + if geni_available: + filter['boot_state'] = 'boot' filter.update({'peer_id': None}) nodes = self.api.driver.GetNodes(filter) @@ -218,7 +223,7 @@ class Aggregate: return (rspec_nodes, links) - def get_rspec(self, slice_xrn=None, version = None): + def get_rspec(self, slice_xrn=None, version = None, options={}): version_manager = VersionManager() version = version_manager.get_version(version) @@ -228,7 +233,7 @@ class Aggregate: rspec_version = version_manager._get_version(version.type, version.version, 'manifest') slice, slivers = self.get_slice_and_slivers(slice_xrn) - rspec = RSpec(version=rspec_version, user_options=self.user_options) + rspec = RSpec(version=rspec_version, user_options=options) if slice and 'expires' in slice: rspec.xml.set('expires', epochparse(slice['expires'])) diff --git a/sfa/rspecs/elements/element.py b/sfa/rspecs/elements/element.py index e185490a..b288cbbd 100644 --- a/sfa/rspecs/elements/element.py +++ b/sfa/rspecs/elements/element.py @@ -13,8 +13,8 @@ class Element(dict): def __getattr__(self, name): - if hasattr(self, name): - return getattr(self, name) + if hasattr(self.__dict__, name): + return getattr(self.__dict__, name) elif hasattr(self.element, name): return getattr(self.element, name) else: diff --git a/sfa/rspecs/elements/versions/sfav1Node.py b/sfa/rspecs/elements/versions/sfav1Node.py index 4e129e68..26d41a97 100644 --- a/sfa/rspecs/elements/versions/sfav1Node.py +++ b/sfa/rspecs/elements/versions/sfav1Node.py @@ -134,6 +134,11 @@ class SFAv1Node: node['slivers'] = SFAv1Sliver.get_slivers(node_elem) # get tags node['tags'] = SFAv1PLTag.get_pl_tags(node_elem, ignore=Node.fields) + + parent = node_elem.getparent() + if (parent != None) and (parent.tag=="network") and ("name" in parent.attrib): + node['network_name'] = parent.attrib['name'] + nodes.append(node) return nodes - + diff --git a/sfa/server/sfa-start.py b/sfa/server/sfa-start.py index d4a3131d..dbd5e4f7 100755 --- a/sfa/server/sfa-start.py +++ b/sfa/server/sfa-start.py @@ -40,7 +40,8 @@ from sfa.util.sfalogging import logger from sfa.util.xrn import get_authority, hrn_to_urn from sfa.util.config import Config import sfa.client.xmlrpcprotocol as xmlrpcprotocol - +from sfa.trust.gid import GID +from sfa.trust.trustedroots import TrustedRoots from sfa.trust.certificate import Keypair, Certificate from sfa.trust.hierarchy import Hierarchy from sfa.trust.gid import GID @@ -60,81 +61,13 @@ def daemon(): devnull = os.open(os.devnull, os.O_RDWR) os.dup2(devnull, 0) # xxx fixme - this is just to make sure that nothing gets stupidly lost - should use devnull - crashlog = os.open('/var/log/httpd/sfa_access_log', os.O_RDWR | os.O_APPEND | os.O_CREAT, 0644) + logdir='/var/log/httpd' + # when installed in standalone we might not have httpd installed + if not os.path.isdir(logdir): os.mkdir('/var/log/httpd') + crashlog = os.open('%s/sfa_access_log'%logdir, os.O_RDWR | os.O_APPEND | os.O_CREAT, 0644) os.dup2(crashlog, 1) os.dup2(crashlog, 2) -def init_server_key(server_key_file, server_cert_file, config, hierarchy): - - hrn = config.SFA_INTERFACE_HRN.lower() - # check if the server's private key exists. If it doesnt, - # get the right one from the authorities directory. If it cant be - # found in the authorities directory, generate a random one - if not os.path.exists(server_key_file): - hrn = config.SFA_INTERFACE_HRN.lower() - hrn_parts = hrn.split(".") - rel_key_path = hrn - pkey_filename = hrn+".pkey" - - # sub authority's have "." in their hrn. This must - # be converted to os.path separator - if len(hrn_parts) > 0: - rel_key_path = hrn.replace(".", os.sep) - pkey_filename= hrn_parts[-1]+".pkey" - - key_file = os.sep.join([hierarchy.basedir, rel_key_path, pkey_filename]) - if not os.path.exists(key_file): - # if it doesnt exist then this is probably a fresh interface - # with no records. Generate a random keypair for now - logger.debug("server's public key not found in %s" % key_file) - - logger.debug("generating a random server key pair") - key = Keypair(create=True) - key.save_to_file(server_key_file) - init_server_cert(hrn, key, server_cert_file, self_signed=True) - - else: - # the pkey was found in the authorites directory. lets - # copy it to where the server key should be and generate - # the cert - key = Keypair(filename=key_file) - key.save_to_file(server_key_file) - init_server_cert(hrn, key, server_cert_file) - - # If private key exists and cert doesnt, recreate cert - if (os.path.exists(server_key_file)) and (not os.path.exists(server_cert_file)): - key = Keypair(filename=server_key_file) - init_server_cert(hrn, key, server_cert_file) - - -def init_server_cert(hrn, key, server_cert_file, self_signed=False): - """ - Setup the certificate for this server. Attempt to use gid before - creating a self signed cert - """ - if self_signed: - init_self_signed_cert(hrn, key, server_cert_file) - else: - try: - # look for gid file - logger.debug("generating server cert from gid: %s"% hrn) - hierarchy = Hierarchy() - auth_info = hierarchy.get_auth_info(hrn) - gid = GID(filename=auth_info.gid_filename) - gid.save_to_file(filename=server_cert_file) - except: - # fall back to self signed cert - logger.debug("gid for %s not found" % hrn) - init_self_signed_cert(hrn, key, server_cert_file) - -def init_self_signed_cert(hrn, key, server_cert_file): - logger.debug("generating self signed cert") - # generate self signed certificate - cert = Certificate(subject=hrn) - cert.set_issuer(key=key, subject=hrn) - cert.set_pubkey(key) - cert.sign() - cert.save_to_file(server_cert_file) def install_peer_certs(server_key_file, server_cert_file): """ @@ -253,12 +186,16 @@ def main(): config = Config() if config.SFA_API_DEBUG: pass - hierarchy = Hierarchy() - server_key_file = os.path.join(hierarchy.basedir, "server.key") - server_cert_file = os.path.join(hierarchy.basedir, "server.cert") - init_server_key(server_key_file, server_cert_file, config, hierarchy) + # ge the server's key and cert + hierarchy = Hierarchy() + auth_info = hierarchy.get_interface_auth_info() + server_key_file = auth_info.get_privkey_filename() + server_cert_file = auth_info.get_gid_filename() + # ensure interface cert is present in trusted roots dir + trusted_roots = TrustedRoots(config.get_trustedroots_dir()) + trusted_roots.add_gid(GID(filename=server_cert_file)) if (options.daemon): daemon() if options.trusted_certs: diff --git a/sfa/server/sfaapi.py b/sfa/server/sfaapi.py index 70850379..845ccffe 100644 --- a/sfa/server/sfaapi.py +++ b/sfa/server/sfaapi.py @@ -8,8 +8,8 @@ from sfa.trust.auth import Auth from sfa.trust.certificate import Keypair, Certificate from sfa.trust.credential import Credential from sfa.trust.rights import determine_rights - from sfa.server.xmlrpcapi import XmlrpcApi +from sfa.util.genicode import GENICODE # thgen xxx fixme this is wrong all right, but temporary, will use generic from sfa.util.table import SfaTable @@ -205,3 +205,48 @@ class SfaApi (XmlrpcApi): # cache version for 24 hours self.cache.add(cache_key, server_version, ttl= 60*60*24) return server_version + + + def get_geni_code(self, result): + code = { + 'geni_code': GENICODE.SUCCESS, + 'am_type': 'sfa', + 'am_code': None, + } + if isinstnace(result, SfaFault): + code['geni_code'] = result.faultCode + code['am_code'] = result.faultCode + + return code + + def get_geni_value(self, result): + value = result + if isinstance(result, SfaFault): + value = "" + return value + + def get_geni_output(self, result): + output = "" + if isinstance(result, SFaFault): + output = result.faultString + return output + + def prepare_response_v2_am(self, result): + response = { + 'code': self.get_geni_code(result), + 'value': self.get_geni_value(result), + 'output': self.get_geni_output(result), + } + return response + + def prepare_response(self, result, method=""): + """ + Converts the specified result into a standard GENI compliant + response + """ + if self.interface.lower() == 'aggregate': + if hasattr(self.config, 'SFA_AGGREGATE_API_VERSION') and \ + self.config.SFA_AGGREGATE_API_VERSION == "2": + result = self.prepare_response_v2_am(result) + return XmlrpcApi.prepare_response(self, result, method) + diff --git a/sfa/trust/hierarchy.py b/sfa/trust/hierarchy.py index 9648c9d4..239240e2 100644 --- a/sfa/trust/hierarchy.py +++ b/sfa/trust/hierarchy.py @@ -112,8 +112,8 @@ class Hierarchy: # @param basedir the base directory to store the hierarchy in def __init__(self, basedir = None): + self.config = Config() if not basedir: - self.config = Config() basedir = os.path.join(self.config.SFA_DATA_DIR, "authorities") self.basedir = basedir ## @@ -165,7 +165,6 @@ class Hierarchy: parent_urn = hrn_to_urn(parent_hrn, 'authority') if (parent_hrn) and (not self.auth_exists(parent_urn)) and (create_parents): self.create_auth(parent_urn, create_parents) - (directory, gid_filename, privkey_filename, dbinfo_filename) = \ self.get_auth_filenames(hrn) @@ -194,6 +193,32 @@ class Hierarchy: dbinfo_file.write(str(dbinfo)) dbinfo_file.close() + def create_top_level_auth(self, hrn=None): + """ + Create top level records (includes root and sub authorities (local/remote) + """ + if not hrn: + hrn = self.config.SFA_INTERFACE_HRN + # make sure parent exists + parent_hrn = get_authority(hrn) + if not parent_hrn: + parent_hrn = hrn + if not parent_hrn == hrn: + self.create_top_level_auth(parent_hrn) + + # create the authority if it doesnt alrady exist + if not self.auth_exists(hrn): + self.create_auth(hrn) + + + def get_interface_auth_info(self, create=True): + hrn = self.config.SFA_INTERFACE_HRN + if not self.auth_exists(hrn): + if create==True: + self.create_top_level_auth(hrn) + else: + raise MissingAuthority(hrn) + return self.get_auth_info(hrn) ## # Return the AuthInfo object for the specified authority. If the authority # does not exist, then an exception is thrown. As a side effect, disk files @@ -231,13 +256,14 @@ class Hierarchy: def create_gid(self, xrn, uuid, pkey, CA=False): hrn, type = urn_to_hrn(xrn) + if not type: + type = 'authority' parent_hrn = get_authority(hrn) # Using hrn_to_urn() here to make sure the urn is in the right format # If xrn was a hrn instead of a urn, then the gid's urn will be # of type None urn = hrn_to_urn(hrn, type) gid = GID(subject=hrn, uuid=uuid, hrn=hrn, urn=urn) - # is this a CA cert if hrn == self.config.SFA_INTERFACE_HRN or not parent_hrn: # root or sub authority diff --git a/sfa/util/PostgreSQL.py b/sfa/util/PostgreSQL.py index f16f48d7..de6f9fab 100644 --- a/sfa/util/PostgreSQL.py +++ b/sfa/util/PostgreSQL.py @@ -69,22 +69,22 @@ class PostgreSQL: if psycopg2: try: # Try UNIX socket first - self.connection = psycopg2.connect(user = self.config.SFA_PLC_DB_USER, - password = self.config.SFA_PLC_DB_PASSWORD, - database = self.config.SFA_PLC_DB_NAME) + self.connection = psycopg2.connect(user = self.config.SFA_DB_USER, + password = self.config.SFA_DB_PASSWORD, + database = self.config.SFA_DB_NAME) except psycopg2.OperationalError: # Fall back on TCP - self.connection = psycopg2.connect(user = self.config.SFA_PLC_DB_USER, - password = self.config.SFA_PLC_DB_PASSWORD, - database = self.config.SFA_PLC_DB_NAME, - host = self.config.SFA_PLC_DB_HOST, - port = self.config.SFA_PLC_DB_PORT) + self.connection = psycopg2.connect(user = self.config.SFA_DB_USER, + password = self.config.SFA_DB_PASSWORD, + database = self.config.SFA_DB_NAME, + host = self.config.SFA_DB_HOST, + port = self.config.SFA_DB_PORT) self.connection.set_client_encoding("UNICODE") else: - self.connection = pgdb.connect(user = self.config.SFA_PLC_DB_USER, - password = self.config.SFA_PLC_DB_PASSWORD, - host = "%s:%d" % (self.config.SFA_PLC_DB_HOST, self.config.SFA_PLC_DB_PORT), - database = self.config.SFA_PLC_DB_NAME) + self.connection = pgdb.connect(user = self.config.SFA_DB_USER, + password = self.config.SFA_DB_PASSWORD, + host = "%s:%d" % (self.config.SFA_DB_HOST, self.config.SFA_DB_PORT), + database = self.config.SFA_DB_NAME) (self.rowcount, self.description, self.lastrowid) = \ (None, None, None) diff --git a/sfa/util/config.py b/sfa/util/config.py index 14669160..2ad7f7b5 100644 --- a/sfa/util/config.py +++ b/sfa/util/config.py @@ -106,11 +106,11 @@ class Config: def get_plc_dbinfo(self): return { - 'dbname' : self.SFA_PLC_DB_NAME, - 'address' : self.SFA_PLC_DB_HOST, - 'port' : self.SFA_PLC_DB_PORT, - 'user' : self.SFA_PLC_DB_USER, - 'password' : self.SFA_PLC_DB_PASSWORD + 'dbname' : self.SFA_DB_NAME, + 'address' : self.SFA_DB_HOST, + 'port' : self.SFA_DB_PORT, + 'user' : self.SFA_DB_USER, + 'password' : self.SFA_DB_PASSWORD } # TODO: find a better place to put this method diff --git a/sfa/util/faults.py b/sfa/util/faults.py index 91e5300b..4a1a5e46 100644 --- a/sfa/util/faults.py +++ b/sfa/util/faults.py @@ -3,6 +3,7 @@ # import xmlrpclib +from sfa.util.genicode import GENICODE class SfaFault(xmlrpclib.Fault): def __init__(self, faultCode, faultString, extra = None): @@ -15,7 +16,7 @@ class SfaInvalidAPIMethod(SfaFault): faultString = "Invalid method " + method if interface: faultString += " for interface " + interface - SfaFault.__init__(self, 100, faultString, extra) + SfaFault.__init__(self, GENICODE.UNSUPPORTED, faultString, extra) class SfaInvalidArgumentCount(SfaFault): def __init__(self, got, min, max = min, extra = None): @@ -25,7 +26,7 @@ class SfaInvalidArgumentCount(SfaFault): expected = "%d" % min faultString = "Expected %s arguments, got %d" % \ (expected, got) - SfaFault.__init__(self, 101, faultString, extra) + SfaFault.__init__(self, GENICODE.BADARGS, faultString, extra) class SfaInvalidArgument(SfaFault): def __init__(self, extra = None, name = None): @@ -33,40 +34,40 @@ class SfaInvalidArgument(SfaFault): faultString = "Invalid %s value" % name else: faultString = "Invalid argument" - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.BADARGS, faultString, extra) class SfaAuthenticationFailure(SfaFault): def __init__(self, extra = None): faultString = "Failed to authenticate call" - SfaFault.__init__(self, 103, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) class SfaDBError(SfaFault): def __init__(self, extra = None): faultString = "Database error" - SfaFault.__init__(self, 106, faultString, extra) + SfaFault.__init__(self, GENICODE.DBERROR, faultString, extra) class SfaPermissionDenied(SfaFault): def __init__(self, extra = None): faultString = "Permission denied" - SfaFault.__init__(self, 108, faultString, extra) + SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra) class SfaNotImplemented(SfaFault): def __init__(self, interface=None, extra = None): faultString = "Not implemented" if interface: faultString += " at interface " + interface - SfaFault.__init__(self, 109, faultString, extra) + SfaFault.__init__(self, GENICODE.UNSUPPORTED, faultString, extra) class SfaAPIError(SfaFault): def __init__(self, extra = None): faultString = "Internal API error" - SfaFault.__init__(self, 111, faultString, extra) + SfaFault.__init__(self, GENICODE.SERVERERROR, faultString, extra) class MalformedHrnException(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Malformed HRN: %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, extra) def __str__(self): return repr(self.value) @@ -74,7 +75,7 @@ class TreeException(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Tree Exception: %(value)s, " % locals() - SfaFault.__init__(self, 111, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -82,7 +83,7 @@ class NonExistingRecord(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Non exsiting record %(value)s, " % locals() - SfaFault.__init__(self, 111, faultString, extra) + SfaFault.__init__(self, GENICODE.SEARCHFAILED, faultString, extra) def __str__(self): return repr(self.value) @@ -90,32 +91,16 @@ class ExistingRecord(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Existing record: %(value)s, " % locals() - SfaFault.__init__(self, 111, faultString, extra) + SfaFault.__init__(self, GENICODE.REFUSED, faultString, extra) def __str__(self): return repr(self.value) -class NonexistingCredType(SfaFault): - def __init__(self, value, extra = None): - self.value = value - faultString = "Non existing record: %(value)s, " % locals() - SfaFault.__init__(self, 111, faultString, extra) - def __str__(self): - return repr(self.value) - -class NonexistingFile(SfaFault): - def __init__(self, value, extra = None): - self.value = value - faultString = "Non existing file: %(value)s, " % locals() - SfaFault.__init__(self, 111, faultString, extra) - def __str__(self): - return repr(self.value) - class InvalidRPCParams(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Invalid RPC Params: %(value)s, " % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.RPCERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -125,7 +110,7 @@ class ConnectionKeyGIDMismatch(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Connection Key GID mismatch: %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -133,7 +118,7 @@ class MissingCallerGID(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Missing Caller GID: %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -141,7 +126,7 @@ class RecordNotFound(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Record not found: %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -149,7 +134,7 @@ class UnknownSfaType(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Unknown SFA Type: %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -157,7 +142,7 @@ class MissingAuthority(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Missing authority: %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -165,7 +150,7 @@ class PlanetLabRecordDoesNotExist(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "PlanetLab record does not exist : %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -173,7 +158,7 @@ class PermissionError(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Permission error: %(value)s" % locals() - SfaFault.__init__(self, 108, faultString, extra) + SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra) def __str__(self): return repr(self.value) @@ -181,7 +166,7 @@ class InsufficientRights(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Insufficient rights: %(value)s" % locals() - SfaFault.__init__(self, 108, faultString, extra) + SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra) def __str__(self): return repr(self.value) @@ -189,7 +174,7 @@ class MissingDelegateBit(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Missing delegate bit: %(value)s" % locals() - SfaFault.__init__(self, 108, faultString, extra) + SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra) def __str__(self): return repr(self.value) @@ -197,7 +182,7 @@ class ChildRightsNotSubsetOfParent(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Child rights not subset of parent: %(value)s" % locals() - SfaFault.__init__(self, 103, faultString, extra) + SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra) def __str__(self): return repr(self.value) @@ -205,7 +190,7 @@ class CertMissingParent(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Cert missing parent: %(value)s" % locals() - SfaFault.__init__(self, 103, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -213,7 +198,7 @@ class CertNotSignedByParent(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Cert not signed by parent: %(value)s" % locals() - SfaFault.__init__(self, 103, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -221,7 +206,7 @@ class GidParentHrn(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Cert URN is not an extension of its parent: %(value)s" % locals() - SfaFault.__init__(self, 103, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -229,7 +214,7 @@ class GidInvalidParentHrn(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "GID invalid parent hrn: %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -237,20 +222,20 @@ class SliverDoesNotExist(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Sliver does not exist : %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) class BadRequestHash(xmlrpclib.Fault): def __init__(self, hash = None, extra = None): faultString = "bad request hash: " + str(hash) - xmlrpclib.Fault.__init__(self, 902, faultString) + xmlrpclib.Fault.__init__(self, GENICODE.ERROR, faultString) class MissingTrustedRoots(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Trusted root directory does not exist: %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.SERVERERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -258,7 +243,7 @@ class MissingSfaInfo(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Missing information: %(value)s" % locals() - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -266,7 +251,7 @@ class InvalidRSpec(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Invalid RSpec: %(value)s" % locals() - SfaFault.__init__(self, 108, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -274,7 +259,7 @@ class InvalidRSpecElement(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Invalid RSpec Element: %(value)s" % locals() - SfaFault.__init__(self, 108, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -282,22 +267,14 @@ class InvalidXML(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Invalid XML Document: %(value)s" % locals() - SfaFault.__init__(self, 108, faultString, extra) - def __str__(self): - return repr(self.value) - -class InvalidXMLElement(SfaFault): - def __init__(self, value, extra = None): - self.value = value - faultString = "Invalid XML Element: %(value)s" % locals() - SfaFault.__init__(self, 108, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) class AccountNotEnabled(SfaFault): def __init__(self, extra = None): faultString = "Account Disabled" - SfaFault.__init__(self, 108, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -305,7 +282,7 @@ class CredentialNotVerifiable(SfaFault): def __init__(self, value, extra = None): self.value = value faultString = "Unable to verify credential: %(value)s, " %locals() - SfaFault.__init__(self, 115, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) def __str__(self): return repr(self.value) @@ -313,5 +290,5 @@ class CertExpired(SfaFault): def __init__(self, value, extra=None): self.value = value faultString = "%s cert is expired" % value - SfaFault.__init__(self, 102, faultString, extra) + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) diff --git a/sfa/util/genicode.py b/sfa/util/genicode.py new file mode 100644 index 00000000..855d440a --- /dev/null +++ b/sfa/util/genicode.py @@ -0,0 +1,22 @@ +from sfa.util.enumeration import Enum + +GENICODE = Enum( + SUCCESS=0, + BADARGS=1, + ERROR=2, + FORBIDDEN=3, + BADVERSION=4, + SERVERERROR=5, + TOOBIG=6, + REFUSED=7, + TIMEDOUT=8, + DBERROR=9, + RPCERROR=10, + UNAVAILABLE=11, + SEARCHFAILED=12, + UNSUPPORTED=13, + BUSY=14, + EXPIRED=15, + INPORGRESS=16, + ALREADYEXISTS=17 +) diff --git a/sfa/util/sfatablesRuntime.py b/sfa/util/sfatablesRuntime.py index 170fa880..24437772 100644 --- a/sfa/util/sfatablesRuntime.py +++ b/sfa/util/sfatablesRuntime.py @@ -1,36 +1,47 @@ -from sfatables.runtime import SFATablesRules +# sfa should not depend on sfatables +# if the sfatables.runtime import fails, just define run_sfatables as identity -def fetch_context(slice_hrn, user_hrn, contexts): - """ - Returns the request context required by sfatables. At some point, this - mechanism should be changed to refer to "contexts", which is the - information that sfatables is requesting. But for now, we just return - the basic information needed in a dict. - """ - base_context = {'sfa':{'user':{'hrn':user_hrn}, 'slice':{'hrn':slice_hrn}}} - return base_context +try: + from sfatables.runtime import SFATablesRules -def run_sfatables(chain, hrn, origin_hrn, rspec, context_callback = None ): - """ - Run the rspec through sfatables - @param chain Name of rule chain - @param hrn Object's hrn - @param origin_hrn Original caller's hrn - @param rspec Incoming rspec - @param context_callback Callback used to generate the request context + def fetch_context(slice_hrn, user_hrn, contexts): + """ + Returns the request context required by sfatables. At some point, this + mechanism should be changed to refer to "contexts", which is the + information that sfatables is requesting. But for now, we just return + the basic information needed in a dict. + """ + base_context = {'sfa':{'user':{'hrn':user_hrn}, 'slice':{'hrn':slice_hrn}}} + return base_context - @return rspec - """ - if not context_callback: - context_callback = fetch_context + def run_sfatables(chain, hrn, origin_hrn, rspec, context_callback = None ): + """ + Run the rspec through sfatables + @param chain Name of rule chain + @param hrn Object's hrn + @param origin_hrn Original caller's hrn + @param rspec Incoming rspec + @param context_callback Callback used to generate the request context + + @return rspec + """ + if not context_callback: + context_callback = fetch_context - chain = chain.upper() - rules = SFATablesRules(chain) - if rules.sorted_rule_list: - contexts = rules.contexts - request_context = context_callback(hrn, origin_hrn, contexts) - rules.set_context(request_context) - newrspec = rules.apply(rspec) - else: - newrspec = rspec - return newrspec + chain = chain.upper() + rules = SFATablesRules(chain) + if rules.sorted_rule_list: + contexts = rules.contexts + request_context = context_callback(hrn, origin_hrn, contexts) + rules.set_context(request_context) + newrspec = rules.apply(rspec) + else: + newrspec = rspec + return newrspec + +except: + + from sfa.util.logging import logger + def run_sfatables (_,__,___, rspec, ____=None): + logger.warning("Cannot import sfatables.runtime, please install package sfa-sfatables") + return rspec diff --git a/sfa/util/version.py.in b/sfa/util/version.py.in index 52913281..46b31d39 100644 --- a/sfa/util/version.py.in +++ b/sfa/util/version.py.in @@ -4,9 +4,7 @@ scm_url="@SCMURL@" import socket def version_core (more={}): - core = { 'geni_api':1, - 'sfa' : 1, - 'code_tag' : version_tag, + core = { 'code_tag' : version_tag, 'code_url' : scm_url, 'hostname' : socket.gethostname(), }