Merge "v0.4.61 fixed 37 Deploying multisite get properly the information from sites...
[osm/RO.git] / vimconn_vmware.py
index fb7d49b..7836eff 100644 (file)
 # contact with: nfvlabs@tid.es
 ##
 
-'''
+"""
 vimconn_vmware implementation an Abstract class in order to interact with VMware  vCloud Director.
 mbayramov@vmware.com
-'''
+"""
+from progressbar import Percentage, Bar, ETA, FileTransferSpeed, ProgressBar
+
+import vimconn
 import os
 import traceback
-
 import itertools
 import requests
 
@@ -53,21 +55,17 @@ import time
 import uuid
 import httplib
 
+# global variable for vcd connector type
+STANDALONE = 'standalone'
+
+# global variable for number of retry
 DELETE_INSTANCE_RETRY = 3
 
+VCAVERSION = '5.9'
+
 __author__ = "Mustafa Bayramov"
 __date__ = "$26-Aug-2016 11:09:29$"
-
-# Error variables
-HTTP_Bad_Request = 400
-HTTP_Unauthorized = 401
-HTTP_Not_Found = 404
-HTTP_Method_Not_Allowed = 405
-HTTP_Request_Timeout = 408
-HTTP_Conflict = 409
-HTTP_Not_Implemented = 501
-HTTP_Service_Unavailable = 503
-HTTP_Internal_Server_Error = 500
+__version__ = '0.1'
 
 #     -1: "Could not be created",
 #     0: "Unresolved",
@@ -101,68 +99,46 @@ netStatus2manoFormat = {'ACTIVE': 'ACTIVE', 'PAUSED': 'PAUSED', 'INACTIVE': 'INA
                         'ERROR': 'ERROR', 'DELETED': 'DELETED'
                         }
 
+# dict used to store flavor in memory
+flavorlist = {}
 
-class vimconnException(Exception):
-    '''Common and base class Exception for all vimconnector exceptions'''
-
-    def __init__(self, message, http_code=HTTP_Bad_Request):
-        Exception.__init__(self, message)
-        self.http_code = http_code
-
-
-class vimconnConnectionException(vimconnException):
-    '''Connectivity error with the VIM'''
-
-    def __init__(self, message, http_code=HTTP_Service_Unavailable):
-        vimconnException.__init__(self, message, http_code)
-
-
-class vimconnUnexpectedResponse(vimconnException):
-    '''Get an wrong response from VIM'''
-
-    def __init__(self, message, http_code=HTTP_Service_Unavailable):
-        vimconnException.__init__(self, message, http_code)
-
-
-class vimconnAuthException(vimconnException):
-    '''Invalid credentials or authorization to perform this action over the VIM'''
-
-    def __init__(self, message, http_code=HTTP_Unauthorized):
-        vimconnException.__init__(self, message, http_code)
-
-
-class vimconnNotFoundException(vimconnException):
-    '''The item is not found at VIM'''
-
-    def __init__(self, message, http_code=HTTP_Not_Found):
-        vimconnException.__init__(self, message, http_code)
-
-
-class vimconnConflictException(vimconnException):
-    '''There is a conflict, e.g. more item found than one'''
-
-    def __init__(self, message, http_code=HTTP_Conflict):
-        vimconnException.__init__(self, message, http_code)
 
+class vimconnector(vimconn.vimconnector):
+    def __init__(self, uuid=None, name=None, tenant_id=None, tenant_name=None,
+                 url=None, url_admin=None, user=None, passwd=None, log_level=None, config={}):
+        """
+        Constructor create vmware connector to vCloud director.
 
-class vimconnNotImplemented(vimconnException):
-    '''The method is not implemented by the connected'''
+        By default construct doesn't validate connection state. So client can create object with None arguments.
+        If client specified username , password and host and VDC name.  Connector initialize other missing attributes.
 
-    def __init__(self, message, http_code=HTTP_Not_Implemented):
-        vimconnException.__init__(self, message, http_code)
+        a) It initialize organization UUID
+        b) Initialize tenant_id/vdc ID.   (This information derived from tenant name)
 
+        Args:
+            uuid - is organization uuid.
+            name - is organization name that must be presented in vCloud director.
+            tenant_id - is VDC uuid it must be presented in vCloud director
+            tenant_name - is VDC name.
+            url - is hostname or ip address of vCloud director
+            url_admin - same as above.
+            user - is user that administrator for organization. Caller must make sure that
+                    username has right privileges.
 
-flavorlist = {}
+            password - is password for a user.
 
+            VMware connector also requires PVDC administrative privileges and separate account.
+            This variables must be passed via config argument dict contains keys
 
-class vimconnector():
-    '''Vmware VIM Connector base class
-    '''
+            dict['admin_username']
+            dict['admin_password']
 
-    def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None,
-                 log_level="ERROR", config={}):
+            Returns:
+                Nothing.
+        """
 
-        print config
+        vimconn.vimconnector.__init__(self, uuid, name, tenant_id, tenant_name, url,
+                                      url_admin, user, passwd, log_level, config)
         self.id = uuid
         self.name = name
         self.org_name = name
@@ -177,25 +153,26 @@ class vimconnector():
         self.admin_user = None
 
         self.logger = logging.getLogger('openmano.vim.vmware')
+        self.logger.setLevel(10)
+
+        if log_level:
+            self.logger.setLevel(getattr(logging, log_level))
 
         try:
             self.admin_user = config['admin_username']
             self.admin_password = config['admin_password']
         except KeyError:
-            raise vimconnException(message="Error admin username or admin password is empty.")
+            raise vimconn.vimconnException(message="Error admin username or admin password is empty.")
 
-        self.logger = logging.getLogger('mano.vim.vmware')
         self.org_uuid = None
         self.vca = None
 
         if not url:
-            raise TypeError, 'url param can not be NoneType'
+            raise vimconn.vimconnException('url param can not be NoneType')
 
         if not self.url_admin:  # try to use normal url
             self.url_admin = self.url
 
-        self.vcaversion = '5.6'
-
         logging.debug("Calling constructor with following paramters")
         logging.debug("UUID: {} name: {} tenant_id: {} tenant name {}".format(self.id, self.name,
                                                                               self.tenant_id, self.tenant_name))
@@ -203,8 +180,8 @@ class vimconnector():
         logging.debug("vcd admin username {} vcd admin passowrd {}".format(self.admin_user, self.admin_password))
 
         # initialize organization
-        if self.user is not None and self.passwd is not None:
-            self.init_org_uuid()
+        if self.user is not None and self.passwd is not None and self.url:
+            self.init_organization()
 
     def __getitem__(self, index):
         if index == 'tenant_id':
@@ -260,7 +237,9 @@ class vimconnector():
             raise KeyError("Invalid key '%s'" % str(index))
 
     def connect_as_admin(self):
-        """ Method connect as admin user to vCloud director.
+        """ Method connect as pvdc admin user to vCloud director.
+            There are certain action that can be done only by provider vdc admin user.
+            Organization creation / provider network creation etc.
 
             Returns:
                 The return vca object that letter can be used to connect to vcloud direct as admin for provider vdc
@@ -268,17 +247,16 @@ class vimconnector():
 
         self.logger.debug("Logging in to a vca {} as admin.".format(self.name))
 
-        service_type = 'standalone'
-        version = '5.6'
         vca_admin = VCA(host=self.url,
                         username=self.admin_user,
-                        service_type=service_type,
-                        version=version,
+                        service_type=STANDALONE,
+                        version=VCAVERSION,
                         verify=False,
                         log=False)
         result = vca_admin.login(password=self.admin_password, org='System')
         if not result:
-            raise vimconnConnectionException("Can't connect to a vCloud director as: {}".format(self.admin_user))
+            raise vimconn.vimconnConnectionException(
+                "Can't connect to a vCloud director as: {}".format(self.admin_user))
         result = vca_admin.login(token=vca_admin.token, org='System', org_url=vca_admin.vcloud_session.org_url)
         if result is True:
             self.logger.info(
@@ -293,27 +271,35 @@ class vimconnector():
                 The return vca object that letter can be used to connect to vCloud director as admin for VDC
         """
 
-        service_type = 'standalone'
-        version = '5.9'
+        try:
+            self.logger.debug("Logging in to a vca {} as {} to datacenter {}.".format(self.name, self.user, self.name))
+            vca = VCA(host=self.url,
+                      username=self.user,
+                      service_type=STANDALONE,
+                      version=VCAVERSION,
+                      verify=False,
+                      log=False)
+
+            result = vca.login(password=self.passwd, org=self.name)
+            if not result:
+                raise vimconn.vimconnConnectionException("Can't connect to a vCloud director as: {}".format(self.user))
+            result = vca.login(token=vca.token, org=self.name, org_url=vca.vcloud_session.org_url)
+            if result is True:
+                self.logger.info(
+                    "Successfully logged to a vcloud direct org: {} as user: {}".format(self.name, self.user))
 
