Beispiel #1
0
def parse_server_string(server_str):
    """Parses the given server_string and returns a tuple of host and port.

    If it's not a combination of host part and port, the port element
    is an empty string. If the input is invalid expression, return a tuple of
    two empty strings.
    """

    try:
        # First of all, exclude pure IPv6 address (w/o port).
        if netaddr.valid_ipv6(server_str):
            return (server_str, '')

        # Next, check if this is IPv6 address with a port number combination.
        if server_str.find("]:") != -1:
            (address, port) = server_str.replace('[', '', 1).split(']:')
            return (address, port)

        # Third, check if this is a combination of an address and a port
        if server_str.find(':') == -1:
            return (server_str, '')

        # This must be a combination of an address and a port
        (address, port) = server_str.split(':')
        return (address, port)

    except (ValueError, netaddr.AddrFormatError):
        LOG.error(_LE('Invalid server_string: %s'), server_str)
        return ('', '')
def parse_server_string(server_str):
    """Parses the given server_string and returns a tuple of host and port.
    If it's not a combination of host part and port, the port element
    is an empty string. If the input is invalid expression, return a tuple of
    two empty strings.
    """
    try:
        # First of all, exclude pure IPv6 address (w/o port).
        if netaddr.valid_ipv6(server_str):
            return (server_str, '')

        # Next, check if this is IPv6 address with a port number combination.
        if server_str.find("]:") != -1:
            (address, port) = server_str.replace('[', '', 1).split(']:')
            return (address, port)

        # Third, check if this is a combination of an address and a port
        if server_str.find(':') == -1:
            return (server_str, '')

        # This must be a combination of an address and a port
        (address, port) = server_str.split(':')
        return (address, port)

    except (ValueError, netaddr.AddrFormatError):
        LOG.error(_LE('Invalid server_string: %s'), server_str)
        return ('', '')
Beispiel #3
0
 def local_free(self, handle):
     try:
         self._run_and_check_output(kernel32.LocalFree, handle)
     except exceptions.Win32Exception:
         LOG.exception(
             _LE("Could not deallocate memory. "
                 "There could be a memory leak."))
Beispiel #4
0
 def local_free(self, handle):
     try:
         self._run_and_check_output(kernel32.LocalFree, handle)
     except exceptions.Win32Exception:
         LOG.exception(
             _LE("Could not deallocate memory. "
                 "There could be a memory leak."))
Beispiel #5
0
    def get_network_iface_ip(self, network_name):
        networks = [n for n in self._get_network_ifaces_by_name(network_name)
                    if n.DriverDescription == self._HYPERV_VIRT_ADAPTER]

        if not networks:
            LOG.error(_LE('No vswitch was found with name: %s'), network_name)
            return None, None

        ip_addr = self._scimv2.MSFT_NetIPAddress(
            InterfaceIndex=networks[0].InterfaceIndex,
            AddressFamily=self._IPV4_ADDRESS_FAMILY)

        if not ip_addr:
            LOG.error(_LE('No IP Address could be found for network: %s'),
                      network_name)
            return None, None

        return ip_addr[0].IPAddress, ip_addr[0].PrefixLength
Beispiel #6
0
 def run(self):
     try:
         self._copy()
     except IOError as err:
         self._stopped.set()
         # Invalid argument error means that the vm console pipe was closed,
         # probably the vm was stopped. The worker can stop it's execution.
         if err.errno != errno.EINVAL:
             LOG.error(_LE("Error writing vm console log file from " "serial console pipe. Error: %s") % err)
Beispiel #7
0
 def _migrate_vm(self, vm_name, new_host, migration_type):
     vm_group = self._lookup_vm_group_check(vm_name)
     try:
         vm_group.MoveToNewNodeParams(self._IGNORE_LOCKED, new_host,
                                      [migration_type])
     except Exception as e:
         LOG.error(_LE('Exception during cluster live migration of '
                       '%(vm_name)s to %(host)s: %(exception)s'),
                       {'vm_name': vm_name,
                        'host': new_host,
                        'exception': e})
 def run(self):
     try:
         self._copy()
     except IOError as err:
         self._stopped.set()
         # Invalid argument error means that the vm console pipe was closed,
         # probably the vm was stopped. The worker can stop it's execution.
         if err.errno != errno.EINVAL:
             LOG.error(
                 _LE("Error writing vm console log file from "
                     "serial console pipe. Error: %s") % err)
