Esempio n. 1
0
    def _create_connection(self, url, file_size, cookies):
        """Create HTTP connection to write to the file with given URL."""
        LOG.debug(
            "Creating HTTP connection to write to file with "
            "size = %(file_size)d and URL = %(url)s.", {
                'file_size': file_size,
                'url': url
            })
        _urlparse = urlparse.urlparse(url)
        scheme, netloc, path, params, query, fragment = _urlparse

        try:
            if scheme == 'http':
                conn = httplib.HTTPConnection(netloc)
            elif scheme == 'https':
                conn = httplib.HTTPSConnection(netloc)
            else:
                excep_msg = _("Invalid scheme: %s.") % scheme
                LOG.error(excep_msg)
                raise ValueError(excep_msg)

            conn.putrequest('PUT', path + '?' + query)
            conn.putheader('User-Agent', USER_AGENT)
            conn.putheader('Content-Length', file_size)
            conn.putheader('Cookie', self._build_vim_cookie_header(cookies))
            conn.endheaders()
            return conn
        except (httplib.InvalidURL, httplib.CannotSendRequest,
                httplib.CannotSendHeader) as excep:
            excep_msg = _("Error occurred while creating HTTP connection "
                          "to write to file with URL = %s.") % url
            LOG.exception(excep_msg)
            raise exceptions.VimConnectionException(excep_msg, excep)
Esempio n. 2
0
    def __init__(self,
                 ref,
                 name,
                 capacity=None,
                 freespace=None,
                 type=None,
                 datacenter=None):
        """Datastore object holds ref and name together for convenience.

        :param ref: a vSphere reference to a datastore
        :param name: vSphere unique name for this datastore
        :param capacity: (optional) capacity in bytes of this datastore
        :param freespace: (optional) free space in bytes of datastore
        :param type: (optional) datastore type
        :param datacenter: (optional) oslo.vmware Datacenter object
        """
        if name is None:
            raise ValueError(_("Datastore name cannot be None"))
        if ref is None:
            raise ValueError(_("Datastore reference cannot be None"))
        if freespace is not None and capacity is None:
            raise ValueError(_("Invalid capacity"))
        if capacity is not None and freespace is not None:
            if capacity < freespace:
                raise ValueError(_("Capacity is smaller than free space"))

        self.ref = ref
        self.name = name
        self.capacity = capacity
        self.freespace = freespace
        self.type = type
        self.datacenter = datacenter
Esempio n. 3
0
 def connect(self, method, content_length, cookie):
     try:
         if self._scheme == 'http':
             conn = httplib.HTTPConnection(self._server)
         elif self._scheme == 'https':
             conn = httplib.HTTPSConnection(self._server)
         else:
             excep_msg = _("Invalid scheme: %s.") % self._scheme
             LOG.error(excep_msg)
             raise ValueError(excep_msg)
         conn.putrequest(method, '/folder/%s?%s' % (self.path, self._query))
         conn.putheader('User-Agent', constants.USER_AGENT)
         conn.putheader('Content-Length', content_length)
         conn.putheader('Cookie', cookie)
         conn.endheaders()
         LOG.debug(
             "Created HTTP connection to transfer the file with "
             "URL = %s.", str(self))
         return conn
     except (httplib.InvalidURL, httplib.CannotSendRequest,
             httplib.CannotSendHeader) as excep:
         excep_msg = _("Error occurred while creating HTTP connection "
                       "to write to file with URL = %s.") % str(self)
     LOG.exception(excep_msg)
     raise exceptions.VimConnectionException(excep_msg, excep)
Esempio n. 4
0
    def __init__(self, ref, name, capacity=None, freespace=None,
                 type=None, datacenter=None):
        """Datastore object holds ref and name together for convenience.

        :param ref: a vSphere reference to a datastore
        :param name: vSphere unique name for this datastore
        :param capacity: (optional) capacity in bytes of this datastore
        :param freespace: (optional) free space in bytes of datastore
        :param type: (optional) datastore type
        :param datacenter: (optional) oslo.vmware Datacenter object
        """
        if name is None:
            raise ValueError(_("Datastore name cannot be None"))
        if ref is None:
            raise ValueError(_("Datastore reference cannot be None"))
        if freespace is not None and capacity is None:
            raise ValueError(_("Invalid capacity"))
        if capacity is not None and freespace is not None:
            if capacity < freespace:
                raise ValueError(_("Capacity is smaller than free space"))

        self.ref = ref
        self.name = name
        self.capacity = capacity
        self.freespace = freespace
        self.type = type
        self.datacenter = datacenter
Esempio n. 5
0
    def _create_connection(self, url, file_size, cookies):
        """Create HTTP connection to write to the file with given URL."""
        LOG.debug("Creating HTTP connection to write to file with "
                  "size = %(file_size)d and URL = %(url)s.",
                  {'file_size': file_size,
                   'url': url})
        _urlparse = urlparse.urlparse(url)
        scheme, netloc, path, params, query, fragment = _urlparse

        try:
            if scheme == 'http':
                conn = httplib.HTTPConnection(netloc)
            elif scheme == 'https':
                conn = httplib.HTTPSConnection(netloc)
            else:
                excep_msg = _("Invalid scheme: %s.") % scheme
                LOG.error(excep_msg)
                raise ValueError(excep_msg)

            conn.putrequest('PUT', path + '?' + query)
            conn.putheader('User-Agent', USER_AGENT)
            conn.putheader('Content-Length', file_size)
            conn.putheader('Cookie', self._build_vim_cookie_header(cookies))
            conn.endheaders()
            return conn
        except (httplib.InvalidURL, httplib.CannotSendRequest,
                httplib.CannotSendHeader) as excep:
            excep_msg = _("Error occurred while creating HTTP connection "
                          "to write to file with URL = %s.") % url
            LOG.exception(excep_msg)
            raise exceptions.VimConnectionException(excep_msg, excep)