-        self.logger.debug("Logging in to a vca {} as {} to datacenter {}.".format(self.name, self.user, self.name))
-        vca = VCA(host=self.url,
-                  username=self.user,
-                  service_type=service_type,
-                  version=version,
-                  verify=False,
-                  log=False)
-        result = vca.login(password=self.passwd, org=self.name)
-        if not result:
-            raise vimconnConnectionException("Can't connect to a vCloud director as: {}".format(self.user))
-        result = vca.login(token=vca.token, org=self.name, org_url=vca.vcloud_session.org_url)
-        if result is True:
-            self.logger.info("Successfully logged to a vcloud direct org: {} as user: {}".format(self.name, self.user))
+        except:
+            raise vimconn.vimconnConnectionException("Can't connect to a vCloud director as: {}".format(self.user))
 
         return vca
 
-    def init_org_uuid(self):
-        """ Method available organization for a logged in tenant
+    def init_organization(self):
+        """ Method initialize organization UUID and VDC parameters.
+
+            At bare minimum client must provide organization name that present in vCloud director and VDC.
+
+            The VDC - UUID ( tenant_id) will be initialized at the run time if client didn't call constructor.
+            The Org - UUID will be initialized at the run time if data center present in vCloud director.
 
             Returns:
                 The return vca object that letter can be used to connect to vcloud direct as admin
@@ -322,8 +308,41 @@ class vimconnector():
             if self.org_uuid is None:
                 org_dict = self.get_org_list()
                 for org in org_dict:
+                    # we set org UUID at the init phase but we can do it only when we have valid credential.
                     if org_dict[org] == self.org_name:
                         self.org_uuid = org
+                        self.logger.debug("Setting organization UUID {}".format(self.org_uuid))
+                        break
+
+                else:
+                    raise vimconn.vimconnException("Vcloud director organization {} not found".format(self.org_name))
+
+                # if well good we require for org details
+                org_details_dict = self.get_org(org_uuid=self.org_uuid)
+
+                # we have two case if we want to initialize VDC ID or VDC name at run time
+                # tenant_name provided but no tenant id
+                if self.tenant_id is None and self.tenant_name is not None and 'vdcs' in org_details_dict:
+                    vdcs_dict = org_details_dict['vdcs']
+                    for vdc in vdcs_dict:
+                        if vdcs_dict[vdc] == self.tenant_name:
+                            self.tenant_id = vdc
+                            self.logger.debug("Setting vdc uuid {} for organization UUID {}".format(self.tenant_id,
+                                                                                                    self.name))
+                            break
+                    else:
+                        raise vimconn.vimconnException("Tenant name indicated but not present in vcloud director.")
+                    # case two we have tenant_id but we don't have tenant name so we find and set it.
+                    if self.tenant_id is not None and self.tenant_name is None and 'vdcs' in org_details_dict:
+                        vdcs_dict = org_details_dict['vdcs']
+                        for vdc in vdcs_dict:
+                            if vdc == self.tenant_id:
+                                self.tenant_name = vdcs_dict[vdc]
+                                self.logger.debug("Setting vdc uuid {} for organization UUID {}".format(self.tenant_id,
+                                                                                                        self.name))
+                                break
+                        else:
+                            raise vimconn.vimconnException("Tenant id indicated but not present in vcloud director")
             self.logger.debug("Setting organization uuid {}".format(self.org_uuid))
         except:
             self.logger.debug("Failed initialize organization UUID for org {}".format(self.org_name))
@@ -331,42 +350,40 @@ class vimconnector():
             self.org_uuid = None
 
     def new_tenant(self, tenant_name=None, tenant_description=None):
-        """
-        Adds a new tenant to VIM with this name and description
+        """ Method adds a new tenant to VIM with this name.
+            This action requires access to create VDC action in vCloud director.
 
-        :param tenant_name:
-        :param tenant_description:
-        :return: returns the tenant identifier
-        """
+            Args:
+                tenant_name is tenant_name to be created.
+                tenant_description not used for this call
+
+            Return:
+                returns the tenant identifier in UUID format.
+                If action is failed method will throw vimconn.vimconnException method
+            """
         vdc_task = self.create_vdc(vdc_name=tenant_name)
         if vdc_task is not None:
             vdc_uuid, value = vdc_task.popitem()
             self.logger.info("Crated new vdc {} and uuid: {}".format(tenant_name, vdc_uuid))
             return vdc_uuid
         else:
-            raise vimconnException("Failed create tenant {}".format(tenant_name))
+            raise vimconn.vimconnException("Failed create tenant {}".format(tenant_name))
 
-    def delete_tenant(self, tenant_id):
+    def delete_tenant(self, tenant_id=None):
         """Delete a tenant from VIM"""
         'Returns the tenant identifier'
-
-        print(" ")
-        print(" ######## delete_tenant {} ".format(tenant_id))
-        print(" ")
-
-        raise vimconnNotImplemented("Should have implemented this")
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def get_tenant_list(self, filter_dict={}):
-        '''Obtain tenants of VIM
+        """Obtain tenants of VIM
         filter_dict can contain the following keys:
             name: filter by tenant name
             id: filter by tenant uuid/id
             <other VIM specific>
-        Returns the tenant list of dictionaries: 
+        Returns the tenant list of dictionaries:
             [{'name':'<name>, 'id':'<id>, ...}, ...]
 
-        '''
-
+        """
         org_dict = self.get_org(self.org_uuid)
         vdcs_dict = org_dict['vdcs']
 
@@ -374,25 +391,29 @@ class vimconnector():
         try:
             for k in vdcs_dict:
                 entry = {'name': vdcs_dict[k], 'id': k}
-                filtered_entry = entry.copy()
-                filtered_dict = set(entry.keys()) - set(filter_dict)
-                for unwanted_key in filtered_dict: del entry[unwanted_key]
-                if filter_dict == entry:
-                    vdclist.append(filtered_entry)
+                # if caller didn't specify dictionary we return all tenants.
+                if filter_dict is not None and filter_dict:
+                    filtered_entry = entry.copy()
+                    filtered_dict = set(entry.keys()) - set(filter_dict)
+                    for unwanted_key in filtered_dict: del entry[unwanted_key]
+                    if filter_dict == entry:
+                        vdclist.append(filtered_entry)
+                else:
+                    vdclist.append(entry)
         except:
             self.logger.debug("Error in get_tenant_list()")
             self.logger.debug(traceback.format_exc())
-            pass
+            raise vimconn.vimconnException("Incorrect state. {}")
 
         return vdclist
 
     def new_network(self, net_name, net_type, ip_profile=None, shared=False):
-        '''Adds a tenant network to VIM
+        """Adds a tenant network to VIM
             net_name is the name
             net_type can be 'bridge','data'.'ptp'.  TODO: this need to be revised
-            ip_profile is a dict containing the IP parameters of the network 
+            ip_profile is a dict containing the IP parameters of the network
             shared is a boolean
-        Returns the network identifier'''
+        Returns the network identifier"""
 
         self.logger.debug(
             "new_network tenant {} net_type {} ip_profile {} shared {}".format(net_name, net_type, ip_profile, shared))
@@ -405,7 +426,7 @@ class vimconnector():
         if network_uuid is not None:
             return network_uuid
         else:
-            raise vimconnUnexpectedResponse("Failed create a new network {}".format(net_name))
+            raise vimconn.vimconnUnexpectedResponse("Failed create a new network {}".format(net_name))
 
     def get_vcd_network_list(self):
         """ Method available organization for a logged in tenant
@@ -451,7 +472,7 @@ class vimconnector():
         return network_list
 
     def get_network_list(self, filter_dict={}):
-        '''Obtain tenant networks of VIM
+        """Obtain tenant networks of VIM
         Filter_dict can be:
             name: network name  OR/AND
             id: network uuid    OR/AND
@@ -465,7 +486,7 @@ class vimconnector():
         Returns the network list of dictionaries:
             [{<the fields at Filter_dict plus some VIM specific>}, ...]
             List can be empty
-        '''
+        """
 
         vca = self.connect()
         if not vca:
@@ -501,11 +522,14 @@ class vimconnector():
                 filter_entry["type"] = "bridge"
                 filtered_entry = filter_entry.copy()
 
-                # we remove all the key : value we dont' care and match only
-                # respected field
-                filtered_dict = set(filter_entry.keys()) - set(filter_dict)
-                for unwanted_key in filtered_dict: del filter_entry[unwanted_key]
-                if filter_dict == filter_entry:
+                if filter_dict is not None and filter_dict:
+                    # we remove all the key : value we don't care and match only
+                    # respected field
+                    filtered_dict = set(filter_entry.keys()) - set(filter_dict)
+                    for unwanted_key in filtered_dict: del filter_entry[unwanted_key]
+                    if filter_dict == filter_entry:
+                        network_list.append(filtered_entry)
+                else:
                     network_list.append(filtered_entry)
         except:
             self.logger.debug("Error in get_vcd_network_list")
