fix merge problem
authorsmbaker <smbaker@fc8clean.lan>
Mon, 28 Nov 2011 03:06:16 +0000 (19:06 -0800)
committersmbaker <smbaker@fc8clean.lan>
Mon, 28 Nov 2011 03:06:16 +0000 (19:06 -0800)
47 files changed:
INSTALL.txt
README.txt [deleted file]
config/default_config.xml
config/sfa-config-tty
flashpolicy/__init__.py [deleted file]
rspec/model/Registry.ecore [deleted file]
rspec/model/planetlab.ecore [deleted file]
rspec/model/planetlab.ecore_diagram [deleted file]
rspec/model/planetlab.genmodel [deleted file]
rspec/model/planetlab.xsd [deleted file]
rspec/sample_rspec.xml [deleted file]
setup.py
sfa.spec
sfa/client/return_value.py [new file with mode: 0644]
sfa/client/sfi.py [changed mode: 0755->0644]
sfa/generic/__init__.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/driver.py [new file with mode: 0644]
sfa/managers/registry_manager.py
sfa/managers/slice_manager.py
sfa/methods/ListResources.py
sfa/methods/__init__.py
sfa/methods/get_key.py [deleted file]
sfa/methods/get_key_from_incoming_ip.py [new file with mode: 0644]
sfa/plc/aggregate.py
sfa/plc/plcomponentdriver.py
sfa/plc/pldriver.py
sfa/plc/plshell.py
sfa/plc/remoteshell.py [deleted file]
sfa/rspecs/elements/versions/pgv2Link.py
sfa/rspecs/elements/versions/pgv2Node.py
sfa/rspecs/elements/versions/pgv2Services.py
sfa/rspecs/elements/versions/sfav1Node.py
sfa/rspecs/elements/versions/sfav1Sliver.py
sfa/rspecs/pg_rspec_converter.py
sfa/rspecs/versions/pgv2.py
sfa/server/sfa_component_setup.py
sfa/server/sfaapi.py
sfa/util/config.py
sfa/util/faults.py
sfa/util/genicode.py
sfa/util/sfatablesRuntime.py
sfa/util/version.py.in

index b93abae..074d1fb 100644 (file)
@@ -1,146 +1,4 @@
-This installation note assumes that you have installed and configured MyPLC in the usual manner, and you have set up your yum repo like for a MyPLC install.
+Please refer to the trac page below for installing and using this software
 
-Once you have completed the server configuration, a brief introduction to the SFA user tools is here:
-    http://svn.planet-lab.org/wiki/SFAGuide
-
------
-1) Install the SFA packages:
-
-# yum install sfa-plc sfa-client
-
-Note that the above command installs both sfa server (sfa-plc) and sfa client packages along with necessary dependency packages. Depending on the requirements, you may choose to install the appropriate one (server, client or both) for you. For e.g. to set up your own SFA server on top of your MyPLC, you need sfa-plc. On the other hand, if you plan to use an existing SFA server, you would typically need the sfa-client only.
--------
-2) Note down the PLC_ROOT_USER, PLC_ROOT_PASSWORD, PLC_DB_USER and PLC_DB_PASSWORD of your MyPLC installation:
-
-# plc-config-tty 
-Enter command (u for usual changes, w to save, ? for help) s PLC_ROOT_USER
-PLC_ROOT_USER = root@test.onelab.eu
-Enter command (u for usual changes, w to save, ? for help) s PLC_ROOT_PASSWORD
-PLC_ROOT_PASSWORD = test++
-Enter command (u for usual changes, w to save, ? for help) s PLC_DB_USER
-PLC_DB_USER = pgsqluser
-Enter command (u for usual changes, w to save, ? for help) s PLC_DB_PASSWORD
-PLC_DB_PASSWORD = 4a333aba-a322-41b1-9c05-90b4f34d1332
-
-These four configuration parameters are required for SFA server configuration
--------
-3) Configure and start SFA servers: 
-
-(a) # sfa-config-tty
-
- set SFA_PLC_USER              to     PLC_ROOT_USER 
- set SFA_PLC_PASSWORD          to     PLC_ROOT_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
-
-(b) # sfa-import-plc.py 
-
-(o/p will look like this)
-Import: creating top level authorities
-Hierarchy: creating authority: plc
-plc : 
-Import: creating table for authority plc
-NOTICE:  table "sfa$plc" does not exist, skipping
-  inserting authority record for plc
-Import: adding plc to trusted list
-Import_Site: importing site plc.internet2
-Hierarchy: creating authority: plc.internet2
-  inserting authority record for plc.internet2
-Import_Site: importing site plc.pl
-Hierarchy: creating authority: plc.pl
-  inserting authority record for plc.pl
-Import: importing person plc.pl.root
-Import: creating table for authority plc.pl
-NOTICE:  table "sfa$plc$pl" does not exist, skipping
-
-(c)  run sfa-config-tty again and select q to come out of the config command
-This will initialize /etc/sfa/authorities/server.key from /etc/sfa/authorities/plc/plc.pkey 
-
-(d) # service sfa start
-This will start Registry, Slice Manager and Aggregate Manager. Your ps command output would look like:
-
-# ps -ef | grep python
-root     24944     1  0 May11 ?        00:00:00 /usr/bin/python /usr/bin/sfa-start.py -r -d
-root     24957     1  0 May11 ?        00:00:00 /usr/bin/python /usr/bin/sfa-start.py -a -d
-root     24970     1  0 May11 ?        00:00:00 /usr/bin/python /usr/bin/sfa-start.py -s -d
--------
-4) Configure SFA client:
-
- (a) # mkdir ~/.sfi 
- (b)copy your private RSA key to ~/.sfi/username.pkey Replace username with your actual account name.  NOTE: DSA KEYS WILL NOT WORK
- (c) # cp  /etc/sfa/sfi_config ~/.sfi/
- (d) edit ~/.sfi/sfi_config. A sample configuration looks like:
-
-       SFI_AUTH='plc.pl'
-       SFI_USER='plc.pl.root'
-       SFI_REGISTRY='http://vplc25.inria.fr:12345/'
-       SFI_SM='http://vplc25.inria.fr:12347/' 
-
-------
-5) Testing:
-
-At this stage you should be able to run sfi command. Some sample outputs are:
-
- (a) # sfi.py list plc.pl
-     plc.pl.netflow (slice)
-     plc.pl.sirius (slice)
-     plc.pl.root (user)
-     plc.pl.pif (node)
-
- (b) # sfi.py show plc.pl.pif
-     gid:
-          hrn: plc.pl.pif
-         uuid: 99878316891261700702442883738232624912
-     hrn: plc.pl.pif
-     type: node
-     node_type: regular
-     hostname: pif.inria.fr
- (c) # sfi.py show plc.pl.root
-       gid:
-          hrn: plc.pl.root
-         uuid: 67306954103472941609600457537601239401
-     hrn: plc.pl.root
-     type: user
-     last_name: Administrator
-     phone: None
-     key: plc.pl.root#user
-     first_name: Default
-     email: root@vplc25.inria.fr
-
- (d) # sfi.py slices
-     plc.pl.netflow
-     plc.pl.sirius
-
- (e) # sfi.py resources
-<?xml version="1.0" ?>
-<RSpec duration="3600" start_time="1246736949"><networks><NetSpec duration="3600" name="plc" start_time="1246736950"><nodes><NodeSpec cpu_min="" cpu_pct="" cpu_share="" disk_max="" duration="" init_params="" name="pif.inria.fr" start_time="" type=""><net_if><IfSpec addr="138.96.250.224" init_params="" ip_spoof="" max_kbyte="" max_rate="" min_rate="" name="True" type="ipv4"/></net_if></NodeSpec></nodes></NetSpec></networks></RSpec>
-------
-
-6) Federation configuration:
-
-(a) Follow the same procedure to install and configure second MyPLC with SFA server.
-(b) On each PLC, edit the /etc/sfa/registries.xml file
-
-    set addr to ip or hostname of federated (remote) peer
-    set port to sfa service port on federated (remote) peer
-    set hrn to human readable name of federated (remote) peer interface
-Sample configuration:
-
-<registries>
-       <registry addr="vplc26.inria.fr" hrn="ple" port="12345"/>
-</registries>
-
-(c) Likewise, edit the /etc/sfa/aggregates.xml
-Sampel configuration
-
-<aggregates>
-       <aggregate addr="vplc26.inria.fr" hrn="ple" port="12346"/>
-</aggregates>
-
-(d) trade trusted root gid's (seen on /etc/sfa/trusted_roots)
-we have to copy the gid of first SFA server to the /etc/sfa/trusted_roots directory of second one and vice-versa. 
+http://svn.planet-lab.org/wiki/SFATutorial#SFATutorial
 
diff --git a/README.txt b/README.txt
deleted file mode 100644 (file)
index 42255d4..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-This module (sfa) is installed as part of MyPLC, available as
-part of the PlanetLab development effort. For more information on
-accessing, installing, developing and deploying PlanetLab software,
-visit http://svn.planet-lab.org.
-
-For a brief introduction to the SFA user tools, please visit:
-    http://svn.planet-lab.org/wiki/SFAGuide
index e633a60..5427283 100644 (file)
@@ -18,12 +18,27 @@ 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="interface_hrn" type="string">
           <name>Human readable name</name>
           <value>plc</value>
           <description>The human readable name for this interface.</description>
         </variable>
 
+        <variable id="aggregate_api_version" type="int">
+          <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>
@@ -53,15 +68,6 @@ Thierry Parmentelat
             </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>
-
       </variablelist>
     </category>
 
@@ -194,6 +200,12 @@ Thierry Parmentelat
       <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>Enabled</name>
+         <value>true</value>
+         <description>Enable the database server on this machine.</description>
+       </variable>
+
        <variable id="host" type="hostname">
          <name>Database host</name>
          <value>localhost</value>
@@ -208,7 +220,7 @@ Thierry Parmentelat
 
        <variable id="user" type="string">
          <name>Database user</name>
-         <value>pgsqluser</value>
+         <value>sfadbuser</value>
          <description>When SFA gets co-hosted with a myplc, this should match the PLC config.</description>
        </variable>
 