Esempio n. 6
0
 def __init__(self, ref, name):
     """Datacenter object holds ref and name together for convenience."""
     if name is None:
         raise ValueError(_("Datacenter name cannot be None"))
     if ref is None:
         raise ValueError(_("Datacenter reference cannot be None"))
     self.ref = ref
     self.name = name
Esempio n. 7
0
 def __init__(self, ref, name):
     """Datacenter object holds ref and name together for convenience."""
     if name is None:
         raise ValueError(_("Datacenter name cannot be None"))
     if ref is None:
         raise ValueError(_("Datacenter reference cannot be None"))
     self.ref = ref
     self.name = name
Esempio n. 8
0
 def __init__(self, fault_list, message, cause=None, details=None):
     super(VimFaultException, self).__init__(message, cause)
     if not isinstance(fault_list, list):
         raise ValueError(_("fault_list must be a list"))
     if details is not None and not isinstance(details, dict):
         raise ValueError(_("details must be a dict"))
     self.fault_list = fault_list
     self.details = details
Esempio n. 9
0
 def __init__(self, datastore_name, *paths):
     if datastore_name is None or datastore_name == '':
         raise ValueError(_("Datastore name cannot be empty"))
     self._datastore_name = datastore_name
     self._rel_path = ''
     if paths:
         if None in paths:
             raise ValueError(_("Path component cannot be None"))
         self._rel_path = posixpath.join(*paths)
Esempio n. 10
0
 def __init__(self, datastore_name, *paths):
     if datastore_name is None or datastore_name == '':
         raise ValueError(_("Datastore name cannot be empty"))
     self._datastore_name = datastore_name
     self._rel_path = ''
     if paths:
         if None in paths:
             raise ValueError(_("Path component cannot be None"))
         self._rel_path = posixpath.join(*paths)
Esempio n. 11
0
        def _inner():
            """Task performing the image write operation.

            This method performs image data transfer through an update call.
            After the update, it waits until the image state becomes
            'active', 'killed' or unknown. If the final state is not 'active'
            an instance of ImageTransferException is thrown.

            :raises: ImageTransferException
            """
            LOG.debug(
                "Calling image service update on image: %(image)s " "with meta: %(meta)s",
                {"image": self._image_id, "meta": self._image_meta},
            )

            try:
                self._image_service.update(self._context, self._image_id, self._image_meta, data=self._input_file)
                self._running = True
                while self._running:
                    LOG.debug("Retrieving status of image: %s.", self._image_id)
                    image_meta = self._image_service.show(self._context, self._image_id)
                    image_status = image_meta.get("status")
                    if image_status == "active":
                        self.stop()
                        LOG.debug("Image: %s is now active.", self._image_id)
                        self._done.send(True)
                    elif image_status == "killed":
                        self.stop()
                        excep_msg = _("Image: %s is in killed state.") % self._image_id
                        LOG.error(excep_msg)
                        excep = exceptions.ImageTransferException(excep_msg)
                        self._done.send_exception(excep)
                    elif image_status in ["saving", "queued"]:
                        LOG.debug(
                            "Image: %(image)s is in %(state)s state; " "sleeping for %(sleep)d seconds.",
                            {"image": self._image_id, "state": image_status, "sleep": IMAGE_SERVICE_POLL_INTERVAL},
                        )
                        greenthread.sleep(IMAGE_SERVICE_POLL_INTERVAL)
                    else:
                        self.stop()
                        excep_msg = _("Image: %(image)s is in unknown " "state: %(state)s.") % {
                            "image": self._image_id,
                            "state": image_status,
                        }
                        LOG.error(excep_msg)
                        excep = exceptions.ImageTransferException(excep_msg)
                        self._done.send_exception(excep)
            except Exception as excep:
                self.stop()
                excep_msg = _("Error occurred while writing image: %s") % self._image_id
                LOG.exception(excep_msg)
                excep = exceptions.ImageTransferException(excep_msg, excep)
                self._done.send_exception(excep)
Esempio n. 12
0
        def _inner():
            """Task performing the file read-write operation."""
            self._running = True
            while self._running:
                try:
                    data = self._input_file.read(rw_handles.READ_CHUNKSIZE)
                    if not data:
                        LOG.debug("File read-write task is done.")
                        self.stop()
                        self._done.send(True)
                    self._output_file.write(data)

                    # update lease progress if applicable
                    if hasattr(self._input_file, "update_progress"):
                        self._input_file.update_progress()
                    if hasattr(self._output_file, "update_progress"):
                        self._output_file.update_progress()

                    greenthread.sleep(FILE_READ_WRITE_TASK_SLEEP_TIME)
                except Exception as excep:
                    self.stop()
                    excep_msg = _("Error occurred during file read-write "
                                  "task.")
                    LOG.exception(excep_msg)
                    excep = exceptions.ImageTransferException(excep_msg, excep)
                    self._done.send_exception(excep)
Esempio n. 13
0
        def _inner():
            """Task performing the file read-write operation."""
            self._running = True
            while self._running:
                try:
                    data = self._input_file.read(rw_handles.READ_CHUNKSIZE)
                    if not data:
                        LOG.debug("File read-write task is done.")
                        self.stop()
                        self._done.send(True)
                    self._output_file.write(data)

                    # update lease progress if applicable
                    if hasattr(self._input_file, "update_progress"):
                        self._input_file.update_progress()
                    if hasattr(self._output_file, "update_progress"):
                        self._output_file.update_progress()

                    greenthread.sleep(FILE_READ_WRITE_TASK_SLEEP_TIME)
                except Exception as excep:
                    self.stop()
                    excep_msg = _("Error occurred during file read-write " "task.")
                    LOG.exception(excep_msg)
                    excep = exceptions.ImageTransferException(excep_msg, excep)
                    self._done.send_exception(excep)