@@ -515,7 +539,7 @@ class vimconnector():
         return network_list
 
     def get_network(self, net_id):
-        """Method bbtain network details of net_id VIM network
+        """Method obtains network details of net_id VIM network
            Return a dict with  the fields at filter_dict (see get_network_list) plus some VIM specific>}, ...]"""
 
         vca = self.connect()
@@ -559,37 +583,33 @@ class vimconnector():
 
         vca = self.connect()
         if not vca:
-            raise vimconn.vimconnConnectionException("self.connect() for tenant {} is failed".format(self.tenant_name))
+            raise vimconn.vimconnConnectionException("self.connect() for tenant {} is failed.".format(self.tenant_name))
 
-        if self.delete_network_action(net_id):
-            return net_id
+        vcd_network = self.get_vcd_network(network_uuid=net_id)
+        if vcd_network is not None and vcd_network:
+            if self.delete_network_action(network_uuid=net_id):
+                return net_id
         else:
             raise vimconn.vimconnNotFoundException("Network {} not found".format(net_id))
 
     def refresh_nets_status(self, net_list):
-        '''Get the status of the networks
+        """Get the status of the networks
            Params: the list of network identifiers
            Returns a dictionary with:
                 net_id:         #VIM id of this network
                     status:     #Mandatory. Text with one of:
                                 #  DELETED (not found at vim)
-                                #  VIM_ERROR (Cannot connect to VIM, VIM response error, ...) 
+                                #  VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
                                 #  OTHER (Vim reported other status not understood)
                                 #  ERROR (VIM indicates an ERROR status)
-                                #  ACTIVE, INACTIVE, DOWN (admin down), 
+                                #  ACTIVE, INACTIVE, DOWN (admin down),
                                 #  BUILD (on building process)
                                 #
-                    error_msg:  #Text with VIM error message, if any. Or the VIM connection ERROR 
+                    error_msg:  #Text with VIM error message, if any. Or the VIM connection ERROR
                     vim_info:   #Text with plain information obtained from vim (yaml.safe_dump)
 
-        '''
-
-        # for net in net_list:
-        #     net['status']
-        #     net['error_msg']
-        #     net['vim_info']
+        """
 
-        # vim vimcon failed == ERROR
         vca = self.connect()
         if not vca:
             raise vimconn.vimconnConnectionException("self.connect() is failed")
@@ -597,29 +617,31 @@ class vimconnector():
         dict_entry = {}
         try:
             for net in net_list:
-                status = ''
                 errormsg = ''
                 vcd_network = self.get_vcd_network(network_uuid=net)
-                if vcd_network is not None:
+                if vcd_network is not None and vcd_network:
                     if vcd_network['status'] == 1:
                         status = 'ACTIVE'
                     else:
                         status = 'DOWN'
                 else:
                     status = 'DELETED'
-                    errormsg = 'network not found'
-                    dict_entry['net'] = {'status': status, 'error_msg': errormsg,
-                                         'vm_info': yaml.safe_dump(vcd_network)}
+                    errormsg = 'Network not found.'
+
+                dict_entry[net] = {'status': status, 'error_msg': errormsg,
+                                   'vm_info': yaml.safe_dump(vcd_network)}
         except:
             self.logger.debug("Error in refresh_nets_status")
             self.logger.debug(traceback.format_exc())
 
         return dict_entry
 
-    def get_flavor(flavor_id):
+    def get_flavor(self, flavor_id):
         """Obtain flavor details from the  VIM
             Returns the flavor dict details {'id':<>, 'name':<>, other vim specific } #TODO to concrete
         """
+        if flavor_id not in flavorlist:
+            raise vimconn.vimconnNotFoundException("Flavor not found.")
         return flavorlist[flavor_id]
 
     def new_flavor(self, flavor_data):
@@ -654,62 +676,83 @@ class vimconnector():
     def delete_flavor(self, flavor_id):
         """Deletes a tenant flavor from VIM identify by its id
 
-        Returns the used id or raise an exception
+           Returns the used id or raise an exception
         """
+        if flavor_id not in flavorlist:
+            raise vimconn.vimconnNotFoundException("Flavor not found.")
 
-        # if key not present it will raise KeyError
-        # TODO check do I need raise any specific exception
         flavorlist.pop(flavor_id, None)
         return flavor_id
 
     def new_image(self, image_dict):
-        '''
+        """
         Adds a tenant image to VIM
         Returns:
             200, image-id        if the image is created
             <0, message          if there is an error
-        '''
+        """
 
         return self.get_image_id_from_path(image_dict['location'])
 
     def delete_image(self, image_id):
-        '''Deletes a tenant image from VIM'''
-        '''Returns the HTTP response code and a message indicating details of the success or fail'''
+        """
 
-        print " ################################################################### "
-        print " delete_image contains  {}".format(image_id)
-        print " ################################################################### "
+        :param image_id:
+        :return:
+        """
 
-        raise vimconnNotImplemented("Should have implemented this")
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def catalog_exists(self, catalog_name, catalogs):
+        """
+
+        :param catalog_name:
+        :param catalogs:
+        :return:
+        """
         for catalog in catalogs:
             if catalog.name == catalog_name:
                 return True
         return False
 
-    def create_vimcatalog(self, vca, catalog_name):
-        """Create Catalog entry in VIM"""
-        task = vca.create_catalog(catalog_name, catalog_name)
-        result = vca.block_until_completed(task)
-        if not result:
+    def create_vimcatalog(self, vca=None, catalog_name=None):
+        """ Create new catalog entry in vCloud director.
+
+            Args
+                vca:  vCloud director.
+                catalog_name catalog that client wish to create.   Note no validation done for a name.
+                Client must make sure that provide valid string representation.
+
+             Return (bool) True if catalog created.
+
+        """
+        try:
+            task = vca.create_catalog(catalog_name, catalog_name)
+            result = vca.block_until_completed(task)
+            if not result:
+                return False
+            catalogs = vca.get_catalogs()
+        except:
             return False
-        catalogs = vca.get_catalogs()
         return self.catalog_exists(catalog_name, catalogs)
 
-    def upload_ovf(self, vca, catalog_name, item_name, media_file_name, description='', display_progress=False,
-                   chunk_bytes=128 * 1024):
+    # noinspection PyIncorrectDocstring
+    def upload_ovf(self, vca=None, catalog_name=None, image_name=None, media_file_name=None,
+                   description='', progress=False, chunk_bytes=128 * 1024):
         """
         Uploads a OVF file to a vCloud catalog
 
+        :param chunk_bytes:
+        :param progress:
+        :param description:
+        :param image_name:
+        :param vca:
         :param catalog_name: (str): The name of the catalog to upload the media.
-        :param item_name: (str): The name of the media file in the catalog.
         :param media_file_name: (str): The name of the local media file to upload.
         :return: (bool) True if the media file was successfully uploaded, false otherwise.
         """
         os.path.isfile(media_file_name)
         statinfo = os.stat(media_file_name)
-        statinfo.st_size
 
         #  find a catalog entry where we upload OVF.
         #  create vApp Template and check the status if vCD able to read OVF it will respond with appropirate
