From 1238858888ef90d9948fe4eb2f0175e2ff7c9ee5 Mon Sep 17 00:00:00 2001
From: Henrik Thostrup Jensen <htj@nordu.net>
Date: Mon, 17 Feb 2014 16:34:28 +0100
Subject: [PATCH] fix issue with being able to provision a connection that was
 not commited (solution: have allocated flag in database)

---
 datafiles/schema-delete.sql               |  1 +
 datafiles/schema.sql                      | 10 +++++++++-
 opennsa/backends/common/genericbackend.py | 20 +++++++++++++++-----
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/datafiles/schema-delete.sql b/datafiles/schema-delete.sql
index 0fc47985..0f55000b 100644
--- a/datafiles/schema-delete.sql
+++ b/datafiles/schema-delete.sql
@@ -5,5 +5,6 @@ DROP TABLE generic_backend_connections;
 DROP TABLE sub_connections;
 DROP TABLE service_connections;
 DROP TYPE directionality;
+DROP TYPE parameter;
 DROP TYPE label;
 
diff --git a/datafiles/schema.sql b/datafiles/schema.sql
index d0fbcf29..150aa836 100644
--- a/datafiles/schema.sql
+++ b/datafiles/schema.sql
@@ -7,6 +7,11 @@ CREATE TYPE label AS (
     label_value     text
 );
 
+CREATE TYPE parameter AS (
+    label_type      text,
+    label_value     text
+);
+
 CREATE TYPE directionality AS ENUM ('Bidirectional', 'Unidirectional');
 
 
@@ -34,6 +39,7 @@ CREATE TABLE service_connections (
     symmetrical             boolean                     NOT NULL,
     directionality          directionality              NOT NULL,
     bandwidth               integer                     NOT NULL, -- mbps
+    parameter               parameter[],
     connection_trace        text[]
 );
 
@@ -84,6 +90,8 @@ CREATE TABLE generic_backend_connections (
     end_time                timestamp                   NOT NULL,
     symmetrical             boolean                     NOT NULL,
     directionality          directionality              NOT NULL,
-    bandwidth               integer                     NOT NULL -- mbps
+    bandwidth               integer                     NOT NULL, -- mbps
+    parameter               parameter[],
+    allocated               boolean                     NOT NULL  -- indicated if the resources are actually allocated
 );
 
diff --git a/opennsa/backends/common/genericbackend.py b/opennsa/backends/common/genericbackend.py
index bd82409b..116e4b7b 100644
--- a/opennsa/backends/common/genericbackend.py
+++ b/opennsa/backends/common/genericbackend.py
@@ -263,7 +263,7 @@ class GenericBackend(service.Service):
                                          source_network=source_stp.network, source_port=source_stp.port, source_label=src_label,
                                          dest_network=dest_stp.network, dest_port=dest_stp.port, dest_label=dst_label,
                                          start_time=schedule.start_time, end_time=schedule.end_time,
-                                         symmetrical=sd.symmetric, directionality=sd.directionality, bandwidth=sd.capacity)
+                                         symmetrical=sd.symmetric, directionality=sd.directionality, bandwidth=sd.capacity, allocated=False)
         yield conn.save()
         reactor.callWhenRunning(self._doReserve, conn, header.correlation_id)
         defer.returnValue(connection_id)
@@ -278,10 +278,17 @@ class GenericBackend(service.Service):
         if conn.lifecycle_state in (state.TERMINATING, state.TERMINATED):
             raise error.ConnectionGoneError('Connection %s has been terminated')
 
-        yield state.reserveCommit(conn)
-        self.logStateUpdate(conn, 'RESERVE COMMIT')
-        yield state.reserved(conn)
-        self.logStateUpdate(conn, 'RESERVED')
+        # this it not the nicest code in the world, but the double state write is silly
+        # further the switch to reserve start and allocated must be in same transaction
+        state._switchState(state.RESERVE_TRANSITIONS, conn.reservation_state, state.RESERVE_COMMITTING)
+        conn.reservation_state = state.RESERVE_COMMITTING
+
+        state._switchState(state.RESERVE_TRANSITIONS, conn.reservation_state, state.RESERVE_START)
+        conn.reservation_state = state.RESERVE_START
+
+        conn.allocated = True
+        yield conn.save()
+        self.logStateUpdate(conn, 'COMMIT/RESERVED')
 
         # cancel abort and schedule end time call
         self.scheduler.cancelCall(connection_id)
@@ -320,6 +327,9 @@ class GenericBackend(service.Service):
         if conn.lifecycle_state in (state.TERMINATING, state.TERMINATED):
             raise error.ConnectionGoneError('Connection %s has been terminated')
 
+        if not conn.allocated:
+            raise error.ConnectionError('No resource allocated to the connection, cannot provision')
+
         if conn.reservation_state != state.RESERVE_START:
             raise error.InvalidTransitionError('Cannot provision connection in a non-reserved state')
 
-- 
GitLab