Esempio n. 14
0
        def _invoke_api(module, method, *args, **kwargs):
            try:
                api_method = getattr(module, method)
                return api_method(*args, **kwargs)
            except exceptions.VimFaultException as excep:
                # If this is due to an inactive session, we should re-create
                # the session and retry.
                if exceptions.NOT_AUTHENTICATED in excep.fault_list:
                    # The NotAuthenticated fault is set by the fault checker
                    # due to an empty response. An empty response could be a
                    # valid response; for e.g., response for the query to
                    # return the VMs in an ESX server which has no VMs in it.
                    # Also, the server responds with an empty response in the
                    # case of an inactive session. Therefore, we need a way to
                    # differentiate between these two cases.
                    if self._is_current_session_active():
                        LOG.debug(
                            "Returning empty response for "
                            "%(module)s.%(method)s invocation.", {
                                'module': module,
                                'method': method
                            })
                        return []
                    else:
                        # empty response is due to an inactive session
                        excep_msg = (
                            _("Current session: %(session)s is inactive; "
                              "re-creating the session while invoking "
                              "method %(module)s.%(method)s.") % {
                                  'session': _trunc_id(self._session_id),
                                  'module': module,
                                  'method': method
                              })
                        LOG.warn(excep_msg, exc_info=True)
                        self._create_session()
                        raise exceptions.VimConnectionException(
                            excep_msg, excep)
                else:
                    # no need to retry for other VIM faults like
                    # InvalidArgument
                    # Raise specific exceptions here if possible
                    if excep.fault_list:
                        LOG.debug("Fault list: %s", excep.fault_list)
                        fault = excep.fault_list[0]
                        clazz = exceptions.get_fault_class(fault)
                        raise clazz(unicode(excep), excep.details)
                    raise

            except exceptions.VimConnectionException:
                with excutils.save_and_reraise_exception():
                    # Re-create the session during connection exception.
                    LOG.warn(_LW("Re-creating session due to connection "
                                 "problems while invoking method "
                                 "%(module)s.%(method)s."), {
                                     'module': module,
                                     'method': method
                                 },
                             exc_info=True)
                    self._create_session()
Esempio n. 15
0
def register_fault_class(name, exception):
    fault_class = _fault_classes_registry.get(name)
    if not issubclass(exception, VMwareDriverException):
        raise TypeError(_("exception should be a subclass of "
                          "VMwareDriverException"))
    if fault_class:
        LOG.debug('Overriding exception for %s', name)
    _fault_classes_registry[name] = exception
Esempio n. 16
0
    def __init__(self, message, cause=None):
        Exception.__init__(self)
        if isinstance(message, list):
            # we need this to protect against developers using
            # this method like VimFaultException
            raise ValueError(_("exception_summary must not be a list"))

        self.msg = message
        self.cause = cause
Esempio n. 17
0
        def _invoke_api(module, method, *args, **kwargs):
            try:
                api_method = getattr(module, method)
                return api_method(*args, **kwargs)
            except exceptions.VimFaultException as excep:
                # If this is due to an inactive session, we should re-create
                # the session and retry.
                if exceptions.NOT_AUTHENTICATED in excep.fault_list:
                    # The NotAuthenticated fault is set by the fault checker
                    # due to an empty response. An empty response could be a
                    # valid response; for e.g., response for the query to
                    # return the VMs in an ESX server which has no VMs in it.
                    # Also, the server responds with an empty response in the
                    # case of an inactive session. Therefore, we need a way to
                    # differentiate between these two cases.
                    if self._is_current_session_active():
                        LOG.debug("Returning empty response for "
                                  "%(module)s.%(method)s invocation.",
                                  {'module': module,
                                   'method': method})
                        return []
                    else:
                        # empty response is due to an inactive session
                        excep_msg = (
                            _("Current session: %(session)s is inactive; "
                              "re-creating the session while invoking "
                              "method %(module)s.%(method)s.") %
                            {'session': _trunc_id(self._session_id),
                             'module': module,
                             'method': method})
                        LOG.warn(excep_msg, exc_info=True)
                        self._create_session()
                        raise exceptions.VimConnectionException(excep_msg,
                                                                excep)
                else:
                    # no need to retry for other VIM faults like
                    # InvalidArgument
                    # Raise specific exceptions here if possible
                    if excep.fault_list:
                        LOG.debug("Fault list: %s", excep.fault_list)
                        fault = excep.fault_list[0]
                        clazz = exceptions.get_fault_class(fault)
                        raise clazz(six.text_type(excep), excep.details)
                    raise

            except exceptions.VimConnectionException:
                with excutils.save_and_reraise_exception():
                    # Re-create the session during connection exception.
                    LOG.warn(_LW("Re-creating session due to connection "
                                 "problems while invoking method "
                                 "%(module)s.%(method)s."),
                             {'module': module,
                              'method': method},
                             exc_info=True)
                    self._create_session()
Esempio n. 18
0
    def _poll_lease(self, lease):
        """Poll the state of the given lease.

        When the lease is ready, the event (param done) is notified. In case
        of any error, appropriate exception is set in the event.

        :param lease: lease whose state is to be polled
        """
        LOG.debug("Invoking VIM API to read state of lease: %s.", lease)
        try:
            state = self.invoke_api(vim_util,
                                    'get_object_property',
                                    self.vim,
                                    lease,
                                    'state')
        except exceptions.VimException:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("Error occurred while checking "
                                  "state of lease: %s."),
                              lease)
        else:
            if state == 'ready':
                LOG.debug("Lease: %s is ready.", lease)
                raise loopingcall.LoopingCallDone()
            elif state == 'initializing':
                LOG.debug("Lease: %s is initializing.", lease)
            elif state == 'error':
                LOG.debug("Invoking VIM API to read lease: %s error.",
                          lease)
                error_msg = self._get_error_message(lease)
                excep_msg = _("Lease: %(lease)s is in error state. Details: "
                              "%(error_msg)s.") % {'lease': lease,
                                                   'error_msg': error_msg}
                LOG.error(excep_msg)
                raise exceptions.VimException(excep_msg)
            else:
                # unknown state
                excep_msg = _("Unknown state: %(state)s for lease: "
                              "%(lease)s.") % {'state': state,
                                               'lease': lease}
                LOG.error(excep_msg)
                raise exceptions.VimException(excep_msg)
