You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by er...@apache.org on 2014/12/08 21:52:39 UTC

libcloud git commit: Add Routes to GCE driver. Closes #410

Repository: libcloud
Updated Branches:
  refs/heads/trunk c35222511 -> f813ea17b


Add Routes to GCE driver.
Closes #410

Signed-off-by: Eric Johnson <er...@google.com>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/f813ea17
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/f813ea17
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/f813ea17

Branch: refs/heads/trunk
Commit: f813ea17b1372a9e5e577647d175d37eff4c6b11
Parents: c352225
Author: Eric Johnson <er...@google.com>
Authored: Tue Dec 2 22:46:46 2014 +0000
Committer: Eric Johnson <er...@google.com>
Committed: Mon Dec 8 20:51:38 2014 +0000

----------------------------------------------------------------------
 CHANGES.rst                                     |   4 +
 libcloud/compute/drivers/gce.py                 | 168 +++++++++++++++++++
 .../compute/fixtures/gce/global_routes.json     |  58 +++++++
 .../fixtures/gce/global_routes_lcdemoroute.json |  27 +++
 .../gce/global_routes_lcdemoroute_delete.json   |  13 ++
 .../fixtures/gce/global_routes_post.json        |  13 ++
 ...ration_global_routes_lcdemoroute_delete.json |  13 ++
 ...operations_operation_global_routes_post.json |  13 ++
 libcloud/test/compute/test_gce.py               |  58 ++++++-
 9 files changed, 366 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/f813ea17/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index 8fddb8a..e4858e7 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -16,6 +16,10 @@ General
 Compute
 ~~~~~~~
 
+- Add Routes to GCE driver.
+  (GITHUB-410)
+  [Eric Johnson]
+
 - Add missing ``ubuntu-os-cloud`` images to the GCE driver.
   (LIBCLOUD-632, GITHUB-385)
   [Borja Martin]

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f813ea17/libcloud/compute/drivers/gce.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/gce.py b/libcloud/compute/drivers/gce.py
index 6efb912..c8bbeca 100644
--- a/libcloud/compute/drivers/gce.py
+++ b/libcloud/compute/drivers/gce.py
@@ -296,6 +296,34 @@ class GCENetwork(UuidMixin):
             self.id, self.name, self.cidr)
 
 