@@ -723,7 +766,7 @@ class vimconnector():
             assert len(link) == 1
             data = """
             <UploadVAppTemplateParams name="%s Template" xmlns="http://www.vmware.com/vcloud/v1.5" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"><Description>%s vApp Template</Description></UploadVAppTemplateParams>
-            """ % (escape(item_name), escape(description))
+            """ % (escape(image_name), escape(description))
             headers = vca.vcloud_session.get_vcloud_headers()
             headers['Content-Type'] = 'application/vnd.vmware.vcloud.uploadVAppTemplateParams+xml'
             response = Http.post(link[0].get_href(), headers=headers, data=data, verify=vca.verify, logger=self.logger)
@@ -738,13 +781,13 @@ class vimconnector():
 
                 if response.status_code == requests.codes.ok:
                     media = mediaType.parseString(response.content, True)
-                    link = \
-                        filter(lambda link: link.get_rel() == 'upload:default',
-                               media.get_Files().get_File()[0].get_Link())[
-                            0]
+                    link = filter(lambda link: link.get_rel() == 'upload:default',
+                                  media.get_Files().get_File()[0].get_Link())[0]
                     headers = vca.vcloud_session.get_vcloud_headers()
                     headers['Content-Type'] = 'Content-Type text/xml'
-                    response = Http.put(link.get_href(), data=open(media_file_name, 'rb'), headers=headers,
+                    response = Http.put(link.get_href(),
+                                        data=open(media_file_name, 'rb'),
+                                        headers=headers,
                                         verify=vca.verify, logger=self.logger)
                     if response.status_code != requests.codes.ok:
                         self.logger.debug(
@@ -759,54 +802,68 @@ class vimconnector():
                                   format(catalog_name, media_file_name))
 
                 # uploading VMDK file
-                # check status of OVF upload
-                response = Http.get(template, headers=vca.vcloud_session.get_vcloud_headers(), verify=vca.verify,
+                # check status of OVF upload and upload remaining files.
+                response = Http.get(template,
+                                    headers=vca.vcloud_session.get_vcloud_headers(),
+                                    verify=vca.verify,
                                     logger=self.logger)
+
                 if response.status_code == requests.codes.ok:
                     media = mediaType.parseString(response.content, True)
-                    link = \
-                        filter(lambda link: link.get_rel() == 'upload:default',
-                               media.get_Files().get_File()[0].get_Link())[
-                            0]
-
-                    # The OVF file and VMDK must be in a same directory
-                    head, tail = os.path.split(media_file_name)
-                    filevmdk = head + '/' + os.path.basename(link.get_href())
-
-                    os.path.isfile(filevmdk)
-                    statinfo = os.stat(filevmdk)
-
-                    # TODO debug output remove it
-                    # print media.get_Files().get_File()[0].get_Link()[0].get_href()
-                    # print media.get_Files().get_File()[1].get_Link()[0].get_href()
-                    # print link.get_href()
-
-                    # in case first element is pointer to OVF.
-                    hrefvmdk = link.get_href().replace("descriptor.ovf", "Cirros-disk1.vmdk")
-
-                    f = open(filevmdk, 'rb')
-                    bytes_transferred = 0
-                    while bytes_transferred < statinfo.st_size:
-                        my_bytes = f.read(chunk_bytes)
-                        if len(my_bytes) <= chunk_bytes:
-                            headers = vca.vcloud_session.get_vcloud_headers()
-                            headers['Content-Range'] = 'bytes %s-%s/%s' % (
-                                bytes_transferred, len(my_bytes) - 1, statinfo.st_size)
-                            headers['Content-Length'] = str(len(my_bytes))
-                            response = Http.put(hrefvmdk,
-                                                headers=headers,
-                                                data=my_bytes,
-                                                verify=vca.verify,
-                                                logger=None)
-                            if response.status_code == requests.codes.ok:
-                                bytes_transferred += len(my_bytes)
-                                self.logger.debug('transferred %s of %s bytes' % (str(bytes_transferred),
-                                                                                  str(statinfo.st_size)))
-                            else:
-                                self.logger.debug('file upload failed with error: [%s] %s' % (response.status_code,
-                                                                                              response.content))
+                    number_of_files = len(media.get_Files().get_File())
+                    for index in xrange(0, number_of_files):
+                        links_list = filter(lambda link: link.get_rel() == 'upload:default',
+                                            media.get_Files().get_File()[index].get_Link())
+                        for link in links_list:
+                            # we skip ovf since it already uploaded.
+                            if 'ovf' in link.get_href():
+                                continue
+                            # The OVF file and VMDK must be in a same directory
+                            head, tail = os.path.split(media_file_name)
+                            file_vmdk = head + '/' + link.get_href().split("/")[-1]
+                            if not os.path.isfile(file_vmdk):
+                                return False
+                            statinfo = os.stat(file_vmdk)
+                            if statinfo.st_size == 0:
                                 return False
-                    f.close()
+                            hrefvmdk = link.get_href()
+
+                            if progress:
+                                print("Uploading file: {}".format(file_vmdk))
+                            if progress:
+                                widgets = ['Uploading file: ', Percentage(), ' ', Bar(), ' ', ETA(), ' ',
+                                           FileTransferSpeed()]
+                                progress_bar = ProgressBar(widgets=widgets, maxval=statinfo.st_size).start()
+
+                            bytes_transferred = 0
+                            f = open(file_vmdk, 'rb')
+                            while bytes_transferred < statinfo.st_size:
+                                my_bytes = f.read(chunk_bytes)
+                                if len(my_bytes) <= chunk_bytes:
+                                    headers = vca.vcloud_session.get_vcloud_headers()
+                                    headers['Content-Range'] = 'bytes %s-%s/%s' % (
+                                        bytes_transferred, len(my_bytes) - 1, statinfo.st_size)
+                                    headers['Content-Length'] = str(len(my_bytes))
+                                    response = Http.put(hrefvmdk,
+                                                        headers=headers,
+                                                        data=my_bytes,
+                                                        verify=vca.verify,
+                                                        logger=None)
+
+                                    if response.status_code == requests.codes.ok:
+                                        bytes_transferred += len(my_bytes)
+                                        if progress:
+                                            progress_bar.update(bytes_transferred)
+                                    else:
+                                        self.logger.debug(
+                                            'file upload failed with error: [%s] %s' % (response.status_code,
+                                                                                        response.content))
+
+                                        f.close()
+                                        return False
+                            f.close()
+                            if progress:
+                                progress_bar.finish()
                     return True
                 else:
                     self.logger.debug("Failed retrieve vApp template for catalog name {} for OVF {}".
@@ -816,58 +873,112 @@ class vimconnector():
         self.logger.debug("Failed retrieve catalog name {} for OVF file {}".format(catalog_name, media_file_name))
         return False
 
-    def upload_vimimage(self, vca, catalog_name, media_name, medial_file_name):
+    def upload_vimimage(self, vca=None, catalog_name=None, media_name=None, medial_file_name=None, progress=False):
         """Upload media file"""
-        # TODO add named parameters for readbility
-        return self.upload_ovf(vca, catalog_name, media_name.split(".")[0], medial_file_name, medial_file_name, True)
+        # TODO add named parameters for readability
+
+        return self.upload_ovf(vca=vca, catalog_name=catalog_name, image_name=media_name.split(".")[0],
+                               media_file_name=medial_file_name, description='medial_file_name', progress=progress)
+
+    def validate_uuid4(self, uuid_string=None):
+        """  Method validate correct format of UUID.
+
+        Return: true if string represent valid uuid
+        """
+        try:
+            val = uuid.UUID(uuid_string, version=4)
+        except ValueError:
+            return False
+        return True
+
+    def get_catalogid(self, catalog_name=None, catalogs=None):
+        """  Method check catalog and return catalog ID in UUID format.
+
+        Args
+            catalog_name: catalog name as string
+            catalogs:  list of catalogs.
+
+        Return: catalogs uuid
+        """
 
-    def get_catalogid(self, catalog_name, catalogs):
         for catalog in catalogs:
             if catalog.name == catalog_name:
                 catalog_id = catalog.get_id().split(":")
                 return catalog_id[3]
         return None
 
-    def get_catalogbyid(self, catalog_id, catalogs):
+    def get_catalogbyid(self, catalog_uuid=None, catalogs=None):
+        """  Method check catalog and return catalog name lookup done by catalog UUID.
+
+        Args
+            catalog_name: catalog name as string
+            catalogs:  list of catalogs.
+
+        Return: catalogs name or None
+        """
+
+        if not self.validate_uuid4(uuid_string=catalog_uuid):
+            return None
+
         for catalog in catalogs:
-            catalogid = catalog.get_id().split(":")[3]
-            if catalogid == catalog_id:
+            catalog_id = catalog.get_id().split(":")[3]
+            if catalog_id == catalog_uuid:
                 return catalog.name
         return None
 
-    def get_image_id_from_path(self, path):
-        '''Get the image id from image path in the VIM database'''
-        '''Returns:
-             0,"Image not found"   if there are no images with that path
-             1,image-id            if there is one image with that path
-             <0,message            if there was an error (Image not found, error contacting VIM, more than 1 image with that path, etc.) 
-        '''
+    def get_image_id_from_path(self, path=None, progress=False):
+        """  Method upload OVF image to vCloud director.
+
+        Each OVF image represented as single catalog entry in vcloud director.
+        The method check for existing catalog entry.  The check done by file name without file extension.
+
+        if given catalog name already present method will respond with existing catalog uuid otherwise
+        it will create new catalog entry and upload OVF file to newly created catalog.
 