Esempio n. 19
0
    def _poll_lease(self, lease):
        """Poll the state of the given lease.

        When the lease is ready, the event (param done) is notified. In case
        of any error, appropriate exception is set in the event.

        :param lease: lease whose state is to be polled
        """
        LOG.debug("Invoking VIM API to read state of lease: %s.", lease)
        try:
            state = self.invoke_api(vim_util, 'get_object_property', self.vim,
                                    lease, 'state')
        except exceptions.VimException:
            with excutils.save_and_reraise_exception():
                LOG.exception(
                    _LE("Error occurred while checking "
                        "state of lease: %s."), lease)
        else:
            if state == 'ready':
                LOG.debug("Lease: %s is ready.", lease)
                raise loopingcall.LoopingCallDone()
            elif state == 'initializing':
                LOG.debug("Lease: %s is initializing.", lease)
            elif state == 'error':
                LOG.debug("Invoking VIM API to read lease: %s error.", lease)
                error_msg = self._get_error_message(lease)
                excep_msg = _("Lease: %(lease)s is in error state. Details: "
                              "%(error_msg)s.") % {
                                  'lease': lease,
                                  'error_msg': error_msg
                              }
                LOG.error(excep_msg)
                raise exceptions.VimException(excep_msg)
            else:
                # unknown state
                excep_msg = _("Unknown state: %(state)s for lease: "
                              "%(lease)s.") % {
                                  'state': state,
                                  'lease': lease
                              }
                LOG.error(excep_msg)
                raise exceptions.VimException(excep_msg)
Esempio n. 20
0
    def parse(cls, datastore_path):
        """Constructs a DatastorePath object given a datastore path string."""
        if not datastore_path:
            raise ValueError(_("Datastore path cannot be empty"))

        spl = datastore_path.split('[', 1)[1].split(']', 1)
        path = ""
        if len(spl) == 1:
            datastore_name = spl[0]
        else:
            datastore_name, path = spl
        return cls(datastore_name, path.strip())
Esempio n. 21
0
    def parse(cls, datastore_path):
        """Constructs a DatastorePath object given a datastore path string."""
        if not datastore_path:
            raise ValueError(_("Datastore path cannot be empty"))

        spl = datastore_path.split('[', 1)[1].split(']', 1)
        path = ""
        if len(spl) == 1:
            datastore_name = spl[0]
        else:
            datastore_name, path = spl
        return cls(datastore_name, path.strip())
Esempio n. 22
0
    def write(self, data):
        """Write data to the file.

        :param data: data to be written
        :raises: VimConnectionException, VimException
        """
        try:
            self._file_handle.send(data)
        except (socket.error, httplib.NotConnected) as excep:
            excep_msg = _("Connection error occurred while writing data to"
                          " %s.") % self._url
            LOG.exception(excep_msg)
            raise exceptions.VimConnectionException(excep_msg, excep)
        except Exception as excep:
            # TODO(vbala) We need to catch and raise specific exceptions
            # related to connection problems, invalid request and invalid
            # arguments.
            excep_msg = _("Error occurred while writing data to"
                          " %s.") % self._url
            LOG.exception(excep_msg)
            raise exceptions.VimException(excep_msg, excep)
Esempio n. 23
0
    def write(self, data):
        """Write data to the file.

        :param data: data to be written
        :raises: VimConnectionException, VimException
        """
        try:
            self._file_handle.send(data)
        except (socket.error, httplib.NotConnected) as excep:
            excep_msg = _("Connection error occurred while writing data to"
                          " %s.") % self._url
            LOG.exception(excep_msg)
            raise exceptions.VimConnectionException(excep_msg, excep)
        except Exception as excep:
            # TODO(vbala) We need to catch and raise specific exceptions
            # related to connection problems, invalid request and invalid
            # arguments.
            excep_msg = _("Error occurred while writing data to"
                          " %s.") % self._url
            LOG.exception(excep_msg)
            raise exceptions.VimException(excep_msg, excep)
Esempio n. 24
0
 def _find_vmdk_url(self, lease_info, host, port):
     """Find the URL corresponding to a VMDK file in lease info."""
     url = None
     for deviceUrl in lease_info.deviceUrl:
         if deviceUrl.disk:
             url = self._fix_esx_url(deviceUrl.url, host, port)
             break
     if not url:
         excep_msg = _("Could not retrieve VMDK URL from lease info.")
         LOG.error(excep_msg)
         raise exceptions.VimException(excep_msg)
     LOG.debug("Found VMDK URL: %s from lease info.", url)
     return url
Esempio n. 25
0
 def _find_vmdk_url(self, lease_info, host, port):
     """Find the URL corresponding to a VMDK file in lease info."""
     url = None
     for deviceUrl in lease_info.deviceUrl:
         if deviceUrl.disk:
             url = self._fix_esx_url(deviceUrl.url, host, port)
             break
     if not url:
         excep_msg = _("Could not retrieve VMDK URL from lease info.")
         LOG.error(excep_msg)
         raise exceptions.VimException(excep_msg)
     LOG.debug("Found VMDK URL: %s from lease info.", url)
     return url
