Merge branch 'upstreammaster'
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Fri, 25 Nov 2011 07:29:49 +0000 (08:29 +0100)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Fri, 25 Nov 2011 07:29:49 +0000 (08:29 +0100)
35 files changed:
INSTALL.txt
config/default_config.xml
config/sfa-config-tty
flashpolicy/__init__.py [deleted file]
setup.py
sfa.spec
sfa/client/sfi.py
sfa/importer/sfa-import-plc.py
sfa/importer/sfaImport.py
sfa/init.d/sfa
sfa/managers/aggregate_manager.py
sfa/managers/aggregate_manager_eucalyptus.py
sfa/managers/aggregate_manager_max.py
sfa/managers/slice_manager.py
sfa/methods/CreateSliver.py
sfa/methods/DeleteSliver.py
sfa/methods/GetTicket.py
sfa/methods/GetVersion.py
sfa/methods/ListResources.py
sfa/methods/ListSlices.py
sfa/methods/RenewSliver.py
sfa/methods/SliverStatus.py
sfa/methods/UpdateSliver.py
sfa/plc/aggregate.py
sfa/rspecs/elements/element.py
sfa/rspecs/elements/versions/sfav1Node.py
sfa/server/sfa-start.py
sfa/server/sfaapi.py
sfa/trust/hierarchy.py
sfa/util/PostgreSQL.py
sfa/util/config.py
sfa/util/faults.py
sfa/util/genicode.py [new file with mode: 0644]
sfa/util/sfatablesRuntime.py
sfa/util/version.py.in

index cc59ceb..b93abae 100644 (file)
@@ -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
index 670d6f2..10471bc 100644 (file)
@@ -18,14 +18,14 @@ Thierry Parmentelat
       <description>Basic system variables.</description>
 
       <variablelist>
-       <variable id="generic_flavour" type="string">
-         <name>Generic Flavour</name>
-         <value>pl</value>
-         <description>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.
-         </description>
-       </variable>
+        <variable id="generic_flavour" type="string">
+          <name>Generic Flavour</name>
+          <value>pl</value>
+          <description>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.
+          </description>
+        </variable>
 
         <variable id="interface_hrn" type="string">
           <name>Human readable name</name>
@@ -33,6 +33,12 @@ Thierry Parmentelat
           <description>The human readable name for this interface.</description>
         </variable>
 
+        <variable id="aggregate_api_version" type="string">
+          <name>Aggregate Manager API Version</name>
+          <value>1</value>
+          <description>The Aggregate API version</description>
+        </variable>
+
         <variable id="credential_schema" type="string">
           <name>Credential Schema</name>
           <value>/etc/sfa/credential.xsd</value>
@@ -109,6 +115,42 @@ Thierry Parmentelat
     </variablelist>
     </category>
 
+    <!-- ======================================== -->
+    <category id="sfa_sm">
+      <name>Slice Manager</name>
+      <description>The settings that affect the slice manager that will run
+      as part of this SFA instance.</description>
+
+      <variablelist>
+       <variable id="enabled" type="boolean">
+         <name>Enable Slice Manager</name>
+         <value>true</value>
+         <description>Allows this local SFA instance to run as a
+         slice manager.</description>
+       </variable>
+
+       <variable id="type" type="string">
+         <name>Slice Manager type</name>
+         <value>pl</value>
+         <description>The type of backend server for this
+         slice manager. Not all slice managers are myplc.</description>
+       </variable>
+
+       <variable id="host" type="hostname">
+         <name>Hostname</name>
+         <value>localhost</value>
+         <description>The hostname where the slice manager is expected to
+         be found.</description>
+       </variable>
+
+       <variable id="port" type="int">
+         <name>Port number</name>
+         <value>12347</value>
+         <description>The port where the slice manager is to be found.</description>
+       </variable>
+      </variablelist>
+    </category>
+
     <!-- ======================================== -->
     <category id="sfa_aggregate">
       <name>Aggregate</name>
@@ -153,38 +195,48 @@ Thierry Parmentelat
     </category>
 
     <!-- ======================================== -->
-    <category id="sfa_sm">
-      <name>Slice Manager</name>
-      <description>The settings that affect the slice manager that will run
-      as part of this SFA instance.</description>
+    <category id="sfa_db">
+      <name></name>
+      <description>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.</description>
 
       <variablelist>
        <variable id="enabled" type="boolean">
-         <name>Enable Slice Manager</name>
+         <name>Enabled</name>
          <value>true</value>
-         <description>Allows this local SFA instance to run as a
-         slice manager.</description>
-       </variable>
-
-       <variable id="type" type="string">
-         <name>Slice Manager type</name>
-         <value>pl</value>
-         <description>The type of backend server for this
-         slice manager. Not all slice managers are myplc.</description>
+         <description>Enable the database server on this machine.</description>
        </variable>
 
        <variable id="host" type="hostname">
-         <name>Hostname</name>
+         <name>Database host</name>
          <value>localhost</value>
