CAL refactoring
[osm/SO.git] / rwcal / plugins / vala / rwcal_openstack / rift / rwcal / openstack / openstack_drv.py
index 191a06f..500f10c 100644 (file)
 #   limitations under the License.
 #
 
-import json
 import logging
-import ipaddress
 
-from keystoneclient import v3 as ksclientv3
-from keystoneclient.v2_0 import client as ksclientv2
-from novaclient import client as nova_client
-from neutronclient.neutron import client as ntclient
-from glanceclient.v2 import client as glclient
-from ceilometerclient import client as ceilo_client
-from cinderclient.v2 import client as cinder_client
+from . import session as sess_drv
+from . import keystone as ks_drv
+from . import nova as nv_drv
+from . import neutron as nt_drv
+from . import glance as gl_drv
+from . import ceilometer as ce_drv
+from . import cinder as ci_drv
+from . import portchain as port_drv
+from . import utils as drv_utils
 
 # Exceptions
-import novaclient.exceptions as NovaException
 import keystoneclient.exceptions as KeystoneExceptions
-import neutronclient.common.exceptions as NeutronException
-import glanceclient.exc as GlanceException
-import cinderclient.exceptions as CinderException
 
-logger = logging.getLogger('rwcal.openstack.drv')
-logger.setLevel(logging.DEBUG)
 
 class ValidationError(Exception):
     pass
 
 
-class KeystoneDriver(object):
+class DriverUtilities(object):
     """
-    Driver base-class for keystoneclient APIs
+    Class with utility method 
     """