Esempio n. 26
0
    def _create_connection(self, session, url, vmdk_size):
        """Create HTTP connection to write to VMDK file."""
        LOG.debug(
            "Creating HTTP connection to write to VMDK file with "
            "size = %(vmdk_size)d and URL = %(url)s.", {
                'vmdk_size': vmdk_size,
                'url': url
            })
        cookies = session.vim.client.options.transport.cookiejar
        _urlparse = urlparse.urlparse(url)
        scheme, netloc, path, params, query, fragment = _urlparse

        try:
            if scheme == 'http':
                conn = httplib.HTTPConnection(netloc)
            elif scheme == 'https':
                conn = httplib.HTTPSConnection(netloc)
            else:
                excep_msg = _("Invalid scheme: %s.") % scheme
                LOG.error(excep_msg)
                raise ValueError(excep_msg)

            if query:
                path = path + '?' + query
            conn.putrequest('PUT', path)
            conn.putheader('User-Agent', USER_AGENT)
            conn.putheader('Content-Length', str(vmdk_size))
            conn.putheader('Overwrite', 't')
            conn.putheader('Cookie', self._build_vim_cookie_header(cookies))
            conn.putheader('Content-Type', 'binary/octet-stream')
            conn.endheaders()
            return conn
        except (httplib.InvalidURL, httplib.CannotSendRequest,
                httplib.CannotSendHeader) as excep:
            excep_msg = _("Error occurred while creating HTTP connection "
                          "to write to VMDK file with URL = %s.") % url
            LOG.exception(excep_msg)
            raise exceptions.VimConnectionException(excep_msg, excep)
Esempio n. 27
0
    def _create_connection(self, session, url, vmdk_size):
        """Create HTTP connection to write to VMDK file."""
        LOG.debug("Creating HTTP connection to write to VMDK file with "
                  "size = %(vmdk_size)d and URL = %(url)s.",
                  {'vmdk_size': vmdk_size,
                   'url': url})
        cookies = session.vim.client.options.transport.cookiejar
        _urlparse = urlparse.urlparse(url)
        scheme, netloc, path, params, query, fragment = _urlparse

        try:
            if scheme == 'http':
                conn = httplib.HTTPConnection(netloc)
            elif scheme == 'https':
                conn = httplib.HTTPSConnection(netloc)
            else:
                excep_msg = _("Invalid scheme: %s.") % scheme
                LOG.error(excep_msg)
                raise ValueError(excep_msg)

            if query:
                path = path + '?' + query
            conn.putrequest('PUT', path)
            conn.putheader('User-Agent', USER_AGENT)
            conn.putheader('Content-Length', str(vmdk_size))
            conn.putheader('Overwrite', 't')
            conn.putheader('Cookie', self._build_vim_cookie_header(cookies))
            conn.putheader('Content-Type', 'binary/octet-stream')
            conn.endheaders()
            return conn
        except (httplib.InvalidURL, httplib.CannotSendRequest,
                httplib.CannotSendHeader) as excep:
            excep_msg = _("Error occurred while creating HTTP connection "
                          "to write to VMDK file with URL = %s.") % url
            LOG.exception(excep_msg)
            raise exceptions.VimConnectionException(excep_msg, excep)
Esempio n. 28
0
    def build_url(self, scheme, server, rel_path, datacenter_name=None):
        """Constructs and returns a DatastoreURL.

        :param scheme: scheme of the URL (http, https).
        :param server: hostname or ip
        :param rel_path: relative path of the file on the datastore
        :param datacenter_name: (optional) datacenter name
        :return: a DatastoreURL object
        """
        if self.datacenter is None and datacenter_name is None:
            raise ValueError(_("datacenter must be set to build url"))
        if datacenter_name is None:
            datacenter_name = self.datacenter.name
        return DatastoreURL(scheme, server, rel_path, datacenter_name,
                            self.name)
Esempio n. 29
0
    def build_url(self, scheme, server, rel_path, datacenter_name=None):
        """Constructs and returns a DatastoreURL.

        :param scheme: scheme of the URL (http, https).
        :param server: hostname or ip
        :param rel_path: relative path of the file on the datastore
        :param datacenter_name: (optional) datacenter name
        :return: a DatastoreURL object
        """
        if self.datacenter is None and datacenter_name is None:
            raise ValueError(_("datacenter must be set to build url"))
        if datacenter_name is None:
            datacenter_name = self.datacenter.name
        return DatastoreURL(scheme, server, rel_path, datacenter_name,
                            self.name)
Esempio n. 30
0
    def join(self, *paths):
        """Join one or more path components intelligently into a datastore path.

        If any component is an absolute path, all previous components are
        thrown away, and joining continues. The return value is the
        concatenation of the paths with exactly one slash ('/') inserted
        between components, unless p is empty.

        :return: A datastore path
        """
        if paths:
            if None in paths:
                raise ValueError(_("Path component cannot be None"))
            return DatastorePath(self.datastore, self._rel_path, *paths)
        return self
Esempio n. 31
0
 def connect(self, method, content_length, cookie):
     try:
         if self._scheme == 'http':
             conn = httplib.HTTPConnection(self._server)
         elif self._scheme == 'https':
             conn = httplib.HTTPSConnection(self._server)
         else:
             excep_msg = _("Invalid scheme: %s.") % self._scheme
             LOG.error(excep_msg)
             raise ValueError(excep_msg)
         conn.putrequest(method, '/folder/%s?%s' % (self.path, self._query))
         conn.putheader('User-Agent', constants.USER_AGENT)
         conn.putheader('Content-Length', content_length)
         conn.putheader('Cookie', cookie)
         conn.endheaders()
         LOG.debug("Created HTTP connection to transfer the file with "
                   "URL = %s.", str(self))
         return conn
     except (httplib.InvalidURL, httplib.CannotSendRequest,
             httplib.CannotSendHeader) as excep:
         excep_msg = _("Error occurred while creating HTTP connection "
                       "to write to file with URL = %s.") % str(self)
     LOG.exception(excep_msg)
     raise exceptions.VimConnectionException(excep_msg, excep)
Esempio n. 32
0
    def join(self, *paths):
        """Join one or more path components intelligently into a datastore path.

        If any component is an absolute path, all previous components are
        thrown away, and joining continues. The return value is the
        concatenation of the paths with exactly one slash ('/') inserted
        between components, unless p is empty.

        :return: A datastore path
        """
        if paths:
            if None in paths:
                raise ValueError(_("Path component cannot be None"))
            return DatastorePath(self.datastore, self._rel_path, *paths)
        return self