+        If method can't create catalog entry or upload a file it will throw exception.
+
+        Method accept boolean flag progress that will output progress bar. It useful method
+        for standalone upload use case. In case to test large file upload.
+
+        Args
+            path: - valid path to OVF file.
+            progress - boolean progress bar show progress bar.
+
+        Return: if image uploaded correct method will provide image catalog UUID.
+        """
         vca = self.connect()
         if not vca:
-            raise vimconn.vimconnConnectionException("self.connect() is failed")
+            raise vimconn.vimconnConnectionException("self.connect() is failed.")
+
+        if path is None:
+            raise vimconn.vimconnException("Image path can't be None.")
 
-        self.logger.debug("get_image_id_from_path path {}".format(path))
+        if not os.path.isfile(path):
+            raise vimconn.vimconnException("Can't read file. File not found.")
+
+        if not os.access(path, os.R_OK):
+            raise vimconn.vimconnException("Can't read file. Check file permission to read.")
+
+        self.logger.debug("get_image_id_from_path() client requesting {} ".format(path))
 
         dirpath, filename = os.path.split(path)
         flname, file_extension = os.path.splitext(path)
         if file_extension != '.ovf':
-            self.logger.debug("Wrong file extension {}".format(file_extension))
-            return -1, "Wrong container.  vCloud director supports only OVF."
+            self.logger.debug("Wrong file extension {} connector support only OVF container.".format(file_extension))
+            raise vimconn.vimconnException("Wrong container.  vCloud director supports only OVF.")
         catalog_name = os.path.splitext(filename)[0]
-
         self.logger.debug("File name {} Catalog Name {} file path {}".format(filename, catalog_name, path))
-        self.logger.debug("Catalog name {}".format(catalog_name))
 
         catalogs = vca.get_catalogs()
         if len(catalogs) == 0:
-            self.logger.info("Creating new catalog entry {} in vcloud director".format(catalog_name))
+            self.logger.info("Creating new catalog entry {} in vcloud director".format(catalog_name))
             result = self.create_vimcatalog(vca, catalog_name)
             if not result:
-                return -1, "Failed create new catalog {} ".format(catalog_name)
-            result = self.upload_vimimage(vca, catalog_name, filename, path)
+                raise vimconn.vimconnException("Failed create new catalog {} ".format(catalog_name))
+            result = self.upload_vimimage(vca=vca, catalog_name=catalog_name,
+                                          media_name=filename, medial_file_name=path, progress=progress)
             if not result:
-                return -1, "Failed create vApp template for catalog {} ".format(catalog_name)
+                raise vimconn.vimconnException("Failed create vApp template for catalog {} ".format(catalog_name))
             return self.get_catalogid(catalog_name, vca.get_catalogs())
         else:
             for catalog in catalogs:
@@ -880,14 +991,16 @@ class vimconnector():
                                                                                                      catalogs)))
                     return self.get_catalogid(catalog_name, vca.get_catalogs())
 
-        # if we didn't find existing catalog we create a new one.
+        # if we didn't find existing catalog we create a new one and upload image.
         self.logger.debug("Creating new catalog entry".format(catalog_name))
         result = self.create_vimcatalog(vca, catalog_name)
         if not result:
-            return -1, "Failed create new catalog {} ".format(catalog_name)
-        result = self.upload_vimimage(vca, catalog_name, filename, path)
+            raise vimconn.vimconnException("Failed create new catalog {} ".format(catalog_name))
+
+        result = self.upload_vimimage(vca=vca, catalog_name=catalog_name,
+                                      media_name=filename, medial_file_name=path, progress=progress)
         if not result:
-            return -1, "Failed create vApp template for catalog {} ".format(catalog_name)
+            raise vimconn.vimconnException("Failed create vApp template for catalog {} ".format(catalog_name))
 
         return self.get_catalogid(catalog_name, vca.get_catalogs())
 
@@ -895,17 +1008,12 @@ class vimconnector():
         """ Method takes vdc object and vApp name and returns vapp uuid or None
 
         Args:
-            vca: Connector to VCA
             vdc: The VDC object.
             vapp_name: is application vappp name identifier
 
