Added required dependency to install script. Fixed licensing issue in the file. ... 80/480/1
authorbayramov <mbayramov@vmware.com>
Tue, 4 Oct 2016 03:53:41 +0000 (07:53 +0400)
committerbayramov <mbayramov@vmware.com>
Tue, 4 Oct 2016 03:54:02 +0000 (07:54 +0400)
Signed-off-by: bayramov <mbayramov@vmware.com>
scripts/install-openmano.sh
vimconn_vmware.py
vmwarerecli.py

index d46b22b..9aaf028 100755 (executable)
@@ -241,8 +241,14 @@ echo '
 #################################################################
 #####        INSTALL PYTHON PACKAGES                        #####
 #################################################################'
-[ "$_DISTRO" == "Ubuntu" ] && install_packages "python-yaml python-bottle python-mysqldb python-jsonschema python-paramiko python-argcomplete python-requests python-logutils"
-[ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "PyYAML MySQL-python python-jsonschema python-paramiko python-argcomplete python-requests python-logutils"
+[ "$_DISTRO" == "Ubuntu" ] && install_packages "python-yaml python-bottle python-mysqldb python-jsonschema python-paramiko python-argcomplete python-requests python-logutils libxml2-dev libxslt-dev python-dev python-pip"
+[ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "PyYAML MySQL-python python-jsonschema python-paramiko python-argcomplete python-requests python-logutils libxslt-devel libxml2-devel python-devel python-pip"
+
+#required for vmware connector TODO move that to separete opt in install script
+sudo pip install --upgrade pip
+sudo pip install pyvcloud
+sudo pip install progressbar
+sudo pip install prettytable
 
 #The only way to install python-bottle on Centos7 is with easy_install or pip
 [ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && easy_install -U bottle
index 069c0bc..e59b93c 100644 (file)
@@ -25,6 +25,7 @@
 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
@@ -64,6 +65,7 @@ VCAVERSION = '5.9'
 
 __author__ = "Mustafa Bayramov"
 __date__ = "$26-Aug-2016 11:09:29$"
+__version__ = '0.1'
 
 #     -1: "Could not be created",
 #     0: "Unresolved",
@@ -151,6 +153,8 @@ class vimconnector(vimconn.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) )
 
@@ -281,7 +285,8 @@ class vimconnector(vimconn.vimconnector):
                 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.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))
@@ -534,7 +539,7 @@ class vimconnector(vimconn.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()
@@ -578,10 +583,12 @@ class vimconnector(vimconn.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))
 