Esempio n. 33
0
 def _create_connection(self, session, url):
     LOG.debug("Opening URL: %s for reading.", url)
     try:
         cookies = session.vim.client.options.transport.cookiejar
         headers = {'User-Agent': USER_AGENT,
                    'Cookie': self._build_vim_cookie_header(cookies)}
         request = urllib2.Request(url, None, headers)
         conn = urllib2.urlopen(request)
         return conn
     except Exception as excep:
         # TODO(vbala) We need to catch and raise specific exceptions
         # related to connection problems, invalid request and invalid
         # arguments.
         excep_msg = _("Error occurred while opening URL: %s for "
                       "reading.") % url
         LOG.exception(excep_msg)
         raise exceptions.VimException(excep_msg, excep)
Esempio n. 34
0
 def _create_connection(self, session, url):
     LOG.debug("Opening URL: %s for reading.", url)
     try:
         cookies = session.vim.client.options.transport.cookiejar
         headers = {
             'User-Agent': USER_AGENT,
             'Cookie': self._build_vim_cookie_header(cookies)
         }
         request = urllib2.Request(url, None, headers)
         conn = urllib2.urlopen(request)
         return conn
     except Exception as excep:
         # TODO(vbala) We need to catch and raise specific exceptions
         # related to connection problems, invalid request and invalid
         # arguments.
         excep_msg = _("Error occurred while opening URL: %s for "
                       "reading.") % url
         LOG.exception(excep_msg)
         raise exceptions.VimException(excep_msg, excep)
Esempio n. 35
0
    def read(self, chunk_size):
        """Read a chunk of data from the VMDK file.

        :param chunk_size: size of read chunk
        :returns: the data
        :raises: VimException
        """
        try:
            data = self._file_handle.read(READ_CHUNKSIZE)
            self._bytes_read += len(data)
            return data
        except Exception as excep:
            # TODO(vbala) We need to catch and raise specific exceptions
            # related to connection problems, invalid request and invalid
            # arguments.
            excep_msg = _("Error occurred while reading data from"
                          " %s.") % self._url
            LOG.exception(excep_msg)
            raise exceptions.VimException(excep_msg, excep)
Esempio n. 36
0
    def read(self, chunk_size):
        """Read a chunk of data from the VMDK file.

        :param chunk_size: size of read chunk
        :returns: the data
        :raises: VimException
        """
        try:
            data = self._file_handle.read(READ_CHUNKSIZE)
            self._bytes_read += len(data)
            return data
        except Exception as excep:
            # TODO(vbala) We need to catch and raise specific exceptions
            # related to connection problems, invalid request and invalid
            # arguments.
            excep_msg = _("Error occurred while reading data from"
                          " %s.") % self._url
            LOG.exception(excep_msg)
            raise exceptions.VimException(excep_msg, excep)
Esempio n. 37
0
    def _retrieve_properties_ex_fault_checker(response):
        """Checks the RetrievePropertiesEx API response for errors.

        Certain faults are sent in the SOAP body as a property of missingSet.
        This method raises VimFaultException when a fault is found in the
        response.

        :param response: response from RetrievePropertiesEx API call
        :raises: VimFaultException
        """
        fault_list = []
        details = {}
        if not response:
            # This is the case when the session has timed out. ESX SOAP
            # server sends an empty RetrievePropertiesExResponse. Normally
            # missingSet in the response objects has the specifics about
            # the error, but that's not the case with a timed out idle
            # session. It is as bad as a terminated session for we cannot
            # use the session. Therefore setting fault to NotAuthenticated
            # fault.
            LOG.debug("RetrievePropertiesEx API response is empty; setting "
                      "fault to %s.",
                      exceptions.NOT_AUTHENTICATED)
            fault_list = [exceptions.NOT_AUTHENTICATED]
        else:
            for obj_cont in response.objects:
                if hasattr(obj_cont, 'missingSet'):
                    for missing_elem in obj_cont.missingSet:
                        f_type = missing_elem.fault.fault
                        f_name = f_type.__class__.__name__
                        fault_list.append(f_name)
                        if f_name == exceptions.NO_PERMISSION:
                            details['object'] = f_type.object.value
                            details['privilegeId'] = f_type.privilegeId

        if fault_list:
            fault_string = _("Error occurred while calling "
                             "RetrievePropertiesEx.")
            raise exceptions.VimFaultException(fault_list,
                                               fault_string,
                                               details=details)
Esempio n. 38
0
    def _poll_task(self, task):
        """Poll the given task until completion.

        If the task completes successfully, the method returns the task info
        using the input event (param done). In case of any error, appropriate
        exception is set in the event.

        :param task: managed object reference of the task
        """
        LOG.debug("Invoking VIM API to read info of task: %s.", task)
        try:
            task_info = self.invoke_api(vim_util,
                                        'get_object_property',
                                        self.vim,
                                        task,
                                        'info')
        except exceptions.VimException:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("Error occurred while reading info of "
                                  "task: %s."),
                              task)
        else:
            if task_info.state in ['queued', 'running']:
                if hasattr(task_info, 'progress'):
                    LOG.debug("Task: %(task)s progress is %(progress)s%%.",
                              {'task': task,
                               'progress': task_info.progress})
            elif task_info.state == 'success':
                LOG.debug("Task: %s status is success.", task)
                raise loopingcall.LoopingCallDone(task_info)
            else:
                error_msg = six.text_type(task_info.error.localizedMessage)
                excep_msg = _("Task: %(task)s failed with error: "
                              "%(error)s.") % {'task': task,
                                               'error': error_msg}
                LOG.error(excep_msg)
                error = task_info.error
                name = error.fault.__class__.__name__
                task_ex = exceptions.get_fault_class(name)(error_msg)
                raise task_ex
Esempio n. 39
0
 def test_vim_fault_exception(self):
     vfe = exceptions.VimFaultException([ValueError("example")], _("cause"))
     string = str(vfe)
     self.assertEqual("cause\nFaults: [ValueError('example',)]", string)