-         <description>The hostname where the slice manager is expected to
-         be found.</description>
+         <description>The host where the SFA database can be reached.</description>
        </variable>
 
        <variable id="port" type="int">
-         <name>Port number</name>
-         <value>12347</value>
-         <description>The port where the slice manager is to be found.</description>
+         <name>Database port</name>
+         <value>5432</value>
+         <description>The port where the SFA database can be reached.</description>
+       </variable>
+
+       <variable id="user" type="string">
+         <name>Database user</name>
+         <value>sfadbuser</value>
+         <description>When SFA gets co-hosted with a myplc, this should match the PLC config.</description>
        </variable>
+
+       <variable id="password" type="string">
+         <name>Database password</name>
+         <value></value>
+         <description>When SFA gets co-hosted with a myplc, this should match the PLC config.</description>
+       </variable>
+
+       <variable id="name" type="string">
+         <name>Database name</name>
+         <value>sfa</value>
+         <description>SFA database name.</description>
+       </variable>
+
+
       </variablelist>
     </category>
 
@@ -212,39 +264,11 @@ Thierry Parmentelat
          <description>Full URL of PLC interface.</description>
        </variable>
 
-       <variable id="db_name" type="string">
-         <name>Database name</name>
-         <value>planetlab5</value>
-         <description>Planetlab database name.</description>
-       </variable>
-
-       <variable id="db_host" type="hostname">
-         <name>Datbase host</name>
-         <value>localhost</value>
-         <description>The host where the PLC database can be reached.</description>
-       </variable>
-
-       <variable id="db_port" type="int">
-         <name>Database port</name>
-         <value>5432</value>
-         <description>The port where the PLC database can be reached.</description>
-       </variable>
-
-       <variable id="db_user" type="string">
-         <name>Database user</name>
-         <value>pgsqluser</value>
-         <description></description>
-       </variable>
-
-       <variable id="db_password" type="string">
-         <name>Database password</name>
-         <value></value>
-         <description>The password for PLC_DB_USER.</description>
-       </variable>
-
       </variablelist>
     </category>
 
+
+    <!-- ======================================== -->
     <category id="sfa_flashpolicy">
       <name>SFA Flash Policy</name>
       <description>The settings that affect the flash policy server that will run
index 9b2c439..9fef0f9 100755 (executable)
@@ -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 (file)
index e69de29..0000000
index a9735a0..0c02f32 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -52,7 +52,6 @@ package_dirs = [
     'sfatables',
     'sfatables/commands',
     'sfatables/processors',
-    'flashpolicy',
     ]
 
 
index 1fad71d..57cebec 100644 (file)
--- 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 <support@planet-lab.org>
 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 <thierry.parmentelat@sophia.inria.fr> - 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 <thierry.parmentelat@sophia.inria.fr> - sfa-1.1-4
 - fixed links and attributes in rspecs
 - minor cleanup in the API methods, and more consistent names in manager methods
index fc6a7b4..9ed3c84 100755 (executable)
@@ -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:
index 6873f48..15a5bc6 100755 (executable)
@@ -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()
index 4de6e1b..568fce8 100644 (file)
@@ -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()
index 08975dc..7247339 100755 (executable)
@@ -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
 }
 
 
index 1b069f7..56d6008 100644 (file)
@@ -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)
index 3f2d512..55e14ce 100644 (file)
@@ -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)
index 09e56b7..91130bc 100644 (file)
@@ -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 "<?xml version=\"1.0\" ?> <RSpec type=\"SFA\"> Error! </RSpec>"
     
-    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')
index 50edb9a..7c58a68 100644 (file)
@@ -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()
         
index dd76d9b..218986e 100644 (file)
@@ -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
index 58b8846..fe07b6a 100644 (file)
@@ -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 
index 174bd4c..b1d8f87 100644 (file)
@@ -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)
         
index 8c215c4..801b339 100644 (file)
@@ -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)
index a12447f..6b1e785 100644 (file)
@@ -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']:
index e8521c1..eed408f 100644 (file)
@@ -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)
  
index b34d424..48d6493 100644 (file)
@@ -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)    
     
index 2f4bc0c..2a0ac5d 100644 (file)
@@ -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
     
index f9baae4..245b207 100644 (file)
@@ -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)
     
index 3ec538a..0eff6cc 100644 (file)
@@ -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']))
 
index e185490..b288cbb 100644 (file)
@@ -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:
index 4e129e6..26d41a9 100644 (file)
@@ -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            
-            
+
index d4a3131..dbd5e4f 100755 (executable)
@@ -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:
index 7085037..845ccff 100644 (file)
@@ -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)
+
index 9648c9d..239240e 100644 (file)
@@ -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  
index f16f48d..de6f9fa 100644 (file)
@@ -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)
index 1466916..2ad7f7b 100644 (file)
@@ -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
index 91e5300..4a1a5e4 100644 (file)
@@ -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 (file)
index 0000000..855d440
--- /dev/null
@@ -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       
+)   
index 170fa88..2443777 100644 (file)
@@ -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
index 5291328..46b31d3 100644 (file)
@@ -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(),
              }