@@ -603,12 +610,6 @@ class vimconnector(vimconn.vimconnector):
 
         """
 
-        # 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")
@@ -616,19 +617,19 @@ class vimconnector(vimconn.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())
@@ -639,6 +640,8 @@ class vimconnector(vimconn.vimconnector):
         """Obtain flavor details from the  VIM
             Returns the flavor dict details {'id':<>, 'name':<>, other vim specific } #TODO to concrete
         """
+        if not flavorlist.has_key(flavor_id):
+            raise vimconn.vimconnNotFoundException("Flavor not found.")
         return flavorlist[flavor_id]
 
     def new_flavor(self, flavor_data):
@@ -673,11 +676,11 @@ class vimconnector(vimconn.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 not flavorlist.has_key(flavor_id):
+            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
 
@@ -692,19 +695,29 @@ class vimconnector(vimconn.vimconnector):
         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'''
+        """
+
+        :param image_id:
+        :return:
+        """
+        self.vca;
+
         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=None, catalog_name=None):
-        """ Create new catalog entry in vcloud director.
-
+        """ Create new catalog entry in vCloud director.
 
             Args
                 vca:  vCloud director.
@@ -724,8 +737,8 @@ class vimconnector(vimconn.vimconnector):
             return False
         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):
+    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
 
@@ -750,7 +763,7 @@ class vimconnector(vimconn.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)
@@ -765,12 +778,13 @@ class vimconnector(vimconn.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(
@@ -785,52 +799,68 @@ class vimconnector(vimconn.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)
-                    links_list = filter(lambda link: link.get_rel() == 'upload:default',
-                                        media.get_Files().get_File()[0].get_Link())
-
-                    for link in links_list:
-                        # The OVF file and VMDK must be in a same directory
-                        head, tail = os.path.split(media_file_name)
-                        media_file_name = link.get_href()
-                        if 'ovf' in media_file_name:
-                            print "skiping {}".format(media_file_name)
-                            continue
-                        file_vmdk = head + '/' + os.path.basename(link.get_href())
-                        os.path.isfile(file_vmdk)
-                        statinfo = os.stat(file_vmdk)
-
-                        # in case first element is pointer to OVF.
-                        hrefvmdk = link.get_href().replace("descriptor.ovf", media_file_name)
-                        print("Uploading file {}".format(hrefvmdk))
-
-                        f = open(file_vmdk, '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))
-                                    return False
-                        f.close()
+                    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
+                            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 {}".
@@ -840,10 +870,12 @@ class vimconnector(vimconn.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.
@@ -891,7 +923,7 @@ class vimconnector(vimconn.vimconnector):
                 return catalog.name
         return None
 
-    def get_image_id_from_path(self, path=None):
+    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.
@@ -902,33 +934,46 @@ class vimconnector(vimconn.vimconnector):
 
         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.
+            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.")
+
+        if not os.path.isfile(path):
+            raise vimconn.vimconnException("Can't read file. File not found.")
 
-        self.logger.debug("get_image_id_from_path path {}".format(path))
+        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))
+            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:
                 raise vimconn.vimconnException("Failed create new catalog {} ".format(catalog_name))
-            result = self.upload_vimimage(vca, catalog_name, filename, path)
+            result = self.upload_vimimage(vca=vca, catalog_name=catalog_name,
+                                          media_name=filename, medial_file_name=path, progress=progress)
             if not result:
                 raise vimconn.vimconnException("Failed create vApp template for catalog {} ".format(catalog_name))
             return self.get_catalogid(catalog_name, vca.get_catalogs())
@@ -943,12 +988,14 @@ class vimconnector(vimconn.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:
             raise vimconn.vimconnException("Failed create new catalog {} ".format(catalog_name))
-        result = self.upload_vimimage(vca, catalog_name, filename, path)
+
+        result = self.upload_vimimage(vca=vca, catalog_name=catalog_name,
+                                      media_name=filename, medial_file_name=path, progress=progress)
         if not result:
             raise vimconn.vimconnException("Failed create vApp template for catalog {} ".format(catalog_name))
 
@@ -978,12 +1025,8 @@ class vimconnector(vimconn.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
@@ -991,7 +1034,7 @@ class vimconnector(vimconn.vimconnector):
                 vappid: vappid is application identifier
 
             Returns:
-                The return vApp name otherwise None
+                The return True if vApp deployed
         """
         try:
             refs = filter(lambda ref:
@@ -1000,20 +1043,20 @@ class vimconnector(vimconn.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
@@ -1025,7 +1068,7 @@ class vimconnector(vimconn.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)
@@ -1035,7 +1078,8 @@ class vimconnector(vimconn.vimconnector):
             return None
         return None
 
-    def new_vminstance(self, name=None, description="", start=False, image_id=None, flavor_id=None, 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
@@ -1073,11 +1117,11 @@ class vimconnector(vimconn.vimconnector):
         # we check for presence of VDC, Catalog entry and Flavor.
         vdc = vca.get_vdc(self.tenant_name)
         if vdc is None:
-            raise vimconn.vimconnUnexpectedResponse(
+            raise vimconn.vimconnNotFoundException(
                 "new_vminstance(): Failed create vApp {}: (Failed retrieve VDC information)".format(name))
         catalogs = vca.get_catalogs()
         if catalogs is None:
-            raise vimconn.vimconnUnexpectedResponse(
+            raise vimconn.vimconnNotFoundException(
                 "new_vminstance(): Failed create vApp {}: Failed create vApp {}: "
                 "(Failed retrieve catalog information)".format(name))
 
@@ -1086,19 +1130,16 @@ class vimconnector(vimconn.vimconnector):
         if flavor_id is not None:
             flavor = flavorlist[flavor_id]
             if flavor is None:
-                raise vimconn.vimconnUnexpectedResponse(
+                raise vimconn.vimconnNotFoundException(
                     "new_vminstance(): Failed create vApp {}: (Failed retrieve flavor information)".format(name))
             else:
                 try:
-                    vm_cpus  = flavor['vcpus']
-                    vm_memory= flavor['ram']
+                    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.
-
-        print image_id
-
         templateName = self.get_catalogbyid(catalog_uuid=image_id, catalogs=catalogs) + ' Template'
         power_on = 'false'
         if start:
@@ -1124,11 +1165,11 @@ class vimconnector(vimconn.vimconnector):
         # create vApp.  Set vcpu and ram based on flavor id.
         vapptask = vca.create_vapp(self.tenant_name, name, templateName,
                                    self.get_catalogbyid(image_id, catalogs),
-                                   network_name=primary_net_name,           # can be None if net_list None
+                                   network_name=primary_net_name,  # can be None if net_list None
                                    network_mode='bridged',
                                    vm_name=name,
-                                   vm_cpus=vm_cpus,                         # can be None if flavor is None
-                                   vm_memory=vm_memory)                     # can be None if flavor is None
+                                   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:
             raise vimconn.vimconnUnexpectedResponse("new_vminstance(): failed deploy vApp {}".format(name))
@@ -1201,7 +1242,7 @@ class vimconnector(vimconn.vimconnector):
     #   error_msg:
     #   interfaces: …
     #
-    def get_vminstance(self, vim_vm_uuid):
+    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))
@@ -1211,43 +1252,35 @@ class vimconnector(vimconn.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)
+            raise vimconn.vimconnNotFoundException("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()
-
-        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 vm_info_dict.has_key('interfaces'):
+                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
 
@@ -2268,3 +2301,125 @@ class vimconnector(vimconn.vimconnector):
                     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 network_section.attrib.has_key('networkName'):
+                    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 adapters.attrib.has_key('network'):
+                                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 link.attrib.has_key('rel'):
+                            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 acuireConsole(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, vm_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 None
+
+        return response.content
index c332cdb..c85b1d5 100755 (executable)
@@ -62,6 +62,7 @@ import uuid
 
 from xml.etree import ElementTree as ET
 
+import sys
 from pyvcloud import Http
 
 import logging
@@ -420,7 +421,6 @@ def view_actions(vim=None, action=None, namespace=None):
 
     # view vapp action
     if action == 'vapp' or namespace.action == 'vapp':
-        print namespace.vapp_name
         if namespace.vapp_name is not None and namespace.uuid:
             logger.debug("Requesting vapp {} for vdc {}".format(namespace.vapp_name, namespace.vcdvdc))
             vapp_dict = {}
@@ -432,8 +432,12 @@ def view_actions(vim=None, action=None, namespace=None):
                     print("Can't find vapp by given name {}".format(namespace.vapp_name))
                     return
 
-            vapp_dict = vim.get_vapp(vdc_name=namespace.vcdvdc, vapp_name=vapp_uuid, isuuid=True)
-            if vapp_dict is not None:
+            print " namespace {}".format(namespace)
+            if vapp_dict is not None and namespace.osm:
+                vm_info_dict = vim.get_vminstance(vim_vm_uuid=vapp_uuid)
+                print vm_info_dict
+            if vapp_dict is not None and namespace.osm != True:
+                vapp_dict = vim.get_vapp(vdc_name=namespace.vcdvdc, vapp_name=vapp_uuid, isuuid=True)
                 print_vapp(vapp_dict=vapp_dict)
 
     # view network
@@ -512,13 +516,13 @@ def upload_image(vim=None, image_file=None):
             The return true if image uploaded correctly
     """
     try:
-        catalog_uuid = vim.get_image_id_from_path(path=image_file)
+        catalog_uuid = vim.get_image_id_from_path(path=image_file, progress=True)
         if catalog_uuid is not None and validate_uuid4(catalog_uuid):
             print("Image uploaded and uuid {}".format(catalog_uuid))
             return True
-    except:
+    except vimconn.vimconnException as upload_exception:
         print("Failed uploaded {} image".format(image_file))
-
+        print("Error Reason: {}".format(upload_exception.message))
     return False
 
 
@@ -558,6 +562,8 @@ def boot_image(vim=None, image_name=None, vm_name=None):
     except:
         print("Failed uploaded {} image".format(image_name))
 
+    return False
+
 
 def image_action(vim=None, action=None, namespace=None):
     """ Function present set of action to manipulate with image.
@@ -638,6 +644,7 @@ def vmwarecli(command=None, action=None, namespace=None):
                            log_level="DEBUG",
                            config={'admin_username': namespace.vcdamdin, 'admin_password': namespace.vcdadminpassword})
         vim.vca = vim.connect()
+
     except vimconn.vimconnConnectionException:
         print("Failed connect to vcloud director. Please check credential and hostname.")
         return
@@ -746,6 +753,7 @@ if __name__ == '__main__':
     view_vapp_parser.add_argument('vapp_name', action='store',
                                   help='- view vapp for specific vapp name in vcloud director')
     view_vapp_parser.add_argument('-u', '--uuid', default=False, action='store_true', help='view vapp based on uuid')
+    view_vapp_parser.add_argument('-o', '--osm', default=False, action='store_true',  help='provide view in OSM format')
 
     # view network
     view_network = view_sub_subparsers.add_parser('network')