top button
    Connect to us
      Facebook Login
      Site Registration Why to Join

Facebook Login
Site Registration
Print Preview

Snippets of Python code for OpenStack (Icehouse) Integration

+1 vote
343 views

Some working code snippets from our OpenStack POC.

Background:
In LTE packet core (EPC), PCRF provides policy control. Our POC shows how a PCRF built using LCN Gx interface can be virtualized, and how an instance of this PCRF is created, LCN Diameter load balancer detects this and starts forwarding Diameter requests to the new PCRF instance. Please check the article http://community.lcnpl.com/68/virtual-epc-a-technology-demonstrator for more information on the POC.

Note: LCN offers only the Diameter stack and the DSC (load balancer). The PCRF used in the POC is only a sample implementation developed for demonstration.

Here we produce key code snippets used to monitor VM instance creation, floating IP address assignment etc. When we did this work, we had to read some documentation (when everything else failed :). We didn't find many examples. The purpose is to share our experience and hopefully make it easier for other developers to start off.

First, the Python libraries we use:

 # for creating a consumer for nova and neurton notifications
from kombu.mixins import ConsumerMixin
from kombu import Queue, Exchange
 #for searching for specific events and other information
import re
 #process json notifications
import json
 # to query nova for VM instance information
import novaclient.client 
 # for getting credentials
from os import environ as env
 #invoking application specific commands
import subprocess
 #sleep
import time
import sys
 # for looking up specific VM image
import glanceclient
 # for access credentials
import keystoneclient.v2_0.client as ksclient

The following function uses Glance client to query the image database, and to extract image id for a specific application. You will see its application later

# Get Image Id for "lcn_gxs" - name of our PCRF image snapshot
 # We do this once in the beginning, so that later when notifications are 
 # received, we can identify the VM instance

def GetImageId():
    keysarg = {}
    keysarg['username']=env['OS_USERNAME']
    keysarg['password']=env['OS_PASSWORD']

 # Aside: you need 'password' and 'tenant_name' here, Nova needs 'api_key' and
 # 'project_name :(  

    keysarg['tenant_name']=env['OS_TENANT_NAME']
    keysarg['auth_url']=env['OS_AUTH_URL']
    keystone = ksclient.Client(**keysarg)
    glance_endpoint = keystone.service_catalog.url_for(service_type='image',
                                                   endpoint_type='publicURL')
    glClient = glanceclient.Client('2',glance_endpoint, token=keystone.auth_token)
 # we have instantiated a Glance client, now query the list of images and
 # extract the image id for 'lcn_gxs'

    l = glClient.images.list()
    for s in l: 
      if s.name == 'lcn_gxs' :
        global gx_image_id
        gx_image_id = s.id
        print "Found image " + gx_image_id
        break
    else:
 # we didn't find our image in the store, so let us not waste our time
       print "Couldn't find the image" 
       sys.exit(1)

The most important part - the consumer that listens to required notifications. We want to capture 'floating-ip-assignment' from neutron and if it is our application, take the required steps to configure our DSC (Diameter router) so that new requests get forwarded to this server. (Diameter specific details are skipped here for clarity).

class Worker(ConsumerMixin):

 # neutron and nova exchanges to which we will bind. 
    neutx = Exchange('neutron', 'topic', durable=False)
    novax = Exchange('nova', 'topic', durable=False)

 # create new queues to listen to nova messages. Temp queue, get deleted when
 # this  program exits
 # Aside: we started with existing queues (created by OpenStack), but realized
 # that there are other consumers listening on those queues, and notifications
 # are distributed in round-robin fashion. Then we realized that this is a
 # better approach.

 # to get VM instance deletion information
    vminfoq = Queue('lcndiamc_omp_queue', novax, durable=False, routing_key='notifications.info',exclusive=True)
 # to get floating-ip-assignment notification
    netinfoq = Queue('lcndiam_net_queue', neutx, durable=False, routing_key='#',exclusive=True)

    def __init__(self, connection):
        self.connection = connection

    def get_consumers(self, Consumer, channel):
        return [Consumer(queues=[self.netinfoq, self.vminfoq ],
 # for now, only json
                         accept=['json'],
                         callbacks=[self.process_task])]

 # OK, finally the real worker

    def process_task(self, body, message):
        message.ack()

 # check if this is floating-ip assignment
 # Python experts: please suggest better ways of doing this - probably
 # by creating a dictionary

        msg =  repr(json.dumps(body))
        if re.search('.event_type.:\s*.floatingip.update.end.', msg):
 #          Found floatingip.update.end. Extract floating ip with the prefix
          m = re.search('.floating_ip_address.:\s*.\d+.\d+.\d+.\d+', msg)
          if m:
 #          Extract fixed  ip also. Probaby we don't need this, but is used
 #     in searching for the servers
            m_fixed = re.search('.fixed_ip_address.:\s*.\d+.\d+.\d+.\d+', msg)
            DiameterAddRoute(m.group(), m_fixed.group())
 #  VM deletion
        if re.search('.event_type.:\s*.compute.instance.delete.start.', msg):
           if re.search (gx_image_id, msg):
 # a server instance is getting deleted...
             m = re.search('.instance_id.:\s*"\w+-\w+-\w+-\w+-\w+"', msg)
 #       Extract instance id for dict lookup
             DiameterDeleteRoute(m.group())


We will skip application details, but here is a Nova client example:

def DiameterAddRoute( fl_text, fi_text):
 # <skipping some application code>
 #
 # Note: we had to sleep for a few secs. Looks like it takes a while before 
 # nova database gets updated. This is a problem, we can't afford to sleep here....
  time.sleep(5)
 # now find the VM and see if it is our image
  l = novaClient.servers.list(detailed=True )
  for s in l:
      image = json.dumps(s.image)
      if re.search (gx_image_id, image):
        print "Found a Gx sever image " + s.name
 # Continue ... Check its addresses and if it the new server
 # do application specific processing.

Finally, the 'main'

if __name__ == '__main__':
 #first, get the image id for "lcn_gxs" image
 # Exits if it doesn't find the image

    GetImageId()
 # Initialzie nova client object for  later use

    keysarg = {}
    keysarg['username']=env['OS_USERNAME']
    keysarg['api_key']=env['OS_PASSWORD']
    keysarg['auth_url']=env['OS_AUTH_URL']
    keysarg['project_id']=env['OS_TENANT_NAME']
    novaClient = novaclient.client.Client(2,**keysarg)
 #used later as seen above.


    from kombu import Connection
 # Now enter the event loop

    print "Entering loop "
with Connection('amqp://guest:guest@localhost:5672//') as conn:
        try:
            print(conn)
            worker = Worker(conn)
            worker.run()
        except KeyboardInterrupt:
            print('bye bye')
posted Jan 15, 2015 by Rathnakumar Kayyar

  Promote This Article
Facebook Share Button Twitter Share Button Google+ Share Button LinkedIn Share Button Multiple Social Share Button

...