Esempio n. 40
0
 def test_vim_fault_exception(self):
     vfe = exceptions.VimFaultException([ValueError("example")], _("cause"))
     string = str(vfe)
     self.assertEqual("cause\nFaults: [ValueError('example',)]", string)
Esempio n. 41
0
 def test_exception_summary_string(self):
     e = exceptions.VimException(_("string"), ValueError("foo"))
     string = str(e)
     self.assertEqual("string\nCause: foo", string)
Esempio n. 42
0
def _start_transfer(context, timeout_secs, read_file_handle, max_data_size,
                    write_file_handle=None, image_service=None, image_id=None,
                    image_meta=None):
    """Start the image transfer.

    The image reader reads the data from the image source and writes to the
    blocking queue. The image source is always a file handle (VmdkReadHandle
    or ImageReadHandle); therefore, a FileReadWriteTask is created for this
    transfer. The image writer reads the data from the blocking queue and
    writes it to the image destination. The image destination is either a
    file or VMDK in VMware datastore or an image in the image service.

    If the destination is a file or VMDK in VMware datastore, the method
    creates a FileReadWriteTask which reads from the blocking queue and
    writes to either FileWriteHandle or VmdkWriteHandle. In the case of
    image service as the destination, an instance of ImageWriter task is
    created which reads from the blocking queue and writes to the image
    service.

    :param context: write context needed for the image service
    :param timeout_secs: time in seconds to wait for the transfer to complete
    :param read_file_handle: handle to read data from
    :param max_data_size: maximum transfer size
    :param write_file_handle: handle to write data to; if this is None, then
                              param image_service  and param image_id should
                              be set.
    :param image_service: image service handle
    :param image_id: ID of the image in the image service
    :param image_meta: image meta-data
    :raises: ImageTransferException, ValueError
    """

    # Create the blocking queue
    blocking_queue = BlockingQueue(BLOCKING_QUEUE_SIZE, max_data_size)

    # Create the image reader
    reader = FileReadWriteTask(read_file_handle, blocking_queue)

    # Create the image writer
    if write_file_handle:
        # File or VMDK in VMware datastore is the image destination
        writer = FileReadWriteTask(blocking_queue, write_file_handle)
    elif image_service and image_id:
        # Image service image is the destination
        writer = ImageWriter(context,
                             blocking_queue,
                             image_service,
                             image_id,
                             image_meta)
    else:
        excep_msg = _("No image destination given.")
        LOG.error(excep_msg)
        raise ValueError(excep_msg)

    # Start the reader and writer
    LOG.debug("Starting image transfer with reader: %(reader)s and writer: "
              "%(writer)s",
              {'reader': reader,
               'writer': writer})
    reader.start()
    writer.start()
    timer = timeout.Timeout(timeout_secs)
    try:
        # Wait for the reader and writer to complete
        reader.wait()
        writer.wait()
    except (timeout.Timeout, exceptions.ImageTransferException) as excep:
        excep_msg = (_("Error occurred during image transfer with reader: "
                       "%(reader)s and writer: %(writer)s") %
                     {'reader': reader,
                      'writer': writer})
        LOG.exception(excep_msg)
        reader.stop()
        writer.stop()

        if isinstance(excep, exceptions.ImageTransferException):
            raise
        raise exceptions.ImageTransferException(excep_msg, excep)
    finally:
        timer.cancel()
        read_file_handle.close()
        if write_file_handle:
            write_file_handle.close()
Esempio n. 43
0
 def test_exception_summary_string(self):
     e = exceptions.VimException(_("string"), ValueError("foo"))
     string = str(e)
     self.assertEqual("string\nCause: foo", string)
Esempio n. 44
0
        def request_handler(managed_object, **kwargs):
            """Handler for vSphere API calls.

            Invokes the API and parses the response for fault checking and
            other errors.

            :param managed_object: managed object reference argument of the
                                   API call
            :param kwargs: keyword arguments of the API call
            :returns: response of the API call
            :raises: VimException, VimFaultException, VimAttributeException,
                     VimSessionOverLoadException, VimConnectionException
            """
            try:
                if isinstance(managed_object, str):
                    # For strings, use string value for value and type
                    # of the managed object.
                    managed_object = vim_util.get_moref(managed_object,
                                                        managed_object)
                if managed_object is None:
                    return
                request = getattr(self.client.service, attr_name)
                response = request(managed_object, **kwargs)
                if (attr_name.lower() == 'retrievepropertiesex'):
                    Service._retrieve_properties_ex_fault_checker(response)
                return response
            except exceptions.VimFaultException:
                # Catch the VimFaultException that is raised by the fault
                # check of the SOAP response.
                raise

            except suds.WebFault as excep:
                fault_string = None
                if excep.fault:
                    fault_string = excep.fault.faultstring

                doc = excep.document
                detail = None
                if doc is not None:
                    detail = doc.childAtPath('/detail')
                    if not detail:
                        # NOTE(arnaud): this is needed with VC 5.1
                        detail = doc.childAtPath('/Envelope/Body/Fault/detail')
                fault_list = []
                details = {}
                if detail:
                    for fault in detail.getChildren():
                        fault_list.append(fault.get("type"))
                        for child in fault.getChildren():
                            details[child.name] = child.getText()
                raise exceptions.VimFaultException(fault_list, fault_string,
                                                   excep, details)

            except AttributeError as excep:
                raise exceptions.VimAttributeException(
                    _("No such SOAP method %s.") % attr_name, excep)

            except (httplib.CannotSendRequest,
                    httplib.ResponseNotReady,
                    httplib.CannotSendHeader) as excep:
                raise exceptions.VimSessionOverLoadException(
                    _("httplib error in %s.") % attr_name, excep)

            except requests.RequestException as excep:
                raise exceptions.VimConnectionException(
                    _("requests error in %s.") % attr_name, excep)

            except Exception as excep:
                # TODO(vbala) should catch specific exceptions and raise
                # appropriate VimExceptions.

                # Socket errors which need special handling; some of these
                # might be caused by server API call overload.
                if (six.text_type(excep).find(ADDRESS_IN_USE_ERROR) != -1 or
                        six.text_type(excep).find(CONN_ABORT_ERROR)) != -1:
                    raise exceptions.VimSessionOverLoadException(
                        _("Socket error in %s.") % attr_name, excep)
                # Type error which needs special handling; it might be caused
                # by server API call overload.
                elif six.text_type(excep).find(RESP_NOT_XML_ERROR) != -1:
                    raise exceptions.VimSessionOverLoadException(
                        _("Type error in %s.") % attr_name, excep)
                else:
                    raise exceptions.VimException(
                        _("Exception in %s.") % attr_name, excep)