+class GCERoute(UuidMixin):
+    """A GCE Route object class."""
+    def __init__(self, id, name, dest_range, priority, network="default",
+                 tags=None, driver=None, extra=None):
+        self.id = str(id)
+        self.name = name
+        self.dest_range = dest_range
+        self.priority = priority
+        self.network = network
+        self.tags = tags
+        self.driver = driver
+        self.extra = extra
+        UuidMixin.__init__(self)
+
+    def destroy(self):
+        """
+        Destroy this route
+
+        :return: True if successful
+        :rtype:  ``bool``
+        """
+        return self.driver.ex_destroy_route(route=self)
+
+    def __repr__(self):
+        return '<GCERoute id="%s" name="%s" dest_range="%s" network="%s">' % (
+            self.id, self.name, self.dest_range, self.network.name)
+
+
 class GCENodeSize(NodeSize):
     """A GCE Node Size (MachineType) class."""
     def __init__(self, id, name, ram, disk, bandwidth, price, driver,
@@ -783,6 +811,20 @@ class GCENodeDriver(NodeDriver):
         list_locations = [self._to_node_location(l) for l in response['items']]
         return list_locations
 
+    def ex_list_routes(self):
+        """
+        Return the list of routes.
+
+        :return: A list of route objects.
+        :rtype: ``list`` of :class:`GCERoute`
+        """
+        list_routes = []
+        request = '/global/routes'
+        response = self.connection.request(request, method='GET').object
+        list_routes = [self._to_route(n) for n in
+                       response.get('items', [])]
+        return list_routes
+
     def ex_list_networks(self):
         """
         Return the list of networks.
@@ -1254,6 +1296,70 @@ class GCENodeDriver(NodeDriver):
 
         return self.ex_get_image(name)
 
+    def ex_create_route(self, name, dest_range, priority=500,
+                        network="default", tags=None, next_hop=None,
+                        description=None):
+        """
+        Create a route.
+
+        :param  name: Name of route to be created
+        :type   name: ``str``
+
+        :param  dest_range: Address range of route in CIDR format.
+        :type   dest_range: ``str``
+
+        :param  priority: Priority value, lower values take precedence
+        :type   priority: ``int``
+
+        :param  network: The network the route belongs to. Can be either the
+                         full URL of the network or a libcloud object.
+        :type   network: ``str`` or ``GCENetwork``
+
+        :param  tags: List of instance-tags for routing, empty for all nodes
+        :type   tags: ``list`` of ``str`` or ``None``
+
+        :param  next_hop: Next traffic hop. Use ``None`` for the default
+                          Internet gateway, or specify an instance or IP
+                          address.
+        :type   next_hop: ``str``, ``GCENode``, or ``None``
+
+        :param  description: Custom description for the route.
+        :type   description: ``str`` or ``None``
+
+        :return:  Route object
+        :rtype:   :class:`GCERoute`
+        """
+        route_data = {}
+        route_data['name'] = name
+        route_data['destRange'] = dest_range
+        route_data['priority'] = priority
+        route_data['description'] = description
+        if isinstance(network, str) and network.startswith('https://'):
+            network_uri = network
+        elif isinstance(network, str):
+            network = self.ex_get_network(network)
+            network_uri = network.extra['selfLink']
+        else:
+            network_uri = network.extra['selfLink']
+        route_data['network'] = network_uri
+        route_data['tags'] = tags
+        if next_hop is None:
+            url = 'https://www.googleapis.com/compute/%s/projects/%s/%s' % (
+                  API_VERSION, self.project,
+                  "global/gateways/default-internet-gateway")
+            route_data['nextHopGateway'] = url
+        elif isinstance(next_hop, str):
+            route_data['nextHopIp'] = next_hop
+        else:
+            node = self.ex_get_node(next_hop)
+            route_data['nextHopInstance'] = node.extra['selfLink']
+
+        request = '/global/routes'
+        self.connection.async_request(request, method='POST',
+                                      data=route_data)
+
+        return self.ex_get_route(name)
+
     def ex_create_network(self, name, cidr, description=None):
         """
         Create a network.
@@ -2333,6 +2439,20 @@ class GCENodeDriver(NodeDriver):
         self.connection.async_request(request, method='DELETE')
         return True
 
+    def ex_destroy_route(self, route):
+        """
+        Destroy a route.
+
+        :param  route: Route object to destroy
+        :type   route: :class:`GCERoute`
+
+        :return:  True if successful
+        :rtype:   ``bool``
+        """
+        request = '/global/routes/%s' % (route.name)
+        self.connection.async_request(request, method='DELETE')
+        return True
+
     def ex_destroy_network(self, network):
         """
         Destroy a network.
@@ -2630,6 +2750,20 @@ class GCENodeDriver(NodeDriver):
                 image = self._match_images('ubuntu-os-cloud', partial_name)
         return image
 
+    def ex_get_route(self, name):
+        """
+        Return a Route object based on a route name.
+
+        :param  name: The name of the route
+        :type   name: ``str``
+
+        :return:  A Route object for the named route
+        :rtype:   :class:`GCERoute`
+        """
+        request = '/global/routes/%s' % (name)
+        response = self.connection.request(request, method='GET').object
+        return self._to_route(response)
+
     def ex_get_network(self, name):
         """
         Return a Network object based on a network name.
@@ -3477,6 +3611,40 @@ class GCENodeDriver(NodeDriver):
                           cidr=network.get('IPv4Range'),
                           driver=self, extra=extra)
 
