def _start_transfer(read_handle, write_handle, timeout_secs): # read_handle/write_handle could be an NFC lease, so we need to # periodically update its progress read_updater = _create_progress_updater(read_handle) write_updater = _create_progress_updater(write_handle) timer = timeout.Timeout(timeout_secs) try: while True: data = read_handle.read(CHUNK_SIZE) if not data: break write_handle.write(data) except timeout.Timeout as excep: msg = (_('Timeout, read_handle: "%(src)s", write_handle: "%(dest)s"') % {'src': read_handle, 'dest': write_handle}) LOG.exception(msg) raise exceptions.ImageTransferException(msg, excep) except Exception as excep: msg = (_('Error, read_handle: "%(src)s", write_handle: "%(dest)s"') % {'src': read_handle, 'dest': write_handle}) LOG.exception(msg) raise exceptions.ImageTransferException(msg, excep) finally: timer.cancel() if read_updater: read_updater.stop() if write_updater: write_updater.stop() read_handle.close() write_handle.close()
def _start_transfer(read_handle, write_handle, timeout_secs): # write_handle could be an NFC lease, so we need to periodically # update its progress update_cb = getattr(write_handle, 'update_progress', lambda: None) updater = loopingcall.FixedIntervalLoopingCall(update_cb) timer = timeout.Timeout(timeout_secs) try: updater.start(interval=NFC_LEASE_UPDATE_PERIOD) while True: data = read_handle.read(CHUNK_SIZE) if not data: break write_handle.write(data) except timeout.Timeout as excep: msg = (_('Timeout, read_handle: "%(src)s", write_handle: "%(dest)s"') % {'src': read_handle, 'dest': write_handle}) LOG.exception(msg) raise exceptions.ImageTransferException(msg, excep) except Exception as excep: msg = (_('Error, read_handle: "%(src)s", write_handle: "%(dest)s"') % {'src': read_handle, 'dest': write_handle}) LOG.exception(msg) raise exceptions.ImageTransferException(msg, excep) finally: timer.cancel() updater.stop() read_handle.close() write_handle.close()
def __init__(self, message=None, details=None, **kwargs): if message is not None and isinstance(message, list): # we need this to protect against developers using # this method like VimFaultException raise ValueError(_("exception message must not be a list")) if details is not None and not isinstance(details, dict): raise ValueError(_("details must be a dict")) self.kwargs = kwargs self.details = details self.cause = None if not message: try: message = self.msg_fmt % kwargs except Exception: # kwargs doesn't match a variable in the message # log the issue and the kwargs LOG.exception('Exception in string format operation') for name, value in six.iteritems(kwargs): LOG.error("%(name)s: %(value)s", {'name': name, 'value': value}) # at least get the core message out if something happened message = self.msg_fmt self.message = message super(VMwareDriverException, self).__init__(message)
def connect(self, method, content_length, cookie): try: if self._scheme == 'http': conn = httplib.HTTPConnection(self._server) elif self._scheme == 'https': # TODO(browne): This needs to be changed to use python requests conn = httplib.HTTPSConnection(self._server) # nosec 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)
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)
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
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
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
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)
class NsxvException(Exception): """Base Neutron Exception. To correctly use this class, inherit from it and define a 'message' property. That message will get printf'd with the keyword arguments provided to the constructor. """ message = _("An unknown exception occurred.") def __init__(self, **kwargs): try: super(NsxvException, self).__init__(self.message % kwargs) self.msg = self.message % kwargs except Exception: with excutils.save_and_reraise_exception() as ctxt: if not self.use_fatal_exceptions(): ctxt.reraise = False # at least get the core message out if something happened super(NsxvException, self).__init__(self.message) def __unicode__(self): return unicode(self.msg) def use_fatal_exceptions(self): return False
def _create_write_connection(self, method, url, file_size=None, cookies=None, overwrite=None, content_type=None, cacerts=False, ssl_thumbprint=None): """Create HTTP connection to write to VMDK file.""" LOG.debug("Creating HTTP connection to write to file with " "size = %(file_size)d and URL = %(url)s.", {'file_size': file_size, 'url': url}) try: conn = self._create_connection(url, method, cacerts, ssl_thumbprint) headers = {'User-Agent': USER_AGENT} if file_size: headers.update({'Content-Length': str(file_size)}) if overwrite: headers.update({'Overwrite': overwrite}) if cookies: headers.update({'Cookie': self._build_vim_cookie_header(cookies)}) if content_type: headers.update({'Content-Type': content_type}) for key, value in headers.items(): conn.putheader(key, value) conn.endheaders() return conn except requests.RequestException 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)
class VMwareDriverException(Exception): """Base VMware Driver Exception To correctly use this class, inherit from it and define a 'msg_fmt' property. That msg_fmt will get printf'd with the keyword arguments provided to the constructor. """ msg_fmt = _("An unknown exception occurred.") def __init__(self, message=None, details=None, **kwargs): self.kwargs = kwargs self.details = details if not message: try: message = self.msg_fmt % kwargs except Exception: # kwargs doesn't match a variable in the message # log the issue and the kwargs LOG.exception(_LE('Exception in string format operation')) for name, value in six.iteritems(kwargs): LOG.error(_LE("%(name)s: %(value)s"), { 'name': name, 'value': value }) # at least get the core message out if something happened message = self.msg_fmt super(VMwareDriverException, self).__init__(message)
def _create_connection(self, url, method, cacerts=False, ssl_thumbprint=None): _urlparse = urlparse.urlparse(url) scheme, netloc, path, params, query, fragment = _urlparse if scheme == 'http': conn = httplib.HTTPConnection(netloc) elif scheme == 'https': conn = httplib.HTTPSConnection(netloc) cert_reqs = None # cacerts can be either True or False or contain # actual certificates. If it is a boolean, then # we need to set cert_reqs and clear the cacerts if isinstance(cacerts, bool): if cacerts: cert_reqs = ssl.CERT_REQUIRED else: cert_reqs = ssl.CERT_NONE cacerts = None conn.set_cert(ca_certs=cacerts, cert_reqs=cert_reqs, assert_fingerprint=ssl_thumbprint) else: excep_msg = _("Invalid scheme: %s.") % scheme LOG.error(excep_msg) raise ValueError(excep_msg) if query: path = path + '?' + query conn.putrequest(method, path) return conn
def test_vim_fault_exception(self): vfe = exceptions.VimFaultException([ValueError("example")], _("cause")) string = str(vfe) self.assertIn(string, [ "cause\nFaults: [ValueError('example',)]", "cause\nFaults: [ValueError('example')]" ])
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)
def _create_write_connection(self, method, url, file_size=None, cookies=None, overwrite=None, content_type=None, cacerts=False, ssl_thumbprint=None): """Create HTTP connection to write to VMDK file.""" LOG.debug("Creating HTTP connection to write to file with " "size = %(file_size)d and URL = %(url)s.", {'file_size': file_size, 'url': url}) try: conn = self._create_connection(url, method, cacerts, ssl_thumbprint) headers = {'User-Agent': USER_AGENT} if file_size: headers.update({'Content-Length': str(file_size)}) if overwrite: headers.update({'Overwrite': overwrite}) if cookies: headers.update({'Cookie': self._build_vim_cookie_header(cookies)}) if content_type: headers.update({'Content-Type': content_type}) for key, value in six.iteritems(headers): conn.putheader(key, value) conn.endheaders() return conn except requests.RequestException 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)
def _create_connection(self, url, method, cacerts=False, ssl_thumbprint=None): _urlparse = urlparse.urlparse(url) scheme, netloc, path, params, query, fragment = _urlparse if scheme == 'http': conn = httplib.HTTPConnection(netloc) elif scheme == 'https': conn = httplib.HTTPSConnection(netloc) cert_reqs = None # cacerts can be either True or False or contain # actual certificates. If it is a boolean, then # we need to set cert_reqs and clear the cacerts if isinstance(cacerts, bool): if cacerts: cert_reqs = ssl.CERT_REQUIRED else: cert_reqs = ssl.CERT_NONE cacerts = requests.certs.where() conn.set_cert(ca_certs=cacerts, cert_reqs=cert_reqs, assert_fingerprint=ssl_thumbprint) else: excep_msg = _("Invalid scheme: %s.") % scheme LOG.error(excep_msg) raise ValueError(excep_msg) if query: path = path + '?' + query conn.putrequest(method, path) return conn
class VMwareDriverException(Exception): """Base oslo.vmware exception To correctly use this class, inherit from it and define a 'msg_fmt' property. That msg_fmt will get printf'd with the keyword arguments provided to the constructor. """ msg_fmt = _("An unknown exception occurred.") if six.PY2: __str__ = lambda self: six.text_type(self).encode('utf8') __unicode__ = lambda self: self.description else: __str__ = lambda self: self.description def __init__(self, message=None, details=None, **kwargs): if message is not None and isinstance(message, list): # we need this to protect against developers using # this method like VimFaultException raise ValueError(_("exception message must not be a list")) if details is not None and not isinstance(details, dict): raise ValueError(_("details must be a dict")) self.kwargs = kwargs self.details = details self.cause = None if not message: try: message = self.msg_fmt % kwargs except Exception: # kwargs doesn't match a variable in the message # log the issue and the kwargs LOG.exception('Exception in string format operation') for name, value in six.iteritems(kwargs): LOG.error("%(name)s: %(value)s", {'name': name, 'value': value}) # at least get the core message out if something happened message = self.msg_fmt self.message = message super(VMwareDriverException, self).__init__(message) @property def msg(self): return self.message @property def description(self): # NOTE(jecarey): self.msg and self.cause may be i18n objects # that do not support str or concatenation, but can be used # as replacement text. descr = six.text_type(self.msg) if self.cause: descr += '\nCause: ' + six.text_type(self.cause) return descr
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.debug(excep_msg) 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) if clazz: raise clazz(six.text_type(excep), details=excep.details) raise except exceptions.VimConnectionException: with excutils.save_and_reraise_exception(): # Re-create the session during connection exception only # if the session has expired. Otherwise, it could be # a transient issue. if not self.is_current_session_active(): LOG.debug("Re-creating session due to connection " "problems while invoking method " "%(module)s.%(method)s.", {'module': module, 'method': method}) self._create_session()
def register_fault_class(name, exception): fault_class = _fault_classes_registry.get(name) if not issubclass(exception, VimException): raise TypeError(_("exception should be a subclass of " "VimException")) if fault_class: LOG.debug('Overriding exception for %s', name) _fault_classes_registry[name] = exception
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 """ try: state = self.invoke_api(vim_util, 'get_object_property', self.vim, lease, 'state', skip_op_id=True) except exceptions.VimException: with excutils.save_and_reraise_exception(): LOG.exception( "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)
class NsxvApiException(NsxvException): message = _("An unknown exception %(status)s occurred: %(response)s.") def __init__(self, **kwargs): super(NsxvApiException, self).__init__(**kwargs) self.status = kwargs.get('status') self.header = kwargs.get('header') self.response = kwargs.get('response')
class VMwareDriverConfigurationException(VMwareDriverException): """Base class for all configuration exceptions. """ msg_fmt = _("VMware Driver configuration fault.") def __init__(self, message=None, details=None, **kwargs): super(VMwareDriverConfigurationException, self).__init__( message, details, **kwargs) _print_deprecation_warning(self.__class__)
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
def get_imported_vm(self): """"Get managed object reference of the VM created for import. :raises: VimException """ if self._get_progress() < 100: excep_msg = _("Incomplete VMDK upload to %s.") % self._url LOG.exception(excep_msg) raise exceptions.ImageTransferException(excep_msg) return self._vm_ref
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 requests.RequestException 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)
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())
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
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
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)
def _create_read_connection(self, url, cookies=None, cacerts=False, ssl_thumbprint=None): LOG.debug("Opening URL: %s for reading.", url) try: conn = self._create_connection(url, 'GET', cacerts, ssl_thumbprint) vim_cookie = self._build_vim_cookie_header(cookies) conn.putheader('User-Agent', USER_AGENT) conn.putheader('Cookie', vim_cookie) conn.endheaders() return conn.getresponse() 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)
def _create_read_connection(self, url, cookies=None, cacerts=False): LOG.debug("Opening URL: %s for reading.", url) try: headers = {'User-Agent': USER_AGENT} if cookies: headers.update({'Cookie': self._build_vim_cookie_header(cookies)}) response = requests.get(url, headers=headers, stream=True, verify=cacerts) return response.raw 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)
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)
def download_stream_optimized_image(context, timeout_secs, image_service, image_id, **kwargs): """Download stream optimized image from image service to VMware server. :param context: image service write context :param timeout_secs: time in seconds to wait for the download to complete :param image_service: image service handle :param image_id: ID of the image to be downloaded :param kwargs: keyword arguments to configure the destination VMDK write handle :returns: managed object reference of the VM created for import to VMware server :raises: VimException, VimFaultException, VimAttributeException, VimSessionOverLoadException, VimConnectionException, ImageTransferException, ValueError """ metadata = image_service.show(context, image_id) container_format = metadata.get('container_format') LOG.debug( "Downloading image: %(id)s (container: %(container)s) from image" " service as a stream optimized file.", { 'id': image_id, 'container': container_format }) # TODO(vbala) catch specific exceptions raised by download call read_iter = image_service.download(context, image_id) read_handle = rw_handles.ImageReadHandle(read_iter) if container_format == 'ova': read_handle = _get_vmdk_handle(read_handle) if read_handle is None: raise exceptions.ImageTransferException( _("No vmdk found in the OVA image %s.") % image_id) imported_vm = download_stream_optimized_data(context, timeout_secs, read_handle, **kwargs) LOG.debug( "Downloaded image: %s from image service as a stream " "optimized file.", image_id) return imported_vm
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)
def download_stream_optimized_image(context, timeout_secs, image_service, image_id, **kwargs): """Download stream optimized image from image service to VMware server. :param context: image service write context :param timeout_secs: time in seconds to wait for the download to complete :param image_service: image service handle :param image_id: ID of the image to be downloaded :param kwargs: keyword arguments to configure the destination VMDK write handle :returns: managed object reference of the VM created for import to VMware server :raises: VimException, VimFaultException, VimAttributeException, VimSessionOverLoadException, VimConnectionException, ImageTransferException, ValueError """ metadata = image_service.show(context, image_id) container_format = metadata.get('container_format') LOG.debug("Downloading image: %(id)s (container: %(container)s) from image" " service as a stream optimized file.", {'id': image_id, 'container': container_format}) # TODO(vbala) catch specific exceptions raised by download call read_iter = image_service.download(context, image_id) read_handle = rw_handles.ImageReadHandle(read_iter) if container_format == 'ova': read_handle = _get_vmdk_handle(read_handle) if read_handle is None: raise exceptions.ImageTransferException( _("No vmdk found in the OVA image %s.") % image_id) imported_vm = download_stream_optimized_data(context, timeout_secs, read_handle, **kwargs) LOG.debug("Downloaded image: %s from image service as a stream " "optimized file.", image_id) return imported_vm
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)
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()
def __init__(self, fault_list, message, cause=None, details=None): super(VimFaultException, self).__init__(message, cause, details) if not isinstance(fault_list, list): raise ValueError(_("fault_list must be a list")) self.fault_list = fault_list
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_type = fault.get('type') if fault_type.endswith(exceptions.SECURITY_ERROR): fault_type = exceptions.NOT_AUTHENTICATED fault_list.append(fault_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)
def test_exception_summary_string(self): e = exceptions.VimException(_("string"), ValueError("foo")) string = str(e) self.assertEqual("string\nCause: foo", string)
def test_vim_fault_exception(self): vfe = exceptions.VimFaultException([ValueError("example")], _("cause")) string = str(vfe) self.assertEqual("cause\nFaults: [ValueError('example',)]", string)