-    def __init__(self, ksclient):
+    def __init__(self, driver):
         """
-        Constructor for KeystoneDriver base class
-        Arguments: None
-        Returns: None
-        """
-        self.ksclient = ksclient
-
-    def get_username(self):
-        """
-        Returns the username associated with keystoneclient connection
-        """
-        return self._username
-
-    def get_password(self):
-        """
-        Returns the password associated with keystoneclient connection
-        """
-        return self._password
-
-    def get_tenant_name(self):
-        """
-        Returns the tenant name associated with keystoneclient connection
-        """
-        return self._tenant_name
-
-    def get_user_domain_name(self):
-        """
-        Returns None as this field does not exist for v2.
-        """
-        return None;
-
-    def get_project_domain_name(self):
-        """
-        Returns None as this field does not exist for v2.
-        """
-        return None;
-
-    def _get_keystone_connection(self):
-        """
-        Returns object of class python-keystoneclient class
-        """
-        if not hasattr(self, '_keystone_connection'):
-            self._keystone_connection = self.ksclient(**self._get_keystone_credentials())
-        return self._keystone_connection
-
-    def is_auth_token_valid(self, token_expiry, time_fmt):
-        """
-        Performs validity on auth_token
-        Arguments:
-          token_expiry (string): Expiry time for token
-          time_fmt (string)    : Format for expiry string in auth_ref
-
-        Returns:
-        True/False (Boolean):  (auth_token is valid or auth_token is invalid)
-        """
-        import time
-        import datetime
-        import dateutil.parser
-        try:
-            now = datetime.datetime.timetuple(datetime.datetime.utcnow())
-            expires_at = dateutil.parser.parse(token_expiry)
-            t_now = time.mktime(now)
-            t_expiry = time.mktime(expires_at.timetuple())
-
-            if (t_expiry <= t_now) or ((t_expiry - t_now) < 300 ):
-                ### Token has expired or about to expire (5 minute)
-                delattr(self, '_keystone_connection')
-                return False
-            else:
-                return True
-        except Exception as e:
-            logger.error("Received except %s during auth_token validity check" %str(e))
-            logger.info("Can not validate the auth_token. Assuming invalid")
-            return False
-
-
-    def get_service_endpoint(self, service_type, endpoint_type):
-        """
-        Returns requested type of endpoint for requested service type
-        Arguments:
-          service_type (string): Service Type (e.g. computev3, image, network)
-          endpoint_type(string): Endpoint Type (e.g. publicURL,adminURL,internalURL)
-        Returns:
-          service_endpoint(string): Service endpoint string
-        """
-        endpoint_kwargs   = {'service_type'  : service_type,
-                             'endpoint_type' : endpoint_type}
-        try:
-            ksconn = self._get_keystone_connection()
-            service_endpoint  = ksconn.service_catalog.url_for(**endpoint_kwargs)
-        except (KeystoneExceptions.Unauthorized, KeystoneExceptions.AuthorizationFailure) as e:
-            raise
-        except Exception as e:
-            logger.error("OpenstackDriver: Service Catalog discovery operation failed for service_type: %s, endpoint_type: %s. Exception: %s" %(service_type, endpoint_type, str(e)))
-            raise
-        return service_endpoint
-
-
-    def get_raw_token(self):
-        """
-        Returns a valid raw_auth_token string
-
-        Returns (string): raw_auth_token string
-        """
-        ksconn = self._get_keystone_connection()
-        try:
-            raw_token = ksconn.get_raw_token_from_identity_service(auth_url = self._auth_url,
-                                                                   token    = self.get_auth_token())
-        except KeystoneExceptions.AuthorizationFailure as e:
-            logger.error("OpenstackDriver: get_raw_token_from_identity_service Failure. Exception: %s" %(str(e)))
-            return None
-
-        except Exception as e:
-            logger.error("OpenstackDriver: Could not retrieve raw_token. Exception: %s" %(str(e)))
-
-        return raw_token
-
-    def get_tenant_id(self):
-        """
-        Returns tenant_id for the project/tenant. Tenant name is provided during
-        class instantiation
-
-        Returns (string): Tenant ID
-        """
-        ksconn = self._get_keystone_connection()
-        return ksconn.tenant_id
-
-    def get_security_mode(self):
-        """
-        Returns certificate_validation policy in case of SSL/TLS connection.
-        This policy is provided during class instantiation
-
-        Returns (boolean):
-        The boolean returned are designed to match the python-client class instantiation ("insecure") value.
-        for nova/neutron/glance/keystone clients
-
-        True: No certificate validation required -- Insecure mode
-        False: Certificate validation required -- Secure mode
-        """
-        return self._insecure
-
-    def tenant_list(self):
-        """
-        Returns list of tenants
-        """
-        pass
-
-    def tenant_create(self, name):
-        """
-        Create a new tenant
-        """
-        pass
-
-    def tenant_delete(self, tenant_id):
-        """
-        Deletes a tenant identified by tenant_id
-        """
-        pass
-
-    def roles_list(self):
-        pass
-
-    def roles_create(self):
-        pass
-
-    def roles_delete(self):
-        pass
-
-class KeystoneDriverV2(KeystoneDriver):
-    """
-    Driver class for keystoneclient V2 APIs
-    """
-    def __init__(self, username, password, auth_url,tenant_name, insecure, region):
-        """
-        Constructor for KeystoneDriverV3 class
-        Arguments:
-        username (string)  : Username
-        password (string)  : Password
-        auth_url (string)  : Authentication URL
-        tenant_name(string): Tenant Name
-        region (string)    : Region name
-        Returns: None
-        """
-        self._username    = username
-        self._password    = password
-        self._auth_url    = auth_url
-        self._tenant_name = tenant_name
-        self._insecure    = insecure
-        self._region      = region
-        super(KeystoneDriverV2, self).__init__(ksclientv2.Client)
-
-    def _get_keystone_credentials(self):
-        """
-        Returns the dictionary of kwargs required to instantiate python-keystoneclient class
-        """
-        creds                 = {}
-        #creds['user_domain'] = self._domain_name
-        creds['username']     = self._username
-        creds['password']     = self._password
-        creds['auth_url']     = self._auth_url
-        creds['tenant_name']  = self._tenant_name
-        creds['insecure']     = self.get_security_mode()
-        creds['region_name']  = self._region
-        return creds
-
-    def get_auth_token(self):
-        """
-        Returns a valid auth_token
-
-        Returns (string): auth_token string
-        """
-        ksconn = self._get_keystone_connection()
-        return ksconn.auth_token
-
-    def is_auth_token_valid(self):
-        """
-        Performs validity on auth_token
-        Arguments:
-
-        Returns:
-        True/False (Boolean):  (auth_token is valid or auth_token is invalid)
-        """
-        ksconn = self._get_keystone_connection()
-        result = super(KeystoneDriverV2, self).is_auth_token_valid(ksconn.auth_ref['token']['expires'],
-                                                                   "%Y-%m-%dT%H:%M:%SZ")
-        return result
-
-
-class KeystoneDriverV3(KeystoneDriver):
-    """
-    Driver class for keystoneclient V3 APIs
-    """
-    def __init__(self, username,
-                 password,
-                 auth_url,
-                 tenant_name,
-                 insecure,
-                 user_domain_name = None,
-                 project_domain_name = None,
-                 region = None):
-        """
-        Constructor for KeystoneDriverV3 class
-        Arguments:
-        username (string)  : Username
-        password (string)  : Password
-        auth_url (string)  : Authentication URL
-        tenant_name(string): Tenant Name
-        user_domain_name (string) : User domain name
-        project_domain_name (string): Project domain name
-        region (string)    : Region name
-        Returns: None
-        """
-        self._username             = username
-        self._password             = password
-        self._auth_url             = auth_url
-        self._tenant_name          = tenant_name
-        self._insecure             = insecure
-        self._user_domain_name     = user_domain_name
-        self._project_domain_name  = project_domain_name
-        self._region               = region
-        super(KeystoneDriverV3, self).__init__(ksclientv3.Client)
-
-    def _get_keystone_credentials(self):
-        """
-        Returns the dictionary of kwargs required to instantiate python-keystoneclient class
-        """
-        creds                        = {}
-        creds['username']            = self._username
-        creds['password']            = self._password
-        creds['auth_url']            = self._auth_url
-        creds['project_name']        = self._tenant_name
-        creds['insecure']            = self._insecure
-        creds['user_domain_name']    = self._user_domain_name
-        creds['project_domain_name'] = self._project_domain_name
-        creds['region_name']         = self._region
-        return creds
-
-    def get_user_domain_name(self):
-        """
-        Returns the domain_name of the associated OpenStack user account
-        """
-        return self._user_domain_name;
-
-    def get_project_domain_name(self):
-        """
-        Returns the domain_name of the associated OpenStack project
-        """
-        return self._project_domain_name;
-
-    def get_auth_token(self):
-        """
-        Returns a valid auth_token
-
-        Returns (string): auth_token string
-        """
-        ksconn = self._get_keystone_connection()
-        return ksconn.auth_ref['auth_token']
-
-    def is_auth_token_valid(self):
-        """
-        Performs validity on auth_token
-        Arguments:
-
-        Returns:
-        True/False (Boolean):  (auth_token is valid or auth_token is invalid)
-        """
-        ksconn = self._get_keystone_connection()
-        result = super(KeystoneDriverV3, self).is_auth_token_valid(ksconn.auth_ref['expires_at'],
-                                                                   "%Y-%m-%dT%H:%M:%S.%fZ")
-        return result
-
-class NovaDriver(object):
-    """
-    Driver for openstack nova_client
-    """
-    def __init__(self, ks_drv, service_name, version):
-        """
-        Constructor for NovaDriver
-        Arguments: KeystoneDriver class object
-        """
-        self.ks_drv = ks_drv
-        self._service_name = service_name
-        self._version = version
-
-    def _get_nova_credentials(self):
-        """
-        Returns a dictionary of kwargs required to instantiate python-novaclient class
-        """
-        creds               = {}
-        creds['version']    = self._version
-        creds['bypass_url'] = self.ks_drv.get_service_endpoint(self._service_name, "publicURL")
-        creds['username']   = self.ks_drv.get_username()
-        creds['project_id'] = self.ks_drv.get_tenant_name()
-        creds['auth_token'] = self.ks_drv.get_auth_token()
-        creds['insecure']   = self.ks_drv.get_security_mode()
-        #creds['user_domain_name'] = self.ks_drv.get_user_domain_name()
-        #creds['project_domain_name'] = self.ks_drv.get_project_domain_name()
-
-        return creds
-
-    def _get_nova_connection(self):
-        """
-        Returns an object of class python-novaclient
-        """
-        if not hasattr(self, '_nova_connection'):
-            self._nova_connection = nova_client.Client(**self._get_nova_credentials())
-        else:
-            # Reinitialize if auth_token is no longer valid
-            if not self.ks_drv.is_auth_token_valid():
-                self._nova_connection = nova_client.Client(**self._get_nova_credentials())
-        return self._nova_connection
-
-    def _flavor_get(self, flavor_id):
-        """
-        Get flavor by flavor_id
-        Arguments:
-           flavor_id(string): UUID of flavor_id
-
-        Returns:
-        dictionary of flavor parameters
-        """
-        nvconn = self._get_nova_connection()
-        try:
-            flavor = nvconn.flavors.get(flavor_id)
-        except Exception as e:
-            logger.info("OpenstackDriver: Did not find flavor with flavor_id : %s. Exception: %s"%(flavor_id, str(e)))
-            raise
-
-        try:
-            extra_specs = flavor.get_keys()
-        except Exception as e:
-            logger.info("OpenstackDriver: Could not get the EPA attributes for flavor with flavor_id : %s. Exception: %s"%(flavor_id, str(e)))
-            raise
-
-        response = flavor.to_dict()
-        assert 'extra_specs' not in response, "Key extra_specs present as flavor attribute"
-        response['extra_specs'] = extra_specs
-        return response
-
-    def flavor_get(self, flavor_id):
-        """
-        Get flavor by flavor_id
-        Arguments:
-           flavor_id(string): UUID of flavor_id
-
-        Returns:
-        dictionary of flavor parameters
-        """
-        return self._flavor_get(flavor_id)
-
-    def flavor_list(self):
-        """
-        Returns list of all flavors (dictionary per flavor)
-
-        Arguments:
-           None
-        Returns:
-           A list of dictionaries. Each dictionary contains attributes for a single flavor instance
-        """
-        flavors = []
-        flavor_info = []
-        nvconn =  self._get_nova_connection()
-        try:
-            flavors = nvconn.flavors.list()
-        except Exception as e:
-            logger.error("OpenstackDriver: List Flavor operation failed. Exception: %s"%(str(e)))
-            raise
-        if flavors:
-            flavor_info = [ self.flavor_get(flv.id) for flv in flavors ]
-        return flavor_info
-
-    def flavor_create(self, name, ram, vcpu, disk, extra_specs):
-        """
-        Create a new flavor
-
-        Arguments:
-           name   (string):  Name of the new flavor
-           ram    (int)   :  Memory in MB
-           vcpus  (int)   :  Number of VCPUs
-           disk   (int)   :  Secondary storage size in GB
-           extra_specs (dictionary): EPA attributes dictionary
-
-        Returns:
-           flavor_id (string): UUID of flavor created
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            flavor = nvconn.flavors.create(name        = name,
-                                           ram         = ram,
-                                           vcpus       = vcpu,
-                                           disk        = disk,
-                                           flavorid    = 'auto',
-                                           ephemeral   = 0,
-                                           swap        = 0,
-                                           rxtx_factor = 1.0,
-                                           is_public    = True)
-        except Exception as e:
-            logger.error("OpenstackDriver: Create Flavor operation failed. Exception: %s"%(str(e)))
-            raise
-
-        if extra_specs:
-            try:
-                flavor.set_keys(extra_specs)
-            except Exception as e:
-                logger.error("OpenstackDriver: Set Key operation failed for flavor: %s. Exception: %s" %(flavor.id, str(e)))
-                raise
-        return flavor.id
-
-    def flavor_delete(self, flavor_id):
-        """
-        Deletes a flavor identified by flavor_id
-
-        Arguments:
-           flavor_id (string):  UUID of flavor to be deleted
-
-        Returns: None
-        """
-        assert flavor_id == self._flavor_get(flavor_id)['id']
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.flavors.delete(flavor_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Delete flavor operation failed for flavor: %s. Exception: %s" %(flavor_id, str(e)))
-            raise
-
-
-    def server_list(self):
-        """
-        Returns a list of available VMs for the project
-
-        Arguments: None
-
-        Returns:
-           A list of dictionaries. Each dictionary contains attributes associated
-           with individual VM
-        """
-        servers     = []
-        server_info = []
-        nvconn      = self._get_nova_connection()
-        try:
-            servers     = nvconn.servers.list()
-        except Exception as e:
-            logger.error("OpenstackDriver: List Server operation failed. Exception: %s" %(str(e)))
-            raise
-        server_info = [ server.to_dict() for server in servers]
-        return server_info
-
-    def _nova_server_get(self, server_id):
-        """
-        Returns a dictionary of attributes associated with VM identified by service_id
-
-        Arguments:
-          server_id (string): UUID of the VM/server for which information is requested
-
-        Returns:
-          A dictionary object with attributes associated with VM identified by server_id
-        """
-        nvconn = self._get_nova_connection()
-        try:
-            server = nvconn.servers.get(server = server_id)
-        except Exception as e:
-            logger.info("OpenstackDriver: Get Server operation failed for server_id: %s. Exception: %s" %(server_id, str(e)))
-            raise
-        else:
-            return server.to_dict()
-
-    def server_get(self, server_id):
-        """
-        Returns a dictionary of attributes associated with VM identified by service_id
-
-        Arguments:
-          server_id (string): UUID of the VM/server for which information is requested
-
-        Returns:
-          A dictionary object with attributes associated with VM identified by server_id
-        """
-        return self._nova_server_get(server_id)
-
-    def server_create(self, **kwargs):
-        """
-        Creates a new VM/server instance
-
-        Arguments:
-          A dictionary of following key-value pairs
-         {
-           server_name(string)        : Name of the VM/Server
-           flavor_id  (string)        : UUID of the flavor to be used for VM
-           image_id   (string)        : UUID of the image to be used VM/Server instance,
-                                             This could be None if volumes (with images) are being used
-           network_list(List)         : A List of network_ids. A port will be created in these networks
-           port_list (List)           : A List of port-ids. These ports will be added to VM.
-           metadata   (dict)          : A dictionary of arbitrary key-value pairs associated with VM/server
-           userdata   (string)        : A script which shall be executed during first boot of the VM
-           availability_zone (string) : A name of the availability zone where instance should be launched
-           scheduler_hints (string)   : Openstack scheduler_hints to be passed to nova scheduler
-         }
-        Returns:
-          server_id (string): UUID of the VM/server created
-
-        """
-        nics = []
-        if 'network_list' in kwargs:
-            for network_id in kwargs['network_list']:
-                nics.append({'net-id': network_id})
-
-        if 'port_list' in kwargs:
-            for port_id in kwargs['port_list']:
-                nics.append({'port-id': port_id})
-
-        nvconn = self._get_nova_connection()
-
-
-        try:
-            server = nvconn.servers.create(kwargs['name'],
-                                           kwargs['image_id'],
-                                           kwargs['flavor_id'],
-                                           meta                 = kwargs['metadata'],
-                                           files                = kwargs['files'],
-                                           reservation_id       = None,
-                                           min_count            = None,
-                                           max_count            = None,
-                                           userdata             = kwargs['userdata'],
-                                           security_groups      = kwargs['security_groups'],
-                                           availability_zone    = kwargs['availability_zone'],
-                                           block_device_mapping_v2 = kwargs['block_device_mapping_v2'],
-                                           nics                 = nics,
-                                           scheduler_hints      = kwargs['scheduler_hints'],
-                                           config_drive         = kwargs['config_drive'])
-        except Exception as e:
-            logger.info("OpenstackDriver: Create Server operation failed. Exception: %s" %(str(e)))
-            raise
-        return server.to_dict()['id']
-
-    def server_delete(self, server_id):
-        """
-        Deletes a server identified by server_id
-
-        Arguments:
-           server_id (string): UUID of the server to be deleted
-
-        Returns: None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.delete(server_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Delete server operation failed for server_id: %s. Exception: %s" %(server_id, str(e)))
-            raise
-
-    def server_start(self, server_id):
-        """
-        Starts a server identified by server_id
-
-        Arguments:
-           server_id (string): UUID of the server to be started
-
-        Returns: None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.start(server_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Start Server operation failed for server_id : %s. Exception: %s" %(server_id, str(e)))
-            raise
-
-    def server_stop(self, server_id):
-        """
-        Arguments:
-           server_id (string): UUID of the server to be stopped
-
-        Returns: None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.stop(server_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Stop Server operation failed for server_id : %s. Exception: %s" %(server_id, str(e)))
-            raise
-
-    def server_pause(self, server_id):
-        """
-        Arguments:
-           server_id (string): UUID of the server to be paused
-
-        Returns: None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.pause(server_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Pause Server operation failed for server_id : %s. Exception: %s" %(server_id, str(e)))
-            raise
-
-    def server_unpause(self, server_id):
-        """
-        Arguments:
-           server_id (string): UUID of the server to be unpaused
-
-        Returns: None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.unpause(server_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Resume Server operation failed for server_id : %s. Exception: %s" %(server_id, str(e)))
-            raise
-
-
-    def server_suspend(self, server_id):
-        """
-        Arguments:
-           server_id (string): UUID of the server to be suspended
-
-        Returns: None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.suspend(server_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Suspend Server operation failed for server_id : %s. Exception: %s" %(server_id, str(e)))
-
-
-    def server_resume(self, server_id):
-        """
-        Arguments:
-           server_id (string): UUID of the server to be resumed
-
-        Returns: None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.resume(server_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Resume Server operation failed for server_id : %s. Exception: %s" %(server_id, str(e)))
-            raise
-
-    def server_reboot(self, server_id, reboot_type):
-        """
-        Arguments:
-           server_id (string) : UUID of the server to be rebooted
-           reboot_type(string):
-                         'SOFT': Soft Reboot
-                         'HARD': Hard Reboot
-        Returns: None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.reboot(server_id, reboot_type)
-        except Exception as e:
-            logger.error("OpenstackDriver: Reboot Server operation failed for server_id: %s. Exception: %s" %(server_id, str(e)))
-            raise
-
-    def server_console(self, server_id, console_type = 'novnc'):
-        """
-        Arguments:
-           server_id (string) : UUID of the server to be rebooted
-           console_type(string):
-                               'novnc',
-                               'xvpvnc'
-        Returns:
-          A dictionary object response for console information
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            console_info = nvconn.servers.get_vnc_console(server_id, console_type)
-        except Exception as e:
-            logger.error("OpenstackDriver: Server Get-Console operation failed for server_id: %s. Exception: %s" %(server_id, str(e)))
-            raise
-        return console_info
-
-    def server_rebuild(self, server_id, image_id):
-        """
-        Arguments:
-           server_id (string) : UUID of the server to be rebooted
-           image_id (string)  : UUID of the image to use
-        Returns: None
-        """
-
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.rebuild(server_id, image_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Rebuild Server operation failed for server_id: %s. Exception: %s" %(server_id, str(e)))
-            raise
-
-
-    def server_add_port(self, server_id, port_id):
-        """
-        Arguments:
-           server_id (string): UUID of the server
-           port_id   (string): UUID of the port to be attached
-
-        Returns: None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.interface_attach(server_id,
-                                            port_id,
-                                            net_id = None,
-                                            fixed_ip = None)
-        except Exception as e:
-            logger.error("OpenstackDriver: Server Port Add operation failed for server_id : %s, port_id : %s. Exception: %s" %(server_id, port_id, str(e)))
-            raise
-
-    def server_delete_port(self, server_id, port_id):
-        """
-        Arguments:
-           server_id (string): UUID of the server
-           port_id   (string): UUID of the port to be deleted
-        Returns: None
-
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.interface_detach(server_id, port_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Server Port Delete operation failed for server_id : %s, port_id : %s. Exception: %s" %(server_id, port_id, str(e)))
-            raise
-
-    def floating_ip_list(self):
-        """
-        Arguments:
-            None
-        Returns:
-            List of objects of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            ip_list = nvconn.floating_ips.list()
-        except Exception as e:
-            logger.error("OpenstackDriver: Floating IP List operation failed. Exception: %s" %str(e))
-            raise
-
-        return ip_list
-
-    def floating_ip_create(self, pool):
-        """
-        Arguments:
-           pool (string): Name of the pool (optional)
-        Returns:
-           An object of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            floating_ip = nvconn.floating_ips.create(pool)
-        except Exception as e:
-            logger.error("OpenstackDriver: Floating IP Create operation failed. Exception: %s"  %str(e))
-            raise
-
-        return floating_ip
-
-    def floating_ip_delete(self, floating_ip):
-        """
-        Arguments:
-           floating_ip: An object of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
-        Returns:
-           None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            floating_ip = nvconn.floating_ips.delete(floating_ip)
-        except Exception as e:
-            logger.error("OpenstackDriver: Floating IP Delete operation failed. Exception: %s"  %str(e))
-            raise
-
-    def floating_ip_assign(self, server_id, floating_ip, fixed_ip):
-        """
-        Arguments:
-           server_id (string)  : UUID of the server
-           floating_ip (string): IP address string for floating-ip
-           fixed_ip (string)   : IP address string for the fixed-ip with which floating ip will be associated
-        Returns:
-           None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.add_floating_ip(server_id, floating_ip, fixed_ip)
-        except Exception as e:
-            logger.error("OpenstackDriver: Assign Floating IP operation failed. Exception: %s"  %str(e))
-            raise
-
-    def floating_ip_release(self, server_id, floating_ip):
-        """
-        Arguments:
-           server_id (string)  : UUID of the server
-           floating_ip (string): IP address string for floating-ip
-        Returns:
-           None
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            nvconn.servers.remove_floating_ip(server_id, floating_ip)
-        except Exception as e:
-            logger.error("OpenstackDriver: Release Floating IP operation failed. Exception: %s"  %str(e))
-            raise
-
-    def volume_list(self, server_id):
-        """
-          List of volumes attached to the server
-  
-          Arguments:
-              None
-          Returns:
-             List of dictionary objects where dictionary is representation of class (novaclient.v2.volumes.Volume)
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            volumes = nvconn.volumes.get_server_volumes(server_id=server_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Get volume information failed. Exception: %s"  %str(e))
-            raise
-
-        volume_info = [v.to_dict() for v in volumes]
-        return volume_info
-
-
-    def group_list(self):
-        """
-        List of Server Affinity and Anti-Affinity Groups
-
-        Arguments:
-            None
-        Returns:
-           List of dictionary objects where dictionary is representation of class (novaclient.v2.server_groups.ServerGroup)
-        """
-        nvconn =  self._get_nova_connection()
-        try:
-            group_list = nvconn.server_groups.list()
-        except Exception as e:
-            logger.error("OpenstackDriver: Server Group List operation failed. Exception: %s"  %str(e))
-            raise
-
-        group_info = [ group.to_dict() for group in group_list ]
-        return group_info
-
-
-
-class NovaDriverV2(NovaDriver):
-    """
-    Driver class for novaclient V2 APIs
-    """
-    def __init__(self, ks_drv):
-        """
-        Constructor for NovaDriver
-        Arguments: KeystoneDriver class object
-        """
-        super(NovaDriverV2, self).__init__(ks_drv, 'compute', '2.0')
-
-class NovaDriverV21(NovaDriver):
-    """
-    Driver class for novaclient V2 APIs
-    """
-    def __init__(self, ks_drv):
-        """
-        Constructor for NovaDriver
-        Arguments: KeystoneDriver class object
-        """
-        super(NovaDriverV21, self).__init__(ks_drv, 'compute', '2.1')
-
-class GlanceDriver(object):
-    """
-    Driver for openstack glance-client
-    """
-    def __init__(self, ks_drv, service_name, version):
-        """
-        Constructor for GlanceDriver
-        Arguments: KeystoneDriver class object
-        """
-        self.ks_drv = ks_drv
-        self._service_name = service_name
-        self._version = version
-
-    def _get_glance_credentials(self):
-        """
-        Returns a dictionary of kwargs required to instantiate python-glanceclient class
-
-        Arguments: None
-
-        Returns:
-           A dictionary object of arguments
-        """
-        creds             = {}
-        creds['version']  = self._version
-        creds['endpoint'] = self.ks_drv.get_service_endpoint(self._service_name, 'publicURL')
-        creds['token']    = self.ks_drv.get_auth_token()
-        creds['insecure'] = self.ks_drv.get_security_mode()
-        return creds
-
-    def _get_glance_connection(self):
-        """
-        Returns a object of class python-glanceclient
-        """
-        if not hasattr(self, '_glance_connection'):
-            self._glance_connection = glclient.Client(**self._get_glance_credentials())
-        else:
-            # Reinitialize if auth_token is no longer valid
-            if not self.ks_drv.is_auth_token_valid():
-                self._glance_connection = glclient.Client(**self._get_glance_credentials())
-        return self._glance_connection
-
-    def image_list(self):
-        """
-        Returns list of dictionaries. Each dictionary contains attributes associated with
-        image
-
-        Arguments: None
-
-        Returns: List of dictionaries.
-        """
-        glconn = self._get_glance_connection()
-        images = []
-        try:
-            image_info = glconn.images.list()
-        except Exception as e:
-            logger.error("OpenstackDriver: List Image operation failed. Exception: %s" %(str(e)))
-            raise
-        images = [ img for img in image_info ]
-        return images
-
-    def image_create(self, **kwargs):
-        """
-        Creates an image
-        Arguments:
-           A dictionary of kwargs with following keys
-           {
-              'name'(string)         : Name of the image
-              'location'(string)     : URL (http://....) where image is located
-              'disk_format'(string)  : Disk format
-                    Possible values are 'ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso'
-              'container_format'(string): Container format
-                                       Possible values are 'ami', 'ari', 'aki', 'bare', 'ovf'
-              'tags'                 : A list of user tags
-              'checksum'             : The image md5 checksum
-           }
-        Returns:
-           image_id (string)  : UUID of the image
-
-        """
-        glconn = self._get_glance_connection()
-        try:
-            image = glconn.images.create(**kwargs)
-        except Exception as e:
-            logger.error("OpenstackDriver: Create Image operation failed. Exception: %s" %(str(e)))
-            raise
-
-        return image.id
-
-    def image_upload(self, image_id, fd):
-        """
-        Upload the image
-
-        Arguments:
-            image_id: UUID of the image
-            fd      : File descriptor for the image file
-        Returns: None
-        """
-        glconn = self._get_glance_connection()
-        try:
-            glconn.images.upload(image_id, fd)
-        except Exception as e:
-            logger.error("OpenstackDriver: Image upload operation failed. Exception: %s" %(str(e)))
-            raise
-
-    def image_add_location(self, image_id, location, metadata):
-        """
-        Add image URL location
-
-        Arguments:
-           image_id : UUID of the image
-           location : http URL for the image
-
-        Returns: None
-        """
-        glconn = self._get_glance_connection()
-        try:
-            image = glconn.images.add_location(image_id, location, metadata)
-        except Exception as e:
-            logger.error("OpenstackDriver: Image location add operation failed. Exception: %s" %(str(e)))
-            raise
-
-    def image_update(self):
-        pass
-
-    def image_delete(self, image_id):
-        """
-        Delete an image
-
-        Arguments:
-           image_id: UUID of the image
-
-        Returns: None
-
-        """
-        assert image_id == self._image_get(image_id)['id']
-        glconn = self._get_glance_connection()
-        try:
-            glconn.images.delete(image_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Delete Image operation failed for image_id : %s. Exception: %s" %(image_id, str(e)))
-            raise
-
-
-    def _image_get(self, image_id):
-        """
-        Returns a dictionary object of VM image attributes
-
-        Arguments:
-           image_id (string): UUID of the image
-
-        Returns:
-           A dictionary of the image attributes
-        """
-        glconn = self._get_glance_connection()
-        try:
-            image = glconn.images.get(image_id)
-        except GlanceException.HTTPBadRequest:
-            # RIFT-14241: The get image request occasionally returns the below message.  Retry in case of bad request exception.
-            # Error code 400.: Message: Bad request syntax ('0').: Error code explanation: 400 = Bad request syntax or unsupported method. (HTTP 400)
-            logger.warning("OpenstackDriver: Got bad request response during get_image request.  Retrying.")
-            image = glconn.images.get(image_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Get Image operation failed for image_id : %s. Exception: %s" %(image_id, str(e)))
-            raise
-
-        return image
-
-    def image_get(self, image_id):
-        """
-        Returns a dictionary object of VM image attributes
-
-        Arguments:
-           image_id (string): UUID of the image
-
-        Returns:
-           A dictionary of the image attributes
-        """
-        return self._image_get(image_id)
-
-class GlanceDriverV2(GlanceDriver):
-    """
-    Driver for openstack glance-client V2
-    """
-    def __init__(self, ks_drv):
-        super(GlanceDriverV2, self).__init__(ks_drv, 'image', 2)
-
-class NeutronDriver(object):
-    """
-    Driver for openstack neutron neutron-client
-    """
-    def __init__(self, ks_drv, service_name, version):
-        """
-        Constructor for NeutronDriver
-        Arguments: KeystoneDriver class object
-        """
-        self.ks_drv = ks_drv
-        self._service_name = service_name
-        self._version = version
-
-    def _get_neutron_credentials(self):
-        """
-        Returns a dictionary of kwargs required to instantiate python-neutronclient class
-
-        Returns:
-          Dictionary of kwargs
-        """
-        creds                 = {}
-        creds['api_version']  = self._version
-        creds['endpoint_url'] = self.ks_drv.get_service_endpoint(self._service_name, 'publicURL')
-        creds['token']        = self.ks_drv.get_auth_token()
-        creds['tenant_name']  = self.ks_drv.get_tenant_name()
-        creds['insecure']     = self.ks_drv.get_security_mode()
-        return creds
-
-    def _get_neutron_connection(self):
-        """
-        Returns an object of class python-neutronclient
-        """
-        if not hasattr(self, '_neutron_connection'):
-            self._neutron_connection = ntclient.Client(**self._get_neutron_credentials())
-        else:
-            # Reinitialize if auth_token is no longer valid
-            if not self.ks_drv.is_auth_token_valid():
-                self._neutron_connection = ntclient.Client(**self._get_neutron_credentials())
-        return self._neutron_connection
-
-    def network_list(self):
-        """
-        Returns list of dictionaries. Each dictionary contains the attributes for a network
-        under project
-
-        Arguments: None
-
-        Returns:
-          A list of dictionaries
-        """
-        networks = []
-        ntconn   = self._get_neutron_connection()
-        try:
-            networks = ntconn.list_networks()
-        except Exception as e:
-            logger.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e)))
-            raise
-        return networks['networks']
-
-    def network_create(self, **kwargs):
-        """
-        Creates a new network for the project
-
-        Arguments:
-          A dictionary with following key-values
-        {
-          name (string)              : Name of the network
-          admin_state_up(Boolean)    : True/False (Defaults: True)
-          external_router(Boolean)   : Connectivity with external router. True/False (Defaults: False)
-          shared(Boolean)            : Shared among tenants. True/False (Defaults: False)
-          physical_network(string)   : The physical network where this network object is implemented (optional).
-          network_type               : The type of physical network that maps to this network resource (optional).
-                                       Possible values are: 'flat', 'vlan', 'vxlan', 'gre'
-          segmentation_id            : An isolated segment on the physical network. The network_type attribute
-                                       defines the segmentation model. For example, if the network_type value
-                                       is vlan, this ID is a vlan identifier. If the network_type value is gre,
-                                       this ID is a gre key.
-        }
-        """
-        params = {'network':
-                  {'name'                 : kwargs['name'],
-                   'admin_state_up'       : kwargs['admin_state_up'],
-                   'tenant_id'            : self.ks_drv.get_tenant_id(),
-                   'shared'               : kwargs['shared'],
-                   #'port_security_enabled': port_security_enabled,
-                   'router:external'      : kwargs['external_router']}}
-
-        if 'physical_network' in kwargs:
-            params['network']['provider:physical_network'] = kwargs['physical_network']
-        if 'network_type' in kwargs:
-            params['network']['provider:network_type'] = kwargs['network_type']
-        if 'segmentation_id' in kwargs:
-            params['network']['provider:segmentation_id'] = kwargs['segmentation_id']
-
-        ntconn = self._get_neutron_connection()
-        try:
-            logger.debug("Calling neutron create_network() with params: %s", str(params))
-            net = ntconn.create_network(params)
-        except Exception as e:
-            logger.error("OpenstackDriver: Create Network operation failed. Exception: %s" %(str(e)))
-            raise
-        logger.debug("Got create_network response from neutron connection: %s", str(net))
-        network_id = net['network']['id']
-        if not network_id:
-            raise Exception("Empty network id returned from create_network. (params: %s)" % str(params))
-
-        return network_id
-
-    def network_delete(self, network_id):
-        """
-        Deletes a network identified by network_id
-
-        Arguments:
-          network_id (string): UUID of the network
-
-        Returns: None
-        """
-        assert network_id == self._network_get(network_id)['id']
-        ntconn = self._get_neutron_connection()
-        try:
-            ntconn.delete_network(network_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Delete Network operation failed. Exception: %s" %(str(e)))
-            raise
-
-    def _network_get(self, network_id):
-        """
-        Returns a dictionary object describing the attributes of the network
-
-        Arguments:
-           network_id (string): UUID of the network
-
-        Returns:
-           A dictionary object of the network attributes
-        """
-        ntconn = self._get_neutron_connection()
-        network = ntconn.list_networks(id = network_id)['networks']
-        if not network:
-            raise NeutronException.NotFound("Network with id %s not found"%(network_id))
-
-        return network[0]
-
-    def network_get(self, network_id):
-        """
-        Returns a dictionary object describing the attributes of the network
-
-        Arguments:
-           network_id (string): UUID of the network
-
-        Returns:
-           A dictionary object of the network attributes
-        """
-        return self._network_get(network_id)
-
-    def subnet_create(self, **kwargs):
-        """
-        Creates a subnet on the network
-
+        Constructor of DriverUtilities class
         Arguments:
-        A dictionary with following key value pairs
-        {
-          network_id(string)  : UUID of the network where subnet needs to be created
-          subnet_cidr(string) : IPv4 address prefix (e.g. '1.1.1.0/24') for the subnet
-          ip_version (integer): 4 for IPv4 and 6 for IPv6
-        
-        }
-
-        Returns:
-           subnet_id (string): UUID of the created subnet
+          driver: Object of OpenstackDriver
         """
-        params = {}
-        params['network_id'] = kwargs['network_id']
-        params['ip_version'] = kwargs['ip_version']
-
-        # if params['ip_version'] == 6:
-        #     assert 0, "IPv6 is not supported"
+        self.flavor_utils = drv_utils.FlavorUtils(driver)
+        self.network_utils = drv_utils.NetworkUtils(driver)
+        self.image_utils = drv_utils.ImageUtils(driver)
+        self.compute_utils = drv_utils.ComputeUtils(driver)
         
-        if 'subnetpool_id' in kwargs:
-            params['subnetpool_id'] = kwargs['subnetpool_id']
-        else:
-            params['cidr'] = kwargs['cidr']
-
-        if 'gateway_ip' in kwargs:
-            params['gateway_ip'] = kwargs['gateway_ip']
-        else:
-            params['gateway_ip'] = None
-
-        if 'dhcp_params' in kwargs:
-            params['enable_dhcp'] = kwargs['dhcp_params']['enable_dhcp']
-            if 'start_address' in kwargs['dhcp_params'] and 'count' in kwargs['dhcp_params']:
-                end_address = (ipaddress.IPv4Address(kwargs['dhcp_params']['start_address']) + kwargs['dhcp_params']['count']).compressed
-                params['allocation_pools'] = [ {'start': kwargs['dhcp_params']['start_address'] ,
-                                                'end' : end_address} ]
-                
-        if 'dns_server' in kwargs:
-            params['dns_nameservers'] = []
-            for server in kwargs['dns_server']:
-                params['dns_nameservers'].append(server)
-
-        ntconn = self._get_neutron_connection()
-        try:
-            subnet = ntconn.create_subnet({'subnets': [params]})
-        except Exception as e:
-            logger.error("OpenstackDriver: Create Subnet operation failed. Exception: %s" %(str(e)))
-            raise
-
-        return subnet['subnets'][0]['id']
-
-    def subnet_list(self):
-        """
-        Returns a list of dictionaries. Each dictionary contains attributes describing the subnet
-
-        Arguments: None
-
-        Returns:
-           A dictionary of the objects of subnet attributes
-        """
-        ntconn = self._get_neutron_connection()
-        try:
-            subnets = ntconn.list_subnets()['subnets']
-        except Exception as e:
-            logger.error("OpenstackDriver: List Subnet operation failed. Exception: %s" %(str(e)))
-            raise
-        return subnets
-
-    def _subnet_get(self, subnet_id):
-        """
-        Returns a dictionary object describing the attributes of a subnet.
-
-        Arguments:
-           subnet_id (string): UUID of the subnet
-
-        Returns:
-           A dictionary object of the subnet attributes
-        """
-        ntconn = self._get_neutron_connection()
-        subnets = ntconn.list_subnets(id=subnet_id)
-        if not subnets['subnets']:
-            logger.error("OpenstackDriver: Get subnet operation failed for subnet_id: %s" %(subnet_id))
-            #raise NeutronException.NotFound("Could not find subnet_id %s" %(subnet_id))
-            return {'cidr': ''}
-        else:
-            return subnets['subnets'][0]
-
-    def subnet_get(self, subnet_id):
-        """
-        Returns a dictionary object describing the attributes of a subnet.
-
-        Arguments:
-           subnet_id (string): UUID of the subnet
-
-        Returns:
-           A dictionary object of the subnet attributes
-        """
-        return self._subnet_get(subnet_id)
-
-    def subnet_delete(self, subnet_id):
-        """
-        Deletes a subnet identified by subnet_id
-
-        Arguments:
-           subnet_id (string): UUID of the subnet to be deleted
-
-        Returns: None
-        """
-        ntconn = self._get_neutron_connection()
-        assert subnet_id == self._subnet_get(self,subnet_id)
-        try:
-            ntconn.delete_subnet(subnet_id)
-        except Exception as e:
-            logger.error("OpenstackDriver: Delete Subnet operation failed for subnet_id : %s. Exception: %s" %(subnet_id, str(e)))
-            raise
-
-    def port_list(self, **kwargs):
-        """
-        Returns a list of dictionaries. Each dictionary contains attributes describing the port
-
-        Arguments:
-            kwargs (dictionary): A dictionary for filters for port_list operation
-
-        Returns:
-           A dictionary of the objects of port attributes
-
-        """
-        ports  = []
-        ntconn = self._get_neutron_connection()
-
-        kwargs['tenant_id'] = self.ks_drv.get_tenant_id()
-
-        try:
-            ports  = ntconn.list_ports(**kwargs)
-        except Exception as e:
-            logger.info("OpenstackDriver: List Port operation failed. Exception: %s" %(str(e)))
-            raise
-        return ports['ports']
-
-    def port_create(self, **kwargs):
-        """
-        Create a port in network
-
-        Arguments:
-           A dictionary of following
-           {
-              name (string)      : Name of the port
-              network_id(string) : UUID of the network_id identifying the network to which port belongs
-              subnet_id(string)  : UUID of the subnet_id from which IP-address will be assigned to port
-              vnic_type(string)  : Possible values are "normal", "direct", "macvtap"
-           }
-        Returns:
-           port_id (string)   : UUID of the port
-        """
-        params = {
-            "port": {
-                "admin_state_up"    : kwargs['admin_state_up'],
-                "name"              : kwargs['name'],
-                "network_id"        : kwargs['network_id'],
-                "fixed_ips"         : [ {"subnet_id": kwargs['subnet_id']}],
-                "binding:vnic_type" : kwargs['port_type']}}
-        if 'port_security_enabled' in kwargs:
-            params["port"]["port_security_enabled"] = kwargs['port_security_enabled']
-
-        ntconn = self._get_neutron_connection()
-        try:
-            port  = ntconn.create_port(params)
-        except Exception as e:
-            logger.error("OpenstackDriver: Port Create operation failed. Exception: %s" %(str(e)))
-            raise
-        return port['port']['id']
-
-    def _port_get(self, port_id):
-        """
-        Returns a dictionary object describing the attributes of the port
-
-        Arguments:
-           port_id (string): UUID of the port
-
-        Returns:
-           A dictionary object of the port attributes
-        """
-        ntconn = self._get_neutron_connection()
-        port   = ntconn.list_ports(id=port_id)['ports']
-        if not port:
-            raise NeutronException.NotFound("Could not find port_id %s" %(port_id))
-        return port[0]
-
-    def port_get(self, port_id):
-        """
-        Returns a dictionary object describing the attributes of the port
-
-        Arguments:
-           port_id (string): UUID of the port
-
-        Returns:
-           A dictionary object of the port attributes
-        """
-        return self._port_get(port_id)
-
-    def port_delete(self, port_id):
-        """
-        Deletes a port identified by port_id
-
-        Arguments:
-           port_id (string) : UUID of the port
+    @property
+    def flavor(self):
+        return self.flavor_utils
 
-        Returns: None
-        """
-        assert port_id == self._port_get(port_id)['id']
-        ntconn = self._get_neutron_connection()
-        try:
-            ntconn.delete_port(port_id)
-        except Exception as e:
-            logger.error("Port Delete operation failed for port_id : %s. Exception: %s" %(port_id, str(e)))
-            raise
+    @property
+    def compute(self):
+        return self.compute_utils
+    
+    @property
+    def network(self):
+        return self.network_utils
+    
+    @property
+    def image(self):
+        return self.image_utils
 
-    def security_group_list(self):
+    
+class OpenstackDriver(object):
+    """
+    Driver for openstack nova, neutron, glance, keystone, swift, cinder services
+    """
+    def __init__(self, logger = None, **kwargs):
         """
-        Returns a list of dictionaries. Each dictionary contains attributes describing the security group
-
+        OpenstackDriver Driver constructor
         Arguments:
-           None
-
-        Returns:
-           A dictionary of the objects of security group attributes
-        """
-        ntconn = self._get_neutron_connection()
-        try:
-            group_list = ntconn.list_security_groups(tenant_id=self.ks_drv.get_tenant_id())
-        except Exception as e:
-            logger.error("List Security group operation, Exception: %s" %(str(e)))
-            raise
-
-        if 'security_groups' in group_list:
-            return group_list['security_groups']
+           logger: (instance of logging.Logger)
+           kwargs:  A dictionary of 
+            {
+              username (string)                   : Username for project/tenant.
+              password (string)                   : Password
+              auth_url (string)                   : Keystone Authentication URL.
+              project  (string)                   : Openstack project name
+              mgmt_network(string, optional)      : Management network name. Each VM created with this cloud-account will
+                                                    have a default interface into management network.
+              cert_validate (boolean, optional)   : In case of SSL/TLS connection if certificate validation is required or not.
+              user_domain                         : Domain name for user
+              project_domain                      : Domain name for project
+              region                              : Region name
+            }
+        """
+
+        if logger is None:
+            self.log = logging.getLogger('rwcal.openstack.driver')
+            self.log.setLevel(logging.DEBUG)
         else:
-            return []
-
-    def subnetpool_list(self, **kwargs):
-        """
-        Returns a list of dictionaries. Each dictionary contains attributes describing a subnet prefix pool
+            self.log = logger
+
+        args =  dict(auth_url            = kwargs['auth_url'],
+                     username            = kwargs['username'],
+                     password            = kwargs['password'],
+                     project_name        = kwargs['project'],
+                     project_domain_name = kwargs['project_domain'] if 'project_domain' in kwargs else None,
+                     user_domain_name    = kwargs['user_domain'] if 'user_domain' in kwargs else None,)
+
+        cert_validate = kwargs['cert_validate'] if 'cert_validate' in kwargs else False
+        region = kwargs['region_name'] if 'region_name' in kwargs else False
+        mgmt_network = kwargs['mgmt_network'] if 'mgmt_network' in kwargs else None
+        
+        discover = ks_drv.KeystoneVersionDiscover(kwargs['auth_url'], logger = self.log)
+        (major, minor) = discover.get_version()
+
+        self.sess_drv = sess_drv.SessionDriver(auth_method = 'password',
+                                               version = str(major),
+                                               cert_validate = cert_validate,
+                                               logger = self.log,
+                                               **args)
+
+        self.ks_drv = ks_drv.KeystoneDriver(str(major),
+                                            self.sess_drv,
+                                            logger = self.log)
+        
+        self.nova_drv = nv_drv.NovaDriver(self.sess_drv,
+                                          region_name = region,
+                                          logger = self.log)
+        
+        self.neutron_drv = nt_drv.NeutronDriver(self.sess_drv,
+                                                region_name = region,
+                                                logger = self.log)
+        
+        self.glance_drv = gl_drv.GlanceDriver(self.sess_drv,
+                                              region_name = region,
+                                              logger = self.log)
+        
+        self.cinder_drv = ci_drv.CinderDriver(self.sess_drv,
+                                              region_name = region,
+                                              logger = self.log)
+        
+        self.ceilo_drv = ce_drv.CeilometerDriver(self.sess_drv,
+                                                 region_name = region,
+                                                 logger = self.log)
+        
+        self.portchain_drv = port_drv.L2PortChainDriver(self.sess_drv,
+                                                        self.neutron_drv,
+                                                        logger = self.log)
+        self.utils = DriverUtilities(self)
+        
+        self._mgmt_network = mgmt_network
+        
+        self._cache = dict(neutron = dict(),
+                           nova = dict(),
+                           cinder = dict(),
+                           glance = dict())
+        self.build_resource_cache()
 
-        Arguments:
-           None
+    @property
+    def nova_cache(self):
+        return self._cache['nova']
 
-        Returns:
-           A dictionary of the objects of subnet prefix pool
-        """
-        ntconn = self._get_neutron_connection()
-        try:
-            pool_list = ntconn.list_subnetpools(**kwargs)
-        except Exception as e:
-            logger.error("List SubnetPool operation, Exception: %s" %(str(e)))
-            raise
+    @property
+    def neutron_cache(self):
+        return self._cache['neutron']
+    
+    @property
+    def glance_cache(self):
+        return self._cache['glance']
 
-        if 'subnetpools' in pool_list:
-            return pool_list['subnetpools']
+    @property
+    def cinder_cache(self):
+        return self._cache['cinder']
+    
+    def build_resource_cache(self):
+        self.build_network_resource_cache()
+        self.build_nova_resource_cache()
+        self.build_cinder_resource_cache()
+        self.build_glance_resource_cache()
+
+    def _cache_populate(self, method, datatype, *args, **kwargs):
+        try:
+            rsp = method(*args, **kwargs)
+        except Exception as e:
+            self.log.exception("Exception %s occured during execution of %s",
+                               str(e), method)
+            return datatype
         else:
-            return []
+            return rsp
         
-class NeutronDriverV2(NeutronDriver):
-    """
-    Driver for openstack neutron neutron-client v2
-    """
-    def __init__(self, ks_drv):
-        """
-        Constructor for NeutronDriver
-        Arguments: KeystoneDriver class object
-        """
-        super(NeutronDriverV2, self).__init__(ks_drv, 'network', '2.0')
-
+    def _build_nova_security_group_list(self):
+        self.log.info("Building Nova security group cache")
+        self.nova_cache['security_groups'] = self._cache_populate(self.nova_drv.security_group_list,
+                                                                  list())
+        return self.nova_cache['security_groups']
+    
+    def _build_nova_affinity_group_list(self):
+        self.log.info("Building Nova affinity/anti-affinity group cache")
+        self.nova_cache['affinity_groups'] = self._cache_populate(self.nova_server_group_list,
+                                                                  list())              
+        return self.nova_cache['affinity_groups']
+    
+    def _build_neutron_security_group_list(self):
+        self.log.info("Discovering neutron security group")
+        self.neutron_cache['security_groups'] = self._cache_populate(self.neutron_security_group_list,
+                                                                     list())
+        return self.neutron_cache['security_groups']
+
+    def _build_neutron_subnet_prefix_list(self):
+        self.log.info("Discovering subnet prefix pools")
+        self.neutron_cache['subnet_pool'] = self._cache_populate(self.neutron_subnetpool_list,
+                                                                 list())
+        return self.neutron_cache['subnet_pool']
+
+    def _get_neutron_mgmt_network(self):
+        if self._mgmt_network:
+            self.log.info("Discovering management network %s", self._mgmt_network)
+            network_list = self._cache_populate(self.neutron_drv.network_get,
+                                                None,
+                                                **{'network_name':self._mgmt_network})
+            if network_list:
+                self.neutron_cache['mgmt_net'] = network_list['id']
+            else:
+                raise KeyError("Error")
 
+            
+    def _build_glance_image_list(self):
+        self.log.info("Discovering images")
+        self.glance_cache['images'] = self._cache_populate(self.glance_image_list,
+                                                           list())
+        return self.glance_cache['images']
+    
+                                                                 
+    def build_nova_resource_cache(self):
+        self.log.info("Building nova resource cache")
+        self._build_nova_security_group_list()
+        self._build_nova_affinity_group_list()
+        
+            
+    def build_network_resource_cache(self):
+        self.log.info("Building network resource cache")
+        self._get_neutron_mgmt_network()
+        self._build_neutron_security_group_list()
+        self._build_neutron_subnet_prefix_list()
 
-class CeilometerDriver(object):
-    """
-    Driver for openstack ceilometer client
-    """
+    def build_cinder_resource_cache(self):
+        pass
 
-    def __init__(self, ks_drv, service_name, version):
-        """
-        Constructor for CeilometerDriver
-        Arguments: KeystoneDriver class object
-        """
-        self.ks_drv = ks_drv
-        self._service_name = service_name
-        self._version = version
-        self._client = None
 
-    @property
-    def version(self):
-        """The version of the ceilometer client used by the driver"""
-        return self._version
+    def build_glance_resource_cache(self):
+        self.log.info("Building glance resource cache")
+        self._build_glance_image_list()
 
+        
     @property
-    def client(self):
-        """The instance of ceilometer client used by the driver"""
-        if self._client is None or not self.ks_drv.is_auth_token_valid():
-            self._client = ceilo_client.Client(**self.credentials)
-
-        return self._client
+    def _nova_affinity_group(self):
+        if 'affinity_groups' in self.nova_cache:
+            return self.nova_cache['affinity_groups']
+        else:
+            return self._build_nova_affinity_group_list()
 
     @property
-    def auth_token(self):
-        """The authorization token for the ceilometer client"""
-        try:
-            return self.ks_drv.get_auth_token()
-        except KeystoneExceptions.EndpointNotFound as e:
-            logger.error("OpenstackDriver: unable to get authorization token for ceilometer. Exception: %s" %(str(e)))
-            raise
-
+    def _nova_security_groups(self):
+        if 'security_groups' in self.nova_cache:
+            return self.nova_cache['security_groups']
+        else:
+            return self._build_nova_security_group_list()
+        
     @property
-    def security_mode(self):
-        """The security mode for the ceilometer client"""
-        try:
-            return self.ks_drv.get_security_mode()
-        except KeystoneExceptions.EndpointNotFound as e:
-            logger.error("OpenstackDriver: unable to get security mode for ceilometer. Exception: %s" %(str(e)))
-            raise
-
+    def mgmt_network(self):
+        return self._mgmt_network
+    
     @property
-    def endpoint(self):
-        """The service endpoint for the ceilometer client"""
-        try:
-            return self.ks_drv.get_service_endpoint(self._service_name, "publicURL")
-        except KeystoneExceptions.EndpointNotFound as e:
-            logger.error("OpenstackDriver: unable to get endpoint for ceilometer. Exception: %s" %(str(e)))
-            raise
+    def _mgmt_network_id(self):
+        if 'mgmt_net' in self.neutron_cache:
+            return self.neutron_cache['mgmt_net']
+        else:
+            return list()
 
     @property
-    def credentials(self):
-        """A dictionary of credentials for the ceilometer client"""
-        return dict(
-                version=self.version,
-                endpoint=self.endpoint,
-                token=self.auth_token,
-                insecure=self.security_mode,
-                )
+    def _neutron_security_groups(self):
+        if 'security_groups' in self.neutron_cache:
+            return self.neutron_cache['security_groups']
+        else:
+            return self._build_neutron_security_group_list()
 
     @property
-    def meters(self):
-        """A list of the available meters"""
-        try:
-            return self.client.meters.list()
-        except Exception as e:
-            logger.error("OpenstackDriver: List meters operation failed. Exception: %s" %(str(e)))
-            raise
-
+    def _neutron_subnet_prefix_pool(self):
+        if 'subnet_pool' in self.neutron_cache:
+            return self.neutron_cache['subnet_pool']
+        else:
+            return self._build_neutron_subnet_prefix_list()
+        
     @property
-    def alarms(self):
-        """The ceilometer client alarms manager"""
-        return self.client.alarms
-
-    def query_samples(self, vim_instance_id, counter_name, limit=1):
-        """Returns a list of samples
-
-        Arguments:
-            vim_instance_id - the ID of the VIM that the samples are from
-            counter_name    - the counter that the samples will come from
-            limit           - a limit on the number of samples to return
-                              (default: 1)
-
-        Returns:
-            A list of samples
-
-        """
-        try:
-            filter = json.dumps({
-                "and": [
-                    {"=": {"resource": vim_instance_id}},
-                    {"=": {"counter_name": counter_name}}
-                    ]
-                })
-            result = self.client.query_samples.query(filter=filter, limit=limit)
-            return result[-limit:]
-
-        except Exception as e:
-            logger.exception(e)
-
-        return []
-
-
-class CeilometerDriverV2(CeilometerDriver):
-    """
-    Driver for openstack ceilometer ceilometer-client
-    """
-    def __init__(self, ks_drv):
-        """
-        Constructor for CeilometerDriver
-        Arguments: CeilometerDriver class object
-        """
-        super(CeilometerDriverV2, self).__init__(ks_drv, 'metering', '2')
-
-class OpenstackDriver(object):
-    """
-    Driver for openstack nova, neutron, glance, keystone, swift, cinder services
-    """
-    def __init__(self, username,
-                 password,
-                 auth_url,
-                 tenant_name,
-                 mgmt_network = None,
-                 cert_validate = False,
-                 user_domain_name = None,
-                 project_domain_name = None,
-                 region = None):
-        """
-        OpenstackDriver Driver constructor
-        Arguments:
-          username (string)                   : Username for project/tenant.
-          password (string)                   : Password
-          auth_url (string)                   : Keystone Authentication URL.
-          tenant_name (string)                : Openstack project name
-          mgmt_network(string, optional)      : Management network name. Each VM created with this cloud-account will
-                                                have a default interface into management network.
-          cert_validate (boolean, optional)   : In case of SSL/TLS connection if certificate validation is required or not.
-          user_domain_name                    : Domain name for user
-          project_domain_name                 : Domain name for project
-          region                              : Region name
-        """
-        insecure = not cert_validate
-        if auth_url.find('/v3') != -1:
-            self.ks_drv        = KeystoneDriverV3(username,
-                                                  password,
-                                                  auth_url,
-                                                  tenant_name,
-                                                  insecure,
-                                                  user_domain_name,
-                                                  project_domain_name,
-                                                  region)
-            self.glance_drv    = GlanceDriverV2(self.ks_drv)
-            self.nova_drv      = NovaDriverV21(self.ks_drv)
-            self.neutron_drv   = NeutronDriverV2(self.ks_drv)
-            self.ceilo_drv     = CeilometerDriverV2(self.ks_drv)
-            self.cinder_drv     = CinderDriverV2(self.ks_drv)
-        elif auth_url.find('/v2') != -1:
-            
-            self.ks_drv        = KeystoneDriverV2(username,
-                                                  password,
-                                                  auth_url,
-                                                  tenant_name,
-                                                  insecure,
-                                                  region)
-            self.glance_drv    = GlanceDriverV2(self.ks_drv)
-            self.nova_drv      = NovaDriverV2(self.ks_drv)
-            self.neutron_drv   = NeutronDriverV2(self.ks_drv)
-            self.ceilo_drv     = CeilometerDriverV2(self.ks_drv)
-            self.cinder_drv     = CinderDriverV2(self.ks_drv)
+    def _glance_image_list(self):
+        if 'images' in self.glance_cache:
+            return self.glance_cache['images']
         else:
-            logger.error("Could not identity the version information for openstack service endpoints. Auth_URL should contain \"/v2\" or \"/v3\" string in it")
-            raise NotImplementedError("Auth URL is wrong or invalid. Only Keystone v2 & v3 supported")
-
-        self._mgmt_network_id = None
-        if mgmt_network != None:
-            self._mgmt_network = mgmt_network
-
-            networks = []
-            try:
-                ntconn   = self.neutron_drv._get_neutron_connection()
-                networks = ntconn.list_networks()
-            except (KeystoneExceptions.Unauthorized, KeystoneExceptions.AuthorizationFailure) as e:
-                raise
-            except Exception as e:
-                logger.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e)))
-                raise
-
-            network_list = [ network for network in networks['networks'] if network['name'] == mgmt_network ]
-
-            if not network_list:
-                raise NeutronException.NotFound("Could not find network %s" %(mgmt_network))
-            self._mgmt_network_id = network_list[0]['id']
-
+            return self._build_glance_image_list()
+    
     def validate_account_creds(self):
         try:
-            ksconn = self.ks_drv._get_keystone_connection()
+            self.sess_drv.invalidate_auth_token()
+            self.sess_drv.auth_token
+            self.build_resource_cache()
         except KeystoneExceptions.AuthorizationFailure as e:
-            logger.error("OpenstackDriver: Unable to authenticate or validate the existing credentials. Exception: %s" %(str(e)))
+            self.log.error("Unable to authenticate or validate the existing credentials. Exception: %s", str(e))
             raise ValidationError("Invalid Credentials: "+ str(e))
         except Exception as e:
-            logger.error("OpenstackDriver: Could not connect to Openstack. Exception: %s" %(str(e)))
+            self.log.error("Could not connect to Openstack. Exception: %s", str(e))
             raise ValidationError("Connection Error: "+ str(e))
 
-    def get_mgmt_network_id(self):
-        return self._mgmt_network_id
-
+    
     def glance_image_create(self, **kwargs):
         if not 'disk_format' in kwargs:
             kwargs['disk_format'] = 'qcow2'
@@ -1791,6 +327,9 @@ class OpenstackDriver(object):
     def glance_image_add_location(self, image_id, location):
         self.glance_drv.image_add_location(image_id, location)
 
+    def glance_image_update(self, image_id, remove_props = None, **kwargs):
+        self.glance_drv.image_update(image_id, remove_props=remove_props, **kwargs)
+
     def glance_image_delete(self, image_id):
         self.glance_drv.image_delete(image_id)
 
@@ -1800,17 +339,18 @@ class OpenstackDriver(object):
     def glance_image_get(self, image_id):
         return self.glance_drv.image_get(image_id)
 
-
     def nova_flavor_list(self):
         return self.nova_drv.flavor_list()
 
-    def nova_flavor_create(self, name, ram, vcpus, disk, epa_specs):
-        extra_specs = epa_specs if epa_specs else {}
+    def nova_flavor_find(self, **kwargs):
+        return self.nova_drv.flavor_find(**kwargs)
+    
+    def nova_flavor_create(self, name, ram, vcpus, disk, epa_specs = dict()):
         return self.nova_drv.flavor_create(name,
                                            ram         = ram,
                                            vcpu        = vcpus,
                                            disk        = disk,
-                                           extra_specs = extra_specs)
+                                           extra_specs = epa_specs)
 
     def nova_flavor_delete(self, flavor_id):
         self.nova_drv.flavor_delete(flavor_id)
@@ -1819,34 +359,8 @@ class OpenstackDriver(object):
         return self.nova_drv.flavor_get(flavor_id)
 
     def nova_server_create(self, **kwargs):
-        def _verify_image(image_id):
-            image = self.glance_drv.image_get(image_id)
-            if image['status'] != 'active':
-                raise GlanceException.NotFound("Image with image_id: %s not found in active state. Current State: %s" %(image['id'], image['status']))
-
-        assert kwargs['flavor_id'] == self.nova_drv.flavor_get(kwargs['flavor_id'])['id']
-
-        if kwargs['block_device_mapping_v2'] is not None:
-            for block_map in kwargs['block_device_mapping_v2']:
-                if 'uuid' in block_map:
-                    _verify_image(block_map['uuid'])
-        else:
-            _verify_image(kwargs['image_id'])
-
-        # if 'network_list' in kwargs:
-        #     kwargs['network_list'].append(self._mgmt_network_id)
-        # else:
-        #     kwargs['network_list'] = [self._mgmt_network_id]
-
         if 'security_groups' not in kwargs:
-            nvconn = self.nova_drv._get_nova_connection()
-            sec_groups = nvconn.security_groups.list()
-            if sec_groups:
-                ## Should we add VM in all availability security_groups ???
-                kwargs['security_groups'] = [x.name for x in sec_groups]
-            else:
-                kwargs['security_groups'] = None
-
+            kwargs['security_groups'] = [ s['name'] for s in self._nova_security_groups ]
         return self.nova_drv.server_create(**kwargs)
 
     def nova_server_add_port(self, server_id, port_id):
@@ -1904,7 +418,7 @@ class OpenstackDriver(object):
         return self.neutron_drv.network_list()
 
     def neutron_network_get(self, network_id):
-        return self.neutron_drv.network_get(network_id)
+        return self.neutron_drv.network_get(network_id=network_id)
 
     def neutron_network_create(self, **kwargs):
         return self.neutron_drv.network_create(**kwargs)
@@ -1913,7 +427,7 @@ class OpenstackDriver(object):
         self.neutron_drv.network_delete(network_id)
 
     def neutron_subnet_list(self):
-        return self.neutron_drv.subnet_list()
+        return self.neutron_drv.subnet_list(**{})
 
     def neutron_subnet_get(self, subnet_id):
         return self.neutron_drv.subnet_get(subnet_id)
@@ -1933,7 +447,7 @@ class OpenstackDriver(object):
             return pool_list[0]
         else:
             return None
-        
+
     def neutron_port_list(self, **kwargs):
         return self.neutron_drv.port_list(**kwargs)
 
@@ -1941,25 +455,21 @@ class OpenstackDriver(object):
         return self.neutron_drv.port_get(port_id)
 
     def neutron_port_create(self, **kwargs):
-        subnets = [subnet for subnet in self.neutron_drv.subnet_list() if subnet['network_id'] == kwargs['network_id']]
-        assert len(subnets) == 1
-        kwargs['subnet_id'] = subnets[0]['id']
-        if not 'admin_state_up' in kwargs:
-            kwargs['admin_state_up'] = True
-        port_id =  self.neutron_drv.port_create(**kwargs)
-
+        port_id =  self.neutron_drv.port_create([kwargs])[0]
         if 'vm_id' in kwargs:
             self.nova_server_add_port(kwargs['vm_id'], port_id)
         return port_id
 
+    def neutron_multi_port_create(self, ports):
+        return self.neutron_drv.port_create(ports)
+        
     def neutron_security_group_list(self):
-        return self.neutron_drv.security_group_list()
+        return self.neutron_drv.security_group_list(**{})
 
     def neutron_security_group_by_name(self, group_name):
-        group_list = self.neutron_drv.security_group_list()
-        groups = [group for group in group_list if group['name'] == group_name]
-        if groups:
-            return groups[0]
+        group_list = self.neutron_drv.security_group_list(**{'name': group_name})
+        if group_list:
+            return group_list[0]
         else:
             return None
 
@@ -1982,47 +492,7 @@ class OpenstackDriver(object):
             A dict of NFVI metrics
 
         """
-        def query_latest_sample(counter_name):
-            try:
-                filter = json.dumps({
-                    "and": [
-                        {"=": {"resource": vim_id}},
-                        {"=": {"counter_name": counter_name}}
-                        ]
-                    })
-                orderby = json.dumps([{"timestamp": "DESC"}])
-                result = self.ceilo_drv.client.query_samples.query(
-                        filter=filter,
-                        orderby=orderby,
-                        limit=1,
-                        )
-                return result[0]
-
-            except IndexError:
-                pass
-
-            except Exception as e:
-                logger.error("Got exception while querying ceilometer, exception details:%s " %str(e))
-
-            return None
-
-        memory_usage = query_latest_sample("memory.usage")
-        disk_usage = query_latest_sample("disk.usage")
-        cpu_util = query_latest_sample("cpu_util")
-
-        metrics = dict()
-
-        if memory_usage is not None:
-            memory_usage.volume = 1e6 * memory_usage.volume
-            metrics["memory_usage"] = memory_usage.to_dict()
-
-        if disk_usage is not None:
-            metrics["disk_usage"] = disk_usage.to_dict()
-
-        if cpu_util is not None:
-            metrics["cpu_util"] = cpu_util.to_dict()
-
-        return metrics
+        return self.ceilo_drv.nfvi_metrics(vim_id)
 
     def ceilo_alarm_list(self):
         """Returns a list of ceilometer alarms"""
@@ -2077,22 +547,20 @@ class OpenstackDriver(object):
         alarm_actions = actions.get('alarm') if actions is not None else None
         insufficient_data_actions = actions.get('insufficient_data') if actions is not None else None
 
-        return self.ceilo_drv.client.alarms.create(
-                name=name,
-                meter_name=meter,
-                statistic=statistic,
-                comparison_operator=operation,
-                threshold=threshold,
-                period=period,
-                evaluation_periods=evaluations,
-                severity=severity,
-                repeat_actions=repeat,
-                enabled=enabled,
-                ok_actions=ok_actions,
-                alarm_actions=alarm_actions,
-                insufficient_data_actions=insufficient_data_actions,
-                **kwargs
-                )
+        return self.ceilo_drv.client.alarms.create(name=name,
+                                                   meter_name=meter,
+                                                   statistic=statistic,
+                                                   comparison_operator=operation,
+                                                   threshold=threshold,
+                                                   period=period,
+                                                   evaluation_periods=evaluations,
+                                                   severity=severity,
+                                                   repeat_actions=repeat,
+                                                   enabled=enabled,
+                                                   ok_actions=ok_actions,
+                                                   alarm_actions=alarm_actions,
+                                                   insufficient_data_actions=insufficient_data_actions,
+                                                   **kwargs)
 
     def ceilo_alarm_update(self, alarm_id, **kwargs):
         """Updates an existing alarm
@@ -2107,6 +575,83 @@ class OpenstackDriver(object):
     def ceilo_alarm_delete(self, alarm_id):
         self.ceilo_drv.client.alarms.delete(alarm_id)
 
+    def create_port_chain(self,name,port_lists):
+        "Create port chain"
+        #Create port pair
+        ppgrp_list = list()
+        for index,port_pair in  enumerate(port_lists):
+            ppair_list = list()
+            ingress_port,egress_port = port_pair
+            #Disable security group and port security for the port
+            self.neutron_drv.port_update(ingress_port,no_security_groups=True,port_security_enabled=False)
+            if ingress_port != egress_port:
+                self.neutron_drv.port_update(egress_port,no_security_groups=True,port_security_enabled=False)
+
+            ppair_id = self.portchain_drv.create_port_pair(name+'ppair'+str(index),ingress_port,egress_port)
+            ppair_list.append(ppair_id)
+            # Create port pair group
+            ppgrp_id = self.portchain_drv.create_port_pair_group(name+'_ppgrp_'+str(index),ppair_list)
+            ppgrp_list.append(ppgrp_id)
+        #Create port chain
+        port_chain_id = self.portchain_drv.create_port_chain(name,ppgrp_list)
+        return port_chain_id
+
+    def delete_port_chain(self,port_chain_id):
+        "Delete port chain"
+        try:
+            result = self.portchain_drv.get_port_chain(port_chain_id)
+            port_chain = result.json() 
+            self.log.debug("Port chain result is %s", port_chain)
+            port_pair_groups = port_chain["port_chain"]["port_pair_groups"]
+            self.portchain_drv.delete_port_chain(port_chain_id)
+
+            # Get port pairs and delete port pair groups
+            port_pairs = list()
+            self.log.debug("Port pair groups during delete is %s", port_pair_groups)
+            for port_pair_group_id in port_pair_groups:
+                result = self.portchain_drv.get_port_pair_group(port_pair_group_id)
+                port_pair_group = result.json() 
+                self.log.debug("Port pair group result is %s", port_pair_group)
+                port_pairs.extend(port_pair_group["port_pair_group"]["port_pairs"])
+                self.portchain_drv.delete_port_pair_group(port_pair_group_id)
+
+            self.log.debug("Port pairs during delete is %s",port_pairs)
+
+            for port_pair_id in port_pairs:
+                self.portchain_drv.delete_port_pair(port_pair_id)
+                pass
+        except Exception as e:
+            self.log.error("Error while delete port chain with id %s, exception %s", port_chain_id,str(e))
+           
+    def update_port_chain(self,port_chain_id,flow_classifier_list):
+        result = self.portchain_drv.get_port_chain(port_chain_id)
+        result.raise_for_status()
+        port_chain = result.json()['port_chain']
+        new_flow_classifier_list = list()
+        if port_chain and port_chain['flow_classifiers']:
+           new_flow_classifier_list.extend(port_chain['flow_classifiers'])
+        new_flow_classifier_list.extend(flow_classifier_list)
+        port_chain_id = self.portchain_drv.update_port_chain(port_chain['id'],flow_classifiers=new_flow_classifier_list)
+        return port_chain_id
+        
+    def create_flow_classifer(self,classifier_name,classifier_dict):
+        "Create flow classifier"
+        flow_classifier_id = self.portchain_drv.create_flow_classifier(classifier_name,classifier_dict)
+        return flow_classifier_id
+
+    def delete_flow_classifier(self,classifier_id):
+        "Create flow classifier"
+        try:
+            self.portchain_drv.delete_flow_classifier(classifier_id)
+        except Exception as e:
+            self.log.error("Error while deleting flow classifier with id %s, exception %s", classifier_id,str(e))
+
+    def get_port_chain_list(self):
+        result = self.portchain_drv.get_port_chain_list()
+        port_chain_list = result.json()
+        if 'port_chains' in port_chain_list:
+            return port_chain_list['port_chains'] 
     def cinder_volume_list(self):
         return self.cinder_drv.volume_list()
   
@@ -2121,121 +666,3 @@ class OpenstackDriver(object):
           
               
           
-class CinderDriver(object):
-      """
-      Driver for openstack cinder-client
-      """
-      def __init__(self, ks_drv, service_name, version):
-          """
-          Constructor for CinderDriver
-          Arguments: KeystoneDriver class object
-          """
-          self.ks_drv = ks_drv
-          self._service_name = service_name
-          self._version = version
-  
-      def _get_cinder_credentials(self):
-          """
-          Returns a dictionary of kwargs required to instantiate python-cinderclient class
-  
-          Arguments: None
-  
-          Returns:
-             A dictionary object of arguments
-          """
-          creds             = {}
-          creds['version']  = self._version 
-          creds['username']   = self.ks_drv.get_username() 
-          creds['api_key']   = self.ks_drv.get_password() 
-          creds['auth_url'] = self.ks_drv.get_service_endpoint("identity", "publicURL") 
-          creds['project_id'] = self.ks_drv.get_tenant_name() 
-          creds['insecure']   = self.ks_drv.get_security_mode()
-  
-          return creds
-
-      def _get_cinder_connection(self):
-          """
-          Returns a object of class python-cinderclient
-          """
-          if not hasattr(self, '_cinder_connection'):
-              self._cinder_connection = cinder_client.Client(**self._get_cinder_credentials())
-          else:
-              # Reinitialize if auth_token is no longer valid
-              if not self.ks_drv.is_auth_token_valid():
-                  self._cinder_connection = cinder_client.Client(**self._get_cinder_credentials())
-          return self._cinder_connection
-  
-      def volume_list(self):
-          """
-          Returns list of dictionaries. Each dictionary contains attributes associated with
-          volumes
-  
-          Arguments: None
-  
-          Returns: List of dictionaries.
-          """
-          cinderconn = self._get_cinder_connection()
-          volumes = []
-          try:
-              volume_info = cinderconn.volumes.list()
-          except Exception as e:
-              logger.error("OpenstackDriver: List volumes operation failed. Exception: %s" %(str(e)))
-              raise
-          volumes = [ volume for volume in volume_info ]
-          return volumes
-  
-      def volume_get(self, volume_id):
-          """
-          Get details volume
-  
-          Arguments: None
-  
-          Returns: List of dictionaries.
-          """
-          cinderconn = self._get_cinder_connection()
-          try:
-              vol = cinderconn.volumes.get(volume_id)
-          except Exception as e:
-              logger.error("OpenstackDriver: Get volume operation failed. Exception: %s" %(str(e)))
-              raise
-          return vol
-
-      def volume_set_metadata(self, volume_id, metadata):
-          """
-          Set metadata for volume
-          Metadata is a dictionary of key-value pairs
-  
-          Arguments: None
-  
-          Returns: List of dictionaries.
-          """
-          cinderconn = self._get_cinder_connection()
-          try:
-              cinderconn.volumes.set_metadata(volume_id, metadata)
-          except Exception as e:
-              logger.error("OpenstackDriver: Set metadata operation failed. Exception: %s" %(str(e)))
-              raise
-  
-      def volume_delete_metadata(self, volume_id, metadata):
-          """
-          Delete metadata for volume
-          Metadata is a dictionary of key-value pairs
-  
-          Arguments: None
-  
-          Returns: List of dictionaries.
-          """
-          cinderconn = self._get_cinder_connection()
-          try:
-              cinderconn.volumes.delete_metadata(volume_id, metadata)
-          except Exception as e:
-              logger.error("OpenstackDriver: Delete metadata operation failed. Exception: %s" %(str(e)))
-              raise
-  
-class CinderDriverV2(CinderDriver):
-      """
-      Driver for openstack cinder-client V2
-      """
-      def __init__(self, ks_drv):
-          super(CinderDriverV2, self).__init__(ks_drv, 'volumev2', 2)
-