Beispiel #9
0
        def _handle_events(callback):
            if patcher.is_monkey_patched('thread'):
                # Retrieve one by one all the events that occurred in
                # the checked interval.
                #
                # We use eventlet.tpool for retrieving the events in
                # order to avoid issues caused by greenthread/thread
                # communication. Note that PyMI must use the unpatched
                # threading module.
                listen = functools.partial(tpool.execute, listener,
                                           event_timeout)
            else:
                listen = functools.partial(listener, event_timeout)

            while True:
                try:
                    event = listen()

                    vm_name = event.ElementName
                    vm_state = event.EnabledState
                    vm_power_state = self.get_vm_power_state(vm_state)

                    try:
                        callback(vm_name, vm_power_state)
                    except Exception:
                        err_msg = _LE("Executing VM power state change event "
                                      "callback failed. "
                                      "VM name: %(vm_name)s, "
                                      "VM power state: %(vm_power_state)s.")
                        LOG.exception(
                            err_msg,
                            dict(vm_name=vm_name,
                                 vm_power_state=vm_power_state))
                except exceptions.x_wmi_timed_out:
                    pass
                except Exception:
                    LOG.exception(
                        _LE("The VM power state change event listener "
                            "encountered an unexpected exception."))
                    time.sleep(event_timeout / 1000)
Beispiel #10
0
        def _handle_events(callback):
            if patcher.is_monkey_patched('thread'):
                # Retrieve one by one all the events that occurred in
                # the checked interval.
                #
                # We use eventlet.tpool for retrieving the events in
                # order to avoid issues caused by greenthread/thread
                # communication. Note that PyMI must use the unpatched
                # threading module.
                listen = functools.partial(tpool.execute, listener,
                                           event_timeout)
            else:
                listen = functools.partial(listener, event_timeout)

            while True:
                try:
                    event = listen()

                    vm_name = event.ElementName
                    vm_state = event.EnabledState
                    vm_power_state = self.get_vm_power_state(vm_state)

                    try:
                        callback(vm_name, vm_power_state)
                    except Exception:
                        err_msg = _LE("Executing VM power state change event "
                                      "callback failed. "
                                      "VM name: %(vm_name)s, "
                                      "VM power state: %(vm_power_state)s.")
                        LOG.exception(err_msg,
                                      dict(vm_name=vm_name,
                                           vm_power_state=vm_power_state))
                except wmi.x_wmi_timed_out:
                    pass
                except Exception:
                    LOG.exception(
                        _LE("The VM power state change event listener "
                            "encountered an unexpected exception."))
                    time.sleep(event_timeout / 1000)
Beispiel #11
0
 def _migrate_vm(self, vm_name, new_host, migration_type):
     vm_group = self._lookup_vm_group_check(vm_name)
     try:
         vm_group.MoveToNewNodeParams(self._IGNORE_LOCKED, new_host,
                                      [migration_type])
     except Exception as e:
         LOG.error(
             _LE('Exception during cluster live migration of '
                 '%(vm_name)s to %(host)s: %(exception)s'), {
                     'vm_name': vm_name,
                     'host': new_host,
                     'exception': e
                 })
 def _get_conn_v2(self, host='localhost'):
     try:
         return wmi.WMI(moniker='//%s/root/virtualization/v2' % host)
     except wmi.x_wmi as ex:
         LOG.exception(_LE('Get version 2 connection error'))
         if ex.com_error.hresult == -2147217394:
             msg = (_('Live migration is not supported on target host "%s"')
                    % host)
         elif ex.com_error.hresult == -2147023174:
             msg = (_('Target live migration host "%s" is unreachable')
                    % host)
         else:
             msg = _('Live migration failed: %s') % ex.message
         raise exceptions.HyperVException(msg)
Beispiel #13
0
 def _get_conn_v2(self, host='localhost'):
     try:
         return self._get_wmi_obj(self._wmi_namespace % host)
     except exceptions.x_wmi as ex:
         LOG.exception(_LE('Get version 2 connection error'))
         if ex.com_error.hresult == -2147217394:
             msg = (_('Live migration is not supported on target host "%s"')
                    % host)
         elif ex.com_error.hresult == -2147023174:
             msg = (_('Target live migration host "%s" is unreachable')
                    % host)
         else:
             msg = _('Live migration failed: %s') % ex.message
         raise exceptions.HyperVException(msg)
