cancel
Showing results for 
Search instead for 
Did you mean: 
cancel

Best REST in OpenStack

1321
Views
2
Helpful
0
Comments
Cisco Employee

This is a blog about the best practices to develop, test, debug and scale REST APIs in an OpenStack cloud.  OpenStack is a great way to deploy a cloud in data centers and is one of the most popular open-source projects to deploy highly-scalable clouds.  OpenStack is all about RESTful services.  Every service in OpenStack talks to every other service using REST APIs.  As a cloud operator deploying OpenStack, it is very important to understand how REST APIs work in order to debug and scale an OpenStack cloud effectively.

What is a RESTful service?

  • Representational State Transfer (REST) is a stateless, client-server based, cacheable web service
  • Uses HTTP protocol for communication
  • Data is considered as a “resource” and accessed using Uniform Resource Identifiers (URIs) that typically look like a web link
  • URI is RFC3986 (RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax)
  • Uses HTTP clients like curl, browsers (Google Chrome Postman) and wget

REST in OpenStack

OS.png

I gave a talk "Best REST in OpenStack" at Cisco Live in Las Vegas in 2016.  My talk covered the following topics:

  • Run OpenStack Neutron CLIs and analyze REST packets in WireShark
  • REST for big data use cases – REST pagination in Neutron
  • Implementing a RESTful server using Python Flask

The slides from my talk are at http://www.slideshare.net/Vikram_Hosakote/best-rest-in-openstack.

The scripts I used in my talk are at GitHub - vhosakot/Cisco-Live-Workshop: Scripts for Cisco Live Workshops.

Troubleshooting / debugging REST APIs

Sample script to troubleshoot / debug REST APIs using Python

import httplib

import logging

import requests

httplib.HTTPConnection.debuglevel = 1

logging.basicConfig()

logging.getLogger().setLevel(logging.DEBUG)

requests_log = logging.getLogger("requests.packages.urllib3")

requests_log.setLevel(logging.DEBUG)

requests_log.propagate = True

result = requests.get('http://www.cisco.com/')


Output of above Python script with REST API debug messages


>>> result = requests.get('http://www.cisco.com/')

INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): www.cisco.com

send: 'GET / HTTP/1.1\r\nHost: www.cisco.com\r\nConnection: keep-alive\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nUser-Agent: python-requests/2.10.0\r\n\r\n'

reply: 'HTTP/1.1 200 OK\r\n'

header: Server: Apache

header: ETag: "10839-53789488e5b33"

header: Accept-Ranges: bytes

header: Content-Encoding: gzip

header: CDCHOST: wemxweb-publish-prod1-01

header: Content-Length: 14215

header: Content-Type: text/html

header: Expires: Wed, 13 Jul 2016 20:25:27 GMT

header: Cache-Control: max-age=0, no-cache, no-store

header: Pragma: no-cache

header: Date: Wed, 13 Jul 2016 20:25:27 GMT

header: Connection: keep-alive

header: access-control-allow-origin: *

DEBUG:requests.packages.urllib3.connectionpool:"GET / HTTP/1.1" 200 14215


>>> print result

<Response [200]>

Sample script to mock a REST server to unit-test Python REST APIs

$ python

>>> import requests

>>> import requests_mock

>>> session = requests.Session()

>>> adapter = requests_mock.Adapter()

>>> session.mount('mock', adapter)

>>> adapter.register_uri('GET', 'mock://test.com', text='data')

>>> resp = session.get('mock://test.com')

>>> resp.status_code, resp.text

(200, 'data')

https://github.com/openstack/requests-mock

https://pypi.python.org/pypi/mock-server/0.3.7

https://github.com/gabrielfalcao/HTTPretty

http://python-mock-tutorial.readthedocs.io/en/latest/mock.html

REST API caching and cache-aware REST clients

RFC 7234 - https://tools.ietf.org/html/rfc7234#section-5

REST supports the following HTTP cache-control headers:

  • max-age
  • max-stale
  • min-fresh
  • no-cache
  • no-store
  • no-transform
  • only-if-cached
  • must-revalidate
  • public
  • private


cache.png

Bulk REST operations and REST API batching


Bulk REST operations allow us to perform REST operations (GET, POST, PUT, DELETE) on bulk (more than one) objects (networks, ports, subnets, etc) at once.  This reduces the number of REST messages between client and the server.

http://developer.openstack.org/api-ref-networking-v2.html#bulkCreateNetwork

https://wiki.openstack.org/wiki/Neutron/APIv2-specification#Bulk_version

Bulk REST API JSON request format to create five neutron networks in OpenStack using POST operation:


POST v2.0/networks.json

Content-Type: application/json

Accept: application/json

{

"networks": [

   {

     "name": "sample_network_1",

     "admin_state_up": false

   },

   {

     "name": "sample_network_2",

     "admin_state_up": false

   }

   {

     "name": "sample_network_3”,

     "admin_state_up": true

   }

   {

     "name": "sample_network_4”,

     "admin_state_up": true

   }

   {

     "name": "sample_network_5”,

     "admin_state_up": false

   }]

}

This widget could not be displayed.