Esempio n. 45
0
def _start_transfer(
    context,
    timeout_secs,
    read_file_handle,
    max_data_size,
    write_file_handle=None,
    image_service=None,
    image_id=None,
    image_meta=None,
):
    """Start the image transfer.

    The image reader reads the data from the image source and writes to the
    blocking queue. The image source is always a file handle (VmdkReadHandle
    or ImageReadHandle); therefore, a FileReadWriteTask is created for this
    transfer. The image writer reads the data from the blocking queue and
    writes it to the image destination. The image destination is either a
    file or VMDK in VMware datastore or an image in the image service.

    If the destination is a file or VMDK in VMware datastore, the method
    creates a FileReadWriteTask which reads from the blocking queue and
    writes to either FileWriteHandle or VmdkWriteHandle. In the case of
    image service as the destination, an instance of ImageWriter task is
    created which reads from the blocking queue and writes to the image
    service.

    :param context: write context needed for the image service
    :param timeout_secs: time in seconds to wait for the transfer to complete
    :param read_file_handle: handle to read data from
    :param max_data_size: maximum transfer size
    :param write_file_handle: handle to write data to; if this is None, then
                              param image_service  and param image_id should
                              be set.
    :param image_service: image service handle
    :param image_id: ID of the image in the image service
    :param image_meta: image meta-data
    :raises: ImageTransferException, ValueError
    """

    # Create the blocking queue
    blocking_queue = BlockingQueue(BLOCKING_QUEUE_SIZE, max_data_size)

    # Create the image reader
    reader = FileReadWriteTask(read_file_handle, blocking_queue)

    # Create the image writer
    if write_file_handle:
        # File or VMDK in VMware datastore is the image destination
        writer = FileReadWriteTask(blocking_queue, write_file_handle)
    elif image_service and image_id:
        # Image service image is the destination
        writer = ImageWriter(context, blocking_queue, image_service, image_id, image_meta)
    else:
        excep_msg = _("No image destination given.")
        LOG.error(excep_msg)
        raise ValueError(excep_msg)

    # Start the reader and writer
    LOG.debug(
        "Starting image transfer with reader: %(reader)s and writer: " "%(writer)s",
        {"reader": reader, "writer": writer},
    )
    reader.start()
    writer.start()
    timer = timeout.Timeout(timeout_secs)
    try:
        # Wait for the reader and writer to complete
        reader.wait()
        writer.wait()
    except (timeout.Timeout, exceptions.ImageTransferException) as excep:
        excep_msg = _("Error occurred during image transfer with reader: " "%(reader)s and writer: %(writer)s") % {
            "reader": reader,
            "writer": writer,
        }
        LOG.exception(excep_msg)
        reader.stop()
        writer.stop()

        if isinstance(excep, exceptions.ImageTransferException):
            raise
        raise exceptions.ImageTransferException(excep_msg, excep)
    finally:
        timer.cancel()
        read_file_handle.close()
        if write_file_handle:
            write_file_handle.close()
Esempio n. 46
0
        def _inner():
            """Task performing the image write operation.

            This method performs image data transfer through an update call.
            After the update, it waits until the image state becomes
            'active', 'killed' or unknown. If the final state is not 'active'
            an instance of ImageTransferException is thrown.

            :raises: ImageTransferException
            """
            LOG.debug("Calling image service update on image: %(image)s "
                      "with meta: %(meta)s",
                      {'image': self._image_id,
                       'meta': self._image_meta})

            try:
                self._image_service.update(self._context,
                                           self._image_id,
                                           self._image_meta,
                                           data=self._input_file)
                self._running = True
                while self._running:
                    LOG.debug("Retrieving status of image: %s.",
                              self._image_id)
                    image_meta = self._image_service.show(self._context,
                                                          self._image_id)
                    image_status = image_meta.get('status')
                    if image_status == 'active':
                        self.stop()
                        LOG.debug("Image: %s is now active.",
                                  self._image_id)
                        self._done.send(True)
                    elif image_status == 'killed':
                        self.stop()
                        excep_msg = (_("Image: %s is in killed state.") %
                                     self._image_id)
                        LOG.error(excep_msg)
                        excep = exceptions.ImageTransferException(excep_msg)
                        self._done.send_exception(excep)
                    elif image_status in ['saving', 'queued']:
                        LOG.debug("Image: %(image)s is in %(state)s state; "
                                  "sleeping for %(sleep)d seconds.",
                                  {'image': self._image_id,
                                   'state': image_status,
                                   'sleep': IMAGE_SERVICE_POLL_INTERVAL})
                        greenthread.sleep(IMAGE_SERVICE_POLL_INTERVAL)
                    else:
                        self.stop()
                        excep_msg = (_("Image: %(image)s is in unknown "
                                       "state: %(state)s.") %
                                     {'image': self._image_id,
                                      'state': image_status})
                        LOG.error(excep_msg)
                        excep = exceptions.ImageTransferException(excep_msg)
                        self._done.send_exception(excep)
            except Exception as excep:
                self.stop()
                excep_msg = (_("Error occurred while writing image: %s") %
                             self._image_id)
                LOG.exception(excep_msg)
                excep = exceptions.ImageTransferException(excep_msg, excep)
                self._done.send_exception(excep)