;; Global variables for hardware types and problem categories (useful ;; when reading the choice (integer) of the user to get a readable ;; name instead of a number) (defglobal ?*hardware-types* = (create$ workstation server laptop embedded) ?*problem-categories* = (create$ computer-does-not-start computer-blank-screen os-does-not-boot no-login-prompt network-trouble software-crash) ) (deftemplate support (slot kind (type SYMBOL) (allowed-values distribution device)) (slot level (type INTEGER) (allowed-values 1 2 3 4)) (slot category (type SYMBOL) (allowed-values power-supply battery graphic-login console-login bios network bootloader kernel unknown)) ) (defrule init ?x <- (initial-fact) => (retract ?x) (assert (start)) ) ;; First of all, ask the hardware type (defrule prompt-hardware-type ?x <- (start) => (printout t crlf "This program helps diagnosing a hardware or software program on GNU/Linux" crlf "What is the type of the system?" crlf " 1) Workstation" crlf " 2) Server" crlf " 3) Laptop" crlf " 4) Embedded" crlf) (retract ?x) (assert (hardware-type-id (read-number))) ) (defrule prompt-hardware-type-nil ?x <- (hardware-type nil) => (retract ?x) (assert (start)) ) (defrule prompt-hardware-type-name ?old-answer <- (hardware-type-id ?answer&~"*** READ ERROR ***") => (retract ?old-answer) (assert (hardware-type (nth$ ?answer ?*hardware-types*))) ) ; The hardware type must be valid! (defrule prompt-hardware-type-invalid ?hw-type <- (hardware-type-id nil|"*** READ ERROR ***") => (retract ?hw-type) (assert (start)) ) ;; Secondly, the kind of problem (defrule prompt-problem-category (hardware-type ~nil) => (printout t crlf "This program helps diagnosing a software or hardware problem" crlf "What kind of problem do you have?" crlf " 1) The computer does not start" crlf " 2) The computer starts but nothing displayed on the screen" crlf " 3) GNU/Linux does not boot" crlf " 4) No graphic or text login prompt" crlf " 5) Network trouble" crlf " 6) Software crash" crlf) (assert (problem-category-id (read-number))) ) (defrule problem-category-name ?old-answer <- (problem-category-id ?answer&~"*** READ ERROR ***") => (retract ?old-answer) (assert (problem-category (nth$ ?answer ?*problem-categories*))) ) (defrule prompt-problem-category-nil ?x <- (problem-category nil) ?y <- (hardware-type ?type) => (retract ?x) (retract ?y) (assert (hardware-type ?type)) ) ; The kind of problem must be valid! (defrule problem-category-invalid ?p-cat <- (problem-category-id nil|"*** READ ERROR ***") ?hw-type <- (hardware-type ?type) => (retract ?p-cat) (retract ?hw-type) (assert (hardware-type ?type)) ) ;; Global functions for problem resolution (deffunction is-problem-solved(?current-check) (printout t crlf "[Y/N] ") (assert (is-problem-solved-answer ?current-check (format nil "%c" (get-char t)))) ) (defrule check-problem-solved (problem-category ?category) ?answer <- (is-problem-solved-answer ?check ~"Y"&~"N") => (retract ?answer) (is-problem-solved ?check) ) ;; The computer does not start at all ; Check the computer is powered (defrule is-power-on (problem-category computer-does-not-start) => (printout t crlf "Is there any power? ") (is-problem-solved power-on) ) ; Check the cables if relevant (defrule check-cables (problem-category computer-does-not-start) (is-problem-solved-answer power-on "Y") => (printout t crlf "Are the cables properly plugged? ") (is-problem-solved cables-plugged) ) ; Check the battery if relevant (defrule check-battery (declare (salience -1)) (problem-category computer-does-not-start) (hardware-type laptop|embedded) (is-problem-solved-answer power-on "Y") (not (is-problem-solved-answer cables-plugged "N")) => (printout t crlf "Does it works by plugging the device directly on a power socket? ") (is-problem-solved battery-problem) ) ; What the client should do in case of power supply problem (defrule system-does-not-start (declare (salience -1)) (problem-category computer-does-not-start) (is-problem-solved-answer power-on "Y") (is-problem-solved-answer cables-plugged "Y") (not (support (kind ?) (level ?) (category ?))) => (printout t crlf "Please contact your computer technical support" crlf) (assert (support (kind device) (level 1) (category power-supply))) ) (defrule laptop-does-not-start (problem-category computer-does-not-start) (hardware-type laptop) (is-problem-solved-answer power-on "Y") (is-problem-solved-answer cables-plugged "Y") (is-problem-solved-answer battery-problem "Y") (not (support (kind ?) (level ?) (category ?))) => (printout t crlf "Please contact your computer technical support" crlf) (assert (support (kind device) (level 1) (category battery))) ) (defrule embedded-computer-does-not-start (problem-category computer-does-not-start) (hardware-type embedded) (is-problem-solved-answer power-on "Y") (is-problem-solved-answer battery-problem "Y") (not (support (kind ?) (level ?) (category ?))) => (printout t crlf "Please contact your computer technical support" crlf) (assert (support (kind device) (level 1) (category battery))) ) ;; The login prompt (graphical or console) is not displayed (defrule is-graphic-login (problem-category no-login-prompt) => (printout t "Do you use a graphical mode to login? ") (is-problem-solved is-graphic-login) ) ; Graphic login (defrule graphic-login-software (is-problem-solved-answer is-graphic-login "Y") => (printout t "What login manager do you use (GDM or KDM)? ") (assert (graphic-login-manager (read))) ) (defrule is-graphic-login-software-valid (graphic-login-manager ~GDM&~KDM) ?x <- (is-problem-solved-answer is-graphic-login ?) => (printout t "Invalid login manager" crlf) (retract ?x) (assert (is-problem-solved-answer is-graphic-login "Y")) ) (defrule check-graphic-login-logs (graphic-login-manager ?g) => (printout t "Please check the log in /var/log/" (lowcase ?g) ".log, what error message do you have?" crlf) (assert (graphic-login-manager-error-messages (read))) (printout t "Then please check: http://manual.distribution.org/graphic_login_manager/" (lowcase ?g) ", did this page help? ") (is-problem-solved graphic-login-manual-helped) ) (defrule is-graphic-login-manual-helped (is-problem-solved-answer graphic-login-manual-helped "N") => (printout t "Please contact the distribution technical support" crlf) (assert (support (kind distribution) (level 1) (category graphic-login))) ) ; Console login (defrule is-console-login (is-problem-solved-answer is-graphic-login "N") => (printout t "What are the last messages you get? " crlf) (assert (console-login-messages (read))) ) (defrule check-console-login-manual (console-login-messages ?msg) => (printout t "Please check: http://manual.distribution.org/console_login/search?" ?msg ", did this page help? ") (is-problem-solved console-login-manual-helped) ) (defrule console-login-manual-did-not-help (is-problem-solved-answer console-login-manual-helped "N") => (printout t crlf "Please contact the distribution technical support" crlf) (assert (support (kind distribution) (level 1) (category console-login))) ) ;; Problems on computer startup (before the bootloader) (defrule embedded-startup (problem-category computer-blank-screen) (hardware-type embedded) => (printout t crlf "Please contact your computer technical support" crlf) (assert (support (kind device) (level 1) (category unknown))) ) (defrule computer-startup-check-cables (problem-category computer-blank-screen) (hardware-type ~embedded) => (printout t crlf "Are the cables plugged in properly? ") (is-problem-solved computer-startup-cables-plugged) ) (defrule computer-startup-check-bios-beeps (hardware-type ~embedded) (is-problem-solved-answer computer-startup-cables-plugged "Y") => (printout t crlf "Please check: http://manual.vendor.com/bios according to the number of beeps, did it help? ") (is-problem-solved computer-startup-bios-manual-helped) ) (defrule computer-startup-manual-did-not-help (is-problem-solved-answer computer-startup-bios-manual-helped "N") => (printout t crlf "Please contact your computer technical support" crlf) (assert (support (kind device) (level 2) (category bios))) ) ;; Network trouble (defrule check-network-trouble (problem-category network-trouble) => (printout t crlf "What kind of device is it (wireless or wired)? ") (assert (connection-type (string-to-field (read)))) ) (defrule network-type-invalid ?network-fact <- (problem-category network-trouble) (connection-type ~wireless&~wired) => (printout t crlf "Invalid network type given") (retract ?network-fact) (assert (problem-category network-trouble)) ) (defrule check-wireless-interface-trouble (connection-type wireless) => (printout t crlf "Are you are associated and the link quality correct when running 'iwconfig' command? ") (is-problem-solved is-link-ok) ) (defrule check-wired-interface-trouble (connection-type wired) => (printout t crlf "Is the link correct when running 'mii-tool' command as root? ") (is-problem-solved is-link-ok) ) (defrule invalid-interface-link (connection-type ?type) (is-problem-solved-answer is-link-ok "N") => (printout t crlf "Please check the possible problems on http://manual.distribution.org/network/troubleshooting/" ?type ", did it help? ") (is-problem-solved network-manual-helped) ) (defrule invalid-network-link-manual-did-not-help (is-problem-solved-answer network-manual-helped "N") => (printout t crlf "Please contact your distribution technical support" crlf) (assert (support (kind distribution) (level 2) (category network))) ) (defrule check-ifconfig (is-problem-solved-answer is-link-ok "Y") => (printout t crlf "Are your network settings correct when running 'ifconfig -a' and 'route -taupen' commands? ") (is-problem-solved ifconfig-ok) ) (defrule check-ping-ip (is-problem-solved-answer ifconfig-ok "Y") => (printout t crlf "Are you able to ping any IP address inside/outside the current network? ") (is-problem-solved can-ping-ip) ) (defrule check-dns-resolution (is-problem-solved-answer can-ping-ip "N") => (printout t crlf "Are you able to ping an domain name? ") (is-problem-solved can-resolv-dns) ) (defrule invalid-network-settings (is-problem-solved-answer ifconfig-ok|can-ping-ip|can-resolv-dns "N") => (printout t crlf "Please set up your interfaces properly by reading: http://manual.distribution.org/network/settings, did it help? ") (is-problem-solved network-settings-manual-helped) ) (defrule invalid-network-settings-unknown (is-problem-solved-answer network-settings-manual-helped "N") => (printout t crlf "Please contact your distribution technical support" crlf) (assert (support (kind distribution) (level 2) (category network))) ) ;; Problems when the system does not boot ; Bootloader problem (defrule is-bootloader-menu-shown (problem-category os-does-not-boot) => (printout t crlf "Does it display the bootloader menu? ") (is-problem-solved bootloader-menu-shown) ) (defrule bootloader-errors-list (is-problem-solved-answer bootloader-menu-shown "N") => (printout t crlf "What is the error code? ") (assert (bootloader-error-code (read-number))) ) (defrule bootloader-error-invalid ?error <- (bootloader-error-code "*** READ ERROR ***") ?menu <- (is-problem-solved-answer bootloader-menu-show ?answer) => (retract ?menu) (retract ?error) (assert (is-problem-solved-answer bootloader-menu-show ?answer)) ) (defrule is-bootloader-manual-helped (bootloader-error-code ?error&~"*** READ ERROR ***") => (printout t crlf "Please check the error code at: http://manual.distribution.org/grub/error_code?code=" ?error crlf) (printout t crlf "Did the previous page helped to solve the problem? ") (is-problem-solved bootloader-manual-helped) ) (defrule bootloader-unsolved-problem (is-problem-solved-answer bootloader-manual-helped "N") => (printout t crlf "Please contact the distribution technical support" crlf) (assert (support (kind distribution) (level 2) (category bootloader))) ) ; Kernel problem (defrule get-kernel-error-message (is-problem-solved-answer bootloader-menu-shown "Y") => (printout t "What error message do you have on kernel boot? ") (assert (kernel-error-message (read))) ) (defrule kernel-search-for-boot-message (kernel-error-message ?msg) (hardware-type ?type) => (printout t "Please look for the error message at: http://manual.distribution.org/kernel/search?msg=" ?msg "&type=" ?type ", were you able to find the corresponding error message? ") (is-problem-solved kernel-manual-helped) ) (defrule kernel-unsolved-error-message (is-problem-solved-answer kernel-manual-helped "N") => (printout t "Please contact the distribution technical support" crlf) (assert (support (kind distribution) (level 3) (category kernel))) ) ;; Software crashes (defrule software-crash-prompt-name (problem-category software-crash) => (printout t crlf "Name of the software? ") (assert (software-crash-name (read))) ) (defrule software-crashes-prompt-severity (software-crash-name ?) => (printout t crlf "Severity (serious, important, normal, minor, wishlist)? ") (assert (software-crash-severity (string-to-field (read)))) ) (defrule is-software-crashes-severity-valid ?severity-fact <- (software-crash-severity ~serious&~important&~normal&~minor&~wishlist) ?name-fact <- (software-crash-name ?name) => (printout t crlf "Invalid severity given") (retract ?severity-fact) (retract ?name-fact) (assert (software-crash-name ?name)) ) (defrule software-suggested-resolution (declare (salience -1)) (software-crash-name ?name) (software-crash-severity ?severity) (hardware-type ?type) => (printout t crlf "You can check the bug report at: http://bugtracker.distribution.org/" ?name "/" severity "?type=" ?type " and report a new bug if it does not exist yet" crlf) )