Beispiel #14
0
 def _get_conn_v2(self, host='localhost'):
     try:
         return self._get_wmi_obj(self._wmi_namespace % host)
     except wmi.x_wmi as ex:
         LOG.exception(_LE('Get version 2 connection error'))
         if ex.com_error.hresult == -2147217394:
             msg = (_('Live migration is not supported on target host "%s"')
                    % host)
         elif ex.com_error.hresult == -2147023174:
             msg = (_('Target live migration host "%s" is unreachable')
                    % host)
         else:
             msg = _('Live migration failed: %s') % ex.message
         raise exceptions.HyperVException(msg)
 def listener(callback):
     while True:
         # We avoid setting an infinite timeout in order to let
         # the process gracefully stop. Note that the os-win WMI
         # event listeners are meant to be used as long running
         # daemons, so no stop API is provided ATM.
         try:
             self.monitor_vm_failover(
                 callback,
                 constants.DEFAULT_WMI_EVENT_TIMEOUT_MS)
         except Exception:
             LOG.exception(_LE("The VM cluster group owner change "
                               "event listener encountered an "
                               "unexpected exception."))
             time.sleep(constants.DEFAULT_WMI_EVENT_TIMEOUT_MS / 1000)
    def monitor_vm_failover(self, callback,
                            event_timeout_ms=_WMI_EVENT_TIMEOUT_MS):
        """Creates a monitor to check for new WMI MSCluster_Resource

        events.

        This method will poll the last _WMI_EVENT_CHECK_INTERVAL + 1
        seconds for new events and listens for _WMI_EVENT_TIMEOUT_MS
        miliseconds, since listening is a thread blocking action.

        Any event object caught will then be processed.
        """

        # TODO(lpetrut): mark this method as private once compute-hyperv
        # stops using it. We should also remove the instance '_watcher'
        # attribute since we end up spawning unused event listeners.

        vm_name = None
        new_host = None
        try:
            # wait for new event for _WMI_EVENT_TIMEOUT_MS miliseconds.
            if patcher.is_monkey_patched('thread'):
                wmi_object = tpool.execute(self._watcher,
                                           event_timeout_ms)
            else:
                wmi_object = self._watcher(event_timeout_ms)

            old_host = wmi_object.previous.OwnerNode
            new_host = wmi_object.OwnerNode
            # wmi_object.Name field is of the form:
            # 'Virtual Machine nova-instance-template'
            # wmi_object.Name filed is a key and as such is not affected
            # by locale, so it will always be 'Virtual Machine'
            match = self._instance_name_regex.search(wmi_object.Name)
            if match:
                vm_name = match.group(1)

            if vm_name:
                try:
                    callback(vm_name, old_host, new_host)
                except Exception:
                    LOG.exception(
                        _LE("Exception during failover callback."))
        except exceptions.x_wmi_timed_out:
            pass
Beispiel #17
0
    def monitor_vm_failover(self, callback):
        """Creates a monitor to check for new WMI MSCluster_Resource

        events.

        This method will poll the last _WMI_EVENT_CHECK_INTERVAL + 1
        seconds for new events and listens for _WMI_EVENT_TIMEOUT_MS
        miliseconds, since listening is a thread blocking action.

        Any event object caught will then be processed.
        """

        vm_name = None
        new_host = None
        try:
            # wait for new event for _WMI_EVENT_TIMEOUT_MS miliseconds.
            if patcher.is_monkey_patched('thread'):
                wmi_object = tpool.execute(self._watcher,
                                           self._WMI_EVENT_TIMEOUT_MS)
            else:
                wmi_object = self._watcher(self._WMI_EVENT_TIMEOUT_MS)

            old_host = wmi_object.previous.OwnerNode
            new_host = wmi_object.OwnerNode
            # wmi_object.Name field is of the form:
            # 'Virtual Machine nova-instance-template'
            # wmi_object.Name filed is a key and as such is not affected
            # by locale, so it will always be 'Virtual Machine'
            match = self._instance_name_regex.search(wmi_object.Name)
            if match:
                vm_name = match.group(1)

            if vm_name:
                try:
                    callback(vm_name, old_host, new_host)
                except Exception:
                    LOG.exception(
                        _LE("Exception during failover callback."))
        except exceptions.x_wmi_timed_out:
            pass
