From 824bbe4fed48b6ece36257537aec2192d8d0293a Mon Sep 17 00:00:00 2001 From: felix-jenkins Date: Wed, 2 Sep 2015 12:28:30 +0200 Subject: [PATCH] Automatic merge of 'ocf' into 'master' --- .gitignore | 80 + CHANGELOG | 667 +++ LICENSE | 12 + README.md | 152 + core/__init__.py | 0 core/lib/__init__.py | 0 core/lib/am/__init__.py | 0 core/lib/am/ambase/__init__.py | 0 core/lib/am/ambase/src/__init__.py | 34 + core/lib/am/ambase/src/abstract/__init__.py | 0 .../ambase/src/abstract/classes/__init__.py | 5 + .../abstract/classes/credentialmanagerbase.py | 21 + .../src/abstract/classes/delegatebase.py | 62 + .../src/abstract/classes/handlerbase.py | 55 + .../abstract/classes/resourcemanagerbase.py | 39 + .../src/abstract/classes/rspecmanagerbase.py | 33 + core/lib/am/ambase/src/ambase/__init__.py | 0 core/lib/am/ambase/src/ambase/exceptions.py | 28 + core/lib/am/ambase/src/geni/__init__.py | 0 .../am/ambase/src/geni/exceptions/__init__.py | 1 + .../am/ambase/src/geni/exceptions/manager.py | 24 + core/lib/am/ambase/src/geni/v3/__init__.py | 0 .../ambase/src/geni/v3/delegate/__init__.py | 0 .../ambase/src/geni/v3/delegate/delegate.py | 123 + .../am/ambase/src/geni/v3/handler/__init__.py | 0 .../am/ambase/src/geni/v3/handler/handler.py | 474 ++ core/lib/am/credentials/__init__.py | 0 core/lib/am/credentials/src/DEPENDENCIES | 4 + core/lib/am/credentials/src/__init__.py | 0 .../am/credentials/src/manager/__init__.py | 0 .../am/credentials/src/manager/gcfmanager.py | 78 + .../lib/am/credentials/src/manager/manager.py | 82 + core/lib/am/credentials/src/trust/__init__.py | 0 .../credentials/src/trust/abaccredential.py | 285 ++ core/lib/am/credentials/src/trust/auth.py | 309 ++ .../am/credentials/src/trust/certificate.py | 782 +++ .../am/credentials/src/trust/credential.py | 1138 +++++ .../src/trust/credential_legacy.py | 272 ++ core/lib/am/credentials/src/trust/gid.py | 262 + .../lib/am/credentials/src/trust/hierarchy.py | 380 ++ core/lib/am/credentials/src/trust/rights.py | 253 + .../lib/am/credentials/src/trust/sfaticket.py | 126 + .../am/credentials/src/trust/trustedroots.py | 43 + .../am/credentials/src/trustgcf/__init__.py | 0 .../src/trustgcf/abac_credential.py | 282 ++ .../am/credentials/src/trustgcf/cert_util.py | 111 + .../credentials/src/trustgcf/certificate.py | 794 +++ .../am/credentials/src/trustgcf/cred_util.py | 367 ++ .../am/credentials/src/trustgcf/credential.py | 1143 +++++ .../src/trustgcf/credential_factory.py | 109 + .../src/trustgcf/credential_legacy.py | 272 ++ core/lib/am/credentials/src/trustgcf/gid.py | 259 + .../lib/am/credentials/src/trustgcf/rights.py | 276 ++ .../src/trustgcf/speaksfor_util.py | 455 ++ core/lib/am/ext/my_roots/alice-cert.pem | 28 + core/lib/am/ext/my_roots/alice-key.pem | 16 + core/lib/am/ext/my_roots/topdomain.gid | 14 + core/lib/am/ext/schemas/credential.xsd | 214 + core/lib/am/ext/trusted_roots/alice-cert.pem | 28 + core/lib/am/ext/trusted_roots/gpo.gid | 14 + core/lib/am/ext/trusted_roots/topdomain.gid | 14 + core/lib/am/geniutils/__init__.py | 0 core/lib/am/geniutils/src/__init__.py | 0 core/lib/am/geniutils/src/faults/__init__.py | 0 core/lib/am/geniutils/src/faults/faults.py | 344 ++ core/lib/am/geniutils/src/faults/genicode.py | 45 + core/lib/am/geniutils/src/time/__init__.py | 0 core/lib/am/geniutils/src/time/timewrapper.py | 43 + core/lib/am/geniutils/src/urn/__init__.py | 0 core/lib/am/geniutils/src/urn/utils.py | 248 + core/lib/am/geniutils/src/xrn/__init__.py | 0 core/lib/am/geniutils/src/xrn/xrn.py | 268 + core/lib/am/rspecs/__init__.py | 0 core/lib/am/rspecs/src/__init__.py | 0 core/lib/am/rspecs/src/geni/__init__.py | 0 core/lib/am/rspecs/src/geni/v3/__init__.py | 0 .../rspecs/src/geni/v3/container/__init__.py | 0 .../rspecs/src/geni/v3/container/aggregate.py | 37 + .../am/rspecs/src/geni/v3/container/link.py | 54 + .../rspecs/src/geni/v3/container/resource.py | 113 + .../am/rspecs/src/geni/v3/container/slice.py | 57 + .../am/rspecs/src/geni/v3/container/sliver.py | 89 + .../am/rspecs/src/geni/v3/craftermanager.py | 132 + core/lib/am/rspecs/src/geni/v3/manager.py | 18 + .../rspecs/src/geni/v3/openflow/__init__.py | 0 .../geni/v3/openflow/container/__init__.py | 0 .../geni/v3/openflow/container/controller.py | 51 + .../src/geni/v3/openflow/container/dpid.py | 31 + .../geni/v3/openflow/container/flowspace.py | 56 + .../src/geni/v3/openflow/container/group.py | 44 + .../src/geni/v3/openflow/container/link.py | 41 + .../src/geni/v3/openflow/container/match.py | 134 + .../src/geni/v3/openflow/container/port.py | 30 + .../src/geni/v3/openflow/foamlibcrafter.py | 141 + .../src/geni/v3/openflow/foamlibparser.py | 192 + .../am/rspecs/src/geni/v3/openflow/manager.py | 19 + .../am/rspecs/src/geni/v3/parsermanager.py | 81 + core/lib/am/settings/__init__.py | 0 core/lib/am/settings/src/__init__.py | 0 core/lib/am/settings/src/settings.py | 32 + deploy/common/certificates/ca_cert.conf | 23 + deploy/common/certificates/certificates.sh | 173 + deploy/common/certificates/server_cert.conf | 23 + deploy/dependencies/apache.sh | 22 + deploy/dependencies/flowvisor.sh | 137 + deploy/dependencies/mysqlserver.sh | 68 + deploy/gui/checklist.sh | 18 + deploy/gui/end.sh | 22 + deploy/gui/info.sh | 16 + deploy/gui/splash.sh | 155 + deploy/gui/start_step.sh | 36 + deploy/gui/yesno.sh | 15 + deploy/install.py | 22 + deploy/migrate.py | 18 + deploy/remove.py | 16 + deploy/upgrade.py | 19 + deploy/utils/__init__.py | 0 deploy/utils/migrate.sh | 122 + deploy/utils/scripts/flowvisor_cron.sh | 20 + deploy/utils/utils.py | 183 + deploy/utils/utils.sh | 114 + expedient/.gitignore | 44 + expedient/bin/common/commands | 108 + expedient/bin/common/init | 87 + expedient/bin/common/modules | 68 + expedient/bin/common/repository | 59 + expedient/bin/common/utils | 247 + expedient/bin/common/versioning | 45 + expedient/bin/log/.gitignore | 0 expedient/bin/ofver | 85 + expedient/bin/repo | 14 + expedient/bin/rescue/.gitignore | 0 expedient/bin/settings | 17 + .../bin/versions/0.13/upgrade/0.12/backup | 32 + .../0.13/upgrade/0.12/pre-backup-upgrade-hook | 50 + .../0.14.2/upgrade/default/pre-upgrade-hook | 54 + .../0.2/upgrade/default/post-upgrade-hook | 22 + .../default/tools/permissionsRefactor.py | 68 + expedient/bin/versions/0.21.1 | 1 + expedient/bin/versions/0.21/upgrade/0.14.2 | 1 + expedient/bin/versions/0.2RC1 | 1 + .../0.3/upgrade/default/post-upgrade-hook | 38 + .../0.3/upgrade/default/pre-upgrade-hook | 151 + expedient/bin/versions/0.3RC1 | 1 + expedient/bin/versions/0.4.1 | 1 + expedient/bin/versions/0.4.2 | 1 + expedient/bin/versions/0.4.3 | 1 + .../0.4/upgrade/default/pre-upgrade-hook | 62 + .../0.5/upgrade/default/pre-upgrade-hook | 96 + .../0.6.1/upgrade/0.5/post-upgrade-hook | 55 + .../0.6.1/upgrade/0.5/pre-upgrade-hook | 61 + expedient/bin/versions/0.6.1/upgrade/0.6 | 1 + .../0.6/upgrade/default/pre-upgrade-hook | 38 + .../0.7/upgrade/default/pre-upgrade-hook | 36 + expedient/bin/versions/0.8.1 | 1 + expedient/bin/versions/0.8.2 | 1 + .../default/lib/set_environment_variables | 1 + .../0.8.3/upgrade/default/pre-upgrade-hook | 102 + .../0.8/upgrade/default/pre-upgrade-hook | 98 + expedient/bin/versions/default/install/backup | 13 + .../bin/versions/default/install/install | 84 + .../versions/default/install/lib/dependencies | 9 + .../versions/default/install/lib/django-db | 13 + .../default/install/lib/django-settings | 57 + .../bin/versions/default/install/lib/pypelib | 48 + .../install/lib/set_environment_variables | 47 + .../bin/versions/default/install/lib/ssl | 90 + .../default/install/post-install-hook | 20 + .../versions/default/install/pre-install-hook | 38 + expedient/bin/versions/default/install/repo | 16 + .../bin/versions/default/install/rollback | 13 + .../versions/default/upgrade/default/backup | 28 + .../default/upgrade/default/dependencies | 9 + .../default/lib/set_environment_variables | 1 + .../default/upgrade/default/post-upgrade-hook | 23 + .../default/upgrade/default/pre-upgrade-hook | 49 + .../versions/default/upgrade/default/rollback | 36 + .../versions/default/upgrade/default/upgrade | 44 + .../default/upgrade/tools/cleanCache.py | 27 + .../bin/versions/default/upgrade/tools/prova | 1782 +++++++ .../versions/default/upgrade/tools/prova.cfg | 6 + .../versions/default/upgrade/tools/sqlDump.py | 65 + .../default/upgrade/tools/sqlRestore.py | 54 + expedient/bin/versions/version-checks | 57 + .../aggregate/sr_manager/src/__init__.py | 0 .../sr_manager/src/__init__.py~ofelia.stable | 0 .../src/communications/XmlRpcAPI.py | 27 + .../src/communications/XmlRpcServer.py | 142 + .../sr_manager/src/communications/__init__.py | 0 .../src/controller/ResourceController.py | 29 + .../sr_manager/src/controller/__init__.py | 0 .../aggregate/sr_manager/src/resources.xml | 49 + .../src/security/certificates/sr_am.crt | 13 + .../src/security/certificates/sr_am.key | 15 + .../aggregate/sr_manager/src/server.py | 17 + .../aggregate/sr_manager/src/settings.py | 32 + .../sr_manager/src/tests/parse_resources.py | 68 + .../aggregate/sr_manager/src/utils/Logger.py | 35 + .../sr_manager/src/utils/__init__.py | 0 .../plugin/sample_resource/__init__.py | 0 .../controller/GUIdispatcher.py | 174 + .../sample_resource/controller/__init__.py | 0 .../sample_resource/controller/aggregate.py | 207 + .../sample_resource/controller/resource.py | 70 + .../sample_resource/forms/SampleResource.py | 37 + .../forms/SampleResourceAggregate.py | 22 + .../plugin/sample_resource/forms/__init__.py | 0 .../forms/xmlrpcServerProxy.py | 53 + .../sample_resource/models/SampleResource.py | 100 + .../models/SampleResourceAggregate.py | 71 + .../plugin/sample_resource/models/__init__.py | 27 + .../models/xmlrpcServerProxy.py | 30 + .../plugin/sample_resource/settings.conf | 110 + .../static/media/default/css/style.css | 54 + .../static/media/default/img/sensor-tiny.png | Bin 0 -> 1368 bytes .../samples/plugin/sample_resource/urls.py | 14 + .../plugin/sample_resource/utils/__init__.py | 0 .../sample_resource/utils/validators.py | 28 + .../sample_resource_add_resources.html | 104 + .../sample_resource_aggregate_crud.html | 27 + .../sample_resource_list_resources.html | 77 + .../sample_resource_resource_crud.html | 34 + .../apache/vhost-clearinghouse.conf | 7 + .../expedient/common/apache/vhost-macros.conf | 340 ++ expedient/src/doc/expedient/Makefile | 142 + .../src/doc/expedient/source/admin/index.rst | 9 + .../doc/expedient/source/admin/install.rst | 472 ++ .../doc/expedient/source/admin/openflow.rst | 99 + expedient/src/doc/expedient/source/conf.py | 220 + .../doc/expedient/source/developer/index.rst | 9 + ...slice-aggregate-resource-relationships.png | Bin 0 -> 9417 bytes .../source/developer/sshaggregate/__init__.py | 0 .../source/developer/sshaggregate/models.py | 249 + .../sshaggregate/aggregate_add_servers.html | 30 + .../sshaggregate/aggregate_crud.html | 26 + .../sshaggregate/sshaggregate_base.html | 1 + .../source/developer/sshaggregate/tests.py | 243 + .../source/developer/sshaggregate/urls.py | 7 + .../source/developer/sshaggregate/views.py | 58 + .../expedient/source/developer/tutorial.rst | 873 ++++ expedient/src/doc/expedient/source/index.rst | 53 + .../src/doc/expedient/source/user/index.rst | 14 + .../doc/expedient/source/user/tutorial.rst | 157 + expedient/src/python/expedient/__init__.py | 0 .../expedient/clearinghouse/__init__.py | 0 .../clearinghouse/administration/__init__.py | 0 .../clearinghouse/administration/urls.py | 13 + .../clearinghouse/administration/views.py | 168 + .../clearinghouse/aggregate/__init__.py | 5 + .../clearinghouse/aggregate/admin.py | 9 + .../clearinghouse/aggregate/forms.py | 18 + .../clearinghouse/aggregate/models.py | 361 ++ .../clearinghouse/aggregate/permissions.py | 31 + .../clearinghouse/aggregate/tests/__init__.py | 1 + .../clearinghouse/aggregate/tests/forms.py | 12 + .../clearinghouse/aggregate/tests/models.py | 41 + .../templates/aggregate_tests/empty.html | 0 .../tests/templates/aggregate_tests/form.html | 3 + .../clearinghouse/aggregate/tests/tests.py | 156 + .../clearinghouse/aggregate/tests/urls.py | 11 + .../clearinghouse/aggregate/tests/views.py | 33 + .../expedient/clearinghouse/aggregate/urls.py | 13 + .../clearinghouse/aggregate/utils.py | 34 + .../clearinghouse/aggregate/views.py | 160 + .../clearinghouse/bootstrap_local_settings.py | 30 + .../clearinghouse/commands/__init__.py | 0 .../commands/management/__init__.py | 0 .../commands/management/commands/__init__.py | 0 .../commands/bootstrap_local_settings.py | 31 + .../commands/clean_inconsistent_db_entries.py | 25 + .../commands/create_default_root.py | 39 + .../management/commands/create_dummy_oms.py | 39 + .../management/commands/create_secret_key.py | 23 + .../commands/install_cert_makefile.py | 80 + .../management/commands/load_openflow_data.py | 194 + .../management/commands/setup_expedient.py | 21 + .../management/commands/setup_media.py | 31 + .../commands/standardize_flowvisor_slices.py | 240 + .../management/commands/test_expedient.py | 36 + .../clearinghouse/commands/models.py | 5 + .../expedient/clearinghouse/commands/utils.py | 100 + .../clearinghouse/defaultsettings/__init__.py | 0 .../clearinghouse/defaultsettings/admins.py | 16 + .../clearinghouse/defaultsettings/cbas.py | 11 + .../clearinghouse/defaultsettings/database.py | 31 + .../clearinghouse/defaultsettings/django.py | 253 + .../clearinghouse/defaultsettings/email.py | 19 + .../defaultsettings/expedient.py | 112 + .../clearinghouse/defaultsettings/gcf.py | 79 + .../defaultsettings/ldapSettings.py | 133 + .../clearinghouse/defaultsettings/logging.py | 15 + .../defaultsettings/messaging.py | 13 + .../clearinghouse/defaultsettings/openflow.py | 38 + .../defaultsettings/openflowtests.py | 99 + .../clearinghouse/defaultsettings/plugin.py | 59 + .../clearinghouse/defaultsettings/required.py | 20 + .../clearinghouse/defaultsettings/site.py | 16 + .../clearinghouse/defaultsettings/tests.py | 21 + .../clearinghouse/defaultsettings/utils.py | 69 + .../clearinghouse/defaultsettings/xmlrpc.py | 19 + .../expedient/clearinghouse/fapi/.gitignore | 1 + .../expedient/clearinghouse/fapi/LICENSE | 201 + .../expedient/clearinghouse/fapi/__init__.py | 1 + .../expedient/clearinghouse/fapi/cbas.py | 414 ++ .../clearinghouse/fapi/communication_tools.py | 52 + .../fapi/creds/expedient-cred.xml | 152 + .../clearinghouse/firstapp/__init__.py | 0 .../clearinghouse/firstapp/models.py | 16 + .../clearinghouse/gcf-x509-trusted.crt/ch.crt | 13 + .../expedient/clearinghouse/geni/__init__.py | 0 .../expedient/clearinghouse/geni/backends.py | 63 + .../clearinghouse/geni/clearinghouse.py | 139 + .../expedient/clearinghouse/geni/forms.py | 174 + .../clearinghouse/geni/gopenflow/__init__.py | 0 .../clearinghouse/geni/gopenflow/models.py | 70 + .../geni/gopenflow/tests/__init__.py | 283 ++ .../geni/gopenflow/tests/models.py | 27 + .../clearinghouse/geni/gopenflow/tests/rpc.py | 123 + .../geni/gopenflow/tests/urls.py | 10 + .../clearinghouse/geni/gopenflow/urls.py | 12 + .../clearinghouse/geni/gopenflow/views.py | 51 + .../clearinghouse/geni/management.py | 63 + .../clearinghouse/geni/middleware.py | 13 + .../expedient/clearinghouse/geni/models.py | 315 ++ .../clearinghouse/geni/permissions.py | 17 + .../clearinghouse/geni/planetlab/__init__.py | 0 .../geni/planetlab/exceptions.py | 17 + .../clearinghouse/geni/planetlab/models.py | 116 + .../geni/planetlab/sfa-models.py | 456 ++ .../clearinghouse/geni/planetlab/urls.py | 11 + .../expedient/clearinghouse/geni/rpc.py | 28 + .../expedient/clearinghouse/geni/tests.py | 70 + .../expedient/clearinghouse/geni/urls.py | 21 + .../expedient/clearinghouse/geni/utils.py | 267 + .../expedient/clearinghouse/geni/views.py | 479 ++ .../expedient/clearinghouse/help/__init__.py | 0 .../expedient/clearinghouse/help/urls.py | 9 + .../expedient/clearinghouse/help/views.py | 27 + .../expedient/clearinghouse/ldap.ssl/ca.crt | 17 + .../clearinghouse/localsettings-example | 280 ++ .../python/expedient/clearinghouse/manage.py | 13 + .../clearinghouse/messagecenter/__init__.py | 0 .../clearinghouse/messagecenter/urls.py | 8 + .../clearinghouse/messagecenter/views.py | 24 + .../clearinghouse/middleware/__init__.py | 0 .../expedient/clearinghouse/mit/__init__.py | 188 + .../monitoring/AggregateMonitoringThread.py | 102 + .../monitoring/BackgroundMonitor.py | 75 + .../monitoring/SessionMonitoringThread.py | 37 + .../clearinghouse/monitoring/__init__.py | 0 .../clearinghouse/permissionmgmt/__init__.py | 0 .../clearinghouse/permissionmgmt/models.py | 33 + .../clearinghouse/permissionmgmt/tests.py | 85 + .../clearinghouse/permissionmgmt/urls.py | 11 + .../clearinghouse/permissionmgmt/utils.py | 13 + .../clearinghouse/permissionmgmt/views.py | 266 + .../clearinghouse/project/__init__.py | 0 .../expedient/clearinghouse/project/admin.py | 9 + .../expedient/clearinghouse/project/forms.py | 160 + .../expedient/clearinghouse/project/models.py | 279 ++ .../clearinghouse/project/permissions.py | 137 + .../expedient/clearinghouse/project/tests.py | 124 + .../expedient/clearinghouse/project/urls.py | 19 + .../expedient/clearinghouse/project/views.py | 588 +++ .../clearinghouse/resources/__init__.py | 0 .../clearinghouse/resources/admin.py | 10 + .../clearinghouse/resources/models.py | 62 + .../expedient/clearinghouse/roles/__init__.py | 0 .../expedient/clearinghouse/roles/forms.py | 173 + .../expedient/clearinghouse/roles/models.py | 239 + .../expedient/clearinghouse/roles/tests.py | 297 ++ .../expedient/clearinghouse/roles/urls.py | 13 + .../expedient/clearinghouse/roles/utils.py | 39 + .../expedient/clearinghouse/roles/views.py | 246 + .../expedient/clearinghouse/settings.py | 130 + .../expedient/clearinghouse/slice/__init__.py | 0 .../expedient/clearinghouse/slice/admin.py | 9 + .../expedient/clearinghouse/slice/forms.py | 15 + .../expedient/clearinghouse/slice/models.py | 298 ++ .../expedient/clearinghouse/slice/tests.py | 105 + .../expedient/clearinghouse/slice/urls.py | 20 + .../expedient/clearinghouse/slice/utils.py | 26 + .../expedient/clearinghouse/slice/views.py | 355 ++ .../python/expedient/clearinghouse/urls.py | 139 + .../expedient/clearinghouse/users/__init__.py | 0 .../expedient/clearinghouse/users/admin.py | 9 + .../expedient/clearinghouse/users/forms.py | 135 + .../expedient/clearinghouse/users/models.py | 54 + .../clearinghouse/users/permissions.py | 24 + .../expedient/clearinghouse/users/urls.py | 12 + .../expedient/clearinghouse/users/views.py | 223 + .../python/expedient/clearinghouse/utils.py | 263 + .../python/expedient/clearinghouse/views.py | 62 + .../clearinghouse/xmlrpc-ssl.crt/.test | 0 .../clearinghouse/xmlrpc-ssl.crt/Makefile | 54 + .../src/python/expedient/common/__init__.py | 0 .../expedient/common/backends/__init__.py | 0 .../expedient/common/backends/remoteuser.py | 16 + .../expedient/common/breadcrumbs/__init__.py | 0 .../breadcrumbs/templatetags/__init__.py | 0 .../breadcrumbs/templatetags/breadcrumbs.py | 53 + .../expedient/common/clients/__init__.py | 0 .../python/expedient/common/clients/geni.py | 46 + .../python/expedient/common/clients/xmlrpc.py | 20 + .../expedient/common/defaultsite/__init__.py | 0 .../common/defaultsite/management.py | 30 + .../expedient/common/defaultsite/settings.py | 19 + .../expedient/common/extendable/__init__.py | 0 .../common/extendable/inheritance.py | 56 + .../expedient/common/extendable/models.py | 272 ++ .../common/extendable/tests/__init__.py | 1 + .../common/extendable/tests/models.py | 48 + .../common/extendable/tests/tests.py | 53 + .../expedient/common/extendable/utils.py | 18 + .../expedient/common/extendable/views.py | 1 + .../expedient/common/federation/__init__.py | 0 .../federation/geni/SecureXMLRPCServer.py | 93 + .../common/federation/geni/__init__.py | 29 + .../expedient/common/federation/geni/am.py | 567 +++ .../expedient/common/federation/geni/ca.py | 68 + .../expedient/common/federation/geni/ch.py | 358 ++ .../common/federation/geni/config.py | 54 + .../common/federation/geni/util/__init__.py | 0 .../common/federation/geni/util/cert_util.py | 71 + .../common/federation/geni/util/cred_util.py | 302 ++ .../geni/util/secure_xmlrpc_client.py | 54 + .../common/federation/geni/util/urn_util.py | 174 + .../expedient/common/federation/sfa/README.md | 78 + .../common/federation/sfa/__init__.py | 0 .../common/federation/sfa/trust/__init__.py | 0 .../federation/sfa/trust/certificate.py | 618 +++ .../common/federation/sfa/trust/credential.py | 855 ++++ .../federation/sfa/trust/credential_legacy.py | 271 ++ .../common/federation/sfa/trust/gid.py | 230 + .../common/federation/sfa/trust/rights.py | 312 ++ .../common/federation/sfa/util/__init__.py | 0 .../common/federation/sfa/util/faults.py | 321 ++ .../common/federation/sfa/util/namespace.py | 131 + .../common/federation/sfa/util/sfalogging.py | 63 + .../expedient/common/ldapproxy/__init__.py | 0 .../expedient/common/ldapproxy/models.py | 90 + .../python/expedient/common/loggingconf.py | 27 + .../expedient/common/messaging/__init__.py | 0 .../expedient/common/messaging/admin.py | 9 + .../common/messaging/context_processors.py | 15 + .../expedient/common/messaging/forms.py | 32 + .../expedient/common/messaging/models.py | 130 + .../expedient/common/messaging/tests.py | 23 + .../python/expedient/common/messaging/urls.py | 22 + .../expedient/common/messaging/views.py | 140 + .../expedient/common/middleware/__init__.py | 0 .../expedient/common/middleware/basicauth.py | 65 + .../common/middleware/exceptionprinter.py | 14 + .../common/middleware/sitelockdown.py | 43 + .../common/middleware/threadlocals.py | 116 + .../expedient/common/middleware/utils.py | 25 + .../expedient/common/permissions/__init__.py | 0 .../expedient/common/permissions/admin.py | 12 + .../expedient/common/permissions/backend.py | 33 + .../common/permissions/decorators.py | 106 + .../common/permissions/exceptions.py | 123 + .../expedient/common/permissions/forms.py | 75 + .../common/permissions/management.py | 60 + .../expedient/common/permissions/managers.py | 538 ++ .../common/permissions/middleware.py | 167 + .../expedient/common/permissions/models.py | 253 + .../expedient/common/permissions/shortcuts.py | 158 + .../permissions/templatetags/__init__.py | 0 .../permissions/templatetags/permissions.py | 37 + .../common/permissions/tests/__init__.py | 1 + .../common/permissions/tests/models.py | 44 + .../common/permissions/tests/test_urls.py | 34 + .../common/permissions/tests/tests.py | 565 +++ .../common/permissions/tests/views.py | 92 + .../expedient/common/permissions/urls.py | 11 + .../expedient/common/permissions/utils.py | 216 + .../expedient/common/permissions/views.py | 183 + .../expedient/common/rpc4django/__init__.py | 61 + .../common/rpc4django/jsonrpcdispatcher.py | 154 + .../expedient/common/rpc4django/models.py | 11 + .../common/rpc4django/rpcdispatcher.py | 267 + .../rpc4django/rpcmethod_summary.html | 137 + .../rpc4django/templatetags/__init__.py | 0 .../common/rpc4django/templatetags/rpctags.py | 48 + .../common/rpc4django/tests/__init__.py | 11 + .../tests/test_jsonrpcdispatcher.py | 145 + .../rpc4django/tests/test_rpcdispatcher.py | 155 + .../common/rpc4django/tests/test_rpcviews.py | 175 + .../common/rpc4django/tests/test_urls.py | 12 + .../rpc4django/tests/test_xmlrpcdispatcher.py | 33 + .../rpc4django/tests/testmod/__init__.py | 10 + .../common/rpc4django/tests/testmod/models.py | 5 + .../tests/testmod/testsubmod/__init__.py | 9 + .../expedient/common/rpc4django/utils.py | 20 + .../expedient/common/rpc4django/views.py | 278 ++ .../common/rpc4django/xmlrpcdispatcher.py | 96 + .../python/expedient/common/tests/__init__.py | 5 + .../python/expedient/common/tests/client.py | 239 + .../python/expedient/common/tests/commands.py | 45 + .../python/expedient/common/tests/manager.py | 75 + .../python/expedient/common/tests/utils.py | 104 + .../python/expedient/common/timer/__init__.py | 0 .../expedient/common/timer/exceptions.py | 35 + .../common/timer/management/__init__.py | 0 .../timer/management/commands/__init__.py | 0 .../management/commands/run_timer_jobs.py | 21 + .../python/expedient/common/timer/models.py | 138 + .../python/expedient/common/timer/models_or | 141 + .../python/expedient/common/timer/tests.py | 142 + .../python/expedient/common/timer/utils.py | 11 + .../common/utils/ExpedientThemeManager.py | 74 + .../expedient/common/utils/ServiceThread.py | 32 + .../python/expedient/common/utils/__init__.py | 42 + .../expedient/common/utils/certtransport.py | 55 + .../common/utils/context_processors.py | 20 + .../expedient/common/utils/formfields.py | 78 + .../src/python/expedient/common/utils/mail.py | 28 + .../python/expedient/common/utils/managers.py | 99 + .../expedient/common/utils/modelfields.py | 84 + .../common/utils/plugins/__init__.py | 0 .../common/utils/plugins/confparser.py | 54 + .../utils/plugins/plugincommunicator.py | 74 + .../common/utils/plugins/plugininterface.py | 35 + .../common/utils/plugins/pluginloader.py | 118 + .../utils/plugins/resources/__init__.py | 0 .../common/utils/plugins/resources/link.py | 20 + .../common/utils/plugins/resources/node.py | 25 + .../common/utils/plugins/topologygenerator.py | 220 + .../expedient/common/utils/plugins/utils.py | 27 + .../python/expedient/common/utils/signals.py | 6 + .../common/utils/templatetags/__init__.py | 0 .../common/utils/templatetags/ch_extras.py | 76 + .../common/utils/templatetags/flowspace.py | 37 + .../common/utils/templatetags/servers.py | 23 + .../common/utils/templatetags/url.py | 83 + .../expedient/common/utils/transport.py | 49 + .../expedient/common/utils/validators.py | 66 + .../python/expedient/common/utils/views.py | 85 + .../common/xmlrpc_serverproxy/__init__.py | 0 .../common/xmlrpc_serverproxy/admin.py | 9 + .../common/xmlrpc_serverproxy/forms.py | 91 + .../common/xmlrpc_serverproxy/models.py | 234 + expedient/src/python/expedient/ui/__init__.py | 0 .../src/python/expedient/ui/rspec/__init__.py | 8 + .../src/python/expedient/ui/rspec/forms.py | 12 + .../src/python/expedient/ui/rspec/models.py | 5 + .../ui/rspec/templates/rspec/home.html | 34 + .../src/python/expedient/ui/rspec/urls.py | 12 + .../src/python/expedient/ui/rspec/views.py | 62 + expedient/src/python/ez_setup.py | 284 ++ expedient/src/python/omnilib/__init__.py | 0 .../src/python/omnilib/frameworks/__init__.py | 0 .../omnilib/frameworks/framework_base.py | 87 + .../omnilib/frameworks/framework_gcf.py | 112 + .../python/omnilib/frameworks/framework_of.py | 112 + .../python/omnilib/frameworks/framework_pg.py | 300 ++ .../omnilib/frameworks/framework_sfa.py | 290 ++ .../src/python/omnilib/omnispec/__init__.py | 27 + .../src/python/omnilib/omnispec/omnispec.py | 144 + .../src/python/omnilib/omnispec/rspec_gcf.py | 58 + .../src/python/omnilib/omnispec/rspec_of.py | 325 ++ .../src/python/omnilib/omnispec/rspec_pg.py | 163 + .../src/python/omnilib/omnispec/rspec_sfa.py | 91 + .../python/omnilib/omnispec/translation.py | 59 + expedient/src/python/omnilib/util/__init__.py | 0 .../src/python/omnilib/util/namespace.py | 38 + .../src/python/omnilib/xmlrpc/__init__.py | 0 expedient/src/python/omnilib/xmlrpc/client.py | 53 + expedient/src/python/plugins/__init__.py | 0 .../src/python/plugins/m_gui/__init__.py | 0 .../python/plugins/m_gui/forms/__init__.py | 0 .../python/plugins/m_gui/forms/monitoring.py | 206 + .../src/python/plugins/m_gui/models/MGUI.py | 13 + .../python/plugins/m_gui/models/__init__.py | 28 + .../src/python/plugins/m_gui/settings.conf | 163 + .../default/css/jquery.datetimepicker.css | 306 ++ .../static/media/default/css/monitor_cp.css | 123 + .../media/default/css/monitor_network.css | 123 + .../static/media/default/css/ocf-iframe.css | 1221 +++++ .../media/default/css/tooltip.monitor_cp.css | 48 + .../default/css/tooltip.monitor_network.css | 48 + .../media/default/css/tooltip.topology.css | 113 + .../static/media/default/css/topology.css | 24 + .../static/media/default/img/switch-se.png | Bin 0 -> 1159 bytes .../m_gui/static/media/default/img/tn.png | Bin 0 -> 1221 bytes .../static/media/default/js/d3.v2.min.js | 4 + .../media/default/js/jquery.datetimepicker.js | 1502 ++++++ .../media/default/js/tooltip.monitor_cp.js | 75 + .../default/js/tooltip.monitor_network.js | 75 + .../media/default/js/tooltip.topology.js | 92 + .../static/media/default/js/topology.layer.js | 430 ++ .../static/media/default/js/topology.util.js | 429 ++ .../plugins/m_gui/templates/default/base.html | 133 + .../m_gui/templates/default/iframebase.html | 23 + .../m_gui/templates/default/monitor_cp.html | 416 ++ .../templates/default/monitor_network.html | 417 ++ .../m_gui/templates/default/monitoring.html | 43 + .../m_gui/templates/default/slice.html | 72 + .../m_gui/templates/default/slice_detail.html | 27 + .../m_gui/templates/default/topology.html | 621 +++ expedient/src/python/plugins/m_gui/urls.py | 17 + .../python/plugins/m_gui/views/__init__.py | 0 .../python/plugins/m_gui/views/monitoring.py | 1277 +++++ .../src/python/plugins/openflow/__init__.py | 0 .../plugins/openflow/dummyom/__init__.py | 6 + .../python/plugins/openflow/dummyom/ch_api.py | 134 + .../python/plugins/openflow/dummyom/models.py | 150 + .../python/plugins/openflow/dummyom/urls.py | 11 + .../plugins/openflow/plugin/__init__.py | 3 + .../python/plugins/openflow/plugin/admin.py | 19 + .../python/plugins/openflow/plugin/forms.py | 271 ++ .../plugins/openflow/plugin/gapi/__init__.py | 2 + .../plugins/openflow/plugin/gapi/gapi.py | 253 + .../plugins/openflow/plugin/gapi/rpc.py | 144 + .../plugins/openflow/plugin/gapi/rspec.py | 607 +++ .../python/plugins/openflow/plugin/models.py | 647 +++ .../python/plugins/openflow/plugin/tests.py | 1029 ++++ .../python/plugins/openflow/plugin/urls.py | 25 + .../python/plugins/openflow/plugin/views.py | 971 ++++ .../plugins/openflow/plugin/vlan/__init__.py | 0 .../plugins/openflow/plugin/vlan/manager.py | 117 + .../plugins/openflow/plugin/vlan/utils.py | 15 + .../python/plugins/openflow/plugin/vlans.py | 66 + .../python/plugins/openflow/plugin/xmlrpc.py | 28 + .../src/python/plugins/openflow/settings.conf | 112 + .../static/media/default/img/genilogo.png | Bin 0 -> 8919 bytes .../static/media/default/img/host-tiny.png | Bin 0 -> 2072 bytes .../static/media/default/img/switch-tiny.png | Bin 0 -> 1967 bytes .../static/media/default/js/loop_detection.js | 157 + .../python/plugins/openflow/tests/__init__.py | 0 .../plugins/openflow/tests/full/__init__.py | 0 .../plugins/openflow/tests/full/fulltests.py | 690 +++ .../plugins/openflow/tests/full/helpers.py | 67 + .../plugins/openflow/tests/gapi/__init__.py | 0 .../plugins/openflow/tests/gapi/gapi.py | 500 ++ .../python/plugins/openflow/tests/helpers.py | 318 ++ .../openflow/tests/manual_test/__init__.py | 0 .../openflow/tests/manual_test/manual.py | 193 + .../plugins/openflow/tests/om/__init__.py | 0 .../python/plugins/openflow/tests/om/om.py | 432 ++ .../openflow/tests/omctl/XMLRPCServerProxy.py | 187 + .../plugins/openflow/tests/omctl/__init__.py | 0 .../plugins/openflow/tests/omctl/helpers.py | 233 + .../plugins/openflow/tests/omctl/omctl.py | 110 + .../openflow/tests/omctl/omctl_settings.py | 2 + .../tests/post_deployment/__init__.py | 0 .../openflow/tests/post_deployment/tests.py | 203 + .../plugins/openflow/tests/ssl/Makefile | 47 + .../plugins/openflow/tests/test_settings.py | 74 + .../python/plugins/openflow/tests/tests.py | 14 + .../default/openflow_add_resources.html | 343 ++ .../default/openflow_aggregate_add_links.html | 60 + .../openflow_aggregate_add_to_slice.html | 61 + .../default/openflow_aggregate_crud.html | 32 + .../default/openflow_select_flowspace.html | 247 + .../default/openflow_select_resources.html | 514 ++ .../src/python/plugins/vt_plugin/__init__.py | 0 .../vt_plugin/communication/__init__.py | 1 + .../communication/southCommInterface.py | 19 + .../controller/VMcontroller/VMcontroller.py | 84 + .../controller/VMcontroller/__init__.py | 0 .../plugins/vt_plugin/controller/__init__.py | 0 .../controller/dispatchers/GUIdispatcher.py | 417 ++ .../dispatchers/InformationDispatcher.py | 96 + .../MonitoringResponseDispatcher.py | 31 + .../dispatchers/ProvisioningDispatcher.py | 178 + .../ProvisioningResponseDispatcher.py | 174 + .../controller/dispatchers/__init__.py | 0 .../vtAggregateController/__init__.py | 0 .../vtAggregateController/forms/__init__.py | 0 .../vtAggregateController/forms/forms.py | 64 + .../vtAggregateController.py | 185 + .../src/python/plugins/vt_plugin/forms/VM.py | 20 + .../plugins/vt_plugin/forms/__init__.py | 0 .../plugins/vt_plugin/forms/remove_vm.py | 14 + .../python/plugins/vt_plugin/models/Action.py | 22 + .../src/python/plugins/vt_plugin/models/VM.py | 223 + .../plugins/vt_plugin/models/VTServer.py | 142 + .../plugins/vt_plugin/models/VTServerIface.py | 13 + .../plugins/vt_plugin/models/VtPlugin.py | 71 + .../plugins/vt_plugin/models/__init__.py | 29 + .../python/plugins/vt_plugin/models/iface.py | 19 + .../plugins/vt_plugin/models/resourcesHash.py | 14 + .../vt_plugin/models/xmlrpcServerProxy.py | 26 + .../python/plugins/vt_plugin/settings.conf | 110 + .../static/media/default/img/server-tiny.png | Bin 0 -> 2103 bytes .../plugins/vt_plugin/tests/deleteAllVMs.py | 24 + .../plugins/vt_plugin/tests/deleteVM.py | 24 + .../src/python/plugins/vt_plugin/urls.py | 24 + .../plugins/vt_plugin/utils/ServiceThread.py | 25 + .../plugins/vt_plugin/utils/Translator.py | 188 + .../plugins/vt_plugin/utils/__init__.py | 0 .../plugins/vt_plugin/utils/validators.py | 36 + .../default/vt_plugin_add_resources.html | 320 ++ .../default/vt_plugin_administration.html | 62 + ..._plugin_aggregate_add_virtualmachines.html | 67 + .../default/vt_plugin_aggregate_crud.html | 27 + .../templates/default/vt_plugin_base.html | 1 + .../default/vt_plugin_list_resources.html | 112 + .../default/vt_plugin_messages_panel.html | 24 + .../media/FELIX/css/notifications.css | 102 + .../clearinghouse/media/FELIX/css/ocf.css | 1415 ++++++ .../media/FELIX/img/logo_expedient.png | Bin 0 -> 4178 bytes .../clearinghouse/media/FIBRE/css/ocf.css | 1415 ++++++ .../media/FIBRE/img/logo_expedient.png | Bin 0 -> 19842 bytes .../media/default/css/aggregate.css | 11 + .../media/default/css/css/aggregate.css | 11 + .../media/default/css/css/help.css | 8 + .../css/images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../css/images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../css/images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../css/images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../css/images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../css/images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../media/default/css/css/jquery-ui.css | 464 ++ .../media/default/css/css/notifications.css | 74 + .../media/default/css/css/ocf-iframe.css | 1050 ++++ .../media/default/css/css/ocf.css | 1227 +++++ .../media/default/css/css/permission.css | 11 + .../media/default/css/css/project.css | 4 + .../media/default/css/css/slice.css | 49 + .../media/default/css/css/slice.topology.css | 51 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_55_fbec88_40x100.png | Bin 0 -> 182 bytes .../images/ui-bg_glass_75_d0e5f5_1x400.png | Bin 0 -> 124 bytes .../images/ui-bg_glass_85_dfeffc_1x400.png | Bin 0 -> 123 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_gloss-wave_55_5c9ccc_500x100.png | Bin 0 -> 3457 bytes .../ui-bg_inset-hard_100_f5f8f9_1x100.png | Bin 0 -> 104 bytes .../ui-bg_inset-hard_100_fcfdfd_1x100.png | Bin 0 -> 88 bytes .../images/ui-icons_217bc0_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_469bdd_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_6da8d5_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_d8e7f3_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_f9bd01_256x240.png | Bin 0 -> 4369 bytes .../css/css/themes/redmond/jquery-ui.css | 563 +++ .../themes/redmond/jquery.ui.accordion.css | 19 + .../themes/redmond/jquery.ui.autocomplete.css | 53 + .../css/css/themes/redmond/jquery.ui.base.css | 11 + .../css/themes/redmond/jquery.ui.button.css | 38 + .../css/css/themes/redmond/jquery.ui.core.css | 38 + .../themes/redmond/jquery.ui.datepicker.css | 66 + .../css/themes/redmond/jquery.ui.dialog.css | 21 + .../themes/redmond/jquery.ui.progressbar.css | 11 + .../themes/redmond/jquery.ui.resizable.css | 20 + .../themes/redmond/jquery.ui.selectable.css | 10 + .../css/themes/redmond/jquery.ui.slider.css | 24 + .../css/css/themes/redmond/jquery.ui.tabs.css | 18 + .../css/themes/redmond/jquery.ui.theme.css | 249 + .../media/default/css/css/tooltip.css | 49 + .../default/css/css/tooltip.topology.css | 48 + .../media/default/css/egeni-iframe.css | 982 ++++ .../clearinghouse/media/default/css/egeni.css | 596 +++ .../clearinghouse/media/default/css/help.css | 8 + .../css/images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../css/images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../css/images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../css/images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../css/images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../css/images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../media/default/css/jquery-ui.css | 464 ++ .../media/default/css/notifications.css | 102 + .../media/default/css/ocf-iframe.css | 1221 +++++ .../clearinghouse/media/default/css/ocf.css | 1413 ++++++ .../media/default/css/permission.css | 11 + .../media/default/css/project.css | 90 + .../clearinghouse/media/default/css/slice.css | 49 + .../media/default/css/slice.topology.css | 51 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_55_fbec88_40x100.png | Bin 0 -> 182 bytes .../images/ui-bg_glass_75_d0e5f5_1x400.png | Bin 0 -> 124 bytes .../images/ui-bg_glass_85_dfeffc_1x400.png | Bin 0 -> 123 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_gloss-wave_55_5c9ccc_500x100.png | Bin 0 -> 3457 bytes .../ui-bg_inset-hard_100_f5f8f9_1x100.png | Bin 0 -> 104 bytes .../ui-bg_inset-hard_100_fcfdfd_1x100.png | Bin 0 -> 88 bytes .../images/ui-icons_217bc0_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_469bdd_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_6da8d5_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_d8e7f3_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_f9bd01_256x240.png | Bin 0 -> 4369 bytes .../default/css/themes/redmond/jquery-ui.css | 563 +++ .../themes/redmond/jquery.ui.accordion.css | 19 + .../css/themes/redmond/jquery.ui.all.css | 11 + .../themes/redmond/jquery.ui.autocomplete.css | 53 + .../css/themes/redmond/jquery.ui.base.css | 11 + .../css/themes/redmond/jquery.ui.button.css | 38 + .../css/themes/redmond/jquery.ui.core.css | 38 + .../themes/redmond/jquery.ui.datepicker.css | 66 + .../css/themes/redmond/jquery.ui.dialog.css | 21 + .../themes/redmond/jquery.ui.progressbar.css | 11 + .../themes/redmond/jquery.ui.resizable.css | 20 + .../themes/redmond/jquery.ui.selectable.css | 10 + .../css/themes/redmond/jquery.ui.slider.css | 24 + .../css/themes/redmond/jquery.ui.tabs.css | 18 + .../css/themes/redmond/jquery.ui.theme.css | 249 + .../media/default/css/tooltip.css | 49 + .../media/default/css/tooltip.topology.css | 48 + .../media/default/img/account.png | Bin 0 -> 3443 bytes .../media/default/img/active.png | Bin 0 -> 4171 bytes .../media/default/img/aggregate-tiny.png | Bin 0 -> 2527 bytes .../clearinghouse/media/default/img/black.png | Bin 0 -> 1213 bytes .../media/default/img/black_arrow.png | Bin 0 -> 2129 bytes .../media/default/img/black_arrow_big.png | Bin 0 -> 4510 bytes .../media/default/img/black_big.png | Bin 0 -> 2734 bytes .../media/default/img/button.pxm | Bin 0 -> 6747 bytes .../media/default/img/dashboard.png | Bin 0 -> 3833 bytes .../media/default/img/expand.png | Bin 0 -> 500 bytes .../media/default/img/favicon.ico | Bin 0 -> 4286 bytes .../media/default/img/groupin.png | Bin 0 -> 1097 bytes .../clearinghouse/media/default/img/help.png | Bin 0 -> 3091 bytes .../media/default/img/inactive.png | Bin 0 -> 3925 bytes .../media/default/img/loading.gif | Bin 0 -> 1849 bytes .../media/default/img/logo_expedient.png | Bin 0 -> 23342 bytes .../media/default/img/logout.png | Bin 0 -> 3319 bytes .../media/default/img/msg_announcement.png | Bin 0 -> 493 bytes .../media/default/img/msg_error.png | Bin 0 -> 549 bytes .../media/default/img/msg_info.png | Bin 0 -> 859 bytes .../media/default/img/msg_success.png | Bin 0 -> 628 bytes .../media/default/img/msg_user2user.png | Bin 0 -> 747 bytes .../media/default/img/navigation.png | Bin 0 -> 274 bytes .../media/default/img/notification_16x16.png | Bin 0 -> 553 bytes .../media/default/img/ofelia.png | Bin 0 -> 10205 bytes .../clearinghouse/media/default/img/play.png | Bin 0 -> 299 bytes .../media/default/img/question_mark.png | Bin 0 -> 185486 bytes .../media/default/img/question_mark_15x15.png | Bin 0 -> 1067 bytes .../media/default/img/reload.png | Bin 0 -> 586 bytes .../media/default/img/slice-tiny.png | Bin 0 -> 2477 bytes .../clearinghouse/media/default/img/slice.png | Bin 0 -> 3425 bytes .../default/img/status-question-small.jpg | Bin 0 -> 1220 bytes .../media/default/img/status-question.jpg | Bin 0 -> 62652 bytes .../clearinghouse/media/default/img/stop.png | Bin 0 -> 161 bytes .../media/default/img/switch-5406zl.png | Bin 0 -> 22661 bytes .../media/default/img/switch-cat6500.png | Bin 0 -> 93452 bytes .../media/default/img/switch-juniper.png | Bin 0 -> 78003 bytes .../media/default/img/switch-nec-ip8800.png | Bin 0 -> 40585 bytes .../media/default/img/switch-netfpga.png | Bin 0 -> 78800 bytes .../media/default/img/switch-nf2.png | Bin 0 -> 49952 bytes .../media/default/img/switch.png | Bin 0 -> 7167 bytes .../media/default/img/tiny_arrow.png | Bin 0 -> 2431 bytes .../media/default/img/users-tiny.png | Bin 0 -> 2518 bytes .../media/default/img/warning.png | Bin 0 -> 1148 bytes .../clearinghouse/media/default/img/white.png | Bin 0 -> 1218 bytes .../media/default/img/white_arrow.png | Bin 0 -> 2085 bytes .../media/default/img/white_arrow_big.png | Bin 0 -> 4494 bytes .../media/default/img/white_big.png | Bin 0 -> 2788 bytes .../clearinghouse/media/default/img/zoom.png | Bin 0 -> 898 bytes .../media/default/img/zoomin.png | Bin 0 -> 1061 bytes .../media/default/img/zoomout.png | Bin 0 -> 982 bytes .../media/default/js/agg_status.js | 11 + .../media/default/js/base.helptext.icons.js | 18 + .../clearinghouse/media/default/js/common.js | 40 + .../media/default/js/d3.v2.min.js | 4 + .../default/js/flowspace.helptext.icons.js | 33 + .../clearinghouse/media/default/js/iframe.js | 46 + .../clearinghouse/media/default/js/index.js | 13 + .../media/default/js/jquery-1.10.2.min.map | 1 + .../media/default/js/jquery-ui.min.js | 12 + .../media/default/js/jquery.blockUI.js | 499 ++ .../media/default/js/jquery.colorbox-min.js | 4 + .../media/default/js/jquery.min.js | 6 + .../media/default/js/jquery.tools.min.js | 122 + .../default/js/jsencrypt/bin/jsencrypt.js | 4319 +++++++++++++++++ .../default/js/jsencrypt/bin/jsencrypt.min.js | 6 + .../js/jsencrypt/lib/asn1js/LICENSE.txt | 16 + .../default/js/jsencrypt/lib/asn1js/asn1.js | 535 ++ .../default/js/jsencrypt/lib/asn1js/base64.js | 86 + .../default/js/jsencrypt/lib/asn1js/hex.js | 65 + .../default/js/jsencrypt/lib/asn1js/oids.js | 1962 ++++++++ .../default/js/jsencrypt/lib/jsbn/LICENSE.txt | 42 + .../default/js/jsencrypt/lib/jsbn/README.md | 6 + .../default/js/jsencrypt/lib/jsbn/base64.js | 71 + .../default/js/jsencrypt/lib/jsbn/jsbn.js | 559 +++ .../default/js/jsencrypt/lib/jsbn/jsbn2.js | 656 +++ .../default/js/jsencrypt/lib/jsbn/prng4.js | 45 + .../default/js/jsencrypt/lib/jsbn/rng.js | 65 + .../js/jsencrypt/lib/jsbn/rsa-async.js | 152 + .../default/js/jsencrypt/lib/jsbn/rsa.js | 112 + .../default/js/jsencrypt/lib/jsbn/rsa2.js | 132 + .../js/jsencrypt/lib/jsrsasign/LICENSE.txt | 25 + .../js/jsencrypt/lib/jsrsasign/asn1-1.0.js | 1346 +++++ .../default/js/jsrsasign-latest-all-min.js | 258 + .../clearinghouse/media/default/js/slice.js | 58 + .../media/default/js/tooltip.funcs.js | 108 + .../media/default/js/tooltip.topology.js | 75 + .../media/default/js/validation.js | 175 + .../FELIX/expedient/clearinghouse/base.html | 163 + .../FIBRE/expedient/clearinghouse/base.html | 160 + .../expedient/clearinghouse/base.html.old | 148 + .../default/expedient/clearinghouse/404.html | 17 + .../default/expedient/clearinghouse/500.html | 19 + .../clearinghouse/administration/index.html | 265 + .../clearinghouse/administration/log.html | 3 + .../clearinghouse/aggregate/delete.html | 17 + .../clearinghouse/aggregate/info.html | 12 + .../clearinghouse/aggregate/list.html | 21 + .../clearinghouse/aggregate/list_actions.html | 2 + .../clearinghouse/aggregate/list_table.html | 93 + .../default/expedient/clearinghouse/base.html | 163 + .../expedient/clearinghouse/div_base.html | 2 + .../expedient/clearinghouse/fixformtable.js | 27 + .../clearinghouse/geni/aggregate_crud.html | 40 + .../expedient/clearinghouse/geni/sshkeys.html | 37 + .../geni/user_cert_generate.html | 15 + .../clearinghouse/geni/user_cert_manage.html | 77 + .../clearinghouse/geni/user_cert_upload.html | 19 + .../clearinghouse/geni/user_key_upload.html | 18 + .../geni/user_new_keys_download.html | 32 + .../geni/user_new_ssh_key_download.html | 32 + .../expedient/clearinghouse/help/index.html | 71 + .../clearinghouse/help/index_original | 173 + .../expedient/clearinghouse/iframebase.html | 23 + .../expedient/clearinghouse/index.html | 75 + .../clearinghouse/messagecenter/index.html | 15 + .../permissionmgmt/confirm_requests.html | 107 + .../permissionmgmt/dashboard.html | 135 + .../permissionmgmt/request_permission.html | 91 + .../clearinghouse/project/add_aggregates.html | 26 + .../clearinghouse/project/add_member.html | 29 + .../project/agg_add_actions.html | 4 + .../project/agg_list_actions.html | 6 + .../clearinghouse/project/confirm_delete.html | 17 + .../clearinghouse/project/create_update.html | 22 + .../clearinghouse/project/detail.html | 267 + .../expedient/clearinghouse/project/list.html | 142 + .../clearinghouse/project/list_details.html | 102 + .../project/project_simple_agg_list.html | 91 + .../clearinghouse/project/remove_member.html | 20 + .../clearinghouse/project/update_member.html | 29 + .../clearinghouse/registration/activate.html | 17 + .../registration/activation_email.txt | 6 + .../registration/activation_email_subject.txt | 1 + .../clearinghouse/registration/home.html | 15 + .../clearinghouse/registration/login.html | 155 + .../clearinghouse/registration/logout.html | 11 + .../registration/password_change_done.html | 11 + .../registration/password_change_form.html | 11 + .../registration/password_reset_complete.html | 11 + .../registration/password_reset_confirm.html | 22 + .../registration/password_reset_done.html | 8 + .../registration/password_reset_email.html | 5 + .../password_reset_email_ofreg.html | 5 + .../registration/password_reset_form.html | 12 + .../registration/registration_complete.html | 9 + .../registration/registration_form.html | 12 + .../registration/registration_incomplete.html | 9 + .../clearinghouse/roles/confirm_request.html | 34 + .../expedient/clearinghouse/roles/create.html | 29 + .../expedient/clearinghouse/roles/delete.html | 34 + .../clearinghouse/roles/make_request.html | 21 + .../clearinghouse/roles/no_permission.html | 15 + .../expedient/clearinghouse/roles/update.html | 31 + .../clearinghouse/slice/add_aggregates.html | 27 + .../clearinghouse/slice/confirm_delete.html | 15 + .../clearinghouse/slice/create_update.html | 26 + .../expedient/clearinghouse/slice/detail.html | 165 + .../clearinghouse/slice/select_ui_plugin.html | 40 + .../clearinghouse/slice/topology.html | 710 +++ .../clearinghouse/under_construction.html | 7 + .../clearinghouse/users/confirm_delete.html | 12 + .../expedient/clearinghouse/users/detail.html | 63 + .../expedient/clearinghouse/users/home.html | 42 + .../expedient/clearinghouse/users/saved.html | 9 + .../expedient/clearinghouse/users/tooltip.js | 4 + .../clearinghouse/users/tooltipdesc.html | 14 + .../clearinghouse/users/tooltiplist.html | 11 + .../common/Default/messaging/create.html | 15 + .../common/Default/messaging/created.html | 22 + .../common/Default/messaging/list.html | 67 + .../common/Default/permissions/empty.html | 0 .../expedient/common/messaging/create.html | 15 + .../expedient/common/messaging/created.html | 22 + .../expedient/common/messaging/list.html | 105 + .../expedient/common/permissions/empty.html | 0 .../wsgi/expedient/clearinghouse/auth.wsgi | 43 + .../wsgi/expedient/clearinghouse/django.wsgi | 16 + .../src/wsgi/expedient/clearinghouse/mon.wsgi | 28 + expedient/version | 1 + ofam/README.md | 117 + ofam/bin/common | 1 + ofam/bin/log/.gitignore | 0 ofam/bin/ofver | 1 + ofam/bin/repo | 1 + ofam/bin/rescue/.gitignore | 0 ofam/bin/settings | 1 + ofam/bin/versions/0.7/upgrade | 1 + ofam/bin/versions/default/install/backup | 13 + .../bin/versions/default/install/dependencies | 9 + ofam/bin/versions/default/install/install | 92 + .../versions/default/install/lib/dependencies | 8 + .../default/install/lib/django-settings | 61 + ofam/bin/versions/default/install/lib/ssl | 89 + .../default/install/post-install-hook | 64 + .../versions/default/install/pre-install-hook | 28 + ofam/bin/versions/default/install/repo | 16 + ofam/bin/versions/default/install/rollback | 13 + .../versions/default/upgrade/default/README | 0 .../versions/default/upgrade/default/backup | 13 + .../default/upgrade/default/dependencies | 9 + ofam/bin/versions/default/upgrade/default/lib | 1 + .../default/upgrade/default/post-upgrade-hook | 19 + .../default/upgrade/default/pre-upgrade-hook | 19 + .../versions/default/upgrade/default/rollback | 13 + .../versions/default/upgrade/default/upgrade | 44 + ofam/bin/versions/version-checks | 1 + ofam/src/.gitignore | 8 + ofam/src/ACKS | 8 + ofam/src/CHANGELOG | 21 + ofam/src/COPYING | 22 + ofam/src/NOTES | 126 + ofam/src/README | 13 + ofam/src/debian/README.Debian | 6 + ofam/src/debian/README.source | 9 + ofam/src/debian/changelog | 1037 ++++ ofam/src/debian/compat | 1 + ofam/src/debian/control | 14 + ofam/src/debian/copyright | 370 ++ ofam/src/debian/dirs | 7 + ofam/src/debian/docs | 1 + ofam/src/debian/emacsen-install.ex | 45 + ofam/src/debian/emacsen-remove.ex | 15 + ofam/src/debian/emacsen-startup.ex | 25 + ofam/src/debian/foam.cron.d | 6 + ofam/src/debian/foam.default.ex | 10 + ofam/src/debian/foam.doc-base.EX | 20 + ofam/src/debian/init.d | 80 + ofam/src/debian/manpage.1.ex | 59 + ofam/src/debian/manpage.sgml.ex | 154 + ofam/src/debian/manpage.xml.ex | 291 ++ ofam/src/debian/menu.ex | 2 + ofam/src/debian/postinst.lucid | 55 + ofam/src/debian/postinst.squeeze | 52 + ofam/src/debian/postrm | 37 + ofam/src/debian/preinst.ex | 35 + ofam/src/debian/prerm | 39 + ofam/src/debian/python-module-stampdir/foam | 0 ofam/src/debian/pyversions | 1 + ofam/src/debian/rules | 20 + ofam/src/debian/source/format | 1 + ofam/src/debian/watch.ex | 23 + ofam/src/docs/INSTALL | 54 + ofam/src/install.py | 181 + ofam/src/package.py | 187 + ofam/src/plugins/rpc-gapi-v1/manifest.json | 5 + ofam/src/plugins/rpc-gapi-v2/manifest.json | 5 + ofam/src/schemas/ad.xsd | 77 + ofam/src/schemas/any-extension-schema.xsd | 38 + ofam/src/schemas/foam-config-1.xsd | 8 + ofam/src/schemas/fv-resv-1.xsd | 143 + ofam/src/schemas/of-resv-3.xsd | 222 + ofam/src/schemas/of-resv-4.xsd | 64 + ofam/src/schemas/request-common.xsd | 222 + ofam/src/schemas/request.xsd | 94 + ofam/src/setup.py | 89 + ofam/src/src/dev-server.py | 6 + ofam/src/src/ext/geni/SecureXMLRPCServer.py | 94 + ofam/src/src/ext/geni/__init__.py | 29 + ofam/src/src/ext/geni/am.py | 634 +++ ofam/src/src/ext/geni/ca.py | 68 + ofam/src/src/ext/geni/ch.py | 381 ++ ofam/src/src/ext/geni/config.py | 54 + ofam/src/src/ext/geni/util/__init__.py | 0 ofam/src/src/ext/geni/util/cert_util.py | 79 + ofam/src/src/ext/geni/util/cred_util.py | 329 ++ .../src/ext/geni/util/secure_xmlrpc_client.py | 54 + ofam/src/src/ext/geni/util/urn_util.py | 177 + ofam/src/src/ext/jsonrpc/__init__.py | 26 + ofam/src/src/ext/jsonrpc/_tests/__init__.py | 20 + .../src/ext/jsonrpc/_tests/test_cgiwrapper.py | 55 + ofam/src/src/ext/jsonrpc/_tests/test_json.py | 184 + .../ext/jsonrpc/_tests/test_modpywrapper.py | 98 + ofam/src/src/ext/jsonrpc/_tests/test_proxy.py | 61 + .../ext/jsonrpc/_tests/test_serviceHandler.py | 153 + ofam/src/src/ext/jsonrpc/cgiwrapper.py | 45 + ofam/src/src/ext/jsonrpc/json.py | 230 + ofam/src/src/ext/jsonrpc/modpywrapper.py | 52 + ofam/src/src/ext/jsonrpc/proxy.py | 49 + ofam/src/src/ext/jsonrpc/serviceHandler.py | 113 + ofam/src/src/ext/sfa/README.md | 67 + ofam/src/src/ext/sfa/__init__.py | 0 ofam/src/src/ext/sfa/trust/__init__.py | 0 ofam/src/src/ext/sfa/trust/certificate.py | 784 +++ ofam/src/src/ext/sfa/trust/credential.py | 1055 ++++ .../src/ext/sfa/trust/credential_legacy.py | 273 ++ ofam/src/src/ext/sfa/trust/gid.py | 240 + ofam/src/src/ext/sfa/trust/rights.py | 271 ++ ofam/src/src/ext/sfa/util/__init__.py | 0 ofam/src/src/ext/sfa/util/faults.py | 319 ++ ofam/src/src/ext/sfa/util/sfalogging.py | 186 + ofam/src/src/ext/sfa/util/sfatime.py | 47 + ofam/src/src/ext/sfa/util/xrn.py | 222 + ofam/src/src/foam.conf | 79 + ofam/src/src/foam/__init__.py | 0 ofam/src/src/foam/api/__init__.py | 2 + ofam/src/src/foam/api/admin.py | 771 +++ ofam/src/src/foam/api/auth.py | 54 + ofam/src/src/foam/api/auto.py | 107 + ofam/src/src/foam/api/debug.py | 64 + ofam/src/src/foam/api/gapi1.py | 264 + ofam/src/src/foam/api/gapi2.py | 360 ++ ofam/src/src/foam/api/geni.py | 260 + ofam/src/src/foam/api/jsonrpc.py | 30 + ofam/src/src/foam/api/legacyexpedientapi.py | 1012 ++++ ofam/src/src/foam/api/sfaapi.py | 348 ++ ofam/src/src/foam/api/xmlrpc.py | 27 + ofam/src/src/foam/app.py | 85 + ofam/src/src/foam/config.py | 46 + ofam/src/src/foam/core/__init__.py | 0 ofam/src/src/foam/core/allocation.py | 49 + ofam/src/src/foam/core/auth.py | 79 + ofam/src/src/foam/core/configdb.py | 595 +++ ofam/src/src/foam/core/exception.py | 9 + ofam/src/src/foam/core/htpasswd.py | 70 + ofam/src/src/foam/core/json.py | 69 + ofam/src/src/foam/core/log.py | 9 + ofam/src/src/foam/core/tracer.py | 63 + ofam/src/src/foam/creds.py | 84 + .../src/foam/ethzlegacyoptinstuff/__init__.py | 0 .../api_exp_to_rspecv3/__init__.py | 0 .../expdatatogeniv3rspec.py | 257 + .../api_exp_to_rspecv3/expedientapi.py | 642 +++ .../api_exp_to_rspecv3/testexpedientapi.py | 642 +++ .../legacyoptin/__init__.py | 0 .../legacyoptin/expedienturls.py | 5 + .../legacyoptin/flowspacemodels.py | 87 + .../legacyoptin/flowspaceutils.py | 56 + .../legacyoptin/optsmodels.py | 126 + .../legacyoptin/xmlrpcmodels.py | 74 + .../xmlrpc_server_ch_api_ethmerged | 539 ++ .../xmlrpc_server_models_ethmerged | 108 + ofam/src/src/foam/eventmanager.py | 156 + ofam/src/src/foam/events.py | 23 + .../src/foam/flowclashdetection/__init__.py | 0 .../foam/flowclashdetection/flowfieldtrees.py | 32 + .../flowclashdetection/interval_structure.py | 222 + .../test_interval_structure.py | 30 + .../utils/flowspaceutils.py | 46 + ofam/src/src/foam/flowvisor.py | 313 ++ ofam/src/src/foam/fsdb.py | 46 + ofam/src/src/foam/geni/__init__.py | 0 ofam/src/src/foam/geni/approval.py | 454 ++ ofam/src/src/foam/geni/codes.py | 36 + ofam/src/src/foam/geni/db.py | 471 ++ ofam/src/src/foam/geni/lib.py | 556 +++ ofam/src/src/foam/geni/ofeliaapproval.py | 507 ++ ofam/src/src/foam/geni/topology.py | 64 + ofam/src/src/foam/lib.py | 328 ++ ofam/src/src/foam/ofeliasettings/__init__.py | 0 .../openflow/foam/apache/vhost-foam.conf | 7 + .../foam/common/apache/vhost-macros.conf | 286 ++ .../foam/ofeliasettings/localsettings-example | 17 + .../ofeliasettings/openflow/foam/__init__.py | 0 .../foam/monitoring/BackgroundMonitor.py | 35 + .../monitoring/SessionMonitoringThread.py | 36 + .../openflow/foam/monitoring/__init__.py | 0 .../ofeliasettings/openflow/foam/settings.py | 83 + .../wsgi/openflow/foam/auth.wsgi | 33 + .../wsgi/openflow/foam/django.wsgi | 14 + .../wsgi/openflow/foam/mon.wsgi | 16 + ofam/src/src/foam/openflow/__init__.py | 0 ofam/src/src/foam/openflow/types.py | 92 + ofam/src/src/foam/plugin_manager.py | 16 + ofam/src/src/foam/sfa/__init__.py | 0 ofam/src/src/foam/sfa/drivers/OFAggregate.py | 32 + ofam/src/src/foam/sfa/drivers/OFSfaDriver.py | 24 + ofam/src/src/foam/sfa/drivers/__init__.py | 0 ofam/src/src/foam/sfa/lib.py | 132 + .../foam/sfa/methods/.ListResources.py.swo | Bin 0 -> 12288 bytes ofam/src/src/foam/sfa/methods/CreateGid.py | 47 + ofam/src/src/foam/sfa/methods/CreateSliver.py | 21 + ofam/src/src/foam/sfa/methods/DeleteSliver.py | 16 + .../src/src/foam/sfa/methods/GetCredential.py | 48 + ofam/src/src/foam/sfa/methods/GetGids.py | 45 + .../src/foam/sfa/methods/GetSelfCredential.py | 87 + ofam/src/src/foam/sfa/methods/GetTicket.py | 57 + ofam/src/src/foam/sfa/methods/GetVersion.py | 20 + ofam/src/src/foam/sfa/methods/List.py | 36 + .../src/src/foam/sfa/methods/ListResources.py | 42 + .../src/foam/sfa/methods/ListResources.py.bak | 58 + ofam/src/src/foam/sfa/methods/ListSlices.py | 33 + ofam/src/src/foam/sfa/methods/RedeemTicket.py | 29 + ofam/src/src/foam/sfa/methods/Register.py | 41 + ofam/src/src/foam/sfa/methods/Remove.py | 44 + ofam/src/src/foam/sfa/methods/RenewSliver.py | 46 + ofam/src/src/foam/sfa/methods/Resolve.py | 52 + ofam/src/src/foam/sfa/methods/ResolveGENI.py | 19 + ofam/src/src/foam/sfa/methods/Shutdown.py | 23 + ofam/src/src/foam/sfa/methods/SliverStatus.py | 10 + ofam/src/src/foam/sfa/methods/Start.py | 13 + ofam/src/src/foam/sfa/methods/Stop.py | 11 + ofam/src/src/foam/sfa/methods/Update.py | 41 + ofam/src/src/foam/sfa/methods/UpdateSliver.py | 33 + ofam/src/src/foam/sfa/methods/__init__.py | 29 + .../sfa/methods/get_key_from_incoming_ip.py | 24 + .../src/foam/sfa/methods/get_trusted_certs.py | 40 + .../foam/sfa/methods/permission_manager.py | 13 + ofam/src/src/foam/sfa/methods/reset_slice.py | 30 + .../foam/sfa/rspecs/.oldversions/__init__.py | 0 .../foam/sfa/rspecs/.oldversions/federica.py | 17 + .../foam/sfa/rspecs/.oldversions/nitosv1.py | 244 + .../foam/sfa/rspecs/.oldversions/ocfvtv1.py | 228 + .../src/foam/sfa/rspecs/.oldversions/pgv2.py | 244 + .../src/foam/sfa/rspecs/.oldversions/pgv3.py | 35 + .../src/foam/sfa/rspecs/.oldversions/sfav1.py | 233 + ofam/src/src/foam/sfa/rspecs/__init__.py | 0 .../src/foam/sfa/rspecs/elements/__init__.py | 0 .../src/foam/sfa/rspecs/elements/__init__.pyo | Bin 0 -> 151 bytes .../src/foam/sfa/rspecs/elements/bwlimit.py | 8 + .../src/foam/sfa/rspecs/elements/bwlimit.pyo | Bin 0 -> 478 bytes .../src/foam/sfa/rspecs/elements/channel.py | 13 + .../src/foam/sfa/rspecs/elements/channel.pyo | Bin 0 -> 586 bytes .../foam/sfa/rspecs/elements/disk_image.py | 9 + .../foam/sfa/rspecs/elements/disk_image.pyo | Bin 0 -> 520 bytes .../src/foam/sfa/rspecs/elements/element.py | 21 + .../src/foam/sfa/rspecs/elements/element.pyo | Bin 0 -> 1123 bytes .../src/foam/sfa/rspecs/elements/execute.py | 7 + .../src/foam/sfa/rspecs/elements/execute.pyo | Bin 0 -> 480 bytes .../src/foam/sfa/rspecs/elements/fw_rule.py | 10 + .../src/foam/sfa/rspecs/elements/fw_rule.pyo | Bin 0 -> 526 bytes .../foam/sfa/rspecs/elements/granularity.py | 7 + .../foam/sfa/rspecs/elements/granularity.pyo | Bin 0 -> 475 bytes .../foam/sfa/rspecs/elements/hardware_type.py | 7 + .../sfa/rspecs/elements/hardware_type.pyo | Bin 0 -> 479 bytes .../src/foam/sfa/rspecs/elements/install.py | 8 + .../src/foam/sfa/rspecs/elements/install.pyo | Bin 0 -> 502 bytes .../src/foam/sfa/rspecs/elements/interface.py | 12 + .../foam/sfa/rspecs/elements/interface.pyo | Bin 0 -> 600 bytes .../src/src/foam/sfa/rspecs/elements/lease.py | 11 + .../src/foam/sfa/rspecs/elements/lease.pyo | Bin 0 -> 538 bytes ofam/src/src/foam/sfa/rspecs/elements/link.py | 16 + .../src/src/foam/sfa/rspecs/elements/link.pyo | Bin 0 -> 662 bytes .../src/foam/sfa/rspecs/elements/location.py | 9 + .../src/foam/sfa/rspecs/elements/location.pyo | Bin 0 -> 505 bytes .../src/src/foam/sfa/rspecs/elements/login.py | 9 + .../src/foam/sfa/rspecs/elements/login.pyo | Bin 0 -> 516 bytes .../sfa/rspecs/elements/network_interface.py | 17 + ofam/src/src/foam/sfa/rspecs/elements/node.py | 27 + .../src/src/foam/sfa/rspecs/elements/node.pyo | Bin 0 -> 817 bytes .../foam/sfa/rspecs/elements/ocf_vt_server.py | 17 + .../sfa/rspecs/elements/openflow_switch.py | 11 + .../src/src/foam/sfa/rspecs/elements/pltag.py | 9 + .../src/foam/sfa/rspecs/elements/pltag.pyo | Bin 0 -> 474 bytes .../foam/sfa/rspecs/elements/position_3d.py | 9 + .../foam/sfa/rspecs/elements/position_3d.pyo | Bin 0 -> 492 bytes .../src/foam/sfa/rspecs/elements/property.py | 12 + .../src/foam/sfa/rspecs/elements/property.pyo | Bin 0 -> 543 bytes .../src/src/foam/sfa/rspecs/elements/range.py | 11 + .../src/foam/sfa/rspecs/elements/services.py | 10 + .../src/foam/sfa/rspecs/elements/services.pyo | Bin 0 -> 500 bytes .../src/foam/sfa/rspecs/elements/sliver.py | 13 + .../src/foam/sfa/rspecs/elements/sliver.pyo | Bin 0 -> 585 bytes .../src/foam/sfa/rspecs/elements/spectrum.py | 5 + .../src/foam/sfa/rspecs/elements/spectrum.pyo | Bin 0 -> 453 bytes .../sfa/rspecs/elements/versions/__init__.py | 0 .../elements/versions/nitosv1Channel.py | 73 + .../rspecs/elements/versions/nitosv1Lease.py | 103 + .../rspecs/elements/versions/nitosv1Node.py | 185 + .../rspecs/elements/versions/nitosv1PLTag.py | 19 + .../rspecs/elements/versions/nitosv1Sliver.py | 57 + .../sfa/rspecs/elements/versions/ocfofNode.py | 213 + .../rspecs/elements/versions/ocfofSlivers.py | 44 + .../sfa/rspecs/elements/versions/ocfvtNode.py | 202 + .../rspecs/elements/versions/ocfvtSlivers.py | 83 + .../elements/versions/ocfvtSlivers.py.old | 83 + .../rspecs/elements/versions/pgv2DiskImage.py | 24 + .../rspecs/elements/versions/pgv2Interface.py | 20 + .../sfa/rspecs/elements/versions/pgv2Link.py | 104 + .../sfa/rspecs/elements/versions/pgv2Node.py | 147 + .../rspecs/elements/versions/pgv2Services.py | 43 + .../elements/versions/pgv2SliverType.py | 60 + .../rspecs/elements/versions/plosv1FWRule.py | 25 + .../rspecs/elements/versions/sfav1Lease.py | 111 + .../sfa/rspecs/elements/versions/sfav1Node.py | 166 + .../rspecs/elements/versions/sfav1PLTag.py | 19 + .../rspecs/elements/versions/sfav1Sliver.py | 54 + ofam/src/src/foam/sfa/rspecs/elements/vm.py | 21 + .../foam/sfa/rspecs/elements/vm_interface.py | 11 + .../src/foam/sfa/rspecs/pg_rspec_converter.py | 94 + ofam/src/src/foam/sfa/rspecs/rspec.py | 123 + .../src/foam/sfa/rspecs/rspec_converter.py | 46 + .../src/src/foam/sfa/rspecs/rspec_elements.py | 35 + .../foam/sfa/rspecs/sfa_rspec_converter.py | 86 + ofam/src/src/foam/sfa/rspecs/version.py | 30 + .../src/foam/sfa/rspecs/version_manager.py | 104 + .../src/foam/sfa/rspecs/versions/__init__.py | 0 .../src/foam/sfa/rspecs/versions/ocfofv1.py | 154 + .../src/foam/sfa/rspecs/versions/ocfvtv1.py | 219 + ofam/src/src/foam/sfa/schemas/credential.xsd | 214 + .../sfa/schemas/protogeni-rspec-common.xsd | 120 + ofam/src/src/foam/sfa/schemas/sig.xsd | 11 + ofam/src/src/foam/sfa/schemas/top.xsd | 312 ++ ofam/src/src/foam/sfa/schemas/xml.xsd | 10 + ofam/src/src/foam/sfa/sfa_config/__init__.py | 0 ofam/src/src/foam/sfa/sfa_config/config.py | 80 + ofam/src/src/foam/sfa/trust/__init__.py | 0 ofam/src/src/foam/sfa/trust/auth.py | 307 ++ ofam/src/src/foam/sfa/trust/certificate.py | 779 +++ ofam/src/src/foam/sfa/trust/credential.py | 1083 +++++ .../src/foam/sfa/trust/credential_legacy.py | 270 ++ ofam/src/src/foam/sfa/trust/gid.py | 259 + ofam/src/src/foam/sfa/trust/hierarchy.py | 376 ++ ofam/src/src/foam/sfa/trust/rights.py | 253 + ofam/src/src/foam/sfa/trust/sfaticket.py | 126 + ofam/src/src/foam/sfa/trust/trustedroots.py | 44 + .../src/foam/sfa/trusted_roots/fed4fire.gid | 14 + .../src/src/foam/sfa/trusted_roots/iminds.gid | 27 + ofam/src/src/foam/sfa/trusted_roots/ocf.gid | 18 + .../src/foam/sfa/trusted_roots/optin_ocf.gid | 14 + ofam/src/src/foam/sfa/trusted_roots/ple.gid | 13 + ofam/src/src/foam/sfa/trusted_roots/sfa.gid | 28 + .../src/foam/sfa/trusted_roots/topdomain.gid | 14 + .../foam/sfa/trusted_roots/vwall-iminds3.gid | 27 + ofam/src/src/foam/sfa/util/__init__.py | 0 ofam/src/src/foam/sfa/util/cache.py | 116 + ofam/src/src/foam/sfa/util/callids.py | 72 + ofam/src/src/foam/sfa/util/config.py | 317 ++ ofam/src/src/foam/sfa/util/defaultdict.py | 38 + ofam/src/src/foam/sfa/util/enumeration.py | 35 + ofam/src/src/foam/sfa/util/faults.py | 344 ++ ofam/src/src/foam/sfa/util/genicode.py | 45 + ofam/src/src/foam/sfa/util/method.py | 290 ++ ofam/src/src/foam/sfa/util/parameter.py | 103 + ofam/src/src/foam/sfa/util/sfalogging.py | 201 + ofam/src/src/foam/sfa/util/sfatime.py | 66 + ofam/src/src/foam/sfa/util/version.py | 12 + ofam/src/src/foam/sfa/util/xml.py | 358 ++ ofam/src/src/foam/sfa/util/xrn.py | 268 + ofam/src/src/foam/task.py | 267 + ofam/src/src/foam/types/DateTime.py | 36 + ofam/src/src/foam/types/URN.py | 12 + ofam/src/src/foam/types/__init__.py | 4 + ofam/src/src/foam/types/event_type.py | 27 + ofam/src/src/foam/types/trigger_type.py | 27 + ofam/src/src/foam/version.py | 1 + ofam/src/src/foam/webgui/set/settings.py | 1 + .../foam/media/default/add_rule_dark.png | Bin 0 -> 3352 bytes .../openflow/foam/media/default/back_dark.png | Bin 0 -> 2765 bytes .../openflow/foam/media/default/dashboard.png | Bin 0 -> 3833 bytes .../foam/media/default/egeni-iframe.css | 979 ++++ .../openflow/foam/media/default/egeni.css | 1182 +++++ .../foam/media/default/experiments_dark.png | Bin 0 -> 4102 bytes .../foam/media/default/fs_req_dark.png | Bin 0 -> 5585 bytes .../openflow/foam/media/default/help.png | Bin 0 -> 3091 bytes .../media/default/js/formtable.tooltip.js | 140 + .../foam/media/default/js/jquery.min.js | 167 + .../foam/media/default/js/jquery.tools.min.js | 192 + .../foam/media/default/js/tooltip.funcs.js | 108 + .../openflow/foam/media/default/logout.png | Bin 0 -> 3319 bytes .../foam/media/default/ofelialogo.png | Bin 0 -> 10205 bytes .../foam/media/default/remove_rule_dark.png | Bin 0 -> 3824 bytes .../openflow/foam/media/default/slice.png | Bin 0 -> 3425 bytes .../openflow/foam/media/default/tooltip.css | 31 + .../foam/media/default/view_exp_dark.png | Bin 0 -> 2854 bytes .../templates/default/openflow/foam/base.html | 53 + .../default/openflow/foam/tooltip.funcs.js | 100 + ofam/src/src/foamext/IPy.py | 1385 ++++++ ofam/src/src/foamext/__init__.py | 0 ofam/src/src/foamext/importlib.py | 38 + ofam/src/src/foamext/triggers/__init__.py | 2 + ofam/src/src/scripts/daily-queue | 12 + ofam/src/src/scripts/expire | 11 + ofam/src/src/scripts/expire-emails | 12 + ofam/src/src/scripts/foam-db-convert.py | 202 + ofam/src/src/scripts/foam.fcgi | 42 + ofam/src/src/scripts/foamctl | 833 ++++ ofam/src/src/trusted | 0 .../email.event.approvesliver.admin.txt | 13 + .../email.event.approvesliver.exp.txt | 13 + .../email.event.createsliver.admin.txt | 13 + .../email.event.createsliver.exp.txt | 17 + .../email.event.disablesliver.admin.txt | 12 + .../email.event.disablesliver.exp.txt | 16 + .../email.event.expiresliver.admin.txt | 13 + .../email.event.expiresliver.exp.txt | 14 + .../email.event.expiresliverday.admin.txt | 13 + .../email.event.expiresliverday.exp.txt | 17 + .../email.event.expiresliverweek.admin.txt | 13 + .../email.event.expiresliverweek.exp.txt | 17 + .../email.event.gapi-deletesliver.admin.txt | 12 + .../email.event.gapi-deletesliver.exp.txt | 13 + .../email.event.json-deletesliver.admin.txt | 12 + .../email.event.json-deletesliver.exp.txt | 13 + .../email.event.pendingqueue.admin.txt | 7 + .../email.event.rejectsliver.admin.txt | 13 + .../email.event.rejectsliver.exp.txt | 18 + .../email.event.renewsliver.admin.txt | 13 + .../templates/email.event.renewsliver.exp.txt | 14 + .../email.event.shutdownsliver.admin.txt | 12 + .../email.event.shutdownsliver.exp.txt | 13 + ofam/version | 1 + ofreg/.gitignore | 5 + ofreg/README.txt | 52 + ofreg/__init__.py | 0 ofreg/db/.gitignore | 1 + ofreg/deploy/apache-ofreg.conf | 15 + ofreg/deploy/ofreg.wsgi | 9 + ofreg/deploy/ssl/make_key.sh | 5 + ofreg/localsettings.py-example | 51 + ofreg/manage.py | 12 + ofreg/registration/__init__.py | 0 ofreg/registration/models/__init__.py | 1 + ofreg/registration/models/login.py | 31 + ofreg/registration/models/password_reset.py | 37 + ofreg/registration/models/registration.py | 173 + ofreg/registration/static/css/ofreg.css | 77 + ofreg/registration/static/img/ofelia.png | Bin 0 -> 24885 bytes ofreg/registration/static/img/warning.png | Bin 0 -> 1148 bytes ofreg/registration/static/openvpn.tar.gz | Bin 0 -> 1064 bytes ofreg/registration/templates/base.html | 31 + ofreg/registration/templates/login/login.html | 18 + .../registration/templates/login/success.html | 19 + .../templates/mailer/password_reset_reset.txt | 15 + .../mailer/registration_complete.txt | 10 + .../mailer/registration_validation.txt | 5 + .../templates/password_reset/forgotten.html | 20 + .../templates/password_reset/reset.html | 8 + .../templates/registration/register.html | 35 + .../registration/register_success.html | 8 + .../registration/validate_error.html | 12 + .../registration/validate_success.html | 8 + .../registration/templates/welcome/index.html | 7 + ofreg/registration/templatetags/__init__.py | 0 .../registration/templatetags/form_helper.py | 21 + ofreg/registration/tests.py | 23 + ofreg/registration/urls.py | 24 + ofreg/registration/views/__init__.py | 0 ofreg/registration/views/login.py | 19 + ofreg/registration/views/password_reset.py | 32 + ofreg/registration/views/registration.py | 48 + ofreg/registration/views/welcome.py | 7 + ofreg/settings.py | 79 + ofreg/urls.py | 10 + ofreg/util.py | 38 + optin_manager/bin/common | 1 + optin_manager/bin/log/.gitignore | 0 optin_manager/bin/ofver | 1 + optin_manager/bin/repo | 1 + optin_manager/bin/rescue/.gitignore | 0 optin_manager/bin/settings | 1 + .../bin/versions/0.13/upgrade/0.12/backup | 32 + .../0.13/upgrade/0.12/pre-backup-upgrade-hook | 38 + .../0.3/upgrade/default/post-upgrade-hook | 38 + .../0.3/upgrade/default/pre-upgrade-hook | 1 + optin_manager/bin/versions/0.3RC1 | 1 + optin_manager/bin/versions/0.4.1 | 1 + optin_manager/bin/versions/0.4.2 | 1 + optin_manager/bin/versions/0.4.3 | 1 + .../0.4/upgrade/default/post-upgrade-hook | 24 + optin_manager/bin/versions/0.5 | 1 + optin_manager/bin/versions/0.6 | 1 + optin_manager/bin/versions/0.6.1 | 1 + .../0.7/upgrade/default/pre-upgrade-hook | 36 + optin_manager/bin/versions/0.8 | 1 + optin_manager/bin/versions/0.8.1 | 1 + optin_manager/bin/versions/0.8.2 | 1 + .../bin/versions/default/install/backup | 13 + .../bin/versions/default/install/dependencies | 9 + .../bin/versions/default/install/install | 77 + .../versions/default/install/lib/dependencies | 19 + .../versions/default/install/lib/django-db | 12 + .../default/install/lib/django-settings | 57 + .../install/lib/set_environment_variables | 1 + .../bin/versions/default/install/lib/ssl | 90 + .../default/install/post-install-hook | 20 + .../versions/default/install/pre-install-hook | 51 + .../bin/versions/default/install/repo | 16 + .../bin/versions/default/install/rollback | 13 + .../versions/default/upgrade/default/README | 0 .../versions/default/upgrade/default/backup | 28 + .../default/upgrade/default/dependencies | 9 + .../default/lib/set_environment_variables | 1 + .../default/upgrade/default/post-upgrade-hook | 23 + .../default/upgrade/default/pre-upgrade-hook | 42 + .../versions/default/upgrade/default/rollback | 36 + .../versions/default/upgrade/default/upgrade | 40 + .../bin/versions/default/upgrade/tools/prova | 1782 +++++++ .../versions/default/upgrade/tools/prova.cfg | 6 + .../versions/default/upgrade/tools/sqlDump.py | 1 + .../default/upgrade/tools/sqlRestore.py | 1 + optin_manager/bin/versions/version-checks | 1 + .../optin_manager/apache/vhost-optinmgr.conf | 7 + .../common/apache/vhost-macros.conf | 286 ++ optin_manager/src/python/openflow/__init__.py | 0 .../src/python/openflow/common/__init__.py | 0 .../openflow/common/backends/__init__.py | 0 .../openflow/common/backends/remoteuser.py | 13 + .../openflow/common/breadcrumbs/__init__.py | 0 .../breadcrumbs/templatetags/__init__.py | 0 .../breadcrumbs/templatetags/breadcrumbs.py | 39 + .../openflow/common/defaultsite/__init__.py | 0 .../openflow/common/defaultsite/management.py | 30 + .../openflow/common/defaultsite/settings.py | 19 + .../openflow/common/extendable/__init__.py | 0 .../openflow/common/extendable/inheritance.py | 55 + .../openflow/common/extendable/models.py | 232 + .../common/extendable/tests/__init__.py | 1 + .../common/extendable/tests/models.py | 48 + .../openflow/common/extendable/tests/tests.py | 53 + .../openflow/common/extendable/utils.py | 18 + .../openflow/common/extendable/views.py | 1 + .../src/python/openflow/common/loggingconf.py | 15 + .../openflow/common/messaging/__init__.py | 0 .../python/openflow/common/messaging/admin.py | 9 + .../common/messaging/context_processors.py | 15 + .../python/openflow/common/messaging/forms.py | 27 + .../openflow/common/messaging/models.py | 123 + .../python/openflow/common/messaging/tests.py | 23 + .../python/openflow/common/messaging/urls.py | 22 + .../python/openflow/common/messaging/views.py | 54 + .../openflow/common/middleware/__init__.py | 0 .../openflow/common/middleware/basicauth.py | 65 + .../common/middleware/sitelockdown.py | 43 + .../common/middleware/threadlocals.py | 45 + .../openflow/common/middleware/utils.py | 25 + .../openflow/common/permissions/__init__.py | 0 .../openflow/common/permissions/admin.py | 12 + .../openflow/common/permissions/backend.py | 33 + .../openflow/common/permissions/decorators.py | 140 + .../openflow/common/permissions/exceptions.py | 69 + .../openflow/common/permissions/forms.py | 24 + .../openflow/common/permissions/management.py | 42 + .../openflow/common/permissions/middleware.py | 157 + .../openflow/common/permissions/models.py | 280 ++ .../common/permissions/permissions.py | 5 + .../common/permissions/tests/__init__.py | 1 + .../common/permissions/tests/models.py | 30 + .../common/permissions/tests/test_urls.py | 33 + .../common/permissions/tests/tests.py | 417 ++ .../common/permissions/tests/views.py | 96 + .../openflow/common/permissions/urls.py | 11 + .../openflow/common/permissions/utils.py | 260 + .../openflow/common/permissions/views.py | 117 + .../openflow/common/rpc4django/__init__.py | 61 + .../common/rpc4django/jsonrpcdispatcher.py | 154 + .../openflow/common/rpc4django/models.py | 11 + .../common/rpc4django/rpcdispatcher.py | 268 + .../rpc4django/rpcmethod_summary.html | 137 + .../rpc4django/templatetags/__init__.py | 0 .../common/rpc4django/templatetags/rpctags.py | 48 + .../common/rpc4django/tests/__init__.py | 11 + .../tests/test_jsonrpcdispatcher.py | 145 + .../rpc4django/tests/test_rpcdispatcher.py | 173 + .../common/rpc4django/tests/test_rpcviews.py | 164 + .../common/rpc4django/tests/test_urls.py | 12 + .../rpc4django/tests/test_xmlrpcdispatcher.py | 33 + .../rpc4django/tests/testmod/__init__.py | 10 + .../common/rpc4django/tests/testmod/models.py | 5 + .../tests/testmod/testsubmod/__init__.py | 9 + .../openflow/common/rpc4django/utils.py | 20 + .../openflow/common/rpc4django/views.py | 274 ++ .../common/rpc4django/xmlrpcdispatcher.py | 80 + .../python/openflow/common/tests/__init__.py | 5 + .../python/openflow/common/tests/client.py | 183 + .../python/openflow/common/tests/commands.py | 45 + .../python/openflow/common/tests/manager.py | 75 + .../src/python/openflow/common/tests/utils.py | 93 + .../common/utils/OptinThemeManager.py | 74 + .../python/openflow/common/utils/__init__.py | 35 + .../openflow/common/utils/certtransport.py | 16 + .../common/utils/context_processors.py | 12 + .../openflow/common/utils/formfields.py | 17 + .../python/openflow/common/utils/managers.py | 99 + .../openflow/common/utils/modelfields.py | 42 + .../common/utils/templatetags/__init__.py | 0 .../common/utils/templatetags/ch_extras.py | 54 + .../openflow/common/utils/templatetags/url.py | 83 + .../python/openflow/common/utils/transport.py | 42 + .../openflow/common/utils/validators.py | 10 + .../src/python/openflow/common/utils/views.py | 79 + .../common/xmlrpc_serverproxy/__init__.py | 0 .../common/xmlrpc_serverproxy/admin.py | 9 + .../common/xmlrpc_serverproxy/forms.py | 67 + .../common/xmlrpc_serverproxy/models.py | 225 + .../src/python/openflow/dummyom/__init__.py | 6 + .../src/python/openflow/dummyom/ch_api.py | 134 + .../src/python/openflow/dummyom/models.py | 150 + .../src/python/openflow/dummyom/urls.py | 11 + .../python/openflow/optin_manager/__init__.py | 0 .../optin_manager/admin_manager/__init__.py | 0 .../optin_manager/admin_manager/admin.py | 8 + .../optin_manager/admin_manager/forms.py | 75 + .../optin_manager/admin_manager/helper.py | 286 ++ .../optin_manager/admin_manager/models.py | 59 + .../optin_manager/admin_manager/tests.py | 395 ++ .../optin_manager/admin_manager/urls.py | 19 + .../optin_manager/admin_manager/views.py | 1390 ++++++ .../auto_approval_scripts/__init__.py | 0 .../auto_approval_scripts/approve_all.py | 50 + .../approve_sender_ip.py | 69 + .../auto_approval_scripts/postpone_all.py | 32 + .../auto_approval_scripts/reject_all.py | 32 + .../optin_manager/commands/__init__.py | 0 .../commands/management/__init__.py | 0 .../commands/management/commands/__init__.py | 0 .../commands/bootstrap_local_settings.py | 30 + .../commands/clean_inconsistent_db_entries.py | 37 + .../commands/create_default_root.py | 39 + .../management/commands/create_secret_key.py | 23 + .../commands/install_cert_makefile.py | 80 + .../management/commands/setup_media.py | 30 + .../commands/setup_optin_manager.py | 21 + .../commands/standardize_flowvisor_slices.py | 123 + .../commands/management/commands/test_om.py | 22 + .../openflow/optin_manager/commands/models.py | 0 .../openflow/optin_manager/commands/utils.py | 99 + .../optin_manager/controls/__init__.py | 0 .../openflow/optin_manager/controls/forms.py | 64 + .../openflow/optin_manager/controls/models.py | 3 + .../openflow/optin_manager/controls/tests.py | 23 + .../openflow/optin_manager/controls/urls.py | 6 + .../openflow/optin_manager/controls/views.py | 89 + .../optin_manager/defaultsettings/__init__.py | 0 .../defaultsettings/admin_manager.py | 21 + .../optin_manager/defaultsettings/admins.py | 16 + .../optin_manager/defaultsettings/database.py | 28 + .../optin_manager/defaultsettings/django.py | 178 + .../optin_manager/defaultsettings/email.py | 14 + .../defaultsettings/openflowtests.py | 99 + .../defaultsettings/optin_manager.py | 27 + .../optin_manager/defaultsettings/required.py | 17 + .../optin_manager/defaultsettings/site.py | 16 + .../optin_manager/defaultsettings/tests.py | 13 + .../optin_manager/dummyfv/__init__.py | 2 + .../openflow/optin_manager/dummyfv/admin.py | 14 + .../openflow/optin_manager/dummyfv/models.py | 68 + .../openflow/optin_manager/dummyfv/rpc.py | 164 + .../openflow/optin_manager/dummyfv/urls.py | 11 + .../ethz_code/xmlrpc_server_ch_api_ethmerged | 539 ++ .../ethz_code/xmlrpc_server_models_ethmerged | 108 + .../optin_manager/flowspace/__init__.py | 0 .../optin_manager/flowspace/helper.py | 402 ++ .../optin_manager/flowspace/models.py | 90 + .../openflow/optin_manager/flowspace/tests.py | 133 + .../openflow/optin_manager/flowspace/utils.py | 56 + .../openflow/optin_manager/flowspace/views.py | 0 .../openflow/optin_manager/geni/__init__.py | 0 .../optin_manager/geni/v3/__init__.py | 0 .../geni/v3/configurators/__init__.py | 0 .../geni/v3/configurators/optin.py | 66 + .../optin_manager/geni/v3/drivers/__init__.py | 0 .../optin_manager/geni/v3/drivers/optin.py | 540 +++ .../geni/v3/managers/__init__.py | 0 .../optin_manager/geni/v3/managers/optin.py | 83 + .../geni/v3/settings/__init__.py | 0 .../optin_manager/geni/v3/settings/optin.py | 28 + .../optin_manager/geni/v3/tests/__init__.py | 0 .../geni/v3/tests/drivers/__init__.py | 0 .../geni/v3/tests/drivers/optin/devicetest.py | 45 + .../geni/v3/tests/handler/__init__.py | 0 .../geni/v3/tests/handler/listresources.py | 32 + .../geni/v3/trusted_roots/fed4fire.gid | 14 + .../geni/v3/trusted_roots/fuseco.gid | 56 + .../geni/v3/trusted_roots/geni-carolina.gid | 14 + .../geni/v3/trusted_roots/netmode.gid | 14 + .../geni/v3/trusted_roots/ocf.gid | 18 + .../geni/v3/trusted_roots/ofam.gid | 36 + .../geni/v3/trusted_roots/omf.gid | 13 + .../geni/v3/trusted_roots/ple.gid | 13 + .../geni/v3/trusted_roots/smartsantander.gid | 14 + .../geni/v3/trusted_roots/topdomain.gid | 14 + .../geni/v3/trusted_roots/wall2.gid | 27 + .../optin_manager/geni/v3/utils/__init__.py | 0 .../optin_manager/geni/v3/utils/flowvisor.py | 46 + .../optin_manager/geni/v3/utils/optin.py | 263 + .../optin_manager/geni/v3/utils/sliver.py | 272 ++ .../optin_manager/localsettings-example | 85 + .../python/openflow/optin_manager/manage.py | 16 + .../monitoring/BackgroundMonitor.py | 35 + .../monitoring/SessionMonitoringThread.py | 48 + .../optin_manager/monitoring/__init__.py | 0 .../background_expiration_monitoring.py | 18 + .../optin_manager/monitoring/reservation.py | 13 + .../optin_manager/monitoring/util/__init__.py | 0 .../monitoring/util/expiration_manager.py | 98 + .../optin_manager/monitoring/util/queue.py | 45 + .../openflow/optin_manager/opts/__init__.py | 0 .../openflow/optin_manager/opts/admin.py | 13 + .../optin_manager/opts/autofsgranter.py | 97 + .../openflow/optin_manager/opts/forms.py | 115 + .../openflow/optin_manager/opts/helper.py | 358 ++ .../openflow/optin_manager/opts/models.py | 148 + .../openflow/optin_manager/opts/tests.py | 291 ++ .../openflow/optin_manager/opts/urls.py | 14 + .../openflow/optin_manager/opts/views.py | 718 +++ .../optin_manager/opts/vlans/__init__.py | 0 .../opts/vlans/vlanController.py | 61 + .../python/openflow/optin_manager/settings.py | 103 + .../openflow/optin_manager/sfa/.gitignore | 6 + .../openflow/optin_manager/sfa/__init__.py | 0 .../openflow/optin_manager/sfa/add_gid.sh | 28 + .../sfa/credentials/topdomain.cred | 81 + .../optin_manager/sfa/drivers/OFAggregate.py | 65 + .../optin_manager/sfa/drivers/OFSfaDriver.py | 76 + .../optin_manager/sfa/drivers/OFShell.py | 182 + .../optin_manager/sfa/drivers/__init__.py | 0 .../optin_manager/sfa/jfed_roots/jfed.gid | 17 + .../optin_manager/sfa/jfed_roots/jfed2.gid | 23 + .../optin_manager/sfa/jfed_roots/jfed3.gid | 23 + .../optin_manager/sfa/jfed_roots/jfed4.gid | 24 + .../optin_manager/sfa/jfed_roots/jfed5.gid | 23 + .../optin_manager/sfa/jfed_roots/jfed6.gid | 22 + .../optin_manager/sfa/jfed_roots/jfed8.gid | 24 + .../optin_manager/sfa/jfed_roots/ocf_of.gid | 14 + .../optin_manager/sfa/jfed_roots/wall.gid | 24 + .../optin_manager/sfa/jfed_roots/wall2.gid | 27 + .../sfa/managers/AggregateManager.py | 94 + .../sfa/managers/MetaSfaRegistry.py | 26 + .../optin_manager/sfa/managers/__init__.py | 0 .../sfa/methods/.ListResources.py.swo | Bin 0 -> 12288 bytes .../optin_manager/sfa/methods/CreateGid.py | 47 + .../optin_manager/sfa/methods/CreateSliver.py | 21 + .../optin_manager/sfa/methods/DeleteSliver.py | 16 + .../sfa/methods/GetCredential.py | 48 + .../optin_manager/sfa/methods/GetGids.py | 45 + .../sfa/methods/GetSelfCredential.py | 87 + .../optin_manager/sfa/methods/GetTicket.py | 57 + .../optin_manager/sfa/methods/GetVersion.py | 20 + .../optin_manager/sfa/methods/List.py | 36 + .../sfa/methods/ListResources.py | 42 + .../sfa/methods/ListResources.py.bak | 58 + .../optin_manager/sfa/methods/ListSlices.py | 33 + .../optin_manager/sfa/methods/RedeemTicket.py | 29 + .../optin_manager/sfa/methods/Register.py | 41 + .../optin_manager/sfa/methods/Remove.py | 44 + .../optin_manager/sfa/methods/RenewSliver.py | 46 + .../optin_manager/sfa/methods/Resolve.py | 52 + .../optin_manager/sfa/methods/ResolveGENI.py | 19 + .../optin_manager/sfa/methods/Shutdown.py | 23 + .../optin_manager/sfa/methods/SliverStatus.py | 10 + .../optin_manager/sfa/methods/Start.py | 13 + .../optin_manager/sfa/methods/Stop.py | 11 + .../optin_manager/sfa/methods/Update.py | 41 + .../optin_manager/sfa/methods/UpdateSliver.py | 33 + .../optin_manager/sfa/methods/__init__.py | 29 + .../sfa/methods/get_key_from_incoming_ip.py | 24 + .../sfa/methods/get_trusted_certs.py | 40 + .../sfa/methods/permission_manager.py | 12 + .../optin_manager/sfa/methods/reset_slice.py | 30 + .../openflow/optin_manager/sfa/models.py | 14 + .../authorities/topdomain/topdomain.gid | 14 + .../authorities/topdomain/topdomain.pkey | 16 + .../sfa/openflow_utils/CreateOFSliver.py | 179 + .../sfa/openflow_utils/ServiceThread.py | 23 + .../sfa/openflow_utils/SliverRSpecParser.py | 199 + .../sfa/openflow_utils/__init__.py | 0 .../sfa/openflow_utils/delete_slice.py | 38 + .../sfa/openflow_utils/expiration_manager.py | 33 + .../openflow_utils/federationlinkmanager.py | 6 + .../sfa/openflow_utils/foam_rspec_lib.py | 159 + .../sfa/openflow_utils/rspec3_to_expedient.py | 144 + .../sfa/openflow_utils/sliver_status.py | 75 + .../optin_manager/sfa/rspecs/__init__.py | 0 .../sfa/rspecs/elements/__init__.py | 0 .../sfa/rspecs/elements/__init__.pyo | Bin 0 -> 151 bytes .../sfa/rspecs/elements/bwlimit.py | 8 + .../sfa/rspecs/elements/bwlimit.pyo | Bin 0 -> 478 bytes .../sfa/rspecs/elements/channel.py | 13 + .../sfa/rspecs/elements/channel.pyo | Bin 0 -> 586 bytes .../sfa/rspecs/elements/disk_image.py | 9 + .../sfa/rspecs/elements/disk_image.pyo | Bin 0 -> 520 bytes .../sfa/rspecs/elements/element.py | 21 + .../sfa/rspecs/elements/element.pyo | Bin 0 -> 1123 bytes .../sfa/rspecs/elements/execute.py | 7 + .../sfa/rspecs/elements/execute.pyo | Bin 0 -> 480 bytes .../sfa/rspecs/elements/fw_rule.py | 10 + .../sfa/rspecs/elements/fw_rule.pyo | Bin 0 -> 526 bytes .../sfa/rspecs/elements/granularity.py | 7 + .../sfa/rspecs/elements/granularity.pyo | Bin 0 -> 475 bytes .../sfa/rspecs/elements/hardware_type.py | 7 + .../sfa/rspecs/elements/hardware_type.pyo | Bin 0 -> 479 bytes .../sfa/rspecs/elements/install.py | 8 + .../sfa/rspecs/elements/install.pyo | Bin 0 -> 502 bytes .../sfa/rspecs/elements/interface.py | 12 + .../sfa/rspecs/elements/interface.pyo | Bin 0 -> 600 bytes .../sfa/rspecs/elements/lease.py | 11 + .../sfa/rspecs/elements/lease.pyo | Bin 0 -> 538 bytes .../optin_manager/sfa/rspecs/elements/link.py | 16 + .../sfa/rspecs/elements/link.pyo | Bin 0 -> 662 bytes .../sfa/rspecs/elements/location.py | 9 + .../sfa/rspecs/elements/location.pyo | Bin 0 -> 505 bytes .../sfa/rspecs/elements/login.py | 9 + .../sfa/rspecs/elements/login.pyo | Bin 0 -> 516 bytes .../sfa/rspecs/elements/network_interface.py | 17 + .../optin_manager/sfa/rspecs/elements/node.py | 27 + .../sfa/rspecs/elements/node.pyo | Bin 0 -> 817 bytes .../sfa/rspecs/elements/ocf_vt_server.py | 17 + .../sfa/rspecs/elements/openflow_switch.py | 11 + .../sfa/rspecs/elements/pltag.py | 9 + .../sfa/rspecs/elements/pltag.pyo | Bin 0 -> 474 bytes .../sfa/rspecs/elements/position_3d.py | 9 + .../sfa/rspecs/elements/position_3d.pyo | Bin 0 -> 492 bytes .../sfa/rspecs/elements/property.py | 12 + .../sfa/rspecs/elements/property.pyo | Bin 0 -> 543 bytes .../sfa/rspecs/elements/range.py | 11 + .../sfa/rspecs/elements/services.py | 10 + .../sfa/rspecs/elements/services.pyo | Bin 0 -> 500 bytes .../sfa/rspecs/elements/sliver.py | 13 + .../sfa/rspecs/elements/sliver.pyo | Bin 0 -> 585 bytes .../sfa/rspecs/elements/spectrum.py | 5 + .../sfa/rspecs/elements/spectrum.pyo | Bin 0 -> 453 bytes .../sfa/rspecs/elements/versions/__init__.py | 0 .../elements/versions/nitosv1Channel.py | 73 + .../rspecs/elements/versions/nitosv1Lease.py | 103 + .../rspecs/elements/versions/nitosv1Node.py | 185 + .../rspecs/elements/versions/nitosv1PLTag.py | 19 + .../rspecs/elements/versions/nitosv1Sliver.py | 57 + .../sfa/rspecs/elements/versions/ocfofNode.py | 213 + .../rspecs/elements/versions/ocfofSlivers.py | 44 + .../sfa/rspecs/elements/versions/ocfvtNode.py | 202 + .../rspecs/elements/versions/ocfvtSlivers.py | 83 + .../elements/versions/ocfvtSlivers.py.old | 83 + .../rspecs/elements/versions/pgv2DiskImage.py | 24 + .../rspecs/elements/versions/pgv2Interface.py | 20 + .../sfa/rspecs/elements/versions/pgv2Link.py | 104 + .../sfa/rspecs/elements/versions/pgv2Node.py | 147 + .../rspecs/elements/versions/pgv2Services.py | 43 + .../elements/versions/pgv2SliverType.py | 60 + .../rspecs/elements/versions/plosv1FWRule.py | 25 + .../rspecs/elements/versions/sfav1Lease.py | 111 + .../sfa/rspecs/elements/versions/sfav1Node.py | 166 + .../rspecs/elements/versions/sfav1PLTag.py | 19 + .../rspecs/elements/versions/sfav1Sliver.py | 54 + .../optin_manager/sfa/rspecs/elements/vm.py | 21 + .../sfa/rspecs/elements/vm_interface.py | 11 + .../sfa/rspecs/pg_rspec_converter.py | 94 + .../optin_manager/sfa/rspecs/rspec.py | 123 + .../sfa/rspecs/rspec_converter.py | 46 + .../sfa/rspecs/rspec_elements.py | 35 + .../sfa/rspecs/sfa_rspec_converter.py | 86 + .../optin_manager/sfa/rspecs/version.py | 30 + .../sfa/rspecs/version_manager.py | 104 + .../sfa/rspecs/versions/__init__.py | 0 .../sfa/rspecs/versions/ocfofv1.py | 154 + .../sfa/rspecs/versions/ocfvtv1.py | 219 + .../optin_manager/sfa/schemas/credential.xsd | 214 + .../sfa/schemas/protogeni-rspec-common.xsd | 120 + .../optin_manager/sfa/schemas/sig.xsd | 11 + .../optin_manager/sfa/schemas/top.xsd | 312 ++ .../optin_manager/sfa/schemas/xml.xsd | 10 + .../optin_manager/sfa/server/__init__.py | 0 .../optin_manager/sfa/server/registry.py | 219 + .../optin_manager/sfa/server/sfaclientlib.py | 410 ++ .../optin_manager/sfa/server/sm_test.py | 121 + .../optin_manager/sfa/setUp/__init__.py | 0 .../sfa/setUp/authority_create.py | 11 + .../sfa/setUp/credential_create.py | 5 + .../openflow/optin_manager/sfa/setUp/setup.py | 19 + .../sfa/setUp/setup_config-EXAMPLE | 24 + .../optin_manager/sfa/sfa_config/__init__.py | 0 .../optin_manager/sfa/sfa_config/config.py | 87 + .../optin_manager/sfa/tests/SLIVER_EXAMPLE | 45 + .../optin_manager/sfa/tests/__init__.py | 0 .../openflow/optin_manager/sfa/tests/ad.py | 100 + .../optin_manager/sfa/tests/create_sliver.py | 6 + .../sfa/tests/credential_create.py | 3 + .../tests/credential_procedure/__init__.py | 0 .../testing_credentials.py | 12 + .../topdomain.nitos.pi.user.cred | 160 + .../optin_manager/sfa/tests/data_example.py | 3 + .../optin_manager/sfa/tests/list_resources.py | 5 + .../optin_manager/sfa/tests/manage_slice.py | 25 + .../optin_manager/sfa/tests/of_rspec.py | 13 + .../optin_manager/sfa/tests/resources_example | 24 + .../optin_manager/sfa/tests/sliver_example.py | 38 + .../optin_manager/sfa/tests/sliver_status.py | 5 + .../sfa/tests/to_openflow_rspec.py | 206 + .../optin_manager/sfa/trust/__init__.py | 0 .../openflow/optin_manager/sfa/trust/auth.py | 308 ++ .../optin_manager/sfa/trust/certificate.py | 781 +++ .../optin_manager/sfa/trust/credential.py | 1086 +++++ .../sfa/trust/credential_legacy.py | 270 ++ .../openflow/optin_manager/sfa/trust/gid.py | 260 + .../optin_manager/sfa/trust/hierarchy.py | 376 ++ .../optin_manager/sfa/trust/rights.py | 255 + .../optin_manager/sfa/trust/sfaticket.py | 126 + .../optin_manager/sfa/trust/trustedroots.py | 44 + .../sfa/trusted_roots/optin_ocf.gid | 14 + .../optin_manager/sfa/util/__init__.py | 0 .../openflow/optin_manager/sfa/util/cache.py | 116 + .../optin_manager/sfa/util/callids.py | 79 + .../openflow/optin_manager/sfa/util/config.py | 320 ++ .../optin_manager/sfa/util/defaultdict.py | 38 + .../optin_manager/sfa/util/enumeration.py | 35 + .../openflow/optin_manager/sfa/util/faults.py | 344 ++ .../optin_manager/sfa/util/genicode.py | 45 + .../openflow/optin_manager/sfa/util/method.py | 290 ++ .../optin_manager/sfa/util/parameter.py | 103 + .../optin_manager/sfa/util/sfalogging.py | 201 + .../optin_manager/sfa/util/sfatime.py | 66 + .../optin_manager/sfa/util/version.py | 12 + .../openflow/optin_manager/sfa/util/xml.py | 358 ++ .../openflow/optin_manager/sfa/util/xrn.py | 299 ++ .../openflow/optin_manager/testparser.py | 36 + .../src/python/openflow/optin_manager/urls.py | 82 + .../openflow/optin_manager/users/__init__.py | 0 .../openflow/optin_manager/users/admin.py | 8 + .../openflow/optin_manager/users/forms.py | 18 + .../openflow/optin_manager/users/models.py | 52 + .../users/user_signal_handler.py | 22 + .../openflow/optin_manager/users/views.py | 131 + .../optin_manager/xmlrpc_server/__init__.py | 5 + .../optin_manager/xmlrpc_server/ch_api.py | 805 +++ .../optin_manager/xmlrpc_server/fv_api.py | 12 + .../optin_manager/xmlrpc_server/gapi3.py | 69 + .../optin_manager/xmlrpc_server/models.py | 71 + .../optin_manager/xmlrpc_server/sfa_api.py | 158 + .../optin_manager/xmlrpc_server/tests.py | 535 ++ .../optin_manager/xmlrpc_server/urls.py | 7 + .../src/python/openflow/tests/__init__.py | 0 .../python/openflow/tests/full/__init__.py | 0 .../python/openflow/tests/full/fulltests.py | 690 +++ .../src/python/openflow/tests/full/helpers.py | 67 + .../src/python/openflow/tests/helpers.py | 318 ++ .../openflow/tests/manual_test/__init__.py | 0 .../openflow/tests/manual_test/manual.py | 198 + .../openflow/tests/omctl/XMLRPCServerProxy.py | 186 + .../python/openflow/tests/omctl/__init__.py | 1 + .../python/openflow/tests/omctl/helpers.py | 233 + .../src/python/openflow/tests/omctl/omctl.py | 110 + .../openflow/tests/omctl/omctl_settings.py | 2 + .../tests/post_deployment/__init__.py | 0 .../openflow/tests/post_deployment/tests.py | 203 + .../src/python/openflow/tests/ssl/Makefile | 47 + .../python/openflow/tests/test_settings.py | 74 + .../src/python/openflow/tests/tests.py | 14 + .../PKG-INFO | 10 + .../SOURCES.txt | 250 + .../dependency_links.txt | 1 + .../entry_points.txt | 5 + .../not-zip-safe | 1 + .../requires.txt | 18 + .../top_level.txt | 2 + optin_manager/src/python/scripts/__init__.py | 0 .../src/python/scripts/create-superuser.py | 25 + .../src/python/scripts/create-users.py | 18 + .../src/python/scripts/create_oms.py | 14 + optin_manager/src/python/scripts/setup_ch.py | 96 + .../scripts/setup_expedient_params_clean.py | 114 + optin_manager/src/python/scripts/setup_om.py | 95 + .../optin_manager/media/FELIX/logo_optin.png | Bin 0 -> 4178 bytes .../optin_manager/media/FELIX/ocf.css | 1234 +++++ .../optin_manager/media/FIBRE/logo_optin.png | Bin 0 -> 19842 bytes .../optin_manager/media/default/account.png | Bin 0 -> 3443 bytes .../optin_manager/media/default/active.png | Bin 0 -> 2351 bytes .../media/default/add_rule_dark.png | Bin 0 -> 3352 bytes .../media/default/add_rule_light.png | Bin 0 -> 3321 bytes .../media/default/admin_abandon_fs_dark.png | Bin 0 -> 4916 bytes .../media/default/admin_abandon_fs_light.png | Bin 0 -> 4972 bytes .../media/default/admin_fs_dark.png | Bin 0 -> 5327 bytes .../media/default/admin_fs_light.png | Bin 0 -> 5331 bytes .../media/default/admin_fses_dark.png | Bin 0 -> 4720 bytes .../media/default/admin_fses_light.png | Bin 0 -> 4667 bytes .../media/default/admin_req_dark.png | Bin 0 -> 4747 bytes .../media/default/admin_req_fs_dark.png | Bin 0 -> 4816 bytes .../media/default/admin_req_fs_light.png | Bin 0 -> 4807 bytes .../media/default/admin_req_light.png | Bin 0 -> 4760 bytes .../media/default/aggregate-tiny.png | Bin 0 -> 2527 bytes .../media/default/auto_approve_dark.png | Bin 0 -> 4632 bytes .../media/default/auto_approve_light.png | Bin 0 -> 4571 bytes .../optin_manager/media/default/back_dark.png | Bin 0 -> 2765 bytes .../media/default/back_light.png | Bin 0 -> 2763 bytes .../optin_manager/media/default/button.pxm | Bin 0 -> 6747 bytes .../media/default/contact_exp_dark.png | Bin 0 -> 3494 bytes .../media/default/contact_exp_light.png | Bin 0 -> 3526 bytes .../optin_manager/media/default/dashboard.png | Bin 0 -> 3833 bytes .../media/default/dashboard_dark.png | Bin 0 -> 3742 bytes .../media/default/dashboard_light.png | Bin 0 -> 3678 bytes .../media/default/edit_profile_dark.png | Bin 0 -> 3481 bytes .../media/default/edit_profile_light.png | Bin 0 -> 3425 bytes .../media/default/egeni-iframe.css | 973 ++++ .../media/default/experiments_dark.png | Bin 0 -> 4102 bytes .../media/default/experiments_light.png | Bin 0 -> 4083 bytes .../optin_manager/media/default/favicon.ico | Bin 0 -> 4286 bytes .../media/default/fs_req_dark.png | Bin 0 -> 5585 bytes .../media/default/fs_req_light.png | Bin 0 -> 5578 bytes .../optin_manager/media/default/genilogo.png | Bin 0 -> 10205 bytes .../media/default/give_up_fs_dark.png | Bin 0 -> 4828 bytes .../media/default/give_up_fs_light.png | Bin 0 -> 4816 bytes .../optin_manager/media/default/help.png | Bin 0 -> 3091 bytes .../optin_manager/media/default/host-tiny.png | Bin 0 -> 2072 bytes .../optin_manager/media/default/inactive.png | Bin 0 -> 2099 bytes .../media/default/js/formtable.tooltip.js | 140 + .../media/default/js/jquery.min.js | 167 + .../media/default/js/jquery.tools.min.js | 192 + .../media/default/js/tooltip.funcs.js | 108 + .../media/default/logo_optin.png | Bin 0 -> 24566 bytes .../optin_manager/media/default/logout.png | Bin 0 -> 3319 bytes .../media/default/logout_dark.png | Bin 0 -> 3414 bytes .../media/default/logout_light.png | Bin 0 -> 3414 bytes .../media/default/manage_fs_dark.png | Bin 0 -> 5136 bytes .../media/default/manage_fs_light.png | Bin 0 -> 5164 bytes .../media/default/manage_site_dark.png | Bin 0 -> 5163 bytes .../media/default/manage_site_light.png | Bin 0 -> 5188 bytes .../optin_manager/media/default/ocf.css | 1234 +++++ .../media/default/optin_dark.png | Bin 0 -> 2843 bytes .../media/default/optin_light.png | Bin 0 -> 2843 bytes .../media/default/optout_dark.png | Bin 0 -> 3409 bytes .../media/default/optout_light.png | Bin 0 -> 3382 bytes .../media/default/profile_dark.png | Bin 0 -> 2973 bytes .../media/default/profile_light.png | Bin 0 -> 2962 bytes .../media/default/promote_to_admin_dark.png | Bin 0 -> 4145 bytes .../media/default/promote_to_admin_light.png | Bin 0 -> 4142 bytes .../media/default/question_mark_15x15.png | Bin 0 -> 873 bytes .../media/default/remove_rule_dark.png | Bin 0 -> 3824 bytes .../media/default/remove_rule_light.png | Bin 0 -> 3776 bytes .../media/default/request_fs_dark.png | Bin 0 -> 5080 bytes .../media/default/request_fs_light.png | Bin 0 -> 5044 bytes .../media/default/resign_admin_dark.png | Bin 0 -> 4803 bytes .../media/default/resign_admin_light.png | Bin 0 -> 4799 bytes .../media/default/sample_rules.txt | 41 + .../media/default/set_ch_dark.png | Bin 0 -> 4890 bytes .../media/default/set_ch_light.png | Bin 0 -> 4936 bytes .../media/default/set_fv_dark.png | Bin 0 -> 4072 bytes .../media/default/set_fv_light.png | Bin 0 -> 4029 bytes .../media/default/set_priority_dark.png | Bin 0 -> 3843 bytes .../media/default/set_priority_light.png | Bin 0 -> 3826 bytes .../media/default/set_rule_priority_dark.png | Bin 0 -> 4587 bytes .../media/default/set_rule_priority_light.png | Bin 0 -> 4626 bytes .../media/default/slice-tiny.png | Bin 0 -> 2477 bytes .../optin_manager/media/default/slice.png | Bin 0 -> 3425 bytes .../media/default/step0_dark.png | Bin 0 -> 54007 bytes .../media/default/step0_light.png | Bin 0 -> 28572 bytes .../media/default/step1_dark.png | Bin 0 -> 65415 bytes .../media/default/step2_manage_dark.png | Bin 0 -> 8540 bytes .../media/default/step2_manage_light.png | Bin 0 -> 9121 bytes .../media/default/step2_optin_dark.png | Bin 0 -> 6517 bytes .../media/default/step2_optin_light.png | Bin 0 -> 7468 bytes .../media/default/step2_optout_dark.png | Bin 0 -> 7410 bytes .../media/default/step2_optout_light.png | Bin 0 -> 8157 bytes .../media/default/switch-5406zl.png | Bin 0 -> 22661 bytes .../media/default/switch-cat6500.png | Bin 0 -> 93452 bytes .../media/default/switch-juniper.png | Bin 0 -> 78003 bytes .../media/default/switch-nec-ip8800.png | Bin 0 -> 40585 bytes .../media/default/switch-netfpga.png | Bin 0 -> 78800 bytes .../media/default/switch-nf2.png | Bin 0 -> 49952 bytes .../media/default/switch-tiny.png | Bin 0 -> 1967 bytes .../optin_manager/media/default/switch.png | Bin 0 -> 7167 bytes .../optin_manager/media/default/tooltip.css | 31 + .../media/default/user_fses_dark.png | Bin 0 -> 4736 bytes .../media/default/user_fses_light.png | Bin 0 -> 4756 bytes .../media/default/user_req_dark.png | Bin 0 -> 4381 bytes .../media/default/user_req_light.png | Bin 0 -> 4350 bytes .../media/default/users-tiny.png | Bin 0 -> 2518 bytes .../media/default/view_exp_dark.png | Bin 0 -> 2854 bytes .../media/default/view_exp_light.png | Bin 0 -> 2868 bytes .../FELIX/openflow/optin_manager/base.html | 50 + .../openflow/optin_manager/base_admin.html | 277 ++ .../openflow/optin_manager/base_user.html | 184 + .../FELIX/openflow/optin_manager/footer.html | 6 + .../FIBRE/openflow/optin_manager/base.html | 50 + .../openflow/optin_manager/base_admin.html | 277 ++ .../openflow/optin_manager/base_user.html | 184 + .../admin_manager/admin_req_fs.html | 91 + .../admin_request_successful.html | 17 + .../admin_manager/admin_unreg_fs.html | 35 + .../admin_manager/approve_admin.html | 104 + .../admin_manager/approve_user.html | 74 + .../admin_manager/change_admin_fs.html | 127 + .../admin_manager/change_user_fs.html | 46 + .../admin_manager/manage_admin_fs.html | 43 + .../admin_manager/manage_user_fs.html | 43 + .../admin_manager/promote_to_admin.html | 45 + .../admin_manager/reg_request_successful.html | 31 + .../admin_manager/resign_admin.html | 23 + .../admin_manager/set_auto_approve.html | 56 + .../admin_manager/user_reg_fs.html | 14 + .../admin_manager/user_unreg_fs.html | 35 + .../default/openflow/optin_manager/base.html | 50 + .../openflow/optin_manager/base_admin.html | 278 ++ .../openflow/optin_manager/base_user.html | 184 + .../controls/set_clearinghouse.html | 14 + .../optin_manager/controls/set_flowvisor.html | 22 + .../optin_manager/dashboard_admin.html | 43 + .../optin_manager/dashboard_user.html | 96 + .../openflow/optin_manager/footer.html | 7 + .../default/openflow/optin_manager/index.html | 13 + .../optin_manager/opts/admin_opt_in.html | 222 + .../optin_manager/opts/admin_opt_out.html | 41 + .../opts/change_priority_successful.html | 17 + .../opts/opt_in_successful_admin.html | 18 + .../opts/opt_in_successful_user.html | 18 + .../optin_manager/opts/user_opt_in.html | 45 + .../optin_manager/opts/user_opt_out.html | 40 + .../opts/view_experiment_admin.html | 18 + .../opts/view_experiment_simple.html | 106 + .../opts/view_experiment_user.html | 18 + .../opts/view_experiments_admin.html | 16 + .../opts/view_experiments_user.html | 16 + .../optin_manager/opts/view_opt_simple.html | 21 + .../optin_manager/opts/view_opts_admin.html | 268 + .../optin_manager/opts/view_opts_user.html | 276 ++ .../optin_manager/registration/activate.html | 15 + .../registration/activation_email.txt | 6 + .../registration/activation_email_subject.txt | 1 + .../optin_manager/registration/login.html | 19 + .../optin_manager/registration/logout.html | 9 + .../registration/registration_complete.html | 10 + .../registration/registration_form.html | 10 + .../openflow/optin_manager/tooltip.funcs.js | 100 + .../users/change_profile_admin.html | 20 + .../users/change_profile_user.html | 19 + .../src/wsgi/openflow/optin_manager/auth.wsgi | 34 + .../wsgi/openflow/optin_manager/django.wsgi | 14 + .../src/wsgi/openflow/optin_manager/mon.wsgi | 20 + optin_manager/version | 1 + vt_manager/.gitignore | 1 + vt_manager/bin/common | 1 + vt_manager/bin/log/.gitignore | 0 vt_manager/bin/ofver | 1 + vt_manager/bin/repo | 1 + vt_manager/bin/rescue/.gitignore | 0 vt_manager/bin/settings | 1 + .../0.12/upgrade/0.11/post-upgrade-hook | 26 + .../bin/versions/0.13/upgrade/0.12/backup | 32 + .../0.13/upgrade/0.12/pre-backup-upgrade-hook | 38 + .../versions/0.14.2/install/post-install-hook | 56 + .../0.14.2/upgrade/default/post-upgrade-hook | 61 + .../0.2/upgrade/default/post-upgrade-hook | 64 + vt_manager/bin/versions/0.2RC1 | 1 + .../0.3/upgrade/default/post-upgrade-hook | 38 + .../0.3/upgrade/default/pre-upgrade-hook | 1 + vt_manager/bin/versions/0.3RC1 | 1 + vt_manager/bin/versions/0.4.1 | 1 + vt_manager/bin/versions/0.4.2 | 1 + vt_manager/bin/versions/0.4.3 | 1 + .../0.4/upgrade/default/post-upgrade-hook | 19 + .../0.4/upgrade/default/pre-upgrade-hook | 33 + .../default/tools/vmCallBackURLupdate.py | 33 + vt_manager/bin/versions/0.5 | 1 + vt_manager/bin/versions/0.6 | 1 + vt_manager/bin/versions/0.6.1 | 1 + .../0.7/upgrade/default/pre-upgrade-hook | 36 + vt_manager/bin/versions/0.8 | 1 + vt_manager/bin/versions/0.8.1 | 1 + vt_manager/bin/versions/0.8.2 | 1 + .../bin/versions/0.8.3/upgrade/default/lib | 1 + .../0.8.3/upgrade/default/pre-upgrade-hook | 36 + .../versions/0.8.3/upgrade/default/upgrade | 39 + .../bin/versions/default/install/backup | 13 + .../bin/versions/default/install/install | 79 + .../versions/default/install/lib/dependencies | 8 + .../versions/default/install/lib/django-db | 12 + .../default/install/lib/django-settings | 57 + .../bin/versions/default/install/lib/pypelib | 1 + .../install/lib/set_environment_variables | 1 + .../versions/default/install/lib/sfa-settings | 60 + .../bin/versions/default/install/lib/ssl | 90 + .../default/install/post-install-hook | 21 + .../versions/default/install/pre-install-hook | 35 + vt_manager/bin/versions/default/install/repo | 16 + .../bin/versions/default/install/rollback | 13 + .../versions/default/upgrade/default/backup | 28 + .../default/upgrade/default/dependencies | 9 + .../default/lib/set_environment_variables | 1 + .../default/upgrade/default/post-upgrade-hook | 23 + .../default/upgrade/default/pre-upgrade-hook | 52 + .../versions/default/upgrade/default/rollback | 36 + .../versions/default/upgrade/default/upgrade | 40 + .../default/upgrade/tools/UpgradeTools.py | 36 + .../versions/default/upgrade/tools/prova.cfg | 6 + .../versions/default/upgrade/tools/sqlDump.py | 1 + .../default/upgrade/tools/sqlRestore.py | 1 + vt_manager/bin/versions/version-checks | 1 + vt_manager/src/config/agent/OfeliaLauncher.sh | 6 + vt_manager/src/config/agent/oxad | 177 + vt_manager/src/config/agent/oxad-python | 156 + vt_manager/src/config/agent/prova.py | 6 + .../vt_manager/apache/vhost-macros-vt.conf | 163 + .../config/vt_manager/apache/vhost-vt.conf | 5 + .../common/apache/vhost-macros.conf | 286 ++ vt_manager/src/python/agent/OfeliaAgent.py | 118 + vt_manager/src/python/agent/README.md | 142 + vt_manager/src/python/agent/__init__.py | 0 .../agent/communications/XmlRpcClient.py | 95 + .../agent/communications/XmlRpcServer.py | 173 + .../python/agent/communications/__init__.py | 0 .../src/python/agent/communications/prova.xml | 20 + .../agent/communications/tests/client.py | 10 + .../python/agent/communications/tests/mon.xml | 11 + .../agent/communications/tests/prov.xml | 49 + .../agent/communications/tests/prova2.xml | 41 + .../agent/monitoring/LibvirtMonitoring.py | 451 ++ .../agent/monitoring/MonitoringDispatcher.py | 67 + .../src/python/agent/monitoring/__init__.py | 0 .../src/python/agent/mySettings-example.py | 73 + .../provisioning/ProvisioningDispatcher.py | 97 + .../src/python/agent/provisioning/__init__.py | 0 .../src/python/agent/security/__init__.py | 0 .../src/python/agent/security/certs/Makefile | 21 + .../src/python/agent/settings/__init__.py | 0 .../python/agent/settings/settingsLoader.py | 15 + .../python/agent/settings/spirentSettings.py | 14 + .../python/agent/settings/staticSettings.py | 77 + vt_manager/src/python/agent/tools/common | 1 + .../src/python/agent/tools/log/.gitignore | 0 vt_manager/src/python/agent/tools/ofver | 1 + vt_manager/src/python/agent/tools/repo | 1 + .../src/python/agent/tools/rescue/.gitignore | 0 vt_manager/src/python/agent/tools/settings | 1 + .../versions/0.12/upgrade/0.11/lib/template | 1 + .../0.12/upgrade/0.11/post-upgrade-hook | 19 + .../0.3/upgrade/default/post-upgrade-hook | 23 + .../0.3/upgrade/default/pre-upgrade-hook | 1 + .../src/python/agent/tools/versions/0.3RC1 | 1 + .../0.5/upgrade/default/post-upgrade-hook | 103 + .../0.5/upgrade/default/pre-upgrade-hook | 97 + .../0.8.2/upgrade/default/pre-upgrade-hook | 37 + .../tools/versions/default/install/backup | 13 + .../tools/versions/default/install/install | 51 + .../tools/versions/default/install/lib/daemon | 6 + .../versions/default/install/lib/dependencies | 7 + .../versions/default/install/lib/directories | 10 + .../versions/default/install/lib/settings | 58 + .../tools/versions/default/install/lib/ssl | 33 + .../versions/default/install/lib/template | 73 + .../default/install/post-install-hook | 18 + .../versions/default/install/pre-install-hook | 31 + .../tools/versions/default/install/rollback | 13 + .../versions/default/upgrade/default/backup | 13 + .../upgrade/default/lib/get_templates.py | 1 + .../default/upgrade/default/lib/template | 1 + .../default/upgrade/default/post-upgrade-hook | 17 + .../default/upgrade/default/pre-upgrade-hook | 31 + .../versions/default/upgrade/default/rollback | 15 + .../versions/default/upgrade/default/upgrade | 26 + .../agent/tools/versions/version-checks | 1 + .../src/python/agent/utils/AgentExceptions.py | 12 + .../src/python/agent/utils/LibvirtLogger.py | 22 + vt_manager/src/python/agent/utils/Logger.py | 39 + .../utils/MonitoringCallbackFunctions.py | 6 + .../src/python/agent/utils/ServiceThread.py | 28 + .../src/python/agent/utils/VmMutexStore.py | 56 + vt_manager/src/python/agent/utils/XmlUtils.py | 86 + vt_manager/src/python/agent/utils/__init__.py | 0 .../utils/template_downloader/ordered_dict.py | 258 + .../template_downloader.py | 486 ++ .../src/python/agent/utils/xml/Makefile | 12 + .../src/python/agent/utils/xml/__init__.py | 0 .../utils/xml/emptyMonitoringResponse.xml | 11 + .../xml/emptyMonitoringVMsInfoResponse.xml | 25 + .../utils/xml/emptyProvisioningResponse.xml | 16 + .../src/python/agent/utils/xml/query.xml | 41 + .../src/python/agent/utils/xml/response.xml | 84 + .../src/python/agent/utils/xml/schema.xsd | 334 ++ .../agent/utils/xml/vtRspecInterface.py | 2492 ++++++++++ .../agent/utils/xml/vtRspecInterfaceStub.py | 291 ++ vt_manager/src/python/agent/version | 1 + .../src/python/agent/xen/XendManager.py | 189 + vt_manager/src/python/agent/xen/__init__.py | 0 .../agent/xen/monitoring/DomainMonitor.py | 31 + .../xen/monitoring/XenMonitoringDispatcher.py | 29 + .../python/agent/xen/monitoring/__init__.py | 0 .../agent/xen/provisioning/HdManager.py | 83 + .../agent/xen/provisioning/VMConfigurator.py | 47 + .../provisioning/XenProvisioningDispatcher.py | 154 + .../python/agent/xen/provisioning/__init__.py | 0 .../provisioning/configurators/__init__.py | 0 .../debian7/DebianWheezyVMConfigurator.py | 177 + .../configurators/debian7/__init__.py | 0 .../templates/fullVirtualizedFileHd.pt | 50 + .../irati/IratiDebianVMConfigurator.py | 177 + .../configurators/irati/__init__.py | 0 .../irati/templates/fullVirtualizedFileHd.pt | 59 + .../mediacat/MediacatVMConfigurator.py | 66 + .../configurators/mediacat/__init__.py | 0 .../mediacat/templates/mediacatHVMFileHd.pt | 67 + .../ofelia/OfeliaDebianVMConfigurator.py | 177 + .../configurators/ofelia/__init__.py | 0 .../ofelia/templates/paraVirtualizedFileHd.pt | 53 + .../spirent/SpirentCentOSVMConfigurator.py | 218 + .../configurators/spirent/__init__.py | 0 .../spirent/templates/spirentSTCVMTemplate.pt | 57 + .../hdmanagers/FileFullHdManager.py | 292 ++ .../provisioning/hdmanagers/FileHdManager.py | 315 ++ .../provisioning/hdmanagers/LVMHdManager.py | 90 + .../xen/provisioning/hdmanagers/__init__.py | 0 vt_manager/src/python/agent/xen/xmlTest.py | 83 + vt_manager/src/python/scripts/__init__.py | 0 .../src/python/scripts/create-superuser.py | 25 + vt_manager/src/python/scripts/create-users.py | 18 + vt_manager/src/python/scripts/create_oms.py | 14 + vt_manager/src/python/scripts/setup_ch.py | 96 + .../scripts/setup_expedient_params_clean.py | 114 + vt_manager/src/python/scripts/setup_om.py | 95 + vt_manager/src/python/vt_manager/__init__.py | 0 .../src/python/vt_manager/common/__init__.py | 0 .../vt_manager/common/backends/__init__.py | 0 .../vt_manager/common/backends/remoteuser.py | 13 + .../vt_manager/common/commands/__init__.py | 0 .../common/commands/management/__init__.py | 0 .../commands/management/commands/__init__.py | 0 .../commands/clean_inconsistent_db_entries.py | 25 + .../vt_manager/common/commands/models.py | 6 + .../vt_manager/common/defaultsite/__init__.py | 0 .../common/defaultsite/management.py | 30 + .../vt_manager/common/defaultsite/settings.py | 19 + .../common/longer_username/__init__.py | 10 + .../vt_manager/common/messaging/__init__.py | 0 .../vt_manager/common/messaging/admin.py | 9 + .../common/messaging/context_processors.py | 15 + .../vt_manager/common/messaging/forms.py | 27 + .../vt_manager/common/messaging/models.py | 123 + .../vt_manager/common/messaging/tests.py | 23 + .../vt_manager/common/messaging/urls.py | 22 + .../vt_manager/common/messaging/views.py | 54 + .../vt_manager/common/middleware/__init__.py | 0 .../vt_manager/common/middleware/basicauth.py | 65 + .../common/middleware/sitelockdown.py | 43 + .../common/middleware/thread_local.py | 20 + .../vt_manager/common/middleware/utils.py | 25 + .../vt_manager/common/rpc4django/__init__.py | 61 + .../common/rpc4django/jsonrpcdispatcher.py | 154 + .../vt_manager/common/rpc4django/models.py | 11 + .../common/rpc4django/rpcdispatcher.py | 268 + .../rpc4django/rpcmethod_summary.html | 137 + .../rpc4django/templatetags/__init__.py | 0 .../common/rpc4django/templatetags/rpctags.py | 48 + .../common/rpc4django/tests/__init__.py | 11 + .../tests/test_jsonrpcdispatcher.py | 145 + .../rpc4django/tests/test_rpcdispatcher.py | 173 + .../common/rpc4django/tests/test_rpcviews.py | 164 + .../common/rpc4django/tests/test_urls.py | 12 + .../rpc4django/tests/test_xmlrpcdispatcher.py | 33 + .../rpc4django/tests/testmod/__init__.py | 10 + .../common/rpc4django/tests/testmod/models.py | 5 + .../tests/testmod/testsubmod/__init__.py | 9 + .../vt_manager/common/rpc4django/utils.py | 20 + .../vt_manager/common/rpc4django/views.py | 276 ++ .../common/rpc4django/xmlrpcdispatcher.py | 80 + .../vt_manager/common/utils/__init__.py | 35 + .../vt_manager/common/utils/certtransport.py | 16 + .../common/utils/context_processors.py | 13 + .../vt_manager/common/utils/formfields.py | 17 + .../vt_manager/common/utils/managers.py | 99 + .../vt_manager/common/utils/modelfields.py | 42 + .../common/utils/templatetags/__init__.py | 0 .../common/utils/templatetags/ch_extras.py | 54 + .../vt_manager/common/utils/transport.py | 42 + .../vt_manager/common/utils/validators.py | 54 + .../python/vt_manager/common/utils/views.py | 79 + .../vt_manager/communication/XmlRpcClient.py | 45 + .../vt_manager/communication/__init__.py | 10 + .../communication/gapi3communication.py | 67 + .../vt_manager/communication/geni/__init__.py | 0 .../communication/geni/v3/__init__.py | 0 .../geni/v3/configurators/__init__.py | 0 .../v3/configurators/handlerconfigurator.py | 66 + .../communication/geni/v3/drivers/__init__.py | 0 .../communication/geni/v3/drivers/vtam.py | 854 ++++ .../geni/v3/managers/__init__.py | 0 .../communication/geni/v3/managers/vtam.py | 145 + .../geni/v3/settings/__init__.py | 0 .../communication/geni/v3/settings/vtam.py | 19 + .../communication/geni/v3/tests/__init__.py | 0 .../geni/v3/tests/configurators/__init__.py | 0 .../v3/tests/configurators/vtam/__init__.py | 0 .../vtam/testcredentialmanager.py | 33 + .../vtam/testdriverconfiguration.py | 33 + .../testgeniexceptionmanagerconfiguration.py | 33 + .../vtam/testhandlerconfiguration.py | 45 + .../vtam/testresourcemanagerconfiguration.py | 38 + .../vtam/testrspecmanagerconfiguration.py | 33 + .../geni/v3/tests/drivers/__init__.py | 0 .../geni/v3/tests/drivers/vtam/__init__.py | 0 .../v3/tests/drivers/vtam/expected_outputs.py | 9 + .../geni/v3/tests/drivers/vtam/testhrns.py | 58 + .../v3/tests/drivers/vtam/testreservation.py | 71 + .../drivers/vtam/testtranslatortoclass.py | 96 + .../drivers/vtam/testtranslatortodict.py | 50 + .../geni/v3/tests/drivers/vtam/testurns.py | 60 + .../geni/v3/tests/managers/__init__.py | 0 .../geni/v3/tests/managers/vtam/__init__.py | 0 .../v3/tests/managers/vtam/testmanager.py | 54 + .../geni/v3/tests/mockers/__init__.py | 0 .../geni/v3/tests/mockers/driver.py | 77 + .../geni/v3/tests/mockers/reservation.py | 82 + .../geni/v3/tests/mockers/resource.py | 16 + .../geni/v3/tests/mockers/server.py | 17 + .../geni/v3/tests/settings/__init__.py | 0 .../geni/v3/tests/settings/vtam/__init__.py | 0 .../v3/tests/settings/vtam/testsettings.py | 28 + .../geni/v3/trusted_roots/fed4fire.gid | 14 + .../geni/v3/trusted_roots/fuseco.gid | 56 + .../geni/v3/trusted_roots/geni-ch.gid | 61 + .../geni/v3/trusted_roots/netmode.gid | 14 + .../geni/v3/trusted_roots/ocf.gid | 18 + .../geni/v3/trusted_roots/ofam.gid | 36 + .../geni/v3/trusted_roots/omf.gid | 13 + .../geni/v3/trusted_roots/ple.gid | 13 + .../geni/v3/trusted_roots/smartsantander.gid | 14 + .../geni/v3/trusted_roots/topdomain.gid | 14 + .../geni/v3/trusted_roots/wall2.gid | 27 + .../communication/northCommInterface.py | 158 + .../vt_manager/communication/sfa/__init__.py | 6 + .../vt_manager/communication/sfa/add_gid.sh | 28 + .../communication/sfa/configs/config | 9 + .../communication/sfa/configs/credentials.xsd | 214 + .../communication/sfa/configs/sig.xsd | 11 + .../communication/sfa/configs/top.xsd | 312 ++ .../communication/sfa/credentials/ocf.cred | 93 + .../sfa/credentials/ocf.i2cat.cred | 182 + .../sfa/credentials/ocf.i2cat.ofam.cred | 331 ++ .../sfa/credentials/topdomain.cred | 81 + .../communication/sfa/drivers/VMAggregate.py | 233 + .../communication/sfa/drivers/VTSfaDriver.py | 147 + .../communication/sfa/drivers/VTShell.py | 147 + .../communication/sfa/drivers/__init__.py | 0 .../communication/sfa/jfed_roots/jfed.gid | 17 + .../communication/sfa/jfed_roots/jfed2.gid | 23 + .../communication/sfa/jfed_roots/jfed3.gid | 23 + .../communication/sfa/jfed_roots/jfed4.gid | 24 + .../communication/sfa/jfed_roots/jfed5.gid | 23 + .../communication/sfa/jfed_roots/jfed6.gid | 22 + .../communication/sfa/jfed_roots/jfed8.gid | 24 + .../communication/sfa/jfed_roots/ocf_of.gid | 14 + .../communication/sfa/jfed_roots/ple.gid | 13 + .../sfa/jfed_roots/topdomain.gid | 14 + .../communication/sfa/jfed_roots/wall.gid | 24 + .../communication/sfa/jfed_roots/wall2.gid | 27 + .../sfa/managers/AggregateManager.py | 80 + .../communication/sfa/managers/__init__.py | 0 .../communication/sfa/methods/CreateGid.py | 47 + .../communication/sfa/methods/CreateSliver.py | 21 + .../communication/sfa/methods/DeleteSliver.py | 14 + .../sfa/methods/GetCredential.py | 48 + .../communication/sfa/methods/GetGids.py | 45 + .../sfa/methods/GetSelfCredential.py | 87 + .../communication/sfa/methods/GetTicket.py | 57 + .../communication/sfa/methods/GetVersion.py | 20 + .../communication/sfa/methods/List.py | 36 + .../sfa/methods/ListResources.py | 41 + .../sfa/methods/ListResources.py.bak | 58 + .../communication/sfa/methods/ListSlices.py | 33 + .../communication/sfa/methods/RedeemTicket.py | 29 + .../communication/sfa/methods/Register.py | 41 + .../communication/sfa/methods/Remove.py | 44 + .../communication/sfa/methods/RenewSliver.py | 46 + .../communication/sfa/methods/Resolve.py | 54 + .../communication/sfa/methods/ResolveGENI.py | 19 + .../communication/sfa/methods/Shutdown.py | 23 + .../communication/sfa/methods/SliverStatus.py | 10 + .../communication/sfa/methods/Start.py | 11 + .../communication/sfa/methods/Stop.py | 11 + .../communication/sfa/methods/Update.py | 41 + .../communication/sfa/methods/UpdateSliver.py | 33 + .../communication/sfa/methods/__init__.py | 29 + .../sfa/methods/get_key_from_incoming_ip.py | 24 + .../sfa/methods/get_trusted_certs.py | 40 + .../sfa/methods/permission_manager.py | 14 + .../communication/sfa/methods/reset_slice.py | 30 + .../sfa/my_roots/authorities/ocf/ocf.gid | 17 + .../sfa/my_roots/authorities/ocf/ocf.pkey | 15 + .../my_roots/authorities/ocf/ofam/ofam.gid | 34 + .../my_roots/authorities/ocf/ofam/ofam.pkey | 15 + .../authorities/topdomain/topdomain.gid | 14 + .../authorities/topdomain/topdomain.pkey | 16 + .../communication/sfa/rspecs/__init__.py | 0 .../sfa/rspecs/elements/__init__.py | 0 .../sfa/rspecs/elements/__init__.pyo | Bin 0 -> 151 bytes .../sfa/rspecs/elements/bwlimit.py | 8 + .../sfa/rspecs/elements/bwlimit.pyo | Bin 0 -> 478 bytes .../sfa/rspecs/elements/channel.py | 13 + .../sfa/rspecs/elements/channel.pyo | Bin 0 -> 586 bytes .../sfa/rspecs/elements/disk_image.py | 9 + .../sfa/rspecs/elements/disk_image.pyo | Bin 0 -> 520 bytes .../sfa/rspecs/elements/element.py | 21 + .../sfa/rspecs/elements/element.pyo | Bin 0 -> 1123 bytes .../sfa/rspecs/elements/execute.py | 7 + .../sfa/rspecs/elements/execute.pyo | Bin 0 -> 480 bytes .../sfa/rspecs/elements/fw_rule.py | 10 + .../sfa/rspecs/elements/fw_rule.pyo | Bin 0 -> 526 bytes .../sfa/rspecs/elements/granularity.py | 7 + .../sfa/rspecs/elements/granularity.pyo | Bin 0 -> 475 bytes .../sfa/rspecs/elements/hardware_type.py | 7 + .../sfa/rspecs/elements/hardware_type.pyo | Bin 0 -> 479 bytes .../sfa/rspecs/elements/install.py | 8 + .../sfa/rspecs/elements/install.pyo | Bin 0 -> 502 bytes .../sfa/rspecs/elements/interface.py | 12 + .../sfa/rspecs/elements/interface.pyo | Bin 0 -> 600 bytes .../sfa/rspecs/elements/lease.py | 11 + .../sfa/rspecs/elements/lease.pyo | Bin 0 -> 538 bytes .../communication/sfa/rspecs/elements/link.py | 16 + .../sfa/rspecs/elements/link.pyo | Bin 0 -> 662 bytes .../sfa/rspecs/elements/location.py | 9 + .../sfa/rspecs/elements/location.pyo | Bin 0 -> 505 bytes .../sfa/rspecs/elements/login.py | 9 + .../sfa/rspecs/elements/login.pyo | Bin 0 -> 516 bytes .../sfa/rspecs/elements/network_interface.py | 17 + .../communication/sfa/rspecs/elements/node.py | 27 + .../sfa/rspecs/elements/node.pyo | Bin 0 -> 817 bytes .../sfa/rspecs/elements/ocf_vt_server.py | 17 + .../sfa/rspecs/elements/pltag.py | 9 + .../sfa/rspecs/elements/pltag.pyo | Bin 0 -> 474 bytes .../sfa/rspecs/elements/position_3d.py | 9 + .../sfa/rspecs/elements/position_3d.pyo | Bin 0 -> 492 bytes .../sfa/rspecs/elements/property.py | 12 + .../sfa/rspecs/elements/property.pyo | Bin 0 -> 543 bytes .../sfa/rspecs/elements/range.py | 11 + .../sfa/rspecs/elements/services.py | 10 + .../sfa/rspecs/elements/services.pyo | Bin 0 -> 500 bytes .../sfa/rspecs/elements/sliver.py | 13 + .../sfa/rspecs/elements/sliver.pyo | Bin 0 -> 585 bytes .../sfa/rspecs/elements/spectrum.py | 5 + .../sfa/rspecs/elements/spectrum.pyo | Bin 0 -> 453 bytes .../sfa/rspecs/elements/versions/__init__.py | 0 .../elements/versions/nitosv1Channel.py | 73 + .../rspecs/elements/versions/nitosv1Lease.py | 103 + .../rspecs/elements/versions/nitosv1Node.py | 185 + .../rspecs/elements/versions/nitosv1PLTag.py | 19 + .../rspecs/elements/versions/nitosv1Sliver.py | 57 + .../sfa/rspecs/elements/versions/ocfvtNode.py | 289 ++ .../rspecs/elements/versions/ocfvtSlivers.py | 83 + .../elements/versions/ocfvtSlivers.py.old | 83 + .../rspecs/elements/versions/pgv2DiskImage.py | 24 + .../rspecs/elements/versions/pgv2Interface.py | 20 + .../sfa/rspecs/elements/versions/pgv2Link.py | 104 + .../sfa/rspecs/elements/versions/pgv2Node.py | 147 + .../rspecs/elements/versions/pgv2Services.py | 44 + .../elements/versions/pgv2SliverType.py | 60 + .../rspecs/elements/versions/plosv1FWRule.py | 25 + .../rspecs/elements/versions/sfav1Lease.py | 111 + .../sfa/rspecs/elements/versions/sfav1Node.py | 166 + .../rspecs/elements/versions/sfav1PLTag.py | 19 + .../rspecs/elements/versions/sfav1Sliver.py | 54 + .../communication/sfa/rspecs/elements/vm.py | 22 + .../sfa/rspecs/elements/vm_interface.py | 11 + .../sfa/rspecs/pg_rspec_converter.py | 94 + .../communication/sfa/rspecs/rspec.py | 123 + .../sfa/rspecs/rspec_converter.py | 46 + .../sfa/rspecs/rspec_elements.py | 35 + .../sfa/rspecs/sfa_rspec_converter.py | 86 + .../communication/sfa/rspecs/version.py | 30 + .../sfa/rspecs/version_manager.py | 96 + .../sfa/rspecs/versions/__init__.py | 0 .../sfa/rspecs/versions/ocfvtv1.py | 227 + .../communication/sfa/schemas/credential.xsd | 214 + .../sfa/schemas/protogeni-rspec-common.xsd | 120 + .../communication/sfa/schemas/sig.xsd | 11 + .../communication/sfa/schemas/top.xsd | 312 ++ .../communication/sfa/schemas/xml.xsd | 10 + .../communication/sfa/setUp/__init__.py | 0 .../sfa/setUp/authority_create.py | 11 + .../communication/sfa/setUp/setup.py | 16 + .../sfa/setUp/setup_config-EXAMPLE | 24 + .../communication/sfa/setUp/setup_config.py | 17 + .../communication/sfa/sfa_config/__init__.py | 0 .../sfa/sfa_config/config-example | 129 + .../sfa/tests/Expected-Outputs/ListResources | 65 + .../communication/sfa/tests/__init__.py | 0 .../sfa/tests/example_vm_rspec.py | 68 + .../communication/sfa/tests/hardcoded_vars.py | 2 + .../communication/sfa/tests/response.py | 17 + .../communication/sfa/tests/schema.xsd | 125 + .../communication/sfa/tests/server_schema.xsd | 52 + .../sfa/tests/test_aggregate_manager.py | 46 + .../communication/sfa/tests/vm_schema.xsd | 68 + .../communication/sfa/tests/vm_schema.xsd.old | 59 + .../communication/sfa/trust/__init__.py | 0 .../communication/sfa/trust/auth.py | 308 ++ .../communication/sfa/trust/certificate.py | 781 +++ .../communication/sfa/trust/credential.py | 1086 +++++ .../sfa/trust/credential_legacy.py | 270 ++ .../vt_manager/communication/sfa/trust/gid.py | 260 + .../communication/sfa/trust/hierarchy.py | 375 ++ .../communication/sfa/trust/rights.py | 255 + .../communication/sfa/trust/sfaticket.py | 126 + .../communication/sfa/trust/trustedroots.py | 44 + .../sfa/trusted_roots/fed4fire.gid | 14 + .../sfa/trusted_roots/felix-ch.gid | 14 + .../sfa/trusted_roots/new_wall2.gid | 27 + .../sfa/trusted_roots/optin_ocf.gid | 14 + .../communication/sfa/trusted_roots/ple.gid | 13 + .../sfa/trusted_roots/topdomain2.gid | 14 + .../communication/sfa/trusted_roots/wall2.gid | 27 + .../communication/sfa/util/__init__.py | 0 .../communication/sfa/util/cache.py | 116 + .../communication/sfa/util/callids.py | 79 + .../communication/sfa/util/config.py | 315 ++ .../communication/sfa/util/defaultdict.py | 38 + .../communication/sfa/util/enumeration.py | 35 + .../communication/sfa/util/faults.py | 332 ++ .../communication/sfa/util/genicode.py | 45 + .../communication/sfa/util/sfalogging.py | 201 + .../communication/sfa/util/sfatime.py | 66 + .../communication/sfa/util/version.py | 12 + .../vt_manager/communication/sfa/util/xml.py | 355 ++ .../vt_manager/communication/sfa/util/xrn.py | 298 ++ .../sfa/vm_utils/SfaCommunicator.py | 44 + .../communication/sfa/vm_utils/Translator.py | 62 + .../sfa/vm_utils/VMSfaManager.py | 85 + .../communication/sfa/vm_utils/__init__.py | 0 .../sfa/vm_utils/expiration_manager.py | 32 + .../communication/sfa/vm_utils/ldapManager.py | 169 + .../communication/sfaCommunication.py | 127 + .../communication/southCommInterface.py | 27 + .../communication/test_rpcmethod.py | 5 + .../communication/utils/XmlHelper.py | 150 + .../communication/utils/__init__.py | 0 .../communication/utils/xml/emptyResponse.xml | 17 + .../communication/utils/xml/list.xml | 84 + .../utils/xml/listActiveVMsQuery.xml | 11 + .../utils/xml/queryProvisioning.xml | 26 + .../utils/xml/simpleActionQuery.xml | 45 + .../utils/xml/simpleListResources.xml | 57 + .../python/vt_manager/controller/__init__.py | 0 .../controller/actions/ActionController.py | 97 + .../vt_manager/controller/actions/__init__.py | 0 .../controller/dispatchers/__init__.py | 0 .../dispatchers/forms/NetworkInterfaceForm.py | 28 + .../dispatchers/forms/ServerForm.py | 32 + .../controller/dispatchers/forms/__init__.py | 0 .../dispatchers/ui/GUIdispatcher.py | 559 +++ .../dispatchers/ui/PolicyDispatcher.py | 298 ++ .../controller/dispatchers/ui/__init__.py | 0 .../dispatchers/xmlrpc/DispatcherLauncher.py | 56 + .../xmlrpc/InformationDispatcher.py | 162 + .../xmlrpc/MonitoringResponseDispatcher.py | 49 + .../xmlrpc/ProvisioningDispatcher.py | 104 + .../xmlrpc/ProvisioningResponseDispatcher.py | 265 + .../controller/dispatchers/xmlrpc/__init__.py | 0 .../vt_manager/controller/drivers/VTDriver.py | 207 + .../controller/drivers/XenDriver.py | 109 + .../vt_manager/controller/drivers/__init__.py | 0 .../monitoring/AgentMonitoringThread.py | 61 + .../monitoring/BackgroundMonitor.py | 49 + .../monitoring/SessionMonitoringThread.py | 36 + .../controller/monitoring/VMMonitor.py | 64 + .../controller/monitoring/__init__.py | 0 .../background_expiration_monitoring.py | 18 + .../monitoring/backgroundexpiration.py | 66 + .../monitoring/backgroundreservation.py | 36 + .../networking/EthernetController.py | 36 + .../controller/networking/Ip4Controller.py | 36 + .../controller/networking/__init__.py | 0 .../controller/policies/ControllerMappings.py | 76 + .../controller/policies/RuleTableManager.py | 335 ++ .../controller/policies/__init__.py | 0 .../controller/policies/utils/PELogConf.py | 2 + .../controller/policies/utils/PolicyLogger.py | 49 + .../controller/policies/utils/__init__.py | 0 .../controller/policies/utils/log/.gitignore | 1 + .../controller/policies/utils/log/__init__.py | 0 .../vt_manager/controller/users/__init__.py | 0 .../vt_manager/controller/users/forms.py | 12 + .../controller/users/urlHandlers.py | 84 + vt_manager/src/python/vt_manager/manage.py | 15 + .../src/python/vt_manager/models/Action.py | 159 + .../src/python/vt_manager/models/Ip4Range.py | 329 ++ .../src/python/vt_manager/models/Ip4Slot.py | 97 + .../src/python/vt_manager/models/MacRange.py | 306 ++ .../src/python/vt_manager/models/MacSlot.py | 96 + .../vt_manager/models/NetworkInterface.py | 201 + .../src/python/vt_manager/models/VTServer.py | 383 ++ .../vt_manager/models/VirtualMachine.py | 216 + .../vt_manager/models/VirtualMachineKeys.py | 56 + .../src/python/vt_manager/models/XenServer.py | 112 + .../src/python/vt_manager/models/XenVM.py | 141 + .../src/python/vt_manager/models/__init__.py | 30 + .../vt_manager/models/expiring_components.py | 19 + .../src/python/vt_manager/models/faults.py | 52 + .../python/vt_manager/models/reservation.py | 47 + .../python/vt_manager/models/resourcesHash.py | 13 + .../src/python/vt_manager/models/tests/a.py | 3 + .../src/python/vt_manager/models/tests/b.py | 4 + .../python/vt_manager/models/utils/Choices.py | 74 + .../vt_manager/models/utils/__init__.py | 1 + .../src/python/vt_manager/mySettings-example | 119 + .../python/vt_manager/settings/__init__.py | 0 .../vt_manager/settings/settingsLoader.py | 32 + .../vt_manager/settings/staticSettings.py | 229 + vt_manager/src/python/vt_manager/templatetags | 1 + .../src/python/vt_manager/tests/__init__.py | 0 .../python/vt_manager/tests/createServer.py | 16 + .../vt_manager/tests/dataModel/createVM.py | 43 + .../vt_manager/tests/dataModel/prova.py | 99 + .../python/vt_manager/tests/deleteAllVMs.py | 25 + .../src/python/vt_manager/tests/deleteVM.py | 20 + .../vt_manager/tests/interfaces/testcreate.py | 13 + .../src/python/vt_manager/tests/prova.py | 14 + .../python/vt_manager/tests/provisioning/1 | 40 + .../tests/provisioning/createVM.xml | 40 + .../tests/provisioning/failresponse.xml | 11 + .../provisioning/list_resources_nodes_test.py | 39 + .../vt_manager/tests/provisioning/prueba.py | 42 + .../tests/provisioning/pruebaCreate.xml | 47 + .../vt_manager/tests/provisioning/temp.py | 25 + .../src/python/vt_manager/tests/prueba.py | 21 + .../python/vt_manager/tests/sendStartQuery.py | 33 + .../src/python/vt_manager/tests/synctest.py | 15 + .../src/python/vt_manager/tests/test.py | 19 + .../vt_manager/tests/testRandomImport.sh | 13 + .../src/python/vt_manager/tests/testReload.py | 12 + .../src/python/vt_manager/tests/testasync.py | 9 + .../src/python/vt_manager/tests/testcreate.py | 13 + .../python/vt_manager/tests/testcreate2.py | 12 + .../python/vt_manager/tests/testcreatesync.py | 9 + .../src/python/vt_manager/tests/testdelete.py | 12 + .../src/python/vt_manager/tests/testifaces.py | 12 + .../src/python/vt_manager/tests/testlocker.py | 20 + .../src/python/vt_manager/tests/testmac.py | 13 + .../src/python/vt_manager/tests/testreboot.py | 12 + .../src/python/vt_manager/tests/testslot.py | 6 + .../src/python/vt_manager/tests/teststart2.py | 12 + .../src/python/vt_manager/tests/teststop.py | 13 + .../python/vt_manager/tests/xmlrpcsynctest.py | 17 + .../src/python/vt_manager/tests/xmltest.xml | 49 + vt_manager/src/python/vt_manager/urls.py | 119 + .../python/vt_manager/utils/EthernetUtils.py | 243 + .../src/python/vt_manager/utils/HttpUtils.py | 67 + .../src/python/vt_manager/utils/IP4Utils.py | 290 ++ .../src/python/vt_manager/utils/MutexStore.py | 64 + .../python/vt_manager/utils/ServiceProcess.py | 26 + .../python/vt_manager/utils/ServiceThread.py | 22 + .../src/python/vt_manager/utils/SyncThread.py | 29 + .../python/vt_manager/utils/ThemeManager.py | 76 + .../src/python/vt_manager/utils/UrlUtils.py | 14 + .../src/python/vt_manager/utils/__init__.py | 0 .../utils/contextualization/__init__.py | 0 .../contextualize_sudoers.txt | 25 + .../contextualization/vm_contextualize.py | 52 + .../src/python/vt_manager/views/__init__.py | 0 .../views/static/media/FELIX/css/ocf.css | 690 +++ .../media/FELIX/images/logo_vm_manager.png | Bin 0 -> 4178 bytes .../media/FIBRE/images/logo_vm_manager.png | Bin 0 -> 19842 bytes .../static/media/default/css/ocf-iframe.css | 974 ++++ .../views/static/media/default/css/ocf.css | 690 +++ .../static/media/default/css/tooltip.css | 41 + .../static/media/default/fancybox/blank.gif | Bin 0 -> 43 bytes .../media/default/fancybox/fancy_close.png | Bin 0 -> 1517 bytes .../media/default/fancybox/fancy_loading.png | Bin 0 -> 10195 bytes .../media/default/fancybox/fancy_nav_left.png | Bin 0 -> 1446 bytes .../default/fancybox/fancy_nav_right.png | Bin 0 -> 1454 bytes .../media/default/fancybox/fancy_shadow_e.png | Bin 0 -> 107 bytes .../media/default/fancybox/fancy_shadow_n.png | Bin 0 -> 106 bytes .../default/fancybox/fancy_shadow_ne.png | Bin 0 -> 347 bytes .../default/fancybox/fancy_shadow_nw.png | Bin 0 -> 324 bytes .../media/default/fancybox/fancy_shadow_s.png | Bin 0 -> 111 bytes .../default/fancybox/fancy_shadow_se.png | Bin 0 -> 352 bytes .../default/fancybox/fancy_shadow_sw.png | Bin 0 -> 340 bytes .../media/default/fancybox/fancy_shadow_w.png | Bin 0 -> 103 bytes .../default/fancybox/fancy_title_left.png | Bin 0 -> 503 bytes .../default/fancybox/fancy_title_main.png | Bin 0 -> 96 bytes .../default/fancybox/fancy_title_over.png | Bin 0 -> 70 bytes .../default/fancybox/fancy_title_right.png | Bin 0 -> 506 bytes .../media/default/fancybox/fancybox-x.png | Bin 0 -> 203 bytes .../media/default/fancybox/fancybox-y.png | Bin 0 -> 176 bytes .../media/default/fancybox/fancybox.png | Bin 0 -> 15287 bytes .../fancybox/jquery.easing-1.3.pack.js | 72 + .../fancybox/jquery.fancybox-1.3.4.css | 359 ++ .../default/fancybox/jquery.fancybox-1.3.4.js | 1156 +++++ .../fancybox/jquery.fancybox-1.3.4.pack.js | 46 + .../fancybox/jquery.mousewheel-3.0.4.pack.js | 14 + .../static/media/default/images/account.png | Bin 0 -> 3443 bytes .../static/media/default/images/active.png | Bin 0 -> 2351 bytes .../static/media/default/images/active_t.png | Bin 0 -> 2318 bytes .../media/default/images/add_rule_dark.png | Bin 0 -> 3352 bytes .../media/default/images/add_rule_light.png | Bin 0 -> 3321 bytes .../default/images/admin_abandon_fs_dark.png | Bin 0 -> 4916 bytes .../default/images/admin_abandon_fs_light.png | Bin 0 -> 4972 bytes .../media/default/images/admin_fs_dark.png | Bin 0 -> 5327 bytes .../media/default/images/admin_fs_light.png | Bin 0 -> 5331 bytes .../media/default/images/admin_fses_dark.png | Bin 0 -> 4720 bytes .../media/default/images/admin_fses_light.png | Bin 0 -> 4667 bytes .../media/default/images/admin_req_dark.png | Bin 0 -> 4747 bytes .../default/images/admin_req_fs_dark.png | Bin 0 -> 4816 bytes .../default/images/admin_req_fs_light.png | Bin 0 -> 4807 bytes .../media/default/images/admin_req_light.png | Bin 0 -> 4760 bytes .../media/default/images/aggregate-tiny.png | Bin 0 -> 2527 bytes .../static/media/default/images/arrow.gif | Bin 0 -> 47 bytes .../static/media/default/images/arrow2.gif | Bin 0 -> 77 bytes .../default/images/auto_approve_dark.png | Bin 0 -> 4632 bytes .../default/images/auto_approve_light.png | Bin 0 -> 4571 bytes .../static/media/default/images/back_dark.png | Bin 0 -> 2765 bytes .../media/default/images/back_light.png | Bin 0 -> 2763 bytes .../static/media/default/images/base_dark.png | Bin 0 -> 593 bytes .../media/default/images/base_light.png | Bin 0 -> 598 bytes .../static/media/default/images/button.pxm | Bin 0 -> 6747 bytes .../media/default/images/contact_exp_dark.png | Bin 0 -> 3494 bytes .../default/images/contact_exp_light.png | Bin 0 -> 3526 bytes .../static/media/default/images/dashboard.png | Bin 0 -> 3833 bytes .../media/default/images/dashboard_dark.png | Bin 0 -> 3742 bytes .../media/default/images/dashboard_light.png | Bin 0 -> 3678 bytes .../default/images/edit_profile_dark.png | Bin 0 -> 3481 bytes .../default/images/edit_profile_light.png | Bin 0 -> 3425 bytes .../media/default/images/experiments_dark.png | Bin 0 -> 4102 bytes .../default/images/experiments_light.png | Bin 0 -> 4083 bytes .../static/media/default/images/favicon.ico | Bin 0 -> 4286 bytes .../media/default/images/fs_req_dark.png | Bin 0 -> 5585 bytes .../media/default/images/fs_req_light.png | Bin 0 -> 5578 bytes .../static/media/default/images/genilogo.png | Bin 0 -> 8919 bytes .../media/default/images/give_up_fs_dark.png | Bin 0 -> 4828 bytes .../media/default/images/give_up_fs_light.png | Bin 0 -> 4816 bytes .../static/media/default/images/help.png | Bin 0 -> 3091 bytes .../static/media/default/images/host-tiny.png | Bin 0 -> 2072 bytes .../static/media/default/images/inactive.png | Bin 0 -> 2099 bytes .../media/default/images/inactive_t.png | Bin 0 -> 2107 bytes .../static/media/default/images/loading.gif | Bin 0 -> 1849 bytes .../media/default/images/logo_expedient.png | Bin 0 -> 23342 bytes .../media/default/images/logo_vm_manager.png | Bin 0 -> 24912 bytes .../static/media/default/images/logout.png | Bin 0 -> 3319 bytes .../media/default/images/logout_dark.png | Bin 0 -> 3414 bytes .../media/default/images/logout_light.png | Bin 0 -> 3414 bytes .../media/default/images/manage_fs_dark.png | Bin 0 -> 5136 bytes .../media/default/images/manage_fs_light.png | Bin 0 -> 5164 bytes .../media/default/images/manage_site_dark.png | Bin 0 -> 5163 bytes .../default/images/manage_site_light.png | Bin 0 -> 5188 bytes .../media/default/images/ofelialogo.png | Bin 0 -> 14621 bytes .../media/default/images/ofelialogo2.png | Bin 0 -> 17162 bytes .../media/default/images/optin_dark.png | Bin 0 -> 2843 bytes .../media/default/images/optin_light.png | Bin 0 -> 2843 bytes .../media/default/images/optout_dark.png | Bin 0 -> 3409 bytes .../media/default/images/optout_light.png | Bin 0 -> 3382 bytes .../static/media/default/images/plus.gif | Bin 0 -> 88 bytes .../media/default/images/profile_dark.png | Bin 0 -> 2973 bytes .../media/default/images/profile_light.png | Bin 0 -> 2962 bytes .../media/default/images/progressbar.gif | Bin 0 -> 120 bytes .../media/default/images/progressbg_black.gif | Bin 0 -> 1626 bytes .../media/default/images/progressbg_green.gif | Bin 0 -> 1308 bytes .../default/images/progressbg_orange.gif | Bin 0 -> 1308 bytes .../media/default/images/progressbg_red.gif | Bin 0 -> 1308 bytes .../default/images/progressbg_yellow.gif | Bin 0 -> 1308 bytes .../default/images/promote_to_admin_dark.png | Bin 0 -> 4145 bytes .../default/images/promote_to_admin_light.png | Bin 0 -> 4142 bytes .../default/images/question_mark_15x15.png | Bin 0 -> 873 bytes .../media/default/images/remove_rule_dark.png | Bin 0 -> 3824 bytes .../default/images/remove_rule_light.png | Bin 0 -> 3776 bytes .../media/default/images/request_fs_dark.png | Bin 0 -> 5080 bytes .../media/default/images/request_fs_light.png | Bin 0 -> 5044 bytes .../default/images/resign_admin_dark.png | Bin 0 -> 4803 bytes .../default/images/resign_admin_light.png | Bin 0 -> 4799 bytes .../media/default/images/right_arrow.gif | Bin 0 -> 860 bytes .../media/default/images/set_ch_dark.png | Bin 0 -> 4890 bytes .../media/default/images/set_ch_light.png | Bin 0 -> 4936 bytes .../media/default/images/set_fv_dark.png | Bin 0 -> 4072 bytes .../media/default/images/set_fv_light.png | Bin 0 -> 4029 bytes .../default/images/set_priority_dark.png | Bin 0 -> 3843 bytes .../default/images/set_priority_light.png | Bin 0 -> 3826 bytes .../default/images/set_rule_priority_dark.png | Bin 0 -> 4587 bytes .../images/set_rule_priority_light.png | Bin 0 -> 4626 bytes .../media/default/images/slice-tiny.png | Bin 0 -> 2477 bytes .../static/media/default/images/slice.png | Bin 0 -> 3425 bytes .../media/default/images/step0_dark.png | Bin 0 -> 54007 bytes .../media/default/images/step0_light.png | Bin 0 -> 28572 bytes .../media/default/images/step1_dark.png | Bin 0 -> 65415 bytes .../default/images/step2_manage_dark.png | Bin 0 -> 8540 bytes .../default/images/step2_manage_light.png | Bin 0 -> 9121 bytes .../media/default/images/step2_optin_dark.png | Bin 0 -> 6517 bytes .../default/images/step2_optin_light.png | Bin 0 -> 7468 bytes .../default/images/step2_optout_dark.png | Bin 0 -> 7410 bytes .../default/images/step2_optout_light.png | Bin 0 -> 8157 bytes .../media/default/images/switch-5406zl.png | Bin 0 -> 22661 bytes .../media/default/images/switch-cat6500.png | Bin 0 -> 93452 bytes .../media/default/images/switch-juniper.png | Bin 0 -> 78003 bytes .../default/images/switch-nec-ip8800.png | Bin 0 -> 40585 bytes .../media/default/images/switch-netfpga.png | Bin 0 -> 78800 bytes .../media/default/images/switch-nf2.png | Bin 0 -> 49952 bytes .../media/default/images/switch-tiny.png | Bin 0 -> 1967 bytes .../static/media/default/images/switch.png | Bin 0 -> 7167 bytes .../media/default/images/user_fses_dark.png | Bin 0 -> 4736 bytes .../media/default/images/user_fses_light.png | Bin 0 -> 4756 bytes .../media/default/images/user_req_dark.png | Bin 0 -> 4381 bytes .../media/default/images/user_req_light.png | Bin 0 -> 4350 bytes .../media/default/images/users-tiny.png | Bin 0 -> 2518 bytes .../media/default/images/view_exp_dark.png | Bin 0 -> 2854 bytes .../media/default/images/view_exp_light.png | Bin 0 -> 2868 bytes .../static/media/default/js/dragndrop.js | 264 + .../media/default/js/formtable.tooltip.js | 44 + .../media/default/js/jquery-1.6.2.min.js | 18 + .../media/default/js/jquery.formset.min.js | 10 + .../static/media/default/js/jquery.min.js | 167 + .../default/js/jquery.progressbar.min.js | 20 + .../default/js/jquery.progressbar.min2.js | 18 + .../media/default/js/jquery.tools.min.js | 11 + .../static/media/default/js/redips-drag.js | 4287 ++++++++++++++++ .../static/media/default/js/tooltip.funcs.js | 108 + .../views/static/media/default/js/utils.js | 106 + .../static/media/default/js/validation.js | 145 + .../views/templates/FELIX/base.html | 45 + .../views/templates/FELIX/base_admin.html | 104 + .../views/templates/FELIX/base_user.html | 109 + .../views/templates/FELIX/footer.html | 6 + .../views/templates/FELIX/users/base.html | 43 + .../templates/FELIX/users/base_admin.html | 112 + .../views/templates/FIBRE/base.html | 45 + .../views/templates/FIBRE/base_admin.html | 106 + .../views/templates/FIBRE/base_user.html | 109 + .../views/templates/FIBRE/fancybase.html | 20 + .../views/templates/FIBRE/index.html | 12 + .../templates/FIBRE/registration/login.html | 26 + .../FIBRE/registration/registration_form.html | 10 + .../views/templates/FIBRE/users/base.html | 43 + .../templates/FIBRE/users/base_admin.html | 112 + .../templates/FIBRE/users/base_user.html | 110 + .../templates/FIBRE/users/fancybase.html | 20 + .../views/templates/FIBRE/users/index.html | 12 + .../FIBRE/users/registration/login.html | 26 + .../users/registration/registration_form.html | 10 + .../views/templates/default/base.html | 45 + .../views/templates/default/base_admin.html | 104 + .../views/templates/default/base_user.html | 109 + .../templates/default/dashboard_admin.html | 64 + .../views/templates/default/fancybase.html | 20 + .../views/templates/default/footer.html | 6 + .../views/templates/default/index.html | 12 + .../templates/default/networking/base.html | 1 + .../default/networking/ethernet/index.html | 54 + .../networking/ethernet/rangeCrud.html | 41 + .../networking/ethernet/rangeDetail.html | 113 + .../templates/default/networking/index.html | 154 + .../default/networking/ip4/index.html | 53 + .../default/networking/ip4/rangeCrud.html | 41 + .../default/networking/ip4/rangeDetail.html | 114 + .../policyEngine/condition_create.html | 332 ++ .../default/policyEngine/edit_ruleset.html | 39 + .../default/policyEngine/policy.html | 37 + .../policyEngine/policy_RuleTableCreate.html | 82 + .../default/policyEngine/policy_create.html | 442 ++ .../default/policyEngine/policy_edit.html | 100 + .../default/policyEngine/table_view.html | 109 + .../default/registration/activate.html | 15 + .../default/registration/activation_email.txt | 6 + .../registration/activation_email_subject.txt | 1 + .../templates/default/registration/login.html | 26 + .../default/registration/logout.html | 9 + .../registration/registration_complete.html | 10 + .../registration/registration_form.html | 10 + .../default/servers/add_server_admin.html | 27 + .../default/servers/admin_servers.html | 50 + .../default/servers/delete_server.html | 31 + .../default/servers/network_iface.html | 31 + .../default/servers/server_vm_details.html | 60 + .../default/servers/servers_add_server.html | 33 + .../default/servers/servers_base.html | 4 + .../default/servers/servers_crud.html | 227 + .../default/servers/servers_dataIfaces.html | 62 + .../default/servers/servers_listVMs.html | 47 + .../default/servers/servers_list_vms.html | 63 + .../default/servers/servers_net.html | 33 + .../servers_subscribeEthernetRanges.html | 49 + .../servers/servers_subscribeIp4Ranges.html | 47 + .../views/templates/default/users/base.html | 43 + .../templates/default/users/base_admin.html | 112 + .../templates/default/users/base_user.html | 110 + .../default/users/change_profile_admin.html | 22 + .../default/users/change_profile_user.html | 19 + .../default/users/dashboard_admin.html | 64 + .../templates/default/users/fancybase.html | 20 + .../views/templates/default/users/footer.html | 5 + .../views/templates/default/users/index.html | 12 + .../default/users/networking/base.html | 1 + .../users/networking/ethernet/index.html | 54 + .../users/networking/ethernet/rangeCrud.html | 36 + .../networking/ethernet/rangeDetail.html | 113 + .../default/users/networking/index.html | 154 + .../default/users/networking/ip4/index.html | 53 + .../users/networking/ip4/rangeCrud.html | 36 + .../users/networking/ip4/rangeDetail.html | 114 + .../users/policyEngine/condition_create.html | 324 ++ .../users/policyEngine/edit_ruleset.html | 39 + .../default/users/policyEngine/policy.html | 37 + .../policyEngine/policy_RuleTableCreate.html | 82 + .../users/policyEngine/policy_create.html | 438 ++ .../users/policyEngine/table_view.html | 109 + .../default/users/registration/activate.html | 15 + .../users/registration/activation_email.txt | 6 + .../registration/activation_email_subject.txt | 1 + .../default/users/registration/login.html | 26 + .../default/users/registration/logout.html | 9 + .../registration/registration_complete.html | 10 + .../users/registration/registration_form.html | 10 + .../users/servers/add_server_admin.html | 27 + .../default/users/servers/admin_servers.html | 50 + .../default/users/servers/delete_server.html | 31 + .../default/users/servers/network_iface.html | 31 + .../users/servers/server_vm_details.html | 60 + .../users/servers/servers_add_server.html | 33 + .../default/users/servers/servers_base.html | 4 + .../default/users/servers/servers_crud.html | 223 + .../users/servers/servers_dataIfaces.html | 72 + .../users/servers/servers_listVMs.html | 47 + .../users/servers/servers_list_vms.html | 59 + .../default/users/servers/servers_net.html | 33 + .../servers_subscribeEthernetRanges.html | 49 + .../servers/servers_subscribeIp4Ranges.html | 47 + .../vt_manager/views/templates/not_admin.html | 21 + .../vt_manager/views/templatetags/__init__.py | 0 .../views/templatetags/accessDict.py | 7 + .../vt_manager/views/templatetags/url.py | 83 + vt_manager/src/wsgi/vt_manager/auth.wsgi | 51 + vt_manager/src/wsgi/vt_manager/django.wsgi | 18 + vt_manager/src/wsgi/vt_manager/mon.wsgi | 23 + vt_manager/version | 1 + 3010 files changed, 239608 insertions(+) create mode 100644 .gitignore create mode 100755 CHANGELOG create mode 100755 LICENSE create mode 100755 README.md create mode 100644 core/__init__.py create mode 100644 core/lib/__init__.py create mode 100644 core/lib/am/__init__.py create mode 100755 core/lib/am/ambase/__init__.py create mode 100644 core/lib/am/ambase/src/__init__.py create mode 100644 core/lib/am/ambase/src/abstract/__init__.py create mode 100644 core/lib/am/ambase/src/abstract/classes/__init__.py create mode 100644 core/lib/am/ambase/src/abstract/classes/credentialmanagerbase.py create mode 100644 core/lib/am/ambase/src/abstract/classes/delegatebase.py create mode 100644 core/lib/am/ambase/src/abstract/classes/handlerbase.py create mode 100644 core/lib/am/ambase/src/abstract/classes/resourcemanagerbase.py create mode 100644 core/lib/am/ambase/src/abstract/classes/rspecmanagerbase.py create mode 100644 core/lib/am/ambase/src/ambase/__init__.py create mode 100644 core/lib/am/ambase/src/ambase/exceptions.py create mode 100644 core/lib/am/ambase/src/geni/__init__.py create mode 100644 core/lib/am/ambase/src/geni/exceptions/__init__.py create mode 100644 core/lib/am/ambase/src/geni/exceptions/manager.py create mode 100644 core/lib/am/ambase/src/geni/v3/__init__.py create mode 100644 core/lib/am/ambase/src/geni/v3/delegate/__init__.py create mode 100644 core/lib/am/ambase/src/geni/v3/delegate/delegate.py create mode 100644 core/lib/am/ambase/src/geni/v3/handler/__init__.py create mode 100644 core/lib/am/ambase/src/geni/v3/handler/handler.py create mode 100644 core/lib/am/credentials/__init__.py create mode 100644 core/lib/am/credentials/src/DEPENDENCIES create mode 100644 core/lib/am/credentials/src/__init__.py create mode 100644 core/lib/am/credentials/src/manager/__init__.py create mode 100644 core/lib/am/credentials/src/manager/gcfmanager.py create mode 100644 core/lib/am/credentials/src/manager/manager.py create mode 100644 core/lib/am/credentials/src/trust/__init__.py create mode 100644 core/lib/am/credentials/src/trust/abaccredential.py create mode 100644 core/lib/am/credentials/src/trust/auth.py create mode 100644 core/lib/am/credentials/src/trust/certificate.py create mode 100644 core/lib/am/credentials/src/trust/credential.py create mode 100644 core/lib/am/credentials/src/trust/credential_legacy.py create mode 100644 core/lib/am/credentials/src/trust/gid.py create mode 100644 core/lib/am/credentials/src/trust/hierarchy.py create mode 100644 core/lib/am/credentials/src/trust/rights.py create mode 100644 core/lib/am/credentials/src/trust/sfaticket.py create mode 100644 core/lib/am/credentials/src/trust/trustedroots.py create mode 100644 core/lib/am/credentials/src/trustgcf/__init__.py create mode 100644 core/lib/am/credentials/src/trustgcf/abac_credential.py create mode 100644 core/lib/am/credentials/src/trustgcf/cert_util.py create mode 100644 core/lib/am/credentials/src/trustgcf/certificate.py create mode 100644 core/lib/am/credentials/src/trustgcf/cred_util.py create mode 100644 core/lib/am/credentials/src/trustgcf/credential.py create mode 100644 core/lib/am/credentials/src/trustgcf/credential_factory.py create mode 100644 core/lib/am/credentials/src/trustgcf/credential_legacy.py create mode 100644 core/lib/am/credentials/src/trustgcf/gid.py create mode 100644 core/lib/am/credentials/src/trustgcf/rights.py create mode 100644 core/lib/am/credentials/src/trustgcf/speaksfor_util.py create mode 100755 core/lib/am/ext/my_roots/alice-cert.pem create mode 100644 core/lib/am/ext/my_roots/alice-key.pem create mode 100644 core/lib/am/ext/my_roots/topdomain.gid create mode 100644 core/lib/am/ext/schemas/credential.xsd create mode 100755 core/lib/am/ext/trusted_roots/alice-cert.pem create mode 100644 core/lib/am/ext/trusted_roots/gpo.gid create mode 100644 core/lib/am/ext/trusted_roots/topdomain.gid create mode 100644 core/lib/am/geniutils/__init__.py create mode 100644 core/lib/am/geniutils/src/__init__.py create mode 100644 core/lib/am/geniutils/src/faults/__init__.py create mode 100644 core/lib/am/geniutils/src/faults/faults.py create mode 100644 core/lib/am/geniutils/src/faults/genicode.py create mode 100644 core/lib/am/geniutils/src/time/__init__.py create mode 100644 core/lib/am/geniutils/src/time/timewrapper.py create mode 100644 core/lib/am/geniutils/src/urn/__init__.py create mode 100644 core/lib/am/geniutils/src/urn/utils.py create mode 100644 core/lib/am/geniutils/src/xrn/__init__.py create mode 100644 core/lib/am/geniutils/src/xrn/xrn.py create mode 100644 core/lib/am/rspecs/__init__.py create mode 100644 core/lib/am/rspecs/src/__init__.py create mode 100644 core/lib/am/rspecs/src/geni/__init__.py create mode 100644 core/lib/am/rspecs/src/geni/v3/__init__.py create mode 100644 core/lib/am/rspecs/src/geni/v3/container/__init__.py create mode 100644 core/lib/am/rspecs/src/geni/v3/container/aggregate.py create mode 100644 core/lib/am/rspecs/src/geni/v3/container/link.py create mode 100644 core/lib/am/rspecs/src/geni/v3/container/resource.py create mode 100644 core/lib/am/rspecs/src/geni/v3/container/slice.py create mode 100644 core/lib/am/rspecs/src/geni/v3/container/sliver.py create mode 100644 core/lib/am/rspecs/src/geni/v3/craftermanager.py create mode 100644 core/lib/am/rspecs/src/geni/v3/manager.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/__init__.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/container/__init__.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/container/controller.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/container/dpid.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/container/flowspace.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/container/group.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/container/link.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/container/match.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/container/port.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/foamlibcrafter.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/foamlibparser.py create mode 100644 core/lib/am/rspecs/src/geni/v3/openflow/manager.py create mode 100644 core/lib/am/rspecs/src/geni/v3/parsermanager.py create mode 100644 core/lib/am/settings/__init__.py create mode 100644 core/lib/am/settings/src/__init__.py create mode 100644 core/lib/am/settings/src/settings.py create mode 100755 deploy/common/certificates/ca_cert.conf create mode 100755 deploy/common/certificates/certificates.sh create mode 100755 deploy/common/certificates/server_cert.conf create mode 100755 deploy/dependencies/apache.sh create mode 100755 deploy/dependencies/flowvisor.sh create mode 100755 deploy/dependencies/mysqlserver.sh create mode 100755 deploy/gui/checklist.sh create mode 100755 deploy/gui/end.sh create mode 100755 deploy/gui/info.sh create mode 100755 deploy/gui/splash.sh create mode 100755 deploy/gui/start_step.sh create mode 100755 deploy/gui/yesno.sh create mode 100644 deploy/install.py create mode 100644 deploy/migrate.py create mode 100644 deploy/remove.py create mode 100644 deploy/upgrade.py create mode 100644 deploy/utils/__init__.py create mode 100755 deploy/utils/migrate.sh create mode 100755 deploy/utils/scripts/flowvisor_cron.sh create mode 100644 deploy/utils/utils.py create mode 100755 deploy/utils/utils.sh create mode 100644 expedient/.gitignore create mode 100644 expedient/bin/common/commands create mode 100644 expedient/bin/common/init create mode 100644 expedient/bin/common/modules create mode 100644 expedient/bin/common/repository create mode 100644 expedient/bin/common/utils create mode 100644 expedient/bin/common/versioning create mode 100644 expedient/bin/log/.gitignore create mode 100755 expedient/bin/ofver create mode 100755 expedient/bin/repo create mode 100644 expedient/bin/rescue/.gitignore create mode 100755 expedient/bin/settings create mode 100644 expedient/bin/versions/0.13/upgrade/0.12/backup create mode 100644 expedient/bin/versions/0.13/upgrade/0.12/pre-backup-upgrade-hook create mode 100644 expedient/bin/versions/0.14.2/upgrade/default/pre-upgrade-hook create mode 100644 expedient/bin/versions/0.2/upgrade/default/post-upgrade-hook create mode 100644 expedient/bin/versions/0.2/upgrade/default/tools/permissionsRefactor.py create mode 120000 expedient/bin/versions/0.21.1 create mode 120000 expedient/bin/versions/0.21/upgrade/0.14.2 create mode 120000 expedient/bin/versions/0.2RC1 create mode 100644 expedient/bin/versions/0.3/upgrade/default/post-upgrade-hook create mode 100644 expedient/bin/versions/0.3/upgrade/default/pre-upgrade-hook create mode 120000 expedient/bin/versions/0.3RC1 create mode 120000 expedient/bin/versions/0.4.1 create mode 120000 expedient/bin/versions/0.4.2 create mode 120000 expedient/bin/versions/0.4.3 create mode 100644 expedient/bin/versions/0.4/upgrade/default/pre-upgrade-hook create mode 100644 expedient/bin/versions/0.5/upgrade/default/pre-upgrade-hook create mode 100644 expedient/bin/versions/0.6.1/upgrade/0.5/post-upgrade-hook create mode 100644 expedient/bin/versions/0.6.1/upgrade/0.5/pre-upgrade-hook create mode 120000 expedient/bin/versions/0.6.1/upgrade/0.6 create mode 100644 expedient/bin/versions/0.6/upgrade/default/pre-upgrade-hook create mode 100644 expedient/bin/versions/0.7/upgrade/default/pre-upgrade-hook create mode 120000 expedient/bin/versions/0.8.1 create mode 120000 expedient/bin/versions/0.8.2 create mode 120000 expedient/bin/versions/0.8.3/upgrade/default/lib/set_environment_variables create mode 100644 expedient/bin/versions/0.8.3/upgrade/default/pre-upgrade-hook create mode 100644 expedient/bin/versions/0.8/upgrade/default/pre-upgrade-hook create mode 100644 expedient/bin/versions/default/install/backup create mode 100644 expedient/bin/versions/default/install/install create mode 100644 expedient/bin/versions/default/install/lib/dependencies create mode 100644 expedient/bin/versions/default/install/lib/django-db create mode 100644 expedient/bin/versions/default/install/lib/django-settings create mode 100644 expedient/bin/versions/default/install/lib/pypelib create mode 100755 expedient/bin/versions/default/install/lib/set_environment_variables create mode 100644 expedient/bin/versions/default/install/lib/ssl create mode 100644 expedient/bin/versions/default/install/post-install-hook create mode 100644 expedient/bin/versions/default/install/pre-install-hook create mode 100644 expedient/bin/versions/default/install/repo create mode 100644 expedient/bin/versions/default/install/rollback create mode 100644 expedient/bin/versions/default/upgrade/default/backup create mode 100644 expedient/bin/versions/default/upgrade/default/dependencies create mode 120000 expedient/bin/versions/default/upgrade/default/lib/set_environment_variables create mode 100644 expedient/bin/versions/default/upgrade/default/post-upgrade-hook create mode 100644 expedient/bin/versions/default/upgrade/default/pre-upgrade-hook create mode 100644 expedient/bin/versions/default/upgrade/default/rollback create mode 100644 expedient/bin/versions/default/upgrade/default/upgrade create mode 100755 expedient/bin/versions/default/upgrade/tools/cleanCache.py create mode 100644 expedient/bin/versions/default/upgrade/tools/prova create mode 100644 expedient/bin/versions/default/upgrade/tools/prova.cfg create mode 100755 expedient/bin/versions/default/upgrade/tools/sqlDump.py create mode 100755 expedient/bin/versions/default/upgrade/tools/sqlRestore.py create mode 100644 expedient/bin/versions/version-checks create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/__init__.py create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/__init__.py~ofelia.stable create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/XmlRpcAPI.py create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/XmlRpcServer.py create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/__init__.py create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/controller/ResourceController.py create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/controller/__init__.py create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/resources.xml create mode 100755 expedient/doc/plugins/samples/aggregate/sr_manager/src/security/certificates/sr_am.crt create mode 100755 expedient/doc/plugins/samples/aggregate/sr_manager/src/security/certificates/sr_am.key create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/server.py create mode 100755 expedient/doc/plugins/samples/aggregate/sr_manager/src/settings.py create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/tests/parse_resources.py create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/utils/Logger.py create mode 100644 expedient/doc/plugins/samples/aggregate/sr_manager/src/utils/__init__.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/__init__.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/controller/GUIdispatcher.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/controller/__init__.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/controller/aggregate.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/controller/resource.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/forms/SampleResource.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/forms/SampleResourceAggregate.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/forms/__init__.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/forms/xmlrpcServerProxy.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/models/SampleResource.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/models/SampleResourceAggregate.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/models/__init__.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/models/xmlrpcServerProxy.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/settings.conf create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/static/media/default/css/style.css create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/static/media/default/img/sensor-tiny.png create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/urls.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/utils/__init__.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/utils/validators.py create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_add_resources.html create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_aggregate_crud.html create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_list_resources.html create mode 100644 expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_resource_crud.html create mode 100644 expedient/src/config/expedient/clearinghouse/apache/vhost-clearinghouse.conf create mode 100644 expedient/src/config/expedient/common/apache/vhost-macros.conf create mode 100644 expedient/src/doc/expedient/Makefile create mode 100644 expedient/src/doc/expedient/source/admin/index.rst create mode 100755 expedient/src/doc/expedient/source/admin/install.rst create mode 100644 expedient/src/doc/expedient/source/admin/openflow.rst create mode 100644 expedient/src/doc/expedient/source/conf.py create mode 100644 expedient/src/doc/expedient/source/developer/index.rst create mode 100644 expedient/src/doc/expedient/source/developer/slice-aggregate-resource-relationships.png create mode 100644 expedient/src/doc/expedient/source/developer/sshaggregate/__init__.py create mode 100644 expedient/src/doc/expedient/source/developer/sshaggregate/models.py create mode 100644 expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/aggregate_add_servers.html create mode 100644 expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/aggregate_crud.html create mode 100644 expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/sshaggregate_base.html create mode 100644 expedient/src/doc/expedient/source/developer/sshaggregate/tests.py create mode 100644 expedient/src/doc/expedient/source/developer/sshaggregate/urls.py create mode 100644 expedient/src/doc/expedient/source/developer/sshaggregate/views.py create mode 100644 expedient/src/doc/expedient/source/developer/tutorial.rst create mode 100644 expedient/src/doc/expedient/source/index.rst create mode 100644 expedient/src/doc/expedient/source/user/index.rst create mode 100644 expedient/src/doc/expedient/source/user/tutorial.rst create mode 100644 expedient/src/python/expedient/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/administration/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/administration/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/administration/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/admin.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/forms.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/permissions.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/tests/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/tests/forms.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/tests/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/tests/templates/aggregate_tests/empty.html create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/tests/templates/aggregate_tests/form.html create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/tests/tests.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/tests/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/tests/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/utils.py create mode 100644 expedient/src/python/expedient/clearinghouse/aggregate/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/bootstrap_local_settings.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/bootstrap_local_settings.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/clean_inconsistent_db_entries.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/create_default_root.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/create_dummy_oms.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/create_secret_key.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/install_cert_makefile.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/load_openflow_data.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/setup_expedient.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/setup_media.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/standardize_flowvisor_slices.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/management/commands/test_expedient.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/commands/utils.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/admins.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/cbas.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/database.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/django.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/email.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/expedient.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/gcf.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/ldapSettings.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/logging.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/messaging.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/openflow.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/openflowtests.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/plugin.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/required.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/site.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/tests.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/utils.py create mode 100644 expedient/src/python/expedient/clearinghouse/defaultsettings/xmlrpc.py create mode 100644 expedient/src/python/expedient/clearinghouse/fapi/.gitignore create mode 100755 expedient/src/python/expedient/clearinghouse/fapi/LICENSE create mode 100644 expedient/src/python/expedient/clearinghouse/fapi/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/fapi/cbas.py create mode 100644 expedient/src/python/expedient/clearinghouse/fapi/communication_tools.py create mode 100644 expedient/src/python/expedient/clearinghouse/fapi/creds/expedient-cred.xml create mode 100644 expedient/src/python/expedient/clearinghouse/firstapp/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/firstapp/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/gcf-x509-trusted.crt/ch.crt create mode 100644 expedient/src/python/expedient/clearinghouse/geni/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/backends.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/clearinghouse.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/forms.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/gopenflow/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/gopenflow/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/gopenflow/tests/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/gopenflow/tests/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/gopenflow/tests/rpc.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/gopenflow/tests/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/gopenflow/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/gopenflow/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/management.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/middleware.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/permissions.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/planetlab/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/planetlab/exceptions.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/planetlab/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/planetlab/sfa-models.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/planetlab/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/rpc.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/tests.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/utils.py create mode 100644 expedient/src/python/expedient/clearinghouse/geni/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/help/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/help/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/help/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/ldap.ssl/ca.crt create mode 100644 expedient/src/python/expedient/clearinghouse/localsettings-example create mode 100755 expedient/src/python/expedient/clearinghouse/manage.py create mode 100644 expedient/src/python/expedient/clearinghouse/messagecenter/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/messagecenter/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/messagecenter/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/middleware/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/mit/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/monitoring/AggregateMonitoringThread.py create mode 100644 expedient/src/python/expedient/clearinghouse/monitoring/BackgroundMonitor.py create mode 100644 expedient/src/python/expedient/clearinghouse/monitoring/SessionMonitoringThread.py create mode 100644 expedient/src/python/expedient/clearinghouse/monitoring/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/permissionmgmt/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/permissionmgmt/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/permissionmgmt/tests.py create mode 100644 expedient/src/python/expedient/clearinghouse/permissionmgmt/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/permissionmgmt/utils.py create mode 100644 expedient/src/python/expedient/clearinghouse/permissionmgmt/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/project/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/project/admin.py create mode 100644 expedient/src/python/expedient/clearinghouse/project/forms.py create mode 100644 expedient/src/python/expedient/clearinghouse/project/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/project/permissions.py create mode 100644 expedient/src/python/expedient/clearinghouse/project/tests.py create mode 100644 expedient/src/python/expedient/clearinghouse/project/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/project/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/resources/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/resources/admin.py create mode 100644 expedient/src/python/expedient/clearinghouse/resources/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/roles/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/roles/forms.py create mode 100644 expedient/src/python/expedient/clearinghouse/roles/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/roles/tests.py create mode 100644 expedient/src/python/expedient/clearinghouse/roles/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/roles/utils.py create mode 100644 expedient/src/python/expedient/clearinghouse/roles/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/settings.py create mode 100644 expedient/src/python/expedient/clearinghouse/slice/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/slice/admin.py create mode 100644 expedient/src/python/expedient/clearinghouse/slice/forms.py create mode 100644 expedient/src/python/expedient/clearinghouse/slice/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/slice/tests.py create mode 100644 expedient/src/python/expedient/clearinghouse/slice/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/slice/utils.py create mode 100644 expedient/src/python/expedient/clearinghouse/slice/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/users/__init__.py create mode 100644 expedient/src/python/expedient/clearinghouse/users/admin.py create mode 100644 expedient/src/python/expedient/clearinghouse/users/forms.py create mode 100644 expedient/src/python/expedient/clearinghouse/users/models.py create mode 100644 expedient/src/python/expedient/clearinghouse/users/permissions.py create mode 100644 expedient/src/python/expedient/clearinghouse/users/urls.py create mode 100644 expedient/src/python/expedient/clearinghouse/users/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/utils.py create mode 100644 expedient/src/python/expedient/clearinghouse/views.py create mode 100644 expedient/src/python/expedient/clearinghouse/xmlrpc-ssl.crt/.test create mode 100644 expedient/src/python/expedient/clearinghouse/xmlrpc-ssl.crt/Makefile create mode 100644 expedient/src/python/expedient/common/__init__.py create mode 100644 expedient/src/python/expedient/common/backends/__init__.py create mode 100644 expedient/src/python/expedient/common/backends/remoteuser.py create mode 100644 expedient/src/python/expedient/common/breadcrumbs/__init__.py create mode 100644 expedient/src/python/expedient/common/breadcrumbs/templatetags/__init__.py create mode 100644 expedient/src/python/expedient/common/breadcrumbs/templatetags/breadcrumbs.py create mode 100644 expedient/src/python/expedient/common/clients/__init__.py create mode 100644 expedient/src/python/expedient/common/clients/geni.py create mode 100644 expedient/src/python/expedient/common/clients/xmlrpc.py create mode 100644 expedient/src/python/expedient/common/defaultsite/__init__.py create mode 100644 expedient/src/python/expedient/common/defaultsite/management.py create mode 100644 expedient/src/python/expedient/common/defaultsite/settings.py create mode 100644 expedient/src/python/expedient/common/extendable/__init__.py create mode 100644 expedient/src/python/expedient/common/extendable/inheritance.py create mode 100644 expedient/src/python/expedient/common/extendable/models.py create mode 100644 expedient/src/python/expedient/common/extendable/tests/__init__.py create mode 100644 expedient/src/python/expedient/common/extendable/tests/models.py create mode 100644 expedient/src/python/expedient/common/extendable/tests/tests.py create mode 100644 expedient/src/python/expedient/common/extendable/utils.py create mode 100644 expedient/src/python/expedient/common/extendable/views.py create mode 100644 expedient/src/python/expedient/common/federation/__init__.py create mode 100644 expedient/src/python/expedient/common/federation/geni/SecureXMLRPCServer.py create mode 100644 expedient/src/python/expedient/common/federation/geni/__init__.py create mode 100644 expedient/src/python/expedient/common/federation/geni/am.py create mode 100644 expedient/src/python/expedient/common/federation/geni/ca.py create mode 100644 expedient/src/python/expedient/common/federation/geni/ch.py create mode 100644 expedient/src/python/expedient/common/federation/geni/config.py create mode 100644 expedient/src/python/expedient/common/federation/geni/util/__init__.py create mode 100644 expedient/src/python/expedient/common/federation/geni/util/cert_util.py create mode 100644 expedient/src/python/expedient/common/federation/geni/util/cred_util.py create mode 100644 expedient/src/python/expedient/common/federation/geni/util/secure_xmlrpc_client.py create mode 100644 expedient/src/python/expedient/common/federation/geni/util/urn_util.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/README.md create mode 100644 expedient/src/python/expedient/common/federation/sfa/__init__.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/trust/__init__.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/trust/certificate.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/trust/credential.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/trust/credential_legacy.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/trust/gid.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/trust/rights.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/util/__init__.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/util/faults.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/util/namespace.py create mode 100644 expedient/src/python/expedient/common/federation/sfa/util/sfalogging.py create mode 100644 expedient/src/python/expedient/common/ldapproxy/__init__.py create mode 100644 expedient/src/python/expedient/common/ldapproxy/models.py create mode 100644 expedient/src/python/expedient/common/loggingconf.py create mode 100644 expedient/src/python/expedient/common/messaging/__init__.py create mode 100644 expedient/src/python/expedient/common/messaging/admin.py create mode 100644 expedient/src/python/expedient/common/messaging/context_processors.py create mode 100644 expedient/src/python/expedient/common/messaging/forms.py create mode 100644 expedient/src/python/expedient/common/messaging/models.py create mode 100644 expedient/src/python/expedient/common/messaging/tests.py create mode 100644 expedient/src/python/expedient/common/messaging/urls.py create mode 100644 expedient/src/python/expedient/common/messaging/views.py create mode 100644 expedient/src/python/expedient/common/middleware/__init__.py create mode 100644 expedient/src/python/expedient/common/middleware/basicauth.py create mode 100644 expedient/src/python/expedient/common/middleware/exceptionprinter.py create mode 100644 expedient/src/python/expedient/common/middleware/sitelockdown.py create mode 100644 expedient/src/python/expedient/common/middleware/threadlocals.py create mode 100644 expedient/src/python/expedient/common/middleware/utils.py create mode 100644 expedient/src/python/expedient/common/permissions/__init__.py create mode 100644 expedient/src/python/expedient/common/permissions/admin.py create mode 100644 expedient/src/python/expedient/common/permissions/backend.py create mode 100644 expedient/src/python/expedient/common/permissions/decorators.py create mode 100644 expedient/src/python/expedient/common/permissions/exceptions.py create mode 100644 expedient/src/python/expedient/common/permissions/forms.py create mode 100644 expedient/src/python/expedient/common/permissions/management.py create mode 100644 expedient/src/python/expedient/common/permissions/managers.py create mode 100644 expedient/src/python/expedient/common/permissions/middleware.py create mode 100644 expedient/src/python/expedient/common/permissions/models.py create mode 100644 expedient/src/python/expedient/common/permissions/shortcuts.py create mode 100644 expedient/src/python/expedient/common/permissions/templatetags/__init__.py create mode 100644 expedient/src/python/expedient/common/permissions/templatetags/permissions.py create mode 100644 expedient/src/python/expedient/common/permissions/tests/__init__.py create mode 100644 expedient/src/python/expedient/common/permissions/tests/models.py create mode 100644 expedient/src/python/expedient/common/permissions/tests/test_urls.py create mode 100644 expedient/src/python/expedient/common/permissions/tests/tests.py create mode 100644 expedient/src/python/expedient/common/permissions/tests/views.py create mode 100644 expedient/src/python/expedient/common/permissions/urls.py create mode 100644 expedient/src/python/expedient/common/permissions/utils.py create mode 100644 expedient/src/python/expedient/common/permissions/views.py create mode 100644 expedient/src/python/expedient/common/rpc4django/__init__.py create mode 100644 expedient/src/python/expedient/common/rpc4django/jsonrpcdispatcher.py create mode 100644 expedient/src/python/expedient/common/rpc4django/models.py create mode 100644 expedient/src/python/expedient/common/rpc4django/rpcdispatcher.py create mode 100644 expedient/src/python/expedient/common/rpc4django/templates/rpc4django/rpcmethod_summary.html create mode 100644 expedient/src/python/expedient/common/rpc4django/templatetags/__init__.py create mode 100644 expedient/src/python/expedient/common/rpc4django/templatetags/rpctags.py create mode 100644 expedient/src/python/expedient/common/rpc4django/tests/__init__.py create mode 100644 expedient/src/python/expedient/common/rpc4django/tests/test_jsonrpcdispatcher.py create mode 100644 expedient/src/python/expedient/common/rpc4django/tests/test_rpcdispatcher.py create mode 100644 expedient/src/python/expedient/common/rpc4django/tests/test_rpcviews.py create mode 100644 expedient/src/python/expedient/common/rpc4django/tests/test_urls.py create mode 100644 expedient/src/python/expedient/common/rpc4django/tests/test_xmlrpcdispatcher.py create mode 100644 expedient/src/python/expedient/common/rpc4django/tests/testmod/__init__.py create mode 100644 expedient/src/python/expedient/common/rpc4django/tests/testmod/models.py create mode 100644 expedient/src/python/expedient/common/rpc4django/tests/testmod/testsubmod/__init__.py create mode 100644 expedient/src/python/expedient/common/rpc4django/utils.py create mode 100644 expedient/src/python/expedient/common/rpc4django/views.py create mode 100644 expedient/src/python/expedient/common/rpc4django/xmlrpcdispatcher.py create mode 100644 expedient/src/python/expedient/common/tests/__init__.py create mode 100644 expedient/src/python/expedient/common/tests/client.py create mode 100644 expedient/src/python/expedient/common/tests/commands.py create mode 100644 expedient/src/python/expedient/common/tests/manager.py create mode 100644 expedient/src/python/expedient/common/tests/utils.py create mode 100644 expedient/src/python/expedient/common/timer/__init__.py create mode 100644 expedient/src/python/expedient/common/timer/exceptions.py create mode 100644 expedient/src/python/expedient/common/timer/management/__init__.py create mode 100644 expedient/src/python/expedient/common/timer/management/commands/__init__.py create mode 100644 expedient/src/python/expedient/common/timer/management/commands/run_timer_jobs.py create mode 100644 expedient/src/python/expedient/common/timer/models.py create mode 100644 expedient/src/python/expedient/common/timer/models_or create mode 100644 expedient/src/python/expedient/common/timer/tests.py create mode 100644 expedient/src/python/expedient/common/timer/utils.py create mode 100644 expedient/src/python/expedient/common/utils/ExpedientThemeManager.py create mode 100644 expedient/src/python/expedient/common/utils/ServiceThread.py create mode 100644 expedient/src/python/expedient/common/utils/__init__.py create mode 100644 expedient/src/python/expedient/common/utils/certtransport.py create mode 100644 expedient/src/python/expedient/common/utils/context_processors.py create mode 100644 expedient/src/python/expedient/common/utils/formfields.py create mode 100644 expedient/src/python/expedient/common/utils/mail.py create mode 100644 expedient/src/python/expedient/common/utils/managers.py create mode 100644 expedient/src/python/expedient/common/utils/modelfields.py create mode 100644 expedient/src/python/expedient/common/utils/plugins/__init__.py create mode 100644 expedient/src/python/expedient/common/utils/plugins/confparser.py create mode 100644 expedient/src/python/expedient/common/utils/plugins/plugincommunicator.py create mode 100644 expedient/src/python/expedient/common/utils/plugins/plugininterface.py create mode 100644 expedient/src/python/expedient/common/utils/plugins/pluginloader.py create mode 100644 expedient/src/python/expedient/common/utils/plugins/resources/__init__.py create mode 100644 expedient/src/python/expedient/common/utils/plugins/resources/link.py create mode 100644 expedient/src/python/expedient/common/utils/plugins/resources/node.py create mode 100644 expedient/src/python/expedient/common/utils/plugins/topologygenerator.py create mode 100644 expedient/src/python/expedient/common/utils/plugins/utils.py create mode 100644 expedient/src/python/expedient/common/utils/signals.py create mode 100644 expedient/src/python/expedient/common/utils/templatetags/__init__.py create mode 100644 expedient/src/python/expedient/common/utils/templatetags/ch_extras.py create mode 100644 expedient/src/python/expedient/common/utils/templatetags/flowspace.py create mode 100644 expedient/src/python/expedient/common/utils/templatetags/servers.py create mode 100644 expedient/src/python/expedient/common/utils/templatetags/url.py create mode 100644 expedient/src/python/expedient/common/utils/transport.py create mode 100644 expedient/src/python/expedient/common/utils/validators.py create mode 100644 expedient/src/python/expedient/common/utils/views.py create mode 100644 expedient/src/python/expedient/common/xmlrpc_serverproxy/__init__.py create mode 100644 expedient/src/python/expedient/common/xmlrpc_serverproxy/admin.py create mode 100644 expedient/src/python/expedient/common/xmlrpc_serverproxy/forms.py create mode 100644 expedient/src/python/expedient/common/xmlrpc_serverproxy/models.py create mode 100644 expedient/src/python/expedient/ui/__init__.py create mode 100644 expedient/src/python/expedient/ui/rspec/__init__.py create mode 100644 expedient/src/python/expedient/ui/rspec/forms.py create mode 100644 expedient/src/python/expedient/ui/rspec/models.py create mode 100644 expedient/src/python/expedient/ui/rspec/templates/rspec/home.html create mode 100644 expedient/src/python/expedient/ui/rspec/urls.py create mode 100644 expedient/src/python/expedient/ui/rspec/views.py create mode 100644 expedient/src/python/ez_setup.py create mode 100644 expedient/src/python/omnilib/__init__.py create mode 100644 expedient/src/python/omnilib/frameworks/__init__.py create mode 100644 expedient/src/python/omnilib/frameworks/framework_base.py create mode 100644 expedient/src/python/omnilib/frameworks/framework_gcf.py create mode 100644 expedient/src/python/omnilib/frameworks/framework_of.py create mode 100644 expedient/src/python/omnilib/frameworks/framework_pg.py create mode 100644 expedient/src/python/omnilib/frameworks/framework_sfa.py create mode 100644 expedient/src/python/omnilib/omnispec/__init__.py create mode 100644 expedient/src/python/omnilib/omnispec/omnispec.py create mode 100644 expedient/src/python/omnilib/omnispec/rspec_gcf.py create mode 100644 expedient/src/python/omnilib/omnispec/rspec_of.py create mode 100644 expedient/src/python/omnilib/omnispec/rspec_pg.py create mode 100644 expedient/src/python/omnilib/omnispec/rspec_sfa.py create mode 100644 expedient/src/python/omnilib/omnispec/translation.py create mode 100644 expedient/src/python/omnilib/util/__init__.py create mode 100644 expedient/src/python/omnilib/util/namespace.py create mode 100644 expedient/src/python/omnilib/xmlrpc/__init__.py create mode 100644 expedient/src/python/omnilib/xmlrpc/client.py create mode 100644 expedient/src/python/plugins/__init__.py create mode 100644 expedient/src/python/plugins/m_gui/__init__.py create mode 100644 expedient/src/python/plugins/m_gui/forms/__init__.py create mode 100644 expedient/src/python/plugins/m_gui/forms/monitoring.py create mode 100644 expedient/src/python/plugins/m_gui/models/MGUI.py create mode 100644 expedient/src/python/plugins/m_gui/models/__init__.py create mode 100644 expedient/src/python/plugins/m_gui/settings.conf create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/css/jquery.datetimepicker.css create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/css/monitor_cp.css create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/css/monitor_network.css create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/css/ocf-iframe.css create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/css/tooltip.monitor_cp.css create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/css/tooltip.monitor_network.css create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/css/tooltip.topology.css create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/css/topology.css create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/img/switch-se.png create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/img/tn.png create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/js/d3.v2.min.js create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/js/jquery.datetimepicker.js create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/js/tooltip.monitor_cp.js create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/js/tooltip.monitor_network.js create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/js/tooltip.topology.js create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/js/topology.layer.js create mode 100644 expedient/src/python/plugins/m_gui/static/media/default/js/topology.util.js create mode 100644 expedient/src/python/plugins/m_gui/templates/default/base.html create mode 100644 expedient/src/python/plugins/m_gui/templates/default/iframebase.html create mode 100644 expedient/src/python/plugins/m_gui/templates/default/monitor_cp.html create mode 100644 expedient/src/python/plugins/m_gui/templates/default/monitor_network.html create mode 100644 expedient/src/python/plugins/m_gui/templates/default/monitoring.html create mode 100644 expedient/src/python/plugins/m_gui/templates/default/slice.html create mode 100644 expedient/src/python/plugins/m_gui/templates/default/slice_detail.html create mode 100644 expedient/src/python/plugins/m_gui/templates/default/topology.html create mode 100644 expedient/src/python/plugins/m_gui/urls.py create mode 100644 expedient/src/python/plugins/m_gui/views/__init__.py create mode 100644 expedient/src/python/plugins/m_gui/views/monitoring.py create mode 100644 expedient/src/python/plugins/openflow/__init__.py create mode 100644 expedient/src/python/plugins/openflow/dummyom/__init__.py create mode 100644 expedient/src/python/plugins/openflow/dummyom/ch_api.py create mode 100644 expedient/src/python/plugins/openflow/dummyom/models.py create mode 100644 expedient/src/python/plugins/openflow/dummyom/urls.py create mode 100644 expedient/src/python/plugins/openflow/plugin/__init__.py create mode 100644 expedient/src/python/plugins/openflow/plugin/admin.py create mode 100644 expedient/src/python/plugins/openflow/plugin/forms.py create mode 100644 expedient/src/python/plugins/openflow/plugin/gapi/__init__.py create mode 100644 expedient/src/python/plugins/openflow/plugin/gapi/gapi.py create mode 100644 expedient/src/python/plugins/openflow/plugin/gapi/rpc.py create mode 100644 expedient/src/python/plugins/openflow/plugin/gapi/rspec.py create mode 100644 expedient/src/python/plugins/openflow/plugin/models.py create mode 100644 expedient/src/python/plugins/openflow/plugin/tests.py create mode 100644 expedient/src/python/plugins/openflow/plugin/urls.py create mode 100644 expedient/src/python/plugins/openflow/plugin/views.py create mode 100644 expedient/src/python/plugins/openflow/plugin/vlan/__init__.py create mode 100644 expedient/src/python/plugins/openflow/plugin/vlan/manager.py create mode 100644 expedient/src/python/plugins/openflow/plugin/vlan/utils.py create mode 100644 expedient/src/python/plugins/openflow/plugin/vlans.py create mode 100644 expedient/src/python/plugins/openflow/plugin/xmlrpc.py create mode 100644 expedient/src/python/plugins/openflow/settings.conf create mode 100644 expedient/src/python/plugins/openflow/static/media/default/img/genilogo.png create mode 100644 expedient/src/python/plugins/openflow/static/media/default/img/host-tiny.png create mode 100644 expedient/src/python/plugins/openflow/static/media/default/img/switch-tiny.png create mode 100644 expedient/src/python/plugins/openflow/static/media/default/js/loop_detection.js create mode 100644 expedient/src/python/plugins/openflow/tests/__init__.py create mode 100644 expedient/src/python/plugins/openflow/tests/full/__init__.py create mode 100644 expedient/src/python/plugins/openflow/tests/full/fulltests.py create mode 100644 expedient/src/python/plugins/openflow/tests/full/helpers.py create mode 100644 expedient/src/python/plugins/openflow/tests/gapi/__init__.py create mode 100644 expedient/src/python/plugins/openflow/tests/gapi/gapi.py create mode 100644 expedient/src/python/plugins/openflow/tests/helpers.py create mode 100644 expedient/src/python/plugins/openflow/tests/manual_test/__init__.py create mode 100644 expedient/src/python/plugins/openflow/tests/manual_test/manual.py create mode 100644 expedient/src/python/plugins/openflow/tests/om/__init__.py create mode 100644 expedient/src/python/plugins/openflow/tests/om/om.py create mode 100644 expedient/src/python/plugins/openflow/tests/omctl/XMLRPCServerProxy.py create mode 100644 expedient/src/python/plugins/openflow/tests/omctl/__init__.py create mode 100644 expedient/src/python/plugins/openflow/tests/omctl/helpers.py create mode 100644 expedient/src/python/plugins/openflow/tests/omctl/omctl.py create mode 100644 expedient/src/python/plugins/openflow/tests/omctl/omctl_settings.py create mode 100644 expedient/src/python/plugins/openflow/tests/post_deployment/__init__.py create mode 100644 expedient/src/python/plugins/openflow/tests/post_deployment/tests.py create mode 100644 expedient/src/python/plugins/openflow/tests/ssl/Makefile create mode 100644 expedient/src/python/plugins/openflow/tests/test_settings.py create mode 100644 expedient/src/python/plugins/openflow/tests/tests.py create mode 100644 expedient/src/python/plugins/openflow/views/templates/default/openflow_add_resources.html create mode 100644 expedient/src/python/plugins/openflow/views/templates/default/openflow_aggregate_add_links.html create mode 100644 expedient/src/python/plugins/openflow/views/templates/default/openflow_aggregate_add_to_slice.html create mode 100644 expedient/src/python/plugins/openflow/views/templates/default/openflow_aggregate_crud.html create mode 100644 expedient/src/python/plugins/openflow/views/templates/default/openflow_select_flowspace.html create mode 100644 expedient/src/python/plugins/openflow/views/templates/default/openflow_select_resources.html create mode 100644 expedient/src/python/plugins/vt_plugin/__init__.py create mode 100644 expedient/src/python/plugins/vt_plugin/communication/__init__.py create mode 100644 expedient/src/python/plugins/vt_plugin/communication/southCommInterface.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/VMcontroller/VMcontroller.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/VMcontroller/__init__.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/__init__.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/dispatchers/GUIdispatcher.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/dispatchers/InformationDispatcher.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/dispatchers/MonitoringResponseDispatcher.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/dispatchers/ProvisioningDispatcher.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/dispatchers/ProvisioningResponseDispatcher.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/dispatchers/__init__.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/vtAggregateController/__init__.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/vtAggregateController/forms/__init__.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/vtAggregateController/forms/forms.py create mode 100644 expedient/src/python/plugins/vt_plugin/controller/vtAggregateController/vtAggregateController.py create mode 100644 expedient/src/python/plugins/vt_plugin/forms/VM.py create mode 100644 expedient/src/python/plugins/vt_plugin/forms/__init__.py create mode 100644 expedient/src/python/plugins/vt_plugin/forms/remove_vm.py create mode 100644 expedient/src/python/plugins/vt_plugin/models/Action.py create mode 100644 expedient/src/python/plugins/vt_plugin/models/VM.py create mode 100644 expedient/src/python/plugins/vt_plugin/models/VTServer.py create mode 100644 expedient/src/python/plugins/vt_plugin/models/VTServerIface.py create mode 100644 expedient/src/python/plugins/vt_plugin/models/VtPlugin.py create mode 100644 expedient/src/python/plugins/vt_plugin/models/__init__.py create mode 100644 expedient/src/python/plugins/vt_plugin/models/iface.py create mode 100644 expedient/src/python/plugins/vt_plugin/models/resourcesHash.py create mode 100644 expedient/src/python/plugins/vt_plugin/models/xmlrpcServerProxy.py create mode 100644 expedient/src/python/plugins/vt_plugin/settings.conf create mode 100644 expedient/src/python/plugins/vt_plugin/static/media/default/img/server-tiny.png create mode 100644 expedient/src/python/plugins/vt_plugin/tests/deleteAllVMs.py create mode 100644 expedient/src/python/plugins/vt_plugin/tests/deleteVM.py create mode 100644 expedient/src/python/plugins/vt_plugin/urls.py create mode 100644 expedient/src/python/plugins/vt_plugin/utils/ServiceThread.py create mode 100644 expedient/src/python/plugins/vt_plugin/utils/Translator.py create mode 100644 expedient/src/python/plugins/vt_plugin/utils/__init__.py create mode 100644 expedient/src/python/plugins/vt_plugin/utils/validators.py create mode 100644 expedient/src/python/plugins/vt_plugin/views/templates/default/vt_plugin_add_resources.html create mode 100644 expedient/src/python/plugins/vt_plugin/views/templates/default/vt_plugin_administration.html create mode 100644 expedient/src/python/plugins/vt_plugin/views/templates/default/vt_plugin_aggregate_add_virtualmachines.html create mode 100644 expedient/src/python/plugins/vt_plugin/views/templates/default/vt_plugin_aggregate_crud.html create mode 100644 expedient/src/python/plugins/vt_plugin/views/templates/default/vt_plugin_base.html create mode 100644 expedient/src/python/plugins/vt_plugin/views/templates/default/vt_plugin_list_resources.html create mode 100644 expedient/src/python/plugins/vt_plugin/views/templates/default/vt_plugin_messages_panel.html create mode 100644 expedient/src/static/expedient/clearinghouse/media/FELIX/css/notifications.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/FELIX/css/ocf.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/FELIX/img/logo_expedient.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/FIBRE/css/ocf.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/FIBRE/img/logo_expedient.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/aggregate.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/aggregate.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/help.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-icons_222222_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-icons_2e83ff_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-icons_454545_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-icons_888888_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/images/ui-icons_cd0a0a_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/jquery-ui.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/notifications.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/ocf-iframe.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/ocf.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/permission.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/project.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/slice.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/slice.topology.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-bg_flat_55_fbec88_40x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-bg_glass_85_dfeffc_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-icons_217bc0_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-icons_2e83ff_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-icons_469bdd_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-icons_6da8d5_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-icons_cd0a0a_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-icons_d8e7f3_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/images/ui-icons_f9bd01_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery-ui.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.accordion.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.autocomplete.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.base.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.button.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.core.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.datepicker.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.dialog.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.progressbar.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.resizable.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.selectable.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.slider.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.tabs.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/themes/redmond/jquery.ui.theme.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/tooltip.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/css/tooltip.topology.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/egeni-iframe.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/egeni.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/help.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-icons_222222_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-icons_2e83ff_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-icons_454545_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-icons_888888_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/images/ui-icons_cd0a0a_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/jquery-ui.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/notifications.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/ocf-iframe.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/ocf.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/permission.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/project.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/slice.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/slice.topology.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-bg_flat_55_fbec88_40x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-bg_glass_85_dfeffc_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-icons_217bc0_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-icons_2e83ff_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-icons_469bdd_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-icons_6da8d5_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-icons_cd0a0a_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-icons_d8e7f3_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/images/ui-icons_f9bd01_256x240.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery-ui.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.accordion.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.all.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.autocomplete.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.base.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.button.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.core.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.datepicker.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.dialog.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.progressbar.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.resizable.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.selectable.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.slider.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.tabs.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/themes/redmond/jquery.ui.theme.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/tooltip.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/css/tooltip.topology.css create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/account.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/active.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/aggregate-tiny.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/black.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/black_arrow.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/black_arrow_big.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/black_big.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/button.pxm create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/dashboard.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/expand.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/favicon.ico create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/groupin.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/help.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/inactive.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/loading.gif create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/logo_expedient.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/logout.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/msg_announcement.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/msg_error.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/msg_info.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/msg_success.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/msg_user2user.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/navigation.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/notification_16x16.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/ofelia.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/play.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/question_mark.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/question_mark_15x15.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/reload.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/slice-tiny.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/slice.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/status-question-small.jpg create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/status-question.jpg create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/stop.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/switch-5406zl.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/switch-cat6500.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/switch-juniper.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/switch-nec-ip8800.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/switch-netfpga.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/switch-nf2.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/switch.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/tiny_arrow.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/users-tiny.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/warning.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/white.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/white_arrow.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/white_arrow_big.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/white_big.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/zoom.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/zoomin.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/img/zoomout.png create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/agg_status.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/base.helptext.icons.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/common.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/d3.v2.min.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/flowspace.helptext.icons.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/iframe.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/index.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jquery-1.10.2.min.map create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jquery-ui.min.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jquery.blockUI.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jquery.colorbox-min.js create mode 100755 expedient/src/static/expedient/clearinghouse/media/default/js/jquery.min.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jquery.tools.min.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/bin/jsencrypt.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/bin/jsencrypt.min.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/asn1js/LICENSE.txt create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/asn1js/asn1.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/asn1js/base64.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/asn1js/hex.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/asn1js/oids.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsbn/LICENSE.txt create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsbn/README.md create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsbn/base64.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsbn/jsbn.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsbn/jsbn2.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsbn/prng4.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsbn/rng.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsbn/rsa-async.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsbn/rsa.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsbn/rsa2.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsrsasign/LICENSE.txt create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsencrypt/lib/jsrsasign/asn1-1.0.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/jsrsasign-latest-all-min.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/slice.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/tooltip.funcs.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/tooltip.topology.js create mode 100644 expedient/src/static/expedient/clearinghouse/media/default/js/validation.js create mode 100644 expedient/src/templates/FELIX/expedient/clearinghouse/base.html create mode 100644 expedient/src/templates/FIBRE/expedient/clearinghouse/base.html create mode 100644 expedient/src/templates/FIBRE/expedient/clearinghouse/base.html.old create mode 100644 expedient/src/templates/default/expedient/clearinghouse/404.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/500.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/administration/index.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/administration/log.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/aggregate/delete.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/aggregate/info.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/aggregate/list.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/aggregate/list_actions.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/aggregate/list_table.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/base.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/div_base.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/fixformtable.js create mode 100644 expedient/src/templates/default/expedient/clearinghouse/geni/aggregate_crud.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/geni/sshkeys.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/geni/user_cert_generate.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/geni/user_cert_manage.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/geni/user_cert_upload.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/geni/user_key_upload.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/geni/user_new_keys_download.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/geni/user_new_ssh_key_download.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/help/index.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/help/index_original create mode 100644 expedient/src/templates/default/expedient/clearinghouse/iframebase.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/index.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/messagecenter/index.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/permissionmgmt/confirm_requests.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/permissionmgmt/dashboard.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/permissionmgmt/request_permission.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/add_aggregates.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/add_member.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/agg_add_actions.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/agg_list_actions.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/confirm_delete.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/create_update.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/detail.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/list.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/list_details.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/project_simple_agg_list.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/remove_member.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/project/update_member.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/activate.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/activation_email.txt create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/activation_email_subject.txt create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/home.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/login.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/logout.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/password_change_done.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/password_change_form.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/password_reset_complete.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/password_reset_confirm.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/password_reset_done.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/password_reset_email.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/password_reset_email_ofreg.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/password_reset_form.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/registration_complete.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/registration_form.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/registration/registration_incomplete.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/roles/confirm_request.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/roles/create.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/roles/delete.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/roles/make_request.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/roles/no_permission.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/roles/update.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/slice/add_aggregates.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/slice/confirm_delete.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/slice/create_update.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/slice/detail.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/slice/select_ui_plugin.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/slice/topology.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/under_construction.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/users/confirm_delete.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/users/detail.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/users/home.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/users/saved.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/users/tooltip.js create mode 100644 expedient/src/templates/default/expedient/clearinghouse/users/tooltipdesc.html create mode 100644 expedient/src/templates/default/expedient/clearinghouse/users/tooltiplist.html create mode 100644 expedient/src/templates/default/expedient/common/Default/messaging/create.html create mode 100644 expedient/src/templates/default/expedient/common/Default/messaging/created.html create mode 100644 expedient/src/templates/default/expedient/common/Default/messaging/list.html create mode 100644 expedient/src/templates/default/expedient/common/Default/permissions/empty.html create mode 100644 expedient/src/templates/default/expedient/common/messaging/create.html create mode 100644 expedient/src/templates/default/expedient/common/messaging/created.html create mode 100644 expedient/src/templates/default/expedient/common/messaging/list.html create mode 100644 expedient/src/templates/default/expedient/common/permissions/empty.html create mode 100644 expedient/src/wsgi/expedient/clearinghouse/auth.wsgi create mode 100644 expedient/src/wsgi/expedient/clearinghouse/django.wsgi create mode 100644 expedient/src/wsgi/expedient/clearinghouse/mon.wsgi create mode 100644 expedient/version create mode 100755 ofam/README.md create mode 120000 ofam/bin/common create mode 100644 ofam/bin/log/.gitignore create mode 120000 ofam/bin/ofver create mode 120000 ofam/bin/repo create mode 100644 ofam/bin/rescue/.gitignore create mode 120000 ofam/bin/settings create mode 120000 ofam/bin/versions/0.7/upgrade create mode 100644 ofam/bin/versions/default/install/backup create mode 100644 ofam/bin/versions/default/install/dependencies create mode 100644 ofam/bin/versions/default/install/install create mode 100644 ofam/bin/versions/default/install/lib/dependencies create mode 100644 ofam/bin/versions/default/install/lib/django-settings create mode 100644 ofam/bin/versions/default/install/lib/ssl create mode 100644 ofam/bin/versions/default/install/post-install-hook create mode 100644 ofam/bin/versions/default/install/pre-install-hook create mode 100644 ofam/bin/versions/default/install/repo create mode 100644 ofam/bin/versions/default/install/rollback create mode 100644 ofam/bin/versions/default/upgrade/default/README create mode 100644 ofam/bin/versions/default/upgrade/default/backup create mode 100644 ofam/bin/versions/default/upgrade/default/dependencies create mode 120000 ofam/bin/versions/default/upgrade/default/lib create mode 100644 ofam/bin/versions/default/upgrade/default/post-upgrade-hook create mode 100644 ofam/bin/versions/default/upgrade/default/pre-upgrade-hook create mode 100644 ofam/bin/versions/default/upgrade/default/rollback create mode 100644 ofam/bin/versions/default/upgrade/default/upgrade create mode 120000 ofam/bin/versions/version-checks create mode 100644 ofam/src/.gitignore create mode 100644 ofam/src/ACKS create mode 100755 ofam/src/CHANGELOG create mode 100644 ofam/src/COPYING create mode 100644 ofam/src/NOTES create mode 100644 ofam/src/README create mode 100644 ofam/src/debian/README.Debian create mode 100644 ofam/src/debian/README.source create mode 100644 ofam/src/debian/changelog create mode 100644 ofam/src/debian/compat create mode 100644 ofam/src/debian/control create mode 100644 ofam/src/debian/copyright create mode 100644 ofam/src/debian/dirs create mode 100644 ofam/src/debian/docs create mode 100644 ofam/src/debian/emacsen-install.ex create mode 100644 ofam/src/debian/emacsen-remove.ex create mode 100644 ofam/src/debian/emacsen-startup.ex create mode 100644 ofam/src/debian/foam.cron.d create mode 100644 ofam/src/debian/foam.default.ex create mode 100644 ofam/src/debian/foam.doc-base.EX create mode 100644 ofam/src/debian/init.d create mode 100644 ofam/src/debian/manpage.1.ex create mode 100644 ofam/src/debian/manpage.sgml.ex create mode 100644 ofam/src/debian/manpage.xml.ex create mode 100644 ofam/src/debian/menu.ex create mode 100644 ofam/src/debian/postinst.lucid create mode 100644 ofam/src/debian/postinst.squeeze create mode 100644 ofam/src/debian/postrm create mode 100644 ofam/src/debian/preinst.ex create mode 100644 ofam/src/debian/prerm create mode 100644 ofam/src/debian/python-module-stampdir/foam create mode 100644 ofam/src/debian/pyversions create mode 100644 ofam/src/debian/rules create mode 100644 ofam/src/debian/source/format create mode 100644 ofam/src/debian/watch.ex create mode 100644 ofam/src/docs/INSTALL create mode 100644 ofam/src/install.py create mode 100644 ofam/src/package.py create mode 100644 ofam/src/plugins/rpc-gapi-v1/manifest.json create mode 100644 ofam/src/plugins/rpc-gapi-v2/manifest.json create mode 100644 ofam/src/schemas/ad.xsd create mode 100644 ofam/src/schemas/any-extension-schema.xsd create mode 100644 ofam/src/schemas/foam-config-1.xsd create mode 100644 ofam/src/schemas/fv-resv-1.xsd create mode 100644 ofam/src/schemas/of-resv-3.xsd create mode 100644 ofam/src/schemas/of-resv-4.xsd create mode 100644 ofam/src/schemas/request-common.xsd create mode 100644 ofam/src/schemas/request.xsd create mode 100644 ofam/src/setup.py create mode 100644 ofam/src/src/dev-server.py create mode 100644 ofam/src/src/ext/geni/SecureXMLRPCServer.py create mode 100644 ofam/src/src/ext/geni/__init__.py create mode 100644 ofam/src/src/ext/geni/am.py create mode 100644 ofam/src/src/ext/geni/ca.py create mode 100644 ofam/src/src/ext/geni/ch.py create mode 100644 ofam/src/src/ext/geni/config.py create mode 100644 ofam/src/src/ext/geni/util/__init__.py create mode 100644 ofam/src/src/ext/geni/util/cert_util.py create mode 100644 ofam/src/src/ext/geni/util/cred_util.py create mode 100644 ofam/src/src/ext/geni/util/secure_xmlrpc_client.py create mode 100644 ofam/src/src/ext/geni/util/urn_util.py create mode 100644 ofam/src/src/ext/jsonrpc/__init__.py create mode 100644 ofam/src/src/ext/jsonrpc/_tests/__init__.py create mode 100644 ofam/src/src/ext/jsonrpc/_tests/test_cgiwrapper.py create mode 100644 ofam/src/src/ext/jsonrpc/_tests/test_json.py create mode 100644 ofam/src/src/ext/jsonrpc/_tests/test_modpywrapper.py create mode 100644 ofam/src/src/ext/jsonrpc/_tests/test_proxy.py create mode 100644 ofam/src/src/ext/jsonrpc/_tests/test_serviceHandler.py create mode 100644 ofam/src/src/ext/jsonrpc/cgiwrapper.py create mode 100644 ofam/src/src/ext/jsonrpc/json.py create mode 100644 ofam/src/src/ext/jsonrpc/modpywrapper.py create mode 100644 ofam/src/src/ext/jsonrpc/proxy.py create mode 100644 ofam/src/src/ext/jsonrpc/serviceHandler.py create mode 100644 ofam/src/src/ext/sfa/README.md create mode 100644 ofam/src/src/ext/sfa/__init__.py create mode 100644 ofam/src/src/ext/sfa/trust/__init__.py create mode 100644 ofam/src/src/ext/sfa/trust/certificate.py create mode 100644 ofam/src/src/ext/sfa/trust/credential.py create mode 100644 ofam/src/src/ext/sfa/trust/credential_legacy.py create mode 100644 ofam/src/src/ext/sfa/trust/gid.py create mode 100644 ofam/src/src/ext/sfa/trust/rights.py create mode 100644 ofam/src/src/ext/sfa/util/__init__.py create mode 100644 ofam/src/src/ext/sfa/util/faults.py create mode 100644 ofam/src/src/ext/sfa/util/sfalogging.py create mode 100644 ofam/src/src/ext/sfa/util/sfatime.py create mode 100644 ofam/src/src/ext/sfa/util/xrn.py create mode 100644 ofam/src/src/foam.conf create mode 100644 ofam/src/src/foam/__init__.py create mode 100644 ofam/src/src/foam/api/__init__.py create mode 100644 ofam/src/src/foam/api/admin.py create mode 100644 ofam/src/src/foam/api/auth.py create mode 100644 ofam/src/src/foam/api/auto.py create mode 100644 ofam/src/src/foam/api/debug.py create mode 100644 ofam/src/src/foam/api/gapi1.py create mode 100644 ofam/src/src/foam/api/gapi2.py create mode 100644 ofam/src/src/foam/api/geni.py create mode 100644 ofam/src/src/foam/api/jsonrpc.py create mode 100644 ofam/src/src/foam/api/legacyexpedientapi.py create mode 100644 ofam/src/src/foam/api/sfaapi.py create mode 100644 ofam/src/src/foam/api/xmlrpc.py create mode 100644 ofam/src/src/foam/app.py create mode 100644 ofam/src/src/foam/config.py create mode 100644 ofam/src/src/foam/core/__init__.py create mode 100644 ofam/src/src/foam/core/allocation.py create mode 100644 ofam/src/src/foam/core/auth.py create mode 100644 ofam/src/src/foam/core/configdb.py create mode 100644 ofam/src/src/foam/core/exception.py create mode 100644 ofam/src/src/foam/core/htpasswd.py create mode 100644 ofam/src/src/foam/core/json.py create mode 100644 ofam/src/src/foam/core/log.py create mode 100644 ofam/src/src/foam/core/tracer.py create mode 100644 ofam/src/src/foam/creds.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/__init__.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/api_exp_to_rspecv3/__init__.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/api_exp_to_rspecv3/expdatatogeniv3rspec.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/api_exp_to_rspecv3/expedientapi.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/api_exp_to_rspecv3/testexpedientapi.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/legacyoptin/__init__.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/legacyoptin/expedienturls.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/legacyoptin/flowspacemodels.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/legacyoptin/flowspaceutils.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/legacyoptin/optsmodels.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/legacyoptin/xmlrpcmodels.py create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/very_old_code_topo_callback/xmlrpc_server_ch_api_ethmerged create mode 100644 ofam/src/src/foam/ethzlegacyoptinstuff/very_old_code_topo_callback/xmlrpc_server_models_ethmerged create mode 100644 ofam/src/src/foam/eventmanager.py create mode 100644 ofam/src/src/foam/events.py create mode 100644 ofam/src/src/foam/flowclashdetection/__init__.py create mode 100644 ofam/src/src/foam/flowclashdetection/flowfieldtrees.py create mode 100644 ofam/src/src/foam/flowclashdetection/interval_structure.py create mode 100644 ofam/src/src/foam/flowclashdetection/test_interval_structure.py create mode 100644 ofam/src/src/foam/flowclashdetection/utils/flowspaceutils.py create mode 100644 ofam/src/src/foam/flowvisor.py create mode 100644 ofam/src/src/foam/fsdb.py create mode 100644 ofam/src/src/foam/geni/__init__.py create mode 100644 ofam/src/src/foam/geni/approval.py create mode 100644 ofam/src/src/foam/geni/codes.py create mode 100644 ofam/src/src/foam/geni/db.py create mode 100644 ofam/src/src/foam/geni/lib.py create mode 100644 ofam/src/src/foam/geni/ofeliaapproval.py create mode 100644 ofam/src/src/foam/geni/topology.py create mode 100644 ofam/src/src/foam/lib.py create mode 100644 ofam/src/src/foam/ofeliasettings/__init__.py create mode 100644 ofam/src/src/foam/ofeliasettings/apache-config/openflow/foam/apache/vhost-foam.conf create mode 100644 ofam/src/src/foam/ofeliasettings/apache-config/openflow/foam/common/apache/vhost-macros.conf create mode 100644 ofam/src/src/foam/ofeliasettings/localsettings-example create mode 100644 ofam/src/src/foam/ofeliasettings/openflow/foam/__init__.py create mode 100644 ofam/src/src/foam/ofeliasettings/openflow/foam/monitoring/BackgroundMonitor.py create mode 100644 ofam/src/src/foam/ofeliasettings/openflow/foam/monitoring/SessionMonitoringThread.py create mode 100644 ofam/src/src/foam/ofeliasettings/openflow/foam/monitoring/__init__.py create mode 100644 ofam/src/src/foam/ofeliasettings/openflow/foam/settings.py create mode 100644 ofam/src/src/foam/ofeliasettings/wsgi/openflow/foam/auth.wsgi create mode 100644 ofam/src/src/foam/ofeliasettings/wsgi/openflow/foam/django.wsgi create mode 100644 ofam/src/src/foam/ofeliasettings/wsgi/openflow/foam/mon.wsgi create mode 100644 ofam/src/src/foam/openflow/__init__.py create mode 100644 ofam/src/src/foam/openflow/types.py create mode 100644 ofam/src/src/foam/plugin_manager.py create mode 100644 ofam/src/src/foam/sfa/__init__.py create mode 100644 ofam/src/src/foam/sfa/drivers/OFAggregate.py create mode 100644 ofam/src/src/foam/sfa/drivers/OFSfaDriver.py create mode 100644 ofam/src/src/foam/sfa/drivers/__init__.py create mode 100644 ofam/src/src/foam/sfa/lib.py create mode 100644 ofam/src/src/foam/sfa/methods/.ListResources.py.swo create mode 100644 ofam/src/src/foam/sfa/methods/CreateGid.py create mode 100644 ofam/src/src/foam/sfa/methods/CreateSliver.py create mode 100644 ofam/src/src/foam/sfa/methods/DeleteSliver.py create mode 100644 ofam/src/src/foam/sfa/methods/GetCredential.py create mode 100644 ofam/src/src/foam/sfa/methods/GetGids.py create mode 100644 ofam/src/src/foam/sfa/methods/GetSelfCredential.py create mode 100644 ofam/src/src/foam/sfa/methods/GetTicket.py create mode 100644 ofam/src/src/foam/sfa/methods/GetVersion.py create mode 100644 ofam/src/src/foam/sfa/methods/List.py create mode 100644 ofam/src/src/foam/sfa/methods/ListResources.py create mode 100644 ofam/src/src/foam/sfa/methods/ListResources.py.bak create mode 100644 ofam/src/src/foam/sfa/methods/ListSlices.py create mode 100644 ofam/src/src/foam/sfa/methods/RedeemTicket.py create mode 100644 ofam/src/src/foam/sfa/methods/Register.py create mode 100644 ofam/src/src/foam/sfa/methods/Remove.py create mode 100644 ofam/src/src/foam/sfa/methods/RenewSliver.py create mode 100644 ofam/src/src/foam/sfa/methods/Resolve.py create mode 100644 ofam/src/src/foam/sfa/methods/ResolveGENI.py create mode 100644 ofam/src/src/foam/sfa/methods/Shutdown.py create mode 100644 ofam/src/src/foam/sfa/methods/SliverStatus.py create mode 100644 ofam/src/src/foam/sfa/methods/Start.py create mode 100644 ofam/src/src/foam/sfa/methods/Stop.py create mode 100644 ofam/src/src/foam/sfa/methods/Update.py create mode 100644 ofam/src/src/foam/sfa/methods/UpdateSliver.py create mode 100644 ofam/src/src/foam/sfa/methods/__init__.py create mode 100644 ofam/src/src/foam/sfa/methods/get_key_from_incoming_ip.py create mode 100644 ofam/src/src/foam/sfa/methods/get_trusted_certs.py create mode 100644 ofam/src/src/foam/sfa/methods/permission_manager.py create mode 100644 ofam/src/src/foam/sfa/methods/reset_slice.py create mode 100644 ofam/src/src/foam/sfa/rspecs/.oldversions/__init__.py create mode 100644 ofam/src/src/foam/sfa/rspecs/.oldversions/federica.py create mode 100644 ofam/src/src/foam/sfa/rspecs/.oldversions/nitosv1.py create mode 100644 ofam/src/src/foam/sfa/rspecs/.oldversions/ocfvtv1.py create mode 100644 ofam/src/src/foam/sfa/rspecs/.oldversions/pgv2.py create mode 100644 ofam/src/src/foam/sfa/rspecs/.oldversions/pgv3.py create mode 100644 ofam/src/src/foam/sfa/rspecs/.oldversions/sfav1.py create mode 100644 ofam/src/src/foam/sfa/rspecs/__init__.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/__init__.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/__init__.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/bwlimit.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/bwlimit.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/channel.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/channel.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/disk_image.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/disk_image.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/element.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/element.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/execute.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/execute.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/fw_rule.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/fw_rule.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/granularity.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/granularity.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/hardware_type.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/hardware_type.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/install.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/install.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/interface.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/interface.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/lease.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/lease.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/link.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/link.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/location.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/location.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/login.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/login.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/network_interface.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/node.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/node.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/ocf_vt_server.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/openflow_switch.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/pltag.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/pltag.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/position_3d.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/position_3d.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/property.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/property.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/range.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/services.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/services.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/sliver.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/sliver.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/spectrum.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/spectrum.pyo create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/__init__.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/nitosv1Channel.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/nitosv1Lease.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/nitosv1Node.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/nitosv1PLTag.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/nitosv1Sliver.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/ocfofNode.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/ocfofSlivers.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/ocfvtNode.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/ocfvtSlivers.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/ocfvtSlivers.py.old create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/pgv2DiskImage.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/pgv2Interface.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/pgv2Link.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/pgv2Node.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/pgv2Services.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/pgv2SliverType.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/plosv1FWRule.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/sfav1Lease.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/sfav1Node.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/sfav1PLTag.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/versions/sfav1Sliver.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/vm.py create mode 100644 ofam/src/src/foam/sfa/rspecs/elements/vm_interface.py create mode 100644 ofam/src/src/foam/sfa/rspecs/pg_rspec_converter.py create mode 100644 ofam/src/src/foam/sfa/rspecs/rspec.py create mode 100644 ofam/src/src/foam/sfa/rspecs/rspec_converter.py create mode 100644 ofam/src/src/foam/sfa/rspecs/rspec_elements.py create mode 100644 ofam/src/src/foam/sfa/rspecs/sfa_rspec_converter.py create mode 100644 ofam/src/src/foam/sfa/rspecs/version.py create mode 100644 ofam/src/src/foam/sfa/rspecs/version_manager.py create mode 100644 ofam/src/src/foam/sfa/rspecs/versions/__init__.py create mode 100644 ofam/src/src/foam/sfa/rspecs/versions/ocfofv1.py create mode 100644 ofam/src/src/foam/sfa/rspecs/versions/ocfvtv1.py create mode 100755 ofam/src/src/foam/sfa/schemas/credential.xsd create mode 100755 ofam/src/src/foam/sfa/schemas/protogeni-rspec-common.xsd create mode 100755 ofam/src/src/foam/sfa/schemas/sig.xsd create mode 100755 ofam/src/src/foam/sfa/schemas/top.xsd create mode 100755 ofam/src/src/foam/sfa/schemas/xml.xsd create mode 100644 ofam/src/src/foam/sfa/sfa_config/__init__.py create mode 100644 ofam/src/src/foam/sfa/sfa_config/config.py create mode 100644 ofam/src/src/foam/sfa/trust/__init__.py create mode 100644 ofam/src/src/foam/sfa/trust/auth.py create mode 100644 ofam/src/src/foam/sfa/trust/certificate.py create mode 100644 ofam/src/src/foam/sfa/trust/credential.py create mode 100644 ofam/src/src/foam/sfa/trust/credential_legacy.py create mode 100644 ofam/src/src/foam/sfa/trust/gid.py create mode 100644 ofam/src/src/foam/sfa/trust/hierarchy.py create mode 100644 ofam/src/src/foam/sfa/trust/rights.py create mode 100644 ofam/src/src/foam/sfa/trust/sfaticket.py create mode 100644 ofam/src/src/foam/sfa/trust/trustedroots.py create mode 100644 ofam/src/src/foam/sfa/trusted_roots/fed4fire.gid create mode 100644 ofam/src/src/foam/sfa/trusted_roots/iminds.gid create mode 100644 ofam/src/src/foam/sfa/trusted_roots/ocf.gid create mode 100644 ofam/src/src/foam/sfa/trusted_roots/optin_ocf.gid create mode 100644 ofam/src/src/foam/sfa/trusted_roots/ple.gid create mode 100644 ofam/src/src/foam/sfa/trusted_roots/sfa.gid create mode 100644 ofam/src/src/foam/sfa/trusted_roots/topdomain.gid create mode 100644 ofam/src/src/foam/sfa/trusted_roots/vwall-iminds3.gid create mode 100644 ofam/src/src/foam/sfa/util/__init__.py create mode 100644 ofam/src/src/foam/sfa/util/cache.py create mode 100644 ofam/src/src/foam/sfa/util/callids.py create mode 100644 ofam/src/src/foam/sfa/util/config.py create mode 100644 ofam/src/src/foam/sfa/util/defaultdict.py create mode 100644 ofam/src/src/foam/sfa/util/enumeration.py create mode 100644 ofam/src/src/foam/sfa/util/faults.py create mode 100644 ofam/src/src/foam/sfa/util/genicode.py create mode 100644 ofam/src/src/foam/sfa/util/method.py create mode 100644 ofam/src/src/foam/sfa/util/parameter.py create mode 100644 ofam/src/src/foam/sfa/util/sfalogging.py create mode 100644 ofam/src/src/foam/sfa/util/sfatime.py create mode 100644 ofam/src/src/foam/sfa/util/version.py create mode 100644 ofam/src/src/foam/sfa/util/xml.py create mode 100644 ofam/src/src/foam/sfa/util/xrn.py create mode 100644 ofam/src/src/foam/task.py create mode 100644 ofam/src/src/foam/types/DateTime.py create mode 100644 ofam/src/src/foam/types/URN.py create mode 100644 ofam/src/src/foam/types/__init__.py create mode 100644 ofam/src/src/foam/types/event_type.py create mode 100644 ofam/src/src/foam/types/trigger_type.py create mode 100644 ofam/src/src/foam/version.py create mode 100644 ofam/src/src/foam/webgui/set/settings.py create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/add_rule_dark.png create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/back_dark.png create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/dashboard.png create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/egeni-iframe.css create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/egeni.css create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/experiments_dark.png create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/fs_req_dark.png create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/help.png create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/js/formtable.tooltip.js create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/js/jquery.min.js create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/js/jquery.tools.min.js create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/js/tooltip.funcs.js create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/logout.png create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/ofelialogo.png create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/remove_rule_dark.png create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/slice.png create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/tooltip.css create mode 100644 ofam/src/src/foam/webgui/static/openflow/foam/media/default/view_exp_dark.png create mode 100644 ofam/src/src/foam/webgui/templates/default/openflow/foam/base.html create mode 100644 ofam/src/src/foam/webgui/templates/default/openflow/foam/tooltip.funcs.js create mode 100644 ofam/src/src/foamext/IPy.py create mode 100644 ofam/src/src/foamext/__init__.py create mode 100644 ofam/src/src/foamext/importlib.py create mode 100644 ofam/src/src/foamext/triggers/__init__.py create mode 100644 ofam/src/src/scripts/daily-queue create mode 100644 ofam/src/src/scripts/expire create mode 100644 ofam/src/src/scripts/expire-emails create mode 100644 ofam/src/src/scripts/foam-db-convert.py create mode 100644 ofam/src/src/scripts/foam.fcgi create mode 100755 ofam/src/src/scripts/foamctl create mode 100644 ofam/src/src/trusted create mode 100644 ofam/src/templates/email.event.approvesliver.admin.txt create mode 100644 ofam/src/templates/email.event.approvesliver.exp.txt create mode 100644 ofam/src/templates/email.event.createsliver.admin.txt create mode 100644 ofam/src/templates/email.event.createsliver.exp.txt create mode 100644 ofam/src/templates/email.event.disablesliver.admin.txt create mode 100644 ofam/src/templates/email.event.disablesliver.exp.txt create mode 100644 ofam/src/templates/email.event.expiresliver.admin.txt create mode 100644 ofam/src/templates/email.event.expiresliver.exp.txt create mode 100644 ofam/src/templates/email.event.expiresliverday.admin.txt create mode 100644 ofam/src/templates/email.event.expiresliverday.exp.txt create mode 100644 ofam/src/templates/email.event.expiresliverweek.admin.txt create mode 100644 ofam/src/templates/email.event.expiresliverweek.exp.txt create mode 100644 ofam/src/templates/email.event.gapi-deletesliver.admin.txt create mode 100644 ofam/src/templates/email.event.gapi-deletesliver.exp.txt create mode 100644 ofam/src/templates/email.event.json-deletesliver.admin.txt create mode 100644 ofam/src/templates/email.event.json-deletesliver.exp.txt create mode 100644 ofam/src/templates/email.event.pendingqueue.admin.txt create mode 100644 ofam/src/templates/email.event.rejectsliver.admin.txt create mode 100644 ofam/src/templates/email.event.rejectsliver.exp.txt create mode 100644 ofam/src/templates/email.event.renewsliver.admin.txt create mode 100644 ofam/src/templates/email.event.renewsliver.exp.txt create mode 100644 ofam/src/templates/email.event.shutdownsliver.admin.txt create mode 100644 ofam/src/templates/email.event.shutdownsliver.exp.txt create mode 100644 ofam/version create mode 100644 ofreg/.gitignore create mode 100644 ofreg/README.txt create mode 100644 ofreg/__init__.py create mode 100644 ofreg/db/.gitignore create mode 100644 ofreg/deploy/apache-ofreg.conf create mode 100644 ofreg/deploy/ofreg.wsgi create mode 100755 ofreg/deploy/ssl/make_key.sh create mode 100755 ofreg/localsettings.py-example create mode 100755 ofreg/manage.py create mode 100644 ofreg/registration/__init__.py create mode 100644 ofreg/registration/models/__init__.py create mode 100644 ofreg/registration/models/login.py create mode 100644 ofreg/registration/models/password_reset.py create mode 100644 ofreg/registration/models/registration.py create mode 100644 ofreg/registration/static/css/ofreg.css create mode 100644 ofreg/registration/static/img/ofelia.png create mode 100644 ofreg/registration/static/img/warning.png create mode 100644 ofreg/registration/static/openvpn.tar.gz create mode 100644 ofreg/registration/templates/base.html create mode 100644 ofreg/registration/templates/login/login.html create mode 100644 ofreg/registration/templates/login/success.html create mode 100644 ofreg/registration/templates/mailer/password_reset_reset.txt create mode 100644 ofreg/registration/templates/mailer/registration_complete.txt create mode 100644 ofreg/registration/templates/mailer/registration_validation.txt create mode 100644 ofreg/registration/templates/password_reset/forgotten.html create mode 100644 ofreg/registration/templates/password_reset/reset.html create mode 100644 ofreg/registration/templates/registration/register.html create mode 100644 ofreg/registration/templates/registration/register_success.html create mode 100644 ofreg/registration/templates/registration/validate_error.html create mode 100644 ofreg/registration/templates/registration/validate_success.html create mode 100644 ofreg/registration/templates/welcome/index.html create mode 100644 ofreg/registration/templatetags/__init__.py create mode 100644 ofreg/registration/templatetags/form_helper.py create mode 100644 ofreg/registration/tests.py create mode 100644 ofreg/registration/urls.py create mode 100644 ofreg/registration/views/__init__.py create mode 100644 ofreg/registration/views/login.py create mode 100644 ofreg/registration/views/password_reset.py create mode 100644 ofreg/registration/views/registration.py create mode 100644 ofreg/registration/views/welcome.py create mode 100644 ofreg/settings.py create mode 100644 ofreg/urls.py create mode 100644 ofreg/util.py create mode 120000 optin_manager/bin/common create mode 100644 optin_manager/bin/log/.gitignore create mode 120000 optin_manager/bin/ofver create mode 120000 optin_manager/bin/repo create mode 100644 optin_manager/bin/rescue/.gitignore create mode 120000 optin_manager/bin/settings create mode 100644 optin_manager/bin/versions/0.13/upgrade/0.12/backup create mode 100644 optin_manager/bin/versions/0.13/upgrade/0.12/pre-backup-upgrade-hook create mode 100644 optin_manager/bin/versions/0.3/upgrade/default/post-upgrade-hook create mode 120000 optin_manager/bin/versions/0.3/upgrade/default/pre-upgrade-hook create mode 120000 optin_manager/bin/versions/0.3RC1 create mode 120000 optin_manager/bin/versions/0.4.1 create mode 120000 optin_manager/bin/versions/0.4.2 create mode 120000 optin_manager/bin/versions/0.4.3 create mode 100644 optin_manager/bin/versions/0.4/upgrade/default/post-upgrade-hook create mode 120000 optin_manager/bin/versions/0.5 create mode 120000 optin_manager/bin/versions/0.6 create mode 120000 optin_manager/bin/versions/0.6.1 create mode 100644 optin_manager/bin/versions/0.7/upgrade/default/pre-upgrade-hook create mode 120000 optin_manager/bin/versions/0.8 create mode 120000 optin_manager/bin/versions/0.8.1 create mode 120000 optin_manager/bin/versions/0.8.2 create mode 100644 optin_manager/bin/versions/default/install/backup create mode 100644 optin_manager/bin/versions/default/install/dependencies create mode 100644 optin_manager/bin/versions/default/install/install create mode 100644 optin_manager/bin/versions/default/install/lib/dependencies create mode 100644 optin_manager/bin/versions/default/install/lib/django-db create mode 100644 optin_manager/bin/versions/default/install/lib/django-settings create mode 120000 optin_manager/bin/versions/default/install/lib/set_environment_variables create mode 100644 optin_manager/bin/versions/default/install/lib/ssl create mode 100644 optin_manager/bin/versions/default/install/post-install-hook create mode 100644 optin_manager/bin/versions/default/install/pre-install-hook create mode 100644 optin_manager/bin/versions/default/install/repo create mode 100644 optin_manager/bin/versions/default/install/rollback create mode 100644 optin_manager/bin/versions/default/upgrade/default/README create mode 100644 optin_manager/bin/versions/default/upgrade/default/backup create mode 100644 optin_manager/bin/versions/default/upgrade/default/dependencies create mode 120000 optin_manager/bin/versions/default/upgrade/default/lib/set_environment_variables create mode 100644 optin_manager/bin/versions/default/upgrade/default/post-upgrade-hook create mode 100644 optin_manager/bin/versions/default/upgrade/default/pre-upgrade-hook create mode 100644 optin_manager/bin/versions/default/upgrade/default/rollback create mode 100644 optin_manager/bin/versions/default/upgrade/default/upgrade create mode 100644 optin_manager/bin/versions/default/upgrade/tools/prova create mode 100644 optin_manager/bin/versions/default/upgrade/tools/prova.cfg create mode 120000 optin_manager/bin/versions/default/upgrade/tools/sqlDump.py create mode 120000 optin_manager/bin/versions/default/upgrade/tools/sqlRestore.py create mode 120000 optin_manager/bin/versions/version-checks create mode 100644 optin_manager/src/config/openflow/optin_manager/apache/vhost-optinmgr.conf create mode 100644 optin_manager/src/config/openflow/optin_manager/common/apache/vhost-macros.conf create mode 100644 optin_manager/src/python/openflow/__init__.py create mode 100644 optin_manager/src/python/openflow/common/__init__.py create mode 100644 optin_manager/src/python/openflow/common/backends/__init__.py create mode 100644 optin_manager/src/python/openflow/common/backends/remoteuser.py create mode 100644 optin_manager/src/python/openflow/common/breadcrumbs/__init__.py create mode 100644 optin_manager/src/python/openflow/common/breadcrumbs/templatetags/__init__.py create mode 100644 optin_manager/src/python/openflow/common/breadcrumbs/templatetags/breadcrumbs.py create mode 100644 optin_manager/src/python/openflow/common/defaultsite/__init__.py create mode 100644 optin_manager/src/python/openflow/common/defaultsite/management.py create mode 100644 optin_manager/src/python/openflow/common/defaultsite/settings.py create mode 100644 optin_manager/src/python/openflow/common/extendable/__init__.py create mode 100644 optin_manager/src/python/openflow/common/extendable/inheritance.py create mode 100644 optin_manager/src/python/openflow/common/extendable/models.py create mode 100644 optin_manager/src/python/openflow/common/extendable/tests/__init__.py create mode 100644 optin_manager/src/python/openflow/common/extendable/tests/models.py create mode 100644 optin_manager/src/python/openflow/common/extendable/tests/tests.py create mode 100644 optin_manager/src/python/openflow/common/extendable/utils.py create mode 100644 optin_manager/src/python/openflow/common/extendable/views.py create mode 100644 optin_manager/src/python/openflow/common/loggingconf.py create mode 100644 optin_manager/src/python/openflow/common/messaging/__init__.py create mode 100644 optin_manager/src/python/openflow/common/messaging/admin.py create mode 100644 optin_manager/src/python/openflow/common/messaging/context_processors.py create mode 100644 optin_manager/src/python/openflow/common/messaging/forms.py create mode 100644 optin_manager/src/python/openflow/common/messaging/models.py create mode 100644 optin_manager/src/python/openflow/common/messaging/tests.py create mode 100644 optin_manager/src/python/openflow/common/messaging/urls.py create mode 100644 optin_manager/src/python/openflow/common/messaging/views.py create mode 100644 optin_manager/src/python/openflow/common/middleware/__init__.py create mode 100644 optin_manager/src/python/openflow/common/middleware/basicauth.py create mode 100644 optin_manager/src/python/openflow/common/middleware/sitelockdown.py create mode 100644 optin_manager/src/python/openflow/common/middleware/threadlocals.py create mode 100644 optin_manager/src/python/openflow/common/middleware/utils.py create mode 100644 optin_manager/src/python/openflow/common/permissions/__init__.py create mode 100644 optin_manager/src/python/openflow/common/permissions/admin.py create mode 100644 optin_manager/src/python/openflow/common/permissions/backend.py create mode 100644 optin_manager/src/python/openflow/common/permissions/decorators.py create mode 100644 optin_manager/src/python/openflow/common/permissions/exceptions.py create mode 100644 optin_manager/src/python/openflow/common/permissions/forms.py create mode 100644 optin_manager/src/python/openflow/common/permissions/management.py create mode 100644 optin_manager/src/python/openflow/common/permissions/middleware.py create mode 100644 optin_manager/src/python/openflow/common/permissions/models.py create mode 100644 optin_manager/src/python/openflow/common/permissions/permissions.py create mode 100644 optin_manager/src/python/openflow/common/permissions/tests/__init__.py create mode 100644 optin_manager/src/python/openflow/common/permissions/tests/models.py create mode 100644 optin_manager/src/python/openflow/common/permissions/tests/test_urls.py create mode 100644 optin_manager/src/python/openflow/common/permissions/tests/tests.py create mode 100644 optin_manager/src/python/openflow/common/permissions/tests/views.py create mode 100644 optin_manager/src/python/openflow/common/permissions/urls.py create mode 100644 optin_manager/src/python/openflow/common/permissions/utils.py create mode 100644 optin_manager/src/python/openflow/common/permissions/views.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/__init__.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/jsonrpcdispatcher.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/models.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/rpcdispatcher.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/templates/rpc4django/rpcmethod_summary.html create mode 100644 optin_manager/src/python/openflow/common/rpc4django/templatetags/__init__.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/templatetags/rpctags.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/tests/__init__.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/tests/test_jsonrpcdispatcher.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/tests/test_rpcdispatcher.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/tests/test_rpcviews.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/tests/test_urls.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/tests/test_xmlrpcdispatcher.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/tests/testmod/__init__.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/tests/testmod/models.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/tests/testmod/testsubmod/__init__.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/utils.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/views.py create mode 100644 optin_manager/src/python/openflow/common/rpc4django/xmlrpcdispatcher.py create mode 100644 optin_manager/src/python/openflow/common/tests/__init__.py create mode 100644 optin_manager/src/python/openflow/common/tests/client.py create mode 100644 optin_manager/src/python/openflow/common/tests/commands.py create mode 100644 optin_manager/src/python/openflow/common/tests/manager.py create mode 100644 optin_manager/src/python/openflow/common/tests/utils.py create mode 100644 optin_manager/src/python/openflow/common/utils/OptinThemeManager.py create mode 100644 optin_manager/src/python/openflow/common/utils/__init__.py create mode 100644 optin_manager/src/python/openflow/common/utils/certtransport.py create mode 100644 optin_manager/src/python/openflow/common/utils/context_processors.py create mode 100644 optin_manager/src/python/openflow/common/utils/formfields.py create mode 100644 optin_manager/src/python/openflow/common/utils/managers.py create mode 100644 optin_manager/src/python/openflow/common/utils/modelfields.py create mode 100644 optin_manager/src/python/openflow/common/utils/templatetags/__init__.py create mode 100644 optin_manager/src/python/openflow/common/utils/templatetags/ch_extras.py create mode 100644 optin_manager/src/python/openflow/common/utils/templatetags/url.py create mode 100644 optin_manager/src/python/openflow/common/utils/transport.py create mode 100644 optin_manager/src/python/openflow/common/utils/validators.py create mode 100644 optin_manager/src/python/openflow/common/utils/views.py create mode 100644 optin_manager/src/python/openflow/common/xmlrpc_serverproxy/__init__.py create mode 100644 optin_manager/src/python/openflow/common/xmlrpc_serverproxy/admin.py create mode 100644 optin_manager/src/python/openflow/common/xmlrpc_serverproxy/forms.py create mode 100644 optin_manager/src/python/openflow/common/xmlrpc_serverproxy/models.py create mode 100644 optin_manager/src/python/openflow/dummyom/__init__.py create mode 100644 optin_manager/src/python/openflow/dummyom/ch_api.py create mode 100644 optin_manager/src/python/openflow/dummyom/models.py create mode 100644 optin_manager/src/python/openflow/dummyom/urls.py create mode 100644 optin_manager/src/python/openflow/optin_manager/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/admin_manager/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/admin_manager/admin.py create mode 100644 optin_manager/src/python/openflow/optin_manager/admin_manager/forms.py create mode 100644 optin_manager/src/python/openflow/optin_manager/admin_manager/helper.py create mode 100644 optin_manager/src/python/openflow/optin_manager/admin_manager/models.py create mode 100644 optin_manager/src/python/openflow/optin_manager/admin_manager/tests.py create mode 100644 optin_manager/src/python/openflow/optin_manager/admin_manager/urls.py create mode 100644 optin_manager/src/python/openflow/optin_manager/admin_manager/views.py create mode 100644 optin_manager/src/python/openflow/optin_manager/auto_approval_scripts/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/auto_approval_scripts/approve_all.py create mode 100644 optin_manager/src/python/openflow/optin_manager/auto_approval_scripts/approve_sender_ip.py create mode 100644 optin_manager/src/python/openflow/optin_manager/auto_approval_scripts/postpone_all.py create mode 100644 optin_manager/src/python/openflow/optin_manager/auto_approval_scripts/reject_all.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/commands/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/commands/bootstrap_local_settings.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/commands/clean_inconsistent_db_entries.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/commands/create_default_root.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/commands/create_secret_key.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/commands/install_cert_makefile.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/commands/setup_media.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/commands/setup_optin_manager.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/commands/standardize_flowvisor_slices.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/management/commands/test_om.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/models.py create mode 100644 optin_manager/src/python/openflow/optin_manager/commands/utils.py create mode 100644 optin_manager/src/python/openflow/optin_manager/controls/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/controls/forms.py create mode 100644 optin_manager/src/python/openflow/optin_manager/controls/models.py create mode 100644 optin_manager/src/python/openflow/optin_manager/controls/tests.py create mode 100644 optin_manager/src/python/openflow/optin_manager/controls/urls.py create mode 100644 optin_manager/src/python/openflow/optin_manager/controls/views.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/admin_manager.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/admins.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/database.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/django.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/email.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/openflowtests.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/optin_manager.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/required.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/site.py create mode 100644 optin_manager/src/python/openflow/optin_manager/defaultsettings/tests.py create mode 100644 optin_manager/src/python/openflow/optin_manager/dummyfv/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/dummyfv/admin.py create mode 100644 optin_manager/src/python/openflow/optin_manager/dummyfv/models.py create mode 100644 optin_manager/src/python/openflow/optin_manager/dummyfv/rpc.py create mode 100644 optin_manager/src/python/openflow/optin_manager/dummyfv/urls.py create mode 100644 optin_manager/src/python/openflow/optin_manager/ethz_code/xmlrpc_server_ch_api_ethmerged create mode 100644 optin_manager/src/python/openflow/optin_manager/ethz_code/xmlrpc_server_models_ethmerged create mode 100644 optin_manager/src/python/openflow/optin_manager/flowspace/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/flowspace/helper.py create mode 100644 optin_manager/src/python/openflow/optin_manager/flowspace/models.py create mode 100644 optin_manager/src/python/openflow/optin_manager/flowspace/tests.py create mode 100644 optin_manager/src/python/openflow/optin_manager/flowspace/utils.py create mode 100644 optin_manager/src/python/openflow/optin_manager/flowspace/views.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/configurators/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/configurators/optin.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/drivers/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/drivers/optin.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/managers/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/managers/optin.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/settings/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/settings/optin.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/tests/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/tests/drivers/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/tests/drivers/optin/devicetest.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/tests/handler/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/tests/handler/listresources.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/fed4fire.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/fuseco.gid create mode 100755 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/geni-carolina.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/netmode.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/ocf.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/ofam.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/omf.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/ple.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/smartsantander.gid create mode 100755 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/topdomain.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/trusted_roots/wall2.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/utils/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/utils/flowvisor.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/utils/optin.py create mode 100644 optin_manager/src/python/openflow/optin_manager/geni/v3/utils/sliver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/localsettings-example create mode 100644 optin_manager/src/python/openflow/optin_manager/manage.py create mode 100644 optin_manager/src/python/openflow/optin_manager/monitoring/BackgroundMonitor.py create mode 100644 optin_manager/src/python/openflow/optin_manager/monitoring/SessionMonitoringThread.py create mode 100644 optin_manager/src/python/openflow/optin_manager/monitoring/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/monitoring/background_expiration_monitoring.py create mode 100644 optin_manager/src/python/openflow/optin_manager/monitoring/reservation.py create mode 100644 optin_manager/src/python/openflow/optin_manager/monitoring/util/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/monitoring/util/expiration_manager.py create mode 100644 optin_manager/src/python/openflow/optin_manager/monitoring/util/queue.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/admin.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/autofsgranter.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/forms.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/helper.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/models.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/tests.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/urls.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/views.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/vlans/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/opts/vlans/vlanController.py create mode 100644 optin_manager/src/python/openflow/optin_manager/settings.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/.gitignore create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/__init__.py create mode 100755 optin_manager/src/python/openflow/optin_manager/sfa/add_gid.sh create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/credentials/topdomain.cred create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/drivers/OFAggregate.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/drivers/OFSfaDriver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/drivers/OFShell.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/drivers/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/jfed_roots/jfed.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/jfed_roots/jfed2.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/jfed_roots/jfed3.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/jfed_roots/jfed4.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/jfed_roots/jfed5.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/jfed_roots/jfed6.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/jfed_roots/jfed8.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/jfed_roots/ocf_of.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/jfed_roots/wall.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/jfed_roots/wall2.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/managers/AggregateManager.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/managers/MetaSfaRegistry.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/managers/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/.ListResources.py.swo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/CreateGid.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/CreateSliver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/DeleteSliver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/GetCredential.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/GetGids.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/GetSelfCredential.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/GetTicket.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/GetVersion.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/List.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/ListResources.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/ListResources.py.bak create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/ListSlices.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/RedeemTicket.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/Register.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/Remove.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/RenewSliver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/Resolve.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/ResolveGENI.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/Shutdown.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/SliverStatus.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/Start.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/Stop.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/Update.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/UpdateSliver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/get_key_from_incoming_ip.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/get_trusted_certs.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/permission_manager.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/methods/reset_slice.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/models.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/my_roots/authorities/topdomain/topdomain.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/my_roots/authorities/topdomain/topdomain.pkey create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/openflow_utils/CreateOFSliver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/openflow_utils/ServiceThread.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/openflow_utils/SliverRSpecParser.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/openflow_utils/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/openflow_utils/delete_slice.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/openflow_utils/expiration_manager.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/openflow_utils/federationlinkmanager.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/openflow_utils/foam_rspec_lib.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/openflow_utils/rspec3_to_expedient.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/openflow_utils/sliver_status.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/__init__.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/bwlimit.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/bwlimit.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/channel.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/channel.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/disk_image.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/disk_image.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/element.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/element.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/execute.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/execute.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/fw_rule.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/fw_rule.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/granularity.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/granularity.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/hardware_type.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/hardware_type.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/install.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/install.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/interface.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/interface.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/lease.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/lease.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/link.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/link.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/location.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/location.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/login.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/login.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/network_interface.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/node.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/node.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/ocf_vt_server.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/openflow_switch.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/pltag.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/pltag.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/position_3d.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/position_3d.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/property.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/property.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/range.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/services.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/services.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/sliver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/sliver.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/spectrum.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/spectrum.pyo create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/nitosv1Channel.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/nitosv1Lease.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/nitosv1Node.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/nitosv1PLTag.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/nitosv1Sliver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/ocfofNode.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/ocfofSlivers.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/ocfvtNode.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/ocfvtSlivers.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/ocfvtSlivers.py.old create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/pgv2DiskImage.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/pgv2Interface.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/pgv2Link.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/pgv2Node.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/pgv2Services.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/pgv2SliverType.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/plosv1FWRule.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/sfav1Lease.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/sfav1Node.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/sfav1PLTag.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/versions/sfav1Sliver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/vm.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/elements/vm_interface.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/pg_rspec_converter.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/rspec.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/rspec_converter.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/rspec_elements.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/sfa_rspec_converter.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/version.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/version_manager.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/versions/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/versions/ocfofv1.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/rspecs/versions/ocfvtv1.py create mode 100755 optin_manager/src/python/openflow/optin_manager/sfa/schemas/credential.xsd create mode 100755 optin_manager/src/python/openflow/optin_manager/sfa/schemas/protogeni-rspec-common.xsd create mode 100755 optin_manager/src/python/openflow/optin_manager/sfa/schemas/sig.xsd create mode 100755 optin_manager/src/python/openflow/optin_manager/sfa/schemas/top.xsd create mode 100755 optin_manager/src/python/openflow/optin_manager/sfa/schemas/xml.xsd create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/server/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/server/registry.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/server/sfaclientlib.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/server/sm_test.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/setUp/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/setUp/authority_create.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/setUp/credential_create.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/setUp/setup.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/setUp/setup_config-EXAMPLE create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/sfa_config/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/sfa_config/config.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/SLIVER_EXAMPLE create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/ad.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/create_sliver.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/credential_create.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/credential_procedure/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/credential_procedure/testing_credentials.py create mode 100755 optin_manager/src/python/openflow/optin_manager/sfa/tests/credential_procedure/topdomain.nitos.pi.user.cred create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/data_example.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/list_resources.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/manage_slice.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/of_rspec.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/resources_example create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/sliver_example.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/sliver_status.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/tests/to_openflow_rspec.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/trust/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/trust/auth.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/trust/certificate.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/trust/credential.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/trust/credential_legacy.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/trust/gid.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/trust/hierarchy.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/trust/rights.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/trust/sfaticket.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/trust/trustedroots.py create mode 100755 optin_manager/src/python/openflow/optin_manager/sfa/trusted_roots/optin_ocf.gid create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/cache.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/callids.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/config.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/defaultdict.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/enumeration.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/faults.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/genicode.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/method.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/parameter.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/sfalogging.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/sfatime.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/version.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/xml.py create mode 100644 optin_manager/src/python/openflow/optin_manager/sfa/util/xrn.py create mode 100644 optin_manager/src/python/openflow/optin_manager/testparser.py create mode 100644 optin_manager/src/python/openflow/optin_manager/urls.py create mode 100644 optin_manager/src/python/openflow/optin_manager/users/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/users/admin.py create mode 100644 optin_manager/src/python/openflow/optin_manager/users/forms.py create mode 100644 optin_manager/src/python/openflow/optin_manager/users/models.py create mode 100644 optin_manager/src/python/openflow/optin_manager/users/user_signal_handler.py create mode 100644 optin_manager/src/python/openflow/optin_manager/users/views.py create mode 100644 optin_manager/src/python/openflow/optin_manager/xmlrpc_server/__init__.py create mode 100644 optin_manager/src/python/openflow/optin_manager/xmlrpc_server/ch_api.py create mode 100644 optin_manager/src/python/openflow/optin_manager/xmlrpc_server/fv_api.py create mode 100644 optin_manager/src/python/openflow/optin_manager/xmlrpc_server/gapi3.py create mode 100644 optin_manager/src/python/openflow/optin_manager/xmlrpc_server/models.py create mode 100644 optin_manager/src/python/openflow/optin_manager/xmlrpc_server/sfa_api.py create mode 100644 optin_manager/src/python/openflow/optin_manager/xmlrpc_server/tests.py create mode 100644 optin_manager/src/python/openflow/optin_manager/xmlrpc_server/urls.py create mode 100644 optin_manager/src/python/openflow/tests/__init__.py create mode 100644 optin_manager/src/python/openflow/tests/full/__init__.py create mode 100644 optin_manager/src/python/openflow/tests/full/fulltests.py create mode 100644 optin_manager/src/python/openflow/tests/full/helpers.py create mode 100644 optin_manager/src/python/openflow/tests/helpers.py create mode 100644 optin_manager/src/python/openflow/tests/manual_test/__init__.py create mode 100644 optin_manager/src/python/openflow/tests/manual_test/manual.py create mode 100644 optin_manager/src/python/openflow/tests/omctl/XMLRPCServerProxy.py create mode 100644 optin_manager/src/python/openflow/tests/omctl/__init__.py create mode 100644 optin_manager/src/python/openflow/tests/omctl/helpers.py create mode 100644 optin_manager/src/python/openflow/tests/omctl/omctl.py create mode 100644 optin_manager/src/python/openflow/tests/omctl/omctl_settings.py create mode 100644 optin_manager/src/python/openflow/tests/post_deployment/__init__.py create mode 100644 optin_manager/src/python/openflow/tests/post_deployment/tests.py create mode 100644 optin_manager/src/python/openflow/tests/ssl/Makefile create mode 100644 optin_manager/src/python/openflow/tests/test_settings.py create mode 100644 optin_manager/src/python/openflow/tests/tests.py create mode 100644 optin_manager/src/python/optin_manager-0.2.3-py2.6.egg-info/PKG-INFO create mode 100644 optin_manager/src/python/optin_manager-0.2.3-py2.6.egg-info/SOURCES.txt create mode 100644 optin_manager/src/python/optin_manager-0.2.3-py2.6.egg-info/dependency_links.txt create mode 100644 optin_manager/src/python/optin_manager-0.2.3-py2.6.egg-info/entry_points.txt create mode 100644 optin_manager/src/python/optin_manager-0.2.3-py2.6.egg-info/not-zip-safe create mode 100644 optin_manager/src/python/optin_manager-0.2.3-py2.6.egg-info/requires.txt create mode 100644 optin_manager/src/python/optin_manager-0.2.3-py2.6.egg-info/top_level.txt create mode 100644 optin_manager/src/python/scripts/__init__.py create mode 100644 optin_manager/src/python/scripts/create-superuser.py create mode 100644 optin_manager/src/python/scripts/create-users.py create mode 100644 optin_manager/src/python/scripts/create_oms.py create mode 100644 optin_manager/src/python/scripts/setup_ch.py create mode 100644 optin_manager/src/python/scripts/setup_expedient_params_clean.py create mode 100644 optin_manager/src/python/scripts/setup_om.py create mode 100644 optin_manager/src/static/openflow/optin_manager/media/FELIX/logo_optin.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/FELIX/ocf.css create mode 100644 optin_manager/src/static/openflow/optin_manager/media/FIBRE/logo_optin.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/account.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/active.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/add_rule_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/add_rule_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/admin_abandon_fs_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/admin_abandon_fs_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/admin_fs_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/admin_fs_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/admin_fses_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/admin_fses_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/admin_req_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/admin_req_fs_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/admin_req_fs_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/admin_req_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/aggregate-tiny.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/auto_approve_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/auto_approve_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/back_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/back_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/button.pxm create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/contact_exp_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/contact_exp_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/dashboard.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/dashboard_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/dashboard_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/edit_profile_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/edit_profile_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/egeni-iframe.css create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/experiments_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/experiments_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/favicon.ico create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/fs_req_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/fs_req_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/genilogo.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/give_up_fs_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/give_up_fs_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/help.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/host-tiny.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/inactive.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/js/formtable.tooltip.js create mode 100755 optin_manager/src/static/openflow/optin_manager/media/default/js/jquery.min.js create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/js/jquery.tools.min.js create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/js/tooltip.funcs.js create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/logo_optin.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/logout.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/logout_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/logout_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/manage_fs_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/manage_fs_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/manage_site_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/manage_site_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/ocf.css create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/optin_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/optin_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/optout_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/optout_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/profile_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/profile_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/promote_to_admin_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/promote_to_admin_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/question_mark_15x15.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/remove_rule_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/remove_rule_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/request_fs_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/request_fs_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/resign_admin_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/resign_admin_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/sample_rules.txt create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/set_ch_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/set_ch_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/set_fv_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/set_fv_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/set_priority_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/set_priority_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/set_rule_priority_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/set_rule_priority_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/slice-tiny.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/slice.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/step0_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/step0_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/step1_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/step2_manage_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/step2_manage_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/step2_optin_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/step2_optin_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/step2_optout_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/step2_optout_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/switch-5406zl.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/switch-cat6500.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/switch-juniper.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/switch-nec-ip8800.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/switch-netfpga.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/switch-nf2.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/switch-tiny.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/switch.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/tooltip.css create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/user_fses_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/user_fses_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/user_req_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/user_req_light.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/users-tiny.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/view_exp_dark.png create mode 100644 optin_manager/src/static/openflow/optin_manager/media/default/view_exp_light.png create mode 100644 optin_manager/src/templates/FELIX/openflow/optin_manager/base.html create mode 100644 optin_manager/src/templates/FELIX/openflow/optin_manager/base_admin.html create mode 100644 optin_manager/src/templates/FELIX/openflow/optin_manager/base_user.html create mode 100644 optin_manager/src/templates/FELIX/openflow/optin_manager/footer.html create mode 100644 optin_manager/src/templates/FIBRE/openflow/optin_manager/base.html create mode 100644 optin_manager/src/templates/FIBRE/openflow/optin_manager/base_admin.html create mode 100644 optin_manager/src/templates/FIBRE/openflow/optin_manager/base_user.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/admin_req_fs.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/admin_request_successful.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/admin_unreg_fs.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/approve_admin.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/approve_user.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/change_admin_fs.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/change_user_fs.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/manage_admin_fs.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/manage_user_fs.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/promote_to_admin.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/reg_request_successful.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/resign_admin.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/set_auto_approve.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/user_reg_fs.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/admin_manager/user_unreg_fs.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/base.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/base_admin.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/base_user.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/controls/set_clearinghouse.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/controls/set_flowvisor.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/dashboard_admin.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/dashboard_user.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/footer.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/index.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/admin_opt_in.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/admin_opt_out.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/change_priority_successful.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/opt_in_successful_admin.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/opt_in_successful_user.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/user_opt_in.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/user_opt_out.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/view_experiment_admin.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/view_experiment_simple.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/view_experiment_user.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/view_experiments_admin.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/view_experiments_user.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/view_opt_simple.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/view_opts_admin.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/opts/view_opts_user.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/registration/activate.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/registration/activation_email.txt create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/registration/activation_email_subject.txt create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/registration/login.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/registration/logout.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/registration/registration_complete.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/registration/registration_form.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/tooltip.funcs.js create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/users/change_profile_admin.html create mode 100644 optin_manager/src/templates/default/openflow/optin_manager/users/change_profile_user.html create mode 100644 optin_manager/src/wsgi/openflow/optin_manager/auth.wsgi create mode 100644 optin_manager/src/wsgi/openflow/optin_manager/django.wsgi create mode 100644 optin_manager/src/wsgi/openflow/optin_manager/mon.wsgi create mode 100644 optin_manager/version create mode 100644 vt_manager/.gitignore create mode 120000 vt_manager/bin/common create mode 100644 vt_manager/bin/log/.gitignore create mode 120000 vt_manager/bin/ofver create mode 120000 vt_manager/bin/repo create mode 100644 vt_manager/bin/rescue/.gitignore create mode 120000 vt_manager/bin/settings create mode 100644 vt_manager/bin/versions/0.12/upgrade/0.11/post-upgrade-hook create mode 100644 vt_manager/bin/versions/0.13/upgrade/0.12/backup create mode 100644 vt_manager/bin/versions/0.13/upgrade/0.12/pre-backup-upgrade-hook create mode 100644 vt_manager/bin/versions/0.14.2/install/post-install-hook create mode 100644 vt_manager/bin/versions/0.14.2/upgrade/default/post-upgrade-hook create mode 100644 vt_manager/bin/versions/0.2/upgrade/default/post-upgrade-hook create mode 120000 vt_manager/bin/versions/0.2RC1 create mode 100644 vt_manager/bin/versions/0.3/upgrade/default/post-upgrade-hook create mode 120000 vt_manager/bin/versions/0.3/upgrade/default/pre-upgrade-hook create mode 120000 vt_manager/bin/versions/0.3RC1 create mode 120000 vt_manager/bin/versions/0.4.1 create mode 120000 vt_manager/bin/versions/0.4.2 create mode 120000 vt_manager/bin/versions/0.4.3 create mode 100644 vt_manager/bin/versions/0.4/upgrade/default/post-upgrade-hook create mode 100644 vt_manager/bin/versions/0.4/upgrade/default/pre-upgrade-hook create mode 100755 vt_manager/bin/versions/0.4/upgrade/default/tools/vmCallBackURLupdate.py create mode 120000 vt_manager/bin/versions/0.5 create mode 120000 vt_manager/bin/versions/0.6 create mode 120000 vt_manager/bin/versions/0.6.1 create mode 100644 vt_manager/bin/versions/0.7/upgrade/default/pre-upgrade-hook create mode 120000 vt_manager/bin/versions/0.8 create mode 120000 vt_manager/bin/versions/0.8.1 create mode 120000 vt_manager/bin/versions/0.8.2 create mode 120000 vt_manager/bin/versions/0.8.3/upgrade/default/lib create mode 100644 vt_manager/bin/versions/0.8.3/upgrade/default/pre-upgrade-hook create mode 100644 vt_manager/bin/versions/0.8.3/upgrade/default/upgrade create mode 100644 vt_manager/bin/versions/default/install/backup create mode 100644 vt_manager/bin/versions/default/install/install create mode 100644 vt_manager/bin/versions/default/install/lib/dependencies create mode 100644 vt_manager/bin/versions/default/install/lib/django-db create mode 100644 vt_manager/bin/versions/default/install/lib/django-settings create mode 120000 vt_manager/bin/versions/default/install/lib/pypelib create mode 120000 vt_manager/bin/versions/default/install/lib/set_environment_variables create mode 100644 vt_manager/bin/versions/default/install/lib/sfa-settings create mode 100644 vt_manager/bin/versions/default/install/lib/ssl create mode 100644 vt_manager/bin/versions/default/install/post-install-hook create mode 100644 vt_manager/bin/versions/default/install/pre-install-hook create mode 100644 vt_manager/bin/versions/default/install/repo create mode 100644 vt_manager/bin/versions/default/install/rollback create mode 100644 vt_manager/bin/versions/default/upgrade/default/backup create mode 100644 vt_manager/bin/versions/default/upgrade/default/dependencies create mode 120000 vt_manager/bin/versions/default/upgrade/default/lib/set_environment_variables create mode 100644 vt_manager/bin/versions/default/upgrade/default/post-upgrade-hook create mode 100644 vt_manager/bin/versions/default/upgrade/default/pre-upgrade-hook create mode 100644 vt_manager/bin/versions/default/upgrade/default/rollback create mode 100644 vt_manager/bin/versions/default/upgrade/default/upgrade create mode 100755 vt_manager/bin/versions/default/upgrade/tools/UpgradeTools.py create mode 100644 vt_manager/bin/versions/default/upgrade/tools/prova.cfg create mode 120000 vt_manager/bin/versions/default/upgrade/tools/sqlDump.py create mode 120000 vt_manager/bin/versions/default/upgrade/tools/sqlRestore.py create mode 120000 vt_manager/bin/versions/version-checks create mode 100755 vt_manager/src/config/agent/OfeliaLauncher.sh create mode 100755 vt_manager/src/config/agent/oxad create mode 100755 vt_manager/src/config/agent/oxad-python create mode 100755 vt_manager/src/config/agent/prova.py create mode 100644 vt_manager/src/config/vt_manager/apache/vhost-macros-vt.conf create mode 100644 vt_manager/src/config/vt_manager/apache/vhost-vt.conf create mode 100644 vt_manager/src/config/vt_manager/common/apache/vhost-macros.conf create mode 100755 vt_manager/src/python/agent/OfeliaAgent.py create mode 100755 vt_manager/src/python/agent/README.md create mode 100644 vt_manager/src/python/agent/__init__.py create mode 100644 vt_manager/src/python/agent/communications/XmlRpcClient.py create mode 100644 vt_manager/src/python/agent/communications/XmlRpcServer.py create mode 100644 vt_manager/src/python/agent/communications/__init__.py create mode 100644 vt_manager/src/python/agent/communications/prova.xml create mode 100644 vt_manager/src/python/agent/communications/tests/client.py create mode 100644 vt_manager/src/python/agent/communications/tests/mon.xml create mode 100644 vt_manager/src/python/agent/communications/tests/prov.xml create mode 100644 vt_manager/src/python/agent/communications/tests/prova2.xml create mode 100644 vt_manager/src/python/agent/monitoring/LibvirtMonitoring.py create mode 100644 vt_manager/src/python/agent/monitoring/MonitoringDispatcher.py create mode 100644 vt_manager/src/python/agent/monitoring/__init__.py create mode 100644 vt_manager/src/python/agent/mySettings-example.py create mode 100644 vt_manager/src/python/agent/provisioning/ProvisioningDispatcher.py create mode 100644 vt_manager/src/python/agent/provisioning/__init__.py create mode 100644 vt_manager/src/python/agent/security/__init__.py create mode 100644 vt_manager/src/python/agent/security/certs/Makefile create mode 100644 vt_manager/src/python/agent/settings/__init__.py create mode 100644 vt_manager/src/python/agent/settings/settingsLoader.py create mode 100644 vt_manager/src/python/agent/settings/spirentSettings.py create mode 100644 vt_manager/src/python/agent/settings/staticSettings.py create mode 120000 vt_manager/src/python/agent/tools/common create mode 100644 vt_manager/src/python/agent/tools/log/.gitignore create mode 120000 vt_manager/src/python/agent/tools/ofver create mode 120000 vt_manager/src/python/agent/tools/repo create mode 100644 vt_manager/src/python/agent/tools/rescue/.gitignore create mode 120000 vt_manager/src/python/agent/tools/settings create mode 120000 vt_manager/src/python/agent/tools/versions/0.12/upgrade/0.11/lib/template create mode 100644 vt_manager/src/python/agent/tools/versions/0.12/upgrade/0.11/post-upgrade-hook create mode 100644 vt_manager/src/python/agent/tools/versions/0.3/upgrade/default/post-upgrade-hook create mode 120000 vt_manager/src/python/agent/tools/versions/0.3/upgrade/default/pre-upgrade-hook create mode 120000 vt_manager/src/python/agent/tools/versions/0.3RC1 create mode 100644 vt_manager/src/python/agent/tools/versions/0.5/upgrade/default/post-upgrade-hook create mode 100644 vt_manager/src/python/agent/tools/versions/0.5/upgrade/default/pre-upgrade-hook create mode 100644 vt_manager/src/python/agent/tools/versions/0.8.2/upgrade/default/pre-upgrade-hook create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/backup create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/install create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/lib/daemon create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/lib/dependencies create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/lib/directories create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/lib/settings create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/lib/ssl create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/lib/template create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/post-install-hook create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/pre-install-hook create mode 100644 vt_manager/src/python/agent/tools/versions/default/install/rollback create mode 100644 vt_manager/src/python/agent/tools/versions/default/upgrade/default/backup create mode 120000 vt_manager/src/python/agent/tools/versions/default/upgrade/default/lib/get_templates.py create mode 120000 vt_manager/src/python/agent/tools/versions/default/upgrade/default/lib/template create mode 100644 vt_manager/src/python/agent/tools/versions/default/upgrade/default/post-upgrade-hook create mode 100644 vt_manager/src/python/agent/tools/versions/default/upgrade/default/pre-upgrade-hook create mode 100644 vt_manager/src/python/agent/tools/versions/default/upgrade/default/rollback create mode 100644 vt_manager/src/python/agent/tools/versions/default/upgrade/default/upgrade create mode 120000 vt_manager/src/python/agent/tools/versions/version-checks create mode 100644 vt_manager/src/python/agent/utils/AgentExceptions.py create mode 100644 vt_manager/src/python/agent/utils/LibvirtLogger.py create mode 100644 vt_manager/src/python/agent/utils/Logger.py create mode 100644 vt_manager/src/python/agent/utils/MonitoringCallbackFunctions.py create mode 100644 vt_manager/src/python/agent/utils/ServiceThread.py create mode 100644 vt_manager/src/python/agent/utils/VmMutexStore.py create mode 100644 vt_manager/src/python/agent/utils/XmlUtils.py create mode 100644 vt_manager/src/python/agent/utils/__init__.py create mode 100644 vt_manager/src/python/agent/utils/template_downloader/ordered_dict.py create mode 100644 vt_manager/src/python/agent/utils/template_downloader/template_downloader.py create mode 100644 vt_manager/src/python/agent/utils/xml/Makefile create mode 100644 vt_manager/src/python/agent/utils/xml/__init__.py create mode 100644 vt_manager/src/python/agent/utils/xml/emptyMonitoringResponse.xml create mode 100644 vt_manager/src/python/agent/utils/xml/emptyMonitoringVMsInfoResponse.xml create mode 100644 vt_manager/src/python/agent/utils/xml/emptyProvisioningResponse.xml create mode 100644 vt_manager/src/python/agent/utils/xml/query.xml create mode 100644 vt_manager/src/python/agent/utils/xml/response.xml create mode 100644 vt_manager/src/python/agent/utils/xml/schema.xsd create mode 100644 vt_manager/src/python/agent/utils/xml/vtRspecInterface.py create mode 100644 vt_manager/src/python/agent/utils/xml/vtRspecInterfaceStub.py create mode 100644 vt_manager/src/python/agent/version create mode 100644 vt_manager/src/python/agent/xen/XendManager.py create mode 100644 vt_manager/src/python/agent/xen/__init__.py create mode 100644 vt_manager/src/python/agent/xen/monitoring/DomainMonitor.py create mode 100644 vt_manager/src/python/agent/xen/monitoring/XenMonitoringDispatcher.py create mode 100644 vt_manager/src/python/agent/xen/monitoring/__init__.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/HdManager.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/VMConfigurator.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/XenProvisioningDispatcher.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/__init__.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/__init__.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/debian7/DebianWheezyVMConfigurator.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/debian7/__init__.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/debian7/templates/fullVirtualizedFileHd.pt create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/irati/IratiDebianVMConfigurator.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/irati/__init__.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/irati/templates/fullVirtualizedFileHd.pt create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/mediacat/MediacatVMConfigurator.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/mediacat/__init__.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/mediacat/templates/mediacatHVMFileHd.pt create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/ofelia/OfeliaDebianVMConfigurator.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/ofelia/__init__.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/ofelia/templates/paraVirtualizedFileHd.pt create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/spirent/SpirentCentOSVMConfigurator.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/spirent/__init__.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/configurators/spirent/templates/spirentSTCVMTemplate.pt create mode 100644 vt_manager/src/python/agent/xen/provisioning/hdmanagers/FileFullHdManager.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/hdmanagers/FileHdManager.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/hdmanagers/LVMHdManager.py create mode 100644 vt_manager/src/python/agent/xen/provisioning/hdmanagers/__init__.py create mode 100644 vt_manager/src/python/agent/xen/xmlTest.py create mode 100644 vt_manager/src/python/scripts/__init__.py create mode 100644 vt_manager/src/python/scripts/create-superuser.py create mode 100644 vt_manager/src/python/scripts/create-users.py create mode 100644 vt_manager/src/python/scripts/create_oms.py create mode 100644 vt_manager/src/python/scripts/setup_ch.py create mode 100644 vt_manager/src/python/scripts/setup_expedient_params_clean.py create mode 100644 vt_manager/src/python/scripts/setup_om.py create mode 100644 vt_manager/src/python/vt_manager/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/backends/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/backends/remoteuser.py create mode 100644 vt_manager/src/python/vt_manager/common/commands/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/commands/management/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/commands/management/commands/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/commands/management/commands/clean_inconsistent_db_entries.py create mode 100644 vt_manager/src/python/vt_manager/common/commands/models.py create mode 100644 vt_manager/src/python/vt_manager/common/defaultsite/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/defaultsite/management.py create mode 100644 vt_manager/src/python/vt_manager/common/defaultsite/settings.py create mode 100644 vt_manager/src/python/vt_manager/common/longer_username/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/messaging/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/messaging/admin.py create mode 100644 vt_manager/src/python/vt_manager/common/messaging/context_processors.py create mode 100644 vt_manager/src/python/vt_manager/common/messaging/forms.py create mode 100644 vt_manager/src/python/vt_manager/common/messaging/models.py create mode 100644 vt_manager/src/python/vt_manager/common/messaging/tests.py create mode 100644 vt_manager/src/python/vt_manager/common/messaging/urls.py create mode 100644 vt_manager/src/python/vt_manager/common/messaging/views.py create mode 100644 vt_manager/src/python/vt_manager/common/middleware/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/middleware/basicauth.py create mode 100644 vt_manager/src/python/vt_manager/common/middleware/sitelockdown.py create mode 100644 vt_manager/src/python/vt_manager/common/middleware/thread_local.py create mode 100644 vt_manager/src/python/vt_manager/common/middleware/utils.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/jsonrpcdispatcher.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/models.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/rpcdispatcher.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/templates/rpc4django/rpcmethod_summary.html create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/templatetags/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/templatetags/rpctags.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/tests/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/tests/test_jsonrpcdispatcher.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/tests/test_rpcdispatcher.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/tests/test_rpcviews.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/tests/test_urls.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/tests/test_xmlrpcdispatcher.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/tests/testmod/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/tests/testmod/models.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/tests/testmod/testsubmod/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/utils.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/views.py create mode 100644 vt_manager/src/python/vt_manager/common/rpc4django/xmlrpcdispatcher.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/certtransport.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/context_processors.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/formfields.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/managers.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/modelfields.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/templatetags/__init__.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/templatetags/ch_extras.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/transport.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/validators.py create mode 100644 vt_manager/src/python/vt_manager/common/utils/views.py create mode 100644 vt_manager/src/python/vt_manager/communication/XmlRpcClient.py create mode 100644 vt_manager/src/python/vt_manager/communication/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/gapi3communication.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/configurators/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/configurators/handlerconfigurator.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/drivers/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/drivers/vtam.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/managers/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/managers/vtam.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/settings/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/settings/vtam.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/configurators/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/configurators/vtam/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/configurators/vtam/testcredentialmanager.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/configurators/vtam/testdriverconfiguration.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/configurators/vtam/testgeniexceptionmanagerconfiguration.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/configurators/vtam/testhandlerconfiguration.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/configurators/vtam/testresourcemanagerconfiguration.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/configurators/vtam/testrspecmanagerconfiguration.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/drivers/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/drivers/vtam/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/drivers/vtam/expected_outputs.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/drivers/vtam/testhrns.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/drivers/vtam/testreservation.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/drivers/vtam/testtranslatortoclass.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/drivers/vtam/testtranslatortodict.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/drivers/vtam/testurns.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/managers/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/managers/vtam/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/managers/vtam/testmanager.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/mockers/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/mockers/driver.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/mockers/reservation.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/mockers/resource.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/mockers/server.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/settings/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/settings/vtam/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/tests/settings/vtam/testsettings.py create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/fed4fire.gid create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/fuseco.gid create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/geni-ch.gid create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/netmode.gid create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/ocf.gid create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/ofam.gid create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/omf.gid create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/ple.gid create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/smartsantander.gid create mode 100755 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/topdomain.gid create mode 100644 vt_manager/src/python/vt_manager/communication/geni/v3/trusted_roots/wall2.gid create mode 100644 vt_manager/src/python/vt_manager/communication/northCommInterface.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/__init__.py create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/add_gid.sh create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/configs/config create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/configs/credentials.xsd create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/configs/sig.xsd create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/configs/top.xsd create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/credentials/ocf.cred create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/credentials/ocf.i2cat.cred create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/credentials/ocf.i2cat.ofam.cred create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/credentials/topdomain.cred create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/drivers/VMAggregate.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/drivers/VTSfaDriver.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/drivers/VTShell.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/drivers/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/jfed.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/jfed2.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/jfed3.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/jfed4.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/jfed5.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/jfed6.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/jfed8.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/ocf_of.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/ple.gid create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/topdomain.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/wall.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/jfed_roots/wall2.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/managers/AggregateManager.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/managers/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/CreateGid.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/CreateSliver.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/DeleteSliver.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/GetCredential.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/GetGids.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/GetSelfCredential.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/GetTicket.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/GetVersion.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/List.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/ListResources.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/ListResources.py.bak create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/ListSlices.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/RedeemTicket.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/Register.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/Remove.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/RenewSliver.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/Resolve.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/ResolveGENI.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/Shutdown.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/SliverStatus.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/Start.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/Stop.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/Update.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/UpdateSliver.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/get_key_from_incoming_ip.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/get_trusted_certs.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/permission_manager.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/methods/reset_slice.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/my_roots/authorities/ocf/ocf.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/my_roots/authorities/ocf/ocf.pkey create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/my_roots/authorities/ocf/ofam/ofam.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/my_roots/authorities/ocf/ofam/ofam.pkey create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/my_roots/authorities/topdomain/topdomain.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/my_roots/authorities/topdomain/topdomain.pkey create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/__init__.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/bwlimit.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/bwlimit.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/channel.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/channel.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/disk_image.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/disk_image.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/element.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/element.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/execute.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/execute.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/fw_rule.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/fw_rule.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/granularity.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/granularity.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/hardware_type.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/hardware_type.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/install.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/install.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/interface.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/interface.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/lease.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/lease.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/link.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/link.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/location.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/location.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/login.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/login.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/network_interface.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/node.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/node.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/ocf_vt_server.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/pltag.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/pltag.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/position_3d.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/position_3d.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/property.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/property.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/range.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/services.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/services.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/sliver.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/sliver.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/spectrum.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/spectrum.pyo create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/nitosv1Channel.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/nitosv1Lease.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/nitosv1Node.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/nitosv1PLTag.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/nitosv1Sliver.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/ocfvtNode.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/ocfvtSlivers.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/ocfvtSlivers.py.old create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/pgv2DiskImage.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/pgv2Interface.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/pgv2Link.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/pgv2Node.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/pgv2Services.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/pgv2SliverType.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/plosv1FWRule.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/sfav1Lease.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/sfav1Node.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/sfav1PLTag.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/versions/sfav1Sliver.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/vm.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/elements/vm_interface.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/pg_rspec_converter.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/rspec.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/rspec_converter.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/rspec_elements.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/sfa_rspec_converter.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/version.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/version_manager.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/versions/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/rspecs/versions/ocfvtv1.py create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/schemas/credential.xsd create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/schemas/protogeni-rspec-common.xsd create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/schemas/sig.xsd create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/schemas/top.xsd create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/schemas/xml.xsd create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/setUp/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/setUp/authority_create.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/setUp/setup.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/setUp/setup_config-EXAMPLE create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/setUp/setup_config.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/sfa_config/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/sfa_config/config-example create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/tests/Expected-Outputs/ListResources create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/tests/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/tests/example_vm_rspec.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/tests/hardcoded_vars.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/tests/response.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/tests/schema.xsd create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/tests/server_schema.xsd create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/tests/test_aggregate_manager.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/tests/vm_schema.xsd create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/tests/vm_schema.xsd.old create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/trust/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/trust/auth.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/trust/certificate.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/trust/credential.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/trust/credential_legacy.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/trust/gid.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/trust/hierarchy.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/trust/rights.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/trust/sfaticket.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/trust/trustedroots.py create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/trusted_roots/fed4fire.gid create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/trusted_roots/felix-ch.gid create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/trusted_roots/new_wall2.gid create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/trusted_roots/optin_ocf.gid create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/trusted_roots/ple.gid create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/trusted_roots/topdomain2.gid create mode 100755 vt_manager/src/python/vt_manager/communication/sfa/trusted_roots/wall2.gid create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/cache.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/callids.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/config.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/defaultdict.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/enumeration.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/faults.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/genicode.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/sfalogging.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/sfatime.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/version.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/xml.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/util/xrn.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/vm_utils/SfaCommunicator.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/vm_utils/Translator.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/vm_utils/VMSfaManager.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/vm_utils/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/vm_utils/expiration_manager.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfa/vm_utils/ldapManager.py create mode 100644 vt_manager/src/python/vt_manager/communication/sfaCommunication.py create mode 100644 vt_manager/src/python/vt_manager/communication/southCommInterface.py create mode 100644 vt_manager/src/python/vt_manager/communication/test_rpcmethod.py create mode 100644 vt_manager/src/python/vt_manager/communication/utils/XmlHelper.py create mode 100644 vt_manager/src/python/vt_manager/communication/utils/__init__.py create mode 100644 vt_manager/src/python/vt_manager/communication/utils/xml/emptyResponse.xml create mode 100644 vt_manager/src/python/vt_manager/communication/utils/xml/list.xml create mode 100644 vt_manager/src/python/vt_manager/communication/utils/xml/listActiveVMsQuery.xml create mode 100644 vt_manager/src/python/vt_manager/communication/utils/xml/queryProvisioning.xml create mode 100644 vt_manager/src/python/vt_manager/communication/utils/xml/simpleActionQuery.xml create mode 100644 vt_manager/src/python/vt_manager/communication/utils/xml/simpleListResources.xml create mode 100644 vt_manager/src/python/vt_manager/controller/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/actions/ActionController.py create mode 100644 vt_manager/src/python/vt_manager/controller/actions/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/forms/NetworkInterfaceForm.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/forms/ServerForm.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/forms/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/ui/GUIdispatcher.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/ui/PolicyDispatcher.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/ui/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/xmlrpc/DispatcherLauncher.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/xmlrpc/InformationDispatcher.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/xmlrpc/MonitoringResponseDispatcher.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/xmlrpc/ProvisioningDispatcher.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/xmlrpc/ProvisioningResponseDispatcher.py create mode 100644 vt_manager/src/python/vt_manager/controller/dispatchers/xmlrpc/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/drivers/VTDriver.py create mode 100644 vt_manager/src/python/vt_manager/controller/drivers/XenDriver.py create mode 100644 vt_manager/src/python/vt_manager/controller/drivers/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/monitoring/AgentMonitoringThread.py create mode 100644 vt_manager/src/python/vt_manager/controller/monitoring/BackgroundMonitor.py create mode 100644 vt_manager/src/python/vt_manager/controller/monitoring/SessionMonitoringThread.py create mode 100644 vt_manager/src/python/vt_manager/controller/monitoring/VMMonitor.py create mode 100644 vt_manager/src/python/vt_manager/controller/monitoring/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/monitoring/background_expiration_monitoring.py create mode 100644 vt_manager/src/python/vt_manager/controller/monitoring/backgroundexpiration.py create mode 100644 vt_manager/src/python/vt_manager/controller/monitoring/backgroundreservation.py create mode 100644 vt_manager/src/python/vt_manager/controller/networking/EthernetController.py create mode 100644 vt_manager/src/python/vt_manager/controller/networking/Ip4Controller.py create mode 100644 vt_manager/src/python/vt_manager/controller/networking/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/policies/ControllerMappings.py create mode 100644 vt_manager/src/python/vt_manager/controller/policies/RuleTableManager.py create mode 100644 vt_manager/src/python/vt_manager/controller/policies/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/policies/utils/PELogConf.py create mode 100644 vt_manager/src/python/vt_manager/controller/policies/utils/PolicyLogger.py create mode 100644 vt_manager/src/python/vt_manager/controller/policies/utils/__init__.py create mode 100755 vt_manager/src/python/vt_manager/controller/policies/utils/log/.gitignore create mode 100755 vt_manager/src/python/vt_manager/controller/policies/utils/log/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/users/__init__.py create mode 100644 vt_manager/src/python/vt_manager/controller/users/forms.py create mode 100644 vt_manager/src/python/vt_manager/controller/users/urlHandlers.py create mode 100644 vt_manager/src/python/vt_manager/manage.py create mode 100644 vt_manager/src/python/vt_manager/models/Action.py create mode 100644 vt_manager/src/python/vt_manager/models/Ip4Range.py create mode 100644 vt_manager/src/python/vt_manager/models/Ip4Slot.py create mode 100644 vt_manager/src/python/vt_manager/models/MacRange.py create mode 100644 vt_manager/src/python/vt_manager/models/MacSlot.py create mode 100644 vt_manager/src/python/vt_manager/models/NetworkInterface.py create mode 100644 vt_manager/src/python/vt_manager/models/VTServer.py create mode 100644 vt_manager/src/python/vt_manager/models/VirtualMachine.py create mode 100644 vt_manager/src/python/vt_manager/models/VirtualMachineKeys.py create mode 100644 vt_manager/src/python/vt_manager/models/XenServer.py create mode 100644 vt_manager/src/python/vt_manager/models/XenVM.py create mode 100644 vt_manager/src/python/vt_manager/models/__init__.py create mode 100644 vt_manager/src/python/vt_manager/models/expiring_components.py create mode 100644 vt_manager/src/python/vt_manager/models/faults.py create mode 100644 vt_manager/src/python/vt_manager/models/reservation.py create mode 100644 vt_manager/src/python/vt_manager/models/resourcesHash.py create mode 100644 vt_manager/src/python/vt_manager/models/tests/a.py create mode 100644 vt_manager/src/python/vt_manager/models/tests/b.py create mode 100644 vt_manager/src/python/vt_manager/models/utils/Choices.py create mode 100644 vt_manager/src/python/vt_manager/models/utils/__init__.py create mode 100644 vt_manager/src/python/vt_manager/mySettings-example create mode 100644 vt_manager/src/python/vt_manager/settings/__init__.py create mode 100644 vt_manager/src/python/vt_manager/settings/settingsLoader.py create mode 100644 vt_manager/src/python/vt_manager/settings/staticSettings.py create mode 120000 vt_manager/src/python/vt_manager/templatetags create mode 100644 vt_manager/src/python/vt_manager/tests/__init__.py create mode 100644 vt_manager/src/python/vt_manager/tests/createServer.py create mode 100644 vt_manager/src/python/vt_manager/tests/dataModel/createVM.py create mode 100644 vt_manager/src/python/vt_manager/tests/dataModel/prova.py create mode 100644 vt_manager/src/python/vt_manager/tests/deleteAllVMs.py create mode 100644 vt_manager/src/python/vt_manager/tests/deleteVM.py create mode 100644 vt_manager/src/python/vt_manager/tests/interfaces/testcreate.py create mode 100644 vt_manager/src/python/vt_manager/tests/prova.py create mode 100644 vt_manager/src/python/vt_manager/tests/provisioning/1 create mode 100644 vt_manager/src/python/vt_manager/tests/provisioning/createVM.xml create mode 100644 vt_manager/src/python/vt_manager/tests/provisioning/failresponse.xml create mode 100644 vt_manager/src/python/vt_manager/tests/provisioning/list_resources_nodes_test.py create mode 100644 vt_manager/src/python/vt_manager/tests/provisioning/prueba.py create mode 100644 vt_manager/src/python/vt_manager/tests/provisioning/pruebaCreate.xml create mode 100644 vt_manager/src/python/vt_manager/tests/provisioning/temp.py create mode 100644 vt_manager/src/python/vt_manager/tests/prueba.py create mode 100755 vt_manager/src/python/vt_manager/tests/sendStartQuery.py create mode 100644 vt_manager/src/python/vt_manager/tests/synctest.py create mode 100644 vt_manager/src/python/vt_manager/tests/test.py create mode 100755 vt_manager/src/python/vt_manager/tests/testRandomImport.sh create mode 100644 vt_manager/src/python/vt_manager/tests/testReload.py create mode 100644 vt_manager/src/python/vt_manager/tests/testasync.py create mode 100644 vt_manager/src/python/vt_manager/tests/testcreate.py create mode 100644 vt_manager/src/python/vt_manager/tests/testcreate2.py create mode 100644 vt_manager/src/python/vt_manager/tests/testcreatesync.py create mode 100644 vt_manager/src/python/vt_manager/tests/testdelete.py create mode 100644 vt_manager/src/python/vt_manager/tests/testifaces.py create mode 100644 vt_manager/src/python/vt_manager/tests/testlocker.py create mode 100644 vt_manager/src/python/vt_manager/tests/testmac.py create mode 100644 vt_manager/src/python/vt_manager/tests/testreboot.py create mode 100644 vt_manager/src/python/vt_manager/tests/testslot.py create mode 100644 vt_manager/src/python/vt_manager/tests/teststart2.py create mode 100644 vt_manager/src/python/vt_manager/tests/teststop.py create mode 100644 vt_manager/src/python/vt_manager/tests/xmlrpcsynctest.py create mode 100644 vt_manager/src/python/vt_manager/tests/xmltest.xml create mode 100644 vt_manager/src/python/vt_manager/urls.py create mode 100644 vt_manager/src/python/vt_manager/utils/EthernetUtils.py create mode 100644 vt_manager/src/python/vt_manager/utils/HttpUtils.py create mode 100644 vt_manager/src/python/vt_manager/utils/IP4Utils.py create mode 100644 vt_manager/src/python/vt_manager/utils/MutexStore.py create mode 100644 vt_manager/src/python/vt_manager/utils/ServiceProcess.py create mode 100644 vt_manager/src/python/vt_manager/utils/ServiceThread.py create mode 100644 vt_manager/src/python/vt_manager/utils/SyncThread.py create mode 100644 vt_manager/src/python/vt_manager/utils/ThemeManager.py create mode 100644 vt_manager/src/python/vt_manager/utils/UrlUtils.py create mode 100644 vt_manager/src/python/vt_manager/utils/__init__.py create mode 100644 vt_manager/src/python/vt_manager/utils/contextualization/__init__.py create mode 100644 vt_manager/src/python/vt_manager/utils/contextualization/contextualize_sudoers.txt create mode 100644 vt_manager/src/python/vt_manager/utils/contextualization/vm_contextualize.py create mode 100644 vt_manager/src/python/vt_manager/views/__init__.py create mode 100644 vt_manager/src/python/vt_manager/views/static/media/FELIX/css/ocf.css create mode 100644 vt_manager/src/python/vt_manager/views/static/media/FELIX/images/logo_vm_manager.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/FIBRE/images/logo_vm_manager.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/css/ocf-iframe.css create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/css/ocf.css create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/css/tooltip.css create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/blank.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_close.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_loading.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_nav_left.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_nav_right.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_shadow_e.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_shadow_n.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_shadow_ne.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_shadow_nw.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_shadow_s.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_shadow_se.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_shadow_sw.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_shadow_w.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_title_left.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_title_main.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_title_over.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancy_title_right.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancybox-x.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancybox-y.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/fancybox.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/jquery.easing-1.3.pack.js create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/jquery.fancybox-1.3.4.css create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/jquery.fancybox-1.3.4.js create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/jquery.fancybox-1.3.4.pack.js create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/fancybox/jquery.mousewheel-3.0.4.pack.js create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/account.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/active.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/images/active_t.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/add_rule_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/add_rule_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/admin_abandon_fs_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/admin_abandon_fs_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/admin_fs_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/admin_fs_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/admin_fses_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/admin_fses_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/admin_req_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/admin_req_fs_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/admin_req_fs_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/admin_req_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/aggregate-tiny.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/images/arrow.gif create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/images/arrow2.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/auto_approve_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/auto_approve_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/back_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/back_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/base_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/base_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/button.pxm create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/contact_exp_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/contact_exp_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/dashboard.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/dashboard_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/dashboard_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/edit_profile_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/edit_profile_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/experiments_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/experiments_light.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/images/favicon.ico create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/fs_req_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/fs_req_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/genilogo.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/give_up_fs_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/give_up_fs_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/help.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/host-tiny.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/inactive.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/images/inactive_t.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/images/loading.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/logo_expedient.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/logo_vm_manager.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/logout.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/logout_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/logout_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/manage_fs_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/manage_fs_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/manage_site_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/manage_site_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/ofelialogo.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/ofelialogo2.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/optin_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/optin_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/optout_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/optout_light.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/images/plus.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/profile_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/profile_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/progressbar.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/progressbg_black.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/progressbg_green.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/progressbg_orange.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/progressbg_red.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/progressbg_yellow.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/promote_to_admin_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/promote_to_admin_light.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/images/question_mark_15x15.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/remove_rule_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/remove_rule_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/request_fs_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/request_fs_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/resign_admin_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/resign_admin_light.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/images/right_arrow.gif create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/set_ch_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/set_ch_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/set_fv_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/set_fv_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/set_priority_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/set_priority_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/set_rule_priority_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/set_rule_priority_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/slice-tiny.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/slice.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/step0_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/step0_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/step1_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/step2_manage_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/step2_manage_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/step2_optin_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/step2_optin_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/step2_optout_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/step2_optout_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/switch-5406zl.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/switch-cat6500.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/switch-juniper.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/switch-nec-ip8800.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/switch-netfpga.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/switch-nf2.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/switch-tiny.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/switch.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/user_fses_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/user_fses_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/user_req_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/user_req_light.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/users-tiny.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/view_exp_dark.png create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/images/view_exp_light.png create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/js/dragndrop.js create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/js/formtable.tooltip.js create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/js/jquery-1.6.2.min.js create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/js/jquery.formset.min.js create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/js/jquery.min.js create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/js/jquery.progressbar.min.js create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/js/jquery.progressbar.min2.js create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/js/jquery.tools.min.js create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/js/redips-drag.js create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/js/tooltip.funcs.js create mode 100755 vt_manager/src/python/vt_manager/views/static/media/default/js/utils.js create mode 100644 vt_manager/src/python/vt_manager/views/static/media/default/js/validation.js create mode 100644 vt_manager/src/python/vt_manager/views/templates/FELIX/base.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FELIX/base_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FELIX/base_user.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FELIX/footer.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FELIX/users/base.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FELIX/users/base_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/base.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/base_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/base_user.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/fancybase.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/index.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/registration/login.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/registration/registration_form.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/users/base.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/users/base_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/users/base_user.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/users/fancybase.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/users/index.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/users/registration/login.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/FIBRE/users/registration/registration_form.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/base.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/base_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/base_user.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/dashboard_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/fancybase.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/footer.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/index.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/networking/base.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/networking/ethernet/index.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/networking/ethernet/rangeCrud.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/networking/ethernet/rangeDetail.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/networking/index.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/networking/ip4/index.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/networking/ip4/rangeCrud.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/networking/ip4/rangeDetail.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/policyEngine/condition_create.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/policyEngine/edit_ruleset.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/policyEngine/policy.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/policyEngine/policy_RuleTableCreate.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/policyEngine/policy_create.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/policyEngine/policy_edit.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/policyEngine/table_view.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/registration/activate.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/registration/activation_email.txt create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/registration/activation_email_subject.txt create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/registration/login.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/registration/logout.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/registration/registration_complete.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/registration/registration_form.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/add_server_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/admin_servers.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/delete_server.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/network_iface.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/server_vm_details.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/servers_add_server.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/servers_base.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/servers_crud.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/servers_dataIfaces.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/servers_listVMs.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/servers_list_vms.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/servers_net.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/servers_subscribeEthernetRanges.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/servers/servers_subscribeIp4Ranges.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/base.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/base_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/base_user.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/change_profile_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/change_profile_user.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/dashboard_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/fancybase.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/footer.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/index.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/networking/base.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/networking/ethernet/index.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/networking/ethernet/rangeCrud.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/networking/ethernet/rangeDetail.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/networking/index.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/networking/ip4/index.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/networking/ip4/rangeCrud.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/networking/ip4/rangeDetail.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/policyEngine/condition_create.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/policyEngine/edit_ruleset.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/policyEngine/policy.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/policyEngine/policy_RuleTableCreate.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/policyEngine/policy_create.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/policyEngine/table_view.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/registration/activate.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/registration/activation_email.txt create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/registration/activation_email_subject.txt create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/registration/login.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/registration/logout.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/registration/registration_complete.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/registration/registration_form.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/add_server_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/admin_servers.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/delete_server.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/network_iface.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/server_vm_details.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/servers_add_server.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/servers_base.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/servers_crud.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/servers_dataIfaces.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/servers_listVMs.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/servers_list_vms.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/servers_net.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/servers_subscribeEthernetRanges.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/default/users/servers/servers_subscribeIp4Ranges.html create mode 100644 vt_manager/src/python/vt_manager/views/templates/not_admin.html create mode 100644 vt_manager/src/python/vt_manager/views/templatetags/__init__.py create mode 100644 vt_manager/src/python/vt_manager/views/templatetags/accessDict.py create mode 100644 vt_manager/src/python/vt_manager/views/templatetags/url.py create mode 100644 vt_manager/src/wsgi/vt_manager/auth.wsgi create mode 100644 vt_manager/src/wsgi/vt_manager/django.wsgi create mode 100644 vt_manager/src/wsgi/vt_manager/mon.wsgi create mode 100644 vt_manager/version diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..4aa3b2d2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,80 @@ +*.class +*.pyc +*~ +egeni.db +*.pyc +.*.swp +test +*~ +\#*\# +*.aux +*.bbl +*.log +*.dvi +*.blg +*.out +.xpdf-running +*.orig +*.ngc +*.o +*.so +*\#* +*vsim* +*coregen* +.cproject +.project +chi_tool +pmac_tool +test.pl +fig-vnodes.dia +icing-tr.pdf +om.db +clearinghouse.db +.project +.pydevproject +db/openflow/optin_manager/om.db +secret_key.py +*.0 +*.launch +gcf-x509.*/ +expedient/src/python/expedient/clearinghouse/gcf-x509-user.crt/* +expedient/src/python/expedient/clearinghouse/gcf-x509-trusted.crt/* +expedient/src/static/expedient/clearinghouse/media/css +expedient/src/static/expedient/clearinghouse/media/js +expedient/src/static/expedient/clearinghouse/media/img +*.db +build/ +localsettings.py +vt_manager/src/python/vt_manager/settings.py +expedient/src/python/expedient/clearinghouse/localsettings.py +optin_manager/src/python/openflow/optin_manager/localsettings.py +vt_manager/src/python/agent/settings.py +vt_manager/src/python/vt_manager/mySettings.py +vt_manager/src/python/agent/mySettings.py +vt_manager/src/python/agent/.currentVersion +vt_manager/src/python/agent/security/certs/agent.crt +vt_manager/src/python/agent/security/certs/agent.key + +expedient/.currentVersion +expedient/bin/log/* +expedient/bin/.upgradeReg +expedient/bin/.ofverLock +expedient/bin/rescue/* +ofam/.currentVersion +ofam/local/* +ofam/bin/log/* +ofam/bin/.upgradeReg +ofam/rescue/* +optin_manager/.currentVersion +optin_manager/bin/log/* +optin_manager/bin/.upgradeReg +optin_manager/bin/.ofverLock +optin_manager/rescue/* +vt_manager/.currentVersion +vt_manager/bin/log/* +vt_manager/bin/.upgradeReg +vt_manager/bin/.ofverLock +vt_manager/rescue/* +ofrelease +updater* +!.gitignore diff --git a/CHANGELOG b/CHANGELOG new file mode 100755 index 00000000..c1b720bc --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,667 @@ +============= +PREVIOUS INFO +============= + +Caption +[+] Added features +[*] Improved/Changed features +[-] Missing features +[T] Known issues/TODOs +[B] Fixed bugs + +Components: + +EXP: Expedient +OPT: Opt-in +OFA: OFAM +VTA: VT AM +AGN: Agent +OFR: Ofelia Registration +OFVER: OFELIA VERsioning + + +======== +VERSIONS +======== + +-------------------------------------------------- +v0.8.3 +-------------------------------------------------- +Released: XX/10/2014 + +Change log: + +[+] OFVER: Allow migration of the framework to another directory. Issue xyz +[+] EXP, OPT, VTA: Adapt OCF to Debian7 and keep compatibility with Debian6. Issue 128 +[*] EXP: Cannot monitor status of AMsoil-based aggregates enhancement Expedient. Issue 217 +[+] AGN: Locate server to store VM images and develop a template downloader for virtualisation agent. Issue 203 + +-------------------------------------------------- +v0.8.1 +-------------------------------------------------- +Released: 26/05/2014 + +Change log: + +[B] OPT, VTA: Actions being kept unrelated to their referred VMs. Issue 221 +[B] EXP, VTA: Force Update VMs - Does not clean the interfaces. Issue 220 +[B] EXP, OPT, VTA: Error during upgrading from OCF 0.6.1 to 0.7. Issue 219 +[+] EXP: Choose OF controller from existing VMs at the slice. Issue 218 + +-------------------------------------------------- +v0.8 +-------------------------------------------------- +Released: 31/03/2014 + +Change log: + +[B] OPT: E-mails to administrators when flowspace is removed bug OFManager. Issue 216 +[*] EXP: Ports to be selected automatically for flowspace selection enhancement. Issue 215 +[B] VTA: Exception when defining IP ranges with repeated name not captured bug enhancement. Issue 214 +[*] AGN, EXP, VTA: Add Force Update Button for VMs. Issue 213 +[+] EXP, OPT: Automatic VLAN assignment for new FlowSpaces. Issue 212 +[+] EXP, OPT: Automatic FlowSpace Approval. Issue 210 +[+] EXP, OPT, VTA: Implement OCF version Tracker Engine for AMs. Issue 209 +[B] VTA: VMs cannot be created on development Branch. Issue 208 +[B] VTA, AGN: Failure on ListActiveVMs call. Issue 207 +[B] OPT: Failed import in background daemon for expiration bug OFManager. Issue 205 +[*] EXP: Simplify FlowSpace selection through Expedient OpenFlow plug-in. Issue 204 +[+] EXP, VTA, AGN: Offer Debian Wheezy VMs. Issue 202 +[-] EXP: Updating Project/Slice names in expedient cause inestabilities on OFManager and VMManager. Issue 201 +[B] EXP: JS validation not working anymore. Issue 200 +[+] OFVER: Install FlowVisor with OCF. Issue 199 +[B] OFA: Fixing dependencies in FOAM. Issue 195 +[*] EXP: Hide user admin links for local island users. Issue 193 +[*] VTA: Warnings about VMs in empty servers not being reconfigured on adding new bridges. Issue 191 +[B] VTA: Cannot create new server with bridges bug. Issue 190 +[*] EXP: Improve project list loading with a waiting message. Issue 189 +[B] EXP: Some errors are barely visible. Issue 188 +[*] AGN: OXAD init script throws warning on stop agent. Issue 187 +[*] EXP, OFA: Missing FOAM log in administration panel. Issue 186 +[*] EXP: Expedient project list/table loads very slow. Issue 182 +[B] EXP, OPT: Expedient and Optin FS mismatch. Issue 137 +[B] EXP, OPT: Flowspace visualization errors. Issue 117 + +-------------------------------------------------- +v0.7 +-------------------------------------------------- +Released: 21/11/2013 + +Change log: + +[+] EXP, VTA, AGN: Support for IRATI VMs. Issue 181 +[+] EXP, VTA, OPT: FIBRE Theme files. Issue 180 +[*] EXP: Expedient GUI redesign. Issue 179 +[+] OPT, OFVER: Integrate FOAM. Issue 178 + +-------------------------------------------------- +v0.6.1 +-------------------------------------------------- +Released: 24/10/2013 + +Change log: + +[B] EXP, OPT: Slices being created in FlowVisor with an inconsistent slice ID. Issue 176 +[B] EXP: check_vms_status per slice returns the whole list of VMs. Issue 175 +[+] VTA: Call to OXAD breaking alternative (sync) protocol. Issue 174 +[B] EXP: Granted flowspaces not being shown on Expedient. Issue 173 + +-------------------------------------------------- +v0.6 +-------------------------------------------------- +Released: 20/09/2013 + +Change log: + +[+] OPT, VTA: Add SFA API for each AM. Issue 172 +[*] VTA: Improve north communication interface for VT planner. Issue 171 +[+] EXP, VTA: Support for Spirent VM templates. Issue 170 +[*] EXP: Requested flowspace for an AM showing for every other AM. Issue 161 + +-------------------------------------------------- +v0.5 +-------------------------------------------------- +Released: 04/06/2013 + +Change log: + +[B] EXP, VTA: Settings not accessible from manage.py. Issue 163 +[B] AGN, OFVER: Missing settings for agent. Issue 162 +[B] EXP: Referencing same requested flowspaces to show the ones granted. Issue 159 +[B] EXP: Plugin system interferes with basic authentication for AMs. Issue 158 +[B] EXP: Exception booking flowspace in simple mode. Issue 155 +[T] Migrate repositories. Issue 149 +[B] EXP: Role permissions not being updated for users with that role. Issue 148 +[B] EXP: Permission error when project owner edits other's roles. Issue 141 +[*] EXP: Mail delivery may take too long under some circumstances. Issue 139 +[*] EXP: Add VMs names in the same slice validation. Issue 138 +[*] EXP: Redesign the permission management for project creation. Issue 127 +[*] EXP: Project description validator is too restrictive. Issue 126 +[*] EXP: Setting loopback interface as slice controller can crash FlowVisor. Issue 125 +[*] EXP: Warning message when stoping a slice. Issue 124 +[B] OPT: Small error in the used VLANs lists in the add rule page. Issue 123 +[B] OPT: Optin error handling flowspace request. Issue 122 +[*] EXP, OPT: Allow updating the slice controller without having to start/update it. Issue 121 +[*] EXP: Change in VM's SSH details. Issue 120 +[*] AGN: Differentiate exceptions when creating VMs. Issue 119 +[*] OFR: Warning in the approval e-mail. Issue 116 +[+] EXP: Refactoring of Expedient plugin system. Issue 68 + + +-------------------------------------------------- +v0.4.3 +-------------------------------------------------- +Released: 04/02/2013 + +Change log: + +[*] OFVER: PyPElib and ofver consistency. Issues: 114, 115 +[B] OFVER: ofver not installing PyPElib for fresh installs. Issue 113 +[*] OPT: Add project name to the flowspace granted mail notification. Issue 112 +[B] OPT: Optin is not being updated when a rule for a new experiment is added. Issue 111 +[*] OPT: mispelling in Flowspace messages. Issue 110 +[B] EXP: Email notifications links use IPs addresses instead of URLs. Issue 109 + + +-------------------------------------------------- +v0.4.2 +-------------------------------------------------- +Released: 15/01/2013 + +Change log: + +[B] EXP : Mail notifications not arriving. Issue 106 +[*] VTA : Issue showing slices that contain VMs with incorrect names (retaken). Issue 105 +[B] VTA : MacSlot is reserved even when VM is not created. Issue 70 + + +-------------------------------------------------- +v0.4.1 +-------------------------------------------------- +Released: 07/01/2013 + +Change log: + +[B] OFVER : Fixed bug raleted with backup restoration. Issue 104 +[+] OFVER : Ofver lock functions handling PIDs and forks. Issue 102 +[B] EXP : New VM naming policies crashed slices containing VMs with names containing "_". Issue 105 + + +-------------------------------------------------- +v0.4 +-------------------------------------------------- +Released: 04/01/2013 + +Change log: + +[B] EXP : Fixed bug originated by a race condition between askForAggregateResouces and async communication model. Issue 98 +[+] OFVER : Modify ofver scripts to check pyPElib version and upgrade it when a new version is available. Issue 95 +[B] VTA : pyPElib does not correctly handle rule tables exceptions when multiple PolicyRuleTable's exist. Issue 94 +[+] EXP, OPT, VTA : Add favicon to all the applications. Compatible with Theme Manager. Issue 93 +[*] VTA : Cleanup of VM Manager policy code. Issue 92 +[B] VTA, EXP, AGN : VM naming conflicts when names are duplicated. Issue 90 +[B] OPT : Parse exceptions raised from Optin to avoid the raising of the full URL including HTTP basic auth. Issue 85 +[B] EXP : Theme manager not working for UI/ subfolder specializations. Issue 84 +[B] EXP : Raise exception when registration e-mail cannot be sent to avoid Error 500. Issue 81 +[B] OFVER, EXP, OPT, VTA : Activate Apache module (add symbolic link from Apache's mods-enabled to mods-available) to avoid ofver installation fail because of Apache's mod_wsgi. Issue 78 +[B] EXP : Automatically install pyPElib in Expedient module. Issue 77 +[B] VTA, EXP : Add trailing slash in urls.py file to avoid Error HTTP 301 for some AJAX calls. Issue 75 +[+] EXP : Add remove AM functionality to Slices and Projects. Issue 74 +[B] VTA : When MacRange has no MacSlots, table in the view (template) is bad formatted. Issue 71 +[*] EXP : Modified VM name field validator to not allow underscores in VMs names since GNU/Linux does not accept them due to some standard convention. Issue 69 +[*] EXP : Preserve data in the VT AM form and raise exception when URL is not available to avoid loss of the inputted data. Issue 54 +[*] OFVER : Add ofver update for django_auth_ldap to support Active Directory. Issue 53 +[*] EXP : Improve the form used by the user to ask for a project. It must be specified at least the project name, organization, approx. duration and description. Issue 52 +[B] OFVER : ofver upgraded to v0.22 to allow to be run again when user manually halts it. Issue 46 +[+] EXP : Show connections with servers in the table of the select_resources page so the port of the siwtch connected to a server is shown in the other edge of the link. Issue 45 +[B] EXP, VTA : Cross dependencies between Expedient and VM Manager affecting installation. Moved imports to allow the communication package and all its contents may be used independently from other modules. Issue 43 +[B] VTA, EXP : Security issue between VM AM and Expedient. Fixed bug that exposed users' credentials in error message when VM status update fails. Issue 42 +[B] EXP : Correct display of requested and granted flowspaces. Issue 38 +[+] EXP : Detect loops in requested topologies and warn user. Issue 37 +[*] EXP, OPT : Simplified FlowSpace allocation mode added. Issue 36 +[B] EXP : Fixed mySettings-example file in Expedient which contained wrong uncommented lines. Issue 34 +[B] EXP : Fixed ofreg url in Expedient. Issue 33 +[+] OFVER : ofver backups the current template when it downloads a new template and replace echo with print so the messages are logged in the log file. Issue 32 +[B] VTA, EXP, AGN : Fixed bug that avoided VMs containing '/' characters to be started. Issue 30 + + +-------------------------------------------------- +v0.3 +-------------------------------------------------- +Released: 25/09/2012 + +Change log: + +[*] EXP : Migration from protovis to d3 to display topology. Several improvements and enhancements in resources visualization and selection facing intrafederation. Issue 26 +[B] OFVER : Add pyparsing dependency in v0.3 pre-upgrade script. Issue 16 +[B] VTA, AGN : Fixed bug when creating VMs due to but handling of VM's interfaces. Issue 17 +[B] EXP : Fixed LDAP TLS certificate problem. Issue 18 +[B] EXP : OFREF URL updated. Issue 19 +[B] EXP : Fix bug causing the "Flowspace not granted" message remain in some AMs although it is granted. Issue 20 +[B] EXP : Fixed some files location problem due to refactor done by the Theme Manager. Issue 23 +[B] EXP : Fixed bug of Expedient crashing when trying to retrieve granted flow space if the AM is not available. Issue 24 + +Known issues/TODOs: + +[T] VTA : Check Server information update (Enable checkbox). +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] VTA : Check oxad version when creating a VM. + + +-------------------------------------------------- +v0.3RC1 +-------------------------------------------------- +Released: 03/09/2012 + +Change log: + +[B] OFVER : Custom scripts for OCF v0.3RC1/0.3 +[*] ALL : Added Theme Manager to customize look & fill (images, css, colors, etc) of the different modules. Issue 14 +[B] OFVER : lock file is deleted when installation fails. Issue 12 +[*] EXP : Flowvisor password in Slice controller page not needed nor shown anymore. Issue 11 +[B] EXP : Fixed visualization errors of the flowspaces when having multiple OF AMs (federation). Issue 10 +[B] AGN : Fixed improperly partitioning of Swap on File Image hard disks. Issue 9 +[B] EXP,OPT : Fixed exception message when adding OF AM due to the lack of the proper xmlrpc-ssl/xxxx-ca.crt file. Issue 8 +[B] EXP,OPT : Fixed permission problem with AMs and flowspaces requests in intra-federation environments. Issue 5 +[*] VTA : Policy Engine based on pypelib and corresponding GUI integrated in VM Manager. Issue 3 +[B] EXP,VTA,AGN : Fixed interfaces mismatch between real topology and its visualization. Issue 2 +[B] EXP,VTA : Fixed bug when creating a VM having multiple VM AMs (federation). Issue 1 + +Known issues/TODOs: + +[T] VTA : Check Server information update (Enable checkbox). +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] VTA : Check oxad version when creating a VM. + + +-------------------------------------------------- +v0.21.1 +-------------------------------------------------- +Released: 06/06/2012 + +Change log: + +[B] OFVER : Custom scripts for OCF v0.21.1 +[B] EXP : Fixed bug in listResources method in Expedient producing no VMs in the Resources Visualization Panel. +[B] EXP : Fixed small UI bug in the Resources Visualization Panel. +[B] EXP : Fixed bug when adding a new Virtualilzation AM. + +Known issues/TODOs: + +[T] VTA : Check Server information update (Enable checkbox). +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] OFVER : If ofver run fails for wrong inputs, lockfile is not removed. Next run gets blocked. +[T] OFVER : Incorrect handling of invalid inputs. Use default value or repeat question. +[T] EXP : Improve error message if a project with duplicated UUID is attempted to be created. +[T] VTA : Check oxad version when creating a VM. + + +-------------------------------------------------- +v0.21 +-------------------------------------------------- +Released: 24/05/2012 + +Change log: + +[B] OFVER : Custom scripts for OCF v0.21 +[B] EXP : Fixed and improved listResources method in Expedient to retrieve VMs status from VT AM. +[B] VTA : Fixed and improved mechanism to perioically retrieve information from the agent about the status of the VMs. +[B] VTA : Fixed and improved mechanism to retrieve information from the agent about the status of the VMs when agent is up again. +[*] EXP : Improved UI in the Resources Visualization Panel adding collapsable sections. +[B] EXP : Fixed bug in the generation of the RSPEC resulting in a wrong order of the VM's interfaces. + +Known issues/TODOs: + +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] OFVER : If ofver run fails for wrong inputs, lockfile is not removed. Next run gets blocked. +[T] OFVER : Incorrect handling of invalid inputs. Use default value or repeat question. +[T] EXP : VMs status does not update. +[T] EXP : Improve error message if a project with duplicated UUID is attempted to be created. +[T] VTA : Check oxad version when creating a VM. + + +-------------------------------------------------- +v0.2 +-------------------------------------------------- +Released: 16/05/2012 + +Change log: + +[B] OFVER : Installation process checked. Permissions reorganization script checked. +[+] EXP : UI cleaned. +[+] ALL : Identification of TODOs in 0.2RC1 (check in 0.2RC1 changelog). + +Known issues/TODOs: + +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] OFVER : If ofver run fails for wrong inputs, lockfile is not removed. Next run gets blocked. +[T] OFVER : Incorrect handling of invalid inputs. Use default value or repeat question. +[T] EXP : VMs status does not update. +[T] EXP : Improve error message if a project with duplicated UUID is attempted to be created. +[T] VTA : Check oxad version when creating a VM. + + +-------------------------------------------------- +v0.2RC1 +-------------------------------------------------- +Released: 19/04/2012 + +Change log: + +[B] OFVER : Wrong message targeting same version when force flag was used +[B] OFVER : Remove unnecessary messages displayed. +[B] VTA : Corrected the order VMs interfaces are bridged to server’s ones. +[+] EXP : New merged view of Resource Visualization Panel and slice details pages. Workflow modified. +[+] EXP : UI cosmetics in previous sections very enhanced. +[B] EXP : Fixed problem with Start/Stop VM button which sometimes required 2 clicks. +[+] EXP : Slice expiration mechanism disabled. +[B+] EXP : Solved problem when Project owner cannot start slices from his project created by other users. Changes in permissions management. +[B] EXP : Validation in project and slice names to avoid '@' character. +[+] EXP : Better exception handling in Start/Stop slice. +[+] EXP : Clean FlowVisor exception messages. + +Known issues/TODOs: + +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] OFVER : If ofver run fails for wrong inputs, lockfile is not removed. Next run gets blocked. +[T] OFVER : Incorrect handling of invalid inputs. Use default value or repeat question. +[T] OFVER : Check script to update researchers permissions. +[T] EXP : Change “Add aggregate Manager” button stile. +[T] EXP : VMs status does not update. +[T] EXP : Check if projects with duplicated UUIDs are created. Modify error message if required. +[T] VTA : Check oxad version when creating a VM. + + +-------------------------------------------------- +v0.14.2 +-------------------------------------------------- +Released: 23/03/2012 + +Change log: + +[B] EXP : Exception messaged raised by VT AM when it is not able to connect the agent treated in Message Panel. +[+] EXP : Valildation in the project/slice name and description fields to filter not allowed characters. +[+] EXP : Tested mail notifications and smptp server in EICT. +[+] EXP : Help tooltip y user mail list in help page. +[B] VTA : Visualization error in VT AM in the server's details page in Firefox for Linux. +[*] VTA : Improved XMLRPC communicatin with VT_AM, using an XMLRPC_USER which is stored in local configuration variables not to have to provide superuser credentials when intrafederating. +[*] OFVER : Added build-essential and python-pyparsing dependencies in the installers of all modules. +[+] OFVER : Custom processes for OFELIA (project islands) and NON OFELIA (any one installing the OCF) installation/upgrades. +[+] OFVER : VM template for NON OFELIA installations not using LDAP authentication and other custom OFELIA configurations. Dedicated storage space in codebasin.net. +[+] OFVER : LDAP domain name added to /etc/hosts in the Expedient machine. +[B] OFVER : Fixed ofver .ofverLock bug +[B] OFVER : Fixed BUG in OFVER's agent's module, expecting non yet existing VM template HASH file when installing. +[B] AGN : Fixed BUG in agent not handling file descriptors correctly which causes that agents crash after some time because the amount of open file descriptors. +[B] AGN : Fixed BUG when unmounting VMs. +[*] AGN : New VM template for OFELIA installations fixing LDAP and local authentication. +[B] ALL : License file renamed. + +Known issues/TODOs: + +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. + + +-------------------------------------------------- +v0.14.1 +-------------------------------------------------- +Released: 13/12/2011 + +Change log: + +[B] EXP : Fixed bug: Project owners and members correctly displayed in Dashboard. +[*] ALL : Monitoring of expired sessions to prevent huge size of databases. +[*] VTA : IP and Mac ranges details page showing mapping between IP/MAC and VM-interface/Project/Slice +[*] ALL : Added Liscence file + +Known issues/TODOs: + +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] AGN : When connection is lost with LDAP even local users cannot login to the VMs; this is an incorrect configuration of the VM's template. +[T] AGN : Slow performance on SSH logins (probably related to above issue). + + +-------------------------------------------------- +v0.14 +-------------------------------------------------- +Released: 16/11/2011 + +Change log: + +[*] EXP : Projects and Slices can not be deleted if there are exisiting VMs. A message is displayed to the user in the Message Panel. +[*] EXP : "Reset password" link in the login page supports ldap users by redirecting to ofreg and local users through the old reset system (email) +[*] EXP : "Account" link redirects to ofreg for ldap users and to a local page for local users. +[*] EXP : Several visual improvents and fixes +[*] EXP : Servers bridges are not editable. Existing ones are shown in grey. +[*] EXP : Help tooltip when creating a requesting a project to provide proper information (users were not filling this information correctly) +[B] EXP : Introduced BUG in v0.13 because of which topology was not recovered when adding an OF AM for first time. +[*] OFVER : ofver v0.21 deployed. + +Known issues/TODOs: + +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] AGN : When connection is lost with LDAP even local users cannot login to the VMs; this is an incorrect configuration of the VM's template. +[T] AGN : Slow performance on SSH logins (probably related to above issue). + + +-------------------------------------------------- +v0.13 +-------------------------------------------------- +Released: 07/10/2011 + +Change log: + +[B] EXP : Fixed bug of the topology map which was displaying wrong information regarding the port mapping of the switches connections. +[*] ALL : Local Settings reorder. +[*] EXP : can_create_project permission improved. When IM receives the request (email notification) would proceed to create the project and assign the user as "owner". The "owner" user will automatcally have the permissions to add new users to the project. "Researcher" users are not allowed to add members to the project. "Can Delegate" flag deleted. +[*] EXP : Email Notification to the user when he is added to a Project. +[*] EXP : Possibility to enable/disable local registration of users +[*] EXP : Message pannel and Message center improved. Possibility of sending messages inside Expedient between users showing sender. +[*] EXP : Mail notification to the user when some other user inside the clearinghouse sends him a message. +[*] ALL : Software version and island name displayed in all the modules under the OFELIA logo. +[*] OFVER : Custom upgrade script for v0.13 +[*] OPT: Email notification to the IM when a new FlowSpace request arrives +[*] OPT: Email notigication to the user when his FlowSpace request has been attended. +[B] EXP : Fixed bug when creating adding an OpenFlow AM (Identified by Nikos) +[B] EXP : Fixed bug when creating projects, the LDAP was creating two projects with different names (one with the uuid attached and the other not) +[*] EXP : New Set of admin users in the LDAP, one for each island. +[B] EXP : Slice controller help tooltip fixed. +[*] EXP : Help Tooltips next to the VM's names showing how to access them via ssh. +[*] EXP/OPT : Granted FlowSpace recover by the Clearinhouse and displayed in the resources panel. +[B] AGN : Supports same VM names in different projects + +Known issues/TODOs: + +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] AGN : When connection is lost with LDAP even local users cannot login to the VMs; this is an incorrect configuration of the VM's template. +[T] AGN : Slow performance on SSH logins (probably related to above issue). + + +-------------------------------------------------- +v0.12 +-------------------------------------------------- +Released: 12/08/2011 + +Change log: + +[B] EXP : Fixed bug Expedient was sometimes caching UUIDs of projects and slices, causing duplicated and non random UUID assignation. +[B] EXP : Fixed some links in "Openflow resources reservation process" that were pointing to wrong locations. +[*] EXP : UI improvements: added confirmation to VM deletion and added confirmation to "Done" button in Openflow "Openflow resources reservation process" process. +[*] EXP : Notification email sent to the IM when project creation request is generated. +[B] VTA : Solved bug preventing status bars of the network dashboard UI to be shown properly and other minor UI improvements. +[B] VTA : VTAM was not handling correctly release of IP and MAC slots, hence leaking slots. +[B] VTA : Was leaving already deleted slots in DB. +[B] AGN : Fixed bug, LDAP SSH configuration was not scaping spaces in Project names, making users unable to login to the VMs. (Note that already created VMs will not be updated) +[B] AGN : Missing XEN modules required by paravirtualized VMs now installed in the new template version. (Note that already created VMs will not be updated) +[B] AGN : AGN was not correctly handling catched exceptions while cloning, and hence sometimes not deleting disks on error. +[*] AGN: New version of VM template with improved software organization, precompiled OF software. (Note that already created VMs will not be updated) + +Known issues/TODOs: + +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] AGN : When connection is lost with LDAP even local users cannot login to the VMs; this is an incorrect configuration of the VM's template. +[T] AGN : Slow performance on SSH logins (probably related to above issue). +[T] EXP : In early versions of Expedient, under one installation some strange errors on permission delegation were seen. However, in this final version of the release, this behaviour was unreproducible. Needs deeper testing. + +Missing Features: + +[-] EXP : Export VT Manager data model to VT plugin in Expedient. + + +-------------------------------------------------- +v0.11 +-------------------------------------------------- +Released: 03/08/2011 + +Change log: + +[B] EXP : Fixed bug when adding an OF AM and it has no flowvisor set. +[+] EXP/VTA/AGN : More help tooltips along the configuration process for island managers. +[+] EXP : Help page updated with links to the OFELIA User Documentation and OFELIA Help Desk. +[B] EXP : Fixed bug when trying to delete Projects + +Known issues/TODOs: + +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] AGN : When connection is lost with LDAP even local users cannot login to the VMs; this is an incorrect configuration of the VM's template. + +Missing Features: + +[-] EXP : Export VT Manager data model to VT plugin in Expedient. + + +-------------------------------------------------- +v0.1 +-------------------------------------------------- +Released: 22/07/2011 + +Change log: + +[B] EXP/VTA : Resources hash mechanism for listing resources supports multiple VT Manager instances. +[B] VTA : Some UI disadjustments (Chrome BUG). +[B] EXP : Information messages for the user are automatically refreshed in the message panel. +[+] VTA/AGN: New Default template for the VMs. +[+] VTA/AGN: LDAP support for SSH in the VMs added. +[+] AGN: New cloning process for creating VMs. Disks are created using dd and then template's filesystem is decompressed. Improved performance and reliability. Also changed priority of cloning processes to not affect VM's I/O rate. +[+] VTA: AJAX implementation of GUI in order to update VM status and IPs without refreshing the page. +[+] VTA : AJAX implementation of GUI in order to trigger actions over VMs without reloading pages. +[B] VTA : Exceptions were not treated when trying to create VMs in a server not subscribed to any range. +[B] VTA : Exceptions were not treated when trying to delete a server with existing VMs. +[+] EXP/VTA/AGN : Settings files simplified. +[+] EXP/VTA/AGN : OFELIA Version Manager (ofver) deployed: installation and upgrade processes now are extremely simplified by emans of a set of bash scripts. This tool will also allow smart upgrades between versions with particular workflows. + +Known issues/TODOs: + +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. +[T] OPT : Optin Manager change topology callback to Expedient: code merge done, but further testing required. +[T] EXP : Not possible to delete projects +[T] AGN : When connection is lost with LDAP even local users cannot login to the VMs; this is an incorrect configuration of the template. +[T] EXP : When trying to add an OpenFlow AM and the Opt-In Manager has not the FlowVisor set, Expedient crashes + +Missing Features: + +[-] EXP : Export VT Manager data model to VT plugin in Expedient. + + +-------------------------------------------------- +v0.1RC2 +-------------------------------------------------- +Released: 23/06/2011 + +Change log: + +[*] EXP/VTA : Better error handling and rollback. +[+] EXP : AJAX implementation of GUI in order to update VM status and IPs without refreshing the page. +[+] EXP : AJAX implementation of GUI in order to realize action over VMs without reloading pages. +[*] EXP/VTA : Improve data validators for VT Manager and Clearinghouse (Expedient) GUIs +[+] VTA/AGN : Monitoring of VM state when connection with server agent is recovered. +[*] EXP/VTA : Communication mechanism to list resources from VT Manager to Clearinghouse through hash value improved. +[+] AGN: Server agent using libvirt for almost all tasks. +[+] AGN: Server agent setup script to facilitate installation. +[+] VTA: Server agent's password settable in Server configuration web page in VT Manager. +[*] VTA : VT Manager data model completely redesign allowing: +- Networking interfaces management totally improved for servers and VMs. +- Definition of Mac Ranges and IP Ranges that servers can subscribe to. +- Mac and IP exceptions configurable inside Mac and IP ranges. +- Virtualization technology drivers to support servers not using Xen hypervisor (only Xen drivers and base class implemented so far). +[+] EXP : Expedient is able to authenticate against LDAP and push projects and slices. Due to this, Expedient requires connectivity with the LDAP and a flag was created in the settings file to enable/disable this capability. (SSH and LDAP in VMs not finished yet). +[B] Several bug fixing. +[*] Several UI improvements. +[+] EXP : Start/Stop slice in Expedient starts/stops VMs in the slice. +[+] VTA : Information message displayed to all the users of the slice if an action over a VM is performed by the Island Manager through the VT Manager. +[*] VTA : Settings configuration for VT Manager improved by isolating static and island dependent variables. + +Known issues/TODOs: + +[T] Resources hash mechanism does not work properly when more than one VT Manager are present. +[T] Some UI disadjustments. +[T] Information messages for the user are not displayed in the message panel if webpage is not refreshed . +[T] VTA : Action model callBackURL attribute is no longer needed in VT Manager. + +Missing Features: + +[-] Finishing the SSH configuration in the VMs to allow them use the LDAP. This feature will probably require a new default template for VMs and updating the agent code. +[-] VTA : AJAX in VT Manager GUI following Expedient GUI implementation. +[-] OPT : Optin Manager change topology callback to Expedient. +[-] EXP : Export VT Manager data model to VT plugin in Expedient. + + +-------------------------------------------------- +v0.1RC1 +-------------------------------------------------- +Released: 18/04/2011 + +Change log: + +[B] Lots of bug fixing +[*] EXP/VTA : Monitoring mechanisms to ensure connectivity between Expedient-AM and VT_AM-agent +[*] Improved monitoring(control) of the VMs and error recovery. +[+] Now virtualization plugin informs of errors during the creation, start and stop. +[*] New logos and customized UI. +[+] New "Resource visualization panel" +[*] VTA : Now links between switches and servers are shown, information is filled in VT_AM (visualization engine must be improved). +[*] Now it can be specified where the servers are physically connected (switch and port); no more hardcoded bridge information in the configuration file for the VMs +[*] Now VMs take as hostname the name of the VM. + +Known issues/TODOs: + +[T] VTA : Javascript bug regarding the addition of interfaces in the VT_AM (it deletes values in the form). Suggestion: first add all the interfaces needed, then put the values. +[T] EXP : Reboot machine is NOT working; this is due to an obscure bug in the libvirt library (we might have to use stop and then start method of libvirt, as sometimes reboot method in libvirt silently fails). +[T] EXP : Sometimes appears a NONE before Mgmt IP in the Resource visualization panel in Expedient. IP is correct though. +[-] EXP : New information in visualization panel for the Openflow resources. +[-] EXP/VTA : AJAX recovery of the VM status in both resource vis. panel in Expedient and VT_AM. + + +-------------------------------------------------- +v0.1Alpha +-------------------------------------------------- +Released: 15/03/2011 + +Change log: + +[*] EXP : Customized version of Expedient; Apparence, simplification of the AMs selection on projects and slices (now is not necessary), plugin for Virtualization Aggregate Manager +[*] OPT : Customized version of Optin Manager: only look&feel +[*] EXP : Customized version of Expedient; Several things of apparence (look&feel, controls, visualization of topology...), simplification of the AMs selection on projects and slices (now is not necessary), plugin for Virtualization Aggregate Manager +[*] OPT : Customized version of Optin Manager: only look&feel +[*] VTA/AGN : XEN virtualization management (plugin + AM + agent) +Known BUGS and improvements: +[T] EXP : In the slice and project pages, Aggregate Managers box has to be deleted (since all the slices and projects use all AMs). In the slice a (unique) button must be put to specify Openflow controller instead of current approach +[T] VTA : Look and feel of both VT_AM and plugin needs to be improved. +[T] VTA : VT plugin fails to retrieve the status of the AM itself (it always OK status). while this is not corrected, the way to make sure Expedient is properly connected to the Virtualization AM, is to define a server in the AM (doesn't matter for the moment is not there ) try to allocate resource, and see that this servers is listed --> will be corrected soon. +[T] VTA : still doesn't correctly manage situations were connectivity problems appear between AM and Agent in the XEN server (not yet implemented) --> will be corrected soon. +[T] VTA : VT plugin still does not show servers on the topology (on process). +[T] VTA : VT_plugin does not refresh status of the VM that have pending actions in process (will be corrected via AJAX). +[T] EXP : Expedient DOES NOT use LDAP yet (LDAP code has not been merged to expedient in ofelia.development, since no LDAP server reachable for everyone is yet deployed) +[T] EXP : Expedient does not populate slice info to LDAP, and Agent still does not configure VMs to restrict login to them based on LDAP slice groups (not yet implemented). +[T] EXP : Expedient does not show in the topology the switch and host icons instead of boxes (this is indeed a bug from Stanford code that we will try to sort out). diff --git a/LICENSE b/LICENSE new file mode 100755 index 00000000..f898659f --- /dev/null +++ b/LICENSE @@ -0,0 +1,12 @@ +Copyright © 2013 OFELIA FP7-Project. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/README.md b/README.md new file mode 100755 index 00000000..abed49d2 --- /dev/null +++ b/README.md @@ -0,0 +1,152 @@ +======== +OVERVIEW +======== + +OFELIA Control Framework (OCF) is a set of software tools for testbed +management. It controls experimentation life-cycle; reservation, +instantiation, configuration, monitoring and uninistantiation. + +Features: + +Full software stack: frontend, clearinghouse and resources managers +(AMs) Support for mangement of Openflow, Virtual Machines (currently XEN) +and Emulab resources. +OCF is currently deployed in OFELIA FP7 project testbed, the European +Openflow testbed. The ideas behind its architecture are heavily influenced +by the experience of other testbed management tools and GENI architectural +concepts. Take a look at Overview section for more details. + + +============== +INSTALLING OCF +============== + +1. Requirements +--------------- + +* Expedient, Opt-in and VT manager + * One (or more) GNU/Linux Debian-based distros (see Note #1) + * Developed and ensured to work under Debian 7.0 (Wheezy) using + the following packages: + * Python 2.7 + * Django 1.4.5 (automatically installed) + * MySQL server (automatically installed) +* OXAD (virtualization servers) + * One (or more) GNU/Linux Debian-based distros to be virtualized by XEN + * Developed and ensured to work under Debian 6.0 (Squeeze) using + the following packages: + * Python 2.6 + * Django 1.2.3 (automatically installed) + * MySQL server (automatically installed) +* FlowVisor (Opt-in Manager installations only) (automatically installed) + +Note #1: the OCF upgrading system (OFVER) [http://code.google.com/p/ofver/] +supports Debian-based distros only. For other distros you shall install +the components manually. + + +2. Installing +------------- + +2.1 Clone the OCF repository: + + 2.1.1 For Expedient, Opt-in, VT manager: you may place it anywhere + (e.g. under /opt/ofelia) + + 2.1.2 For OXAD (XEN agent for virtualization purposes); you MUST + place it under /opt/ofelia + + git clone https://github.com/fp7-ofelia/ocf.git /opt/ofelia + + Alternatively you can download the tarball and uncompress in place + +2.2 For Expedient, Opt-in, VT manager: choose the components to install + as a root user. This will implicitly trigger OFVER: + + cd /opt/ofelia/deploy + python install.py + + The following actions will take place: + * Install dependencies + * Build Certificates (see Note #2) + * Configure Apache + * Set file permissions + * Modify the localsettings.py or mySettings.py depending on the + component being installed + * Populate database + * When installation starts, ofver will ask if it is an OFELIA + project installation or not. Select No (N) for non OFELIA testbeds. + + Note #2: When installing the component, you will need to create the + certificates for the Certification Authority (CA) first and for the + component later. Do not use the same Common Name (CN) for both of them, + and make sure that the CN you use in the component later certificate + (you can use an IP) is the same you then set in the SITE_DOMAIN field + in the localsettings.py file. + +2.3 For OXAD (XEN agent for virtualization purposes): + + Create the directory and clone the repository: + + mkdir -p /opt/ofelia/oxa + git clone https://github.com/fp7-ofelia/ocf.git /opt/ofelia/oxa/repository + + The tree should look like: + + marc@foix:/opt/ofelia/oxa$ tree . -L 1 + '-- repository + + Trigger OFVER install by performing the following as a root user (see Note #3): + + cd /opt/ofelia/oxa/repository/vt_manager/src/python/agent/tools + ./ofver install + + Note #3: When installation starts, ofver will ask if it is an OFELIA project + installation or not, and accordingly ofver will download the VMs templates + from the proper storage. + + +3. Upgrading +------------ + +3.1 For Expedient, Opt-in, VT manager: choose the components to install as a + root user. This will implicitly trigger OFVER: + + cd /opt/ofelia/deploy + python upgrade.py + +3.2 For OXAD (XEN agent for virtualization purposes): + + cd /opt/ofelia/oxa/repository/vt_manager/src/python/agent/tools + ./ofver upgrade + + +4. Migrating +------------ + +4.1 For Expedient, Opt-in, VT manager: choose the new path in your servers + where you want the OCF stack code to be migrated: + + cd /opt/ofelia/deploy + python migrate.py + +4.2 For OXAD (XEN agent for virtualization purposes); this features is not + supported + + +5. Additional notes +------------------- + +Please have a look to Manuals [https://github.com/fp7-ofelia/ocf/wiki/Manuals] +for further component configuration. + +You can use -f force flag on OFVER to force installation/upgrade. Take a look +at ./ofver -h for more details. + + +=============== +FURTHER READING +=============== + +For more information about configuration, troubleshooting, contribution and +so on please visit https://github.com/fp7-ofelia/ocf/wiki diff --git a/core/__init__.py b/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/__init__.py b/core/lib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/__init__.py b/core/lib/am/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/ambase/__init__.py b/core/lib/am/ambase/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/core/lib/am/ambase/src/__init__.py b/core/lib/am/ambase/src/__init__.py new file mode 100644 index 00000000..cdd47473 --- /dev/null +++ b/core/lib/am/ambase/src/__init__.py @@ -0,0 +1,34 @@ +class Handler: + + def __init__(self): + self.__component_manager_id = None + self.__component_id = None + + def ListResources(self, credentials=list(), options=dict()): + pass + + def Describe(self,urns=list(), credentials=list(), options=dict()): + pass + + def Allocate(self, slice_urn, credentials=list(), rspec="", options=dict()): + pass + + def Provision(self, urns=list(), credentials=list(), options=dict()): + pass + + def Renew(self, urns=list(), credentials=list(), expiration_time="", options=dict()): + pass + + def Status(self, urns=list(), credentials=list(), options=dict()): + pass + + def PerformOperationalAction(self, urns=list(), credentials=list(), action="", options=dict()): + pass + + def Delete(self, urns=list(), credentials=list(), options=dict()): + pass + + def Shutdown(self, slice_urn, credentials=list(), options=dict()): + pass + + diff --git a/core/lib/am/ambase/src/abstract/__init__.py b/core/lib/am/ambase/src/abstract/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/ambase/src/abstract/classes/__init__.py b/core/lib/am/ambase/src/abstract/classes/__init__.py new file mode 100644 index 00000000..20b1b359 --- /dev/null +++ b/core/lib/am/ambase/src/abstract/classes/__init__.py @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/core/lib/am/ambase/src/abstract/classes/credentialmanagerbase.py b/core/lib/am/ambase/src/abstract/classes/credentialmanagerbase.py new file mode 100644 index 00000000..9e611e94 --- /dev/null +++ b/core/lib/am/ambase/src/abstract/classes/credentialmanagerbase.py @@ -0,0 +1,21 @@ +from abc import ABCMeta +from abc import abstractmethod + +class CredentialManagerBase: + + __metaclass__ = ABCMeta + + @abstractmethod + def validate_for(self, credentials, method): + return "" + + @abstractmethod + def get_valid_creds(self): + return "" + + @abstractmethod + def get_expiration_list(self): + return "" + + #TODO add methods to this class + diff --git a/core/lib/am/ambase/src/abstract/classes/delegatebase.py b/core/lib/am/ambase/src/abstract/classes/delegatebase.py new file mode 100644 index 00000000..89ff573d --- /dev/null +++ b/core/lib/am/ambase/src/abstract/classes/delegatebase.py @@ -0,0 +1,62 @@ +from abc import ABCMeta +from abc import abstractmethod + +class DelegateBase: + + """ + Handle internal exceptions to pass to the handler + """ + + __metaclass__= ABCMeta + + @abstractmethod + def get_version(self): + return + + @abstractmethod + def list_resources(self, geni_available=False): + return + + @abstractmethod + def describe(self, urns=dict()): + return + + @abstractmethod + def reserve(self, slice_urn, reservation, expiration, users): + """ + Allocate slivers + """ + # If there is no value, use empty string + #slice_urn = slice_urn or "" + return + + @abstractmethod + def create(self, urns, expiration, users): + """ + Provision slivers + """ + return + + @abstractmethod + def delete(self, urns=list()): + """ + Delete slivers + """ + return + + @abstractmethod + def perform_operational_action(self, urns=list(), action=None, geni_besteffort=True): + return + + @abstractmethod + def status(self, urns=list()): + return + + @abstractmethod + def renew(self, urns=list(), expiration_time=None): + return + + @abstractmethod + def shut_down(self, urns=list()): + return + diff --git a/core/lib/am/ambase/src/abstract/classes/handlerbase.py b/core/lib/am/ambase/src/abstract/classes/handlerbase.py new file mode 100644 index 00000000..ef0be713 --- /dev/null +++ b/core/lib/am/ambase/src/abstract/classes/handlerbase.py @@ -0,0 +1,55 @@ +from abc import ABCMeta +from abc import abstractmethod + +class HandlerBase: + + """ + 1. Handle credentials & options + 2. Translate RSpecs to {aggregate, slice, sliver, resource} instances + """ + + __metaclass__= ABCMeta + + @abstractmethod + def GetVersion(self, options=dict()): + """ + Does not require credentials + """ + return + + @abstractmethod + def ListResources(self, credentials=list(), options=dict()): + return + + @abstractmethod + def Describe(self, urns=dict(), credentials=dict(),options=dict()): + return + + @abstractmethod + def Allocate(self, slice_urn="", credentials=list(), rspec="", options=dict()): + return + + @abstractmethod + def Provision(self, urns=list(), credentials=list(), options=dict()): + return + + @abstractmethod + def Delete(self, urns=list(), credentials=list(), options=dict()): + return + + @abstractmethod + def PerformOperationalAction(self, urns=list(), credentials=list(), action=None, options=dict()): + return + + @abstractmethod + def Status(self, urns=list(), credentials=list(), options=dict()): + return + + @abstractmethod + def Renew(self, urns=list(), credentials=list(), expiration_time=None, options=dict()): + return + + @abstractmethod + def Shutdown(self, slice_urn="", credentials=list(), options=dict()): + return + diff --git a/core/lib/am/ambase/src/abstract/classes/resourcemanagerbase.py b/core/lib/am/ambase/src/abstract/classes/resourcemanagerbase.py new file mode 100644 index 00000000..0760f273 --- /dev/null +++ b/core/lib/am/ambase/src/abstract/classes/resourcemanagerbase.py @@ -0,0 +1,39 @@ +from abc import ABCMeta +from abc import abstractmethod + +class ResourceManagerBase: + + __metaclass__= ABCMeta + + @abstractmethod + def get_resources(self, urns = None): + return + + @abstractmethod + def create_resources(self, urns, expiration, users): + return + + @abstractmethod + def reserve_resources(self, slice_urn, reservation, expiration, users): + return + + @abstractmethod + def start_resources(self, urns, geni_best_effort): + return + + @abstractmethod + def stop_resources(self, urns, geni_best_effort): + return + + @abstractmethod + def reboot_resources(self, urns, geni_best_effort): + return + + @abstractmethod + def delete_resources(self, urns, geni_best_effort): + return + + @abstractmethod + def renew_resources(self, urns, geni_best_effort): + return + diff --git a/core/lib/am/ambase/src/abstract/classes/rspecmanagerbase.py b/core/lib/am/ambase/src/abstract/classes/rspecmanagerbase.py new file mode 100644 index 00000000..df6631ef --- /dev/null +++ b/core/lib/am/ambase/src/abstract/classes/rspecmanagerbase.py @@ -0,0 +1,33 @@ +from abc import ABCMeta +from abc import abstractmethod + +class RSpecManagerBase: + """ + Abstract class, to be implemented in a new class. + """ + __metaclass__ = ABCMeta + + @abstractmethod + def compose_advertisement(self, resources): + """ + Returns the advertisement RSpec using a set of + resources as input. + """ + return + + @abstractmethod + def compose_manifest(self, slivers): + """ + Returns the manifest RSpec using a set of slivers + (group of resources) as input. + """ + return + + @abstractmethod + def parse_request(self, request_rspec): + """ + Translates the request RSpec into a set of + resources. + """ + return + diff --git a/core/lib/am/ambase/src/ambase/__init__.py b/core/lib/am/ambase/src/ambase/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/ambase/src/ambase/exceptions.py b/core/lib/am/ambase/src/ambase/exceptions.py new file mode 100644 index 00000000..c3e7715f --- /dev/null +++ b/core/lib/am/ambase/src/ambase/exceptions.py @@ -0,0 +1,28 @@ +class SliceAlreadyExists(Exception): + pass + +class AllocationError(Exception): + pass + +class ProvisionError(Exception): + pass + +class DeleteError(Exception): + pass + +class Shutdown(Exception): + pass + +class UnsupportedState(Exception): + pass + +class PerformOperationalStateError(Exception): + pass + +class ApiErrorException(Exception): + def __init__(self, code, output): + self.code = code + self.output = output + + def __str__(self): + return "ApiError(%r, %r)" % (self.code, self.output) diff --git a/core/lib/am/ambase/src/geni/__init__.py b/core/lib/am/ambase/src/geni/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/ambase/src/geni/exceptions/__init__.py b/core/lib/am/ambase/src/geni/exceptions/__init__.py new file mode 100644 index 00000000..136d0638 --- /dev/null +++ b/core/lib/am/ambase/src/geni/exceptions/__init__.py @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/lib/am/ambase/src/geni/exceptions/manager.py b/core/lib/am/ambase/src/geni/exceptions/manager.py new file mode 100644 index 00000000..889f9b18 --- /dev/null +++ b/core/lib/am/ambase/src/geni/exceptions/manager.py @@ -0,0 +1,24 @@ +class GENIExceptionManager: + """ + See http://groups.geni.net/geni/attachment/wiki/GAPI_AM_API_V3/CommonConcepts/geni-error-codes.xml + """ + SUCCESS = 0 + BADARGS = 1 + ERROR = 2 + FORBIDDEN = 3 + BADVERSION = 4 + SERVERERROR = 5 + TOOBIG = 6 + REFUSED = 7 + TIMEDOUT = 8 + DBERROR = 9 + RPCERROR = 10 + UNAVAILABLE = 11 + SEARCHFAILED = 12 + UNSUPPORTED = 13 + BUSY = 14 + EXPIRED = 15 + INPROGRESS = 16 + ALREADYEXISTS = 17 + VLAN_UNAVAILABLE = 24 + INSUFFICIENT_BANDWIDTH = 25 diff --git a/core/lib/am/ambase/src/geni/v3/__init__.py b/core/lib/am/ambase/src/geni/v3/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/ambase/src/geni/v3/delegate/__init__.py b/core/lib/am/ambase/src/geni/v3/delegate/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/ambase/src/geni/v3/delegate/delegate.py b/core/lib/am/ambase/src/geni/v3/delegate/delegate.py new file mode 100644 index 00000000..9068905e --- /dev/null +++ b/core/lib/am/ambase/src/geni/v3/delegate/delegate.py @@ -0,0 +1,123 @@ +from ambase.src.abstract.classes.delegatebase import DelegateBase +from ambase.src.ambase.exceptions import SliceAlreadyExists +from ambase.src.ambase.exceptions import AllocationError +from ambase.src.ambase.exceptions import ProvisionError +from ambase.src.ambase.exceptions import DeleteError +from ambase.src.ambase.exceptions import Shutdown +from ambase.src.ambase.exceptions import PerformOperationalStateError + +class GeniV3Delegate(DelegateBase): + + """ + Handle internal exceptions to pass to the handler + """ + + def __init__(self): + self.__resource_manager = None + self.__config = None + + def get_version(self): + '''Specify version information about this AM. That could + include API version information, RSpec format and version + information, etc. Return a dict.''' + reqver = [dict(type=self.__config.REQ_RSPEC_TYPE, + version=self.__config.REQ_RSPEC_VERSION, + schema=self.__config.REQ_RSPEC_SCHEMA, + namespace=self.__config.REQ_RSPEC_NAMESPACE, + extensions=self.__config.REQ_RSPEC_EXTENSIONS)] + adver = [dict(type=self.__config.AD_RSPEC_TYPE, + version=self.__config.AD_RSPEC_VERSION, + schema=self.__config.AD_RSPEC_SCHEMA, + namespace=self.__config.AD_RSPEC_NAMESPACE, + extensions=self.__config.AD_RSPEC_EXTENSIONS)] + + api_versions = dict() + api_versions[str(self.__config.GENI_API_VERSION)] = self.__config.AM_URL + credential_types = [dict(geni_type = self.__config.CREDENTIAL_TYPE, + geni_version = self.__config.GENI_API_VERSION)] + versions = dict(geni_api= self.__config.GENI_API_VERSION, + geni_api_versions=api_versions, + geni_request_rspec_versions=reqver, + geni_ad_rspec_versions=adver, + geni_credential_types=credential_types) + versions.keys().sort() + extensions = self.__resource_manager.get_version() + return versions + + def list_resources(self, geni_available=False): + # No URNs are passed to this command, thus set to "None" + return self.__resource_manager.get_resources(None, geni_available) + + def describe(self, urns=dict()): + return self.__resource_manager.get_resources(urns) + + def reserve(self, slice_urn, reservation, expiration, users=list()): + """ + Allocate slivers + """ + try: + return self.__resource_manager.reserve_resources(slice_urn, reservation, expiration) + except SliceAlreadyExists as e: + raise SliceAlreadyExists(str(e)) + except Exception as e: + raise AllocationError(str(e)) + + #def create(self, urns=list(), expiration=None, users=list(), geni_best_effort=True): + # XXX Default geni_best_effort = False + def create(self, urns=list(), expiration=None, users=list(), geni_best_effort=False): + """ + Provision slivers + """ + try: + return self.__resource_manager.create_resources(urns, expiration, users) + except Exception as e: + raise ProvisionError(e) + + def delete(self, urns=list(), geni_best_effort=False): + """ + Delete slivers + """ + try: + return self.__resource_manager.delete_resources(urns, geni_best_effort) + except Exception as e: + raise DeleteError(str(e)) + + def perform_operational_action(self, urns=list(), action=None, geni_best_effort=False, options=dict()): + try: + if action == "geni_start": + return self.__resource_manager.start_resources(urns, geni_best_effort) + elif action == "geni_stop": + return self.__resource_manager.stop_resources(urns, geni_best_effort) + elif action == "geni_restart": + return self.__resource_manager.reboot_resources(urns, geni_best_effort) + elif action == "geni_update_users": + return self.__resource_manager.update_resources_users(urns, geni_best_effort, options) + elif action == "geni_updating_users_cancel": + return self.__resource_manager.cancel_update_resources_users(urns, geni_best_effort) + elif action == "geni_console_url": + return self.__resource_manager.retrieve_resources_url(urns, geni_best_effort) + raise PerformOperationalStateError("Unknown Operational Action %s" % str(action)) + except Exception as e: + raise PerformOperationalStateError("PerformOperationalError Failed for action %s. Error was: %s " % (action, str(e))) + + def status(self, urns=list()): + return self.__resource_manager.get_resources(urns) + + def renew(self, urns=list(), expiration_time=None, geni_best_effort=False): + return self.__resource_manager.renew_resources(urns, expiration_time, geni_best_effort) + + def shut_down(self, urns=list()): + return None + + def get_resource_manager(self): + return self.__resource_manager + + def get_config(self): + return self.__config + + def set_resource_manager(self, value): + self.__resource_manager = value + + def set_config(self, value): + self.__config = value + diff --git a/core/lib/am/ambase/src/geni/v3/handler/__init__.py b/core/lib/am/ambase/src/geni/v3/handler/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/ambase/src/geni/v3/handler/handler.py b/core/lib/am/ambase/src/geni/v3/handler/handler.py new file mode 100644 index 00000000..a9e25dbe --- /dev/null +++ b/core/lib/am/ambase/src/geni/v3/handler/handler.py @@ -0,0 +1,474 @@ +from ambase.src.abstract.classes.handlerbase import HandlerBase +from ambase.src.ambase.exceptions import SliceAlreadyExists +from ambase.src.ambase.exceptions import AllocationError +from ambase.src.ambase.exceptions import ProvisionError +from ambase.src.ambase.exceptions import DeleteError +from ambase.src.ambase.exceptions import Shutdown +from ambase.src.ambase.exceptions import PerformOperationalStateError + +import base64 +import datetime +import dateutil.parser +import re +import zlib + +class GeniV3Handler(HandlerBase): + + def __init__(self): + self.__delegate = None + self.__credential_manager = None + self.__rspec_manager = None + self.__geni_exception_manager = None + self.__config = None + + def GetVersion(self, options=dict()): + try: + value = self.__delegate.get_version() + except Exception as e: + return self.error_result(self.__geni_exception_manager.ERROR, e) + return self.success_result(result=value) + + def ListResources(self, credentials=list(), options=dict()): + # Credential validation + try: + self.__credential_manager.validate_for("ListResources", credentials) + except Exception as e: + return self.error_result(self.__geni_exception_manager.FORBIDDEN, e) + # Required options validation + if not options.has_key("geni_rspec_version"): + return self.error_result(self.__geni_exception_manager.BADARGS, "Bad Arguments: option geni_rspec_version required in options") + required_options = set(["type", "version"]) + option_list = set(options["geni_rspec_version"].keys()) + if not required_options.issubset(option_list): + return self.error_result(self.__geni_exception_manager.BADARGS, "Bad Arguments: option geni_rspec_version does not have a version, type or geni_rspec_version fields.") + + # Allow only the rspec versions advertised in GetVersion + user_geni_rspec_version = str(options.get("geni_rspec_version").get("version")).lower() + # TODO: Retrieve 'am_geni_rspec_version' and 'am_geni_rspec_type' as a list of values; not just the first one! + am_geni_rspec_version = str(self.__delegate.get_version().get("geni_ad_rspec_versions")[0].get("version")).lower() + user_geni_rspec_type = str(options.get("geni_rspec_version").get("type")).lower() + am_geni_rspec_type = str(self.__delegate.get_version().get("geni_ad_rspec_versions")[0].get("type")).lower() + if user_geni_rspec_version != am_geni_rspec_version or user_geni_rspec_type != am_geni_rspec_type: + return self.error_result(self.__geni_exception_manager.BADVERSION, "Bad Version: option geni_rspec_version defines an invalid version, type or geni_rspec_version value.") + # Retrieving raw resources + geni_available = options.get("geni_available", False) + resources = self.__delegate.list_resources(geni_available) + # Crafting resources into RSpec + output = self.__rspec_manager.compose_advertisement(resources) + # Preparing the output + if options.get("geni_compressed", False): + output = base64.b64encode(zlib.compress(output)) + return self.listresources_success_result(output) + + def Describe(self, urns=dict(),credentials=dict(),options=dict()): + # Credential validation + try: + self.__credential_manager.validate_for("Describe", credentials) + except Exception as e: + return self.error_result(self.__geni_exception_manager.FORBIDDEN, e) + if not options.get("geni_rspec_version"): + return self.error_result(self.__geni_exception_manager.BADARGS, "Bad Arguments: option geni_rspec_version does not have a version, type or geni_rspec_version fields.") + # Options validation + required_options = set(["type", "version"]) + option_list = set(options["geni_rspec_version"].keys()) + if not required_options.issubset(option_list): + return self.error_result(self.__geni_exception_manager.BADARGS, "Bad Arguments: option geni_rspec_version does not have a version, type or geni_rspec_version fields.") + + # Retrieving slivers to manifest + slivers = self.__delegate.describe(urns) + + # Crafting slivers to manifest RSpec + output = self.__rspec_manager.compose_manifest(slivers) + + if options.get("geni_compressed", False): + output = base64.b64encode(zlib.compress(output)) + + if slivers: + # Only act if there is a result + if not type(slivers) == list: + slivers = [slivers] + try: + slice_urn = slivers[0].get_sliver().get_slice_urn() + except: + slice_urn = slivers[0].get_slice_urn() + else: + slice_urn = urns[0] + + return self.success_result(output, slivers, slice_urn) + + def Allocate(self, slice_urn="", credentials=list(), rspec="", options=dict()): + # Credential validation + try: + creds = self.__credential_manager.validate_for("Allocate", credentials) + except Exception as e: + return self.error_result(self.__geni_exception_manager.FORBIDDEN, e) + reservation = self.__rspec_manager.parse_request(rspec) + # expiration == self.__get_expiration(creds) + # First is datetime, Second is RFC3339 + expiration = self.__credential_manager.get_slice_expiration(creds) + # It is possible to request for sliver expiration time < credentials expiration time + if "geni_end_time" in options: + expiration = min(self.__get_expiration(creds), options["geni_end_time"]) + users = self.__get_users_pubkeys(creds) + try: + allocated_slivers = self.__delegate.reserve(slice_urn, reservation, expiration, users) + except SliceAlreadyExists as e: + return self.error_result(self.__geni_exception_manager.ALREADYEXISTS, e) + except AllocationError as e: + return self.error_result(self.__geni_exception_manager.ERROR, e) + + manifest = self.__rspec_manager.compose_manifest(allocated_slivers) + if not type(allocated_slivers) == list: + allocated_slivers = [allocated_slivers] + + return self.success_result(manifest, allocated_slivers) + + def Provision(self, urns=list(), credentials=list(), options=dict()): + # Credential validation + try: + creds = self.__credential_manager.validate_for("Provision", credentials) + except Exception as e: + return self.error_result(self.__geni_exception_manager.FORBIDDEN, e) + + #expiration = self.__get_expiration() + expiration = self.__credential_manager.get_slice_expiration(creds) + if "geni_end_time" in options: + #XXX I know, theory says that should be the minimum, but I don't trust the credentials expiration, yet + expiration = max(self.__get_expiration(creds), options["geni_end_time"]) + if not "geni_users" in options: + users = self.__get_users_pubkeys(creds) + else: + users = self.__format_geni_users(options["geni_users"]) + if not options.get("geni_rspec_version"): + return self.error_result(self.__geni_exception_manager.BADARGS, "Bad Arguments: option geni_rspec_version does not have a version, type or geni_rspec_version fields.") + # Options validation + required_options = set(["type", "version"]) + option_list = set(options["geni_rspec_version"].keys()) + if not required_options.issubset(option_list): + return self.error_result(self.__geni_exception_manager.BADARGS, "Bad Arguments: option geni_rspec_version does not have a version, type or geni_rspec_version fields.") + # geni_best_effort filled up when present + geni_best_effort = options.get("geni_best_effort", False) + try: + slivers = self.__delegate.create(urns, expiration, users, geni_best_effort) + except ProvisionError as e: + if "NO ALLOCATION FOUND" in str(e).upper(): + return self.error_result(self.__geni_exception_manager.SEARCHFAILED, str(e)) + elif "RE-PROVISIONING" in str(e).upper(): + return self.error_result(self.__geni_exception_manager.EXPIRED, str(e)) + else: + return self.error_result(self.__geni_exception_manager.ERROR, str(e)) + + manifest = self.__rspec_manager.compose_manifest(slivers) + if not type(slivers) == list: + slivers = [slivers] + return self.success_result(manifest, slivers) + + def Delete(self, urns=list(), credentials=list(), options=dict()): + # Credential validation + try: + creds = self.__credential_manager.validate_for("Delete", credentials) + except Exception as e: + return self.error_result(self.__geni_exception_manager.FORBIDDEN, e) + + # Calling Delete() on an unknown, expired or deleted sliver (by explicit URN) shall + # result in an error (e.g. SEARCHFAILED, EXPIRED, or ERROR) (unless geni_best_effort + # is true, in which case the method may succeed and return a geni_error for each + # sliver that failed). Attempting to Delete a slice (no slivers identified) with + # no current slivers at this aggregate may return an empty list of slivers, may + # return a list of previous slivers that have since been deleted, or may even + # return an error (e.g. SEARCHFAILED or `EXPIRED); details are aggregate specific. + + # geni_best_effort filled up when present + geni_best_effort = options.get("geni_best_effort", False) + try: + result = self.__delegate.delete(urns, geni_best_effort) + # Return error codes depending on given exception + except DeleteError as e: + return self.error_result(self.__geni_exception_manager.ERROR, e) + + return self.delete_success_result(result) + + def PerformOperationalAction(self, urns=list(), credentials=list(), action=None, options=dict()): + # Credential validation + try: + creds = self.__credential_manager.validate_for("PerformOperationalAction", credentials) + except Exception as e: + return self.error_result(self.__geni_exception_manager.FORBIDDEN, e) + + actions = ["geni_start", "geni_restart", "geni_stop", "geni_update_users", + "geni_updating_users_cancel", "geni_console_url"] + # TODO Add geni_updating_users_cancel + if action not in actions: + return self.error_result(self.__geni_exception_manager.UNSUPPORTED, "Unsupported Action") + + if options.get("geni_best_effort"): + best_effort = True + else: + best_effort = False + + try: + result = self.__delegate.perform_operational_action(urns, action, best_effort, options) + except PerformOperationalStateError as e: + if "BUSY" in str(e).upper(): + return self.error_result(self.__geni_exception_manager.BUSY, e) + elif "REFUSED" in str(e).upper(): + return self.error_result(self.__geni_exception_manager.REFUSED, e) + else: + return self.error_result(self.__geni_exception_manager.BADARGS, e) + + # Format undefined for this option, since it is "not fully implemented" + if action == "geni_console_url": + return result + return self.success_result(slivers_direct=result) + + def Status(self, urns=list(), credentials=list(), options=dict()): + # Credential validation + try: + creds = self.__credential_manager.validate_for("Status", credentials) + except Exception as e: + return self.error_result(self.__geni_exception_manager.FORBIDDEN, e) + + #expiration = self.__credential_manager.get_slice_expiration(creds) + + try: + result = self.__delegate.status(urns) + except Exception as e: + return self.error_result(self.__geni_exception_manager.ERROR, e) + + if result: + # Only act if there is a result + if not type(result) == list: + result = [result] + try: + + slice_urn = result[0].get_sliver().get_slice_urn() + except: + slice_urn = result[0].get_slice_urn() + else: + slice_urn = urns[0] + return self.success_result(slivers=result, slice_urn=slice_urn) + + def Renew(self, urns=list(), credentials=list(), expiration_time=None, options=dict()): + # Credential validation + try: + creds = self.__credential_manager.validate_for("Renew", credentials) + except Exception as e: + return self.error_result(self.__geni_exception_manager.FORBIDDEN, e) + slice_expiration = self.__credential_manager.get_slice_expiration(creds) + try: + slice_expiration = self.__rfc3339_to_datetime(slice_expiration) + except Exception as e: + return self.error_result(self.__geni_exception_manager.SEARCHFAILED, e) + # Format dates to expected output + try: + expiration_time = self.__rfc3339_to_datetime(expiration_time) + except Exception as e: + return self.error_result(self.__geni_exception_manager.ERROR, e) + now = datetime.datetime.utcnow() + # NOTE: Possibly existing on GCF, but not on GENIv3 API. Using it here, though + if "geni_extend_alap" in options and options["geni_extend_alap"]: + if slice_expiration < expiration_time: + slice_expiration = expiration_time + # If slice already expired & user tries to extend... + if slice_expiration < expiration_time: + # Fail the call, the requested expiration exceeds the slice expir. + msg = "Expired slice or slivers: Requested expiration %s exceeds sliver expiration %s" \ + % (expiration_time, slice_expiration) + return self.error_result(self.__geni_exception_manager.EXPIRED, msg) + # If user tries to extend to a past date... + elif expiration_time < now: + msg = "Expired slice or slivers: Requested expiration %s is in the past (current time: %s)" \ + % (expiration_time, now.strftime("%Y-%m-%d %H:%M:%S.%f")) + return self.error_result(self.__geni_exception_manager.ERROR, msg) + # When requested expiration time is less than the slice expiration and a valid expiration date, serve + else: + # Check options and perform call to delegate + geni_best_effort = options.get("geni_best_effort", False) + try: + result = self.__delegate.renew(urns, expiration_time, geni_best_effort) + except Exception as e: +# if "NOT FOUND" in str(e).upper(): + return self.error_result(self.__geni_exception_manager.SEARCHFAILED, str(e)) + return self.success_result(slivers_direct=result) + + def Shutdown(self, slice_urn="", credentials=list(), options=dict()): + return self.error_result(self.__geni_exception_manager.FORBIDDEN, "Shutdown method is only available for the AM administrators") + + def __get_max_expiration(self): + #six_months = datetime.timedelta(weeks = 6 * 4) #6 months + one_hour = datetime.timedelta(hours = 1) + return one_hour + + # Helper methods + def __get_expiration(self, creds): + now = datetime.datetime.utcnow() + expires = self.__credential_manager.get_expiration_list(creds) + # max_duration is a datetime.timedelta object + max_duration = self.__get_max_expiration() + if max_duration: + expires.append(now + max_duration) + return self.__datetime_to_rfc3339(min(expires)) + + def __datetime_to_rfc3339(self, date): + """ + Returns a datetime object that is formatted according to RFC3339. + """ + try: + # Hint: use "strict_rfc3339" package for validation: strict_rfc3339.validate_rfc3339(...) + # May also be computed as date.replace(...).isoformat("T") + formatted_date = date.replace(tzinfo=dateutil.tz.tzutc()).strftime("%Y-%m-%d %H:%M:%S.%f").replace(" ", "T")+"Z" + except: + try: + formatted_date = date.replace(tzinfo=dateutil.tz.tzutc()).strftime("%Y-%m-%d %H:%M:%S").replace(" ", "T")+"Z" + except: + formatted_date = date + return formatted_date + + def __rfc3339_to_datetime(self, date): + """ + Returns a datetime object from an input string formatted according to RFC3339. + """ + try: + # Removes everything after a "+" or a "." + #date_form = re.sub(r'[\+|\.].+', "", date) + # Removes everything after a "+" + date_form = re.sub(r'[\+].+', "", date).replace("Z", "") + try: + formatted_date = datetime.datetime.strptime(date_form.replace("T"," "), "%Y-%m-%d %H:%M:%S.%f") + #formatted_date = datetime.datetime.strptime(date[:-1].replace("T"," "), "%Y-%m-%d %H:%M:%S") + except: + formatted_date = datetime.datetime.strptime(date_form.replace("T"," "), "%Y-%m-%d %H:%M:%S") + except: + formatted_date = date + return formatted_date + + def delete_success_result(self, slivers): + value = list() + + for sliver in slivers: + try: + sliver = sliver.get_sliver() + error_msg = sliver.get_error_message() + except: + sliver = sliver + error_msg = None + sliver_struct = dict() + sliver_struct["geni_sliver_urn"] = sliver.get_urn() + sliver_struct["geni_allocation_status"] = sliver.get_allocation_status() + sliver_struct["geni_expires"] = sliver.get_expiration() + if not error_msg == None: + sliver_struct["geni_error"] = error_msg + value.append(sliver_struct) + return self.build_property_list(self.__geni_exception_manager.SUCCESS, value=value) + + def listresources_success_result(self, rspec): + return self.build_property_list(self.__geni_exception_manager.SUCCESS, value=rspec) + + def success_result(self, rspec=None, slivers=[], slice_urn=None, slivers_direct=list(), result=None): + """ + Prepares "value" struct. + """ + if slivers_direct: + value = list() + for sliver in slivers_direct: + geni_sliver_special_struct = self.__get_geni_sliver_structure(sliver) + value.append(geni_sliver_special_struct) + elif result != None: + value = result + else: + value = dict() + if rspec: + value["geni_rspec"] = rspec + if slice_urn: + value["geni_urn"] = slice_urn + # Return empty list of slivers for some cases + value["geni_slivers"] = list() + for sliver in slivers: + geni_sliver_struct = self.__get_geni_sliver_structure(sliver) + value["geni_slivers"].append(geni_sliver_struct) + return self.build_property_list(self.__geni_exception_manager.SUCCESS, value=value) + + def error_result(self, code, output): + return self.build_property_list(code, output=str(output)) + + def build_property_list(self, geni_code, value=None, output=None): + result = {} + result["geni_api"] = self.__config.GENI_API_VERSION + result["code"] = {"geni_code": geni_code} + if self.__config: + if self.__config.AM_TYPE: + result["code"]["am_type"] = self.__config.AM_TYPE + if self.__config.AM_CODE_VERSION: + result["code"]["am_code"] = self.__config.AM_CODE_VERSION + # Non-zero geni_code implies error: output is required, value is optional + if geni_code: + result["output"] = output + result["value"] = "" + if value: + result["value"] = value + # Zero geni_code implies success: value is required, output is optional + else: + result["value"] = value + return result + + def __get_geni_sliver_structure(self, resource): + try: + sliver = resource.get_sliver() + error_message = resource.get_error_message() + except: + sliver = resource + error_message = None + sliver_struct = dict() + sliver_struct["geni_sliver_urn"] = sliver.get_urn() + sliver_struct["geni_allocation_status"] = sliver.get_allocation_status() + sliver_struct["geni_expires"] = self.__datetime_to_rfc3339(sliver.get_expiration()) + sliver_struct["geni_operational_status"] = sliver.get_operational_status() + if error_message: + sliver_struct["geni_error"] = error_message + return sliver_struct + + def __get_users_pubkeys(self, creds): + users = list() + for cred in creds: + user = dict() + user_gid = cred.get_gid_caller() + user["name"] = user_gid.get_urn() + user["keys"] = user_gid.get_pubkey().get_pubkey_string() + if not type(user["keys"]) == list: + user["keys"] = [user["keys"]] + users.append(user) + return users + + def __format_geni_users(self, geni_users): + users = list() + for user in geni_users: + name = user['urn'] + users.append({'name':name, 'keys':user['keys']}) + return users + + def get_delegate(self): + return self.__delegate + + def get_credential_manager(self): + return self.__credential_manager + + def get_rspec_manager(self): + return self.__rspec_manager + + def get_geni_exception_manager(self): + return self.__geni_exception_manager + + def set_delegate(self, value): + self.__delegate = value + + def set_credential_manager(self, value): + self.__credential_manager = value + + def set_rspec_manager(self, value): + self.__rspec_manager = value + + def set_geni_exception_manager(self, value): + self.__geni_exception_manager = value + + def set_config(self, value): + self.__config = value diff --git a/core/lib/am/credentials/__init__.py b/core/lib/am/credentials/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/credentials/src/DEPENDENCIES b/core/lib/am/credentials/src/DEPENDENCIES new file mode 100644 index 00000000..42a826d4 --- /dev/null +++ b/core/lib/am/credentials/src/DEPENDENCIES @@ -0,0 +1,4 @@ +lxml +openssl +m2crypto +xmlsec1 \ No newline at end of file diff --git a/core/lib/am/credentials/src/__init__.py b/core/lib/am/credentials/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/credentials/src/manager/__init__.py b/core/lib/am/credentials/src/manager/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/credentials/src/manager/gcfmanager.py b/core/lib/am/credentials/src/manager/gcfmanager.py new file mode 100644 index 00000000..3eb10d2d --- /dev/null +++ b/core/lib/am/credentials/src/manager/gcfmanager.py @@ -0,0 +1,78 @@ +from ambase.src.abstract.classes.credentialmanagerbase import CredentialManagerBase +from credentials.src.trustgcf.cred_util import CredentialVerifier + +class GCFCredentialManager(CredentialManagerBase): + + def __init__(self): + self.__config = None + self.__root_cert = None + self.__auth = None#CredentialVerifier() + + def get_auth(self): + return self.__auth + + def get_config(self): + return self.__config + + def get_root_cert(self): + return self.__root_cert + + def set_auth(self, value): + self.__auth = value + + def set_config(self, value): + self.__config = value + root_cert = open(self.__config.ROOT_CERT, 'r').read() + self.__root_cert = root_cert + self.__auth = CredentialVerifier(self.__config.TRUSTED_ROOTS_DIR) + + def set_root_cert(self,value): + self.__root_cert = value + + def validate_for(self, method, credentials): + credentials = self.__clean_credentials(credentials) + return self._get_geniv2_validation(method, credentials) + + def get_valid_creds(self): + return "" + + def get_expiration_list(self, credentials): + expirations = list() + for cred in credentials: + expirations.append(cred.expiration) + return expirations + + def get_slice_expiration(self, credentials): + return credentials[0].expiration + + def _get_geniv2_validation(self, method, credentials): + method = (self._translate_to_geniv2_method(method),) + try: + valid_cred = self.__auth.verify_from_strings(self.__root_cert,credentials,None, method, {}) + return valid_cred + except Exception as e: + raise e + + def _translate_to_geniv2_method(self, method): + if method == "Allocate" or method == "Provision": + return "createsliver" + elif method == "ListResources": + return "listnodes" + elif method == "Describe" or method == "Status": + return "sliverstatus" + elif method == "PerformOperationalAction": + return "createsliver" + elif method == "Delete": + return "deletesliver" + elif method == "Renew": + return "renewsliver" + raise Exception("Unknown method %s", method) + + def __clean_credentials(self, credentials): + creds = list() + for cred in credentials: + if cred.get("geni_value"): + creds.append(cred["geni_value"]) + else: + creds.append(cred) + return creds diff --git a/core/lib/am/credentials/src/manager/manager.py b/core/lib/am/credentials/src/manager/manager.py new file mode 100644 index 00000000..d015834a --- /dev/null +++ b/core/lib/am/credentials/src/manager/manager.py @@ -0,0 +1,82 @@ +from ambase.src.abstract.classes.credentialmanagerbase import CredentialManagerBase +from credentials.src.trust.auth import Auth +from credentials.src.trust.credential import Credential +from credentials.src.trust.abaccredential import ABACCredential +from ambase.src.ambase.exceptions import ApiErrorException +from ambase.src.geni.exceptions.manager import GENIExceptionManager + +class CredentialManager(CredentialManagerBase): + + def __init__(self): + self.__config = None + self.__auth = None#Auth() + + def get_auth(self): + return self.__auth + + def set_auth(self, value): + self.__auth = value + + def validate_for(self, method, credentials): + return self._get_geniv2_validation(method, credentials) + + def get_valid_creds(self): + return "" + + def get_expiration_list(selfi, credentials): + expirations = list() + for cred in credentials: + expirations.append(cred.expiration) + return expirations + + def get_slice_expiration(self, credentials): + + return "" + + def __clean_credentials(self, credentials): + clean_creds = [c['geni_value'] for c in filter(self.__is_geni_cred, credentials)] + return clean_creds + + def _get_geniv2_validation(self, method, credentials): + method = self._translate_to_geniv2_method(method) + try: + if self.__auth == None: + self.__auth = Auth(config=self.__config) + credentials = self.__clean_credentials(credentials)#[c['geni_value'] for c in filter(self.__is_geni_cred, credentials)] + valid_cred = self.__auth.checkCredentials(credentials, method) + except Exception as e: + raise e + + def _translate_to_geniv2_method(self, method): + if method == "Allocate" or method == "Provision": + return "createsliver" + elif method == "ListResources": + return "listnodes" + elif method == "Describe" or method == "Status": + return "sliverstatus" + elif method == "PerforOperationalAction": + return "startslice" + elif method == "Delete": + return "deletesliver" + elif method == "Renew": + return "renewsliver" + raise Exception("Unknown method: %s" % method) + + def __is_geni_cred(self, credential): + """ + Filter (for use with filter()) to yield all 'geni_sfa' credentials + regardless over version. + """ + if not isinstance(credential, dict): + msg = "Bad Arguments: Received credential of unknown type %r" + msg = msg % (type(credential)) + raise ApiErrorException(GENIExceptionManager.BADARGS, msg) + return ('geni_type' in credential + and str(credential['geni_type']).lower() in [Credential.SFA_CREDENTIAL_TYPE, + ABACCredential.ABAC_CREDENTIAL_TYPE]) + + def get_config(self): + return self.__config + + def set_config(self, value): + self.__config = value diff --git a/core/lib/am/credentials/src/trust/__init__.py b/core/lib/am/credentials/src/trust/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/credentials/src/trust/abaccredential.py b/core/lib/am/credentials/src/trust/abaccredential.py new file mode 100644 index 00000000..7854c0a4 --- /dev/null +++ b/core/lib/am/credentials/src/trust/abaccredential.py @@ -0,0 +1,285 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2014 Raytheon BBN Technologies +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- + +from __future__ import absolute_import + +from credentials.src.trust.credential import Credential +from credentials.src.trust.credential import DEFAULT_CREDENTIAL_LIFETIME +from credentials.src.trust.credential import append_sub + + +from StringIO import StringIO +from xml.dom.minidom import Document, parseString +from geniutils.src.faults.faults import CredentialNotVerifiable +import datetime +from dateutil import tz + +HAVELXML = False +try: + from lxml import etree + HAVELXML = True +except: + pass + +# This module defines a subtype of sfa.trust,credential.Credential +# called an ABACCredential. An ABAC credential is a signed statement +# asserting a role representing the relationship between a subject and target +# or between a subject and a class of targets (all those satisfying a role). +# +# An ABAC credential is like a normal SFA credential in that it has +# a validated signature block and is checked for expiration. +# It does not, however, have 'privileges'. Rather it contains a 'head' and +# list of 'tails' of elements, each of which represents a principal and +# role. + +# A special case of an ABAC credential is a speaks_for credential. Such +# a credential is simply an ABAC credential in form, but has a single +# tail and fixed role 'speaks_for'. In ABAC notation, it asserts +# AGENT.speaks_for(AGENT)<-CLIENT, or "AGENT asserts that CLIENT may speak +# for AGENT". The AGENT in this case is the head and the CLIENT is the +# tail and 'speaks_for_AGENT' is the role on the head. These speaks-for +# Credentials are used to allow a tool to 'speak as' itself but be recognized +# as speaking for an individual and be authorized to the rights of that +# individual and not to the rights of the tool itself. + +# For more detail on the semantics and syntax and expected usage patterns +# of ABAC credentials, see http://groups.geni.net/geni/wiki/TIEDABACCredential. + + +# An ABAC element contains a principal (keyid and optional mnemonic) +# and optional role and linking_role element +class ABACElement: + def __init__(self, principal_keyid, principal_mnemonic=None, \ + role=None, linking_role=None): + self._principal_keyid = principal_keyid + self._principal_mnemonic = principal_mnemonic + self._role = role + self._linking_role = linking_role + + def get_principal_keyid(self): return self._principal_keyid + def get_principal_mnemonic(self): return self._principal_mnemonic + def get_role(self): return self._role + def get_linking_role(self): return self._linking_role + + def __str__(self): + ret = self._principal_keyid + if self._principal_mnemonic: + ret = "%s (%s)" % (self._principal_mnemonic, self._principal_keyid) + if self._linking_role: + ret += ".%s" % self._linking_role + if self._role: + ret += ".%s" % self._role + return ret + +# Subclass of Credential for handling ABAC credentials +# They have a different cred_type (geni_abac vs. geni_sfa) +# and they have a head and tail and role (as opposed to privileges) +class ABACCredential(Credential): + + ABAC_CREDENTIAL_TYPE = 'geni_abac' + + def __init__(self, create=False, subject=None, + string=None, filename=None): + self.head = None # An ABACElemenet + self.tails = [] # List of ABACElements + super(ABACCredential, self).__init__(create=create, + subject=subject, + string=string, + filename=filename) + self.cred_type = ABACCredential.ABAC_CREDENTIAL_TYPE + + def get_head(self) : + if not self.head: + self.decode() + return self.head + + def get_tails(self) : + if len(self.tails) == 0: + self.decode() + return self.tails + + def decode(self): + super(ABACCredential, self).decode() + # Pull out the ABAC-specific info + doc = parseString(self.xml) + rt0s = doc.getElementsByTagName('rt0') + if len(rt0s) != 1: + raise CredentialNotVerifiable("ABAC credential had no rt0 element") + rt0_root = rt0s[0] + heads = self._get_abac_elements(rt0_root, 'head') + if len(heads) != 1: + raise CredentialNotVerifiable("ABAC credential should have exactly 1 head element, had %d" % len(heads)) + + self.head = heads[0] + self.tails = self._get_abac_elements(rt0_root, 'tail') + + def _get_abac_elements(self, root, label): + abac_elements = [] + elements = root.getElementsByTagName(label) + for elt in elements: + keyids = elt.getElementsByTagName('keyid') + if len(keyids) != 1: + raise CredentialNotVerifiable("ABAC credential element '%s' should have exactly 1 keyid, had %d." % (label, len(keyids))) + keyid_elt = keyids[0] + keyid = keyid_elt.childNodes[0].nodeValue.strip() + + mnemonic = None + mnemonic_elts = elt.getElementsByTagName('mnemonic') + if len(mnemonic_elts) > 0: + mnemonic = mnemonic_elts[0].childNodes[0].nodeValue.strip() + + role = None + role_elts = elt.getElementsByTagName('role') + if len(role_elts) > 0: + role = role_elts[0].childNodes[0].nodeValue.strip() + + linking_role = None + linking_role_elts = elt.getElementsByTagName('linking_role') + if len(linking_role_elts) > 0: + linking_role = linking_role_elts[0].childNodes[0].nodeValue.strip() + + abac_element = ABACElement(keyid, mnemonic, role, linking_role) + abac_elements.append(abac_element) + + return abac_elements + + def dump_string(self, dump_parents=False, show_xml=False): + result = "ABAC Credential\n" + filename=self.get_filename() + if filename: result += "Filename %s\n"%filename + if self.expiration: + result += "\texpiration: %s \n" % self.expiration.isoformat() + + result += "\tHead: %s\n" % self.get_head() + for tail in self.get_tails(): + result += "\tTail: %s\n" % tail + if self.get_signature(): + result += " gidIssuer:\n" + result += self.get_signature().get_issuer_gid().dump_string(8, dump_parents) + if show_xml and HAVELXML: + try: + tree = etree.parse(StringIO(self.xml)) + aside = etree.tostring(tree, pretty_print=True) + result += "\nXML:\n\n" + result += aside + result += "\nEnd XML\n" + except: + import traceback + print "exc. Credential.dump_string / XML" + traceback.print_exc() + return result + + # sounds like this should be __repr__ instead ?? + # Produce the ABAC assertion. Something like [ABAC cred: Me.role<-You] or similar + def get_summary_tostring(self): + result = "[ABAC cred: " + str(self.get_head()) + for tail in self.get_tails(): + result += "<-%s" % str(tail) + result += "]" + return result + + def createABACElement(self, doc, tagName, abacObj): + kid = abacObj.get_principal_keyid() + mnem = abacObj.get_principal_mnemonic() # may be None + role = abacObj.get_role() # may be None + link = abacObj.get_linking_role() # may be None + ele = doc.createElement(tagName) + prin = doc.createElement('ABACprincipal') + ele.appendChild(prin) + append_sub(doc, prin, "keyid", kid) + if mnem: + append_sub(doc, prin, "mnemonic", mnem) + if role: + append_sub(doc, ele, "role", role) + if link: + append_sub(doc, ele, "linking_role", link) + return ele + + ## + # Encode the attributes of the credential into an XML string + # This should be done immediately before signing the credential. + # WARNING: + # In general, a signed credential obtained externally should + # not be changed else the signature is no longer valid. So, once + # you have loaded an existing signed credential, do not call encode() or sign() on it. + + def encode(self): + # Create the XML document + doc = Document() + signed_cred = doc.createElement("signed-credential") + +# Declare namespaces +# Note that credential/policy.xsd are really the PG schemas +# in a PL namespace. +# Note that delegation of credentials between the 2 only really works +# cause those schemas are identical. +# Also note these PG schemas talk about PG tickets and CM policies. + signed_cred.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") + signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.geni.net/resources/credential/2/credential.xsd") + signed_cred.setAttribute("xsi:schemaLocation", "http://www.planet-lab.org/resources/sfa/ext/policy/1 http://www.planet-lab.org/resources/sfa/ext/policy/1/policy.xsd") + +# PG says for those last 2: +# signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.protogeni.net/resources/credential/credential.xsd") +# signed_cred.setAttribute("xsi:schemaLocation", "http://www.protogeni.net/resources/credential/ext/policy/1 http://www.protogeni.net/resources/credential/ext/policy/1/policy.xsd") + + doc.appendChild(signed_cred) + + # Fill in the bit + cred = doc.createElement("credential") + cred.setAttribute("xml:id", self.get_refid()) + signed_cred.appendChild(cred) + append_sub(doc, cred, "type", "abac") + + # Stub fields + append_sub(doc, cred, "serial", "8") + append_sub(doc, cred, "owner_gid", '') + append_sub(doc, cred, "owner_urn", '') + append_sub(doc, cred, "target_gid", '') + append_sub(doc, cred, "target_urn", '') + append_sub(doc, cred, "uuid", "") + + if not self.expiration: + self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) + self.expiration = self.expiration.replace(microsecond=0) + if self.expiration.tzinfo is not None and self.expiration.tzinfo.utcoffset(self.expiration) is not None: + # TZ aware. Make sure it is UTC + self.expiration = self.expiration.astimezone(tz.tzutc()) + append_sub(doc, cred, "expires", self.expiration.strftime('%Y-%m-%dT%H:%M:%SZ')) # RFC3339 + + abac = doc.createElement("abac") + rt0 = doc.createElement("rt0") + abac.appendChild(rt0) + cred.appendChild(abac) + append_sub(doc, rt0, "version", "1.1") + head = self.createABACElement(doc, "head", self.get_head()) + rt0.appendChild(head) + for tail in self.get_tails(): + tailEle = self.createABACElement(doc, "tail", tail) + rt0.appendChild(tailEle) + + # Create the tag + signatures = doc.createElement("signatures") + signed_cred.appendChild(signatures) + + # Get the finished product + self.xml = doc.toxml("utf-8") diff --git a/core/lib/am/credentials/src/trust/auth.py b/core/lib/am/credentials/src/trust/auth.py new file mode 100644 index 00000000..5d8125dc --- /dev/null +++ b/core/lib/am/credentials/src/trust/auth.py @@ -0,0 +1,309 @@ + +# +# SfaAPI authentication +# + +from geniutils.src.faults.faults import InsufficientRights +from geniutils.src.faults.faults import MissingCallerGID +from geniutils.src.faults.faults import MissingTrustedRoots +from geniutils.src.faults.faults import PermissionError +from geniutils.src.faults.faults import BadRequestHash +from geniutils.src.faults.faults import ConnectionKeyGIDMismatch +from geniutils.src.faults.faults import SfaPermissionDenied + +from geniutils.src.xrn.xrn import get_authority + +from credentials.src.trust.gid import GID +from credentials.src.trust.rights import Rights +from credentials.src.trust.certificate import Certificate +from credentials.src.trust.credential import Credential +from credentials.src.trust.trustedroots import TrustedRoots +from credentials.src.trust.hierarchy import Hierarchy +from credentials.src.trust.sfaticket import SfaTicket + +from settings.src.settings import Settings as CONFIG + + +class Auth: + """ + Credential based authentication + """ + + def __init__(self, peer_cert = None, config = None ): + self.peer_cert = peer_cert + if not config: + self.config = CONFIG#Config() + else: + self.config = config + self.hierarchy = Hierarchy(self.config) + self.load_trusted_certs() + + def load_trusted_certs(self): + self.trusted_cert_list = TrustedRoots(self.config.TRUSTED_ROOTS_DIR).get_list() + self.trusted_cert_file_list = TrustedRoots(self.config.TRUSTED_ROOTS_DIR).get_file_list() + + def checkCredentials(self, creds, operation, hrn = None): + valid = [] + error = None + if not isinstance(creds, list): + creds = [creds] + for cred in creds: + try: + self.check(cred, operation, hrn) + valid.append(cred) + except Exception as e: + cred_obj=Credential(string=cred) + error = e#sys.exc_info()[:2] + continue + if not len(valid): + if not error: + error = "No valid credentials found" + raise InsufficientRights('Access denied: %s' % (str(error))) + return valid + + def check(self, cred, operation, hrn = None): + """ + Check the credential against the peer cert (callerGID included + in the credential matches the caller that is connected to the + HTTPS connection, check if the credential was signed by a + trusted cert and check if the credential is allowed to perform + the specified operation. + """ + self.client_cred = Credential(string = cred) + self.client_gid = self.client_cred.get_gid_caller() + self.object_gid = self.client_cred.get_gid_object() + # make sure the client_gid is not blank + if not self.client_gid: + raise MissingCallerGID(self.client_cred.get_subject()) + + # validate the client cert if it exists + if self.peer_cert: + self.verifyPeerCert(self.peer_cert, self.client_gid) + + # make sure the client is allowed to perform the operation + if operation: + if not self.client_cred.can_perform(operation): + raise InsufficientRights(operation) + if self.trusted_cert_list: + self.client_cred.verify(self.trusted_cert_file_list, self.config.SFA_CREDENTIAL_SCHEMA) + else: + raise MissingTrustedRoots(self.config.get_trustedroots_dir()) + + # Make sure the credential's target matches the specified hrn. + # This check does not apply to trusted peers + trusted_peers = [gid.get_hrn() for gid in self.trusted_cert_list] + if hrn and self.client_gid.get_hrn() not in trusted_peers: + target_hrn = self.object_gid.get_hrn() + if not hrn == target_hrn: + raise PermissionError("Target hrn: %s doesn't match specified hrn: %s " % \ + (target_hrn, hrn) ) + return True + + def check_ticket(self, ticket): + """ + Check if the tickt was signed by a trusted cert + """ + if self.trusted_cert_list: + client_ticket = SfaTicket(string=ticket) + client_ticket.verify_chain(self.trusted_cert_list) + else: + raise MissingTrustedRoots(self.config.get_trustedroots_dir()) + + return True + + def verifyPeerCert(self, cert, gid): + # make sure the client_gid matches client's certificate + if not cert.is_pubkey(gid.get_pubkey()): + raise ConnectionKeyGIDMismatch(gid.get_subject()+":"+cert.get_subject()) + + def verifyGidRequestHash(self, gid, hash, arglist): + key = gid.get_pubkey() + if not key.verify_string(str(arglist), hash): + raise BadRequestHash(hash) + + def verifyCredRequestHash(self, cred, hash, arglist): + gid = cred.get_gid_caller() + self.verifyGidRequestHash(gid, hash, arglist) + + def validateGid(self, gid): + if self.trusted_cert_list: + gid.verify_chain(self.trusted_cert_list) + + def validateCred(self, cred): + if self.trusted_cert_list: + cred.verify(self.trusted_cert_file_list) + + def authenticateGid(self, gidStr, argList, requestHash=None): + gid = GID(string = gidStr) + self.validateGid(gid) + # request_hash is optional + if requestHash: + self.verifyGidRequestHash(gid, requestHash, argList) + return gid + + def authenticateCred(self, credStr, argList, requestHash=None): + cred = Credential(string = credStr) + self.validateCred(cred) + # request hash is optional + if requestHash: + self.verifyCredRequestHash(cred, requestHash, argList) + return cred + + def authenticateCert(self, certStr, requestHash): + cert = Certificate(string=certStr) + # xxx should be validateCred ?? + self.validateCred(cert) + + def gidNoop(self, gidStr, value, requestHash): + self.authenticateGid(gidStr, [gidStr, value], requestHash) + return value + + def credNoop(self, credStr, value, requestHash): + self.authenticateCred(credStr, [credStr, value], requestHash) + return value + + def verify_cred_is_me(self, credential): + cred = Credential(string=credential) + caller_gid = cred.get_gid_caller() + caller_hrn = caller_gid.get_hrn() + if caller_hrn != self.config.SFA_INTERFACE_HRN: + raise SfaPermissionDenied(self.config.SFA_INTEFACE_HRN) + return + + def get_auth_info(self, auth_hrn): + """ + Given an authority name, return the information for that authority. + This is basically a stub that calls the hierarchy module. + + @param auth_hrn human readable name of authority + """ + return self.hierarchy.get_auth_info(auth_hrn) + + + def veriry_auth_belongs_to_me(self, name): + """ + Verify that an authority belongs to our hierarchy. + This is basically left up to the implementation of the hierarchy + module. If the specified name does not belong, ane exception is + thrown indicating the caller should contact someone else. + + @param auth_name human readable name of authority + """ + + # get auth info will throw an exception if the authority doesnt exist + self.get_auth_info(name) + + + def verify_object_belongs_to_me(self, name): + """ + Verify that an object belongs to our hierarchy. By extension, + this implies that the authority that owns the object belongs + to our hierarchy. If it does not an exception is thrown. + + @param name human readable name of object + """ + auth_name = self.get_authority(name) + if not auth_name: + auth_name = name + if name == self.config.SFA_INTERFACE_HRN: + return + self.verify_auth_belongs_to_me(auth_name) + + def verify_auth_belongs_to_me(self, name): + # get auth info will throw an exception if the authority doesnt exist + self.get_auth_info(name) + + + def verify_object_permission(self, name): + """ + Verify that the object gid that was specified in the credential + allows permission to the object 'name'. This is done by a simple + prefix test. For example, an object_gid for plc.arizona would + match the objects plc.arizona.slice1 and plc.arizona. + + @param name human readable name to test + """ + object_hrn = self.object_gid.get_hrn() + if object_hrn == name: + return + if name.startswith(object_hrn + "."): + return + #if name.startswith(get_authority(name)): + #return + + raise PermissionError(name) + + def determine_user_rights(self, caller_hrn, reg_record): + """ + Given a user credential and a record, determine what set of rights the + user should have to that record. + + This is intended to replace determine_user_rights() and + verify_cancreate_credential() + """ + + rl = Rights() + type = reg_record.type + + + if type == 'slice': + # researchers in the slice are in the DB as-is + researcher_hrns = [ user.hrn for user in reg_record.reg_researchers ] + # locating PIs attached to that slice + slice_pis=reg_record.get_pis() + pi_hrns = [ user.hrn for user in slice_pis ] + if (caller_hrn in researcher_hrns + pi_hrns): + rl.add('refresh') + rl.add('embed') + rl.add('bind') + rl.add('control') + rl.add('info') + + elif type == 'authority': + pi_hrns = [ user.hrn for user in reg_record.reg_pis ] + if (caller_hrn == self.config.SFA_INTERFACE_HRN): + rl.add('authority') + rl.add('sa') + rl.add('ma') + if (caller_hrn in pi_hrns): + rl.add('authority') + rl.add('sa') + # NOTE: for the PL implementation, this 'operators' list + # amounted to users with 'tech' role in that site + # it seems like this is not needed any longer, so for now I just drop that + # operator_hrns = reg_record.get('operator',[]) + # if (caller_hrn in operator_hrns): + # rl.add('authority') + # rl.add('ma') + + elif type == 'user': + rl.add('refresh') + rl.add('resolve') + rl.add('info') + + elif type == 'node': + rl.add('operator') + + return rl + + def get_authority(self, hrn): + return get_authority(hrn) + + def filter_creds_by_caller(self, creds, caller_hrn_list): + """ + Returns a list of creds who's gid caller matches the + specified caller hrn + """ + if not isinstance(creds, list): + creds = [creds] + creds = [] + if not isinstance(caller_hrn_list, list): + caller_hrn_list = [caller_hrn_list] + for cred in creds: + try: + tmp_cred = Credential(string=cred) + if tmp_cred.get_gid_caller().get_hrn() in [caller_hrn_list]: + creds.append(cred) + except: pass + return creds + diff --git a/core/lib/am/credentials/src/trust/certificate.py b/core/lib/am/credentials/src/trust/certificate.py new file mode 100644 index 00000000..23f9fc56 --- /dev/null +++ b/core/lib/am/credentials/src/trust/certificate.py @@ -0,0 +1,782 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- + +## +# SFA uses two crypto libraries: pyOpenSSL and M2Crypto to implement +# the necessary crypto functionality. Ideally just one of these libraries +# would be used, but unfortunately each of these libraries is independently +# lacking. The pyOpenSSL library is missing many necessary functions, and +# the M2Crypto library has crashed inside of some of the functions. The +# design decision is to use pyOpenSSL whenever possible as it seems more +# stable, and only use M2Crypto for those functions that are not possible +# in pyOpenSSL. +# +# This module exports two classes: Keypair and Certificate. +## +# + +import functools +import os +import tempfile +import base64 +from tempfile import mkstemp + +from OpenSSL import crypto +import M2Crypto +from M2Crypto import X509 + +from geniutils.src.faults.faults import CertExpired +from geniutils.src.faults.faults import CertMissingParent +from geniutils.src.faults.faults import CertNotSignedByParent + + +glo_passphrase_callback = None + +## +# A global callback may be implemented for requesting passphrases from the +# user. The function will be called with three arguments: +# +# keypair_obj: the keypair object that is calling the passphrase +# string: the string containing the private key that's being loaded +# x: unknown, appears to be 0, comes from pyOpenSSL and/or m2crypto +# +# The callback should return a string containing the passphrase. + +def set_passphrase_callback(callback_func): + global glo_passphrase_callback + + glo_passphrase_callback = callback_func + +## +# Sets a fixed passphrase. + +def set_passphrase(passphrase): + set_passphrase_callback( lambda k,s,x: passphrase ) + +## +# Check to see if a passphrase works for a particular private key string. +# Intended to be used by passphrase callbacks for input validation. + +def test_passphrase(string, passphrase): + try: + crypto.load_privatekey(crypto.FILETYPE_PEM, string, (lambda x: passphrase)) + return True + except: + return False + +def convert_public_key(key): + keyconvert_path = "/usr/bin/keyconvert.py" + if not os.path.isfile(keyconvert_path): + raise IOError, "Could not find keyconvert in %s" % keyconvert_path + + # we can only convert rsa keys + if "ssh-dss" in key: + raise Exception, "keyconvert: dss keys are not supported" + + (ssh_f, ssh_fn) = tempfile.mkstemp() + ssl_fn = tempfile.mktemp() + os.write(ssh_f, key) + os.close(ssh_f) + + cmd = keyconvert_path + " " + ssh_fn + " " + ssl_fn + os.system(cmd) + + # this check leaves the temporary file containing the public key so + # that it can be expected to see why it failed. + # TODO: for production, cleanup the temporary files + if not os.path.exists(ssl_fn): + raise Exception, "keyconvert: generated certificate not found. keyconvert may have failed." + + k = Keypair() + try: + k.load_pubkey_from_file(ssl_fn) + return k + except Exception as e: + raise e + finally: + # remove the temporary files + if os.path.exists(ssh_fn): + os.remove(ssh_fn) + if os.path.exists(ssl_fn): + os.remove(ssl_fn) + +## +# Public-private key pairs are implemented by the Keypair class. +# A Keypair object may represent both a public and private key pair, or it +# may represent only a public key (this usage is consistent with OpenSSL). + +class Keypair: + key = None # public/private keypair + m2key = None # public key (m2crypto format) + + ## + # Creates a Keypair object + # @param create If create==True, creates a new public/private key and + # stores it in the object + # @param string If string!=None, load the keypair from the string (PEM) + # @param filename If filename!=None, load the keypair from the file + + def __init__(self, create=False, string=None, filename=None): + if create: + self.create() + if string: + self.load_from_string(string) + if filename: + self.load_from_file(filename) + + ## + # Create a RSA public/private key pair and store it inside the keypair object + + def create(self): + self.key = crypto.PKey() + self.key.generate_key(crypto.TYPE_RSA, 1024) + + ## + # Save the private key to a file + # @param filename name of file to store the keypair in + + def save_to_file(self, filename): + open(filename, 'w').write(self.as_pem()) + self.filename=filename + + ## + # Load the private key from a file. Implicity the private key includes the public key. + + def load_from_file(self, filename): + self.filename=filename + buffer = open(filename, 'r').read() + self.load_from_string(buffer) + + ## + # Load the private key from a string. Implicitly the private key includes the public key. + + def load_from_string(self, string): + if glo_passphrase_callback: + self.key = crypto.load_privatekey(crypto.FILETYPE_PEM, string, functools.partial(glo_passphrase_callback, self, string) ) + self.m2key = M2Crypto.EVP.load_key_string(string, functools.partial(glo_passphrase_callback, self, string) ) + else: + self.key = crypto.load_privatekey(crypto.FILETYPE_PEM, string) + self.m2key = M2Crypto.EVP.load_key_string(string) + + ## + # Load the public key from a string. No private key is loaded. + + def load_pubkey_from_file(self, filename): + # load the m2 public key + m2rsakey = M2Crypto.RSA.load_pub_key(filename) + self.m2key = M2Crypto.EVP.PKey() + self.m2key.assign_rsa(m2rsakey) + + # create an m2 x509 cert + m2name = M2Crypto.X509.X509_Name() + m2name.add_entry_by_txt(field="CN", type=0x1001, entry="junk", len=-1, loc=-1, set=0) + m2x509 = M2Crypto.X509.X509() + m2x509.set_pubkey(self.m2key) + m2x509.set_serial_number(0) + m2x509.set_issuer_name(m2name) + m2x509.set_subject_name(m2name) + ASN1 = M2Crypto.ASN1.ASN1_UTCTIME() + ASN1.set_time(500) + m2x509.set_not_before(ASN1) + m2x509.set_not_after(ASN1) + # x509v3 so it can have extensions + # prob not necc since this cert itself is junk but still... + m2x509.set_version(2) + junk_key = Keypair(create=True) + m2x509.sign(pkey=junk_key.get_m2_pkey(), md="sha1") + + # convert the m2 x509 cert to a pyopenssl x509 + m2pem = m2x509.as_pem() + pyx509 = crypto.load_certificate(crypto.FILETYPE_PEM, m2pem) + + # get the pyopenssl pkey from the pyopenssl x509 + self.key = pyx509.get_pubkey() + self.filename=filename + + ## + # Load the public key from a string. No private key is loaded. + + def load_pubkey_from_string(self, string): + (f, fn) = tempfile.mkstemp() + os.write(f, string) + os.close(f) + self.load_pubkey_from_file(fn) + os.remove(fn) + + ## + # Return the private key in PEM format. + + def as_pem(self): + return crypto.dump_privatekey(crypto.FILETYPE_PEM, self.key) + + ## + # Return an M2Crypto key object + + def get_m2_pkey(self): + if not self.m2key: + self.m2key = M2Crypto.EVP.load_key_string(self.as_pem()) + return self.m2key + + ## + # Returns a string containing the public key represented by this object. + + def get_pubkey_string(self): + m2pkey = self.get_m2_pkey() + return base64.b64encode(m2pkey.as_der()) + + ## + # Return an OpenSSL pkey object + + def get_openssl_pkey(self): + return self.key + + ## + # Given another Keypair object, return TRUE if the two keys are the same. + + def is_same(self, pkey): + return self.as_pem() == pkey.as_pem() + + def sign_string(self, data): + k = self.get_m2_pkey() + k.sign_init() + k.sign_update(data) + return base64.b64encode(k.sign_final()) + + def verify_string(self, data, sig): + k = self.get_m2_pkey() + k.verify_init() + k.verify_update(data) + return M2Crypto.m2.verify_final(k.ctx, base64.b64decode(sig), k.pkey) + + def compute_hash(self, value): + return self.sign_string(str(value)) + + # only informative + def get_filename(self): + return getattr(self,'filename',None) + + def dump (self, *args, **kwargs): + print self.dump_string(*args, **kwargs) + + def dump_string (self): + result="" + result += "KEYPAIR: pubkey=%40s..."%self.get_pubkey_string() + filename=self.get_filename() + if filename: result += "Filename %s\n"%filename + return result + +## +# The certificate class implements a general purpose X509 certificate, making +# use of the appropriate pyOpenSSL or M2Crypto abstractions. It also adds +# several addition features, such as the ability to maintain a chain of +# parent certificates, and storage of application-specific data. +# +# Certificates include the ability to maintain a chain of parents. Each +# certificate includes a pointer to it's parent certificate. When loaded +# from a file or a string, the parent chain will be automatically loaded. +# When saving a certificate to a file or a string, the caller can choose +# whether to save the parent certificates as well. + +class Certificate: + digest = "md5" + + cert = None + issuerKey = None + issuerSubject = None + parent = None + isCA = None # will be a boolean once set + + separator="-----parent-----" + + ## + # Create a certificate object. + # + # @param lifeDays life of cert in days - default is 1825==5 years + # @param create If create==True, then also create a blank X509 certificate. + # @param subject If subject!=None, then create a blank certificate and set + # it's subject name. + # @param string If string!=None, load the certficate from the string. + # @param filename If filename!=None, load the certficiate from the file. + # @param isCA If !=None, set whether this cert is for a CA + + def __init__(self, lifeDays=1825, create=False, subject=None, string=None, filename=None, isCA=None): + self.data = {} + if create or subject: + self.create(lifeDays) + if subject: + self.set_subject(subject) + if string: + self.load_from_string(string) + if filename: + self.load_from_file(filename) + + # Set the CA bit if a value was supplied + if isCA != None: + self.set_is_ca(isCA) + + # Create a blank X509 certificate and store it in this object. + + def create(self, lifeDays=1825): + self.cert = crypto.X509() + # FIXME: Use different serial #s + self.cert.set_serial_number(3) + self.cert.gmtime_adj_notBefore(0) # 0 means now + self.cert.gmtime_adj_notAfter(lifeDays*60*60*24) # five years is default + self.cert.set_version(2) # x509v3 so it can have extensions + + + ## + # Given a pyOpenSSL X509 object, store that object inside of this + # certificate object. + + def load_from_pyopenssl_x509(self, x509): + self.cert = x509 + + ## + # Load the certificate from a string + + def load_from_string(self, string): + # if it is a chain of multiple certs, then split off the first one and + # load it (support for the ---parent--- tag as well as normal chained certs) + + string = string.strip() + + # If it's not in proper PEM format, wrap it + if string.count('-----BEGIN CERTIFICATE') == 0: + string = '-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----' % string + + # If there is a PEM cert in there, but there is some other text first + # such as the text of the certificate, skip the text + beg = string.find('-----BEGIN CERTIFICATE') + if beg > 0: + # skipping over non cert beginning + string = string[beg:] + + parts = [] + + if string.count('-----BEGIN CERTIFICATE-----') > 1 and \ + string.count(Certificate.separator) == 0: + parts = string.split('-----END CERTIFICATE-----',1) + parts[0] += '-----END CERTIFICATE-----' + else: + parts = string.split(Certificate.separator, 1) + + #print "Parts----", parts + self.cert = crypto.load_certificate(crypto.FILETYPE_PEM, parts[0]) + + # if there are more certs, then create a parent and let the parent load + # itself from the remainder of the string + if len(parts) > 1 and parts[1] != '': + self.parent = self.__class__() + self.parent.load_from_string(parts[1]) + + ## + # Load the certificate from a file + + def load_from_file(self, filename): + file = open(filename) + string = file.read() + self.load_from_string(string) + self.filename=filename + + ## + # Save the certificate to a string. + # + # @param save_parents If save_parents==True, then also save the parent certificates. + + def save_to_string(self, save_parents=True): + string = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cert) + if save_parents and self.parent: + string = string + self.parent.save_to_string(save_parents) + return string + + ## + # Save the certificate to a file. + # @param save_parents If save_parents==True, then also save the parent certificates. + + def save_to_file(self, filename, save_parents=True, filep=None): + string = self.save_to_string(save_parents=save_parents) + if filep: + f = filep + else: + f = open(filename, 'w') + f.write(string) + f.close() + self.filename=filename + + ## + # Save the certificate to a random file in /tmp/ + # @param save_parents If save_parents==True, then also save the parent certificates. + def save_to_random_tmp_file(self, save_parents=True): + fp, filename = mkstemp(suffix='cert', text=True) + fp = os.fdopen(fp, "w") + self.save_to_file(filename, save_parents=True, filep=fp) + return filename + + ## + # Sets the issuer private key and name + # @param key Keypair object containing the private key of the issuer + # @param subject String containing the name of the issuer + # @param cert (optional) Certificate object containing the name of the issuer + + def set_issuer(self, key, subject=None, cert=None): + self.issuerKey = key + if subject: + # it's a mistake to use subject and cert params at the same time + assert(not cert) + if isinstance(subject, dict) or isinstance(subject, str): + req = crypto.X509Req() + reqSubject = req.get_subject() + if (isinstance(subject, dict)): + for key in subject.keys(): + setattr(reqSubject, key, subject[key]) + else: + setattr(reqSubject, "CN", subject) + subject = reqSubject + # subject is not valid once req is out of scope, so save req + self.issuerReq = req + if cert: + # if a cert was supplied, then get the subject from the cert + subject = cert.cert.get_subject() + assert(subject) + self.issuerSubject = subject + + ## + # Get the issuer name + + def get_issuer(self, which="CN"): + x = self.cert.get_issuer() + return getattr(x, which) + + ## + # Set the subject name of the certificate + + def set_subject(self, name): + req = crypto.X509Req() + subj = req.get_subject() + if (isinstance(name, dict)): + for key in name.keys(): + setattr(subj, key, name[key]) + else: + setattr(subj, "CN", name) + self.cert.set_subject(subj) + + ## + # Get the subject name of the certificate + + def get_subject(self, which="CN"): + x = self.cert.get_subject() + return getattr(x, which) + + def get_extended_subject(self): + x = self.cert.get_subject() + subject = dict() + return dict(x.get_components()) + + ## + # Get a pretty-print subject name of the certificate + + def get_printable_subject(self): + x = self.cert.get_subject() + return "[ OU: %s, CN: %s, SubjectAltName: %s ]" % (getattr(x, "OU"), getattr(x, "CN"), self.get_data()) + + ## + # Get the public key of the certificate. + # + # @param key Keypair object containing the public key + + def set_pubkey(self, key): + assert(isinstance(key, Keypair)) + self.cert.set_pubkey(key.get_openssl_pkey()) + + ## + # Get the public key of the certificate. + # It is returned in the form of a Keypair object. + + def get_pubkey(self): + m2x509 = X509.load_cert_string(self.save_to_string()) + pkey = Keypair() + pkey.key = self.cert.get_pubkey() + pkey.m2key = m2x509.get_pubkey() + return pkey + + def set_intermediate_ca(self, val): + return self.set_is_ca(val) + + # Set whether this cert is for a CA. All signers and only signers should be CAs. + # The local member starts unset, letting us check that you only set it once + # @param val Boolean indicating whether this cert is for a CA + def set_is_ca(self, val): + if val is None: + return + + if self.isCA != None: + # Can't double set properties + raise Exception, "Cannot set basicConstraints CA:?? more than once. Was %s, trying to set as %s" % (self.isCA, val) + + self.isCA = val + if val: + self.add_extension('basicConstraints', 1, 'CA:TRUE') + else: + self.add_extension('basicConstraints', 1, 'CA:FALSE') + + + + ## + # Add an X509 extension to the certificate. Add_extension can only be called + # once for a particular extension name, due to limitations in the underlying + # library. + # + # @param name string containing name of extension + # @param value string containing value of the extension + + def add_extension(self, name, critical, value): + oldExtVal = None + try: + oldExtVal = self.get_extension(name) + except: + # M2Crypto LookupError when the extension isn't there (yet) + pass + + # This code limits you from adding the extension with the same value + # The method comment says you shouldn't do this with the same name + # But actually it (m2crypto) appears to allow you to do this. + if oldExtVal and oldExtVal == value: + # don't add this extension again + # just do nothing as here + return + # FIXME: What if they are trying to set with a different value? + # Is this ever OK? Or should we raise an exception? +# elif oldExtVal: +# raise "Cannot add extension %s which had val %s with new val %s" % (name, oldExtVal, value) + + ext = crypto.X509Extension (name, critical, value) + self.cert.add_extensions([ext]) + + ## + # Get an X509 extension from the certificate + + def get_extension(self, name): + + # pyOpenSSL does not have a way to get extensions + m2x509 = X509.load_cert_string(self.save_to_string()) + value = m2x509.get_ext(name).get_value() + + return value + + ## + # Set_data is a wrapper around add_extension. It stores the parameter str in + # the X509 subject_alt_name extension. Set_data can only be called once, due + # to limitations in the underlying library. + + def set_data(self, str, field='subjectAltName'): + # pyOpenSSL only allows us to add extensions, so if we try to set the + # same extension more than once, it will not work + if self.data.has_key(field): + raise "Cannot set ", field, " more than once" + self.data[field] = str + self.add_extension(field, 0, str) + + ## + # Return the data string that was previously set with set_data + + def get_data(self, field='subjectAltName'): + if self.data.has_key(field): + return self.data[field] + + try: + uri = self.get_extension(field) + self.data[field] = uri + except LookupError: + return None + + return self.data[field] + + ## + # Sign the certificate using the issuer private key and issuer subject previous set with set_issuer(). + + def sign(self): + assert self.cert != None + assert self.issuerSubject != None + assert self.issuerKey != None + self.cert.set_issuer(self.issuerSubject) + self.cert.sign(self.issuerKey.get_openssl_pkey(), self.digest) + + ## + # Verify the authenticity of a certificate. + # @param pkey is a Keypair object representing a public key. If Pkey + # did not sign the certificate, then an exception will be thrown. + + def verify(self, pkey): + # pyOpenSSL does not have a way to verify signatures + m2x509 = X509.load_cert_string(self.save_to_string()) + m2pkey = pkey.get_m2_pkey() + # verify it + return m2x509.verify(m2pkey) + + # XXX alternatively, if openssl has been patched, do the much simpler: + # try: + # self.cert.verify(pkey.get_openssl_key()) + # return 1 + # except: + # return 0 + + ## + # Return True if pkey is identical to the public key that is contained in the certificate. + # @param pkey Keypair object + + def is_pubkey(self, pkey): + return self.get_pubkey().is_same(pkey) + + ## + # Given a certificate cert, verify that this certificate was signed by the + # public key contained in cert. Throw an exception otherwise. + # + # @param cert certificate object + + def is_signed_by_cert(self, cert): + k = cert.get_pubkey() + result = self.verify(k) + return result + + ## + # Set the parent certficiate. + # + # @param p certificate object. + + def set_parent(self, p): + self.parent = p + + ## + # Return the certificate object of the parent of this certificate. + + def get_parent(self): + return self.parent + + ## + # Verification examines a chain of certificates to ensure that each parent + # signs the child, and that some certificate in the chain is signed by a + # trusted certificate. + # + # Verification is a basic recursion:
+    #     if this_certificate was signed by trusted_certs:
+    #         return
+    #     else
+    #         return verify_chain(parent, trusted_certs)
+    # 
+ # + # At each recursion, the parent is tested to ensure that it did sign the + # child. If a parent did not sign a child, then an exception is thrown. If + # the bottom of the recursion is reached and the certificate does not match + # a trusted root, then an exception is thrown. + # Also require that parents are CAs. + # + # @param Trusted_certs is a list of certificates that are trusted. + # + + def verify_chain(self, trusted_certs = None): + # Verify a chain of certificates. Each certificate must be signed by + # the public key contained in it's parent. The chain is recursed + # until a certificate is found that is signed by a trusted root. + + # verify expiration time + if self.cert.has_expired(): + raise CertExpired(self.get_printable_subject(), "client cert") + + # if this cert is signed by a trusted_cert, then we are set + for trusted_cert in trusted_certs: + if self.is_signed_by_cert(trusted_cert): + # verify expiration of trusted_cert ? + if not trusted_cert.cert.has_expired(): + return trusted_cert + else: + raise CertExpired(self.get_printable_subject()," signer trusted_cert %s"%trusted_cert.get_printable_subject()) + + # if there is no parent, then no way to verify the chain + if not self.parent: + raise CertMissingParent(self.get_printable_subject() + ": Issuer %s is not one of the %d trusted roots, and cert has no parent." % (self.get_issuer(), len(trusted_certs))) + + # if it wasn't signed by the parent... + if not self.is_signed_by_cert(self.parent): + raise CertNotSignedByParent("%s: Parent %s, issuer %s"\ + % (self.get_printable_subject(), + self.parent.get_printable_subject(), + self.get_issuer())) + + # Confirm that the parent is a CA. Only CAs can be trusted as + # signers. + # Note that trusted roots are not parents, so don't need to be + # CAs. + # Ugly - cert objects aren't parsed so we need to read the + # extension and hope there are no other basicConstraints + if not self.parent.isCA and not (self.parent.get_extension('basicConstraints') == 'CA:TRUE'): + raise CertNotSignedByParent("%s: Parent %s not a CA" % (self.get_printable_subject(), + self.parent.get_printable_subject())) + + # if the parent isn't verified... + self.parent.verify_chain(trusted_certs) + + return + + ### more introspection + def get_extensions(self): + # pyOpenSSL does not have a way to get extensions + triples=[] + m2x509 = X509.load_cert_string(self.save_to_string()) + nb_extensions=m2x509.get_ext_count() + for i in range(nb_extensions): + ext=m2x509.get_ext_at(i) + triples.append( (ext.get_name(), ext.get_value(), ext.get_critical(),) ) + return triples + + def get_data_names(self): + return self.data.keys() + + def get_all_datas (self): + triples=self.get_extensions() + for name in self.get_data_names(): + triples.append( (name,self.get_data(name),'data',) ) + return triples + + # only informative + def get_filename(self): + return getattr(self,'filename',None) + + def dump (self, *args, **kwargs): + print self.dump_string(*args, **kwargs) + + def dump_string (self,show_extensions=False): + result = "" + result += "CERTIFICATE for %s\n"%self.get_printable_subject() + result += "Issued by %s\n"%self.get_issuer() + filename=self.get_filename() + if filename: result += "Filename %s\n"%filename + if show_extensions: + all_datas=self.get_all_datas() + result += " has %d extensions/data attached"%len(all_datas) + for (n,v,c) in all_datas: + if c=='data': + result += " data: %s=%s\n"%(n,v) + else: + result += " ext: %s (crit=%s)=<<<%s>>>\n"%(n,c,v) + return result diff --git a/core/lib/am/credentials/src/trust/credential.py b/core/lib/am/credentials/src/trust/credential.py new file mode 100644 index 00000000..96da28ae --- /dev/null +++ b/core/lib/am/credentials/src/trust/credential.py @@ -0,0 +1,1138 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- +## +# Implements SFA Credentials +# +# Credentials are signed XML files that assign a subject gid privileges to an object gid +## + +import os +from types import StringTypes +import datetime +from StringIO import StringIO +from tempfile import mkstemp +from xml.dom.minidom import Document, parseString + +HAVELXML = False +try: + from lxml import etree + HAVELXML = True +except: + pass +HAVELXML = False + +from xml.parsers.expat import ExpatError + +from geniutils.src.faults.faults import CredentialNotVerifiable +from geniutils.src.faults.faults import ChildRightsNotSubsetOfParent +from geniutils.src.time.timewrapper import utcparse +from credentials.src.trust.credential_legacy import CredentialLegacy +from credentials.src.trust.rights import Right, Rights, determine_rights +from credentials.src.trust.gid import GID +from geniutils.src.xrn.xrn import urn_to_hrn +from geniutils.src.xrn.xrn import hrn_authfor_hrn + +# 2 weeks, in seconds +DEFAULT_CREDENTIAL_LIFETIME = 86400 * 31 + +signature_template = \ +''' + + + + + + + + + + + + + + + + + + + + + + +''' + +# PG formats the template (whitespace) slightly differently. +# Note that they don't include the xmlns in the template, but add it later. +# Otherwise the two are equivalent. +#signature_template_as_in_pg = \ +#''' +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +#''' + +## +# Convert a string into a bool +# used to convert an xsd:boolean to a Python boolean +def str2bool(str): + if str.lower() in ['true','1']: + return True + return False + + +## +# Utility function to get the text of an XML element + +def getTextNode(element, subele): + sub = element.getElementsByTagName(subele)[0] + if len(sub.childNodes) > 0: + return sub.childNodes[0].nodeValue + else: + return None + +## +# Utility function to set the text of an XML element +# It creates the element, adds the text to it, +# and then appends it to the parent. + +def append_sub(doc, parent, element, text): + ele = doc.createElement(element) + ele.appendChild(doc.createTextNode(text)) + parent.appendChild(ele) + +## +# Signature contains information about an xmlsec1 signature +# for a signed-credential +# + +class Signature(object): + + def __init__(self, string=None): + self.refid = None + self.issuer_gid = None + self.xml = None + if string: + self.xml = string + self.decode() + + + def get_refid(self): + if not self.refid: + self.decode() + return self.refid + + def get_xml(self): + if not self.xml: + self.encode() + return self.xml + + def set_refid(self, id): + self.refid = id + + def get_issuer_gid(self): + if not self.gid: + self.decode() + return self.gid + + def set_issuer_gid(self, gid): + self.gid = gid + + def decode(self): + try: + doc = parseString(self.xml) + except ExpatError,e: + raise + sig = doc.getElementsByTagName("Signature")[0] + ref_id = sig.getAttribute("xml:id").strip().strip("Sig_") + # The xml:id tag is optional, and could be in a + # Reference xml:id or Reference UID sub element instead + if not ref_id or ref_id == '': + reference = sig.getElementsByTagName('Reference')[0] + ref_id = reference.getAttribute('xml:id').strip().strip('Sig_') + if not ref_id or ref_id == '': + ref_id = reference.getAttribute('URI').strip().strip('#') + self.set_refid(ref_id) + keyinfos = sig.getElementsByTagName("X509Data") + gids = None + for keyinfo in keyinfos: + certs = keyinfo.getElementsByTagName("X509Certificate") + for cert in certs: + if len(cert.childNodes) > 0: + szgid = cert.childNodes[0].nodeValue + szgid = szgid.strip() + szgid = "-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----" % szgid + if gids is None: + gids = szgid + else: + gids += "\n" + szgid + if gids is None: + raise CredentialNotVerifiable("Malformed XML: No certificate found in signature") + self.set_issuer_gid(GID(string=gids)) + + def encode(self): + self.xml = signature_template % (self.get_refid(), self.get_refid()) + + +## +# A credential provides a caller gid with privileges to an object gid. +# A signed credential is signed by the object's authority. +# +# Credentials are encoded in one of two ways. The legacy style places +# it in the subjectAltName of an X509 certificate. The new credentials +# are placed in signed XML. +# +# WARNING: +# In general, a signed credential obtained externally should +# not be changed else the signature is no longer valid. So, once +# you have loaded an existing signed credential, do not call encode() or sign() on it. + +def filter_creds_by_caller(creds, caller_hrn_list): + """ + Returns a list of creds who's gid caller matches the + specified caller hrn + """ + if not isinstance(creds, list): creds = [creds] + if not isinstance(caller_hrn_list, list): + caller_hrn_list = [caller_hrn_list] + caller_creds = [] + for cred in creds: + try: + tmp_cred = Credential(string=cred) + if tmp_cred.get_cred_type() != Credential.SFA_CREDENTIAL_TYPE: + continue + if tmp_cred.get_gid_caller().get_hrn() in caller_hrn_list: + caller_creds.append(cred) + except: pass + return caller_creds + +class Credential(object): + + SFA_CREDENTIAL_TYPE = "geni_sfa" + + ## + # Create a Credential object + # + # @param create If true, create a blank x509 certificate + # @param subject If subject!=None, create an x509 cert with the subject name + # @param string If string!=None, load the credential from the string + # @param filename If filename!=None, load the credential from the file + # FIXME: create and subject are ignored! + def __init__(self, create=False, subject=None, string=None, filename=None): + self.gidCaller = None + self.gidObject = None + self.expiration = None + self.privileges = None + self.issuer_privkey = None + self.issuer_gid = None + self.issuer_pubkey = None + self.parent = None + self.signature = None + self.xml = None + self.refid = None + self.legacy = None + self.cred_type = Credential.SFA_CREDENTIAL_TYPE + + # Check if this is a legacy credential, translate it if so + if string or filename: + if string: + str = string + elif filename: + str = file(filename).read() + + if str.strip().startswith("-----"): + self.legacy = CredentialLegacy(False,string=str) + self.translate_legacy(str) + else: + self.xml = str + self.decode() + + # Find an xmlsec1 path + self.xmlsec_path = '' + paths = ['/usr/bin','/usr/local/bin','/bin','/opt/bin','/opt/local/bin'] + for path in paths: + if os.path.isfile(path + '/' + 'xmlsec1'): + self.xmlsec_path = path + '/' + 'xmlsec1' + break + if not self.xmlsec_path: + pass + + def get_cred_type(self): + return self.cred_type + + def get_subject(self): + if not self.gidObject: + self.decode() + return self.gidObject.get_subject() + + # sounds like this should be __repr__ instead ?? + def get_summary_tostring(self): + if not self.gidObject: + self.decode() + obj = self.gidObject.get_printable_subject() + caller = self.gidCaller.get_printable_subject() + exp = self.get_expiration() + # Summarize the rights too? The issuer? + return "[ Grant %s rights on %s until %s ]" % (caller, obj, exp) + + def get_signature(self): + if not self.signature: + self.decode() + return self.signature + + def set_signature(self, sig): + self.signature = sig + + + ## + # Translate a legacy credential into a new one + # + # @param String of the legacy credential + + def translate_legacy(self, str): + legacy = CredentialLegacy(False,string=str) + self.gidCaller = legacy.get_gid_caller() + self.gidObject = legacy.get_gid_object() + lifetime = legacy.get_lifetime() + if not lifetime: + self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) + else: + self.set_expiration(int(lifetime)) + self.lifeTime = legacy.get_lifetime() + self.set_privileges(legacy.get_privileges()) + self.get_privileges().delegate_all_privileges(legacy.get_delegate()) + + ## + # Need the issuer's private key and name + # @param key Keypair object containing the private key of the issuer + # @param gid GID of the issuing authority + + def set_issuer_keys(self, privkey, gid): + self.issuer_privkey = privkey + self.issuer_gid = gid + + + ## + # Set this credential's parent + def set_parent(self, cred): + self.parent = cred + self.updateRefID() + + ## + # set the GID of the caller + # + # @param gid GID object of the caller + + def set_gid_caller(self, gid): + self.gidCaller = gid + # gid origin caller is the caller's gid by default + self.gidOriginCaller = gid + + ## + # get the GID of the object + + def get_gid_caller(self): + if not self.gidCaller: + self.decode() + return self.gidCaller + + ## + # set the GID of the object + # + # @param gid GID object of the object + + def set_gid_object(self, gid): + self.gidObject = gid + + ## + # get the GID of the object + + def get_gid_object(self): + if not self.gidObject: + self.decode() + return self.gidObject + + ## + # Expiration: an absolute UTC time of expiration (as either an int or string or datetime) + # + def set_expiration(self, expiration): + if isinstance(expiration, (int, float)): + self.expiration = datetime.datetime.fromtimestamp(expiration) + elif isinstance (expiration, datetime.datetime): + self.expiration = expiration + elif isinstance (expiration, StringTypes): + self.expiration = utcparse (expiration) + else: + pass + + + ## + # get the lifetime of the credential (always in datetime format) + + def get_expiration(self): + if not self.expiration: + self.decode() + # at this point self.expiration is normalized as a datetime - DON'T call utcparse again + return self.expiration + + ## + # For legacy sake + def get_lifetime(self): + return self.get_expiration() + + ## + # set the privileges + # + # @param privs either a comma-separated list of privileges of a Rights object + + def set_privileges(self, privs): + if isinstance(privs, str): + self.privileges = Rights(string = privs) + else: + self.privileges = privs + + ## + # return the privileges as a Rights object + + def get_privileges(self): + if not self.privileges: + self.decode() + return self.privileges + + ## + # determine whether the credential allows a particular operation to be + # performed + # + # @param op_name string specifying name of operation ("lookup", "update", etc) + + def can_perform(self, op_name): + rights = self.get_privileges() + + if not rights: + return False + + return rights.can_perform(op_name) + + + ## + # Encode the attributes of the credential into an XML string + # This should be done immediately before signing the credential. + # WARNING: + # In general, a signed credential obtained externally should + # not be changed else the signature is no longer valid. So, once + # you have loaded an existing signed credential, do not call encode() or sign() on it. + + def encode(self): + # Create the XML document + doc = Document() + signed_cred = doc.createElement("signed-credential") + +# Declare namespaces +# Note that credential/policy.xsd are really the PG schemas +# in a PL namespace. +# Note that delegation of credentials between the 2 only really works +# cause those schemas are identical. +# Also note these PG schemas talk about PG tickets and CM policies. + signed_cred.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") + # FIXME: See v2 schema at www.geni.net/resources/credential/2/credential.xsd + signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.planet-lab.org/resources/sfa/credential.xsd") + signed_cred.setAttribute("xsi:schemaLocation", "http://www.planet-lab.org/resources/sfa/ext/policy/1 http://www.planet-lab.org/resources/sfa/ext/policy/1/policy.xsd") + +# PG says for those last 2: +# signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.protogeni.net/resources/credential/credential.xsd") +# signed_cred.setAttribute("xsi:schemaLocation", "http://www.protogeni.net/resources/credential/ext/policy/1 http://www.protogeni.net/resources/credential/ext/policy/1/policy.xsd") + + doc.appendChild(signed_cred) + + # Fill in the bit + cred = doc.createElement("credential") + cred.setAttribute("xml:id", self.get_refid()) + signed_cred.appendChild(cred) + append_sub(doc, cred, "type", "privilege") + append_sub(doc, cred, "serial", "8") + append_sub(doc, cred, "owner_gid", self.gidCaller.save_to_string()) + append_sub(doc, cred, "owner_urn", self.gidCaller.get_urn()) + append_sub(doc, cred, "target_gid", self.gidObject.save_to_string()) + append_sub(doc, cred, "target_urn", self.gidObject.get_urn()) + append_sub(doc, cred, "uuid", "") + if not self.expiration: + self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) + self.expiration = self.expiration.replace(microsecond=0) + if self.expiration.tzinfo is not None and self.expiration.tzinfo.utcoffset(self.expiration) is not None: + # TZ aware. Make sure it is UTC + self.expiration = self.expiration.astimezone(tz.tzutc()) + append_sub(doc, cred, "expires", self.expiration.strftime('%Y-%m-%dT%H:%M:%SZ')) # RFC3339 + privileges = doc.createElement("privileges") + cred.appendChild(privileges) + + if self.privileges: + rights = self.get_privileges() + for right in rights.rights: + priv = doc.createElement("privilege") + append_sub(doc, priv, "name", right.kind) + append_sub(doc, priv, "can_delegate", str(right.delegate).lower()) + privileges.appendChild(priv) + + # Add the parent credential if it exists + if self.parent: + sdoc = parseString(self.parent.get_xml()) + # If the root node is a signed-credential (it should be), then + # get all its attributes and attach those to our signed_cred + # node. + # Specifically, PG and PLadd attributes for namespaces (which is reasonable), + # and we need to include those again here or else their signature + # no longer matches on the credential. + # We expect three of these, but here we copy them all: +# signed_cred.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") +# and from PG (PL is equivalent, as shown above): +# signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.protogeni.net/resources/credential/credential.xsd") +# signed_cred.setAttribute("xsi:schemaLocation", "http://www.protogeni.net/resources/credential/ext/policy/1 http://www.protogeni.net/resources/credential/ext/policy/1/policy.xsd") + + # HOWEVER! + # PL now also declares these, with different URLs, so + # the code notices those attributes already existed with + # different values, and complains. + # This happens regularly on delegation now that PG and + # PL both declare the namespace with different URLs. + # If the content ever differs this is a problem, + # but for now it works - different URLs (values in the attributes) + # but the same actual schema, so using the PG schema + # on delegated-to-PL credentials works fine. + + # Note: you could also not copy attributes + # which already exist. It appears that both PG and PL + # will actually validate a slicecred with a parent + # signed using PG namespaces and a child signed with PL + # namespaces over the whole thing. But I don't know + # if that is a bug in xmlsec1, an accident since + # the contents of the schemas are the same, + # or something else, but it seems odd. And this works. + parentRoot = sdoc.documentElement + if parentRoot.tagName == "signed-credential" and parentRoot.hasAttributes(): + for attrIx in range(0, parentRoot.attributes.length): + attr = parentRoot.attributes.item(attrIx) + # returns the old attribute of same name that was + # on the credential + # Below throws InUse exception if we forgot to clone the attribute first + oldAttr = signed_cred.setAttributeNode(attr.cloneNode(True)) + if oldAttr and oldAttr.value != attr.value: + msg = "Delegating cred from owner %s to %s over %s:\n - Replaced attribute %s value '%s' with '%s'" % (self.parent.gidCaller.get_urn(), self.gidCaller.get_urn(), self.gidObject.get_urn(), oldAttr.name, oldAttr.value, attr.value) + #raise CredentialNotVerifiable("Can't encode new valid delegated credential: %s" % msg) + + p_cred = doc.importNode(sdoc.getElementsByTagName("credential")[0], True) + p = doc.createElement("parent") + p.appendChild(p_cred) + cred.appendChild(p) + # done handling parent credential + + # Create the tag + signatures = doc.createElement("signatures") + signed_cred.appendChild(signatures) + + # Add any parent signatures + if self.parent: + for cur_cred in self.get_credential_list()[1:]: + sdoc = parseString(cur_cred.get_signature().get_xml()) + ele = doc.importNode(sdoc.getElementsByTagName("Signature")[0], True) + signatures.appendChild(ele) + + # Get the finished product + self.xml = doc.toxml("utf-8") + + + def save_to_random_tmp_file(self): + fp, filename = mkstemp(suffix='cred', text=True) + fp = os.fdopen(fp, "w") + self.save_to_file(filename, save_parents=True, filep=fp) + return filename + + def save_to_file(self, filename, save_parents=True, filep=None): + if not self.xml: + self.encode() + if filep: + f = filep + else: + f = open(filename, "w") + f.write(self.xml) + f.close() + + def save_to_string(self, save_parents=True): + if not self.xml: + self.encode() + return self.xml + + def get_refid(self): + if not self.refid: + self.refid = 'ref0' + return self.refid + + def set_refid(self, rid): + self.refid = rid + + ## + # Figure out what refids exist, and update this credential's id + # so that it doesn't clobber the others. Returns the refids of + # the parents. + + def updateRefID(self): + if not self.parent: + self.set_refid('ref0') + return [] + + refs = [] + + next_cred = self.parent + while next_cred: + refs.append(next_cred.get_refid()) + if next_cred.parent: + next_cred = next_cred.parent + else: + next_cred = None + + + # Find a unique refid for this credential + rid = self.get_refid() + while rid in refs: + val = int(rid[3:]) + rid = "ref%d" % (val + 1) + + # Set the new refid + self.set_refid(rid) + + # Return the set of parent credential ref ids + return refs + + def get_xml(self): + if not self.xml: + self.encode() + return self.xml + + ## + # Sign the XML file created by encode() + # + # WARNING: + # In general, a signed credential obtained externally should + # not be changed else the signature is no longer valid. So, once + # you have loaded an existing signed credential, do not call encode() or sign() on it. + + def sign(self): + if not self.issuer_privkey: + return + if not self.issuer_gid: + return + doc = parseString(self.get_xml()) + sigs = doc.getElementsByTagName("signatures")[0] + + # Create the signature template to be signed + signature = Signature() + signature.set_refid(self.get_refid()) + sdoc = parseString(signature.get_xml()) + sig_ele = doc.importNode(sdoc.getElementsByTagName("Signature")[0], True) + sigs.appendChild(sig_ele) + + self.xml = doc.toxml("utf-8") + + + # Split the issuer GID into multiple certificates if it's a chain + chain = GID(filename=self.issuer_gid) + gid_files = [] + while chain: + gid_files.append(chain.save_to_random_tmp_file(False)) + if chain.get_parent(): + chain = chain.get_parent() + else: + chain = None + + + # Call out to xmlsec1 to sign it + ref = 'Sig_%s' % self.get_refid() + filename = self.save_to_random_tmp_file() + print "**********************************",'%s --sign --node-id "%s" --privkey-pem %s,%s %s' % (self.xmlsec_path, ref, self.issuer_privkey, ",".join(gid_files), filename) + command='%s --sign --node-id "%s" --privkey-pem %s,%s %s' \ + % (self.xmlsec_path, ref, self.issuer_privkey, ",".join(gid_files), filename) +# print 'command',command + signed = os.popen(command).read() + print "*************************************",signed + os.remove(filename) + + for gid_file in gid_files: + os.remove(gid_file) + + self.xml = signed + + # This is no longer a legacy credential + if self.legacy: + self.legacy = None + + # Update signatures + self.decode() + + + ## + # Retrieve the attributes of the credential from the XML. + # This is automatically called by the various get_* methods of + # this class and should not need to be called explicitly. + + def decode(self): + if not self.xml: + return + doc = parseString(self.xml) + sigs = [] + signed_cred = doc.getElementsByTagName("signed-credential") + + # Is this a signed-cred or just a cred? + if len(signed_cred) > 0: + creds = signed_cred[0].getElementsByTagName("credential") + signatures = signed_cred[0].getElementsByTagName("signatures") + if len(signatures) > 0: + sigs = signatures[0].getElementsByTagName("Signature") + else: + creds = doc.getElementsByTagName("credential") + + if creds is None or len(creds) == 0: + # malformed cred file + raise CredentialNotVerifiable("Malformed XML: No credential tag found") + + # Just take the first cred if there are more than one + cred = creds[0] + + self.set_refid(cred.getAttribute("xml:id")) + self.set_expiration(utcparse(getTextNode(cred, "expires"))) + +# import traceback +# stack = traceback.extract_stack() + + og = getTextNode(cred, "owner_gid") + # ABAC creds will have this be None and use this method +# if og is None: +# found = False +# for frame in stack: +# if 'super(ABACCredential, self).decode()' in frame: +# found = True +# break +# if not found: +# raise CredentialNotVerifiable("Malformed XML: No owner_gid found") + self.gidCaller = GID(string=og) + tg = getTextNode(cred, "target_gid") +# if tg is None: +# found = False +# for frame in stack: +# if 'super(ABACCredential, self).decode()' in frame: +# found = True +# break +# if not found: +# raise CredentialNotVerifiable("Malformed XML: No target_gid found") + self.gidObject = GID(string=tg) + + # Process privileges + rlist = Rights() + priv_nodes = cred.getElementsByTagName("privileges") + if len(priv_nodes) > 0: + privs = priv_nodes[0] + for priv in privs.getElementsByTagName("privilege"): + kind = getTextNode(priv, "name") + deleg = str2bool(getTextNode(priv, "can_delegate")) + if kind == '*': + # Convert * into the default privileges for the credential's type + # Each inherits the delegatability from the * above + _ , type = urn_to_hrn(self.gidObject.get_urn()) + rl = determine_rights(type, self.gidObject.get_urn()) + for r in rl.rights: + r.delegate = deleg + rlist.add(r) + else: + rlist.add(Right(kind.strip(), deleg)) + self.set_privileges(rlist) + + + # Is there a parent? + parent = cred.getElementsByTagName("parent") + if len(parent) > 0: + parent_doc = parent[0].getElementsByTagName("credential")[0] + parent_xml = parent_doc.toxml("utf-8") + if parent_xml is None or parent_xml.strip() == "": + raise CredentialNotVerifiable("Malformed XML: Had parent tag but it is empty") + self.parent = Credential(string=parent_xml) + self.updateRefID() + + # Assign the signatures to the credentials + for sig in sigs: + Sig = Signature(string=sig.toxml("utf-8")) + + for cur_cred in self.get_credential_list(): + if cur_cred.get_refid() == Sig.get_refid(): + cur_cred.set_signature(Sig) + + + ## + # Verify + # trusted_certs: A list of trusted GID filenames (not GID objects!) + # Chaining is not supported within the GIDs by xmlsec1. + # + # trusted_certs_required: Should usually be true. Set False means an + # empty list of trusted_certs would still let this method pass. + # It just skips xmlsec1 verification et al. Only used by some utils + # + # Verify that: + # . All of the signatures are valid and that the issuers trace back + # to trusted roots (performed by xmlsec1) + # . The XML matches the credential schema + # . That the issuer of the credential is the authority in the target's urn + # . In the case of a delegated credential, this must be true of the root + # . That all of the gids presented in the credential are valid + # . Including verifying GID chains, and includ the issuer + # . The credential is not expired + # + # -- For Delegates (credentials with parents) + # . The privileges must be a subset of the parent credentials + # . The privileges must have "can_delegate" set for each delegated privilege + # . The target gid must be the same between child and parents + # . The expiry time on the child must be no later than the parent + # . The signer of the child must be the owner of the parent + # + # -- Verify does *NOT* + # . ensure that an xmlrpc client's gid matches a credential gid, that + # must be done elsewhere + # + # @param trusted_certs: The certificates of trusted CA certificates + def verify(self, trusted_certs=None, schema=None, trusted_certs_required=True): + if not self.xml: + print "\n\n\n\n\n\n\n\n\n\n\n\n\n----------------------CRED\n\n\n\n\n\n\n\n\n\n\n\n\n" + print "not xml" + self.decode() + + # validate against RelaxNG schema + if HAVELXML and not self.legacy: + if schema and os.path.exists(schema): + tree = etree.parse(StringIO(self.xml)) + schema_doc = etree.parse(schema) + xmlschema = etree.XMLSchema(schema_doc) + if not xmlschema.validate(tree): + error = xmlschema.error_log.last_error + message = "%s: %s (line %s)" % (self.get_summary_tostring(), error.message, error.line) + raise CredentialNotVerifiable(message) + + if trusted_certs_required and trusted_certs is None: + trusted_certs = [] + +# trusted_cert_objects = [GID(filename=f) for f in trusted_certs] + trusted_cert_objects = [] + ok_trusted_certs = [] + # If caller explicitly passed in None that means skip cert chain validation. + # Strange and not typical + if trusted_certs is not None: + for f in trusted_certs: + try: + # Failures here include unreadable files + # or non PEM files + trusted_cert_objects.append(GID(filename=f)) + ok_trusted_certs.append(f) + except Exception, exc: + pass + trusted_certs = ok_trusted_certs + + # Use legacy verification if this is a legacy credential + if self.legacy: + self.legacy.verify_chain(trusted_cert_objects) + if self.legacy.client_gid: + self.legacy.client_gid.verify_chain(trusted_cert_objects) + if self.legacy.object_gid: + self.legacy.object_gid.verify_chain(trusted_cert_objects) + return True + + # make sure it is not expired + if self.get_expiration() < datetime.datetime.utcnow(): + raise CredentialNotVerifiable("Credential %s expired at %s" % (self.get_summary_tostring(), self.expiration.isoformat())) + + # Verify the signatures + filename = self.save_to_random_tmp_file() + if trusted_certs is not None: + cert_args = " ".join(['--trusted-pem %s' % x for x in trusted_certs]) + + # If caller explicitly passed in None that means skip cert chain validation. + # - Strange and not typical + if trusted_certs is not None: + # Verify the gids of this cred and of its parents + for cur_cred in self.get_credential_list(): + cur_cred.get_gid_object().verify_chain(trusted_cert_objects) + cur_cred.get_gid_caller().verify_chain(trusted_cert_objects) + + refs = [] + refs.append("Sig_%s" % self.get_refid()) + + parentRefs = self.updateRefID() + for ref in parentRefs: + refs.append("Sig_%s" % ref) + + for ref in refs: + # If caller explicitly passed in None that means skip xmlsec1 validation. + # Strange and not typical + if trusted_certs is None: + break + + verified = os.popen('%s --verify --node-id "%s" %s %s 2>&1' \ + % (self.xmlsec_path, ref, cert_args, filename)).read() + if not verified.strip().startswith("OK"): + # xmlsec errors have a msg= which is the interesting bit. + mstart = verified.find("msg=") + msg = "" + if mstart > -1 and len(verified) > 4: + mstart = mstart + 4 + mend = verified.find('\\', mstart) + msg = verified[mstart:mend] + raise CredentialNotVerifiable("xmlsec1 error verifying cred %s using Signature ID %s: %s %s" % (self.get_summary_tostring(), ref, msg, verified.strip())) + os.remove(filename) + + # Verify the parents (delegation) + if self.parent: + self.verify_parent(self.parent) + + # Make sure the issuer is the target's authority, and is + # itself a valid GID + self.verify_issuer(trusted_cert_objects) + return True + + ## + # Creates a list of the credential and its parents, with the root + # (original delegated credential) as the last item in the list + def get_credential_list(self): + cur_cred = self + list = [] + while cur_cred: + list.append(cur_cred) + if cur_cred.parent: + cur_cred = cur_cred.parent + else: + cur_cred = None + return list + + ## + # Make sure the credential's target gid (a) was signed by or (b) + # is the same as the entity that signed the original credential, + # or (c) is an authority over the target's namespace. + # Also ensure that the credential issuer / signer itself has a valid + # GID signature chain (signed by an authority with namespace rights). + def verify_issuer(self, trusted_gids): + root_cred = self.get_credential_list()[-1] + root_target_gid = root_cred.get_gid_object() + if root_cred.get_signature() is None: + # malformed + raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred has no signature" % (self.gidCaller.get_urn(), self.gidObject.get_urn())) + + root_cred_signer = root_cred.get_signature().get_issuer_gid() + + # Case 1: + # Allow non authority to sign target and cred about target. + # + # Why do we need to allow non authorities to sign? + # If in the target gid validation step we correctly + # checked that the target is only signed by an authority, + # then this is just a special case of case 3. + # This short-circuit is the common case currently - + # and cause GID validation doesn't check 'authority', + # this allows users to generate valid slice credentials. + if root_target_gid.is_signed_by_cert(root_cred_signer): + # cred signer matches target signer, return success + return + + # Case 2: + # Allow someone to sign credential about themeselves. Used? + # If not, remove this. + #root_target_gid_str = root_target_gid.save_to_string() + #root_cred_signer_str = root_cred_signer.save_to_string() + #if root_target_gid_str == root_cred_signer_str: + # # cred signer is target, return success + # return + + # Case 3: + + # root_cred_signer is not the target_gid + # So this is a different gid that we have not verified. + # xmlsec1 verified the cert chain on this already, but + # it hasn't verified that the gid meets the HRN namespace + # requirements. + # Below we'll ensure that it is an authority. + # But we haven't verified that it is _signed by_ an authority + # We also don't know if xmlsec1 requires that cert signers + # are marked as CAs. + + # Note that if verify() gave us no trusted_gids then this + # call will fail. So skip it if we have no trusted_gids + if trusted_gids and len(trusted_gids) > 0: + root_cred_signer.verify_chain(trusted_gids) + else: + pass + # See if the signer is an authority over the domain of the target. + # There are multiple types of authority - accept them all here + # Maybe should be (hrn, type) = urn_to_hrn(root_cred_signer.get_urn()) + root_cred_signer_type = root_cred_signer.get_type() + if (root_cred_signer_type.find('authority') == 0): + #logger.debug('Cred signer is an authority') + # signer is an authority, see if target is in authority's domain + signerhrn = root_cred_signer.get_hrn() + if hrn_authfor_hrn(signerhrn, root_target_gid.get_hrn()): + return + + # We've required that the credential be signed by an authority + # for that domain. Reasonable and probably correct. + # A looser model would also allow the signer to be an authority + # in my control framework - eg My CA or CH. Even if it is not + # the CH that issued these, eg, user credentials. + + # Give up, credential does not pass issuer verification + + raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred signer %s not the trusted authority for Cred target %s" % (self.gidCaller.get_urn(), self.gidObject.get_urn(), root_cred_signer.get_hrn(), root_target_gid.get_hrn())) + + + ## + # -- For Delegates (credentials with parents) verify that: + # . The privileges must be a subset of the parent credentials + # . The privileges must have "can_delegate" set for each delegated privilege + # . The target gid must be the same between child and parents + # . The expiry time on the child must be no later than the parent + # . The signer of the child must be the owner of the parent + def verify_parent(self, parent_cred): + # make sure the rights given to the child are a subset of the + # parents rights (and check delegate bits) + if not parent_cred.get_privileges().is_superset(self.get_privileges()): + raise ChildRightsNotSubsetOfParent(("Parent cred ref %s rights " % parent_cred.get_refid()) + + self.parent.get_privileges().save_to_string() + (" not superset of delegated cred %s ref %s rights " % (self.get_summary_tostring(), self.get_refid())) + + self.get_privileges().save_to_string()) + + # make sure my target gid is the same as the parent's + if not parent_cred.get_gid_object().save_to_string() == \ + self.get_gid_object().save_to_string(): + raise CredentialNotVerifiable("Delegated cred %s: Target gid not equal between parent and child. Parent %s" % (self.get_summary_tostring(), parent_cred.get_summary_tostring())) + + # make sure my expiry time is <= my parent's + if not parent_cred.get_expiration() >= self.get_expiration(): + raise CredentialNotVerifiable("Delegated credential %s expires after parent %s" % (self.get_summary_tostring(), parent_cred.get_summary_tostring())) + + # make sure my signer is the parent's caller + if not parent_cred.get_gid_caller().save_to_string(False) == \ + self.get_signature().get_issuer_gid().save_to_string(False): + raise CredentialNotVerifiable("Delegated credential %s not signed by parent %s's caller" % (self.get_summary_tostring(), parent_cred.get_summary_tostring())) + + # Recurse + if parent_cred.parent: + parent_cred.verify_parent(parent_cred.parent) + + + def delegate(self, delegee_gidfile, caller_keyfile, caller_gidfile): + """ + Return a delegated copy of this credential, delegated to the + specified gid's user. + """ + # get the gid of the object we are delegating + object_gid = self.get_gid_object() + object_hrn = object_gid.get_hrn() + + # the hrn of the user who will be delegated to + delegee_gid = GID(filename=delegee_gidfile) + delegee_hrn = delegee_gid.get_hrn() + + #user_key = Keypair(filename=keyfile) + #user_hrn = self.get_gid_caller().get_hrn() + subject_string = "%s delegated to %s" % (object_hrn, delegee_hrn) + dcred = Credential(subject=subject_string) + dcred.set_gid_caller(delegee_gid) + dcred.set_gid_object(object_gid) + dcred.set_parent(self) + dcred.set_expiration(self.get_expiration()) + dcred.set_privileges(self.get_privileges()) + dcred.get_privileges().delegate_all_privileges(True) + #dcred.set_issuer_keys(keyfile, delegee_gidfile) + dcred.set_issuer_keys(caller_keyfile, caller_gidfile) + dcred.encode() + dcred.sign() + + return dcred + + # only informative + def get_filename(self): + return getattr(self,'filename',None) + + ## + # Dump the contents of a credential to stdout in human-readable format + # + # @param dump_parents If true, also dump the parent certificates + def dump (self, *args, **kwargs): + print self.dump_string(*args, **kwargs) + + def dump_string(self, dump_parents=False, show_xml=False): + result="" + result += "CREDENTIAL %s\n" % self.get_subject() + filename=self.get_filename() + if filename: result += "Filename %s\n"%filename + result += " privs: %s\n" % self.get_privileges().save_to_string() + gidCaller = self.get_gid_caller() + if gidCaller: + result += " gidCaller:\n" + result += gidCaller.dump_string(8, dump_parents) + + if self.get_signature(): + result += " gidIssuer:\n" + result += self.get_signature().get_issuer_gid().dump_string(8, dump_parents) + + if self.expiration: + result += " expiration: " + self.expiration.isoformat() + "\n" + + gidObject = self.get_gid_object() + if gidObject: + result += " gidObject:\n" + result += gidObject.dump_string(8, dump_parents) + + if self.parent and dump_parents: + result += "\nPARENT" + result += self.parent.dump_string(True) + + if show_xml and HAVELXML: + try: + tree = etree.parse(StringIO(self.xml)) + aside = etree.tostring(tree, pretty_print=True) + result += "\nXML:\n\n" + result += aside + result += "\nEnd XML\n" + except: + import traceback + traceback.print_exc() + + return result diff --git a/core/lib/am/credentials/src/trust/credential_legacy.py b/core/lib/am/credentials/src/trust/credential_legacy.py new file mode 100644 index 00000000..57c8bb02 --- /dev/null +++ b/core/lib/am/credentials/src/trust/credential_legacy.py @@ -0,0 +1,272 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- +## +# Implements SFA Credentials +# +# Credentials are layered on top of certificates, and are essentially a +# certificate that stores a tuple of parameters. +## + + +import xmlrpclib + +from geniutils.src.faults.faults import MissingDelegateBit +from geniutils.src.faults.faults import ChildRightsNotSubsetOfParent +from credentials.src.trust.certificate import Certificate +from credentials.src.trust.gid import GID +from credentials.src.trust.rights import Rights + +## +# Credential is a tuple: +# (GIDCaller, GIDObject, LifeTime, Privileges, Delegate) +# +# These fields are encoded using xmlrpc into the subjectAltName field of the +# x509 certificate. Note: Call encode() once the fields have been filled in +# to perform this encoding. + +class CredentialLegacy(Certificate): + gidCaller = None + gidObject = None + lifeTime = None + privileges = None + delegate = False + + ## + # Create a Credential object + # + # @param create If true, create a blank x509 certificate + # @param subject If subject!=None, create an x509 cert with the subject name + # @param string If string!=None, load the credential from the string + # @param filename If filename!=None, load the credential from the file + + def __init__(self, create=False, subject=None, string=None, filename=None): + Certificate.__init__(self, create, subject, string, filename) + + ## + # set the GID of the caller + # + # @param gid GID object of the caller + + def set_gid_caller(self, gid): + self.gidCaller = gid + # gid origin caller is the caller's gid by default + self.gidOriginCaller = gid + + ## + # get the GID of the object + + def get_gid_caller(self): + if not self.gidCaller: + self.decode() + return self.gidCaller + + ## + # set the GID of the object + # + # @param gid GID object of the object + + def set_gid_object(self, gid): + self.gidObject = gid + + ## + # get the GID of the object + + def get_gid_object(self): + if not self.gidObject: + self.decode() + return self.gidObject + + ## + # set the lifetime of this credential + # + # @param lifetime lifetime of credential + + def set_lifetime(self, lifeTime): + self.lifeTime = lifeTime + + ## + # get the lifetime of the credential + + def get_lifetime(self): + if not self.lifeTime: + self.decode() + return self.lifeTime + + ## + # set the delegate bit + # + # @param delegate boolean (True or False) + + def set_delegate(self, delegate): + self.delegate = delegate + + ## + # get the delegate bit + + def get_delegate(self): + if not self.delegate: + self.decode() + return self.delegate + + ## + # set the privileges + # + # @param privs either a comma-separated list of privileges of a Rights object + + def set_privileges(self, privs): + if isinstance(privs, str): + self.privileges = Rights(string = privs) + else: + self.privileges = privs + + ## + # return the privileges as a Rights object + + def get_privileges(self): + if not self.privileges: + self.decode() + return self.privileges + + ## + # determine whether the credential allows a particular operation to be + # performed + # + # @param op_name string specifying name of operation ("lookup", "update", etc) + + def can_perform(self, op_name): + rights = self.get_privileges() + if not rights: + return False + return rights.can_perform(op_name) + + ## + # Encode the attributes of the credential into a string and store that + # string in the alt-subject-name field of the X509 object. This should be + # done immediately before signing the credential. + + def encode(self): + dict = {"gidCaller": None, + "gidObject": None, + "lifeTime": self.lifeTime, + "privileges": None, + "delegate": self.delegate} + if self.gidCaller: + dict["gidCaller"] = self.gidCaller.save_to_string(save_parents=True) + if self.gidObject: + dict["gidObject"] = self.gidObject.save_to_string(save_parents=True) + if self.privileges: + dict["privileges"] = self.privileges.save_to_string() + str = xmlrpclib.dumps((dict,), allow_none=True) + self.set_data('URI:http://' + str) + + ## + # Retrieve the attributes of the credential from the alt-subject-name field + # of the X509 certificate. This is automatically done by the various + # get_* methods of this class and should not need to be called explicitly. + + def decode(self): + data = self.get_data().lstrip('URI:http://') + + if data: + dict = xmlrpclib.loads(data)[0][0] + else: + dict = {} + + self.lifeTime = dict.get("lifeTime", None) + self.delegate = dict.get("delegate", None) + + privStr = dict.get("privileges", None) + if privStr: + self.privileges = Rights(string = privStr) + else: + self.privileges = None + + gidCallerStr = dict.get("gidCaller", None) + if gidCallerStr: + self.gidCaller = GID(string=gidCallerStr) + else: + self.gidCaller = None + + gidObjectStr = dict.get("gidObject", None) + if gidObjectStr: + self.gidObject = GID(string=gidObjectStr) + else: + self.gidObject = None + + ## + # Verify that a chain of credentials is valid (see cert.py:verify). In + # addition to the checks for ordinary certificates, verification also + # ensures that the delegate bit was set by each parent in the chain. If + # a delegate bit was not set, then an exception is thrown. + # + # Each credential must be a subset of the rights of the parent. + + def verify_chain(self, trusted_certs = None): + # do the normal certificate verification stuff + Certificate.verify_chain(self, trusted_certs) + + if self.parent: + # make sure the parent delegated rights to the child + if not self.parent.get_delegate(): + raise MissingDelegateBit(self.parent.get_subject()) + + # make sure the rights given to the child are a subset of the + # parents rights + if not self.parent.get_privileges().is_superset(self.get_privileges()): + raise ChildRightsNotSubsetOfParent(self.get_subject() + + " " + self.parent.get_privileges().save_to_string() + + " " + self.get_privileges().save_to_string()) + + return + + ## + # Dump the contents of a credential to stdout in human-readable format + # + # @param dump_parents If true, also dump the parent certificates + + def dump(self, *args, **kwargs): + print self.dump_string(*args,**kwargs) + + def dump_string(self, dump_parents=False): + result="" + result += "CREDENTIAL %s\n" % self.get_subject() + + result += " privs: %s\n" % self.get_privileges().save_to_string() + + gidCaller = self.get_gid_caller() + if gidCaller: + result += " gidCaller:\n" + gidCaller.dump(8, dump_parents) + + gidObject = self.get_gid_object() + if gidObject: + result += " gidObject:\n" + result += gidObject.dump_string(8, dump_parents) + + result += " delegate: %s" % self.get_delegate() + + if self.parent and dump_parents: + result += "PARENT\n" + result += self.parent.dump_string(dump_parents) + + return result diff --git a/core/lib/am/credentials/src/trust/gid.py b/core/lib/am/credentials/src/trust/gid.py new file mode 100644 index 00000000..831d8fb4 --- /dev/null +++ b/core/lib/am/credentials/src/trust/gid.py @@ -0,0 +1,262 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- +## +# Implements SFA GID. GIDs are based on certificates, and the GID class is a +# descendant of the certificate class. +## + +import xmlrpclib +import uuid + +from credentials.src.trust.certificate import Certificate + +from geniutils.src.faults.faults import GidInvalidParentHrn +from geniutils.src.faults.faults import GidParentHrn + +from geniutils.src.xrn.xrn import hrn_to_urn +from geniutils.src.xrn.xrn import urn_to_hrn +from geniutils.src.xrn.xrn import hrn_authfor_hrn + +## +# Create a new uuid. Returns the UUID as a string. + +def create_uuid(): + return str(uuid.uuid4().int) + +## +# GID is a tuple: +# (uuid, urn, public_key) +# +# UUID is a unique identifier and is created by the python uuid module +# (or the utility function create_uuid() in gid.py). +# +# HRN is a human readable name. It is a dotted form similar to a backward domain +# name. For example, planetlab.us.arizona.bakers. +# +# URN is a human readable identifier of form: +# "urn:publicid:IDN+toplevelauthority[:sub-auth.]*[\res. type]\ +object name" +# For example, urn:publicid:IDN+planetlab:us:arizona+user+bakers +# +# PUBLIC_KEY is the public key of the principal identified by the UUID/HRN. +# It is a Keypair object as defined in the cert.py module. +# +# It is expected that there is a one-to-one pairing between UUIDs and HRN, +# but it is uncertain how this would be inforced or if it needs to be enforced. +# +# These fields are encoded using xmlrpc into the subjectAltName field of the +# x509 certificate. Note: Call encode() once the fields have been filled in +# to perform this encoding. + + +class GID(Certificate): + ## + # Create a new GID object + # + # @param create If true, create the X509 certificate + # @param subject If subject!=None, create the X509 cert and set the subject name + # @param string If string!=None, load the GID from a string + # @param filename If filename!=None, load the GID from a file + # @param lifeDays life of GID in days - default is 1825==5 years + + def __init__(self, create=False, subject=None, string=None, filename=None, uuid=None, hrn=None, urn=None, lifeDays=1825, email=None): + self.uuid = None + self.hrn = None + self.urn = None + self.email = None # for adding to the SubjectAltName + Certificate.__init__(self, lifeDays, create, subject, string, filename) + + if subject: + print "Creating GID for subject: %s" % subject + if uuid: + self.uuid = int(uuid) + if hrn: + self.hrn = hrn + self.urn = hrn_to_urn(hrn, 'unknown') + if urn: + self.urn = urn + self.hrn, type = urn_to_hrn(urn) + if email: + self.set_email(email) + + def set_uuid(self, uuid): + if isinstance(uuid, str): + self.uuid = int(uuid) + else: + self.uuid = uuid + + def get_uuid(self): + if not self.uuid: + self.decode() + return self.uuid + + def set_hrn(self, hrn): + self.hrn = hrn + + def get_hrn(self): + if not self.hrn: + self.decode() + return self.hrn + + def set_urn(self, urn): + self.urn = urn + self.hrn, type = urn_to_hrn(urn) + + def get_urn(self): + if not self.urn: + self.decode() + return self.urn + + # Will be stuffed into subjectAltName + def set_email(self, email): + self.email = email + + def get_email(self): + if not self.email: + self.decode() + return self.email + + def get_type(self): + if not self.urn: + self.decode() + _, t = urn_to_hrn(self.urn) + return t + + ## + # Encode the GID fields and package them into the subject-alt-name field + # of the X509 certificate. This must be called prior to signing the + # certificate. It may only be called once per certificate. + + def encode(self): + if self.urn: + urn = self.urn + else: + urn = hrn_to_urn(self.hrn, None) + + str = "URI:" + urn + + if self.uuid: + str += ", " + "URI:" + uuid.UUID(int=self.uuid).urn + + if self.email: + str += ", " + "email:" + self.email + + self.set_data(str, 'subjectAltName') + + + ## + # Decode the subject-alt-name field of the X509 certificate into the + # fields of the GID. This is automatically called by the various get_*() + # functions in this class. + + def decode(self): + data = self.get_data('subjectAltName') + dict = {} + if data: + if data.lower().startswith('uri:http://'): + dict = xmlrpclib.loads(data[11:])[0][0] + else: + spl = data.split(', ') + for val in spl: + if val.lower().startswith('uri:urn:uuid:'): + dict['uuid'] = uuid.UUID(val[4:]).int + elif val.lower().startswith('uri:urn:publicid:idn+'): + dict['urn'] = val[4:] + elif val.lower().startswith('email:'): + # FIXME: Ensure there isn't cruft in that address... + # EG look for email:copy,.... + dict['email'] = val[6:] + + self.uuid = dict.get("uuid", None) + self.urn = dict.get("urn", None) + self.hrn = dict.get("hrn", None) + self.email = dict.get("email", None) + if self.urn: + self.hrn = urn_to_hrn(self.urn)[0] + + ## + # Dump the credential to stdout. + # + # @param indent specifies a number of spaces to indent the output + # @param dump_parents If true, also dump the parents of the GID + + def dump(self, *args, **kwargs): + print self.dump_string(*args,**kwargs) + + def dump_string(self, indent=0, dump_parents=False): + result=" "*(indent-2) + "GID\n" + result += " "*indent + "hrn:" + str(self.get_hrn()) +"\n" + result += " "*indent + "urn:" + str(self.get_urn()) +"\n" + result += " "*indent + "uuid:" + str(self.get_uuid()) + "\n" + if self.get_email() is not None: + result += " "*indent + "email:" + str(self.get_email()) + "\n" + filename=self.get_filename() + if filename: result += "Filename %s\n"%filename + + if self.parent and dump_parents: + result += " "*indent + "parent:\n" + result += self.parent.dump_string(indent+4, dump_parents) + return result + + ## + # Verify the chain of authenticity of the GID. First perform the checks + # of the certificate class (verifying that each parent signs the child, + # etc). In addition, GIDs also confirm that the parent's HRN is a prefix + # of the child's HRN, and the parent is of type 'authority'. + # + # Verifying these prefixes prevents a rogue authority from signing a GID + # for a principal that is not a member of that authority. For example, + # planetlab.us.arizona cannot sign a GID for planetlab.us.princeton.foo. + + def verify_chain(self, trusted_certs = None): + # do the normal certificate verification stuff + trusted_root = Certificate.verify_chain(self, trusted_certs) + + if self.parent: + # make sure the parent's hrn is a prefix of the child's hrn + if not hrn_authfor_hrn(self.parent.get_hrn(), self.get_hrn()): + raise GidParentHrn("This cert HRN %s isn't in the namespace for parent HRN %s" % (self.get_hrn(), self.parent.get_hrn())) + + # Parent must also be an authority (of some type) to sign a GID + # There are multiple types of authority - accept them all here + if not self.parent.get_type().find('authority') == 0: + raise GidInvalidParentHrn("This cert %s's parent %s is not an authority (is a %s)" % (self.get_hrn(), self.parent.get_hrn(), self.parent.get_type())) + + # Then recurse up the chain - ensure the parent is a trusted + # root or is in the namespace of a trusted root + self.parent.verify_chain(trusted_certs) + else: + # make sure that the trusted root's hrn is a prefix of the child's + trusted_gid = GID(string=trusted_root.save_to_string()) + trusted_type = trusted_gid.get_type() + trusted_hrn = trusted_gid.get_hrn() + #if trusted_type == 'authority': + # trusted_hrn = trusted_hrn[:trusted_hrn.rindex('.')] + cur_hrn = self.get_hrn() + if not hrn_authfor_hrn(trusted_hrn, cur_hrn): + raise GidParentHrn("Trusted root with HRN %s isn't a namespace authority for this cert: %s" % (trusted_hrn, cur_hrn)) + + # There are multiple types of authority - accept them all here + if not trusted_type.find('authority') == 0: + raise GidInvalidParentHrn("This cert %s's trusted root signer %s is not an authority (is a %s)" % (self.get_hrn(), trusted_hrn, trusted_type)) + + return diff --git a/core/lib/am/credentials/src/trust/hierarchy.py b/core/lib/am/credentials/src/trust/hierarchy.py new file mode 100644 index 00000000..85d6d9fc --- /dev/null +++ b/core/lib/am/credentials/src/trust/hierarchy.py @@ -0,0 +1,380 @@ +## +# This module implements a hierarchy of authorities and performs a similar +# function as the "tree" module of the original SFA prototype. An HRN +# is assumed to be a string of authorities separated by dots. For example, +# "planetlab.us.arizona.bakers". Each component of the HRN is a different +# authority, with the last component being a leaf in the tree. +# +# Each authority is stored in a subdirectory on the registry. Inside this +# subdirectory are several files: +# *.GID - GID file +# *.PKEY - private key file +## + +import os + +from geniutils.src.faults.faults import MissingAuthority +#from openflow.optin_manager.sfa.util.openflow.optin_manager.sfa.ogging import logger +from geniutils.src.xrn.xrn import get_leaf +from geniutils.src.xrn.xrn import get_authority +from geniutils.src.xrn.xrn import hrn_to_urn +from geniutils.src.xrn.xrn import urn_to_hrn +from credentials.src.trust.certificate import Keypair +from credentials.src.trust.credential import Credential +from credentials.src.trust.gid import GID, create_uuid +from settings.src.settings import Settings as config +from credentials.src.trust.sfaticket import SfaTicket +#XXX:Use the ClearingHouse +#from openflow.optin_manager.sfa.setUp import setup_config as auth_config +## +# The AuthInfo class contains the information for an authority. This information +# includes the GID, private key, and database connection information. + +class AuthInfo: + hrn = None + gid_object = None + gid_filename = None + privkey_filename = None + ## + # Initialize and authority object. + # + # @param xrn the human readable name of the authority (urn will be converted to hrn) + # @param gid_filename the filename containing the GID + # @param privkey_filename the filename containing the private key + + def __init__(self, xrn, gid_filename, privkey_filename): + hrn, type = urn_to_hrn(xrn) + self.hrn = hrn + self.set_gid_filename(gid_filename) + self.privkey_filename = privkey_filename + + ## + # Set the filename of the GID + # + # @param fn filename of file containing GID + + def set_gid_filename(self, fn): + self.gid_filename = fn + self.gid_object = None + + def get_privkey_filename(self): + return self.privkey_filename + + def get_gid_filename(self): + return self.gid_filename + + ## + # Get the GID in the form of a GID object + + def get_gid_object(self): + if not self.gid_object: + self.gid_object = GID(filename = self.gid_filename) + return self.gid_object + + ## + # Get the private key in the form of a Keypair object + + def get_pkey_object(self): + return Keypair(filename = self.privkey_filename) + + ## + # Replace the GID with a new one. The file specified by gid_filename is + # overwritten with the new GID object + # + # @param gid object containing new GID + + def update_gid_object(self, gid): + gid.save_to_file(self.gid_filename) + self.gid_object = gid + +## +# The Hierarchy class is responsible for managing the tree of authorities. +# Each authority is a node in the tree and exists as an AuthInfo object. +# +# The tree is stored on disk in a hierarchical manner than reflects the +# structure of the tree. Each authority is a subdirectory, and each subdirectory +# contains the GID and pkey files for that authority (as well as +# subdirectories for each sub-authority) + +class Hierarchy: + ## + # Create the hierarchy object. + # + # @param basedir the base directory to store the hierarchy in + + def __init__(self, basedir = None, config=None): + if config: + self.config = config + if not basedir: + basedir = os.path.join(self.config.SFA_DATA_DIR, "authorities") + self.basedir = basedir + ## + # Given a hrn, return the filenames of the GID, private key + # files. + # + # @param xrn the human readable name of the authority (urn will be convertd to hrn) + + def get_auth_filenames(self, xrn): + hrn, type = urn_to_hrn(xrn) + leaf = get_leaf(hrn) + parent_hrn = get_authority(hrn) + directory = os.path.join(self.basedir, hrn.replace(".", "/")) + + gid_filename = os.path.join(directory, leaf+".gid") + privkey_filename = os.path.join(directory, leaf+".pkey") + + return (directory, gid_filename, privkey_filename) + + ## + # Check to see if an authority exists. An authority exists if it's disk + # files exist. + # + # @param the human readable name of the authority to check + + def auth_exists(self, xrn): + hrn, type = urn_to_hrn(xrn) + (directory, gid_filename, privkey_filename) = \ + self.get_auth_filenames(hrn) + print directory, gid_filename, privkey_filename + + return os.path.exists(gid_filename) and os.path.exists(privkey_filename) + + ## + # Create an authority. A private key for the authority and the associated + # GID are created and signed by the parent authority. + # + # @param xrn the human readable name of the authority to create (urn will be converted to hrn) + # @param create_parents if true, also create the parents if they do not exist + + def create_auth(self, xrn, create_parents=False): + hrn, type = urn_to_hrn(str(xrn)) + + # create the parent authority if necessary + parent_hrn = get_authority(hrn) + parent_urn = hrn_to_urn(parent_hrn, 'authority') + if (parent_hrn) and (not self.auth_exists(parent_urn)) and (create_parents): + self.create_auth(parent_urn, create_parents) + (directory, gid_filename, privkey_filename,) = \ + self.get_auth_filenames(hrn) + + # create the directory to hold the files + try: + os.makedirs(directory) + # if the path already exists then pass + except OSError, (errno, strerr): + if errno == 17: + pass + + if os.path.exists(privkey_filename): + pkey = Keypair(filename = privkey_filename) + else: + pkey = Keypair(create = True) + pkey.save_to_file(privkey_filename) + + gid = self.create_gid(xrn, create_uuid(), pkey) + gid.save_to_file(gid_filename, save_parents=True) + + def create_top_level_auth(self, hrn=None): + """ + Create top level records (includes root and sub authorities (local/remote) + """ + # create the authority if it doesnt alrady exist + if not self.auth_exists(hrn): + self.create_auth(hrn, create_parents=True) + + + def get_interface_auth_info(self, create=True): + hrn = self.config.SFA_INTERFACE_HRN + if not self.auth_exists(hrn): + if create==True: + self.create_top_level_auth(hrn) + else: + raise MissingAuthority(hrn) + return self.get_auth_info(hrn) + ## + # Return the AuthInfo object for the specified authority. If the authority + # does not exist, then an exception is thrown. As a side effect, disk files + # and a subdirectory may be created to store the authority. + # + # @param xrn the human readable name of the authority to create (urn will be converted to hrn). + + def get_auth_info(self, xrn): + hrn, type = urn_to_hrn(xrn) + if not self.auth_exists(hrn): + raise MissingAuthority(hrn) + + (directory, gid_filename, privkey_filename, ) = \ + self.get_auth_filenames(hrn) + + auth_info = AuthInfo(hrn, gid_filename, privkey_filename) + + # check the GID and see if it needs to be refreshed + gid = auth_info.get_gid_object() + gid_refreshed = self.refresh_gid(gid) + if gid != gid_refreshed: + auth_info.update_gid_object(gid_refreshed) + + return auth_info + + ## + # Create a new GID. The GID will be signed by the authority that is it's + # immediate parent in the hierarchy (and recursively, the parents' GID + # will be signed by its parent) + # + # @param hrn the human readable name to store in the GID + # @param uuid the unique identifier to store in the GID + # @param pkey the public key to store in the GID + + def create_gid(self, xrn, uuid, pkey, CA=False, email=None): + hrn, type = urn_to_hrn(xrn) + if not type: + type = 'authority' + parent_hrn = get_authority(hrn) + # Using hrn_to_urn() here to make sure the urn is in the right format + # If xrn was a hrn instead of a urn, then the gid's urn will be + # of type None + urn = hrn_to_urn(hrn, type) + subject = self.get_subject(hrn) + if not subject: + subject = hrn + gid = GID(subject=subject, uuid=uuid, hrn=hrn, urn=urn, email=email) + # is this a CA cert + if hrn == self.config.SFA_INTERFACE_HRN or not parent_hrn: + # root or sub authority + gid.set_intermediate_ca(True) + elif type and 'authority' in type: + # authority type + gid.set_intermediate_ca(False) + elif CA: + gid.set_intermediate_ca(True) + else: + gid.set_intermediate_ca(False) + + # set issuer + if not parent_hrn or hrn == self.config.SFA_INTERFACE_HRN: + # if there is no parent hrn, then it must be self-signed. this + # is where we terminate the recursion + gid.set_issuer(pkey, subject) + else: + # we need the parent's private key in order to sign this GID + parent_auth_info = self.get_auth_info(parent_hrn) + parent_gid = parent_auth_info.get_gid_object() + gid.set_issuer(parent_auth_info.get_pkey_object(), parent_gid.get_extended_subject()) + gid.set_parent(parent_auth_info.get_gid_object()) + + gid.set_pubkey(pkey) + gid.encode() + gid.sign() + + return gid + + def get_subject(self,hrn): + if len(hrn.split('.'))>1: + subject = auth_config.SUBJECT + else: + subject = auth_config.PARENT_SUBJECT + return subject + + + ## + # Refresh a GID. The primary use of this function is to refresh the + # the expiration time of the GID. It may also be used to change the HRN, + # UUID, or Public key of the GID. + # + # @param gid the GID to refresh + # @param hrn if !=None, change the hrn + # @param uuid if !=None, change the uuid + # @param pubkey if !=None, change the public key + def refresh_gid(self, gid, xrn=None, uuid=None, pubkey=None): + # TODO: compute expiration time of GID, refresh it if necessary + gid_is_expired = False + + # update the gid if we need to + if gid_is_expired or xrn or uuid or pubkey: + + if not xrn: + xrn = gid.get_urn() + if not uuid: + uuid = gid.get_uuid() + if not pubkey: + pubkey = gid.get_pubkey() + + gid = self.create_gid(xrn, uuid, pubkey) + + return gid + + ## + # Retrieve an authority credential for an authority. The authority + # credential will contain the authority privilege and will be signed by + # the authority's parent. + # + # @param hrn the human readable name of the authority (urn is converted to hrn) + # @param authority type of credential to return (authority | sa | ma) + + def get_auth_cred(self, xrn, kind="authority"): + hrn, type = urn_to_hrn(xrn) + auth_info = self.get_auth_info(hrn) + gid = auth_info.get_gid_object() + + cred = Credential(subject=hrn) + cred.set_gid_caller(gid) + cred.set_gid_object(gid) + cred.set_privileges(kind) + cred.get_privileges().delegate_all_privileges(True) + #cred.set_pubkey(auth_info.get_gid_object().get_pubkey()) + + parent_hrn = get_authority(hrn) + if not parent_hrn or hrn == self.config.SFA_INTERFACE_HRN: + # if there is no parent hrn, then it must be self-signed. this + # is where we terminate the recursion + cred.set_issuer_keys(auth_info.get_privkey_filename(), auth_info.get_gid_filename()) + else: + # we need the parent's private key in order to sign this GID + parent_auth_info = self.get_auth_info(parent_hrn) + cred.set_issuer_keys(parent_auth_info.get_privkey_filename(), parent_auth_info.get_gid_filename()) + + + cred.set_parent(self.get_auth_cred(parent_hrn, kind)) + + cred.encode() + cred.sign() + + return cred + ## + # Retrieve an authority ticket. An authority ticket is not actually a + # redeemable ticket, but only serves the purpose of being included as the + # parent of another ticket, in order to provide a chain of authentication + # for a ticket. + # + # This looks almost the same as get_auth_cred, but works for tickets + # XXX does similarity imply there should be more code re-use? + # + # @param xrn the human readable name of the authority (urn is converted to hrn) + + def get_auth_ticket(self, xrn): + hrn, type = urn_to_hrn(xrn) + auth_info = self.get_auth_info(hrn) + gid = auth_info.get_gid_object() + + ticket = SfaTicket(subject=hrn) + ticket.set_gid_caller(gid) + ticket.set_gid_object(gid) + ticket.set_delegate(True) + ticket.set_pubkey(auth_info.get_gid_object().get_pubkey()) + + parent_hrn = get_authority(hrn) + if not parent_hrn: + # if there is no parent hrn, then it must be self-signed. this + # is where we terminate the recursion + ticket.set_issuer(auth_info.get_pkey_object(), hrn) + else: + # we need the parent's private key in order to sign this GID + parent_auth_info = self.get_auth_info(parent_hrn) + ticket.set_issuer(parent_auth_info.get_pkey_object(), parent_auth_info.hrn) + ticket.set_parent(self.get_auth_cred(parent_hrn)) + + ticket.encode() + ticket.sign() + + return ticket + diff --git a/core/lib/am/credentials/src/trust/rights.py b/core/lib/am/credentials/src/trust/rights.py new file mode 100644 index 00000000..1b8baa4f --- /dev/null +++ b/core/lib/am/credentials/src/trust/rights.py @@ -0,0 +1,253 @@ +## +# This Module implements rights and lists of rights for the SFA. Rights +# are implemented by two classes: +# +# Right - represents a single right +# +# Rights - represents a list of rights +# +# A right may allow several different operations. For example, the "info" right +# allows "listslices", "listcomponentresources", etc. +## + + + +## +# privilege_table is a list of priviliges and what operations are allowed +# per privilege. +# Note that "*" is a privilege granted by ProtoGENI slice authorities, and we +# give it access to the GENI AM calls + +privilege_table = {"authority": ["register", "remove", "update", "resolve", "list", "getcredential", "*"], + "refresh": ["remove", "update"], + "resolve": ["resolve", "list", "getcredential"], + "sa": ["getticket", "redeemslice", "redeemticket", "createslice", "createsliver", "deleteslice", "deletesliver", "updateslice", + "getsliceresources", "getticket", "loanresources", "stopslice", "startslice", "renewsliver", + "deleteslice", "deletesliver", "resetslice", "listslices", "listnodes", "getpolicy", "sliverstatus"], + "embed": ["getticket", "redeemslice", "redeemticket", "createslice", "createsliver", "renewsliver", "deleteslice", + "deletesliver", "updateslice", "sliverstatus", "getsliceresources", "shutdown"], + "bind": ["getticket", "loanresources", "redeemticket"], + "control": ["updateslice", "createslice", "createsliver", "renewsliver", "sliverstatus", "stopslice", "startslice", + "deleteslice", "deletesliver", "resetslice", "getsliceresources", "getgids"], + "info": ["listslices", "listnodes", "getpolicy"], + "ma": ["setbootstate", "getbootstate", "reboot", "getgids", "gettrustedcerts"], + "operator": ["gettrustedcerts", "getgids"], + "*": ["createsliver", "deletesliver", "sliverstatus", "renewsliver", "shutdown"]} + + + +## +# Determine the rights that an object should have. The rights are entirely +# dependent on the type of the object. For example, users automatically +# get "refresh", "resolve", and "info". +# +# @param type the type of the object (user | sa | ma | slice | node) +# @param name human readable name of the object (not used at this time) +# +# @return Rights object containing rights + +def determine_rights(type, name): + rl = Rights() + + # rights seem to be somewhat redundant with the type of the credential. + # For example, a "sa" credential implies the authority right, because + # a sa credential cannot be issued to a user who is not an owner of + # the authority + if type == "user": + rl.add("refresh") + rl.add("resolve") + rl.add("info") + elif type in ["sa", "authority+sa"]: + rl.add("authority") + rl.add("sa") + elif type in ["ma", "authority+ma", "cm", "authority+cm", "sm", "authority+sm"]: + rl.add("authority") + rl.add("ma") + elif type == "authority": + rl.add("authority") + rl.add("sa") + rl.add("ma") + elif type == "slice": + rl.add("refresh") + rl.add("embed") + rl.add("bind") + rl.add("control") + rl.add("info") +# wouldn't that be authority+cm instead ? + elif type == "component": + rl.add("operator") + return rl + + +## +# The Right class represents a single privilege. + + + +class Right: + ## + # Create a new right. + # + # @param kind is a string naming the right. For example "control" + + def __init__(self, kind, delegate=False): + self.kind = kind + self.delegate = delegate + + def __repr__ (self): return ""%self.kind + + ## + # Test to see if this right object is allowed to perform an operation. + # Returns True if the operation is allowed, False otherwise. + # + # @param op_name is a string naming the operation. For example "listslices". + + def can_perform(self, op_name): + allowed_ops = privilege_table.get(self.kind.lower(), None) + if not allowed_ops: + return False + + # if "*" is specified, then all ops are permitted + if "*" in allowed_ops: + return True + + return (op_name.lower() in allowed_ops) + + ## + # Test to see if this right is a superset of a child right. A right is a + # superset if every operating that is allowed by the child is also allowed + # by this object. + # + # @param child is a Right object describing the child right + + def is_superset(self, child): + my_allowed_ops = privilege_table.get(self.kind.lower(), None) + child_allowed_ops = privilege_table.get(child.kind.lower(), None) + + if not self.delegate: + return False + + if "*" in my_allowed_ops: + return True + + for right in child_allowed_ops: + if not right in my_allowed_ops: + return False + + return True + +## +# A Rights object represents a list of privileges. + +class Rights: + ## + # Create a new rightlist object, containing no rights. + # + # @param string if string!=None, load the rightlist from the string + + def __init__(self, string=None): + self.rights = [] + if string: + self.load_from_string(string) + + def __repr__ (self): return "[" + " ".join( ["%s"%r for r in self.rights]) + "]" + + def is_empty(self): + return self.rights == [] + + ## + # Add a right to this list + # + # @param right is either a Right object or a string describing the right + + def add(self, right, delegate=False): + if isinstance(right, str): + right = Right(right, delegate) + self.rights.append(right) + + ## + # Load the rightlist object from a string + + def load_from_string(self, string): + self.rights = [] + + # none == no rights, so leave the list empty + if not string: + return + + parts = string.split(",") + for part in parts: + if ':' in part: + spl = part.split(':') + kind = spl[0].strip() + delegate = bool(int(spl[1])) + else: + kind = part.strip() + delegate = 0 + self.rights.append(Right(kind, bool(delegate))) + + ## + # Save the rightlist object to a string. It is saved in the format of a + # comma-separated list. + + def save_to_string(self): + right_names = [] + for right in self.rights: + right_names.append('%s:%d' % (right.kind.strip(), right.delegate)) + + return ",".join(right_names) + + ## + # Check to see if some right in this list allows an operation. This is + # done by evaluating the can_perform function of each operation in the + # list. + # + # @param op_name is an operation to check, for example "listslices" + + def can_perform(self, op_name): + + for right in self.rights: + if right.can_perform(op_name): + return True + return False + + ## + # Check to see if all of the rights in this rightlist are a superset + # of all the rights in a child rightlist. A rightlist is a superset + # if there is no operation in the child rightlist that cannot be + # performed in the parent rightlist. + # + # @param child is a rightlist object describing the child + + def is_superset(self, child): + for child_right in child.rights: + allowed = False + for my_right in self.rights: + if my_right.is_superset(child_right): + allowed = True + break + if not allowed: + return False + return True + + + ## + # set the delegate bit to 'delegate' on + # all privileges + # + # @param delegate boolean (True or False) + + def delegate_all_privileges(self, delegate): + for right in self.rights: + right.delegate = delegate + + ## + # true if all privileges have delegate bit set true + # false otherwise + + def get_all_delegate(self): + for right in self.rights: + if not right.delegate: + return False + return True + diff --git a/core/lib/am/credentials/src/trust/sfaticket.py b/core/lib/am/credentials/src/trust/sfaticket.py new file mode 100644 index 00000000..e8caf632 --- /dev/null +++ b/core/lib/am/credentials/src/trust/sfaticket.py @@ -0,0 +1,126 @@ +# +# implements SFA tickets +# + +import xmlrpclib + +from credentials.src.trust.certificate import Certificate +from credentials.src.trust.gid import GID + +# Ticket is tuple: +# (gidCaller, gidObject, attributes, rspec, delegate) +# +# gidCaller = GID of the caller performing the operation +# gidObject = GID of the slice +# attributes = slice attributes (keys, vref, instantiation, etc) +# rspec = resources + +class SfaTicket(Certificate): + gidCaller = None + gidObject = None + attributes = {} + rspec = {} + delegate = False + + def __init__(self, create=False, subject=None, string=None, filename=None): + Certificate.__init__(self, create, subject, string, filename) + + def set_gid_caller(self, gid): + self.gidCaller = gid + + def get_gid_caller(self): + if not self.gidCaller: + self.decode() + return self.gidCaller + + def set_gid_object(self, gid): + self.gidObject = gid + + def get_gid_object(self): + if not self.gidObject: + self.decode() + return self.gidObject + + def set_attributes(self, gid): + self.attributes = gid + + def get_attributes(self): + if not self.attributes: + self.decode() + return self.attributes + + def set_rspec(self, gid): + self.rspec = gid + + def get_rspec(self): + if not self.rspec: + self.decode() + return self.rspec + + def set_delegate(self, delegate): + self.delegate = delegate + + def get_delegate(self): + if not self.delegate: + self.decode() + return self.delegate + + def encode(self): + dict = {"gidCaller": None, + "gidObject": None, + "attributes": self.attributes, + "rspec": self.rspec, + "delegate": self.delegate} + if self.gidCaller: + dict["gidCaller"] = self.gidCaller.save_to_string(save_parents=True) + if self.gidObject: + dict["gidObject"] = self.gidObject.save_to_string(save_parents=True) + str = "URI:" + xmlrpclib.dumps((dict,), allow_none=True) + self.set_data(str) + + def decode(self): + data = self.get_data() + if data: + dict = xmlrpclib.loads(self.get_data()[4:])[0][0] + else: + dict = {} + + self.attributes = dict.get("attributes", {}) + self.rspec = dict.get("rspec", {}) + self.delegate = dict.get("delegate", False) + + gidCallerStr = dict.get("gidCaller", None) + if gidCallerStr: + self.gidCaller = GID(string=gidCallerStr) + else: + self.gidCaller = None + + gidObjectStr = dict.get("gidObject", None) + if gidObjectStr: + self.gidObject = GID(string=gidObjectStr) + else: + self.gidObject = None + + def dump(self, dump_parents=False): + print "TICKET", self.get_subject() + + print " gidCaller:" + gidCaller = self.get_gid_caller() + if gidCaller: + gidCaller.dump(8, dump_parents) + + print " gidObject:" + gidObject = self.get_gid_object() + if gidObject: + gidObject.dump(8, dump_parents) + + print " attributes:" + for attrname in self.get_attributes().keys(): + print " ", attrname, self.get_attributes()[attrname] + + print " rspec:" + print " ", self.get_rspec() + + if self.parent and dump_parents: + print "PARENT", + self.parent.dump(dump_parents) diff --git a/core/lib/am/credentials/src/trust/trustedroots.py b/core/lib/am/credentials/src/trust/trustedroots.py new file mode 100644 index 00000000..976f2e8e --- /dev/null +++ b/core/lib/am/credentials/src/trust/trustedroots.py @@ -0,0 +1,43 @@ +import os.path +import glob + +from credentials.src.trust.gid import GID + + +class TrustedRoots: + + # we want to avoid reading all files in the directory + # this is because it's common to have backups of all kinds + # e.g. *~, *.hide, *-00, *.bak and the like + supported_extensions= [ 'gid', 'cert', 'pem' ] + + def __init__(self, dir): + self.basedir = dir + # create the directory to hold the files, if not existing + if not os.path.isdir (self.basedir): + os.makedirs(self.basedir) + + def add_gid(self, gid): + fn = os.path.join(self.basedir, gid.get_hrn() + ".gid") + gid.save_to_file(fn) + + def get_list(self): + gid_list = [GID(filename=cert_file) for cert_file in self.get_file_list()] + return gid_list + + def get_file_list(self): + file_list = [] + pattern=os.path.join(self.basedir,"*") + for cert_file in glob.glob(pattern): + if os.path.isfile(cert_file): + if self.has_supported_extension(cert_file): + file_list.append(cert_file) + else: + print "File %s ignored - supported extensions are %r"%\ + (cert_file,TrustedRoots.supported_extensions) + return file_list + + def has_supported_extension (self,path): + (_,ext)=os.path.splitext(path) + ext=ext.replace('.','').lower() + return ext in TrustedRoots.supported_extensions diff --git a/core/lib/am/credentials/src/trustgcf/__init__.py b/core/lib/am/credentials/src/trustgcf/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/credentials/src/trustgcf/abac_credential.py b/core/lib/am/credentials/src/trustgcf/abac_credential.py new file mode 100644 index 00000000..0f96bca3 --- /dev/null +++ b/core/lib/am/credentials/src/trustgcf/abac_credential.py @@ -0,0 +1,282 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2014 Raytheon BBN Technologies +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- + +from __future__ import absolute_import + +from credentials.src.trustgcf.credential import Credential, append_sub +from StringIO import StringIO +from xml.dom.minidom import Document, parseString +import datetime +from dateutil import tz + +HAVELXML = False +try: + from lxml import etree + HAVELXML = True +except: + pass + +# This module defines a subtype of sfa.trust,credential.Credential +# called an ABACCredential. An ABAC credential is a signed statement +# asserting a role representing the relationship between a subject and target +# or between a subject and a class of targets (all those satisfying a role). +# +# An ABAC credential is like a normal SFA credential in that it has +# a validated signature block and is checked for expiration. +# It does not, however, have 'privileges'. Rather it contains a 'head' and +# list of 'tails' of elements, each of which represents a principal and +# role. + +# A special case of an ABAC credential is a speaks_for credential. Such +# a credential is simply an ABAC credential in form, but has a single +# tail and fixed role 'speaks_for'. In ABAC notation, it asserts +# AGENT.speaks_for(AGENT)<-CLIENT, or "AGENT asserts that CLIENT may speak +# for AGENT". The AGENT in this case is the head and the CLIENT is the +# tail and 'speaks_for_AGENT' is the role on the head. These speaks-for +# Credentials are used to allow a tool to 'speak as' itself but be recognized +# as speaking for an individual and be authorized to the rights of that +# individual and not to the rights of the tool itself. + +# For more detail on the semantics and syntax and expected usage patterns +# of ABAC credentials, see http://groups.geni.net/geni/wiki/TIEDABACCredential. + + +# An ABAC element contains a principal (keyid and optional mnemonic) +# and optional role and linking_role element + +DEFAULT_CREDENTIAL_LIFETIME = 3600 +class ABACElement: + def __init__(self, principal_keyid, principal_mnemonic=None, \ + role=None, linking_role=None): + self._principal_keyid = principal_keyid + self._principal_mnemonic = principal_mnemonic + self._role = role + self._linking_role = linking_role + + def get_principal_keyid(self): return self._principal_keyid + def get_principal_mnemonic(self): return self._principal_mnemonic + def get_role(self): return self._role + def get_linking_role(self): return self._linking_role + + def __str__(self): + ret = self._principal_keyid + if self._principal_mnemonic: + ret = "%s (%s)" % (self._principal_mnemonic, self._principal_keyid) + if self._linking_role: + ret += ".%s" % self._linking_role + if self._role: + ret += ".%s" % self._role + return ret + +# Subclass of Credential for handling ABAC credentials +# They have a different cred_type (geni_abac vs. geni_sfa) +# and they have a head and tail and role (as opposed to privileges) +class ABACCredential(Credential): + + ABAC_CREDENTIAL_TYPE = 'geni_abac' + + def __init__(self, create=False, subject=None, + string=None, filename=None): + self.head = None # An ABACElemenet + self.tails = [] # List of ABACElements + super(ABACCredential, self).__init__(create=create, + subject=subject, + string=string, + filename=filename) + self.cred_type = ABACCredential.ABAC_CREDENTIAL_TYPE + + def get_head(self) : + if not self.head: + self.decode() + return self.head + + def get_tails(self) : + if len(self.tails) == 0: + self.decode() + return self.tails + + def decode(self): + super(ABACCredential, self).decode() + # Pull out the ABAC-specific info + doc = parseString(self.xml) + rt0s = doc.getElementsByTagName('rt0') + if len(rt0s) != 1: + raise Exception("ABAC credential had no rt0 element") + rt0_root = rt0s[0] + heads = self._get_abac_elements(rt0_root, 'head') + if len(heads) != 1: + raise Exception("ABAC credential should have exactly 1 head element, had %d" % len(heads)) + + self.head = heads[0] + self.tails = self._get_abac_elements(rt0_root, 'tail') + + def _get_abac_elements(self, root, label): + abac_elements = [] + elements = root.getElementsByTagName(label) + for elt in elements: + keyids = elt.getElementsByTagName('keyid') + if len(keyids) != 1: + raise Exception("ABAC credential element '%s' should have exactly 1 keyid, had %d." % (label, len(keyids))) + keyid_elt = keyids[0] + keyid = keyid_elt.childNodes[0].nodeValue.strip() + + mnemonic = None + mnemonic_elts = elt.getElementsByTagName('mnemonic') + if len(mnemonic_elts) > 0: + mnemonic = mnemonic_elts[0].childNodes[0].nodeValue.strip() + + role = None + role_elts = elt.getElementsByTagName('role') + if len(role_elts) > 0: + role = role_elts[0].childNodes[0].nodeValue.strip() + + linking_role = None + linking_role_elts = elt.getElementsByTagName('linking_role') + if len(linking_role_elts) > 0: + linking_role = linking_role_elts[0].childNodes[0].nodeValue.strip() + + abac_element = ABACElement(keyid, mnemonic, role, linking_role) + abac_elements.append(abac_element) + + return abac_elements + + def dump_string(self, dump_parents=False, show_xml=False): + result = "ABAC Credential\n" + filename=self.get_filename() + if filename: result += "Filename %s\n"%filename + if self.expiration: + result += "\texpiration: %s \n" % self.expiration.isoformat() + + result += "\tHead: %s\n" % self.get_head() + for tail in self.get_tails(): + result += "\tTail: %s\n" % tail + if self.get_signature(): + result += " gidIssuer:\n" + result += self.get_signature().get_issuer_gid().dump_string(8, dump_parents) + if show_xml and HAVELXML: + try: + tree = etree.parse(StringIO(self.xml)) + aside = etree.tostring(tree, pretty_print=True) + result += "\nXML:\n\n" + result += aside + result += "\nEnd XML\n" + except: + import traceback + print "exc. Credential.dump_string / XML" + traceback.print_exc() + return result + + # sounds like this should be __repr__ instead ?? + # Produce the ABAC assertion. Something like [ABAC cred: Me.role<-You] or similar + def get_summary_tostring(self): + result = "[ABAC cred: " + str(self.get_head()) + for tail in self.get_tails(): + result += "<-%s" % str(tail) + result += "]" + return result + + def createABACElement(self, doc, tagName, abacObj): + kid = abacObj.get_principal_keyid() + mnem = abacObj.get_principal_mnemonic() # may be None + role = abacObj.get_role() # may be None + link = abacObj.get_linking_role() # may be None + ele = doc.createElement(tagName) + prin = doc.createElement('ABACprincipal') + ele.appendChild(prin) + append_sub(doc, prin, "keyid", kid) + if mnem: + append_sub(doc, prin, "mnemonic", mnem) + if role: + append_sub(doc, ele, "role", role) + if link: + append_sub(doc, ele, "linking_role", link) + return ele + + ## + # Encode the attributes of the credential into an XML string + # This should be done immediately before signing the credential. + # WARNING: + # In general, a signed credential obtained externally should + # not be changed else the signature is no longer valid. So, once + # you have loaded an existing signed credential, do not call encode() or sign() on it. + + def encode(self): + # Create the XML document + doc = Document() + signed_cred = doc.createElement("signed-credential") + +# Declare namespaces +# Note that credential/policy.xsd are really the PG schemas +# in a PL namespace. +# Note that delegation of credentials between the 2 only really works +# cause those schemas are identical. +# Also note these PG schemas talk about PG tickets and CM policies. + signed_cred.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") + signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.geni.net/resources/credential/2/credential.xsd") + signed_cred.setAttribute("xsi:schemaLocation", "http://www.planet-lab.org/resources/sfa/ext/policy/1 http://www.planet-lab.org/resources/sfa/ext/policy/1/policy.xsd") + +# PG says for those last 2: +# signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.protogeni.net/resources/credential/credential.xsd") +# signed_cred.setAttribute("xsi:schemaLocation", "http://www.protogeni.net/resources/credential/ext/policy/1 http://www.protogeni.net/resources/credential/ext/policy/1/policy.xsd") + + doc.appendChild(signed_cred) + + # Fill in the bit + cred = doc.createElement("credential") + cred.setAttribute("xml:id", self.get_refid()) + signed_cred.appendChild(cred) + append_sub(doc, cred, "type", "abac") + + # Stub fields + append_sub(doc, cred, "serial", "8") + append_sub(doc, cred, "owner_gid", '') + append_sub(doc, cred, "owner_urn", '') + append_sub(doc, cred, "target_gid", '') + append_sub(doc, cred, "target_urn", '') + append_sub(doc, cred, "uuid", "") + + if not self.expiration: + self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) + self.expiration = self.expiration.replace(microsecond=0) + if self.expiration.tzinfo is not None and self.expiration.tzinfo.utcoffset(self.expiration) is not None: + # TZ aware. Make sure it is UTC + self.expiration = self.expiration.astimezone(tz.tzutc()) + append_sub(doc, cred, "expires", self.expiration.strftime('%Y-%m-%dT%H:%M:%SZ')) # RFC3339 + + abac = doc.createElement("abac") + rt0 = doc.createElement("rt0") + abac.appendChild(rt0) + cred.appendChild(abac) + append_sub(doc, rt0, "version", "1.1") + head = self.createABACElement(doc, "head", self.get_head()) + rt0.appendChild(head) + for tail in self.get_tails(): + tailEle = self.createABACElement(doc, "tail", tail) + rt0.appendChild(tailEle) + + # Create the tag + signatures = doc.createElement("signatures") + signed_cred.appendChild(signatures) + + # Get the finished product + self.xml = doc.toxml("utf-8") diff --git a/core/lib/am/credentials/src/trustgcf/cert_util.py b/core/lib/am/credentials/src/trustgcf/cert_util.py new file mode 100644 index 00000000..3ca11263 --- /dev/null +++ b/core/lib/am/credentials/src/trustgcf/cert_util.py @@ -0,0 +1,111 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2011-2014 Raytheon BBN Technologies +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- +''' +Certificate (GID in SFA terms) creation and verification utilities. +''' + +import uuid + +from geniutils.src.urn.utils import URN +from credentials.src.trustgcf.gid import GID +from credentials.src.trustgcf.certificate import Keypair + +def create_cert(urn, issuer_key=None, issuer_cert=None, ca=False, + public_key=None, lifeDays=1825, email=None, uuidarg=None): + '''Create a new certificate and return it and the associated keys. + If issuer cert and key are given, they sign the certificate. Otherwise + it is a self-signed certificate. + + If ca then mark this as a CA certificate (can sign other certs). + + lifeDays is the lifetime of the supplied cert - default is 1825 (5 years). + + Certificate URN must be supplied. + CN of the cert will be dotted notation authority.type.name from the URN. + ''' + # Note the below throws a ValueError if it wasnt a valid URN + c_urn = URN(urn=urn) + dotted = '%s.%s.%s' % (c_urn.getAuthority(), c_urn.getType(), c_urn.getName()) + + subject = dict() + subject['CN'] = dotted[:64] + if email: + subject['emailAddress'] = email + + uuidI = None + if uuidarg: + uuidO = None + if isinstance(uuidarg, uuid.UUID): + uuidO = uuidarg + else: + try: + uuidO = uuid.UUID(uuidarg) + except: + try: + uuidO = uuid.UUID(int=uuidarg) + except Exception, e: + try: + uuidO = uuid.UUID(int=int(uuidarg)) + except Exception, e: + try: + uuidO = uuid.UUID(fields=uuidarg) + except: + try: + uuidO = uuid.UUID(bytes=uuidarg) + except: + try: + uuidO = uuid.UUID(bytes_le=uuidarg) + except: + pass + if uuidO is not None: + uuidI = uuidO.int + + newgid = GID(create=True, subject=subject, uuid=uuidI, urn=urn, lifeDays=lifeDays) + if email: + newgid.set_email(email) + + if public_key is None: + # create a new key pair + keys = Keypair(create=True) + else: + # use the specified public key file + keys = Keypair() + keys.load_pubkey_from_file(public_key) + newgid.set_pubkey(keys) + newgid.set_is_ca(ca) + + if issuer_key and issuer_cert: + # the given issuer will issue this cert + if isinstance(issuer_key,str): + issuer_key = Keypair(filename=issuer_key) + if isinstance(issuer_cert,str): + issuer_cert = GID(filename=issuer_cert) + newgid.set_issuer(issuer_key, cert=issuer_cert) + newgid.set_parent(issuer_cert) + else: + # create a self-signed cert + newgid.set_issuer(keys, subject=dotted) + + newgid.encode() + newgid.sign() + return newgid, keys diff --git a/core/lib/am/credentials/src/trustgcf/certificate.py b/core/lib/am/credentials/src/trustgcf/certificate.py new file mode 100644 index 00000000..5aa091f1 --- /dev/null +++ b/core/lib/am/credentials/src/trustgcf/certificate.py @@ -0,0 +1,794 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- + +## +# SFA uses two crypto libraries: pyOpenSSL and M2Crypto to implement +# the necessary crypto functionality. Ideally just one of these libraries +# would be used, but unfortunately each of these libraries is independently +# lacking. The pyOpenSSL library is missing many necessary functions, and +# the M2Crypto library has crashed inside of some of the functions. The +# design decision is to use pyOpenSSL whenever possible as it seems more +# stable, and only use M2Crypto for those functions that are not possible +# in pyOpenSSL. +# +# This module exports two classes: Keypair and Certificate. +## +# + +from __future__ import absolute_import + +import functools +import os +import tempfile +import base64 +from tempfile import mkstemp + +from OpenSSL import crypto +import M2Crypto +from M2Crypto import X509 + +from geniutils.src.faults.faults import CertExpired, CertMissingParent, CertNotSignedByParent + +glo_passphrase_callback = None + +## +# A global callback may be implemented for requesting passphrases from the +# user. The function will be called with three arguments: +# +# keypair_obj: the keypair object that is calling the passphrase +# string: the string containing the private key that's being loaded +# x: unknown, appears to be 0, comes from pyOpenSSL and/or m2crypto +# +# The callback should return a string containing the passphrase. + +def set_passphrase_callback(callback_func): + global glo_passphrase_callback + + glo_passphrase_callback = callback_func + +## +# Sets a fixed passphrase. + +def set_passphrase(passphrase): + set_passphrase_callback( lambda k,s,x: passphrase ) + +## +# Check to see if a passphrase works for a particular private key string. +# Intended to be used by passphrase callbacks for input validation. + +def test_passphrase(string, passphrase): + try: + crypto.load_privatekey(crypto.FILETYPE_PEM, string, (lambda x: passphrase)) + return True + except: + return False + +def convert_public_key(key): + keyconvert_path = "/usr/bin/keyconvert.py" + if not os.path.isfile(keyconvert_path): + raise IOError, "Could not find keyconvert in %s" % keyconvert_path + + # we can only convert rsa keys + if "ssh-dss" in key: + raise Exception, "keyconvert: dss keys are not supported" + + (ssh_f, ssh_fn) = tempfile.mkstemp() + ssl_fn = tempfile.mktemp() + os.write(ssh_f, key) + os.close(ssh_f) + + cmd = keyconvert_path + " " + ssh_fn + " " + ssl_fn + os.system(cmd) + + # this check leaves the temporary file containing the public key so + # that it can be expected to see why it failed. + # TODO: for production, cleanup the temporary files + if not os.path.exists(ssl_fn): + raise Exception, "keyconvert: generated certificate not found. keyconvert may have failed." + + k = Keypair() + try: + k.load_pubkey_from_file(ssl_fn) + return k + except: + raise + finally: + # remove the temporary files + if os.path.exists(ssh_fn): + os.remove(ssh_fn) + if os.path.exists(ssl_fn): + os.remove(ssl_fn) + +## +# Public-private key pairs are implemented by the Keypair class. +# A Keypair object may represent both a public and private key pair, or it +# may represent only a public key (this usage is consistent with OpenSSL). + +class Keypair: + key = None # public/private keypair + m2key = None # public key (m2crypto format) + + ## + # Creates a Keypair object + # @param create If create==True, creates a new public/private key and + # stores it in the object + # @param string If string!=None, load the keypair from the string (PEM) + # @param filename If filename!=None, load the keypair from the file + + def __init__(self, create=False, string=None, filename=None): + if create: + self.create() + if string: + self.load_from_string(string) + if filename: + self.load_from_file(filename) + + ## + # Create a RSA public/private key pair and store it inside the keypair object + + def create(self): + self.key = crypto.PKey() + self.key.generate_key(crypto.TYPE_RSA, 1024) + + ## + # Save the private key to a file + # @param filename name of file to store the keypair in + + def save_to_file(self, filename): + open(filename, 'w').write(self.as_pem()) + self.filename=filename + + ## + # Load the private key from a file. Implicity the private key includes the public key. + + def load_from_file(self, filename): + self.filename=filename + buffer = open(filename, 'r').read() + self.load_from_string(buffer) + + ## + # Load the private key from a string. Implicitly the private key includes the public key. + + def load_from_string(self, string): + if glo_passphrase_callback: + self.key = crypto.load_privatekey(crypto.FILETYPE_PEM, string, functools.partial(glo_passphrase_callback, self, string) ) + self.m2key = M2Crypto.EVP.load_key_string(string, functools.partial(glo_passphrase_callback, self, string) ) + else: + self.key = crypto.load_privatekey(crypto.FILETYPE_PEM, string) + self.m2key = M2Crypto.EVP.load_key_string(string) + + ## + # Load the public key from a string. No private key is loaded. + + def load_pubkey_from_file(self, filename): + # load the m2 public key + m2rsakey = M2Crypto.RSA.load_pub_key(filename) + self.m2key = M2Crypto.EVP.PKey() + self.m2key.assign_rsa(m2rsakey) + + # create an m2 x509 cert + m2name = M2Crypto.X509.X509_Name() + m2name.add_entry_by_txt(field="CN", type=0x1001, entry="junk", len=-1, loc=-1, set=0) + m2x509 = M2Crypto.X509.X509() + m2x509.set_pubkey(self.m2key) + m2x509.set_serial_number(0) + m2x509.set_issuer_name(m2name) + m2x509.set_subject_name(m2name) + ASN1 = M2Crypto.ASN1.ASN1_UTCTIME() + ASN1.set_time(500) + m2x509.set_not_before(ASN1) + m2x509.set_not_after(ASN1) + # x509v3 so it can have extensions + # prob not necc since this cert itself is junk but still... + m2x509.set_version(2) + junk_key = Keypair(create=True) + m2x509.sign(pkey=junk_key.get_m2_pkey(), md="sha1") + + # convert the m2 x509 cert to a pyopenssl x509 + m2pem = m2x509.as_pem() + pyx509 = crypto.load_certificate(crypto.FILETYPE_PEM, m2pem) + + # get the pyopenssl pkey from the pyopenssl x509 + self.key = pyx509.get_pubkey() + self.filename=filename + + ## + # Load the public key from a string. No private key is loaded. + + def load_pubkey_from_string(self, string): + (f, fn) = tempfile.mkstemp() + os.write(f, string) + os.close(f) + self.load_pubkey_from_file(fn) + os.remove(fn) + + ## + # Return the private key in PEM format. + + def as_pem(self): + return crypto.dump_privatekey(crypto.FILETYPE_PEM, self.key) + + ## + # Return an M2Crypto key object + + def get_m2_pkey(self): + if not self.m2key: + self.m2key = M2Crypto.EVP.load_key_string(self.as_pem()) + return self.m2key + + ## + # Returns a string containing the public key represented by this object. + + def get_pubkey_string(self): + m2pkey = self.get_m2_pkey() + return base64.b64encode(m2pkey.as_der()) + + ## + # Return an OpenSSL pkey object + + def get_openssl_pkey(self): + return self.key + + ## + # Given another Keypair object, return TRUE if the two keys are the same. + + def is_same(self, pkey): + return self.as_pem() == pkey.as_pem() + + def sign_string(self, data): + k = self.get_m2_pkey() + k.sign_init() + k.sign_update(data) + return base64.b64encode(k.sign_final()) + + def verify_string(self, data, sig): + k = self.get_m2_pkey() + k.verify_init() + k.verify_update(data) + return M2Crypto.m2.verify_final(k.ctx, base64.b64decode(sig), k.pkey) + + def compute_hash(self, value): + return self.sign_string(str(value)) + + # only informative + def get_filename(self): + return getattr(self,'filename',None) + + def dump (self, *args, **kwargs): + print self.dump_string(*args, **kwargs) + + def dump_string (self): + result="" + result += "KEYPAIR: pubkey=%40s..."%self.get_pubkey_string() + filename=self.get_filename() + if filename: result += "Filename %s\n"%filename + return result + +## +# The certificate class implements a general purpose X509 certificate, making +# use of the appropriate pyOpenSSL or M2Crypto abstractions. It also adds +# several addition features, such as the ability to maintain a chain of +# parent certificates, and storage of application-specific data. +# +# Certificates include the ability to maintain a chain of parents. Each +# certificate includes a pointer to it's parent certificate. When loaded +# from a file or a string, the parent chain will be automatically loaded. +# When saving a certificate to a file or a string, the caller can choose +# whether to save the parent certificates as well. + +class Certificate: + digest = "md5" + + cert = None + issuerKey = None + issuerSubject = None + parent = None + isCA = None # will be a boolean once set + + separator="-----parent-----" + + ## + # Create a certificate object. + # + # @param lifeDays life of cert in days - default is 1825==5 years + # @param create If create==True, then also create a blank X509 certificate. + # @param subject If subject!=None, then create a blank certificate and set + # it's subject name. + # @param string If string!=None, load the certficate from the string. + # @param filename If filename!=None, load the certficiate from the file. + # @param isCA If !=None, set whether this cert is for a CA + + def __init__(self, lifeDays=1825, create=False, subject=None, string=None, filename=None, isCA=None): + self.data = {} + if create or subject: + self.create(lifeDays) + if subject: + self.set_subject(subject) + if string: + self.load_from_string(string) + if filename: + self.load_from_file(filename) + + # Set the CA bit if a value was supplied + if isCA != None: + self.set_is_ca(isCA) + + # Create a blank X509 certificate and store it in this object. + + def create(self, lifeDays=1825): + self.cert = crypto.X509() + # FIXME: Use different serial #s + self.cert.set_serial_number(3) + self.cert.gmtime_adj_notBefore(0) # 0 means now + self.cert.gmtime_adj_notAfter(lifeDays*60*60*24) # five years is default + self.cert.set_version(2) # x509v3 so it can have extensions + + + ## + # Given a pyOpenSSL X509 object, store that object inside of this + # certificate object. + + def load_from_pyopenssl_x509(self, x509): + self.cert = x509 + + ## + # Load the certificate from a string + + def load_from_string(self, string): + # if it is a chain of multiple certs, then split off the first one and + # load it (support for the ---parent--- tag as well as normal chained certs) + + if string is None or string.strip() == "": + return + + string = string.strip() + + # If it's not in proper PEM format, wrap it + if string.count('-----BEGIN CERTIFICATE') == 0: + string = '-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----' % string + + # If there is a PEM cert in there, but there is some other text first + # such as the text of the certificate, skip the text + beg = string.find('-----BEGIN CERTIFICATE') + if beg > 0: + # skipping over non cert beginning + string = string[beg:] + + parts = [] + + if string.count('-----BEGIN CERTIFICATE-----') > 1 and \ + string.count(Certificate.separator) == 0: + parts = string.split('-----END CERTIFICATE-----',1) + parts[0] += '-----END CERTIFICATE-----' + else: + parts = string.split(Certificate.separator, 1) + + self.cert = crypto.load_certificate(crypto.FILETYPE_PEM, parts[0]) + + if self.cert is None: + msg = "Loaded from string but cert is None: %s" % string + + # if there are more certs, then create a parent and let the parent load + # itself from the remainder of the string + if len(parts) > 1 and parts[1] != '': + self.parent = self.__class__() + self.parent.load_from_string(parts[1]) + + ## + # Load the certificate from a file + + def load_from_file(self, filename): + file = open(filename) + string = file.read() + self.load_from_string(string) + self.filename=filename + + ## + # Save the certificate to a string. + # + # @param save_parents If save_parents==True, then also save the parent certificates. + + def save_to_string(self, save_parents=True): + if self.cert is None: + msg = "None cert in certificate.save_to_string" + return "" + string = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cert) + if save_parents and self.parent: + string = string + self.parent.save_to_string(save_parents) + return string + + ## + # Save the certificate to a file. + # @param save_parents If save_parents==True, then also save the parent certificates. + + def save_to_file(self, filename, save_parents=True, filep=None): + string = self.save_to_string(save_parents=save_parents) + if filep: + f = filep + else: + f = open(filename, 'w') + f.write(string) + f.close() + self.filename=filename + + ## + # Save the certificate to a random file in /tmp/ + # @param save_parents If save_parents==True, then also save the parent certificates. + def save_to_random_tmp_file(self, save_parents=True): + fp, filename = mkstemp(suffix='cert', text=True) + fp = os.fdopen(fp, "w") + self.save_to_file(filename, save_parents=True, filep=fp) + return filename + + ## + # Sets the issuer private key and name + # @param key Keypair object containing the private key of the issuer + # @param subject String containing the name of the issuer + # @param cert (optional) Certificate object containing the name of the issuer + + def set_issuer(self, key, subject=None, cert=None): + self.issuerKey = key + if subject: + # it's a mistake to use subject and cert params at the same time + assert(not cert) + if isinstance(subject, dict) or isinstance(subject, str): + req = crypto.X509Req() + reqSubject = req.get_subject() + if (isinstance(subject, dict)): + for key in reqSubject.keys(): + setattr(reqSubject, key, subject[key]) + else: + setattr(reqSubject, "CN", subject) + subject = reqSubject + # subject is not valid once req is out of scope, so save req + self.issuerReq = req + if cert: + # if a cert was supplied, then get the subject from the cert + subject = cert.cert.get_subject() + assert(subject) + self.issuerSubject = subject + + ## + # Get the issuer name + + def get_issuer(self, which="CN"): + x = self.cert.get_issuer() + return getattr(x, which) + + ## + # Set the subject name of the certificate + + def set_subject(self, name): + req = crypto.X509Req() + subj = req.get_subject() + if (isinstance(name, dict)): + for key in name.keys(): + setattr(subj, key, name[key]) + else: + setattr(subj, "CN", name) + self.cert.set_subject(subj) + + ## + # Get the subject name of the certificate + + def get_subject(self, which="CN"): + x = self.cert.get_subject() + return getattr(x, which) + + ## + # Get a pretty-print subject name of the certificate + + def get_printable_subject(self): + x = self.cert.get_subject() + return "[ OU: %s, CN: %s, SubjectAltName: %s ]" % (getattr(x, "OU"), getattr(x, "CN"), self.get_data()) + + ## + # Get the public key of the certificate. + # + # @param key Keypair object containing the public key + + def set_pubkey(self, key): + assert(isinstance(key, Keypair)) + self.cert.set_pubkey(key.get_openssl_pkey()) + + ## + # Get the public key of the certificate. + # It is returned in the form of a Keypair object. + + def get_pubkey(self): + m2x509 = X509.load_cert_string(self.save_to_string()) + pkey = Keypair() + pkey.key = self.cert.get_pubkey() + pkey.m2key = m2x509.get_pubkey() + return pkey + + def set_intermediate_ca(self, val): + return self.set_is_ca(val) + + # Set whether this cert is for a CA. All signers and only signers should be CAs. + # The local member starts unset, letting us check that you only set it once + # @param val Boolean indicating whether this cert is for a CA + def set_is_ca(self, val): + if val is None: + return + + if self.isCA != None: + # Can't double set properties + raise Exception, "Cannot set basicConstraints CA:?? more than once. Was %s, trying to set as %s" % (self.isCA, val) + + self.isCA = val + if val: + self.add_extension('basicConstraints', 1, 'CA:TRUE') + else: + self.add_extension('basicConstraints', 1, 'CA:FALSE') + + + + ## + # Add an X509 extension to the certificate. Add_extension can only be called + # once for a particular extension name, due to limitations in the underlying + # library. + # + # @param name string containing name of extension + # @param value string containing value of the extension + + def add_extension(self, name, critical, value): + oldExtVal = None + try: + oldExtVal = self.get_extension(name) + except: + # M2Crypto LookupError when the extension isn't there (yet) + pass + + # This code limits you from adding the extension with the same value + # The method comment says you shouldn't do this with the same name + # But actually it (m2crypto) appears to allow you to do this. + if oldExtVal and oldExtVal == value: + # don't add this extension again + # just do nothing as here + return + # FIXME: What if they are trying to set with a different value? + # Is this ever OK? Or should we raise an exception? +# elif oldExtVal: +# raise "Cannot add extension %s which had val %s with new val %s" % (name, oldExtVal, value) + + ext = crypto.X509Extension (name, critical, value) + self.cert.add_extensions([ext]) + + ## + # Get an X509 extension from the certificate + + def get_extension(self, name): + + if name is None: + return None + + certstr = self.save_to_string() + if certstr is None or certstr == "": + return None + # pyOpenSSL does not have a way to get extensions + m2x509 = X509.load_cert_string(certstr) + if m2x509 is None: + msg = "No cert loaded in get_extension" + return None + if m2x509.get_ext(name) is None: + return None + value = m2x509.get_ext(name).get_value() + + return value + + ## + # Set_data is a wrapper around add_extension. It stores the parameter str in + # the X509 subject_alt_name extension. Set_data can only be called once, due + # to limitations in the underlying library. + + def set_data(self, str, field='subjectAltName'): + # pyOpenSSL only allows us to add extensions, so if we try to set the + # same extension more than once, it will not work + if self.data.has_key(field): + raise "Cannot set ", field, " more than once" + self.data[field] = str + self.add_extension(field, 0, str) + + ## + # Return the data string that was previously set with set_data + + def get_data(self, field='subjectAltName'): + if self.data.has_key(field): + return self.data[field] + + try: + uri = self.get_extension(field) + self.data[field] = uri + except LookupError: + return None + + return self.data[field] + + ## + # Sign the certificate using the issuer private key and issuer subject previous set with set_issuer(). + + def sign(self): + + assert self.cert != None + assert self.issuerSubject != None + assert self.issuerKey != None + self.cert.set_issuer(self.issuerSubject) + self.cert.sign(self.issuerKey.get_openssl_pkey(), self.digest) + + ## + # Verify the authenticity of a certificate. + # @param pkey is a Keypair object representing a public key. If Pkey + # did not sign the certificate, then an exception will be thrown. + + def verify(self, pkey): + # pyOpenSSL does not have a way to verify signatures + m2x509 = X509.load_cert_string(self.save_to_string()) + m2pkey = pkey.get_m2_pkey() + # verify it + return m2x509.verify(m2pkey) + + # XXX alternatively, if openssl has been patched, do the much simpler: + # try: + # self.cert.verify(pkey.get_openssl_key()) + # return 1 + # except: + # return 0 + + ## + # Return True if pkey is identical to the public key that is contained in the certificate. + # @param pkey Keypair object + + def is_pubkey(self, pkey): + return self.get_pubkey().is_same(pkey) + + ## + # Given a certificate cert, verify that this certificate was signed by the + # public key contained in cert. Throw an exception otherwise. + # + # @param cert certificate object + + def is_signed_by_cert(self, cert): + k = cert.get_pubkey() + result = self.verify(k) + return result + + ## + # Set the parent certficiate. + # + # @param p certificate object. + + def set_parent(self, p): + self.parent = p + + ## + # Return the certificate object of the parent of this certificate. + + def get_parent(self): + return self.parent + + ## + # Verification examines a chain of certificates to ensure that each parent + # signs the child, and that some certificate in the chain is signed by a + # trusted certificate. + # + # Verification is a basic recursion:
+    #     if this_certificate was signed by trusted_certs:
+    #         return
+    #     else
+    #         return verify_chain(parent, trusted_certs)
+    # 
+ # + # At each recursion, the parent is tested to ensure that it did sign the + # child. If a parent did not sign a child, then an exception is thrown. If + # the bottom of the recursion is reached and the certificate does not match + # a trusted root, then an exception is thrown. + # Also require that parents are CAs. + # + # @param Trusted_certs is a list of certificates that are trusted. + # + + def verify_chain(self, trusted_certs = None): + # Verify a chain of certificates. Each certificate must be signed by + # the public key contained in it's parent. The chain is recursed + # until a certificate is found that is signed by a trusted root. + + # verify expiration time + if self.cert.has_expired(): + raise CertExpired(self.get_printable_subject(), "client cert") + + # if this cert is signed by a trusted_cert, then we are set + for trusted_cert in trusted_certs: + if self.is_signed_by_cert(trusted_cert): + # verify expiration of trusted_cert ? + if not trusted_cert.cert.has_expired(): + return trusted_cert + else: + raise CertExpired(self.get_printable_subject()," signer trusted_cert %s"%trusted_cert.get_printable_subject()) + + # if there is no parent, then no way to verify the chain + if not self.parent: + raise CertMissingParent(self.get_printable_subject() + ": Issuer %s is not one of the %d trusted roots, and cert has no parent." % (self.get_issuer(), len(trusted_certs))) + + # if it wasn't signed by the parent... + if not self.is_signed_by_cert(self.parent): + raise CertNotSignedByParent("%s: Parent %s, issuer %s"\ + % (self.get_printable_subject(), + self.parent.get_printable_subject(), + self.get_issuer())) + + # Confirm that the parent is a CA. Only CAs can be trusted as + # signers. + # Note that trusted roots are not parents, so don't need to be + # CAs. + # Ugly - cert objects aren't parsed so we need to read the + # extension and hope there are no other basicConstraints + if not self.parent.isCA and not (self.parent.get_extension('basicConstraints') == 'CA:TRUE'): + raise CertNotSignedByParent("%s: Parent %s not a CA" % (self.get_printable_subject(), + self.parent.get_printable_subject())) + + # if the parent isn't verified... + return + + ### more introspection + def get_extensions(self): + # pyOpenSSL does not have a way to get extensions + triples=[] + m2x509 = X509.load_cert_string(self.save_to_string()) + nb_extensions=m2x509.get_ext_count() + for i in range(nb_extensions): + ext=m2x509.get_ext_at(i) + triples.append( (ext.get_name(), ext.get_value(), ext.get_critical(),) ) + return triples + + def get_data_names(self): + return self.data.keys() + + def get_all_datas (self): + triples=self.get_extensions() + for name in self.get_data_names(): + triples.append( (name,self.get_data(name),'data',) ) + return triples + + # only informative + def get_filename(self): + return getattr(self,'filename',None) + + def dump (self, *args, **kwargs): + print self.dump_string(*args, **kwargs) + + def dump_string (self,show_extensions=False): + result = "" + result += "CERTIFICATE for %s\n"%self.get_printable_subject() + result += "Issued by %s\n"%self.get_issuer() + filename=self.get_filename() + if filename: result += "Filename %s\n"%filename + if show_extensions: + all_datas=self.get_all_datas() + result += " has %d extensions/data attached"%len(all_datas) + for (n,v,c) in all_datas: + if c=='data': + result += " data: %s=%s\n"%(n,v) + else: + result += " ext: %s (crit=%s)=<<<%s>>>\n"%(n,c,v) + return result diff --git a/core/lib/am/credentials/src/trustgcf/cred_util.py b/core/lib/am/credentials/src/trustgcf/cred_util.py new file mode 100644 index 00000000..ce71dcc8 --- /dev/null +++ b/core/lib/am/credentials/src/trustgcf/cred_util.py @@ -0,0 +1,367 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2010-2014 Raytheon BBN Technologies +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- +from geniutils.src.xrn.xrn import hrn_authfor_hrn +''' +Credential creation and verification utilities. +''' +import os +import logging +import xmlrpclib +import sys +import datetime +import dateutil + +from credentials.src.trustgcf import credential as cred +from credentials.src.trustgcf import gid +from credentials.src.trustgcf import rights + +from credentials.src.trustgcf.credential_factory import CredentialFactory +from credentials.src.trustgcf.abac_credential import ABACCredential +from credentials.src.trustgcf.certificate import Certificate + +from credentials.src.trustgcf.speaksfor_util import determine_speaks_for + +def naiveUTC(dt): + """Converts dt to a naive datetime in UTC. + + if 'dt' has a timezone then + convert to UTC + strip off timezone (make it "naive" in Python parlance) + """ + if dt.tzinfo: + tz_utc = dateutil.tz.tzutc() + dt = dt.astimezone(tz_utc) + dt = dt.replace(tzinfo=None) + return dt + +class CredentialVerifier(object): + """Utilities to verify signed credentials from a given set of + root certificates. Will compare target and source URNs, and privileges. + See verify and verify_from_strings methods in particular.""" + + CATEDCERTSFNAME = 'CATedCACerts.pem' + + # root_cert_fileordir is a trusted root cert file or directory of + # trusted roots for verifying credentials + def __init__(self, root_cert_fileordir): + if root_cert_fileordir is None: + raise Exception("Missing Root certs argument") + elif os.path.isdir(root_cert_fileordir): + files = os.listdir(root_cert_fileordir) + self.root_cert_files = [] + for file in files: + # FIXME: exclude files that aren't cert files? + #print file == CredentialVerifier.CATEDCERTSFNAME + if file == CredentialVerifier.CATEDCERTSFNAME: + continue + self.root_cert_files.append(os.path.expanduser(os.path.join(root_cert_fileordir, file))) + + #self.root_cert_files = [root_cert_fileordir] + else: + raise Exception("Couldn't find Root certs in %s" % root_cert_fileordir) + + + @classmethod + def getCAsFileFromDir(cls, caCerts): + '''Take a directory of CA certificates and concatenate them into a single + file suitable for use by the Python SSL library to validate client + credentials. Existing file is replaced.''' + if caCerts is None: + raise Exception ('Missing caCerts argument') + if os.path.isfile(os.path.expanduser(caCerts)): + return caCerts + if not os.path.isdir(os.path.expanduser(caCerts)): + raise Exception ('caCerts arg Not a file or a dir: %s' % caCerts) + + + + # Now we have a dir of caCerts files + # For each file in the dir (isfile), concatenate them into a new file + comboFullPath = os.path.join(caCerts, CredentialVerifier.CATEDCERTSFNAME) + + caFiles = os.listdir(caCerts) + #logger.debug('Got %d potential caCert files in the dir', len(caFiles)) + + outfile = open(comboFullPath, "w") + okFileCount = 0 + for filename in caFiles: + filepath = os.path.join(caCerts, filename) + # Confirm it's a CA file? + # if not file.endswith('.pem'): + # continue + if not os.path.isfile(os.path.expanduser(filepath)): + + continue + if filename == CredentialVerifier.CATEDCERTSFNAME: + # logger.debug('Skipping previous cated certs file') + continue + okFileCount += 1 + + certfile = open(filepath) + for line in certfile: + outfile.write(line) + certfile.close() + outfile.close() + if okFileCount == 0: + sys.exit('Found NO trusted certs in %s!' % caCerts) + + return comboFullPath + + def verify_from_strings(self, gid_string, cred_strings, target_urn, + privileges, options=None): + + '''Create Credential and GID objects from the given strings, + and then verify the GID has the right privileges according + to the given credentials on the given target.''' + def make_cred(cred_string): + credO = None + try: + credO = CredentialFactory.createCred(credString=cred_string) + except Exception, e: + print e + return credO + + root_certs = \ + [Certificate(filename=root_cert_file) \ + for root_cert_file in self.root_cert_files] + + caller_gid = gid.GID(string=gid_string) + + # Potentially, change gid_string to be the cert of the actual user + # if this is a 'speaks-for' invocation + speaksfor_gid = \ + determine_speaks_for(None, \ + cred_strings, # May include ABAC speaks_for credential + caller_gid, # Caller cert (may be the tool 'speaking for' user) + options, # May include 'geni_speaking_for' option with user URN + root_certs + ) + if caller_gid.get_subject() != speaksfor_gid.get_subject(): + speaksfor_urn = speaksfor_gid.get_urn() + caller_gid = speaksfor_gid + + + # Remove the abac credentials + cred_strings = [cred_string for cred_string in cred_strings \ + if CredentialFactory.getType(cred_string) == cred.Credential.SFA_CREDENTIAL_TYPE] + + return self.verify(caller_gid, + map(make_cred, cred_strings), + target_urn, + privileges) + + def verify_source(self, source_gid, credential): + '''Ensure the credential is giving privileges to the caller/client. + Return True iff the given source (client) GID's URN + is == the given credential's Caller (Owner) URN''' + source_urn = source_gid.get_urn() + cred_source_urn = credential.get_gid_caller().get_urn() + #self.logger.debug('Verifying source %r against credential source %r (cred target %s)', + # source_urn, cred_source_urn, credential.get_gid_object().get_urn()) + result = (cred_source_urn == source_urn) + if result: + # self.logger.debug('Source URNs match') + pass + return result + + def verify_target(self, target_urn, credential): + '''Ensure the credential is giving privileges on the right subject/target. + Return True if no target is specified, or the target URN + matches the credential's Object's (target's) URN, else return False. + No target is required, for example, to ListResources.''' + if not target_urn: +# self.logger.debug('No target specified, considering it a match.') + return True + else: + cred_target_urn = credential.get_gid_object().get_urn() + # self.logger.debug('Verifying target %r against credential target %r', + # target_urn, cred_target_urn) + result = target_urn == cred_target_urn + if result: + # self.logger.debug('Target URNs match.') + pass + return result + + def verify_privileges(self, privileges, credential): + ''' Return True iff the given credential gives the privilege + to perform ALL of the privileges (actions) in the given list. + In particular, the given list of 'privileges' is really a list + of names of operations. The privileges in credentials are + each turned in to Rights objects (see sfa/trust/rights.py). + And the SFA rights table is used to map from names of privileges + as specified in credentials, to names of operations.''' + result = True + privs = credential.get_privileges() + for priv in privileges: + + if not privs.can_perform(priv): + result = False + return result + + def verify(self, gid, credentials, target_urn, privileges): + '''Verify that the given Source GID supplied at least one credential + in the given list of credentials that has all the privileges required + in the privileges list on the given target. + IE if any of the supplied credentials has a caller that matches gid + and a target that matches target_urn, and has all the privileges in + the given list, then return the list of credentials that were ok. + Throw an Exception if we fail to verify any credential.''' + + # Note that here we treat a list of credentials as being options + # Alternatively could accumulate privileges for example + # The semantics of the list of credentials is under specified. + + result = list() + failure = "" + tried_creds = "" + if len(credentials) == 0: + failure = "No credentials found" + for cred in credentials: + if cred is None: + failure = "Credential was unparseable" + continue + if cred.get_cred_type() == cred.SFA_CREDENTIAL_TYPE: + cS = cred.get_gid_caller().get_urn() + elif cred.get_cred_type() == ABACCredential.ABAC_CREDENTIAL_TYPE: + cS = cred.get_summary_tostring() + else: + cS = "Unknown credential type %s" % cred.get_cred_type() + + if tried_creds != "": + tried_creds = "%s, %s" % (tried_creds, cS) + else: + tried_creds = cS + if cred.get_cred_type() != cred.SFA_CREDENTIAL_TYPE: + failure = "Not an SFA credential: " + cS + continue + + #if not self.verify_source(gid, cred): + # failure = "Cred %s fails: Credential doesn't grant rights to you (%s), but to %s (over object %s)" % (cred.get_gid_caller().get_urn(), gid.get_urn(), cred.get_gid_caller().get_urn(), cred.get_gid_object().get_urn()) + # continue + + if not self.verify_target(target_urn, cred): + failure = "Cred granting rights to %s on %s fails: It grants permissions over a different target, not %s (URNs dont match)" % (cred.get_gid_caller().get_urn(), cred.get_gid_object().get_urn(), target_urn) + continue + if not self.verify_privileges(privileges, cred): + failure = "Cred for %s over %s doesn't provide sufficient privileges" % (cred.get_gid_caller().get_urn(), cred.get_gid_object().get_urn()) + continue + try: + if not cred.verify(self.root_cert_files): + failure = "Couldn't validate credential for caller %s with target %s with any of %d known root certs" % (cred.get_gid_caller().get_urn(), cred.get_gid_object().get_urn(), len(self.root_cert_files)) + continue + except Exception, exc: + failure = "Couldn't validate credential for caller %s with target %s with any of %d known root certs: %s: %s" % (cred.get_gid_caller().get_urn(), cred.get_gid_object().get_urn(), len(self.root_cert_files), exc.__class__.__name__, exc) + continue + # If got here it verified + result.append(cred) + + if result and result != list(): + # At least one credential verified ok and was added to the list + # return that list + return result + else: + # We did not find any credential with sufficient privileges + # Raise an exception. + fault_code = 'Insufficient privileges' + fault_string = 'No credential was found with appropriate privileges. Tried %s. Last failure: %s' % (tried_creds, failure) + # GCF ticket #120 - do not raise an xmlrpclib Fault here - + # just an Exception. But the caller may want to turn this + # into one +# raise xmlrpclib.Fault(fault_code, fault_string) + raise Exception(fault_string) + +def create_credential(caller_gid, object_gid, expiration, typename, issuer_keyfile, issuer_certfile, trusted_roots, delegatable=False): + '''Create and Return a Credential object issued by given key/cert for the given caller + and object GID objects, given life in seconds, and given type. + Privileges are determined by type per sfa/trust/rights.py + Privileges are delegatable if requested.''' + # FIXME: Validate args: my gids, >0 life, + # type of cred one I can issue + # and readable key and cert files + if caller_gid is None: + raise ValueError("Missing Caller GID") + if object_gid is None: + raise ValueError("Missing Object GID") + if expiration is None: + raise ValueError("Missing expiration") + naive_expiration = naiveUTC(expiration) + duration = naive_expiration - datetime.datetime.utcnow() + life_secs = duration.seconds + duration.days * 24 * 3600 + if life_secs < 1: + raise ValueError("Credential expiration is in the past") + if trusted_roots is None: + raise ValueError("Missing list of trusted roots") + + if typename is None or typename.strip() == '': + raise ValueError("Missing credential type") + typename = typename.strip().lower() + if typename not in ("user", "sa", "ma", "authority", "slice", "component"): + raise ValueError("Unknown credential type %s" % typename) + + if not os.path.isfile(issuer_keyfile): + raise ValueError("Cant read issuer key file %s" % issuer_keyfile) + + if not os.path.isfile(issuer_certfile): + raise ValueError("Cant read issuer cert file %s" % issuer_certfile) + + issuer_gid = gid.GID(filename=issuer_certfile) + + if not (object_gid.get_urn() == issuer_gid.get_urn() or + (issuer_gid.get_type().find('authority') == 0 and + hrn_authfor_hrn(issuer_gid.get_hrn(), object_gid.get_hrn()))): + raise ValueError("Issuer not authorized to issue credential: Issuer=%s Target=%s" % (issuer_gid.get_urn(), object_gid.get_urn())) + + + + ucred = cred.Credential() + # FIXME: Validate the caller_gid and object_gid + # are my user and slice + # Do get_issuer and compare to the issuer cert? + # Or do gid.is_signed_by_cert(issuer_certfile)? + ucred.set_gid_caller(caller_gid) + ucred.set_gid_object(object_gid) + ucred.set_expiration(expiration) + # Use sfa/trust/rights.py to figure out what privileges + # the credential should have. + # user means refresh, resolve, info + # per the privilege_table that lets users do + # remove, update, resolve, list, getcredential, + # listslices, listnodes, getpolicy + # Note that it does not allow manipulating slivers + + # And every right is delegatable if any are delegatable (default False) + privileges = rights.determine_rights(typename, None) + privileges.delegate_all_privileges(delegatable) + ucred.set_privileges(privileges) + ucred.encode() + ucred.set_issuer_keys(issuer_keyfile, issuer_certfile) + ucred.sign() + + try: + ucred.verify(trusted_roots) + except Exception, exc: + raise Exception("Create Credential failed to verify new credential from trusted roots: %s" % exc) + + return ucred + + diff --git a/core/lib/am/credentials/src/trustgcf/credential.py b/core/lib/am/credentials/src/trustgcf/credential.py new file mode 100644 index 00000000..e2b2888b --- /dev/null +++ b/core/lib/am/credentials/src/trustgcf/credential.py @@ -0,0 +1,1143 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- +## +# Implements SFA Credentials +# +# Credentials are signed XML files that assign a subject gid privileges to an object gid +## + +from __future__ import absolute_import + +import os +from types import StringTypes +import datetime +from StringIO import StringIO +from tempfile import mkstemp +from xml.dom.minidom import Document, parseString +from dateutil import tz + +HAVELXML = False +try: + from lxml import etree + HAVELXML = True +except: + pass + +from xml.parsers.expat import ExpatError +from geniutils.src.faults.faults import CredentialNotVerifiable, ChildRightsNotSubsetOfParent +from geniutils.src.time.timewrapper import utcparse +from geniutils.src.xrn.xrn import urn_to_hrn, hrn_authfor_hrn +from credentials.src.trustgcf.credential_legacy import CredentialLegacy +from credentials.src.trustgcf.rights import Right, Rights, determine_rights +from credentials.src.trustgcf.gid import GID + +# 2 weeks, in seconds +DEFAULT_CREDENTIAL_LIFETIME = 86400 * 31 + + +# TODO: +# . make privs match between PG and PL +# . Need to add support for other types of credentials, e.g. tickets +# . add namespaces to signed-credential element? + +signature_template = \ +''' + + + + + + + + + + + + + + + + + + + + + + +''' + +# PG formats the template (whitespace) slightly differently. +# Note that they don't include the xmlns in the template, but add it later. +# Otherwise the two are equivalent. +#signature_template_as_in_pg = \ +#''' +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +#''' + +## +# Convert a string into a bool +# used to convert an xsd:boolean to a Python boolean +def str2bool(str): + if str.lower() in ['true','1']: + return True + return False + + +## +# Utility function to get the text of an XML element + +def getTextNode(element, subele): + sub = element.getElementsByTagName(subele)[0] + if len(sub.childNodes) > 0: + return sub.childNodes[0].nodeValue + else: + return None + +## +# Utility function to set the text of an XML element +# It creates the element, adds the text to it, +# and then appends it to the parent. + +def append_sub(doc, parent, element, text): + ele = doc.createElement(element) + ele.appendChild(doc.createTextNode(text)) + parent.appendChild(ele) + +## +# Signature contains information about an xmlsec1 signature +# for a signed-credential +# + +class Signature(object): + + def __init__(self, string=None): + self.refid = None + self.issuer_gid = None + self.xml = None + if string: + self.xml = string + self.decode() + + + def get_refid(self): + if not self.refid: + self.decode() + return self.refid + + def get_xml(self): + if not self.xml: + self.encode() + return self.xml + + def set_refid(self, id): + self.refid = id + + def get_issuer_gid(self): + if not self.gid: + self.decode() + return self.gid + + def set_issuer_gid(self, gid): + self.gid = gid + + def decode(self): + try: + doc = parseString(self.xml) + except ExpatError,e: + raise + sig = doc.getElementsByTagName("Signature")[0] + ref_id = sig.getAttribute("xml:id").strip().strip("Sig_") + # The xml:id tag is optional, and could be in a + # Reference xml:id or Reference UID sub element instead + if not ref_id or ref_id == '': + reference = sig.getElementsByTagName('Reference')[0] + ref_id = reference.getAttribute('xml:id').strip().strip('Sig_') + if not ref_id or ref_id == '': + ref_id = reference.getAttribute('URI').strip().strip('#') + self.set_refid(ref_id) + keyinfos = sig.getElementsByTagName("X509Data") + gids = None + for keyinfo in keyinfos: + certs = keyinfo.getElementsByTagName("X509Certificate") + for cert in certs: + if len(cert.childNodes) > 0: + szgid = cert.childNodes[0].nodeValue + szgid = szgid.strip() + szgid = "-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----" % szgid + if gids is None: + gids = szgid + else: + gids += "\n" + szgid + if gids is None: + raise CredentialNotVerifiable("Malformed XML: No certificate found in signature") + self.set_issuer_gid(GID(string=gids)) + + def encode(self): + self.xml = signature_template % (self.get_refid(), self.get_refid()) + + +## +# A credential provides a caller gid with privileges to an object gid. +# A signed credential is signed by the object's authority. +# +# Credentials are encoded in one of two ways. The legacy style places +# it in the subjectAltName of an X509 certificate. The new credentials +# are placed in signed XML. +# +# WARNING: +# In general, a signed credential obtained externally should +# not be changed else the signature is no longer valid. So, once +# you have loaded an existing signed credential, do not call encode() or sign() on it. + +def filter_creds_by_caller(creds, caller_hrn_list): + """ + Returns a list of creds who's gid caller matches the + specified caller hrn + """ + if not isinstance(creds, list): creds = [creds] + if not isinstance(caller_hrn_list, list): + caller_hrn_list = [caller_hrn_list] + caller_creds = [] + for cred in creds: + try: + tmp_cred = Credential(string=cred) + if tmp_cred.get_cred_type() != Credential.SFA_CREDENTIAL_TYPE: + continue + if tmp_cred.get_gid_caller().get_hrn() in caller_hrn_list: + caller_creds.append(cred) + except: pass + return caller_creds + +class Credential(object): + + SFA_CREDENTIAL_TYPE = "geni_sfa" + + ## + # Create a Credential object + # + # @param create If true, create a blank x509 certificate + # @param subject If subject!=None, create an x509 cert with the subject name + # @param string If string!=None, load the credential from the string + # @param filename If filename!=None, load the credential from the file + # FIXME: create and subject are ignored! + def __init__(self, create=False, subject=None, string=None, filename=None): + self.gidCaller = None + self.gidObject = None + self.expiration = None + self.privileges = None + self.issuer_privkey = None + self.issuer_gid = None + self.issuer_pubkey = None + self.parent = None + self.signature = None + self.xml = None + self.refid = None + self.legacy = None + self.cred_type = Credential.SFA_CREDENTIAL_TYPE + + # Check if this is a legacy credential, translate it if so + if string or filename: + if string: + str = string + elif filename: + str = file(filename).read() + + if str.strip().startswith("-----"): + self.legacy = CredentialLegacy(False,string=str) + self.translate_legacy(str) + else: + self.xml = str + self.decode() + + # Find an xmlsec1 path + self.xmlsec_path = '' + paths = ['/usr/bin','/usr/local/bin','/bin','/opt/bin','/opt/local/bin'] + for path in paths: + if os.path.isfile(path + '/' + 'xmlsec1'): + self.xmlsec_path = path + '/' + 'xmlsec1' + break + if not self.xmlsec_path: + pass + + def get_cred_type(self): + return self.cred_type + + def get_subject(self): + if not self.gidObject: + self.decode() + return self.gidObject.get_subject() + + # sounds like this should be __repr__ instead ?? + def get_summary_tostring(self): + if not self.gidObject: + self.decode() + obj = self.gidObject.get_printable_subject() + caller = self.gidCaller.get_printable_subject() + exp = self.get_expiration() + # Summarize the rights too? The issuer? + return "[ Grant %s rights on %s until %s ]" % (caller, obj, exp) + + def get_signature(self): + if not self.signature: + self.decode() + return self.signature + + def set_signature(self, sig): + self.signature = sig + + + ## + # Translate a legacy credential into a new one + # + # @param String of the legacy credential + + def translate_legacy(self, str): + legacy = CredentialLegacy(False,string=str) + self.gidCaller = legacy.get_gid_caller() + self.gidObject = legacy.get_gid_object() + lifetime = legacy.get_lifetime() + if not lifetime: + self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) + else: + self.set_expiration(int(lifetime)) + self.lifeTime = legacy.get_lifetime() + self.set_privileges(legacy.get_privileges()) + self.get_privileges().delegate_all_privileges(legacy.get_delegate()) + + ## + # Need the issuer's private key and name + # @param key Keypair object containing the private key of the issuer + # @param gid GID of the issuing authority + + def set_issuer_keys(self, privkey, gid): + self.issuer_privkey = privkey + self.issuer_gid = gid + + + ## + # Set this credential's parent + def set_parent(self, cred): + self.parent = cred + self.updateRefID() + + ## + # set the GID of the caller + # + # @param gid GID object of the caller + + def set_gid_caller(self, gid): + self.gidCaller = gid + # gid origin caller is the caller's gid by default + self.gidOriginCaller = gid + + ## + # get the GID of the object + + def get_gid_caller(self): + if not self.gidCaller: + self.decode() + return self.gidCaller + + ## + # set the GID of the object + # + # @param gid GID object of the object + + def set_gid_object(self, gid): + self.gidObject = gid + + ## + # get the GID of the object + + def get_gid_object(self): + if not self.gidObject: + self.decode() + return self.gidObject + + ## + # Expiration: an absolute UTC time of expiration (as either an int or string or datetime) + # + def set_expiration(self, expiration): + if isinstance(expiration, (int, float)): + self.expiration = datetime.datetime.fromtimestamp(expiration) + elif isinstance (expiration, datetime.datetime): + self.expiration = expiration + elif isinstance (expiration, StringTypes): + self.expiration = utcparse (expiration) + else: + pass + + + ## + # get the lifetime of the credential (always in datetime format) + + def get_expiration(self): + if not self.expiration: + self.decode() + # at this point self.expiration is normalized as a datetime - DON'T call utcparse again + return self.expiration + + ## + # For legacy sake + def get_lifetime(self): + return self.get_expiration() + + ## + # set the privileges + # + # @param privs either a comma-separated list of privileges of a Rights object + + def set_privileges(self, privs): + if isinstance(privs, str): + self.privileges = Rights(string = privs) + else: + self.privileges = privs + + ## + # return the privileges as a Rights object + + def get_privileges(self): + if not self.privileges: + self.decode() + return self.privileges + + ## + # determine whether the credential allows a particular operation to be + # performed + # + # @param op_name string specifying name of operation ("lookup", "update", etc) + + def can_perform(self, op_name): + rights = self.get_privileges() + + if not rights: + return False + + return rights.can_perform(op_name) + + + ## + # Encode the attributes of the credential into an XML string + # This should be done immediately before signing the credential. + # WARNING: + # In general, a signed credential obtained externally should + # not be changed else the signature is no longer valid. So, once + # you have loaded an existing signed credential, do not call encode() or sign() on it. + + def encode(self): + # Create the XML document + doc = Document() + signed_cred = doc.createElement("signed-credential") + +# Declare namespaces +# Note that credential/policy.xsd are really the PG schemas +# in a PL namespace. +# Note that delegation of credentials between the 2 only really works +# cause those schemas are identical. +# Also note these PG schemas talk about PG tickets and CM policies. + signed_cred.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") + # FIXME: See v2 schema at www.geni.net/resources/credential/2/credential.xsd + signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.planet-lab.org/resources/sfa/credential.xsd") + signed_cred.setAttribute("xsi:schemaLocation", "http://www.planet-lab.org/resources/sfa/ext/policy/1 http://www.planet-lab.org/resources/sfa/ext/policy/1/policy.xsd") + +# PG says for those last 2: +# signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.protogeni.net/resources/credential/credential.xsd") +# signed_cred.setAttribute("xsi:schemaLocation", "http://www.protogeni.net/resources/credential/ext/policy/1 http://www.protogeni.net/resources/credential/ext/policy/1/policy.xsd") + + doc.appendChild(signed_cred) + + # Fill in the bit + cred = doc.createElement("credential") + cred.setAttribute("xml:id", self.get_refid()) + signed_cred.appendChild(cred) + append_sub(doc, cred, "type", "privilege") + append_sub(doc, cred, "serial", "8") + append_sub(doc, cred, "owner_gid", self.gidCaller.save_to_string()) + append_sub(doc, cred, "owner_urn", self.gidCaller.get_urn()) + append_sub(doc, cred, "target_gid", self.gidObject.save_to_string()) + append_sub(doc, cred, "target_urn", self.gidObject.get_urn()) + append_sub(doc, cred, "uuid", "") + if not self.expiration: + self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) + self.expiration = self.expiration.replace(microsecond=0) + if self.expiration.tzinfo is not None and self.expiration.tzinfo.utcoffset(self.expiration) is not None: + # TZ aware. Make sure it is UTC + self.expiration = self.expiration.astimezone(tz.tzutc()) + append_sub(doc, cred, "expires", self.expiration.strftime('%Y-%m-%dT%H:%M:%SZ')) # RFC3339 + privileges = doc.createElement("privileges") + cred.appendChild(privileges) + + if self.privileges: + rights = self.get_privileges() + for right in rights.rights: + priv = doc.createElement("privilege") + append_sub(doc, priv, "name", right.kind) + append_sub(doc, priv, "can_delegate", str(right.delegate).lower()) + privileges.appendChild(priv) + + # Add the parent credential if it exists + if self.parent: + sdoc = parseString(self.parent.get_xml()) + # If the root node is a signed-credential (it should be), then + # get all its attributes and attach those to our signed_cred + # node. + # Specifically, PG and PLadd attributes for namespaces (which is reasonable), + # and we need to include those again here or else their signature + # no longer matches on the credential. + # We expect three of these, but here we copy them all: +# signed_cred.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") +# and from PG (PL is equivalent, as shown above): +# signed_cred.setAttribute("xsi:noNamespaceSchemaLocation", "http://www.protogeni.net/resources/credential/credential.xsd") +# signed_cred.setAttribute("xsi:schemaLocation", "http://www.protogeni.net/resources/credential/ext/policy/1 http://www.protogeni.net/resources/credential/ext/policy/1/policy.xsd") + + # HOWEVER! + # PL now also declares these, with different URLs, so + # the code notices those attributes already existed with + # different values, and complains. + # This happens regularly on delegation now that PG and + # PL both declare the namespace with different URLs. + # If the content ever differs this is a problem, + # but for now it works - different URLs (values in the attributes) + # but the same actual schema, so using the PG schema + # on delegated-to-PL credentials works fine. + + # Note: you could also not copy attributes + # which already exist. It appears that both PG and PL + # will actually validate a slicecred with a parent + # signed using PG namespaces and a child signed with PL + # namespaces over the whole thing. But I don't know + # if that is a bug in xmlsec1, an accident since + # the contents of the schemas are the same, + # or something else, but it seems odd. And this works. + parentRoot = sdoc.documentElement + if parentRoot.tagName == "signed-credential" and parentRoot.hasAttributes(): + for attrIx in range(0, parentRoot.attributes.length): + attr = parentRoot.attributes.item(attrIx) + # returns the old attribute of same name that was + # on the credential + # Below throws InUse exception if we forgot to clone the attribute first + oldAttr = signed_cred.setAttributeNode(attr.cloneNode(True)) + if oldAttr and oldAttr.value != attr.value: + msg = "Delegating cred from owner %s to %s over %s:\n - Replaced attribute %s value '%s' with '%s'" % (self.parent.gidCaller.get_urn(), self.gidCaller.get_urn(), self.gidObject.get_urn(), oldAttr.name, oldAttr.value, attr.value) + #raise CredentialNotVerifiable("Can't encode new valid delegated credential: %s" % msg) + + p_cred = doc.importNode(sdoc.getElementsByTagName("credential")[0], True) + p = doc.createElement("parent") + p.appendChild(p_cred) + cred.appendChild(p) + # done handling parent credential + + # Create the tag + signatures = doc.createElement("signatures") + signed_cred.appendChild(signatures) + + # Add any parent signatures + if self.parent: + for cur_cred in self.get_credential_list()[1:]: + sdoc = parseString(cur_cred.get_signature().get_xml()) + ele = doc.importNode(sdoc.getElementsByTagName("Signature")[0], True) + signatures.appendChild(ele) + + # Get the finished product + self.xml = doc.toxml("utf-8") + + + def save_to_random_tmp_file(self): + fp, filename = mkstemp(suffix='cred', text=True) + fp = os.fdopen(fp, "w") + self.save_to_file(filename, save_parents=True, filep=fp) + return filename + + def save_to_file(self, filename, save_parents=True, filep=None): + if not self.xml: + self.encode() + if filep: + f = filep + else: + f = open(filename, "w") + f.write(self.xml) + f.close() + + def save_to_string(self, save_parents=True): + if not self.xml: + self.encode() + return self.xml + + def get_refid(self): + if not self.refid: + self.refid = 'ref0' + return self.refid + + def set_refid(self, rid): + self.refid = rid + + ## + # Figure out what refids exist, and update this credential's id + # so that it doesn't clobber the others. Returns the refids of + # the parents. + + def updateRefID(self): + if not self.parent: + self.set_refid('ref0') + return [] + + refs = [] + + next_cred = self.parent + while next_cred: + refs.append(next_cred.get_refid()) + if next_cred.parent: + next_cred = next_cred.parent + else: + next_cred = None + + + # Find a unique refid for this credential + rid = self.get_refid() + while rid in refs: + val = int(rid[3:]) + rid = "ref%d" % (val + 1) + + # Set the new refid + self.set_refid(rid) + + # Return the set of parent credential ref ids + return refs + + def get_xml(self): + if not self.xml: + self.encode() + return self.xml + + ## + # Sign the XML file created by encode() + # + # WARNING: + # In general, a signed credential obtained externally should + # not be changed else the signature is no longer valid. So, once + # you have loaded an existing signed credential, do not call encode() or sign() on it. + + def sign(self): + if not self.issuer_privkey: + return + if not self.issuer_gid: + return + doc = parseString(self.get_xml()) + sigs = doc.getElementsByTagName("signatures")[0] + + # Create the signature template to be signed + signature = Signature() + signature.set_refid(self.get_refid()) + sdoc = parseString(signature.get_xml()) + sig_ele = doc.importNode(sdoc.getElementsByTagName("Signature")[0], True) + sigs.appendChild(sig_ele) + + self.xml = doc.toxml("utf-8") + + + # Split the issuer GID into multiple certificates if it's a chain + chain = GID(filename=self.issuer_gid) + gid_files = [] + while chain: + gid_files.append(chain.save_to_random_tmp_file(False)) + if chain.get_parent(): + chain = chain.get_parent() + else: + chain = None + + + # Call out to xmlsec1 to sign it + ref = 'Sig_%s' % self.get_refid() + filename = self.save_to_random_tmp_file() + print "**********************************",'%s --sign --node-id "%s" --privkey-pem %s,%s %s' % (self.xmlsec_path, ref, self.issuer_privkey, ",".join(gid_files), filename) + command='%s --sign --node-id "%s" --privkey-pem %s,%s %s' \ + % (self.xmlsec_path, ref, self.issuer_privkey, ",".join(gid_files), filename) + signed = os.popen(command).read() + os.remove(filename) + + for gid_file in gid_files: + os.remove(gid_file) + + self.xml = signed + + # This is no longer a legacy credential + if self.legacy: + self.legacy = None + + # Update signatures + self.decode() + + + ## + # Retrieve the attributes of the credential from the XML. + # This is automatically called by the various get_* methods of + # this class and should not need to be called explicitly. + + def decode(self): + if not self.xml: + return + doc = parseString(self.xml) + sigs = [] + signed_cred = doc.getElementsByTagName("signed-credential") + + # Is this a signed-cred or just a cred? + if len(signed_cred) > 0: + creds = signed_cred[0].getElementsByTagName("credential") + signatures = signed_cred[0].getElementsByTagName("signatures") + if len(signatures) > 0: + sigs = signatures[0].getElementsByTagName("Signature") + else: + creds = doc.getElementsByTagName("credential") + + if creds is None or len(creds) == 0: + # malformed cred file + raise CredentialNotVerifiable("Malformed XML: No credential tag found") + + # Just take the first cred if there are more than one + cred = creds[0] + + self.set_refid(cred.getAttribute("xml:id")) + self.set_expiration(utcparse(getTextNode(cred, "expires"))) + +# import traceback +# stack = traceback.extract_stack() + + og = getTextNode(cred, "owner_gid") + # ABAC creds will have this be None and use this method +# if og is None: +# found = False +# for frame in stack: +# if 'super(ABACCredential, self).decode()' in frame: +# found = True +# break +# if not found: +# raise CredentialNotVerifiable("Malformed XML: No owner_gid found") + self.gidCaller = GID(string=og) + tg = getTextNode(cred, "target_gid") +# if tg is None: +# found = False +# for frame in stack: +# if 'super(ABACCredential, self).decode()' in frame: +# found = True +# break +# if not found: +# raise CredentialNotVerifiable("Malformed XML: No target_gid found") + self.gidObject = GID(string=tg) + + # Process privileges + rlist = Rights() + priv_nodes = cred.getElementsByTagName("privileges") + if len(priv_nodes) > 0: + privs = priv_nodes[0] + for priv in privs.getElementsByTagName("privilege"): + kind = getTextNode(priv, "name") + deleg = str2bool(getTextNode(priv, "can_delegate")) + if kind == '*': + # Convert * into the default privileges for the credential's type + # Each inherits the delegatability from the * above + _ , type = urn_to_hrn(self.gidObject.get_urn()) + rl = determine_rights(type, self.gidObject.get_urn()) + for r in rl.rights: + r.delegate = deleg + rlist.add(r) + else: + rlist.add(Right(kind.strip(), deleg)) + self.set_privileges(rlist) + + + # Is there a parent? + parent = cred.getElementsByTagName("parent") + if len(parent) > 0: + parent_doc = parent[0].getElementsByTagName("credential")[0] + parent_xml = parent_doc.toxml("utf-8") + if parent_xml is None or parent_xml.strip() == "": + raise CredentialNotVerifiable("Malformed XML: Had parent tag but it is empty") + self.parent = Credential(string=parent_xml) + self.updateRefID() + + # Assign the signatures to the credentials + for sig in sigs: + Sig = Signature(string=sig.toxml("utf-8")) + + for cur_cred in self.get_credential_list(): + if cur_cred.get_refid() == Sig.get_refid(): + cur_cred.set_signature(Sig) + + + ## + # Verify + # trusted_certs: A list of trusted GID filenames (not GID objects!) + # Chaining is not supported within the GIDs by xmlsec1. + # + # trusted_certs_required: Should usually be true. Set False means an + # empty list of trusted_certs would still let this method pass. + # It just skips xmlsec1 verification et al. Only used by some utils + # + # Verify that: + # . All of the signatures are valid and that the issuers trace back + # to trusted roots (performed by xmlsec1) + # . The XML matches the credential schema + # . That the issuer of the credential is the authority in the target's urn + # . In the case of a delegated credential, this must be true of the root + # . That all of the gids presented in the credential are valid + # . Including verifying GID chains, and includ the issuer + # . The credential is not expired + # + # -- For Delegates (credentials with parents) + # . The privileges must be a subset of the parent credentials + # . The privileges must have "can_delegate" set for each delegated privilege + # . The target gid must be the same between child and parents + # . The expiry time on the child must be no later than the parent + # . The signer of the child must be the owner of the parent + # + # -- Verify does *NOT* + # . ensure that an xmlrpc client's gid matches a credential gid, that + # must be done elsewhere + # + # @param trusted_certs: The certificates of trusted CA certificates + def verify(self, trusted_certs=None, schema=None, trusted_certs_required=True): + if not self.xml: + self.decode() + + # validate against RelaxNG schema + if HAVELXML and not self.legacy: + if schema and os.path.exists(schema): + tree = etree.parse(StringIO(self.xml)) + schema_doc = etree.parse(schema) + xmlschema = etree.XMLSchema(schema_doc) + if not xmlschema.validate(tree): + error = xmlschema.error_log.last_error + message = "%s: %s (line %s)" % (self.get_summary_tostring(), error.message, error.line) + raise CredentialNotVerifiable(message) + + if trusted_certs_required and trusted_certs is None: + trusted_certs = [] + +# trusted_cert_objects = [GID(filename=f) for f in trusted_certs] + trusted_cert_objects = [] + ok_trusted_certs = [] + # If caller explicitly passed in None that means skip cert chain validation. + # Strange and not typical + if trusted_certs is not None: + for f in trusted_certs: + try: + # Failures here include unreadable files + # or non PEM files + trusted_cert_objects.append(GID(filename=f)) + ok_trusted_certs.append(f) + except Exception, exc: + pass + trusted_certs = ok_trusted_certs + + # Use legacy verification if this is a legacy credential + if self.legacy: + self.legacy.verify_chain(trusted_cert_objects) + if self.legacy.client_gid: + self.legacy.client_gid.verify_chain(trusted_cert_objects) + if self.legacy.object_gid: + self.legacy.object_gid.verify_chain(trusted_cert_objects) + return True + + # make sure it is not expired + if self.get_expiration() < datetime.datetime.utcnow(): + raise CredentialNotVerifiable("Credential %s expired at %s" % (self.get_summary_tostring(), self.expiration.isoformat())) + + # Verify the signatures + filename = self.save_to_random_tmp_file() + if trusted_certs is not None: + cert_args = " ".join(['--trusted-pem %s' % x for x in trusted_certs]) + + # If caller explicitly passed in None that means skip cert chain validation. + # - Strange and not typical + if trusted_certs is not None: + # Verify the gids of this cred and of its parents + for cur_cred in self.get_credential_list(): + cur_cred.get_gid_object().verify_chain(trusted_cert_objects) + cur_cred.get_gid_caller().verify_chain(trusted_cert_objects) + + refs = [] + refs.append("Sig_%s" % self.get_refid()) + + parentRefs = self.updateRefID() + for ref in parentRefs: + refs.append("Sig_%s" % ref) + + for ref in refs: + # If caller explicitly passed in None that means skip xmlsec1 validation. + # Strange and not typical + if trusted_certs is None: + break + +# print "Doing %s --verify --node-id '%s' %s %s 2>&1" % \ +# (self.xmlsec_path, ref, cert_args, filename) + verified = os.popen('%s --verify --node-id "%s" %s %s 2>&1' \ + % (self.xmlsec_path, ref, cert_args, filename)).read() + if not verified.strip().startswith("OK"): + # xmlsec errors have a msg= which is the interesting bit. + mstart = verified.find("msg=") + msg = "" + if mstart > -1 and len(verified) > 4: + mstart = mstart + 4 + mend = verified.find('\\', mstart) + msg = verified[mstart:mend] + raise CredentialNotVerifiable("xmlsec1 error verifying cred %s using Signature ID %s: %s %s" % (self.get_summary_tostring(), ref, msg, verified.strip())) + os.remove(filename) + + # Verify the parents (delegation) + if self.parent: + self.verify_parent(self.parent) + + # Make sure the issuer is the target's authority, and is + # itself a valid GID + self.verify_issuer(trusted_cert_objects) + return True + + ## + # Creates a list of the credential and its parents, with the root + # (original delegated credential) as the last item in the list + def get_credential_list(self): + cur_cred = self + list = [] + while cur_cred: + list.append(cur_cred) + if cur_cred.parent: + cur_cred = cur_cred.parent + else: + cur_cred = None + return list + + ## + # Make sure the credential's target gid (a) was signed by or (b) + # is the same as the entity that signed the original credential, + # or (c) is an authority over the target's namespace. + # Also ensure that the credential issuer / signer itself has a valid + # GID signature chain (signed by an authority with namespace rights). + def verify_issuer(self, trusted_gids): + root_cred = self.get_credential_list()[-1] + root_target_gid = root_cred.get_gid_object() + if root_cred.get_signature() is None: + # malformed + raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred has no signature" % (self.gidCaller.get_urn(), self.gidObject.get_urn())) + + root_cred_signer = root_cred.get_signature().get_issuer_gid() + + # Case 1: + # Allow non authority to sign target and cred about target. + # + # Why do we need to allow non authorities to sign? + # If in the target gid validation step we correctly + # checked that the target is only signed by an authority, + # then this is just a special case of case 3. + # This short-circuit is the common case currently - + # and cause GID validation doesn't check 'authority', + # this allows users to generate valid slice credentials. + if root_target_gid.is_signed_by_cert(root_cred_signer): + # cred signer matches target signer, return success + return + + # Case 2: + # Allow someone to sign credential about themeselves. Used? + # If not, remove this. + #root_target_gid_str = root_target_gid.save_to_string() + #root_cred_signer_str = root_cred_signer.save_to_string() + #if root_target_gid_str == root_cred_signer_str: + # # cred signer is target, return success + # return + + # Case 3: + + # root_cred_signer is not the target_gid + # So this is a different gid that we have not verified. + # xmlsec1 verified the cert chain on this already, but + # it hasn't verified that the gid meets the HRN namespace + # requirements. + # Below we'll ensure that it is an authority. + # But we haven't verified that it is _signed by_ an authority + # We also don't know if xmlsec1 requires that cert signers + # are marked as CAs. + + # Note that if verify() gave us no trusted_gids then this + # call will fail. So skip it if we have no trusted_gids + if trusted_gids and len(trusted_gids) > 0: + root_cred_signer.verify_chain(trusted_gids) + else: + pass + # See if the signer is an authority over the domain of the target. + # There are multiple types of authority - accept them all here + # Maybe should be (hrn, type) = urn_to_hrn(root_cred_signer.get_urn()) + root_cred_signer_type = root_cred_signer.get_type() + if (root_cred_signer_type.find('authority') == 0): + #logger.debug('Cred signer is an authority') + # signer is an authority, see if target is in authority's domain + signerhrn = root_cred_signer.get_hrn() + if hrn_authfor_hrn(signerhrn, root_target_gid.get_hrn()): + return + + # We've required that the credential be signed by an authority + # for that domain. Reasonable and probably correct. + # A looser model would also allow the signer to be an authority + # in my control framework - eg My CA or CH. Even if it is not + # the CH that issued these, eg, user credentials. + + # Give up, credential does not pass issuer verification + + raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred signer %s not the trusted authority for Cred target %s" % (self.gidCaller.get_urn(), self.gidObject.get_urn(), root_cred_signer.get_hrn(), root_target_gid.get_hrn())) + + + ## + # -- For Delegates (credentials with parents) verify that: + # . The privileges must be a subset of the parent credentials + # . The privileges must have "can_delegate" set for each delegated privilege + # . The target gid must be the same between child and parents + # . The expiry time on the child must be no later than the parent + # . The signer of the child must be the owner of the parent + def verify_parent(self, parent_cred): + # make sure the rights given to the child are a subset of the + # parents rights (and check delegate bits) + if not parent_cred.get_privileges().is_superset(self.get_privileges()): + raise ChildRightsNotSubsetOfParent(("Parent cred ref %s rights " % parent_cred.get_refid()) + + self.parent.get_privileges().save_to_string() + (" not superset of delegated cred %s ref %s rights " % (self.get_summary_tostring(), self.get_refid())) + + self.get_privileges().save_to_string()) + + # make sure my target gid is the same as the parent's + if not parent_cred.get_gid_object().save_to_string() == \ + self.get_gid_object().save_to_string(): + raise CredentialNotVerifiable("Delegated cred %s: Target gid not equal between parent and child. Parent %s" % (self.get_summary_tostring(), parent_cred.get_summary_tostring())) + + # make sure my expiry time is <= my parent's + if not parent_cred.get_expiration() >= self.get_expiration(): + raise CredentialNotVerifiable("Delegated credential %s expires after parent %s" % (self.get_summary_tostring(), parent_cred.get_summary_tostring())) + + # make sure my signer is the parent's caller + if not parent_cred.get_gid_caller().save_to_string(False) == \ + self.get_signature().get_issuer_gid().save_to_string(False): + raise CredentialNotVerifiable("Delegated credential %s not signed by parent %s's caller" % (self.get_summary_tostring(), parent_cred.get_summary_tostring())) + + # Recurse + if parent_cred.parent: + parent_cred.verify_parent(parent_cred.parent) + + + def delegate(self, delegee_gidfile, caller_keyfile, caller_gidfile): + """ + Return a delegated copy of this credential, delegated to the + specified gid's user. + """ + # get the gid of the object we are delegating + object_gid = self.get_gid_object() + object_hrn = object_gid.get_hrn() + + # the hrn of the user who will be delegated to + delegee_gid = GID(filename=delegee_gidfile) + delegee_hrn = delegee_gid.get_hrn() + + #user_key = Keypair(filename=keyfile) + #user_hrn = self.get_gid_caller().get_hrn() + subject_string = "%s delegated to %s" % (object_hrn, delegee_hrn) + dcred = Credential(subject=subject_string) + dcred.set_gid_caller(delegee_gid) + dcred.set_gid_object(object_gid) + dcred.set_parent(self) + dcred.set_expiration(self.get_expiration()) + dcred.set_privileges(self.get_privileges()) + dcred.get_privileges().delegate_all_privileges(True) + #dcred.set_issuer_keys(keyfile, delegee_gidfile) + dcred.set_issuer_keys(caller_keyfile, caller_gidfile) + dcred.encode() + dcred.sign() + + return dcred + + # only informative + def get_filename(self): + return getattr(self,'filename',None) + + ## + # Dump the contents of a credential to stdout in human-readable format + # + # @param dump_parents If true, also dump the parent certificates + def dump (self, *args, **kwargs): + print self.dump_string(*args, **kwargs) + + + def dump_string(self, dump_parents=False, show_xml=False): + result="" + result += "CREDENTIAL %s\n" % self.get_subject() + filename=self.get_filename() + if filename: result += "Filename %s\n"%filename + result += " privs: %s\n" % self.get_privileges().save_to_string() + gidCaller = self.get_gid_caller() + if gidCaller: + result += " gidCaller:\n" + result += gidCaller.dump_string(8, dump_parents) + + if self.get_signature(): + result += " gidIssuer:\n" + result += self.get_signature().get_issuer_gid().dump_string(8, dump_parents) + + if self.expiration: + result += " expiration: " + self.expiration.isoformat() + "\n" + + gidObject = self.get_gid_object() + if gidObject: + result += " gidObject:\n" + result += gidObject.dump_string(8, dump_parents) + + if self.parent and dump_parents: + result += "\nPARENT" + result += self.parent.dump_string(True) + + if show_xml and HAVELXML: + try: + tree = etree.parse(StringIO(self.xml)) + aside = etree.tostring(tree, pretty_print=True) + result += "\nXML:\n\n" + result += aside + result += "\nEnd XML\n" + except: + import traceback + print "exc. Credential.dump_string / XML" + traceback.print_exc() + + return result diff --git a/core/lib/am/credentials/src/trustgcf/credential_factory.py b/core/lib/am/credentials/src/trustgcf/credential_factory.py new file mode 100644 index 00000000..1eed25e5 --- /dev/null +++ b/core/lib/am/credentials/src/trustgcf/credential_factory.py @@ -0,0 +1,109 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2014 Raytheon BBN Technologies +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- + +from __future__ import absolute_import + +from credentials.src.trustgcf.credential import Credential +from credentials.src.trustgcf.abac_credential import ABACCredential + +import json +import re + +# Factory for creating credentials of different sorts by type. +# Specifically, this factory can create standard SFA credentials +# and ABAC credentials from XML strings based on their identifying content + +class CredentialFactory: + + UNKNOWN_CREDENTIAL_TYPE = 'geni_unknown' + + # Static Credential class method to determine the type of a credential + # string depending on its contents + @staticmethod + def getType(credString): + credString_nowhitespace = re.sub('\s', '', credString) + if credString_nowhitespace.find('abac') > -1: + return ABACCredential.ABAC_CREDENTIAL_TYPE + elif credString_nowhitespace.find('privilege') > -1: + return Credential.SFA_CREDENTIAL_TYPE + else: + st = credString_nowhitespace.find('') + end = credString_nowhitespace.find('', st) + return credString_nowhitespace[st + len(''):end] +# return CredentialFactory.UNKNOWN_CREDENTIAL_TYPE + + # Static Credential class method to create the appropriate credential + # (SFA or ABAC) depending on its type + @staticmethod + def createCred(credString=None, credFile=None): + if not credString and not credFile: + raise Exception("CredentialFactory.createCred called with no argument") + if credFile: + try: + credString = open(credFile).read() + except Exception, e: + return None + + # Try to treat the file as JSON, getting the cred_type from the struct + try: + credO = json.loads(credString, encoding='ascii') + if credO.has_key('geni_value') and credO.has_key('geni_type'): + cred_type = credO['geni_type'] + credString = credO['geni_value'] + except Exception, e: + # It wasn't a struct. So the credString is XML. Pull the type directly from the string + cred_type = CredentialFactory.getType(credString) + + if cred_type == Credential.SFA_CREDENTIAL_TYPE: + try: + cred = Credential(string=credString) + return cred + except Exception, e: + if credFile: + msg = "credString started: %s" % credString[:50] + raise Exception("%s not a parsable SFA credential: %s. " % (credFile, e) + msg) + else: + raise Exception("SFA Credential not parsable: %s. Cred start: %s..." % (e, credString[:50])) + + elif cred_type == ABACCredential.ABAC_CREDENTIAL_TYPE: + try: + cred = ABACCredential(string=credString) + return cred + except Exception, e: + if credFile: + raise Exception("%s not a parsable ABAC credential: %s" % (credFile, e)) + else: + raise Exception("ABAC Credential not parsable: %s. Cred start: %s..." % (e, credString[:50])) + else: + raise Exception("Unknown credential type '%s'" % cred_type) + +if __name__ == "__main__": + c2 = open('/tmp/sfa.xml').read() + cred1 = CredentialFactory.createCred(credFile='/tmp/cred.xml') + cred2 = CredentialFactory.createCred(credString=c2) + + print "C1 = %s" % cred1 + print "C2 = %s" % cred2 + c1s = cred1.dump_string() + print "C1 = %s" % c1s +# print "C2 = %s" % cred2.dump_string() diff --git a/core/lib/am/credentials/src/trustgcf/credential_legacy.py b/core/lib/am/credentials/src/trustgcf/credential_legacy.py new file mode 100644 index 00000000..016412bc --- /dev/null +++ b/core/lib/am/credentials/src/trustgcf/credential_legacy.py @@ -0,0 +1,272 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- +## +# Implements SFA Credentials +# +# Credentials are layered on top of certificates, and are essentially a +# certificate that stores a tuple of parameters. +## + +from __future__ import absolute_import + +import xmlrpclib + +from geniutils.src.faults.faults import MissingDelegateBit, ChildRightsNotSubsetOfParent +from credentials.src.trustgcf.certificate import Certificate +from credentials.src.trustgcf.gid import GID +from credentials.src.trustgcf.rights import Rights + +## +# Credential is a tuple: +# (GIDCaller, GIDObject, LifeTime, Privileges, Delegate) +# +# These fields are encoded using xmlrpc into the subjectAltName field of the +# x509 certificate. Note: Call encode() once the fields have been filled in +# to perform this encoding. + +class CredentialLegacy(Certificate): + gidCaller = None + gidObject = None + lifeTime = None + privileges = None + delegate = False + + ## + # Create a Credential object + # + # @param create If true, create a blank x509 certificate + # @param subject If subject!=None, create an x509 cert with the subject name + # @param string If string!=None, load the credential from the string + # @param filename If filename!=None, load the credential from the file + + def __init__(self, create=False, subject=None, string=None, filename=None): + Certificate.__init__(self, create, subject, string, filename) + + ## + # set the GID of the caller + # + # @param gid GID object of the caller + + def set_gid_caller(self, gid): + self.gidCaller = gid + # gid origin caller is the caller's gid by default + self.gidOriginCaller = gid + + ## + # get the GID of the object + + def get_gid_caller(self): + if not self.gidCaller: + self.decode() + return self.gidCaller + + ## + # set the GID of the object + # + # @param gid GID object of the object + + def set_gid_object(self, gid): + self.gidObject = gid + + ## + # get the GID of the object + + def get_gid_object(self): + if not self.gidObject: + self.decode() + return self.gidObject + + ## + # set the lifetime of this credential + # + # @param lifetime lifetime of credential + + def set_lifetime(self, lifeTime): + self.lifeTime = lifeTime + + ## + # get the lifetime of the credential + + def get_lifetime(self): + if not self.lifeTime: + self.decode() + return self.lifeTime + + ## + # set the delegate bit + # + # @param delegate boolean (True or False) + + def set_delegate(self, delegate): + self.delegate = delegate + + ## + # get the delegate bit + + def get_delegate(self): + if not self.delegate: + self.decode() + return self.delegate + + ## + # set the privileges + # + # @param privs either a comma-separated list of privileges of a Rights object + + def set_privileges(self, privs): + if isinstance(privs, str): + self.privileges = Rights(string = privs) + else: + self.privileges = privs + + ## + # return the privileges as a Rights object + + def get_privileges(self): + if not self.privileges: + self.decode() + return self.privileges + + ## + # determine whether the credential allows a particular operation to be + # performed + # + # @param op_name string specifying name of operation ("lookup", "update", etc) + + def can_perform(self, op_name): + rights = self.get_privileges() + if not rights: + return False + return rights.can_perform(op_name) + + ## + # Encode the attributes of the credential into a string and store that + # string in the alt-subject-name field of the X509 object. This should be + # done immediately before signing the credential. + + def encode(self): + dict = {"gidCaller": None, + "gidObject": None, + "lifeTime": self.lifeTime, + "privileges": None, + "delegate": self.delegate} + if self.gidCaller: + dict["gidCaller"] = self.gidCaller.save_to_string(save_parents=True) + if self.gidObject: + dict["gidObject"] = self.gidObject.save_to_string(save_parents=True) + if self.privileges: + dict["privileges"] = self.privileges.save_to_string() + str = xmlrpclib.dumps((dict,), allow_none=True) + self.set_data('URI:http://' + str) + + ## + # Retrieve the attributes of the credential from the alt-subject-name field + # of the X509 certificate. This is automatically done by the various + # get_* methods of this class and should not need to be called explicitly. + + def decode(self): + data = self.get_data().lstrip('URI:http://') + + if data: + dict = xmlrpclib.loads(data)[0][0] + else: + dict = {} + + self.lifeTime = dict.get("lifeTime", None) + self.delegate = dict.get("delegate", None) + + privStr = dict.get("privileges", None) + if privStr: + self.privileges = Rights(string = privStr) + else: + self.privileges = None + + gidCallerStr = dict.get("gidCaller", None) + if gidCallerStr: + self.gidCaller = GID(string=gidCallerStr) + else: + self.gidCaller = None + + gidObjectStr = dict.get("gidObject", None) + if gidObjectStr: + self.gidObject = GID(string=gidObjectStr) + else: + self.gidObject = None + + ## + # Verify that a chain of credentials is valid (see cert.py:verify). In + # addition to the checks for ordinary certificates, verification also + # ensures that the delegate bit was set by each parent in the chain. If + # a delegate bit was not set, then an exception is thrown. + # + # Each credential must be a subset of the rights of the parent. + + def verify_chain(self, trusted_certs = None): + # do the normal certificate verification stuff + Certificate.verify_chain(self, trusted_certs) + + if self.parent: + # make sure the parent delegated rights to the child + if not self.parent.get_delegate(): + raise MissingDelegateBit(self.parent.get_subject()) + + # make sure the rights given to the child are a subset of the + # parents rights + if not self.parent.get_privileges().is_superset(self.get_privileges()): + raise ChildRightsNotSubsetOfParent(self.get_subject() + + " " + self.parent.get_privileges().save_to_string() + + " " + self.get_privileges().save_to_string()) + + return + + ## + # Dump the contents of a credential to stdout in human-readable format + # + # @param dump_parents If true, also dump the parent certificates + + def dump(self, *args, **kwargs): + print self.dump_string(*args,**kwargs) + + def dump_string(self, dump_parents=False): + result="" + result += "CREDENTIAL %s\n" % self.get_subject() + + result += " privs: %s\n" % self.get_privileges().save_to_string() + + gidCaller = self.get_gid_caller() + if gidCaller: + result += " gidCaller:\n" + gidCaller.dump(8, dump_parents) + + gidObject = self.get_gid_object() + if gidObject: + result += " gidObject:\n" + result += gidObject.dump_string(8, dump_parents) + + result += " delegate: %s" % self.get_delegate() + + if self.parent and dump_parents: + result += "PARENT\n" + result += self.parent.dump_string(dump_parents) + + return result diff --git a/core/lib/am/credentials/src/trustgcf/gid.py b/core/lib/am/credentials/src/trustgcf/gid.py new file mode 100644 index 00000000..a798ffa4 --- /dev/null +++ b/core/lib/am/credentials/src/trustgcf/gid.py @@ -0,0 +1,259 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- +## +# Implements SFA GID. GIDs are based on certificates, and the GID class is a +# descendant of the certificate class. +## + +from __future__ import absolute_import + +import xmlrpclib +import uuid + +from credentials.src.trustgcf.certificate import Certificate +from geniutils.src.faults.faults import GidInvalidParentHrn, GidParentHrn +from geniutils.src.xrn.xrn import hrn_to_urn, urn_to_hrn, hrn_authfor_hrn + +## +# Create a new uuid. Returns the UUID as a string. + +def create_uuid(): + return str(uuid.uuid4().int) + +## +# GID is a tuple: +# (uuid, urn, public_key) +# +# UUID is a unique identifier and is created by the python uuid module +# (or the utility function create_uuid() in gid.py). +# +# HRN is a human readable name. It is a dotted form similar to a backward domain +# name. For example, planetlab.us.arizona.bakers. +# +# URN is a human readable identifier of form: +# "urn:publicid:IDN+toplevelauthority[:sub-auth.]*[\res. type]\ +object name" +# For example, urn:publicid:IDN+planetlab:us:arizona+user+bakers +# +# PUBLIC_KEY is the public key of the principal identified by the UUID/HRN. +# It is a Keypair object as defined in the cert.py module. +# +# It is expected that there is a one-to-one pairing between UUIDs and HRN, +# but it is uncertain how this would be inforced or if it needs to be enforced. +# +# These fields are encoded using xmlrpc into the subjectAltName field of the +# x509 certificate. Note: Call encode() once the fields have been filled in +# to perform this encoding. + + +class GID(Certificate): + ## + # Create a new GID object + # + # @param create If true, create the X509 certificate + # @param subject If subject!=None, create the X509 cert and set the subject name + # @param string If string!=None, load the GID from a string + # @param filename If filename!=None, load the GID from a file + # @param lifeDays life of GID in days - default is 1825==5 years + # @param email Email address to put in subjectAltName - default is None + def __init__(self, create=False, subject=None, string=None, filename=None, uuid=None, hrn=None, urn=None, lifeDays=1825, email=None): + self.uuid = None + self.hrn = None + self.urn = None + self.email = None # for adding to the SubjectAltName + Certificate.__init__(self, lifeDays, create, subject, string, filename) + + if subject: + pass + if uuid: + self.uuid = int(uuid) + if hrn: + self.hrn = hrn + self.urn = hrn_to_urn(hrn, 'unknown') + if urn: + self.urn = urn + self.hrn, type = urn_to_hrn(urn) + if email: + self.set_email(email) + + def set_uuid(self, uuid): + if isinstance(uuid, str): + self.uuid = int(uuid) + else: + self.uuid = uuid + + def get_uuid(self): + if not self.uuid: + self.decode() + return self.uuid + + def set_hrn(self, hrn): + self.hrn = hrn + + def get_hrn(self): + if not self.hrn: + self.decode() + return self.hrn + + def set_urn(self, urn): + self.urn = urn + self.hrn, type = urn_to_hrn(urn) + + def get_urn(self): + if not self.urn: + self.decode() + return self.urn + + # Will be stuffed into subjectAltName + def set_email(self, email): + self.email = email + + def get_email(self): + if not self.email: + self.decode() + return self.email + + def get_type(self): + if not self.urn: + self.decode() + _, t = urn_to_hrn(self.urn) + return t + + ## + # Encode the GID fields and package them into the subject-alt-name field + # of the X509 certificate. This must be called prior to signing the + # certificate. It may only be called once per certificate. + + def encode(self): + if self.urn: + urn = self.urn + else: + urn = hrn_to_urn(self.hrn, None) + + str = "URI:" + urn + + if self.uuid: + str += ", " + "URI:" + uuid.UUID(int=self.uuid).urn + + if self.email: + str += ", " + "email:" + self.email + + self.set_data(str, 'subjectAltName') + + + ## + # Decode the subject-alt-name field of the X509 certificate into the + # fields of the GID. This is automatically called by the various get_*() + # functions in this class. + + def decode(self): + data = self.get_data('subjectAltName') + dict = {} + if data: + if data.lower().startswith('uri:http://'): + dict = xmlrpclib.loads(data[11:])[0][0] + else: + spl = data.split(', ') + for val in spl: + if val.lower().startswith('uri:urn:uuid:'): + dict['uuid'] = uuid.UUID(val[4:]).int + elif val.lower().startswith('uri:urn:publicid:idn+'): + dict['urn'] = val[4:] + elif val.lower().startswith('email:'): + # FIXME: Ensure there isn't cruft in that address... + # EG look for email:copy,.... + dict['email'] = val[6:] + + self.uuid = dict.get("uuid", None) + self.urn = dict.get("urn", None) + self.hrn = dict.get("hrn", None) + self.email = dict.get("email", None) + if self.urn: + self.hrn = urn_to_hrn(self.urn)[0] + + ## + # Dump the credential to stdout. + # + # @param indent specifies a number of spaces to indent the output + # @param dump_parents If true, also dump the parents of the GID + + def dump(self, *args, **kwargs): + print self.dump_string(*args,**kwargs) + + def dump_string(self, indent=0, dump_parents=False): + result=" "*(indent-2) + "GID\n" + result += " "*indent + "hrn:" + str(self.get_hrn()) +"\n" + result += " "*indent + "urn:" + str(self.get_urn()) +"\n" + result += " "*indent + "uuid:" + str(self.get_uuid()) + "\n" + if self.get_email() is not None: + result += " "*indent + "email:" + str(self.get_email()) + "\n" + filename=self.get_filename() + if filename: result += "Filename %s\n"%filename + + if self.parent and dump_parents: + result += " "*indent + "parent:\n" + result += self.parent.dump_string(indent+4, dump_parents) + return result + + ## + # Verify the chain of authenticity of the GID. First perform the checks + # of the certificate class (verifying that each parent signs the child, + # etc). In addition, GIDs also confirm that the parent's HRN is a prefix + # of the child's HRN, and the parent is of type 'authority'. + # + # Verifying these prefixes prevents a rogue authority from signing a GID + # for a principal that is not a member of that authority. For example, + # planetlab.us.arizona cannot sign a GID for planetlab.us.princeton.foo. + + def verify_chain(self, trusted_certs = None): + # do the normal certificate verification stuff + trusted_root = Certificate.verify_chain(self, trusted_certs) + + if self.parent: + # make sure the parent's hrn is a prefix of the child's hrn + if not hrn_authfor_hrn(self.parent.get_hrn(), self.get_hrn()): + raise GidParentHrn("This cert HRN %s isn't in the namespace for parent HRN %s" % (self.get_hrn(), self.parent.get_hrn())) + + # Parent must also be an authority (of some type) to sign a GID + # There are multiple types of authority - accept them all here + if not self.parent.get_type().find('authority') == 0: + raise GidInvalidParentHrn("This cert %s's parent %s is not an authority (is a %s)" % (self.get_hrn(), self.parent.get_hrn(), self.parent.get_type())) + + # Then recurse up the chain - ensure the parent is a trusted + # root or is in the namespace of a trusted root + self.parent.verify_chain(trusted_certs) + else: + # make sure that the trusted root's hrn is a prefix of the child's + trusted_gid = GID(string=trusted_root.save_to_string()) + trusted_type = trusted_gid.get_type() + trusted_hrn = trusted_gid.get_hrn() + #if trusted_type == 'authority': + # trusted_hrn = trusted_hrn[:trusted_hrn.rindex('.')] + cur_hrn = self.get_hrn() + if not hrn_authfor_hrn(trusted_hrn, cur_hrn): + raise GidParentHrn("Trusted root with HRN %s isn't a namespace authority for this cert: %s" % (trusted_hrn, cur_hrn)) + + # There are multiple types of authority - accept them all here + if not trusted_type.find('authority') == 0: + raise GidInvalidParentHrn("This cert %s's trusted root signer %s is not an authority (is a %s)" % (self.get_hrn(), trusted_hrn, trusted_type)) + + return diff --git a/core/lib/am/credentials/src/trustgcf/rights.py b/core/lib/am/credentials/src/trustgcf/rights.py new file mode 100644 index 00000000..7fa4fa43 --- /dev/null +++ b/core/lib/am/credentials/src/trustgcf/rights.py @@ -0,0 +1,276 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- + +## +# This Module implements rights and lists of rights for the SFA. Rights +# are implemented by two classes: +# +# Right - represents a single right +# +# Rights - represents a list of rights +# +# A right may allow several different operations. For example, the "info" right +# allows "listslices", "listcomponentresources", etc. +## + + + +## +# privilege_table is a list of priviliges and what operations are allowed +# per privilege. +# Note that "*" is a privilege granted by ProtoGENI slice authorities, and we +# give it access to the GENI AM calls + +privilege_table = {"authority": ["register", "remove", "update", "resolve", "list", "getcredential", "*"], + "refresh": ["remove", "update"], + "resolve": ["resolve", "list", "getcredential"], + "sa": ["getticket", "redeemslice", "redeemticket", "createslice", "createsliver", "deleteslice", "deletesliver", "updateslice", + "getsliceresources", "getticket", "loanresources", "stopslice", "startslice", "renewsliver", + "deleteslice", "deletesliver", "resetslice", "listslices", "listnodes", "getpolicy", "sliverstatus"], + "embed": ["getticket", "redeemslice", "redeemticket", "createslice", "createsliver", "renewsliver", "deleteslice", + "deletesliver", "updateslice", "sliverstatus", "getsliceresources", "shutdown"], + "bind": ["getticket", "loanresources", "redeemticket"], + "control": ["updateslice", "createslice", "createsliver", "renewsliver", "sliverstatus", "stopslice", "startslice", + "deleteslice", "deletesliver", "resetslice", "getsliceresources", "getgids"], + "info": ["listslices", "listnodes", "getpolicy"], + "ma": ["setbootstate", "getbootstate", "reboot", "getgids", "gettrustedcerts"], + "operator": ["gettrustedcerts", "getgids"], + "*": ["createsliver", "deletesliver", "sliverstatus", "renewsliver", "shutdown"]} + + + +## +# Determine the rights that an object should have. The rights are entirely +# dependent on the type of the object. For example, users automatically +# get "refresh", "resolve", and "info". +# +# @param type the type of the object (user | sa | ma | slice | node) +# @param name human readable name of the object (not used at this time) +# +# @return Rights object containing rights + +def determine_rights(type, name): + rl = Rights() + + # rights seem to be somewhat redundant with the type of the credential. + # For example, a "sa" credential implies the authority right, because + # a sa credential cannot be issued to a user who is not an owner of + # the authority + if type == "user": + rl.add("refresh") + rl.add("resolve") + rl.add("info") + elif type in ["sa", "authority+sa"]: + rl.add("authority") + rl.add("sa") + elif type in ["ma", "authority+ma", "cm", "authority+cm", "sm", "authority+sm"]: + rl.add("authority") + rl.add("ma") + elif type == "authority": + rl.add("authority") + rl.add("sa") + rl.add("ma") + elif type == "slice": + rl.add("refresh") + rl.add("embed") + rl.add("bind") + rl.add("control") + rl.add("info") +# wouldn't that be authority+cm instead ? + elif type == "component": + rl.add("operator") + return rl + + +## +# The Right class represents a single privilege. + + + +class Right: + ## + # Create a new right. + # + # @param kind is a string naming the right. For example "control" + + def __init__(self, kind, delegate=False): + self.kind = kind + self.delegate = delegate + + def __repr__ (self): return ""%self.kind + + ## + # Test to see if this right object is allowed to perform an operation. + # Returns True if the operation is allowed, False otherwise. + # + # @param op_name is a string naming the operation. For example "listslices". + + def can_perform(self, op_name): + allowed_ops = privilege_table.get(self.kind.lower(), None) + if not allowed_ops: + return False + + # if "*" is specified, then all ops are permitted + if "*" in allowed_ops: + return True + + return (op_name.lower() in allowed_ops) + + ## + # Test to see if this right is a superset of a child right. A right is a + # superset if every operating that is allowed by the child is also allowed + # by this object. + # + # @param child is a Right object describing the child right + + def is_superset(self, child): + my_allowed_ops = privilege_table.get(self.kind.lower(), None) + child_allowed_ops = privilege_table.get(child.kind.lower(), None) + + if not self.delegate: + return False + + if "*" in my_allowed_ops: + return True + + for right in child_allowed_ops: + if not right in my_allowed_ops: + return False + + return True + +## +# A Rights object represents a list of privileges. + +class Rights: + ## + # Create a new rightlist object, containing no rights. + # + # @param string if string!=None, load the rightlist from the string + + def __init__(self, string=None): + self.rights = [] + if string: + self.load_from_string(string) + + def __repr__ (self): return "[" + " ".join( ["%s"%r for r in self.rights]) + "]" + + def is_empty(self): + return self.rights == [] + + ## + # Add a right to this list + # + # @param right is either a Right object or a string describing the right + + def add(self, right, delegate=False): + if isinstance(right, str): + right = Right(right, delegate) + self.rights.append(right) + + ## + # Load the rightlist object from a string + + def load_from_string(self, string): + self.rights = [] + + # none == no rights, so leave the list empty + if not string: + return + + parts = string.split(",") + for part in parts: + if ':' in part: + spl = part.split(':') + kind = spl[0].strip() + delegate = bool(int(spl[1])) + else: + kind = part.strip() + delegate = 0 + self.rights.append(Right(kind, bool(delegate))) + + ## + # Save the rightlist object to a string. It is saved in the format of a + # comma-separated list. + + def save_to_string(self): + right_names = [] + for right in self.rights: + right_names.append('%s:%d' % (right.kind.strip(), right.delegate)) + + return ",".join(right_names) + + ## + # Check to see if some right in this list allows an operation. This is + # done by evaluating the can_perform function of each operation in the + # list. + # + # @param op_name is an operation to check, for example "listslices" + + def can_perform(self, op_name): + + for right in self.rights: + if right.can_perform(op_name): + return True + return False + + ## + # Check to see if all of the rights in this rightlist are a superset + # of all the rights in a child rightlist. A rightlist is a superset + # if there is no operation in the child rightlist that cannot be + # performed in the parent rightlist. + # + # @param child is a rightlist object describing the child + + def is_superset(self, child): + for child_right in child.rights: + allowed = False + for my_right in self.rights: + if my_right.is_superset(child_right): + allowed = True + break + if not allowed: + return False + return True + + + ## + # set the delegate bit to 'delegate' on + # all privileges + # + # @param delegate boolean (True or False) + + def delegate_all_privileges(self, delegate): + for right in self.rights: + right.delegate = delegate + + ## + # true if all privileges have delegate bit set true + # false otherwise + + def get_all_delegate(self): + for right in self.rights: + if not right.delegate: + return False + return True + diff --git a/core/lib/am/credentials/src/trustgcf/speaksfor_util.py b/core/lib/am/credentials/src/trustgcf/speaksfor_util.py new file mode 100644 index 00000000..feecef2b --- /dev/null +++ b/core/lib/am/credentials/src/trustgcf/speaksfor_util.py @@ -0,0 +1,455 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2014 Raytheon BBN Technologies +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- + +from __future__ import absolute_import + +import datetime +from dateutil import parser as du_parser, tz as du_tz +import optparse +import os +import subprocess +import sys +import tempfile +from xml.dom.minidom import * +from StringIO import StringIO + +from credentials.src.trustgcf.abac_credential import ABACCredential, ABACElement +from credentials.src.trustgcf.certificate import Certificate +from credentials.src.trustgcf.credential import Credential, signature_template, HAVELXML +from credentials.src.trustgcf.credential_factory import CredentialFactory +from credentials.src.trustgcf.gid import GID + + +# Routine to validate that a speaks-for credential +# says what it claims to say: +# It is a signed credential wherein the signer S is attesting to the +# ABAC statement: +# S.speaks_for(S)<-T Or "S says that T speaks for S" + +# Requires that openssl be installed and in the path +# create_speaks_for requires that xmlsec1 be on the path + +# Simple XML helper functions + +# Find the text associated with first child text node +def findTextChildValue(root): + child = findChildNamed(root, '#text') + if child: return str(child.nodeValue) + return None + +# Find first child with given name +def findChildNamed(root, name): + for child in root.childNodes: + if child.nodeName == name: + return child + return None + +# Write a string to a tempfile, returning name of tempfile +def write_to_tempfile(str): + str_fd, str_file = tempfile.mkstemp() + if str: + os.write(str_fd, str) + os.close(str_fd) + return str_file + +# Run a subprocess and return output +def run_subprocess(cmd, stdout, stderr): + try: + proc = subprocess.Popen(cmd, stdout=stdout, stderr=stderr) + proc.wait() + if stdout: + output = proc.stdout.read() + else: + output = proc.returncode + return output + except Exception as e: + raise Exception("Failed call to subprocess '%s': %s" % (" ".join(cmd), e)) + +def get_cert_keyid(gid): + """Extract the subject key identifier from the given certificate. + Return they key id as lowercase string with no colon separators + between pairs. The key id as shown in the text output of a + certificate are in uppercase with colon separators. + + """ + raw_key_id = gid.get_extension('subjectKeyIdentifier') + # Raw has colons separating pairs, and all characters are upper case. + # Remove the colons and convert to lower case. + keyid = raw_key_id.replace(':', '').lower() + return keyid + +# Pull the cert out of a list of certs in a PEM formatted cert string +def grab_toplevel_cert(cert): + start_label = '-----BEGIN CERTIFICATE-----' + if cert.find(start_label) > -1: + start_index = cert.find(start_label) + len(start_label) + else: + start_index = 0 + end_label = '-----END CERTIFICATE-----' + end_index = cert.find(end_label) + first_cert = cert[start_index:end_index] + pieces = first_cert.split('\n') + first_cert = "".join(pieces) + return first_cert + +# Validate that the given speaks-for credential represents the +# statement User.speaks_for(User)<-Tool for the given user and tool certs +# and was signed by the user +# Return: +# Boolean indicating whether the given credential +# is not expired +# is an ABAC credential +# was signed by the user associated with the speaking_for_urn +# is verified by xmlsec1 +# asserts U.speaks_for(U)<-T ("user says that T may speak for user") +# If schema provided, validate against schema +# is trusted by given set of trusted roots (both user cert and tool cert) +# String user certificate of speaking_for user if the above tests succeed +# (None otherwise) +# Error message indicating why the speaks_for call failed ("" otherwise) +def verify_speaks_for(cred, tool_gid, speaking_for_urn, \ + trusted_roots, schema=None, logger=None): + + # Credential has not expired + if cred.expiration and cred.expiration < datetime.datetime.utcnow(): + return False, None, "ABAC Credential expired at %s (%s)" % (cred.expiration.isoformat(), cred.get_summary_tostring()) + + # Must be ABAC + if cred.get_cred_type() != ABACCredential.ABAC_CREDENTIAL_TYPE: + return False, None, "Credential not of type ABAC but %s" % cred.get_cred_type + + if cred.signature is None or cred.signature.gid is None: + return False, None, "Credential malformed: missing signature or signer cert. Cred: %s" % cred.get_summary_tostring() + user_gid = cred.signature.gid + user_urn = user_gid.get_urn() + + # URN of signer from cert must match URN of 'speaking-for' argument + if user_urn != speaking_for_urn: + return False, None, "User URN from cred doesn't match speaking_for URN: %s != %s (cred %s)" % \ + (user_urn, speaking_for_urn, cred.get_summary_tostring()) + + tails = cred.get_tails() + if len(tails) != 1: + return False, None, "Invalid ABAC-SF credential: Need exactly 1 tail element, got %d (%s)" % \ + (len(tails), cred.get_summary_tostring()) + + user_keyid = get_cert_keyid(user_gid) + tool_keyid = get_cert_keyid(tool_gid) + subject_keyid = tails[0].get_principal_keyid() + + head = cred.get_head() + principal_keyid = head.get_principal_keyid() + role = head.get_role() + + # Credential must pass xmlsec1 verify + cred_file = write_to_tempfile(cred.save_to_string()) + cert_args = [] + if trusted_roots: + for x in trusted_roots: + cert_args += ['--trusted-pem', x.filename] + # FIXME: Why do we not need to specify the --node-id option as credential.py does? + xmlsec1_args = [cred.xmlsec_path, '--verify'] + cert_args + [ cred_file] + output = run_subprocess(xmlsec1_args, stdout=None, stderr=subprocess.PIPE) + os.unlink(cred_file) + if output != 0: + # FIXME + # xmlsec errors have a msg= which is the interesting bit. + # But does this go to stderr or stdout? Do we have it here? + verified = "" + mstart = verified.find("msg=") + msg = "" + if mstart > -1 and len(verified) > 4: + mstart = mstart + 4 + mend = verified.find('\\', mstart) + msg = verified[mstart:mend] + if msg == "": + msg = output + return False, None, "ABAC credential failed to xmlsec1 verify: %s" % msg + + # Must say U.speaks_for(U)<-T + if user_keyid != principal_keyid or \ + tool_keyid != subject_keyid or \ + role != ('speaks_for_%s' % user_keyid): + return False, None, "ABAC statement doesn't assert U.speaks_for(U)<-T (%s)" % cred.get_summary_tostring() + + # If schema provided, validate against schema + if HAVELXML and schema and os.path.exists(schema): + from lxml import etree + tree = etree.parse(StringIO(cred.xml)) + schema_doc = etree.parse(schema) + xmlschema = etree.XMLSchema(schema_doc) + if not xmlschema.validate(tree): + error = xmlschema.error_log.last_error + message = "%s: %s (line %s)" % (cred.get_summary_tostring(), error.message, error.line) + return False, None, ("XML Credential schema invalid: %s" % message) + + if trusted_roots: + # User certificate must validate against trusted roots + try: + user_gid.verify_chain(trusted_roots) + except Exception, e: + return False, None, \ + "Cred signer (user) cert not trusted: %s" % e + + # Tool certificate must validate against trusted roots + try: + tool_gid.verify_chain(trusted_roots) + except Exception, e: + return False, None, \ + "Tool cert not trusted: %s" % e + + return True, user_gid, "" + +# Determine if this is a speaks-for context. If so, validate +# And return either the tool_cert (not speaks-for or not validated) +# or the user cert (validated speaks-for) +# +# credentials is a list of GENI-style credentials: +# Either a cred string xml string, or Credential object of a tuple +# [{'geni_type' : geni_type, 'geni_value : cred_value, +# 'geni_version' : version}] +# caller_gid is the raw X509 cert gid +# options is the dictionary of API-provided options +# trusted_roots is a list of Certificate objects from the system +# trusted_root directory +# Optionally, provide an XML schema against which to validate the credential +def determine_speaks_for(logger, credentials, caller_gid, options, \ + trusted_roots, schema=None): + if options and 'geni_speaking_for' in options: + speaking_for_urn = options['geni_speaking_for'].strip() + for cred in credentials: + # Skip things that aren't ABAC credentials + if type(cred) == dict: + if cred['geni_type'] != ABACCredential.ABAC_CREDENTIAL_TYPE: continue + cred_value = cred['geni_value'] + elif isinstance(cred, Credential): + if not isinstance(cred, ABACCredential): + continue + else: + cred_value = cred + else: + if CredentialFactory.getType(cred) != ABACCredential.ABAC_CREDENTIAL_TYPE: continue + cred_value = cred + + # If the cred_value is xml, create the object + if not isinstance(cred_value, ABACCredential): + cred = CredentialFactory.createCred(cred_value) + +# print "Got a cred to check speaksfor for: %s" % cred.get_summary_tostring() +# #cred.dump(True, True) +# print "Caller: %s" % caller_gid.dump_string(2, True) + + # See if this is a valid speaks_for + is_valid_speaks_for, user_gid, msg = \ + verify_speaks_for(cred, + caller_gid, speaking_for_urn, \ + trusted_roots, schema, logger) + + if is_valid_speaks_for: + return user_gid # speaks-for + else: + if logger: + logger.info("Got speaks-for option but not a valid speaks_for with this credential: %s" % msg) + else: + print "Got a speaks-for option but not a valid speaks_for with this credential: " + msg + return caller_gid # Not speaks-for + +# Create an ABAC Speaks For credential using the ABACCredential object and it's encode&sign methods +def create_sign_abaccred(tool_gid, user_gid, ma_gid, user_key_file, cred_filename, dur_days=365): + print "Creating ABAC SpeaksFor using ABACCredential...\n" + # Write out the user cert + from tempfile import mkstemp + ma_str = ma_gid.save_to_string() + user_cert_str = user_gid.save_to_string() + if not user_cert_str.endswith(ma_str): + user_cert_str += ma_str + fp, user_cert_filename = mkstemp(suffix='cred', text=True) + fp = os.fdopen(fp, "w") + fp.write(user_cert_str) + fp.close() + + # Create the cred + cred = ABACCredential() + cred.set_issuer_keys(user_key_file, user_cert_filename) + tool_urn = tool_gid.get_urn() + user_urn = user_gid.get_urn() + user_keyid = get_cert_keyid(user_gid) + tool_keyid = get_cert_keyid(tool_gid) + cred.head = ABACElement(user_keyid, user_urn, "speaks_for_%s" % user_keyid) + cred.tails.append(ABACElement(tool_keyid, tool_urn)) + cred.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(days=dur_days)) + cred.expiration = cred.expiration.replace(microsecond=0) + + # Produce the cred XML + cred.encode() + + # Sign it + cred.sign() + # Save it + cred.save_to_file(cred_filename) + print "Created ABAC credential: '%s' in file %s" % \ + (cred.get_summary_tostring(), cred_filename) + +# FIXME: Assumes xmlsec1 is on path +# FIXME: Assumes signer is itself signed by an 'ma_gid' that can be trusted +def create_speaks_for(tool_gid, user_gid, ma_gid, \ + user_key_file, cred_filename, dur_days=365): + tool_urn = tool_gid.get_urn() + user_urn = user_gid.get_urn() + + header = '' + reference = "ref0" + signature_block = \ + '\n' + \ + signature_template + \ + '' + template = header + '\n' + \ + '\n' + \ + 'abac\n' + \ + '\n' +\ + '\n' + \ + '\n' + \ + '\n' + \ + '\n' + \ + '\n' + \ + '%s' +\ + '\n' + \ + '\n' + \ + '%s\n' + \ + '\n' + \ + '%s%s\n' +\ + 'speaks_for_%s\n' + \ + '\n' + \ + '\n' +\ + '%s%s\n' +\ + '\n' +\ + '\n' + \ + '\n' + \ + '\n' + \ + signature_block + \ + '\n' + + + credential_duration = datetime.timedelta(days=dur_days) + expiration = datetime.datetime.now(du_tz.tzutc()) + credential_duration + expiration_str = expiration.strftime('%Y-%m-%dT%H:%M:%SZ') # FIXME: libabac can't handle .isoformat() + version = "1.1" + + user_keyid = get_cert_keyid(user_gid) + tool_keyid = get_cert_keyid(tool_gid) + unsigned_cred = template % (reference, expiration_str, version, \ + user_keyid, user_urn, user_keyid, tool_keyid, tool_urn, \ + reference, reference) + unsigned_cred_filename = write_to_tempfile(unsigned_cred) + + # Now sign the file with xmlsec1 + # xmlsec1 --sign --privkey-pem privkey.pem,cert.pem + # --output signed.xml tosign.xml + pems = "%s,%s,%s" % (user_key_file, user_gid.get_filename(), + ma_gid.get_filename()) + # FIXME: assumes xmlsec1 is on path + cmd = ['xmlsec1', '--sign', '--privkey-pem', pems, + '--output', cred_filename, unsigned_cred_filename] + +# print " ".join(cmd) + sign_proc_output = run_subprocess(cmd, stdout=subprocess.PIPE, stderr=None) + if sign_proc_output == None: + print "OUTPUT = %s" % sign_proc_output + else: + print "Created ABAC credential: '%s speaks_for %s' in file %s" % \ + (tool_urn, user_urn, cred_filename) + os.unlink(unsigned_cred_filename) + + +# Test procedure +if __name__ == "__main__": + + parser = optparse.OptionParser() + parser.add_option('--cred_file', + help='Name of credential file') + parser.add_option('--tool_cert_file', + help='Name of file containing tool certificate') + parser.add_option('--user_urn', + help='URN of speaks-for user') + parser.add_option('--user_cert_file', + help="filename of x509 certificate of signing user") + parser.add_option('--ma_cert_file', + help="filename of x509 cert of MA that signed user cert") + parser.add_option('--user_key_file', + help="filename of private key of signing user") + parser.add_option('--trusted_roots_directory', + help='Directory of trusted root certs') + parser.add_option('--create', + help="name of file of ABAC speaksfor cred to create") + parser.add_option('--useObject', action='store_true', default=False, + help='Use the ABACCredential object to create the credential (default False)') + + options, args = parser.parse_args(sys.argv) + + tool_gid = GID(filename=options.tool_cert_file) + + if options.create: + if options.user_cert_file and options.user_key_file \ + and options.ma_cert_file: + user_gid = GID(filename=options.user_cert_file) + ma_gid = GID(filename=options.ma_cert_file) + if options.useObject: + create_sign_abaccred(tool_gid, user_gid, ma_gid, \ + options.user_key_file, \ + options.create) + else: + create_speaks_for(tool_gid, user_gid, ma_gid, \ + options.user_key_file, \ + options.create) + else: + print "Usage: --create cred_file " + \ + "--user_cert_file user_cert_file" + \ + " --user_key_file user_key_file --ma_cert_file ma_cert_file" + sys.exit() + + user_urn = options.user_urn + + # Get list of trusted rootcerts + if options.cred_file and not options.trusted_roots_directory: + sys.exit("Must supply --trusted_roots_directory to validate a credential") + + trusted_roots_directory = options.trusted_roots_directory + trusted_roots = \ + [Certificate(filename=os.path.join(trusted_roots_directory, file)) \ + for file in os.listdir(trusted_roots_directory) \ + if file.endswith('.pem') and file != 'CATedCACerts.pem'] + + cred = open(options.cred_file).read() + + creds = [{'geni_type' : ABACCredential.ABAC_CREDENTIAL_TYPE, 'geni_value' : cred, + 'geni_version' : '1'}] + gid = determine_speaks_for(None, creds, tool_gid, \ + {'geni_speaking_for' : user_urn}, \ + trusted_roots) + + + print 'SPEAKS_FOR = %s' % (gid != tool_gid) + print "CERT URN = %s" % gid.get_urn() diff --git a/core/lib/am/ext/my_roots/alice-cert.pem b/core/lib/am/ext/my_roots/alice-cert.pem new file mode 100755 index 00000000..d605f604 --- /dev/null +++ b/core/lib/am/ext/my_roots/alice-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIICNDCCAZ2gAwIBAgIBAzANBgkqhkiG9w0BAQQFADAmMSQwIgYDVQQDExtnZW5p +Ly9ncG8vL2djZi5hdXRob3JpdHkuc2EwHhcNMTQwNTA1MTA0MTIxWhcNMTkwNTA0 +MTA0MTIxWjAkMSIwIAYDVQQDExlnZW5pLy9ncG8vL2djZi51c2VyLmFsaWNlMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDwOxFmz8WryBcIfO55hAF5QNDmUGuy +dgyGVtghz+5OZz/BT+QCV22oEXQd+XKSukg4wAxQX3+RdQh0P44vo3mzNeDP61Cy +FmLQxtXilGWRhkfZ0py8ERHqKyBlaxSX9tQZmillcrd+5MwRO7pjUVS2/KC6MPur +a0L/Qj4HDHbPAQIDAQABo3QwcjAMBgNVHRMBAf8EAjAAMGIGA1UdEQRbMFmGKHVy +bjpwdWJsaWNpZDpJRE4rZ2VuaTpncG86Z2NmK3VzZXIrYWxpY2WGLXVybjp1dWlk +OjU0YTQ1MzZjLTNjMmUtNDFhMi1hMWZmLTU3NjQ1MWYyMmM0ODANBgkqhkiG9w0B +AQQFAAOBgQA43MOSr3ttuKloiF/o1YAPZGMiYboqc1cXcLZos07V15QMBcd00Ong +F4ITeHGvbFIiWCZdxBfzEJ/Oz9Qc+tRfbWAFeoFldWS5IUulZe/supr9i0KJf5ZJ +vlcOHhBSVA9a1eDtWJJiOtkjWfpNsOLNqZy5dMiybhPvaJyducyG4g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICOzCCAaSgAwIBAgIBAzANBgkqhkiG9w0BAQQFADAmMSQwIgYDVQQDExtnZW5p +Ly9ncG8vL2djZi5hdXRob3JpdHkuc2EwHhcNMTQwNTA1MTA0MTIxWhcNMTkwNTA0 +MTA0MTIxWjAmMSQwIgYDVQQDExtnZW5pLy9ncG8vL2djZi5hdXRob3JpdHkuc2Ew +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKVQQEOvcGgSZmIlklIPT8/HlQlF +ZY9EmTs5K5Q0vT64BQN5Tql1naVFuOSdtATRuloSOJ6dUhgeZWv3p5ApiF0pbbVC +Yia+t4q4k/z092o78iX2ipH3cjo2MWzR8NkJIT0Y2rdQGp4jAZvbC7MzPxAgBadi +sAtf9Vkb1UlPH0XfAgMBAAGjeTB3MA8GA1UdEwEB/wQFMAMBAf8wZAYDVR0RBF0w +W4YqdXJuOnB1YmxpY2lkOklETitnZW5pOmdwbzpnY2YrYXV0aG9yaXR5K3Nhhi11 +cm46dXVpZDpjNzljODQ3Zi1kMTYxLTQwNWItOWFjYy00NGU1ZTE1NzYxY2YwDQYJ +KoZIhvcNAQEEBQADgYEAIosFUKR4vzewriRZX2kbVSNXNhfnVoap56w/OEQMOKQL +PQgaYI2V0GL7CrejA0E8MAv1qInop1vnF5MK2N5PTEzirxXna/TWhai5sOENCsaG ++M3K9Scu6N9MsN+L1AO2xpSNuRw5DHDqxQINj0AmtrJf3BuYBM/Tj9pAhwVSH14= +-----END CERTIFICATE----- diff --git a/core/lib/am/ext/my_roots/alice-key.pem b/core/lib/am/ext/my_roots/alice-key.pem new file mode 100644 index 00000000..482463a7 --- /dev/null +++ b/core/lib/am/ext/my_roots/alice-key.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPA7EWbPxavIFwh8 +7nmEAXlA0OZQa7J2DIZW2CHP7k5nP8FP5AJXbagRdB35cpK6SDjADFBff5F1CHQ/ +ji+jebM14M/rULIWYtDG1eKUZZGGR9nSnLwREeorIGVrFJf21BmaKWVyt37kzBE7 +umNRVLb8oLow+6trQv9CPgcMds8BAgMBAAECgYBaX+5g/kNAJ8s6fz1764ReaFru +eky5251EoME4ny/owQEEKZj+pIN1WfOUHzbSKlBnQSCgz/x+7Udb7FkCZP6wCTpB +XUfICKkiOfbOQmZ9UtbvAXn/8tVBdyZmLLhQVWEcDwqa8G53/oPShIrK3j9D95ex +82dvj/RLURXg0p2b0QJBAPkeZp0bG4M0x24UuVVj4waJr6f8EMmtDxJa8IRQrlwE +mp7b1WjwFKbcwt3taZPsrm/ItvvBu/u9RiWO3ZxgsoUCQQD23dEso332QWRi6LgY +5wp91GL1dxG2NnMn5ArdtLtJvlvqbFlr9Yh9Fn4IRTMLehkc7QMlA5RBg/crRU4g +k7lNAkEA2kHCUV7QifGR0GYjwiZTXwT+esSiyK7wh3pZQvOU71WxSgD8RoYg8dh0 +eg9o8orogVNuzb98vR+k937ltf4aKQJAD5wXDeuIm3mnD1oHygtR7oLvfvX4eL0Y +qv0QctRqw072IOyY+uqbps01SvCVObSOwfV6rWx8g2gEyQeo2QZ+QQJBAKGWjPlj +0yzqcl6lFbSmqDCGfeQbCmI1w4iu2z7a9CXcFGtrt0CyVWhYX8EGgbqRYHG+fODG +1QtAdblJABSJKxU= +-----END PRIVATE KEY----- diff --git a/core/lib/am/ext/my_roots/topdomain.gid b/core/lib/am/ext/my_roots/topdomain.gid new file mode 100644 index 00000000..a31fc7c8 --- /dev/null +++ b/core/lib/am/ext/my_roots/topdomain.gid @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICFDCCAX2gAwIBAgIBAzANBgkqhkiG9w0BAQQFADAUMRIwEAYDVQQDEwl0b3Bk +b21haW4wHhcNMTIxMjI3MDgwNDEyWhcNMTcxMjI2MDgwNDEyWjAUMRIwEAYDVQQD +Ewl0b3Bkb21haW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO+j5DIFYJhA +jyB+2VtipZhFIx/bcGOa35vOEZfagKsaaIgdelBZwyALG99yB3pLvDF8wprO16Je +KODSBhN/VjF0QM2CKpSOJXQvvpeWeTXFEhOUA0N6xkCLyzMwe0tchXlKZRPLXhBu +WaWgt9E1rOEYAkCro5tx1e98SlH9wQM3AgMBAAGjdjB0MA8GA1UdEwEB/wQFMAMB +Af8wYQYDVR0RBFowWIYndXJuOnB1YmxpY2lkOklETit0b3Bkb21haW4rYXV0aG9y +aXR5K3Nhhi11cm46dXVpZDpjN2RmZDU5Yy1jOTNjLTRmZDUtOWQ1My03MzQ1MDQw +NDcwODMwDQYJKoZIhvcNAQEEBQADgYEAHCjfsJt348ew4JQorY98gCjMVadJg/wn +0HJie1RrJl0nxxaY6u71SZ7AxXCAvKWcqFzQ7vvP/mgrWhZmCo018xj9tPvdKKAs +UePmSIEjb1zcmW5hrWqNKAlBG7KjNJ23iaK4F/9Zhyih9jYqXAFsysH5g1KnI9T3 +JK9yxZ7Nytw= +-----END CERTIFICATE----- diff --git a/core/lib/am/ext/schemas/credential.xsd b/core/lib/am/ext/schemas/credential.xsd new file mode 100644 index 00000000..a57b94c0 --- /dev/null +++ b/core/lib/am/ext/schemas/credential.xsd @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Can the ticket be delegated? + + + + + + A desciption of the resources that are being promised + + + + + + + + + The ticket must be "cashed in" by this date + + + + + + + + + + + + A credential granting privileges or a ticket. + + + + + + + + + + + + + + + + + + + Privileges or a ticket + + + + + + + + + + + + + + The type of this credential. Currently a Privilege set or a Ticket. + + + + + + + + + + + + A serial number. + + + + + GID of the owner of this credential. + + + + + URN of the owner. Not everyone can parse DER + + + + + GID of the target of this credential. + + + + + URN of the target. + + + + + UUID of this credential + + + + + Expires on + + + + + Optional Extensions + + + + + + + + + Parent that delegated to us + + + + + + + + + + + + + + diff --git a/core/lib/am/ext/trusted_roots/alice-cert.pem b/core/lib/am/ext/trusted_roots/alice-cert.pem new file mode 100755 index 00000000..d605f604 --- /dev/null +++ b/core/lib/am/ext/trusted_roots/alice-cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIICNDCCAZ2gAwIBAgIBAzANBgkqhkiG9w0BAQQFADAmMSQwIgYDVQQDExtnZW5p +Ly9ncG8vL2djZi5hdXRob3JpdHkuc2EwHhcNMTQwNTA1MTA0MTIxWhcNMTkwNTA0 +MTA0MTIxWjAkMSIwIAYDVQQDExlnZW5pLy9ncG8vL2djZi51c2VyLmFsaWNlMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDwOxFmz8WryBcIfO55hAF5QNDmUGuy +dgyGVtghz+5OZz/BT+QCV22oEXQd+XKSukg4wAxQX3+RdQh0P44vo3mzNeDP61Cy +FmLQxtXilGWRhkfZ0py8ERHqKyBlaxSX9tQZmillcrd+5MwRO7pjUVS2/KC6MPur +a0L/Qj4HDHbPAQIDAQABo3QwcjAMBgNVHRMBAf8EAjAAMGIGA1UdEQRbMFmGKHVy +bjpwdWJsaWNpZDpJRE4rZ2VuaTpncG86Z2NmK3VzZXIrYWxpY2WGLXVybjp1dWlk +OjU0YTQ1MzZjLTNjMmUtNDFhMi1hMWZmLTU3NjQ1MWYyMmM0ODANBgkqhkiG9w0B +AQQFAAOBgQA43MOSr3ttuKloiF/o1YAPZGMiYboqc1cXcLZos07V15QMBcd00Ong +F4ITeHGvbFIiWCZdxBfzEJ/Oz9Qc+tRfbWAFeoFldWS5IUulZe/supr9i0KJf5ZJ +vlcOHhBSVA9a1eDtWJJiOtkjWfpNsOLNqZy5dMiybhPvaJyducyG4g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICOzCCAaSgAwIBAgIBAzANBgkqhkiG9w0BAQQFADAmMSQwIgYDVQQDExtnZW5p +Ly9ncG8vL2djZi5hdXRob3JpdHkuc2EwHhcNMTQwNTA1MTA0MTIxWhcNMTkwNTA0 +MTA0MTIxWjAmMSQwIgYDVQQDExtnZW5pLy9ncG8vL2djZi5hdXRob3JpdHkuc2Ew +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKVQQEOvcGgSZmIlklIPT8/HlQlF +ZY9EmTs5K5Q0vT64BQN5Tql1naVFuOSdtATRuloSOJ6dUhgeZWv3p5ApiF0pbbVC +Yia+t4q4k/z092o78iX2ipH3cjo2MWzR8NkJIT0Y2rdQGp4jAZvbC7MzPxAgBadi +sAtf9Vkb1UlPH0XfAgMBAAGjeTB3MA8GA1UdEwEB/wQFMAMBAf8wZAYDVR0RBF0w +W4YqdXJuOnB1YmxpY2lkOklETitnZW5pOmdwbzpnY2YrYXV0aG9yaXR5K3Nhhi11 +cm46dXVpZDpjNzljODQ3Zi1kMTYxLTQwNWItOWFjYy00NGU1ZTE1NzYxY2YwDQYJ +KoZIhvcNAQEEBQADgYEAIosFUKR4vzewriRZX2kbVSNXNhfnVoap56w/OEQMOKQL +PQgaYI2V0GL7CrejA0E8MAv1qInop1vnF5MK2N5PTEzirxXna/TWhai5sOENCsaG ++M3K9Scu6N9MsN+L1AO2xpSNuRw5DHDqxQINj0AmtrJf3BuYBM/Tj9pAhwVSH14= +-----END CERTIFICATE----- diff --git a/core/lib/am/ext/trusted_roots/gpo.gid b/core/lib/am/ext/trusted_roots/gpo.gid new file mode 100644 index 00000000..3333b493 --- /dev/null +++ b/core/lib/am/ext/trusted_roots/gpo.gid @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICOzCCAaSgAwIBAgIBAzANBgkqhkiG9w0BAQQFADAmMSQwIgYDVQQDExtnZW5p +Ly9ncG8vL2djZi5hdXRob3JpdHkuc2EwHhcNMTQwNTA1MTA0MTIxWhcNMTkwNTA0 +MTA0MTIxWjAmMSQwIgYDVQQDExtnZW5pLy9ncG8vL2djZi5hdXRob3JpdHkuc2Ew +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKVQQEOvcGgSZmIlklIPT8/HlQlF +ZY9EmTs5K5Q0vT64BQN5Tql1naVFuOSdtATRuloSOJ6dUhgeZWv3p5ApiF0pbbVC +Yia+t4q4k/z092o78iX2ipH3cjo2MWzR8NkJIT0Y2rdQGp4jAZvbC7MzPxAgBadi +sAtf9Vkb1UlPH0XfAgMBAAGjeTB3MA8GA1UdEwEB/wQFMAMBAf8wZAYDVR0RBF0w +W4YqdXJuOnB1YmxpY2lkOklETitnZW5pOmdwbzpnY2YrYXV0aG9yaXR5K3Nhhi11 +cm46dXVpZDpjNzljODQ3Zi1kMTYxLTQwNWItOWFjYy00NGU1ZTE1NzYxY2YwDQYJ +KoZIhvcNAQEEBQADgYEAIosFUKR4vzewriRZX2kbVSNXNhfnVoap56w/OEQMOKQL +PQgaYI2V0GL7CrejA0E8MAv1qInop1vnF5MK2N5PTEzirxXna/TWhai5sOENCsaG ++M3K9Scu6N9MsN+L1AO2xpSNuRw5DHDqxQINj0AmtrJf3BuYBM/Tj9pAhwVSH14= +-----END CERTIFICATE----- diff --git a/core/lib/am/ext/trusted_roots/topdomain.gid b/core/lib/am/ext/trusted_roots/topdomain.gid new file mode 100644 index 00000000..a31fc7c8 --- /dev/null +++ b/core/lib/am/ext/trusted_roots/topdomain.gid @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICFDCCAX2gAwIBAgIBAzANBgkqhkiG9w0BAQQFADAUMRIwEAYDVQQDEwl0b3Bk +b21haW4wHhcNMTIxMjI3MDgwNDEyWhcNMTcxMjI2MDgwNDEyWjAUMRIwEAYDVQQD +Ewl0b3Bkb21haW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO+j5DIFYJhA +jyB+2VtipZhFIx/bcGOa35vOEZfagKsaaIgdelBZwyALG99yB3pLvDF8wprO16Je +KODSBhN/VjF0QM2CKpSOJXQvvpeWeTXFEhOUA0N6xkCLyzMwe0tchXlKZRPLXhBu +WaWgt9E1rOEYAkCro5tx1e98SlH9wQM3AgMBAAGjdjB0MA8GA1UdEwEB/wQFMAMB +Af8wYQYDVR0RBFowWIYndXJuOnB1YmxpY2lkOklETit0b3Bkb21haW4rYXV0aG9y +aXR5K3Nhhi11cm46dXVpZDpjN2RmZDU5Yy1jOTNjLTRmZDUtOWQ1My03MzQ1MDQw +NDcwODMwDQYJKoZIhvcNAQEEBQADgYEAHCjfsJt348ew4JQorY98gCjMVadJg/wn +0HJie1RrJl0nxxaY6u71SZ7AxXCAvKWcqFzQ7vvP/mgrWhZmCo018xj9tPvdKKAs +UePmSIEjb1zcmW5hrWqNKAlBG7KjNJ23iaK4F/9Zhyih9jYqXAFsysH5g1KnI9T3 +JK9yxZ7Nytw= +-----END CERTIFICATE----- diff --git a/core/lib/am/geniutils/__init__.py b/core/lib/am/geniutils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/geniutils/src/__init__.py b/core/lib/am/geniutils/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/geniutils/src/faults/__init__.py b/core/lib/am/geniutils/src/faults/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/geniutils/src/faults/faults.py b/core/lib/am/geniutils/src/faults/faults.py new file mode 100644 index 00000000..06e3d537 --- /dev/null +++ b/core/lib/am/geniutils/src/faults/faults.py @@ -0,0 +1,344 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- +# +# SFA API faults +# + +import xmlrpclib +from geniutils.src.faults.genicode import GENICODE + +class SfaFault(xmlrpclib.Fault): + def __init__(self, faultCode, faultString, extra = None): + if extra: + faultString += ": " + str(extra) + xmlrpclib.Fault.__init__(self, faultCode, faultString) + +class OCFSfaPermissionDenied(SfaFault): + def __init__(self,value='',extra = None): + self.faultString = "Permission denied: %s" % value + self.code = GENICODE.FORBIDDEN + SfaFault.__init__(self, self.code, self.faultString, extra) + +class OCFSfaError(SfaFault): + def __init__(self,value='',method='',extra = None): + self.faultString = "Error in method %s %s" % (method, value) + self.code = GENICODE.ERROR + SfaFault.__init__(self, self.code, self.faultString, extra) + +class SfaInvalidAPIMethod(SfaFault): + def __init__(self, method, interface = None, extra = None): + faultString = "Invalid method " + method + if interface: + faultString += " for interface " + interface + SfaFault.__init__(self, GENICODE.UNSUPPORTED, faultString, extra) + +class SfaInvalidArgumentCount(SfaFault): + def __init__(self, got, min, max = min, extra = None): + if min != max: + expected = "%d-%d" % (min, max) + else: + expected = "%d" % min + faultString = "Expected %s arguments, got %d" % \ + (expected, got) + SfaFault.__init__(self, GENICODE.BADARGS, faultString, extra) + +class SfaInvalidArgument(SfaFault): + def __init__(self, extra = None, name = None): + if name is not None: + faultString = "Invalid %s value" % name + else: + faultString = "Invalid argument" + SfaFault.__init__(self, GENICODE.BADARGS, faultString, extra) + +class SfaAuthenticationFailure(SfaFault): + def __init__(self, extra = None): + faultString = "Failed to authenticate call" + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + +class SfaDBError(SfaFault): + def __init__(self, extra = None): + faultString = "Database error" + SfaFault.__init__(self, GENICODE.DBERROR, faultString, extra) + +class SfaPermissionDenied(SfaFault): + def __init__(self, extra = None): + faultString = "Permission denied" + SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra) + +class SfaNotImplemented(SfaFault): + def __init__(self, interface=None, extra = None): + faultString = "Not implemented" + if interface: + faultString += " at interface " + interface + SfaFault.__init__(self, GENICODE.UNSUPPORTED, faultString, extra) + +class SfaAPIError(SfaFault): + def __init__(self, extra = None): + faultString = "Internal API error" + SfaFault.__init__(self, GENICODE.SERVERERROR, faultString, extra) + +class MalformedHrnException(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Malformed HRN: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, extra) + def __str__(self): + return repr(self.value) + +class TreeException(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Tree Exception: %(value)s, " % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class NonExistingRecord(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Non exsiting record %(value)s, " % locals() + SfaFault.__init__(self, GENICODE.SEARCHFAILED, faultString, extra) + def __str__(self): + return repr(self.value) + +class ExistingRecord(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Existing record: %(value)s, " % locals() + SfaFault.__init__(self, GENICODE.REFUSED, faultString, extra) + def __str__(self): + return repr(self.value) + + +class InvalidRPCParams(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Invalid RPC Params: %(value)s, " % locals() + SfaFault.__init__(self, GENICODE.RPCERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +# SMBAKER exceptions follow + +class ConnectionKeyGIDMismatch(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Connection Key GID mismatch: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class MissingCallerGID(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Missing Caller GID: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class RecordNotFound(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Record not found: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class UnknownSfaType(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Unknown SFA Type: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class MissingAuthority(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Missing authority: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class PlanetLabRecordDoesNotExist(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "PlanetLab record does not exist : %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class PermissionError(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Permission error: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra) + def __str__(self): + return repr(self.value) + +class InsufficientRights(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Insufficient rights: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra) + def __str__(self): + return repr(self.value) + +class MissingDelegateBit(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Missing delegate bit: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra) + def __str__(self): + return repr(self.value) + +class ChildRightsNotSubsetOfParent(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Child rights not subset of parent: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra) + def __str__(self): + return repr(self.value) + +class CertMissingParent(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Cert missing parent: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class CertNotSignedByParent(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Cert not signed by parent: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class GidParentHrn(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Cert URN is not an extension of its parent: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class GidInvalidParentHrn(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "GID invalid parent hrn: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class SliverDoesNotExist(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Sliver does not exist : %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class BadRequestHash(xmlrpclib.Fault): + def __init__(self, hash = None, extra = None): + faultString = "bad request hash: " + str(hash) + xmlrpclib.Fault.__init__(self, GENICODE.ERROR, faultString) + +class MissingTrustedRoots(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Trusted root directory does not exist: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.SERVERERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class MissingSfaInfo(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Missing information: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class InvalidRSpec(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Invalid RSpec: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + 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 + faultString = "Invalid RSpec Element: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class InvalidXML(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Invalid XML Document: %(value)s" % locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class AccountNotEnabled(SfaFault): + def __init__(self, extra = None): + faultString = "Account Disabled" + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class CredentialNotVerifiable(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Unable to verify credential: %(value)s, " %locals() + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + def __str__(self): + return repr(self.value) + +class CertExpired(SfaFault): + def __init__(self, value, extra=None): + self.value = value + faultString = "%s cert is expired" % value + SfaFault.__init__(self, GENICODE.ERROR, faultString, extra) + diff --git a/core/lib/am/geniutils/src/faults/genicode.py b/core/lib/am/geniutils/src/faults/genicode.py new file mode 100644 index 00000000..14f0807b --- /dev/null +++ b/core/lib/am/geniutils/src/faults/genicode.py @@ -0,0 +1,45 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- + + +class GENICODE: + SUCCESS = 0 + BADARGS = 1 + ERROR = 2 + FORBIDDEN = 3 + BADVERSION = 4 + SERVERERROR = 5 + TOOBIG = 6 + REFUSED = 7 + TIMEDOUT = 8 + DBERROR = 9 + RPCERROR = 10 + UNAVAILABLE = 11 + SEARCHFAILED = 12 + UNSUPPORTED = 13 + BUSY = 14 + EXPIRED = 15 + INPROGRESS = 16 + ALREADYEXISTS = 17 + VLAN_UNAVAILABLE = 24 + INSUFFICIENT_BANDWIDTH = 25 diff --git a/core/lib/am/geniutils/src/time/__init__.py b/core/lib/am/geniutils/src/time/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/geniutils/src/time/timewrapper.py b/core/lib/am/geniutils/src/time/timewrapper.py new file mode 100644 index 00000000..408b0444 --- /dev/null +++ b/core/lib/am/geniutils/src/time/timewrapper.py @@ -0,0 +1,43 @@ +from types import StringTypes +import dateutil.parser +import datetime +import time + +#from openflow.optin_manager.sfa.util.sfalogging import logger + +DATEFORMAT = "%Y-%m-%dT%H:%M:%SZ" + +def utcparse(input): + """ Translate a string into a time using dateutil.parser.parse but make sure it's in UTC time and strip +the timezone, so that it's compatible with normal datetime.datetime objects. + +For safety this can also handle inputs that are either timestamps, or datetimes +""" + # prepare the input for the checks below by + # casting strings ('1327098335') to ints + if isinstance(input, StringTypes): + try: + input = int(input) + except ValueError: + pass + + if isinstance (input, datetime.datetime): + return input + elif isinstance (input, StringTypes): + t = dateutil.parser.parse(input) + if t.utcoffset() is not None: + t = t.utcoffset() + t.replace(tzinfo=None) + return t + elif isinstance (input, (int,float,long)): + return datetime.datetime.fromtimestamp(input) + else: + print "Unexpected type in utcparse [%s]"%type(input) + +def datetime_to_string(input): + return datetime.datetime.strftime(input, DATEFORMAT) + +def datetime_to_utc(input): + return time.gmtime(datetime_to_epoch(input)) + +def datetime_to_epoch(input): + return int(time.mktime(input.timetuple())) diff --git a/core/lib/am/geniutils/src/urn/__init__.py b/core/lib/am/geniutils/src/urn/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/geniutils/src/urn/utils.py b/core/lib/am/geniutils/src/urn/utils.py new file mode 100644 index 00000000..813480a4 --- /dev/null +++ b/core/lib/am/geniutils/src/urn/utils.py @@ -0,0 +1,248 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2010-2014 Raytheon BBN Technologies +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- +''' +URN creation and verification utilities. +''' + +import re +from geniutils.src.xrn.xrn import Xrn # for URN_PREFIX + +class URN(object): + """ + A class that creates and extracts values from URNs + URN Convention: + urn:publicid:IDN+++ + Authority, type, and name are public ids transcribed into URN format + By convention a CH's name should be "ch" and an AM's should be "am" + The authority of the CH should be the prefix for all of your AM and user authorities + For instance: CH authority = "gcf//gpo//bbn", AM authority = "gcf//gpo/bbn//am1", user authority = "gcf//gpo//bbn" + + EXAMPLES: + + ch_urn = URN("gcf//gpo//bbn", "authority", "sa").urn_string() for a clearinghouse URN + am1_urn = URN("gcf//gpo//bbn//site1", "authority", "am").urn_string() for an AM at this authority + Looks like urn:publicid:IDN+gcf:gpo:bbn:site1+authority+am + am2_urn = URN("gcf//gpo//bbn//site2", "authority", "am").urn_string() for a second AM at this authority + Looks like urn:publicid:IDN+gcf:gpo:bbn:site2+authority+am + user_urn = URN("gcf//gpo//bbn", "user", "jane").urn_string() for a user made by the clearinghouse + Looks like urn:publicid:IDN+gcf:gpo:bbn+user+jane + slice_urn = URN("gcf//gpo//bbn", "slice", "my-great-experiment").urn_string() + Looks like urn:publicid:IDN+gcf:gpo:bbn+slice+my-great-experiment + resource_at_am1_urn = URN("gcf//gpo//bbn/site1", "node", "LinuxBox23").urn_string() for Linux Machine 23 managed by AM1 (at site 1) + Looks like urn:publicid:IDN+gcf:gpo:bbn:site1+node+LinuxBox23 + """ + def __init__(self, authority=None, type=None, name=None, urn=None): + if not urn is None: + if not is_valid_urn(urn): + raise ValueError("Invalid URN %s" % urn) + + spl = urn.split('+') + if len(spl) < 4: + raise ValueError("Invalid URN %s" % urn) + self.authority = urn_to_string_format(spl[1]) + self.type = urn_to_string_format(spl[2]) + self.name = urn_to_string_format('+'.join(spl[3:])) + self.urn = urn + else: + if not authority or not type or not name: + raise ValueError("Must provide either all of authority, type, and name, or a urn must be provided") + + + for i in [authority, type, name]: + if i.strip() == '': + raise ValueError("Parameter to create_urn was empty string") + + self.authority = authority + self.type = type + self.name = name + + # FIXME: check these are valid more? + if not is_valid_urn_string(authority): + authority = string_to_urn_format(authority) + if not is_valid_urn_string(type): + type = string_to_urn_format(type) + if not is_valid_urn_string(name): + name = string_to_urn_format(name) + + self.urn = '%s+%s+%s+%s' % (Xrn.URN_PREFIX, authority, type, name) + if not is_valid_urn(self.urn): + raise ValueError("Failed to create valid URN from args %s, %s, %s" % (self.authority, self.type, self.name)) + + def __str__(self): + return self.urn_string() + + def urn_string(self): + return self.urn + + def getAuthority(self): + '''Get the authority in un-escaped publicid format''' + return self.authority + def getType(self): + '''Get the URN type in un-escaped publicid format''' + return self.type + def getName(self): + '''Get the name in un-escaped publicid format''' + return self.name + + +# Translate publicids to URN format. +# The order of these rules matters +# because we want to catch things like double colons before we +# translate single colons. This is only a subset of the rules. +# See the GENI Wiki: GAPI_Identifiers +# See http://www.faqs.org/rfcs/rfc3151.html +publicid_xforms = [('%', '%25'), + (';', '%3B'), + ('+', '%2B'), + (' ', '+' ), # note you must first collapse WS + ('#', '%23'), + ('?', '%3F'), + ("'", '%27'), + ('::', ';' ), + (':', '%3A'), + ('//', ':' ), + ('/', '%2F')] + +# FIXME: See sfa/util/xrn/Xrn.URN_PREFIX which is ...:IDN +publicid_urn_prefix = 'urn:publicid:' + +def nameFromURN(instr): + '''Get the name from the given URN, or empty if not a valid URN''' + if not instr: + return "" + try: + urn = URN(urn=instr) + return urn.getName() + except Exception, e: +# print 'exception parsing urn: %s' % e + return "" + +# validate urn +# Note that this is not sufficient but it is necessary +def is_valid_urn_string(instr): + '''Could this string be part of a URN''' + if instr is None or not (isinstance(instr, str) or + isinstance(instr, unicode)): + return False + #No whitespace + # no # or ? or / + if isinstance(instr, unicode): + instr = instr.encode('utf8') + if re.search("[\s|\?\/\#]", instr) is None: + return True + return False + +# Note that this is not sufficient but it is necessary +def is_valid_urn(inurn): + ''' Check that this string is a valid URN''' + # FIXME: This could pull out the type and do the type specific + # checks that are currently below + # FIXME: This should check for non empty authority and name pieces + return is_valid_urn_string(inurn) and \ + inurn.startswith(publicid_urn_prefix) and \ + len(inurn.split('+')) > 3 + +def is_valid_urn_bytype(inurn, urntype, logger=None): + if not is_valid_urn(inurn): + return False + urnObj = URN(urn=inurn) + if not urntype: + urntype = "" + urntype = urntype.lower() + if not urnObj.getType().lower() == urntype: + if logger: + logger.warn("URN %s not of right type: %s, not %s", inurn, urnObj.getType().lower(), urntype) + return False + if len(urnObj.getAuthority()) == 0: + if logger: + logger.warn("URN %s has empty authority", inurn) + return False + name = urnObj.getName() + if urntype == 'slice': + # Slice names are <=19 characters, only alphanumeric plus hyphen (no hyphen in first character): '^[a-zA-Z0-9][-a-zA-Z0-9]{0,18}$' + if len(name) > 19: + if logger: + logger.warn("URN %s too long. Slice names are max 19 characters", inurn) + return False + if not re.match("^[a-zA-Z0-9][-a-zA-Z0-9]{0,18}$", name): + if logger: + logger.warn("Slice names may only be alphanumeric plus hyphen (no leading hyphen): %s", name) + return False + elif urntype == 'sliver': + # May use only alphanumeric characters plus hyphen + # Note that EG uses a ':' as well. + if not re.match("^[-a-zA-Z0-9_\.]+$", name): + if logger: + logger.warn("Sliver names may only be alphanumeric plus hyphen, underscore, or period: %s", name) + return False + elif urntype == 'user': + # Usernames should begin with a letter and be alphanumeric or underscores; no hyphen or '.': ('^[a-zA-Z][\w]{0,7}$'). + # Usernames are limited to 8 characters. + if len(name) > 8: + if logger: + logger.warn("URN %s too long. User names are max 8 characters", inurn) + return False + if not re.match("^[a-zA-Z][\w]{0,7}$", name): + if logger: + logger.warn("User names may only be alphanumeric plus underscore, beginning with a letter: %s", name) + return False + elif len(name) == 0: + if logger: + logger.warn("Empty name in URN %s", inurn) + return False + return True + +def urn_to_publicid(urn): + '''Convert a URN like urn:publicid:... to a publicid''' + # Remove prefix + if urn is None or not is_valid_urn(urn): + # Erroneous urn for conversion + raise ValueError('Invalid urn: ' + urn) + publicid = urn[len(publicid_urn_prefix):] + # return the un-escaped string + return urn_to_string_format(publicid) + +def publicid_to_urn(id): + '''Convert a publicid to a urn like urn:publicid:.....''' + # prefix with 'urn:publicid:' and escape chars + return publicid_urn_prefix + string_to_urn_format(id) + +def string_to_urn_format(instr): + '''Make a string URN compatible, collapsing whitespace and escaping chars''' + if instr is None or instr.strip() == '': + raise ValueError("Empty string cant be in a URN") + # Collapse whitespace + instr = ' '.join(instr.strip().split()) + for a, b in publicid_xforms: + instr = instr.replace(a, b) + return instr + +def urn_to_string_format(urnstr): + '''Turn a part of a URN into publicid format, undoing transforms''' + if urnstr is None or urnstr.strip() == '': + return urnstr + publicid = urnstr + # Validate it is reasonable URN string? + for a, b in reversed(publicid_xforms): + publicid = publicid.replace(b, a) + return publicid \ No newline at end of file diff --git a/core/lib/am/geniutils/src/xrn/__init__.py b/core/lib/am/geniutils/src/xrn/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/geniutils/src/xrn/xrn.py b/core/lib/am/geniutils/src/xrn/xrn.py new file mode 100644 index 00000000..2093c9c1 --- /dev/null +++ b/core/lib/am/geniutils/src/xrn/xrn.py @@ -0,0 +1,268 @@ +#---------------------------------------------------------------------- +# Copyright (c) 2008 Board of Trustees, Princeton University +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and/or hardware specification (the "Work") to +# deal in the Work without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Work, and to permit persons to whom the Work +# is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Work. +# +# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS +# IN THE WORK. +#---------------------------------------------------------------------- + +import re + +from geniutils.src.faults.faults import SfaAPIError + +# for convenience and smoother translation - we should get rid of these functions eventually +def get_leaf(hrn): return Xrn(hrn).get_leaf() +def get_authority(hrn): return Xrn(hrn).get_authority_hrn() +def urn_to_hrn(urn): xrn=Xrn(urn); return (xrn.hrn, xrn.type) +def hrn_to_urn(hrn,type): return Xrn(hrn, type=type).urn +def hrn_authfor_hrn(parenthrn, hrn): return Xrn.hrn_is_auth_for_hrn(parenthrn, hrn) + +class Xrn: + + ########## basic tools on HRNs + # split a HRN-like string into pieces + # this is like split('.') except for escaped (backslashed) dots + # e.g. hrn_split ('a\.b.c.d') -> [ 'a\.b','c','d'] + @staticmethod + def hrn_split(hrn): + return [ x.replace('--sep--','\\.') for x in hrn.replace('\\.','--sep--').split('.') ] + + # e.g. hrn_leaf ('a\.b.c.d') -> 'd' + @staticmethod + def hrn_leaf(hrn): return Xrn.hrn_split(hrn)[-1] + + # e.g. hrn_auth_list ('a\.b.c.d') -> ['a\.b', 'c'] + @staticmethod + def hrn_auth_list(hrn): return Xrn.hrn_split(hrn)[0:-1] + + # e.g. hrn_auth ('a\.b.c.d') -> 'a\.b.c' + @staticmethod + def hrn_auth(hrn): return '.'.join(Xrn.hrn_auth_list(hrn)) + + # e.g. escape ('a.b') -> 'a\.b' + @staticmethod + def escape(token): return re.sub(r'([^\\])\.', r'\1\.', token) + + # e.g. unescape ('a\.b') -> 'a.b' + @staticmethod + def unescape(token): return token.replace('\\.','.') + + # Return the HRN authority chain from top to bottom. + # e.g. hrn_auth_chain('a\.b.c.d') -> ['a\.b', 'a\.b.c'] + @staticmethod + def hrn_auth_chain(hrn): + parts = Xrn.hrn_auth_list(hrn) + chain = [] + for i in range(len(parts)): + chain.append('.'.join(parts[:i+1])) + # Include the HRN itself? + #chain.append(hrn) + return chain + + # Is the given HRN a true authority over the namespace of the other + # child HRN? + # A better alternative than childHRN.startswith(parentHRN) + # e.g. hrn_is_auth_for_hrn('a\.b', 'a\.b.c.d') -> True, + # but hrn_is_auth_for_hrn('a', 'a\.b.c.d') -> False + # Also hrn_is_auth_for_hrn('a\.b.c.d', 'a\.b.c.d') -> True + @staticmethod + def hrn_is_auth_for_hrn(parenthrn, hrn): + if parenthrn == hrn: + return True + for auth in Xrn.hrn_auth_chain(hrn): + if parenthrn == auth: + return True + return False + + ########## basic tools on URNs + URN_PREFIX = "urn:publicid:IDN" + URN_PREFIX_lower = "urn:publicid:idn" + + @staticmethod + def is_urn (text): + return text.lower().startswith(Xrn.URN_PREFIX_lower) + + @staticmethod + def urn_full (urn): + if Xrn.is_urn(urn): return urn + else: return Xrn.URN_PREFIX+urn + @staticmethod + def urn_meaningful (urn): + if Xrn.is_urn(urn): return urn[len(Xrn.URN_PREFIX):] + else: return urn + @staticmethod + def urn_split (urn): + return Xrn.urn_meaningful(urn).split('+') + + #################### + # the local fields that are kept consistent + # self.urn + # self.hrn + # self.type + # self.path + # provide either urn, or (hrn + type) + def __init__ (self, xrn, type=None, id=None): + if not xrn: xrn = "" + # user has specified xrn : guess if urn or hrn + self.id = id + self.type = type + + if Xrn.is_urn(xrn): + self.hrn=None + self.urn=xrn + self.urn_to_hrn() + if id: + self.hrn_to_urn() + else: + self.urn=None + self.hrn=xrn + self.type=type + self.hrn_to_urn() + + self._normalize() +# happens all the time .. +# if not type: +# debug_logger.debug("type-less Xrn's are not safe") + + def __repr__ (self): + result=" 1: + self.id = ":".join(parts[1:]) + name = parts[0] + hrn += '.%s' % Xrn.escape(name) + + self.hrn=str(hrn) + self.type=str(type) + + def hrn_to_urn(self): + """ + compute urn from (hrn, type) + """ + +# if not self.hrn or self.hrn.startswith(Xrn.URN_PREFIX): + if Xrn.is_urn(self.hrn): + raise SfaAPIError, "Xrn.hrn_to_urn, hrn=%s"%self.hrn + + if self.type and self.type.startswith('authority'): + self.authority = Xrn.hrn_auth_list(self.hrn) + leaf = self.get_leaf() + #if not self.authority: + # self.authority = [self.hrn] + type_parts = self.type.split("+") + self.type = type_parts[0] + name = 'sa' + if len(type_parts) > 1: + name = type_parts[1] + auth_parts = [part for part in [self.get_authority_urn(), leaf] if part] + authority_string = ":".join(auth_parts) + else: + self.authority = Xrn.hrn_auth_list(self.hrn) + name = Xrn.hrn_leaf(self.hrn) + # separate name from id + authority_string = self.get_authority_urn() + + if self.type == None: + urn = "+".join(['',authority_string,Xrn.unescape(name)]) + else: + urn = "+".join(['',authority_string,self.type,Xrn.unescape(name)]) + + if hasattr(self, 'id') and self.id: + urn = "%s-%s" % (urn, self.id) + + self.urn = Xrn.URN_PREFIX + urn + + def dump_string(self): + result="-------------------- XRN\n" + result += "URN=%s\n"%self.urn + result += "HRN=%s\n"%self.hrn + result += "TYPE=%s\n"%self.type + result += "LEAF=%s\n"%self.get_leaf() + result += "AUTH(hrn format)=%s\n"%self.get_authority_hrn() + result += "AUTH(urn format)=%s\n"%self.get_authority_urn() + return result + diff --git a/core/lib/am/rspecs/__init__.py b/core/lib/am/rspecs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/rspecs/src/__init__.py b/core/lib/am/rspecs/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/rspecs/src/geni/__init__.py b/core/lib/am/rspecs/src/geni/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/rspecs/src/geni/v3/__init__.py b/core/lib/am/rspecs/src/geni/v3/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/rspecs/src/geni/v3/container/__init__.py b/core/lib/am/rspecs/src/geni/v3/container/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/rspecs/src/geni/v3/container/aggregate.py b/core/lib/am/rspecs/src/geni/v3/container/aggregate.py new file mode 100644 index 00000000..c321c50c --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/container/aggregate.py @@ -0,0 +1,37 @@ +class Aggregate: + + def __init__(self): + self.__component_id = None + self.__component_manager_id = None + self.__authority_urn = None + self.__slices = list() + + def get_component_manager_id(self): + return self.__component_manager_id + + def get_authority_urn(self): + return self.__authority_urn + + def get_slices(self): + return self.__slices + + def set_component_manager_id(self, value): + self.__component_manager_id = value + + def set_authority_urn(self, value): + self.__authority_urn = value + + def set_slices(self, value): + self.__slices = value + + def __str__(self): + to_return = self.__class__.__name__ + " [ " + for attr in self.__dict__.keys(): + new_attr = attr + "=" + str(getattr(self, attr)) + ", " + to_return += new_attr + to_return += "]" + return to_return + + def __repr__(self): + return self.__str__() + diff --git a/core/lib/am/rspecs/src/geni/v3/container/link.py b/core/lib/am/rspecs/src/geni/v3/container/link.py new file mode 100644 index 00000000..3e0312de --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/container/link.py @@ -0,0 +1,54 @@ +from rspecs.src.geni.v3.container.resource import Resource + +class Link(Resource): + + def __init__(self): + Resource.__init__(self) + self.__source_id = None + self.__dest_id = None + self.__type = None + #TODO add fancy fields + self.__capacity = None + self.__latency = None + + + def get_source_id(self): + return self.__source_id + + + def get_dest_id(self): + return self.__dest_id + + + def get_type(self): + return self.__type + + + def get_capacity(self): + return self.__capacity + + + def get_latency(self): + return self.__latency + + + def set_source_id(self, value): + self.__source_id = value + + + def set_dest_id(self, value): + self.__dest_id = value + + + def set_type(self, value): + self.__type = value + + + def set_capacity(self, value): + self.__capacity = value + + + def set_latency(self, value): + self.__latency = value + + \ No newline at end of file diff --git a/core/lib/am/rspecs/src/geni/v3/container/resource.py b/core/lib/am/rspecs/src/geni/v3/container/resource.py new file mode 100644 index 00000000..677ec86a --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/container/resource.py @@ -0,0 +1,113 @@ +class Resource: + + def __init__(self): + self.__id = None + self.__uuid = None + self.__allocation_state = None + self.__operational_state = None + self.__sliver = None + self.__component_id = None + self.__component_name = None + self.__component_manager_id = None + self.__component_manager_name = None + self.__available = None + self.__exclusive = None + self.__type = None + self.__error_message = None + + def get_id(self): + return self.__id + + def get_uuid(self): + return self.__uuid + + def get_allocation_state(self): + return self.__allocation_state + + def get_operational_state(self): + return self.__operational_state + + def get_sliver(self): + return self.__sliver + + def get_component_id(self): + return self.__component_id + + def get_component_name(self): + return self.__component_name + + def get_component_manager_id(self): + return self.__component_manager_id + + def get_component_manager_name(self): + return self.__component_manager_name + + def get_available(self): + return self.__available + + def get_exclusive(self): + return self.__exclusive + + def get_type(self): + return self.__type + + def get_error_message(self): + return self.__error_message + + def set_id(self, value): + self.__id = value + + def set_uuid(self, value): + self.__uuid = value + + def set_allocation_state(self, value): + self.__allocation_state = value + + def set_operational_state(self, value): + self.__operational_state = value + + def set_sliver(self, value): + self.__sliver = value + + def set_component_id(self, value): + self.__component_id = value + + def set_component_name(self, value): + self.__component_name = value + + def set_component_manager_id(self, value): + self.__component_manager_id = value + + def set_component_manager_name(self, value): + self.__component_manager_name = value + + def set_available(self, value): + self.__available = value + + def set_exclusive(self, value): + self.__exclusive = value + + def set_type(self, value): + self.__type = value + + def set_error_message(self, value): + self.__error_mesage = value + +# def add_sliver(self, value): +# if not type(self.__slivers) == list: +# self.__slivers = [value] +# else: +# self.__slivers.append(value) + + def __str__(self): + to_return = self.__class__.__name__ + " [ " + attrs = self.__dict__.keys() + attrs.sort() + for attr in attrs: + new_attr = attr + "=" + str(getattr(self, attr)) + ", " + to_return += new_attr + to_return += "]" + return to_return + + def __repr__(self): + return self.__str__() diff --git a/core/lib/am/rspecs/src/geni/v3/container/slice.py b/core/lib/am/rspecs/src/geni/v3/container/slice.py new file mode 100644 index 00000000..bc7f853a --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/container/slice.py @@ -0,0 +1,57 @@ +class Slice: + + def __init__(self): + self.__id = None + self.__urn = None + self.__expiration = None + self.__operational_state = None + self.__client_id = None + self.__slivers = list() + + def get_client_id(self): + return self.__client_id + + def set_client_id(self, value): + self.__client_id = value + + def get_id(self): + return self.__id + + def get_urn(self): + return self.__urn + + def get_expiration(self): + return self.__expiration + + def get_status(self): + return self.__operational_state + + def get_slivers(self): + return self.__slivers + + def set_id(self, value): + self.__id = value + + def set_urn(self, value): + self.__urn = value + + def set_expiration(self, value): + self.__expiration = value + + def set_status(self, value): + self.__operational_state = value + + def set_slivers(self, value): + self.__slivers = value + + def __str__(self): + to_return = self.__class__.__name__ + " [ " + for attr in self.__dict__.keys(): + new_attr = attr + "=" + str(getattr(self, attr)) + ", " + to_return += new_attr + to_return += "]" + return to_return + + def __repr__(self): + return self.__str__() + diff --git a/core/lib/am/rspecs/src/geni/v3/container/sliver.py b/core/lib/am/rspecs/src/geni/v3/container/sliver.py new file mode 100644 index 00000000..fe5f44dc --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/container/sliver.py @@ -0,0 +1,89 @@ +class Sliver: + + def __init__(self): + self.__urn = None + self.__name = None + self.__slice_urn = None + self.__allocation_status = None + self.__operational_status = None + self.__expiration = None + self.__resource = None + self.__type = None + self.__services = list() + self.__client_id = None + + def get_urn(self): + return self.__urn + + def get_name(self): + return self.__name + + def get_slice_urn(self): + return self.__slice_urn + + def get_allocation_status(self): + return self.__allocation_status + + def get_operational_status(self): + return self.__operational_status + + def get_expiration(self): + return self.__expiration + + def get_resource(self): + return self.__resource + + def get_type(self): + return self.__type + + def get_services(self): + return self.__services + + def get_client_id(self): + return self.__client_id + + def set_urn(self, value): + self.__urn = value + + def set_name(self, value): + self.__name = value + + def set_slice_urn(self, value): + self.__slice_urn = value + + def set_allocation_status(self, value): + self.__allocation_status = value + + def set_operational_status(self, value): + self.__operational_status = value + + def set_expiration(self, value): + self.__expiration = value + + def set_resource(self, value): + self.__resource = value + + def set_type(self, value): + self.__type = value + + def set_services(self, value): + self.__services = value + + def set_client_id(self, value): + self.__client_id = value + + def __str__(self): + to_return = self.__class__.__name__ + " [ " + attrs = self.__dict__.keys() + attrs.sort() + for attr in attrs: + if attr == "_Sliver__resource": + continue + new_attr = attr + "=" + str(getattr(self, attr)) + ", " + to_return += new_attr + to_return += "]" + return to_return + + def __repr__(self): + return self.__str__() + diff --git a/core/lib/am/rspecs/src/geni/v3/craftermanager.py b/core/lib/am/rspecs/src/geni/v3/craftermanager.py new file mode 100644 index 00000000..8b517d85 --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/craftermanager.py @@ -0,0 +1,132 @@ +from rspecs.src.geni.v3.container.resource import Resource +from rspecs.src.geni.v3.container.link import Link +class CrafterManager: + + #TODO: Take into account extensions + + def __init__(self, resources=[], options={}): + self.resources = resources + self.options = options + self._urn_authority = "urn:publicID:MYAUTHORITY" + + def get_advertisement(self, resources): + """ + Return advertisement with information of resources. + """ + output = self.advert_header() + for resource in resources: + output += self.advert_resource(resource) + output += self.advert_footer() + return output + + def advert_node_template(self): + tmpl = """ + + +""" + return tmpl + + def advert_link_template(self): + tmpl = ''' + + + ''' + return tmpl + + def advert_resource(self,resource): + resource_dir = dir(resource) + if resource_dir == dir(Link()): + return self.advert_link(resource) + elif resource_dir == dir(Resource()): + return self.advert_node(resource) + else: + return "" + + + def advert_node(self, resource): + resource_component_manager_id = str(resource.get_component_manager_id()) + resource_exclusive = str(resource.get_exclusive()).lower() + resource_available = str(resource.get_available()).lower() + resource_component_name = resource.get_component_name() + resource_component_id = resource.get_component_id() + return self.advert_node_template() % (resource_component_manager_id, + resource_component_name, + resource_component_id, + resource_exclusive, + resource_available) + + def advert_link(self, link): + resource_component_name = link.get_component_name() + resource_component_id = link.get_component_id() + resource_source_id = link.get_source_id() + resource_dest_id = link.get_dest_id() + resource_capacity = link.get_capacity() + resource_type = link.get_type() + return self.advert_link_template() % (resource_component_id, + resource_component_name, + resource_source_id, + resource_dest_id, + str(resource_capacity), + resource_type) + + + def advert_header(self): + header = """ +\n""" + return header + + def advert_footer(self): + return "\n" + + def manifest_header(self): + header = """ +\n""" + return header + + def manifest_template(self): + template ="""\n""" + return template + + def manifest_node_close_template(self): + template ="""\n""" + return template + + def manifest_sliver_type_template(self): + template = """\n""" + return template + + def manifest_services_template(self): + template = """\n""" + return template + + def manifest_services_template_root(self): + # BasicAuth for root; PKI for others + template = """\n""" + return template + + def manifest_slivers(self, resources): + """ + Return manifest with information of slivers. + """ + result = self.manifest_header() + for resource in resources: + sliver = resource.get_sliver() + result += self.manifest_template() % (sliver.get_client_id(), resource.get_component_id(), resource.get_component_manager_id(), sliver.get_urn()) + if sliver.get_type(): + result += self.manifest_sliver_type_template() % (sliver.get_type()) + if sliver.get_services(): + services = sliver.get_services() + result += "\n" + for service in services: + if service["login"]["username"].startswith("root:"): + result += self.manifest_services_template_root() % service["login"]["hostname"] + else: + result += self.manifest_services_template() % (service["login"]["hostname"], service["login"]["username"]) + result += "\n" + result += self.manifest_node_close_template() + result += self.manifest_footer() + return result + + def manifest_footer(self): + return "\n" + diff --git a/core/lib/am/rspecs/src/geni/v3/manager.py b/core/lib/am/rspecs/src/geni/v3/manager.py new file mode 100644 index 00000000..4fa214ff --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/manager.py @@ -0,0 +1,18 @@ +from ambase.src.abstract.classes.rspecmanagerbase import RSpecManagerBase +from rspecs.src.geni.v3.craftermanager import CrafterManager +from rspecs.src.geni.v3.parsermanager import ParserManager + +class RSpecManager(RSpecManagerBase): + + def __init__(self): + self.__crafter = CrafterManager() + self.__parser = ParserManager() + + def compose_advertisement(self, resources): + return self.__crafter.get_advertisement(resources) + + def compose_manifest(self, slivers): + return self.__crafter.manifest_slivers(slivers) + + def parse_request(self, request_rspec): + return self.__parser.parse_request_rspec(request_rspec) diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/__init__.py b/core/lib/am/rspecs/src/geni/v3/openflow/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/container/__init__.py b/core/lib/am/rspecs/src/geni/v3/openflow/container/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/container/controller.py b/core/lib/am/rspecs/src/geni/v3/openflow/container/controller.py new file mode 100644 index 00000000..5a37e670 --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/openflow/container/controller.py @@ -0,0 +1,51 @@ +from rspecs.src.geni.v3.container.resource import Resource + +class Controller(Resource): + + def __init__(self): + Resource.__init__(self) + self.__uri = None + self.__port = None + self.__type = None + self.__protocol = None + + def get_uri(self): + return self.__uri + + + def get_port(self): + return self.__port + + + def get_type(self): + return self.__type + + def get_protocol(self): + return self.__protocol + + def set_uri(self, value): + self.__uri = value + + + def set_port(self, value): + self.__port = value + + + def set_type(self, value): + self.__type = value + + def set_protocol(self, value): + self.__protocol = value + + def get_url(self): + return "%s:%s:%d" % (self.__protocol, self.__uri, self.__port) + + def parse_url(self, url): + parts = url.split(":") + self.__protocol = parts[0] + self.__uri = parts[1] + self.__port = int(parts[2]) + + + + \ No newline at end of file diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/container/dpid.py b/core/lib/am/rspecs/src/geni/v3/openflow/container/dpid.py new file mode 100644 index 00000000..8b52e4bf --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/openflow/container/dpid.py @@ -0,0 +1,31 @@ +from rspecs.src.geni.v3.container.resource import Resource + +class DPID(Resource): + + def __init__(self): + Resource.__init__(self) + self.__datapath = None + self.__ports = list() + + def get_datapath(self): + return self.__datapath + + + def get_ports(self): + return self.__ports + + + def set_datapath(self, value): + self.__datapath = value + + + def set_ports(self, value): + self.__ports = value + + def add_port(self, value): + if not self.__ports: + self.__ports = list() + self.__ports.append(value) + + + \ No newline at end of file diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/container/flowspace.py b/core/lib/am/rspecs/src/geni/v3/openflow/container/flowspace.py new file mode 100644 index 00000000..843dad84 --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/openflow/container/flowspace.py @@ -0,0 +1,56 @@ +from rspecs.src.geni.v3.container.sliver import Sliver + +class FlowSpace(Sliver): + + def __init__(self): + Sliver.__init__(self) + self.__email = None + self.__description = None + self.__controller = None + self.__groups = list() + self.__state = None + + def get_email(self): + return self.__email + + + def get_description(self): + return self.__description + + + def get_controller(self): + return self.__controller + + + def get_groups(self): + return self.__groups + + + def get_state(self): + return self.__state + + + def set_email(self, value): + self.__email = value + + + def set_description(self, value): + self.__description = value + + + def set_controller(self, value): + self.__controller = value + + + def set_groups(self, value): + self.__groups = value + + + def set_state(self, value): + self.__state = value + + + def add_group(self, value): + self.__groups.append(value) + + diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/container/group.py b/core/lib/am/rspecs/src/geni/v3/openflow/container/group.py new file mode 100644 index 00000000..bcb553bd --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/openflow/container/group.py @@ -0,0 +1,44 @@ +from rspecs.src.geni.v3.container.resource import Resource + +class Group(Resource): + + def __init__(self): + Resource.__init__(self) + self.__name = None + self.__dpids = list() + self.__matches = list() + + def get_name(self): + return self.__name + + + def get_dpids(self): + return self.__dpids + + + def get_matches(self): + return self.__matches + + + def set_name(self, value): + self.__name = value + + + def set_dpids(self, value): + self.__dpids = value + + + def set_matches(self, value): + self.__matches = value + + + def add_dpid(self, value): + self.__dpids.append(value) + + + def add_match(self, value): + self.__matches.append(value) + + + + \ No newline at end of file diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/container/link.py b/core/lib/am/rspecs/src/geni/v3/openflow/container/link.py new file mode 100644 index 00000000..ef478809 --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/openflow/container/link.py @@ -0,0 +1,41 @@ +from rspecs.src.geni.v3.container.resource import Resource + +class Link(Resource): + + def __init__(self): + Resource.__init__(self) + self.__src_dpid = None + self.__src_port = None + self.__dst_dpid = None + self.__dst_port = None + + def get_src_dpid(self): + return self.__src_dpid + + + def get_src_port(self): + return self.__src_port + + + def get_dst_dpid(self): + return self.__dst_dpid + + + def get_dst_port(self): + return self.__dst_port + + + def set_src_dpid(self, value): + self.__src_dpid = value + + + def set_src_port(self, value): + self.__src_port = value + + + def set_dst_dpid(self, value): + self.__dst_dpid = value + + + def set_dst_port(self, value): + self.__dst_port = value diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/container/match.py b/core/lib/am/rspecs/src/geni/v3/openflow/container/match.py new file mode 100644 index 00000000..9c965e36 --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/openflow/container/match.py @@ -0,0 +1,134 @@ +from rspecs.src.geni.v3.container.resource import Resource + +class Match(Resource): + + def __init__(self): + Resource.__init__(self) + self.__group = None + self.__dl_src = list() + self.__dl_dst = list() + self.__dl_type = list() + self.__dl_vlan = list() + self.__nw_src = list() + self.__nw_dst = list() + self.__nw_proto = list() + self.__tp_src = list() + self.__tp_dst = list() + + def get_group(self): + return self.__group + + def get_dl_src(self): + return self.__dl_src + + + def get_dl_dst(self): + return self.__dl_dst + + + def get_dl_type(self): + return self.__dl_type + + + def get_dl_vlan(self): + return self.__dl_vlan + + + def get_nw_src(self): + return self.__nw_src + + + def get_nw_dst(self): + return self.__nw_dst + + + def get_nw_proto(self): + return self.__nw_proto + + + def get_tp_src(self): + return self.__tp_src + + + def get_tp_dst(self): + return self.__tp_dst + + + def set_group(self, value): + self.__group = value + + + def set_dl_src(self, value): + self.__dl_src = value + + + def set_dl_dst(self, value): + self.__dl_dst = value + + + def set_dl_type(self, value): + self.__dl_type = value + + + def set_dl_vlan(self, value): + self.__dl_vlan = value + + + def set_nw_src(self, value): + self.__nw_src = value + + + def set_nw_dst(self, value): + self.__nw_dst = value + + + def set_nw_proto(self, value): + self.__nw_proto = value + + + def set_tp_src(self, value): + self.__tp_src = value + + + def set_tp_dst(self, value): + self.__tp_dst = value + + def add_dl_src(self, value): + self.__dl_src.append(value) + + + def add_dl_dst(self, value): + self.__dl_dst.append(value) + + + def add_dl_type(self, value): + self.__dl_type.append(value) + + + def add_dl_vlan(self, value): + self.__dl_vlan.append(value) + + + def add_nw_src(self, value): + self.__nw_src.append(value) + + + def add_nw_dst(self, value): + self.__nw_dst.append(value) + + + def add_nw_proto(self, value): + self.__nw_proto.append(value) + + + def add_tp_src(self, value): + self.__tp_src.append(value) + + + def add_tp_dst(self, value): + self.__tp_dst.append(value) + + + + + \ No newline at end of file diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/container/port.py b/core/lib/am/rspecs/src/geni/v3/openflow/container/port.py new file mode 100644 index 00000000..cf0ec100 --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/openflow/container/port.py @@ -0,0 +1,30 @@ +from rspecs.src.geni.v3.container.resource import Resource + +class Port(Resource): + + def __init__(self): + Resource.__init__(self) + self.__name = None + self.__num = None + self.__features = None + + def get_name(self): + return self.__name + + def get_num(self): + return self.__num + + def get_features(self): + return self.__features + + def set_name(self, value): + self.__name = value + + def set_num(self, value): + self.__num = value + + def set_features(self, value): + self.__features = value + + + \ No newline at end of file diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/foamlibcrafter.py b/core/lib/am/rspecs/src/geni/v3/openflow/foamlibcrafter.py new file mode 100644 index 00000000..eb60332e --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/openflow/foamlibcrafter.py @@ -0,0 +1,141 @@ +# Copyright (c) 2011-2012 The Board of Trustees of The Leland Stanford Junior University + +from cStringIO import StringIO +from lxml import etree as ET + + +class FOAMLibCrafter: + + def __init__(self): + + self.OFNSv3 = "http://www.geni.net/resources/rspec/ext/openflow/3" + self.OFNSv4 = "http://www.geni.net/resources/rspec/ext/openflow/4" + #TOPONSv1 = "http://geni.bssoftworks.com/rspec/ext/topo/1" + self.PGNS = "http://www.geni.net/resources/rspec/3" + self.XSNS = "http://www.w3.org/2001/XMLSchema-instance" + self.__config = None + + def get_config(self): + return self.__config + + def set_config(self, value): + self.__config = value + + def get_advertisement(self, resources): + NSMAP = {None: "%s" % (self.PGNS), + "xs" : "%s" % (self.XSNS), + "openflow" : "%s" % (self.OFNSv3)} + + rspec = ET.Element("rspec", nsmap=NSMAP) + rspec.attrib["{%s}schemaLocation" % (self.XSNS)] = self.PGNS + " " \ + "http://www.geni.net/resources/rspec/3/ad.xsd " + \ + self.OFNSv3 + " " \ + "http://www.geni.net/resources/rspec/ext/openflow/3/of-ad.xsd" + rspec.attrib["type"] = "advertisement" + + links = self.filter_links(resources) + devices = self.filter_devices(resources) + + for dpid in devices: + self.ad_device(rspec, dpid) + + for link in links: + self.ad_link(rspec, link) + + xml = StringIO() + ET.ElementTree(rspec).write(xml) + return xml.getvalue() + + + #def generateSwitchComponentID(self, dpid): + # return "urn:publicid:IDN+openflow:%s+datapath+%s" % (config.HRN, dpid.get_datapath()) + + + def ad_device (self, rspec, dpid, active=True): + od = ET.SubElement(rspec, "{%s}datapath" % (self.OFNSv3)) + od.attrib["component_id"] = dpid.get_component_id() + od.attrib["component_manager_id"] = dpid.get_component_manager_id() + od.attrib["dpid"] = str(dpid.get_datapath()) + + locdata = None + if locdata: + ET.SubElement(od, "{%s}location" % (self.OFNSv3), country=locdata.country, latitude=locdata.lat, longitude=locdata.long) + + if active: + ports = dpid.get_ports() + for port in ports: + if (port.get_features() == None): + p = ET.SubElement(od, "{%s}port" % (self.OFNSv3), num=str(port.get_num()), name=str(port.get_name())) + else: + p = ET.SubElement(od, "{%s}port" % (self.OFNSv3), num=str(port.get_num()), name=str(port.get_name()), features=port.get_features()) + #for info in attachments.setdefault(port.name, []): + # a = ET.SubElement(p, "{%s}attachment" % (self.OFNSv3)) + # a.attrib["remote_component_id"] = info.remote_component_id + # a.attrib["remote_port"] = info.remote_port + # a.attrib["desc"] = info.desc + + def ad_link(self, rspec, link, federated=False): + + def add_dpid(od, datapath): + dpids = ET.SubElement(od, "{%s}datapath" %(self.OFNSv3)) + dpids.attrib["component_id"] = datapath.get_component_id()#"urn:publicid:IDN+openflow:%s+datapath+%s" % (config.HRN, str(datapath)) + dpids.attrib["component_manager_id"] = datapath.get_component_manager_id()#"urn:publicid:IDN+openflow:%s+cm" % (config.HRN) + dpids.attrib["dpid"] = str(datapath.get_datapath()) + + def add_port(od, port): + ps = ET.SubElement(od, "{%s}port" %(self.OFNSv3)) + ps.attrib["port_num"] = str(port) + + def add_device(od, device): + devices = ET.SubElement(od, "{%s}device" %(self.OFNSv3)) + devices.attrib["component_id"] = device.get_component_id() #"urn:publicid:IDN+federation:%s+device+%s" % (config.HRN, device) + devices.attrib["component_manager_id"] = device.get_component_manager_id()#"urn:publicid:IDN+federation:%s+cm" % (config.HRN) + + if federated: + add = add_device + else: + add = add_dpid + + od = ET.SubElement(rspec, "{%s}link" % (self.OFNSv3)) + od.attrib["component_id"] = link.get_component_id()#"urn:publicid:IDN+openflow:%s+link+%s_%s_%s_%s" %(config.HRN,str(link.get_src_dpid().get_datapath()), str(link.get_src_port().get_num()),str(link.get_dst_dpid().get_datapath()),str(link.get_dst_port().get_num())) + add(od, link.get_src_dpid()) + add_port(od, link.get_src_port().get_num()) + add(od,link.get_dst_dpid()) + add_port(od,link.get_dst_port().get_num()) + + def get_manifest(self, flowspace): + NSMAP = {None: "%s" % (self.PGNS), + "xs" : "%s" % (self.XSNS), + "openflow" : "%s" % (self.OFNSv3)} + + rspec = ET.Element("rspec", nsmap=NSMAP) + rspec.attrib["{%s}schemaLocation" % (self.XSNS)] = self.PGNS + " " \ + "http://www.geni.net/resources/rspec/3/manifest.xsd " + \ + self.OFNSv3 + " " \ + "http://www.geni.net/resources/rspec/ext/openflow/3/of-resv.xsd" + rspec.attrib["type"] = "manifest" + + od = ET.SubElement(rspec, "{%s}sliver" % (self.OFNSv3)) + od.attrib["urn"] = flowspace.get_urn() + od.attrib["description"] = flowspace.get_urn() + od.attrib["email"] = flowspace.get_email() + od.attrib["status"] = flowspace.get_state() + + xml = StringIO() + ET.ElementTree(rspec).write(xml) + return xml.getvalue() + + def filter_links(self, resources): + return self.__filter_by("Link", resources) + + def filter_devices(self, resources): + return self.__filter_by("Device", resources) + + + def __filter_by(self, filter_key, resources ): + filtered_resources = list() + for r in resources: + if r.get_type() == filter_key: + filtered_resources.append(r) + return filtered_resources + diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/foamlibparser.py b/core/lib/am/rspecs/src/geni/v3/openflow/foamlibparser.py new file mode 100644 index 00000000..a2d219ee --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/openflow/foamlibparser.py @@ -0,0 +1,192 @@ +from cStringIO import StringIO +from lxml import etree as ET +from rspecs.src.geni.v3.openflow.container.flowspace import FlowSpace +from rspecs.src.geni.v3.openflow.container.controller import Controller +from rspecs.src.geni.v3.openflow.container.group import Group +from rspecs.src.geni.v3.openflow.container.match import Match +from rspecs.src.geni.v3.openflow.container.dpid import DPID +from rspecs.src.geni.v3.openflow.container.port import Port + +class FOAMLibParser: + + def __init__(self): + self.OFNSv3 = "http://www.geni.net/resources/rspec/ext/openflow/3" + + + def parse_request(self, rspec): + + s = StringIO(rspec) + dom = ET.parse(s) + + sliver_dom = dom.find('{%s}sliver' % (self.OFNSv3)) + controller_elems = sliver_dom.findall('{%s}controller' % (self.OFNSv3)) + groups = sliver_dom.findall('{%s}group' % (self.OFNSv3)) + matches_dom = sliver_dom.findall('{%s}match' % (self.OFNSv3)) + + try: + flowspace = self.__parse_sliver(sliver_dom) + except: + raise Exception("Error Parsing OpenFlow RSpec on Sliver part") + try: + controller = self.__parse_controller(controller_elems) + except: + raise Exception("Error Parsing OpenFlow RSpec on Controller Part") + try: + groups = self.__parse_groups(groups) + except: + raise Exception("Error Parsing OpenFlow RSpec on Groups Part") + try: + matches, raw_groups = self.__parse_matches(matches_dom) + except Exception as e: + print e + raise Exception("Error Parsing OpenFlow RSpec on Match Part") + + if raw_groups: + groups.extend(raw_groups) + groups_w_match = list() + for group in groups: + for match in matches: + if group.get_name() == match.get_group(): + group.add_match(match) + groups_w_match.append(group) + flowspace.set_controller(controller) + flowspace.set_groups(groups_w_match) + return flowspace + + #vlinks = sliver_dom.findall('{%s}vlink' % (self.OFNSv3)) + #for virtuallink in vlinks: + # vl = self.parseVirtualLink(virtuallink, self.OFNSv3) + # self.addVirtualLink(vl) + + def __parse_sliver(self, sliver_dom): + if sliver_dom is None: + raise Exception("No Sliver Defined") + flowspace = FlowSpace() + flowspace.set_email(sliver_dom.get("email", None)) + flowspace.set_description(sliver_dom.get("description", None)) + flowspace.set_ref = sliver_dom.get("ref", None) + return flowspace + + def __parse_controller(self, controller_elems): + controller = Controller() + if controller_elems is None: + raise Exception("No Controller Defined")#NoControllersDefined() + controller_elems = controller_elems[0] + controller.set_type(controller_elems.get("type")) + controller.parse_url(controller_elems.get("url")) + return controller + + def __parse_groups(self, groups_dom): + groups = list() + for grp in groups_dom: + group = Group() + dplist = [] + grpname = grp.get("name") + if grpname is None: + raise Exception("No grup name for group")#NoGroupName() + datapaths = grp.findall('{%s}datapath' % (self.OFNSv3)) + for dp in datapaths: + dplist.append(self.__parse_datapath(dp)) + group.set_name(grpname) + group.set_dpids(dplist) + groups.append(group) + return groups + + def __create_raw_group(self, group_name, datapath_dom): + group = Group() + dplist = [] + for dp in datapath_dom: + dplist.append(self.__parse_datapath(dp)) + group.set_name(group_name) + group.set_dpids(dplist) + return group + + + def __parse_datapath(self, dpid_dom): + component_manager_id = dpid_dom.get("component_manager_id") + component_id = dpid_dom.get("component_id") + datapath_id = dpid_dom.get("dpid") + + dpid = DPID() + dpid.set_component_manager_id(component_manager_id) + dpid.set_component_id(component_id) + dpid.set_datapath(datapath_id) + + ports = list() + for port_dom in dpid_dom.findall('{%s}port' % (self.OFNSv3)): + p = Port() + p.set_num(int(port_dom.get("num"))) + p.set_name(str(port_dom.get("name"))) + ports.append(p) + dpid.set_ports(ports) + return dpid + + def __parse_matches(self, matches_dom): + matches = list() + raw_groups = list() + for match_dom in matches_dom: + group_dom = match_dom.find("{%s}use-group" % (self.OFNSv3)) + if group_dom != None: + group_name = group_dom.get("name") + else: + group_name = "default" + str(matches_dom.index(match_dom)) + raw_groups.append(self.__create_raw_group(group_name, match_dom.findall('{%s}datapath' % (self.OFNSv3)))) + + match = self.__parse_flowspec(match_dom) + match.set_group(group_name) + matches.append(match) + return matches, raw_groups + + + def __parse_flowspec(self, match_dom): + packet_dom = match_dom.find("{%s}packet" % (self.OFNSv3)) + + match = Match() + + nodes = packet_dom.findall('{%s}dl_src' % (self.OFNSv3)) + for dls in nodes: + macstr = dls.get("value").strip() + match.add_dl_src(macstr) + + nodes = packet_dom.findall('{%s}dl_dst' % (self.OFNSv3)) + for dld in nodes: + macstr = dld.get("value").strip() + match.add_dl_dst(macstr) + + nodes = packet_dom.findall('{%s}dl_type' % (self.OFNSv3)) + for dlt in nodes: + dltstr = dlt.get("value").strip() + match.add_dl_type(dltstr) + + nodes = packet_dom.findall('{%s}dl_vlan' % (self.OFNSv3)) + for elem in nodes: + vlidstr = elem.get("value").strip() + match.add_dl_vlan(vlidstr) + + nodes = packet_dom.findall('{%s}nw_src' % (self.OFNSv3)) + for elem in nodes: + nwstr = elem.get("value").strip() + match.add_nw_src(nwstr) + + nodes = packet_dom.findall('{%s}nw_dst' % (self.OFNSv3)) + for elem in nodes: + nwstr = elem.get("value").strip() + match.add_nw_dst(nwstr) + + nodes = packet_dom.findall('{%s}nw_proto' % (self.OFNSv3)) + for elem in nodes: + nwproto = elem.get("value").strip() + match.add_nw_proto(nwproto) + + nodes = packet_dom.findall('{%s}tp_src' % (self.OFNSv3)) + for elem in nodes: + tpsrc = elem.get("value").strip() + match.add_tp_src(tpsrc) + + nodes = packet_dom.findall('{%s}tp_dst' % (self.OFNSv3)) + for elem in nodes: + tpdst = elem.get("value").strip() + match.add_tp_dst(tpdst) + + return match + diff --git a/core/lib/am/rspecs/src/geni/v3/openflow/manager.py b/core/lib/am/rspecs/src/geni/v3/openflow/manager.py new file mode 100644 index 00000000..8becb084 --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/openflow/manager.py @@ -0,0 +1,19 @@ +from ambase.src.abstract.classes.rspecmanagerbase import RSpecManagerBase +from rspecs.src.geni.v3.openflow.foamlibcrafter import FOAMLibCrafter +from rspecs.src.geni.v3.openflow.foamlibparser import FOAMLibParser + +class OpenFlowRSpecManager(RSpecManagerBase): + + def __init__(self): + self.__crafter = FOAMLibCrafter() + self.__parser = FOAMLibParser() + + def compose_advertisement(self, resources): + return self.__crafter.get_advertisement(resources) + + def compose_manifest(self, slivers): + return self.__crafter.get_manifest(slivers) + + def parse_request(self,rspec): + return self.__parser.parse_request(rspec) + diff --git a/core/lib/am/rspecs/src/geni/v3/parsermanager.py b/core/lib/am/rspecs/src/geni/v3/parsermanager.py new file mode 100644 index 00000000..d775010e --- /dev/null +++ b/core/lib/am/rspecs/src/geni/v3/parsermanager.py @@ -0,0 +1,81 @@ +from xml.dom.minidom import parseString +from rspecs.src.geni.v3.container.resource import Resource +from rspecs.src.geni.v3.container.sliver import Sliver +from rspecs.src.geni.v3.container.link import Link + +class ParserManager: + + def __init__(self): + pass + + def parse_request_rspec(self,rspec): + rspec_dom = parseString(rspec) + resources = list() + geni_nodes = rspec_dom.getElementsByTagName('node') + geni_links = rspec_dom.getElementsByTagName('link') + nodes = self.parse_nodes(geni_nodes) + resources.extend(nodes) + links = self.parse_links(geni_links) + resources.extend(links) + return resources + + def parse_nodes(self, nodes): + vms = list() + for element in nodes: + node = element.attributes + resource = Resource() + sliver = Sliver() + if node.has_key('client_id'): + resource.set_id(node.get('client_id').value) + if node.has_key('interfaces'): + pass #Implement when needed + if node.has_key('component_manager_id'): + resource.set_component_manager_id(node.get('component_manager_id').value) + + if node.has_key('component_manager_name'): + resource.set_component_manager_name(node.get('component_manager_name').value) + + if node.has_key('component_id'): + resource.set_component_id(node.get('component_id').value) + + if node.has_key('component_name'): + resource.set_component_id(node.get('component_name').value) + + if node.has_key('services'): + pass #Implement when needed + + slivers = element.getElementsByTagName("sliver_type") + for sliver_elem in slivers: + sliver = Sliver() + attrs = sliver_elem.attributes + if attrs.has_key('name'): + sliver.set_name(attrs.get('name').value) + + sliver.set_resource(resource) + resource.set_sliver(sliver) + + vms.append(resource) + return vms + + def parse_links(self, link_elems): + links = list() + for elem in link_elems: + elem_attrs = elem.attributes + link = Link() + if elem_attrs.has_key("component_id"): + link.set_component_id(elem_attrs.get("component_id").value) + if elem_attrs.has_key("component_name"): + link.set_component_id(elem_attrs.get("component_name").value) + link_props = elem.getElementsByTagName("property") + link_prop = link_props[0].attributes + if link_prop.has_key("source_id"): + link.set_source_id(link_prop.get("source_id").value) + if link_prop.has_key("dest_id"): + link.set_dest_id(link_prop.get("dest_id").value) + if link_prop.has_key("capacity"): + link.set_capacity(link_prop.get("capacity").value) + link_type = elem.getElementsByTagName("link_type")[0].attributes + if link_type.has_key("name"): + link.set_type(link_type.get("name").value) + links.append(link) + return links diff --git a/core/lib/am/settings/__init__.py b/core/lib/am/settings/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/settings/src/__init__.py b/core/lib/am/settings/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/lib/am/settings/src/settings.py b/core/lib/am/settings/src/settings.py new file mode 100644 index 00000000..53f6a30c --- /dev/null +++ b/core/lib/am/settings/src/settings.py @@ -0,0 +1,32 @@ +class Settings: + import os + OCF_PATH = os.getenv("OCF_PATH") + + SFA_DATA_DIR = os.path.join(OCF_PATH, "optin_manager/src/python/openflow/optin_manager/sfa/my_roots/") + SFA_INTERFACE_HRN = "ambase" + MY_ROOTS_DIR = os.path.join(OCF_PATH, "core/lib/am/ext/my_roots/") + ROOT_CERT = os.path.join(MY_ROOTS_DIR, "topdomain.gid") + TRUSTED_ROOTS_DIR = os.path.join(OCF_PATH, "core/lib/am/ext/trusted_roots/") + SFA_CREDENTIAL_SCHEMA = os.path.join(OCF_PATH, "optin_manager/src/python/openflow/optin_manager/sfa/schemas/credential.xsd") + + """Default Authority Settings""" + HRN = "MyAuthority" + + """ Delegate Settings """ + REQ_RSPEC_TYPE = "GENI" + REQ_RSPEC_VERSION = 3 + REQ_RSPEC_SCHEMA = "http://www.geni.net/resources/rspec/3/request.xsd" + REQ_RSPEC_NAMESPACE = "http://www.geni.net/resources/rspec/3" + REQ_RSPEC_EXTENSIONS = [] + + AD_RSPEC_TYPE = "GENI" + AD_RSPEC_VERSION = 3 + AD_RSPEC_SCHEMA = "http://www.geni.net/resources/rspec/3/ad.xsd" + AD_RSPEC_NAMESPACE = "http://www.geni.net/resources/rspec/3" + AD_RSPEC_EXTENSIONS = [] + + GENI_API_VERSION = 3 + AM_URL = "https://llull.ctx.i2cat.net:8445/xmlrpc/geni/3" + CREDENTIAL_TYPE = "geni_sfa" + AM_TYPE = "GENI" + AM_CODE_VERSION = 2.7 diff --git a/deploy/common/certificates/ca_cert.conf b/deploy/common/certificates/ca_cert.conf new file mode 100755 index 00000000..17adc065 --- /dev/null +++ b/deploy/common/certificates/ca_cert.conf @@ -0,0 +1,23 @@ +[ req ] +default_bits = 4096 +#default_keyfile = ca.key +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no + +[ req_distinguished_name ] +CN = OfeliaHost +OU = DANA +O = i2cat +C = ES + +[ req_attributes ] + +[ca_extensions] +basicConstraints=critical,CA:true +subjectAltName = 'URI:urn:publicid:IDN+fibre+am+authority+sa', URI:urn:uuid:e709558d-193d-4a3b-a54a-70b9233ecda6, 'email:carolina.fernandez@i2cat.net' + +[cert_extensions] +basicConstraints=critical,CA:false +subjectAltName = 'URI:urn:publicid:IDN+fibre+am+authority+sa', URI:urn:uuid:e709558d-193d-4a3b-a54a-70b9233ecda6, 'email:carolina.fernandez@i2cat.net' + diff --git a/deploy/common/certificates/certificates.sh b/deploy/common/certificates/certificates.sh new file mode 100755 index 00000000..d8192a4d --- /dev/null +++ b/deploy/common/certificates/certificates.sh @@ -0,0 +1,173 @@ +#!/bin/bash + +# XXX: Move somewhere else +#source ../utils/utils.sh + +### +# Check if certificates are installed under /etc/apache2/ssl.crt/ +# 1 - Installed: check that these are GIDs (check extensions) +# 1.1 - If GIDs, do nothing +# 1.2 - If no GIDs, parse current certificates and generate GIDs from them +# 2 - Not installed: generate from scratch (check code under ofver's lib/ssl/) +### + +# 1. Check if installation = OFELIA + +cd $PWD + +accept_generate_certificates=0 +can_parse_certs=true + +server_cert_file=/etc/apache2/ssl.crt/server.crt +ca_cert_file=/etc/apache2/ssl.crt/ca.crt + +if [[ ! -f $ca_cert_file ]] && [[ ! -f $server_cert_file ]]; then + $can_parse_certs=false + accept_generate_certificates="y" + echo "Certificates not found: preparing to generate new ones..." + +else + isGID=$(openssl x509 -text -in $ca_cert_file -noout | grep "X509v3 Subject Alternative Name:") + if [[ ! -z "$isGID" ]]; then + echo "There were found GID-based certificates already" + exit 1 + else + + while [[ ! $accept_generate_certificates =~ ^[y|Y|n|N]$ ]] + do + echo "Do you wish to generate GID-based certificates? [y/N]" + read accept_generate_certificates + if [[ ! $accept_generate_certificates =~ ^[y|Y|n|N]$ ]]; then + echo "Please accept (\"y\") or reject (\"n\") the generation" + fi + if [[ $accept_generate_certificates =~ ^[n|N]$ ]]; then + echo "Certificate generation aborted by user" + exit 1 + fi + done + fi +fi + + +# XXX: Perform generation of GIDs + +while [[ ! $ofelia_install =~ ^[y|Y|n|N]$ ]] + do + echo "Is this an OFELIA installation? [y/N]" + read ofelia_install + if [[ ! $ofelia_install =~ ^[y|Y|n|N]$ ]]; then + echo "Please say yes (\"y\") or no (\"n\")" + fi + done + +if [[ $ofelia_install =~ ^[n|N]$ ]]; then + + URI_AUTHORITY="'URI:urn:publicid:IDN+fibre+authority+sa'" + URI_SUBAUTHORITY="'URI:urn:publicid:IDN+fibre:am+cm'" +else + + URI_AUTHORITY="'URI:urn:publicid:IDN+ofelia+authority+sa'" + URI_SUBAUTHORITY="'URI:urn:publicid:IDN+ofelia:am+cm'" +fi + +function parse_cert { + #Pass the cerificate file location in the first arg + #Pass the config_file location as second arg + #Pass the URI_AUTHORITY as third arg + + PARSED_COUNTRY=$(openssl x509 -in $1 -noout -text | grep "Subject:" | grep -oPm1 "(?<=C=)[^<]+" | cut -d"," -f1) + PARSED_OU=$(openssl x509 -in $1 -noout -text | grep "Subject:" | grep -oPm1 "(?<=OU=)[^<]+" | cut -d"," -f1) + PARSED_ORG=$(openssl x509 -in $1 -noout -text | grep "Subject:" | grep -oPm1 "(?<=O=)[^<]+" | cut -d"," -f1) + PARSED_CN=$(openssl x509 -in $1 -noout -text | grep "Subject:" | grep -oPm1 "(?<=CN=)[^<]+" | cut -d"," -f1| cut -d "/" -f1) + PARSED_EMAIL=$(openssl x509 -in $ca_cert_file -noout -text | grep "Subject:" | grep -oPm1 "(?<=CN=)[^<]+" | cut -d"," -f1 | cut -d "/" -f2 | cut -d "=" -f2) + URI_HEADER="URI:urn:uuid:" + UUID=$(python -c 'import uuid; print uuid.uuid4()') + URI_UUID="'"$URI_HEADER$UUID"'" + EMAIL_STR="email:" + EMAIL_SET="'"$EMAIL_STR$PARSED_EMAIL"'" + SUBJECT_ALT_NAME="$3,$URI_UUID,$EMAIL_SET" + + populate_config_file $2 $PARSED_CN $PARSED_OU $PARSED_ORG $PARSED_COUNTRY $SUBJECT_ALT_NAME + +} + +function create_cert { + #Pass the certificate_config file as first argument + #Pass the URI_AUTHORITY as second param + echo "Please enter the following Certificate params" + read -p "Common Name (CN): " cn + read -p "Organizational Unit Name (OU): " ou + read -p "Organization (O): " org + read -p "Country (C): " count + read -p "Email: " email + CREATED_URI_HEADER="URI:urn:uuid:" + CREATED_UUID=$(python -c 'import uuid; print uuid.uuid4()') + CREATED_URI_UUID="'"$CREATED_URI_HEADER$CREATED_UUID"'" + CREATED_EMAIL_STR="email:" + CREATED_EMAIL_SET="$CREATED_EMAIL_STR$email" + CREATED_SUBJECT_ALT_NAME="$2,$CREATED_URI_UUID,$CREATED_EMAIL_SET" + populate_config_file $1 $cn $ou $org $count $CREATED_SUBJECT_ALT_NAME + +} + +function populate_config_file { + #Pass the config file location as firs arg + #Pass the CN as second arg + #Pass the OU as third arg + #Pass the O as fourth arg + #Pass the C as fith arg + #pass the subjectAltName as sixth arg + sed -i "s/\(CN *= *\).*/\1$2/g" $1 + sed -i "s/\(OU *= *\).*/\1$3/g" $1 + sed -i "s/\(O *= *\).*/\1$4/g" $1 + sed -i "s/\(C *= *\).*/\1$5/g" $1 + sed -i "s/\(subjectAltName *= *\).*/\1$6/g" $1 +} + +cp ca_cert.conf ca_cert_copy.conf +cp server_cert.conf server_cert_copy.conf +ca_config_file="ca_cert_copy.conf" +server_config_file="server_cert_copy.conf" + +if [[ $can_parse_certs==true ]]; then + parse_cert $ca_cert_file $ca_config_file $URI_AUTHORITY + parse_cert $server_cert_file $server_config_file $URI_SUBAUTHORITY + +else + echo "Setting up CA parameters" + create_cert $ca_config_file $URI_AUTHORITY + echo "Setting up Server parameters" + create_cert $server_config_file $URI_SUBAUTHORITY + +fi + +#Generating the certificates + +#Generate CA key +openssl genrsa -out ca.key 4096 + +#Generate signature request for CA +openssl req -new -nodes -config $ca_config_file > ca.csr + +#Generate CA certificate with extensions +openssl x509 -extfile $ca_config_file -extensions ca_extensions -sha1 -req -signkey ca.key -days 7300 < ca.csr > ca.crt + +#Generate server key +openssl genrsa -out server.key 4096 + +#Generate signature request for server to CA +openssl req -new -nodes -key server.key -config $server_config_file > server.csr + +#Generate server certificate with extensions signed by CA +openssl x509 -extfile $server_config_file -extensions cert_extensions -sha1 -req -CAcreateserial -CAkey ca.key -CA ca.crt -days 3650 < server.csr > server.crt + + +echo cleaning directory... +rm -rf *.csr +mv *.crt /etc/apache2/ssl.crt +mv *.key /etc/apache2/ssl.key + +rm $server_config_file +rm $ca_config_file + +echo "Certificates successfully generated" diff --git a/deploy/common/certificates/server_cert.conf b/deploy/common/certificates/server_cert.conf new file mode 100755 index 00000000..089023bb --- /dev/null +++ b/deploy/common/certificates/server_cert.conf @@ -0,0 +1,23 @@ +[ req ] +default_bits = 4096 +#default_keyfile = ca.key +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no + +[ req_distinguished_name ] +CN = exp.i2cat.fp7-fibre.eu +OU = DANA +O = i2CAT +C = SP + +[ req_attributes ] + +[ca_extensions] +basicConstraints=critical,CA:false +subjectAltName = "URI:urn:publicid:IDN+fibre+authority+sa", "URI:urn:uuid:ff161085-ffff-4e85-912b-21589358a6fc","email:leonardo.bergesio@i2cat.net" + +[cert_extensions] +basicConstraints=critical,CA:false +subjectAltName = "URI:urn:publicid:IDN+fibre+am+authority+sa", "URI:urn:uuid:fe161095-eeee-4e85-992a-21589368a6fc","email:leonardo.bergesio@i2cat.net" + diff --git a/deploy/dependencies/apache.sh b/deploy/dependencies/apache.sh new file mode 100755 index 00000000..fecff012 --- /dev/null +++ b/deploy/dependencies/apache.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: script to install Apache2 and potentially its CA and server certificates +### + + +# XXX: Move somewhere else +source ../utils/utils.sh + +# If dpkg shows entry with $FLOWVISOR_RELEASE on it, do not install +if [[ $(dpkg -l | grep "apache2") != "" ]]; then + warning "Apache2 already installed. Skipping..." + exit 1 +else + apt-get -y install apache2 +fi + +success "Apache2 successfully installed" diff --git a/deploy/dependencies/flowvisor.sh b/deploy/dependencies/flowvisor.sh new file mode 100755 index 00000000..852c7807 --- /dev/null +++ b/deploy/dependencies/flowvisor.sh @@ -0,0 +1,137 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: script to install a specific FlowVisor release and configure according to our needs +### + + +# XXX: Move somewhere else +source ../utils/utils.sh + +FLOWVISOR_RELEASE="1.4.0-1" +flowvisor_path="/etc/flowvisor" +flowvisor_config_file="$flowvisor_path/config.json" + +# Folders +flowvisor_etc_folder="/etc/flowvisor" +flowvisor_db_folder="/usr/share/db/flowvisor" +flowvisor_log_folder="/var/log/flowvisor" + +# Set hourly job to determine that FlowVisor is running (otherwise restarts it) +function link_cron_job() +{ + current_dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + if [ -f $current_dir/../utils/scripts/flowvisor_cron.sh ] && [ -d /etc/cron.hourly ]; then + chmod +x $current_dir/../utils/scripts/flowvisor_cron.sh + ln -s $current_dir/../utils/scripts/flowvisor_cron.sh /etc/cron.hourly/flowvisor + fi +} + +# If dpkg shows entry with $FLOWVISOR_RELEASE on it, do not install +if [[ $(dpkg -l | grep flowvisor) =~ $FLOWVISOR_RELEASE ]]; then + link_cron_job + warning "FlowVisor $FLOWVISOR_RELEASE already installed. Skipping..." + exit 1 +elif [[ $(which flowvisor) ]]; then + warning "FlowVisor already installed. If you want to upgrade, please do so manually.\ + +Keep in mind to make a backup of your configuration file (either config.xml or config.json) beforehand.\ + +More information: https://github.com/OPENNETWORKINGLAB/flowvisor/wiki/Installation-from-Source#upgrading-flowvisor" + exit 1 +fi + +# Create backup if folders already exist. This is done to avoid problems in installation +if [[ -d $flowvisor_etc_folder ]]; then + warning "Folder '$flowvisor_etc_folder' present: backup to '$flowvisor_etc_folder.bak'" + mv $flowvisor_etc_folder $flowvisor_etc_folder.bak +fi +if [[ -d $flowvisor_db_folder ]]; then + warning "Folder '$flowvisor_db_folder' present: backup to '$flowvisor_db_folder.bak'" + mv $flowvisor_db_folder $flowvisor_db_folder.bak +fi +if [[ -d $flowvisor_log_folder ]]; then + warning "Folder '$flowvisor_log_folder' present: backup to '$flowvisor_log_folder.bak'" + mv $flowvisor_log_folder $flowvisor_log_folder.bak +fi + +# Otherwise, ask for confirmation on the installation of FlowVisor +# and warn about compatibility issues +accept_deploy_flowvisor=0 +while [[ ! $accept_deploy_flowvisor =~ ^[y|Y|n|N]$ ]] + do + print_header "Do you wish to install FlowVisor $FLOWVISOR_RELEASE? [y/n]" +# warning " Notice that you *must* use FOAM with this." + warning " Note: if you already installed a FlowVisor outside the Debian package system, you should $(print_bold back up) and transfer your current flowspace(s) to the newly installed FlowVisor and finally $(print_bold removing) your old version." +# print " > If you want to keep using Opt-in please press \"n\"\n > If you want to keep the flowspaces at your current FlowVisor and are not able to backup these, please press \"n\"" + print " > If you have some flowspaces at your current FlowVisor that you want to keep, press \"n\"" + read accept_deploy_flowvisor + if [[ ! $accept_deploy_flowvisor =~ ^[y|Y|n|N]$ ]]; then + print "Please accept (\"y\") or reject (\"n\") the installation" + fi + if [[ $accept_deploy_flowvisor =~ ^[n|N]$ ]]; then + warning "FlowVisor installation aborted by user" + exit 1 + fi + done + +# Obtain public repository key, install it, remove it +wget http://updates.onlab.us/GPG-KEY-ONLAB +apt-key add GPG-KEY-ONLAB +rm GPG-KEY-ONLAB + +# Add the following line to /etc/apt/sources.list (if not already there) +if [[ ! $(grep "deb http://updates.onlab.us/debian" /etc/apt/sources.list | grep -v "^#") ]]; then + echo """ +# +# FlowVisor at ON.LAB +# +## Release - the latest and greatest +deb http://updates.onlab.us/debian stable/ +# Staging - what's coming next +deb http://updates.onlab.us/debian staging/ +# Nightly - the bleeding edge +deb http://updates.onlab.us/debian unstable/""" >> /etc/apt/sources.list +fi + +# Update your apt database +apt-get update + +# Install sudo package to be able to run some commands at FlowVisor initscript +apt-get -y install sudo +# Install chosen version of FlowVisor +apt-get -y install flowvisor=$FLOWVISOR_RELEASE + +# Generate new configuration and load it +if [[ ! -f $flowvisor_config_file ]]; then + fvconfig generate $flowvisor_config_file +fi +# Change configuration to show topology links +sed -i "s/\"run_topology_server\": false/\"run_topology_server\": true/g" $flowvisor_config_file +# Load configuration in database +fvconfig load $flowvisor_path/config.json + +# Modify to meet our requirements +# Correct permissions in order to be able to pass this point and write to the DB +chown flowvisor:flowvisor /usr/share/db/flowvisor -R +chown flowvisor:flowvisor $flowvisor_path -R +chmod 755 /usr/share/db/flowvisor/derby.log +# Modify log configuration to avoid writing on stdout +sed -i -e "s/^log4j.rootCategory=WARN, system/#log4j.rootCategory=WARN, system\nlog4j.rootCategory=WARN/" $flowvisor_path/fvlog.config + +# Start FlowVisor +/etc/init.d/flowvisor restart + +# Set hourly job to determine that FlowVisor is running (otherwise restarts it) +current_dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +if [ -f $current_dir/../utils/scripts/flowvisor_cron.sh ] && [ -d /etc/cron.hourly ]; then + ln -s $current_dir/../utils/scripts/flowvisor_cron.sh /etc/cron.hourly/flowvisor +fi + +# Link to hourly cron job +link_cron_job + +success "FlowVisor successfully installed" diff --git a/deploy/dependencies/mysqlserver.sh b/deploy/dependencies/mysqlserver.sh new file mode 100755 index 00000000..dcd18354 --- /dev/null +++ b/deploy/dependencies/mysqlserver.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: script to install MySQL-server and create the databases +### + + +# XXX: Move somewhere else +source ../utils/utils.sh + +if [[ $(dpkg -l | grep mysql-server) != "" ]]; then + warning "MySQL server already installed. Skipping..." +else + apt-get -y install mysql-server +fi + +#ocf_modules=("expedient" "optin_manager" "vt_manager") +ocf_modules=$@ +# Replace all "[", "]", ",", "'" by a space +ocf_modules=${ocf_modules//[\[\]\,\']/ } +# Create array from list +ocf_modules=($ocf_modules) +# TODO fix and call method 'list_to_array' +#source ../utils/utils.sh +#ocf_modules=$(list_to_array "$ocf_modules") + +prefix_database="ocf__" +host="localhost" + +## Ask for root and user credentials +while [[ $user_root == "" ]] + do + echo "" + print "Provide your MySQL root credentials in order to create the OCF databases" + read -p "MySQL root user: " user_root + #user=${user:-root} + echo -n Password: + read -s password_root + echo "" +done +while [[ $user == "" ]] + do + echo "" + print "Credentials for the user with access the OCF databases (if doubtful use the previous ones)" + read -p "User: " user + echo -n Password: + read -s password + echo "" +done + +## Create user if it does not exists +if [[ $(mysql -u $user_root -p$password_root --execute="SELECT * FROM mysql.user WHERE User='$user';") == "" ]]; then + mysql -u $user_root -p$password_root --execute="CREATE USER '$user'@$host IDENTIFIED BY '$password';" + echo "Creating MySQL user $user@$host" +fi + +for module in "${ocf_modules[@]}" + do + mysql -u $user_root -p$password_root --execute="CREATE DATABASE IF NOT EXISTS $prefix_database$module;" + echo "CREATE DATABASE IF NOT EXISTS $prefix_database$module;" + mysql -u $user_root -p$password_root --execute="GRANT ALL ON $prefix_database$module.* to $user@$host IDENTIFIED BY '$password';" + echo "Granting privileges on $prefix_database$module.* to $user@$host" +done + +success "MySQL databases successfully created" diff --git a/deploy/gui/checklist.sh b/deploy/gui/checklist.sh new file mode 100755 index 00000000..df665aee --- /dev/null +++ b/deploy/gui/checklist.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: OFELIA FP7 +# @description: Checklist dialog with Whiptail. +### + +## Arguments +title=$1 +message=$2 +height=$3 +width=$4 +list_num=$5 +list_options=$6 + +whiptail --backtitle "OFELIA Control Framework" --title "$title" --checklist "$message" "$height" "$width" "$list_length" "$list_options" diff --git a/deploy/gui/end.sh b/deploy/gui/end.sh new file mode 100755 index 00000000..33d1195f --- /dev/null +++ b/deploy/gui/end.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: OFELIA FP7 +# @description: Ending info screen dialog with Whiptail. +### + +## Arguments +whiptail_action=$1 +whiptail_action=${whiptail_action,,} +whiptail_message_title="OCF $whiptail_action" +whiptail_message_description="The $whiptail_action process has finished"; + +## Parameters for whiptail screen +whiptail_width=45 + +## Paths +gui_path="./deploy/gui" + +.${gui_path}/info.sh "$whiptail_message_title finished" "$whiptail_message_description" "8" "$whiptail_width" diff --git a/deploy/gui/info.sh b/deploy/gui/info.sh new file mode 100755 index 00000000..a17cd5af --- /dev/null +++ b/deploy/gui/info.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: OFELIA FP7 +# @description: Message box dialog with Whiptail. +### + +## Arguments +title=$1 +message=$2 +height=$3 +width=$4 + +whiptail --backtitle "OFELIA Control Framework" --title "$title" --msgbox "$message" $height $width diff --git a/deploy/gui/splash.sh b/deploy/gui/splash.sh new file mode 100755 index 00000000..fbaa4353 --- /dev/null +++ b/deploy/gui/splash.sh @@ -0,0 +1,155 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: OFELIA FP7 +# @description: Common entry point for installation, upgrade and removal. +### + +## Arguments +action_arg=$1 +shift # Consume first argument +whiptail_args=$@ +num_whiptail_args=$# +# Replace all "[", "]", "," by a space +whiptail_args=${whiptail_args//[\[\]\,]/ } +# Create array from list +whiptail_args=($whiptail_args) +# TODO fix and call method 'list_to_array' +#source ../utils/utils.sh +#ocf_modules=$(list_to_array "$whiptail_args") + +## Paths +gui_path="./deploy/gui" + +## Return code +confirm_deploy=0 + +## Parameters for whiptail screen +whiptail_width=45 + +ofver_actions=(install upgrade update remove) +case $action_arg in + install ) + whiptail_action_title="OCF installation"; + whiptail_message_title="Installation"; + whiptail_message_description="You have stopped or cancelled the installation"; + ;; + upgrade|update ) + whiptail_action_title="OCF upgrade"; + whiptail_message_title="Upgrade"; + whiptail_message_description="You have stopped or cancelled the upgrade"; + ;; + remove ) + whiptail_action_title="OCF removal"; + whiptail_message_title="Removal"; + whiptail_message_description="You have stopped or cancelled the removal"; + ;; + migrate ) + whiptail_action_title="OCF migration"; + whiptail_message_title="Migration"; + whiptail_message_description="You have stopped or cancelled the migration"; + ;; + *) + echo "Usage: ./splash {install | upgrade | update | remove | migrate} "; + exit 1; + ;; +esac +whiptail_checklist_description="Choose the modules by pressing SPACE key and then TAB to reach or " +whiptail_checklist_options="" + + +function exit_on_null_arg() +{ + if [[ $1 == "" ]]; then + .${gui_path}/info.sh "$whiptail_message_title stopped" "$whiptail_message_description" "8" "$whiptail_width" + confirm_deploy=1 + exit $confirm_deploy + fi +} + +function contains_element() +{ + local e + for e in "${@:2}"; do + [[ "$e" == "$1" ]] && echo 0 && return 0; + done + echo 1 && return 1 +} + +function do_ofver_action() +{ + for i in "${whiptail_args[@]}" + do + whiptail_checklist_options="$whiptail_checklist_options $i false" + done + + ocf_modules_deploy="" + while [ $confirm_deploy -eq 0 ]; do + #./${gui_path}/checklist.sh "$whiptail_action_title" "$whiptail_checklist_description" $(($((2+$num_whiptail_args))*3)) $whiptail_width $num_whiptail_args $whiptail_checklist_options + ocf_modules_deploy=$(whiptail --checklist --noitem "$whiptail_checklist_description" $(($(($num_whiptail_args))*3)) $whiptail_width $num_whiptail_args $whiptail_checklist_options --backtitle "OFELIA Control Framework" --title "$whiptail_action_title" 3>&1 1>&2 2>&3) + #ocf_modules_deploy=$? + # Saving the return code (0/1) + exit_on_null_arg $ocf_modules_deploy + + ocf_modules_deploy_exitcode=$(echo $ocf_modules_deploy | rev | cut -d "\"" -f1) + # Removing the return code + ocf_modules_deploy=$(echo $ocf_modules_deploy | head -c -2) + # If installation is cancelled (ocf_modules_deploy_exitcode != 0), no further step is loaded + exit_on_null_arg $ocf_modules_deploy + + # Formatting the chosen OCF modules to show in a confirm box + ocf_modules_deploy_confirmed="" + ocf_modules_deploy_confirmed_set=($ocf_modules_deploy) + num_ocf_modules_deploy_confirmed_set=${#ocf_modules_deploy_confirmed_set[@]} + if [[ num_ocf_modules_deploy_confirmed_set -eq 0 ]]; then + num_ocf_modules_deploy_confirmed_set=1 + fi + + for i in "${ocf_modules_deploy_confirmed_set[@]}" + do + # Remove quotes from module names also + ocf_modules_deploy_confirmed="$ocf_modules_deploy_confirmed *${i//[\"]/ }\n" + done + + .${gui_path}/yesno.sh "You are going to $action_arg the following modules:\n\n$ocf_modules_deploy_confirmed" $(($(($num_ocf_modules_deploy_confirmed_set+4))*2)) $whiptail_width + confirm_deploy=$? + # Negate exit code (whiptail --yesno => yes: 1, no: 0) + confirm_deploy=$((! $confirm_deploy )) + done + # Write file to be parsed later + echo $ocf_modules_deploy > ocf_modules_deploy +} + +function do_migration() +{ + chosen_folder=$(dirname $PWD) + while [ $confirm_deploy -eq 0 ]; do + ocf_modules_deploy=$(whiptail --inputbox "Please choose the destination path for your code" 8 78 $chosen_folder --title "$whiptail_action_title" --backtitle "OFELIA Control Framework" 3>&1 1>&2 2>&3) + # Update chosen folder to the last value set by the user + chosen_folder=$ocf_modules_deploy + # Saving the return code (0/1) + exit_on_null_arg $chosen_folder + + .${gui_path}/yesno.sh "You are about to $action_arg the OCF modules to the following location:\n\n$ocf_modules_deploy" $(($((1+4))*2)) $whiptail_width + confirm_deploy=$? + # Negate exit code (whiptail --yesno => yes: 1, no: 0) + confirm_deploy=$((! $confirm_deploy )) + done + # Write file to be parsed later + echo $ocf_modules_deploy > ocf_modules_deploy +} + +function main() +{ + if [[ $(contains_element "$action_arg" "${ofver_actions[@]}") == 0 ]]; then + do_ofver_action $@ + elif [[ $action_arg == "migrate" ]]; then + do_migration $@ + fi +} + +main $@ +return_code=$? +exit $return_code diff --git a/deploy/gui/start_step.sh b/deploy/gui/start_step.sh new file mode 100755 index 00000000..41e04e25 --- /dev/null +++ b/deploy/gui/start_step.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: OFELIA FP7 +# @description: Step to inform that an action over a module is about to take place. +### + +## Arguments +action_arg=$1 +shift # Consume first argument +ocf_module=$@ + +## Paths +gui_path="./deploy/gui" + +## Parameters for whiptail screen +case $action_arg in + install ) + message_title="OCF installation"; + ;; + upgrade|update ) + message_title="OCF upgrade"; + ;; + remove ) + message_title="OCF removal"; + ;; + *) + echo "Usage: ./start_step {install | upgrade | update | remove} "; + exit 1; + ;; +esac +message_description="Continue to $action_arg module $ocf_module..."; + +.${gui_path}/info.sh "$message_title" "$message_description" "8" "45" diff --git a/deploy/gui/yesno.sh b/deploy/gui/yesno.sh new file mode 100755 index 00000000..df7c895e --- /dev/null +++ b/deploy/gui/yesno.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: OFELIA FP7 +# @description: Yes/no dialog with Whiptail. +### + +## Arguments +message=$1 +height=$2 +width=$3 + +whiptail --backtitle "OFELIA Control Framework" --yesno "$message" $height $width diff --git a/deploy/install.py b/deploy/install.py new file mode 100644 index 00000000..31755891 --- /dev/null +++ b/deploy/install.py @@ -0,0 +1,22 @@ +import os +from utils import utils + +""" +@author: CarolinaFernandez + +Installs OCF modules and external libraries/dependencies. +""" + +# Show choice screen for OCF modules available for install +ocf_modules_install = utils.invoke_splash_screen("install", utils.get_modules()) + +if ocf_modules_install: + # Perform installation of common files + utils.install_dependencies(utils.common_path, ocf_modules_install) + # Perform installation of external libraries+dependencies + utils.install_dependencies(utils.dependencies_path, ocf_modules_install) + # Perform installation of available modules + utils.install_modules(ocf_modules_install) + +# Show ending screen +utils.invoke_ending_screen("Installation") diff --git a/deploy/migrate.py b/deploy/migrate.py new file mode 100644 index 00000000..8d6ce7b7 --- /dev/null +++ b/deploy/migrate.py @@ -0,0 +1,18 @@ +import os +from utils import utils + +""" +@author: CarolinaFernandez + +Migrate OCF components to another physical location within the host. +""" + +# Show input screen to set new path for OCF components +new_location = utils.invoke_splash_screen("migrate", utils.get_modules()) + +if new_location: + # Perform migration to new location + utils.migrate_framework(new_location[0]) + +# Show ending screen. Cannot run when files are migrated +#utils.invoke_ending_screen("Migration") diff --git a/deploy/remove.py b/deploy/remove.py new file mode 100644 index 00000000..beb29345 --- /dev/null +++ b/deploy/remove.py @@ -0,0 +1,16 @@ +from utils import utils + +""" +@author: CarolinaFernandez + +Removes OCF modules and external libraries/dependencies. +""" + +# Show choice screen for OCF modules installed (available for removal) +ocf_modules_remove = utils.invoke_splash_screen("remove", utils.get_installed_modules()) + +if ocf_modules_remove: + utils.remove_modules(ocf_modules_remove) + +# Show ending screen +utils.invoke_ending_screen("Removal") diff --git a/deploy/upgrade.py b/deploy/upgrade.py new file mode 100644 index 00000000..c5784de1 --- /dev/null +++ b/deploy/upgrade.py @@ -0,0 +1,19 @@ +from utils import utils + +""" +@author: CarolinaFernandez + +Upgrades OCF modules. +""" + +# Show choice screen for OCF modules installed (available for upgrade) +ocf_modules_upgrade = utils.invoke_splash_screen("upgrade", utils.get_installed_modules()) + +if ocf_modules_upgrade: + # Perform installation of common files + utils.install_dependencies(utils.common_path, ocf_modules_upgrade) + # Perform upgrade of already installed modules + utils.upgrade_modules(ocf_modules_upgrade) + +# Show ending screen +utils.invoke_ending_screen("Upgrade") diff --git a/deploy/utils/__init__.py b/deploy/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/deploy/utils/migrate.sh b/deploy/utils/migrate.sh new file mode 100755 index 00000000..7ebae1a6 --- /dev/null +++ b/deploy/utils/migrate.sh @@ -0,0 +1,122 @@ +#!/bin/bash + +### +# @author: msune, CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: Shell migration file +### + + +### Import to use other functions +source utils.sh + +function update_apache_symlinks() +{ + current_ocf_path=$1 + new_ocf_path=$2 + + APACHE_SITES_AVAILABLE=/etc/apache2/sites-available + sites_available=$(ls -la $APACHE_SITES_AVAILABLE) + + print_header "Updating symlinks under Apache ($APACHE_SITES_AVAILABLE)..." + for f in $sites_available; do + f=$APACHE_SITES_AVAILABLE/$f + if [[ -L "$f" && -f "$f" ]]; then + current_link=$(readlink $f) + if [[ $current_link == *$current_ocf_path* ]]; then + new_link=$(echo $current_link | sed -e "s|${current_ocf_path}|${new_ocf_path}|g") + echo "Unlinking old file: $current_link" + rm $f + echo "Relinking new file: $new_link" + ln -s $new_link $f + fi + fi + done + + APACHE_SITES_CONFD=/etc/apache2/conf.d + sites_available=$(ls -la $APACHE_SITES_CONFD) + + print_header "Updating symlinks under Apache ($APACHE_SITES_CONFD)..." + for f in $sites_available; do + f=$APACHE_SITES_CONFD/$f + if [[ -L "$f" && -f "$f" ]]; then + current_link=$(readlink $f) + if [[ $current_link == *$current_ocf_path* ]]; then + new_link=$(echo $current_link | sed -e "s|${current_ocf_path}|${new_ocf_path}|g") + echo "Unlinking old file: $current_link" + rm $f + echo "Relinking new file: $new_link" + ln -s $new_link $f + fi + fi + done +} + +function update_framework_envvars() +{ + # Update value for environment variable: OCF_PATH + current_ocf_path=$1 + new_ocf_path=$2 + + # Set environment variables in Apache's envvars file + APACHE_ENVVARS=/etc/apache2/envvars + if [ -f $APACHE_ENVVARS ]; then + if [ -z $(grep -q $OCF_PATH $APACHE_ENVVARS) ]; then + print_header "Updating Apache env vars ($APACHE_ENVVARS)..." + # Using different delimiters, as "/" is used within OCF_PATH + sed -i "s|OCF_PATH=$OCF_PATH|OCF_PATH=$new_ocf_path|g" $APACHE_ENVVARS + fi + fi + + # Set environment variables under OS's profile.d folder + PROFILE_D=/etc/profile.d + PROFILE_D_OCF=$PROFILE_D/ocf.sh + if [ -d $PROFILE_D ]; then + if [ -f $PROFILE_D_OCF ]; then + print_header "Updating Unix env vars ($PROFILE_D_OCF)..." + # Using different delimiters, as "/" is used within OCF_PATH + sed -i "s|OCF_PATH=$OCF_PATH|OCF_PATH=$new_ocf_path|g" $PROFILE_D_OCF + fi + fi +} + +function validate_new_ocf_path() +{ + new_ocf_path=$1 + + # Ensure the new path ends with a "/" + last_char=${new_ocf_path#${new_ocf_path%?}} + if [[ $last_char != "/" ]]; then + new_ocf_path=$new_ocf_path/ + fi + + # Ensure the path for the migration still does not exist + if [ -d $new_ocf_path ]; then + error "Path '$new_ocf_path' already exists. Migration cannot be completed" + fi +} + +function migrate_framework() +{ + # Identify current value for OCF_PATH to move symlinks + current_ocf_path=$OCF_PATH + new_ocf_path=$1 + validate_new_ocf_path $new_ocf_path + if [ -d $current_ocf_path ]; then + cp -Rp $current_ocf_path $new_ocf_path + update_apache_symlinks $current_ocf_path $new_ocf_path + update_framework_envvars $current_ocf_path $new_ocf_path + if [ -d $new_ocf_path ]; then + if [ ! -z $(which rsync) ]; then + echo "Syncing files: $current_ocf_path => $new_ocf_path..." + # Double-check everything is in its place + rsync -a $current_ocf_path/ $new_ocf_path + rm -r $current_ocf_path + fi + fi + fi +} + +migrate_framework $@ + diff --git a/deploy/utils/scripts/flowvisor_cron.sh b/deploy/utils/scripts/flowvisor_cron.sh new file mode 100755 index 00000000..f3615bf1 --- /dev/null +++ b/deploy/utils/scripts/flowvisor_cron.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +RESULT=`/bin/ps aux | /bin/grep flowvisor | /bin/grep java | /bin/grep -v flowvisor_cron | /bin/grep -v grep` +FLOWVISOR_LOG=/var/log/flowvisor/flowvisor-stderr.log + +if [ "$RESULT" == "" ]; then + if [ -f $FLOWVISOR_LOG ]; then + echo "[`date`] FlowVisor has failed" >> $FLOWVISOR_LOG + fi + if [ -f /etc/init.d/flowvisor ]; then + /etc/init.d/flowvisor start + else + /usr/local/sbin/flowvisor /usr/local/etc/flowvisor/config.xml > /dev/null 1>&2 & + fi + if [ -f $FLOWVISOR_LOG ]; then + echo "[`date`] FlowVisor restarted" >> $FLOWVISOR_LOG + fi +else + echo "FlowVisor is OK..." +fi diff --git a/deploy/utils/utils.py b/deploy/utils/utils.py new file mode 100644 index 00000000..221d6465 --- /dev/null +++ b/deploy/utils/utils.py @@ -0,0 +1,183 @@ +import os +import subprocess + +""" +@author: CarolinaFernandez + +Utils for the installation of OCF modules. +""" + +ocf_path = os.path.join(os.path.dirname(__file__), "../../") +deploy_path = os.path.join(ocf_path, "deploy") +gui_path = os.path.join(deploy_path, "gui") +common_path = os.path.join(deploy_path, "common") +dependencies_path = os.path.join(deploy_path, "dependencies") + +## Print + +def print_header(text): + print "\033[94m%s\033[0m" % str(text) + +def print_error(text): + print "\033[91m%s\033[0m" % str(text) + +## Paths and files + +def get_modules(): + unallowed_folders = [".git", "core", "deploy", "doc", "modules"] + ocf_modules = sorted(os.walk(ocf_path).next()[1]) + for unallowed_folder in unallowed_folders: + try: + ocf_modules.remove(unallowed_folder) + except ValueError: + pass + return ocf_modules + +def get_installed_modules(): + """ + A module is installed if it contains a .currentVersion file. + """ + ocf_modules_installed = [] + ocf_modules = get_modules() + for ocf_module in ocf_modules: + try: + with open(os.path.join(ocf_path, ocf_module, ".currentVersion")): + ocf_modules_installed.append(ocf_module) + except: + pass + return ocf_modules_installed + +def get_script_files(path): + return [ f for f in os.listdir(path) if f.endswith(".sh") and not f.startswith(".") ] + +def list_modules(modules): + print_header("\nInput all the modules you want to install: ") + for module in modules.keys(): + print_header("%s: %s" % (str(module), str(modules[module]))) + +## System execution + +def execute_command(arg_list): + return_code = subprocess.call(arg_list) + return return_code + +## Screens + +def invoke_step_start_screen(deploy_action, arg): + execute_command(["%s/start_step.sh" % gui_path] + [deploy_action] + [arg]) + +def invoke_info_screen(title, content, height, width): + execute_command(["%s/info.sh" % gui_path] + [title, content, height, width]) + +def invoke_splash_screen(deploy_action, arg_list): + #os.system("./gui/splash.sh %s" % str(ocf_modules)) + + #process = subprocess.Popen(["./gui/splash.sh"], shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + #process.stdin.write(str(arg_list)) + ## Wait for the process to terminate + #out, err = process.communicate() + ##errcode = process.returncode + if not arg_list: + invoke_info_screen("%s stopped" % deploy_action, "There are no modules available for this operation", "8", "45") + return None + return_code = execute_command(["%s/splash.sh" % gui_path] + [deploy_action] + arg_list) + chosen_modules = [] + # Return code for UNIX scripts (0: good, 1: error) + if not return_code: + try: + chosen_modules = open("./ocf_modules_deploy", "r").readlines() + # Parse and convert to list of modules + chosen_modules = " ".join(chosen_modules).replace("\"", "").replace("\n","").split(" ") + os.remove("./ocf_modules_deploy") + except Exception as e: + print_error(e) + return chosen_modules + +def invoke_ending_screen(deploy_action): + if not deploy_action: + return None + else: + return execute_command(["%s/end.sh" % gui_path] + [deploy_action]) + +def clear_screen(): + execute_command(["clear"]) + +## Operations over modules (upgrade, install, remove) + +def upgrade_module(ocf_path, ocf_module): + try: + clear_screen() + current_dir = os.getcwd() + os.chdir(os.path.join(ocf_path, ocf_module, "bin")) + print_header(">> Invoking ofver for %s\n\n" % str(ocf_module)) + return_code = execute_command(["./ofver","upgrade","-f"]) + os.chdir(current_dir) + except Exception as e: + print_error(e) + +def upgrade_modules(ocf_modules): + for ocf_module in ocf_modules: + invoke_step_start_screen("upgrade", ocf_module) + upgrade_module(ocf_path, ocf_module) + +def install_module(ocf_path, ocf_module): + try: + clear_screen() + current_dir = os.getcwd() + os.chdir(os.path.join(ocf_path, ocf_module, "bin")) + print_header(">> Invoking ofver for %s\n\n" % str(ocf_module)) + return_code = execute_command(["./ofver","install","-f"]) + os.chdir(current_dir) + except Exception as e: + print_error(e) + +def install_modules(ocf_modules): + for ocf_module in ocf_modules: + invoke_step_start_screen("install", ocf_module) + install_module(ocf_path, ocf_module) + +def remove_module(ocf_path, ocf_module): + try: + clear_screen() + current_dir = os.getcwd() + os.chdir(os.path.join(ocf_path, ocf_module)) + os.remove(".currentVersion") + os.chdir(current_dir) + except Exception as e: + print_error(e) + +def remove_modules(ocf_modules): + for ocf_module in ocf_modules: + invoke_step_start_screen("remove", ocf_module) + remove_module(ocf_path, ocf_module) + +## Operations over framework (migrate) + +def migrate_framework(new_location): + try: + clear_screen() + current_dir = os.getcwd() + utils_dir = os.path.dirname(__file__) + os.chdir(utils_dir) + return_code = execute_command(["./migrate.sh", new_location]) + os.chdir(new_location) + except Exception as e: + print_error(e) + +## External libraries and dependencies + +def install_dependency(dependencies_path, ocf_dependency, ocf_modules): + try: + clear_screen() + current_dir = os.getcwd() + os.chdir(dependencies_path) + print_header(">> Invoking %s\n\n" % str(ocf_dependency)) + return_code = execute_command(["./%s" % ocf_dependency, "%s" % ocf_modules]) + os.chdir(current_dir) + except Exception as e: + print_error(e) + +def install_dependencies(path, ocf_modules): + ocf_dependencies = get_script_files(path) + for ocf_dependency in ocf_dependencies: + install_dependency(path, ocf_dependency, ocf_modules) diff --git a/deploy/utils/utils.sh b/deploy/utils/utils.sh new file mode 100755 index 00000000..e1bd0361 --- /dev/null +++ b/deploy/utils/utils.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +### +# @author: msune, CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: Shell utils file +### + + +###I/O functions + +##Output utils +txtrst=$(tput sgr0) # Text reset +txtred=$(tput setaf 1) # Red +txtgreen=$(tput setaf 2) # Green +txtylw=$(tput setaf 3) # Yellow +txtbold=$(tput bold) # Bold text + +# Simple print +function print() +{ + if [ "$2" == 1 ]; then + OUT="/dev/stderr" + else + OUT="/dev/stdout" + fi + echo -e "$1" > $OUT +} + +# Make bold text +function print_bold() +{ + print "${txtbold} $@ ${txtrst}" +} + +# Heading print +function print_header() +{ + print "" + print "" + print_bold "${txtgreen}$1 `print_bold $2`" +} + +# Success +function success() +{ + print "${txtgreen}SUCCESS:${txtrst} $1" +} + +# Warning +function warning() +{ + print "${txtylw}WARNING:${txtrst} $1" +} + +# Error function; invoques restore +function error() +{ + print "${txtred}FATAL ERROR:${txtrst} $1" + exit 1 +} + +## INPUT UTILS + +# Confirmation with exit +# Usage: $1: message, [$2 throw error on its presence $NO_RETURN], [$3 when $2 present, do not rollback; $NO_RESCUE] +function confirm() +{ + local VALUE + while : + do + echo "$1. Do you confirm (Y/N)?" + read VALUE + if [ "$VALUE" == "Y" ] || [ "$VALUE" == "y" ]; then + # Accepted + return 0 + elif [ "$VALUE" == "N" ] || [ "$VALUE" == "n" ]; then + # Rejected + error "'$1' clause not confirmed. Aborting..." $3 + fi + done +} + +function pause() +{ + echo $1 + echo -n "Press any key to continue..." + read +} + +## FILE UTILS + +# Recover directory path +function get_directory() +{ + echo `dirname $(readlink -f $1)` +} + +## POST-PROCESSING + +# Convert list (i.e. Python) to bash array +function list_to_array() +{ + list=$@ + # Replace all "[", "]", "," by a space + string=${list//[\[\]\,]/ } + # Create array from list + array=($string) + echo "$array" +} +#arr=$(list_to_array "['expedient', 'vt_manager']") +#echo "array: $arr" + diff --git a/expedient/.gitignore b/expedient/.gitignore new file mode 100644 index 00000000..efcfae0d --- /dev/null +++ b/expedient/.gitignore @@ -0,0 +1,44 @@ +*.pyc +*~ +egeni.db +*.pyc +.*.swp +test +*~ +\#*\# +*.aux +*.bbl +*.log +*.dvi +*.blg +*.out +.xpdf-running +*.orig +*.ngc +*.o +*.so +*\#* +*vsim* +*coregen* +.cproject +.project +chi_tool +pmac_tool +test.pl +fig-vnodes.dia +icing-tr.pdf +om.db +clearinghouse.db +.project +.pydevproject +db/openflow/optin_manager/om.db +src/python/expedient/clearinghouse/deployment_settings.py +secret_key.py +*.0 +*.launch +gcf-x509.*/ +src/python/expedient/clearinghouse/xmlrpc-ssl.crt/*.crt +expedient-settings +deployment_settings.py +*.db +build/ diff --git a/expedient/bin/common/commands b/expedient/bin/common/commands new file mode 100644 index 00000000..a466fd1b --- /dev/null +++ b/expedient/bin/common/commands @@ -0,0 +1,108 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: Commands library +### + +## +#Commands +## + +#Install +function performInstall() +{ + #Override backup (not needed for install) + BACKUP=0 + + #Download app code from repo + downloadCodeFromRepo + + #Determine version + setVersions + + #Version checks + printHeader "Version checkings." "Executing version checking code..." + source "$VERSIONS_PATH/version-checks" + + #Summary&Acceptance + summary `importModule description $DONT_ABORT` + confirm "Proceed with installation/upgrade." $NO_RETURN $NO_RESCUE + + #No backup; rollback should only undo changes + + #Pre-install hook + printHeader "Pre-install." "Executing pre-install hook code..." + loadModule "pre-install-hook" $NO_RESCUE + + #install + printHeader "Install." "Installing software..." + loadModule "install" + + #Post-install hook + printHeader "Post-install." "Executing post-install hook code..." + loadModule "post-install-hook" + + #Install new version file + printHeader "Version file." "Installing/updating version file..." + writeVersion + + printHeader "Installation has been successful for version $TARGETED_VERSION." "Please, make appropiate tests (if not done by installation code) to make sure installation has been completely successful..." + +} + +function performUpgrade() +{ + if [ "$OFVER_UPGRADED_STATUS" != "1" ]; then + + #Load backup to set restoration point + if [ "$BACKUP" == "1" ]; then + printHeader "Backup." "Starting backup..." + loadModule "backup" + fi + + + #Upgrade ofver from repo + upgradeOfverFromRepo + + #Restart with new ofver code + restartOfverInstance + fi + + #Upgrade code from repo (if not already upgraded) + upgradeCodeFromRepo + + #Determine version + setVersions + + #Version checks + printHeader "Version checkings." "Executing version checking code..." + checkVersionJump + source "$VERSIONS_PATH/version-checks" + + #Summary&Acceptance + summary `importModule description $DONT_ABORT` + confirm "Proceed with installation/upgrade." $NO_RETURN $NO_RESCUE + + #Pre-upgrade hook + printHeader "Pre-upgrade." "Executing pre-upgrade hook code..." + loadModule "pre-upgrade-hook" $NO_RESCUE + + #Upgrade + printHeader "Upgrade." "Upgrading software..." + loadModule "upgrade" + + #Post-upgrade hook + printHeader "Post-upgrade." "Executing post-upgrade hook code..." + loadModule "post-upgrade-hook" + + #Install new version file + printHeader "Version file." "Installing/updating version file..." + writeVersion + + printHeader "Upgrade has been succesful to $TARGETED_VERSION from $CURRENT_VERSION." "\nPlease, make appropiate tests (if not done by upgrade code) to make sure upgrade has been completely successful" + +} + diff --git a/expedient/bin/common/init b/expedient/bin/common/init new file mode 100644 index 00000000..0ce333bd --- /dev/null +++ b/expedient/bin/common/init @@ -0,0 +1,87 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: Initialization library +### + +#Usage functions +function usage() +{ + splash 1 + echo "" + echo "Usage: $APP_NAME {install upgrade} [options] " + echo "" + echo -e "\t -h \t Help and usage" + echo -e "\t -d \t Enable debug mode" + echo -e "\t -n \t Disable logging" + echo -e "\t -b \t Disable backup" + echo -e "\t -f \t Force mode. DO NOT USE 'Force mode' in PRODUCTION systems." + echo "" +} + + + +function checkAction() +{ + #Two actions {install,upgrade} + + if [ "$1" == "install" ]; then + ACTION="install" + ACTION_="performInstall" + return + elif [ "$1" == "upgrade" ]; then + ACTION="upgrade" + ACTION_="performUpgrade" + return + elif [ "-h" == "$1" ]; then + usage + exit 0 + fi + + usage + error "Unknown action: $1. Supported actions {install,upgrade}" $NO_RESCUE +} + +#Checks variables existance +function varChecks(){ + if [ "$OFVER_IN_BRANCH" != "1" -a "$OFVER_IN_BRANCH" != "0" ]; then + error 'Invalid or unexistent value for $OFVER_IN_BRANCH setting' $NO_RESCUE + fi +} + +function checkArgsAndParseOpts() +{ + #Save all args + ALL_ARGS="$@" + + printDebug $ALL_ARGS + + #At least one argument required + + if [ $# -lt 1 ]; then + usage + error "Incorrect number of parameters" $NO_RESCUE + fi + + #Check action arg + checkAction $1 + shift 1 + + #Extra args + while getopts ":dnbf" o + do + case "$o" in + + d) DEBUG=1 ;; + n) USE_LOG=0;; + b) BACKUP=0 ;; + f) FORCE=1 ;; + [?]) error "Unkown Option: $1" $NO_RESCUE && usage && exit 1 + exit 1;; + esac + done + +} diff --git a/expedient/bin/common/modules b/expedient/bin/common/modules new file mode 100644 index 00000000..a22fde41 --- /dev/null +++ b/expedient/bin/common/modules @@ -0,0 +1,68 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: Modules library +### + + +## +#Modules +## + + + +#executeModule execute $1 command with the module (e.g. `source` to load or `cat` to import +#Parameters: $1 Command to execute $2 Module name [$3 Flags $NO_RESCUE or $DONT_ABORT ] +function executeModule(){ + #Define file locations + if [ "$ACTION" == "install" ]; then + local FPATH="$VERSIONS_PATH/$TARGETED_VERSION/install/$2" + local DPATH="$VERSIONS_PATH/default/install/$2" + + else + local FPATH="$VERSIONS_PATH/$TARGETED_VERSION/upgrade/$CURRENT_VERSION/$2" #specific v1 -> v2 + local DPATH="$VERSIONS_PATH/$TARGETED_VERSION/upgrade/default/$2" #Generic from , specific to: whatever -> v1 + local DDPATH="$VERSIONS_PATH/default/upgrade/default/$2" #Default + fi + + #Verify existance + #printDebug "Version specific module path: $FPATH" + #printDebug "Default module path: $DPATH" + + if [ -f $FPATH ]; then + #Check version specific first + CURRENT_DIRECTORY=`getDirectory $FPATH` + $1 $FPATH || error "Error importing module '$2'" + return + elif [ -f $DPATH ]; then + #Go to default + CURRENT_DIRECTORY=`getDirectory $DPATH` + $1 $DPATH || error "Error importing module '$2'" + return + elif [ "$ACTION" == "upgrade" ]; then + if [ -f $DDPATH ]; then + #Go to default + CURRENT_DIRECTORY=`getDirectory $DDPATH` + $1 $DDPATH || error "Error importing module '$2'" + return + fi + fi + + #No module + if [ -z "$3" ] || [ "$3" == "$NO_RESCUE" ]; then + error "Could not load module: $2" $3 + fi +} + +#Loads (source) module +function loadModule(){ + executeModule "source" $1 $2 $3 +} + +#echos module path +function importModule(){ + executeModule "echo" $1 $2 $3 +} diff --git a/expedient/bin/common/repository b/expedient/bin/common/repository new file mode 100644 index 00000000..30e925f7 --- /dev/null +++ b/expedient/bin/common/repository @@ -0,0 +1,59 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: repository utils +### + +function recoverUpgradeState(){ + if [ -f $UPGRADE_REG ]; then + OFVER_UPGRADED_STATUS="1" + printDebug "Recovering state..." + source $UPGRADE_REG + rm -f $UGPRADE_REG + printDebug "Recovered state: EXECPID=$EXECPID, BACKUP_PATH=$BACKUP_PATH, LOG=$LOG" + fi +} + +function upgradeOfverFromRepo(){ + #Call user-defined code to upgrade ofver code (and if in-branch the app code) + source "$EXECPATH/repo" || error "Could not load $EXECPATH/repo script to upgrade ofver code" $NO_RESCUE +} + +function restartOfverInstance(){ + #Save upgrade info + echo -e "EXECPID=$EXECPID\nBACKUP_PATH=$BACKUP_PATH\nLOG=$LOG" > $UPGRADE_REG + + #Unlock + unlock + + #Execute ofver again with all params and exit + TO_EXECUTE="$EXECPATH/ofver $ALL_ARGS" + print "Restarting ofver...\n" + printDebug "Restarting ofver by triggering: $TO_EXECUTE" + + /bin/bash $TO_EXECUTE + exit 0 +} + +function upgradeCodeFromRepo(){ + if [ "$OFVER_IN_BRANCH" != "1" ]; then + #Upgrade app code + print "Upgrading application code..." + loadModule "repo" $NO_RESCUE + else + print "Using in-branch ofver code. Application code already retrieved" + fi +} + +function downloadCodeFromRepo(){ + if [ "$OFVER_IN_BRANCH" != "1" ]; then + #Downloading app code + print "Downloading application code..." + loadModule "repo" $NO_RESCUE + else + print "Using in-branch ofver code. Application code already retrieved" + fi +} diff --git a/expedient/bin/common/utils b/expedient/bin/common/utils new file mode 100644 index 00000000..288ff630 --- /dev/null +++ b/expedient/bin/common/utils @@ -0,0 +1,247 @@ +#!/bin/bash + +### +# @author: msune, CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: Shell utils file +### + + + +###I/O functions + +##Output utils +txtrst=$(tput sgr0) # Text reset +txtred=$(tput setaf 1) # Red +txtgreen=$(tput setaf 2) # Green +txtylw=$(tput setaf 3) # Yellow +txtbold=$(tput bold) # Bold text + +#Log function +function log() +{ + if [ "$USE_LOG" == 1 ]; then + echo -e "`date`> $1" >> $LOG + fi +} + +#Simple print +function print() +{ + if [ "$2" == 1 ]; then + #stderr + OUT="/dev/stderr" + else + OUT="/dev/stdout" + fi + log "$1" + echo -e "$1" > $OUT +} + +#Make bold text +function printBold() +{ + print "${txtbold} $@ ${txtrst}" +} + +#Heading print +function printHeader() +{ + print "" + print "" +# print "${txtgreen}$1 ${txtrst} $2" +# printBold "${txtgreen}$1 `printBold $2`" + printBold "${txtgreen}$1 $2" +} + +#debug print +function printDebug() +{ + if [ "$DEBUG" == 1 ]; then + print "$1" + log "$1" + fi +} + +#Warning +function warning() +{ + print "${txtylw}WARNING:${txtrst} $1" +} + +#Splash +function splash() +{ + echo -e "\n$APP_NAME v$APP_VER \n" + if [ "$1" == "1" ]; then + echo -e "Description: $APP_DESC" + echo -e "Authorship: $APP_AUTHOR" + fi + echo -e "Websites: $APP_WEB" + echo "" +} + +#Summary +function summary() +{ + print "" + print "" + print SUMMARY INSTALL/UPGRADE + print "******************************************************************************" + print "Action type: ${txtgreen} $ACTION ${txtrst}" + if [ "$ACTION" == "install" ]; then + print "Targeted version: $TARGETED_VERSION" + else + print "Targeted version: $TARGETED_VERSION \t Current(installed): $CURRENT_VERSION" + fi + print "" + print "Flags:" + + #Flags + if [ "$ACTION" == "upgrade" ]; then + if [ "$BACKUP" == "0" ]; then + print "\t - ${txtylw}Backup DISABLED!!!!${txtrst}" + else + print "\t + ${txtgreen}Backup enabled${txtrst}" + fi + fi + + if [ "$USE_LOG" == "1" ]; then + print "\t + Logging enabled" + else + print "\t - Logging disabled" + fi + if [ "$DEBUG" == "1" ]; then + print "\t + Debug Mode enabled" + fi + if [ "$FORCE" == "1" ]; then + print "\t + ${txtred}Force mode...${txtrst}" + fi + + print "" + #Description + if [ -n "$1" ]; then + print "Description:" + cat "$1" + fi + print "******************************************************************************" + +} + +#Error function; invoques restore +function error() +{ + local ERROR="${txtred}FATAL ERROR:${txtrst} $1" + + print "$ERROR" + + if [ -z "$2" ]; then + loadModule rollback + fi + + #printDebug "Unlocking and exiting..." + unlock + rm -rf $UPGRADE_REG + + exit 1 +} + +##Input utils + +#Confirmation with exit +# Usage: $1: message, [$2 throw error on its presence $NO_RETURN], [$3 when $2 present, do not rollback; $NO_RESCUE] +function confirm() +{ + local VALUE + while : + do + echo "$1. Do you confirm (Y/N)?" + read VALUE + + if [ "$VALUE" == "Y" ] || [ "$VALUE" == "y" ]; then + #Accepted + return 0 + elif [ "$VALUE" == "N" ] || [ "$VALUE" == "n" ]; then + #Rejected + if [ "$2" == "$DONT_ABORT" ]; then + return 1 + else + error "'$1' clause not confirmed. Aborting..." $3 + fi + fi + done + +} + +function pause +{ + echo $1 + echo -n "Press any key to continue..." + read +} + +##File utils +#Recover directory path +#$1 contains +function getDirectory() +{ + echo `dirname $(readlink -f $1)` +} + +#Aux functions for lock +function is_number() +{ + printf '%f' "$1" &>/dev/null && echo "1" || echo "0"; +} + +function get_parent_pid() +{ + process=$1 + while [[ `is_number $process` == 1 ]]; do + if [[ $process -gt 0 ]]; then + process=`cat /proc/$((process))/stat | awk '{print $4 }'` + echo $process + else + break + fi + done +} + +function contains_element() +{ + local e + for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 1; done + return 0 +} + +#Check that no other OFVER instance is already running +function lock() +{ + currentPID=$$ + pids=( $(ps aux | grep "ofver" | grep "bash" | grep -v "grep" | awk '{print $2}') ) + for pid in "${pids[@]}"; do + # Do not lock if non-related (not parent of the current + # process) and older PIDs run in the same folder + if [[ $pid -lt $((currentPID-1)) && + `pwdx $pid | awk '{print $2}'` == $PWD ]]; then + pidFromParent=0 + if [[ $ENABLE_OFVER_SON_PROCESSES -eq 1 ]]; then + parent_pids=( $(get_parent_pid $currentPID) ) + contains_element $pid "${parent_pids[@]}" + pidFromParent=$? + fi + if [[ $pidFromParent -eq 0 ]]; then + print "${txtred}FATAL ERROR:${txtrst} Could not acquire lock... Other instance (PID $pid) of ofver is already running." + exit 1 + fi + fi + done +} + +#Unlocks automatically (process terminated after execution) +function unlock() +{ + return +} + diff --git a/expedient/bin/common/versioning b/expedient/bin/common/versioning new file mode 100644 index 00000000..0f59c32f --- /dev/null +++ b/expedient/bin/common/versioning @@ -0,0 +1,45 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: Versioning library +### + +## +#Versioning +## + +function checkVersionJump() +{ + local FPATH="$VERSIONS_PATH/$TARGETED_VERSION/upgrade/$CURRENT_VERSION/forbidden" + printDebug "Checking forbidden file in $FPATH" + + if [ -f "$FPATH" ]; then + error "Forbidden upgrade from version $CURRENT_VERSION to $TARGETED_VERSION" $NO_RESCUE + fi +} + +function setVersions() +{ + TARGETED_VERSION=`cat $TARGETED_VERSION_PATH` || error "Could not find targeted(new) version identifier. File missing" $NO_RESCUE + + printDebug "Detected target version:$TARGETED_VERSION" + + if [ -f "$CURRENT_VERSION_PATH" ]; then + CURRENT_VERSION=`cat $CURRENT_VERSION_PATH ` + else + if [ "$ACTION" == "upgrade" ]; then + warning "Could not determine current(installed) version. \"default\" upgrade will be used..." + CURRENT_VERSION=default + fi + fi + + printDebug "Detected current version:$CURRENT_VERSION" +} + +function writeVersion() +{ + echo $TARGETED_VERSION > $CURRENT_VERSION_PATH +} diff --git a/expedient/bin/log/.gitignore b/expedient/bin/log/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/expedient/bin/ofver b/expedient/bin/ofver new file mode 100755 index 00000000..6503aa02 --- /dev/null +++ b/expedient/bin/ofver @@ -0,0 +1,85 @@ +#!/bin/bash + +### +# @author: msune, CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: +### + +##GENERAL parameters +BASH="/bin/bash" +EXECPATH=$PWD +EXECPID=$$ +LOG="$EXECPATH/log/`date +"%R-%d%m%y"`#$EXECPID" +BACKUP_PATH="$EXECPATH/rescue/`date +"%R-%d%m%y"`#$EXECPID" +DEBUG=0 +USE_LOG=1 +BACKUP=1 +FORCE=0 +#Enable/disable ofver to call itself (through a son process) without being blocked +ENABLE_OFVER_SON_PROCESSES=1 + +##STATIC CONSTANTS +NO_RETURN=1 +DONT_ABORT=2 +NO_RESCUE=1 +UPGRADE_REG=".upgradeReg" + +##Other info +APP_NAME="ofver" +APP_VER="0.4" +APP_DESC="OFelia VERsioning system; a simple set of bash scripts to simplify repository based installations and upgrades." +APP_AUTHOR="{ marc.sune, leonardo.bergesio } @i2cat.net (i2CAT foundation)" +APP_WEB="http://code.google.com/p/ofver/, http://www.fp7-ofelia.eu" + + + +##Main method +function main() +{ + #Check root + if [ "$(id -u)" != "0" ]; then + echo "$(tput setaf 1)FATAL ERROR: $(tput sgr0)$APP_NAME must be run by root user" + exit 1 + fi + + ##Load settings + source "$EXECPATH/settings" || ( echo "FATAL ERROR: Cannot import settings" && exit 1 ) + + ##Load libraries + source "$EXECPATH/common/utils" || ( echo "FATAL ERROR: Cannot import utils library" && exit 1 ) + source "$EXECPATH/common/init" || error "Cannot import init library" $NO_RESCUE + source "$EXECPATH/common/versioning" ||error "Cannot import commands library" $NO_RESCUE + source "$EXECPATH/common/modules" ||error "Cannot import module library" $NO_RESCUE + source "$EXECPATH/common/commands" ||error "Cannot import commands library" $NO_RESCUE + source "$EXECPATH/common/repository" ||error "Cannot import repository library" $NO_RESCUE + + lock + + #Check in_branch flag + varChecks + + #Arguments + checkArgsAndParseOpts $@ + + #Try to recover upgrade from the 2 step process + recoverUpgradeState + + #Splash + splash + + #Invoke action + eval $ACTION_ + + #Finish + unlock + rm -rf $UPGRADE_REG + + print "Finishing execution..." + exit 0 +} + + +#Calling main +main $@ diff --git a/expedient/bin/repo b/expedient/bin/repo new file mode 100755 index 00000000..7e2f3684 --- /dev/null +++ b/expedient/bin/repo @@ -0,0 +1,14 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: script for upgrading ofver code (and application code if you are using ofver in-branch). This can be as simple as a 'git pull' or 'svn update', for instance. +### + +#Example +#/usr/bin/git pull +#echo /usr/bin/git pull + +git pull || error "Could not upgrade ofver code" diff --git a/expedient/bin/rescue/.gitignore b/expedient/bin/rescue/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/expedient/bin/settings b/expedient/bin/settings new file mode 100755 index 00000000..51019416 --- /dev/null +++ b/expedient/bin/settings @@ -0,0 +1,17 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description:settings file +### + +VERSIONS_PATH="$EXECPATH/versions/" + +#Version files +CURRENT_VERSION_PATH="$EXECPATH/../.currentVersion" # Make sure this file is under .svnignore .gitignore... +TARGETED_VERSION_PATH="$EXECPATH/../version" # Make sure this file is NOT under .svnignore .gitignore... + +#Use ofver in branch or out of the branch (either in another repository branch or in a separate repository) +OFVER_IN_BRANCH=1 diff --git a/expedient/bin/versions/0.13/upgrade/0.12/backup b/expedient/bin/versions/0.13/upgrade/0.12/backup new file mode 100644 index 00000000..4ae1c078 --- /dev/null +++ b/expedient/bin/versions/0.13/upgrade/0.12/backup @@ -0,0 +1,32 @@ +#!/bin/bash + +### +# @author: msune, lbergesio +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: backup module +### + +#inform user +printHeader "info#" "Using specific v0.13 backup module..." + +SRC_DIR=/opt/ofelia/expedient/ + +#Backing up files +mkdir -p $BACKUP_PATH +cp -R $SRC_DIR/src $BACKUP_PATH + +#Backing up database +local TMP_PATH=$PWD + +#Load the pre-backup-upgrade-hook in order to update localsettings before using python manage.py +printHeader "Pre-backup." "Executing custom backup code in order to upgrade localsettings ..." +loadModule "pre-backup-upgrade-hook" $NO_RESCUE + + +cd $SRC_DIR/src/python/expedient/clearinghouse/ || error "Target directory does not exist anymore?¿" + +python manage.py dumpdata > $BACKUP_PATH/dbdump.data || warning "Could not backup data. Check database for inconsistencies in foreign keys or many-to-many relationships" +python $TMP_PATH/versions/default/upgrade/tools/sqlDump.py $BACKUP_PATH/dbdump.sql "expedient.clearinghouse.settings" || warning "Could not backup data using SQL... (is redundant). Proceeding with upgrade..." +cd $TMP_PATH + diff --git a/expedient/bin/versions/0.13/upgrade/0.12/pre-backup-upgrade-hook b/expedient/bin/versions/0.13/upgrade/0.12/pre-backup-upgrade-hook new file mode 100644 index 00000000..2a88e99c --- /dev/null +++ b/expedient/bin/versions/0.13/upgrade/0.12/pre-backup-upgrade-hook @@ -0,0 +1,50 @@ +#!/bin/bash + +### +# @author:lbergesio +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: post-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.12-0.13 post-upgrade-hook module..." + +SRC_DIR=/opt/ofelia/expedient/ +EMAIL_PATTERNS="EMAIL_ DEFAULT_EMAIL" + +local TMP_PATH=$PWD + +cd $SRC_DIR/src/python/expedient/clearinghouse/ || error "Target directory does not exit anymore?¿" + +#Adding/Moving new variables to localsettings.py +printHeader ">" "Adding new settings to localsettings.py ..." +echo "Set Island name please, it will appear in the header of all the web pages of the Clearinghouse app: " +read ISLAND_NAME +sed -i "/ISLAND_NAME/d" localsettings.py || error "Could not delete old ISLAND_NAME setting from localsettngs.py ..." +echo "ISLAND_NAME = \"$ISLAND_NAME\"" >> localsettings.py || error "Could not add ISLAND_NAME to localsettngs.py ..." +echo "Set LDAP CN to generate DN: " +read LDAP_CN +sed -i "/AUTH_LDAP_BIND_DN/d" localsettings.py || error "Could not delete old AUTH_LDAP_BIND_DN setting from localsettngs.py ..." +echo "AUTH_LDAP_BIND_DN = \"uid=$LDAP_CN,ou=admins,dc=fp7-ofelia,dc=eu\"" >> localsettings.py || error "Could not add AUTH_LDAP_BIND_DN to localsettngs.py ..." +echo "Set LDAP Password: " +read LDAP_PASSWORD +sed -i "/AUTH_LDAP_BIND_PASSWORD/d" localsettings.py || error "Could not delete old AUTH_LDAP_BIND_PASSWORD setting from localsettngs.py ..." +echo "AUTH_LDAP_BIND_PASSWORD = \"$LDAP_PASSWORD\"" >> localsettings.py || error "Could not add AUTH_LDAP_BIND_PASSWORD to localsettngs.py ..." +sed -i "/ALLOW_LOCAL_REGISTRATION/d" localsettings.py || error "Could not delete old ALLOW_LOCAL_REGISTRATION setting from localsettngs.py ..." +echo "ALLOW_LOCAL_REGISTRATION = False" >> localsettings.py || error "Could not add ALLOW_LOCAL_REGISTRATION to localsettngs.py ..." +sed -i "/SLICE_DEFAULT_EXPIRATION_TIME/d" localsettings.py || error "Could not delete old nSLICE_DEFAULT_EXPIRATION_TIME setting from localsettngs.py ..." +echo -e "#In days\nSLICE_DEFAULT_EXPIRATION_TIME = 30" >> localsettings.py || error "Could not add SLICE_DEFAULT_EXPIRATION_TIME to localsettngs.py ..." +echo -e "\n\nYou can change the new settings by editing localsettings.py file" + + +for pattern in $EMAIL_PATTERNS +do + sed -i "/$pattern/d" localsettings.py || error "Could not delete EMAIL settings from localsettngs.py ..." +done + + +#Restarting apache +print "Restarting apache2..." +/usr/sbin/service apache2 restart + diff --git a/expedient/bin/versions/0.14.2/upgrade/default/pre-upgrade-hook b/expedient/bin/versions/0.14.2/upgrade/default/pre-upgrade-hook new file mode 100644 index 00000000..4c6ac195 --- /dev/null +++ b/expedient/bin/versions/0.14.2/upgrade/default/pre-upgrade-hook @@ -0,0 +1,54 @@ +#!/bin/bash + +### +# @author:lbergesio +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.14.2 pre-upgrade-hook module..." + +SRC_DIR=/opt/ofelia/expedient/ + +local TMP_PATH=$PWD + +cd $SRC_DIR/src/python/expedient/clearinghouse/ || error "Target directory does not exit anymore?" + +#Adding/Moving new variables to localsettings.py +printHeader ">" "Adding new settings to localsettings.py ..." +sed -i "/ENABLE_LDAP_BACKEND/d" localsettings.py || error "Could not delete old ENABLE_LDAP_BACKEND setting from localsettngs.py ..." +echo "ENABLE_LDAP_BACKEND = True" >> localsettings.py || error "Could not add ENABLE_LDAP_BACKEND to localsettngs.py ..." + +#Restarting apache +print "Restarting apache2..." +/usr/sbin/service apache2 restart + +#Check for OFELIA installation +OFELIA="none" + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an OFELIA istallation? (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not valid option. Please say yes/no" + fi + done + + +#Add ldap domain to /etc/hosts file +if [ $OFELIA==1 ];then + printHeader ">" "Setting ldap domain in /etc/hosts..." + line=`cat /etc/hosts | grep "ldap.ibbt.fp7-ofelia.eu"` + if [ "$line" == "" ];then + sed -i '1i\10.216.4.2 ldap.ibbt.fp7-ofelia.eu' /etc/hosts + fi +fi + +cd $TMP_PATH diff --git a/expedient/bin/versions/0.2/upgrade/default/post-upgrade-hook b/expedient/bin/versions/0.2/upgrade/default/post-upgrade-hook new file mode 100644 index 00000000..5599461c --- /dev/null +++ b/expedient/bin/versions/0.2/upgrade/default/post-upgrade-hook @@ -0,0 +1,22 @@ +#!/bin/bash + +### +# @author:lbergesio +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: post-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.2 post-upgrade-hook module..." + +SRC_DIR=/opt/ofelia/expedient/ + +local TMP_PATH=$PWD + +python $TMP_PATH/versions/0.2/upgrade/default/tools/permissionsRefactor.py || warning "Could not update Expedient's permissions. You may be to do it manually. Proceeding with upgrade..." + +cd $TMP_PATH + + + diff --git a/expedient/bin/versions/0.2/upgrade/default/tools/permissionsRefactor.py b/expedient/bin/versions/0.2/upgrade/default/tools/permissionsRefactor.py new file mode 100644 index 00000000..a465fa55 --- /dev/null +++ b/expedient/bin/versions/0.2/upgrade/default/tools/permissionsRefactor.py @@ -0,0 +1,68 @@ +import os +import sys +from os.path import dirname, join +from django.conf import * + +#configobj +try: + from configobj import ConfigObj +except: + #FIXME: ugly + os.system("apt-get update && apt-get install python-configobj -y") + from configobj import ConfigObj + + +PYTHON_DIR = join(dirname(__file__), '../../../../../../src/python') + +# This is needed because wsgi disallows using stdout +sys.stdout = sys.stderr + +os.environ['DJANGO_SETTINGS_MODULE'] = 'expedient.clearinghouse.settings' +#os.environ['DJANGO_SETTINGS_MODULE'] = sys.argv[2] + +sys.path.insert(0,PYTHON_DIR) + +from expedient.common.permissions.shortcuts import * +from expedient.clearinghouse.aggregate.models import * +from django.contrib.auth.models import User +from expedient.clearinghouse.roles.models import * + + +##Delete can_delete_slices in the existing researcher roles +for rRole in ProjectRole.objects.filter(name="researcher"): + for permission in rRole.obj_permissions.all(): + if permission.permission.name == "can_delete_slices": + rRole.remove_permission(permission) + #This line deletes the permission from the database + #permission.permission.delete() + #print "I will remove permission %s from role %s in project %s" %(str(permission),str(rRole),str(rRole.project)) + +#Delete can_delete_slices permission over the project if the user is not a project owner +for project in Project.objects.all(): + for member in project.members.exclude(is_superuser=True): + if member not in project.owners and not has_permission(member, project, "can_delete_slices"): + #print "I will remove permission can_delete_slice for member %s in project %s because userIsProjectOwner=%s" %(member.username, project.name, "true" if unicode(member) in project.owners else "false") + delete_permission("can_delete_slices", project, member) +#give permission can_delete_slices over the slice to the slice owner + for slice in project._getSlices(): + if member == slice.owner and has_permission(member, slice, "can_delete_slices"): + #print "I will give permission can_delete_slices to %s over slice %s" %(member.username, slice.name) + give_permission_to("can_delete_slices", slice, member, giver=None, can_delegate=False) + +##Remove can_use_aggregate if user is not member of any other project using the aggregates of this project or give it to the user if it is member and does not have it +for agg in Aggregate.objects.all(): + agg = agg.as_leaf_class() + for user in User.objects.exclude(is_superuser=True): + userUsesAgg = False + for project in Project.objects.all(): + if user in project.members and unicode(agg.name) in project._get_aggregates().values_list("name",flat=True): + userUsesAgg = True + if has_permission(user, agg, "can_use_aggregate"): + #print "I will give can_use_aggregate permission to %s for agg %s" % (user.username, agg.name) + give_permission_to("can_use_aggregate", agg, user, giver=None, can_delegate=False) + #else: + # print user.username+" uses the Agg but he already has permission" + break; + if not userUsesAgg and not has_permission(user, agg, "can_use_aggregate"): + #print "I will remove can_use_aggregate permission to %s for agg %s" % (user.username, agg.name) + agg.remove_from_user(user,"/") diff --git a/expedient/bin/versions/0.21.1 b/expedient/bin/versions/0.21.1 new file mode 120000 index 00000000..9ad28c9c --- /dev/null +++ b/expedient/bin/versions/0.21.1 @@ -0,0 +1 @@ +./0.21/ \ No newline at end of file diff --git a/expedient/bin/versions/0.21/upgrade/0.14.2 b/expedient/bin/versions/0.21/upgrade/0.14.2 new file mode 120000 index 00000000..12ad63a6 --- /dev/null +++ b/expedient/bin/versions/0.21/upgrade/0.14.2 @@ -0,0 +1 @@ +../../0.2/upgrade/default/ \ No newline at end of file diff --git a/expedient/bin/versions/0.2RC1 b/expedient/bin/versions/0.2RC1 new file mode 120000 index 00000000..dfc6ce45 --- /dev/null +++ b/expedient/bin/versions/0.2RC1 @@ -0,0 +1 @@ +0.2/ \ No newline at end of file diff --git a/expedient/bin/versions/0.3/upgrade/default/post-upgrade-hook b/expedient/bin/versions/0.3/upgrade/default/post-upgrade-hook new file mode 100644 index 00000000..db435eb3 --- /dev/null +++ b/expedient/bin/versions/0.3/upgrade/default/post-upgrade-hook @@ -0,0 +1,38 @@ +#!/bin/bash + +### +# @author:lbergesio +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: post-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.3/0.3RC1 post-upgrade-hook module..." + +SRC_DIR=/opt/ofelia/expedient/ + +local TMP_PATH=$PWD + +cd $SRC_DIR/src/python/expedient/clearinghouse/ + +#Adding/Moving new variables to localsettings.py +printHeader ">" "Adding new settings to localsettings.py ..." +sed -i "/THEME/d" localsettings.py || error "Could not delete old THEME setting from localsettngs.py ..." +echo "THEME = \"default\"" >> localsettings.py && echo "Check localsettings-example file for more info about how to configure a custom theme for OCF" || error "Could not add THEME to localsettngs.py ..." + +cd $TMP_PATH + + +#Starting apache +print "Starting apache2..." +/usr/sbin/service apache2 start + +#Cleaning the house +confirm "Delete backup files?" $DONT_ABORT + +if [ $? == 0 ]; then + print "Deleting backups..." + rm -rf $BACKUP_PATH +fi + diff --git a/expedient/bin/versions/0.3/upgrade/default/pre-upgrade-hook b/expedient/bin/versions/0.3/upgrade/default/pre-upgrade-hook new file mode 100644 index 00000000..ef66382e --- /dev/null +++ b/expedient/bin/versions/0.3/upgrade/default/pre-upgrade-hook @@ -0,0 +1,151 @@ +#!/bin/bash + +### +# @author:lbergesio +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.3/0.3RC1 pre-upgrade-hook module..." + +OFELIA_DIR=/opt/ofelia + +local TMP_PATH=$PWD + +cd $OFELIA_DIR || error "Target directory does not exist anymore?" + +#Check for OFELIA installation +OFELIA="none" +NO_OFELIA_SCRIPT="ocfToGithubMigration" +SCRIPT="none" + +#shutdown apache +print "Shutting down apache2..." +/usr/sbin/service apache2 stop + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an official OFELIA island installation (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not a valid option. Please answer yes/no" + fi + done + +if [ -d $OFELIA_DIR/oxa/ ]; then + local GIT_DIR="$OFELIA_DIR/oxa/repository/" +else + local GIT_DIR="$OFELIA_DIR" +fi + +NEW_REPO=`cat $GIT_DIR/.git/config | grep "/home/ofelia/ofelia-git" | grep -v "#"` +GITHUB=`cat $GIT_DIR/.git/config | grep "github.com/fp7-ofelia/ocf.git" | grep -v "#"` + +if [ "$NEW_REPO" == "" ];then + NEW_REPO=1 +else + NEW_REPO=0 +fi +if [ "$GITHUB" == "" ];then + GITHUB=0 +else + GITHUB=1 +fi + +if [[ $OFELIA == 1 ]] && [[ $NEW_REPO == 0 ]]; then + + #Move original files to temp folder + TMP_DIR=/opt/tmp/ofeliatmp$EXECPID + if [ ! -d /opt/tmp ]; then + mkdir -p /opt/tmp + fi + + if [ -d $OFELIA_DIR/oxa/ ]; then + CF_AGENT_INSTALL=1 + TARGET_DIR="oxa/repository/" + mv $OFELIA_DIR/$TARGET_DIR $TMP_DIR || error "Maybe some directory is not present?" + else + CF_AGENT_INSTALL=0 + TARGET_DIR="." + mv $OFELIA_DIR $TMP_DIR || error "Maybe some directory is not present?" + mkdir -p $OFELIA_DIR + fi + + cd $OFELIA_DIR + + #Ask for OFELIA credentials + echo "Please enter your OFELIA username. Credentials are the same ones used in Ofelia's TRAC, WIKI and SVN (email). Usernames and passwords will NOT be stored." + + RERUN="none" + while [ $RERUN != 0 ] + do + RERUN=0 + echo -n "Username:" + read USERNAME + #Clone new repo in old location + git clone ssh://$USERNAME@alpha.fp7-ofelia.eu/home/ofelia/ofelia $TARGET_DIR || RERUN=1 + if [ RERUN == 1 ]; then + echo "Insert your username again, please" + fi + done + + #Restore non tracked files from tmp backup + if [ $CF_AGENT_INSTALL == 0 ]; then + cp -Rp $TMP_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509-user.crt/ $OFELIA_DIR/expedient/src/python/expedient/clearinghouse || error "Could not copy gcf-x509-user.crt folder" + cp -Rp $TMP_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509-trusted.crt/ $OFELIA_DIR/expedient/src/python/expedient/clearinghouse || error "Could not copy gcf-x509-trusted.crt folder" + cp -Rp $TMP_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509.key/ $OFELIA_DIR/expedient/src/python/expedient/clearinghouse || error "Could not copy gcf-x509.key folder" + cp -Rp $TMP_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509.cred/ $OFELIA_DIR/expedient/src/python/expedient/clearinghouse || error "Could not copy gcf-x509.cred folder" + cp -Rp $TMP_DIR/expedient/src/python/expedient/clearinghouse/xmlrpc-ssl.crt/ $OFELIA_DIR/expedient/src/python/expedient/clearinghouse || error "Could not copy xmlrpc-ssl.crt folder" + cp -p $TMP_DIR/expedient/src/python/expedient/clearinghouse/localsettings.py $OFELIA_DIR/expedient/src/python/expedient/clearinghouse/ || error "Could not copy expedient's localsettings.py" + cp -p $TMP_DIR/expedient/.currentVersion $OFELIA_DIR/expedient/.currentVersion || error "Could not copy expedient's .currentVersion file" + cp -p $TMP_DIR/vt_manager/src/python/vt_manager/mySettings.py $OFELIA_DIR/vt_manager/src/python/vt_manager/ || error "Could not copy vt_manager's mySettings.py" + cp -p $TMP_DIR/vt_manager/.currentVersion $OFELIA_DIR/vt_manager/.currentVersion || error "Could not copy vt_manager's .currentVersion file" + cp -p $TMP_DIR/optin_manager/src/python/openflow/optin_manager/localsettings.py $OFELIA_DIR/optin_manager/src/python/openflow/optin_manager/ || error "Could not copy optin manager's localsettings.py" + cp -p $TMP_DIR/optin_manager/.currentVersion $OFELIA_DIR/optin_manager/.currentVersion || error "Could not copy optin's .currentVersion file" + elif [ $CF_AGENT_INSTALL == 1 ]; then + cp -p $TMP_DIR/vt_manager/src/python/agent/mySettings.py $OFELIA_DIR/$TARGET_DIR/vt_manager/src/python/agent/mySettings.py || error "Could not copy agent's mySettings.py" + cp -p $TMP_DIR/vt_manager/src/python/agent/.currentVersion $OFELIA_DIR/$TARGET_DIR/vt_manager/src/python/agent/.currentVersion || error "Could not copy agent's .currentVersion file" + cp -p $TMP_DIR/vt_manager/src/python/agent/security/certs/agent.* $OFELIA_DIR/$TARGET_DIR/vt_manager/src/python/agent/security/certs/ || error "Could not copy agent's certificates" + fi + + #Remove temp folder? + #rm -rf $TMP_DIR + + #restart ofver from appropiate directory + cd $TMP_PATH + print "Repo migration done, restarting ofver..." + unlock + restartOfverInstance + + warning "Old repository backup files are stored at $TMP_PATH. Consider deleting them after checking everything is working..." + exit 0 +elif [[ $OFELIA == 0 ]] && [[ $GITHUB == 0 ]]; then + warning "An error occurred. You are probably upgrading from the repository previously hosted at codebasin and you have not executed the $NO_OFELIA_SCRIPT script first. Please do it and restart ofver..." + unlock + cd $TMP_PATH + exit 1 +fi + +# Installing pyPElib +printHeader "info#" "Downloading pypelib libraries..." + +print "Downloading dependencies [pyparsing]..." +/usr/bin/apt-get -y install python-pyparsing || error "Could not install dependencies (apt-get)" + +print "Downloading latest pypelib version..." +/usr/bin/wget --no-check-certificate https://github.com/fp7-ofelia/pypelib/raw/deb/pypelib_latest_all.deb || error "Could not download pypelib latest version from https://github.com/fp7-ofelia/pypelib/raw/deb/pypelib_latest_all.deb. Do you have connectivity?" + +print "Installing pypelib_latest_all.deb..." +/usr/bin/dpkg -i pypelib_latest_all.deb || error "Could not install pypelib latest version using /usr/bin/dpkg -i pypelib_latest_all.deb" + +print "Removing temporary files..." +rm pypelib_latest_all.deb || warning "Could not remove pypelib_latest_all.deb" + +#cd $SRC_DIR/src/python/expedient/clearinghouse/ || error "Target directory does not exit anymore?" +cd $TMP_PATH diff --git a/expedient/bin/versions/0.3RC1 b/expedient/bin/versions/0.3RC1 new file mode 120000 index 00000000..1d71ef97 --- /dev/null +++ b/expedient/bin/versions/0.3RC1 @@ -0,0 +1 @@ +0.3 \ No newline at end of file diff --git a/expedient/bin/versions/0.4.1 b/expedient/bin/versions/0.4.1 new file mode 120000 index 00000000..52bc0ff7 --- /dev/null +++ b/expedient/bin/versions/0.4.1 @@ -0,0 +1 @@ +0.4/ \ No newline at end of file diff --git a/expedient/bin/versions/0.4.2 b/expedient/bin/versions/0.4.2 new file mode 120000 index 00000000..52bc0ff7 --- /dev/null +++ b/expedient/bin/versions/0.4.2 @@ -0,0 +1 @@ +0.4/ \ No newline at end of file diff --git a/expedient/bin/versions/0.4.3 b/expedient/bin/versions/0.4.3 new file mode 120000 index 00000000..52bc0ff7 --- /dev/null +++ b/expedient/bin/versions/0.4.3 @@ -0,0 +1 @@ +0.4/ \ No newline at end of file diff --git a/expedient/bin/versions/0.4/upgrade/default/pre-upgrade-hook b/expedient/bin/versions/0.4/upgrade/default/pre-upgrade-hook new file mode 100644 index 00000000..ad8d3d9c --- /dev/null +++ b/expedient/bin/versions/0.4/upgrade/default/pre-upgrade-hook @@ -0,0 +1,62 @@ +#!/bin/bash + +### +# @author:lbergesio, CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.4 pre-upgrade-hook module..." + +OFELIA_DIR=/opt/ofelia +#Check for OFELIA installation +OFELIA="none" + +local TMP_PATH=$PWD + +print "Shutting down apache2..." +/usr/sbin/service apache2 stop + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an official OFELIA island installation (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not a valid option. Please answer yes/no" + fi + done + +#Update User certs directory permissions +chmod 777 $OFELIA_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509-user.crt/ || error "Could not change permissions of gcf-x509-user.crt folder" +chown www-data $OFELIA_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509-user.crt/ || error "Could not change ownership of gcf-x509-user.crt folder" + +chmod 777 $OFELIA_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509-trusted.crt/ || error "Could not change permissions of gcf-x509-trusted.crt folder" +chown www-data $OFELIA_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509-trusted.crt/ || error "Could not change ownership of gcf-x509-trusted.crt folder" + +chmod 777 $OFELIA_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509.key/ || error "Could not change permissions of gcf-x509.key folder" +chown www-data $OFELIA_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509.key/ || error "Could not change ownership of gcf-x509.key folder" + +chmod 777 $OFELIA_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509.cred/ || error "Could not change permissions of gcf-x509.cred folder" +chown www-data $OFELIA_DIR/expedient/src/python/expedient/clearinghouse/gcf-x509.cred/ || error "Could not change ownership of gcf-x509.cred folder" + + +#Upgrading django_auth_ldap +easy_install django_auth_ldap==1.0.19 + +## PyPElib installation ... +print "Downloading latest pypelib version..." +/usr/bin/wget --no-check-certificate https://github.com/fp7-ofelia/pypelib/raw/deb/pypelib_latest_all.deb || error "Could not download pypelib latest version from https://github.com/fp7-ofelia/pypelib/raw/deb/pypelib_latest_all.deb. Do you have connectivity?" + +print "Installing pypelib_latest_all.deb..." +/usr/bin/dpkg -i pypelib_latest_all.deb || error "Could not install pypelib latest version using /usr/bin/dpkg -i pypelib_latest_all.deb" + +print "Removing temporary files..." +rm pypelib_latest_all.deb || warning "Could not remove pypelib_latest_all.deb" + +cd $TMP_PATH diff --git a/expedient/bin/versions/0.5/upgrade/default/pre-upgrade-hook b/expedient/bin/versions/0.5/upgrade/default/pre-upgrade-hook new file mode 100644 index 00000000..1d4f74c1 --- /dev/null +++ b/expedient/bin/versions/0.5/upgrade/default/pre-upgrade-hook @@ -0,0 +1,96 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.5 pre-upgrade-hook module..." + +#Check for OFELIA installation +OFELIA="none" +GITHUB_READY=1 +# Move original plugin folders inside temp folder +if [ ! -d /opt/tmp/ ]; then + mkdir -p /opt/tmp/ +fi +TMP_DIR=/opt/tmp/ofeliatmp$EXECPID +TMP_PATH=$PWD +# Determine OFELIA directory to perform migration for data in repository +OFELIA_DIR="/opt/ofelia" + +# SSH keys by default +git_remote_url="git@github.com:fp7-ofelia/ocf.git" +git_authentication_method="y" +git_username="" + +# Backup current OCF data +print "Shutting down apache2..." +/usr/sbin/service apache2 stop + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an official OFELIA island installation (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not a valid option. Please answer yes/no" + fi + done + + +if [[ `git config --get-regexp origin "fp7-ofelia/ocf.git"` == "" ]]; then + GITHUB_READY=0 +fi + +if [[ $GITHUB_READY == 0 ]]; then + print "Generating current repository backup.." + mv $OFELIA_DIR $TMP_DIR || error "Could not backup OCF data from '$SRC_DIR' to '$TMP_DIR'" + + # Clone new Github repository (authentication depends on $OFELIA={0,1}) + if [[ $OFELIA == "1" ]]; then + while true; do + read -p "> How do you prefer to authenticate against the repository? SSH keys (y) or via HTTPS (n): " git_authentication_method + case $git_authentication_method in + [Yy]* ) break;; + [Nn]* ) read -p "> You may set your GitHub username now, if you wish: " git_username; + if [[ $git_username != "" ]]; then + git_username=$git_username"@"; + fi + git_remote_url="https://${git_username}github.com/fp7-ofelia/ocf.git"; break;; + * ) echo "Please answer 'y' or 'n' to use SSH keys or HTTP respectively.";; + esac + done + # Read/write access (SSH keys or HTTPS, depends on user's choice) + git clone $git_remote_url $OFELIA_DIR || error "Could not retrieve data from GitHub repository" + else + # Read access + git clone git://github.com/fp7-ofelia/ocf.git $OFELIA_DIR || error "Could not retrieve data from GitHub repository" + fi + + cd $OFELIA_DIR + git checkout ofelia.stable || error "Could not switch to stable branch" + # Synchronizes repositories: old data from private repository with new data from GitHub repository + rsync -aPp --exclude=.git $TMP_DIR/* ./ +fi + +# Removes old plugin folders before restarting Apache +print "Removing old plugin folders..." + +# Moving basic plugins from old directory to new location to avoid loading their *.pyc files +if [ -d $OFELIA_DIR/expedient/src/python/vt_plugin ]; then + rm -r $OFELIA_DIR/expedient/src/python/vt_plugin || error "Could not remove old plugin 'vt_plugin'" +fi + +if [ -d $OFELIA_DIR/expedient/src/python/openflow ]; then + rm -r $OFELIA_DIR/expedient/src/python/openflow || error "Could not remove old plugin 'openflow'" +fi + +cd $TMP_PATH + diff --git a/expedient/bin/versions/0.6.1/upgrade/0.5/post-upgrade-hook b/expedient/bin/versions/0.6.1/upgrade/0.5/post-upgrade-hook new file mode 100644 index 00000000..a92c6f8c --- /dev/null +++ b/expedient/bin/versions/0.6.1/upgrade/0.5/post-upgrade-hook @@ -0,0 +1,55 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: post-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.6.1 pre-upgrade-hook module..." + +#Starting apache +print "Starting apache2..." +/usr/sbin/service apache2 start + +#function standardize_flowvisor_slices() +#{ +# print "Invoking script to start (previously conflictive, now renamed) slices in FlowVisor. This may take some time..." +# # Call to Expedient's python script where the slice starting is invoked +# python ../src/python/expedient/clearinghouse/manage.py standardize_flowvisor_slices start +# print "Granting flowspaces for renamed slices in FlowVisor. This may take take some time..." +# # Call to Opt-in's python script where the flowspace granting is invoked +# python ../../optin_manager/src/python/openflow/optin_manager/manage.py standardize_flowvisor_slices +#} +# +##After bringing apache back... +##Fixing flowvisor slices naming where corrupted by versions 0.5 or 0.6 +#while true; do +# echo "" +# print "It is HIGHLY important to perform a procedure that will fix the FlowVisor name for those slices and flowspaces requested between versions 0.5 and 0.6. You may perform a copy of your FlowVisor configuration file (e.g. /usr/local/etc/flowvisor/config.xml) to store the original naming for these, in case something went wrong later." +# print " STEP #2: starting slices." +# read -p "Press 'y' when you are ready (y/n): " FIX_FLOWVISOR +# echo "" +# case $FIX_FLOWVISOR in +# [Yy]* ) standardize_flowvisor_slices; break;; +# [Nn]* ) warning "FlowVisor slices won't be restarted to meet the expected names. This might cause some problems in the future, however."; +# while [[ ! $FIX_FLOWVISOR_RE =~ y|Y|n|N ]]; do +# read -p "Last check: do you want to run (y) or not (n) this process?: " FIX_FLOWVISOR_RE +# case $FIX_FLOWVISOR_RE in +# [Yy]* ) standardize_flowvisor_slices; exit;; +# [Nn]* ) exit;; +# esac +# done;; +# * ) print "Please choose y/n";; +# esac +#done + +#Cleaning the house +confirm "Delete backup files?" $DONT_ABORT + +if [ $? == 0 ]; then + print "Deleting backups..." + rm -rf $BACKUP_PATH +fi diff --git a/expedient/bin/versions/0.6.1/upgrade/0.5/pre-upgrade-hook b/expedient/bin/versions/0.6.1/upgrade/0.5/pre-upgrade-hook new file mode 100644 index 00000000..a09ebf0a --- /dev/null +++ b/expedient/bin/versions/0.6.1/upgrade/0.5/pre-upgrade-hook @@ -0,0 +1,61 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.6.1 pre-upgrade-hook module..." + +#function standardize_flowvisor_slices() +#{ +# print "Invoking script to stop conflictive slices in FlowVisor. This may take some time..."; +# # Call to Expedient's python script where the slice stopping is invoked +# python ../src/python/expedient/clearinghouse/manage.py standardize_flowvisor_slices stop +#} +# +##Before shutting down apache... +##Fixing flowvisor slices naming where corrupted by versions 0.5 or 0.6 +#while true; do +# echo "" +# print "It is HIGHLY important to perform a procedure that will fix the FlowVisor name for those slices and flowspaces requested between versions 0.5 and 0.6. You may perform a copy of your FlowVisor configuration file (e.g. /usr/local/etc/flowvisor/config.xml) to store the original naming for these, in case something went wrong later." +# print " STEP #1: stopping slices." +# read -p "Press 'y' when you are ready (y/n): " FIX_FLOWVISOR +# echo "" +# case $FIX_FLOWVISOR in +# [Yy]* ) standardize_flowvisor_slices; break;; +# [Nn]* ) warning "FlowVisor slices won't be restarted to meet the expected names. This might cause some problems in the future, however."; +# while [[ ! $FIX_FLOWVISOR_RE =~ y|Y|n|N ]]; do +# read -p "Last check: do you want to run (y) or not (n) this process?: " FIX_FLOWVISOR_RE +# case $FIX_FLOWVISOR_RE in +# [Yy]* ) standardize_flowvisor_slices; exit;; +# [Nn]* ) exit;; +# esac +# done;; +# * ) print "Please choose y/n";; +# esac +#done + +#shutdown apache +print "Shutting down apache2..." +/usr/sbin/service apache2 stop + +#Check for OFELIA installation +OFELIA="none" + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an OFELIA istallation? (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not valid option. Please say yes/no" + fi + done + diff --git a/expedient/bin/versions/0.6.1/upgrade/0.6 b/expedient/bin/versions/0.6.1/upgrade/0.6 new file mode 120000 index 00000000..ea2303bc --- /dev/null +++ b/expedient/bin/versions/0.6.1/upgrade/0.6 @@ -0,0 +1 @@ +0.5 \ No newline at end of file diff --git a/expedient/bin/versions/0.6/upgrade/default/pre-upgrade-hook b/expedient/bin/versions/0.6/upgrade/default/pre-upgrade-hook new file mode 100644 index 00000000..e5b2a967 --- /dev/null +++ b/expedient/bin/versions/0.6/upgrade/default/pre-upgrade-hook @@ -0,0 +1,38 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.6 pre-upgrade-hook module..." + +# Create certificate folder for SFA GIDs +mkdir -p /etc/apache2/ssl.crt/ca_clients + +#shutdown apache +print "Shutting down apache2..." +/usr/sbin/service apache2 stop + +#Check for OFELIA installation +OFELIA="none" + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an OFELIA istallation? (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not valid option. Please say yes/no" + fi + done + +print "Downloading dependencies [python-lxml]..." +/usr/bin/apt-get -y install python-lxml || error "Could not install dependencies (apt-get)" + diff --git a/expedient/bin/versions/0.7/upgrade/default/pre-upgrade-hook b/expedient/bin/versions/0.7/upgrade/default/pre-upgrade-hook new file mode 100644 index 00000000..a295a855 --- /dev/null +++ b/expedient/bin/versions/0.7/upgrade/default/pre-upgrade-hook @@ -0,0 +1,36 @@ +#!/bin/bash + +### +# @author: OMoya +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.7 pre-upgrade-hook module..." + +#Changing permissions for Apache2 logs +chmod 755 /var/log/apache2 + +#shutdown apache +print "Shutting down apache2..." +/usr/sbin/service apache2 stop + +#Check for OFELIA installation +OFELIA="none" + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an OFELIA istallation? (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not valid option. Please say yes/no" + fi + done + + diff --git a/expedient/bin/versions/0.8.1 b/expedient/bin/versions/0.8.1 new file mode 120000 index 00000000..ce609caf --- /dev/null +++ b/expedient/bin/versions/0.8.1 @@ -0,0 +1 @@ +0.8 \ No newline at end of file diff --git a/expedient/bin/versions/0.8.2 b/expedient/bin/versions/0.8.2 new file mode 120000 index 00000000..ce609caf --- /dev/null +++ b/expedient/bin/versions/0.8.2 @@ -0,0 +1 @@ +0.8 \ No newline at end of file diff --git a/expedient/bin/versions/0.8.3/upgrade/default/lib/set_environment_variables b/expedient/bin/versions/0.8.3/upgrade/default/lib/set_environment_variables new file mode 120000 index 00000000..e01561ab --- /dev/null +++ b/expedient/bin/versions/0.8.3/upgrade/default/lib/set_environment_variables @@ -0,0 +1 @@ +../../../../default/install/lib/set_environment_variables \ No newline at end of file diff --git a/expedient/bin/versions/0.8.3/upgrade/default/pre-upgrade-hook b/expedient/bin/versions/0.8.3/upgrade/default/pre-upgrade-hook new file mode 100644 index 00000000..0500bef4 --- /dev/null +++ b/expedient/bin/versions/0.8.3/upgrade/default/pre-upgrade-hook @@ -0,0 +1,102 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.8.3 pre-upgrade-hook module..." + +# Changing permissions for Apache2 logs +for log_file in $(find /var/log/apache2 -name "*error_log") +do + chmod 755 $log_file + chown www-data $log_file +done + +# ---------------------------------------- +# Removing .pyc files from antique folders +# ---------------------------------------- +# Root for "expedient" folder +expedient_dir=$EXECPATH/.. + +print "Removing old folders..." +# Remove folders that are not tracked anymore (thus, no .py files) +# > Before that, check that no ".py" file is indeed located there +geni_dir=$expedient_dir/src/python/geni +if [ -d $geni_dir ]; then + if [ $(find $geni_dir -name "*.py" | wc -l) == 0 ]; then + rm -r $geni_dir + fi +fi +expedient_geni_dir=$expedient_dir/src/python/expedient_geni +if [ -d $expedient_geni_dir ]; then + if [ $(find $expedient_geni_dir -name "*.py" | wc -l) == 0 ]; then + rm -r $expedient_geni_dir + fi +fi +sfa_dir=$expedient_dir/src/python/sfa +if [ -d $sfa_dir ]; then + if [ $(find $sfa_dir -name "*.py" | wc -l) == 0 ]; then + rm -r $sfa_dir + fi +fi +# ---------------------------------------- + +# ---------------------------------------- +# Removing old (conflicting) Django apps +# ---------------------------------------- +# Root for "manage.py" file +expedient_manage_dir=$expedient_dir/src/python/expedient/clearinghouse +current_dir=$PWD +cd $expedient_manage_dir + +print "Removing old Django apps..." +## Initial backup +#manage_clear_app=$(python manage.py dumpdata gopenflow) +## Retrieve data within braces +#manage_clear_app=$(expr "$manage_clear_app" : '.*\[\(.*\)].*') +#manage_clear_app="[$manage_clear_app]" +#python manage.py loaddata $manage_clear_app + +# Completely clear those apps (no data on them) +#manage_clear_app=$(python manage.py sqlclear gopenflow) +#manage_clear_app=$(expr "$manage_clear_app" : '.*BEGIN;\([^;]*\);.*'); +#manage_clear_app="BEGIN; $manage_clear_app; COMMIT;" +#echo $manage_clear_app | python manage.py dbshell + +# Completely clear those apps AND Django evolution data +python manage.py sqlclear gopenflow planetlab > apps_clear +python manage.py sqlreset django_evolution >> apps_clear +cat apps_clear | python manage.py dbshell +rm apps_clear + +cd $current_dir + + +#shutdown apache +print "Shutting down apache2..." +/usr/sbin/service apache2 stop + +#Check for OFELIA installation +OFELIA="none" + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an OFELIA istallation? (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not valid option. Please say yes/no" + fi + done + +# Determine installation path +print "Setting environment variables..." +source $CURRENT_DIRECTORY/lib/set_environment_variables diff --git a/expedient/bin/versions/0.8/upgrade/default/pre-upgrade-hook b/expedient/bin/versions/0.8/upgrade/default/pre-upgrade-hook new file mode 100644 index 00000000..64f371bf --- /dev/null +++ b/expedient/bin/versions/0.8/upgrade/default/pre-upgrade-hook @@ -0,0 +1,98 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-upgrade-hook module +### + +#inform user +printHeader "info#" "Using specific 0.8.2 pre-upgrade-hook module..." + +# Changing permissions for Apache2 logs +for log_file in $(find /var/log/apache2 -name "*error_log") +do + chmod 755 $log_file + chown www-data $log_file +done + +# ---------------------------------------- +# Removing .pyc files from antique folders +# ---------------------------------------- +# Root for "expedient" folder +expedient_dir=$EXECPATH/.. + +print "Removing old folders..." +# Remove folders that are not tracker anymore (thus, no .py files) +# > Before that, check that no ".py" file is indeed located there +geni_dir=$expedient_dir/src/python/geni +if [ -d $geni_dir ]; then + if [ $(find $geni_dir -name "*.py" | wc -l) == 0 ]; then + rm -r $geni_dir + fi +fi +expedient_geni_dir=$expedient_dir/src/python/expedient_geni +if [ -d $expedient_geni_dir ]; then + if [ $(find $expedient_geni_dir -name "*.py" | wc -l) == 0 ]; then + rm -r $expedient_geni_dir + fi +fi +sfa_dir=$expedient_dir/src/python/sfa +if [ -d $sfa_dir ]; then + if [ $(find $sfa_dir -name "*.py" | wc -l) == 0 ]; then + rm -r $sfa_dir + fi +fi +# ---------------------------------------- + +# ---------------------------------------- +# Removing old (conflicting) Django apps +# ---------------------------------------- +# Root for "manage.py" file +expedient_manage_dir=$expedient_dir/src/python/expedient/clearinghouse +current_dir=$PWD +cd $expedient_manage_dir + +print "Removing old Django apps..." +## Initial backup +#manage_clear_app=$(python manage.py dumpdata gopenflow) +## Retrieve data within braces +#manage_clear_app=$(expr "$manage_clear_app" : '.*\[\(.*\)].*') +#manage_clear_app="[$manage_clear_app]" +#python manage.py loaddata $manage_clear_app + +# Completely clear those apps (no data on them) +manage_clear_app=$(python manage.py sqlclear gopenflow) +manage_clear_app=$(expr "$manage_clear_app" : '.*BEGIN;\([^;]*\);.*'); +manage_clear_app="BEGIN; $manage_clear_app; COMMIT;" +echo $manage_clear_app | python manage.py dbshell + +manage_clear_app=$(python manage.py sqlclear planetlab) +manage_clear_app=$(expr "$manage_clear_app" : '.*BEGIN;\([^;]*\);.*'); +manage_clear_app="BEGIN; $manage_clear_app; COMMIT;" +echo $manage_clear_app | python manage.py dbshell + +cd $current_dir +# ---------------------------------------- + +#shutdown apache +print "Shutting down apache2..." +/usr/sbin/service apache2 stop + +#Check for OFELIA installation +OFELIA="none" + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an OFELIA istallation? (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not valid option. Please say yes/no" + fi + done + diff --git a/expedient/bin/versions/default/install/backup b/expedient/bin/versions/default/install/backup new file mode 100644 index 00000000..d6ae812e --- /dev/null +++ b/expedient/bin/versions/default/install/backup @@ -0,0 +1,13 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: backup module +### + +#Inform user +printHeader "info#" "Using default backup module..." + +print "Nothing to do..." diff --git a/expedient/bin/versions/default/install/install b/expedient/bin/versions/default/install/install new file mode 100644 index 00000000..3ae34435 --- /dev/null +++ b/expedient/bin/versions/default/install/install @@ -0,0 +1,84 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: install module +### + +#Constants +SRC_DIR=${OCF_PATH:-$(echo $(dirname $(dirname $PWD)))} +SRC_DIR=$SRC_DIR/expedient/ +APACHE_USER="www-data" + +#Inform user +printHeader "info#" "Using default install module..." + +##Main routing + +#Install dependencies +printHeader ">" "Installing dependencies through apt-get..." + +source $CURRENT_DIRECTORY/lib/dependencies || error "Cannot import dependencies file" $NO_RESCUE +/usr/bin/apt-get update || error "Could not update repositories (apt-get). Do you have connectivity?" $NO_RESCUE +/usr/bin/apt-get -y install $DEBIAN_DEPENDENCIES || error "Could not install dependencies (apt-get)" $NO_RESCUE +source $CURRENT_DIRECTORY/lib/pypelib || error "Cannot import PyPElib installation file" $NO_RESCUE + +#apt-get start apache => stop it +/usr/sbin/service apache2 stop + +printHeader ">" "Installing remaining dependencies through easy_install..." +warning "easy_install may randomly fail on the installation. This is a common error of easy_install; simply try again installation." +/usr/bin/easy_install $EASY_INSTALL_DEPENDENCIES || error "Could not install dependencies (easy_install)" $NO_RESCUE + +printHeader ">" "Enabling macro and ssl module in apache2..." + + +#Enabling Apache mods +/usr/sbin/a2enmod macro || warn "Could not enable macro module" "; maybe already enabled?" +/usr/sbin/a2enmod ssl || warn "Could not enable ssl module" "; maybe already enabled?" + + +#Build ssl certs +source $CURRENT_DIRECTORY/lib/ssl + +#Create symbolic links +printHeader ">" "Creating symbolic links for the vhost files in apache sites-enabled folder..." + +ln -sf $SRC_DIR/src/config/expedient/common/apache/vhost-macros.conf /etc/apache2/conf.d/ || error "Cannot create vhost-macros symbolic link" +ln -sf $SRC_DIR/src/config/expedient/clearinghouse/apache/vhost-clearinghouse.conf /etc/apache2/sites-available/expedient.conf || error "Cannot create symbolic link in /etc/apache2/sites-available/ for the expedient vhost file..." +ln -sf /etc/apache2/sites-available/expedient.conf /etc/apache2/sites-enabled/ || error "Cannot create symbolic link in /etc/apache2/sites-enabled to enable vhost..." + +#Create application folder for error log +mkdir -p /var/log/apache2/expedient/clearinghouse +# Set proper permissions to log files under /var/log/apache +for log_file in $(find /var/log/apache2 -name "*error_log") +do + chmod 755 $log_file + chown www-data $log_file +done +chown www-data:www-data /var/log/apache2 +#If it does not exist, expedient creates it with root user and then it crashes +touch /var/log/sfa_access.log + +#Django settings +source $CURRENT_DIRECTORY/lib/django-settings + +#Django database +source $CURRENT_DIRECTORY/lib/django-db + +#Change permissions of the code +printHeader ">" "Setting correct file permissions..." +chmod -f a+w $SRC_DIR/src/python/expedient/clearinghouse/gcf-x509* +chown -f $APACHE_USER $SRC_DIR/src/ -R +chown -f $APACHE_USER /var/log/sfa_access.log + +#Add ldap domain to /etc/hosts file +if [ $OFELIA==1 ];then + printHeader ">" "Setting ldap domain in /etc/hosts..." + line=`cat /etc/hosts | grep "ldap.ibbt.fp7-ofelia.eu"` + if [ "$line" == "" ];then + sed -i '1i\10.216.4.2 ldap.ibbt.fp7-ofelia.eu' /etc/hosts + fi +fi diff --git a/expedient/bin/versions/default/install/lib/dependencies b/expedient/bin/versions/default/install/lib/dependencies new file mode 100644 index 00000000..b81b8b71 --- /dev/null +++ b/expedient/bin/versions/default/install/lib/dependencies @@ -0,0 +1,9 @@ +#!/bin/bash + +#Used to define package dependencies + +DEBIAN_DEPENDENCIES="apache2 openssl ssl-cert libapache2-mod-wsgi libapache2-mod-macro python-setuptools python-django python-mysqldb python-ldap python-openssl python-m2crypto python-dateutil python-decorator python-paramiko build-essential python-imaging python-django-registration python-configobj python-pyparsing python-lxml" + +# Compatibility with Debian7 (<=), to use Django 1.4.5 +EASY_INSTALL_DEPENDENCIES="django-evolution<=0.6.9 django-autoslug django-extensions<=1.2.5 django_auth_ldap==1.0.19" + diff --git a/expedient/bin/versions/default/install/lib/django-db b/expedient/bin/versions/default/install/lib/django-db new file mode 100644 index 00000000..290de99e --- /dev/null +++ b/expedient/bin/versions/default/install/lib/django-db @@ -0,0 +1,13 @@ +#!/bin/bash + +#Synchronize database +printHeader ">" "Synchronizing database... It will ask for a root user of the component; use STRONG passwords for it!" + +warning "Make sure the database is already created, and that root passwords in settings file has enough rights to populate database before proceeding, or installation will fail..." +pause "" + +local TMP_PATH=$PWD +cd $SRC_DIR/src/python/expedient/clearinghouse/ && python manage.py syncdb || error "Could not synchronize database using manage.py..." +python manage.py setup_expedient || warning "Could not create secret key..." +cd $TMP_PATH + diff --git a/expedient/bin/versions/default/install/lib/django-settings b/expedient/bin/versions/default/install/lib/django-settings new file mode 100644 index 00000000..21ff2901 --- /dev/null +++ b/expedient/bin/versions/default/install/lib/django-settings @@ -0,0 +1,57 @@ +#!/bin/bash + +#Constants +EDITORS="vi vim emacs nano pico" + +#Copy from template +printHeader ">" "Copying django settings file from template..." + +if [ -f $SRC_DIR/src/python/expedient/clearinghouse/localsettings.py ];then + warning "localsettings file already exists." + + if [ "$FORCE" == "1" ]; then + confirm "Overwrite currently installed localsettings.py." $DONT_ABORT + if [ $? == 0 ]; then + cp $SRC_DIR/src/python/expedient/clearinghouse/localsettings-example $SRC_DIR/src/python/expedient/clearinghouse/localsettings.py -f || error "Cannot copy localsettings.py" + fi + else + print "Skipping copy (will not be overwritten)" + fi +else + print "$SRC_DIR""src/python/expedient/clearinghouse/localsettings-example -> $SRC_DIR""src/python/expedient/clearinghouse/localsettings.py " + cp $SRC_DIR/src/python/expedient/clearinghouse/localsettings-example $SRC_DIR/src/python/expedient/clearinghouse/localsettings.py || error "Cannot copy localsettings.py" +fi + +#Choose editor +printHeader ">" "Choosing the editor..." +select editor in $EDITORS; +do + if [ -z $editor ]; then + print "Invalid option $editor" + continue + fi + print "" + EDITOR=$editor + print "You are going to use $EDITOR for file manipulation..." + break; +done + +#Edit file +printHeader ">" "Editing localsettings file..." +while : +do + print "Now you are going to edit the file $SRC_DIR""src/python/expedient/clearinghouse/localsettings.py using $EDITOR. Save the modifications and do NOT exit using Ctrl+C..." + pause "" + eval $EDITOR $SRC_DIR/src/python/expedient/clearinghouse/localsettings.py + print "" + pause "Now the contents of the file will be shown for a final review. You can scroll up/down to verify the settings. Press 'q' to continue..." + less $SRC_DIR/src/python/expedient/clearinghouse/localsettings.py + + confirm "Everything is OK." $DONT_ABORT $NO_RESCUE + + if [ $? == 0 ]; then + break + fi + +done + diff --git a/expedient/bin/versions/default/install/lib/pypelib b/expedient/bin/versions/default/install/lib/pypelib new file mode 100644 index 00000000..a1c1fa57 --- /dev/null +++ b/expedient/bin/versions/default/install/lib/pypelib @@ -0,0 +1,48 @@ +#!/bin/bash + +# Used to install PyPElib library (after `source lib/dependencies`) +if [[ ! $(dpkg -l | grep pypelib) ]]; then + + while true; do + print "" + warning "PyPElib is going to be installed. You shall be prompted for a series of values (app_label, db_table) that will be REPLACED afterwards so as to integrate it within OCF." + print "" + read -p "Do you agree with the PyPElib warning? (Y/N): " pypelib_yn + case $pypelib_yn in + [Yy]* ) break;; + [Nn]* ) error "'Do you agree with the PyPElib warning?' clause not confirmed. Aborting..." $NO_RESCUE; break;; + * ) echo "Please answer 'Y' or 'N'.";; + esac + done + + ## PyPElib installation ... + print "Downloading latest pypelib version..." + /usr/bin/wget --no-check-certificate https://github.com/fp7-ofelia/pypelib/raw/deb/pypelib_latest_all.deb || error "Could not download pypelib latest version from https://github.com/fp7-ofelia/pypelib/raw/deb/pypelib_latest_all.deb. Do you have connectivity?" + + print "Installing pypelib_latest_all.deb..." + /usr/bin/dpkg -i pypelib_latest_all.deb || error "Could not install pypelib latest version using /usr/bin/dpkg -i pypelib_latest_all.deb" + + print "Removing temporary files..." + rm pypelib_latest_all.deb || warning "Could not remove pypelib_latest_all.deb" + + + ## Replacement of PyPElib data (app_label, db_table) to integrate within VT manager + ## XXX: ONLY FOR INSTALLATION + PYPELIB_DJANGO_PATH="/usr/lib/python2.6/pypelib/persistence/backends/django/" + PYPELIB_DJANGO_FILES="RuleTableModel.py RuleModel.py" + + if [ -d $PYPELIB_DJANGO_PATH ]; then + for file in $PYPELIB_DJANGO_FILES; do + if [ -f $PYPELIB_DJANGO_PATH$file ]; then + cp -p "$PYPELIB_DJANGO_PATH$file" "$PYPELIB_DJANGO_PATH$file".bkp + sed -i "s/app_label".*"/app_label = \'vt_manager\'/g" $PYPELIB_DJANGO_PATH$file + if [ $file == "RuleModel.py" ]; then + sed -i "s/db_table".*"/db_table = \'pypelib_RuleModel\'/g" $PYPELIB_DJANGO_PATH$file + elif [ $file == "RuleTableModel.py" ]; then + sed -i "s/db_table".*"/db_table = \'pypelib_RuleTableModel\'/g" $PYPELIB_DJANGO_PATH$file + fi + fi + done + fi + +fi diff --git a/expedient/bin/versions/default/install/lib/set_environment_variables b/expedient/bin/versions/default/install/lib/set_environment_variables new file mode 100755 index 00000000..7a2ff128 --- /dev/null +++ b/expedient/bin/versions/default/install/lib/set_environment_variables @@ -0,0 +1,47 @@ +#!/bin/bash + +### +# @author: CarolinaFernandez +# @organization: i2CAT +# @description: setting environment variables for OCF +### + +# Determine OCF path +# +# Currently retrieves location of downloaded code +# But any other could be asked for to the administrator... + +#replacement="" +#OCF_PATH=$(echo $PWD | sed -e "s/expedient.*/${replacement}/g") +OCF_PATH_LOCAL=$(dirname $(dirname $PWD)) +# Ensure the new path ends with a "/" +last_char=${OCF_PATH_LOCAL#${OCF_PATH_LOCAL%?}} +if [[ $last_char != "/" ]]; then + OCF_PATH_LOCAL=$OCF_PATH_LOCAL/ +fi + +# Set environment variables in Apache's envvars file +APACHE_ENVVARS=/etc/apache2/envvars +if [ -f $APACHE_ENVVARS ]; then + #if [ -z $(grep -q $OCF_PATH $APACHE_ENVVARS) ]; then + if [[ -z $(grep $OCF_PATH_LOCAL $APACHE_ENVVARS) ]]; then + echo -e """\n# OCF path\nexport OCF_PATH=$OCF_PATH_LOCAL" >> $APACHE_ENVVARS + fi +fi + +# Set environment variables under OS's profile.d folder +PROFILE_D=/etc/profile.d +PROFILE_D_OCF=$PROFILE_D/ocf.sh +if [ -d $PROFILE_D ]; then + if [ ! -f $PROFILE_D_OCF ]; then + echo -e """#!/bin/bash\n\nexport OCF_PATH=$OCF_PATH_LOCAL""" >> $PROFILE_D_OCF + fi +fi + +# Read environment variable after any change (e.g. installation, migration) +# NOTE: re-log in should me made anyway after any change for this env vars +# to be globally available +#if [ -z $OCF_PATH ]; then +if [ "$OCF_PATH" != "$OCF_PATH_LOCAL" ]; then + source $PROFILE_D_OCF +fi diff --git a/expedient/bin/versions/default/install/lib/ssl b/expedient/bin/versions/default/install/lib/ssl new file mode 100644 index 00000000..b46bf4bc --- /dev/null +++ b/expedient/bin/versions/default/install/lib/ssl @@ -0,0 +1,90 @@ +#!/bin/bash + +#SSL routines. Installing SSL certificates in apache2 (according to vhost configurations of the apps) + + + +function installSSLCertificates(){ + + local DAYS=3650 + + mkdir /etc/apache2/ssl.crt/ /etc/apache2/ssl.crt/ca_clients/ /etc/apache2/ssl.key/ /etc/apache2/ssl.crl || warning "Could not mkdir ssl directories under /etc/apache2 (maybe already there?). Proceeding with installation..." + touch /etc/apache2/ssl.crt/ca_clients.crt || warning "Could not touch CA clients file under /etc/apache2/ssl.crt. Proceeding with installation..." + + print "" + print "Generating CA certificate..." + print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + warning "You are creating the CA (Certificate Authority) certificate. Do NOT use the same Common Name (CN) for the CA certificate and the Apache (next step certificate, or apache will issue a 'sec_error_bad_signature'. Since CN must be correct in the next step, just use a different CN (even if it is not valid) for the CA's certificate CN" + print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + print "" + + #CA key + openssl genrsa -passout pass:donotcare -des3 -out /etc/apache2/ssl.crt/ca.key 4096 || error "Could not generate CA certificate." + + print "" + print "Generating CA Request certificate..." + warning "You will be promted for several information. Please make sure CommonName (CN) is correct (correct IP or domain name). Do not enter extra information as it seems apache2/openssl is buggy?¿)" + print "" + + #Request + openssl req -passin pass:donotcare -new -x509 -days $DAYS -key /etc/apache2/ssl.crt/ca.key -out /etc/apache2/ssl.crt/ca.crt || error "Could not generate Request certificate." + + print "" + print "Generating private key..." + print "" + + #Key + openssl genrsa -passout pass:donotcare -des3 -out /etc/apache2/ssl.key/server.key 4096 || error "Could not generate Key." + + print "" + print "Generating Request..." + warning "Make sure this time CN is correct!!" + print "" + + #sign request + openssl req -passin pass:donotcare -new -key /etc/apache2/ssl.key/server.key -out /etc/apache2/ssl.key/server.csr || error "Could not sign request." + + print "" + print "Generating CA-signed SSL certificate..." + print "" + + #Generate certificate + openssl x509 -req -passin pass:donotcare -days $DAYS -in /etc/apache2/ssl.key/server.csr -CA /etc/apache2/ssl.crt/ca.crt -CAkey /etc/apache2/ssl.crt/ca.key -set_serial 01 -out /etc/apache2/ssl.key/server.crt -passin pass:donotcare || error "Could not generate certificate." + + print "" + print "Moving keys and cleaning the house..." + print "" + + #Move keys + openssl rsa -passin pass:donotcare -in /etc/apache2/ssl.key/server.key -out /etc/apache2/ssl.key/server.key.insecure || error "Could not regenerate Key." + mv /etc/apache2/ssl.key/server.key /etc/apache2/ssl.key/server.key.secure || error "Could not move keys." + mv /etc/apache2/ssl.key/server.key.insecure /etc/apache2/ssl.key/server.key|| error "Could not move keys." + mv /etc/apache2/ssl.key/server.crt /etc/apache2/ssl.crt/|| error "Could not move server certificate." + + # Prepare ca_clients.crt for first use + cat /etc/apache2/ssl.crt/ca.crt >> /etc/apache2/ssl.crt/ca_clients.crt || warning "Could not touch ca_clients.crt file under /etc/apache2/ssl.crt (maybe already there?). Proceeding with installation..." +} + +#Routine + +printHeader ">" "Building SSL certificates..." +print "" + +if [ ! -f /etc/apache2/ssl.key/server.key ] || [ ! -f /etc/apache2/ssl.crt/server.crt ]; then + installSSLCertificates + +else + if [ "$FORCE" == 0 ]; then + print "" + warning "SSL certificates exist; this is not a problem if they were previously installed correctly. If you experience problems with SSL certificates, consider using force flag (-f) to overwrite current SSL certificates. " + print "" + else + confirm "SSL certificates seems to be installed in apache's folder. Do you want to overwrite them." $DONT_ABORT $NO_RESCUE + + if [ $? == 0 ]; then + installSSLCertificates + fi + + fi + +fi diff --git a/expedient/bin/versions/default/install/post-install-hook b/expedient/bin/versions/default/install/post-install-hook new file mode 100644 index 00000000..15616b58 --- /dev/null +++ b/expedient/bin/versions/default/install/post-install-hook @@ -0,0 +1,20 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: post-install module +### + +#Inform user +printHeader "info#" "Using default post-install-hook module..." + +#Starting apache +print "Starting apache2..." +/usr/sbin/service apache2 restart + +#Cleaning the house + +#Testing +#TODO diff --git a/expedient/bin/versions/default/install/pre-install-hook b/expedient/bin/versions/default/install/pre-install-hook new file mode 100644 index 00000000..085a0910 --- /dev/null +++ b/expedient/bin/versions/default/install/pre-install-hook @@ -0,0 +1,38 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-install module +### + +#inform user +printHeader "info#" "Using default pre-install-hook module..." + +# Create certificate folder for SFA GIDs +mkdir -p /etc/apache2/ssl.crt/ca_clients + +#shutdown apache +print "Shutting down apache2..." +/usr/sbin/service apache2 stop || warning "Could not stop apache" + +#Check if installations is for OFELIA or not +OFELIA="none" + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an OFELIA istallation? (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not valid option. Please say yes/no" + fi + done + +# Determine installation path +print "Setting environment variables..." +source $CURRENT_DIRECTORY/lib/set_environment_variables diff --git a/expedient/bin/versions/default/install/repo b/expedient/bin/versions/default/install/repo new file mode 100644 index 00000000..1c2146b1 --- /dev/null +++ b/expedient/bin/versions/default/install/repo @@ -0,0 +1,16 @@ +#!/bin/bash + +### +# @author:lbergesio +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: repo module for Non OFELIA's Installations using OUT_BRANCH mode +### + + +#if [ $NOT_OFELIA == "yes"];then +# git clone ssh://gitolite@codebasin.net:ocf.git ocf || error "Not possible to download app code from repo" +#else +# error "For OFELIA installations use IN_BRANCH installation" +#fi + diff --git a/expedient/bin/versions/default/install/rollback b/expedient/bin/versions/default/install/rollback new file mode 100644 index 00000000..8a9b4124 --- /dev/null +++ b/expedient/bin/versions/default/install/rollback @@ -0,0 +1,13 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: rollback module +### + +#Inform user +printHeader "info#" "Using default rollback module..." + +print "Nothing to do..." diff --git a/expedient/bin/versions/default/upgrade/default/backup b/expedient/bin/versions/default/upgrade/default/backup new file mode 100644 index 00000000..c3acceee --- /dev/null +++ b/expedient/bin/versions/default/upgrade/default/backup @@ -0,0 +1,28 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: backup module +### + +#inform user +printHeader "info#" "Using default backup module..." + +SRC_DIR=${OCF_PATH:-$(echo $(dirname $(dirname $PWD)))} +SRC_DIR=$SRC_DIR/expedient/ + +#Backing up files +mkdir -p $BACKUP_PATH +cp -R $SRC_DIR/src $BACKUP_PATH + +#Backing up database +local TMP_PATH=$PWD + +cd $SRC_DIR/src/python/expedient/clearinghouse/ || error "Target directory does not exist anymore?¿" + +python manage.py dumpdata > $BACKUP_PATH/dbdump.data || warning "Could not backup data. Check database for inconsistencies in foreign keys or many-to-many relationships" +python $TMP_PATH/versions/default/upgrade/tools/sqlDump.py $BACKUP_PATH/dbdump.sql "expedient.clearinghouse.settings" || warning "Could not backup data using SQL... (is redundant). Proceeding with upgrade..." +cd $TMP_PATH + diff --git a/expedient/bin/versions/default/upgrade/default/dependencies b/expedient/bin/versions/default/upgrade/default/dependencies new file mode 100644 index 00000000..5ee3a7f3 --- /dev/null +++ b/expedient/bin/versions/default/upgrade/default/dependencies @@ -0,0 +1,9 @@ +#!/bin/bash + +''' + @author: msune + @organization: i2CAT + @project: Ofelia FP7 + @description: +''' + diff --git a/expedient/bin/versions/default/upgrade/default/lib/set_environment_variables b/expedient/bin/versions/default/upgrade/default/lib/set_environment_variables new file mode 120000 index 00000000..d252ae1c --- /dev/null +++ b/expedient/bin/versions/default/upgrade/default/lib/set_environment_variables @@ -0,0 +1 @@ +../../../install/lib/set_environment_variables \ No newline at end of file diff --git a/expedient/bin/versions/default/upgrade/default/post-upgrade-hook b/expedient/bin/versions/default/upgrade/default/post-upgrade-hook new file mode 100644 index 00000000..1be1986a --- /dev/null +++ b/expedient/bin/versions/default/upgrade/default/post-upgrade-hook @@ -0,0 +1,23 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: post-upgrade-hook module +### + +#inform user +printHeader "info#" "Using default post-upgrade-hook module..." + +#Starting apache +print "Starting apache2..." +/usr/sbin/service apache2 start + +#Cleaning the house +confirm "Delete backup files?" $DONT_ABORT + +if [ $? == 0 ]; then + print "Deleting backups..." + rm -rf $BACKUP_PATH +fi diff --git a/expedient/bin/versions/default/upgrade/default/pre-upgrade-hook b/expedient/bin/versions/default/upgrade/default/pre-upgrade-hook new file mode 100644 index 00000000..54c95453 --- /dev/null +++ b/expedient/bin/versions/default/upgrade/default/pre-upgrade-hook @@ -0,0 +1,49 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: pre-upgrade-module +### + +#inform user +printHeader "info#" "Using default pre-upgrade-hook module..." + +#shutdown apache +print "Shutting down apache2..." +/usr/sbin/service apache2 stop + +#Check for OFELIA installation +OFELIA="none" + +while [ $OFELIA != "yes" ] && [ $OFELIA != "no" ] && [ $OFELIA != 1 ] && [ $OFELIA != 0 ] + do + echo "Is this an OFELIA istallation? (yes/no):" + read OFELIA + if [ $OFELIA == yes ]; then + OFELIA=1 + elif [ $OFELIA == no ]; then + OFELIA=0 + else + echo "Not valid option. Please say yes/no" + fi + done + +## PyPElib installation ... +print "Downloading latest pypelib version..." +/usr/bin/wget --no-check-certificate https://github.com/fp7-ofelia/pypelib/raw/deb/pypelib_latest_all.deb || error "Could not download pypelib latest version from https://github.com/fp7-ofelia/pypelib/raw/deb/pypelib_latest_all.deb. Do you have connectivity?" + +print "Installing pypelib_latest_all.deb..." +/usr/bin/dpkg -i pypelib_latest_all.deb || error "Could not install pypelib latest version using /usr/bin/dpkg -i pypelib_latest_all.deb" + +print "Removing temporary files..." +rm pypelib_latest_all.deb || warning "Could not remove pypelib_latest_all.deb" + +## Keeping database consistent +print "Checking and fixing database consistency..." +python $EXECPATH/../src/python/expedient/clearinghouse/manage.py clean_inconsistent_db_entries + +# Determine installation path +print "Setting environment variables..." +source $CURRENT_DIRECTORY/lib/set_environment_variables diff --git a/expedient/bin/versions/default/upgrade/default/rollback b/expedient/bin/versions/default/upgrade/default/rollback new file mode 100644 index 00000000..bdf9e233 --- /dev/null +++ b/expedient/bin/versions/default/upgrade/default/rollback @@ -0,0 +1,36 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: rollback module +### + +#inform user +printHeader "info#" "Using default rollback module..." + + +confirm "It seems something went wrong.. Now you will be able to rollback to the previous state of the filesystem and database. Alternatively you can try to solve the problem manually, avoiding the rollback mechanism. Do you want to rollback now?" $DONT_ABORT $NO_RESCUE + +if [ $? == 1 ]; then + print "Please remember that you can find the log of this upgrade operation under log/ folder. Good luck!" + exit 1 +fi + + + +#Restoring files first +print "Restoring files..." +cp $BACKUP_PATH/* $SRC_DIR/ -Rf || error "Could not restore files. Please take into account that previous state including DB state is in $BACKUP_PATH" +rm -f $SRC_DIR/dbdump.data $SRC_DIR/dbdump.sql $SRC_DIR/dbdump.sql.cfg + +#Restoring database +print "Restoring database..." + +#$PWD/../tools/sqlRestore.py $BACKUP_PATH/dbdump.sql || error "Could not restore database. Please take into account that previous state including DB state is in $BACKUP_PATH" +python $SRC_DIR/bin/versions/default/upgrade/tools/sqlRestore.py $BACKUP_PATH/dbdump.sql || error "Could not restore database. Please take into account that previous state including DB state is in $BACKUP_PATH" $NO_RESCUE + +cd $TMP_PATH + +service apache2 restart diff --git a/expedient/bin/versions/default/upgrade/default/upgrade b/expedient/bin/versions/default/upgrade/default/upgrade new file mode 100644 index 00000000..ee212d9c --- /dev/null +++ b/expedient/bin/versions/default/upgrade/default/upgrade @@ -0,0 +1,44 @@ +#!/bin/bash + +### +# @author: msune +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: Version checkings +### + +#inform user +printHeader "info#" "Using default upgrade module..." + +# SSL certificates: prepare ca_clients.crt for first use +# (file is either empty or does not exist) +if [[ -z $(cat /etc/apache2/ssl.crt/ca_clients.crt) ]]; then + cat /etc/apache2/ssl.crt/ca.crt >> /etc/apache2/ssl.crt/ca_clients.crt || warning "Could not add own CA to trusted clients (ca_clients.crt). Proceeding with upgrade..." +fi + +local TMP_PATH=$PWD + +cd $EXECPATH/../src/python/expedient/clearinghouse/ || error "Target directory does not exists anymore?" + +#Syncing DB +printHeader ">" "Syncing Database..." +python manage.py syncdb || error "Could not synchronize database using manage.py..." + +#Evolving +printHeader ">" "Evolving Database schema..." +python manage.py evolve --hint -x || error "Could not evolve database..." + +# Clean cache +printHeader ">" "Cleaning UI's cache hash values..." +python $TMP_PATH/versions/default/upgrade/tools/cleanCache.py || error "Could not clean UI's hashes..." + +# Set proper permissions to log files under /var/log/apache +for log_file in $(find /var/log/apache2 -name "*error_log") +do + chmod 755 $log_file + chown www-data $log_file +done +chown www-data:www-data /var/log/apache2 + +cd $TMP_PATH + diff --git a/expedient/bin/versions/default/upgrade/tools/cleanCache.py b/expedient/bin/versions/default/upgrade/tools/cleanCache.py new file mode 100755 index 00000000..50a27fc5 --- /dev/null +++ b/expedient/bin/versions/default/upgrade/tools/cleanCache.py @@ -0,0 +1,27 @@ +import os +import sys +from os.path import dirname, join +from django.conf import * + +#configobj +try: + from configobj import ConfigObj +except: + #FIXME: ugly + os.system("apt-get update && apt-get install python-configobj -y") + from configobj import ConfigObj + + +# This is needed because wsgi disallows using stdout +sys.stdout = sys.stderr + +PYTHON_DIR = join(dirname(__file__), '../../../../../src/python') +PLUGINS_DIR = join(dirname(__file__), '../../../../../src/python/plugins') +os.environ['DJANGO_SETTINGS_MODULE'] = 'expedient.clearinghouse.settings' +#os.environ['DJANGO_SETTINGS_MODULE'] = sys.argv[2] +sys.path.insert(0,PLUGINS_DIR) +sys.path.insert(0,PYTHON_DIR) + +from vt_plugin.models import resourcesHash +for rhash in resourcesHash.objects.all(): + rhash.delete() diff --git a/expedient/bin/versions/default/upgrade/tools/prova b/expedient/bin/versions/default/upgrade/tools/prova new file mode 100644 index 00000000..226db3ef --- /dev/null +++ b/expedient/bin/versions/default/upgrade/tools/prova @@ -0,0 +1,1782 @@ +-- MySQL dump 10.13 Distrib 5.1.49, for debian-linux-gnu (i486) +-- +-- Host: localhost Database: expedient +-- ------------------------------------------------------ +-- Server version 5.1.49-3 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `expedient` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `expedient` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `expedient`; + +-- +-- Table structure for table `aggregate_aggregate` +-- + +DROP TABLE IF EXISTS `aggregate_aggregate`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `aggregate_aggregate` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `leaf_name` varchar(100) NOT NULL, + `module_name` varchar(100) NOT NULL, + `name` varchar(200) NOT NULL, + `logo` varchar(100) DEFAULT NULL, + `description` longtext NOT NULL, + `location` varchar(200) NOT NULL, + `available` tinyint(1) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `aggregate_aggregate` +-- + +LOCK TABLES `aggregate_aggregate` WRITE; +/*!40000 ALTER TABLE `aggregate_aggregate` DISABLE KEYS */; +/*!40000 ALTER TABLE `aggregate_aggregate` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `auth_group` +-- + +DROP TABLE IF EXISTS `auth_group`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `auth_group` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(80) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `auth_group` +-- + +LOCK TABLES `auth_group` WRITE; +/*!40000 ALTER TABLE `auth_group` DISABLE KEYS */; +/*!40000 ALTER TABLE `auth_group` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `auth_group_permissions` +-- + +DROP TABLE IF EXISTS `auth_group_permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `auth_group_permissions` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `group_id` int(11) NOT NULL, + `permission_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `group_id` (`group_id`,`permission_id`), + KEY `auth_group_permissions_425ae3c4` (`group_id`), + KEY `auth_group_permissions_1e014c8f` (`permission_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `auth_group_permissions` +-- + +LOCK TABLES `auth_group_permissions` WRITE; +/*!40000 ALTER TABLE `auth_group_permissions` DISABLE KEYS */; +/*!40000 ALTER TABLE `auth_group_permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `auth_message` +-- + +DROP TABLE IF EXISTS `auth_message`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `auth_message` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `message` longtext NOT NULL, + PRIMARY KEY (`id`), + KEY `auth_message_403f60f` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `auth_message` +-- + +LOCK TABLES `auth_message` WRITE; +/*!40000 ALTER TABLE `auth_message` DISABLE KEYS */; +/*!40000 ALTER TABLE `auth_message` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `auth_permission` +-- + +DROP TABLE IF EXISTS `auth_permission`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `auth_permission` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `content_type_id` int(11) NOT NULL, + `codename` varchar(100) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `content_type_id` (`content_type_id`,`codename`), + KEY `auth_permission_1bb8f392` (`content_type_id`) +) ENGINE=MyISAM AUTO_INCREMENT=163 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `auth_permission` +-- + +LOCK TABLES `auth_permission` WRITE; +/*!40000 ALTER TABLE `auth_permission` DISABLE KEYS */; +INSERT INTO `auth_permission` VALUES (1,'Can add permission',1,'add_permission'),(2,'Can change permission',1,'change_permission'),(3,'Can delete permission',1,'delete_permission'),(4,'Can add group',2,'add_group'),(5,'Can change group',2,'change_group'),(6,'Can delete group',2,'delete_group'),(7,'Can add user',3,'add_user'),(8,'Can change user',3,'change_user'),(9,'Can delete user',3,'delete_user'),(10,'Can add message',4,'add_message'),(11,'Can change message',4,'change_message'),(12,'Can delete message',4,'delete_message'),(13,'Can add content type',5,'add_contenttype'),(14,'Can change content type',5,'change_contenttype'),(15,'Can delete content type',5,'delete_contenttype'),(16,'Can add session',6,'add_session'),(17,'Can change session',6,'change_session'),(18,'Can delete session',6,'delete_session'),(19,'Can add site',7,'add_site'),(20,'Can change site',7,'change_site'),(21,'Can delete site',7,'delete_site'),(22,'Can add log entry',8,'add_logentry'),(23,'Can change log entry',8,'change_logentry'),(24,'Can delete log entry',8,'delete_logentry'),(25,'Can add registration profile',9,'add_registrationprofile'),(26,'Can change registration profile',9,'change_registrationprofile'),(27,'Can delete registration profile',9,'delete_registrationprofile'),(28,'Can add version',10,'add_version'),(29,'Can change version',10,'change_version'),(30,'Can delete version',10,'delete_version'),(31,'Can add evolution',11,'add_evolution'),(32,'Can change evolution',11,'change_evolution'),(33,'Can delete evolution',11,'delete_evolution'),(34,'Can add job',12,'add_job'),(35,'Can change job',12,'change_job'),(36,'Can delete job',12,'delete_job'),(37,'Can add expedient permission',13,'add_expedientpermission'),(38,'Can change expedient permission',13,'change_expedientpermission'),(39,'Can delete expedient permission',13,'delete_expedientpermission'),(40,'Can add object permission',14,'add_objectpermission'),(41,'Can change object permission',14,'change_objectpermission'),(42,'Can delete object permission',14,'delete_objectpermission'),(43,'Can add permittee',15,'add_permittee'),(44,'Can change permittee',15,'change_permittee'),(45,'Can delete permittee',15,'delete_permittee'),(46,'Can add permission ownership',16,'add_permissionownership'),(47,'Can change permission ownership',16,'change_permissionownership'),(48,'Can delete permission ownership',16,'delete_permissionownership'),(49,'Can add permission request',17,'add_permissionrequest'),(50,'Can change permission request',17,'change_permissionrequest'),(51,'Can delete permission request',17,'delete_permissionrequest'),(52,'Can add password xmlrpc server proxy',18,'add_passwordxmlrpcserverproxy'),(53,'Can change password xmlrpc server proxy',18,'change_passwordxmlrpcserverproxy'),(54,'Can delete password xmlrpc server proxy',18,'delete_passwordxmlrpcserverproxy'),(55,'Can add dated message',19,'add_datedmessage'),(56,'Can change dated message',19,'change_datedmessage'),(57,'Can delete dated message',19,'delete_datedmessage'),(58,'Can add Generic Aggregate',20,'add_aggregate'),(59,'Can change Generic Aggregate',20,'change_aggregate'),(60,'Can delete Generic Aggregate',20,'delete_aggregate'),(61,'Can add project role',25,'add_projectrole'),(62,'Can change project role',25,'change_projectrole'),(63,'Can delete project role',25,'delete_projectrole'),(64,'Can add project role request',26,'add_projectrolerequest'),(65,'Can change project role request',26,'change_projectrolerequest'),(66,'Can delete project role request',26,'delete_projectrolerequest'),(67,'Can add project',27,'add_project'),(68,'Can change project',27,'change_project'),(69,'Can delete project',27,'delete_project'),(70,'Can add resource',28,'add_resource'),(71,'Can change resource',28,'change_resource'),(72,'Can delete resource',28,'delete_resource'),(73,'Can add sliver',29,'add_sliver'),(74,'Can change sliver',29,'change_sliver'),(75,'Can delete sliver',29,'delete_sliver'),(76,'Can add slice',30,'add_slice'),(77,'Can change slice',30,'change_slice'),(78,'Can delete slice',30,'delete_slice'),(79,'Can add user profile',31,'add_userprofile'),(80,'Can change user profile',31,'change_userprofile'),(81,'Can delete user profile',31,'delete_userprofile'),(82,'Can add open flow slice info',32,'add_openflowsliceinfo'),(83,'Can change open flow slice info',32,'change_openflowsliceinfo'),(84,'Can delete open flow slice info',32,'delete_openflowsliceinfo'),(85,'Can add OpenFlow Aggregate',21,'add_openflowaggregate'),(86,'Can change OpenFlow Aggregate',21,'change_openflowaggregate'),(87,'Can delete OpenFlow Aggregate',21,'delete_openflowaggregate'),(88,'Can add open flow switch',33,'add_openflowswitch'),(89,'Can change open flow switch',33,'change_openflowswitch'),(90,'Can delete open flow switch',33,'delete_openflowswitch'),(91,'Can add open flow connection',34,'add_openflowconnection'),(92,'Can change open flow connection',34,'change_openflowconnection'),(93,'Can delete open flow connection',34,'delete_openflowconnection'),(94,'Can add non open flow connection',35,'add_nonopenflowconnection'),(95,'Can change non open flow connection',35,'change_nonopenflowconnection'),(96,'Can delete non open flow connection',35,'delete_nonopenflowconnection'),(97,'Can add OpenFlow Interface',36,'add_openflowinterface'),(98,'Can change OpenFlow Interface',36,'change_openflowinterface'),(99,'Can delete OpenFlow Interface',36,'delete_openflowinterface'),(100,'Can add open flow interface sliver',37,'add_openflowinterfacesliver'),(101,'Can change open flow interface sliver',37,'change_openflowinterfacesliver'),(102,'Can delete open flow interface sliver',37,'delete_openflowinterfacesliver'),(103,'Can add flow space rule',38,'add_flowspacerule'),(104,'Can change flow space rule',38,'change_flowspacerule'),(105,'Can delete flow space rule',38,'delete_flowspacerule'),(106,'Can add geni slice info',39,'add_genisliceinfo'),(107,'Can change geni slice info',39,'change_genisliceinfo'),(108,'Can delete geni slice info',39,'delete_genisliceinfo'),(109,'Can add geni aggregate',40,'add_geniaggregate'),(110,'Can change geni aggregate',40,'change_geniaggregate'),(111,'Can delete geni aggregate',40,'delete_geniaggregate'),(112,'Can add planet lab sliver',41,'add_planetlabsliver'),(113,'Can change planet lab sliver',41,'change_planetlabsliver'),(114,'Can delete planet lab sliver',41,'delete_planetlabsliver'),(115,'Can add PlanetLab Node',42,'add_planetlabnode'),(116,'Can change PlanetLab Node',42,'change_planetlabnode'),(117,'Can delete PlanetLab Node',42,'delete_planetlabnode'),(118,'Can add PlanetLab GENI-API Aggregate',22,'add_planetlabaggregate'),(119,'Can change PlanetLab GENI-API Aggregate',22,'change_planetlabaggregate'),(120,'Can delete PlanetLab GENI-API Aggregate',22,'delete_planetlabaggregate'),(121,'Can add OpenFlow GENI-API Aggregate',23,'add_gcfopenflowaggregate'),(122,'Can change OpenFlow GENI-API Aggregate',23,'change_gcfopenflowaggregate'),(123,'Can delete OpenFlow GENI-API Aggregate',23,'delete_gcfopenflowaggregate'),(124,'Can add resources hash',43,'add_resourceshash'),(125,'Can change resources hash',43,'change_resourceshash'),(126,'Can delete resources hash',43,'delete_resourceshash'),(127,'Can add vm',44,'add_vm'),(128,'Can change vm',44,'change_vm'),(129,'Can delete vm',44,'delete_vm'),(130,'Can add vt server',45,'add_vtserver'),(131,'Can change vt server',45,'change_vtserver'),(132,'Can delete vt server',45,'delete_vtserver'),(133,'Can add Virtualization Aggregate',24,'add_vtplugin'),(134,'Can change Virtualization Aggregate',24,'change_vtplugin'),(135,'Can delete Virtualization Aggregate',24,'delete_vtplugin'),(136,'Can add i face',46,'add_iface'),(137,'Can change i face',46,'change_iface'),(138,'Can delete i face',46,'delete_iface'),(139,'Can add action',47,'add_action'),(140,'Can change action',47,'change_action'),(141,'Can delete action',47,'delete_action'),(142,'Can add xmlrpc server proxy',48,'add_xmlrpcserverproxy'),(143,'Can change xmlrpc server proxy',48,'change_xmlrpcserverproxy'),(144,'Can delete xmlrpc server proxy',48,'delete_xmlrpcserverproxy'),(145,'Can add vt server iface',49,'add_vtserveriface'),(146,'Can change vt server iface',49,'change_vtserveriface'),(147,'Can delete vt server iface',49,'delete_vtserveriface'),(148,'Can add dummy om',50,'add_dummyom'),(149,'Can change dummy om',50,'change_dummyom'),(150,'Can delete dummy om',50,'delete_dummyom'),(151,'Can add dummy om link',51,'add_dummyomlink'),(152,'Can change dummy om link',51,'change_dummyomlink'),(153,'Can delete dummy om link',51,'delete_dummyomlink'),(154,'Can add dummy om switch',52,'add_dummyomswitch'),(155,'Can change dummy om switch',52,'change_dummyomswitch'),(156,'Can delete dummy om switch',52,'delete_dummyomswitch'),(157,'Can add dummy om slice',53,'add_dummyomslice'),(158,'Can change dummy om slice',53,'change_dummyomslice'),(159,'Can delete dummy om slice',53,'delete_dummyomslice'),(160,'Can add dummy call back proxy',54,'add_dummycallbackproxy'),(161,'Can change dummy call back proxy',54,'change_dummycallbackproxy'),(162,'Can delete dummy call back proxy',54,'delete_dummycallbackproxy'); +/*!40000 ALTER TABLE `auth_permission` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `auth_user` +-- + +DROP TABLE IF EXISTS `auth_user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `auth_user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(255) NOT NULL, + `first_name` varchar(30) NOT NULL, + `last_name` varchar(30) NOT NULL, + `email` varchar(75) NOT NULL, + `password` varchar(128) NOT NULL, + `is_staff` tinyint(1) NOT NULL, + `is_active` tinyint(1) NOT NULL, + `is_superuser` tinyint(1) NOT NULL, + `last_login` datetime NOT NULL, + `date_joined` datetime NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `username` (`username`) +) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `auth_user` +-- + +LOCK TABLES `auth_user` WRITE; +/*!40000 ALTER TABLE `auth_user` DISABLE KEYS */; +INSERT INTO `auth_user` VALUES (1,'expedient','','','aa@aa.com','sha1$6f92a$4a35f8529e5a48567d81d2d215f60b4a1811d6e3',1,1,1,'2011-07-12 05:19:38','2011-07-12 05:19:38'); +/*!40000 ALTER TABLE `auth_user` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `auth_user_groups` +-- + +DROP TABLE IF EXISTS `auth_user_groups`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `auth_user_groups` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `group_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `user_id` (`user_id`,`group_id`), + KEY `auth_user_groups_403f60f` (`user_id`), + KEY `auth_user_groups_425ae3c4` (`group_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `auth_user_groups` +-- + +LOCK TABLES `auth_user_groups` WRITE; +/*!40000 ALTER TABLE `auth_user_groups` DISABLE KEYS */; +/*!40000 ALTER TABLE `auth_user_groups` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `auth_user_user_permissions` +-- + +DROP TABLE IF EXISTS `auth_user_user_permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `auth_user_user_permissions` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `permission_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `user_id` (`user_id`,`permission_id`), + KEY `auth_user_user_permissions_403f60f` (`user_id`), + KEY `auth_user_user_permissions_1e014c8f` (`permission_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `auth_user_user_permissions` +-- + +LOCK TABLES `auth_user_user_permissions` WRITE; +/*!40000 ALTER TABLE `auth_user_user_permissions` DISABLE KEYS */; +/*!40000 ALTER TABLE `auth_user_user_permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `django_admin_log` +-- + +DROP TABLE IF EXISTS `django_admin_log`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `django_admin_log` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `action_time` datetime NOT NULL, + `user_id` int(11) NOT NULL, + `content_type_id` int(11) DEFAULT NULL, + `object_id` longtext, + `object_repr` varchar(200) NOT NULL, + `action_flag` smallint(5) unsigned NOT NULL, + `change_message` longtext NOT NULL, + PRIMARY KEY (`id`), + KEY `django_admin_log_403f60f` (`user_id`), + KEY `django_admin_log_1bb8f392` (`content_type_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `django_admin_log` +-- + +LOCK TABLES `django_admin_log` WRITE; +/*!40000 ALTER TABLE `django_admin_log` DISABLE KEYS */; +/*!40000 ALTER TABLE `django_admin_log` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `django_content_type` +-- + +DROP TABLE IF EXISTS `django_content_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `django_content_type` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `app_label` varchar(100) NOT NULL, + `model` varchar(100) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `app_label` (`app_label`,`model`) +) ENGINE=MyISAM AUTO_INCREMENT=55 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `django_content_type` +-- + +LOCK TABLES `django_content_type` WRITE; +/*!40000 ALTER TABLE `django_content_type` DISABLE KEYS */; +INSERT INTO `django_content_type` VALUES (1,'permission','auth','permission'),(2,'group','auth','group'),(3,'user','auth','user'),(4,'message','auth','message'),(5,'content type','contenttypes','contenttype'),(6,'session','sessions','session'),(7,'site','sites','site'),(8,'log entry','admin','logentry'),(9,'registration profile','registration','registrationprofile'),(10,'version','django_evolution','version'),(11,'evolution','django_evolution','evolution'),(12,'job','timer','job'),(13,'expedient permission','permissions','expedientpermission'),(14,'object permission','permissions','objectpermission'),(15,'permittee','permissions','permittee'),(16,'permission ownership','permissions','permissionownership'),(17,'permission request','permissions','permissionrequest'),(18,'password xmlrpc server proxy','xmlrpc_serverproxy','passwordxmlrpcserverproxy'),(19,'dated message','messaging','datedmessage'),(20,'Generic Aggregate','aggregate','aggregate'),(21,'OpenFlow Aggregate','plugin','openflowaggregate'),(22,'PlanetLab GENI-API Aggregate','planetlab','planetlabaggregate'),(23,'OpenFlow GENI-API Aggregate','gopenflow','gcfopenflowaggregate'),(24,'Virtualization Aggregate','vt_plugin','vtplugin'),(25,'project role','roles','projectrole'),(26,'project role request','roles','projectrolerequest'),(27,'project','project','project'),(28,'resource','resources','resource'),(29,'sliver','resources','sliver'),(30,'slice','slice','slice'),(31,'user profile','users','userprofile'),(32,'open flow slice info','plugin','openflowsliceinfo'),(33,'open flow switch','plugin','openflowswitch'),(34,'open flow connection','plugin','openflowconnection'),(35,'non open flow connection','plugin','nonopenflowconnection'),(36,'OpenFlow Interface','plugin','openflowinterface'),(37,'open flow interface sliver','plugin','openflowinterfacesliver'),(38,'flow space rule','plugin','flowspacerule'),(39,'geni slice info','expedient_geni','genisliceinfo'),(40,'geni aggregate','expedient_geni','geniaggregate'),(41,'planet lab sliver','planetlab','planetlabsliver'),(42,'PlanetLab Node','planetlab','planetlabnode'),(43,'resources hash','vt_plugin','resourceshash'),(44,'vm','vt_plugin','vm'),(45,'vt server','vt_plugin','vtserver'),(46,'i face','vt_plugin','iface'),(47,'action','vt_plugin','action'),(48,'xmlrpc server proxy','vt_plugin','xmlrpcserverproxy'),(49,'vt server iface','vt_plugin','vtserveriface'),(50,'dummy om','dummyom','dummyom'),(51,'dummy om link','dummyom','dummyomlink'),(52,'dummy om switch','dummyom','dummyomswitch'),(53,'dummy om slice','dummyom','dummyomslice'),(54,'dummy call back proxy','dummyom','dummycallbackproxy'); +/*!40000 ALTER TABLE `django_content_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `django_evolution` +-- + +DROP TABLE IF EXISTS `django_evolution`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `django_evolution` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `version_id` int(11) NOT NULL, + `app_label` varchar(200) NOT NULL, + `label` varchar(100) NOT NULL, + PRIMARY KEY (`id`), + KEY `django_evolution_10f4f63` (`version_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `django_evolution` +-- + +LOCK TABLES `django_evolution` WRITE; +/*!40000 ALTER TABLE `django_evolution` DISABLE KEYS */; +/*!40000 ALTER TABLE `django_evolution` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `django_project_version` +-- + +DROP TABLE IF EXISTS `django_project_version`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `django_project_version` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `signature` longtext NOT NULL, + `when` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `django_project_version` +-- + +LOCK TABLES `django_project_version` WRITE; +/*!40000 ALTER TABLE `django_project_version` DISABLE KEYS */; +INSERT INTO `django_project_version` VALUES (1,'(dp1\nS\'xmlrpc_serverproxy\'\np2\nccopy_reg\n_reconstructor\np3\n(cdjango.utils.datastructures\nSortedDict\np4\nc__builtin__\ndict\np5\n(dp6\nS\'PasswordXMLRPCServerProxy\'\np7\n(dp8\nS\'fields\'\np9\n(dp10\nS\'username\'\np11\n(dp12\nS\'field_type\'\np13\ncdjango.db.models.fields\nCharField\np14\nsS\'max_length\'\np15\nI100\nssS\'url\'\np16\n(dp17\ng13\ng14\nsg15\nI1024\nssS\'password_timestamp\'\np18\n(dp19\ng13\ncdjango.db.models.fields\nDateTimeField\np20\nssS\'max_password_age\'\np21\n(dp22\ng13\ncdjango.db.models.fields\nPositiveIntegerField\np23\nssS\'password\'\np24\n(dp25\ng13\ng14\nsg15\nI40\nssS\'id\'\np26\n(dp27\ng13\ncdjango.db.models.fields\nAutoField\np28\nsS\'primary_key\'\np29\nI01\nssS\'verify_certs\'\np30\n(dp31\ng13\ncdjango.db.models.fields\nBooleanField\np32\nsssS\'meta\'\np33\n(dp34\nS\'unique_together\'\np35\n(lp36\nsS\'db_table\'\np37\nS\'xmlrpc_serverproxy_passwordxmlrpcserverproxy\'\np38\nsS\'db_tablespace\'\np39\nS\'\'\nsS\'pk_column\'\np40\ng26\nssstRp41\n(dp42\nS\'keyOrder\'\np43\n(lp44\ng7\nasbsS\'django_extensions\'\np45\ng3\n(g4\ng5\n(dtRp46\n(dp47\ng43\n(lp48\nsbsS\'registration\'\np49\ng3\n(g4\ng5\n(dp50\nS\'RegistrationProfile\'\np51\n(dp52\ng9\n(dp53\nS\'activation_key\'\np54\n(dp55\ng13\ng14\nsg15\nI40\nssg26\n(dp56\ng13\ng28\nsg29\nI01\nssS\'user\'\np57\n(dp58\ng13\ncdjango.db.models.fields.related\nForeignKey\np59\nsS\'unique\'\np60\nI01\nsS\'related_model\'\np61\nS\'auth.User\'\np62\nsssg33\n(dp63\ng35\n(lp64\nsg37\nS\'registration_registrationprofile\'\np65\nsg39\nS\'\'\nsg40\ng26\nssstRp66\n(dp67\ng43\n(lp68\ng51\nasbsS\'vt_plugin\'\np69\ng3\n(g4\ng5\n(dp70\nS\'iFace\'\np71\n(dp72\ng9\n(dp73\nS\'gw\'\np74\n(dp75\ng15\nI15\nsg13\ncdjango.db.models.fields\nIPAddressField\np76\nsS\'null\'\np77\nI01\nssS\'name\'\np78\n(dp79\ng15\nI32\nsg13\ng14\nsg77\nI01\nssS\'ip\'\np80\n(dp81\ng15\nI15\nsg13\ng76\nsg77\nI01\nssS\'dns1\'\np82\n(dp83\ng15\nI15\nsg13\ng76\nsg77\nI01\nssS\'mask\'\np84\n(dp85\ng15\nI15\nsg13\ng76\nsg77\nI01\nssg26\n(dp86\ng13\ng28\nsg29\nI01\nssS\'mac\'\np87\n(dp88\ng15\nI17\nsg13\ng14\nsg77\nI01\nssS\'dns2\'\np89\n(dp90\ng15\nI15\nsg13\ng76\nsg77\nI01\nssS\'bridgeIface\'\np91\n(dp92\ng15\nI32\nsg13\ng14\nsg77\nI01\nssS\'isMgmt\'\np93\n(dp94\ng13\ng32\nsssg33\n(dp95\ng35\n(lp96\nsg37\nS\'vt_plugin_iface\'\np97\nsg39\nS\'\'\nsg40\ng26\nsssS\'resourcesHash\'\np98\n(dp99\ng9\n(dp100\nS\'hashValue\'\np101\n(dp102\ng13\ng14\nsg15\nI1024\nssS\'projectUUID\'\np103\n(dp104\ng13\ng14\nsg15\nI1024\nssg26\n(dp105\ng13\ng28\nsg29\nI01\nssS\'sliceUUID\'\np106\n(dp107\ng13\ng14\nsg15\nI1024\nssS\'vtamID\'\np108\n(dp109\ng13\ncdjango.db.models.fields\nIntegerField\np110\nsssg33\n(dp111\ng35\n(lp112\nsg37\nS\'vt_plugin_resourceshash\'\np113\nsg39\nS\'\'\nsg40\ng26\nsssS\'xmlrpcServerProxy\'\np114\n(dp115\ng9\n(dp116\ng11\n(dp117\ng13\ng14\nsg15\nI100\nssg16\n(dp118\ng13\ncdjango.db.models.fields\nURLField\np119\nsg15\nI1024\nssg24\n(dp120\ng13\ng14\nsg15\nI24\nssg26\n(dp121\ng13\ng28\nsg29\nI01\nsssg33\n(dp122\ng35\n(lp123\nsg37\nS\'vt_plugin_xmlrpcserverproxy\'\np124\nsg39\nS\'\'\nsg40\ng26\nsssS\'VtPlugin\'\np125\n(dp126\ng9\n(dp127\nS\'client\'\np128\n(dp129\ng13\ncdjango.db.models.fields.related\nOneToOneField\np130\nsg60\nI01\nsg77\nI01\nsg61\nS\'vt_plugin.xmlrpcServerProxy\'\np131\nssS\'aggregate_ptr\'\np132\n(dp133\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'aggregate.Aggregate\'\np134\nsssg33\n(dp135\ng35\n(lp136\nsg37\nS\'vt_plugin_vtplugin\'\np137\nsg39\nS\'\'\nsg40\nS\'aggregate_ptr_id\'\np138\nsssS\'VTServerIface\'\np139\n(dp140\ng9\n(dp141\nS\'ifaceName\'\np142\n(dp143\ng15\nI128\nsg13\ng14\nsg77\nI01\nssS\'switchID\'\np144\n(dp145\ng15\nI128\nsg13\ng14\nsg77\nI01\nssg26\n(dp146\ng13\ng28\nsg29\nI01\nssS\'port\'\np147\n(dp148\ng13\ng110\nsg77\nI01\nsssg33\n(dp149\ng35\n(lp150\nsg37\nS\'vt_plugin_vtserveriface\'\np151\nsg39\nS\'\'\nsg40\ng26\nsssS\'VM\'\np152\n(dp153\ng9\n(dp154\nS\'hdOriginPath\'\np155\n(dp156\ng13\ng14\nsg15\nI1024\nssS\'disc_image\'\np157\n(dp158\ng13\ng14\nsg15\nI20\nssS\'virtTech\'\np159\n(dp160\ng13\ng14\nsg15\nI10\nssS\'virtualizationSetupType\'\np161\n(dp162\ng13\ng14\nsg15\nI20\nssS\'projectId\'\np163\n(dp164\ng13\ng14\nsg15\nI1024\nssS\'hdSetupType\'\np165\n(dp166\ng13\ng14\nsg15\nI20\nssS\'state\'\np167\n(dp168\ng13\ng14\nsg15\nI24\nssS\'operatingSystemDistribution\'\np169\n(dp170\ng13\ng14\nsg15\nI512\nssS\'operatingSystemType\'\np171\n(dp172\ng13\ng14\nsg15\nI512\nssS\'sliceId\'\np173\n(dp174\ng13\ng14\nsg15\nI1024\nssS\'memory\'\np175\n(dp176\ng13\ng110\nsg77\nI01\nssS\'operatingSystemVersion\'\np177\n(dp178\ng13\ng14\nsg15\nI512\nssS\'ifaces\'\np179\n(dp180\ng13\ncdjango.db.models.fields.related\nManyToManyField\np181\nsg77\nI01\nsg61\nS\'vt_plugin.iFace\'\np182\nssS\'sliceName\'\np183\n(dp184\ng13\ng14\nsg15\nI1024\nssS\'resource_ptr\'\np185\n(dp186\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'resources.Resource\'\np187\nssS\'serverID\'\np188\n(dp189\ng13\ng14\nsg15\nI1024\nssS\'projectName\'\np190\n(dp191\ng13\ng14\nsg15\nI1024\nssS\'uuid\'\np192\n(dp193\ng13\ng14\nsg15\nI1024\nsssg33\n(dp194\ng35\n(lp195\nsg37\nS\'vt_plugin_vm\'\np196\nsg39\nS\'\'\nsg40\nS\'resource_ptr_id\'\np197\nsssS\'Action\'\np198\n(dp199\ng9\n(dp200\nS\'status\'\np201\n(dp202\ng13\ng14\nsg15\nI16\nssS\'requestUser\'\np203\n(dp204\ng13\ng59\nsg77\nI01\nsg61\nS\'auth.User\'\np205\nssg192\n(dp206\ng13\ng14\nsg15\nI512\nssS\'hyperaction\'\np207\n(dp208\ng13\ng14\nsg15\nI16\nssS\'vm\'\np209\n(dp210\ng13\ng59\nsg77\nI01\nsg61\nS\'vt_plugin.VM\'\np211\nssS\'type\'\np212\n(dp213\ng13\ng14\nsg15\nI16\nssg26\n(dp214\ng13\ng28\nsg29\nI01\nssS\'description\'\np215\n(dp216\ng15\nI512\nsg13\ng14\nsg77\nI01\nsssg33\n(dp217\ng35\n(lp218\nsg37\nS\'vt_plugin_action\'\np219\nsg39\nS\'\'\nsg40\ng26\nsssS\'VTServer\'\np220\n(dp221\ng9\n(dp222\nS\'vmMgmtIface\'\np223\n(dp224\ng13\ng14\nsg15\nI1024\nssg159\n(dp225\ng13\ng14\nsg15\nI1024\nssS\'freeCpu\'\np226\n(dp227\ng13\ncdjango.db.models.fields\nDecimalField\np228\nsg77\nI01\nsS\'max_digits\'\np229\nI3\nsS\'decimal_places\'\np230\nI2\nssg177\n(dp231\ng13\ng14\nsg15\nI512\nssS\'freeMemory\'\np232\n(dp233\ng13\ng110\nsg77\nI01\nssg179\n(dp234\ng13\ng181\nsg77\nI01\nsg61\nS\'vt_plugin.VTServerIface\'\np235\nssg169\n(dp236\ng13\ng14\nsg15\nI512\nssg171\n(dp237\ng13\ng14\nsg15\nI512\nssg175\n(dp238\ng13\ng110\nsg77\nI01\nssS\'freeDiscSpace\'\np239\n(dp240\ng13\ng110\nsg77\nI01\nssS\'resource_ptr\'\np241\n(dp242\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'resources.Resource\'\np243\nssS\'vms\'\np244\n(dp245\ng13\ng181\nsg77\nI01\nsg61\nS\'vt_plugin.VM\'\np246\nssg192\n(dp247\ng13\ng14\nsg15\nI1024\nsssg33\n(dp248\ng35\n(lp249\nsg37\nS\'vt_plugin_vtserver\'\np250\nsg39\nS\'\'\nsg40\nS\'resource_ptr_id\'\np251\nssstRp252\n(dp253\ng43\n(lp254\ng98\nag152\nag220\nag125\nag71\nag198\nag114\nag139\nasbsS\'slice\'\np255\ng3\n(g4\ng5\n(dp256\nS\'Slice\'\np257\n(dp258\ng9\n(dp259\ng192\n(dp260\ng15\nI200\nsg13\ng14\nsg60\nI01\nssg215\n(dp261\ng13\ncdjango.db.models.fields\nTextField\np262\nssS\'started\'\np263\n(dp264\ng13\ng32\nssS\'expiration_date\'\np265\n(dp266\ng13\ncexpedient.common.utils.modelfields\nLimitedDateTimeField\np267\nssS\'modified\'\np268\n(dp269\ng13\ng32\nssS\'project\'\np270\n(dp271\ng13\ng59\nsg61\nS\'project.Project\'\np272\nssS\'owner\'\np273\n(dp274\ng13\ng59\nsg61\nS\'auth.User\'\np275\nssg26\n(dp276\ng13\ng28\nsg29\nI01\nssg78\n(dp277\ng15\nI200\nsg13\ng14\nsg60\nI01\nsssg33\n(dp278\ng35\n(lp279\nsg37\nS\'slice_slice\'\np280\nsg39\nS\'\'\nsg40\ng26\nssstRp281\n(dp282\ng43\n(lp283\ng257\nasbsS\'gopenflow\'\np284\ng3\n(g4\ng5\n(dp285\nS\'GCFOpenFlowAggregate\'\np286\n(dp287\ng9\n(dp288\nS\'geniaggregate_ptr\'\np289\n(dp290\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'expedient_geni.GENIAggregate\'\np291\nsssg33\n(dp292\ng35\n(lp293\nsg37\nS\'gopenflow_gcfopenflowaggregate\'\np294\nsg39\nS\'\'\nsg40\nS\'geniaggregate_ptr_id\'\np295\nssstRp296\n(dp297\ng43\n(lp298\ng286\nasbsS\'sites\'\np299\ng3\n(g4\ng5\n(dp300\nS\'Site\'\np301\n(dp302\ng9\n(dp303\nS\'domain\'\np304\n(dp305\ng13\ng14\nsg15\nI100\nssg26\n(dp306\ng13\ng28\nsg29\nI01\nssg78\n(dp307\ng13\ng14\nsg15\nI50\nsssg33\n(dp308\ng35\n(lp309\nsg37\nS\'django_site\'\np310\nsg39\nS\'\'\nsg40\ng26\nssstRp311\n(dp312\ng43\n(lp313\ng301\nasbsS\'contenttypes\'\np314\ng3\n(g4\ng5\n(dp315\nS\'ContentType\'\np316\n(dp317\ng9\n(dp318\nS\'model\'\np319\n(dp320\ng13\ng14\nsg15\nI100\nssS\'app_label\'\np321\n(dp322\ng13\ng14\nsg15\nI100\nssg26\n(dp323\ng13\ng28\nsg29\nI01\nssg78\n(dp324\ng13\ng14\nsg15\nI100\nsssg33\n(dp325\ng35\n((S\'app_label\'\nS\'model\'\nttp326\nsg37\nS\'django_content_type\'\np327\nsg39\nS\'\'\nsg40\ng26\nssstRp328\n(dp329\ng43\n(lp330\ng316\nasbsS\'html\'\np331\ng3\n(g4\ng5\n(dtRp332\n(dp333\ng43\n(lp334\nsbsS\'__version__\'\np335\nI1\nsS\'resources\'\np336\ng3\n(g4\ng5\n(dp337\nS\'Resource\'\np338\n(dp339\ng9\n(dp340\nS\'available\'\np341\n(dp342\ng13\ng32\nssS\'leaf_name\'\np343\n(dp344\ng13\ng14\nsg15\nI100\nssg78\n(dp345\ng13\ng14\nsg15\nI200\nssS\'status_change_timestamp\'\np346\n(dp347\ng13\ng20\nssS\'slice_set\'\np348\n(dp349\ng13\ng181\nsg61\nS\'slice.Slice\'\np350\nssS\'aggregate\'\np351\n(dp352\ng13\ng59\nsg61\nS\'aggregate.Aggregate\'\np353\nssS\'module_name\'\np354\n(dp355\ng13\ng14\nsg15\nI100\nssg26\n(dp356\ng13\ng28\nsg29\nI01\nsssg33\n(dp357\ng35\n(lp358\nsg37\nS\'resources_resource\'\np359\nsg39\nS\'\'\nsg40\ng26\nsssS\'Sliver\'\np360\n(dp361\ng9\n(dp362\ng354\n(dp363\ng13\ng14\nsg15\nI100\nssS\'slice\'\np364\n(dp365\ng13\ng59\nsg61\nS\'slice.Slice\'\np366\nssg343\n(dp367\ng13\ng14\nsg15\nI100\nssS\'resource\'\np368\n(dp369\ng13\ng59\nsg61\nS\'resources.Resource\'\np370\nssg26\n(dp371\ng13\ng28\nsg29\nI01\nsssg33\n(dp372\ng35\n(lp373\nsg37\nS\'resources_sliver\'\np374\nsg39\nS\'\'\nsg40\ng26\nssstRp375\n(dp376\ng43\n(lp377\ng338\nag360\nasbsS\'rpc4django\'\np378\ng3\n(g4\ng5\n(dtRp379\n(dp380\ng43\n(lp381\nsbsS\'users\'\np382\ng3\n(g4\ng5\n(dp383\nS\'UserProfile\'\np384\n(dp385\ng9\n(dp386\nS\'affiliation\'\np387\n(dp388\ng13\ng14\nsg15\nI100\nssg26\n(dp389\ng13\ng28\nsg29\nI01\nssg57\n(dp390\ng13\ng59\nsg60\nI01\nsg61\nS\'auth.User\'\np391\nsssg33\n(dp392\ng35\n(lp393\nsg37\nS\'users_userprofile\'\np394\nsg39\nS\'\'\nsg40\ng26\nssstRp395\n(dp396\ng43\n(lp397\ng384\nasbsS\'sessions\'\np398\ng3\n(g4\ng5\n(dp399\nS\'Session\'\np400\n(dp401\ng9\n(dp402\nS\'session_key\'\np403\n(dp404\ng13\ng14\nsg15\nI40\nsg29\nI01\nssS\'expire_date\'\np405\n(dp406\ng13\ng20\nssS\'session_data\'\np407\n(dp408\ng13\ng262\nsssg33\n(dp409\ng35\n(lp410\nsg37\nS\'django_session\'\np411\nsg39\nS\'\'\nsg40\ng403\nssstRp412\n(dp413\ng43\n(lp414\ng400\nasbsS\'planetlab\'\np415\ng3\n(g4\ng5\n(dp416\nS\'PlanetLabSliver\'\np417\n(dp418\ng9\n(dp419\nS\'sliver_ptr\'\np420\n(dp421\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'resources.Sliver\'\np422\nsssg33\n(dp423\ng35\n(lp424\nsg37\nS\'planetlab_planetlabsliver\'\np425\nsg39\nS\'\'\nsg40\nS\'sliver_ptr_id\'\np426\nsssS\'PlanetLabNode\'\np427\n(dp428\ng9\n(dp429\nS\'resource_ptr\'\np430\n(dp431\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'resources.Resource\'\np432\nssS\'node_id\'\np433\n(dp434\ng13\ng14\nsg15\nI256\nsssg33\n(dp435\ng35\n(lp436\nsg37\nS\'planetlab_planetlabnode\'\np437\nsg39\nS\'\'\nsg40\nS\'resource_ptr_id\'\np438\nsssS\'PlanetLabAggregate\'\np439\n(dp440\ng9\n(dp441\nS\'rspec\'\np442\n(dp443\ng13\ncdjango.db.models.fields\nXMLField\np444\nssS\'geniaggregate_ptr\'\np445\n(dp446\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'expedient_geni.GENIAggregate\'\np447\nsssg33\n(dp448\ng35\n(lp449\nsg37\nS\'planetlab_planetlabaggregate\'\np450\nsg39\nS\'\'\nsg40\nS\'geniaggregate_ptr_id\'\np451\nssstRp452\n(dp453\ng43\n(lp454\ng417\nag427\nag439\nasbsS\'commands\'\np455\ng3\n(g4\ng5\n(dtRp456\n(dp457\ng43\n(lp458\nsbsS\'auth\'\np459\ng3\n(g4\ng5\n(dp460\nS\'Message\'\np461\n(dp462\ng9\n(dp463\nS\'message\'\np464\n(dp465\ng13\ng262\nssg26\n(dp466\ng13\ng28\nsg29\nI01\nssg57\n(dp467\ng13\ng59\nsg61\nS\'auth.User\'\np468\nsssg33\n(dp469\ng35\n(lp470\nsg37\nS\'auth_message\'\np471\nsg39\nS\'\'\nsg40\ng26\nsssS\'Group\'\np472\n(dp473\ng9\n(dp474\nS\'permissions\'\np475\n(dp476\ng13\ng181\nsg61\nS\'auth.Permission\'\np477\nssg26\n(dp478\ng13\ng28\nsg29\nI01\nssg78\n(dp479\ng15\nI80\nsg13\ng14\nsg60\nI01\nsssg33\n(dp480\ng35\n(lp481\nsg37\nS\'auth_group\'\np482\nsg39\nS\'\'\nsg40\ng26\nsssS\'User\'\np483\n(dp484\ng9\n(dp485\ng11\n(dp486\ng15\nI255\nsg13\ng14\nsg60\nI01\nssS\'first_name\'\np487\n(dp488\ng13\ng14\nsg15\nI30\nssS\'last_name\'\np489\n(dp490\ng13\ng14\nsg15\nI30\nssS\'is_active\'\np491\n(dp492\ng13\ng32\nssS\'email\'\np493\n(dp494\ng13\ncdjango.db.models.fields\nEmailField\np495\nsg15\nI75\nssS\'is_superuser\'\np496\n(dp497\ng13\ng32\nssS\'is_staff\'\np498\n(dp499\ng13\ng32\nssS\'last_login\'\np500\n(dp501\ng13\ng20\nssS\'groups\'\np502\n(dp503\ng13\ng181\nsg61\nS\'auth.Group\'\np504\nssS\'user_permissions\'\np505\n(dp506\ng13\ng181\nsg61\nS\'auth.Permission\'\np507\nssg24\n(dp508\ng13\ng14\nsg15\nI128\nssg26\n(dp509\ng13\ng28\nsg29\nI01\nssS\'date_joined\'\np510\n(dp511\ng13\ng20\nsssg33\n(dp512\ng35\n(lp513\nsg37\nS\'auth_user\'\np514\nsg39\nS\'\'\nsg40\ng26\nsssS\'Permission\'\np515\n(dp516\ng9\n(dp517\nS\'codename\'\np518\n(dp519\ng13\ng14\nsg15\nI100\nssg26\n(dp520\ng13\ng28\nsg29\nI01\nssS\'content_type\'\np521\n(dp522\ng13\ng59\nsg61\nS\'contenttypes.ContentType\'\np523\nssg78\n(dp524\ng13\ng14\nsg15\nI50\nsssg33\n(dp525\ng35\n((S\'content_type\'\nS\'codename\'\nttp526\nsg37\nS\'auth_permission\'\np527\nsg39\nS\'\'\nsg40\ng26\nssstRp528\n(dp529\ng43\n(lp530\ng515\nag472\nag483\nag461\nasbsS\'rspec\'\np531\ng3\n(g4\ng5\n(dtRp532\n(dp533\ng43\n(lp534\nsbsS\'aggregate\'\np535\ng3\n(g4\ng5\n(dp536\nS\'Aggregate\'\np537\n(dp538\ng9\n(dp539\ng341\n(dp540\ng13\ng32\nssg343\n(dp541\ng13\ng14\nsg15\nI100\nssg215\n(dp542\ng13\ng262\nssS\'location\'\np543\n(dp544\ng13\ng14\nsg15\nI200\nssg354\n(dp545\ng13\ng14\nsg15\nI100\nssS\'logo\'\np546\n(dp547\ng15\nI100\nsg13\ncdjango.db.models.fields.files\nImageField\np548\nsg77\nI01\nssg26\n(dp549\ng13\ng28\nsg29\nI01\nssg78\n(dp550\ng15\nI200\nsg13\ng14\nsg60\nI01\nsssg33\n(dp551\ng35\n(lp552\nsg37\nS\'aggregate_aggregate\'\np553\nsg39\nS\'\'\nsg40\ng26\nssstRp554\n(dp555\ng43\n(lp556\ng537\nasbsS\'permissions\'\np557\ng3\n(g4\ng5\n(dp558\nS\'ObjectPermission\'\np559\n(dp560\ng9\n(dp561\nS\'permittees\'\np562\n(dp563\ng13\ng181\nsg61\nS\'permissions.Permittee\'\np564\nssS\'object_type\'\np565\n(dp566\ng13\ng59\nsg61\nS\'contenttypes.ContentType\'\np567\nssg26\n(dp568\ng13\ng28\nsg29\nI01\nssS\'object_id\'\np569\n(dp570\ng13\ng23\nssS\'permission\'\np571\n(dp572\ng13\ng59\nsg61\nS\'permissions.ExpedientPermission\'\np573\nsssg33\n(dp574\ng35\n((S\'permission\'\nS\'object_type\'\nS\'object_id\'\nttp575\nsg37\nS\'permissions_objectpermission\'\np576\nsg39\nS\'\'\nsg40\ng26\nsssS\'ExpedientPermission\'\np577\n(dp578\ng9\n(dp579\ng215\n(dp580\ng13\ng262\nssS\'view\'\np581\n(dp582\ng15\nI300\nsg13\ng14\nsg77\nI01\nssg26\n(dp583\ng13\ng28\nsg29\nI01\nssg78\n(dp584\ng15\nI100\nsg13\ng14\nsg60\nI01\nsssg33\n(dp585\ng35\n(lp586\nsg37\nS\'permissions_expedientpermission\'\np587\nsg39\nS\'\'\nsg40\ng26\nsssS\'PermissionOwnership\'\np588\n(dp589\ng9\n(dp590\nS\'can_delegate\'\np591\n(dp592\ng13\ng32\nssS\'permittee\'\np593\n(dp594\ng13\ng59\nsg61\nS\'permissions.Permittee\'\np595\nssg26\n(dp596\ng13\ng28\nsg29\nI01\nssS\'obj_permission\'\np597\n(dp598\ng13\ng59\nsg61\nS\'permissions.ObjectPermission\'\np599\nsssg33\n(dp600\ng35\n((S\'obj_permission\'\nS\'permittee\'\nttp601\nsg37\nS\'permissions_permissionownership\'\np602\nsg39\nS\'\'\nsg40\ng26\nsssS\'Permittee\'\np603\n(dp604\ng9\n(dp605\ng565\n(dp606\ng13\ng59\nsg61\nS\'contenttypes.ContentType\'\np607\nssg26\n(dp608\ng13\ng28\nsg29\nI01\nssg569\n(dp609\ng13\ng23\nsssg33\n(dp610\ng35\n((S\'object_type\'\nS\'object_id\'\nttp611\nsg37\nS\'permissions_permittee\'\np612\nsg39\nS\'\'\nsg40\ng26\nsssS\'PermissionRequest\'\np613\n(dp614\ng9\n(dp615\nS\'requesting_user\'\np616\n(dp617\ng13\ng59\nsg61\nS\'auth.User\'\np618\nssS\'requested_permission\'\np619\n(dp620\ng13\ng59\nsg61\nS\'permissions.ObjectPermission\'\np621\nssS\'permission_owner\'\np622\n(dp623\ng13\ng59\nsg61\nS\'auth.User\'\np624\nssg464\n(dp625\ng13\ng262\nssg593\n(dp626\ng13\ng59\nsg61\nS\'permissions.Permittee\'\np627\nssg26\n(dp628\ng13\ng28\nsg29\nI01\nsssg33\n(dp629\ng35\n(lp630\nsg37\nS\'permissions_permissionrequest\'\np631\nsg39\nS\'\'\nsg40\ng26\nssstRp632\n(dp633\ng43\n(lp634\ng577\nag559\nag603\nag588\nag613\nasbsS\'autoslug\'\np635\ng3\n(g4\ng5\n(dtRp636\n(dp637\ng43\n(lp638\nsbsS\'extendable\'\np639\ng3\n(g4\ng5\n(dtRp640\n(dp641\ng43\n(lp642\nsbsS\'dummyom\'\np643\ng3\n(g4\ng5\n(dp644\nS\'DummyCallBackProxy\'\np645\n(dp646\ng9\n(dp647\ng16\n(dp648\ng13\ng14\nsg15\nI200\nssg11\n(dp649\ng13\ng14\nsg15\nI1024\nssS\'om\'\np650\n(dp651\ng13\ng130\nsg60\nI01\nsg61\nS\'dummyom.DummyOM\'\np652\nssS\'cookie\'\np653\n(dp654\ng13\ng14\nsg15\nI1024\nssg26\n(dp655\ng13\ng28\nsg29\nI01\nsssg33\n(dp656\ng35\n(lp657\nsg37\nS\'dummyom_dummycallbackproxy\'\np658\nsg39\nS\'\'\nsg40\ng26\nsssS\'DummyOM\'\np659\n(dp660\ng9\n(dp661\ng26\n(dp662\ng13\ng28\nsg29\nI01\nsssg33\n(dp663\ng35\n(lp664\nsg37\nS\'dummyom_dummyom\'\np665\nsg39\nS\'\'\nsg40\ng26\nsssS\'DummyOMSwitch\'\np666\n(dp667\ng9\n(dp668\nS\'nPorts\'\np669\n(dp670\ng13\ng110\nssS\'portList\'\np671\n(dp672\ng13\ng14\nsg15\nI1024\nssg650\n(dp673\ng13\ng59\nsg61\nS\'dummyom.DummyOM\'\np674\nssg26\n(dp675\ng13\ng28\nsg29\nI01\nssS\'dpid\'\np676\n(dp677\ng13\ng14\nsg15\nI100\nsssg33\n(dp678\ng35\n(lp679\nsg37\nS\'dummyom_dummyomswitch\'\np680\nsg39\nS\'\'\nsg40\ng26\nsssS\'DummyOMSlice\'\np681\n(dp682\ng9\n(dp683\ng650\n(dp684\ng13\ng59\nsg61\nS\'dummyom.DummyOM\'\np685\nssS\'project_description\'\np686\n(dp687\ng13\ng262\nssS\'controller_url\'\np688\n(dp689\ng13\ng14\nsg15\nI200\nssS\'slice_id\'\np690\n(dp691\ng13\ng14\nsg15\nI200\nssS\'slice_name\'\np692\n(dp693\ng13\ng14\nsg15\nI200\nssS\'owner_email\'\np694\n(dp695\ng13\ng14\nsg15\nI200\nssS\'project_name\'\np696\n(dp697\ng13\ng14\nsg15\nI200\nssS\'switch_slivers\'\np698\n(dp699\ng13\ng262\nssS\'slice_description\'\np700\n(dp701\ng13\ng262\nssg26\n(dp702\ng13\ng28\nsg29\nI01\nssS\'owner_password\'\np703\n(dp704\ng13\ng14\nsg15\nI200\nsssg33\n(dp705\ng35\n(lp706\nsg37\nS\'dummyom_dummyomslice\'\np707\nsg39\nS\'\'\nsg40\ng26\nsssS\'DummyOMLink\'\np708\n(dp709\ng9\n(dp710\ng650\n(dp711\ng13\ng59\nsg61\nS\'dummyom.DummyOM\'\np712\nssS\'src_port\'\np713\n(dp714\ng13\ng110\nssS\'dst_port\'\np715\n(dp716\ng13\ng110\nssS\'src_dpid\'\np717\n(dp718\ng13\ng14\nsg15\nI100\nssg26\n(dp719\ng13\ng28\nsg29\nI01\nssS\'dst_dpid\'\np720\n(dp721\ng13\ng14\nsg15\nI100\nsssg33\n(dp722\ng35\n(lp723\nsg37\nS\'dummyom_dummyomlink\'\np724\nsg39\nS\'\'\nsg40\ng26\nssstRp725\n(dp726\ng43\n(lp727\ng659\nag708\nag666\nag681\nag645\nasbsS\'roles\'\np728\ng3\n(g4\ng5\n(dp729\nS\'ProjectRole\'\np730\n(dp731\ng9\n(dp732\ng215\n(dp733\ng13\ng262\nssg562\n(dp734\ng13\ng181\nsg61\nS\'permissions.Permittee\'\np735\nssS\'obj_permissions\'\np736\n(dp737\ng13\ng181\nsg61\nS\'permissions.ObjectPermission\'\np738\nssg270\n(dp739\ng13\ng59\nsg61\nS\'project.Project\'\np740\nssg26\n(dp741\ng13\ng28\nsg29\nI01\nssg78\n(dp742\ng13\ng14\nsg15\nI100\nsssg33\n(dp743\ng35\n((S\'name\'\nS\'project\'\nttp744\nsg37\nS\'roles_projectrole\'\np745\nsg39\nS\'\'\nsg40\ng26\nsssS\'ProjectRoleRequest\'\np746\n(dp747\ng9\n(dp748\nS\'requested_role\'\np749\n(dp750\ng13\ng59\nsg61\nS\'roles.ProjectRole\'\np751\nssg464\n(dp752\ng13\ng262\nssg26\n(dp753\ng13\ng28\nsg29\nI01\nssS\'giver\'\np754\n(dp755\ng13\ng59\nsg61\nS\'auth.User\'\np756\nssS\'requester\'\np757\n(dp758\ng13\ng59\nsg61\nS\'auth.User\'\np759\nsssg33\n(dp760\ng35\n(lp761\nsg37\nS\'roles_projectrolerequest\'\np762\nsg39\nS\'\'\nsg40\ng26\nssstRp763\n(dp764\ng43\n(lp765\ng730\nag746\nasbsS\'plugin\'\np766\ng3\n(g4\ng5\n(dp767\nS\'OpenFlowAggregate\'\np768\n(dp769\ng9\n(dp770\nS\'usage_agreement\'\np771\n(dp772\ng13\ng262\nssg128\n(dp773\ng13\ng130\nsg60\nI01\nsg61\nS\'xmlrpc_serverproxy.PasswordXMLRPCServerProxy\'\np774\nssS\'aggregate_ptr\'\np775\n(dp776\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'aggregate.Aggregate\'\np777\nsssg33\n(dp778\ng35\n(lp779\nsg37\nS\'plugin_openflowaggregate\'\np780\nsg39\nS\'\'\nsg40\nS\'aggregate_ptr_id\'\np781\nsssS\'OpenFlowInterface\'\np782\n(dp783\ng9\n(dp784\nS\'ingress_neighbors\'\np785\n(dp786\ng13\ng181\nsg61\nS\'plugin.OpenFlowInterface\'\np787\nssS\'switch\'\np788\n(dp789\ng13\ng59\nsg61\nS\'plugin.OpenFlowSwitch\'\np790\nssS\'resource_ptr\'\np791\n(dp792\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'resources.Resource\'\np793\nssS\'port_num\'\np794\n(dp795\ng13\ng110\nssS\'slug\'\np796\n(dp797\ng13\ncautoslug.fields\nAutoSlugField\np798\nsg15\nI50\nsS\'db_index\'\np799\nI01\nsssg33\n(dp800\ng35\n((S\'switch\'\nS\'port_num\'\nttp801\nsg37\nS\'plugin_openflowinterface\'\np802\nsg39\nS\'\'\nsg40\nS\'resource_ptr_id\'\np803\nsssS\'FlowSpaceRule\'\np804\n(dp805\ng9\n(dp806\nS\'vlan_id_end\'\np807\n(dp808\ng13\ncexpedient.common.utils.modelfields\nLimitedIntegerField\np809\nsg77\nI01\nssS\'tp_dst_start\'\np810\n(dp811\ng13\ng809\nsg77\nI01\nssS\'nw_dst_start\'\np812\n(dp813\ng15\nI15\nsg13\ng76\nsg77\nI01\nssS\'dl_src_end\'\np814\n(dp815\ng15\nI17\nsg13\ncexpedient.common.utils.modelfields\nMACAddressField\np816\nsg77\nI01\nssS\'dl_dst_end\'\np817\n(dp818\ng15\nI17\nsg13\ng816\nsg77\nI01\nssS\'tp_dst_end\'\np819\n(dp820\ng13\ng809\nsg77\nI01\nssS\'nw_src_end\'\np821\n(dp822\ng15\nI15\nsg13\ng76\nsg77\nI01\nssS\'dl_type_start\'\np823\n(dp824\ng13\ng809\nsg77\nI01\nssS\'nw_proto_end\'\np825\n(dp826\ng13\ng809\nsg77\nI01\nssS\'dl_dst_start\'\np827\n(dp828\ng15\nI17\nsg13\ng816\nsg77\nI01\nssS\'tp_src_start\'\np829\n(dp830\ng13\ng809\nsg77\nI01\nssg26\n(dp831\ng13\ng28\nsg29\nI01\nssS\'dl_type_end\'\np832\n(dp833\ng13\ng809\nsg77\nI01\nssS\'nw_proto_start\'\np834\n(dp835\ng13\ng809\nsg77\nI01\nssS\'nw_src_start\'\np836\n(dp837\ng15\nI15\nsg13\ng76\nsg77\nI01\nssS\'nw_dst_end\'\np838\n(dp839\ng15\nI15\nsg13\ng76\nsg77\nI01\nssS\'dl_src_start\'\np840\n(dp841\ng15\nI17\nsg13\ng816\nsg77\nI01\nssS\'tp_src_end\'\np842\n(dp843\ng13\ng809\nsg77\nI01\nssS\'vlan_id_start\'\np844\n(dp845\ng13\ng809\nsg77\nI01\nssS\'slivers\'\np846\n(dp847\ng13\ng181\nsg61\nS\'plugin.OpenFlowInterfaceSliver\'\np848\nsssg33\n(dp849\ng35\n(lp850\nsg37\nS\'plugin_flowspacerule\'\np851\nsg39\nS\'\'\nsg40\ng26\nsssS\'OpenFlowInterfaceSliver\'\np852\n(dp853\ng9\n(dp854\nS\'sliver_ptr\'\np855\n(dp856\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'resources.Sliver\'\np857\nsssg33\n(dp858\ng35\n(lp859\nsg37\nS\'plugin_openflowinterfacesliver\'\np860\nsg39\nS\'\'\nsg40\nS\'sliver_ptr_id\'\np861\nsssS\'OpenFlowConnection\'\np862\n(dp863\ng9\n(dp864\nS\'dst_iface\'\np865\n(dp866\ng13\ng59\nsg61\nS\'plugin.OpenFlowInterface\'\np867\nssS\'src_iface\'\np868\n(dp869\ng13\ng59\nsg61\nS\'plugin.OpenFlowInterface\'\np870\nssg26\n(dp871\ng13\ng28\nsg29\nI01\nssg796\n(dp872\ng13\ng798\nsg15\nI50\nsg799\nI01\nsssg33\n(dp873\ng35\n((S\'src_iface\'\nS\'dst_iface\'\nttp874\nsg37\nS\'plugin_openflowconnection\'\np875\nsg39\nS\'\'\nsg40\ng26\nsssS\'OpenFlowSliceInfo\'\np876\n(dp877\ng9\n(dp878\ng24\n(dp879\ng13\ng14\nsg15\nI64\nssg364\n(dp880\ng13\ng130\nsg60\nI01\nsg61\nS\'slice.Slice\'\np881\nssg688\n(dp882\ng13\ng14\nsg15\nI100\nssg26\n(dp883\ng13\ng28\nsg29\nI01\nsssg33\n(dp884\ng35\n(lp885\nsg37\nS\'plugin_openflowsliceinfo\'\np886\nsg39\nS\'\'\nsg40\ng26\nsssS\'OpenFlowSwitch\'\np887\n(dp888\ng9\n(dp889\nS\'resource_ptr\'\np890\n(dp891\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'resources.Resource\'\np892\nssS\'datapath_id\'\np893\n(dp894\ng15\nI100\nsg13\ng14\nsg60\nI01\nsssg33\n(dp895\ng35\n(lp896\nsg37\nS\'plugin_openflowswitch\'\np897\nsg39\nS\'\'\nsg40\nS\'resource_ptr_id\'\np898\nsssS\'NonOpenFlowConnection\'\np899\n(dp900\ng9\n(dp901\nS\'of_iface\'\np902\n(dp903\ng13\ng59\nsg61\nS\'plugin.OpenFlowInterface\'\np904\nssg368\n(dp905\ng13\ng59\nsg61\nS\'resources.Resource\'\np906\nssg26\n(dp907\ng13\ng28\nsg29\nI01\nsssg33\n(dp908\ng35\n((S\'of_iface\'\nS\'resource\'\nttp909\nsg37\nS\'plugin_nonopenflowconnection\'\np910\nsg39\nS\'\'\nsg40\ng26\nssstRp911\n(dp912\ng43\n(lp913\ng876\nag768\nag887\nag862\nag899\nag782\nag852\nag804\nasbsS\'admin\'\np914\ng3\n(g4\ng5\n(dp915\nS\'LogEntry\'\np916\n(dp917\ng9\n(dp918\nS\'action_flag\'\np919\n(dp920\ng13\ncdjango.db.models.fields\nPositiveSmallIntegerField\np921\nssS\'action_time\'\np922\n(dp923\ng13\ng20\nssS\'object_repr\'\np924\n(dp925\ng13\ng14\nsg15\nI200\nssg569\n(dp926\ng13\ng262\nsg77\nI01\nssS\'change_message\'\np927\n(dp928\ng13\ng262\nssg57\n(dp929\ng13\ng59\nsg61\nS\'auth.User\'\np930\nssg521\n(dp931\ng13\ng59\nsg77\nI01\nsg61\nS\'contenttypes.ContentType\'\np932\nssg26\n(dp933\ng13\ng28\nsg29\nI01\nsssg33\n(dp934\ng35\n(lp935\nsg37\nS\'django_admin_log\'\np936\nsg39\nS\'\'\nsg40\ng26\nssstRp937\n(dp938\ng43\n(lp939\ng916\nasbsS\'expedient_geni\'\np940\ng3\n(g4\ng5\n(dp941\nS\'GENIAggregate\'\np942\n(dp943\ng9\n(dp944\ng16\n(dp945\ng13\ng14\nsg15\nI200\nssS\'aggregate_ptr\'\np946\n(dp947\ng13\ng130\nsg60\nI01\nsg29\nI01\nsg61\nS\'aggregate.Aggregate\'\np948\nsssg33\n(dp949\ng35\n(lp950\nsg37\nS\'expedient_geni_geniaggregate\'\np951\nsg39\nS\'\'\nsg40\nS\'aggregate_ptr_id\'\np952\nsssS\'GENISliceInfo\'\np953\n(dp954\ng9\n(dp955\ng364\n(dp956\ng13\ng130\nsg60\nI01\nsg61\nS\'slice.Slice\'\np957\nssS\'slice_urn\'\np958\n(dp959\ng13\ng14\nsg15\nI256\nssS\'ssh_public_key\'\np960\n(dp961\ng13\ng262\nsg77\nI01\nssS\'ssh_private_key\'\np962\n(dp963\ng13\ng262\nsg77\nI01\nssS\'slice_gid\'\np964\n(dp965\ng13\ng262\nssg26\n(dp966\ng13\ng28\nsg29\nI01\nsssg33\n(dp967\ng35\n(lp968\nsg37\nS\'expedient_geni_genisliceinfo\'\np969\nsg39\nS\'\'\nsg40\ng26\nssstRp970\n(dp971\ng43\n(lp972\ng953\nag942\nasbsS\'timer\'\np973\ng3\n(g4\ng5\n(dp974\nS\'Job\'\np975\n(dp976\ng9\n(dp977\nS\'next_run_time\'\np978\n(dp979\ng13\ng20\nssS\'callable_name\'\np980\n(dp981\ng15\nI255\nsg13\ng14\nsg60\nI01\nssg26\n(dp982\ng13\ng28\nsg29\nI01\nssS\'period\'\np983\n(dp984\ng13\ncdjango.db.models.fields\nBigIntegerField\np985\nsssg33\n(dp986\ng35\n(lp987\nsg37\nS\'timer_job\'\np988\nsg39\nS\'\'\nsg40\ng26\nssstRp989\n(dp990\ng43\n(lp991\ng975\nasbsS\'firstapp\'\np992\ng3\n(g4\ng5\n(dtRp993\n(dp994\ng43\n(lp995\nsbsS\'project\'\np996\ng3\n(g4\ng5\n(dp997\nS\'Project\'\np998\n(dp999\ng9\n(dp1000\ng192\n(dp1001\ng15\nI200\nsg13\ng14\nsg60\nI01\nssg215\n(dp1002\ng13\ng262\nssg26\n(dp1003\ng13\ng28\nsg29\nI01\nssg78\n(dp1004\ng15\nI200\nsg13\ng14\nsg60\nI01\nsssg33\n(dp1005\ng35\n(lp1006\nsg37\nS\'project_project\'\np1007\nsg39\nS\'\'\nsg40\ng26\nssstRp1008\n(dp1009\ng43\n(lp1010\ng998\nasbsS\'permissionmgmt\'\np1011\ng3\n(g4\ng5\n(dtRp1012\n(dp1013\ng43\n(lp1014\nsbsS\'django_evolution\'\np1015\ng3\n(g4\ng5\n(dp1016\nS\'Evolution\'\np1017\n(dp1018\ng9\n(dp1019\nS\'label\'\np1020\n(dp1021\ng13\ng14\nsg15\nI100\nssS\'version\'\np1022\n(dp1023\ng13\ng59\nsg61\nS\'django_evolution.Version\'\np1024\nssg26\n(dp1025\ng13\ng28\nsg29\nI01\nssg321\n(dp1026\ng13\ng14\nsg15\nI200\nsssg33\n(dp1027\ng35\n(lp1028\nsg37\nS\'django_evolution\'\np1029\nsg39\nS\'\'\nsg40\ng26\nsssS\'Version\'\np1030\n(dp1031\ng9\n(dp1032\nS\'when\'\np1033\n(dp1034\ng13\ng20\nssg26\n(dp1035\ng13\ng28\nsg29\nI01\nssS\'signature\'\np1036\n(dp1037\ng13\ng262\nsssg33\n(dp1038\ng35\n(lp1039\nsg37\nS\'django_project_version\'\np1040\nsg39\nS\'\'\nsg40\ng26\nssstRp1041\n(dp1042\ng43\n(lp1043\ng1030\nag1017\nasbsS\'messaging\'\np1044\ng3\n(g4\ng5\n(dp1045\nS\'DatedMessage\'\np1046\n(dp1047\ng9\n(dp1048\nS\'users\'\np1049\n(dp1050\ng13\ng181\nsg61\nS\'auth.User\'\np1051\nssS\'datetime\'\np1052\n(dp1053\ng13\ng20\nssS\'msg_text\'\np1054\n(dp1055\ng13\ng14\nsg15\nI200\nssg212\n(dp1056\ng13\ng14\nsg15\nI20\nssg26\n(dp1057\ng13\ng28\nsg29\nI01\nssS\'sender\'\np1058\n(dp1059\ng13\ng59\nsg77\nI01\nsg61\nS\'auth.User\'\np1060\nsssg33\n(dp1061\ng35\n(lp1062\nsg37\nS\'messaging_datedmessage\'\np1063\nsg39\nS\'\'\nsg40\ng26\nssstRp1064\n(dp1065\ng43\n(lp1066\ng1046\nasbs.','2011-07-12 05:19:27'); +/*!40000 ALTER TABLE `django_project_version` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `django_session` +-- + +DROP TABLE IF EXISTS `django_session`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `django_session` ( + `session_key` varchar(40) NOT NULL, + `session_data` longtext NOT NULL, + `expire_date` datetime NOT NULL, + PRIMARY KEY (`session_key`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `django_session` +-- + +LOCK TABLES `django_session` WRITE; +/*!40000 ALTER TABLE `django_session` DISABLE KEYS */; +INSERT INTO `django_session` VALUES ('5ec764ff188b2e30be25519f7d4d6077','gAJ9cQEoVQticmVhZGNydW1ic3ECXXEDVQp0ZXN0Y29va2llcQRVBndvcmtlZHEFdS4xMGNmYjYz\nNTliMjUzZWQyODdiNmU4Yzc1Zjc0M2YwMg==\n','2011-07-26 05:37:45'),('e1bcfffb2a96b16324adc250fadc9481','gAJ9cQEoVQticmVhZGNydW1ic3ECXXEDVQp0ZXN0Y29va2llcQRVBndvcmtlZHEFdS41ZjBkYWZk\nYTJkNWE4ZTY3NGZiMGEyNWMwNWFkOGM4Ng==\n','2011-07-27 00:28:42'); +/*!40000 ALTER TABLE `django_session` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `django_site` +-- + +DROP TABLE IF EXISTS `django_site`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `django_site` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `domain` varchar(100) NOT NULL, + `name` varchar(50) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `django_site` +-- + +LOCK TABLES `django_site` WRITE; +/*!40000 ALTER TABLE `django_site` DISABLE KEYS */; +INSERT INTO `django_site` VALUES (1,'192.168.254.193','Expedient Clearinghouse'); +/*!40000 ALTER TABLE `django_site` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `dummyom_dummycallbackproxy` +-- + +DROP TABLE IF EXISTS `dummyom_dummycallbackproxy`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `dummyom_dummycallbackproxy` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `url` varchar(200) NOT NULL, + `cookie` varchar(1024) NOT NULL, + `username` varchar(1024) NOT NULL, + `om_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `om_id` (`om_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `dummyom_dummycallbackproxy` +-- + +LOCK TABLES `dummyom_dummycallbackproxy` WRITE; +/*!40000 ALTER TABLE `dummyom_dummycallbackproxy` DISABLE KEYS */; +/*!40000 ALTER TABLE `dummyom_dummycallbackproxy` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `dummyom_dummyom` +-- + +DROP TABLE IF EXISTS `dummyom_dummyom`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `dummyom_dummyom` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `dummyom_dummyom` +-- + +LOCK TABLES `dummyom_dummyom` WRITE; +/*!40000 ALTER TABLE `dummyom_dummyom` DISABLE KEYS */; +/*!40000 ALTER TABLE `dummyom_dummyom` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `dummyom_dummyomlink` +-- + +DROP TABLE IF EXISTS `dummyom_dummyomlink`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `dummyom_dummyomlink` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `src_dpid` varchar(100) NOT NULL, + `src_port` int(11) NOT NULL, + `dst_dpid` varchar(100) NOT NULL, + `dst_port` int(11) NOT NULL, + `om_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + KEY `dummyom_dummyomlink_49d6206a` (`om_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `dummyom_dummyomlink` +-- + +LOCK TABLES `dummyom_dummyomlink` WRITE; +/*!40000 ALTER TABLE `dummyom_dummyomlink` DISABLE KEYS */; +/*!40000 ALTER TABLE `dummyom_dummyomlink` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `dummyom_dummyomslice` +-- + +DROP TABLE IF EXISTS `dummyom_dummyomslice`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `dummyom_dummyomslice` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `slice_id` varchar(200) NOT NULL, + `project_name` varchar(200) NOT NULL, + `project_description` longtext NOT NULL, + `slice_name` varchar(200) NOT NULL, + `slice_description` longtext NOT NULL, + `controller_url` varchar(200) NOT NULL, + `owner_email` varchar(200) NOT NULL, + `owner_password` varchar(200) NOT NULL, + `switch_slivers` longtext NOT NULL, + `om_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + KEY `dummyom_dummyomslice_49d6206a` (`om_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `dummyom_dummyomslice` +-- + +LOCK TABLES `dummyom_dummyomslice` WRITE; +/*!40000 ALTER TABLE `dummyom_dummyomslice` DISABLE KEYS */; +/*!40000 ALTER TABLE `dummyom_dummyomslice` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `dummyom_dummyomswitch` +-- + +DROP TABLE IF EXISTS `dummyom_dummyomswitch`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `dummyom_dummyomswitch` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `dpid` varchar(100) NOT NULL, + `om_id` int(11) NOT NULL, + `nPorts` int(11) NOT NULL, + `portList` varchar(1024) NOT NULL, + PRIMARY KEY (`id`), + KEY `dummyom_dummyomswitch_49d6206a` (`om_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `dummyom_dummyomswitch` +-- + +LOCK TABLES `dummyom_dummyomswitch` WRITE; +/*!40000 ALTER TABLE `dummyom_dummyomswitch` DISABLE KEYS */; +/*!40000 ALTER TABLE `dummyom_dummyomswitch` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `expedient_geni_geniaggregate` +-- + +DROP TABLE IF EXISTS `expedient_geni_geniaggregate`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `expedient_geni_geniaggregate` ( + `aggregate_ptr_id` int(11) NOT NULL, + `url` varchar(200) NOT NULL, + PRIMARY KEY (`aggregate_ptr_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `expedient_geni_geniaggregate` +-- + +LOCK TABLES `expedient_geni_geniaggregate` WRITE; +/*!40000 ALTER TABLE `expedient_geni_geniaggregate` DISABLE KEYS */; +/*!40000 ALTER TABLE `expedient_geni_geniaggregate` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `expedient_geni_genisliceinfo` +-- + +DROP TABLE IF EXISTS `expedient_geni_genisliceinfo`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `expedient_geni_genisliceinfo` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `slice_id` int(11) NOT NULL, + `slice_urn` varchar(256) NOT NULL, + `slice_gid` longtext NOT NULL, + `ssh_public_key` longtext, + `ssh_private_key` longtext, + PRIMARY KEY (`id`), + UNIQUE KEY `slice_id` (`slice_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `expedient_geni_genisliceinfo` +-- + +LOCK TABLES `expedient_geni_genisliceinfo` WRITE; +/*!40000 ALTER TABLE `expedient_geni_genisliceinfo` DISABLE KEYS */; +/*!40000 ALTER TABLE `expedient_geni_genisliceinfo` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `gopenflow_gcfopenflowaggregate` +-- + +DROP TABLE IF EXISTS `gopenflow_gcfopenflowaggregate`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `gopenflow_gcfopenflowaggregate` ( + `geniaggregate_ptr_id` int(11) NOT NULL, + PRIMARY KEY (`geniaggregate_ptr_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `gopenflow_gcfopenflowaggregate` +-- + +LOCK TABLES `gopenflow_gcfopenflowaggregate` WRITE; +/*!40000 ALTER TABLE `gopenflow_gcfopenflowaggregate` DISABLE KEYS */; +/*!40000 ALTER TABLE `gopenflow_gcfopenflowaggregate` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `messaging_datedmessage` +-- + +DROP TABLE IF EXISTS `messaging_datedmessage`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `messaging_datedmessage` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `type` varchar(20) NOT NULL, + `datetime` datetime NOT NULL, + `msg_text` varchar(200) NOT NULL, + `sender_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `messaging_datedmessage_6fe0a617` (`sender_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `messaging_datedmessage` +-- + +LOCK TABLES `messaging_datedmessage` WRITE; +/*!40000 ALTER TABLE `messaging_datedmessage` DISABLE KEYS */; +/*!40000 ALTER TABLE `messaging_datedmessage` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `messaging_datedmessage_users` +-- + +DROP TABLE IF EXISTS `messaging_datedmessage_users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `messaging_datedmessage_users` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `datedmessage_id` int(11) NOT NULL, + `user_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `datedmessage_id` (`datedmessage_id`,`user_id`), + KEY `messaging_datedmessage_users_3521100b` (`datedmessage_id`), + KEY `messaging_datedmessage_users_403f60f` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `messaging_datedmessage_users` +-- + +LOCK TABLES `messaging_datedmessage_users` WRITE; +/*!40000 ALTER TABLE `messaging_datedmessage_users` DISABLE KEYS */; +/*!40000 ALTER TABLE `messaging_datedmessage_users` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `permissions_expedientpermission` +-- + +DROP TABLE IF EXISTS `permissions_expedientpermission`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `permissions_expedientpermission` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `description` longtext NOT NULL, + `view` varchar(300) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM AUTO_INCREMENT=22 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `permissions_expedientpermission` +-- + +LOCK TABLES `permissions_expedientpermission` WRITE; +/*!40000 ALTER TABLE `permissions_expedientpermission` DISABLE KEYS */; +INSERT INTO `permissions_expedientpermission` VALUES (1,'can_add_aggregate','Owners of this permission can add aggregates to Expedient.','expedient.clearinghouse.permissionmgmt.utils.request_permission_wrapper'),(2,'can_edit_aggregate','Owners of this permission can edit or delete the related aggregates in Expedient.','expedient.clearinghouse.permissionmgmt.utils.request_permission_wrapper'),(3,'can_use_aggregate','Projects, slices, and users that are owners of this permission can use the aggregate by starting or stopping slices on it, and by calling other methods.','expedient.clearinghouse.aggregate.views.get_can_use_permission'),(4,'can_create_project','Owners of this permission can create projects in Expedient.','expedient.clearinghouse.permissionmgmt.utils.request_permission_wrapper'),(5,'can_edit_project','Owners of this permission can edit basic project properties.','expedient.clearinghouse.roles.views.make_request'),(6,'can_delete_project','Owners of this permission can edit basic project properties.','expedient.clearinghouse.roles.views.make_request'),(7,'can_view_project','Owners of this permission can view the project. Without other permissions, they are non-functional members.','expedient.clearinghouse.roles.views.make_request'),(8,'can_add_members','Owners of this permission can add members to the project and assign to them roles.','expedient.clearinghouse.roles.views.make_request'),(9,'can_remove_members','Owners of this permission can remove members from the project. They can also remove permissions from roles and remove roles from users.','expedient.clearinghouse.roles.views.make_request'),(10,'can_create_slices','Owners of this permission can create new slices.','expedient.clearinghouse.roles.views.make_request'),(11,'can_edit_slices','Owners of this permission can modify existing slices.','expedient.clearinghouse.roles.views.make_request'),(12,'can_delete_slices','Owners of this permission can delete existing slices.','expedient.clearinghouse.roles.views.make_request'),(13,'can_stop_slices','Owners of this permission can start slices.','expedient.clearinghouse.roles.views.make_request'),(14,'can_start_slices','Owners of this permission can stop slices.','expedient.clearinghouse.roles.views.make_request'),(15,'can_add_aggregates','Owners of this permission can add aggregates to the project.','expedient.clearinghouse.roles.views.make_request'),(16,'can_remove_aggregates','Owners of this permission can remove aggregates from the project.','expedient.clearinghouse.roles.views.make_request'),(17,'can_create_roles','Owners of this permission can create roles in the project','expedient.clearinghouse.roles.views.make_request'),(18,'can_edit_roles','Owners of this permission can modify and delete roles in the project','expedient.clearinghouse.roles.views.make_request'),(19,'can_edit_user','Owners of this permission can modify information about or delete a particular user.','expedient.clearinghouse.permissionmgmt.utils.request_permission_wrapper'),(20,'can_manage_users','Owners of this permission can view/modify/delete users in the user management page.','expedient.clearinghouse.permissionmgmt.utils.request_permission_wrapper'),(21,'can_change_user_cert','Owners of this permission can view/modify users\' GCFcertificates.','expedient.clearinghouse.permissionmgmt.utils.request_permission_wrapper'); +/*!40000 ALTER TABLE `permissions_expedientpermission` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `permissions_objectpermission` +-- + +DROP TABLE IF EXISTS `permissions_objectpermission`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `permissions_objectpermission` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `permission_id` int(11) NOT NULL, + `object_type_id` int(11) NOT NULL, + `object_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `permission_id` (`permission_id`,`object_type_id`,`object_id`), + KEY `permissions_objectpermission_1e014c8f` (`permission_id`), + KEY `permissions_objectpermission_518e5aa5` (`object_type_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `permissions_objectpermission` +-- + +LOCK TABLES `permissions_objectpermission` WRITE; +/*!40000 ALTER TABLE `permissions_objectpermission` DISABLE KEYS */; +/*!40000 ALTER TABLE `permissions_objectpermission` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `permissions_permissionownership` +-- + +DROP TABLE IF EXISTS `permissions_permissionownership`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `permissions_permissionownership` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `obj_permission_id` int(11) NOT NULL, + `permittee_id` int(11) NOT NULL, + `can_delegate` tinyint(1) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `obj_permission_id` (`obj_permission_id`,`permittee_id`), + KEY `permissions_permissionownership_e1137c7` (`obj_permission_id`), + KEY `permissions_permissionownership_16c2d25c` (`permittee_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `permissions_permissionownership` +-- + +LOCK TABLES `permissions_permissionownership` WRITE; +/*!40000 ALTER TABLE `permissions_permissionownership` DISABLE KEYS */; +/*!40000 ALTER TABLE `permissions_permissionownership` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `permissions_permissionrequest` +-- + +DROP TABLE IF EXISTS `permissions_permissionrequest`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `permissions_permissionrequest` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `requesting_user_id` int(11) NOT NULL, + `permittee_id` int(11) NOT NULL, + `permission_owner_id` int(11) NOT NULL, + `requested_permission_id` int(11) NOT NULL, + `message` longtext NOT NULL, + PRIMARY KEY (`id`), + KEY `permissions_permissionrequest_30df5c86` (`requesting_user_id`), + KEY `permissions_permissionrequest_16c2d25c` (`permittee_id`), + KEY `permissions_permissionrequest_f0c1d79` (`permission_owner_id`), + KEY `permissions_permissionrequest_489888a2` (`requested_permission_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `permissions_permissionrequest` +-- + +LOCK TABLES `permissions_permissionrequest` WRITE; +/*!40000 ALTER TABLE `permissions_permissionrequest` DISABLE KEYS */; +/*!40000 ALTER TABLE `permissions_permissionrequest` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `permissions_permittee` +-- + +DROP TABLE IF EXISTS `permissions_permittee`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `permissions_permittee` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `object_type_id` int(11) NOT NULL, + `object_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `object_type_id` (`object_type_id`,`object_id`), + KEY `permissions_permittee_518e5aa5` (`object_type_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `permissions_permittee` +-- + +LOCK TABLES `permissions_permittee` WRITE; +/*!40000 ALTER TABLE `permissions_permittee` DISABLE KEYS */; +/*!40000 ALTER TABLE `permissions_permittee` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `planetlab_planetlabaggregate` +-- + +DROP TABLE IF EXISTS `planetlab_planetlabaggregate`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `planetlab_planetlabaggregate` ( + `geniaggregate_ptr_id` int(11) NOT NULL, + `rspec` longtext NOT NULL, + PRIMARY KEY (`geniaggregate_ptr_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `planetlab_planetlabaggregate` +-- + +LOCK TABLES `planetlab_planetlabaggregate` WRITE; +/*!40000 ALTER TABLE `planetlab_planetlabaggregate` DISABLE KEYS */; +/*!40000 ALTER TABLE `planetlab_planetlabaggregate` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `planetlab_planetlabnode` +-- + +DROP TABLE IF EXISTS `planetlab_planetlabnode`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `planetlab_planetlabnode` ( + `resource_ptr_id` int(11) NOT NULL, + `node_id` varchar(256) NOT NULL, + PRIMARY KEY (`resource_ptr_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `planetlab_planetlabnode` +-- + +LOCK TABLES `planetlab_planetlabnode` WRITE; +/*!40000 ALTER TABLE `planetlab_planetlabnode` DISABLE KEYS */; +/*!40000 ALTER TABLE `planetlab_planetlabnode` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `planetlab_planetlabsliver` +-- + +DROP TABLE IF EXISTS `planetlab_planetlabsliver`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `planetlab_planetlabsliver` ( + `sliver_ptr_id` int(11) NOT NULL, + PRIMARY KEY (`sliver_ptr_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `planetlab_planetlabsliver` +-- + +LOCK TABLES `planetlab_planetlabsliver` WRITE; +/*!40000 ALTER TABLE `planetlab_planetlabsliver` DISABLE KEYS */; +/*!40000 ALTER TABLE `planetlab_planetlabsliver` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin_flowspacerule` +-- + +DROP TABLE IF EXISTS `plugin_flowspacerule`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin_flowspacerule` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `dl_src_start` varchar(17) DEFAULT NULL, + `dl_dst_start` varchar(17) DEFAULT NULL, + `dl_type_start` int(11) DEFAULT NULL, + `vlan_id_start` int(11) DEFAULT NULL, + `nw_src_start` char(15) DEFAULT NULL, + `nw_dst_start` char(15) DEFAULT NULL, + `nw_proto_start` int(11) DEFAULT NULL, + `tp_src_start` int(11) DEFAULT NULL, + `tp_dst_start` int(11) DEFAULT NULL, + `dl_src_end` varchar(17) DEFAULT NULL, + `dl_dst_end` varchar(17) DEFAULT NULL, + `dl_type_end` int(11) DEFAULT NULL, + `vlan_id_end` int(11) DEFAULT NULL, + `nw_src_end` char(15) DEFAULT NULL, + `nw_dst_end` char(15) DEFAULT NULL, + `nw_proto_end` int(11) DEFAULT NULL, + `tp_src_end` int(11) DEFAULT NULL, + `tp_dst_end` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin_flowspacerule` +-- + +LOCK TABLES `plugin_flowspacerule` WRITE; +/*!40000 ALTER TABLE `plugin_flowspacerule` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin_flowspacerule` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin_flowspacerule_slivers` +-- + +DROP TABLE IF EXISTS `plugin_flowspacerule_slivers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin_flowspacerule_slivers` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `flowspacerule_id` int(11) NOT NULL, + `openflowinterfacesliver_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `flowspacerule_id` (`flowspacerule_id`,`openflowinterfacesliver_id`), + KEY `plugin_flowspacerule_slivers_518e4283` (`flowspacerule_id`), + KEY `plugin_flowspacerule_slivers_5ffa5e59` (`openflowinterfacesliver_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin_flowspacerule_slivers` +-- + +LOCK TABLES `plugin_flowspacerule_slivers` WRITE; +/*!40000 ALTER TABLE `plugin_flowspacerule_slivers` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin_flowspacerule_slivers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin_nonopenflowconnection` +-- + +DROP TABLE IF EXISTS `plugin_nonopenflowconnection`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin_nonopenflowconnection` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `of_iface_id` int(11) NOT NULL, + `resource_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `of_iface_id` (`of_iface_id`,`resource_id`), + KEY `plugin_nonopenflowconnection_3e3eb0e4` (`of_iface_id`), + KEY `plugin_nonopenflowconnection_31b73438` (`resource_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin_nonopenflowconnection` +-- + +LOCK TABLES `plugin_nonopenflowconnection` WRITE; +/*!40000 ALTER TABLE `plugin_nonopenflowconnection` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin_nonopenflowconnection` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin_openflowaggregate` +-- + +DROP TABLE IF EXISTS `plugin_openflowaggregate`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin_openflowaggregate` ( + `aggregate_ptr_id` int(11) NOT NULL, + `client_id` int(11) NOT NULL, + `usage_agreement` longtext NOT NULL, + PRIMARY KEY (`aggregate_ptr_id`), + UNIQUE KEY `client_id` (`client_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin_openflowaggregate` +-- + +LOCK TABLES `plugin_openflowaggregate` WRITE; +/*!40000 ALTER TABLE `plugin_openflowaggregate` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin_openflowaggregate` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin_openflowconnection` +-- + +DROP TABLE IF EXISTS `plugin_openflowconnection`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin_openflowconnection` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `src_iface_id` int(11) NOT NULL, + `dst_iface_id` int(11) NOT NULL, + `slug` varchar(50) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `src_iface_id` (`src_iface_id`,`dst_iface_id`), + KEY `plugin_openflowconnection_7a8c6e4c` (`src_iface_id`), + KEY `plugin_openflowconnection_11d6f43d` (`dst_iface_id`), + KEY `plugin_openflowconnection_56ae2a2a` (`slug`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin_openflowconnection` +-- + +LOCK TABLES `plugin_openflowconnection` WRITE; +/*!40000 ALTER TABLE `plugin_openflowconnection` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin_openflowconnection` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin_openflowinterface` +-- + +DROP TABLE IF EXISTS `plugin_openflowinterface`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin_openflowinterface` ( + `resource_ptr_id` int(11) NOT NULL, + `port_num` int(11) NOT NULL, + `switch_id` int(11) NOT NULL, + `slug` varchar(50) NOT NULL, + PRIMARY KEY (`resource_ptr_id`), + UNIQUE KEY `switch_id` (`switch_id`,`port_num`), + KEY `plugin_openflowinterface_394cae66` (`switch_id`), + KEY `plugin_openflowinterface_56ae2a2a` (`slug`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin_openflowinterface` +-- + +LOCK TABLES `plugin_openflowinterface` WRITE; +/*!40000 ALTER TABLE `plugin_openflowinterface` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin_openflowinterface` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin_openflowinterfacesliver` +-- + +DROP TABLE IF EXISTS `plugin_openflowinterfacesliver`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin_openflowinterfacesliver` ( + `sliver_ptr_id` int(11) NOT NULL, + PRIMARY KEY (`sliver_ptr_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin_openflowinterfacesliver` +-- + +LOCK TABLES `plugin_openflowinterfacesliver` WRITE; +/*!40000 ALTER TABLE `plugin_openflowinterfacesliver` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin_openflowinterfacesliver` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin_openflowsliceinfo` +-- + +DROP TABLE IF EXISTS `plugin_openflowsliceinfo`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin_openflowsliceinfo` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `slice_id` int(11) NOT NULL, + `controller_url` varchar(100) NOT NULL, + `password` varchar(64) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `slice_id` (`slice_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin_openflowsliceinfo` +-- + +LOCK TABLES `plugin_openflowsliceinfo` WRITE; +/*!40000 ALTER TABLE `plugin_openflowsliceinfo` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin_openflowsliceinfo` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `plugin_openflowswitch` +-- + +DROP TABLE IF EXISTS `plugin_openflowswitch`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `plugin_openflowswitch` ( + `resource_ptr_id` int(11) NOT NULL, + `datapath_id` varchar(100) NOT NULL, + PRIMARY KEY (`resource_ptr_id`), + UNIQUE KEY `datapath_id` (`datapath_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `plugin_openflowswitch` +-- + +LOCK TABLES `plugin_openflowswitch` WRITE; +/*!40000 ALTER TABLE `plugin_openflowswitch` DISABLE KEYS */; +/*!40000 ALTER TABLE `plugin_openflowswitch` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `project_project` +-- + +DROP TABLE IF EXISTS `project_project`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `project_project` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(200) NOT NULL, + `description` longtext NOT NULL, + `uuid` varchar(200) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`), + UNIQUE KEY `uuid` (`uuid`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `project_project` +-- + +LOCK TABLES `project_project` WRITE; +/*!40000 ALTER TABLE `project_project` DISABLE KEYS */; +/*!40000 ALTER TABLE `project_project` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `registration_registrationprofile` +-- + +DROP TABLE IF EXISTS `registration_registrationprofile`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `registration_registrationprofile` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `activation_key` varchar(40) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `user_id` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `registration_registrationprofile` +-- + +LOCK TABLES `registration_registrationprofile` WRITE; +/*!40000 ALTER TABLE `registration_registrationprofile` DISABLE KEYS */; +/*!40000 ALTER TABLE `registration_registrationprofile` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `resources_resource` +-- + +DROP TABLE IF EXISTS `resources_resource`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `resources_resource` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `leaf_name` varchar(100) NOT NULL, + `module_name` varchar(100) NOT NULL, + `name` varchar(200) NOT NULL, + `available` tinyint(1) NOT NULL, + `status_change_timestamp` datetime NOT NULL, + `aggregate_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + KEY `resources_resource_6c483540` (`aggregate_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `resources_resource` +-- + +LOCK TABLES `resources_resource` WRITE; +/*!40000 ALTER TABLE `resources_resource` DISABLE KEYS */; +/*!40000 ALTER TABLE `resources_resource` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `resources_sliver` +-- + +DROP TABLE IF EXISTS `resources_sliver`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `resources_sliver` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `leaf_name` varchar(100) NOT NULL, + `module_name` varchar(100) NOT NULL, + `resource_id` int(11) NOT NULL, + `slice_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + KEY `resources_sliver_31b73438` (`resource_id`), + KEY `resources_sliver_4c5cd8ab` (`slice_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `resources_sliver` +-- + +LOCK TABLES `resources_sliver` WRITE; +/*!40000 ALTER TABLE `resources_sliver` DISABLE KEYS */; +/*!40000 ALTER TABLE `resources_sliver` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles_projectrole` +-- + +DROP TABLE IF EXISTS `roles_projectrole`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles_projectrole` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `description` longtext NOT NULL, + `project_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`,`project_id`), + KEY `roles_projectrole_499df97c` (`project_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles_projectrole` +-- + +LOCK TABLES `roles_projectrole` WRITE; +/*!40000 ALTER TABLE `roles_projectrole` DISABLE KEYS */; +/*!40000 ALTER TABLE `roles_projectrole` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles_projectrole_obj_permissions` +-- + +DROP TABLE IF EXISTS `roles_projectrole_obj_permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles_projectrole_obj_permissions` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `projectrole_id` int(11) NOT NULL, + `objectpermission_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `projectrole_id` (`projectrole_id`,`objectpermission_id`), + KEY `roles_projectrole_obj_permissions_63e1a684` (`projectrole_id`), + KEY `roles_projectrole_obj_permissions_63416acc` (`objectpermission_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles_projectrole_obj_permissions` +-- + +LOCK TABLES `roles_projectrole_obj_permissions` WRITE; +/*!40000 ALTER TABLE `roles_projectrole_obj_permissions` DISABLE KEYS */; +/*!40000 ALTER TABLE `roles_projectrole_obj_permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles_projectrole_permittees` +-- + +DROP TABLE IF EXISTS `roles_projectrole_permittees`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles_projectrole_permittees` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `projectrole_id` int(11) NOT NULL, + `permittee_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `projectrole_id` (`projectrole_id`,`permittee_id`), + KEY `roles_projectrole_permittees_63e1a684` (`projectrole_id`), + KEY `roles_projectrole_permittees_16c2d25c` (`permittee_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles_projectrole_permittees` +-- + +LOCK TABLES `roles_projectrole_permittees` WRITE; +/*!40000 ALTER TABLE `roles_projectrole_permittees` DISABLE KEYS */; +/*!40000 ALTER TABLE `roles_projectrole_permittees` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles_projectrolerequest` +-- + +DROP TABLE IF EXISTS `roles_projectrolerequest`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles_projectrolerequest` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `requester_id` int(11) NOT NULL, + `requested_role_id` int(11) NOT NULL, + `giver_id` int(11) NOT NULL, + `message` longtext NOT NULL, + PRIMARY KEY (`id`), + KEY `roles_projectrolerequest_47357461` (`requester_id`), + KEY `roles_projectrolerequest_20d91761` (`requested_role_id`), + KEY `roles_projectrolerequest_7ea775ce` (`giver_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles_projectrolerequest` +-- + +LOCK TABLES `roles_projectrolerequest` WRITE; +/*!40000 ALTER TABLE `roles_projectrolerequest` DISABLE KEYS */; +/*!40000 ALTER TABLE `roles_projectrolerequest` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `slice_slice` +-- + +DROP TABLE IF EXISTS `slice_slice`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `slice_slice` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(200) NOT NULL, + `description` longtext NOT NULL, + `project_id` int(11) NOT NULL, + `owner_id` int(11) NOT NULL, + `started` tinyint(1) NOT NULL, + `modified` tinyint(1) NOT NULL, + `uuid` varchar(200) NOT NULL, + `expiration_date` datetime NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`), + UNIQUE KEY `uuid` (`uuid`), + KEY `slice_slice_499df97c` (`project_id`), + KEY `slice_slice_5d52dd10` (`owner_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `slice_slice` +-- + +LOCK TABLES `slice_slice` WRITE; +/*!40000 ALTER TABLE `slice_slice` DISABLE KEYS */; +/*!40000 ALTER TABLE `slice_slice` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `timer_job` +-- + +DROP TABLE IF EXISTS `timer_job`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `timer_job` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `next_run_time` datetime NOT NULL, + `period` bigint(20) NOT NULL, + `callable_name` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `callable_name` (`callable_name`) +) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `timer_job` +-- + +LOCK TABLES `timer_job` WRITE; +/*!40000 ALTER TABLE `timer_job` DISABLE KEYS */; +INSERT INTO `timer_job` VALUES (1,'2011-07-12 06:19:39',3600,'expedient.clearinghouse.slice.models.stop_expired_slices'),(2,'2011-07-13 05:19:39',86400,'expedient.clearinghouse.slice.models.notify_slice_expirations'); +/*!40000 ALTER TABLE `timer_job` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `users_userprofile` +-- + +DROP TABLE IF EXISTS `users_userprofile`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `users_userprofile` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `affiliation` varchar(100) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `user_id` (`user_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `users_userprofile` +-- + +LOCK TABLES `users_userprofile` WRITE; +/*!40000 ALTER TABLE `users_userprofile` DISABLE KEYS */; +/*!40000 ALTER TABLE `users_userprofile` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_action` +-- + +DROP TABLE IF EXISTS `vt_plugin_action`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_action` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `hyperaction` varchar(16) NOT NULL, + `type` varchar(16) NOT NULL, + `uuid` varchar(512) NOT NULL, + `requestUser_id` int(11) DEFAULT NULL, + `status` varchar(16) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `vm_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `vt_plugin_action_17888761` (`requestUser_id`), + KEY `vt_plugin_action_50d39399` (`vm_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_action` +-- + +LOCK TABLES `vt_plugin_action` WRITE; +/*!40000 ALTER TABLE `vt_plugin_action` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_action` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_iface` +-- + +DROP TABLE IF EXISTS `vt_plugin_iface`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_iface` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(32) DEFAULT NULL, + `isMgmt` tinyint(1) NOT NULL, + `mac` varchar(17) DEFAULT NULL, + `ip` char(15) DEFAULT NULL, + `gw` char(15) DEFAULT NULL, + `mask` char(15) DEFAULT NULL, + `dns1` char(15) DEFAULT NULL, + `dns2` char(15) DEFAULT NULL, + `bridgeIface` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_iface` +-- + +LOCK TABLES `vt_plugin_iface` WRITE; +/*!40000 ALTER TABLE `vt_plugin_iface` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_iface` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_resourceshash` +-- + +DROP TABLE IF EXISTS `vt_plugin_resourceshash`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_resourceshash` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `hashValue` varchar(1024) NOT NULL, + `vtamID` int(11) NOT NULL, + `projectUUID` varchar(1024) NOT NULL, + `sliceUUID` varchar(1024) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_resourceshash` +-- + +LOCK TABLES `vt_plugin_resourceshash` WRITE; +/*!40000 ALTER TABLE `vt_plugin_resourceshash` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_resourceshash` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_vm` +-- + +DROP TABLE IF EXISTS `vt_plugin_vm`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_vm` ( + `resource_ptr_id` int(11) NOT NULL, + `uuid` varchar(1024) NOT NULL, + `memory` int(11) DEFAULT NULL, + `virtTech` varchar(10) NOT NULL, + `operatingSystemType` varchar(512) NOT NULL, + `operatingSystemVersion` varchar(512) NOT NULL, + `operatingSystemDistribution` varchar(512) NOT NULL, + `projectId` varchar(1024) NOT NULL, + `projectName` varchar(1024) NOT NULL, + `sliceId` varchar(1024) NOT NULL, + `sliceName` varchar(1024) NOT NULL, + `state` varchar(24) NOT NULL, + `serverID` varchar(1024) NOT NULL, + `hdSetupType` varchar(20) NOT NULL, + `hdOriginPath` varchar(1024) NOT NULL, + `virtualizationSetupType` varchar(20) NOT NULL, + `disc_image` varchar(20) NOT NULL, + PRIMARY KEY (`resource_ptr_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_vm` +-- + +LOCK TABLES `vt_plugin_vm` WRITE; +/*!40000 ALTER TABLE `vt_plugin_vm` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_vm` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_vm_ifaces` +-- + +DROP TABLE IF EXISTS `vt_plugin_vm_ifaces`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_vm_ifaces` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `vm_id` int(11) NOT NULL, + `iface_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `vm_id` (`vm_id`,`iface_id`), + KEY `vt_plugin_vm_ifaces_50d39399` (`vm_id`), + KEY `vt_plugin_vm_ifaces_35cd53ab` (`iface_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_vm_ifaces` +-- + +LOCK TABLES `vt_plugin_vm_ifaces` WRITE; +/*!40000 ALTER TABLE `vt_plugin_vm_ifaces` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_vm_ifaces` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_vtplugin` +-- + +DROP TABLE IF EXISTS `vt_plugin_vtplugin`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_vtplugin` ( + `aggregate_ptr_id` int(11) NOT NULL, + `client_id` int(11) DEFAULT NULL, + PRIMARY KEY (`aggregate_ptr_id`), + UNIQUE KEY `client_id` (`client_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_vtplugin` +-- + +LOCK TABLES `vt_plugin_vtplugin` WRITE; +/*!40000 ALTER TABLE `vt_plugin_vtplugin` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_vtplugin` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_vtserver` +-- + +DROP TABLE IF EXISTS `vt_plugin_vtserver`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_vtserver` ( + `resource_ptr_id` int(11) NOT NULL, + `uuid` varchar(1024) NOT NULL, + `memory` int(11) DEFAULT NULL, + `virtTech` varchar(1024) NOT NULL, + `freeDiscSpace` int(11) DEFAULT NULL, + `freeMemory` int(11) DEFAULT NULL, + `freeCpu` decimal(3,2) DEFAULT NULL, + `operatingSystemType` varchar(512) NOT NULL, + `operatingSystemDistribution` varchar(512) NOT NULL, + `operatingSystemVersion` varchar(512) NOT NULL, + `vmMgmtIface` varchar(1024) NOT NULL, + PRIMARY KEY (`resource_ptr_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_vtserver` +-- + +LOCK TABLES `vt_plugin_vtserver` WRITE; +/*!40000 ALTER TABLE `vt_plugin_vtserver` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_vtserver` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_vtserver_ifaces` +-- + +DROP TABLE IF EXISTS `vt_plugin_vtserver_ifaces`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_vtserver_ifaces` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `vtserver_id` int(11) NOT NULL, + `vtserveriface_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `vtserver_id` (`vtserver_id`,`vtserveriface_id`), + KEY `vt_plugin_vtserver_ifaces_90e8c61` (`vtserver_id`), + KEY `vt_plugin_vtserver_ifaces_2d7da24a` (`vtserveriface_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_vtserver_ifaces` +-- + +LOCK TABLES `vt_plugin_vtserver_ifaces` WRITE; +/*!40000 ALTER TABLE `vt_plugin_vtserver_ifaces` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_vtserver_ifaces` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_vtserver_vms` +-- + +DROP TABLE IF EXISTS `vt_plugin_vtserver_vms`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_vtserver_vms` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `vtserver_id` int(11) NOT NULL, + `vm_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `vtserver_id` (`vtserver_id`,`vm_id`), + KEY `vt_plugin_vtserver_vms_90e8c61` (`vtserver_id`), + KEY `vt_plugin_vtserver_vms_50d39399` (`vm_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_vtserver_vms` +-- + +LOCK TABLES `vt_plugin_vtserver_vms` WRITE; +/*!40000 ALTER TABLE `vt_plugin_vtserver_vms` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_vtserver_vms` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_vtserveriface` +-- + +DROP TABLE IF EXISTS `vt_plugin_vtserveriface`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_vtserveriface` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `ifaceName` varchar(128) DEFAULT NULL, + `switchID` varchar(128) DEFAULT NULL, + `port` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_vtserveriface` +-- + +LOCK TABLES `vt_plugin_vtserveriface` WRITE; +/*!40000 ALTER TABLE `vt_plugin_vtserveriface` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_vtserveriface` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vt_plugin_xmlrpcserverproxy` +-- + +DROP TABLE IF EXISTS `vt_plugin_xmlrpcserverproxy`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vt_plugin_xmlrpcserverproxy` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(100) NOT NULL, + `password` varchar(24) NOT NULL, + `url` varchar(1024) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vt_plugin_xmlrpcserverproxy` +-- + +LOCK TABLES `vt_plugin_xmlrpcserverproxy` WRITE; +/*!40000 ALTER TABLE `vt_plugin_xmlrpcserverproxy` DISABLE KEYS */; +/*!40000 ALTER TABLE `vt_plugin_xmlrpcserverproxy` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `xmlrpc_serverproxy_passwordxmlrpcserverproxy` +-- + +DROP TABLE IF EXISTS `xmlrpc_serverproxy_passwordxmlrpcserverproxy`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `xmlrpc_serverproxy_passwordxmlrpcserverproxy` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(100) NOT NULL, + `password` varchar(40) NOT NULL, + `max_password_age` int(10) unsigned NOT NULL, + `password_timestamp` datetime NOT NULL, + `url` varchar(1024) NOT NULL, + `verify_certs` tinyint(1) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `xmlrpc_serverproxy_passwordxmlrpcserverproxy` +-- + +LOCK TABLES `xmlrpc_serverproxy_passwordxmlrpcserverproxy` WRITE; +/*!40000 ALTER TABLE `xmlrpc_serverproxy_passwordxmlrpcserverproxy` DISABLE KEYS */; +/*!40000 ALTER TABLE `xmlrpc_serverproxy_passwordxmlrpcserverproxy` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2011-07-13 5:42:53 diff --git a/expedient/bin/versions/default/upgrade/tools/prova.cfg b/expedient/bin/versions/default/upgrade/tools/prova.cfg new file mode 100644 index 00000000..ffd948cc --- /dev/null +++ b/expedient/bin/versions/default/upgrade/tools/prova.cfg @@ -0,0 +1,6 @@ +[General] +port = "" +host = "" +password = expedient +user = expedient +database = expedient diff --git a/expedient/bin/versions/default/upgrade/tools/sqlDump.py b/expedient/bin/versions/default/upgrade/tools/sqlDump.py new file mode 100755 index 00000000..cf7bde24 --- /dev/null +++ b/expedient/bin/versions/default/upgrade/tools/sqlDump.py @@ -0,0 +1,65 @@ +import os +import sys +from os.path import dirname, join +from django.conf import * + +#configobj +try: + from configobj import ConfigObj +except: + #FIXME: ugly + os.system("apt-get update && apt-get install python-configobj -y") + from configobj import ConfigObj + + +PYTHON_DIR = join(dirname(__file__), '../../../../../src/python') + +# This is needed because wsgi disallows using stdout +sys.stdout = sys.stderr + +#os.environ['DJANGO_SETTINGS_MODULE'] = 'expedient.clearinghouse.settings' +os.environ['DJANGO_SETTINGS_MODULE'] = sys.argv[2] + +#sys.path.append(PYTHON_DIR) +sys.path.insert(0,PYTHON_DIR) + + +##Retrive Django settings +#print settings.DATABASE_NAME +#print settings.DATABASE_USER +#print settings.DATABASE_PASSWORD +#print settings.DATABASE_HOST +#print settings.DATABASE_PORT + +command="mysqldump --databases "+settings.DATABASE_NAME + +if settings.DATABASE_USER != "": + command+=" --user='"+settings.DATABASE_USER+"'" + +if settings.DATABASE_PASSWORD != "": + command+=" --password='"+settings.DATABASE_PASSWORD+"'" + +if settings.DATABASE_HOST != "": + command+=" --host="+settings.DATABASE_HOST +if settings.DATABASE_PORT != "": + command+=" --port="+settings.DATABASE_PORT + +command+=" > "+str(sys.argv[1]) + +#Store settings so that it is not messed up in the upgrade +cfg = ConfigObj(sys.argv[1]+'.cfg') + +generalSection = { + 'database': settings.DATABASE_NAME, + 'user':settings.DATABASE_USER, + 'password':settings.DATABASE_PASSWORD, + 'host':settings.DATABASE_HOST, + 'port':settings.DATABASE_PORT, +} + +cfg['General'] = generalSection +cfg.write() + +#Dump DB +print "Trying to dump DB using: "+command +sys.exit(os.system(command)) diff --git a/expedient/bin/versions/default/upgrade/tools/sqlRestore.py b/expedient/bin/versions/default/upgrade/tools/sqlRestore.py new file mode 100755 index 00000000..3097634e --- /dev/null +++ b/expedient/bin/versions/default/upgrade/tools/sqlRestore.py @@ -0,0 +1,54 @@ +import os +import sys +from os.path import dirname, join +from django.conf import * + +#configobj +try: + from configobj import ConfigObj +except: + #FIXME: ugly + os.system("apt-get update && apt-get install python-configobj -y") + from configobj import ConfigObj + +cfg = ConfigObj(sys.argv[1]+".cfg") + +section = cfg['General'] + +#Droping the database and recreating + +#Preparing command +command = "" +# User must be 'root' in order to successfully backup the database. +command_root = " --user='root' --password" + +if section["user"] != "": + command+=" --user='"+ section["user"]+"'" +if section["password"] != "": + command+=" --password='"+ section["password"]+"'" +if section["host"] != "": + command += " --host=" + section["host"] + command_root += " --host=" + section["host"] +if section["port"] != "": + command +=" --port=" + section["port"] + command_root +=" --port=" + section["port"] + +command += " " + section["database"] + " < " + sys.argv[1] +command_root += " " + section["database"] + " < " + sys.argv[1] + +if section["host"] == "": + host = "localhost" +else: + host = section["host"] + +# Island Manager will be prompted to enter the root's password for the backup +dropDB = "mysql -e \"drop database " + section["database"] + "; create database " + section["database"] + "; grant all on " + section["database"] + ".* to '" + section["user"] + "'@'" + host + "';\"" + command_root +print dropDB + +print "\nPlease input your MySQL root password in order to perform a backup of %s..." % str(section["database"]) +if os.system(dropDB)>0: + sys.exit(1) + +importDB = "mysql" + command + " < " + sys.argv[1] +print importDB +sys.exit(os.system(importDB)) diff --git a/expedient/bin/versions/version-checks b/expedient/bin/versions/version-checks new file mode 100644 index 00000000..315aa0be --- /dev/null +++ b/expedient/bin/versions/version-checks @@ -0,0 +1,57 @@ +#!/bin/bash + +### +# @author: msune, lbergesio +# @organization: i2CAT +# @project: Ofelia FP7 +# @description: Version checkings +### + +#print "General version checks!" + +MIN_ALLOWED_VERSION="0.14.2" + +if [[ $TARGETED_VERSION == *R* ]] && [ "$FORCE" == "0" ]; then + error "Cannot install Release/Release Candidates in production environments. Use force mode if you want to test them" $NO_RESCUE +fi + +#Check already installed +if [ -n "$CURRENT_VERSION" -a "$ACTION" == "install" ]; then + + if [ "$FORCE" == 0 ]; then + error "Cannot install; It appears that a copy of the version $CURRENT_VERSION is already installed in your system. Upgrade it or use force flag if you want to overwrite it..." $NO_RESCUE + else + confirm "It appears that a copy of the version $CURRENT_VERSION is already installed in your system. Are you sure you want to force install." $DONT_ABORT $NO_RESCUE + if [ $? == 1 ]; then + error "Aborted by the user" $NO_RESCUE + fi + fi + +fi +#Check upgrade +if [ "$ACTION" == "upgrade" ]; then + if [[ "$TARGETED_VERSION" == "$CURRENT_VERSION" ]]; then + if [ "$FORCE" == 0 ]; then + error "Cannot upgrade; targeted version is the same as current installed version ($CURRENT_VERSION). Use force if you want to override this..." $NO_RESCUE + else + confirm "Targeted version and current are the same one ($CURRENT_VERSION). Are you sure you want to force upgrade." $DONT_ABORT $NO_RESCUE + if [ $? == 1 ]; then + error "Aborted by the user" $NO_RESCUE + fi + fi + + fi +fi + +#Check upgrade from version previous to $MIN_ALLOWED_VERSION (0.14.2) +if [ "$CURRENT_VERSION" -a "$ACTION" == "upgrade" ]; then + + if [ "$FORCE" == 0 ]; then + + MIN_VERSION=$(echo -e "$CURRENT_VERSION\n$MIN_ALLOWED_VERSION" | sort -t '.' -g | head -n 1) + if [ ! "$MIN_VERSION" == "$MIN_ALLOWED_VERSION" ]; then + error "Cannot upgrade from installations previous to version $MIN_ALLOWED_VERSION; If you still want to do it under your own responsability use force flag..." $NO_RESCUE + fi + fi +fi + diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/__init__.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/__init__.py~ofelia.stable b/expedient/doc/plugins/samples/aggregate/sr_manager/src/__init__.py~ofelia.stable new file mode 100644 index 00000000..e69de29b diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/XmlRpcAPI.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/XmlRpcAPI.py new file mode 100644 index 00000000..36137099 --- /dev/null +++ b/expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/XmlRpcAPI.py @@ -0,0 +1,27 @@ +""" +Defines the dummy AM API. + +@date: Jun 12, 2013 +@author: CarolinaFernandez +""" + +from controller.ResourceController import ResourceController +import string + +class xmlrpc_wrappers: + """ + Allowed methods on the XMLRPC server + """ + + def __init__(self, callback_function = None): + self.callback_function = callback_function + + def get_resources(self): + return ResourceController.get_resources() + + def ping_auth(self, challenge, password): + return ResourceController.ping_auth(challenge, password) + + def ping(self, challenge): + return ResourceController.ping(challenge) + diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/XmlRpcServer.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/XmlRpcServer.py new file mode 100644 index 00000000..699ff77c --- /dev/null +++ b/expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/XmlRpcServer.py @@ -0,0 +1,142 @@ +""" +Implements the server functionality (connection, +authentication, etc). + +@date: Jun 12, 2013 +@author: Laszlo Nagy, msune, CarolinaFernandez +""" + +"""SecureXMLRPCServer.py - simple XML RPC server supporting SSL. + +Based on this article: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81549 + +For windows users: http://webcleaner.sourceforge.net/pyOpenSSL-0.6.win32-py2.4.exe + +Imported from http://code.activestate.com/recipes/496786-simple-xml-rpc-server-over-https/ +""" +import SocketServer +import BaseHTTPServer +import SimpleHTTPServer +import SimpleXMLRPCServer +import socket, os + +from communications import XmlRpcAPI +from OpenSSL import SSL +from utils.Logger import Logger + +from settings import XMLRPC_SERVER_USER, XMLRPC_SERVER_PASSWORD, \ + XMLRPC_SERVER_LISTEN_HOST,XMLRPC_SERVER_LISTEN_PORT, \ + XMLRPC_SERVER_KEYFILE,XMLRPC_SERVER_CERTFILE + + +class SecureXMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLRPCDispatcher): + def log_request(self, code='-', size='-'): + pass + + def __init__(self, server_address, HandlerClass, logRequests=False): + """Secure XML-RPC server. + + It it very similar to SimpleXMLRPCServer but it uses HTTPS for transporting XML data. + """ + self.logRequests = logRequests + + SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self) + SocketServer.BaseServer.__init__(self, server_address, HandlerClass) + ctx = SSL.Context(SSL.SSLv23_METHOD) + + ctx.use_privatekey_file (XMLRPC_SERVER_KEYFILE) + ctx.use_certificate_file(XMLRPC_SERVER_CERTFILE) + self.socket = SSL.Connection(ctx, socket.socket(self.address_family, + self.socket_type)) + self.server_bind() + self.server_activate() + +class SecureXMLRpcRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): + """Secure XML-RPC request handler class. + + It it very similar to SimpleXMLRPCRequestHandler but it uses HTTPS for transporting XML data. + """ + def setup(self): + self.connection = self.request + self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) + self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) + + ''' + Request Handler that verifies username and password passed to + XML RPC server in HTTP URL sent by client. + ''' + # this is the method we must override + def parse_request(self): + if SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.parse_request(self): + if self.authenticate(self.headers): + return True + else: + self.send_error(401, 'Authentication failed') + return False + + def authenticate(self, headers): + """ + Authenticates the headers against the credentials set in the + configuration file. This method overrides the one with the + same name in SimpleXMLRPCRequestHandler. + + @return whether authentication was successful or not + """ + try: + from base64 import b64decode + (basic, _, encoded) = headers.get('Authorization').partition(' ') + assert basic == 'Basic', 'Only basic authentication supported' + encodedByteString = encoded.encode() + decodedBytes = b64decode(encodedByteString) + decodedString = decodedBytes.decode() + (username, _, password) = decodedString.partition(':') + return (username == XMLRPC_SERVER_USER and password == XMLRPC_SERVER_PASSWORD) + except: + return False + + def do_POST(self): + """Handles the HTTPS POST request. + + It was copied out from SimpleXMLRPCServer.py and modified to shutdown the socket cleanly. + """ + + try: + # get arguments + data = self.rfile.read(int(self.headers["content-length"])) + # In previous versions of SimpleXMLRPCServer, _dispatch + # could be overridden in this class, instead of in + # SimpleXMLRPCDispatcher. To maintain backwards compatibility, + # check to see if a subclass implements _dispatch and dispatch + # using that method if present. + response = self.server._marshaled_dispatch( + data, getattr(self, '_dispatch', None) + ) + except: # This should only happen if the module is buggy + # internal error, report as HTTP server error + self.send_response(500) + self.end_headers() + else: + # got a valid XML RPC response + self.send_response(200) + self.send_header("Content-type", "text/xml") + self.send_header("Content-length", str(len(response))) + self.end_headers() + self.wfile.write(response) + + # shut down the connection + self.wfile.flush() + self.connection.shutdown() # Modified here! + +class XmlRpcServer(): + + logger = Logger.getLogger() + + @staticmethod + def createInstanceAndEngage(callBackFunction,HandlerClass = SecureXMLRpcRequestHandler,ServerClass = SecureXMLRPCServer): + server_address = (XMLRPC_SERVER_LISTEN_HOST, XMLRPC_SERVER_LISTEN_PORT) # (address, port) + server = ServerClass(server_address, HandlerClass) + server.register_instance(XmlRpcAPI.xmlrpc_wrappers(callBackFunction)) + sa = server.socket.getsockname() + XmlRpcServer.logger.debug("Serving HTTPS XMLRPC requests on "+str(sa[0])+":"+ str(sa[1])) + server.serve_forever() + diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/__init__.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/communications/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/controller/ResourceController.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/controller/ResourceController.py new file mode 100644 index 00000000..14f0b2c4 --- /dev/null +++ b/expedient/doc/plugins/samples/aggregate/sr_manager/src/controller/ResourceController.py @@ -0,0 +1,29 @@ +""" +Implements the functionality for those methods defined +in XmlRpcAPI. + +@date: Jun 12, 2013 +@author: CarolinaFernandez +""" + +from settings import XMLRPC_SERVER_PASSWORD + +class ResourceController: + + @staticmethod + def get_resources(): + try: + return open("resources.xml").read() + except: + return "" + + @staticmethod + def ping(challenge): + return challenge + + @staticmethod + def ping_auth(challenge, password): + if password != XMLRPC_SERVER_PASSWORD: + raise Exception("Password mismatch") + return challenge + diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/controller/__init__.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/controller/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/resources.xml b/expedient/doc/plugins/samples/aggregate/sr_manager/src/resources.xml new file mode 100644 index 00000000..2af1b995 --- /dev/null +++ b/expedient/doc/plugins/samples/aggregate/sr_manager/src/resources.xml @@ -0,0 +1,49 @@ + + + Sensor1 + 19.89 + C + + Sensor3 + Sensor4 + + + + Sensor2 + 312.12 + K + + Sensor1 + Sensor3 + Sensor5 + + + + Sensor3 + 98.61 + F + + Sensor1 + Sensor4 + + + + Sensor4 + 2.1 + C + + Sensor2 + Sensor5 + + + + Sensor5 + 359.23 + K + + Sensor1 + Sensor3 + Sensor4 + + + diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/security/certificates/sr_am.crt b/expedient/doc/plugins/samples/aggregate/sr_manager/src/security/certificates/sr_am.crt new file mode 100755 index 00000000..d7d5b5af --- /dev/null +++ b/expedient/doc/plugins/samples/aggregate/sr_manager/src/security/certificates/sr_am.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICATCCAWoCCQCWLcncwun0vDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJl +czETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTEyMDIwMjEzNTI1M1oXDTIyMDEzMDEzNTI1M1owRTELMAkG +A1UEBhMCZXMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxhpm +545VjO6donSLqSJMglaAvU591KxU4ZTzqLuOfTOEb8uW0y2S1KEynbxl8SFLcWJE +jDt8BjcmX4N5HFAwm+N53LdEsRkF7bHiLZ3k01E9gaP/T52DFJSKudeuc8Gm0ZB0 +x1tZv+W/JanNZ3JqCXF04ndAm9BAESbN7AZD4G0CAwEAATANBgkqhkiG9w0BAQUF +AAOBgQBki8wz3N5yQSwbbwARx6W54/i6SMJgNe2Yyc4ny6XgZdXaEQmFfWJMCGwQ +v3GmSwafrk96CRtCeof0tarL+OagYrxxZ1K+aM5H0DHyuZSDKcDsEQt3uUudfVto +g+eiqESfhBk0iI2J2P76Zfzhox7a6p88cZQzX2bKsaPkeg6QiA== +-----END CERTIFICATE----- diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/security/certificates/sr_am.key b/expedient/doc/plugins/samples/aggregate/sr_manager/src/security/certificates/sr_am.key new file mode 100755 index 00000000..8332aedf --- /dev/null +++ b/expedient/doc/plugins/samples/aggregate/sr_manager/src/security/certificates/sr_am.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDGGmbnjlWM7p2idIupIkyCVoC9Tn3UrFThlPOou459M4Rvy5bT +LZLUoTKdvGXxIUtxYkSMO3wGNyZfg3kcUDCb43nct0SxGQXtseItneTTUT2Bo/9P +nYMUlIq5165zwabRkHTHW1m/5b8lqc1ncmoJcXTid0Cb0EARJs3sBkPgbQIDAQAB +AoGAFHYLpOUFnw3SSEJDXo/FWTz4BRWDV6EJD1ekJwxgNjxI9IcRp/QwEzgnEzWv +Tc2Djk15CQbn03iExR6+Npdtva2f+nHzM1j3FThcgyaNFQVYogTsQ41+beHaD8vC +RyL81r79mjdg5+tyCzdUr0/e0jxA5TAhG0BINGGD1RJNouECQQDpDO3xU/luqM/+ +XVrey3N9lMJvm+rFOQxdfkWSrFM+9MTKZx8I90oEJYNq6aJdIyPRuiVse9vlolCc +6ZmjKub1AkEA2Zx4GTHBdFdcRpIxJDg2oAx2iEyIcTGpgSOc7qnl6wpUoxhQlNQs +HrfAOOsBwypz5eEvJHmDKeilvDi2c8l4mQJAHA2rYt556yE1EGiKdMFG4LoUgbzi +EOWiIGr/0v0ddDmgqsCpEro51a/yVt9S5SVCvY9Ly/hI6yaTz5+rF+IlNQJAWitv +yGDJnH+miMeC/VMdr2v6obe0wdKmPhCXsn1L+/yn3Xzxxvmz3nade/hFHq20oIiS +lDaVlwQDyN5nG8tb4QJBAJgpAfBYCD0EGezLgvzYi73AIdiZheuyWKdF7HABVES6 +jffeGZU59AQQMYFpd5jpLAxvZws8Wr+O+b3TLvvykTU= +-----END RSA PRIVATE KEY----- diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/server.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/server.py new file mode 100644 index 00000000..001367b0 --- /dev/null +++ b/expedient/doc/plugins/samples/aggregate/sr_manager/src/server.py @@ -0,0 +1,17 @@ +""" +Keeps the dummy AM server running. + +@date: Jun 12, 2013 +@author: CarolinaFernandez +""" + +from communications.XmlRpcServer import XmlRpcServer + +def main(): + #Engage XMLRPC + XmlRpcServer.createInstanceAndEngage(None) + +#Calling main +if __name__ == "__main__": + main() + diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/settings.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/settings.py new file mode 100755 index 00000000..312d1a6d --- /dev/null +++ b/expedient/doc/plugins/samples/aggregate/sr_manager/src/settings.py @@ -0,0 +1,32 @@ +""" +Basic settings for the dummy AM. + +@date: Jul 3, 2013 +@author: CarolinaFernandez +""" + +# +# Authentication data. Set the user and password +# of your choice to communicate against the AM. +# Do NOT modify the rest. +# +XMLRPC_SERVER_USER = "user" +XMLRPC_SERVER_PASSWORD = "password" +XMLRPC_SERVER_KEYFILE = "security/certificates/sr_am.key" +XMLRPC_SERVER_CERTFILE = "security/certificates/sr_am.crt" + +# +# Log level. Should be one of the following: 'DEBUG', +# 'INFO', 'WARNING', 'ERROR', 'CRITICAL' +# +LOG_LEVEL = "WARNING" + +# +# Network parameters. +# +# XMLRPC_SERVER_LISTEN_HOST: you should not use '' +# here, unless you have a real FQDM +# +XMLRPC_SERVER_LISTEN_HOST = "0.0.0.0" +XMLRPC_SERVER_LISTEN_PORT = 9445 + diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/tests/parse_resources.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/tests/parse_resources.py new file mode 100644 index 00000000..88c95963 --- /dev/null +++ b/expedient/doc/plugins/samples/aggregate/sr_manager/src/tests/parse_resources.py @@ -0,0 +1,68 @@ +""" +Parsing tests. + +@date: Jun 12, 2013 +@author: CarolinaFernandez +""" + +# ----- Parse resources (lxml) ----- +from lxml import etree + +context = etree.iterparse("resources.xml") +for action, elem in context: + if elem.tag == "resource": + print "" + if elem.text.strip(): + print("[%s] %s: %s" % (action, elem.tag, elem.text)) + +# ----- Add resources (lxml) ----- +parser = etree.XMLParser(remove_blank_text=True) +tree = etree.parse("resources.xml", parser) +resources = tree.getroot() + +new_resource = etree.SubElement(resources, "resource") +new_resource_name = etree.SubElement(new_resource, "name") +new_resource_name.text = "Sensor6" +new_resource_temperature = etree.SubElement(new_resource, "temperature") +new_resource_temperature.text = "21" +new_resource_temperature_scale = etree.SubElement(new_resource, "temperature_scale") +new_resource_temperature_scale.text = "K" + +#print "Final XML: %s" % str(etree.tostring(tree, pretty_print=True)) +# Formats output XML +tree.write ("resources.xml", pretty_print=True) + + +## ----- Parse resources (minidom) ----- +#from xml.dom import minidom +# +#def getText(nodelist): +# rc = [] +# for node in nodelist: +# if node.nodeType == node.TEXT_NODE: +# rc.append(node.data) +# return ''.join(rc) +# +#xmldoc = minidom.parse("resources.xml") +#resource_list = xmldoc.getElementsByTagName("resource") +#print len(resource_list) +#print "" +# +#for resource in resource_list: +# name = resource.getElementsByTagName("name")[0] +# temperature = resource.getElementsByTagName("temperature")[0] +# temperature_scale = resource.getElementsByTagName("temperature_scale")[0] +# interface_list = resource.getElementsByTagName("interface") +# for interface in interface_list: +# print "interface: %s" % getText(interface.childNodes) +# +## ----- Add resources (minidom) ----- +# +#resource = xmldoc.createElement("resource") +#resource_text = xmldoc.createTextNode("name") +#resource.appendChild(resource_text) +#print "resource: %s" % str(resource.toxml()) +##print "child nodes: %s" % str(xmldoc.childNodes[0].toxml()) +#xmldoc.childNodes[0].appendChild(resource) +#print xmldoc.toxml() + diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/utils/Logger.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/utils/Logger.py new file mode 100644 index 00000000..05f5d39b --- /dev/null +++ b/expedient/doc/plugins/samples/aggregate/sr_manager/src/utils/Logger.py @@ -0,0 +1,35 @@ +""" +Configuration for the logger. + +@date: Jun 12, 2013 +@author: CarolinaFernandez +""" + +import logging +import threading +#Get log level +from settings import LOG_LEVEL + +#Configure logger +log_level= "" +if LOG_LEVEL == "INFO": + log_level = logging.INFO +elif LOG_LEVEL == "WARNING": + log_level = logging.WARNING +elif LOG_LEVEL == "ERROR": + log_level = logging.ERROR +elif LOG_LEVEL == "CRITICAL": + log_level = logging.CRITICAL +else: + log_level = logging.DEBUG + +threadId="main" + +logging.basicConfig(format='%(asctime)s [%(threadName)s>%(filename)s:%(lineno)d] %(levelname)s: %(message)s', datefmt='%d/%m/%Y %I:%M:%S %p', level=log_level) + +class Logger(): + @staticmethod + def getLogger(): + #Simple wrapper. Ensures logging is always correctly configured (logging.basicConfig is executed) + return logging.getLogger() + diff --git a/expedient/doc/plugins/samples/aggregate/sr_manager/src/utils/__init__.py b/expedient/doc/plugins/samples/aggregate/sr_manager/src/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/__init__.py b/expedient/doc/plugins/samples/plugin/sample_resource/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/controller/GUIdispatcher.py b/expedient/doc/plugins/samples/plugin/sample_resource/controller/GUIdispatcher.py new file mode 100644 index 00000000..0b9c877d --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/controller/GUIdispatcher.py @@ -0,0 +1,174 @@ +""" +Graphical user interface functionalities for the +SampleResource Aggregate Manager. + +@date: Jun 12, 2013 +@author: CarolinaFernandez +""" + +from django.core.exceptions import ValidationError +from django.core.urlresolvers import reverse +from django.http import HttpResponseRedirect, HttpResponse +from django.shortcuts import get_object_or_404 +from expedient.clearinghouse.aggregate.models import Aggregate +from expedient.clearinghouse.slice.models import Slice +from expedient.common.messaging.models import DatedMessage +from expedient.common.utils.plugins.plugincommunicator import * +from expedient.common.utils.plugins.resources.link import Link +from expedient.common.utils.plugins.resources.node import Node +from expedient.common.utils.views import generic_crud +from sample_resource.controller.resource import SampleResource as SampleResourceController +from sample_resource.forms.SampleResource import SampleResource as SampleResourceModelForm +from sample_resource.models import SampleResource as SampleResourceModel,\ + SampleResourceAggregate as SampleResourceAggregateModel + +import copy +import logging +import xmlrpclib + +def create_resource(request, slice_id, agg_id): + """Show a page that allows user to add a SampleResource to the aggregate.""" + + if request.method == "POST": + # Shows error message when aggregate unreachable, disable SampleResource creation and get back to slice detail page + agg = Aggregate.objects.get(id = agg_id) + if agg.check_status() == False: + DatedMessage.objects.post_message_to_user( + "SampleResource Aggregate '%s' is not available" % agg.name, + request.user, msg_type=DatedMessage.TYPE_ERROR,) + return HttpResponseRedirect(reverse("slice_detail", args=[slice_id])) + + if 'create_resource' in request.POST: + return HttpResponseRedirect(reverse("sample_resource_resource_crud", args=[slice_id, agg_id])) + else: + return HttpResponseRedirect(reverse("slice_detail", args=[slice_id])) + +def resource_crud(request, slice_id, agg_id, resource_id = None): + """ + Show a page that allows user to create/edit SampleResource's to the Aggregate. + """ + slice = get_object_or_404(Slice, id = slice_id) + aggregate = Aggregate.objects.get(id = agg_id) + error_crud = "" + + def pre_save(instance, created): + """ + Fills SampleResource instance prior to its saving. + Used within the scope of the generic_crud method. + """ + instance = SampleResourceController.fill(instance, slice, agg_id, resource_id) + + try: + return generic_crud(request, obj_id=resource_id, model=SampleResourceModel, + form_class=SampleResourceModelForm, + template="sample_resource_resource_crud.html", + redirect=lambda inst: reverse("slice_detail", args=[slice_id]), + extra_context={"agg": aggregate, "slice": slice, "exception": error_crud, "breadcrumbs": ( + ("Home", reverse("home")), + ("Project %s" % slice.project.name, reverse("project_detail", args=[slice.project.id])), + ("Slice %s" % slice.name, reverse("slice_detail", args=[slice_id])), + ("%s SampleResource" % "Update" if resource_id else "Create", reverse("sample_resource_resource_crud", args=[slice_id, agg_id])),) + }, extra_form_params={}, template_object_name="object", pre_save=pre_save, + post_save=None, success_msg=None) + except ValidationError as e: + # Django exception message handling is different to Python's... + error_crud = ";".join(e.messages) + except Exception as e: + print "[WARNING] Could not create resource in plugin 'sample_resource'. Details: %s" % str(e) + DatedMessage.objects.post_message_to_user( + "SampleResource might have been created, but some problem ocurred: %s" % str(e), + request.user, msg_type=DatedMessage.TYPE_ERROR) + return HttpResponseRedirect(reverse("slice_detail", args=[slice_id])) + +def manage_resource(request, resource_id, action_type): + """ + Manages the actions executed over SampleResource's. + """ + if action_type == "delete": + SampleResourceController.delete(resource_id) + # Go to manage resources again + return HttpResponse("") + +### +# Topology to show in the Expedient +# + +def get_sr_list(slice): + return SampleResourceModel.objects.filter(slice_id = slice.uuid) + +def get_sr_aggregates(slice): + sr_aggs = [] + try: + sr_aggs = slice.aggregates.filter(leaf_name=SampleResourceAggregateModel.__name__.lower()) + except: + pass + return sr_aggs + +def get_node_description(node): + description = "Sample Resource: " + node.name + "

" + description += "• Temperature: %s (°%s)" % (str(node.get_temperature()), str(node.get_temperature_scale())) + connections = "" + node_connections = node.get_connections() + for i, connection in enumerate(node_connections): + connections += connection.name + if i < len(node_connections)-1: + connections += ", " + description += "
• Connected to: %s" % str(connections) + return description + +def get_nodes_links(slice, chosen_group=None): + nodes = [] + links = [] + sr_aggs = get_sr_aggregates(slice) + + # Getting image for the nodes + # FIXME: avoid to ask the user for the complete name of the method here! he should NOT know it + try: + image_url = reverse('img_media_sample_resource', args=("sensor-tiny.png",)) + except: + image_url = 'sensor-tiny.png' + + # For every SampleResource AM + for i, sr_agg in enumerate(sr_aggs): + sr_agg = sr_agg.sampleresourceaggregate + # Iterates over every SampleResource contained within the slice + for sr in sr_agg.get_resources(): + sr = sr.sampleresource + nodes.append(Node( + # Users shall not be left the choice to choose group/island; otherwise collision may arise + name = sr.name, value = sr.id, aggregate = sr.aggregate, type = "Sample resource", + description = get_node_description(sr), image = image_url) + ) + for connection in sr.get_connections(): + # Two-ways link + links.append( + Link( + target = str(sr.id), source = str(connection.id), + value = "rsc_id_%s-rsc_id_%s" % (connection.id, sr.id) + ), + ) + links.append( + Link( + target = str(sr.id), source = str(connection.id), + value = "rsc_id_%s-rsc_id_%s" % (sr.id, connection.id) + ), + ) + return [nodes, links] + +#from expedient.common.utils.plugins.plugininterface import PluginInterface +# +#class Plugin(PluginInterface): +# @staticmethod +def get_ui_data(slice): + """ + Hook method. Use this very same name so Expedient can get the resources for every plugin. + """ + ui_context = dict() + try: + ui_context['sr_list'] = get_sr_list(slice) + ui_context['sr_aggs'] = get_sr_aggregates(slice) + ui_context['nodes'], ui_context['links'] = get_nodes_links(slice) + except Exception as e: + print "[ERROR] Problem loading UI data for plugin 'sample_resource'. Details: %s" % str(e) + return ui_context + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/controller/__init__.py b/expedient/doc/plugins/samples/plugin/sample_resource/controller/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/controller/aggregate.py b/expedient/doc/plugins/samples/plugin/sample_resource/controller/aggregate.py new file mode 100644 index 00000000..cb90c9a6 --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/controller/aggregate.py @@ -0,0 +1,207 @@ +""" +Controller for the SampleResource aggregate. +Performs aggregate CRUD operations and the +synchronization with the resources it contains. + +@date: Jun 12, 2013 +@author: CarolinaFernandez +""" + +from django.core.urlresolvers import reverse +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404 +from django.views.generic import simple +from expedient.clearinghouse.utils import post_message_to_current_user +from expedient.common.messaging.models import DatedMessage +from expedient.common.permissions.shortcuts import give_permission_to +from io import BytesIO +from lxml import etree +from sample_resource.controller.resource import SampleResource as SampleResourceController +from sample_resource.forms.SampleResourceAggregate import SampleResourceAggregate as SampleResourceAggregateForm +from sample_resource.forms.xmlrpcServerProxy import xmlrpcServerProxy as xmlrpcServerProxyForm +from sample_resource.models.SampleResourceAggregate import SampleResourceAggregate as SampleResourceAggregateModel +from sample_resource.models.SampleResource import SampleResource as SampleResourceModel +import xmlrpclib + +class am_resource(object): + """ + Used to extend any object properties. + """ + pass + +def aggregate_crud(request, agg_id=None): + ''' + Create/update a SampleResource Aggregate. + ''' + if agg_id != None: + aggregate = get_object_or_404(SampleResourceAggregateModel, pk=agg_id) + client = aggregate.client + else: + aggregate = None + client = None + + extra_context_dict = {} + errors = "" + + if request.method == "GET": + agg_form = SampleResourceAggregateForm(instance=aggregate) + client_form = xmlrpcServerProxyForm(instance=client) + + elif request.method == "POST": + agg_form = SampleResourceAggregateForm( + data=request.POST, instance=aggregate) + client_form = xmlrpcServerProxyForm( + data=request.POST, instance=client) + + if client_form.is_valid() and agg_form.is_valid(): + # Ping is tried after every field check + client = client_form.save(commit=False) + s = xmlrpclib.Server('https://'+client.username+':'+client.password+'@'+client.url[8:]) + try: + s.ping('ping') + except: + errors = "Could not connect to server: username, password or url are not correct" + DatedMessage.objects.post_message_to_user( + errors, user=request.user, msg_type=DatedMessage.TYPE_ERROR, + ) + extra_context_dict['errors'] = errors + + if not errors: + client = client_form.save() + aggregate = agg_form.save(commit=False) + aggregate.client = client + aggregate.save() + agg_form.save_m2m() + aggregate.save() + # Update agg_id to sync its resources + agg_id = aggregate.pk + # Get resources from SampleResource AM's xmlrpc server every time the AM is updated + try: + do_sync = True + if agg_form.is_bound: + do_sync = agg_form.data.get("sync_resources") + else: + do_sync = agg_form.initial.get("sync_resources") + + if do_sync: + failed_resources = sync_am_resources(agg_id, s) + + if failed_resources: + DatedMessage.objects.post_message_to_user( + "Could not synchronize resources %s within Expedient" % str(failed_resources), + user=request.user, msg_type=DatedMessage.TYPE_WARNING, + ) + except: + warning = "Could not synchronize AM resources within Expedient" + DatedMessage.objects.post_message_to_user( + errors, user=request.user, msg_type=DatedMessage.TYPE_WARNING, + ) + extra_context_dict['errors'] = warning + + give_permission_to( + "can_use_aggregate", + aggregate, + request.user, + can_delegate=True + ) + give_permission_to( + "can_edit_aggregate", + aggregate, + request.user, + can_delegate=True + ) + DatedMessage.objects.post_message_to_user( + "Successfully created/updated aggregate %s" % aggregate.name, + user=request.user, msg_type=DatedMessage.TYPE_SUCCESS, + ) + return HttpResponseRedirect("/") + else: + return HttpResponseNotAllowed("GET", "POST") + + + if not errors: + extra_context_dict['available'] = aggregate.check_status() if agg_id else False + + # Updates the dictionary with the common fields + extra_context_dict.update({ + "agg_form": agg_form, + "client_form": client_form, + "create": not agg_id, + "aggregate": aggregate, + "breadcrumbs": ( + ('Home', reverse("home")), + ("%s SampleResource Aggregate" % ("Update" if agg_id else "Create"), + request.path), + ) + }) + + return simple.direct_to_template( + request, + template="sample_resource_aggregate_crud.html", + extra_context=extra_context_dict + ) + +def delete_resources(agg_id): + resource_set = SampleResourceAggregateModel.objects.get(id = agg_id).resource_set.all() + for resource in resource_set: + resource.delete() + +def sync_am_resources(agg_id, xmlrpc_server): + """ + Retrieves SampleResource objects from the AM's xmlrpc server every time the AM is updated + """ + connections = dict() + failed_resources = [] + resources = xmlrpc_server.get_resources() + context = etree.iterparse(BytesIO(resources)) + delete_resources(agg_id) + aggregate = SampleResourceAggregateModel.objects.get(id = agg_id) +# for slice in aggregate.slice_set: + # File (nodes) + for action, elem in context: + node_name = "" + instance = am_resource() + children_context = elem.iterchildren() + # Node (tags) + for elem in children_context: + if "connection" not in elem.tag: + setattr(instance, elem.tag, elem.text) + if elem.tag == "name": + node_name = elem.text + elif elem.tag == "connections": + connections[node_name] = [] + connections_context = elem.iterchildren() + for connection in connections_context: + connections[node_name].append(connection.text) + try: + if instance: +# SampleResourceController.create(instance, agg_id, slice) + SampleResourceController.create(instance, agg_id) + except: + try: + failed_resources.append(instance.name) + except: + pass + + # Connections between SampleResources are computed later, when all nodes have been created + try: + for node, node_connections in connections.iteritems(): + connections_aux = [] + for connection in node_connections: + try: + # Linked to another SampleResources + res = SampleResourceModel.objects.get(name = connection) + if res: + connections_aux.append(res) + except: + pass + connections[node] = connections_aux + # Setting connections on resource with name as in 'node' var + node_resource = SampleResourceModel.objects.get(name = node) + node_resource.set_connections(connections[node]) + node_resource.save() + except: + pass + + return failed_resources + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/controller/resource.py b/expedient/doc/plugins/samples/plugin/sample_resource/controller/resource.py new file mode 100644 index 00000000..a13e3edc --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/controller/resource.py @@ -0,0 +1,70 @@ +""" +Controller for the SampleResource object. +Performs the operations to create, update and +delete such objects. + +@date: Jun 12, 2013 +@author: CarolinaFernandez +""" + +from sample_resource.models.SampleResource import SampleResource as SampleResourceModel +from sample_resource.utils.validators import validate_resource_name +import decimal, random + +class SampleResource(): + """ + Manages creation/edition of SampleResources from the input of a given form. + """ + + @staticmethod + def create(instance, aggregate_id, slice=None): + try: + if all(x in instance.__dict__ for x in ["name", "temperature_scale"]): + sr = SampleResourceModel() + sr.aggregate_id = aggregate_id + sr.set_label(instance.__dict__['name']) + sr.set_name(instance.__dict__['name']) + if "temperature" in instance.__dict__: + # XML import (aggregate update) + sr.set_temperature(instance.__dict__['temperature']) + else: + # Normal form + sr.set_temperature(decimal.Decimal(random.randrange(1000))/1000) + sr.set_temperature_scale(instance.__dict__['temperature_scale']) + if slice: + sr.set_project_id(slice.project.id) + sr.set_project_name(slice.project.name) + sr.set_slice_id(slice.id) + sr.set_slice_name(slice.name) + sr.save() + except Exception as e: + if "Duplicate entry" in str(e): + raise Exception("SampleResource with name '%s' already exists." % str(instance.name)) + else: + raise e + + @staticmethod + def fill(instance, slice, aggregate_id, resource_id = None): + # resource_id = False => create. Check that no other resource exists with this name + if not resource_id: + if SampleResourceModel.objects.filter(name = instance.name): + # Every exception will be risen to the upper level + raise Exception("SampleResource with name '%s' already exists." % str(instance.name)) + + instance.aggregate_id = aggregate_id + instance.temperature = decimal.Decimal(random.randrange(1000))/100 + instance.project_id = slice.project.id + instance.project_name = slice.project.name + instance.slice_id = slice.id + instance.slice_name = slice.name + # resource_id = True => edit. Change name/label + instance.label = instance.name + return instance + + @staticmethod + def delete(resource_id): + try: + SampleResourceModel.objects.get(id = resource_id).delete() + except: + pass + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/forms/SampleResource.py b/expedient/doc/plugins/samples/plugin/sample_resource/forms/SampleResource.py new file mode 100644 index 00000000..2ab75a06 --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/forms/SampleResource.py @@ -0,0 +1,37 @@ +''' +Created on Jan 14, 2013 + +@author: CarolinaFernandez +''' + +from django import forms +from sample_resource.models.SampleResource import SampleResource as SampleResourceModel +from sample_resource.utils.validators import validate_resource_name, validate_temperature_scale + +class SampleResource(forms.models.ModelForm): + + connections = forms.ModelMultipleChoiceField(queryset = SampleResourceModel.objects.all().order_by("name"), +# widget = forms.SelectMultiple()) + widget = forms.CheckboxSelectMultiple()) + + class Meta: + fields = ["name", "temperature_scale", "connections"] + model = SampleResourceModel + + def __init__(self, *args, **kwargs): + super(SampleResource, self).__init__(*args,**kwargs) + try: + # Do not allow links to self + current_label = kwargs['instance'].label + self.fields['connections'].queryset = SampleResourceModel.objects.exclude(label = current_label).order_by("name") + except: + pass + + def clean_name(self): + validate_resource_name(self.cleaned_data['name']) + return self.cleaned_data['name'] + + def clean_temperature_scale(self): + validate_temperature_scale(self.cleaned_data['temperature_scale']) + return self.cleaned_data['temperature_scale'] + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/forms/SampleResourceAggregate.py b/expedient/doc/plugins/samples/plugin/sample_resource/forms/SampleResourceAggregate.py new file mode 100644 index 00000000..72d9cf4f --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/forms/SampleResourceAggregate.py @@ -0,0 +1,22 @@ +""" +Model for the SampleResource aggregate. +It defines the fields that will be used in the CRUD form. + +@date: Apr 2, 2013 +@author: CarolinaFernandez +""" + +from django import forms +from sample_resource.models import SampleResourceAggregate as SampleResourceAggregateModel + +class SampleResourceAggregate(forms.ModelForm): + ''' + A form to create and edit SampleResource Aggregates. + ''' + + sync_resources = forms.BooleanField(label = "Sync resources?", initial = True, required = False) + + class Meta: + model = SampleResourceAggregateModel + exclude = ['client', 'owner', 'users', 'available'] + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/forms/__init__.py b/expedient/doc/plugins/samples/plugin/sample_resource/forms/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/forms/xmlrpcServerProxy.py b/expedient/doc/plugins/samples/plugin/sample_resource/forms/xmlrpcServerProxy.py new file mode 100644 index 00000000..00b24e08 --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/forms/xmlrpcServerProxy.py @@ -0,0 +1,53 @@ +""" +Model for the xmlrpcServerProxy. +It defines the fields used in the aggregate CRUD form. + +@date: Apr 29, 2010 +@author: jnaous +""" + +from django import forms +from sample_resource.models import xmlrpcServerProxy + +class xmlrpcServerProxy(forms.ModelForm): + ''' + A form to create and edit OpenFlow Aggregates. + ''' + + confirm_password = forms.CharField( + help_text="Confirm password.", + max_length=40, + widget=forms.PasswordInput(render_value=False)) + + def __init__(self, check_available=False, *args, **kwargs): + super(xmlrpcServerProxy, self).__init__(*args, **kwargs) + self.check_available = check_available + # Fix Django's autocompletion of username/password fields when type is password + self.fields['username'].widget.attrs["autocomplete"] = 'off' + self.fields['password'].widget.attrs["autocomplete"] = 'off' + self.fields['confirm_password'].widget.attrs["autocomplete"] = 'off' + + class Meta: + model = xmlrpcServerProxy + # Defines all the fields in the model by ORDER + fields = ('username', 'password', 'confirm_password', 'url') + # Form widgets: HTML representation of fields + widgets = { + # Shows the password + 'password': forms.PasswordInput(render_value=True), + } + + # Validation and so on + def clean(self): + # Check that both passwords (if present) are the same + password = self.cleaned_data.get('password', None) + confirm_password = self.cleaned_data.get('confirm_password', None) + if password and confirm_password and (password != confirm_password): + raise forms.ValidationError("Passwords don't match") + # Remove fields that are not in the Model to avoid any mismatch when synchronizing + d = dict(self.cleaned_data) + if "confirm_password" in d: + del d["confirm_password"] + p = self._meta.model(**d) + return self.cleaned_data + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/models/SampleResource.py b/expedient/doc/plugins/samples/plugin/sample_resource/models/SampleResource.py new file mode 100644 index 00000000..b98834a7 --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/models/SampleResource.py @@ -0,0 +1,100 @@ +from django.db import models +from expedient.clearinghouse.resources.models import Resource +from sample_resource.utils.validators import TEMPERATURE_SCALE_CHOICES, validate_resource_name, validate_temperature_scale + +class SampleResource(Resource): + + class Meta: + """Meta class for SampleResource model.""" + app_label = 'sample_resource' + + # Unique alphanumeric identifier for the SampleResource + label = models.CharField(max_length = 100, unique=True) + temperature = models.DecimalField(max_digits = 6, decimal_places = 3, blank = True) + temperature_scale = models.CharField(max_length = 10, verbose_name = "Temperature scale", + choices = TEMPERATURE_SCALE_CHOICES, + validators = [validate_temperature_scale]) + connections = models.ManyToManyField("SampleResource", blank = True, null = True) +# connections = models.ManyToManyField("Resource", blank = True, null = True) + project_id = models.CharField(max_length = 1024, default = "") + project_name = models.CharField(max_length = 1024, default = "") + slice_id = models.CharField(max_length = 1024, default = "") + slice_name = models.CharField(max_length = 1024, default = "") + + def get_connections(self): + return self.connections.all() + + def set_connections(self, connections): + for connection in connections: + self.connections.add(connection) + + def get_name(self): + return self.name + + def set_name(self, name): + # Adds or overwrites any validation to Resource's "name" field + if not self.name: + validate_resource_name(name) + self.name = name + + def get_label(self): + return self.label + + def set_label(self, label): + if not self.label: + validate_resource_name(label) + self.label = label + + def get_temperature(self): + return self.temperature + + def set_temperature(self, temperature): + self.temperature = temperature + + def get_temperature_scale(self): + return self.temperature_scale + + def set_temperature_scale(self, temperature_scale): + self.temperature_scale = temperature_scale + + # Returns the whole string ("C" => "Celsius", "F" => "Fahrenheit", etc) + def get_full_temperature_scale(self): + try: + return dict(TEMPERATURE_SCALE_CHOICES)[self.get_temperature_scale()] + except: + return self.get_temperature_scale() + + def get_project_id(self): + return self.project_id + + def set_project_id(self, project_id): + if not isinstance(project_id,str): + project_id = str(project_id) + self.project_id = project_id + + def get_project_name(self): + return self.project_name + + def set_project_name(self,project_name): + if not isinstance(project_name,str): + project_name = str(project_name) + self.project_name = project_name + + def get_slice_id(self): + return self.slice_id + + def set_slice_id(self, value): + self.slice_id = value + + def get_slice_name(self): + return self.slice_name + + def set_slice_name(self, value): + self.slice_name = value + + def delete(self): + for connection in self.connections.all(): + self.connections.remove(connection) +# connection.delete() # deletes connected resources as well + super(SampleResource, self).delete() + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/models/SampleResourceAggregate.py b/expedient/doc/plugins/samples/plugin/sample_resource/models/SampleResourceAggregate.py new file mode 100644 index 00000000..2c030ac0 --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/models/SampleResourceAggregate.py @@ -0,0 +1,71 @@ +""" +Communicates the SampleResource Aggregate Manager with Expedient. + +@date: Jun 12, 2013 +@author: CarolinaFernandez +""" + +from django.db import models +from django.core.exceptions import MultipleObjectsReturned +from expedient.clearinghouse.aggregate.models import Aggregate +from expedient.common.permissions.shortcuts import must_have_permission +from sample_resource.models.SampleResource import SampleResource + +# SampleResource Aggregate class +class SampleResourceAggregate(Aggregate): + # Sample Resource Aggregate information field + information = "An aggregate of sample resources" + + class Meta: + app_label = 'sample_resource' + verbose_name = "Sample Resource Aggregate" + + client = models.OneToOneField('xmlrpcServerProxy', editable = False, blank = True, null = True) + + def stop_slice(self, slice): + super(SampleResourceAggregate, self).stop_slice(slice) + pass + +# def get_resources(self, slice_id): + def get_resources(self): + try: +# return SampleResource.objects.filter(slice_id = slice_id, aggregate = self.pk) + return SampleResource.objects.filter(aggregate = self.pk) + except Exception as e: + return [] + + def remove_from_project(self, project, next): + """ + aggregate.remove_from_project on a SampleResource AM will get here first to check + that no slice inside the project contains SampleResource's for the given aggregate + """ + # Check permission because it won't always call parent method (where permission checks) + must_have_permission("user", self.as_leaf_class(), "can_use_aggregate") + + sample_resources = self.resource_set.filter_for_class(SampleResource).filter(sampleresource__project_id=project.uuid) + offending_slices = [] + for resource in sample_resources: + offending_slices.append(str(resource.SampleResource.get_slice_name())) + # Aggregate has SampleResource's in slices -> stop slices and remove AM from it if possible + if offending_slices: + for slice in project.slice_set.all(): + try: + self.stop_slice(slice) + self.remove_from_slice(slice, next) + except: + pass + raise MultipleObjectsReturned("Please delete all Sample Resources inside aggregate '%s' before removing it from slices %s" % (self.name, str(offending_slices))) + # Aggregate has no SampleResource's in slices (OK) -> delete completely from project (parent method) + else: + return super(SampleResourceAggregate, self).remove_from_project(project, next) + + def remove_from_slice(self, slice, next): + """ + aggregate.remove_from_slice on a SampleResource AM will get here first to check + that the slice does not contain SampleResource's for the given aggregate + """ + # Warn if any SampleResource (created in this slice) is found inside the SampleResource AM + if self.resource_set.filter_for_class(SampleResource).filter(sampleresource__slice_id=slice.uuid): + raise MultipleObjectsReturned("Please delete all Sample Resources inside aggregate '%s' before removing it" % str(self.name)) + return super(SampleResourceAggregate, self).remove_from_slice(slice, next) + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/models/__init__.py b/expedient/doc/plugins/samples/plugin/sample_resource/models/__init__.py new file mode 100644 index 00000000..17edf2bc --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/models/__init__.py @@ -0,0 +1,27 @@ +import os +import re +import types + +PACKAGE = 'sample_resource.models' +MODEL_RE = r"^.*.py$" + +# Search through every file inside this package +model_names = [] +model_dir = os.path.dirname( __file__) +for filename in os.listdir(model_dir): + if not re.match(MODEL_RE, filename) or filename == "__init__.py": + continue + # Import the model file and find all classes inside it + model_module = __import__('%s.%s' % (PACKAGE, filename[:-3]), + {}, {}, + filename[:-3]) + for name in dir(model_module): + item = getattr(model_module, name) + if not isinstance(item, (type, types.ClassType)): + continue + # Found a model, bring into the module namespace + exec "%s = item" % name + model_names.append(name) + +# Hide everything other than the classes from other modules +__all__ = model_names diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/models/xmlrpcServerProxy.py b/expedient/doc/plugins/samples/plugin/sample_resource/models/xmlrpcServerProxy.py new file mode 100644 index 00000000..c7c3cc1b --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/models/xmlrpcServerProxy.py @@ -0,0 +1,30 @@ +""" +Implements a server proxy for XML-RPC calls that checks SSL certs and +uses a password to talk to the server. The password is automatically renewed +whenever it expires. + +@date: Apr 29, 2010 +@author: jnaous +""" + +from django.db import models + +class xmlrpcServerProxy(models.Model): + + class Meta: + app_label = 'sample_resource' + + username = models.CharField( + max_length=100, + help_text="Username to use to access the remote server.") + password = models.CharField( + max_length=24, + help_text="Password to use to access the remote server.") + #max_password_age = models.PositiveIntegerField( + # 'Max Password age (days)', default=0, + # help_text="If this is set to non-zero, the password "\ + # "will automatically be changed once the password ages past the "\ + # "maximum. The new password is then randomly generated.") + #password_timestamp = models.DateTimeField(auto_now_add=True) + url = models.URLField("Server URL", verify_exists = False, max_length=1024, + help_text="URL used to access the remote server's xmlrpc interface, should be https://DOMAIN_OR_IP:PORT/ROUTE_TO_XMLRPC_INTERFACE") diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/settings.conf b/expedient/doc/plugins/samples/plugin/sample_resource/settings.conf new file mode 100644 index 00000000..c11fdeb5 --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/settings.conf @@ -0,0 +1,110 @@ +# +# IMPORTANT: +# * [1] Do not remove any section or property. +# Leave these in blank if you do not wish +# to set a value. +# +# * [2] Each property may be set as: +# a) single value: key = value +# b) multiple values: key = [value1, value2, ...] +# + + +### Section 1: URLs +# +# Paths that should be accepted for Expedient GUI +# + +[urls] + +# +# URL(s) with basic authorization +# +# NOTE: use URLs relative to main module (Expedient) +# and DO use Regular Expressions here +# +BASIC_AUTH_URLS = r'^/sample_resource/xmlrpc/sr_am.*' + + + +### Section 2: Paths +# +# Paths of different components +# + +[paths] + +# +# Directory of CSS, relative to the plugin's root path +# (e.g. 'static/media/default/img') +# +CSS_DIRS = 'static/media/default/css' + +# +# Directory of images, relative to the plugin's root path +# (e.g. 'static/media/default/img') +# +IMG_DIRS = 'static/media/default/img' + +# +# Directory of Javascript, relative to the plugin's root path +# (e.g. 'static/media/default/img') +# +JS_DIRS = 'static/media/default/js' + +# +# Directory of templates, relative to the plugin's root path +# (e.g. 'views/templates/default') +# +TEMPLATE_DIRS = 'views/templates/default' + +# +# Path to the template contained inside the slice detail +# page that allows to manage resources within the slice. +# +# It must be a path relative to the plugin root folder +# (e.g. 'views/templates/default/_add_resources.html') +# +TEMPLATE_RESOURCES = 'views/templates/default/sample_resource_add_resources.html' + +### Section 3: General +# +# General settings +# + +[general] + +# +# Aggregate plugin, to be enabled in Expedient +# +# This is a N-set of 3-tuples: +# +# 1. The first element is the absolute path to the Aggregate class. +# +# 2. The second element is the prefix that is prepended to all urls for +# accessing the plugin. This should be unique across all plugins and +# applications. +# +# 3. The third element is the absolute path to the module that should be +# included in URLConf and that contains all the plugin's URLs. +# +AGGREGATE_PLUGINS = ('sample_resource.models.SampleResourceAggregate', 'sample_resource', 'sample_resource.urls') + +# +# List of the APPs within the plugin to be activated in Django +# +INSTALLED_APPS = 'sample_resource' + +# +# File where the method 'get_ui_data' is defined +# +GET_UI_DATA_LOCATION = 'sample_resource.controller.GUIdispatcher' + +# +# Kind of resource that serves the AM (e.g. switch resources belong to +# "network" category whilst VMs belong to the "computation" type. +# +# Possible choices are 'network' or 'computation' +# +RESOURCE_TYPE = 'computation' + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/static/media/default/css/style.css b/expedient/doc/plugins/samples/plugin/sample_resource/static/media/default/css/style.css new file mode 100644 index 00000000..e4956cc4 --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/static/media/default/css/style.css @@ -0,0 +1,54 @@ +div.sample_resource_create_sensor { + clear: both; +} + +div.sample_resource_no_sensors { + margin-top: 10px; +} + +div.sample_resource_sensors { + margin-bottom: 15px; + margin-right: 10px; +} + +table.sample_resource_sensors { + border: 0px; + border-collapse: collapse; + border-left: 15px solid #333; + border-spacing: 0px; + font-size: 11px; + width: 100%; +} + +table.sample_resource_sensors td { + padding-left: 10px; +} + +table.sample_resource_sensors th { + background-color: #333; + border: 0px; + color: #eee; + padding: 4px; + text-align: left; +} + +table.sample_resource_sensors tr { + border: 0px; +} + +table.sample_resource_sensors tr.even { + background-color: #aaa; +} + +table.sample_resource_sensors tr.odd { + background-color: #ccc; +} + +td ul li { + list-style: none; +} + +/*select { + width: 100% !important; +}*/ + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/static/media/default/img/sensor-tiny.png b/expedient/doc/plugins/samples/plugin/sample_resource/static/media/default/img/sensor-tiny.png new file mode 100644 index 0000000000000000000000000000000000000000..d70155e13ff74fdbb45913114d134db0855c8ec9 GIT binary patch literal 1368 zcmV-e1*iInP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*b` z2^=|bY}g|J00h`cL_t(Y$EB8SOcYlXhTn5%KiOT_UBI|l&}zl4X{=STRUxryMH=i6 z?GLq;k~E>VO*A!v0%~hpwZ!y~R7tIxXg^~7B5h33no>1r6>Jn#h>C`SEcgj7yNj^9 zb5DN^j3R2Jon(^9ow?_}?{m&QcYyzS6&5VZ`gYUC+$X)K{~Eabz`k)FkGs@Fq0D>! zF4SLWPhDD2(D>+gVyJ;v7ZuGsuxDqT+aA4SP&+c!-flQ7M%32T*49;>8Whj)tbr>l z|Md7feVY^Aws}^Q%B(Vo86*e{Am{z;nDWC1#{#%KWCuI8Z8;ii3AH5;v&^#?Bakc! zBmppp2w;ZYqTtonCNCUP4yvnCHCT#%lyNK#pH3c=LME3h(OE|f`o>I0cM5}8eQsl!y2wJV@Fv{WIu84!ucjW z2OoX1+;Qg2v8``sr3XCmW{Zr3b=wdE8fFRNKBCOvzFTKa1VMy&myP3GwldwpqJ;}z z%FW5TZs6|82EhP5P(?(VGEFs;WYQP*HIl>(`ax(`8?wx#eb`D;_ilV7TK-KGBBZs@t)Oa1?u&OH=SRvXXiXg3ANfRLDgSFNfQl&4kd{eUe_W`{qDLJ{UvGMBHhmV{>_FFSyGHPpU%n4u#fZ%JrgJV@^ zQD1)*5DL4U4%)K(&A`&lb!S%;tXMoTZOY{*cGI=RMW1*1YS+3_Qjs+)9ZUowMl_-# z6bfVCp5M@Z%a5CP?;_Ei07qOb%m&f2bNB9%PwL16&VzZ=Q#OuEO|3q8vJMe73LykK z?uM}Y=R?@E=_fR`-hn&Tj4yIuMxtkUSCYq*`Ly7J+VzAvAKzb{zhb{Inx~%m`wF!* z`%qJJ0Tz1<6f&^Q?jWZ-zH!>zr8!wkCR9JmVKt~*eOA26*3i%p?CkWzXjCvN!Gx%= zp(7ZE*Xv!kVPnafp`78$qXWmQsv_Chb4IkZT%YW6xv_Zu^oy#ne&?MqWx>kg!h=Ko aN%$9)FdK&{YN{##0000\d+)/edit/$', 'aggregate_crud', name='sample_resource_aggregate_edit'), +) + +urlpatterns = urlpatterns + patterns('sample_resource.controller.GUIdispatcher', + url(r'^create/(?P\d+)/(?P\d+)/$', 'create_resource', name='sample_resource_resource_create'), + url(r'^edit/(?P\d+)/(?P\d+)/(?P\d+)/$', 'resource_crud', name='sample_resource_resource_edit'), + url(r'^manage/(?P\d+)/(?P\w+)/$', 'manage_resource', name='sample_resource_resource_manage'), + url(r'^crud/(?P\d+)/(?P\d+)/$', 'resource_crud', name='sample_resource_resource_crud'), +) + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/utils/__init__.py b/expedient/doc/plugins/samples/plugin/sample_resource/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/utils/validators.py b/expedient/doc/plugins/samples/plugin/sample_resource/utils/validators.py new file mode 100644 index 00000000..90a79535 --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/utils/validators.py @@ -0,0 +1,28 @@ +''' +Created on Jan 14, 2013 + +@author: CarolinaFernandez +''' + +from django.core.exceptions import ValidationError +from django.core.validators import RegexValidator +import re + +RESOURCE_SR_RE = "^([0-9a-zA-Z\-]){1,64}$" +TEMPERATURE_SCALE_CHOICES = ( + ('C','Celsius'), + ('F','Fahrenheit'), + ('K','Kelvin'), + ) + +def validate_temperature_scale(scale): + """ + Validates the chosen temperature scale against the set 'indices'. + """ + if scale not in [ t[0] for t in TEMPERATURE_SCALE_CHOICES ]: + raise ValidationError("Invalid scale: please choose one from the list") + +validate_resource_name = RegexValidator(re.compile(RESOURCE_SR_RE), + u"Please do not use accented characters, symbols, underscores or whitespaces.", + "invalid") + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_add_resources.html b/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_add_resources.html new file mode 100644 index 00000000..f3143acd --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_add_resources.html @@ -0,0 +1,104 @@ +{% load ch_extras %} +{% block head %} + +{% endblock %} + + +{% block content %} + +{% for agg in sr_aggs %} + +{% endfor %} + + +{% endblock %} diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_aggregate_crud.html b/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_aggregate_crud.html new file mode 100644 index 00000000..e4611315 --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_aggregate_crud.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} + +{% block title %}{% if create %}Add SampleResource Aggregate{% else %}Update SampleResource Aggregate {{ aggregate.name }}{% endif %}.{% endblock title %} + +{% block content %} +
+
{% csrf_token %} + {# Aggregate Manager information #} +

{{ agg_form.non_field_errors }}

+ {{ agg_form.as_p }} + + {# Client information #} +

{{ client_form.non_field_errors }}

+ {{ client_form.as_p }} + +
+ {% if create %} + + {% else %} + + + {% endif %} + +
+
+
+{% endblock content %} diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_list_resources.html b/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_list_resources.html new file mode 100644 index 00000000..fc954cf7 --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_list_resources.html @@ -0,0 +1,77 @@ + {% if agg.resource_set.all %} +
+ + + + + + + + + + {% with agg.resource_set.all as resource_set %} + {# Order resources by name #} + {% regroup resource_set|dictsort:"name" by name as resource_set_ordered %} + {% for resource in resource_set_ordered %} + {# Get the first element within the list #} + {% with resource.list.0.sampleresource as sensor %} + + + + + + + + {# Surrounding SampleResource row #} + {% endwith %} + {% endfor %} + {% endwith %} +
+ Sensor name + + Temperature + + Temperature scale + + Interfaces + + Actions +
+ {{ sensor.get_name }} + + {{ sensor.get_temperature }} + + {{ sensor.get_full_temperature_scale }} + + {% for connection in sensor.get_connections %} + {{ connection.name }}{% if not forloop.last %}, {% endif %} + {% endfor %} + + Edit | Delete +
+
+ {% else %} +
+ The aggregate manager does not contain any sample resource yet, or this Expedient instance has not enough privileges to access current resources... +
+ {% endif %} + + + diff --git a/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_resource_crud.html b/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_resource_crud.html new file mode 100644 index 00000000..1c7e8afe --- /dev/null +++ b/expedient/doc/plugins/samples/plugin/sample_resource/views/templates/default/sample_resource_resource_crud.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} + +{% block title %}Add SampleResource to aggregate {{ agg.name }}.{% endblock title %} + +{% block head %} + +{% endblock %} + +{% block content %} +
+

Create a new Sample Resource in aggregate {{ agg.name }}

+ +
{% csrf_token %} + + + + + {% for field in form %} + {% if field.name != "resource_ptr"%} + + {% endif %} + {% endfor %} +
+ {% if exception != "" %} +
  • {{ exception }}
+ {% endif %} +
{{ field.label_tag }}: {{ field }}
+
+ | + Cancel +
+
+
+{% endblock content %} diff --git a/expedient/src/config/expedient/clearinghouse/apache/vhost-clearinghouse.conf b/expedient/src/config/expedient/clearinghouse/apache/vhost-clearinghouse.conf new file mode 100644 index 00000000..ab644782 --- /dev/null +++ b/expedient/src/config/expedient/clearinghouse/apache/vhost-clearinghouse.conf @@ -0,0 +1,7 @@ +# set the port to listen to! +#Listen 443 +Use SimpleSSLWSGIVHost 443 expedient/clearinghouse ${OCF_PATH}/expedient + +WSGIDaemonProcess monitor +WSGIScriptAlias / ${OCF_PATH}/expedient/src/wsgi/expedient/clearinghouse/mon.wsgi process-group=monitor application-group=%{GLOBAL} + diff --git a/expedient/src/config/expedient/common/apache/vhost-macros.conf b/expedient/src/config/expedient/common/apache/vhost-macros.conf new file mode 100644 index 00000000..e955fcc7 --- /dev/null +++ b/expedient/src/config/expedient/common/apache/vhost-macros.conf @@ -0,0 +1,340 @@ +# Written by Jad Naous + + +Error Missing mod_wsgi! Please install it. + + + + AuthType Basic + AuthName "$authname" + AuthBasicProvider wsgi + WSGIAuthUserScript $app_path/src/wsgi/$app_name/auth.wsgi application-group=$app_name + require valid-user + + + + # Do nothing! + # Dummy directive to avoid Apache complaining about empty contents + #LogLevel warn + + + + WSGIDaemonProcess $app_name processes=1 threads=1 + + + + WSGIDaemonProcess $app_name processes=6 threads=6 user=www-data + + + + #LogLevel: {debug|info|warn} + LogLevel warn + + WSGIScriptAlias $prefix $app_path/src/wsgi/$app_name/django.wsgi + WSGIScriptAlias $prefixadmin $app_path/src/wsgi/$app_name/django.wsgi + + Use $wsgi_daemon $app_name + WSGIProcessGroup $app_name + + + Order allow,deny + Allow from all + # Require SSL be used + SSLOptions +StrictRequire + Use $extra_dir_macro + + + + + + + # General setup for the virtual host + DocumentRoot "$app_path/src/static/$app_name" + + ErrorLog /var/log/apache2/$app_name/error_log + TransferLog /var/log/apache2/$app_name/access_log + CustomLog /var/log/apache2/$app_name/ssl_request_log ssl_combined + + # 2013-03-01. Do not require authentication to access /xmlrpc/sfa/ location + + Allow from all + Satisfy any + + + # 2014-10-8. Do not require authentication to access /xmlrpc/geni/3/ location + + Allow from all + Satisfy any + + + # Require authentication to access xmlrpc locations + # + + Use BasicAuth "RPC Auth" $app_name $app_path + + + Alias $prefixstatic $app_path/src/static/$app_name + + + Order deny,allow + Allow from all + + + Alias $prefixadmin/media /usr/lib/python2.6/site-packages/django/contrib/admin/media + + + Order deny,allow + Allow from all + + +# Alias /favicon.ico $app_path/src/static/$app_name/media/default/img/favicon.ico + + Use WSGISetup $app_name $prefix $app_path $extra_dir_macro MultiWSGIDaemonProcess + + Use $extra_macro + + # SSL Engine Switch: + # Enable/Disable SSL for this virtual host. + SSLEngine on + + # Avoid unsafe versions of SSL + #SSLProtocol ALL -SSLv2 + SSLProtocol All -SSLv2 -SSLv3 + #SSLProxyProtocol ALL -SSLv2 + SSLProxyProtocol All -SSLv2 -SSLv3 + + # Get SSL vars such as REMOTE_USER + SSLOptions +StdEnvVars + # Get the certs too + SSLOptions +ExportCertData + + # Get the username from the client ceritificate when present + SSLUserName SSL_CLIENT_S_DN_CN + + # SSL Cipher Suite: + # List the ciphers that the client is permitted to negotiate. + # See the mod_ssl documentation for a complete list. + SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM + + # Server Certificate: + # Point SSLCertificateFile at a PEM encoded certificate. If + # the certificate is encrypted, then you will be prompted for a + # pass phrase. Note that a kill -HUP will prompt again. Keep + # in mind that if you have both an RSA and a DSA certificate you + # can configure both in parallel (to also allow the use of DSA + # ciphers, etc.) + SSLCertificateFile $certs_path/ssl.crt/server.crt + + # Server Private Key: + # If the key is not combined with the certificate, use this + # directive to point at the key file. Keep in mind that if + # you've both a RSA and a DSA private key you can configure + # both in parallel (to also allow the use of DSA ciphers, etc.) + SSLCertificateKeyFile $certs_path/ssl.key/server.key + + # Server Certificate Chain: + # Point SSLCertificateChainFile at a file containing the + # concatenation of PEM encoded CA certificates which form the + # certificate chain for the server certificate. Alternatively + # the referenced file can be the same as SSLCertificateFile + # when the CA certificates are directly appended to the server + # certificate for convenience. + SSLCertificateChainFile $certs_path/ssl.crt/ca.crt + + # Certificate Authority (CA): + # Set the CA certificate verification path where to find CA + # certificates for client authentication or alternatively one + # huge file containing all of them (file must be PEM encoded) + # Note: Inside SSLCACertificatePath you need hash symlinks + # to point to the certificate files. Use the provided + # Makefile to update the hash symlinks after changes. + #SSLCACertificatePath $certs_path/ssl.crt + #SSLCACertificatePath $certs_path/ssl.crt/ca_clients + + # All-in-one file for CA that issue incoming certificates (e.g. AMs): + # This directive sets the all-in-one file where you can assemble + # the Certificates of Certification Authorities (CA) whose + # clients you deal with. These are used for Client Authentication. + # Such a file is simply the concatenation of the various PEM-encoded + # Certificate files, in order of preference. This can be used + # alternatively and/or additionally to SSLCACertificatePath. + # See: http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#sslcacertificatefile + SSLCACertificateFile $certs_path/ssl.crt/ca_clients.crt + + # Certificate Revocation Lists (CRL): + # Set the CA revocation path where to find CA CRLs for client + # authentication or alternatively one huge file containing all + # of them (file must be PEM encoded) + # Note: Inside SSLCARevocationPath you need hash symlinks + # to point to the certificate files. Use the provided + # Makefile to update the hash symlinks after changes. + SSLCARevocationPath $certs_path/ssl.crl + + # Client Authentication (Type): + # Client certificate verification type and depth. Types are + # none, optional, require and optional_no_ca. Depth is a + # number which specifies how deeply to verify the certificate + # issuer chain before deciding the certificate is not valid. + SSLVerifyClient optional + SSLVerifyDepth 10 + + SetEnvIf User-Agent ".*MSIE.*" \ + nokeepalive ssl-unclean-shutdown \ + downgrade-1.0 force-response-1.0 + + + + + + # Macro to use opensuse defaults for most things + Use SSLWSGIVHost "_default_" $port "/" $app_name $app_path /etc/apache2 EmptyMacro EmptyMacro + + + + + + + # General setup for the virtual host + #DocumentRoot "$app_path/src/static/$app_name" + #DocumentRoot "$app_path/src/static2/$app_name" + DocumentRoot "$app_path/src/python/$app_name/views/static" + + ErrorLog /var/log/apache2/$app_name/error_log + TransferLog /var/log/apache2/$app_name/access_log + CustomLog /var/log/apache2/$app_name/ssl_request_log ssl_combined + + + Allow from all + Satisfy any + + + # 2014-10-8. Do not require authentication to access /xmlrpc/geni/3/ location + + Allow from all + Satisfy any + + + # Require authentication to access xmlrpc locations + + Use BasicAuth "RPC Auth" $app_name $app_path + + + #Alias $prefixstatic $app_path/src/static/$app_name + #Alias $prefixstatic $app_path/src/static2/$app_name + Alias $prefixstatic $app_path/src/python/$app_name/views/static + + # + # + + Order deny,allow + Allow from all + + + Alias $prefixadmin/media /usr/lib/python2.6/site-packages/django/contrib/admin/media + + + Order deny,allow + Allow from all + + + Use WSGISetup $app_name $prefix $app_path $extra_dir_macro MultiWSGIDaemonProcess + + Use $extra_macro + + # SSL Engine Switch: + # Enable/Disable SSL for this virtual host. + SSLEngine on + + # Avoid unsafe versions of SSL + #SSLProtocol ALL -SSLv2 + SSLProtocol All -SSLv2 -SSLv3 + #SSLProxyProtocol ALL -SSLv2 + SSLProxyProtocol All -SSLv2 -SSLv3 + +# Get SSL vars such as REMOTE_USER + SSLOptions +StdEnvVars + # Get the certs too + SSLOptions +ExportCertData + + # Get the username from the client ceritificate when present + SSLUserName SSL_CLIENT_S_DN_CN + + # SSL Cipher Suite: + # List the ciphers that the client is permitted to negotiate. + # See the mod_ssl documentation for a complete list. + SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM + + # Server Certificate: + # Point SSLCertificateFile at a PEM encoded certificate. If + # the certificate is encrypted, then you will be prompted for a + # pass phrase. Note that a kill -HUP will prompt again. Keep + # in mind that if you have both an RSA and a DSA certificate you + # can configure both in parallel (to also allow the use of DSA + # ciphers, etc.) + SSLCertificateFile $certs_path/ssl.crt/server.crt + + # Server Private Key: + # If the key is not combined with the certificate, use this + # directive to point at the key file. Keep in mind that if + # you've both a RSA and a DSA private key you can configure + # both in parallel (to also allow the use of DSA ciphers, etc.) + SSLCertificateKeyFile $certs_path/ssl.key/server.key + + # Server Certificate Chain: + # Point SSLCertificateChainFile at a file containing the + # concatenation of PEM encoded CA certificates which form the + # certificate chain for the server certificate. Alternatively + # the referenced file can be the same as SSLCertificateFile + # when the CA certificates are directly appended to the server + # certificate for convenience. + SSLCertificateChainFile $certs_path/ssl.crt/ca.crt + + # Certificate Authority (CA): + # Set the CA certificate verification path where to find CA + # certificates for client authentication or alternatively one + # huge file containing all of them (file must be PEM encoded) + # Note: Inside SSLCACertificatePath you need hash symlinks + # to point to the certificate files. Use the provided + # Makefile to update the hash symlinks after changes. + #SSLCACertificatePath $certs_path/ssl.crt + #SSLCACertificatePath $certs_path/ssl.crt/ca_clients + + # All-in-one file for CA that issue incoming certificates (e.g. AMs): + # This directive sets the all-in-one file where you can assemble + # the Certificates of Certification Authorities (CA) whose + # clients you deal with. These are used for Client Authentication. + # Such a file is simply the concatenation of the various PEM-encoded + # Certificate files, in order of preference. This can be used + # alternatively and/or additionally to SSLCACertificatePath. + # See: http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#sslcacertificatefile + SSLCACertificateFile $certs_path/ssl.crt/ca_clients.crt + + # Certificate Revocation Lists (CRL): + # Set the CA revocation path where to find CA CRLs for client + # authentication or alternatively one huge file containing all + # of them (file must be PEM encoded) + # Note: Inside SSLCARevocationPath you need hash symlinks + # to point to the certificate files. Use the provided + # Makefile to update the hash symlinks after changes. + SSLCARevocationPath $certs_path/ssl.crl + + # Client Authentication (Type): + # Client certificate verification type and depth. Types are + # none, optional, require and optional_no_ca. Depth is a + # number which specifies how deeply to verify the certificate + # issuer chain before deciding the certificate is not valid. + SSLVerifyClient optional + SSLVerifyDepth 10 + + SetEnvIf User-Agent ".*MSIE.*" \ + nokeepalive ssl-unclean-shutdown \ + downgrade-1.0 force-response-1.0 + + + + + + # Macro to use opensuse defaults for most things + Use SSLWSGIVHostVT "_default_" $port "/" $app_name $app_path /etc/apache2 EmptyMacro EmptyMacro + + diff --git a/expedient/src/doc/expedient/Makefile b/expedient/src/doc/expedient/Makefile new file mode 100644 index 00000000..b22d5ed4 --- /dev/null +++ b/expedient/src/doc/expedient/Makefile @@ -0,0 +1,142 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build +SRCDIR = ../../python +EXPEDIENTDIR = $(SRCDIR)/expedient +OPENFLOWDIR = $(SRCDIR)/openflow/plugin + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Expedient.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Expedient.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Expedient" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Expedient" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +apidocs: + PYTHONPATH=$(SRCDIR) \ + DJANGO_SETTINGS_MODULE=expedient.clearinghouse.settings \ + epydoc -v --html -o $(BUILDDIR)/html/api --name Expedient \ + --url http://yuba.stanford.edu/~jnaous/expedient/ \ + --graph classtree \ + $(EXPEDIENTDIR) $(OPENFLOWDIR) + diff --git a/expedient/src/doc/expedient/source/admin/index.rst b/expedient/src/doc/expedient/source/admin/index.rst new file mode 100644 index 00000000..1865ec5c --- /dev/null +++ b/expedient/src/doc/expedient/source/admin/index.rst @@ -0,0 +1,9 @@ +Administering Expedient +####################### + +.. toctree:: + :maxdepth: 2 + + install + openflow +.. tutorial diff --git a/expedient/src/doc/expedient/source/admin/install.rst b/expedient/src/doc/expedient/source/admin/install.rst new file mode 100755 index 00000000..642ded48 --- /dev/null +++ b/expedient/src/doc/expedient/source/admin/install.rst @@ -0,0 +1,472 @@ +.. _admin-install: + +Installing Expedient +==================== + +There are currently two ways to install Expedient. If you're developing just a +plugin, you can use the RPM install method: + +* :ref:`admin-rpm-install` +* :ref:`admin-git-install` + +.. _admin-rpm-install: + +Install Using an OpenSuSE RPM +----------------------------- + +You will need to do the following: + +#. :ref:`admin-rpm-install-repos` +#. :ref:`admin-rpm-install-configure` +#. :ref:`admin-rpm-install-database` +#. :ref:`admin-rpm-install-apache` +#. :ref:`admin-rpm-install-finalize` +#. :ref:`admin-rpm-add-cron` + +.. _admin-rpm-install-repos: + +Setup Repositories and Install RPMs +................................... + +There are prebuilt OpenSuSE 11.1, 11.2, and 11.3 packages +available. + +You can install them either using the single click wizard `1-Click Install`_ +and skip to :ref:`admin-rpm-install-configure` or manually. If the 1-Click +installer does not start, execute the following in a terminal:: + + $ sudo /sbin/OCICLI http://yuba.stanford.edu/~jnaous/expedient/expedient.ymp + +To install manually, you will need to add the repositories +using zypper and then install the packages. You will also need +to install Apache and MySQL. To add the required repositories:: + + $ sudo zypper addrepo -f http://download.opensuse.org/repositories/devel:/languages:/python/openSUSE_11.X python + $ sudo zypper addrepo -f http://download.opensuse.org/repositories/devel:/languages:/perl/openSUSE_11.X perl + $ sudo zypper addrepo -f http://download.opensuse.org/repositories/home:/jnaous:/expedient/openSUSE_11.X expedient + $ sudo zypper addrepo -f http://download.opensuse.org/repositories/Apache:/Modules/openSUSE_11.X/ Apache:Modules + $ sudo zypper addrepo -f http://packman.inode.at/suse/11.X packman + +Replace the X with the minor version for the OpenSuSE version you're using. + +Then install expedient, apache, and mysql, accepting the prompts to import the +GPG keys for the repos (option ``a``) and install the packages:: + + $ sudo zypper install python-expedient expedient-servers + +.. _1-Click Install: data:text/x-suse-ymu,http://yuba.stanford.edu/~jnaous/expedient/expedient.ymp + +.. _admin-rpm-install-configure: + +Configure Local Settings +........................ + +Next we'll need to configure the local settings. Open +:file:`/etc/expedient/localsettings.py`:: + + $ sudo /etc/expedient/localsettings.py + +You can see more information on the settings at `defaultsettings +documentation`_. Below is a list of the settings that need to be changed: + +* ``ADMINS``: Set this to ``[("", "")]``. See admins_. +* ``EMAIL_HOST``: Set this to the hostname of your smtp + server. e.g. ``"smtp.gmail.com"``. You need check the other email settings + for the defaults. See email_. +* ``DEFAULT_FROM_EMAIL``: Set this to the email address you want users to see when + they receive mail from + Expedient. e.g. ``"no-reply@geni.net"``. See email_ +* ``GCF_BASE_NAME``: Set this to ``"//expedient"``. Replace + ```` with one alphanumeric word. Do not use special + characters. e.g. ``"expedient:stanford"``. See gcf_. +* ``SITE_DOMAIN``: Set this to the fully-qualified domain name of the Expedient + server. e.g. ``"expedient.stanford.edu"``. See site_. +* ``SITE_IP_ADDR``: Used for testing. Set to your Expedient host's IP + address. e.g. ``"192.168.1.1"``. See openflowtests_. +* ``MININET_VMS``: Used for testing. Set to ``[("", + ssh port num)]``. e.g. ``[("192.168.1.2", 22)]``. This will only be needed if you + want to run the full OpenFlow tests. For more information, see + :ref:`openflow-tests` and openflowtests_. +* ``DATABASE_USER``: Set this to the user name for the database that you want to + use. Default should be fine for a new database + installation. See database_. +* ``DATABASE_PASSWORD``: Set this to the password for the + database user. See database_. + +Now to make sure that the syntax is correct, do the following:: + + $ PYTHONPATH=/etc/expedient python -c "import localsettings" + +If you get errors, go back to localsettings.py and fix them. + +.. _defaultsettings documentation: http://yuba.stanford.edu/~jnaous/expedient/docs/api/expedient.clearinghouse.defaultsettings-module.html + +.. _admins: http://yuba.stanford.edu/~jnaous/expedient/docs/api/expedient.clearinghouse.defaultsettings.admins-module.html + +.. _email: http://yuba.stanford.edu/~jnaous/expedient/docs/api/expedient.clearinghouse.defaultsettings.email-module.html + +.. _gcf: http://yuba.stanford.edu/~jnaous/expedient/docs/api/expedient.clearinghouse.defaultsettings.gcf-module.html + +.. _site: http://yuba.stanford.edu/~jnaous/expedient/docs/api/expedient.clearinghouse.defaultsettings.site-module.html + +.. _openflow: http://yuba.stanford.edu/~jnaous/expedient/docs/api/expedient.clearinghouse.defaultsettings.openflow-module.html + +.. _openflowtests: http://yuba.stanford.edu/~jnaous/expedient/docs/api/expedient.clearinghouse.defaultsettings.openflowtests-module.html + +.. _database: http://yuba.stanford.edu/~jnaous/expedient/docs/api/expedient.clearinghouse.defaultsettings.database-module.html + +.. _admin-rpm-install-database: + +Configure MySQL +............... + +If you have not installed or configured MySQL on your OpenSuSE installation +before, you'll need to do so now. + +First, start MySQL:: + + $ sudo /etc/init.d/mysql start + +Initial MySQL Setup +^^^^^^^^^^^^^^^^^^^ + +If you have not previously initialized MySQL and setup the root password, type:: + + $ sudo mysql_secure_installation + +You will be prompted for a password. Use None (i.e. just press Enter). Follow +the prompts to create a root password and setup your server (you can just +agree to all prompts). You can leave the password blank if you want. + +Add MySQL to start on reboot:: + + $ sudo /sbin/insserv mysql + +Expedient MySQL Setup +^^^^^^^^^^^^^^^^^^^^^ + +You will need to run a command to create the database user and the database +for Expedient. Execute:: + + $ PYTHONPATH=/etc/expedient expedient_bootstrap_mysql --rootpassword + +You will get an error about the server's secret key which you can ignore for +now. + +.. _admin-rpm-install-apache: + +Configure Apache +................ + +Now you need to configure Apache. The instructions here assume you have not +configured Apache before, and this is a new installation on OpenSuSE:: + + $ sudo /usr/sbin/a2enmod wsgi + $ sudo /usr/sbin/a2enmod ssl + $ sudo /usr/sbin/a2enflag SSL + $ sudo ln -s /etc/expedient/apache/vhost-clearinghouse.conf /etc/apache2/vhosts.d/ + +Add Apache to start on reboot:: + + $ sudo /sbin/insserv apache2 + +Now generate SSL certificates. Make sure you read the help for +:command:`gensslcert` if you need to customize the generated SSL +certificates (for example, to change the used common name):: + + $ gensslcert -h + $ sudo gensslcert + +.. _admin-rpm-install-finalize: + +Finalize the Setup +.................. + +Create a secret key for the server, and setup the database:: + + $ sudo PYTHONPATH=/etc/expedient expedient_manage create_secret_key + $ sudo PYTHONPATH=/etc/expedient expedient_manage syncdb --noinput + $ sudo PYTHONPATH=/etc/expedient expedient_manage create_default_root + $ sudo /etc/init.d/apache2 restart + +Don't forget to open the ports in your firewall. You can do that by editing +the ``FW_SERVICES_EXT_TCP`` variable in +:file:`/etc/sysconfig/SuSEfirewall2` and include port +``443``. Then restart the firewall:: + + $ sudo /sbin/rcSuSEfirewall2 restart + +You can completely disable the firewall:: + + $ sudo /sbin/rcSuSEfirewall2 stop + $ sudo /sbin/insserv -r SuSEfirewall2_setup + $ sudo /sbin/insserv -r SuSEfirewall2_init + +Test that you can login and register new users. + +You can run the internal tests by executing:: + + $ PYTHONPATH=/etc/expedient expedient_manage test_expedient + +Caveat: 8 of those tests will fail (some of the rpc4django tests). This +is a known bug. You can run those tests separately with:: + + $ PYTHONPATH=/etc/expedient expedient_manage test rpc4django + +They should pass then. + +.. _admin-rpm-add-cron: + +Add Expedient Cron Job: +....................... + +The last thing you need to do is add a cron job that will call:: + + PYTHONPATH=/etc/expedient expedient_manage run_timer_jobs + +every 15 or 30 minutes, depending on the timer resolution you prefer. + +.. _admin-git-install: + +Install From Git +---------------- + +Installing from Git is the best way to create a development environment. + +#. :ref:`admin-git-install-repo` +#. :ref:`admin-git-install-dependencies` +#. :ref:`admin-git-install-configure` +#. :ref:`admin-git-install-database` +#. :ref:`admin-git-install-apache` +#. :ref:`admin-git-install-finalize` + +.. _admin-git-install-repo: + +Checkout the Repository +....................... + +For read-only access:: + + $ git clone git://openflow.org/expedient + +For read-write access, you'll need to have your public key added to gitosis, then:: + + $ git clone git@openflow.org/expedient + +.. _admin-git-install-dependencies: + +Install Package Dependencies +............................ + +Expedient depends on the following non-Python packages: + +* python >= 2.6 +* xmlsec1 +* libxmlsec1-openssl-devel + +If you want to use + +Expedient also depends on the following Python packages: + +* setuptools +* django >= 1.2, < 1.3 +* django_extensions +* django_evolution +* django-autoslug +* django-registration >= 0.7, < 0.8 +* decorator +* m2crypto +* PIL +* python-dateutil +* pycrypto +* paramiko +* django-renderform +* webob +* pyOpenSSL +* pyquery +* sphinx +* pygments +* libxslt-python +* ZSI +* MySQL-python >= 1.2.1p2 + +If you install ``setuptools``, and you have their dependencies +installed, you can install all of these packages using :: + + $ sudo easy_install + +Notes on Installing on Windows with Cygwin +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Cygwin is a little bit annoying because it is not exactly +a Linux environment. Make sure you install the following packages +using your Cygwin's setup.exe before installing the above dependencies: + +* gcc +* gcc-g++ +* swig +* python +* libxml2 +* libxml2-devel +* libxslt +* libxlst-devel +* python-libxml2 +* python-libxslt +* python-paramiko +* python-crypto + +You will also need to install MySQL on the machine before continuing +and making sure mysql-config is on the path (this can be done by +simply selecting the option to add the executables to the PATH +environment variable during the MySQL installaion). + +Open the cygwin bash command prompt, and execute the following: + + $ cd /usr + $ find -name '*.dll' > /tmp/dll.list + +Exit the Cygwin environment, close all cygwin processes (reboot is +preferred), then open the windows command prompt using the +:command:`cmd` command. Execute the following: + + > cd \bin + > ash + $ TMP=/tmp ./rebaseall -T /tmp/dll.list -v + +Once done, you can proceed with installing the dependencies. + +.. _admin-git-install-configure: + +Configure Local Settings +........................ + +Run the following command to create a skeleton :file:`localsetting.py` file:: + + $ cd expedient/src/python + $ PYTHONPATH=. python expedient/clearinghouse/bootstrap_local_settings.py expedient/clearinghouse/ + +Then edit the newly-created :file:`expedient/clearinghouse/localsettings.py` using your favorite editor. + +Take a look at the settings under defaultsettings_ to +understand all the available settings. The created settings in +:file:`localsettings.py` are the minimal ones required, and they +need to be set. + +.. _defaultsettings: http://yuba.stanford.edu/~jnaous/expedient/docs/api/expedient.clearinghouse.defaultsettings-module.html + +.. _admin-git-install-database: + +Configure a MySQL Database +.......................... + +If you have not installed or configured MySQL on your installation +before, you'll need to do so now. Since this part of the manual +is distro agnostic, you'll need to review your distro's +documentation for installing MySQL. + +You will need to do the following: + +#. Install MySQL somewhere and make sure it can be accessed from + the Expedient host. +#. Configure MySQL to allow Expedient to create its users and databases. + +For step 1 above on an OpenSuSE installation, look at :ref:`admin-rpm-install-database` + +For step 2 above, you can use an Expedient function:: + + $ cd expedient/src/python + $ PYTHONPATH=.:expedient/clearinghouse python -c 'from expedient.clearinghouse import settings; from expedient.clearinghouse.commands.utils import create_user; create_user("", "", settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME, settings.DATABASE_HOST or "localhost")' + +Replace ```` and ```` with your +database's root username and password. This will probably be +different than your OS's root username and password. + +You might get an error about the server's secret key which you +can ignore for now. + +.. _admin-git-install-apache: + +Configure Apache +................ + +Now you need to configure Apache. The instructions here assume +you have Apache installed and configured. Enable ``mod_macro``, +``mod_wsgi`` and ``mod_ssl`` according to your OS (you might need +to install them first). On OpenSuSE, you can do:: + + $ sudo /usr/sbin/a2enmod wsgi + $ sudo /usr/sbin/a2enmod ssl + $ sudo /usr/sbin/a2enmod macro + $ sudo /usr/sbin/a2enflag SSL + +Next you will need to edit a configuration file. Open +:file:`expedient/src/config/expedient/clearinghouse/apache/vhost-clearinghouse.conf`. + +In line 3, replace ``443`` with the port you want to use for Apache (note +you will need to make sure that port is enabled through the +firewall), and replace ``/home/expedient/expedient`` with the +path to your checked out Expedient tree. + +Edit +:file:`expedient/src/config/expedient/common/apache/vhost-macros.conf` +and replace the ``user=...`` on line 24 with ``user=:/xmlrpc/xmlrpc/``. The trailing slash is important. +* :guilabel:`Verify Certificates` should currently remain unchecked. Later + versions will use this boolean to decide whether or not to verify the + certificate chain coming back from the Opt-In Manager. + +After filling the form and clicking :guilabel:`Create`, you will be taken to a +page to add static links. This is where you can add links that are not +automatically discovered by the underlying infrastructure such as links +between OpenFlow Aggregates or between the OpenFlow Aggregate and other types +of resources such as PlanetLab nodes. + +You will need to click on :guilabel:`Add Link` to add the link. When done, +click on `Done`. You should see the aggregate added in the list of installed +aggregates in Expedient. If the aggregate has an OpenFlow switch, you should +see a non-zero number under the :guilabel:`Size` column and a green checkmark +under :guilabel:`Status`. + +Changes in the underlying infrastructure and topology should be automatically +reflected through callbacks in Expedient. + + +Configuring the GENI API +======================== + +The GENI API interface is automatically enabled. What is missing are the +certificates of trusted clearinghouses. These certificates need to be +installed wherever Apache stores its trusted certificate list for Expedient's vhost because it is +Apache that verifies that the certificate chain for incoming users are +correct. + +These certificates are installed wherever the ``GCF_X509_TRUSTED_CERT_DIR`` (see +settings_) in your :file:`localsettings.py` points. For a default +install, this would be +:file:`/etc/expedient/gcf-x509-trusted.crt`. Copy the new certificate +there. The next step is to link that certificate using its hash in the +``SSLCACertificatePath`` setting of your apache vhost file. In a default +package install, you can do this by running :command:`make` in :file:`/etc/expedient/apache/ca-certs`. You will also need to +restart Apache. *IMPORTANT*: The Makefile assumes that the certificates you +add all have a ``.crt`` extension. Only certificate files with that extension +work (a rename is sufficient). + +The XMLRPC URL for the GENI API is of the form +``https://:/openflow/gapi/``. +The trailing slash is important. + +.. _settings: http://yuba.stanford.edu/~jnaous/expedient/docs/api/expedient.clearinghouse.defaultsettings.gcf-module.html diff --git a/expedient/src/doc/expedient/source/conf.py b/expedient/src/doc/expedient/source/conf.py new file mode 100644 index 00000000..f2dddf60 --- /dev/null +++ b/expedient/src/doc/expedient/source/conf.py @@ -0,0 +1,220 @@ +# -*- coding: utf-8 -*- +# +# Expedient documentation build configuration file, created by +# sphinx-quickstart on Wed Aug 11 14:56:40 2010. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Expedient' +copyright = u'2011, Stanford University, Jad Naous' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.4.0' +# The full version, including alpha/beta/rc tags. +release = version + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Expedientdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'Expedient.tex', u'Expedient Documentation', + u'Jad Naous', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'expedient', u'Expedient Documentation', + [u'Jad Naous'], 1) +] + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/expedient/src/doc/expedient/source/developer/index.rst b/expedient/src/doc/expedient/source/developer/index.rst new file mode 100644 index 00000000..b3938dfd --- /dev/null +++ b/expedient/src/doc/expedient/source/developer/index.rst @@ -0,0 +1,9 @@ +Developing on Expedient +####################### + +This section attempts to explain how to develop with Expedient. + +.. toctree:: + :maxdepth: 2 + + tutorial diff --git a/expedient/src/doc/expedient/source/developer/slice-aggregate-resource-relationships.png b/expedient/src/doc/expedient/source/developer/slice-aggregate-resource-relationships.png new file mode 100644 index 0000000000000000000000000000000000000000..fa391c4f7e9ef2d9961ffec2df04a3de0dd1746d GIT binary patch literal 9417 zcmeHtXH-*Pvv)!?6bZ#fhae!Lf&>UiuS%05L1|K?3J6FSX#tTY5V}Yer6XNB0!r^l zhky}?bcl56?+N;U?(?qoKA+xCcisDe#X384X8-0lvuDqqeL^(V6=4*N6d(`?rmUo( z1p<-4K_D;#859^PyqJmy{(+sf6y-={8ogV92l8i1dd?sa-Ff04*eY!Rcm>4Za!1z% z~4)nnebqJm1;tNJl1=zX&F^Mq#b7jqTXvkP&GhCd|Q)WJ$K zXQ2kc^fVjSWH1s-Bta}Bkz_A<6)4Hp!TlVV^S43tG>vG`y(Tm~z~?F@8J?adK+}_z z>lsZa88e8IOwPh1wo&#P$1@N=oGk9=eG=02utsnr8m=9$NX{G}Ktc+F_-pF@?+gE# zrDU+{;y`A~V77+w+_+VmMbOP_|6(&ci0@I=FFq}!v{K_V-{ZZMGONC|WO4V16p5IB z(VR@Bd}+4(t)R}TL>o#&vV3#q^)2X$a0@zkvAC%E`T7-cZ>S%Hp9^xuV`;3!Oy|47 zF|V}zlTMF|kbx_R%fdO>NQ%Isi;yeB)CY;NofM4H&p=t`GKc3F{6d#XWA#1KP^>Lz zg^M-sX=0|;NyzONm!CDfk;3$o50)GMM6P*fB>KaRuFhS%KdU1HgLg?_$IWfndGw)o8F^E(4AD(UtQTqP0HX z*`$S-SVQUgGI$VU?*-8V0>QQxRRScQ#ccN+q4`a0L%jZyd3181Y#h zc)zmqz!q{?sAV0doYWhl>`?7{^pUI^8Wqf$!s%ISp5zsUwN7}2@RYEPP0g}IOqJab zE5Hjsyh5jkE$2X(SH&k%mgi?-L&c=7nYi$+8n25Jme+KKJDrjBirDj1h6e~2D-@0( zkeQ4DcTlcO_Rc0kn~fHAcW-h>5I)MoN}R4tjJ7ND_%8oS8s%rFr%9*>J0f^b*t+PB z38tlxxHL9Xoge8E_szuX!66Lb6N1fL^#Ea-iENL`jp^8Zqm3T>X!1_Zd7<*t8SFhl z2SOPmLU2QSUL5phTtvN~d`cCf<~=kK(erx8 zbF5s=9KG$VT_B+|>vA*C>tc2eU$9tbF9KQ-uwZ;IPg!qAb%KrnC}}V{gKTK>wv-|C)kZRB1)NfvvVFooGb~QkZOHLLFD9BTj@-(q~iBRvHL?Yt!3?){bR1 zKiSEuP+wz&a$4O_?|)>&MhtulnWr5RncO!s{cT9oV~-ZSry3Maa5%j;l!wSg`AR|`^tE-RgwXA!(>4&d&Es8kzk9jX2fw=Fgs#4l@M^d%B|L8dlg{0 z4WQChf{Yog#Z4+G>24%t*0oBLn{k&XKeel@2r=!&`aludqU2N%68gx;8&4Mf1FpQ) zFRpHCsXD4Y^fjQePI4pl1KH82~(+Y0iGA&;?8LB zS{ut-_c*kp+`Bd>dJaN@vX*0!+qo{9snba1ztdSe;uhE&XXs%cOqj;7BO3-EIY~j! zq^tNrih=EGR}h=;BmQG#qE~B&bgB0PP@MoJhe-jHb0=q4AFJ1SEHedcbN-rle}Hbb zpg&Eq%yy}3{Qk^PUQrf%^O_b~hEyglYA(>5N+R*S%TM{Zi;IXu~A=D<>^!*4p8LuQz7m`_= z>6L+u3GTCU|6haZnTzokzW1pwdNOYtxhI2JA^!aX8`u0^0xr;||Cl^}8~d!`cqIS{ z4`&r5c!tRm1)~2ENVcyw<-fSMOKYadtSt*r$9w(HTpZ8RF3@l+HRhr+rX+z<@`hsD$QOAr!}4(ux7TW4!IOhm{lZ(5oIyuGVmQe`Sv zv5{qwT5*XMv~a0t^a*86!uISI^vJO2^;!B~RV5cd{^UJeWuIXp$jR|vnoT-auHwC# zxEXiw_d1?So{=~Qh4-PAkQ@7f1`x!H{9}72h(8#d@De;e`b@RyfYB#?nvUuC{j{Rr zncWvnY4b)Fi!NRF#d#s14yZ!diK~8i-3^*F_eDaXGadPgI3-!*&<(hV$YcQ&{{e;( zIaF`*RmfvM8G07W}*|5 z0;A5adBfQ5U)WHEX$T)$H>uKcI3>1Q)uuP;9xR^uDTv< z`_%cWLScr~&@ZJX?(*{+Ot5)?9b-n;Yu1`)(dH1Rpu%snZPQ2lfLYKpCT>^F)4tPk zD6h<`p_a_VxHyI*Zwc4Y>Ive@L~R2>Am|wgNwNKfQpF^#-Q`Cc2cJIPKnbu7@-XBE z9y&Jp!m2IFKqfMPxyuOlV>v~8mAi>3=^T^*CZBw7IMA2briTX9h&GV{jaVoolb4_b z2FBc!4kTC~I!|YrOO5_=T1Co(fO8QTtZRjAR_kbge^*4fu5x;Qi;toD!S4ORcl)&; z8A#AzFeRDHs!e`6_O5lVApnR7{?&#jJG7LqDa5*a(70{P<}8uX`xsN7BnJq;xp zXb8a$Oxw@Otwk?-6RQPI5X?9RY7t2aSCs&aC?Z?9nR1Ku=@B z4GPnN5l5Q#eBc|-fR6%FK>Y7dg={H_Os||l(-JiiT|=Dgem)T?5g+sn=x#0%AyJH; z21H-Z_%)H87#jfpCbL%q0CRy?fKX{{{m&Xs4gaf7*j^5>ji?NuBut+OjOa|j-TW%Z ze^Zw;OanNAhyWmjN#x%E{n3#1!Y7ngim@@(x$OvNcKUvU4Uvu5-mVL@AFwUytOUPP zU<&t$!`i(a9~kClKPJ1M&fMJ>09f^LF}dy3690dn?ZYY8|1XHeju-xu`TyW0@^bNy z6o4M|bdop^FbG)jA?c4vM3HBMj<21<{}Ka)TO+*H?2USXl17`3TKU(b2qLe52S7Qd zQcnjL2_kit=eKYP-(lxYy#%nOX)g8X!K^CnhhGLh<^KPOwVE(O*O;_ymj{l8o+(dx4jF_QUV_Hmvr;tQbia zu~cP-uJ`%*VEUe%ok4uIduX2~`SI>!--x|m-_!n5gpPYCy|ei4*5LJ%)oo9Sbd;c? z5Cg72l1U`*@fb?q(S#U}z(O$b9>&V)Z`j6iApS?$hs%;Zr{SZ#21ecqOTegDckK=e~uM>W^vD5tTM=F ztsGj}ZO;k3Y1u=A)a0&9OBv{MAM%`X>_t%$qifEFzwmt~MX3(y@1!A@$&Xp)xP;-C zTm=lK-K}~IV_R0-AHm=58ti&t9Qn+M!N@N%JIyHOTQuFb)ld{7k=^ouq3{96Ox4J} z>M&u~l31jCw@cThm+31D^U^<$Qm+H+5D2<51lx{!^sPjN{iJkpIg&t&%EzPHYjC~J zM0T45^*d67muA`LLY)~;^P%ViNjKZChx#VoVWg(s%-^+pkR{eh~b+)l$;m;6}*V1f%BU9Y=0*rp*isGnkr7XSA+0XeTZ6~tdkeny= z{VQ)BG9W3Wo^`Ss%`y5$7e#$PT6&i}M8cv5w>vuR@9vFP~V$HajoMIL*ZuAq5l zn|1O0-0ALOQrK8Kv(5v4lFAtS<>8$QhLx%% zz9L}9Y!`}X`-iX*8>!@|-&K`!%_1%-p;NRMW}uz6VTgNw<2JD{y<`o@!Na$Qh&vR4>!c>e@9x#-m>jAQa;P^ zUY^t+qIJ72mETzIvP(6_Bwz%^il+)QPg)SS2VP%|1s$r2x-cy&9Yx(JGP za}2j_;OVZ$zj$K~!h6Jel4Yw>l|AO8RFvZ|sC6O?HFs)@L&^iig*1@Q@I7shSgv$rwWyAyi=2JwzHgpaV$W}@0bW9;E_*cT#h%pSTwGmLFXSx9&3?u z8SGW*6uoy4R?R~trqz?@mIL)+a}@L_r~vE{kwVh{`sADJf->(n>G!ZOf{wiJ;7D!S zyqvO+6iNUIY;Wk>w{#(2slZC}#+Ba}Nh71{V&^gyZe{K_84!d7So`yz?1SedxnfE! zgXyFCkcYulAf?k&%&h))qz{I}fY8m`G8dFj4v}qs$%&PJD0~Ofj#pD&$zSrTq%?GY9c$e4N{>u zNbztJUp{Jt^;j;bMl6;klQw^OStr5z4J!Vqr&H8 z8xGxVRlxK^@_gxMDcg+(pM>t|?k2L2F6|ZfNo&wAw7%9u_-gr;w)fq>I!g|;88nnj zDd;1oDn=ojB}+VS4PQvD?DSoL)~uV3Fwnj}5M@*ZIuzH>L@=QFS?OtQ@3w!q5G}|| zkFlP+4{-O^4?@GwiN7E40{=hsA|+e%4WHqJsQ3PsMXL9Xo?E-he_bF+7*;)-Hq5A# zvcO569BztR^`%aUy00-?&5-<;klXiM(_~TSxjYv9^QGKuHzTk0mLIq*dKv`F4wCMc z5&mhi#}ClGVRZW|^_y=*GfZz3#Y_hE>w36s1E=7Y60p-!*xS%JH(78F_iN7=&ZtwtQqCEoLoS10Wj&cxa6`;Au~ zO!-*u)@W`{Fp4c8;KkYy)1(zFbd*u_POQ`GXV^PxIqqBm_??O`*tyEsN!$b8zMeN5 zhP7*7V~8E#+(0&MCl58aL97-^y;{c0v_r5%{W*jLGUvGFl|)42C^;)o-3 z=vhgiB(4Ygw4u6dxpAmw8r_%hy%9V4un+zsL3D`_G-;s>I5TzVe5&Y^QkQl2q#$ZOn!e`Snj zKdd~W3-I1HloOv83`{e`pT{| zRWb1c+N~SXV5zRGw*kM}@L~WNIYFRfOb!x)^Xv^6xwx%TiwYlq((aiRuw*s-45qCP z%ouxQiv6SngIp*m<^n11pV-#H}ieGu5MnlUn#YaGi8yDylX zp>1HQ(t&wcp~d{7AswbPYV`@nJ-=sy!~mEtLS|AFN`8c=WRz0|!x9oWDvHRf_v_n= zSGOmPCV}fMXAwA$2BGjRYUScRoKJ0i-@rzG=P{1bPGo2bnP{`<20F2exBHKI)qRYW)PO+xD!2UV(*q?r=Sc4y7Eaak&@=Hv0ZSrRvnI)P zII@EexnCaK&7DI}jckcsfi+0Y}ftb#0hZ?>+jsum3usW%(5EvUDPKlkm*^I3<6w` z(vDdH7vLI}v)v(e$x~okbb7_JI>Y3`9W1ZGPH5H^1228#P9r#>7Q9Ycs@a?K7F9DO zY%$<2dBt}sa^O%HZ^$ot;2P6r(JoP=4;iq!q=98#s{J_uRlsXhj-A*abnjfh^7C@7 z@M9U`g~uAS+1Kux)lfH&w^XHcJC-?Fz#_WTUg=FPnO%N7c=5pdaCZ{#$RL0z96?uI zc(-ircg%aQ{($u>dMq?Za<5ih`@~zT@S^D&17rXQ5>C(lNiRA1&Iuna4y zv0tj~hKFJ&8DC_n0_%aWTVXZQem3W1&t`5PvAM7W3uak3^2|P(%ZVIh{)+zXoa(JE zaAFsK-yCqcc5^N3RS}uB;D3;&y!~Tq-Er#tKo*m1RaK1U2ia1l~Ve+bP zgr>Z$LGP9t+6!7KxmRc3(0<}B*>;uNc>i4MIDz8?_kb%mZW#gRxVA%?P@fN_dMu-m zu6Q&1y4!1mut>pHpaEmT0&Om$r;I`!evt~qf3661Nwb(k@r~6~%%{c-3QKB7-!jwa zQ9I&8Ivo+$xmpfzeL@JuQY98VZ1xxViL5^~@ICn6z?)XRig&~KMD%#idCg@~oGx}A zojRWuWW|t&wfg!EmSbENUmqXVx@&xcK`Y+Yed7kXTVmT=c7t#-yIM};eQMGzY57ri z9!Wm4x%+GW_d7x?RdvkRJ|=E7j3!{rQ$GNANZb&C?PRSRqa(fJX7k64IE&6|pwF(E z3EXs)fn{^<{_pn~|M`22|DUf`U{ESh^W)-I7lCHlD)42@pFXXL5M+Zy{0uyVfEbf& zMn@`wfdY^2cAEWfD)F=L;@E_f&5K_JgV`}8TkRh>seli6#%`ZbTi2z2;)@Tt2|R+7 M@2D#j%9;589|l!iO8@`> literal 0 HcmV?d00001 diff --git a/expedient/src/doc/expedient/source/developer/sshaggregate/__init__.py b/expedient/src/doc/expedient/source/developer/sshaggregate/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/src/doc/expedient/source/developer/sshaggregate/models.py b/expedient/src/doc/expedient/source/developer/sshaggregate/models.py new file mode 100644 index 00000000..4442c7cd --- /dev/null +++ b/expedient/src/doc/expedient/source/developer/sshaggregate/models.py @@ -0,0 +1,249 @@ +import shlex, subprocess +from StringIO import StringIO +from django.db import models +from django.db.models.fields import IPAddressField +import paramiko +from paramiko.rsakey import RSAKey +from expedient.clearinghouse.aggregate.models import Aggregate +from expedient.clearinghouse.resources.models import Resource, Sliver +from expedient.common.utils.modelfields import LimitedIntegerField +from expedient.common.middleware import threadlocals +from expedient.clearinghouse.utils import post_message_to_current_user +from expedient.common.messaging.models import DatedMessage +from expedient.clearinghouse.slice.models import Slice + +# SSHServer class +class SSHServer(Resource): + # SSHServer fields + ip_address = IPAddressField( + "IP address", + help_text="Specify the server's IP address.", + ) + ssh_port = LimitedIntegerField( + "SSH port number", + min_value=1, + max_value=2**16-1, + default=22, + help_text="Specify the SSH port number to use." + ) + # end + + def is_alive(self): + """Ping the server and check if it's alive. + + @return: True if ping succeeds, False otherwise. + """ + ret = subprocess.call( + shlex.split("ping -c 1 -W 2 %s" % self.ip_address), + stdout=open('/dev/null', 'w'), + stderr=subprocess.STDOUT, + ) + + if ret == 0: + return True + else: + return False + + def exec_command(self, command, **connection_info): + """Connect to the server using an SSH session and execute a command. + + @param command: The command to execute + @type command: C{str} + @param username: The username to use to connect to the server. + @type username: C{str} + @keyword connection_info: A dict of other info to pass to + C{paramiko.SSHClient.exec_command}. + @return: A (out, err) tuple that is the output read on the + stdout and stderr channels. + @rtype: C{tuple(str, str)} + """ + + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect( + str(self.ip_address), + port=int(self.ssh_port), + **connection_info + ) + _, sout, serr = client.exec_command(command) + o = sout.read() + e = serr.read() + client.close() + return o, e + + def __unicode__(self): + return u"SSH server at IP %s" % self.ip_address + +class SSHServerSliver(Sliver): + pass + +class SSHSliceInfo(models.Model): + slice = models.OneToOneField(Slice) + public_key = models.TextField() + +# SSHAggregate class +class SSHAggregate(Aggregate): + # SSHAggregate information field + information = "An aggregate of SSH servers that are controlled" \ + " by a single administrator, to which users can request" \ + " access. Once approved, users get SSH access to all" \ + " machines using a public key they provide." + # SSHAggregate end information field + + # SSHAggregate meta + class Meta: + verbose_name = "SSH Aggregate" + # SSHAggregate end meta + + # SSHAggregate required fields + admin_username = models.CharField(max_length=255) + private_key = models.TextField() + # SSHAggregate end required fields + + # SSHAggregate optional fields + add_user_command = models.TextField( + default="sh -c 'sudo useradd -m %(username)s'", + help_text="Specify the command to create a new user. " \ + "'%(username)s' will be replaced by the user's " \ + " username. The command should return non-zero on failure " \ + " and 0 on success.", + ) + del_user_command = models.TextField( + default="sh -c 'sudo userdel -r -f %(username)s'", + help_text="Specify the command to delete an existing user. " \ + "'%(username)s' will be replaced by the user's " \ + " username. The command should return non-zero on failure " \ + " and 0 on success.", + ) + add_pubkey_user_command = models.TextField( + default="sudo -u %(username)s mkdir /home/%(username)s/.ssh; " + "sudo -u %(username)s chmod 700 /home/%(username)s/.ssh; " + "sh -c 'sudo -u %(username)s echo %(pubkey)s >> " + "/home/%(username)s/.ssh/authorized_keys'", + help_text="Specify the command to add a public key to a user's " \ + "account. '%(username)s' will be replaced by the user's " \ + " username and '%(pubkey)s' will be replaced by the public key." \ + " The command should return non-zero on failure " \ + " and 0 on success.", + ) + # SSHAggregate end optional fields + + def _op_user(self, op, server, cmd_subs, quiet=False): + """common code for adding/removing users.""" + + pkey_f = StringIO(self.private_key) + pkey = RSAKey.from_private_key(pkey_f) + pkey_f.close() + + cmd = getattr(self, "%s_user_command" % op) % cmd_subs + cmd = cmd + "; echo $?" + out, err = server.exec_command( + cmd, + username=str(self.admin_username), + pkey=pkey, + ) + + lines = out.strip().split("\n") + ret = int(lines[-1]) + + if ret != 0: + error = "".join(lines[:-1]) + if not quiet: + # msg example + msg = "Failed to %s user on %s. Output was:\n%s" \ + % (op, server, error), + post_message_to_current_user( + msg, + msg_type=DatedMessage.TYPE_ERROR, + ) + # end msg example + raise Exception(msg) + + def add_user(self, server, username, pubkey, quiet=False): + """Add a user to a server. + + Add a user with username C{username} with public key C{pubkey} to + server C{server}. + + @param server: The server to add the user to. + @type server: L{SSHServer} + @param username: the new user's username + @type username: C{str} + @param pubkey: The public key to add to the user's account. + @type pubkey: the public key's value a C{str} + @keyword quiet: If True, no messages will be sent on failure. + Defaults to False. + @type quiet: C{boolean} + """ + self._op_user("add", server, {"username": username}, quiet) + self._op_user( + "add_pubkey", + server, + {"username": username, "pubkey": pubkey}, + quiet, + ) + + def del_user(self, server, username, quiet=False): + """Remove user from a server. + + Remove user with username C{username} from server C{server}. + + @param server: The server to remove the user from. + @type server: L{SSHServer} + @param username: the user's username + @type username: C{str} + @keyword quiet: If True, no messages will be sent on failure. + Defaults to False. + @type quiet: C{boolean} + """ + self._op_user("del", server, {"username": username}, quiet) + + def check_status(self): + return self.available and reduce( + lambda x, y: x and y.is_alive(), + SSHServer.objects.filter(aggregate__id=self.id), + ) + + # start_slice func + def start_slice(self, slice): + # start_slice call super + super(SSHAggregate, self).start_slice(slice) + # start_slice end call super + + # start_slice get info + slice_info = SSHSliceInfo.objects.get(slice=slice) + # start_slice get user + user = slice.owner + # start_slice get slivers + slivers = SSHServerSliver.objects.filter( + slice=slice, resource__aggregate__id=self.id) + # start_slice end info + + # start_slice loop + succeeded = [] + for sliver in slivers: + # Execute the command on the server and get status + server = sliver.resource.as_leaf_class() + # start_slice add user + try: + self.add_user(server, user.username, slice_info.public_key) + except: + for s in succeeded: + try: + self.del_user(s, user.username) + except: + pass + raise + + succeeded.append(server) + # start_slice end loop + + def stop_slice(self, slice): + super(SSHAggregate, self).start_slice(slice) + user = threadlocals.get_thread_locals()["user"] + for sliver in SSHServerSliver.objects.filter(slice=slice): + server = sliver.resource.as_leaf_class() + try: + self.del_user(server, user.username) + except: + pass diff --git a/expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/aggregate_add_servers.html b/expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/aggregate_add_servers.html new file mode 100644 index 00000000..72d522dc --- /dev/null +++ b/expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/aggregate_add_servers.html @@ -0,0 +1,30 @@ +{% extends "sshaggregate/sshaggregate_base.html" %} + +{% block title %}Add/Update SSH Servers in {{ aggregate.name }}.{% endblock title %} + +{% block head %} +{% endblock %} + +{% block content %} +
+

Add/Update SSH Servers in {{ aggregate.name }}

+ +
Add all servers that can be administered using the same information + here. You can click save to get more rows once you fill the existing + ones.
+ +
{% csrf_token %} + {{ formset.management_form }} + {% for form in formset.forms %} + {% for hidden in form.hidden_fields %} + {{ hidden }} + {% endfor %} + {{ form.as_p }} + {% endfor %} +
+ | + Home +
+
+
+{% endblock content %} diff --git a/expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/aggregate_crud.html b/expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/aggregate_crud.html new file mode 100644 index 00000000..ea26db27 --- /dev/null +++ b/expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/aggregate_crud.html @@ -0,0 +1,26 @@ +{% extends "sshaggregate/sshaggregate_base.html" %} + +{% block title %}Add/Update SSH Aggregate.{% endblock title %} + +{% block head %} +{% endblock %} + +{% block content %} +
+ {% if aggregate %} +

Update aggregate {{ aggregate.name }}

+ {% else %} +

Add aggregate

+ {% endif %} +
{% csrf_token %} + {{ form.as_p }} +
+ | + {% if aggregate %} + Delete | + {% endif %} + Cancel +
+
+
+{% endblock content %} diff --git a/expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/sshaggregate_base.html b/expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/sshaggregate_base.html new file mode 100644 index 00000000..94d9808c --- /dev/null +++ b/expedient/src/doc/expedient/source/developer/sshaggregate/templates/sshaggregate/sshaggregate_base.html @@ -0,0 +1 @@ +{% extends "base.html" %} diff --git a/expedient/src/doc/expedient/source/developer/sshaggregate/tests.py b/expedient/src/doc/expedient/source/developer/sshaggregate/tests.py new file mode 100644 index 00000000..614a4b65 --- /dev/null +++ b/expedient/src/doc/expedient/source/developer/sshaggregate/tests.py @@ -0,0 +1,243 @@ +import getpass, os +import re +from StringIO import StringIO +from paramiko.rsakey import RSAKey +from django.test import TestCase +from django.contrib.auth.models import User +from django.core.urlresolvers import reverse +from expedient.clearinghouse.slice.models import Slice +from expedient.common.permissions.models import ExpedientPermission +from expedient.clearinghouse.project.models import Project +from expedient.common.tests.client import test_get_and_post_form +from sshaggregate.views import aggregate_add_servers, aggregate_crud +from sshaggregate.models import SSHAggregate, SSHServer, SSHServerSliver,\ + SSHSliceInfo + +# Tests class +class Tests(TestCase): + # start constants + CREATED_USER_FNAME = "/tmp/created_user" + '''Where do we store the created user's username?''' + DELETED_USER_FNAME = "/tmp/deleted_user" + '''Where do we store the deleted user's username?''' + PUBKEY_USER_FNAME = "/tmp/pubkey_user" + '''Where do we store the created user's public key?''' + + TEST_SSH_KEY_NAME = "id_rsa_sshaggregate" + TEST_KEY_COMMENT = "ssh_aggregate_test_key" + # end + def create_test_ssh_key(self): + self.test_key = RSAKey.generate(1024) + self.test_pubkey = "\nssh-rsa %s %s\n" % \ + (self.test_key.get_base64(), Tests.TEST_KEY_COMMENT) + f = open(os.path.expanduser("~/.ssh/authorized_keys"), "a") + f.write(self.test_pubkey) + f.close() + + def delete_test_ssh_key(self): + f = open(os.path.expanduser("~/.ssh/authorized_keys"), "r") + auth_keys = f.read() + f.close() + new_auth_keys = re.sub( + r"\n.*%s\n" % Tests.TEST_KEY_COMMENT,"", auth_keys) + f = open(os.path.expanduser("~/.ssh/authorized_keys"), "w") + f.write(new_auth_keys) + f.close() + + def setUp(self): + # create local user + self.su = User.objects.create_superuser( + "su", "su@stanford.edu", "password") + # end + + # disable permissions + ExpedientPermission.objects.disable_checks() + # end + + # delete existing temp files + for f in Tests.CREATED_USER_FNAME, Tests.DELETED_USER_FNAME,\ + Tests.PUBKEY_USER_FNAME: + if os.access(f, os.F_OK): + os.unlink(f) + # end + + # create ssh key + self.create_test_ssh_key() + # end + + # login user + self.client.login(username="su", password="password") + # end + + def tearDown(self): + for f in Tests.CREATED_USER_FNAME, Tests.DELETED_USER_FNAME,\ + Tests.PUBKEY_USER_FNAME: + if os.access(f, os.F_OK): + os.unlink(f) + + self.delete_test_ssh_key() + + ExpedientPermission.objects.enable_checks() + + # add aggregate tests + def test_add_aggregate(self): + # end + + # check nothing is there + self.assertEqual(SSHAggregate.objects.count(), 0) + # end + + # get private key as string + pkey_f = StringIO() + self.test_key.write_private_key(pkey_f) + pkey = pkey_f.getvalue() + pkey_f.close() + # end + + # Add the aggregate + response = test_get_and_post_form( + self.client, + url=reverse(aggregate_crud), + params=dict( + name="Test Aggregate", + description="Aggregate on localhost", + location="right here", + admin_username=getpass.getuser(), + private_key=pkey, + add_user_command="sh -c 'echo %(username)s >> " + + Tests.CREATED_USER_FNAME + "'", + del_user_command="sh -c 'echo %(username)s >> " + + Tests.DELETED_USER_FNAME + "'", + add_pubkey_user_command="sh -c 'echo %(pubkey)s >> " + + Tests.PUBKEY_USER_FNAME + "'", + ), + ) + self.assertEqual(SSHAggregate.objects.count(), 1) + # end + + # where do we go next? + next_url = reverse(aggregate_add_servers, args=[1]) + self.assertRedirects( + response, next_url) + # end + + # Add the localhost as a server + response = test_get_and_post_form( + self.client, + url=next_url, + params={ + "form-0-name": "localhost", + "form-0-ip_address": "127.0.0.1", + "form-0-ssh_port": "22", + }, + ) + # end + + # check that localhost added + self.assertRedirects( + response, reverse(aggregate_add_servers, args=[1]), + msg_prefix="Response was %s" % response) + self.assertEqual(SSHServer.objects.count(), 1) + # end + + # slice tests + def test_create_delete_slice(self): + # end + + # Add the aggregate + self.test_add_aggregate() + agg = SSHAggregate.objects.all()[0] + # end + + # Create the project + self.client.post( + reverse("project_create"), + data=dict(name="Test Project", description="Blah blah"), + ) + project = Project.objects.get(name="Test Project") + # end + + # Add the aggregate to the project + url = reverse("project_add_agg", args=[project.id]) + response = self.client.post( + path=url, + data={"id": agg.id}, + ) + self.assertTrue(project.aggregates.count() == 1) + self.assertRedirects(response, url) + # end + + # Create the slice + self.client.post( + reverse("slice_create", args=[project.id]), + data=dict( + name="Test Slice", + description="Blah blah", + ) + ) + slice = Slice.objects.get(name="Test Slice") + # end + + # Add the aggregate to the slice + slice_add_agg_url = reverse("slice_add_agg", args=[slice.id]) + response = self.client.post( + path=slice_add_agg_url, + data={"id": agg.id}, + ) + self.assertRedirects(response, slice_add_agg_url) + self.assertEqual( + slice.aggregates.count(), 1, + "Did not add aggregate to slice.") + # end + + # Create a sliver + server = SSHServer.objects.all()[0] + SSHServerSliver.objects.create(resource=server, slice=slice) + # end + + # Create the SSHSliceInfo + SSHSliceInfo.objects.create( + slice=slice, public_key=self.test_pubkey) + # end + + # Start the slice + self.client.post(reverse("slice_start", args=[slice.id])) + # end + + # Check that the add command was executed correctly + self.assertTrue(os.access(Tests.CREATED_USER_FNAME, os.F_OK)) + f = open(Tests.CREATED_USER_FNAME, "r") + username = f.read() + f.close() + self.assertEqual( + username.strip(), self.su.username, + "Add user command not executed correctly. Expected to find '%s' " + "in %s, but found '%s' instead." + % (self.su.username, Tests.CREATED_USER_FNAME, username)) + # end + + # check that the add pub key command executed correctly + f = open(Tests.PUBKEY_USER_FNAME, "r") + pubkey = f.read() + f.close() + self.assertEqual( + username.strip(), self.su.username, + "Add pub key command not executed correctly. Expected to find " + "'%s' in %s, but found '%s' instead." + % (self.test_pubkey, Tests.PUBKEY_USER_FNAME, pubkey)) + # end + + # Stop the slice + self.client.post(reverse("slice_stop", args=[slice.id])) + # end + + # Check that the del user command executed correctly + f = open(Tests.DELETED_USER_FNAME, "r") + username = f.read() + f.close() + self.assertEqual( + username.strip(), self.su.username, + "Del user command not executed correctly. Expected to find '%s' " + "in %s, but found '%s' instead." + % (self.su.username, Tests.DELETED_USER_FNAME, username)) + # end diff --git a/expedient/src/doc/expedient/source/developer/sshaggregate/urls.py b/expedient/src/doc/expedient/source/developer/sshaggregate/urls.py new file mode 100644 index 00000000..d2d13715 --- /dev/null +++ b/expedient/src/doc/expedient/source/developer/sshaggregate/urls.py @@ -0,0 +1,7 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('sshaggregate.views', + url(r'^aggregate/create/$', 'aggregate_crud', name='sshaggregate_aggregate_create'), + url(r'^aggregate/(?P\d+)/edit/$', 'aggregate_crud', name='sshaggregate_aggregate_edit'), + url(r'^aggregate/(?P\d+)/servers/$', 'aggregate_add_servers', name='sshaggregate_aggregate_servers'), +) diff --git a/expedient/src/doc/expedient/source/developer/sshaggregate/views.py b/expedient/src/doc/expedient/source/developer/sshaggregate/views.py new file mode 100644 index 00000000..219e03a6 --- /dev/null +++ b/expedient/src/doc/expedient/source/developer/sshaggregate/views.py @@ -0,0 +1,58 @@ +from django.core.urlresolvers import reverse +from django.forms.models import modelformset_factory +from django.shortcuts import get_object_or_404 +from django.http import HttpResponseRedirect +from django.views.generic import simple +from expedient.common.utils.views import generic_crud +from expedient.common.messaging.models import DatedMessage +from expedient.clearinghouse.aggregate.models import Aggregate +from expedient.clearinghouse.utils import post_message_to_current_user +from sshaggregate.models import SSHAggregate, SSHServer + +def aggregate_crud(request, agg_id=None): + """Show a page for the user to add/edit an SSH aggregate in Expedient.""" + + return generic_crud( + request, + obj_id=agg_id, + model=SSHAggregate, + template_object_name="aggregate", + template="sshaggregate/aggregate_crud.html", + redirect=lambda inst: reverse( + aggregate_add_servers, args=[inst.id]), + success_msg=lambda inst: \ + "Successfully created/updated SSH Aggregate %s" % inst.name, + ) + +def aggregate_add_servers(request, agg_id): + """Show a page that allows user to add SSH servers to the aggregate.""" + + agg = get_object_or_404(SSHAggregate, id=agg_id) + servers = SSHServer.objects.filter(aggregate__id=agg_id) + ServerFormSet = modelformset_factory( + SSHServer, can_delete=True, extra=3, + fields=["name", "ip_address", "ssh_port"], + ) + + if request.method == "POST": + formset = ServerFormSet( + request.POST, queryset=servers) + if formset.is_valid(): + instances = formset.save(commit=False) + for instance in instances: + instance.aggregate = agg + instance.save() + formset.save_m2m() + post_message_to_current_user( + "Successfully added/updated servers "\ + "to aggregate %s" % agg.name, + msg_type=DatedMessage.TYPE_SUCCESS) + + return HttpResponseRedirect(request.path) + + else: + formset = ServerFormSet(queryset=servers) + + return simple.direct_to_template( + request, template="sshaggregate/aggregate_add_servers.html", + extra_context={"aggregate": agg, "formset": formset}) diff --git a/expedient/src/doc/expedient/source/developer/tutorial.rst b/expedient/src/doc/expedient/source/developer/tutorial.rst new file mode 100644 index 00000000..996f03d2 --- /dev/null +++ b/expedient/src/doc/expedient/source/developer/tutorial.rst @@ -0,0 +1,873 @@ +.. _dev-tutorial: + +Expedient Plugin Tutorial +######################### + +Expedient has two types of plugins that interact with each other: +:ref:`agg-plugins` and :ref:`ui-plugins`. This tutorial will guide through the +process of creation of both types of plugins. You'll first need to install +expedient. Please see :ref:`admin-install`. + +.. _agg-plugins: + +Aggregate Plugins +================= + +Aggregate plugins have three main tasks: + +#. Describe resources and their types to the Expedient database +#. Offer an API for other plugins to consume +#. Keep information about resources in an aggregate up-to-date + +In this tutorial, we will go through the process of writing a plugin for a +very simple type of aggregate, an SSH access aggregate consisting of a set of +SSH servers. We will write an aggregate plugin that allows +users on Expedient to request SSH access to SSH servers. The admin of the +SSH aggregate will get an email with a message from the user, +information about the user, and a link on Expedient for approving or +denying the request. + +If the admin approves the request, the plugin will create a login for the +user on each machine the user asks for, and add a public key provided by the +user. The plugin does that by storing a private key that can be used to login +to the server and execute the required commands. + +Preliminaries +------------- + +First, make sure that you have Expedient installed and that its packages are +in your python library path (PYTHONPATH environment variable). Then go through +the Django tutorial here_. Create a +package directory called :file:`sshaggregate` with the following files: + +* :file:`sshaggregate/__init__.py`: An empty file +* :file:`sshaggregate/models.py`: Will contain descriptions of our resources +* :file:`sshaggregate/views.py`: Will contain the plugin's views + +Also the directory hierarchy :file:`sshaggregate/templates/sshaggregate` that +will hold the templates for the plugin. + +.. _here: http://www.djangoproject.com/ + +Writing Models +-------------- + +There are several models that will need to be written. Mainly, the aggregate +model, the resources' models, and any additional info that needs to be stored. + +Edit the :file:`sshaggregate/models.py` so it looks like this: + +.. literalinclude:: sshaggregate/models.py + +Let's go through the code section by section. We use paramiko in order to +communicate with our SSH servers over SSH. Paramiko is a python SSH +library. + +SSHServer +......... + +The first class in our module is the :class:`SSHServer` class which +extends `Resource`_ class. The `Resource`_ class defines a few common fields +and operations for resources. All resources that can be reserved must inherit +from the `Resource`_ class: + +.. literalinclude:: sshaggregate/models.py + :start-after: # SSHServer class + :end-before: # SSHServer fields + +Most importantly, the resource is related to an +`Aggregate`_ by a foreign key relationship. Take a look at the `Resource`_ +class documentation before continuing. + +In the :class:`SSHServer` class, we just define +some extra fields and functions. An :class:`SSHServer` instance has an IP +Address and an SSH port number: + +.. literalinclude:: sshaggregate/models.py + :start-after: # SSHServer fields + :end-before: # end + +We also define two extra functions: +:func:`is_alive` and :func:`exec_command`. + +.. literalinclude:: sshaggregate/models.py + :pyobject: SSHServer.is_alive + +.. literalinclude:: sshaggregate/models.py + :pyobject: SSHServer.exec_command + +The :func:`is_alive` function pings the server and checks that it is up, while +the :func:`exec_command` function executes a command on the server using +:mod:`paramiko`. + +SSHServerSliver +............... + +A slice (represented by the `Slice`_ class) in Expedient is a container of +slivers of different types of resources and across different +aggregates. A sliver (represented by the generic class `Sliver`_) is the +reservation of one resource instance, and it relates the resource to the +slice. A sliver describes information about the reservation of that particular +instance. For example, if reserving a virtual machine, a sliver might describe +the CPU percentage reserved for the VM. + +When an aggregate is about to create a slice across its resources, it looks at +the slice and all the slivers that are for resources it controls. It then uses +those slivers to create the slice. We will see more information on creating a +slice later. + +In our example, we don't have any per sliver information, so our +:class:`SSHServerSliver` is empty: + +.. literalinclude:: sshaggregate/models.py + :pyobject: SSHServerSliver + +We could have also not created the class at +all, but it makes our code clearer. Take a look at the `Sliver`_ and `Slice`_ classes +documentation before continuing. + +SSHSliceInfo +............ + +Some types of resources might require some per-slice info. In our example, +creating a slice requires a public key for the user, so the SSHSliceInfo class +will store that required information: + +.. literalinclude:: sshaggregate/models.py + :pyobject: SSHSliceInfo + +SSHAggregate +............ + +This is the most involved class. The :class:`SSHAggregate` class extends the +generic `Aggregate`_ class. The `Aggregate`_ class defines some +functions and fields that are shared among all aggregate classes. Aggregate +plugins must always define an Aggregate_ class child. + +.. literalinclude:: sshaggregate/models.py + :start-after: # SSHAggregate class + :end-before: # SSHAggregate information field + +The :class:`SSHAggregate` class overrides the ``information`` field that +contains information about the aggregate and describes the aggregate +type. This field is used in the information page that describes the aggregate +type: + +.. literalinclude:: sshaggregate/models.py + :start-after: # SSHAggregate information field + :end-before: # SSHAggregate end information field + +We have modified the verbose name used in for aggregate to make it easier to +understand what the class is: + +.. literalinclude:: sshaggregate/models.py + :start-after: # SSHAggregate meta + :end-before: # SSHAggregate end meta + +It also adds a ``private_key`` and an ``admin_username`` fields that are used to +login to the servers for administering them. These must be the same for all +servers in the aggregate: + +.. literalinclude:: sshaggregate/models.py + :start-after: # SSHAggregate required fields + :end-before: # SSHAggregate end required fields + +We also have three additional fields that specify the commands that should be +used for creating a user (:func:`add_user_command`), deleting a user +(:func:`del_user_command`), and adding a public key to a user +(:func:`add_pubkey_command`). These commands will be executed in an SSH shell when +creating or deleting users. Make sure that SSH servers you add +allow you to execute these commands non-interactively +(i.e. either login as root or give no-password sudo access to the +commands for the user logging in to execute the commands) : + +.. literalinclude:: sshaggregate/models.py + :start-after: # SSHAggregate optional fields + :end-before: # SSHAggregate end optional fields + +We have also defined some helper functions to add and delete users from +particular server (:func:`add_user` and :func:`del_user`). + +.. literalinclude:: sshaggregate/models.py + :pyobject: SSHAggregate.add_user + +.. literalinclude:: sshaggregate/models.py + :pyobject: SSHAggregate.del_user + +These functions use the private method :func:`_op_user`. Note that in case of +error, we post a message to the user: + +.. literalinclude:: sshaggregate/models.py + :start-after: # msg example + :end-before: # end msg example + +This uses the messaging_ module and a utility function +`post_message_to_current_user`_ to post a message to the user indicating an +error has occurred. This message will be shown in the list of messages for the +user. + +The :func:`check_status` method overrides the :class:`Aggregate` class's +:func:`check_status` method to also make sure that all the servers in the +aggregate are up by calling their :func:`is_alive` method. + +.. literalinclude:: sshaggregate/models.py + :pyobject: SSHAggregate.check_status + +At a minimum any child that inherits from Aggregate_ must override +`start_slice`_ and `stop_slice`_ methods. Our :class:`SSHAggregate` class does +that too: + +.. literalinclude:: sshaggregate/models.py + :start-after: # start_slice func + :end-before: # start_slice call super + +The :func:`start_slice` method calls the parent class's :func:`start_slice` +method because the parent class has some permission checking that we would +rather not copy or redo: + +.. literalinclude:: sshaggregate/models.py + :start-after: # start_slice call super + :end-before: # start_slice end call super + +It then gets needed information about the slice: + +.. literalinclude:: sshaggregate/models.py + :start-after: # start_slice get info + :end-before: # start_slice get user + +And the owner of the slice whose username will be used: + +.. literalinclude:: sshaggregate/models.py + :start-after: # start_slice get user + :end-before: # start_slice get slivers + +Then we get the slivers in the slice that are for resources in the aggregate: + +.. literalinclude:: sshaggregate/models.py + :start-after: # start_slice get slivers + :end-before: # start_slice end info + +Note that we don't just do ``resource__aggregate=self`` because that the +resource is related to :class:`SSHAggregate`'s parent class. So we need to +compare them using ids. We could have instead done +``resource__aggregate=self.aggregate_ptr``. + +Now we add the user to the server pointed to by each sliver, keeping track of +our successes for rollback in case of error: + +.. literalinclude:: sshaggregate/models.py + :start-after: # start_slice loop + :end-before: # Execute the command + +The :class:`SSHServerSliver`'s parent class has a pointer to the generic +resource. To obtain the leaf child that the sliver is pointing to, we need to +use a special function. Otherwise, ``sliver.resource`` returns an object of +type generic Resource_: + +.. literalinclude:: sshaggregate/models.py + :start-after: # Execute the command + :end-before: # start_slice add user + +Then we add the user, paying attention to roll back the changes in case of +errors: + +.. literalinclude:: sshaggregate/models.py + :start-after: # start_slice add user + :end-before: # start_slice end loop + +:func:`stop_slice` is very similar to :func:`start_slice` but a bit simpler +since we don't rollback changes in case of errors. + +.. literalinclude:: sshaggregate/models.py + :pyobject: SSHAggregate.stop_slice + +Relationships +............. + +Below we show a summary of the relationships between slices, resources, aggregates, and slivers. + +.. image:: slice-aggregate-resource-relationships.png + :align: center + :width: 300 + +Each aggregate is connected to a number of resources. Each slice +is also related to a number of resources through a sliver. In our +example, an :class:`SSHAggregate` consists of a number of +:class:`SSHServer` instances. A slice can have a number of +:class:`SSHServerSliver` instances that are each part of an +:class:`SSHServer` instance. + +Documenting Code +................ + +You'll notice that the code we wrote uses something very similar to javadoc +for documenting our methods and classes. We use Epydoc_ for documenting code +and automatically generating API docs from the code. Feel free to use whatever +you like, but please document your code thoroughly. + +.. _`Resource`: ../api/expedient.clearinghouse.resources.models.Resource-class.html +.. _`Sliver`: ../api/expedient.clearinghouse.resources.models.Sliver-class.html +.. _`Slice`: ../api/expedient.clearinghouse.slice.models.Slice-class.html +.. _`start_slice`: ../api/expedient.clearinghouse.aggregate.models.Aggregate-class.html#start_slice +.. _`stop_slice`: ../api/expedient.clearinghouse.aggregate.models.Aggregate-class.html#stop_slice +.. _threadlocals: ../api/expedient.common.middleware.threadlocals-module.html +.. _messaging: ../api/expedient.common.messaging-module.html +.. _`post_message_to_current_user`: ../api/expedient.clearinghouse.utils-module.html#post_message_to_current_user +.. _Epydoc: http://epydoc.sourceforge.net/ + +Writing Views and Templates +--------------------------- + +The next step is writing some views and HTML templates for +managing the SSH aggregate in Expedient. This includes pages for +adding the aggregate to Expedient or editing it. + +Views +..... + +The add/edit aggregate view is the page that the user gets +redirected to when she wants +to add an SSH aggregate to Expedient. There will be two steps for adding an +aggregate. In the first, we store information about the aggregate as a +whole. Below, we sketch out what it looks like. We recommend you always sketch +out what your views will look like before writing them:: + + +-------------------------+ + Admin Username: | | + +-------------------------+ + +-------------------------+ + Private Key: | | + +-------------------------+ + +-------------------------+ + Add user command: | | + +-------------------------+ + +-------------------------+ + Del user command: | | + +-------------------------+ + +-------------------------+ + Add pubkey user command: | | + +-------------------------+ + + +------+ + | Next | | Cancel + +------+ + +The next view is where the user specifies the SSH servers to add to this +aggregate. All these servers can be administered using the same information +entered in the previous step:: + + Add all servers that can be administered using the same information + here. You can click save to get more rows once you fill the existing + ones. + + +--------------------------------------------------------+ + | +-------------------------+| + |Name: | || + | +-------------------------+| + | +-------------------------+| + |IP Address: | || + | +-------------------------+| + | +-------------------------+| + |SSH Port: | || + | +-------------------------+| + | +-------------------------+| + |Delete: | || + | +-------------------------+| + +--------------------------------------------------------+ + + +--------------------------------------------------------+ + | +-------------------------+| + |Name: | || + | +-------------------------+| + | +-------------------------+| + |IP Address: | || + | +-------------------------+| + | +-------------------------+| + |SSH Port: | || + | +-------------------------+| + | +-------------------------+| + |Delete: | || + | +-------------------------+| + +--------------------------------------------------------+ + + +------+ + | Save | | Home + +------+ + +These are our two views. We will use a very similar view for +updating aggregates. In fact, we will use the same view with a +minor change: The information about the aggregate would already +be preloaded into the tables. Now, create the file +:file:`sshaggregate/views.py` +and modify it to look like the following: + +.. literalinclude:: sshaggregate/views.py + +The :func:`aggregate_crud` function uses the `generic_crud`_ +generic view to add or update existing +aggregates. :func:`generic_crud` simplifies many of the +operations that are needed for creating or updating database +objects. Take a look at `generic_crud`_'s documentation before +continuing. + +The :func:`aggregate_add_servers` view uses model formsets. See +the Django documentation about `modelformset_factory`_. It +is a convenient way to create and modify a number of objects: + +.. literalinclude:: sshaggregate/views.py + :lines: 32 + +Finally when returning a response we should use one of Django's +`generic views`_ because they use `RequestContext`_ when +generating the context for templates. This allows us to use +context processors to add more variables into template contexts, +one of which is the messages that you see at the top of each page: + +.. literalinclude:: sshaggregate/views.py + :lines: 56-58 + +.. _`generic_crud`: ../api/expedient.common.utils.views-module.html#generic_crud +.. _`generic views`: http://docs.djangoproject.com/en/dev/ref/generic-views/ +.. _`modelformset_factory`: http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#model-formsets +.. _`RequestContext`: http://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext + +Templates +......... + +We need three templates: + +* :file:`sshaggregate/templates/sshaggregate/sshaggregate_base.html` +* :file:`sshaggregate/templates/sshaggregate/aggregate_crud.html` +* :file:`sshaggregate/templates/sshaggregate/aggregate_add_servers.html` + +There is quite a bit that happens behind the scenes in templates, +and there are is a base template that you should use for creating +your own templates. It is a good practice to create a base +template for each plugin or django app from which all other +templates in the plugin or app inherit. Here the base template is +called :file:`sshaggregate_base.html`. + +Edit :file:`sshaggregate_base.html` to look like +the following: + +.. literalinclude:: sshaggregate/templates/sshaggregate/sshaggregate_base.html + +The base right now includes only one line specifying that it +extends the :file:`base.html` template that is used as the base +template for all the templates in Expedient. The base template +has a few style headers and some javascript code that does magic +like changing help text in tables that have the ``formtable`` +class into a question mark. You will see it in action here. + +Next edit the :file:`aggregate_crud.html` file to look like the +following: + +.. literalinclude:: sshaggregate/templates/sshaggregate/aggregate_crud.html + +Let's go through the file. We want our template to extend our +plugin's base template: + +.. literalinclude:: sshaggregate/templates/sshaggregate/aggregate_crud.html + :lines: 1 + +Expedient's base template :file:`base.html` has a number of +blocks that can be extended. + +* ``title``: Gets used as the page's title. +* ``head``: Any code in this block is added to the ```` + element in the html document. You can use this space to add + javascript or css style blocks. +* ``content``: This is where you should put your template's + body. + +We set the title: + +.. literalinclude:: sshaggregate/templates/sshaggregate/aggregate_crud.html + :lines: 3 + +There's nothing in the head: + +.. literalinclude:: sshaggregate/templates/sshaggregate/aggregate_crud.html + :lines: 5-6 + +Then our content start: + +.. literalinclude:: sshaggregate/templates/sshaggregate/aggregate_crud.html + :lines: 8-9 + +We specified that the template object name is ``aggregate`` when +we used the :func:`generic_crud` function. So if it is specified +in the template, it means that the template is being used to +update an existing instance: + +.. literalinclude:: sshaggregate/templates/sshaggregate/aggregate_crud.html + :lines: 10-11 + +Otherwise, we are creating a new instance: + +.. literalinclude:: sshaggregate/templates/sshaggregate/aggregate_crud.html + :lines: 12-14 + +We then add the form to get the info about the aggregate: + +.. literalinclude:: sshaggregate/templates/sshaggregate/aggregate_crud.html + :lines: 15-28 + +Note that we use the ``{% csrf_token %}`` tag because Django's +CSRF protection is enabled. Also note that we give the table in +the form the ``formtable_noborder`` class which defines some css +settings and lets javascript do its magic in moving help text +into balloon tips. + +Next, create the +:file:`sshaggregate/templates/sshaggregate/aggregate_add_servers.html` +and edit it to look like the following: + +.. literalinclude:: sshaggregate/templates/sshaggregate/aggregate_add_servers.html + +This is similar to :file:`aggregate_crud.html`, so we won't go +through it in detail. + +Connecting to Expedient +----------------------- + +To add the plugin to Expedient, there are a few things we need to +do: + +#. Write the URLs +#. Modify Expedient settings to include the plugin + +Write the URLs +.............. + +Create the file :file:`sshaggregate/urls.py` and edit it to look +like the following: + +.. literalinclude:: sshaggregate/urls.py + +We need three urls: + +* Creating the aggregate +* Updating the aggregate +* Adding/removing servers from the aggregate + +The Aggregate_ class by default expects the create and +update urls to have a particular format: +``_aggregate_create`` and +``_aggregate_update``. If the plugin specified an +additional URL ``_aggregate_delete``, the user would be +redirected to that URL when requesting to delete the aggregate +instead of the default deletion confirmation page. + +Note that for both the create and update, we use the same +:func:`aggregate_crud` function. In the create url, it will be +called with no arguments, while in the edit url, it will be +called with the ``agg_id`` argument. + +Update Settings +............... + +First, we need to add the plugin to the list of installed +apps. Edit your :file:`localsettings.py` file to do +so. Eventually, if the plugin makes it into the Expedient +distribution, the settings that you modify here will be added to +the default settings. We will need to edit two settings. + +Default Settings +^^^^^^^^^^^^^^^^ + +All the settings you put in the :file:`localsettings.py` appear in Django's +:mod:`settings` module. So if your application has some default settings that +you would like to add, you will need to add a line similar to:: + + from sshaggregate.defaultsettings import * + +at the top of the :file:`localsettings.py` file. + +You can append additional list items to almost all of the default +settings that are lists. Below we show an example of how this is +done for `INSTALLED_APPS`_ and `AGGREGATE_PLUGINS`_. If +you add an `EXTRA_` at the beginning of the name, the list you +specify next is appended to the setting's list value. + +INSTALLED_APPS +^^^^^^^^^^^^^^ + +Add the following line to your :file:`localsettings.py`:: + + EXTRA_INSTALLED_APPS = [ + 'sshaggregate', + ] + +AGGREGATE_PLUGINS +^^^^^^^^^^^^^^^^^ + +The `AGGREGATE_PLUGINS`_ setting describes the aggregate plugins +that are installed. See the `AGGREGATE_PLUGINS`_ setting +documentation for more information:: + + EXTRA_AGGREGATE_PLUGINS = [ + ('sshaggregate.models.SSHAggregate', 'sshaggregate', 'sshaggregate.urls'), + ] + +.. _`Aggregate`: ../api/expedient.clearinghouse.aggregate.models.Aggregate-class.html +.. _`AGGREGATE_PLUGINS`: ../api/expedient.clearinghouse.defaultsettings.expedient-module.html#AGGREGATE_PLUGINS + +Testing +------- + +Now, you will need to test your plugin to make everything +works. The first phase of testing is going to be manual +prelimiary testing to make sure that the plugin works +well. Before you do so, make sure that you have performed a +``manage.py syncdb`` on the running Expedient instance that you +will use. Here we will cover automated testing. + +The importance of automated testing cannot be stressed enough. Anytime you +make a change, you will need to run the tests, and nothing makes your job of +fixing bugs and adding new features as easy as automated tests. +Django has extensive facilities for testing that come in quite +handy. Create the :file:`sshaggregate/tests.py` and edit it to +look like the following: + +.. literalinclude:: sshaggregate/tests.py + +The tests that we have written test two things: + +* Adding an SSH aggregate to Expedient +* Creating and deleting a slice + +This is not a comprehensive test suite, and your tests should include more +exhaustive testing. The test class does the following. It first sets up the +environment by creating an SSH key for the user running the test, adding it to +the user's authorized keys, and using the user as the admin for the +aggregate. The tests can now SSH into localhost using the created key. + +When adding an aggregate the test suite uses custom commands for creating +users, deleting users, and adding a public key to a user's account. Instead of +these commands actually doing what they are supposed to do, we do the +following. When creating a user, we write the user's username into a temprary +file and we write the user's public key into another file. Then we check that +the commands executed correctly and that these files were written as +expected. Similarly, when deleting a user, we write the user's username into a +temporary file and we check that the file was written as expected. +So let's go through the test code section by section. + +First, we create a class that inherits from the :class:`django.test.TestCase`: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Tests class + :end-before: # start constants + +Expedient also provides a different class you can inherit from, +`expedient.common.tests.manager.SettingsTestCase`_. This test case allows you +to easily change settings in the test case to, for example, add new +django apps that are used in testing. Take a look at +`expedient.clearinghouse.aggregate.tests.tests`_ for an example on how it is +used. + +Next, we define some constants that are used in testing. These are the names +of the temporary files used and information about the temporary SSH key +created for the tests: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # start constants + :end-before: # end + +Next, we define a method to create an SSH key and add it to the current user's +:file:`authorized_keys` file. This function uses :mod:`paramiko` to generate a +key. + +.. literalinclude:: sshaggregate/tests.py + :pyobject: Tests.create_test_ssh_key + +Note that we've given the key a special comment that we can use to +delete the key in the :func:`delete_test_ssh_key` method: + +.. literalinclude:: sshaggregate/tests.py + :pyobject: Tests.delete_test_ssh_key + +The :func:`setUp` function first creates a local user: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # create local user + :end-before: # end + +We chose to create a superuser because it bypasses some of the security +restrictions built into Expedient. You might want to do the testing with a +regular user instead. Then we disable permission checking in Expedient: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # disable permissions + :end-before: # end + +This disables most of the permission checks that Expedient performs. In more +exhaustive testing, you will want to keep permissions enabled. Then we create +an ssh key to ssh into localhost: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # create ssh key + :end-before: # end + +And finally we log in as the user we just created so we can use Django's test +client to make html requests: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # login user + :end-before: # end + +The :func:`tearDown` function does many of :func:`setUp`'s operations +in reverse: + +.. literalinclude:: sshaggregate/tests.py + :pyobject: Tests.tearDown + +Adding Aggregates +................. + +The first test checks that we can add an aggregate: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # add aggregate tests + :end-before: # end + +Make sure that nothing is in Expedient already: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # check nothing is there + :end-before: # end + +Get the private key that we created as a string to use in adding the +aggregate: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # get private key as string + :end-before: # end + +Then we add the aggregate using an html post request using django's +client. Note that here we use a custom function `test_get_and_post_form`_ that +gets a form, and fills in some of the parameters. We use this function to save +some of the trouble of having to add fields with existing defaults or for +fields that are arriving from the server with custom values. After we do the +post request, we check that the aggregate has indeed been added. + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Add the aggregate + :end-before: # end + +Note the custom commands we have used to add a user, delete a user, and add a +public key to a user. We also need to check that after adding the aggregate we +were redirected to the page where we add servers: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # where do we go next? + :end-before: # end + +Now we add the localhost as a server in the aggregate: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Add the localhost as a server + :end-before: # end + +And finally we check that the server was added correctly: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # check that localhost added + :end-before: # end + +Creating and Deleting Slices +............................ + +Next we check that functionality of our aggregate. + +.. literalinclude:: sshaggregate/tests.py + :start-after: # slice tests + :end-before: # end + +We call the previous function to add the aggregate to Expedient first. + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Add the aggregate + :end-before: # end + +Then we create a project. + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Create the project + :end-before: # end + +We add the aggregate to the project, and we check that the project now has the +aggregate: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Add the aggregate to the project + :end-before: # end + +Then we create the slice: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Create the slice + :end-before: # end + +We add the aggregate to the slice, and check that the addition worked. + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Add the aggregate to the slice + :end-before: # end + +Now, if you recall, slices are composed of slivers. To tell Expedient that we +want an SSHServer from a particular aggregate in our slice, we need to a +create a sliver for that resource. We do this by creating an +:class:`SSHServerSliver` instance: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Create a sliver + :end-before: # end + +Next we add more information about the slice using the :class:`SSHSliceInfo` +class: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Create the SSHSliceInfo + :end-before: # end + +Now we can start the slice: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Start the slice + :end-before: # end + +Now we need to check that the command to add users was executed correctly on +the localhost. We do this by checking that the username was written correctly +to the temporary file. + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Check that the add command was executed correctly + :end-before: # end + +We do a similar check to see that the public key for the user was added: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # check that the add pub key command executed correctly + :end-before: # end + +Next, we stop the slice: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Stop the slice + :end-before: # end + +And we make sure that the command executed correctly: + +.. literalinclude:: sshaggregate/tests.py + :start-after: # Check that the del user command executed correctly + :end-before: # end + +And that's it. You now have a basic test suite that you can run. To run the +test, you need to make sure that :mod:`sshaggregate` is in your +PYTHONPATH. Then you can use the :command:`test` management command to run the +:mod:`sshaggregate` test suite. + +.. _`expedient.common.tests.manager.SettingsTestCase`: ../api/expedient.common.tests.manager.SettingsTestCase-class.html +.. _`expedient.clearinghouse.aggregate.tests.tests`: ../api/expedient.clearinghouse.aggregate.tests.tests-module.html +.. _`test_get_and_post_form`: ../api/expedient.common.tests.client-module.html#test_get_and_post_form diff --git a/expedient/src/doc/expedient/source/index.rst b/expedient/src/doc/expedient/source/index.rst new file mode 100644 index 00000000..7be58f3a --- /dev/null +++ b/expedient/src/doc/expedient/source/index.rst @@ -0,0 +1,53 @@ +.. Expedient documentation master file, created by + sphinx-quickstart on Wed Aug 11 14:56:40 2010. + +.. _home: + +Welcome to Expedient's documentation! +##################################### + +|Expedient|_ is a pluggable GENI_ control framework platform that strives to provide a +rich and intuitive user interface for experimenters to create and run +experiments and an easy development environment for developers to add new +types of resources and new user interfaces. + +|Expedient| does not +interfere with how GENI resources work. It does not impose enforce semantics +on resources and it does not force the resources to obey a particular +API. This makes it easier for resource developers to create plugins that +add new types of resources to Expedient. + +There are a few things you can do next. + +.. +----------------------------+---------------------------------+-----------------------------+ +.. | For Users | For Developers | For Administrators | +.. +============================+=================================+=============================+ +.. | #. :ref:`user-tutorial` | #. :ref:`developer-tutorial` | #. :ref:`admin-install` | +.. | #. :ref:`user-manual` | #. :ref:`developer-manual` | #. :ref:`admin-tutorial` | +.. | #. :ref:`user-agg-plugins` | #. :ref:`developer-agg-plugins` | #. :ref:`admin-manual` | +.. | #. :ref:`user-ui-plugins` | #. :ref:`developer-ui-plugins` | #. :ref:`admin-agg-plugins` | +.. | | #. `API Documentation`_ | #. :ref:`admin-ui-plugins` | +.. +----------------------------+---------------------------------+-----------------------------+ + +Contents: + +.. toctree:: + :maxdepth: 2 + + user/index + admin/index + developer/index + +Automatically generated API can be found here: `API Documentation`_ + +Indices and tables +################## + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + +.. |Expedient| replace:: *Expedient* +.. _Expedient: http://yuba.stanford.edu/~jnaous/expedient/ +.. _GENI: http://www.geni.net/ +.. _API Documentation: api/index.html diff --git a/expedient/src/doc/expedient/source/user/index.rst b/expedient/src/doc/expedient/source/user/index.rst new file mode 100644 index 00000000..f543dcd5 --- /dev/null +++ b/expedient/src/doc/expedient/source/user/index.rst @@ -0,0 +1,14 @@ +Using Expedient +############### + +Expedient enables rich user interfaces through a Web interface. Most things + experimenters want to do (create slices, manage users, ...) can be done + through the Web interface. To learn more, either go through the quick + :ref:`user-tutorial` to learn how to create a project, add users, and create + slices or read through the more extensive :ref:`user-manual`. + +.. toctree:: + :maxdepth: 2 + + tutorial +.. manual diff --git a/expedient/src/doc/expedient/source/user/tutorial.rst b/expedient/src/doc/expedient/source/user/tutorial.rst new file mode 100644 index 00000000..b3ed52f1 --- /dev/null +++ b/expedient/src/doc/expedient/source/user/tutorial.rst @@ -0,0 +1,157 @@ +.. _user-tutorial: + +Expedient User Tutorial +======================= + +In this tutorial you will do the following: + +#. Create an account and get permission to create a new project (:ref:`user-tutorial-create-project`). +#. Start a slice with OpenFlow and PlanetLab resources (:ref:`user-tutorial-create-slice`). + +.. _`user-tutorial-create-project`: + +Create a Project +---------------- + +Go to the Expedient site, and click on the :guilabel:`Register` link. Fill-in your +username, email, and password. An email will be sent to you to activate your +account. Once activated, log into your account. + +The home page has four sections. + +* Messages: Here you can look at messages you have received, delete old ones, + and send messages to other users. +* Aggregates: This is a list of resource aggregates that are available at + Expedient.You can use this section to add and remove resource aggregates from + Expedient. Resource aggregates are collections of resources that are made + available to Expedient users. You will need permission to add or remove + aggregates. +* Projects: This section will list the projects of which you are a member. +* Permission Management: Here you can see a list of pending permission + requests that others have made to you. + +Users create slices within the context of projects. A project has a set of +members with different roles. Roles give users permissions to do various +actions in the project such as changing the project's information, adding +users to the project, or creating slices. + +Click on the :guilabel:`Create` button in the Projects section. You will most likely +encounter a "Permission Denied" page. You will need to request the permission +from someone who can allow you to create a project. Most likely, this would be +an administrator. So select a user to make the request to (:guilabel:`Permission +Owner`), add a message that helps the administrator make a decision to allow +you to create a project, and click :guilabel:`Request`. + +Once your administrator approves the request, you can go back to the homepage +and try to create the project again. Choose a simple descriptive short name, +add a description for the project, and click :guilabel:`Save`. + +You will be redirected to the project's detail page where you can manage the +project. + +Each project has a set of members. Each member can have multiple roles. Roles +are project-specific and they define the set of permissions a member has for +the project. + +The project page has the following sections: + +* Members: Shows list of members and links to add/remove/update members. +* Role Requests: When members try an action they do not have permission + to execute, they will be redirected to a page where they can request a role + that allows them to execute that action. This lists any roles other members + have requested from you. +* Aggregates: This section lists the resource aggregates the project is + allowed to use. Slices you create can only use aggregates in this list. +* Slices: List of the slices in the project. +* Roles: List of roles in the project. + +Each new project gets two default roles: "researcher" and "owner". The +"researcher" role only allows the user to create and delete slices, while the +"owner" role allows a user to do everything. + +Add a Member +............ + +Let's start by adding another member to the project. Click on :guilabel:`Add Members` in +the "Members" section. Select another user you want in the project, select +:guilabel:`researcher` role, and click on :guilabel:`Add`. The delegate checkbox can be used to +allow the user to give the roles you give him to others. + +Add Aggregates +.............. + +Now we should add aggregates to the project. Click on :guilabel:`Add Aggregates`. You +will see a list of the aggregates that are available in Expedient. Click the +:guilabel:`Select` button for +the ones you would like to use (choose at least one OpenFlow Aggregate and one +PlanetLab Aggregate). Some other types of aggregates might require additional +steps before an aggregate is added to the project. + + +.. _user-tutorial-create-slice: + +Create a Slice +-------------- + +Now let's create a slice. Click on :guilabel:`Create Slice` in the "Slices" +section. Fill the form and click :guilabel:`Save`. The page you see is your slice's +detail page. + +The :guilabel:`Management` box on the right allows you to edit basic information about +the slice, as well as start and stop the slice. + + +Add Aggregates +.............. + +As in the project detail page, you have to add aggregates to the slice in +order to be able to reserve resources from that aggregate. Select the +PlanetLab and OpenFlow aggregates to add them to the slice. + +When you add an OpenFlow Aggregate, you will need to provide the URL of the +controller for your slice. All OpenFlow aggregates that you add will use the +same information, although it may be requested multiple times. So if you +change it for one, you also change it for all. + +Click :guilabel:`Done`. + +Add Resources +............. + +To add resources to the slice, you will need to use a "User Interface +Plugin". Each such plugin specializes in some subset of resources. Click on +:guilabel:`Manage Resources` to select a plugin to add OpenFlow and PlanetLab resources. +Click on :guilabel:`Open` for the :guilabel:`HTML Table UI` plugin. + +Here you'll see information about the PlanetLab and OpenFlow resources that +are available for the slice. To select a tree from all the resources present, +click on :guilabel:`Select Tree`. When you are done selecting the resources you want in +the slice, click :guilabel:`Next`. + +Select FlowSpace +................ + +Select the flowspace that you want the controller to receive by specifying it +here. Click :guilabel:`Save` and then :guilabel:`Next` when done. + +Download RSA keys +................. + +Expedient generates an RSA key and uses it to create the PlanetLab slice for +you. Here you can download the provate key that you can use to login to your +PlanetLab nodes. Use the given login username to login to the PlanetLab nodes. + +When you are done, click :guilabel:`Done` to go back to the detail page. You can always +come back here later to edit your slice. + +Start the Slice +............... + +At this point nothing has been created at the actual resource aggregates +themselves. To start your slice, click on :guilabel:`Start Slice`. + +Stop the Slice +.............. + +Click :guilabel:`Stop Slice` to free the resources associated with your slice at the +resource aggregates. diff --git a/expedient/src/python/expedient/__init__.py b/expedient/src/python/expedient/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/src/python/expedient/clearinghouse/__init__.py b/expedient/src/python/expedient/clearinghouse/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/src/python/expedient/clearinghouse/administration/__init__.py b/expedient/src/python/expedient/clearinghouse/administration/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/expedient/src/python/expedient/clearinghouse/administration/urls.py b/expedient/src/python/expedient/clearinghouse/administration/urls.py new file mode 100644 index 00000000..9f2bef01 --- /dev/null +++ b/expedient/src/python/expedient/clearinghouse/administration/urls.py @@ -0,0 +1,13 @@ +''' +Created on Jun 30, 2013 + +@author: CarolinaFernandez +''' +from django.conf.urls.defaults import patterns, url + +urlpatterns = patterns('expedient.clearinghouse.administration.views', + url(r'^$', 'home', name='administration_home'), + url(r'^log/(?P\w+)/view/$', 'view_log', name="administration_view_log"), + url(r'^log/(?P\w+)/(?P