Author: jsmeix Date: Thu Nov 20 15:53:49 2008 New Revision: 53489 URL: http://svn.opensuse.org/viewcvs/yast?rev=53489&view=rev Log: - Fixed how to avoid to autoconfigure multiple queues for the same printer. It is now based upon the URI which is sufficient because "usb://HP/" versus "hp:/usb/" duplicates and "parallel:/" versus "hp:/par/" duplicates are already avioded via the ConnectionItems("BasicAddDialog") call. Moved cupsd start when continuing a fresh installation in the target system (i.e. for the hardware proposal) from the Read() function in Printer.ycp to printer_proposal.ycp and wait for a started cupsd to become actually accessible (see Novell/Suse Bugzilla bnc#437735 starting at comment #17). - Added killing of the CUPS backend process to testpage printing to have an emergency break when a wrong driver lets the printer spit out zillions of sheets with nonsense characters. - 2.17.43 Modified: trunk/printer/VERSION trunk/printer/package/yast2-printer.changes trunk/printer/src/Printer.ycp trunk/printer/src/overview.ycp trunk/printer/src/printer_proposal.ycp Modified: trunk/printer/VERSION URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/VERSION?rev=53489&r1=53488&r2=53489&view=diff ============================================================================== --- trunk/printer/VERSION (original) +++ trunk/printer/VERSION Thu Nov 20 15:53:49 2008 @@ -1 +1 @@ -2.17.42 +2.17.43 Modified: trunk/printer/package/yast2-printer.changes URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/package/yast2-printer.changes?rev=53489&r1=53488&r2=53489&view=diff ============================================================================== --- trunk/printer/package/yast2-printer.changes (original) +++ trunk/printer/package/yast2-printer.changes Thu Nov 20 15:53:49 2008 @@ -1,4 +1,22 @@ ------------------------------------------------------------------- +Thu Nov 20 15:31:20 CET 2008 - jsmeix@suse.de + +- Fixed how to avoid to autoconfigure multiple queues for + the same printer. It is now based upon the URI which is + sufficient because "usb://HP/" versus "hp:/usb/" duplicates + and "parallel:/" versus "hp:/par/" duplicates are already + avioded via the ConnectionItems("BasicAddDialog") call. + Moved cupsd start when continuing a fresh installation + in the target system (i.e. for the hardware proposal) from + the Read() function in Printer.ycp to printer_proposal.ycp + and wait for a started cupsd to become actually accessible + (see Novell/Suse Bugzilla bnc#437735 starting at comment #17). +- Added killing of the CUPS backend process to testpage printing + to have an emergency break when a wrong driver lets the printer + spit out zillions of sheets with nonsense characters. +- 2.17.43 + +------------------------------------------------------------------- Wed Nov 19 16:35:13 CET 2008 - jsmeix@suse.de - Avoid to autoconfigure multiple queues for the same printer Modified: trunk/printer/src/Printer.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/Printer.ycp?rev=53489&r1=53488&r2=53489&view=diff ============================================================================== --- trunk/printer/src/Printer.ycp (original) +++ trunk/printer/src/Printer.ycp Thu Nov 20 15:53:49 2008 @@ -39,9 +39,6 @@ import "Summary"; import "Popup"; import "Printerlib"; -import "Mode"; -import "Stage"; -import "Service"; import "SuSEFirewall"; /** @@ -655,28 +652,6 @@ // Therefore try to install cups but because for a "client-only" config // only cups-client is required, proceed even if cups is not installed: Printerlib::TestAndInstallPackage( "cups", "install" ); - // Only in the second stage of the system installation make sure that a local cupsd is running - // because it is needed for automated queue setup during system installation - // see https://bugzilla.novell.com/show_bug.cgi?id=418585 - // Note that otherwise a local cupsd is not required (e.g. when it is a client-only setup). - // There are various checks in each individual case whether or not a local cupsd is required. - // E.g. it is required to "Add" a local queue or to "Share Printers" (i.e. share local queues). - if( Mode::installation() - && Stage::cont() - ) - { if( Service::Status( "cups" ) != 0 ) - { Service::Start( "cups" ); - // I don't know what to do in the second stage of the system installation - // when it fails to start the cupsd (should I show an error popup ?). - // Therefore a failure is currently simply ignored. - // Furthermore shouldn't it wait here until the cupsd is actually accessible - // i.e. until "lpstat -h localhost -r" returns successfully? - // See the Printerlib::GetAndSetCupsdStatus function. - // In particular for the very first start of the cupsd it may take several seconds - // (up to more than a minute on a slow machine) until it is actually accessible, - // compare https://bugzilla.novell.com/show_bug.cgi?id=429397 - } - } // Progress last stage (progress finished): if( Abort() ) return false; Progress::NextStage(); Modified: trunk/printer/src/overview.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/overview.ycp?rev=53489&r1=53488&r2=53489&view=diff ============================================================================== --- trunk/printer/src/overview.ycp (original) +++ trunk/printer/src/overview.ycp Thu Nov 20 15:53:49 2008 @@ -399,6 +399,8 @@ { y2milestone( "printing test page" ); // Delete ' characters because they are used for quoting in the bash commandlines below: string queue_name = deletechars( Printer::queues[selected_queue_index,"name"]:"", "'" ); + // The URI scheme is the first word up to the ':' character in the URI: + string uri_scheme = splitstring( Printer::queues[selected_queue_index,"uri"]:"", ":" )[0]:""; if( "" == queue_name ) { Popup::AnyMessage( // Header of a Popup::AnyMessage when no queue was selected from the list: _("Nothing Selected"), @@ -475,7 +477,7 @@ + testprint_job_title + "' -o page-label=\"" + queue_name - + "_testprint_from_$(hostname)\" /usr/share/cups/data/testprint.ps" + + ":YaST2testprint@$(hostname)\" /usr/share/cups/data/testprint.ps" ) ) { Popup::ErrorDetails( sformat( // Message of a Popup::ErrorDetails @@ -513,8 +515,8 @@ // This helps in usual cases (in particular when a good driver is used) // if something had messed up for an actively printing job but // unfortunately there is no option for the "cancel" command - // which lets the cupsd immediatelly kill the backend process - // as emergency brake when e.g. a wrong driver lets the printer + // which lets the cupsd kill the backend process as emergency brake + // when something is really wrong e.g. a wrong driver lets the printer // spit out zillions of sheets with nonsense characters. // When this command fails for whatever reason, it is a safe fallback // to assume that there are no pending jobs in the queue: @@ -548,6 +550,36 @@ Printerlib::result["stderr"]:"" ); } + // Deal with the backend process regardless whether or not + // the above cancel command was successful because + // killing the backend process is an emergency brake + // when something is really wrong: + string backend_is_running_commandline = "ps -C '" + + uri_scheme + + "' -o pid=,args= | grep '" + + testprint_job_title + + "'"; + // Do nothing to be on the safe side if the next command fails for whatever reason: + if( Printerlib::ExecuteBashCommand( backend_is_running_commandline ) ) + { // A matching backend process is running. + // Sleep 10 seconds to let the backend process terminate orderly + // when the filters have finished because of the above cancel command. + // There is no user feedback while waiting here because I assume that + // the user expects that it takes a bit of time to delete all pending jobs. + sleep( 10000 ); + if( Printerlib::ExecuteBashCommand( backend_is_running_commandline ) ) + { // A matching backend process is still running. + y2milestone( "Still running backend process to be killed: '%1'", Printerlib::result["stdout"]:"" ); + // Kill the backend process: + Printerlib::ExecuteBashCommand( backend_is_running_commandline + + " | cut -s -d ' ' -f1 | head -n 1 | tr -d -c '[:digit:]'" + ); + string backend_pid = Printerlib::result["stdout"]:""; + if( "" != backend_pid ) + { Printerlib::ExecuteBashCommand( "kill -9 '" + backend_pid + "'" ); + } + } + } } } } Modified: trunk/printer/src/printer_proposal.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/printer_proposal.ycp?rev=53489&r1=53488&r2=53489&view=diff ============================================================================== --- trunk/printer/src/printer_proposal.ycp (original) +++ trunk/printer/src/printer_proposal.ycp Thu Nov 20 15:53:49 2008 @@ -35,8 +35,13 @@ textdomain "printer"; import "Printer"; +import "Printerlib"; import "Progress"; import "String"; +import "Mode"; +import "Stage"; +import "Service"; +import "Popup"; /* The main () */ y2milestone("----------------------------------------"); @@ -47,70 +52,172 @@ map ret = $[]; /* create a textual proposal */ -if(func == "MakeProposal") { - list<string> proposal = []; - string warning = nil; - symbol warning_level = nil; - boolean force_reset = param["force_reset"]:false; - - if(force_reset || !Printer::proposal_valid) { - Printer::proposal_valid = true; - boolean progress_orig = Progress::set (false); - Printer::Read(); - Progress::set (progress_orig); +if( func == "MakeProposal" ) +{ list<string> proposal = []; + string warning = nil; + symbol warning_level = nil; + boolean force_reset = param["force_reset"]:false; + + if( force_reset || ! Printer::proposal_valid ) + { Printer::proposal_valid = true; + boolean progress_orig = Progress::set( false ); + Printer::Read(); + Progress::set( progress_orig ); + } + + // Propose configuration for each local printer + // TODO: replace by cups-autoconfig + + // Determine whether or not it is currently a real client-only config + // (i.e. a ServerName != "localhost/127.0.0.1" in /etc/cups/client.conf) + // and ignore when it fails (i.e. use the fallback value silently): + Printerlib::DetermineClientOnly(); + // Skip automated queue setup when it is a client-only config: + if( ! Printerlib::client_only ) + { // Determine whether or not a local cupsd is accessible: + if( ! Printerlib::GetAndSetCupsdStatus( "" ) ) + { // Only in the second stage of the system installation + // try to make silently sure that a local cupsd is running + // (i.e. start the cupsd without user confirmation) + // because it is needed for automated queue setup + // see https://bugzilla.novell.com/show_bug.cgi?id=418585 + // Note that because of Mode::installation() this happens only + // if we are doing a fresh installation (but e.g. not for an update) + // and because of Stage::cont() we are continuing the installation + // in the target system (but we are e.g. not in the inst-sys system) + // so that it should be sufficiently safe to (re)-start and enable + // the cupsd without user confirmation here: + if( Mode::installation() && Stage::cont() ) + { y2milestone("Silently start and enable the cupsd because we are continuing a fresh installation in the target system."); + if( Service::Status( "cups" ) != 0 ) + { Service::Start( "cups" ); + } + else + { // Restart the cupsd when it seems to run according to Service::Status + // but actually it is not accessible according to GetAndSetCupsdStatus. + // For example the cupsd may run but failed to bind to the IPP port 631 + // because whatever other service grabbed this port for a short while + // so that a restart could help here (a known ypbind/portmapper issue): + Service::Restart( "cups" ); + } + Service::Enable( "cups" ); + // Wait until the cupsd is actually accessible. + // In particular for the very first start of the cupsd it may take several seconds + // (up to more than a minute on a slow machine) until it is actually accessible, + // compare https://bugzilla.novell.com/show_bug.cgi?id=429397 + // Sleep one second in any case so that the new started cupsd can become ready to operate: + sleep( 1000 ); + if( ! Printerlib::GetAndSetCupsdStatus( "" ) ) + { // The cupsd is not yet accessible. + // Sleep 9 seconds so that the new started cupsd has more time to become ready to operate: + sleep( 9000 ); + } + if( ! Printerlib::GetAndSetCupsdStatus( "" ) ) + { // After waiting 10 seconds without user notification, become verbose now. + // Wait half a minute for a new started cupsd: + Popup::TimedMessage( _("Started the CUPS daemon.\nWaiting half a minute so that it is ready to operate..."), + 30 + ); + } + if( ! Printerlib::GetAndSetCupsdStatus( "" ) ) + { // It can take up to a few minutes when a cupsd is started + // for the very first time (e.g. on a new installed system) + // until the cupsd is actually ready to operate. + // E.g. because parsing of thousands of PPDs may need much time. + // Therefore enforce waiting one minute now. + // (Plain busy message without title.) + Popup::ShowFeedback( "", _("The CUPS daemon in not yet accessible.\nWaiting one minute so that it is ready to operate...") ); + sleep( 60000 ); + Popup::ClearFeedback(); + } + } } + // Skip automated queue setup when the cupsd is not accessible up to now. + // A special case is when the cupsd does not listen on the official IANA IPP port (631). + // Then Printerlib::GetAndSetCupsdStatus("") returns false because it calls + // "lpstat -h localhost -r" which fails ("-h localhost:port" would have to be used). + // The YaST printer modue does not support when the cupsd listens on a non-official port + // so that also in this special case no automated queue setup is done. + if( Printerlib::GetAndSetCupsdStatus( "" ) ) + { list<term> detected_printers = filter( term row, + (list<term>)Printer::ConnectionItems( "BasicAddDialog" ), + { return( ! issubstring( String::CutBlanks(row[1]:""), "Unknown" ) ); + } + ); + y2milestone( "Detected local printers: %1", detected_printers ); + if( size(detected_printers) > 0 ) + { y2milestone("Local printers detected, will set up queues for them:"); + list<string> already_set_up_uris = []; + // An empty list of autodetected queues is the fallback which is correct: + Printer::AutodetectQueues(); + foreach( map< string, string > queue, + Printer::queues, + { if( "" != queue["uri"]:"" ) + { already_set_up_uris = add( already_set_up_uris, queue["uri"]:"" ); + } + } + ); + foreach( term printer, + detected_printers, + { string model = String::CutBlanks(printer[1]:""); + if( "" != model && "unknown" != tolower( model ) ) + { string uri = String::CutBlanks(printer[2]:""); + if( "" != uri ) + { y2internal("Setting up a queue for URI '%1'", uri); + string queue_name = Printer::NewQueueName( tolower( model ) ); + if( contains( already_set_up_uris, uri ) ) + { y2internal("Skipping printer '%1' because a queue with the same URI already exists.", printer); + continue; + } + y2milestone("Proposed queue name: %1", queue_name); + string driver_filter_string = "^" + filterchars( tolower( model ), Printer::lower_alnum_chars ); + if( "^" != driver_filter_string ) + { list drivers = Printer::DriverItems( driver_filter_string, true ); + if( size(drivers) > 0 ) + { y2internal("Available drivers: %1", drivers); + y2internal("Selected driver: %1", drivers[0]:nil); + Printer::selected_ppds_index = drivers[0,0,0]:-1; + Printer::selected_connections_index = printer[0,0]:-1; + if( Printer::AddQueue( queue_name ) ) + { already_set_up_uris = add( already_set_up_uris, uri ); + // Autodetect queues again so that Printer::NewQueueName + // can compare with existing queue names but ignore whatever failures + // (an empty list of autodetected queues is the fallback result): + Printer::AutodetectQueues(); + } + } + else + { y2error("No available drivers for printer %1", printer); + } + } + } + } + } + ); + } + else + { y2milestone("No local printers detected"); + } + foreach( term queue, + (list<term>)Printer::QueueItems( true, false ), + { // Each proposal entry is a string of queue name and description: + proposal = add(proposal, queue[2]:"" + ": " + queue[3]:""); + } + ); + } + } -// Propose configuration for each local printer -// TODO: replace by cups-autoconfig - - list<term> detected_printers = filter(term row, (list<term>)Printer::ConnectionItems( "BasicAddDialog" ), { return (!issubstring(String::CutBlanks(row[1]:""), "Unknown")); }); - y2milestone("Detected local printers : %1", detected_printers); - if (size(detected_printers)>0){ - y2milestone("Local printers detected, will configure"); - // Autodetect existing queues so that Printer::NewQueueName can compare against existing queue names - // but ignore whatever failures (an empty list of autodetected queues is the fallback result): - Printer::AutodetectQueues(); - list<string> already_set_up_queue_names = []; - foreach(term printer, detected_printers, { - y2internal("Configure queue for backend %1", printer[2]:""); - string queue_name = Printer::NewQueueName( tolower( printer[1]:"" )); - if (contains(already_set_up_queue_names, queue_name)){ - y2internal("Skipping printer '%1' because it is already set up as queue %2", printer, queue_name); - continue; - } - y2milestone("Proposed queue name : %1", queue_name); - list drivers = Printer::DriverItems( filterchars( tolower( String::CutBlanks(printer[1]:"") ), Printer::lower_alnum_chars ), true ); - if (size(drivers)>0){ - y2internal("Available drivers : %1", drivers); - y2internal("Selected driver : %1", drivers[0]:nil); - Printer::selected_ppds_index=drivers[0,0,0]:-1; - Printer::selected_connections_index=printer[0,0]:-1; - if (Printer::AddQueue(queue_name)) already_set_up_queue_names = add(already_set_up_queue_names, queue_name); - } else y2error("No available drivers for printer %1", printer); - }); - } else { - y2milestone("No local printers detected"); - } - - foreach( term queue, (list<term>) Printer::QueueItems(true, false), { - proposal = add(proposal, queue[2]:"" + " : " + queue[3]:""); - }); -/* - proposal = maplist ( map< string, string > queue, Printer::queues, { - string description = queue["description"]:""; - return description; - }); -*/ - proposal = filter (string p, proposal, { return p != ""; }); - if (size (proposal) == 0) - proposal = [ _("No printer queue configured.") ]; - - ret = $[ - "raw_proposal" : proposal, - "warning_level" : warning_level, - "warning" : warning, - ]; + proposal = filter( string p, proposal, { return p != ""; } ); + if( size (proposal) == 0 ) + { proposal = [ _("No printer queue configured.") ]; + } + + ret = $[ "raw_proposal" : proposal, + "warning_level" : warning_level, + "warning" : warning, + ]; } + /* run the module */ else if(func == "AskUser") { map stored = Printer::Export(); -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org