Beispiel #18
0
    def ensure_lun_available(self,
                             target_iqn,
                             target_lun,
                             rescan_attempts=_DEFAULT_RESCAN_ATTEMPTS,
                             retry_interval=0,
                             rescan_disks=True):
        # This method should be called only after the iSCSI
        # target has already been logged in.
        for attempt in range(rescan_attempts + 1):
            sessions = self._get_iscsi_target_sessions(target_iqn)
            for session in sessions:
                try:
                    sid = session.SessionId
                    device = self._get_iscsi_device_from_session(
                        sid, target_lun)
                    if not device:
                        continue

                    device_number = device.StorageDeviceNumber.DeviceNumber
                    device_path = device.LegacyName

                    if device_path and device_number not in (None, -1):
                        return device_number, device_path
                except exceptions.ISCSIInitiatorAPIException:
                    err_msg = _LE("Could not find lun %(target_lun)s "
                                  "for iSCSI target %(target_iqn)s.")
                    LOG.exception(
                        err_msg,
                        dict(target_lun=target_lun, target_iqn=target_iqn))
                    continue
            if attempt <= rescan_attempts:
                if retry_interval:
                    time.sleep(retry_interval)
                if rescan_disks:
                    self._diskutils.rescan_disks()

        raise exceptions.ISCSILunNotAvailable(target_lun=target_lun,
                                              target_iqn=target_iqn)
Beispiel #19
0
    def get_disk_capacity(self, path, ignore_errors=False):
        norm_path = os.path.abspath(path)

        total_bytes = ctypes.c_ulonglong(0)
        free_bytes = ctypes.c_ulonglong(0)

        try:
            self._win32_utils.run_and_check_output(
                kernel32.GetDiskFreeSpaceExW,
                ctypes.c_wchar_p(norm_path),
                None,
                ctypes.pointer(total_bytes),
                ctypes.pointer(free_bytes),
                kernel32_lib_func=True)
            return total_bytes.value, free_bytes.value
        except exceptions.Win32Exception as exc:
            LOG.error(
                _LE("Could not get disk %(path)s capacity info. "
                    "Exception: %(exc)s"), dict(path=path, exc=exc))
            if ignore_errors:
                return 0, 0
            else:
                raise exc
Beispiel #20
0
    def monitor_vm_failover(self, callback):
        """Creates a monitor to check for new WMI MSCluster_Resource
        events.

        This method will poll the last _WMI_EVENT_CHECK_INTERVAL + 1
        seconds for new events and listens for _WMI_EVENT_TIMEOUT_MS
        miliseconds, since listening is a thread blocking action.

        Any event object caught will then be processed.
        """
        vm_name = None
        new_host = None
        try:
            # wait for new event for _WMI_EVENT_TIMEOUT_MS miliseconds.
            if patcher.is_monkey_patched('thread'):
                wmi_object = tpool.execute(self._watcher,
                                           self._WMI_EVENT_TIMEOUT_MS)
            else:
                wmi_object = self._watcher(self._WMI_EVENT_TIMEOUT_MS)

            old_host = wmi_object.previous.OwnerNode
            new_host = wmi_object.OwnerNode
            # wmi_object.Name field is of the form:
            # 'Virtual Machine nova-instance-template'
            # wmi_object.Name filed is a key and as such is not affected
            # by locale, so it will always be 'Virtual Machine'
            match = self._instance_name_regex.search(wmi_object.Name)
            if match:
                vm_name = match.group(1)

            if vm_name:
                try:
                    callback(vm_name, old_host, new_host)
                except Exception:
                    LOG.exception(_LE("Exception during failover callback."))
        except wmi.x_wmi_timed_out:
            pass
Beispiel #21
0
    def get_share_capacity_info(self, share_path, ignore_errors=False):
        norm_path = os.path.abspath(share_path)

        total_bytes = ctypes.c_ulonglong(0)
        free_bytes = ctypes.c_ulonglong(0)

        try:
            self._win32_utils.run_and_check_output(
                kernel32.GetDiskFreeSpaceExW,
                ctypes.c_wchar_p(norm_path),
                None,
                ctypes.pointer(total_bytes),
                ctypes.pointer(free_bytes),
                kernel32_lib_func=True)
            return total_bytes.value, free_bytes.value
        except exceptions.Win32Exception as exc:
            LOG.error(_LE("Could not get share %(share_path)s capacity info. "
                          "Exception: %(exc)s"),
                      dict(share_path=share_path,
                           exc=exc))
            if ignore_errors:
                return 0, 0
            else:
                raise exc
