def get(self, *oids): """ Get/Bulk get operation for scalars. :param oids: list of oids to get. oid can be full dotted OID or (MIB, OID name, [index]). For example, the OID to get sysContact can by any of the following: ('SNMPv2-MIB', 'sysContact', 0) ('SNMPv2-MIB', 'sysContact') '1.3.6.1.2.1.1.4.0' '1.3.6.1.2.1.1.4' :return: a dictionary of <oid, value> """ object_identities = [] for oid in oids: if type(oid) is list or type(oid) is tuple: oid_0 = list(oid) if len(oid_0) == 2: oid_0.append(0) object_identities.append(ObjectIdentity(*oid_0)) else: oid_0 = oid if oid.endswith('.0') else oid + '.0' object_identities.append(ObjectIdentity(oid_0)) self._command(self.cmd_gen.getCmd, *object_identities) oid_2_value = OrderedDict() for var_bind in self.var_binds: modName, mibName, suffix = self.mib_viewer.getNodeLocation(var_bind[0]) oid_value = var_bind[1].prettyPrint() self._check_result_for_errors(oid_value) oid_2_value[mibName] = oid_value return oid_2_value
def set_by_name(self, obj_name, value, idx=(0, )): """Does a SNMP SET request. See `Get` for more information on possible OID notations. Automatic converting to the SNMP type expected by the remote system is only supported for OIDs for which there is a MIB describing it. If you want to use an OID which is not described by a MIB, you'll have to use the `Set XXX`-keyword or `Convert To XXX`-keyword. The optional `idx` is appended to the OID (defaults to `.0`). Example: | Set | SNMPv2::sysDescr | New System Description | """ if self._active_connection is None: raise RuntimeError('No transport host set') mibViewCtl = view.MibViewController(self._active_connection.builder) objIdentity = ObjectIdentity(self.DTM_MIB_LIB_NAME, obj_name) objIdentity.resolveWithMib(mibViewCtl) oid = '.' + str(objIdentity.getOid()) idx = utils.parse_idx(idx) oid = utils.parse_oid(oid) + idx self._set((oid, value))
def get_table_field(self, *oids): """ Get/Bulk get operation for columnar entries. Returns exact value from table for specified oids :param ois: list of oids to get. oid can be full dotted OID or (MIB, OID name, [index]). For example, the OID to get sysContact can by any of the following: ('SNMPv2-MIB', 'sysContact', 0) ('SNMPv2-MIB', 'sysContact') '1.3.6.1.2.1.1.4.0' '1.3.6.1.2.1.1.4' :return: a dictionary of <oid, value> """ object_identities = [] for oid in oids: if type(oid) is list or type(oid) is tuple: oid_0 = list(oid) object_identities.append(ObjectIdentity(*oid_0)) else: oid_0 = oid object_identities.append(ObjectIdentity(oid_0)) self._command(self.cmd_gen.getCmd, *object_identities) oid_2_value = OrderedDict() for var_bind in self.var_binds: mib_name, oid_value, suffix = self._translate_var_bind(var_bind) oid_2_value[mib_name] = oid_value return oid_2_value
def from_snmp(self, host, community): assert host assert community # switch port names and numbers # 1.3.6.1.2.1.31.1.1.1.1 oid = ObjectType(ObjectIdentity('IF-MIB', 'ifName')) for port_num_raw, port_name in _snmp_walk(host, community, oid): sw_port_num = port_num_raw[port_num_raw.rfind('.') + 1:] self._add_switch_port(sw_port_num, port_name) # mac addresses table # 1.3.6.1.2.1.17.7.1.2.2.1.2 oid = ObjectType(ObjectIdentity('1.3.6.1.2.1.17.7.1.2.2.1.2')) for mac_raw, sw_port_num in _snmp_walk(host, community, oid): name_parts = mac_raw.split('.') mac_address = _normalize_mac("".join( [("%02x" % int(name_parts[x])).upper() for x in range(len(name_parts) - 6, len(name_parts))] )).upper() self._add_server_port(self.get_port_name(sw_port_num), mac_address) # arp address table # 3.6.1.2.1.4.22.1.2 oid = ObjectType(ObjectIdentity('IP-MIB', 'ipNetToMediaPhysAddress')) for ip_addr_raw, mac_addr in _snmp_walk(host, community, oid): mac_addr = _normalize_mac(mac_addr) name_parts = ip_addr_raw.split('.') ip_address = ".".join([name_parts[x] for x in range(len(name_parts) - 4, len(name_parts))]) self._add_server_port_ip(mac_addr, ip_address)
def __init__(self, oid, value, snmp_engine, logger): self._raw_oid = oid self._snmp_mib_translator = CommandGeneratorVarBinds.getMibViewController( snmp_engine) self._logger = logger self._mib_id = None self._mib_name = None self._index = None self._raw_value = value self._object_id = ObjectIdentity(self._raw_oid) self._object_type = ObjectType(self._object_id, self._raw_value)
def get_oid_by_name(self, *names): """get oid from custom names. """ if len(names): self._info('get_oid_by_name %s' % ' '.join(list(names))) mibViewCtl = view.MibViewController( self._active_connection.builder) objIdentity = ObjectIdentity(*names) objIdentity.resolveWithMib(mibViewCtl) return '.' + str(objIdentity.getOid())
def get_value_by_name2(self, idx, *names): """get value from custom names direcly. """ if len(names): self._info('get_oid_by_name %s' % ' '.join(list(names))) mibViewCtl = view.MibViewController( self._active_connection.builder) objIdentity = ObjectIdentity(*names) objIdentity.resolveWithMib(mibViewCtl) oid = '.' + str(idx) + '.' + str(objIdentity.getOid()) return self._get(oid)
def f(snmp, portstr): snmp._command( snmp.cmd_gen.setCmd, ObjectType( ObjectIdentity('GEIST-MIB-V3', 'ctrlOutletStatus', int(portstr)), Gauge32(3))) sleep(delay) snmp._command( snmp.cmd_gen.setCmd, ObjectType( ObjectIdentity('GEIST-MIB-V3', 'ctrlOutletStatus', int(portstr)), Gauge32(1)))
def trap(self, work): var_bind_table = [] not_translated_oids = [] remaining_oids = [] oid_values = set() remotemibs = set() metrics = {} for w in work["data"]: if OID_VALIDATOR.match(w[1]): with suppress(Exception): found, mib = self.is_mib_known(w[1], w[1], work["host"]) if found and mib not in oid_values: self.load_mibs([mib]) oid_values.add(mib) try: var_bind_table.append( ObjectType(ObjectIdentity(w[0]), w[1]).resolveWithMib(self.mib_view_controller)) except SmiError: not_translated_oids.append((w[0], w[1])) for oid in not_translated_oids: found, mib = self.is_mib_known(oid[0], oid[0], work["host"]) if found: remotemibs.add(mib) remaining_oids.append((oid[0], oid[1])) if remotemibs: self.load_mibs(remotemibs) for w in remaining_oids: try: var_bind_table.append( ObjectType(ObjectIdentity(w[0]), w[1]).resolveWithMib(self.mib_view_controller)) except SmiError: logger.warning(f"No translation found for {w[0]}") _, _, result = self.process_snmp_data(var_bind_table, metrics, work["host"]) return { "time": time.time(), "result": result, "address": work["host"], "detectchange": False, "sourcetype": "sc4snmp:traps", }
def get_security_engine_id(logger, ir: InventoryRecord, snmpEngine: SnmpEngine): observerContext: Dict[Any, Any] = {} transportTarget = UdpTransportTarget((ir.address, ir.port), timeout=UDP_CONNECTION_TIMEOUT) # Register a callback to be invoked at specified execution point of # SNMP Engine and passed local variables at execution point's local scope snmpEngine.observer.registerObserver( lambda e, p, v, c: c.update(securityEngineId=v["securityEngineId"]), "rfc3412.prepareDataElements:internal", cbCtx=observerContext, ) # Send probe SNMP request with invalid credentials authData = UsmUserData("non-existing-user") errorIndication, errorStatus, errorIndex, varBinds = next( getCmd( snmpEngine, authData, transportTarget, ContextData(), ObjectType(ObjectIdentity("SNMPv2-MIB", "sysDescr", 0)), )) # See if our SNMP engine received REPORT PDU containing securityEngineId securityEngineId = fetch_security_engine_id(observerContext, errorIndication) logger.debug(f"securityEngineId={securityEngineId}") return securityEngineId
def snmp_process(self, host, oid): #user_pre = self.snmp_usr.get("1", END) #user_post = user_pre.strip("\n") #auth_pre = self.snmp_sha.get("1", END) #auth_post = auth_pre.strip("\n") #priv_pre = self.snmp_aes.get("1", END) #priv_post = priv_pre.strip("\n") # SNMP Process Generation for (errorIndication, errorStatus, errorIndex, varBinds) in nextCmd(SnmpEngine(), UsmUserData('PYTHON_USR', authKey='PythonSHA', privKey='PythonAES', authProtocol=usmHMACSHAAuthProtocol, privProtocol=usmAesCfb192Protocol), UdpTransportTarget((host, 161), timeout=3.0, retries=2), ContextData(), ObjectType(ObjectIdentity(oid)), lookupMib=False, lexicographicMode=False): if errorIndication: print(errorIndication, file=sys.stderr) elif errorStatus: print('%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBinds[int(errorIndex) - 1][0] or '?'), file=sys.stderr) else: for varBind in varBinds: output = str('%s = %s' % varBind) return output
def walk(self, oid, *indexes): """ Walk through the given table OID. :param oid: oid of the table to walk through. :param indices: only walk through the requested indices. :return: a dictionary of <index, <attribute, value>> """ self._command(cmd_gen.nextCmd, ObjectIdentity(*oid)) oid_2_value = QualiMibTable(oid[1]) for var_bind in self.var_binds: modName, mibName, suffix = mib_viewer.getNodeLocation(var_bind[0][0]) # We want table index to be numeric if possible. if str(suffix).isdigit(): # Single index like 1, 2, 3... - treat as int index = int(str(suffix)) elif str(suffix).replace('.', '', 1).isdigit(): # Double index like 1.1, 1.2, 2.1... - treat as float index = float(str(suffix)) else: # Triple or more index (like IPv4 in IP-Table) - treat as str. index = str(suffix) if not oid_2_value.get(index): oid_2_value[index] = {'suffix': str(suffix)} oid_2_value[index][mibName] = var_bind[0][1].prettyPrint() if indexes: oid_2_value = oid_2_value.get_rows(*indexes) return oid_2_value
def get_info_snmp(host, oid): for (errorIndication, errorStatus, errorIndex, varBinds) in nextCmd(SnmpEngine(), UsmUserData(GET_USER, authKey=GET_AUTH, privKey=GET_PRIV, authProtocol=usmHMACSHAAuthProtocol, privProtocol=usmAesCfb192Protocol), UdpTransportTarget((host, 161), timeout=3.0, retries=2), ContextData(), ObjectType(ObjectIdentity(oid)), lookupMib=False, lexicographicMode=False): if errorIndication: print(errorIndication, file=sys.stderr) elif errorStatus: print('%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBinds[int(errorIndex) - 1][0] or '?'), file=sys.stderr) else: for varBind in varBinds: output = (str('%s = %s' % varBind)) return output
def set(self, oids): """SNMP Set operation. :param oids: list of oids to set. oid can be full dotted OID or (MIB, OID name, [index]). For example, the OID to get sysContact can by any of the following: ('SNMPv2-MIB', 'sysContact', 0) '1.3.6.1.2.1.1.4.0' snmp.set([(("CISCO-CONFIG-COPY-MIB", "ccCopyProtocol", 10), 1), (("CISCO-CONFIG-COPY-MIB", "ccCopySourceFileType", 10), 1), (("CISCO-CONFIG-COPY-MIB", "ccCopyDestFileType", 10), 3), (("CISCO-CONFIG-COPY-MIB", "ccCopyServerAddress", 10), "10.212.95.180"), (("CISCO-CONFIG-COPY-MIB", "ccCopyFileName", 10), "test_snmp_running_config_save"), (("CISCO-CONFIG-COPY-MIB", "ccCopyVrfName", 10), "management"), (("CISCO-CONFIG-COPY-MIB", "ccCopyEntryRowStatus", 10), 4)]) """ if self.is_read_only: raise Exception(self.__class__.__name__, "SNMP Read Community doesn't support snmp set command") object_identities = [] for oid in oids: if type(oid) is list or type(oid) is tuple: oid_0 = list(oid) if len(oid_0) < 2: raise Exception(self.__class__.__name__, "Missing oid or value data") if type(oid[0]) is list or type(oid[0]) is tuple: if (len(oid_0[0])) < 3: raise Exception(self.__class__.__name__, "Missing oid index") object_identities.append(ObjectType(ObjectIdentity(*oid_0[0]), oid[1])) else: raise Exception(self.__class__.__name__, "Wrong oids parameter") self._write_command(self.cmd_gen.setCmd, *object_identities)
def _send_snmp_trap(host, var_binds, alarm_oid): host_details = host['host'] send_to = str(host_details.get('send_to')) port = str(host_details.get('port', 162)) community_str = host_details.get('community', 'public') if not (send_to and IP_PAT.match(send_to) and PORT_PAT.match(port)): LOG.info("Vitrage snmp Info: an SNMP target host was not" " configured correctly") return LOG.debug("Vitrage snmp Debug: Trap parameters: send_to: %s, " "port: %s, community string: %s" % (send_to, port, community_str)) error_indication, error_status, error_index, var_bins = next( sendNotification( SnmpEngine(), CommunityData(community_str, mpModel=1), UdpTransportTarget((send_to, port)), ContextData(), 'trap', NotificationType( ObjectIdentity(alarm_oid), ).addVarBinds(*var_binds))) if error_indication: LOG.error('Vitrage snmp Error: Notification not sent: %s' % error_indication) elif error_status: LOG.error('Vitrage snmp Error: Notification Receiver ' 'returned error: %s @%s' % (error_status, error_index))
def walk(self, oid, *indexes): """ Walk through the given table OID. :param oid: oid of the table to walk through. :param indices: only walk through the requested indices. :return: a dictionary of <index, <attribute, value>> """ self._command(self.cmd_gen.nextCmd, ObjectIdentity(*oid)) oid_2_value = QualiMibTable(oid[1]) for var_bind in self.var_binds: mibName, mib_value, suffix = self._translate_var_bind(var_bind[0]) # We want table index to be numeric if possible. if str(suffix).isdigit(): # Single index like 1, 2, 3... - treat as int index = int(str(suffix)) else: # Triple or more index (like IPv4 in IP-Table) - treat as str. index = str(suffix) if not oid_2_value.get(index): oid_2_value[index] = {'suffix': str(suffix)} oid_2_value[index][mibName] = mib_value # self.logger.debug('{0}'.format(oid_2_value)) if indexes: oid_2_value = oid_2_value.get_rows(*indexes) return oid_2_value
def power_cycle(self, port_list, delay): self.logger.info("Power cycle called for ports %s" % port_list) for raw_port in port_list: self.logger.info("Power cycling port %s" % raw_port) port = self.Port(raw_port) self.logger.info("Powering off port %s" % raw_port) self.snmp_handler.set( ObjectIdentity('Sentry3-MIB', 'outletControlAction', port.port_number, port.pdu_number, port.outlet_number), Integer(2)) self.logger.info("Sleeping %f second(s)" % delay) sleep(delay) self.logger.info("Powering on port %s" % raw_port) self.snmp_handler.set( ObjectIdentity('Sentry3-MIB', 'outletControlAction', port.port_number, port.pdu_number, port.outlet_number), Integer(1))
def power_cycle(self, port_list, delay): self.logger.info("Power cycle called for ports %s" % port_list) for raw_port in port_list: self.logger.info("Power cycling port %s" % raw_port) port = self.Port(raw_port) self.logger.info("Powering off port %s" % raw_port) self.snmp_handler.set( ObjectIdentity('PM-MIB', 'pmPowerMgmtOutletsTablePowerControl', port.port_number, port.pdu_number, port.outlet_number), Gauge32(3)) self.logger.info("Sleeping %f second(s)" % delay) sleep(delay) self.logger.info("Powering on port %s" % raw_port) self.snmp_handler.set( ObjectIdentity('PM-MIB', 'pmPowerMgmtOutletsTablePowerControl', port.port_number, port.pdu_number, port.outlet_number), Gauge32(2))
def power_on(self, port_list): self.logger.info("Power on called for ports %s" % port_list) for raw_port in port_list: self.logger.info("Powering on port %s" % raw_port) port = self.Port(raw_port) self.snmp_handler.set( ObjectIdentity('Sentry3-MIB', 'outletControlAction', port.port_number, port.pdu_number, port.outlet_number), Integer(1))
def power_on(self, port_list): self.logger.info("Power on called for ports %s" % port_list) for raw_port in port_list: self.logger.info("Powering on port %s" % raw_port) port = self.Port(raw_port) self.snmp_handler.set( ObjectIdentity('PM-MIB', 'pmPowerMgmtOutletsTablePowerControl', port.port_number, port.pdu_number, port.outlet_number), Gauge32(2))
def _create_object_identity(self): object_identity = ObjectIdentity(*(self._mib_name, self._object_name)) if self.index is not None: object_identity = ObjectIdentity( *((self._mib_name, self._object_name) + tuple(str(self.index).split(".")))) if self._asn_mib_sources: object_identity.addAsn1MibSource(self._asn_mib_sources) if self._custom_mib_sources: object_identity.addMibSource(self._custom_mib_sources) return object_identity
def set_many_by_name(self, *name_value_pairs): """ Does a SNMP SET request with multiple values. Set one or more values simultaneously. See `Set` for more information about the OID and possible value. After each value, you can give an index (`idx`, see example below) which is appended to the OIDs. By default the index is `.0`. Examples: | Set Many | SNMPv2::sysDescr | New System Description | | | ... | SNMPv2-MIB::sysName | New System Name | | | Set Many | IF-MIB::ifDescr | IF1 Description | idx=1 | | ... | IF-MIB::ifDescr | IF2 Description | idx=2 | """ if self._active_connection is None: raise RuntimeError('No transport host set') args = list(name_value_pairs) oid_values = list() try: while len(args): obj_name = args.pop(0) mibViewCtl = view.MibViewController( self._active_connection.builder) objIdentity = ObjectIdentity(self.DTM_MIB_LIB_NAME, obj_name) objIdentity.resolveWithMib(mibViewCtl) oid = '.' + str(objIdentity.getOid()) value = args.pop(0) possible_idx = args[0] if len(args) > 0 else '' if possible_idx.startswith('idx='): idx = args.pop(0)[4:] else: idx = (0, ) idx = utils.parse_idx(idx) oid = utils.parse_oid(oid) + idx oid_values.append((oid, value)) except IndexError: raise RuntimeError('Invalid Object Name/value(/index) format') if len(oid_values) < 1: raise RuntimeError( 'You must specify at least one Object Name/value pair') self._set(*oid_values)
def power_cycle(self, port_list, delay): self.logger.info("Power cycle called for ports %s" % port_list) for raw_port in port_list: self.logger.info("Power cycling port %s" % raw_port) port = self.Port(raw_port) self.logger.info("Powering off port %s" % raw_port) # self.snmp_handler.set(ObjectIdentity('PowerNet-MIB', ' rPDUOutletControlOutletCommand', port.port_number), # Integer(2)) self.snmp_handler.set( ObjectIdentity('.1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.%s' % port.port_number), Integer(2)) self.logger.info("Sleeping %f second(s)" % delay) sleep(delay) self.logger.info("Powering on port %s" % raw_port) # self.snmp_handler.set(ObjectIdentity('PowerNet-MIB', ' rPDUOutletControlOutletCommand', port.port_number), # Integer(1)) # might need to be Integer32 instead self.snmp_handler.set( ObjectIdentity('.1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.%s' % port.port_number), Integer(1))
def power_on(self, port_list): self.logger.info("Power on called for ports %s" % port_list) for raw_port in port_list: self.logger.info("Powering on port %s" % raw_port) port = self.Port(raw_port) # self.snmp_handler.set(ObjectIdentity('PowerNet-MIB', ' rPDUOutletControlOutletCommand', port.port_number), # Integer(1)) self.snmp_handler.set( ObjectIdentity('.1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.%s' % port.port_number), Integer(1))
def get_by_name(self, obj_name, idx=(0, )): """Does a SNMP GET request for the specified 'obj_name'. The optional `idx` can be specified as tuple or as a string and defaults to `.0`. Examples: | ${value}= | Get | SNMPv2-MIB::sysDescr | | | ${value}= | Get | .1.3.6.1.2.1.1.1 | | | ${value}= | Get | .iso.org.6.internet.2.1.1.1 | | | ${value}= | Get | sysDescr | | | ${value}= | Get | ifDescr | 2 | """ mibViewCtl = view.MibViewController(self._active_connection.builder) objIdentity = ObjectIdentity(self.DTM_MIB_LIB_NAME, obj_name) objIdentity.resolveWithMib(mibViewCtl) oid = '.' + str(objIdentity.getOid()) return self._get(oid, idx)
def _create_object_identity(self): object_identity = ObjectIdentity(self._oid) if self._asn_mib_sources: object_identity.addAsn1MibSource(self._asn_mib_sources) if self._custom_mib_sources: object_identity.addMibSource(self._custom_mib_sources) return object_identity
def next(self, oid): """ Get next for a scalar. :param oid: oid to getnext. :return: a pair of (next oid, value) """ self._command(self.cmd_gen.nextCmd, ObjectIdentity(*oid), ) var_bind = self.var_binds[0][0] modName, mibName, suffix = self.mib_viewer.getNodeLocation(var_bind[0]) value = var_bind[1].prettyPrint() return (mibName, value)
def power_off(self, port_list): self.logger.info("Power off called for ports %s" % port_list) for raw_port in port_list: self.logger.info("Powering off port %s" % raw_port) port = self.Port(raw_port) # TODO Change the Integer(2) harcoding to use the named value "off" self.snmp_handler.set( ObjectIdentity('Sentry3-MIB', 'outletControlAction', port.port_number, port.pdu_number, port.outlet_number), Integer(2)) status = self.snmp_handler.get( ('Sentry3-MIB', 'outletStatus', port.port_number, port.pdu_number, port.outlet_number))['outletStatus'] self.logger.info("Port {} is now: ".format(raw_port) + status) return "Power Off: Success"
def from_snmp(self, host, community): assert host assert community # load port id map oid = ObjectType(ObjectIdentity('1.3.6.1.2.1.17.1.4.1.2')) for name, value in _snmp_walk(host, community, oid): self.snmpid__port_num__map[value] = name.split('.')[-1] # switch port names and numbers oid = ObjectType(ObjectIdentity('1.3.6.1.2.1.31.1.1.1.1')) for name, value in _snmp_walk(host, community, oid): snmp_port_id = name.split('.')[-1] if snmp_port_id in self.snmpid__port_num__map: real_port_number = self.snmpid__port_num__map[snmp_port_id] self._add_switch_port(real_port_number, value) else: logger.warning("There is no mapping for the SNMP port ID: %s" % snmp_port_id) # mac addresses table oid = ObjectType(ObjectIdentity('1.3.6.1.2.1.17.7.1.2.2.1.2')) for name, value in _snmp_walk(host, community, oid): name_parts = name.split('.') mac_address = "".join([ ("%02x" % int(name_parts[x])).upper() for x in range(len(name_parts) - 6, len(name_parts)) ]).upper() self._add_server_port(self.get_port_name(value), mac_address) # arp address table oid = ObjectType(ObjectIdentity('IP-MIB', 'ipNetToMediaPhysAddress')) for name, value in _snmp_walk(host, community, oid): ip_address = '.'.join(name.split('.')[-4:]) self._add_server_port_ip(value.upper(), ip_address)
def next(self, oid): """ Get next for a scalar. :param oid: oid to getnext. :return: a pair of (next oid, value) """ self._command( self.cmd_gen.nextCmd, ObjectIdentity(*oid), ) var_bind = self.var_binds[0][0] mib_name, value, suffix = self._translate_var_bind(var_bind) return mib_name, value
if opt[0] == '--mib-module': modNames.append(opt[1]) # obsolete begin if opt[0] == '--start-oid': startOID = univ.ObjectIdentifier(opt[1]) if opt[0] == '--stop-oid': stopOID = univ.ObjectIdentifier(opt[1]) # obsolete end if opt[0] == '--mib-source': mibSources.append(opt[1]) if opt[0] == '--start-object': startOID = ObjectIdentity( *opt[1].split('::', 1)) if opt[0] == '--stop-object': stopOID = ObjectIdentity( *opt[1].split('::', 1), **dict(last=True)) if opt[0] == '--manual-values': automaticValues = 0 if opt[0] == '--automatic-values': try: automaticValues = int(opt[1]) except ValueError: sys.stderr.write( 'ERROR: bad value %s: %s\r\n' % (opt[1], sys.exc_info()[1]))