index 1e99163..9fef0f9 100755 (executable)
@@ -22,8 +22,6 @@ usual_variables = [
     "SFA_PLC_USER",
     "SFA_PLC_PASSWORD",
     "SFA_DB_HOST",
-    "SFA_DB_USER",
-    "SFA_DB_PASSWORD",
     ]
 
 configuration={ \
diff --git a/flashpolicy/__init__.py b/flashpolicy/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/rspec/model/Registry.ecore b/rspec/model/Registry.ecore
deleted file mode 100644 (file)
index ae7ecac..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ecore:EPackage xmi:version="2.0"
-    xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="Registry"
-    nsURI="http://www.planet-lab.org/Registry" nsPrefix="Registry">
-  <eClassifiers xsi:type="ecore:EClass" name="UserRecord" eSuperTypes="#//RegistryRecord">
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="email" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
-        iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="first_name" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
-        iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="last_name" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
-        iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="phone" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
-        iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="key" ordered="false" lowerBound="1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="slice" upperBound="-1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" defaultValueLiteral=""/>
-  </eClassifiers>
-  <eClassifiers xsi:type="ecore:EClass" name="SliceRecord" eSuperTypes="#//RegistryRecord">
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" ordered="false" lowerBound="1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="url" ordered="false" lowerBound="1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="expires" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"
-        iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="researcher" lowerBound="1"
-        upperBound="-1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="description" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
-        iD="true"/>
-  </eClassifiers>
-  <eClassifiers xsi:type="ecore:EClass" name="NodeRecord" eSuperTypes="#//RegistryRecord">
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="hostname" lowerBound="1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" defaultValueLiteral=""/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="node_type" lowerBound="1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" defaultValueLiteral="&quot;user&quot;"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="latitude" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
-        iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="longitude" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"
-        iD="true"/>
-  </eClassifiers>
-  <eClassifiers xsi:type="ecore:EClass" name="Authority" eSuperTypes="#//RegistryRecord">
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" ordered="false" lowerBound="1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="last_updated" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"
-        iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="url" ordered="false" lowerBound="1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="researcher" upperBound="-1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="operator" lowerBound="1"
-        upperBound="-1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="PI" lowerBound="1" upperBound="-1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
-  </eClassifiers>
-  <eClassifiers xsi:type="ecore:EClass" name="RegistryRecord">
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="hrn" ordered="false" lowerBound="1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString" iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="gid" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="type" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
-        defaultValueLiteral=""/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="created" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"
-        iD="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="last_updated" ordered="false"
-        lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"
-        iD="true"/>
-  </eClassifiers>
-</ecore:EPackage>
diff --git a/rspec/model/planetlab.ecore b/rspec/model/planetlab.ecore
deleted file mode 100644 (file)
index 68dd1a7..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ecore:EPackage xmi:version="2.0"
-    xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="planetlab"
-    nsURI="http://www.planet-lab.org" nsPrefix="pl">
-  <eClassifiers xsi:type="ecore:EClass" name="RSpec">
-    <eStructuralFeatures xsi:type="ecore:EReference" name="networks" lowerBound="1"
-        upperBound="-1" eType="#//NetSpec"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="start_time" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="duration" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"/>
-  </eClassifiers>
-  <eClassifiers xsi:type="ecore:EClass" name="NetSpec">
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
-    <eStructuralFeatures xsi:type="ecore:EReference" name="nodes" lowerBound="1" upperBound="-1"
-        eType="#//NodeSpec"/>
-    <eStructuralFeatures xsi:type="ecore:EReference" name="links" upperBound="-1"
-        eType="#//LinkSpec" containment="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="start_time" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="duration" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"/>
-  </eClassifiers>
-  <eClassifiers xsi:type="ecore:EClass" name="NodeSpec">
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" upperBound="1000"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="type" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
-        defaultValueLiteral="&quot;&quot;"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="init_params" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EByteArray"
-        defaultValueLiteral=""/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="cpu_min" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"
-        defaultValueLiteral="0"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="cpu_share" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"
-        defaultValueLiteral="0"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="cpu_pct" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"
-        defaultValueLiteral="0"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="disk_max" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"
-        defaultValueLiteral="0"/>
-    <eStructuralFeatures xsi:type="ecore:EReference" name="net_if" lowerBound="1"
-        upperBound="-1" eType="#//IfSpec"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="start_time" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="duration" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"/>
-  </eClassifiers>
-  <eClassifiers xsi:type="ecore:EClass" name="LinkSpec">
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="type" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
-        changeable="false" defaultValueLiteral="&quot;&quot;"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="init_params" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EByteArray"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="bw" upperBound="-1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"
-        defaultValueLiteral="0"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="min_alloc" upperBound="-2"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="0"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="max_alloc" upperBound="-1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="0"/>
-    <eStructuralFeatures xsi:type="ecore:EReference" name="endpoint" lowerBound="1"
-        upperBound="-1" eType="#//IfSpec" changeable="false"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="start_time" upperBound="-2"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="duration" upperBound="-2"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"/>
-  </eClassifiers>
-  <eClassifiers xsi:type="ecore:EClass" name="IfSpec">
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="addr" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="type" upperBound="-2" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
-        changeable="false" defaultValueLiteral=""/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="init_params" upperBound="-2"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EByteArray"
-        defaultValueLiteral=""/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="min_rate" upperBound="-2"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="0"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="max_rate" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"
-        defaultValueLiteral="12207"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="max_kbyte" upperBound="-1"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="5452595"
-        unsettable="true"/>
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="ip_spoof" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"
-        defaultValueLiteral="false"/>
-  </eClassifiers>
-  <eClassifiers xsi:type="ecore:EClass" name="SwitchSpec" eSuperTypes="#//NodeSpec">
-    <eStructuralFeatures xsi:type="ecore:EAttribute" name="fib_max" upperBound="-2"
-        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="0"/>
-  </eClassifiers>
-</ecore:EPackage>
diff --git a/rspec/model/planetlab.ecore_diagram b/rspec/model/planetlab.ecore_diagram
deleted file mode 100644 (file)
index df5642b..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.1/notation" xmi:id="_kVhkUCK_Ed2y9bl2PJcv2g" type="Ecore" measurementUnit="Pixel">
-  <children xmi:type="notation:Node" xmi:id="_kWAFcCK_Ed2y9bl2PJcv2g" type="2001">
-    <children xmi:type="notation:Node" xmi:id="_kWAFcyK_Ed2y9bl2PJcv2g" type="5001"/>
-    <children xmi:type="notation:Node" xmi:id="_kWAFdCK_Ed2y9bl2PJcv2g" type="7001">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWAFdSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWAFdiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWAFdyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWAsgCK_Ed2y9bl2PJcv2g" type="7002">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWAsgSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWAsgiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWAsgyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWAshCK_Ed2y9bl2PJcv2g" type="7003">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWAshSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWAshiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWAshyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <styles xmi:type="notation:ShapeStyle" xmi:id="_kWAFcSK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EClass" href="planetlab.ecore#//Network"/>
-    <layoutConstraint xmi:type="notation:Bounds" xmi:id="_kWAFciK_Ed2y9bl2PJcv2g" x="114" y="55"/>
-  </children>
-  <children xmi:type="notation:Node" xmi:id="_kWAsiCK_Ed2y9bl2PJcv2g" type="2001">
-    <children xmi:type="notation:Node" xmi:id="_kWAsiyK_Ed2y9bl2PJcv2g" type="5001"/>
-    <children xmi:type="notation:Node" xmi:id="_kWAsjCK_Ed2y9bl2PJcv2g" type="7001">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWAsjSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWAsjiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWAsjyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWAskCK_Ed2y9bl2PJcv2g" type="7002">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWAskSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWAskiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWAskyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWBTkCK_Ed2y9bl2PJcv2g" type="7003">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWBTkSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWBTkiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWBTkyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <styles xmi:type="notation:ShapeStyle" xmi:id="_kWAsiSK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EClass" href="planetlab.ecore#//PLNode"/>
-    <layoutConstraint xmi:type="notation:Bounds" xmi:id="_kWAsiiK_Ed2y9bl2PJcv2g" x="242" y="167"/>
-  </children>
-  <children xmi:type="notation:Node" xmi:id="_kWBTlCK_Ed2y9bl2PJcv2g" type="2001">
-    <children xmi:type="notation:Node" xmi:id="_kWBTlyK_Ed2y9bl2PJcv2g" type="5001"/>
-    <children xmi:type="notation:Node" xmi:id="_kWBTmCK_Ed2y9bl2PJcv2g" type="7001">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWBTmSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWBTmiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWBTmyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWBTnCK_Ed2y9bl2PJcv2g" type="7002">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWBTnSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWBTniK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWBTnyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWBToCK_Ed2y9bl2PJcv2g" type="7003">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWBToSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWBToiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWBToyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <styles xmi:type="notation:ShapeStyle" xmi:id="_kWBTlSK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EClass" href="planetlab.ecore#//Link"/>
-    <layoutConstraint xmi:type="notation:Bounds" xmi:id="_kWBTliK_Ed2y9bl2PJcv2g" x="55" y="167"/>
-  </children>
-  <children xmi:type="notation:Node" xmi:id="_kWB6oCK_Ed2y9bl2PJcv2g" type="2001">
-    <children xmi:type="notation:Node" xmi:id="_kWB6oyK_Ed2y9bl2PJcv2g" type="5001"/>
-    <children xmi:type="notation:Node" xmi:id="_kWB6pCK_Ed2y9bl2PJcv2g" type="7001">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWB6pSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWB6piK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWB6pyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWB6qCK_Ed2y9bl2PJcv2g" type="7002">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWB6qSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWB6qiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWB6qyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWB6rCK_Ed2y9bl2PJcv2g" type="7003">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWB6rSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWB6riK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWB6ryK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <styles xmi:type="notation:ShapeStyle" xmi:id="_kWB6oSK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EClass" href="planetlab.ecore#//Endpoint"/>
-    <layoutConstraint xmi:type="notation:Bounds" xmi:id="_kWB6oiK_Ed2y9bl2PJcv2g" x="60" y="350"/>
-  </children>
-  <children xmi:type="notation:Node" xmi:id="_kWChsCK_Ed2y9bl2PJcv2g" type="2001">
-    <children xmi:type="notation:Node" xmi:id="_kWChsyK_Ed2y9bl2PJcv2g" type="5001"/>
-    <children xmi:type="notation:Node" xmi:id="_kWChtCK_Ed2y9bl2PJcv2g" type="7001">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWChtSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWChtiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWChtyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWChuCK_Ed2y9bl2PJcv2g" type="7002">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWChuSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWChuiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWChuyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWChvCK_Ed2y9bl2PJcv2g" type="7003">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWChvSK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWChviK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWChvyK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <styles xmi:type="notation:ShapeStyle" xmi:id="_kWChsSK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EClass" href="planetlab.ecore#//VININode"/>
-    <layoutConstraint xmi:type="notation:Bounds" xmi:id="_kWChsiK_Ed2y9bl2PJcv2g" x="410" y="55"/>
-  </children>
-  <children xmi:type="notation:Node" xmi:id="_kWChwCK_Ed2y9bl2PJcv2g" type="2001">
-    <children xmi:type="notation:Node" xmi:id="_kWDIwCK_Ed2y9bl2PJcv2g" type="5001"/>
-    <children xmi:type="notation:Node" xmi:id="_kWDIwSK_Ed2y9bl2PJcv2g" type="7001">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWDIwiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWDIwyK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWDIxCK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWDIxSK_Ed2y9bl2PJcv2g" type="7002">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWDIxiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWDIxyK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWDIyCK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWDIySK_Ed2y9bl2PJcv2g" type="7003">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWDIyiK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWDIyyK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWDIzCK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <styles xmi:type="notation:ShapeStyle" xmi:id="_kWChwSK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EClass" href="planetlab.ecore#//WirelessNode"/>
-    <layoutConstraint xmi:type="notation:Bounds" xmi:id="_kWChwiK_Ed2y9bl2PJcv2g" x="245" y="55"/>
-  </children>
-  <children xmi:type="notation:Node" xmi:id="_kWDIzSK_Ed2y9bl2PJcv2g" type="2005">
-    <children xmi:type="notation:Node" xmi:id="_kWDv0CK_Ed2y9bl2PJcv2g" type="5005"/>
-    <children xmi:type="notation:Node" xmi:id="_kWDv0SK_Ed2y9bl2PJcv2g" type="7011">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWDv0iK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWDv0yK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWDv1CK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWDv1SK_Ed2y9bl2PJcv2g" type="7012">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWDv1iK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWDv1yK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWDv2CK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <styles xmi:type="notation:ShapeStyle" xmi:id="_kWDIziK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EEnum" href="planetlab.ecore#//Address"/>
-    <layoutConstraint xmi:type="notation:Bounds" xmi:id="_kWDIzyK_Ed2y9bl2PJcv2g" x="546" y="55"/>
-  </children>
-  <children xmi:type="notation:Node" xmi:id="_kWDv2SK_Ed2y9bl2PJcv2g" type="2001">
-    <children xmi:type="notation:Node" xmi:id="_kWDv3CK_Ed2y9bl2PJcv2g" type="5001"/>
-    <children xmi:type="notation:Node" xmi:id="_kWDv3SK_Ed2y9bl2PJcv2g" type="7001">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWDv3iK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWEW4CK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWEW4SK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWEW4iK_Ed2y9bl2PJcv2g" type="7002">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWEW4yK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWEW5CK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWEW5SK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWEW5iK_Ed2y9bl2PJcv2g" type="7003">
-      <styles xmi:type="notation:DrawerStyle" xmi:id="_kWEW5yK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:SortingStyle" xmi:id="_kWEW6CK_Ed2y9bl2PJcv2g"/>
-      <styles xmi:type="notation:FilteringStyle" xmi:id="_kWEW6SK_Ed2y9bl2PJcv2g"/>
-    </children>
-    <styles xmi:type="notation:ShapeStyle" xmi:id="_kWDv2iK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EClass" href="planetlab.ecore#//Interface"/>
-    <layoutConstraint xmi:type="notation:Bounds" xmi:id="_kWDv2yK_Ed2y9bl2PJcv2g" x="412" y="167"/>
-  </children>
-  <styles xmi:type="notation:DiagramStyle" xmi:id="_kVhkUSK_Ed2y9bl2PJcv2g"/>
-  <element xmi:type="ecore:EPackage" href="planetlab.ecore#/"/>
-  <edges xmi:type="notation:Edge" xmi:id="_kWVcoCK_Ed2y9bl2PJcv2g" type="4002" source="_kWAFcCK_Ed2y9bl2PJcv2g" target="_kWAsiCK_Ed2y9bl2PJcv2g">
-    <children xmi:type="notation:Node" xmi:id="_kWWDsSK_Ed2y9bl2PJcv2g" type="6001">
-      <layoutConstraint xmi:type="notation:Location" xmi:id="_kWWDsiK_Ed2y9bl2PJcv2g" x="2" y="-19"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWWDsyK_Ed2y9bl2PJcv2g" type="6003">
-      <layoutConstraint xmi:type="notation:Location" xmi:id="_kWWDtCK_Ed2y9bl2PJcv2g" x="-18" y="5"/>
-    </children>
-    <styles xmi:type="notation:ConnectorStyle" xmi:id="_kWVcoSK_Ed2y9bl2PJcv2g"/>
-    <styles xmi:type="notation:FontStyle" xmi:id="_kWVcoiK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EReference" href="planetlab.ecore#//Network/nodes"/>
-    <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_kWWDsCK_Ed2y9bl2PJcv2g" points="[0, 26, -148, -121]$[148, 86, 0, -61]"/>
-  </edges>
-  <edges xmi:type="notation:Edge" xmi:id="_kWXR0CK_Ed2y9bl2PJcv2g" type="4003" source="_kWAFcCK_Ed2y9bl2PJcv2g" target="_kWBTlCK_Ed2y9bl2PJcv2g">
-    <children xmi:type="notation:Node" xmi:id="_kWX44CK_Ed2y9bl2PJcv2g" type="6002">
-      <layoutConstraint xmi:type="notation:Location" xmi:id="_kWX44SK_Ed2y9bl2PJcv2g" x="4" y="16"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWX44iK_Ed2y9bl2PJcv2g" type="6004">
-      <layoutConstraint xmi:type="notation:Location" xmi:id="_kWX44yK_Ed2y9bl2PJcv2g" x="2" y="28"/>
-    </children>
-    <styles xmi:type="notation:ConnectorStyle" xmi:id="_kWXR0SK_Ed2y9bl2PJcv2g"/>
-    <styles xmi:type="notation:FontStyle" xmi:id="_kWXR0iK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EReference" href="planetlab.ecore#//Network/links"/>
-    <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_kWXR0yK_Ed2y9bl2PJcv2g" points="[0, 26, 31, -121]$[-31, 86, 0, -61]"/>
-  </edges>
-  <edges xmi:type="notation:Edge" xmi:id="_kWZHACK_Ed2y9bl2PJcv2g" type="4002" source="_kWBTlCK_Ed2y9bl2PJcv2g" target="_kWB6oCK_Ed2y9bl2PJcv2g">
-    <children xmi:type="notation:Node" xmi:id="_kWZHBCK_Ed2y9bl2PJcv2g" type="6001">
-      <layoutConstraint xmi:type="notation:Location" xmi:id="_kWZHBSK_Ed2y9bl2PJcv2g" y="40"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kWZHBiK_Ed2y9bl2PJcv2g" type="6003">
-      <layoutConstraint xmi:type="notation:Location" xmi:id="_kWZHByK_Ed2y9bl2PJcv2g" x="-17" y="28"/>
-    </children>
-    <styles xmi:type="notation:ConnectorStyle" xmi:id="_kWZHASK_Ed2y9bl2PJcv2g"/>
-    <styles xmi:type="notation:FontStyle" xmi:id="_kWZHAiK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EReference" href="planetlab.ecore#//Link/endpoints"/>
-    <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_kWZHAyK_Ed2y9bl2PJcv2g" points="[0, 62, 0, -97]$[0, 122, 0, -37]"/>
-  </edges>
-  <edges xmi:type="notation:Edge" xmi:id="_kWf0sCK_Ed2y9bl2PJcv2g" type="4003" source="_kWChsCK_Ed2y9bl2PJcv2g" target="_kWDv2SK_Ed2y9bl2PJcv2g">
-    <children xmi:type="notation:Node" xmi:id="_kWhC0CK_Ed2y9bl2PJcv2g" type="6002">
-      <layoutConstraint xmi:type="notation:Location" xmi:id="_kWhC0SK_Ed2y9bl2PJcv2g" x="-4" y="-41"/>
-    </children>
-    <children xmi:type="notation:Node" xmi:id="_kW2aACK_Ed2y9bl2PJcv2g" type="6004">
-      <layoutConstraint xmi:type="notation:Location" xmi:id="_kW2aASK_Ed2y9bl2PJcv2g" x="-3" y="-27"/>
-    </children>
-    <styles xmi:type="notation:ConnectorStyle" xmi:id="_kWf0sSK_Ed2y9bl2PJcv2g"/>
-    <styles xmi:type="notation:FontStyle" xmi:id="_kWf0siK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xmi:type="ecore:EReference" href="planetlab.ecore#//VININode/interfaces"/>
-    <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_kWf0syK_Ed2y9bl2PJcv2g" points="[0, 26, -35, -121]$[35, 86, 0, -61]"/>
-  </edges>
-  <edges xmi:type="notation:Edge" xmi:id="_kW8goCK_Ed2y9bl2PJcv2g" type="4004" source="_kWChsCK_Ed2y9bl2PJcv2g" target="_kWAsiCK_Ed2y9bl2PJcv2g">
-    <styles xmi:type="notation:ConnectorStyle" xmi:id="_kW8goSK_Ed2y9bl2PJcv2g"/>
-    <styles xmi:type="notation:FontStyle" xmi:id="_kW8goiK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xsi:nil="true"/>
-    <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_kW8goyK_Ed2y9bl2PJcv2g" points="[0, 26, 151, -121]$[-151, 86, 0, -61]"/>
-  </edges>
-  <edges xmi:type="notation:Edge" xmi:id="_kW9uwCK_Ed2y9bl2PJcv2g" type="4004" source="_kWChwCK_Ed2y9bl2PJcv2g" target="_kWAsiCK_Ed2y9bl2PJcv2g">
-    <styles xmi:type="notation:ConnectorStyle" xmi:id="_kW9uwSK_Ed2y9bl2PJcv2g"/>
-    <styles xmi:type="notation:FontStyle" xmi:id="_kW9uwiK_Ed2y9bl2PJcv2g" fontName="Sans"/>
-    <element xsi:nil="true"/>
-    <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_kW9uwyK_Ed2y9bl2PJcv2g" points="[0, 26, 0, -121]$[0, 86, 0, -61]"/>
-  </edges>
-</notation:Diagram>
diff --git a/rspec/model/planetlab.genmodel b/rspec/model/planetlab.genmodel
deleted file mode 100644 (file)
index ce59a87..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<genmodel:GenModel xmi:version="2.0"
-    xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
-    xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" modelDirectory="/PlanetLab/src"
-    editDirectory="/PlanetLab.edit/src" editorDirectory="/PlanetLab.editor/src" modelPluginID="PlanetLab"
-    modelName="Planetlab" editPluginClass="planetlab.planetlab.provider.PlanetlabEditPlugin"
-    editorPluginClass="planetlab.planetlab.presentation.PlanetlabEditorPlugin" codeFormatting="true"
-    copyrightFields="false">
-  <foreignModel>planetlab.ecore</foreignModel>
-  <genPackages prefix="Planetlab" basePackage="planetlab" disposableProviderFactory="true"
-      ecorePackage="planetlab.ecore#/">
-    <genEnums typeSafeEnumCompatible="false" ecoreEnum="planetlab.ecore#//Address"/>
-    <genClasses ecoreClass="planetlab.ecore#//Network">
-      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference planetlab.ecore#//Network/nodes"/>
-      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference planetlab.ecore#//Network/links"/>
-    </genClasses>
-    <genClasses ecoreClass="planetlab.ecore#//PLNode">
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//PLNode/cpu_min"/>
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//PLNode/cpu_share"/>
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//PLNode/net_min_rate"/>
-    </genClasses>
-    <genClasses ecoreClass="planetlab.ecore#//Link">
-      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference planetlab.ecore#//Link/endpoints"/>
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//Link/min_bandwidth"/>
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//Link/max_bandwidth"/>
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//Link/link_kind"/>
-    </genClasses>
-    <genClasses ecoreClass="planetlab.ecore#//Endpoint">
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//Endpoint/addresses"/>
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//Endpoint/endpoint_kind"/>
-    </genClasses>
-    <genClasses ecoreClass="planetlab.ecore#//VININode">
-      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference planetlab.ecore#//VININode/interfaces"/>
-    </genClasses>
-    <genClasses ecoreClass="planetlab.ecore#//WirelessNode"/>
-    <genClasses ecoreClass="planetlab.ecore#//Interface">
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//Interface/min_bandwidth"/>
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//Interface/max_bandwidth"/>
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//Interface/interface_kind"/>
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//Interface/interface_address"/>
-      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute planetlab.ecore#//Interface/interface_name"/>
-    </genClasses>
-  </genPackages>
-</genmodel:GenModel>
diff --git a/rspec/model/planetlab.xsd b/rspec/model/planetlab.xsd
deleted file mode 100644 (file)
index c607602..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<xsd:schema xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:pl="http://www.planet-lab.org" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ecore:nsPrefix="pl" ecore:package="planetlab.planetlab" targetNamespace="http://www.planet-lab.org">
-  <xsd:import namespace="http://www.eclipse.org/emf/2002/Ecore" schemaLocation="platform:/plugin/org.eclipse.emf.ecore/model/Ecore.xsd"/>
-  <xsd:element ecore:ignore="true" name="RSpec" type="pl:RSpec"/>
-  <xsd:element ecore:ignore="true" name="NetSpec" type="pl:NetSpec"/>
-  <xsd:element ecore:ignore="true" name="NodeSpec" type="pl:NodeSpec"/>
-  <xsd:element ecore:ignore="true" name="LinkSpec" type="pl:LinkSpec"/>
-  <xsd:element ecore:ignore="true" name="IfSpec" type="pl:IfSpec"/>
-  <xsd:element ecore:ignore="true" name="SwitchSpec" type="pl:SwitchSpec"/>
-  <xsd:complexType name="RSpec">
-    <xsd:attribute ecore:reference="pl:NetSpec" name="networks" use="required">
-      <xsd:simpleType>
-        <xsd:list itemType="xsd:anyURI"/>
-      </xsd:simpleType>
-    </xsd:attribute>
-    <xsd:attribute ecore:name="start_time" name="start_time" type="ecore:EDate"/>
-    <xsd:attribute name="duration" type="ecore:EDate"/>
-  </xsd:complexType>
-  <xsd:complexType name="NetSpec">
-    <xsd:sequence>
-      <xsd:element ecore:resolveProxies="true" maxOccurs="unbounded" minOccurs="0" name="links" type="pl:LinkSpec"/>
-    </xsd:sequence>
-    <xsd:attribute name="name" type="ecore:EString"/>
-    <xsd:attribute ecore:reference="pl:NodeSpec" name="nodes" use="required">
-      <xsd:simpleType>
-        <xsd:list itemType="xsd:anyURI"/>
-      </xsd:simpleType>
-    </xsd:attribute>
-    <xsd:attribute ecore:name="start_time" name="start_time" type="ecore:EDate"/>
-    <xsd:attribute name="duration" type="ecore:EDate"/>
-  </xsd:complexType>
-  <xsd:complexType name="NodeSpec">
-    <xsd:sequence>
-      <xsd:element ecore:unique="true" maxOccurs="1000" name="name" nillable="true" type="ecore:EString"/>
-    </xsd:sequence>
-    <xsd:attribute default="&quot;&quot;" ecore:unsettable="false" name="type" type="ecore:EString"/>
-    <xsd:attribute default="" ecore:name="init_params" ecore:unsettable="false" name="init_params" type="ecore:EByteArray"/>
-    <xsd:attribute default="0" ecore:name="cpu_min" ecore:unsettable="false" name="cpu_min" type="ecore:EInt"/>
-    <xsd:attribute default="0" ecore:name="cpu_share" ecore:unsettable="false" name="cpu_share" type="ecore:EInt"/>
-    <xsd:attribute default="0" ecore:name="cpu_pct" ecore:unsettable="false" name="cpu_pct" type="ecore:EInt"/>
-    <xsd:attribute default="0" ecore:name="disk_max" ecore:unsettable="false" name="disk_max" type="ecore:EInt"/>
-    <xsd:attribute ecore:name="net_if" ecore:reference="pl:IfSpec" name="net_if" use="required">
-      <xsd:simpleType>
-        <xsd:list itemType="xsd:anyURI"/>
-      </xsd:simpleType>
-    </xsd:attribute>
-    <xsd:attribute ecore:name="start_time" name="start_time" type="ecore:EDate"/>
-    <xsd:attribute name="duration" type="ecore:EDate"/>
-  </xsd:complexType>
-  <xsd:complexType name="LinkSpec">
-    <xsd:sequence>
-      <xsd:element default="0" ecore:unique="true" maxOccurs="unbounded" minOccurs="0" name="bw" type="ecore:EInt"/>
-      <xsd:element default="0" ecore:name="max_alloc" ecore:unique="true" maxOccurs="unbounded" minOccurs="0" name="max_alloc" type="ecore:EInt"/>
-    </xsd:sequence>
-    <xsd:attribute default="&quot;&quot;" ecore:changeable="false" ecore:unsettable="false" name="type" type="ecore:EString"/>
-    <xsd:attribute ecore:name="init_params" name="init_params" type="ecore:EByteArray"/>
-    <xsd:attribute default="0" ecore:name="min_alloc" ecore:unsettable="false" name="min_alloc" type="ecore:EInt"/>
-    <xsd:attribute ecore:changeable="false" ecore:reference="pl:IfSpec" name="endpoint" use="required">
-      <xsd:simpleType>
-        <xsd:list itemType="xsd:anyURI"/>
-      </xsd:simpleType>
-    </xsd:attribute>
-    <xsd:attribute ecore:name="start_time" name="start_time" type="ecore:EDate"/>
-    <xsd:attribute name="duration" type="ecore:EDate"/>
-  </xsd:complexType>
-  <xsd:complexType name="IfSpec">
-    <xsd:sequence>
-      <xsd:element default="5452595" ecore:name="max_kbyte" ecore:unique="true" ecore:unsettable="true" maxOccurs="unbounded" minOccurs="0" name="max_kbyte" type="ecore:EInt"/>
-    </xsd:sequence>
-    <xsd:attribute name="name" type="ecore:EString"/>
-    <xsd:attribute name="addr" type="ecore:EString"/>
-    <xsd:attribute default="" ecore:changeable="false" ecore:unsettable="false" name="type" type="ecore:EString"/>
-    <xsd:attribute default="" ecore:name="init_params" ecore:unsettable="false" name="init_params" type="ecore:EByteArray"/>
-    <xsd:attribute default="0" ecore:name="min_rate" ecore:unsettable="false" name="min_rate" type="ecore:EInt"/>
-    <xsd:attribute default="12207" ecore:name="max_rate" ecore:unsettable="false" name="max_rate" type="ecore:EInt"/>
-    <xsd:attribute default="false" ecore:name="ip_spoof" ecore:unsettable="false" name="ip_spoof" type="ecore:EBoolean"/>
-  </xsd:complexType>
-  <xsd:complexType name="SwitchSpec">
-    <xsd:complexContent>
-      <xsd:extension base="pl:NodeSpec">
-        <xsd:attribute default="0" ecore:name="fib_max" ecore:unsettable="false" name="fib_max" type="ecore:EInt"/>
-      </xsd:extension>
-    </xsd:complexContent>
-  </xsd:complexType>
-</xsd:schema>
diff --git a/rspec/sample_rspec.xml b/rspec/sample_rspec.xml
deleted file mode 100644 (file)
index 886fc8a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<RSpec start_time="1235696400" duration="2419200">
-       <networks>
-               <NetSpec name="planetlab.us" start_time="1235696400" duration="2419200">
-                       <nodes>
-                               <NodeSpec name="planetlab-1.cs.princeton.edu" type="" init_params="" cpu_min="" cpu_share="" cpu_pct="" disk_max="" start_time="" duration="">
-                                       <net_if>
-                                               <IfSpec name="128.112.139.71" addr="128.112.139.71" type="ipv4" init_params="" min_rate="0" max_rate="10000000" max_kbyte="" ip_spoof="" />
-                                       </net_if>
-                               </NodeSpec>
-                               <NodeSpec name="planetlab-2.cs.princeton.edu" type="" init_params="" cpu_min="" cpu_share="" cpu_pct="" disk_max="" start_time="" duration="">
-                                       <net_if>
-                                               <IfSpec name="128.112.139.72" addr="128.112.139.72" type="ipv4" init_params="" min_rate="0" max_rate="10000000" max_kbyte="" ip_spoof="" />
-                                               <IfSpec name="128.112.139.120" addr="128.112.139.120" type="proxy" init_params="" min_rate="0" max_rate="" max_kbyte="" ip_spoof="" />
-                                               <IfSpec name="128.112.139.119" addr="128.112.139.119" type="proxy" init_params="" min_rate="0" max_rate="" max_kbyte="" ip_spoof="" />
-                                       </net_if>
-                               </NodeSpec>
-                       </nodes>
-               </NetSpec>
-               <NetSpec name="planetlab.eu" start_time="" duration="">
-                       <nodes>
-                               <NodeSpec name="onelab03.onelab.eu" type="" init_params="" cpu_min="" cpu_share="" cpu_pct="" disk_max="" start_time="" duration="">
-                                       <net_if>
-                                               <IfSpec name="128.112.139.321" addr="128.112.139.321" type="ipv4" init_params="" min_rate="0" max_rate="10000000" max_kbyte="" ip_spoof="" />
-                                       </net_if>
-                               </NodeSpec>
-                       </nodes>
-               </NetSpec>
-       </networks>
-</RSpec>
index a9735a0..47a1314 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -52,10 +52,11 @@ package_dirs = [
     'sfatables',
     'sfatables/commands',
     'sfatables/processors',
-    'flashpolicy',
     ]
 
 
+initscripts = [ 'sfa', 'sfa-cm' ]
+
 data_files = [('/etc/sfa/', [ 'config/aggregates.xml',
                               'config/registries.xml',
                               'config/default_config.xml',
@@ -71,7 +72,7 @@ data_files = [('/etc/sfa/', [ 'config/aggregates.xml',
                             ]),
               ('/etc/sfatables/matches/', glob('sfatables/matches/*.xml')),
               ('/etc/sfatables/targets/', glob('sfatables/targets/*.xml')),
-              ('/etc/init.d/', ['sfa/init.d/sfa', 'sfa/init.d/sfa-cm'])]
+              ('/etc/init.d/', [ "sfa/init.d/%s"%x for x in initscripts ])]
 
 # add sfatables processors as data_files
 processor_files = [f for f in glob('sfatables/processors/*') if os.path.isfile(f)]
@@ -82,15 +83,13 @@ for d in processor_subdirs:
     d_files = [f for f in glob(d + '/*') if os.path.isfile(f)]
     data_files.append((etc_dir, processor_files))
 
-initscripts = [ '/etc/init.d/sfa', '/etc/init.d/sfa-cm' ]
-
 if sys.argv[1] in ['uninstall', 'remove', 'delete', 'clean']:
     python_path = sys.path
     site_packages_path = [ os.path.join(p,'sfa') for p in python_path if p.endswith('site-packages')]
     site_packages_path += [ os.path.join(p,'sfatables') for p in python_path if p.endswith('site-packages')]
     remove_dirs = ['/etc/sfa/', '/etc/sfatables'] + site_packages_path
     remove_bins = [ '/usr/bin/' + os.path.basename(bin) for bin in bins ]
-    remove_files = remove_bins + initscripts
+    remove_files = remove_bins + [ "/etc/init.d/%s"%x for x in initscripts ]
 
     # remove files   
     for filepath in remove_files:
index 6505eaf..0ec3279 100644 (file)
--- a/sfa.spec
+++ b/sfa.spec
@@ -1,6 +1,6 @@
 %define name sfa
-%define version 1.1
-%define taglevel 4
+%define version 2.0
+%define taglevel 0
 
 %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,15 +18,18 @@ 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
@@ -35,6 +38,8 @@ Requires: python-dateutil
 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,
@@ -49,19 +54,11 @@ Requires: python-psycopg2
 #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
@@ -74,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
@@ -87,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.
@@ -104,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.  
  
@@ -119,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
@@ -149,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*
 
@@ -165,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*
@@ -201,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
diff --git a/sfa/client/return_value.py b/sfa/client/return_value.py
new file mode 100644 (file)
index 0000000..034dcd8
--- /dev/null
@@ -0,0 +1,22 @@
+
+class ReturnValue(dict):
+    
+
+    @staticmethod
+    def get_code(return_value):
+        return ReturnValue.get_key_value('code', return_value) 
+
+    @staticmethod
+    def get_value(return_value):
+        return ReturnValue.get_key_value('value', return_value) 
+
+    @staticmethod
+    def get_output(return_value):
+        return ReturnValue.get_key_value('output', return_value) 
+
+    @staticmethod
+    def get_key_value(key, return_value):
+        if isinstance(return_value, dict) and return_value.has_key(key):
+            return return_value.get(key)
+        else:
+            return return_value              
old mode 100755 (executable)
new mode 100644 (file)
index 64bc550..6299ce2
@@ -4,6 +4,7 @@
 
 import sys
 sys.path.append('.')
+
 import os, os.path
 import tempfile
 import socket
@@ -13,21 +14,26 @@ import pickle
 from lxml import etree
 from StringIO import StringIO
 from optparse import OptionParser
-from sfa.client.client_helper import pg_users_arg, sfa_users_arg
-from sfa.util.sfalogging import sfi_logger
+
 from sfa.trust.certificate import Keypair, Certificate
 from sfa.trust.gid import GID
 from sfa.trust.credential import Credential
 from sfa.trust.sfaticket import SfaTicket
-from sfa.util.record import SfaRecord, UserRecord, SliceRecord, NodeRecord, AuthorityRecord
-from sfa.rspecs.rspec import RSpec
-from sfa.rspecs.rspec_converter import RSpecConverter
+
+from sfa.util.sfalogging import sfi_logger
 from sfa.util.xrn import get_leaf, get_authority, hrn_to_urn
-import sfa.client.xmlrpcprotocol as xmlrpcprotocol
 from sfa.util.config import Config
 from sfa.util.version import version_core
 from sfa.util.cache import Cache
+from sfa.util.record import SfaRecord, UserRecord, SliceRecord, NodeRecord, AuthorityRecord
+
+from sfa.rspecs.rspec import RSpec
+from sfa.rspecs.rspec_converter import RSpecConverter
 from sfa.rspecs.version_manager import VersionManager
+from sfa.client.return_value import ReturnValue
+
+import sfa.client.xmlrpcprotocol as xmlrpcprotocol
+from sfa.client.client_helper import pg_users_arg, sfa_users_arg
 
 AGGREGATE_PORT=12346
 CM_PORT=12346
@@ -417,15 +423,15 @@ class Sfi:
 
         if cache:
             version = cache.get(cache_key)
-            
+
         if not version: 
-            version = server.GetVersion()
+            result = server.GetVersion()
+            version= ReturnValue.get_value(result)
             # cache version for 24 hours
             cache.add(cache_key, version, ttl= 60*60*24)
             self.logger.info("Updating cache file %s" % cache_file)
             cache.save_to_file(cache_file)
 
-
         return version   
         
 
@@ -912,7 +918,8 @@ class Sfi:
                 server=self.registry
             else:
                 server = self.server_proxy_from_opts(opts)
-            version=server.GetVersion()
+            result = server.GetVersion()
+            version = ReturnValue.get_value(result)
         for (k,v) in version.iteritems():
             print "%-20s: %s"%(k,v)
         if opts.file:
@@ -933,8 +940,9 @@ class Sfi:
         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)
+        result = server.ListSlices(*call_args)
+        value = ReturnValue.get_value(result)
+        display_list(value)
         return
     
     # show rspec for named slice
@@ -942,17 +950,19 @@ class Sfi:
         user_cred = self.get_user_cred().save_to_string(save_parents=True)
         server = self.slicemgr
         server = self.server_proxy_from_opts(opts)
-
-        options = {}
-
+   
+        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]
-           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:
             delegated_cred = self.delegate_cred(cred, get_authority(self.authority))
@@ -967,19 +977,14 @@ class Sfi:
                 # this must be a protogeni aggregate. We should request a v2 ad rspec
                 # regardless of what the client user requested 
                 options['rspec_version'] = version_manager.get_version('ProtoGENI 2').to_dict()     
-        #panos add info options
-        if opts.info:
-            options['info'] = opts.info 
 
-        call_args = [creds]
-        if self.server_supports_options_arg(server):
-            options = {'call_id': unique_call_id()}
-        call_args.append(options)
+        call_args = [creds, options]
         result = server.ListResources(*call_args)
+        value = ReturnValue.get_value(result)
         if opts.file is None:
-            display_rspec(result, opts.format)
+            display_rspec(value, opts.format)
         else:
-            save_rspec_to_file(result, opts.file)
+            save_rspec_to_file(value, opts.file)
         return
 
     # created named slice with given rspec
@@ -1031,11 +1036,12 @@ class Sfi:
             options = {'call_id': unique_call_id()}
             call_args.append(options)
         result = server.CreateSliver(*call_args)
+        value = ReturnValue.get_value(result)
         if opts.file is None:
-            print result
+            print value
         else:
-            save_rspec_to_file (result, opts.file)
-        return result
+            save_rspec_to_file (value, opts.file)
+        return value
 
     # get a ticket for the specified slice
     def get_ticket(self, opts, args):
@@ -1157,7 +1163,9 @@ class Sfi:
         if self.server_supports_options_arg(server):
             options = {'call_id': unique_call_id()}
             call_args.append(options)
-        return server.RenewSliver(*call_args)
+        result =  server.RenewSliver(*call_args)
+        value = ReturnValue.get_value(result)
+        return value
 
 
     def status(self, opts, args):
@@ -1174,9 +1182,10 @@ class Sfi:
             options = {'call_id': unique_call_id()}
             call_args.append(options)
         result = server.SliverStatus(*call_args)
-        print result
+        value = ReturnValue.get_value(result)
+        print value
         if opts.file:
-            save_variable_to_file(result, opts.file, opts.fileformat)
+            save_variable_to_file(value, opts.file, opts.fileformat)
 
 
     def shutdown(self, opts, args):
index 0f9043b..363f3dd 100644 (file)
@@ -46,7 +46,7 @@ class Generic:
     # see pl.py for an example
     # some descendant of SfaApi
     def api_class (self) : pass
-    # in practical terms these are modules for now
+    # the python classes to use to build up the context
     def registry_class (self) : pass
     def slicemgr_class (self) : pass
     def aggregate_class (self) : pass
@@ -64,9 +64,10 @@ class Generic:
         driver = self.make_driver (api.config, api.interface)
         ### arrange stuff together
         # add a manager wrapper
-        manager = ManagerWrapper(manager,api.interface)
-        api.manager=manager
+        manager_wrap = ManagerWrapper(manager,api.interface)
+        api.manager=manager_wrap
         # insert driver in manager
+        logger.info("Setting manager.driver, manager=%s"%manager)
         manager.driver=driver
         # add it in api as well for convenience
         api.driver=driver
index 15a5bc6..dad723b 100755 (executable)
@@ -70,9 +70,9 @@ def main():
     interface_hrn = config.SFA_INTERFACE_HRN
     keys_filename = config.config_path + os.sep + 'person_keys.py' 
     sfaImporter = sfaImport()
-    if config.SFA_API_DEBUG: sfaImporter.logger.setLevelDebug()
+    logger=sfaImporter.logger
+    if config.SFA_API_DEBUG: logger.setLevelDebug()
     shell = sfaImporter.shell
-    plc_auth = sfaImporter.plc_auth 
     
     # initialize registry db table
     table = SfaTable()
@@ -86,11 +86,11 @@ def main():
     sfaImporter.create_sm_client_record()
 
     # create interface records
-    sfaImporter.logger.info("Import: creating interface records")
+    logger.info("Import: creating interface records")
     sfaImporter.create_interface_records()
 
     # add local root authority's cert  to trusted list
-    sfaImporter.logger.info("Import: adding " + interface_hrn + " to trusted list")
+    logger.info("Import: adding " + interface_hrn + " to trusted list")
     authority = sfaImporter.AuthHierarchy.get_auth_info(interface_hrn)
     sfaImporter.TrustedRoots.add_gid(authority.get_gid_object())
 
@@ -112,13 +112,13 @@ def main():
         existing_hrns.append(result['hrn']) 
             
     # Get all plc sites
-    sites = shell.GetSites(plc_auth, {'peer_id': None})
+    sites = shell.GetSites({'peer_id': None})
     sites_dict = {}
     for site in sites:
         sites_dict[site['login_base']] = site 
     
     # Get all plc users
-    persons = shell.GetPersons(plc_auth, {'peer_id': None, 'enabled': True}, 
+    persons = shell.GetPersons({'peer_id': None, 'enabled': True}, 
                                ['person_id', 'email', 'key_ids', 'site_ids'])
     persons_dict = {}
     for person in persons:
@@ -126,7 +126,7 @@ def main():
         key_ids.extend(person['key_ids'])
 
     # Get all public keys
-    keys = shell.GetKeys(plc_auth, {'peer_id': None, 'key_id': key_ids})
+    keys = shell.GetKeys( {'peer_id': None, 'key_id': key_ids})
     keys_dict = {}
     for key in keys:
         keys_dict[key['key_id']] = key['key']
@@ -140,20 +140,20 @@ def main():
         person_keys[person['person_id']] = pubkeys
 
     # Get all plc nodes  
-    nodes = shell.GetNodes(plc_auth, {'peer_id': None}, ['node_id', 'hostname', 'site_id'])
+    nodes = shell.GetNodes( {'peer_id': None}, ['node_id', 'hostname', 'site_id'])
     nodes_dict = {}
     for node in nodes:
         nodes_dict[node['node_id']] = node
 
     # Get all plc slices
-    slices = shell.GetSlices(plc_auth, {'peer_id': None}, ['slice_id', 'name'])
+    slices = shell.GetSlices( {'peer_id': None}, ['slice_id', 'name'])
     slices_dict = {}
     for slice in slices:
         slices_dict[slice['slice_id']] = slice
     # start importing 
     for site in sites:
         site_hrn = _get_site_hrn(interface_hrn, site)
-        sfaImporter.logger.info("Importing site: %s" % site_hrn)
+        logger.info("Importing site: %s" % site_hrn)
 
         # import if hrn is not in list of existing hrns or if the hrn exists
         # but its not a site record
@@ -272,7 +272,7 @@ def main():
             sfaImporter.delete_record(record_hrn, type) 
                                    
     # save pub keys
-    sfaImporter.logger.info('Import: saving current pub keys')
+    logger.info('Import: saving current pub keys')
     save_keys(keys_filename, person_keys)                
         
 if __name__ == "__main__":
index 568fce8..082d3ed 100644 (file)
@@ -52,17 +52,12 @@ class sfaImport:
        self.AuthHierarchy = Hierarchy()
        self.config = Config()
        self.TrustedRoots = TrustedRoots(Config.get_trustedroots_dir(self.config))
-       self.plc_auth = self.config.get_plc_auth()
        self.root_auth = self.config.SFA_REGISTRY_ROOT_AUTH
         
-       # connect to planetlab
-       self.shell = None
-       if "Url" in self.plc_auth:
-          from sfa.plc.remoteshell import RemoteShell
-          self.shell = RemoteShell(self.logger)
-       else:
-          import PLC.Shell
-          self.shell = PLC.Shell.Shell(globals = globals())        
+       # should use a driver instead...
+       from sfa.plc.plshell import PlShell
+       # how to connect to planetlab 
+       self.shell = PlShell (self.config)
 
     def create_top_level_auth_records(self, hrn):
         """
@@ -145,7 +140,7 @@ class sfaImport:
             key_ids = person["key_ids"]
             # get the user's private key from the SSH keys they have uploaded
             # to planetlab
-            keys = self.shell.GetKeys(self.plc_auth, key_ids)
+            keys = self.shell.GetKeys(key_ids)
             key = keys[0]['key']
             pkey = None
             try:
index 08975dc..92c70ea 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 >& /dev/null
+           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 >& /dev/null
+       plc-config --category=sfa_db --variable=password --value=$PLC_DB_PASSWORD --save=$sfa_local_config $sfa_local_config >& /dev/null
+       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 >& /dev/null
+    else
+       psql -U postgres -c "ALTER USER $SFA_DB_USER WITH PASSWORD '$SFA_DB_PASSWORD'" template1 >& /dev/null
+    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 a31efc6..5fe1d6f 100644 (file)
@@ -25,8 +25,8 @@ class AggregateManager:
 
     def __init__ (self):
         # xxx Thierry : caching at the aggregate level sounds wrong...
-        #self.caching=True
-        self.caching=False
+        self.caching=True
+        #self.caching=False
     
     def GetVersion(self, api, options={}):
     
@@ -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': 2,
+                        '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)
     
@@ -254,7 +254,7 @@ class AggregateManager:
         return 1
     
     def DeleteSliver(self, api, xrn, creds, options={}):
-        call_id = option.get('call_id')
+        call_id = options.get('call_id')
         if Callids().already_handled(call_id): return ""
         (hrn, _) = urn_to_hrn(xrn)
         slicename = hrn_to_pl_slicename(hrn)
@@ -275,7 +275,7 @@ class AggregateManager:
         return 1
     
     def ListSlices(self, api, creds, options={}):
-        call_id = option.get('call_id')
+        call_id = options.get('call_id')
         if Callids().already_handled(call_id): return []
         # look in cache first
         if self.caching and api.cache:
@@ -295,10 +295,11 @@ class AggregateManager:
         return slice_urns
         
     def ListResources(self, api, creds, options={}):
-        call_id = option.get('call_id')
+        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()
@@ -311,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)
@@ -319,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:
index ff2428c..55e14ce 100644 (file)
@@ -689,13 +689,13 @@ class AggregateManagerEucalyptus:
                 ad_rspec_versions.append(rspec_version.to_dict())
             if rspec_version.content_type in ['*', 'request']:
                 request_rspec_versions.append(rspec_version.to_dict())
-        default_rspec_version = version_manager.get_version("sfa 1").to_dict()
         xrn=Xrn(api.hrn)
         version_more = {'interface':'aggregate',
+                        'sfa': 1,
+                        'geni_api': api.config.SFA_AGGREGATE_API_VERSION,
                         'testbed':'myplc',
                         'hrn':xrn.get_hrn(),
-                        'request_rspec_versions': request_rspec_versions,
-                        'ad_rspec_versions': ad_rspec_versions,
-                        'default_ad_rspec': default_rspec_version
+                        'geni_request_rspec_versions': request_rspec_versions,
+                        'geni_ad_rspec_versions': ad_rspec_versions,
                         }
         return version_core(version_more)
diff --git a/sfa/managers/driver.py b/sfa/managers/driver.py
new file mode 100644 (file)
index 0000000..7d4b5b2
--- /dev/null
@@ -0,0 +1,52 @@
+# 
+# an attempt to document what a driver class should provide, 
+# and implement reasonable defaults
+#
+
+class Driver:
+    
+    def __init__ (self): pass
+
+    # redefine this if you want to check again records 
+    # when running GetCredential
+    # This is to reflect the 'enabled' user field in planetlab testbeds
+    # expected retcod boolean
+    def is_enabled (self, record) : 
+        return True
+
+    # the following is used in Resolve (registry) when run in full mode
+    #     after looking up the sfa db, we wish to be able to display
+    #     testbed-specific info as well
+    # this at minima should fill in the 'researcher' field for slice records
+    def augment_records_with_testbed_info (self, sfa_records):
+        return sfa_records
+
+    # incoming record, as provided by the client to the Register API call
+    # expected retcod 'pointer'
+    # 'pointer' is typically an int db id, that makes sense in the testbed environment
+    # -1 if this feature is not relevant 
+    # here type will be 'authority'
+    def register (self, sfa_record, hrn, pub_key) : 
+        return -1
+
+    # incoming record is the existing sfa_record
+    # expected retcod boolean, error message logged if result is False
+    def remove (self, sfa_record): 
+        return True
+
+    # incoming are the sfa_record:
+    # (*) old_sfa_record is what we have in the db for that hrn
+    # (*) new_sfa_record is what was passed in the Update call
+    # expected retcod boolean, error message logged if result is False
+    # NOTE 1. about keys
+    # this is confusing because a user may have several ssh keys in 
+    # the planetlab database, but we need to pick one to generate its cert
+    # so as much as in principle we should be able to use new_sfa_record['keys']
+    # the manager code actually picks one (the first one), and it seems safer
+    # to pass it along rather than depending on the driver code to do the same
+    #
+    # NOTE 2. about keys
+    # when changing the ssh key through this method the gid gets changed too
+    # should anything be passed back to the caller in this case ?
+    def update (self, old_sfa_record, new_sfa_record, hrn, new_key): 
+        return True
index 941e4b0..da0b127 100644 (file)
@@ -1,14 +1,19 @@
 import types
 import time 
+# for get_key_from_incoming_ip
+import tempfile
+import os
+import commands
 
 from sfa.util.faults import RecordNotFound, AccountNotEnabled, PermissionError, MissingAuthority, \
-    UnknownSfaType, ExistingRecord
+    UnknownSfaType, ExistingRecord, NonExistingRecord
 from sfa.util.prefixTree import prefixTree
 from sfa.util.record import SfaRecord
 from sfa.util.table import SfaTable
-from sfa.util.xrn import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
+from sfa.util.xrn import Xrn, get_authority, hrn_to_urn, urn_to_hrn
 from sfa.util.plxrn import hrn_to_pl_login_base
 from sfa.util.version import version_core
+from sfa.util.sfalogging import logger
 
 from sfa.trust.gid import GID 
 from sfa.trust.credential import Credential
@@ -50,9 +55,7 @@ class RegistryManager:
     
         # verify_cancreate_credential requires that the member lists
         # (researchers, pis, etc) be filled in
-        api.driver.fill_record_info(record, api.aggregates)
-        if record['type']=='user':
-           if not record['enabled']:
+        if not self.driver.is_enabled (record):
               raise AccountNotEnabled(": PlanetLab account %s is not enabled. Please contact your site PI" %(record['email']))
     
         # get the callers gid
@@ -91,13 +94,14 @@ class RegistryManager:
     
     def Resolve(self, api, xrns, type=None, full=True):
     
-        # load all known registry names into a prefix tree and attempt to find
-        # the longest matching prefix
         if not isinstance(xrns, types.ListType):
+            xrns = [xrns]
+            # try to infer type if not set and we get a single input
             if not type:
                 type = Xrn(xrns).get_type()
-            xrns = [xrns]
         hrns = [urn_to_hrn(xrn)[0] for xrn in xrns] 
+        # load all known registry names into a prefix tree and attempt to find
+        # the longest matching prefix
         # create a dict where key is a registry hrn and its value is a
         # hrns at that registry (determined by the known prefix tree).  
         xrn_dict = {}
@@ -124,27 +128,41 @@ class RegistryManager:
             if registry_hrn != api.hrn:
                 credential = api.getCredential()
                 interface = api.registries[registry_hrn]
-                server = api.server_proxy(interface, credential)
-                peer_records = server.Resolve(xrns, credential)
+                server_proxy = api.server_proxy(interface, credential)
+                peer_records = server_proxy.Resolve(xrns, credential)
                 records.extend([SfaRecord(dict=record).as_dict() for record in peer_records])
     
         # try resolving the remaining unfound records at the local registry
-        remaining_hrns = set(hrns).difference([record['hrn'] for record in records])
-        # convert set to list
-        remaining_hrns = [hrn for hrn in remaining_hrns] 
+        local_hrns = list ( set(hrns).difference([record['hrn'] for record in records]) )
+        # 
         table = SfaTable()
-        local_records = table.findObjects({'hrn': remaining_hrns})
+        local_records = table.findObjects({'hrn': local_hrns})
+        
         if full:
-            api.driver.fill_record_info(local_records, api.aggregates)
+            # in full mode we get as much info as we can, which involves contacting the 
+            # testbed for getting implementation details about the record
+            self.driver.augment_records_with_testbed_info(local_records)
+            # also we fill the 'url' field for known authorities
+            # used to be in the driver code, sounds like a poorman thing though
+            def solve_neighbour_url (record):
+                if not record['type'].startswith('authority'): return 
+                hrn=record['hrn']
+                for neighbour_dict in [ api.aggregates, api.registries ]:
+                    if hrn in neighbour_dict:
+                        record['url']=neighbour_dict[hrn].get_url()
+                        return 
+            [ solve_neighbour_url (record) for record in local_records ]
+                    
+        
         
         # convert local record objects to dicts
         records.extend([dict(record) for record in local_records])
-        if not records:
-            raise RecordNotFound(str(hrns))
-    
         if type:
             records = filter(lambda rec: rec['type'] in [type], records)
     
+        if not records:
+            raise RecordNotFound(str(hrns))
+    
         return records
     
     def List(self, api, xrn, origin_hrn=None):
@@ -167,8 +185,8 @@ class RegistryManager:
         if registry_hrn != api.hrn:
             credential = api.getCredential()
             interface = api.registries[registry_hrn]
-            server = api.server_proxy(interface, credential)
-            record_list = server.List(xrn, credential)
+            server_proxy = api.server_proxy(interface, credential)
+            record_list = server_proxy.List(xrn, credential)
             records = [SfaRecord(dict=record).as_dict() for record in record_list]
         
         # if we still have not found the record yet, try the local registry
@@ -194,6 +212,22 @@ class RegistryManager:
         gid = api.auth.hierarchy.create_gid(xrn, create_uuid(), pkey) 
         return gid.save_to_string(save_parents=True)
         
+    # utility for handling relationships among the SFA objects 
+    # given that the SFA db does not handle this sort of relationsships
+    # it will rely on side-effects in the testbed to keep this persistent
+    # field_key is the name of one field in the record, typically 'researcher' for a 'slice' record
+    # hrns is the list of hrns that should be linked to the subject from now on
+    # target_type would be e.g. 'user' in the 'slice' x 'researcher' example
+    def update_relation (self, sfa_record, field_key, hrns, target_type):
+        # locate the linked objects in our db
+        subject_type=sfa_record['type']
+        subject_id=sfa_record['pointer']
+        table = SfaTable()
+        link_sfa_records = table.find ({'type':target_type, 'hrn': hrns})
+        link_ids = [ rec.get('pointer') for rec in link_sfa_records ]
+        self.driver.update_relation (subject_type, target_type, subject_id, link_ids)
+        
+
     def Register(self, api, record):
     
         hrn, type = record['hrn'], record['type']
@@ -210,19 +244,17 @@ class RegistryManager:
            
         record = SfaRecord(dict = record)
         record['authority'] = get_authority(record['hrn'])
-        type = record['type']
-        hrn = record['hrn']
         auth_info = api.auth.get_auth_info(record['authority'])
         pub_key = None
         # make sure record has a gid
         if 'gid' not in record:
             uuid = create_uuid()
             pkey = Keypair(create=True)
-            if 'key' in record and record['key']:
-                if isinstance(record['key'], types.ListType):
-                    pub_key = record['key'][0]
-                else:
-                    pub_key = record['key']
+            if 'keys' in record and record['keys']:
+                pub_key=record['keys']
+                # use only first key in record
+                if isinstance(record['keys'], types.ListType):
+                    pub_key = record['keys'][0]
                 pkey = convert_public_key(pub_key)
     
             gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey)
@@ -238,67 +270,17 @@ class RegistryManager:
             # get the GID from the newly created authority
             gid = auth_info.get_gid_object()
             record.set_gid(gid.save_to_string(save_parents=True))
-            pl_record = api.driver.sfa_fields_to_pl_fields(type, hrn, record)
-            sites = api.driver.GetSites([pl_record['login_base']])
-            if not sites:
-                pointer = api.driver.AddSite(pl_record)
-            else:
-                pointer = sites[0]['site_id']
-    
-            record.set_pointer(pointer)
-            record['pointer'] = pointer
-    
-        elif (type == "slice"):
-            acceptable_fields=['url', 'instantiation', 'name', 'description']
-            pl_record = api.driver.sfa_fields_to_pl_fields(type, hrn, record)
-            for key in pl_record.keys():
-                if key not in acceptable_fields:
-                    pl_record.pop(key)
-            slices = api.driver.GetSlices([pl_record['name']])
-            if not slices:
-                 pointer = api.driver.AddSlice(pl_record)
-            else:
-                 pointer = slices[0]['slice_id']
-            record.set_pointer(pointer)
-            record['pointer'] = pointer
-    
-        elif  (type == "user"):
-            persons = api.driver.GetPersons([record['email']])
-            if not persons:
-                pointer = api.driver.AddPerson(dict(record))
-            else:
-                pointer = persons[0]['person_id']
-    
-            if 'enabled' in record and record['enabled']:
-                api.driver.UpdatePerson(pointer, {'enabled': record['enabled']})
-            # add this persons to the site only if he is being added for the first
-            # time by sfa and doesont already exist in plc
-            if not persons or not persons[0]['site_ids']:
-                login_base = get_leaf(record['authority'])
-                api.driver.AddPersonToSite(pointer, login_base)
-    
-            # What roles should this user have?
-            api.driver.AddRoleToPerson('user', pointer)
-            # Add the user's key
-            if pub_key:
-                api.driver.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
-    
-        elif (type == "node"):
-            pl_record = api.driver.sfa_fields_to_pl_fields(type, hrn, record)
-            login_base = hrn_to_pl_login_base(record['authority'])
-            nodes = api.driver.GetNodes([pl_record['hostname']])
-            if not nodes:
-                pointer = api.driver.AddNode(login_base, pl_record)
-            else:
-                pointer = nodes[0]['node_id']
-    
-        record['pointer'] = pointer
+
+        # update testbed-specific data f needed
+        logger.info("Getting driver from manager=%s"%self)
+        pointer = self.driver.register (record, hrn, pub_key)
+
         record.set_pointer(pointer)
         record_id = table.insert(record)
         record['record_id'] = record_id
     
         # update membership for researchers, pis, owners, operators
-        api.driver.update_membership(None, record)
+        self.update_relation(record, 'researcher', record.get('researcher'), 'user')
     
         return record.get_gid_object().save_to_string(save_parents=True)
     
@@ -315,75 +297,39 @@ class RegistryManager:
         record = records[0]
         record['last_updated'] = time.gmtime()
     
-        # Update_membership needs the membership lists in the existing record
-        # filled in, so it can see if members were added or removed
-        api.driver.fill_record_info(record, api.aggregates)
-    
+        # validate the type
+        if type not in ['authority', 'slice', 'node', 'user']:
+            raise UnknownSfaType(type) 
+
         # Use the pointer from the existing record, not the one that the user
         # gave us. This prevents the user from inserting a forged pointer
         pointer = record['pointer']
-        # update the PLC information that was specified with the record
     
-        if (type == "authority"):
-            api.driver.UpdateSite(pointer, new_record)
-    
-        elif type == "slice":
-            pl_record=api.driver.sfa_fields_to_pl_fields(type, hrn, new_record)
-            if 'name' in pl_record:
-                pl_record.pop('name')
-                api.driver.UpdateSlice(pointer, pl_record)
-    
-        elif type == "user":
-            # SMBAKER: UpdatePerson only allows a limited set of fields to be
-            #    updated. Ideally we should have a more generic way of doing
-            #    this. I copied the field names from UpdatePerson.py...
-            update_fields = {}
-            all_fields = new_record
-            for key in all_fields.keys():
-                if key in ['first_name', 'last_name', 'title', 'email',
-                           'password', 'phone', 'url', 'bio', 'accepted_aup',
-                           'enabled']:
-                    update_fields[key] = all_fields[key]
-            api.driver.UpdatePerson(pointer, update_fields)
-    
-            if 'key' in new_record and new_record['key']:
-                # must check this key against the previous one if it exists
-                persons = api.driver.GetPersons([pointer], ['key_ids'])
-                person = persons[0]
-                keys = person['key_ids']
-                keys = api.driver.GetKeys(person['key_ids'])
-                key_exists = False
-                if isinstance(new_record['key'], types.ListType):
-                    new_key = new_record['key'][0]
-                else:
-                    new_key = new_record['key']
-                
-                # Delete all stale keys
-                for key in keys:
-                    if new_record['key'] != key['key']:
-                        api.driver.DeleteKey(key['key_id'])
-                    else:
-                        key_exists = True
-                if not key_exists:
-                    api.driver.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
-    
-                # update the openssl key and gid
-                pkey = convert_public_key(new_key)
-                uuid = create_uuid()
-                gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey)
-                gid = gid_object.save_to_string(save_parents=True)
-                record['gid'] = gid
-                record = SfaRecord(dict=record)
-                table.update(record)
-    
-        elif type == "node":
-            api.driver.UpdateNode(pointer, new_record)
-    
-        else:
-            raise UnknownSfaType(type)
+        # is the a change in keys ?
+        new_key=None
+        if type=='user':
+            if 'keys' in new_record and new_record['keys']:
+                new_key=new_record['keys']
+                if isinstance (new_key,types.ListType):
+                    new_key=new_key[0]
+
+        # update the PLC information that was specified with the record
+        if not self.driver.update (record, new_record, hrn, new_key):
+            logger.warning("driver.update failed")
     
+        # take new_key into account
+        if new_key:
+            # update the openssl key and gid
+            pkey = convert_public_key(new_key)
+            uuid = create_uuid()
+            gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey)
+            gid = gid_object.save_to_string(save_parents=True)
+            record['gid'] = gid
+            record = SfaRecord(dict=record)
+            table.update(record)
+        
         # update membership for researchers, pis, owners, operators
-        api.driver.update_membership(record, new_record)
+        self.update_relation(record, 'researcher', new_record.get('researcher'), 'user')
         
         return 1 
     
@@ -401,7 +347,10 @@ class RegistryManager:
         if not records: raise RecordNotFound(hrn)
         record = records[0]
         type = record['type']
-    
+        
+        if type not in ['slice', 'user', 'node', 'authority'] :
+            raise UnknownSfaType(type)
+
         credential = api.getCredential()
         registries = api.registries
     
@@ -414,24 +363,77 @@ class RegistryManager:
                         result=registries[registry].remove_peer_object(credential, record, origin_hrn)
                     except:
                         pass
-        if type == "user":
-            persons = api.driver.GetPersons(record['pointer'])
-            # only delete this person if he has site ids. if he doesnt, it probably means
-            # he was just removed from a site, not actually deleted
-            if persons and persons[0]['site_ids']:
-                api.driver.DeletePerson(record['pointer'])
-        elif type == "slice":
-            if api.driver.GetSlices(record['pointer']):
-                api.driver.DeleteSlice(record['pointer'])
-        elif type == "node":
-            if api.driver.GetNodes(record['pointer']):
-                api.driver.DeleteNode(record['pointer'])
-        elif type == "authority":
-            if api.driver.GetSites(record['pointer']):
-                api.driver.DeleteSite(record['pointer'])
-        else:
-            raise UnknownSfaType(type)
-    
+
+        # call testbed callback first
+        # IIUC this is done on the local testbed TOO because of the refreshpeer link
+        if not self.driver.remove(record):
+            logger.warning("driver.remove failed")
+
+        # delete from sfa db
         table.remove(record)
     
         return 1
+
+    # This is a PLC-specific thing...
+    def get_key_from_incoming_ip (self, api):
+        # verify that the callers's ip address exist in the db and is an interface
+        # for a node in the db
+        (ip, port) = api.remote_addr
+        interfaces = self.driver.GetInterfaces({'ip': ip}, ['node_id'])
+        if not interfaces:
+            raise NonExistingRecord("no such ip %(ip)s" % locals())
+        nodes = self.driver.GetNodes([interfaces[0]['node_id']], ['node_id', 'hostname'])
+        if not nodes:
+            raise NonExistingRecord("no such node using ip %(ip)s" % locals())
+        node = nodes[0]
+       
+        # look up the sfa record
+        table = SfaTable()
+        records = table.findObjects({'type': 'node', 'pointer': node['node_id']})
+        if not records:
+            raise RecordNotFound("pointer:" + str(node['node_id']))  
+        record = records[0]
+        
+        # generate a new keypair and gid
+        uuid = create_uuid()
+        pkey = Keypair(create=True)
+        urn = hrn_to_urn(record['hrn'], record['type'])
+        gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey)
+        gid = gid_object.save_to_string(save_parents=True)
+        record['gid'] = gid
+        record.set_gid(gid)
+
+        # update the record
+        table.update(record)
+  
+        # attempt the scp the key
+        # and gid onto the node
+        # this will only work for planetlab based components
+        (kfd, key_filename) = tempfile.mkstemp() 
+        (gfd, gid_filename) = tempfile.mkstemp() 
+        pkey.save_to_file(key_filename)
+        gid_object.save_to_file(gid_filename, save_parents=True)
+        host = node['hostname']
+        key_dest="/etc/sfa/node.key"
+        gid_dest="/etc/sfa/node.gid" 
+        scp = "/usr/bin/scp" 
+        #identity = "/etc/planetlab/root_ssh_key.rsa"
+        identity = "/etc/sfa/root_ssh_key"
+        scp_options=" -i %(identity)s " % locals()
+        scp_options+="-o StrictHostKeyChecking=no " % locals()
+        scp_key_command="%(scp)s %(scp_options)s %(key_filename)s root@%(host)s:%(key_dest)s" %\
+                         locals()
+        scp_gid_command="%(scp)s %(scp_options)s %(gid_filename)s root@%(host)s:%(gid_dest)s" %\
+                         locals()    
+
+        all_commands = [scp_key_command, scp_gid_command]
+        
+        for command in all_commands:
+            (status, output) = commands.getstatusoutput(command)
+            if status:
+                raise Exception, output
+
+        for filename in [key_filename, gid_filename]:
+            os.unlink(filename)
+
+        return 1 
index 6f012e7..9eef80b 100644 (file)
@@ -12,20 +12,18 @@ from sfa.util.sfalogging import logger
 from sfa.util.xrn import Xrn, urn_to_hrn
 from sfa.util.version import version_core
 from sfa.util.callids import Callids
-
 from sfa.server.threadmanager import ThreadManager
-
 from sfa.rspecs.rspec_converter import RSpecConverter
 from sfa.rspecs.version_manager import VersionManager
 from sfa.rspecs.rspec import RSpec 
 from sfa.client.client_helper import sfa_to_pg_users_arg
+from sfa.client.return_value import ReturnValue
 
 class SliceManager:
     def __init__ (self):
     #    self.caching=False
         self.caching=True
         
-    
     def _options_supported(self, api, server):
         """
         Returns true if server support the optional call_id arg, false otherwise.
@@ -65,15 +63,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
@@ -124,7 +122,9 @@ class SliceManager:
             try:
                 version = api.get_cached_server_version(server)
                 # force ProtoGENI aggregates to give us a v2 RSpec
-                if 'sfa' not in version.keys():
+                if 'sfa' in version.keys():
+                    my_opts['rspec_version'] = version_manager.get_version('SFA 1').to_dict()
+                else:
                     my_opts['rspec_version'] = version_manager.get_version('ProtoGENI 2').to_dict()
                 rspec = server.ListResources(*args)
                 return {"aggregate": aggregate, "rspec": rspec, "elapsed": time.time()-tStart, "status": "success"}
@@ -168,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()
@@ -182,7 +182,7 @@ class SliceManager:
             self.add_slicemgr_stat(rspec, "ListResources", result["aggregate"], result["elapsed"], result["status"], result.get("exc_info",None))
             if result["status"]=="success":
                 try:
-                    rspec.version.merge(result["rspec"])
+                    rspec.version.merge(ReturnValue.get_value(result["rspec"]))
                 except:
                     api.logger.log_exc("SM.ListResources: Failed to merge aggregate rspec")
     
@@ -220,7 +220,7 @@ class SliceManager:
                 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 = option.get('call_id')
+        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
@@ -261,7 +261,7 @@ class SliceManager:
             self.add_slicemgr_stat(result_rspec, "CreateSliver", result["aggregate"], result["elapsed"], result["status"], result.get("exc_info",None))
             if result["status"]=="success":
                 try:
-                    result_rspec.version.merge(result["rspec"])
+                    result_rspec.version.merge(ReturnValue.get_value(result["rspec"]))
                 except:
                     api.logger.log_exc("SM.CreateSliver: Failed to merge aggregate rspec")
         return result_rspec.toxml()
@@ -274,7 +274,7 @@ class SliceManager:
                 args.append(options)
             return server.RenewSliver(*args)
     
-        call_id = option.get('call_id')
+        call_id = options.get('call_id')
         if Callids().already_handled(call_id): return True
     
         (hrn, type) = urn_to_hrn(xrn)
@@ -296,7 +296,8 @@ class SliceManager:
             server = api.server_proxy(interface, cred)
             threads.run(_RenewSliver, server, xrn, [cred], expiration_time, call_id)
         # 'and' the results
-        return reduce (lambda x,y: x and y, threads.get_results() , True)
+        results = [ReturnValue.get_value(result) for result in threads.get_results()]
+        return reduce (lambda x,y: x and y, results , True)
     
     def DeleteSliver(self, api, xrn, creds, options={}):
         def _DeleteSliver(server, xrn, creds, options={}):
@@ -306,7 +307,7 @@ class SliceManager:
                 args.append(options)
             return server.DeleteSliver(*args)
 
-        call_id = option.get('call_id') 
+        call_id = options.get('call_id') 
         if Callids().already_handled(call_id): return ""
         (hrn, type) = urn_to_hrn(xrn)
         # get the callers hrn
@@ -350,7 +351,7 @@ class SliceManager:
             interface = api.aggregates[aggregate]
             server = api.server_proxy(interface, cred)
             threads.run (_SliverStatus, server, slice_xrn, [cred], call_id)
-        results = threads.get_results()
+        results = [ReturnValue.get_value(result) for result in threads.get_results()]
     
         # get rid of any void result - e.g. when call_id was hit where by convention we return {}
         results = [ result for result in results if result and result['geni_resources']]
@@ -407,10 +408,10 @@ class SliceManager:
                 continue
             interface = api.aggregates[aggregate]
             server = api.server_proxy(interface, cred)
-            threads.run(_ListSlices, server, [cred], call_id, options)
+            threads.run(_ListSlices, server, [cred], options)
     
         # combime results
-        results = threads.get_results()
+        results = [ReturnValue.get_value(result) for result in threads.get_results()]
         slices = []
         for result in results:
             slices.extend(result)
index 38634de..6b1e785 100644 (file)
@@ -35,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, options)
+        rspec = self.api.manager.ListResources(self.api, creds, options)
 
         # filter rspec through sfatables 
         if self.api.interface in ['aggregate']:
index 0e47df6..8f35200 100644 (file)
@@ -23,7 +23,7 @@ Start
 Stop
 Update
 UpdateSliver
-get_key
+get_key_from_incoming_ip
 get_trusted_certs
 reset_slice
 """.split()
diff --git a/sfa/methods/get_key.py b/sfa/methods/get_key.py
deleted file mode 100644 (file)
index 1195d53..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-import os
-import tempfile
-import commands
-from sfa.util.faults import NonExistingRecord, RecordNotFound
-from sfa.util.xrn import hrn_to_urn
-from sfa.util.method import Method
-from sfa.util.parameter import Parameter
-from sfa.util.table import SfaTable
-from sfa.trust.certificate import Keypair
-from sfa.trust.gid import create_uuid
-
-class get_key(Method):
-    """
-    Generate a new keypair and gid for requesting caller (component).     
-    @return 1 If successful  
-    """
-
-    interfaces = ['registry']
-    
-    accepts = []
-
-    returns = Parameter(int, "1 if successful, faults otherwise")
-    
-    def call(self):
-        # verify that the callers's ip address exist in the db and is an interface
-        # for a node in the db
-        (ip, port) = self.api.remote_addr
-        interfaces = self.api.driver.GetInterfaces({'ip': ip}, ['node_id'])
-        if not interfaces:
-            raise NonExistingRecord("no such ip %(ip)s" % locals())
-        nodes = self.api.driver.GetNodes([interfaces[0]['node_id']], ['node_id', 'hostname'])
-        if not nodes:
-            raise NonExistingRecord("no such node using ip %(ip)s" % locals())
-        node = nodes[0]
-       
-        # look up the sfa record
-        table = SfaTable()
-        records = table.findObjects({'type': 'node', 'pointer': node['node_id']})
-        if not records:
-            raise RecordNotFound("pointer:" + str(node['node_id']))  
-        record = records[0]
-        
-        # generate a new keypair and gid
-        uuid = create_uuid()
-        pkey = Keypair(create=True)
-        urn = hrn_to_urn(record['hrn'], record['type'])
-        gid_object = self.api.auth.hierarchy.create_gid(urn, uuid, pkey)
-        gid = gid_object.save_to_string(save_parents=True)
-        record['gid'] = gid
-        record.set_gid(gid)
-
-        # update the record
-        table.update(record)
-  
-        # attempt the scp the key
-        # and gid onto the node
-        # this will only work for planetlab based components
-        (kfd, key_filename) = tempfile.mkstemp() 
-        (gfd, gid_filename) = tempfile.mkstemp() 
-        pkey.save_to_file(key_filename)
-        gid_object.save_to_file(gid_filename, save_parents=True)
-        host = node['hostname']
-        key_dest="/etc/sfa/node.key"
-        gid_dest="/etc/sfa/node.gid" 
-        scp = "/usr/bin/scp" 
-        #identity = "/etc/planetlab/root_ssh_key.rsa"
-        identity = "/etc/sfa/root_ssh_key"
-        scp_options=" -i %(identity)s " % locals()
-        scp_options+="-o StrictHostKeyChecking=no " % locals()
-        scp_key_command="%(scp)s %(scp_options)s %(key_filename)s root@%(host)s:%(key_dest)s" %\
-                         locals()
-        scp_gid_command="%(scp)s %(scp_options)s %(gid_filename)s root@%(host)s:%(gid_dest)s" %\
-                         locals()    
-
-        all_commands = [scp_key_command, scp_gid_command]
-        
-        for command in all_commands:
-            (status, output) = commands.getstatusoutput(command)
-            if status:
-                raise Exception, output
-
-        for filename in [key_filename, gid_filename]:
-            os.unlink(filename)
-
-        return 1 
diff --git a/sfa/methods/get_key_from_incoming_ip.py b/sfa/methods/get_key_from_incoming_ip.py
new file mode 100644 (file)
index 0000000..c7abb75
--- /dev/null
@@ -0,0 +1,23 @@
+from sfa.util.method import Method
+from sfa.util.parameter import Parameter
+from sfa.util.sfalogging import logger
+
+class get_key_from_incoming_ip(Method):
+    """
+    Generate a new keypair and gid for requesting caller (component/node).     
+    This is a myplc-specific API call used by component manager
+    @return 1 If successful  
+    """
+
+    interfaces = ['registry']
+    
+    accepts = []
+
+    returns = Parameter(int, "1 if successful, faults otherwise")
+    
+    def call(self):
+        if hasattr(self.api.manager,'get_key_from_incoming_ip'):
+            return self.api.manager.get_key_from_incoming_ip (api)
+        else:
+            logger.warning("get_key_from_incoming_ip not supported by registry manager")
+            return 0
index afd7235..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):
@@ -136,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)
@@ -220,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)
@@ -230,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 c991bd6..07a655c 100644 (file)
@@ -51,7 +51,7 @@ class PlComponentDriver:
         cert.save_to_file(certfile)
         registry = self.get_registry()
         # the registry will scp the key onto the node
-        registry.get_key()        
+        registry.get_key_from_incoming_ip()        
 
     # override the method in SfaApi
     def getCredential(self):
index af3b213..834661b 100644 (file)
@@ -1,12 +1,15 @@
 #
-from sfa.util.faults import MissingSfaInfo
+from sfa.util.faults import MissingSfaInfo, UnknownSfaType
 from sfa.util.sfalogging import logger
 from sfa.util.table import SfaTable
 from sfa.util.defaultdict import defaultdict
 
-from sfa.util.xrn import hrn_to_urn
+from sfa.util.xrn import hrn_to_urn, get_leaf
 from sfa.util.plxrn import slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename, hrn_to_pl_login_base
 
+# the driver interface, mostly provides default behaviours
+from sfa.managers.driver import Driver
+
 from sfa.plc.plshell import PlShell
 
 def list_to_dict(recs, key):
@@ -14,10 +17,19 @@ def list_to_dict(recs, key):
     convert a list of dictionaries into a dictionary keyed on the 
     specified dictionary key 
     """
-    keys = [rec[key] for rec in recs]
-    return dict(zip(keys, recs))
+    return dict ( [ (rec[key],rec) for rec in recs ] )
 
-class PlDriver (PlShell):
+#
+# PlShell is just an xmlrpc serverproxy where methods
+# can be sent as-is; it takes care of authentication
+# from the global config
+# 
+# so we inherit PlShell just so one can do driver.GetNodes
+# which would not make much sense in the context of other testbeds
+# so ultimately PlDriver should drop the PlShell inheritance
+# and would have a driver.shell reference to a PlShell instead
+# 
+class PlDriver (Driver, PlShell):
 
     def __init__ (self, config):
         PlShell.__init__ (self, config)
@@ -31,70 +43,219 @@ class PlDriver (PlShell):
         assert (rspec_type == 'pl' or rspec_type == 'vini' or \
                     rspec_type == 'eucalyptus' or rspec_type == 'max')
 
+    ########## disabled users 
+    def is_enabled (self, record):
+        self.fill_record_info(record, deep=False)
+        if record['type'] == 'user':
+            return record['enabled']
+        # only users can be disabled
+        return True
+
+    def augment_records_with_testbed_info (self, sfa_records):
+        return self.fill_record_info (sfa_records, deep=True)
+
+    ########## 
+    def register (self, sfa_record, hrn, pub_key):
+        type = sfa_record['type']
+        pl_record = self.sfa_fields_to_pl_fields(type, hrn, sfa_record)
+
+        if type == 'authority':
+            sites = self.GetSites([pl_record['login_base']])
+            if not sites:
+                pointer = self.AddSite(pl_record)
+            else:
+                pointer = sites[0]['site_id']
+
+        elif type == 'slice':
+            acceptable_fields=['url', 'instantiation', 'name', 'description']
+            for key in pl_record.keys():
+                if key not in acceptable_fields:
+                    pl_record.pop(key)
+            slices = self.GetSlices([pl_record['name']])
+            if not slices:
+                 pointer = self.AddSlice(pl_record)
+            else:
+                 pointer = slices[0]['slice_id']
+
+        elif type == 'user':
+            persons = self.GetPersons([sfa_record['email']])
+            if not persons:
+                pointer = self.AddPerson(dict(sfa_record))
+            else:
+                pointer = persons[0]['person_id']
+    
+            if 'enabled' in sfa_record and sfa_record['enabled']:
+                self.UpdatePerson(pointer, {'enabled': sfa_record['enabled']})
+            # add this person to the site only if she is being added for the first
+            # time by sfa and doesont already exist in plc
+            if not persons or not persons[0]['site_ids']:
+                login_base = get_leaf(sfa_record['authority'])
+                self.AddPersonToSite(pointer, login_base)
+    
+            # What roles should this user have?
+            self.AddRoleToPerson('user', pointer)
+            # Add the user's key
+            if pub_key:
+                self.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
+
+        elif type == 'node':
+            login_base = hrn_to_pl_login_base(sfa_record['authority'])
+            nodes = api.driver.GetNodes([pl_record['hostname']])
+            if not nodes:
+                pointer = api.driver.AddNode(login_base, pl_record)
+            else:
+                pointer = nodes[0]['node_id']
+    
+        return pointer
+        
+    ##########
+    # xxx actually old_sfa_record comes filled with plc stuff as well in the original code
+    def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
+        pointer = old_sfa_record['pointer']
+        type = old_sfa_record['type']
+
+        # new_key implemented for users only
+        if new_key and type not in [ 'user' ]:
+            raise UnknownSfaType(type)
+
+        if (type == "authority"):
+            self.UpdateSite(pointer, new_sfa_record)
+    
+        elif type == "slice":
+            pl_record=self.sfa_fields_to_pl_fields(type, hrn, new_sfa_record)
+            if 'name' in pl_record:
+                pl_record.pop('name')
+                self.UpdateSlice(pointer, pl_record)
+    
+        elif type == "user":
+            # SMBAKER: UpdatePerson only allows a limited set of fields to be
+            #    updated. Ideally we should have a more generic way of doing
+            #    this. I copied the field names from UpdatePerson.py...
+            update_fields = {}
+            all_fields = new_sfa_record
+            for key in all_fields.keys():
+                if key in ['first_name', 'last_name', 'title', 'email',
+                           'password', 'phone', 'url', 'bio', 'accepted_aup',
+                           'enabled']:
+                    update_fields[key] = all_fields[key]
+            self.UpdatePerson(pointer, update_fields)
+    
+            if new_key:
+                # must check this key against the previous one if it exists
+                persons = self.GetPersons([pointer], ['key_ids'])
+                person = persons[0]
+                keys = person['key_ids']
+                keys = self.GetKeys(person['key_ids'])
+                
+                # Delete all stale keys
+                key_exists = False
+                for key in keys:
+                    if new_key != key['key']:
+                        self.DeleteKey(key['key_id'])
+                    else:
+                        key_exists = True
+                if not key_exists:
+                    self.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
+    
+        elif type == "node":
+            self.UpdateNode(pointer, new_sfa_record)
+
+        return True
+        
+
+    ##########
+    def remove (self, sfa_record):
+        type=sfa_record['type']
+        pointer=sfa_record['pointer']
+        if type == 'user':
+            persons = self.GetPersons(pointer)
+            # only delete this person if he has site ids. if he doesnt, it probably means
+            # he was just removed from a site, not actually deleted
+            if persons and persons[0]['site_ids']:
+                self.DeletePerson(pointer)
+        elif type == 'slice':
+            if self.GetSlices(pointer):
+                self.DeleteSlice(pointer)
+        elif type == 'node':
+            if self.GetNodes(pointer):
+                self.DeleteNode(pointer)
+        elif type == 'authority':
+            if self.GetSites(pointer):
+                self.DeleteSite(pointer)
+
+        return True
+
+
+
+
+
     ##
     # Convert SFA fields to PLC fields for use when registering up updating
     # registry record in the PLC database
     #
-    # @param type type of record (user, slice, ...)
-    # @param hrn human readable name
-    # @param sfa_fields dictionary of SFA fields
-    # @param pl_fields dictionary of PLC fields (output)
-
-    def sfa_fields_to_pl_fields(self, type, hrn, record):
 
-        def convert_ints(tmpdict, int_fields):
-            for field in int_fields:
-                if field in tmpdict:
-                    tmpdict[field] = int(tmpdict[field])
+    def sfa_fields_to_pl_fields(self, type, hrn, sfa_record):
 
         pl_record = {}
-        #for field in record:
-        #    pl_record[field] = record[field]
  
         if type == "slice":
-            if not "instantiation" in pl_record:
-                pl_record["instantiation"] = "plc-instantiated"
             pl_record["name"] = hrn_to_pl_slicename(hrn)
-           if "url" in record:
-               pl_record["url"] = record["url"]
-           if "description" in record:
-               pl_record["description"] = record["description"]
-           if "expires" in record:
-               pl_record["expires"] = int(record["expires"])
+            if "instantiation" in sfa_record:
+                pl_record['instantiation']=sfa_record['instantiation']
+            else:
+                pl_record["instantiation"] = "plc-instantiated"
+           if "url" in sfa_record:
+               pl_record["url"] = sfa_record["url"]
+           if "description" in sfa_record:
+               pl_record["description"] = sfa_record["description"]
+           if "expires" in sfa_record:
+               pl_record["expires"] = int(sfa_record["expires"])
 
         elif type == "node":
             if not "hostname" in pl_record:
-                if not "hostname" in record:
+                # fetch from sfa_record
+                if "hostname" not in sfa_record:
                     raise MissingSfaInfo("hostname")
-                pl_record["hostname"] = record["hostname"]
-            if not "model" in pl_record:
+                pl_record["hostname"] = sfa_record["hostname"]
+            if "model" in sfa_record: 
+                pl_record["model"] = sfa_record["model"]
+            else:
                 pl_record["model"] = "geni"
 
         elif type == "authority":
             pl_record["login_base"] = hrn_to_pl_login_base(hrn)
-
-            if not "name" in pl_record:
+            if "name" not in sfa_record:
                 pl_record["name"] = hrn
-
-            if not "abbreviated_name" in pl_record:
+            if "abbreviated_name" not in sfa_record:
                 pl_record["abbreviated_name"] = hrn
-
-            if not "enabled" in pl_record:
+            if "enabled" not in sfa_record:
                 pl_record["enabled"] = True
-
-            if not "is_public" in pl_record:
+            if "is_public" not in sfa_record:
                 pl_record["is_public"] = True
 
         return pl_record
 
+    ####################
+    def fill_record_info(self, records, deep=False):
+        """
+        Given a (list of) SFA record, fill in the PLC specific 
+        and SFA specific fields in the record. 
+        """
+        if not isinstance(records, list):
+            records = [records]
+
+        self.fill_record_pl_info(records)
+        if deep:
+            self.fill_record_hrns(records)
+            self.fill_record_sfa_info(records)
+        return records
+
     def fill_record_pl_info(self, records):
         """
         Fill in the planetlab specific fields of a SFA record. This
         involves calling the appropriate PLC method to retrieve the 
         database record for the object.
-        
-        PLC data is filled into the pl_info field of the record.
-    
+            
         @param record: record to fill in field (in/out param)     
         """
         # get ids by type
@@ -153,9 +314,6 @@ class PlDriver (PlShell):
                     pubkeys = [keys[key_id]['key'] for key_id in record['key_ids'] if key_id in keys] 
                     record['keys'] = pubkeys
 
-        # fill in record hrns
-        records = self.fill_record_hrns(records)   
         return records
 
     def fill_record_hrns(self, records):
@@ -231,7 +389,7 @@ class PlDriver (PlShell):
         return records   
 
     # aggregates is basically api.aggregates
-    def fill_record_sfa_info(self, records, aggregates):
+    def fill_record_sfa_info(self, records):
 
         def startswith(prefix, values):
             return [value for value in values if value.startswith(prefix)]
@@ -274,7 +432,7 @@ class PlDriver (PlShell):
         person_list, persons = [], {}
         person_list = table.find({'type': 'user', 'pointer': person_ids})
         # create a hrns keyed on the sfa record's pointer.
-        # Its possible for  multiple records to have the same pointer so
+        # Its possible for multiple records to have the same pointer so
         # the dict's value will be a list of hrns.
         persons = defaultdict(list)
         for person in person_list:
@@ -312,10 +470,6 @@ class PlDriver (PlShell):
                 
             elif (type.startswith("authority")):
                 record['url'] = None
-                if record['hrn'] in aggregates:
-                    
-                    record['url'] = aggregates[record['hrn']].get_url()
-
                 if record['pointer'] != -1:
                     record['PI'] = []
                     record['operator'] = []
@@ -344,64 +498,24 @@ class PlDriver (PlShell):
                 # xxx TODO: PostalAddress, Phone
             record.update(sfa_info)
 
-    def fill_record_info(self, records, aggregates):
-        """
-        Given a SFA record, fill in the PLC specific and SFA specific
-        fields in the record. 
-        """
-        if not isinstance(records, list):
-            records = [records]
 
-        self.fill_record_pl_info(records)
-        self.fill_record_sfa_info(records, aggregates)
-
-    def update_membership_list(self, oldRecord, record, listName, addFunc, delFunc):
-        # get a list of the HRNs that are members of the old and new records
-        if oldRecord:
-            oldList = oldRecord.get(listName, [])
+    ####################
+    # plcapi works by changes, compute what needs to be added/deleted
+    def update_relation (self, subject_type, target_type, subject_id, target_ids):
+        # hard-wire the code for slice/user for now
+        if subject_type =='slice' and target_type == 'user':
+            subject=self.GetSlices (subject_id)[0]
+            current_target_ids = subject['person_ids']
+            add_target_ids = list ( set (target_ids).difference(current_target_ids))
+            del_target_ids = list ( set (current_target_ids).difference(target_ids))
+            logger.info ("subject_id = %s (type=%s)"%(subject_id,type(subject_id)))
+            for target_id in add_target_ids:
+                self.AddPersonToSlice (target_id,subject_id)
+                logger.info ("add_target_id = %s (type=%s)"%(target_id,type(target_id)))
+            for target_id in del_target_ids:
+                logger.info ("del_target_id = %s (type=%s)"%(target_id,type(target_id)))
+                self.DeletePersonFromSlice (target_id, subject_id)
         else:
-            oldList = []     
-        newList = record.get(listName, [])
-
-        # if the lists are the same, then we don't have to update anything
-        if (oldList == newList):
-            return
+            logger.info('unexpected relation to maintain, %s -> %s'%(subject_type,target_type))
 
-        # build a list of the new person ids, by looking up each person to get
-        # their pointer
-        newIdList = []
-        # xxx thgen fixme - use SfaTable hardwired for now 
-        #table = self.SfaTable()
-        table = SfaTable()
-        records = table.find({'type': 'user', 'hrn': newList})
-        for rec in records:
-            newIdList.append(rec['pointer'])
-
-        # build a list of the old person ids from the person_ids field 
-        if oldRecord:
-            oldIdList = oldRecord.get("person_ids", [])
-            containerId = oldRecord.get_pointer()
-        else:
-            # if oldRecord==None, then we are doing a Register, instead of an
-            # update.
-            oldIdList = []
-            containerId = record.get_pointer()
-
-    # add people who are in the new list, but not the oldList
-        for personId in newIdList:
-            if not (personId in oldIdList):
-                addFunc(personId, containerId)
-
-        # remove people who are in the old list, but not the new list
-        for personId in oldIdList:
-            if not (personId in newIdList):
-                delFunc(personId, containerId)
-
-    def update_membership(self, oldRecord, record):
-        if record.type == "slice":
-            self.update_membership_list(oldRecord, record, 'researcher',
-                                        self.AddPersonToSlice,
-                                        self.DeletePersonFromSlice)
-        elif record.type == "authority":
-            # xxx TODO
-            pass
+        
index 972a97e..eaa772a 100644 (file)
@@ -1,4 +1,9 @@
+import sys
 import xmlrpclib
+import socket
+from urlparse import urlparse
+
+from sfa.util.sfalogging import logger
 
 class PlShell:
     """
@@ -24,16 +29,43 @@ class PlShell:
                     'get_nodes':'GetNodes',
                     }
 
+
+    # use the 'capability' auth mechanism for higher performance when the PLC db is local    
     def __init__ ( self, config ) :
-        self.plauth = {'Username': config.SFA_PLC_USER,
-                       'AuthMethod': 'password',
-                       'AuthString': config.SFA_PLC_PASSWORD}
-        
-        self.url = config.SFA_PLC_URL
-        #self.plauth = {'Username': 'root@test.onelab.eu',
-        #               'AuthMethod': 'password',
-        #               'AuthString': 'test++'}
-        self.proxy_server = xmlrpclib.Server(self.url, verbose = 0, allow_none = True)
+        url = config.SFA_PLC_URL
+        # try to figure if the url is local
+        hostname=urlparse(url).hostname
+        is_local=False
+        if hostname == 'localhost': is_local=True
+        # otherwise compare IP addresses
+        url_ip=socket.gethostbyname(hostname)
+        local_ip=socket.gethostbyname(socket.gethostname())
+        if url_ip==local_ip: is_local=True
+
+        if is_local:
+            try:
+                # too bad this is not installed properly
+                plcapi_path="/usr/share/plc_api"
+                if plcapi_path not in sys.path: sys.path.append(plcapi_path)
+                import PLC.Shell
+                plc_direct_access=True
+            except:
+                plc_direct_access=False
+        if is_local and plc_direct_access:
+            logger.debug('plshell access - capability')
+            self.plauth = { 'AuthMethod': 'capability',
+                            'Username':   config.SFA_PLC_USER,
+                            'AuthString': config.SFA_PLC_PASSWORD,
+                            }
+            self.proxy = PLC.Shell.Shell ()
+
+        else:
+            logger.debug('plshell access - xmlrpc')
+            self.plauth = { 'AuthMethod': 'password',
+                            'Username':   config.SFA_PLC_USER,
+                            'AuthString': config.SFA_PLC_PASSWORD,
+                            }
+            self.proxy = xmlrpclib.Server(url, verbose = 0, allow_none = True)
 
     def __getattr__(self, name):
         def func(*args, **kwds):
@@ -42,5 +74,7 @@ class PlShell:
             if name in PlShell.alias_calls: actual_name=PlShell.alias_calls[name]
             if not actual_name:
                 raise Exception, "Illegal method call %s for PL driver"%(name)
-            return getattr(self.proxy_server, actual_name)(self.plauth, *args, **kwds)
+            result=getattr(self.proxy, actual_name)(self.plauth, *args, **kwds)
+            logger.debug('%s (%s) returned ... %s'%(name,actual_name,result))
+            return result
         return func
diff --git a/sfa/plc/remoteshell.py b/sfa/plc/remoteshell.py
deleted file mode 100644 (file)
index 9deceb6..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-# remoteshell.py
-#
-# interface to the PLC api via xmlrpc
-#
-# RemoteShell() exports an API that looks identical to that exported by
-# PLC.Shell.Shell(). It's meant to be a drop in replacement for running
-# SFA on a different machine than PLC.
-
-import xmlrpclib
-
-class RemoteShell:
-    def __init__(self,logger):
-        self.servers = {}
-        self.logger=logger
-
-    def call(self, name, pl_auth, *args):
-
-        key = pl_auth["Url"] + "#" + pl_auth["Username"]
-
-        if not (key in self.servers):
-            self.logger.info("Connecting to PLCAPI at url %s"%pl_auth['Url'])
-            server = xmlrpclib.Server(pl_auth["Url"], verbose = 0, allow_none=True)
-            #server.AdmAuthCheck(pl_auth)
-            server.AuthCheck(pl_auth)
-            self.servers[key] = server
-
-        server = self.servers[key]
-
-        arglist = ["pl_auth"]
-        for arg in args:
-            arglist.append(repr(arg))
-
-        str = "server." + name + "(" + ",".join(arglist) + ")"
-        result = eval(str)
-
-        return result
-
-    # TODO: there's probably an automatic way to import all these stubs
-
-    def AddInitScript(self, pl_auth, *args):
-        return self.call("AddInitScript", pl_auth, *args)
-
-    def AddNode(self, pl_auth, *args):
-        return self.call("AddNode", pl_auth, *args)
-
-    def AddPerson(self, pl_auth, *args):
-        return self.call("AddPerson", pl_auth, *args)
-
-    def AddPersonToSlice(self, pl_auth, *args):
-        return self.call("AddPersonToSlice", pl_auth, *args)
-
-    def AddSite(self, pl_auth, *args):
-        return self.call("AddSite", pl_auth, *args)
-
-    def AddSlice(self, pl_auth, *args):
-        return self.call("AddSlice", pl_auth, *args)
-
-    def DeleteNode(self, pl_auth, *args):
-        return self.call("DeleteNode", pl_auth, *args)
-
-    def DeletePerson(self, pl_auth, *args):
-        return self.call("DeletePerson", pl_auth, *args)
-
-    def DeletePersonFromSlice(self, pl_auth, *args):
-        return self.call("DeletePersonFromSlice", pl_auth, *args)
-
-    def DeleteSite(self, pl_auth, *args):
-        return self.call("DeleteSite", pl_auth, *args)
-
-    def DeleteSlice(self, pl_auth, *args):
-        return self.call("DeleteSlice", pl_auth, *args)
-
-    def GetInitScripts(self, pl_auth, *args):
-        return self.call("GetInitScripts", pl_auth, *args)
-
-    def GetKeys(self, pl_auth, *args):
-        return self.call("GetKeys", pl_auth, *args)
-
-    def GetNodes(self, pl_auth, *args):
-        return self.call("GetNodes", pl_auth, *args)
-
-    def GetPersons(self, pl_auth, *args):
-        return self.call("GetPersons", pl_auth, *args)
-
-    def GetSites(self, pl_auth, *args):
-        return self.call("GetSites", pl_auth, *args)
-
-    def GetSliceAttributes(self, pl_auth, *args):
-        return self.call("GetSliceAttributes", pl_auth, *args)
-
-    def GetSlices(self, pl_auth, *args):
-        return self.call("GetSlices", pl_auth, *args)
-
-    def UpdateNode(self, pl_auth, *args):
-        return self.call("UpdateNode", pl_auth, *args)
-
-    def UpdatePerson(self, pl_auth, *args):
-        return self.call("UpdatePerson", pl_auth, *args)
-
-    def UpdateSite(self, pl_auth, *args):
-        return self.call("UpdateSite", pl_auth, *args)
-
-    def UpdateSlice(self, pl_auth, *args):
-        return self.call("UpdateSlice", pl_auth, *args)
-
-
index 65513d0..44317be 100644 (file)
@@ -15,15 +15,16 @@ class PGv2Link:
             if 'component_manager' in link and link['component_manager']:
                 cm_element = link_elem.add_element('component_manager', name=link['component_manager'])
             # set interface_ref elements
-            for if_ref in [link['interface1'], link['interface2']]:
-                link_elem.add_instance('interface_ref', if_ref, Interface.fields)
-            # set property elements
-            prop1 = link_elem.add_element('property', source_id = link['interface1']['component_id'],
-                dest_id = link['interface2']['component_id'], capacity=link['capacity'], 
-                latency=link['latency'], packet_loss=link['packet_loss'])
-            prop2 = link_elem.add_element('property', source_id = link['interface2']['component_id'],
-                dest_id = link['interface1']['component_id'], capacity=link['capacity'], 
-                latency=link['latency'], packet_loss=link['packet_loss'])
+            if link.get('interface1') and link.get('interface2'):
+                for if_ref in [link['interface1'], link['interface2']]:
+                    link_elem.add_instance('interface_ref', if_ref, Interface.fields)
+                # set property elements
+                prop1 = link_elem.add_element('property', source_id = link['interface1']['component_id'],
+                    dest_id = link['interface2']['component_id'], capacity=link['capacity'], 
+                    latency=link['latency'], packet_loss=link['packet_loss'])
+                prop2 = link_elem.add_element('property', source_id = link['interface2']['component_id'],
+                    dest_id = link['interface1']['component_id'], capacity=link['capacity'], 
+                    latency=link['latency'], packet_loss=link['packet_loss'])
             if link.get('type'):
                 type_elem = link_elem.add_element('link_type', name=link['type'])            
  
index eb0518f..c37275a 100644 (file)
@@ -25,16 +25,18 @@ class PGv2Node:
                 component_name = xrn_to_hostname(node['component_id'])
                 node_elem.set('component_name', component_name)
             # set hardware types
-            for hardware_type in node.get('hardware_types', []): 
-                node_elem.add_instance('hardware_type', hardware_type, HardwareType.fields)
+            if node.get('hardware_types'):
+                for hardware_type in node.get('hardware_types', []): 
+                    node_elem.add_instance('hardware_type', hardware_type, HardwareType.fields)
             # set location
             if node.get('location'):
                 node_elem.add_instance('location', node['location'], Location.fields)       
             # set interfaces
-            for interface in  node.get('interfaces', []):
-                node_elem.add_instance('interface', interface, ['component_id', 'client_id', 'ipv4'])
+            if node.get('interfaces'):
+                for interface in  node.get('interfaces', []):
+                    node_elem.add_instance('interface', interface, ['component_id', 'client_id', 'ipv4'])
             # set available element
-            if node.get('boot_state', '').lower() == 'boot':
+            if node.get('boot_state') and node.get('boot_state').lower() == 'boot':
                 available_elem = node_elem.add_element('available', now='True')
             else:
                 available_elem = node_elem.add_element('available', now='False')
@@ -47,8 +49,9 @@ class PGv2Node:
                 slivers = Sliver({'type': 'plab-vserver'})
                 # we must also advertise the available initscripts
                 slivers['tags'] = []
-                for initscript in node.get('pl_initscripts', []):
-                    slivers['tags'].append({'name': 'initscript', 'value': initscript['name']})
+                if node.get('pl_initscripts'): 
+                    for initscript in node.get('pl_initscripts', []):
+                        slivers['tags'].append({'name': 'initscript', 'value': initscript['name']})
             PGv2SliverType.add_slivers(node_elem, slivers)
         
         return node_elems
index 7cffc91..be1d618 100644 (file)
@@ -1,6 +1,7 @@
 from sfa.rspecs.elements.element import Element  
 from sfa.rspecs.elements.execute import Execute  
 from sfa.rspecs.elements.install import Install  
+from sfa.rspecs.elements.services import Services  
 from sfa.rspecs.elements.login import Login
 
 class PGv2Services:
index 26d41a9..bf09305 100644 (file)
@@ -62,9 +62,11 @@ class SFAv1Node:
             #    bw_unallocated = etree.SubElement(node_elem, 'bw_unallocated', units='kbps').text = str(int(node['bw_unallocated'])/1000)
 
             PGv2Services.add_services(node_elem, node.get('services', []))
-            for tag in node.get('tags', []):
-                tag_elem = node_elem.add_element(tag['tagname'])
-                tag_elem.set_text(tag['value'])
+            tags = node.get('tags', [])
+            if tags:
+                for tag in tags:
+                    tag_elem = node_elem.add_element(tag['tagname'])
+                    tag_elem.set_text(tag['value'])
             SFAv1Sliver.add_slivers(node_elem, node.get('slivers', []))
 
     @staticmethod 
index d1519e9..207a4a7 100644 (file)
@@ -14,8 +14,10 @@ class SFAv1Sliver:
             slivers = [slivers]
         for sliver in slivers:
             sliver_elem = xml.add_instance('sliver', sliver, ['name'])
-            for tag in sliver.get('tags', []):
-                SFAv1Sliver.add_sliver_attribute(sliver_elem, tag['tagname'], tag['value'])
+            tags = sliver.get('tags', [])
+            if tags:
+                for tag in tags:
+                    SFAv1Sliver.add_sliver_attribute(sliver_elem, tag['tagname'], tag['value'])
             if sliver.get('sliver_id'):
                 sliver_id_leaf = Xrn(sliver.get('sliver_id')).get_leaf()
                 sliver_id_parts = sliver_id_leaf.split(':')
index 1c57d7d..5cccf97 100755 (executable)
@@ -44,10 +44,15 @@ class PGRSpecConverter:
         sfa_version = version_manager._get_version('sfa', '1')    
         sfa_rspec = RSpec(version=sfa_version)
 
+        #nodes = pg_rspec.version.get_nodes()
+        #sfa_rspec.version.add_nodes(nodes())
+        #sfa_rspec.version.add_links(pg_rspec.version.get_links())
+        #return sfa_rspec.toxml() 
+
         # get network
-        network_urn = pg_rspec.version.get_network()
-        network,  _ = urn_to_hrn(network_urn)
-        network_element = sfa_rspec.xml.add_element('network', {'name': network, 'id': network})
+        networks = pg_rspec.version.get_networks()
+        network_hrn = networks[0]
+        network_element = sfa_rspec.xml.add_element('network', name=network_hrn, id=network_hrn)
         
         # get nodes
         pg_nodes_elements = pg_rspec.version.get_node_elements()
@@ -57,18 +62,18 @@ class PGRSpecConverter:
             attribs = dict(pg_node_element.attrib.items()) 
             attribs['id'] = 'n'+str(i)
             
-            node_element = sfa_rspec.xml.add_element('node', attribs, parent=network_element)
+            node_element = network_element.add_element('node')
+            for attrib in attribs:
+                node_element.set(attrib, attribs[attrib])
             urn = pg_node_element.xpath('@component_id', namespaces=pg_rspec.namespaces)
             if urn:
                 urn = urn[0]
                 hostname = Xrn.urn_split(urn)[-1]
-                hostname_element = sfa_rspec.xml.add_element('hostname', parent=node_element, text=hostname)
+                hostname_element = node_element.add_element('hostname')
+                hostname_element.set_text(hostname)
                 if hostname in nodes_with_slivers:
-                    sfa_rspec.xml.add_element('sliver', parent=node_element)
+                    node_element.add_element('sliver')  
                      
-            urn_element = sfa_rspec.xml.add_element('urn', parent=node_element, text=urn)
-
-
             # just copy over remaining child elements  
             for child in pg_node_element.getchildren():
                 node_element.append(transform(child).getroot())
index 60387dc..fba1a26 100644 (file)
@@ -22,7 +22,7 @@ class PGv2(BaseVersion):
     # Networks    
     def get_networks(self):
         networks = set()
-        nodes = self.xml.xpath('//default:node[@component_manager_id]', namespaces=self.namespaces)
+        nodes = self.xml.xpath('//default:node[@component_manager_id] | //node:[@component_manager_id]', namespaces=self.namespaces)
         for node in nodes: 
             if 'component_manager_id' in node:
                 network_urn  = node.get('component_manager_id')
@@ -167,12 +167,24 @@ class PGv2(BaseVersion):
         """
         from sfa.rspecs.rspec import RSpec
         # just copy over all the child elements under the root element
-        if isinstance(in_rspec, RSpec):
-            in_rspec = in_rspec.toxml()
+        if isinstance(in_rspec, basestring):
+            in_rspec = RSpec(in_rspec)
+
+        nodes = in_rspec.version.get_nodes()
+        # protogeni rspecs need to advertise the availabel sliver types
+        for node in nodes:
+            if not node.has_key('sliver') or not node['sliver']:
+                node['sliver'] = {'name': 'plab-vserver'}
+            
+        self.add_nodes(nodes)
+        self.add_links(in_rspec.version.get_links())
+        
+        #
+        #rspec = RSpec(in_rspec)
+        #for child in rspec.xml.iterchildren():
+        #    self.xml.root.append(child)
+        
         
-        rspec = RSpec(in_rspec)
-        for child in rspec.xml.iterchildren():
-            self.xml.root.append(child)
 
     def cleanup(self):
         # remove unncecessary elements, attributes
index ed1ee30..3775391 100755 (executable)
@@ -98,7 +98,7 @@ def get_node_key(registry=None, verbose=False):
     cert.save_to_file(certfile)
     
     registry = server_proxy(url = registry, keyfile=keyfile, certfile=certfile)    
-    registry.get_key()
+    registry.get_key_from_incoming_ip()
 
 def create_server_keypair(keyfile=None, certfile=None, hrn="component", verbose=False):
     """
index 7085037..9afe9b4 100644 (file)
@@ -1,15 +1,16 @@
 import os, os.path
 import datetime
 
-from sfa.util.faults import SfaAPIError
+from sfa.util.faults import SfaFault, SfaAPIError
 from sfa.util.config import Config
 from sfa.util.cache import Cache
 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
+from sfa.client.return_value import ReturnValue
 
 # thgen xxx fixme this is wrong all right, but temporary, will use generic
 from sfa.util.table import SfaTable
@@ -201,7 +202,53 @@ class SfaApi (XmlrpcApi):
         if self.cache:
             server_version = self.cache.get(cache_key)
         if not server_version:
-            server_version = server.GetVersion()
+            result = server.GetVersion()
+            server_version = ReturnValue.get_value(result)
             # 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 isinstance(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() in ['aggregate', 'slicemgr']: 
+            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 2ad7f7b..2261dda 100644 (file)
@@ -36,6 +36,7 @@ class Config:
             # path to configuration data
             self.config_path = os.path.dirname(config_file)
             
+            ### xxx todo implement defaults in default_config.xml 
             # path to server data
             if not hasattr(self, 'SFA_DATA_DIR'):
                 # default to /var/lib/sfa not specified in config
@@ -46,29 +47,12 @@ class Config:
                 
             # path to config data
             if not hasattr(self, 'SFA_CONFIG_DIR'):
-                # default to /var/lib/sfa not specified in config
+                # default to /etc/sfa not specified in config
                 self.SFA_CONFIG_DIR="/etc/sfa"
 
             if not hasattr(self, 'SFA_REGISTRY_LEVEL1_AUTH'):
                 self.SFA_REGISTRY_LEVEL1_AUTH=None
 
-            # define interface types
-            # this will determine which manager to use
-            if not hasattr(self, 'SFA_REGISTRY_TYPE'):
-                self.SFA_REGISTRY_TYPE='pl'
-
-            if not hasattr(self, 'SFA_AGGREGATE_TYPE'):
-                self.SFA_AGGREGATE_TYPE='pl'
-
-            if not hasattr(self, 'SFA_SM_TYPE'):
-                self.SFA_SM_TYPE='pl'
-
-            if not hasattr(self, 'SFA_CM_TYPE'):
-                self.SFA_COMPONENT_TYPE='pl'
-
-            if not hasattr(self, 'SFA_MAX_SLICE_RENEW'):
-                self.SFA_MAX_SLICE_RENEW=60
-
             # create the data directory if it doesnt exist
             if not os.path.isdir(self.SFA_DATA_DIR):
                 try:
@@ -125,20 +109,3 @@ class Config:
 
         return (am_apiclient_path,am_url)
 
-    ##
-    # SFA uses a PLCAPI connection to perform operations on the registry,
-    # such as creating and deleting slices. This connection requires an account
-    # on the PLC server with full administrator access.
-    #
-    # The Url parameter controls whether the connection uses PLCAPI directly (i.e.
-    # SFA is located on the same machine as PLC), or uses a XMLRPC connection
-    # to the PLC machine. If you wish to use the API directly, then remove the Url
-    # field from the dictionary. 
-
-    def get_plc_auth(self):
-        return {
-            'AuthMethod': 'capability',
-            'Username': self.SFA_PLC_USER,
-            'AuthString':  self.SFA_PLC_PASSWORD,
-            "Url": self.SFA_PLC_URL
-            }
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)
    
index b6b3353..855d440 100644 (file)
@@ -20,4 +20,3 @@ GENICODE = Enum(
     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(),
              }