def disconnect_switch_port( self, vswitch_name, switch_port_name, delete_port): """Disconnects the switch port.""" switch_svc = self._conn.Msvm_VirtualSwitchManagementService()[0] switch_port_path = self._get_switch_port_path_by_name( switch_port_name) if not switch_port_path: # Port not found. It happens when the VM was already deleted. return (ret_val, ) = switch_svc.DisconnectSwitchPort( SwitchPort=switch_port_path) if ret_val != 0: data = {'switch_port_name': switch_port_name, 'vswitch_name': vswitch_name, 'ret_val': ret_val} raise vmutils.HyperVException( _('Failed to disconnect port %(switch_port_name)s ' 'from switch %(vswitch_name)s ' 'with error %(ret_val)s') % data) if delete_port: (ret_val, ) = switch_svc.DeleteSwitchPort( SwitchPort=switch_port_path) if ret_val != 0: data = {'switch_port_name': switch_port_name, 'vswitch_name': vswitch_name, 'ret_val': ret_val} raise vmutils.HyperVException( _('Failed to delete port %(switch_port_name)s ' 'from switch %(vswitch_name)s ' 'with error %(ret_val)s') % data)
def _get_vnic_settings(self, vnic_name): vnic_settings = self._conn.Msvm_SyntheticEthernetPortSettingData( ElementName=vnic_name) vnic_settings += self._conn.Msvm_EmulatedEthernetPortSettingData( ElementName=vnic_name) if not vnic_settings: raise vmutils.HyperVException(_('Vnic not found: %s') % vnic_name) if len(vnic_settings) > 1: raise vmutils.HyperVException(_('Multiple vnics found with name: ' '%s') % vnic_name) return vnic_settings[0]
def create_default_reject_all_rules(self, switch_port_name): port, found = self._get_switch_port_allocation(switch_port_name, False) if not found: raise vmutils.HyperVException( _('Port Allocation not found: %s') % switch_port_name) acls = port.associators(wmi_result_class=self._PORT_EXT_ACL_SET_DATA) filtered_acls = [v for v in acls if v.Action == self._ACL_ACTION_DENY] if len(filtered_acls) >= self._REJECT_ACLS_COUNT: return for acl in filtered_acls: self._remove_virt_feature(acl) weight = 0 ipv4_pair = (self._ACL_TYPE_IPV4, self._IPV4_ANY) ipv6_pair = (self._ACL_TYPE_IPV6, self._IPV6_ANY) for direction in [self._ACL_DIR_IN, self._ACL_DIR_OUT]: for acl_type, address in [ipv4_pair, ipv6_pair]: for protocol in [self._TCP_PROTOCOL, self._UDP_PROTOCOL, self._ICMP_PROTOCOL]: self._bind_security_rule( port, direction, acl_type, self._ACL_ACTION_DENY, self._ACL_DEFAULT, protocol, address, weight) weight += 1
def _get_vswitch(self, vswitch_name): vswitch = self._conn.Msvm_VirtualEthernetSwitch( ElementName=vswitch_name) if not len(vswitch): raise vmutils.HyperVException(_('VSwitch not found: %s') % vswitch_name) return vswitch[0]
def create_dynamic_vhd(self, path, max_internal_size, format): vhd_format = self._vhd_format_map.get(format) if not vhd_format: raise vmutils.HyperVException(_("Unsupported disk format: %s") % format) self._create_vhd(self._VHD_TYPE_DYNAMIC, vhd_format, path, max_internal_size=max_internal_size)
def _check_job_status(self, ret_val, jobpath): """Poll WMI job state for completion.""" if not ret_val: return elif ret_val not in [WMI_JOB_STATE_STARTED, WMI_JOB_STATE_RUNNING]: raise vmutils.HyperVException(_('Job failed with error %d') % ret_val) job_wmi_path = jobpath.replace('\\', '/') job = wmi.WMI(moniker=job_wmi_path) while job.JobState == WMI_JOB_STATE_RUNNING: time.sleep(0.1) job = wmi.WMI(moniker=job_wmi_path) if job.JobState != WMI_JOB_STATE_COMPLETED: job_state = job.JobState if job.path().Class == "Msvm_ConcreteJob": err_sum_desc = job.ErrorSummaryDescription err_desc = job.ErrorDescription err_code = job.ErrorCode data = {'job_state': job_state, 'err_sum_desc': err_sum_desc, 'err_desc': err_desc, 'err_code': err_code} raise vmutils.HyperVException( _("WMI job failed with status %(job_state)d. " "Error details: %(err_sum_desc)s - %(err_desc)s - " "Error code: %(err_code)d") % data) else: (error, ret_val) = job.GetError() if not ret_val and error: data = {'job_state': job_state, 'error': error} raise vmutils.HyperVException( _("WMI job failed with status %(job_state)d. " "Error details: %(error)s") % data) else: raise vmutils.HyperVException( _("WMI job failed with status %d. " "No error description available") % job_state) desc = job.Description elap = job.ElapsedTime LOG.debug(_("WMI job succeeded: %(desc)s, Elapsed=%(elap)s"), {'desc': desc, 'elap': elap})
def create_differencing_vhd(self, path, parent_path, size=None): if size is not None: raise vmutils.HyperVException( _('VHD differencing disks cannot be ' 'resized')) image_man_svc = self._conn.Msvm_ImageManagementService()[0] (job_path, ret_val) = image_man_svc.CreateDifferencingVirtualHardDisk( Path=path, ParentPath=parent_path) self._vmutils.check_ret_val(ret_val, job_path)
def create_dynamic_vhd(self, path, max_internal_size, format): if format != constants.DISK_FORMAT_VHD: raise vmutils.HyperVException( _("Unsupported disk format: %s") % format) image_man_svc = self._conn.Msvm_ImageManagementService()[0] (job_path, ret_val) = image_man_svc.CreateDynamicVirtualHardDisk( Path=path, MaxInternalSize=max_internal_size) self._vmutils.check_ret_val(ret_val, job_path)
def _get_vhd_dynamic_blk_size(self, vhd_path): blk_size_offset = VHD_BLK_SIZE_OFFSET try: with open(vhd_path, "rb") as f: f.seek(blk_size_offset) version = f.read(4) except IOError: raise vmutils.HyperVException( _("Unable to obtain block size from" " VHD %(vhd_path)s") % {"vhd_path": vhd_path}) return struct.unpack('>i', version)[0]
def _create_switch_port(self, vswitch_name, switch_port_name): """Creates a switch port.""" switch_svc = self._conn.Msvm_VirtualSwitchManagementService()[0] vswitch_path = self._get_vswitch(vswitch_name).path_() (new_port, ret_val) = switch_svc.CreateSwitchPort( Name=switch_port_name, FriendlyName=switch_port_name, ScopeOfResidence="", VirtualSwitch=vswitch_path) if ret_val != 0: raise vmutils.HyperVException( _('Failed creating port for %s') % vswitch_name) return new_port
def _is_port_vm_started(self, port): vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0] vmsettings = port.associators( wmi_result_class=self._VIRTUAL_SYSTEM_SETTING_DATA) # See http://msdn.microsoft.com/en-us/library/cc160706%28VS.85%29.aspx (ret_val, summary_info) = vs_man_svc.GetSummaryInformation( [self._VM_SUMMARY_ENABLED_STATE], [v.path_() for v in vmsettings]) if ret_val or not summary_info: raise vmutils.HyperVException(_('Cannot get VM summary data ' 'for: %s') % port.ElementName) return summary_info[0].EnabledState is self._HYPERV_VM_STATE_ENABLED
def get_internal_vhd_size_by_file_size(self, vhd_path, new_vhd_file_size): """VHDX Size = Header (1 MB) + Log + Metadata Region + BAT + Payload Blocks Chunk size = maximum number of bytes described by a SB block = 2 ** 23 * LogicalSectorSize """ vhd_format = self.get_vhd_format(vhd_path) if vhd_format == constants.DISK_FORMAT_VHD: return super(VHDUtilsV2, self).get_internal_vhd_size_by_file_size( vhd_path, new_vhd_file_size) else: vhd_info = self.get_vhd_info(vhd_path) vhd_type = vhd_info['Type'] if vhd_type == self._VHD_TYPE_DIFFERENCING: vhd_parent = self.get_vhd_parent_path(vhd_path) return self.get_internal_vhd_size_by_file_size( vhd_parent, new_vhd_file_size) else: try: with open(vhd_path, 'rb') as f: hs = VHDX_HEADER_SECTION_SIZE bes = VHDX_BAT_ENTRY_SIZE lss = vhd_info['LogicalSectorSize'] bs = self._get_vhdx_block_size(f) ls = self._get_vhdx_log_size(f) ms = self._get_vhdx_metadata_size_and_offset(f)[0] chunk_ratio = (1 << 23) * lss / bs size = new_vhd_file_size max_internal_size = ( bs * chunk_ratio * (size - hs - ls - ms - bes - bes / chunk_ratio) / (bs * chunk_ratio + bes * chunk_ratio + bes)) return max_internal_size - (max_internal_size % bs) except IOError as ex: raise vmutils.HyperVException( _("Unable to obtain " "internal size from VHDX: " "%(vhd_path)s. Exception: " "%(ex)s") % { "vhd_path": vhd_path, "ex": ex })
def set_host_nic_ip_address(self, nic_name, dhcp=False, ip_list=None, netmask_list=None, gateway_list=None, gateway_metrics_list=None): net_adapter_list = self._conn_cimv2.Win32_NetworkAdapter( NetConnectionID=nic_name) if not net_adapter_list: raise vmutils.HyperVException(_('Nic not found: %s') % nic_name) net_adapter = net_adapter_list[0] net_adapter_config = net_adapter.associators( wmi_result_class='Win32_NetworkAdapterConfiguration')[0] if dhcp: (ret_val,) = net_adapter_config.EnableDHCP() if ret_val not in [0, 1]: raise vmutils.HyperVException( _('Enabling DHCP failed with error: %s') % ret_val) else: (ret_val,) = net_adapter_config.EnableStatic( IPAddress=ip_list, SubnetMask=netmask_list) if ret_val not in [0, 1]: raise vmutils.HyperVException( _('Setting static IP addresses %(ip_list)s with netmasks ' '%(netmask_list)s on interface %(nic_name)s failed with ' 'error: %(ret_val)s') % {'ip_list': ip_list, 'nic_name': nic_name, 'netmask_list': netmask_list, 'ret_val': ret_val}) if gateway_list: (ret_val,) = net_adapter_config.EnableGateways( DefaultIPGateway=gateway_list, GatewayCostMetric=netmask_list) if ret_val not in [0, 1]: raise vmutils.HyperVException( _('Setting a gateway failed with error: %s') % ret_val)
def create_vswitch(self, vswitch_name, external_port_name=None, create_internal_port=False): LOG.debug('create_vswitch called. vswitch_name: %(vswitch_name)s, ' 'external_port_name: %(external_port_name)s, ' 'create_internal_port: %(create_internal_port)s' % locals()) svc = self._conn.Msvm_VirtualEthernetSwitchManagementService()[0] vswitch_data = self._conn.Msvm_VirtualEthernetSwitchSettingData.new() vswitch_data.ElementName = vswitch_name resource_settings = [] if external_port_name: ext_port_list = self._conn.Msvm_ExternalEthernetPort( ElementName=external_port_name) if not ext_port_list: ext_port_list = self._conn.Msvm_WiFiPort( ElementName=external_port_name) if not ext_port_list: raise vmutils.HyperVException(_('External port not found: ' '%s') % external_port_name) ext_port = ext_port_list[0] port_alloc_ext = self._get_default_setting_data( self._PORT_ALLOC_SET_DATA, self._ETH_CONN_RES_SUB_TYPE) port_alloc_ext.HostResource = [ext_port.path_()] port_alloc_ext.ElementName = vswitch_name resource_settings.append(port_alloc_ext.GetText_(1)) if create_internal_port: port_alloc_int = self._get_default_setting_data( self._PORT_ALLOC_SET_DATA, self._ETH_CONN_RES_SUB_TYPE) host = self._conn.query("SELECT * from Msvm_ComputerSystem " "WHERE InstallDate is NULL")[0] port_alloc_int.HostResource = [host.path_()] port_alloc_int.ElementName = vswitch_name if external_port_name: port_alloc_int.Address = ext_port.PermanentAddress resource_settings.append(port_alloc_int.GetText_(1)) (job_path, out_res_system, ret_val) = svc.DefineSystem( SystemSettings=vswitch_data.GetText_(1), ResourceSettings=resource_settings) self._check_job_status(ret_val, job_path)
def get_vhd_format(self, path): with open(path, 'rb') as f: # Read header if f.read(8) == VHDX_SIGNATURE: return constants.DISK_FORMAT_VHDX # Read footer f.seek(0, 2) file_size = f.tell() if file_size >= 512: f.seek(-512, 2) if f.read(8) == VHD_SIGNATURE: return constants.DISK_FORMAT_VHD raise vmutils.HyperVException(_('Unsupported virtual disk format'))
def _get_switch_port_allocation_check(self, switch_port_name): port_alloc, found = self._get_switch_port_allocation(switch_port_name) if not found: raise vmutils.HyperVException( _('Port allocation not found: %s') % switch_port_name) return port_alloc