-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
##########
tags:
- find . -type f | egrep -v '/\.git/|/\.svn/|TAGS|~$$|\.(py[co]|doc|html|pdf|png|svg|out|bak|xml|dg)$$' | xargs etags
+ find . -type f | egrep -v '/\.git/|/\.svn/|TAGS|AA-|~$$|\.(py[co]|doc|html|pdf|png|svg|out|bak|xml|dg)$$' | xargs etags
.PHONY: tags
signatures:
+$(RSYNC) ./sfa/ $(SSHURL)/usr/lib\*/python2.\*/site-packages/sfa/
+$(RSYNC) ./tests/ $(SSHURL)/root/tests-sfa
+$(RSYNC) $(BINS) $(SSHURL)/usr/bin/
- +$(RSYNC) ./sfa/init.d/sfa $(SSHURL)/etc/init.d/
+ +$(RSYNC) ./init.d/sfa $(SSHURL)/etc/init.d/
+$(RSYNC) ./config/default_config.xml $(SSHURL)/etc/sfa/
$(SSHCOMMAND) exec service sfa restart
endif
+++ /dev/null
-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
<description>The human readable name for this interface.</description>
</variable>
- <variable id="aggregate_api_version" type="string">
+ <variable id="aggregate_api_version" type="int">
<name>Aggregate Manager API Version</name>
<value>1</value>
<description>The Aggregate API version</description>
registry.</description>
</variable>
- <variable id="type" type="string">
- <name>Registry type</name>
- <value>pl</value>
- <description>The type of backend server for this
- registry. Some registries may not be myplc.</description>
- </variable>
-
<variable id="host" type="hostname">
<name>Hostname</name>
<value>localhost</value>
slice manager.</description>
</variable>
- <variable id="type" type="string">
- <name>Slice Manager type</name>
- <value>pl</value>
- <description>The type of backend server for this
- slice manager. Not all slice managers are myplc.</description>
- </variable>
-
<variable id="host" type="hostname">
<name>Hostname</name>
<value>localhost</value>
aggregate manager.</description>
</variable>
- <variable id="type" type="string">
- <name>Aggregate type</name>
- <value>pl</value>
- <description>The type of backend server for this
- aggregate. Some aggregates may not be myplc.</description>
- </variable>
-
<variable id="rspec_schema" type="string">
<name>RSpec Schema</name>
<value>/etc/sfa/pl.rng</value>
# Enable the registry interface
SFA_REGISTRY_ENABLED=0
-#
-# The type of backend server for this registry
-# Some registries may not be myplc
-SFA_REGISTRY_TYPE='pl'
-
# Root Auth
# The hrn of the registry's root auth
SFA_REGISTRY_ROOT_AUTH="plc"
# xxx could be determined from hrn above
SFA_REGISTRY_LEVEL1_AUTH=""
+SFA_GENERIC_FLAVOUR='pl'
+
# Hostname
# The fully qualified hostname of the registry server
SFA_REGISTRY_HOST="localhost"
## Enable the aggregate inteface.
SFA_AGGREGATE_ENABLED=0
-# Aggregate Type
-#
-# The type of backend server for this aggregate
-# Some aggregates may not be myplc
-SFA_AGGREGATE_TYPE='pl'
-
#
#
## Hostname
# Enable the slice manager
SFA_SM_ENABLED=0
-# Slice Manager type
-#
-## The type of backend server for this slice manager
-## The slice manager doesnt rely on a specific backend server so
-## you probably will never need to change this type unless you
-## need to reimplement the slice manager
-SFA_SM_TYPE='pl'
-
# Host
## The fully qualified hostname or IP address of the slice manager server
SFA_SM_HOST="localhost"
--- /dev/null
+As of nov 2011 this is not packaged, use as a template for your installation
# Convert configuration to various formats
if [ -n "$force" -o $sfa_whole_config -nt /etc/sfa/sfa_config ] ; then
- plc-config --shell $sfa_whole_config >/etc/sfa/sfa_config
+ plc-config --shell $sfa_whole_config > /etc/sfa/sfa_config
fi
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
+ plc-config --python $sfa_whole_config > /etc/sfa/sfa_config.py
fi
# if [ -n "$force" -o $sfa_whole_config -nt /etc/sfa/php/sfa_config.php ] ; then
# mkdir -p /etc/sfa/php
# (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
+
+ # reload the shell version
+ [ -f /etc/sfa/sfa_config ] && . /etc/sfa/sfa_config
+
}
### initialize DB (don't chkconfig postgresql on)
######## 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
+ plc-config --category=sfa_db --variable=password --value="$SFA_DB_PASSWORD" --save=$sfa_local_config $sfa_local_config >& /dev/null
reload force
fi
PLC_DB_USER=$(plc-config --category=plc_db --variable=user)
PLC_DB_PASSWORD=$(plc-config --category=plc_db --variable=password)
# store this as the SFA user/password
- plc-config --category=sfa_db --variable=user --value=$PLC_DB_USER --save=$sfa_local_config $sfa_local_config
- plc-config --category=sfa_db --variable=password --value=$PLC_DB_PASSWORD --save=$sfa_local_config $sfa_local_config
+ 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
######## 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
+ 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
+ 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
+ check
+ # install db schema
+ psql -U $SFA_DB_USER -f /usr/share/sfa/sfa.sql $SFA_DB_NAME
+ check
fi
check
# install peer certs
action $"SFA installing peer certs" daemon /usr/bin/sfa-start.py -t -d $OPTIONS
- if [ "$SFA_REGISTRY_ENABLED" -eq 1 ]; then
- action $"SFA Registry" daemon /usr/bin/sfa-start.py -r -d $OPTIONS
- fi
-
- if [ "$SFA_AGGREGATE_ENABLED" -eq 1 ]; then
- action $"SFA Aggregate" daemon /usr/bin/sfa-start.py -a -d $OPTIONS
- fi
+ [ "$SFA_REGISTRY_ENABLED" == 1 ] && action $"SFA Registry" daemon /usr/bin/sfa-start.py -r -d $OPTIONS
+
+ [ "$SFA_AGGREGATE_ENABLED" == 1 ] && action $"SFA Aggregate" daemon /usr/bin/sfa-start.py -a -d $OPTIONS
- if [ "$SFA_SM_ENABLED" -eq 1 ]; then
- action "SFA SliceMgr" daemon /usr/bin/sfa-start.py -s -d $OPTIONS
- fi
+ [ "$SFA_SM_ENABLED" == 1 ] && action "SFA SliceMgr" daemon /usr/bin/sfa-start.py -s -d $OPTIONS
- if [ "$SFA_FLASHPOLICY_ENABLED" -eq 1 ]; then
+ [ "$SFA_FLASHPOLICY_ENABLED" == 1 ] && \
action "Flash Policy Server" daemon /usr/bin/sfa_flashpolicy.py --file="$SFA_FLASHPOLICY_CONFIG_FILE" --port=$SFA_FLASHPOLICY_PORT -d
- fi
touch /var/lock/subsys/sfa-start.py
+++ /dev/null
-<?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=""user""/>
- <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>
+++ /dev/null
-<?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=""""/>
- <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=""""/>
- <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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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="""" 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="""" 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>
+++ /dev/null
-<?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>
package_dirs = [
'sfa',
'sfa/trust',
+ 'sfa/storage',
'sfa/util',
'sfa/client',
'sfa/server',
]
+initscripts = [ 'sfa', 'sfa-cm' ]
+
data_files = [('/etc/sfa/', [ 'config/aggregates.xml',
'config/registries.xml',
'config/default_config.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/', [ "init.d/%s"%x for x in initscripts ]),
+ ('/usr/share/sfa/', [ 'sfa/storage/sfa.sql' ] ),
+ ]
# add sfatables processors as data_files
processor_files = [f for f in glob('sfatables/processors/*') if os.path.isfile(f)]
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:
%define name sfa
-%define version 1.1
-%define taglevel 5
+%define version 2.0
+%define taglevel 1
%define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
%global python_sitearch %( python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)" )
Group: Applications/System
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
+# xxx TODO : package cron.d/
+
Vendor: PlanetLab
Packager: PlanetLab Central <support@planet-lab.org>
Distribution: PlanetLab %{plrelease}
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
+# this gets duplicated
+rm -rf $RPM_BUILD_ROOT/%{python_sitelib}/sfa/storage/sfa.sql
%clean
rm -rf $RPM_BUILD_ROOT
%config /etc/sfa/default_config.xml
%config (noreplace) /etc/sfa/aggregates.xml
%config (noreplace) /etc/sfa/registries.xml
+/usr/share/sfa/sfa.sql
/var/www/html/wsdl/*.wsdl
%files plc
[ "$1" -ge "1" ] && service sfa-cm restart || :
%changelog
+* Wed Nov 30 2011 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - sfa-2.0-1
+- cleaned up all references to SFA_*_TYPE in config
+- enable cache at the aggregate by default
+- registry now uses the driver in a sensible way (see managers/driver.py)
+- slice manager supports sfav1/pgv2 neighbours
+- get_key renamed into get_key_from_incoming_ip
+- new sfa.storage module for record/table and all db-related stuff
+- db schema in sfa.storage.sfa.sql
+- init.d and cron.d move one step up
+- cleaned up rspec/ directory
+- add deps to pyopenssl and myplc-config
+- start support for new API (return value)
+- plc.remoteshell removed, use plshell instead
+- plshell uses a 'capability' auth method whenever possible
+- various tweaks in rspec elements
+- made dependency on sfatables softer
+
* 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
--- /dev/null
+
+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
from types import StringTypes, ListType
from optparse import OptionParser
+from sfa.util.sfalogging import logger
+
from sfa.trust.certificate import Certificate
from sfa.trust.credential import Credential
from sfa.trust.gid import GID
-from sfa.util.record import SfaRecord
-from sfa.util.sfalogging import logger
+
+from sfa.storage.record import SfaRecord
def determine_sfa_filekind(fn):
import sys
sys.path.append('.')
+
import os, os.path
import tempfile
import socket
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.storage.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
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
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:
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
server_version = self.get_cached_server_version(server)
if 'sfa' in server_version:
# just request the version the client wants
- options['rspec_version'] = version_manager.get_version(opts.rspec_version).to_dict()
+ options['geni_rspec_version'] = version_manager.get_version(opts.rspec_version).to_dict()
else:
# this must be a protogeni aggregate. We should request a v2 ad rspec
# regardless of what the client user requested
- options['rspec_version'] = version_manager.get_version('ProtoGENI 2').to_dict()
-
+ options['geni_rspec_version'] = version_manager.get_version('ProtoGENI 2').to_dict()
+ options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'}
+
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
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):
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):
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):
# 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
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
import getopt
import sys
-from sfa.util.table import SfaTable
from sfa.util.xrn import get_leaf, get_authority
from sfa.util.plxrn import hostname_to_hrn, slicename_to_hrn, email_to_hrn, hrn_to_pl_slicename
from sfa.util.config import Config
from sfa.util.xrn import Xrn
+from sfa.storage.table import SfaTable
+
from sfa.importer.sfaImport import sfaImport
def process_options():
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()
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())
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:
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']
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
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__":
import os
from optparse import OptionParser
-from sfa.util.table import SfaTable
from sfa.util.sfalogging import logger
+from sfa.storage.table import SfaTable
+
def main():
usage="%prog: trash the registry DB (the 'sfa' table in the 'planetlab5' database)"
parser = OptionParser(usage=usage)
##
from sfa.util.sfalogging import _SfaLogger
-
-from sfa.util.record import SfaRecord
-from sfa.util.table import SfaTable
from sfa.util.xrn import get_authority, hrn_to_urn
from sfa.util.plxrn import email_to_hrn
from sfa.util.config import Config
+
from sfa.trust.certificate import convert_public_key, Keypair
from sfa.trust.trustedroots import TrustedRoots
from sfa.trust.hierarchy import Hierarchy
from sfa.trust.gid import create_uuid
+from sfa.storage.record import SfaRecord
+from sfa.storage.table import SfaTable
+
def _un_unicode(str):
if isinstance(str, unicode):
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):
"""
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:
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={}):
request_rspec_versions.append(rspec_version.to_dict())
xrn=Xrn(api.hrn)
version_more = {'interface':'aggregate',
- 'sfa': 1,
+ 'sfa': 2,
'geni_api': api.config.SFA_AGGREGATE_API_VERSION,
'testbed':'myplc',
'hrn':xrn.get_hrn(),
version_manager = VersionManager()
# get the rspec's return format from options
- rspec_version = version_manager.get_version(options.get('rspec_version'))
- version_string = "rspec_%s" % (rspec_version.to_string())
+ rspec_version = version_manager.get_version(options.get('geni_rspec_version'))
+ version_string = "rspec_%s" % (rspec_version)
#panos adding the info option to the caching key (can be improved)
if options.get('info'):
--- /dev/null
+#
+# 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
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
from sfa.trust.certificate import Certificate, Keypair, convert_public_key
from sfa.trust.gid import create_uuid
+from sfa.storage.record import SfaRecord
+from sfa.storage.table import SfaTable
+
class RegistryManager:
def __init__ (self): pass
# 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']:
+ self.driver.augment_records_with_testbed_info (record)
+ 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
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 = {}
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):
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
pkey = certificate.get_pubkey()
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
+
+ # subject_record describes the subject of the relationships
+ # ref_record contains the target values for the various relationships we need to manage
+ # (to begin with, this is just the slice x person relationship)
+ def update_relations (self, subject_record, ref_record):
+ type=subject_record['type']
+ if type=='slice':
+ self.update_relation(subject_record, 'researcher', ref_record.get('researcher'), 'user')
+ # 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']
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)
# 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_relations (record, record)
+
return record.get_gid_object().save_to_string(save_parents=True)
def Update(self, api, record_dict):
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_relations (record, new_record)
return 1
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
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
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.
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"}
# get the rspec's return format from options
rspec_version = version_manager.get_version(options.get('rspec_version'))
- version_string = "rspec_%s" % (rspec_version.to_string())
+ version_string = "rspec_%s" % (rspec_version)
# look in cache first
if self.caching and api.cache and not xrn:
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")
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()
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={}):
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']]
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)
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
+from sfa.storage.parameter import Parameter, Mixed
from sfa.trust.credential import Credential
class CreateGid(Method):
from sfa.util.faults import SfaInvalidArgument
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
from sfa.util.sfatablesRuntime import run_sfatables
+
from sfa.trust.credential import Credential
+
+from sfa.storage.parameter import Parameter, Mixed
+
from sfa.rspecs.rspec import RSpec
class CreateSliver(Method):
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+from sfa.storage.parameter import Parameter, Mixed
from sfa.trust.auth import Auth
from sfa.trust.credential import Credential
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter, Mixed
+
class GetCredential(Method):
"""
Retrive a credential for an object
from sfa.util.faults import RecordNotFound
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter, Mixed
+
class GetGids(Method):
"""
Get a list of record information (hrn, gid and type) for
from sfa.util.faults import RecordNotFound, ConnectionKeyGIDMismatch
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
-from sfa.util.record import SfaRecord
+
from sfa.trust.certificate import Certificate
+from sfa.storage.parameter import Parameter, Mixed
+from sfa.storage.record import SfaRecord
+
class GetSelfCredential(Method):
"""
Retrive a credential for an object
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
from sfa.util.sfatablesRuntime import run_sfatables
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter, Mixed
+
class GetTicket(Method):
"""
Retrieve a ticket. This operation is currently implemented on PLC
from sfa.util.method import Method
-from sfa.util.parameter import Parameter
+
+from sfa.storage.parameter import Parameter
class GetVersion(Method):
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
-from sfa.util.record import SfaRecord
+
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter, Mixed
+from sfa.storage.record import SfaRecord
+
class List(Method):
"""
List the records in an authority.
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
-from sfa.trust.credential import Credential
from sfa.util.sfatablesRuntime import run_sfatables
+from sfa.util.faults import SfaInvalidArgument
+from sfa.trust.credential import Credential
+
+from sfa.storage.parameter import Parameter, Mixed
class ListResources(Method):
"""
def call(self, creds, options={}):
self.api.logger.info("interface: %s\tmethod-name: %s" % (self.api.interface, self.name))
-
+
+ # client must specify a version
+ if not options.get('geni_rspec_version'):
+ raise SfaInvalidArgument('Must specify an rspec version option. geni_rspec_version cannot be null')
+
# get slice's hrn from options
xrn = options.get('geni_slice_urn', '')
(hrn, _) = urn_to_hrn(xrn)
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter, Mixed
+
class ListSlices(Method):
"""
List the slices instantiated at this interface
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
+from sfa.storage.parameter import Parameter, Mixed
class RedeemTicket(Method):
"""
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter, Mixed
+
class Register(Method):
"""
Register an object with the registry. In addition to being stored in the
from sfa.util.xrn import Xrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter, Mixed
+
class Remove(Method):
"""
Remove an object from the registry. If the object represents a PLC object,
from sfa.util.faults import InsufficientRights
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter
-from sfa.trust.credential import Credential
from sfa.util.sfatime import utcparse
+from sfa.trust.credential import Credential
+
+from sfa.storage.parameter import Parameter
+
class RenewSliver(Method):
"""
Renews the resources in a sliver, extending the lifetime of the slice.
from sfa.util.xrn import Xrn, urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
from sfa.trust.credential import Credential
-from sfa.util.record import SfaRecord
+
+from sfa.storage.parameter import Parameter, Mixed
+from sfa.storage.record import SfaRecord
class Resolve(Method):
"""
from sfa.util.method import Method
-from sfa.util.parameter import Parameter
+
+from sfa.storage.parameter import Parameter
class ResolveGENI(Method):
"""
-from sfa.util.parameter import Parameter
+from sfa.storage.parameter import Parameter
+
from sfa.methods.Stop import Stop
class Shutdown(Stop):
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
+from sfa.storage.parameter import Parameter, Mixed
class SliverStatus(Method):
"""
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter, Mixed
+
class Start(Method):
"""
Start the specified slice
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter, Mixed
+
class Stop(Method):
"""
Stop the specified slice
from sfa.util.method import Method
-from sfa.util.parameter import Parameter
+
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter
+
class Update(Method):
"""
Update an object in the registry. Currently, this only updates the
-from sfa.util.parameter import Parameter, Mixed
+from sfa.storage.parameter import Parameter, Mixed
+
from sfa.methods.CreateSliver import CreateSliver
class UpdateSliver(CreateSliver):
Stop
Update
UpdateSliver
-get_key
+get_key_from_incoming_ip
get_trusted_certs
reset_slice
""".split()
+++ /dev/null
-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
--- /dev/null
+from sfa.util.method import Method
+from sfa.util.sfalogging import logger
+
+from sfa.storage.parameter import Parameter
+
+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
-#from sfa.util.faults import *
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
from sfa.trust.auth import Auth
from sfa.trust.credential import Credential
+from sfa.storage.parameter import Parameter, Mixed
class get_trusted_certs(Method):
"""
from sfa.util.xrn import urn_to_hrn
from sfa.util.method import Method
-from sfa.util.parameter import Parameter, Mixed
+
+from sfa.storage.parameter import Parameter, Mixed
class reset_slice(Method):
"""
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):
#
-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
+# one would think the driver should not need to mess with the SFA db, but..
+from sfa.storage.table import SfaTable
+
+# 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):
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)
self.hrn = config.SFA_INTERFACE_HRN
- # xxx thgen fixme - use SfaTable hardwired for now
- # will need to extend generic to support multiple storage systems
- #self.SfaTable = SfaTable
- # Initialize the PLC shell only if SFA wraps a myPLC
- rspec_type = config.get_aggregate_type()
- assert (rspec_type == 'pl' or rspec_type == 'vini' or \
- rspec_type == 'eucalyptus' or rspec_type == 'max')
+
+ ########## disabled users
+ def is_enabled (self, record):
+ # the incoming record was augmented already, so 'enabled' should be set
+ 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)
+
+ ##########
+ 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):
+ """
+ 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)
+ 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
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):
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)]
# we obtain
# get the sfa records
- # xxx thgen fixme - use SfaTable hardwired for now
- # table = self.SfaTable()
table = SfaTable()
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:
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'] = []
# 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, [])
- else:
- oldList = []
- newList = record.get(listName, [])
-
- # if the lists are the same, then we don't have to update anything
- if (oldList == newList):
- return
-
- # 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()
+ ####################
+ # 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, could be smarter if needed
+ 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:
- # 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
+ logger.info('unexpected relation to maintain, %s -> %s'%(subject_type,target_type))
+
+
+import sys
import xmlrpclib
+import socket
+from urlparse import urlparse
+
+from sfa.util.sfalogging import logger
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):
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
+++ /dev/null
-# 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)
-
-
'extensions': self.extensions
}
- def to_string(self):
+ def __str__(self):
return "%s %s" % (self.type, self.version)
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'])
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')
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
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:
# 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
for hostname in hostnames:
nodes = SFAv1Node.get_nodes(xml, {'component_id': '*%s*' % hostname})
for node in nodes:
- slivers = SFAv1Slivers.get_slivers(node.element)
+ slivers = SFAv1Sliver.get_slivers(node.element)
for sliver in slivers:
node.element.remove(sliver.element)
# get tags
node['tags'] = SFAv1PLTag.get_pl_tags(node_elem, ignore=Node.fields)
- parent = node_elem.getparent()
- if (parent != None) and (parent.tag=="network") and ("name" in parent.attrib):
- node['network_name'] = parent.attrib['name']
+ # temporary... play nice with old slice manager rspec
+ if not node['component_name']:
+ hostname_elem = node_elem.find("hostname")
+ if hostname_elem != None:
+ node['component_name'] = hostname_elem.text
nodes.append(node)
return nodes
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(':')
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()
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())
else:
#raise InvalidRSpec('unknown rspec schema: %s' % schema)
# TODO: Should start raising an exception once SFA defines a schema.
- # for now we just use the default
- self.version = self.version_manager.get_version()
+ # for now we just default to sfa
+ self.version = self.version_manager.get_version({'type':'sfa','version': '1'})
self.version.xml = self.xml
self.namespaces = self.xml.namespaces
import os
-from sfa.util.faults import InvalidRSpec
+from sfa.util.faults import InvalidRSpec, UnsupportedRSpecVersion
from sfa.rspecs.baseversion import BaseVersion
from sfa.util.sfalogging import logger
class VersionManager:
- default_type = 'SFA'
- default_version_num = '1'
-
def __init__(self):
self.versions = []
self.load_versions()
retval = None
for version in self.versions:
if type is None or type.lower() == version.type.lower():
- if version_num is None or version_num == version.version:
+ if version_num is None or str(version_num) == version.version:
if content_type is None or content_type.lower() == version.content_type.lower() \
or version.content_type == '*':
retval = version
if not retval:
- raise InvalidRSpec("No such version format: %s version: %s type:%s "% (type, version_num, content_type))
+ raise UnvalidRSpecVersion("%s %s is not suported here"% (type, version_num, content_type))
return retval
def get_version(self, version=None):
elif isinstance(version, BaseVersion):
retval = version
else:
- retval = self._get_version(self.default_type, self.default_version_num)
+ raise InvalidRSpecVersion("No such version: %s "% str(version))
return retval
}
namespaces = dict(extensions.items() + [('default', namespace)])
- # Networks
+ # Networks
def get_networks(self):
- networks = set()
- nodes = self.xml.xpath('//default:node[@component_manager_id]', namespaces=self.namespaces)
- for node in nodes:
- if 'component_manager_id' in node:
- network_urn = node.get('component_manager_id')
- network_hrn = Xrn(network_urn).get_hrn()[0]
- networks.add({'name': network_hrn})
- return list(networks)
+ network_names = set()
+ 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.attrib:
+ network_urn = node.get('component_manager_id')
+ if network_urn.startswith("urn:"):
+ network_hrn = Xrn(network_urn).get_hrn()[0]
+ else:
+ # some component_manager_ids are hrns instead of urns??
+ network_hrn = network_urn
+ network_names.add(network_hrn)
+ network_names = list(network_names)
+ networks = [{"name": x} for x in network_names]
+ return networks
# Nodes
"""
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
defaults = network_tag.add_element('sliver_defaults')
elif isinstance(defaults, list):
defaults = defaults[0]
- Sfav1Sliver.add_sliver_attribute(defaults, name, value)
+ SFAv1Sliver.add_sliver_attribute(defaults, name, value)
def get_default_sliver_attributes(self, network=None):
if network:
else:
defaults = self.xml.xpath("//sliver_defaults")
if not defaults: return []
- return Sfav1Sliver.get_sliver_attributes(defaults)
+ return SFAv1Sliver.get_sliver_attributes(defaults[0])
def remove_default_sliver_attribute(self, name, value, network=None):
if network:
defaults = self.xml.xpath("//network[@name='%s']/sliver_defaults" % network)
else:
defaults = self.xml.xpath("//sliver_defaults" % network)
- attribs = Sfav1Sliver.get_sliver_attributes(defaults)
+ attribs = SFAv1Sliver.get_sliver_attributes(defaults)
for attrib in attribs:
if attrib['name'] == name and attrib['value'] == value:
attrib.element.delete()
from optparse import OptionParser
from sfa.util.config import Config
-from sfa.util.table import SfaTable
from sfa.trust.gid import GID, create_uuid
from sfa.trust.hierarchy import Hierarchy
+from sfa.storage.table import SfaTable
+
def main():
args = sys.argv
script_name = args[0]
import traceback
import socket
-import sfa.client.xmlrpcprotocol as xmlrpcprotocol
-from sfa.util.table import SfaTable
from sfa.util.prefixTree import prefixTree
from sfa.util.config import Config
-from sfa.generic import Generic
-
from sfa.trust.certificate import Keypair
from sfa.trust.hierarchy import Hierarchy
from sfa.server.registry import Registries
+from sfa.storage.table import SfaTable
+
+import sfa.client.xmlrpcprotocol as xmlrpcprotocol
+
+from sfa.generic import Generic
+
def main():
config = Config()
if not config.SFA_REGISTRY_ENABLED:
Removes old records from the db.
"""
# import SfaTable here so this module can be loaded by PlcComponentApi
- from sfa.util.table import SfaTable
- from sfa.util.record import SfaRecord
+ from sfa.storage.table import SfaTable
+ from sfa.storage.record import SfaRecord
if not gids:
return
table = SfaTable()
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):
"""
import os, os.path
import datetime
-from sfa.util.faults import SfaAPIError
+from sfa.util.faults import SfaFault, SfaAPIError
+from sfa.util.genicode import GENICODE
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
+from sfa.storage.table import SfaTable
####################
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
'am_type': 'sfa',
'am_code': None,
}
- if isinstnace(result, SfaFault):
+ if isinstance(result, SfaFault):
code['geni_code'] = result.faultCode
code['am_code'] = result.faultCode
def get_geni_output(self, result):
output = ""
- if isinstance(result, SFaFault):
+ if isinstance(result, SfaFault):
output = result.faultString
return output
Converts the specified result into a standard GENI compliant
response
"""
- if self.interface.lower() == 'aggregate':
+ if self.interface.lower() in ['aggregate', 'slicemgr']:
if hasattr(self.config, 'SFA_AGGREGATE_API_VERSION') and \
- self.config.SFA_AGGREGATE_API_VERSION == "2":
+ self.config.SFA_AGGREGATE_API_VERSION == 2:
result = self.prepare_response_v2_am(result)
return XmlrpcApi.prepare_response(self, result, method)
callablemethod = getattr(module, classname)(self)
return getattr(module, classname)(self)
except (ImportError, AttributeError):
+ self.logger.log_exc("Error importing method: %s" % method)
raise SfaInvalidAPIMethod, method
def call(self, source, method, *args):
from types import StringTypes
-try:
- set
-except NameError:
- from sets import Set
- set = Set
-
-try: import pgdb
-except: pass
+import pgdb
from sfa.util.faults import SfaInvalidArgument
-from sfa.util.parameter import Parameter, Mixed, python_type
+from sfa.storage.parameter import Parameter, Mixed, python_type
class Filter(Parameter, dict):
"""
from sfa.trust.gid import GID
-from sfa.util.parameter import Parameter
+from sfa.storage.parameter import Parameter
from sfa.util.xrn import get_authority
-from sfa.util.row import Row
+from sfa.storage.row import Row
from sfa.util.xml import XML
class SfaRecord(Row):
--- /dev/null
+--
+-- SFA database schema
+--
+
+SET client_encoding = 'UNICODE';
+
+--------------------------------------------------------------------------------
+-- Version
+--------------------------------------------------------------------------------
+
+-- Database version
+CREATE TABLE sfa_db_version (
+ version integer NOT NULL,
+ subversion integer NOT NULL DEFAULT 0
+) WITH OIDS;
+
+-- the migration scripts do not use the major 'version' number
+-- so 5.0 sets subversion at 100
+-- in case your database misses the site and persons tags feature,
+-- you might wish to first upgrade to 4.3-rc16 before moving to some 5.0
+-- or run the up script here
+-- http://svn.planet-lab.org/svn/PLCAPI/branches/4.3/migrations/
+
+INSERT INTO sfa_db_version (version, subversion) VALUES (1, 1);
+
+--------------------------------------------------------------------------------
+-- Aggregates and store procedures
+--------------------------------------------------------------------------------
+
+-- Like MySQL GROUP_CONCAT(), this function aggregates values into a
+-- PostgreSQL array.
+CREATE AGGREGATE array_accum (
+ sfunc = array_append,
+ basetype = anyelement,
+ stype = anyarray,
+ initcond = '{}'
+);
+
+-- main table
+CREATE TABLE sfa (
+ record_id serial PRIMARY KEY ,
+ hrn text NOT NULL,
+ authority text NOT NULL,
+ peer_authority text,
+ gid text,
+ type text NOT NULL,
+ pointer integer,
+ date_created timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ last_updated timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+CREATE INDEX sfa_hrn_ids on sfa (hrn);
+CREATE INDEX sfa_type_ids on sfa (type);
+CREATE INDEX sfa_authority_ids on sfa (authority);
+CREATE INDEX sfa_peer_authority_ids on sfa (peer_authority);
+CREATE INDEX sfa_pointer_ids on sfa (pointer);
from types import StringTypes
from sfa.util.config import Config
-from sfa.util.parameter import Parameter
-from sfa.util.filter import Filter
-from sfa.util.PostgreSQL import PostgreSQL
-from sfa.util.record import SfaRecord, AuthorityRecord, NodeRecord, SliceRecord, UserRecord
+
+from sfa.storage.parameter import Parameter
+from sfa.storage.filter import Filter
+from sfa.storage.PostgreSQL import PostgreSQL
+from sfa.storage.record import SfaRecord, AuthorityRecord, NodeRecord, SliceRecord, UserRecord
class SfaTable(list):
if tables:
return True
return False
+
def db_fields(self, obj=None):
db_fields = self.db.fields(self.SFA_TABLE_PREFIX)
def create(self):
-
- querystr = "CREATE TABLE " + self.tablename + " ( \
- record_id serial PRIMARY KEY , \
- hrn text NOT NULL, \
- authority text NOT NULL, \
- peer_authority text, \
- gid text, \
- type text NOT NULL, \
- pointer integer, \
- date_created timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, \
- last_updated timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP);"
- template = "CREATE INDEX %s_%s_idx ON %s (%s);"
- indexes = [template % ( self.tablename, field, self.tablename, field) \
- for field in ['hrn', 'type', 'authority', 'peer_authority', 'pointer']]
- # IF EXISTS doenst exist in postgres < 8.2
- try:
- self.db.do('DROP TABLE IF EXISTS ' + self.tablename)
- except:
- try:
- self.db.do('DROP TABLE' + self.tablename)
- except:
- pass
-
- self.db.do(querystr)
- for index in indexes:
- self.db.do(index)
-
- self.db.commit()
+ pass
+# querystr = "CREATE TABLE " + self.tablename + " ( \
+# record_id serial PRIMARY KEY , \
+# hrn text NOT NULL, \
+# authority text NOT NULL, \
+# peer_authority text, \
+# gid text, \
+# type text NOT NULL, \
+# pointer integer, \
+# date_created timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, \
+# last_updated timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP);"
+# template = "CREATE INDEX %s_%s_idx ON %s (%s);"
+# indexes = [template % ( self.tablename, field, self.tablename, field) \
+# for field in ['hrn', 'type', 'authority', 'peer_authority', 'pointer']]
+# # IF EXISTS doenst exist in postgres < 8.2
+# try:
+# self.db.do('DROP TABLE IF EXISTS ' + self.tablename)
+# except:
+# try:
+# self.db.do('DROP TABLE' + self.tablename)
+# except:
+# pass
+#
+# self.db.do(querystr)
+# for index in indexes:
+# self.db.do(index)
+#
+# self.db.commit()
def remove(self, record):
params = {'record_id': record['record_id']}
# 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
# 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:
return (aggr_mgr_ip,aggr_mgr_port)
- def get_aggregate_type(self):
- if (hasattr(self,'SFA_AGGREGATE_TYPE')):
- return self.SFA_AGGREGATE_TYPE
- else:
- return "pl"
-
def get_interface_hrn(self):
if (hasattr(self,'SFA_INTERFACE_HRN')):
return self.SFA_INTERFACE_HRN
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
- }
def __str__(self):
return repr(self.value)
+class InvalidRSpecVersion(SfaFault):
+ def __init__(self, value, extra = None):
+ self.value = value
+ faultString = "Invalid RSpec version: %(value)s" % locals()
+ SfaFault.__init__(self, GENICODE.BADVERSION, faultString, extra)
+ def __str__(self):
+ return repr(self.value)
+
+class UnsupportedRSpecVersion(SfaFault):
+ def __init__(self, value, extra = None):
+ self.value = value
+ faultString = "Unsupported RSpec version: %(value)s" % locals()
+ SfaFault.__init__(self, GENICODE.UNSUPPORTED, faultString, extra)
+ def __str__(self):
+ return repr(self.value)
+
class InvalidRSpecElement(SfaFault):
def __init__(self, value, extra = None):
self.value = value
from types import IntType, LongType, StringTypes
import textwrap
-
from sfa.util.sfalogging import logger
from sfa.util.faults import SfaFault, SfaInvalidAPIMethod, SfaInvalidArgumentCount, SfaInvalidArgument
-from sfa.util.parameter import Parameter, Mixed, python_type, xmlrpc_type
+
+from sfa.storage.parameter import Parameter, Mixed, python_type, xmlrpc_type
class Method:
"""
import xmlrpclib
from sfa.trust.gid import *
from sfa.util.config import *
-from sfa.util.record import *
+from sfa.storage.record import *
class TestRecord(unittest.TestCase):
def setUp(self):
from types import *
from optparse import OptionParser
-from sfa.util.parameter import Parameter,Mixed
+from sfa.storage.parameter import Parameter,Mixed
import globals