Beispiel #22
0
    def ensure_lun_available(self, target_iqn, target_lun,
                             retry_attempts=_DEFAULT_RESCAN_ATTEMPTS,
                             retry_interval=0,
                             rescan_disks=True):
        # This method should be called only after the iSCSI
        # target has already been logged in.
        for attempt in range(retry_attempts + 1):
            sessions = self._get_iscsi_target_sessions(target_iqn)
            for session in sessions:
                try:
                    sid = session.SessionId
                    device = self._get_iscsi_device_from_session(sid,
                                                                 target_lun)
                    if not device:
                        continue

                    device_number = device.StorageDeviceNumber.DeviceNumber
                    device_path = device.LegacyName

                    if device_path and device_number not in (None, -1):
                        return device_number, device_path
                except exceptions.ISCSIInitiatorAPIException:
                    err_msg = _LE("Could not find lun %(target_lun)s "
                                  "for iSCSI target %(target_iqn)s.")
                    LOG.exception(err_msg,
                                  dict(target_lun=target_lun,
                                       target_iqn=target_iqn))
                    continue
            if attempt <= retry_attempts:
                if retry_interval:
                    time.sleep(retry_interval)
                if rescan_disks:
                    self._diskutils.rescan_disks()

        raise exceptions.ISCSILunNotAvailable(target_lun=target_lun,
                                              target_iqn=target_iqn)
Beispiel #23
0
    def set_port_qos_rule(self, port_id, qos_rule):
        """Sets the QoS rule for the given port.

        :param port_id: the port's ID to which the QoS rule will be applied to.
        :param qos_rule: a dictionary containing the following keys:
            min_kbps, max_kbps, max_burst_kbps, max_burst_size_kb.
        :raises exceptions.HyperVInvalidException: if
            - min_kbps is smaller than 10MB.
            - max_kbps is smaller than min_kbps.
            - max_burst_kbps is smaller than max_kbps.
        :raises exceptions.HyperVException: if the QoS rule cannot be set.
        """

        # Hyper-V stores bandwidth limits in bytes.
        min_bps = qos_rule.get("min_kbps", 0) * units.Ki
        max_bps = qos_rule.get("max_kbps", 0) * units.Ki
        max_burst_bps = qos_rule.get("max_burst_kbps", 0) * units.Ki
        max_burst_sz = qos_rule.get("max_burst_size_kb", 0) * units.Ki

        if not (min_bps or max_bps or max_burst_bps or max_burst_sz):
            # no limits need to be set
            return

        if min_bps and min_bps < 10 * units.Mi:
            raise exceptions.InvalidParameterValue(param_name="min_kbps",
                                                   param_value=min_bps)
        if max_bps and max_bps < min_bps:
            raise exceptions.InvalidParameterValue(param_name="max_kbps",
                                                   param_value=max_bps)
        if max_burst_bps and max_burst_bps < max_bps:
            raise exceptions.InvalidParameterValue(param_name="max_burst_kbps",
                                                   param_value=max_burst_bps)

        port_alloc = self._get_switch_port_allocation(port_id)[0]
        bandwidth = self._get_bandwidth_setting_data_from_port_alloc(
            port_alloc)
        if bandwidth:
            # Removing the feature because it cannot be modified
            # due to a wmi exception.
            self._jobutils.remove_virt_feature(bandwidth)

            # remove from cache.
            self._bandwidth_sds.pop(port_alloc.InstanceID, None)

        bandwidth = self._get_default_setting_data(
            self._PORT_BANDWIDTH_SET_DATA)
        bandwidth.Reservation = min_bps
        bandwidth.Limit = max_bps
        bandwidth.BurstLimit = max_burst_bps
        bandwidth.BurstSize = max_burst_sz

        try:
            self._jobutils.add_virt_feature(bandwidth, port_alloc)
        except Exception as ex:
            if '0x80070057' in ex.message:
                raise exceptions.InvalidParameterValue(param_name="qos_rule",
                                                       param_value=qos_rule)
            raise exceptions.HyperVException(
                _LE('Unable to set qos rule %(qos_rule)s for port %(port)s. '
                    'Error: %(error)s') %
                dict(qos_rule=qos_rule, port=port_alloc, error=ex))