def test_incremental_partial_ip(self): '''IPAddress.incremental_check() parses a partial IPAddress properly''' segments = IPAddress.incremental_check("1.2.3") self.assertEquals([1, 2, 3], segments) segments = IPAddress.incremental_check("1") self.assertEquals([1], segments)
def validate_ip(ip_address): '''Wrap a call to IPAddress.convert_address and raise a UIMessage with appropriate message text ''' if not ip_address: return try: IPAddress.convert_address(ip_address) except ValueError as err: if err[0] == IPAddress.MSG_NO_LEADING_ZEROS: raise UIMessage(NameService.MSG_NO_LEADING_ZEROS) raise UIMessage(NameService.MSG_IP_FMT)
def incremental_validate_ip(edit_field): """ Incrementally validate the IP Address as the user enters it """ ip_address = edit_field.get_text() if not ip_address: return True try: IPAddress.incremental_check(ip_address) except ValueError as err: raise UIMessage(str(err)) return True
def incremental_validate_ip(edit_field): '''Incrementally validate the IP Address as the user enters it''' ip_address = edit_field.get_text() if not ip_address: return True try: IPAddress.incremental_check(ip_address) except ValueError as err: if err[0] == IPAddress.MSG_NO_LEADING_ZEROS: raise UIMessage(NICConfigure.MSG_NO_LEADING_ZEROS % edit_field.data_obj) raise UIMessage(_("%s must be of the form xxx.xxx.xxx.xxx") % edit_field.data_obj) return True
def incremental_validate_ip(edit_field): '''Incrementally validate the IP Address as the user enters it''' ip_address = edit_field.get_text() if not ip_address: return True try: IPAddress.incremental_check(ip_address) except ValueError as err: if err[0] == IPAddress.MSG_NO_LEADING_ZEROS: raise UIMessage(NICConfigure.MSG_NO_LEADING_ZEROS % edit_field.data_obj) raise UIMessage( _("%s must be of the form xxx.xxx.xxx.xxx") % edit_field.data_obj) return True
def incremental_validate_ip(edit_field): '''Incrementally validate the IP Address as the user enters it Arg: edit_field - EditField object for validation Raises: UIMessage on failure ''' ip_address = edit_field.get_text() if not ip_address: return True try: IPAddress.incremental_check(ip_address) except ValueError as err: if err[0] == IPAddress.MSG_NO_LEADING_ZEROS: raise UIMessage(NameService.MSG_NO_LEADING_ZEROS) raise UIMessage(NameService.MSG_IP_FMT) return True
def test_incremental_ip_too_long(self): '''IPAddress.incremental_check() rejects a too-long IP''' try: segments = IPAddress.incremental_check("1.2.3.4.5") except ValueError as err: # Not using 'assertRaises' as we need to examine the ValueError self.assertEquals("Too many octets", err.args[0])
def test_incremental_segment_leading_zeros(self): '''IPAddress.incremental_check() for leading zeros''' try: segments = IPAddress.incremental_check("1.2.3.055") except ValueError as err: # Not using 'assertRaises' as we need to examine the ValueError self.assertEquals(IPAddress.MSG_NO_LEADING_ZEROS, err.args[0])
def dhcp_autodiscovery_toggled(self, widget, user_data=None): ''' Signal handler for "toggled" event in self._discovery_dhcp_radio widget. ''' if widget.get_active(): if self._dhcp_ip is not None: try: segments = IPAddress.convert_address(self._dhcp_ip) except ValueError as error: title = INVALID_IP_MSG msg = self._dhcp_ip + ' : ' + str(error) LOGGER.error(title) LOGGER.error(msg) modal_dialog(title, msg) else: self._discovery_target_ip_1_entry.set_text(str( segments[0])) self._discovery_target_ip_2_entry.set_text(str( segments[1])) self._discovery_target_ip_3_entry.set_text(str( segments[2])) self._discovery_target_ip_4_entry.set_text(str( segments[3])) if self._dhcp_port is not None: self._discovery_port_entry.set_text(str(self._dhcp_port)) if self._dhcp_lun is not None: self._discovery_lun_entry.set_text(str(self._dhcp_lun)) if self._dhcp_target is not None: self._discovery_target_name_entry.set_text( str(self._dhcp_target)) # Gray out the criteria fields self._discovery_criteria_detail_table.set_sensitive(False)
def test_incremental_segment_too_big(self): '''IPAddress.incremental_check() rejects values >255''' try: segments = IPAddress.incremental_check("1.2.3.455") except ValueError as err: # Not using 'assertRaises' as we need to examine the ValueError self.assertEquals("Values should be between 0 and 255", err.args[0])
def validate_ip(edit_field): '''Wrap a call to IPAddress.check_address and raise a UIMessage with appropriate message text ''' ip_address = edit_field.get_text() if not ip_address: return True try: IPAddress.convert_address(ip_address) except ValueError as err: if err[0] == IPAddress.MSG_NO_LEADING_ZEROS: raise UIMessage(NICConfigure.MSG_NO_LEADING_ZEROS % edit_field.data_obj) raise UIMessage( _("%s must be of the form xxx.xxx.xxx.xxx") % edit_field.data_obj) return True
def test_incremental_segment_too_small(self): '''IPAddress.incremental_check() rejects negative segments''' try: segments = IPAddress.incremental_check("1.-2.3.4") except ValueError as err: # Not using 'assertRaises' as we need to examine the ValueError self.assertEquals("Only numbers and '.' (period) are allowed", err.args[0])
def validate_ip(edit_field): '''Wrap a call to IPAddress.check_address and raise a UIMessage with appropriate message text ''' ip_address = edit_field.get_text() if not ip_address: return True try: IPAddress.convert_address(ip_address) except ValueError as err: if err[0] == IPAddress.MSG_NO_LEADING_ZEROS: raise UIMessage(NICConfigure.MSG_NO_LEADING_ZEROS % edit_field.data_obj) raise UIMessage(_("%s must be of the form xxx.xxx.xxx.xxx") % edit_field.data_obj) return True
def validate(self): '''Verify the syntactical validity of the IP Address fields''' ip_fields = [self.ip_field, self.netmask_field, self.gateway_field] for field in ip_fields: validate_ip(field) if not self.ip_field.get_text(): raise UIMessage(_("IP Address must not be empty")) if not self.netmask_field.get_text(): raise UIMessage(_("Netmask must not be empty")) else: try: netmask = self.netmask_field.get_text() IPAddress.convert_address(netmask, check_netmask=True) except ValueError as err: if err[0] == IPAddress.MSG_NO_LEADING_ZEROS: raise UIMessage(NICConfigure.MSG_NO_LEADING_ZEROS % self.netmask_field.data_obj) raise UIMessage(_("'%s' is not a valid netmask") % netmask)
def to_xml(self): data_objects = [] net_physical = SMFConfig("network/physical") data_objects.append(net_physical) net_default = SMFInstance("default", enabled=True) net_physical.insert_children(net_default) netcfg_prop = SMFPropertyGroup("netcfg") net_default.insert_children(netcfg_prop) if self.type == NetworkInfo.AUTOMATIC: netcfg_prop.setprop(name="active_ncp", ptype="astring", value="Automatic") elif self.type == NetworkInfo.MANUAL: netcfg_prop.setprop(name="active_ncp", ptype="astring", value="DefaultFixed") net_install = SMFConfig('network/install') data_objects.append(net_install) net_install_default = SMFInstance("default", enabled=True) net_install.insert_children([net_install_default]) ipv4 = SMFPropertyGroup('install_ipv4_interface') ipv6 = SMFPropertyGroup('install_ipv6_interface') net_install_default.insert_children([ipv4, ipv6]) static_address = IPAddress(self.ip_address, netmask=self.netmask) nic_name = self.get_nic_name(self.nic_iface) # IPv4 configuration ipv4.add_props(static_address=static_address, name='%s/v4' % nic_name, address_type='static') # # IPv4 default route is optional. If it was not configured # on Network screen, do not populate related smf property. # if self.gateway: ipv4.add_props(default_route=self.gateway) # IPv6 configuration ipv6.add_props(name='%s/v6' % nic_name, address_type='addrconf', stateless='yes', stateful='yes') return [do.get_xml_tree() for do in data_objects]
def find_netmask(self): '''Try to determine the netmask info of the NIC if DHCP is running Returns True if this action was successful ''' netmask = self._run_dhcpinfo("Subnet") if netmask: self.netmask = IPAddress(netmask) return True else: return False
def validate_host_or_ip(host_name): '''Validate argument as either a valid hostname or IP address Raises: UIMessage if not valid ''' if not host_name: return # assume host name if input starts with alpha character if host_name[0].isalpha(): for chr in host_name: if not chr.isalnum() and not chr in u"-.": raise UIMessage(_("A host name can only contain letters, " "numbers, periods, and minus signs (-).")) return # attempt validation as a numeric IP address try: IPAddress.convert_address(host_name) except ValueError as err: if err[0] == IPAddress.MSG_NO_LEADING_ZEROS: raise UIMessage(NameService.MSG_NO_LEADING_ZEROS) raise UIMessage(NameService.MSG_HOST_NAME)
def incremental_validate_host(edit_field): '''Incrementally validate the host as the user enters it Arg: edit_field - EditField object for validation Raises: UIMessage on failure ''' host_name = edit_field.get_text() if not host_name: return True # assume host name if input starts with alpha character if host_name[0].isalpha(): for chr in host_name: if not chr.isalnum() and not chr in u"-.": raise UIMessage(_("A host name can only contain letters, " "numbers, periods, and minus signs (-).")) return True # attempt validation as a numeric IP address try: IPAddress.incremental_check(host_name) except ValueError as err: if err[0] == IPAddress.MSG_NO_LEADING_ZEROS: raise UIMessage(NameService.MSG_NO_LEADING_ZEROS) raise UIMessage(NameService.MSG_HOST_NAME) return True
def determine_proptype(propval, iproptype, is_list=False): '''Determine the SMF property type for propval One of: astring, host, net_address, net_address_v4, or count iproptype distinguishes between possible IP address types If propval is a list of properties, return the list equivalent (e.g., "astring_list" instead of "astring") ''' if is_list: if propval: propval = propval[0] else: # Empty list return "astring_list" if propval is None: proptype = "astring" elif isinstance(propval, IPAddress): if iproptype == "host" or iproptype == "net_address": proptype = iproptype else: proptype = "net_address_v4" else: try: IPAddress(propval) if iproptype == "host" or iproptype == "net_address": proptype = iproptype else: proptype = "net_address_v4" except: try: int(propval) proptype = "count" except: if iproptype == "host": proptype = iproptype else: proptype = "astring" if is_list: proptype += "_list" return proptype
def test_get_address_w_netmask(self): '''IPAddress.address property with address and netmask set returns correctly''' ip = IPAddress("1.2.3.4", netmask="255.255.255.0") self.assertEquals("1.2.3.4/24", ip.address)
def test_get_address_none_w_netmask(self): '''IPAddress.address property with no address and netmask returns 0.0.0.0/24''' ip = IPAddress(netmask="255.255.255.0") self.assertEquals("0.0.0.0/24", ip.address)
def test_get_address(self): '''IPAddress.address property with address set returns address''' ip = IPAddress("1.2.3.4") self.assertEquals("1.2.3.4", ip.address)
def test_netmask_prefix(self): '''IPAddress.netmask_prefix() returns correct values''' for mask in NETMASKS: ip = IPAddress(netmask=mask[1]) self.assertEquals(mask[0], ip.netmask_prefix())
def test_get_address_none(self): '''IPAddress.address property with no address set returns default''' ip = IPAddress() self.assertEquals("0.0.0.0", ip.address)
def test_incremental_blank(self): '''IPaddress.incremental_check() parses a blank string properly''' segments = IPAddress.incremental_check("") self.assertEquals([], segments)
def test_incremental_full_ip(self): '''IPAddress.incremental_check() parses a full IPAddress properly''' segments = IPAddress.incremental_check("1.2.3.4") self.assertEquals([1, 2, 3, 4], segments)
def test_convert_address(self): '''IPAddress.convert_address() returns correct segments''' segments = IPAddress.convert_address("1.0.128.255") self.assertEquals([1, 0, 128, 255], segments)
def validate(self): ''' Validate the user selections before proceeding. Raises: NotOkToProceedError ''' LOGGER.info("Starting Disk Discovery validation.") iscsi = None doc = InstallEngine.get_instance().doc # error #1 - at least one disk type must be checked if not self._discovery_local_check.get_active() and \ not self._discovery_iscsi_check.get_active(): msg = "No disk types selected." LOGGER.error(NO_DISK_TYPE_SELECTED_MSG) modal_dialog(NO_DISK_TYPE_SELECTED_MSG, SELECT_DISK_TYPE_MSG) raise NotOkToProceedError(msg) if self._discovery_iscsi_check.get_active(): # Save the on-screen iSCSI criteria values self._target_ip = '' text = self._discovery_target_ip_1_entry.get_text() if len(text): self._target_ip += text self._target_ip += '.' text = self._discovery_target_ip_2_entry.get_text() if len(text): self._target_ip += text self._target_ip += '.' text = self._discovery_target_ip_3_entry.get_text() if len(text): self._target_ip += text self._target_ip += '.' text = self._discovery_target_ip_4_entry.get_text() if len(text): self._target_ip += text text = self._discovery_lun_entry.get_text() if len(text): self._target_lun = text else: self._target_lun = None text = self._discovery_target_name_entry.get_text() if len(text): self._target_name = text else: self._target_name = None text = self._discovery_port_entry.get_text() if len(text): self._target_port = text else: self._target_port = None text = self._discovery_initiator_name_entry.get_text() if len(text): self._initiator_name = text else: self._initiator_name = None if self._discovery_chap_check.get_active(): text = self._discovery_chap_name_entry.get_text() if len(text): self._chap_name = text else: self._chap_name = None text = self._discovery_chap_pass_entry.get_text() if len(text): self._chap_password = text else: self._chap_password = None else: self._chap_name = None self._chap_password = None LOGGER.info("iSCSI criteria") LOGGER.info("==============") LOGGER.info("Target IP: %s", self._target_ip) LOGGER.info("LUN: %s", self._target_lun) LOGGER.info("Target Name: %s", self._target_name) LOGGER.info("Port: %s", self._target_port) LOGGER.info("Initiator Name: %s", self._initiator_name) LOGGER.info("CHAP Name: %s", self._chap_name) if self._chap_password is not None: log_pw = '*' * len(self._chap_password) else: log_pw = None LOGGER.info("CHAP Password: %s", log_pw) # ERROR - required fields must be entered required_fields = { self._discovery_target_ip_1_entry: TARGET_IP_1_FIELD, self._discovery_target_ip_2_entry: TARGET_IP_2_FIELD, self._discovery_target_ip_3_entry: TARGET_IP_3_FIELD, self._discovery_target_ip_4_entry: TARGET_IP_4_FIELD, } # self._discovery_lun_entry: TARGET_LUN_FIELD, for field in required_fields: if not field.get_text(): msg = REQUIRED_FIELD_MISSING_MSG LOGGER.error(msg + " : " + required_fields[field]) modal_dialog( msg, ENTER_REQUIRED_FIELD_MSG + required_fields[field]) field.grab_focus() raise NotOkToProceedError(msg) # ERROR - IP must be proper IP address try: IPAddress.convert_address(self._target_ip) except ValueError as error: msg = INVALID_IP_MSG LOGGER.error(msg + " : " + str(error)) modal_dialog(msg, str(error)) self._discovery_target_ip_1_entry.grab_focus() raise NotOkToProceedError(msg) # ERROR - Initiator Name must match regular expression if self._initiator_name is not None: if IQN_RE.match(self._initiator_name) is None: msg = INVALID_INITIATOR_IQN_MSG LOGGER.error(msg) modal_dialog(msg, ENTER_VALID_VALUE_MSG) self._discovery_initiator_name_entry.grab_focus() raise NotOkToProceedError(msg) # ERROR - Target name name must match regular expression if self._target_name is not None: if IQN_RE.match(self._target_name) is None: msg = INVALID_TARGET_IQN_MSG LOGGER.error(msg) modal_dialog(msg, ENTER_VALID_VALUE_MSG) self._discovery_target_name_entry.grab_focus() raise NotOkToProceedError(msg) # ERROR - if CHAP name is given, password must also # be given, and vice versa if self._chap_name and not self._chap_password: msg = CHAP_PASSWORD_MISSING LOGGER.error(msg) modal_dialog(msg, ENTER_VALID_VALUE_MSG) self._discovery_chap_pass_entry.grab_focus() raise NotOkToProceedError(msg) if self._chap_password and not self._chap_name: msg = CHAP_USERNAME_MISSING LOGGER.error(msg) modal_dialog(msg, ENTER_VALID_VALUE_MSG) self._discovery_chap_name_entry.grab_focus() raise NotOkToProceedError(msg) # ERROR - CHAP password must be correct length if self._chap_password is not None: if not 12 <= len(self._chap_password) <= 16: msg = CHAP_PASSWORD_INVALID_LENGTH LOGGER.error(msg) modal_dialog(msg, ENTER_VALID_VALUE_MSG) self._discovery_chap_pass_entry.grab_focus() raise NotOkToProceedError(msg) # ERROR - must be able to connect to LUN to verify iSCSI disk # teardown any currently-configured Iscsis before trying # to connect to new LUN old_iscsis = doc.volatile.get_children(name=ISCSI_LABEL, class_type=Iscsi) for old_iscsi in old_iscsis: try: LOGGER.debug("teardown previous iSCSI: %s", old_iscsi) old_iscsi.teardown() except CalledProcessError as error: # Not a fatal error LOGGER.warn("Iscsi.teardown failed: " + str(error)) # remove from 'discovered targets' any Disks associated with # this iSCSI target if old_iscsi.ctd_list: discovered = doc.persistent.get_first_child( name=Target.DISCOVERED) for disk in discovered.get_descendants(class_type=Disk): if disk.ctd in old_iscsi.ctd_list: disk.delete() iscsi = Iscsi(ISCSI_LABEL) iscsi.target_ip = self._target_ip iscsi.target_lun = self._target_lun iscsi.target_name = self._target_name iscsi.target_port = self._target_port # Don't attempt to change the initiator node name if iSCSI booting if not is_iscsiboot(): iscsi.initiator_name = self._initiator_name iscsi.chap_name = self._chap_name iscsi.chap_password = self._chap_password # Depending on validity and location of IP, Iscsi.setup_iscsi() # can take a while, so show a status message and run setup_iscsi() # in a separate thread (otherwise the GUI would appear # unresponsive and the user may think it has hung). self.set_back_next(back_sensitive=False, next_sensitive=False) if iscsi.target_lun is not None: self._discovery_status_label.set_markup( '<span font_desc="Bold">%s</span>' % MAPPING_LUN_MSG) else: self._discovery_status_label.set_markup( '<span font_desc="Bold">%s</span>' % MAPPING_TARGET_MSG) self._discovery_status_label.show() thread = SetupIscsiThread(iscsi) # Keep passing control back to Gtk+ to process its event queue # until SetupIscsiThread has completed. while thread.is_alive(): while gtk.events_pending(): gtk.main_iteration(False) # allow the thread some time to do it's work time.sleep(0.1) self._discovery_status_label.hide() self.set_back_next(back_sensitive=True, next_sensitive=True) if thread.error is not None: msg = CANNOT_MAP_LUN_MSG LOGGER.error(msg) LOGGER.error(str(thread.error)) modal_dialog(msg, str(thread.error)) self._discovery_target_ip_1_entry.grab_focus() raise NotOkToProceedError(msg) # Validation is complete. Now: # - save user choices (Local disks, iSCSI) in user profile # if iSCSI option was checked: # - save Iscsi obj in DOC # - run TargetDiscovery(iSCSI), either right now or when # other TDs are finished profile = doc.volatile.get_first_child(name="GUI Install", class_type=InstallProfile) if profile is None: raise RuntimeError("INTERNAL ERROR: Unable to retrieve " "InstallProfile from DataObjectCache") profile.set_disk_selections( show_local=self._discovery_local_check.get_active(), show_iscsi=self._discovery_iscsi_check.get_active()) if self._discovery_iscsi_check.get_active(): # There should only be one Iscsi obj in DOC at a time for old_iscsi in old_iscsis: LOGGER.debug("Removing old Iscsi object from DOC: %s", old_iscsi) old_iscsi.delete() doc.volatile.insert_children(iscsi) # If other TargetDiscoveries (eg local disk) have already # completed, then run TD(iSCSI) now, otherwise queue it to # run later if is_discovery_complete(): LOGGER.debug("Starting TargetDiscovery(iSCSI) directly") start_td_iscsi() else: LOGGER.debug("Queueing TargetDiscovery(iSCSI) to run later") queue_td_iscsi() # Every time we progress from this screen, set a flag to tell # the Disk Screen that it must re-process the TD results set_td_results_state(False)
def test_as_binary_string(self): '''IPAddress.as_binary_string() returns a proper binary string''' binary = IPAddress.as_binary_string(range(255)) self.assertTrue("1" in binary) self.assertTrue("0" in binary) self.assertFalse(binary.strip("10"))
def validate(self): """ validate the iSCSI attributes before continuing to disk selection. """ target_ip = self.target_ip_edit.get_text() target_lun = self.target_lun_edit.get_text() target_port = self.target_port_edit.get_text() target_name = self.target_name_edit.get_text() if not self.is_iscsiboot: initiator_name = self.initiator_name_edit.get_text() chap_name = self.chap_name_edit.get_text() chap_password = self.chap_password_edit.get_text() # validate the target IP if not target_ip: raise UIMessage(IscsiScreen.MISSING_TARGET_IP) else: try: IPAddress.convert_address(target_ip) except ValueError as error: raise UIMessage("%s: %s" % \ (IscsiScreen.INVALID_TARGET_IP, str(error))) # validate the IQN strings (by default re.match only matches at the # beginning of a string) if not self.is_iscsiboot and initiator_name: if IQN_RE.match(initiator_name) is None: raise UIMessage(IscsiScreen.INVALID_INITIATOR_IQN) if target_name: if IQN_RE.match(target_name) is None: raise UIMessage(IscsiScreen.INVALID_TARGET_IQN) # validate that both CHAP username and password were specified (or not # at all) if chap_name and not chap_password: raise UIMessage(IscsiScreen.CHAP_PASSWORD_MISSING) if chap_password and not chap_name: raise UIMessage(IscsiScreen.CHAP_USERNAME_MISSING) # validate the CHAP password if chap_password: if not 12 <= len(chap_password) <= 16: raise UIMessage(IscsiScreen.CHAP_PASSWORD_TOO_SHORT) # Update the Iscsi DOC object self.iscsi_obj.target_ip = target_ip # force target_lun back to None if the user comes back and removes the # LUN entry from the screen if target_lun: self.iscsi_obj.target_lun = target_lun else: self.iscsi_obj.target_lun = None if target_name: self.iscsi_obj.target_name = target_name if target_port: self.iscsi_obj.target_port = target_port if not self.is_iscsiboot and initiator_name: self.iscsi_obj.initiator_name = initiator_name if chap_name: self.iscsi_obj.chap_name = chap_name if chap_password: self.iscsi_obj.chap_password = chap_password # attempt to connect to the LUN if target_lun: self.main_win.error_line.display_err(IscsiScreen.MAPPING_LUN_LABEL) else: self.main_win.error_line.display_err( IscsiScreen.MAPPING_TARGET_LABEL) try: self.iscsi_obj.setup_iscsi() LOGGER.debug("Iscsi object: %s" % str(self.iscsi_obj)) except (CalledProcessError, RuntimeError) as err: # remove the iSCSI configuration since it's invalid try: self.iscsi_obj.teardown() except CalledProcessError: # ignore any errors pass raise UIMessage("%s %s" % (IscsiScreen.UNABLE_TO_MAP, str(err)))
def test_convert_good_netmask(self): '''IPAddress.convert_address() succeeds when checking netmask''' segments = IPAddress.convert_address("255.0.0.0", check_netmask=True) self.assertEquals([255, 0, 0, 0], segments)