+    def _to_route(self, route):
+        """
+        Return a Route object from the json-response dictionary.
+
+        :param  route: The dictionary describing the route.
+        :type   route: ``dict``
+
+        :return: Route object
+        :rtype: :class:`GCERoute`
+        """
+        extra = {}
+
+        extra['selfLink'] = route.get('selfLink')
+        extra['description'] = route.get('description')
+        extra['creationTimestamp'] = route.get('creationTimestamp')
+        network = route.get('network')
+        priority = route.get('priority')
+
+        if 'nextHopInstance' in route:
+            extra['nextHopInstance'] = route['nextHopInstance']
+        if 'nextHopIp' in route:
+            extra['nextHopIp'] = route['nextHopIp']
+        if 'nextHopNetwork' in route:
+            extra['nextHopNetwork'] = route['nextHopNetwork']
+        if 'nextHopGateway' in route:
+            extra['nextHopGateway'] = route['nextHopGateway']
+        if 'warnings' in route:
+            extra['warnings'] = route['warnings']
+
+        return GCERoute(id=route['id'], name=route['name'],
+                        dest_range=route.get('destRange'), priority=priority,
+                        network=network, tags=route.get('tags'),
+                        driver=self, extra=extra)
+
     def _to_node_image(self, image):
         """
         Return an Image object from the json-response dictionary.

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f813ea17/libcloud/test/compute/fixtures/gce/global_routes.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gce/global_routes.json b/libcloud/test/compute/fixtures/gce/global_routes.json
new file mode 100644
index 0000000..d42c884
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gce/global_routes.json
@@ -0,0 +1,58 @@
+{
+ "kind": "compute#routeList",
+ "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes",
+ "id": "projects/project_name/global/routes",
+ "items": [
+  {
+   "kind": "compute#route",
+   "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/default-route-17d11bbbba01ce80",
+   "id": "15220239546867835355",
+   "creationTimestamp": "2014-01-21T10:30:55.592-08:00",
+   "name": "default-route-17d11bbbba01ce80",
+   "description": "Default route to the virtual network.",
+   "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default",
+   "destRange": "10.240.0.0/16",
+   "priority": 1000,
+   "nextHopNetwork": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default"
+  },
+  {
+   "kind": "compute#route",
+   "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/default-route-e1808a2caeaf17fb",
+   "id": "4898173129042082424",
+   "creationTimestamp": "2014-01-21T10:30:55.584-08:00",
+   "name": "default-route-e1808a2caeaf17fb",
+   "description": "Default route to the Internet.",
+   "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default",
+   "destRange": "0.0.0.0/0",
+   "priority": 1000,
+   "nextHopGateway": "https://www.googleapis.com/compute/v1/projects/project_name/global/gateways/default-internet-gateway"
+  },
+  {
+   "kind": "compute#route",
+   "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute",
+   "id": "14575183394193523469",
+   "creationTimestamp": "2014-11-25T11:00:45.062-08:00",
+   "name": "lcdemoroute",
+   "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default",
+   "tags": [
+    "tag1",
+    "tag2"
+   ],
+   "destRange": "192.168.25.0/24",
+   "priority": 1000,
+   "nextHopInstance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100",
+   "warnings": [
+    {
+     "code": "NEXT_HOP_CANNOT_IP_FORWARD",
+     "message": "Next hop instance 'https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100' cannot forward ip traffic. The next hop instance must have canIpForward set.",
+     "data": [
+      {
+       "key": "instance",
+       "value": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100"
+      }
+     ]
+    }
+   ]
+  }
+ ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f813ea17/libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute.json b/libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute.json
new file mode 100644
index 0000000..5931ecc
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute.json
@@ -0,0 +1,27 @@
+{
+ "kind": "compute#route",
+ "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute",
+ "id": "14575183394193523469",
+ "creationTimestamp": "2014-11-25T11:00:45.062-08:00",
+ "name": "lcdemoroute",
+ "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default",
+ "tags": [
+  "tag1",
+  "tag2"
+ ],
+ "destRange": "192.168.25.0/24",
+ "priority": 1000,
+ "nextHopInstance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100",
+ "warnings": [
+  {
+   "code": "NEXT_HOP_CANNOT_IP_FORWARD",
+   "message": "Next hop instance 'https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100' cannot forward ip traffic. The next hop instance must have canIpForward set.",
+   "data": [
+    {
+     "key": "instance",
+     "value": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100"
+    }
+   ]
+  }
+ ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f813ea17/libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute_delete.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute_delete.json b/libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute_delete.json
new file mode 100644
index 0000000..2dd42c4
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute_delete.json
@@ -0,0 +1,13 @@
+{
+ "kind": "compute#operation",
+ "id": "17322940416642455149",
+ "name": "operation-global_routes_lcdemoroute_delete",
+ "operationType": "destroy",
+ "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute",
+ "status": "PENDING",
+ "user": "erjohnso@google.com",
+ "progress": 0,
+ "insertTime": "2014-11-25T11:00:44.049-08:00",
+ "startTime": "2014-11-25T11:00:44.385-08:00",
+ "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_routes_lcdemoroute_delete"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f813ea17/libcloud/test/compute/fixtures/gce/global_routes_post.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gce/global_routes_post.json b/libcloud/test/compute/fixtures/gce/global_routes_post.json
new file mode 100644
index 0000000..a491f8f
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gce/global_routes_post.json
@@ -0,0 +1,13 @@
+{
+ "kind": "compute#operation",
+ "id": "17322940416642455149",
+ "name": "operation-global_routes_post",
+ "operationType": "insert",
+ "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute",
+ "status": "PENDING",
+ "user": "erjohnso@google.com",
+ "progress": 0,
+ "insertTime": "2014-11-25T11:00:44.049-08:00",
+ "startTime": "2014-11-25T11:00:44.385-08:00",
+ "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_routes_post"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f813ea17/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_lcdemoroute_delete.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_lcdemoroute_delete.json b/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_lcdemoroute_delete.json
new file mode 100644
index 0000000..ff6d42d
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_lcdemoroute_delete.json
@@ -0,0 +1,13 @@
+{
+ "kind": "compute#operation",
+ "id": "17322940416642455149",
+ "name": "operation-global_route_lcdemoroute",
+ "operationType": "destroy",
+ "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute",
+ "status": "DONE",
+ "user": "erjohnso@google.com",
+ "progress": 100,
+ "insertTime": "2014-11-25T11:00:44.049-08:00",
+ "startTime": "2014-11-25T11:00:44.385-08:00",
+ "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_route_lcdemoroute"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f813ea17/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_post.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_post.json b/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_post.json
new file mode 100644
index 0000000..bcddbcb
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_post.json
@@ -0,0 +1,13 @@
+{
+ "kind": "compute#operation",
+ "id": "17322940416642455149",
+ "name": "operation-global_routes_lcdemoroute_post",
+ "operationType": "insert",
+ "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute",
+ "status": "DONE",
+ "user": "erjohnso@google.com",
+ "progress": 100,
+ "insertTime": "2014-11-25T11:00:44.049-08:00",
+ "startTime": "2014-11-25T11:00:44.385-08:00",
+ "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_routes_lcdemoroute_post"
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f813ea17/libcloud/test/compute/test_gce.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_gce.py b/libcloud/test/compute/test_gce.py
index de91aaf..b46e04d 100644
--- a/libcloud/test/compute/test_gce.py
+++ b/libcloud/test/compute/test_gce.py
@@ -28,7 +28,8 @@ from libcloud.compute.drivers.gce import (GCENodeDriver, API_VERSION,
                                           GCEFirewall, GCEForwardingRule,
                                           GCENetwork,
                                           GCEZone,
-                                          GCENodeImage)
+                                          GCENodeImage,
+                                          GCERoute)
 from libcloud.common.google import (GoogleBaseAuthConnection,
                                     GoogleInstalledAppAuthConnection,
                                     GoogleBaseConnection,
@@ -157,6 +158,11 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin):
         self.assertEqual(len(locations), 5)
         self.assertEqual(locations[0].name, 'europe-west1-a')
 
+    def test_ex_list_routes(self):
+        routes = self.driver.ex_list_routes()
+        self.assertEqual(len(routes), 3)
+        self.assertTrue('lcdemoroute' in [route.name for route in routes])
+
     def test_ex_list_networks(self):
         networks = self.driver.ex_list_networks()
         self.assertEqual(len(networks), 3)
@@ -288,6 +294,18 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin):
         self.assertEqual(fwr.extra['portRange'], port_range)
         self.assertEqual(fwr.extra['description'], description)
 
+    def test_ex_create_route(self):
+        route_name = 'lcdemoroute'
+        dest_range = '192.168.25.0/24'
+        priority = 1000
+        route = self.driver.ex_create_route(route_name, dest_range)
+        self.assertTrue(isinstance(route, GCERoute))
+        self.assertEqual(route.name, route_name)
+        self.assertEqual(route.priority, priority)
+        self.assertTrue("tag1" in route.tags)
+        self.assertTrue(route.extra['nextHopInstance'].endswith('libcloud-100'))
+        self.assertEqual(route.dest_range, dest_range)
+
     def test_ex_create_network(self):
         network_name = 'lcnetwork'
         cidr = '10.11.0.0/16'
@@ -573,6 +591,11 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin):
         destroyed = fwr.destroy()
         self.assertTrue(destroyed)
 
+    def test_ex_destroy_route(self):
+        route = self.driver.ex_get_route('lcdemoroute')
+        destroyed = route.destroy()
+        self.assertTrue(destroyed)
+
     def test_ex_destroy_network(self):
         network = self.driver.ex_get_network('lcnetwork')
         destroyed = network.destroy()
@@ -675,6 +698,13 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin):
         self.assertEqual(image.name, name)
         self.assertEqual(image.extra['description'], description)
 
+    def test_ex_get_route(self):
+        route_name = 'lcdemoroute'
+        route = self.driver.ex_get_route(route_name)
+        self.assertEqual(route.name, route_name)
+        self.assertEqual(route.dest_range, '192.168.25.0/24')
+        self.assertEqual(route.priority, 1000)
+
     def test_ex_get_network(self):
         network_name = 'lcnetwork'
         network = self.driver.ex_get_network(network_name)
@@ -861,6 +891,13 @@ class GCEMockHttp(MockHttpTestCase):
         body = self.fixtures.load('global_images_debian_6_squeeze_v20130926_deprecate.json')
         return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
 
+    def _global_routes(self, method, url, body, headers):
+        if method == 'POST':
+            body = self.fixtures.load('global_routes_post.json')
+        else:
+            body = self.fixtures.load('global_routes.json')
+        return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
+
     def _global_networks(self, method, url, body, headers):
         if method == 'POST':
             body = self.fixtures.load('global_networks_post.json')
@@ -883,6 +920,13 @@ class GCEMockHttp(MockHttpTestCase):
             'global_networks_libcloud-demo-europe-network.json')
         return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
 
+    def _global_routes_lcdemoroute(self, method, url, body, headers):
+        if method == 'DELETE':
+            body = self.fixtures.load('global_routes_lcdemoroute_delete.json')
+        else:
+            body = self.fixtures.load('global_routes_lcdemoroute.json')
+        return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
+
     def _global_networks_lcnetwork(self, method, url, body, headers):
         if method == 'DELETE':
             body = self.fixtures.load('global_networks_lcnetwork_delete.json')
@@ -944,12 +988,24 @@ class GCEMockHttp(MockHttpTestCase):
             'operations_operation_global_firewalls_post.json')
         return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
 
+    def _global_operations_operation_global_routes_lcdemoroute_delete(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+            'operations_operation_global_routes_lcdemoroute_delete.json')
+        return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
+
     def _global_operations_operation_global_networks_lcnetwork_delete(
             self, method, url, body, headers):
         body = self.fixtures.load(
             'operations_operation_global_networks_lcnetwork_delete.json')
         return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
 
+    def _global_operations_operation_global_routes_post(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+            'operations_operation_global_routes_post.json')
+        return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
+
     def _global_operations_operation_global_networks_post(
             self, method, url, body, headers):
         body = self.fixtures.load(