-            Returns:
+        Returns:
                 The return vApp name otherwise None
         """
-
-        """ Take vdc object and vApp name and returns vapp uuid or None
-        """
-
         if vdc is None or vapp_name is None:
             return None
         # UUID has following format https://host/api/vApp/vapp-30da58a3-e7c7-4d09-8f68-d4c8201169cf
@@ -919,12 +1027,8 @@ class vimconnector():
             return False
         return None
 
-    def check_vapp(self, vdc, vapp_id):
-        """ Take VDC object and vApp ID and return True if given ID in vCloud director
-            otherwise return False
-          """
-
-        """ Method Method returns vApp name from vCD and lookup done by vapp_id.
+    def check_vapp(self, vdc=None, vapp_uuid=None):
+        """ Method Method returns True or False if vapp deployed in vCloud director
 
             Args:
                 vca: Connector to VCA
@@ -932,7 +1036,9 @@ class vimconnector():
                 vappid: vappid is application identifier
 
             Returns:
-                The return vApp name otherwise None
+                The return True if vApp deployed
+                :param vdc:
+                :param vapp_uuid:
         """
         try:
             refs = filter(lambda ref:
@@ -941,20 +1047,20 @@ class vimconnector():
             for ref in refs:
                 vappid = ref.href.split("vapp")[1][1:]
                 # find vapp with respected vapp uuid
-                if vappid == vapp_id:
+                if vappid == vapp_uuid:
                     return True
         except Exception as e:
             self.logger.exception(e)
             return False
         return False
 
-    def get_namebyvappid(self, vca, vdc, vapp_id):
+    def get_namebyvappid(self, vca=None, vdc=None, vapp_uuid=None):
         """Method returns vApp name from vCD and lookup done by vapp_id.
 
         Args:
             vca: Connector to VCA
             vdc: The VDC object.
-            vapp_id: vappid is application identifier
+            vapp_uuid: vappid is application identifier
 
         Returns:
             The return vApp name otherwise None
@@ -966,7 +1072,7 @@ class vimconnector():
             for ref in refs:
                 # we care only about UUID the rest doesn't matter
                 vappid = ref.href.split("vapp")[1][1:]
-                if vappid == vapp_id:
+                if vappid == vapp_uuid:
                     response = Http.get(ref.href, headers=vca.vcloud_session.get_vcloud_headers(), verify=vca.verify,
                                         logger=self.logger)
                     tree = XmlElementTree.fromstring(response.content)
@@ -976,7 +1082,8 @@ class vimconnector():
             return None
         return None
 
-    def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None):
+    def new_vminstance(self, name=None, description="", start=False, image_id=None, flavor_id=None, net_list={},
+                       cloud_config=None):
         """Adds a VM instance to VIM
         Params:
             start: indicates if VM must start or boot in pause mode. Ignored
@@ -1006,56 +1113,79 @@ class vimconnector():
         if not vca:
             raise vimconn.vimconnConnectionException("self.connect() is failed.")
 
+        #new vm name = vmname + tenant_id + uuid
+        new_vm_name = [name, '-', str(uuid.uuid4())]
+        full_name = ''.join(new_vm_name)
+
         # if vm already deployed we return existing uuid
-        vapp_uuid = self.get_vappid(vca.get_vdc(self.tenant_name), name)
-        if vapp_uuid is not None:
-            return vapp_uuid
+        vapp_uuid = self.get_vappid(vca.get_vdc(self.tenant_name), name)
+        if vapp_uuid is not None:
+            return vapp_uuid
 
         # we check for presence of VDC, Catalog entry and Flavor.
         vdc = vca.get_vdc(self.tenant_name)
         if vdc is None:
-            return -1, " Failed create vApp {}: (Failed reprieve VDC information)".format(name)
+            raise vimconn.vimconnNotFoundException(
+                "new_vminstance(): Failed create vApp {}: (Failed retrieve VDC information)".format(name))
         catalogs = vca.get_catalogs()
         if catalogs is None:
-            return -2, " Failed create vApp {}: (Failed reprieve Catalog information)".format(name)
-        flavor = flavorlist[flavor_id]
-        if catalogs is None:
-            return -3, " Failed create vApp {}: (Failed reprieve Flavor information)".format(name)
+            raise vimconn.vimconnNotFoundException(
+                "new_vminstance(): Failed create vApp {}:  ""(Failed retrieve catalog information)".format(name))
+
+        vm_cpus = None
+        vm_memory = None
+        if flavor_id is not None:
+            flavor = flavorlist[flavor_id]
+            if flavor is None:
+                raise vimconn.vimconnNotFoundException(
+                    "new_vminstance(): Failed create vApp {}: (Failed retrieve flavor information)".format(name))
+            else:
+                try:
+                    vm_cpus = flavor['vcpus']
+                    vm_memory = flavor['ram']
+                except KeyError:
+                    raise vimconn.vimconnException("Corrupted flavor. {}".format(flavor_id))
 
         # image upload creates template name as catalog name space Template.
-        templateName = self.get_catalogbyid(image_id, catalogs) + ' Template'
+        templateName = self.get_catalogbyid(catalog_uuid=image_id, catalogs=catalogs) + ' Template'
         power_on = 'false'
         if start:
             power_on = 'true'
 
         # client must provide at least one entry in net_list if not we report error
-        primary_net = net_list[0]
-        if primary_net is None:
-            return -4, "Failed create vApp {}: (Network list is empty)".format(name)
-
-        primary_net_id = primary_net['net_id']
-        primary_net_name = self.get_network_name_by_id(primary_net_id)
-        network_mode = primary_net['use']
+        primary_net_name = None
+        if net_list is not None and len(net_list) > 0:
+            primary_net = net_list[0]
+            if primary_net is None:
+                raise vimconn.vimconnUnexpectedResponse("new_vminstance(): Failed network list is empty.".format(name))
+            else:
+                try:
+                    primary_net_id = primary_net['net_id']
+                    primary_net_name = self.get_network_name_by_id(primary_net_id)
+                    network_mode = primary_net['use']
+                except KeyError:
+                    raise vimconn.vimconnException("Corrupted flavor. {}".format(primary_net))
 
         # use: 'data', 'bridge', 'mgmt'
         # create vApp.  Set vcpu and ram based on flavor id.
-        vapptask = vca.create_vapp(self.tenant_name, name, templateName,
+        vapptask = vca.create_vapp(self.tenant_name, full_name, templateName,
                                    self.get_catalogbyid(image_id, catalogs),
-                                   network_name=primary_net_name,
+                                   network_name=primary_net_name,  # can be None if net_list None
                                    network_mode='bridged',
-                                   vm_name=name,
-                                   vm_cpus=flavor['vcpus'],
-                                   vm_memory=flavor['ram'])
+                                   vm_name=full_name,
+                                   vm_cpus=vm_cpus,  # can be None if flavor is None
+                                   vm_memory=vm_memory)  # can be None if flavor is None
 
         if vapptask is None or vapptask is False:
-            return -1, "create_vapp(): failed deploy vApp {}".format(name)
+            raise vimconn.vimconnUnexpectedResponse("new_vminstance(): failed deploy vApp {}".format(full_name))
         if type(vapptask) is VappTask:
             vca.block_until_completed(vapptask)
 
         # we should have now vapp in undeployed state.
-        vapp = vca.get_vapp(vca.get_vdc(self.tenant_name), name)
+        vapp = vca.get_vapp(vca.get_vdc(self.tenant_name), full_name)
         if vapp is None:
-            return -1, "get_vapp(): failed retrieve vApp {}".format(name)
+            raise vimconn.vimconnUnexpectedResponse(
+                "new_vminstance(): Failed failed retrieve vApp {} after we deployed".format(full_name))
 
         # add first NIC
         try:
@@ -1075,7 +1205,7 @@ class vimconnector():
                             vca.block_until_completed(task)
                         # connect network to VM
                         # TODO figure out mapping between openmano representation to vCloud director.
-                        # one idea use first nic as managment DHCP all remaining in bridge mode
+                        # one idea use first nic as management DHCP all remaining in bridge mode
                         task = vapp.connect_vms(nets[0].name, connection_index=nicIndex,
                                                 connections_primary_index=nicIndex,
                                                 ip_allocation_mode='DHCP')
@@ -1083,9 +1213,9 @@ class vimconnector():
                             vca.block_until_completed(task)
             nicIndex += 1
         except KeyError:
-            # TODO
             # it might be a case if specific mandatory entry in dict is empty
             self.logger.debug("Key error {}".format(KeyError.message))
+            raise vimconn.vimconnUnexpectedResponse("new_vminstance(): Failed create new vm instance {}".format(name))
 
         # deploy and power on vm
         task = vapp.poweron()
@@ -1096,11 +1226,11 @@ class vimconnector():
             vca.block_until_completed(deploytask)
 
         # check if vApp deployed and if that the case return vApp UUID otherwise -1
-        vapp_uuid = self.get_vappid(vca.get_vdc(self.tenant_name), name)
+        vapp_uuid = self.get_vappid(vca.get_vdc(self.tenant_name), full_name)
         if vapp_uuid is not None:
             return vapp_uuid
-
-        return -1, " Failed create vApp {}".format(name)
+        else:
+            raise vimconn.vimconnUnexpectedResponse("new_vminstance(): Failed create new vm instance {}".format(name))
 
     ##
     ##
@@ -1117,8 +1247,8 @@ class vimconnector():
     #   error_msg:
     #   interfaces: â€¦
     #
-    def get_vminstance(self, vim_vm_uuid):
-        '''Returns the VM instance information from VIM'''
+    def get_vminstance(self, vim_vm_uuid=None):
+        """Returns the VM instance information from VIM"""
 
         self.logger.debug("Client requesting vm instance {} ".format(vim_vm_uuid))
         vca = self.connect()
@@ -1127,43 +1257,35 @@ class vimconnector():
 
         vdc = vca.get_vdc(self.tenant_name)
         if vdc is None:
-            return -1, "Failed to get a reference of VDC for a tenant {}".format(self.tenant_name)
+            raise vimconn.vimconnConnectionException(
+                "Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
 
-        vm_name = self.get_namebyvappid(vca, vdc, vim_vm_uuid)
-        if vm_name is None:
+        vm_info_dict = self.get_vapp_details_rest(vapp_uuid=vim_vm_uuid)
+        if not vm_info_dict:
             self.logger.debug("get_vminstance(): Failed to get vApp name by UUID {}".format(vim_vm_uuid))
-            return None, "Failed to get vApp name by UUID {}".format(vim_vm_uuid)
-
-        the_vapp = vca.get_vapp(vdc, vm_name)
-        vm_info = the_vapp.get_vms_details()
+            raise vimconn.vimconnNotFoundException("Failed to get vApp name by UUID {}".format(vim_vm_uuid))
 
-        vm_dict = {'description': vm_info[0]['name'], 'status': vcdStatusCode2manoFormat[the_vapp.me.get_status()],
-                   'error_msg': vcdStatusCode2manoFormat[the_vapp.me.get_status()],
-                   'vim_info': yaml.safe_dump(the_vapp.get_vms_details()), 'interfaces': []}
-
-        # get networks
-        vm_app_networks = the_vapp.get_vms_network_info()
-
-        interfaces = []
+        status_key = vm_info_dict['status']
+        error = ''
         try:
-            org_network_dict = self.get_org(self.org_uuid)['networks']
-            for vapp_network in vm_app_networks:
-                for vm_network in vapp_network:
-                    if vm_network['name'] == vm_name:
-                        interface = {}
-                        # interface['vim_info'] = yaml.safe_dump(vm_network)
-                        interface["mac_address"] = vm_network['mac']
-                        for net_uuid in org_network_dict:
-                            if org_network_dict[net_uuid] == vm_network['network_name']:
-                                interface["vim_net_id"] = net_uuid
-                                interface["vim_interface_id"] = vm_network['network_name']
-                                interface['ip_address'] = vm_network['ip']
-                                interfaces.append(interface)
+            vm_dict = {'created': vm_info_dict['created'],
+                       'description': vm_info_dict['name'],
+                       'status': vcdStatusCode2manoFormat[int(status_key)],
+                       'hostId': vm_info_dict['vmuuid'],
+                       'error_msg': error,
+                       'vim_info': yaml.safe_dump(vm_info_dict), 'interfaces': []}
+
+            if 'interfaces' in vm_info_dict:
+                vm_dict['interfaces'] = vm_info_dict['interfaces']
+            else:
+                vm_dict['interfaces'] = []
         except KeyError:
-            self.logger.debug("Error in respond {}".format(KeyError.message))
-            self.logger.debug(traceback.format_exc())
-
-        vm_dict['interfaces'] = interfaces
+            vm_dict = {'created': '',
+                       'description': '',
+                       'status': vcdStatusCode2manoFormat[int(-1)],
+                       'hostId': vm_info_dict['vmuuid'],
+                       'error_msg': "Inconsistency state",
+                       'vim_info': yaml.safe_dump(vm_info_dict), 'interfaces': []}
 
         return vm_dict
 
@@ -1186,7 +1308,8 @@ class vimconnector():
         if vdc is None:
             self.logger.debug("delete_vminstance(): Failed to get a reference of VDC for a tenant {}".format(
                 self.tenant_name))
-            raise vimconnException("delete_vminstance(): Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
+            raise vimconn.vimconnException(
+                "delete_vminstance(): Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
 
         try:
             vapp_name = self.get_namebyvappid(vca, vdc, vm__vim_uuid)
@@ -1230,16 +1353,17 @@ class vimconnector():
                     if type(task) is GenericTask:
                         vca.block_until_completed(delete_task)
                     if not delete_task:
-                        self.loggger.debug("delete_vminstance(): Failed delete uuid {} ".format(vm__vim_uuid))
+                        self.logger.debug("delete_vminstance(): Failed delete uuid {} ".format(vm__vim_uuid))
                     retry += 1
 
-            if vca.get_vapp(vca.get_vdc(self.tenant_name), vapp_name) is None:
-                return vm__vim_uuid
         except:
             self.logger.debug(traceback.format_exc())
-            raise vimconnException("delete_vminstance(): Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
+            raise vimconn.vimconnException("delete_vminstance(): Failed delete vm instance {}".format(vm__vim_uuid))
 
-        return -1
+        if vca.get_vapp(vca.get_vdc(self.tenant_name), vapp_name) is None:
+            return vm__vim_uuid
+        else:
+            raise vimconn.vimconnException("delete_vminstance(): Failed delete vm instance {}".format(vm__vim_uuid))
 
     def refresh_vms_status(self, vm_list):
         """Get the status of the virtual machines and their interfaces/ports
@@ -1272,7 +1396,7 @@ class vimconnector():
 
         vdc = vca.get_vdc(self.tenant_name)
         if vdc is None:
-            raise vimconnException("Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
+            raise vimconn.vimconnException("Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
 
         vms_dict = {}
         for vmuuid in vm_list:
@@ -1283,10 +1407,9 @@ class vimconnector():
                 vm_info = the_vapp.get_vms_details()
                 vm_status = vm_info[0]['status']
 
-                vm_dict = {'status': None, 'error_msg': None, 'vim_info': None, 'interfaces': []}
-                vm_dict['status'] = vcdStatusCode2manoFormat[the_vapp.me.get_status()]
-                vm_dict['error_msg'] = vcdStatusCode2manoFormat[the_vapp.me.get_status()]
-                vm_dict['vim_info'] = yaml.safe_dump(the_vapp.get_vms_details())
+                vm_dict = {'status': vcdStatusCode2manoFormat[the_vapp.me.get_status()],
+                           'error_msg': vcdStatusCode2manoFormat[the_vapp.me.get_status()],
+                           'vim_info': yaml.safe_dump(the_vapp.get_vms_details()), 'interfaces': []}
 
                 # get networks
                 try:
@@ -1294,12 +1417,11 @@ class vimconnector():
                     for vapp_network in vm_app_networks:
                         for vm_network in vapp_network:
                             if vm_network['name'] == vmname:
-                                interface = {}
+                                interface = {"mac_address": vm_network['mac'],
+                                             "vim_net_id": self.get_network_name_by_id(vm_network['network_name']),
+                                             "vim_interface_id": vm_network['network_name'],
+                                             'ip_address': vm_network['ip']}
                                 # interface['vim_info'] = yaml.safe_dump(vm_network)
-                                interface["mac_address"] = vm_network['mac']
-                                interface["vim_net_id"] = self.get_network_name_by_id(vm_network['network_name'])
-                                interface["vim_interface_id"] = vm_network['network_name']
-                                interface['ip_address'] = vm_network['ip']
                                 vm_dict["interfaces"].append(interface)
                     # add a vm to vm dict
                     vms_dict.setdefault(vmuuid, vm_dict)
@@ -1315,7 +1437,7 @@ class vimconnector():
 
         self.logger.debug("Received action for vm {} and action dict {}".format(vm__vim_uuid, action_dict))
         if vm__vim_uuid is None or action_dict is None:
-            raise vimconnException("Invalid request. VM id or action is None.")
+            raise vimconn.vimconnException("Invalid request. VM id or action is None.")
 
         vca = self.connect()
         if not vca:
@@ -1328,7 +1450,7 @@ class vimconnector():
         vapp_name = self.get_namebyvappid(vca, vdc, vm__vim_uuid)
         if vapp_name is None:
             self.logger.debug("action_vminstance(): Failed to get vm by given {} vm uuid".format(vm__vim_uuid))
-            raise vimconnException("Failed to get vm by given {} vm uuid".format(vm__vim_uuid))
+            raise vimconn.vimconnException("Failed to get vm by given {} vm uuid".format(vm__vim_uuid))
         else:
             self.logger.info("Action_vminstance vApp {} and UUID {}".format(vapp_name, vm__vim_uuid))
 
@@ -1347,10 +1469,10 @@ class vimconnector():
                         the_vapp.poweron()
             elif "pause" in action_dict:
                 pass
-                ##server.pause()
+                ## server.pause()
             elif "resume" in action_dict:
                 pass
-                ##server.resume()
+                ## server.resume()
             elif "shutoff" in action_dict or "shutdown" in action_dict:
                 the_vapp.shutdown()
             elif "forceOff" in action_dict:
@@ -1378,54 +1500,54 @@ class vimconnector():
                 port:     the http, ssh, ... port
                 suffix:   extra text, e.g. the http path and query string
         """
-        raise vimconnNotImplemented("Should have implemented this")
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     # NOT USED METHODS in current version
 
     def host_vim2gui(self, host, server_dict):
-        '''Transform host dictionary from VIM format to GUI format,
+        """Transform host dictionary from VIM format to GUI format,
         and append to the server_dict
-        '''
-        raise vimconnNotImplemented("Should have implemented this")
+        """
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def get_hosts_info(self):
-        '''Get the information of deployed hosts
-        Returns the hosts content'''
-        raise vimconnNotImplemented("Should have implemented this")
+        """Get the information of deployed hosts
+        Returns the hosts content"""
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def get_hosts(self, vim_tenant):
-        '''Get the hosts and deployed instances
-        Returns the hosts content'''
-        raise vimconnNotImplemented("Should have implemented this")
+        """Get the hosts and deployed instances
+        Returns the hosts content"""
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def get_processor_rankings(self):
-        '''Get the processor rankings in the VIM database'''
-        raise vimconnNotImplemented("Should have implemented this")
+        """Get the processor rankings in the VIM database"""
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def new_host(self, host_data):
-        '''Adds a new host to VIM'''
+        """Adds a new host to VIM"""
         '''Returns status code of the VIM response'''
-        raise vimconnNotImplemented("Should have implemented this")
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def new_external_port(self, port_data):
-        '''Adds a external port to VIM'''
+        """Adds a external port to VIM"""
         '''Returns the port identifier'''
-        raise vimconnNotImplemented("Should have implemented this")
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def new_external_network(self, net_name, net_type):
-        '''Adds a external network to VIM (shared)'''
+        """Adds a external network to VIM (shared)"""
         '''Returns the network identifier'''
-        raise vimconnNotImplemented("Should have implemented this")
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def connect_port_network(self, port_id, network_id, admin=False):
-        '''Connects a external port to a network'''
+        """Connects a external port to a network"""
         '''Returns status code of the VIM response'''
-        raise vimconnNotImplemented("Should have implemented this")
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def new_vminstancefromJSON(self, vm_data):
-        '''Adds a VM instance to VIM'''
+        """Adds a VM instance to VIM"""
         '''Returns the instance identifier'''
-        raise vimconnNotImplemented("Should have implemented this")
+        raise vimconn.vimconnNotImplemented("Should have implemented this")
 
     def get_network_name_by_id(self, network_name=None):
         """Method gets vcloud director network named based on supplied uuid.
@@ -1521,15 +1643,16 @@ class vimconnector():
         Method retrieves available organization in vCloud Director
 
         Args:
-            vca - is active VCA connection.
-            vdc_name - is a vdc name that will be used to query vms action
+            org_uuid - is a organization uuid.
 
             Returns:
-                The return dictionary and key for each entry vapp UUID
+                The return dictionary with following key
+                    "network" - for network list under the org
+                    "catalogs" - for network list under the org
+                    "vdcs" - for vdc list under org
         """
 
         org_dict = {}
-
         vca = self.connect()
         if not vca:
             raise vimconn.vimconnConnectionException("self.connect() is failed")
@@ -1688,7 +1811,7 @@ class vimconnector():
 
     def get_vapp(self, vdc_name=None, vapp_name=None, isuuid=False):
         """
-        Method retrieves VM's list deployed vCloud director. It returns a dictionary
+        Method retrieves VM deployed vCloud director. It returns VM attribute as dictionary
         contains a list of all VM's deployed for queried VDC.
         The key for a dictionary is VM UUID
 
@@ -1712,23 +1835,21 @@ class vimconnector():
         try:
             vm_list_xmlroot = XmlElementTree.fromstring(content)
             for vm_xml in vm_list_xmlroot:
-                if vm_xml.tag.split("}")[1] == 'VMRecord':
+                if vm_xml.tag.split("}")[1] == 'VMRecord' and vm_xml.attrib['isVAppTemplate'] == 'false':
+                    # lookup done by UUID
                     if isuuid:
-                        # lookup done by UUID
                         if vapp_name in vm_xml.attrib['container']:
                             rawuuid = vm_xml.attrib['href'].split('/')[-1:]
                             if 'vm-' in rawuuid[0]:
-                                # vm in format vm-e63d40e7-4ff5-4c6d-851f-96c1e4da86a5 we remove
-                                #  vm and use raw UUID as key
                                 vm_dict[rawuuid[0][3:]] = vm_xml.attrib
-                        # lookup done by Name
-                        else:
-                            if vapp_name in vm_xml.attrib['name']:
-                                rawuuid = vm_xml.attrib['href'].split('/')[-1:]
-                                if 'vm-' in rawuuid[0]:
-                                    vm_dict[rawuuid[0][3:]] = vm_xml.attrib
-                                    # vm in format vm-e63d40e7-4ff5-4c6d-851f-96c1e4da86a5 we remove
-                                    #  vm and use raw UUID as key
+                                break
+                    # lookup done by Name
+                    else:
+                        if vapp_name in vm_xml.attrib['name']:
+                            rawuuid = vm_xml.attrib['href'].split('/')[-1:]
+                            if 'vm-' in rawuuid[0]:
+                                vm_dict[rawuuid[0][3:]] = vm_xml.attrib
+                                break
         except:
             pass
 
@@ -1870,7 +1991,8 @@ class vimconnector():
                 The return network uuid or return None
         """
 
-        content = self.create_network_rest(network_name=network_name,
+        new_network_name = [network_name, '-', str(uuid.uuid4())]
+        content = self.create_network_rest(network_name=''.join(new_network_name),
                                            parent_network_uuid=parent_network_uuid,
                                            isshared=isshared)
         if content is None:
@@ -1902,7 +2024,7 @@ class vimconnector():
 
         vca = self.connect_as_admin()
         if not vca:
-            raise vimconn.vimconnConnectionException("self.connect() is failed")
+            raise vimconn.vimconnConnectionException("self.connect() is failed.")
         if network_name is None:
             return None
 
@@ -2017,7 +2139,6 @@ class vimconnector():
 
         xml_content = self.create_vdc_from_tmpl_rest(vdc_name=vdc_name)
         if xml_content is not None:
-            print xml_content
             try:
                 task_resp_xmlroot = XmlElementTree.fromstring(xml_content)
                 for child in task_resp_xmlroot:
@@ -2043,8 +2164,6 @@ class vimconnector():
         """
 
         self.logger.info("Creating new vdc {}".format(vdc_name))
-        print ("Creating new vdc {}".format(vdc_name))
-
         vca = self.connect()
         if not vca:
             raise vimconn.vimconnConnectionException("self.connect() is failed")
@@ -2114,7 +2233,6 @@ class vimconnector():
         """
 
         self.logger.info("Creating new vdc {}".format(vdc_name))
-        print ("Creating new vdc {}".format(vdc_name))
 
         vca = self.connect_as_admin()
         if not vca:
@@ -2153,7 +2271,6 @@ class vimconnector():
                     return None
 
                 response = self.get_provider_rest(vca=vca)
-                print response
                 try:
                     vm_list_xmlroot = XmlElementTree.fromstring(response)
                     for child in vm_list_xmlroot:
@@ -2165,8 +2282,6 @@ class vimconnector():
                     self.logger.debug("Respond body {}".format(response))
                     return None
 
-                print "Add vdc {}".format(add_vdc_rest_url)
-                print "Provider ref {}".format(provider_vdc_ref)
                 if add_vdc_rest_url is not None and provider_vdc_ref is not None:
                     data = """ <CreateVdcParams name="{0:s}" xmlns="http://www.vmware.com/vcloud/v1.5"><Description>{1:s}</Description>
                             <AllocationModel>ReservationPool</AllocationModel>
@@ -2181,15 +2296,134 @@ class vimconnector():
                                                                                                   escape(vdc_name),
                                                                                                   provider_vdc_ref)
 
-                    print data
                     headers = vca.vcloud_session.get_vcloud_headers()
                     headers['Content-Type'] = 'application/vnd.vmware.admin.createVdcParams+xml'
                     response = Http.post(url=add_vdc_rest_url, headers=headers, data=data, verify=vca.verify,
                                          logger=vca.logger)
 
-                    print response.status_code
-                    print response.content
                     # if we all ok we respond with content otherwise by default None
                     if response.status_code == 201:
                         return response.content
         return None
+
+    def get_vapp_details_rest(self, vapp_uuid=None):
+        """
+        Method retrieve vapp detail from vCloud director
+
+        Args:
+            vapp_uuid - is vapp identifier.
+
+            Returns:
+                The return network uuid or return None
+        """
+
+        parsed_respond = {}
+
+        vca = self.connect()
+        if not vca:
+            raise vimconn.vimconnConnectionException("self.connect() is failed")
+        if vapp_uuid is None:
+            return None
+
+        url_list = [vca.host, '/api/vApp/vapp-', vapp_uuid]
+        get_vapp_restcall = ''.join(url_list)
+        if not (not vca.vcloud_session or not vca.vcloud_session.organization):
+            response = Http.get(url=get_vapp_restcall,
+                                headers=vca.vcloud_session.get_vcloud_headers(),
+                                verify=vca.verify,
+                                logger=vca.logger)
+
+            if response.status_code != requests.codes.ok:
+                self.logger.debug("REST API call {} failed. Return status code {}".format(get_vapp_restcall,
+                                                                                          response.status_code))
+                return parsed_respond
+
+            try:
+                xmlroot_respond = XmlElementTree.fromstring(response.content)
+                parsed_respond['ovfDescriptorUploaded'] = xmlroot_respond.attrib['ovfDescriptorUploaded']
+
+                namespaces_ovf = {'ovf': 'http://schemas.dmtf.org/ovf/envelope/1'}
+                namespace_vmm = {'vmw': 'http://www.vmware.com/schema/ovf'}
+                namespace_vm = {'vm': 'http://www.vmware.com/vcloud/v1.5'}
+
+                created_section = xmlroot_respond.find('vm:DateCreated', namespace_vm)
+                if created_section is not None:
+                    parsed_respond['created'] = created_section.text
+
+                network_section = xmlroot_respond.find('vm:NetworkConfigSection/vm:NetworkConfig', namespace_vm)
+                if network_section is not None and 'networkName' in network_section.attrib:
+                    parsed_respond['networkname'] = network_section.attrib['networkName']
+
+                ipscopes_section = \
+                    xmlroot_respond.find('vm:NetworkConfigSection/vm:NetworkConfig/vm:Configuration/vm:IpScopes',
+                                         namespace_vm)
+                if ipscopes_section is not None:
+                    for ipscope in ipscopes_section:
+                        for scope in ipscope:
+                            tag_key = scope.tag.split("}")[1]
+                            if tag_key == 'IpRanges':
+                                ip_ranges = scope.getchildren()
+                                for ipblock in ip_ranges:
+                                    for block in ipblock:
+                                        parsed_respond[block.tag.split("}")[1]] = block.text
+                            else:
+                                parsed_respond[tag_key] = scope.text
+
+                # parse children section for other attrib
+                children_section = xmlroot_respond.find('vm:Children/', namespace_vm)
+                if children_section is not None:
+                    parsed_respond['name'] = children_section.attrib['name']
+                    parsed_respond['nestedHypervisorEnabled'] = children_section.attrib['nestedHypervisorEnabled']
+                    parsed_respond['deployed'] = children_section.attrib['deployed']
+                    parsed_respond['status'] = children_section.attrib['status']
+                    parsed_respond['vmuuid'] = children_section.attrib['id'].split(":")[-1]
+                    network_adapter = children_section.find('vm:NetworkConnectionSection', namespace_vm)
+                    nic_list = []
+                    for adapters in network_adapter:
+                        adapter_key = adapters.tag.split("}")[1]
+                        if adapter_key == 'PrimaryNetworkConnectionIndex':
+                            parsed_respond['primarynetwork'] = adapters.text
+                        if adapter_key == 'NetworkConnection':
+                            vnic = {}
+                            if 'network' in adapters.attrib:
+                                vnic['network'] = adapters.attrib['network']
+                            for adapter in adapters:
+                                setting_key = adapter.tag.split("}")[1]
+                                vnic[setting_key] = adapter.text
+                            nic_list.append(vnic)
+
+                    for link in children_section:
+                        if link.tag.split("}")[1] == 'Link' and 'rel' in link.attrib:
+                            if link.attrib['rel'] == 'screen:acquireTicket':
+                                parsed_respond['acquireTicket'] = link.attrib
+                            if link.attrib['rel'] == 'screen:acquireMksTicket':
+                                parsed_respond['acquireMksTicket'] = link.attrib
+
+                    parsed_respond['interfaces'] = nic_list
+            except:
+                pass
+
+        return parsed_respond
+
+    def acuire_console(self, vm_uuid=None):
+
+        vca = self.connect()
+        if not vca:
+            raise vimconn.vimconnConnectionException("self.connect() is failed")
+        if vm_uuid is None:
+            return None
+
+        if not (not vca.vcloud_session or not vca.vcloud_session.organization):
+            vm_dict = self.get_vapp_details_rest(self, vapp_uuid=vm_uuid)
+            console_dict = vm_dict['acquireTicket']
+            console_rest_call = console_dict['href']
+
+            response = Http.post(url=console_rest_call,
+                                 headers=vca.vcloud_session.get_vcloud_headers(),
+                                 verify=vca.verify,
+                                 logger=vca.logger)
+
+            if response.status_code == requests.codes.ok:
+                return response.content
+
+        return None
\ No newline at end of file