#!/usr/bin/perl

###############################################################################
## Copyright (c) 2007-2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
###############################################################################

use strict;
use warnings;
use FindBin;
BEGIN { unshift @INC, "$FindBin::Bin/../www/perl-lib" }

use SMT::CLI;
use SMT::Utils;
use SMT::SCCSync;
use File::Basename;
use File::Temp;
use Locale::gettext ();
use POSIX ();     # Needed for setlocale()

POSIX::setlocale(&POSIX::LC_MESSAGES, "");

if(!SMT::Utils::dropPrivileges())
{
    print STDERR __("Unable to drop privileges. Abort!\n");
    exit 1;
}

my $debug    = 0;
my $vblevel  = LOG_ERROR|LOG_WARN|LOG_INFO1;
my $help;
my $mail;    # activate sending of report mail
my $attach;  # attach csv report to report mail
my $quiet;   # suppress output to STDOUT
my $csv;     # export data as csv
my $pdf;     # export data as pdf
my $xml;     # export data as xml
my $file;    # write output to file
my $logfile;

my $currenttime = time();
my $dailycheck = 0;
my $haveAlerts = 0;
my $timestampfile = $ENV{HOME}."/.lastsendreport";
my $lastreport = 0;
my $sendReport = 0;

use Getopt::Long;

my $LOG = undef;

# configuration

my $legendLocal = "
Legend:

Subscription Type:       Group of SUSE products which customer may be
                         entitled to receive patches, updates or technical
                         support during the period covered by the subscription.

Locally Registered       the registered machines connected to the SMT
Systems:                 with access to patches, updates or technical
                         support.

Active Purchase Count:   the number of active subscriptions not requiring
                         renewal in 30 days.

Soon expiring            active subscriptions requiring renewal in
Purchase Counts:         next 30 days.

Over Limit:              the registered machines not covered by
                         subscription, meaning the customer must purchase
                         additional subscriptions of the product.

Subscriptions:           SUSE product which customer may be entitled to
                         receive patches, updates or technical support
                         during the period covered by the subscription.

Total Purchase Count:    the total number of subscriptions the customer
                         has purchased.

Used Locally:            the registered machines connected to the SMT
                         with access to patches, updates or technical
                         support.

Subscription Expires:    the ending date of subscription coverage.


1.  This report may not represent all of the SMT servers or machines in
    your environment.
2.  If Customer purchases Upgrade Protection, Customer must purchase
    Upgrade Protection for all copies of the SUSE product(s) installed
    (per SUSE Terms and Conditions of Suse Linux).
";

my $legendSCC   = "
Legend:

Subscription Type:       Group of SUSE products which customer may be
                         entitled to receive patches, updates or technical
                         support during the period covered by the subscription.

Total Systems            the active number of machines registered
Registered with SCC:     by the customer at SUSE Customer Center.

Active Purchase Count:   the number of active subscriptions not requiring
                         renewal in 30 days.

Soon expiring            active subscriptions requiring renewal in
Purchase Counts:         next 30 days.

Over Limit:              the registered machines not covered by
                         subscription, meaning the customer must purchase
                         additional subscriptions of the product.

Subscriptions:           SUSE product which customer may be entitled to
                         receive patches, updates or technical support
                         during the period covered by the subscription.

Activation Code:         the key to validate the product on SUSE Customer
                         Center.

Total Purchase Count:    the total number of subscriptions the customer
                         has purchased.

Total Used:              the number of machines registered to receive
                         patches, updates, or technical support.

Used Locally:            the registered machines connected to the SMT
                         with access to patches, updates or technical
                         support.

Subscription Expires:    the ending date of subscription coverage.

1.  This report may not represent all of the SMT servers or machines in
    your environment.
2.  If Customer purchases Upgrade Protection, Customer must purchase
    Upgrade Protection for all copies of the SUSE product(s) installed
    (per SUSE Terms and Conditions of Suse Linux).
";

my $footer = "
DISCLAIMER:  The optional Subscription Management Tool (SMT) is intended to
assist you in managing your active SUSE Linux Enterprise devices and allow you
to match them against the number of subscriptions you have purchased.  However,
the data generated by the SMT is for informational purposes only and should not
be relied upon as an accurate count of the number of purchased subscriptions
available or the number of subscriptions consumed by your Linux devices. In
particular, you should understand that when you run a copy of the SMT on
multiple servers that each copy of SMT may display the total number of
subscriptions rather than only the number of subscriptions that pertain to the
relevant server.
";


# main hashes that keep the report data
my %REP = ();
my %DATA = ();

### SUBS #####################################################################

sub printUsage
{
    print basename($0) . " : " . __("generate a report")."\n";
    print "  --mail    (-m) : " . __("enable mailing of report")."\n";
    print "  --attach  (-a) : " . __("attach CSV report files to mail (only together with --mail)")."\n";
    print "  --quiet   (-q) : " . __("suppress output")."\n";
    print "  --csv     (-c) : " . __("export data in CSV format")."\n";
    print "  --pdf     (-p) : " . __("generate a PDF file")."\n";
    print "  --xml     (-x) : " . __("export data in XML format")."\n";
    print "  --file    (-F) [<file>] : " . __("write report to a file")."\n";
    print "            " . __("in csv mode <file> expands to [<dir>/]<file-name>-reportname[.<file-extension>]\n");
    print "  --logfile (-L) <file>   : " . __("Path to logfile")."\n";
    print "  --debug   (-d) : " . __("enable debug mode")."\n";
    print "  --verboselevel (-v) level " . __("set the verbose level\n");
}


#
# performs certificate checks and collects the errors found in a list
#      an error is a hash with the type name as key and the message as value
#      returns the error messages as text block
#
sub certificateCheck($$)
{
    my $printIt = shift;
    my $logIt = shift;
    if (!defined $printIt || !defined $logIt) { return ''; }
    my $messageBlock = '';

    my @msg = ();
    my $days = SMT::CLI::certificateExpireCheck(log => $LOG, vblevel => $vblevel);
    if(defined $days && $days > 0 && $days <= 10)
    {
        push @msg, { int(LOG_WARN) => sprintf(__("WARNING: SMT server certificate expired in %s days. Please re-new it soon!"), $days ) };
    }
    elsif(defined $days && $days <= 0)
    {
        push @msg, { int(LOG_ERROR) =>  __("ERROR: SMT server certificate is expired!") };
    }

    foreach my $message (@msg)
    {
        while (my ($type, $message) = each(%{$message}) )
        {
            printLog($LOG, $vblevel, $type, $message, $printIt, $logIt);
            $messageBlock .= $message."\n";
        }
    }

    return $messageBlock;
}


#
# will return rendered report and only (re)render if necessary
#   parameters: renderMode, reportName, [subReportName]
#
sub getReportRenderedAs
{
    my $mode   = shift;
    my $report = shift;
    my $subrep = shift;

    if ( ! defined $mode || ! defined $report ) { return ''; }
    if ( ! exists $DATA{$report} ) { return ''; }

    if (defined $subrep && $subrep ne '')
    {
        if (($subrep eq 'summary' && ref($DATA{$report}{$subrep}) ne "HASH") ||
            ($subrep eq 'alerts' && ref($DATA{$report}{$subrep}) ne "HASH"))
        {
            my $res = "";

            if($mode eq 'html')
            {
                $res .= "<p>\n";
                $res .= join("<br>", split(/\n/, $DATA{$report}{$subrep}));
                $res .= "</p>";
            }
            elsif($mode eq 'xml')
            {
                return '';
                #$res .= "<screen>\n";
                #$res .= $DATA{$report}{$subrep};
                #$res .= "</screen>";
            }
            elsif($mode eq 'docbook')
            {
                $res .= '<screen>';
                $res .= $DATA{$report}{$subrep};
                $res .= '</screen>';
            }
            else
            {
                # do not render summaries
                $res .= $DATA{$report}{$subrep};
            }
            return $res;
        }

        # check if we need to (re)render
        if ( ! exists  $REP{$mode}{$report}{$subrep}  ||
             ! defined $REP{$mode}{$report}{$subrep}    )
        {
            $REP{$mode}{$report}{$subrep} = SMT::CLI::renderReport($DATA{$report}{$subrep}, $mode, $subrep);
        }
        return $REP{$mode}{$report}{$subrep};
    }
    else
    {
        if ( ! exists  $REP{$mode}{$report}  ||
             ! defined $REP{$mode}{$report}    )
        {
            $REP{$mode}{$report} = SMT::CLI::renderReport($DATA{$report}, $mode, $subrep);
        }
        return $REP{$mode}{$report};
    }
    # to be safe
    return '';
}


#
# assemble a merged report
#
sub getMergedReport($)
{
    my $renderMode = shift;
    if (! defined $renderMode) { return ''; }
    my %headings = (
                    'sccreport'   =>  __("Subscription Report based on SCC registrations"),
                    'localreport' =>  __("Subscription Report based on a local calculation")
                   );

    my $res = '';
    my $txt = '';
    my $date = SMT::Utils::getDBTimestamp();

    if($renderMode eq 'html')
    {
        $res .= "<h1>".$headings{'localreport'}."</h1>";
    }
    elsif($renderMode eq 'docbook')
    {
        $res .= "<title>".$headings{'localreport'}."</title>";
    }
    elsif($renderMode eq 'xml')
    {
        $res .= '<report title="'.$headings{'localreport'}.'" id="localreport" date="'.$date.'">';
    }
    else
    {
        $res .= $headings{'localreport'}."\n";
        $res .= sprintf '=' x length($headings{'localreport'})."\n\n";
    }

    $res .= getReportRenderedAs($renderMode, 'localreport', 'alerts')."\n";
    $res .= getReportRenderedAs($renderMode, 'localreport', 'summary')."\n";
    $res .= getReportRenderedAs($renderMode, 'localreport', 'active')."\n";
    $res .= getReportRenderedAs($renderMode, 'localreport', 'soon')."\n";
    $res .= getReportRenderedAs($renderMode, 'localreport', 'expired')."\n";
    $res .= getReportRenderedAs($renderMode, 'localreport', 'wosub')."\n";
    $res .= "\n\n";

    if($renderMode eq 'html')
    {
        $res .= "<pre>\n";
        $res .= $legendLocal."\n\n";
    }
    elsif($renderMode eq 'xml')
    {
        #$res .= "<screen>\n";
    }
    elsif($renderMode eq 'docbook')
    {
        $res .= "<section><title>Footer</title>";
        $res .= "<screen>";
        $res .= $legendLocal."\n\n";
        #$res .= "</para></section>";
    }
    else
    {
        $res .= $legendLocal."\n\n";
    }

    if($renderMode eq 'html')
    {
        $res .= $footer."\n\n";
        $res .= "</pre>";
    }
    elsif($renderMode eq 'xml')
    {
        #$res .= "</screen>";
    }
    elsif($renderMode eq 'docbook')
    {
        $res .= $footer."\n\n";
        $res .= "</screen></section>";
    }
    else
    {
        $res .= $footer."\n\n";
    }

    return $res;
}


#
# return s hash with all reports rendered separately
#
sub getSeparateReports($)
{
    my $renderMode = shift;
    my %res = ();
    if (! defined $renderMode) { return %res; }

    $res{'product_subscription_active'}     = getReportRenderedAs($renderMode, 'localreport', 'active');
    $res{'product_subscription_expiresoon'} = getReportRenderedAs($renderMode, 'localreport', 'soon');
    $res{'product_subscription_expired'}    = getReportRenderedAs($renderMode, 'localreport', 'expired');
    $res{'product_subscription_wosub'}      = getReportRenderedAs($renderMode, 'localreport', 'wosub');
    $res{'product_subscription_summary'}    = getReportRenderedAs($renderMode, 'localreport', 'summary');
    $res{'product_subscription_alerts'}     = getReportRenderedAs($renderMode, 'localreport', 'alerts');

    return %res;
}



### MAIN #####################################################################

Getopt::Long::Configure( 'no_auto_abbrev');
my $optres = Getopt::Long::GetOptions(
                                      'debug|d'    => \$debug,
                                      "verboselevel|v=i" => \$vblevel,
                                      'help|h'     => \$help,
                                      'mail|m'     => \$mail,
                                      'attach|a'   => \$attach,
                                      'quiet|q'    => \$quiet,
                                      'csv|c'      => \$csv,
                                      'pdf|p'      => \$pdf,
                                      'xml|x'      => \$xml,
                                      'file|F:s'   => \$file,      # file name is optional; if missing, it will use a default name
                                      'logfile|L=s'=> \$logfile,
                                      'dailycheck' => \$dailycheck
                                     );

if ( (defined $help && $help == 1 ) || !$optres )
{
    printUsage();
    exit 0;
}

$vblevel = LOG_ERROR|LOG_WARN|LOG_INFO1|LOG_INFO2|LOG_DEBUG|LOG_DEBUG2 if($debug);

# open the logfile
$LOG = SMT::Utils::openLog($logfile);

# calculate best report
my $cfg = SMT::Utils::getSMTConfig();

my $api = $cfg->val('NU', 'ApiType', 'NCC');
if ( $api eq 'NCC')
{
    printLog($LOG, $vblevel, LOG_ERROR, __("NCC is not supported by this version of SMT"));
    exit 1;
}

{
    my $hostname = SMT::Utils::getFQDN();
    my ($uri, $NUUser, $NUPass) = SMT::Utils::getLocalRegInfos();
    my $smtguid = SMT::Utils::getSMTGuid();

    $footer      .= "
Generated on: $hostname
Site ID:      $NUUser
SMT ID:       $smtguid
";
}


$DATA {'localreport'} = SMT::CLI::productSubscriptionReport(log => $LOG, vblevel => $vblevel);
if( $DATA{'localreport'}{'alerts'} ne "" )
{
    $haveAlerts = 1;
}

if( defined $mail && $mail && $dailycheck )
{
    if(-e $timestampfile)
    {
        open(TIME, "< $timestampfile") and do
        {
            $lastreport = <TIME>;
            chomp($lastreport);
            $lastreport = int $lastreport;
            close TIME;
        };
    }

    if( $haveAlerts && ($currenttime > ($lastreport + (47 * 60 * 60))) )
    {
        $sendReport = 1;
    }
    if( (localtime($currenttime))[6] == 0 )
    {
        # do not send reports on sunday
        # this can wait until monday
        $sendReport = 0;
    }

    exit 0 if(!$sendReport);
}


# default settings
my $doPrint = 1;
my $doLog = 1;
my $certErrors = '';
my $datestring = POSIX::strftime("%Y-%m-%d_%H-%M-%S", localtime);
my $defaultFilePrefix = "SMT_report-$datestring";


# set doPrint to 0 if quiet mode selected
if (defined $quiet && $quiet == 1)
{
    $doPrint = 0;
}

# print and log the ascii report if wanted
printLog($LOG, $vblevel, LOG_INFO1, getMergedReport('asciitable'), $doPrint, $doLog);

# print, log and get the certificate check results
$certErrors = certificateCheck($doPrint, $doLog);


if (defined $file)
{
    # exporting the report
    my $fname = '';
    my ($Efile, $Edir, $Eext) = fileparse($file, qr/\.[^.]*/);

    if($Edir eq "." || $Edir eq "./")
    {
        $Edir = $ENV{PWD}."/";
    }

    if ($Efile eq '')
    {
        $Efile = $defaultFilePrefix;
        $Eext  = '';  # trigger automatic extension
    }

    # if file extension is csv we switch to csv export
    if ( (defined $csv && $csv == 1) ||  $Eext eq '.csv' )
    {
        $csv = 1;
    }
    # if file extension is csv we switch to pdf export
    if ( (defined $pdf && $pdf == 1) ||  $Eext eq '.pdf' )
    {
        $pdf = 1;
    }
    # if file extension is csv we switch to xml export
    if ( (defined $xml && $xml == 1) ||  $Eext eq '.xml' )
    {
        $xml = 1;
    }

    if ($csv)
    {
        if ($Eext eq '') { $Eext = '.csv'; }

        my %rep = getSeparateReports('csv');

        while ( my ($rname, $rdata) = each(%rep) )
        {
            my $extension = $Eext;
            if ($extension eq '.csv'  &&  $rname =~ /alerts/i ) { $extension = '.txt';  }
            $fname = $Edir.$Efile.'-'.$rname.$extension;
            open(REPFILE, "> $fname ")  ||  die sprintf(__("Can not open target file %s"), $fname);
            print REPFILE $rdata;
            close REPFILE;
            printLog($LOG, $vblevel, LOG_INFO1, "Report generated at '$fname'");
        }
    }
    elsif( $pdf )
    {
        if( -x "/usr/bin/htmldoc" )
        {
            if ($Eext eq '') { $Eext = '.pdf'; }

            $fname = $Edir.$Efile.$Eext;
            my $html = "<html><head><title>SMT Subscription Report</title></head><body>";
            $html .= getMergedReport('html');
            $html .= "</body></html>";
            my $tfh = new File::Temp(TEMPLATE => "/tmp/smt-report-XXXXXXXX", UNLINK => 1, SUFFIX => ".html");
            my $tname = $tfh->filename();
            print $tfh $html."\n";
            close $tfh;
            my @cmdArgs = ("--webpage", "--quiet", "--size", "11x8.5in", "-f", "$fname", "$tname");
            open(OUT, "-|", '/usr/bin/htmldoc', @cmdArgs) or die "Cannot create PDF: $!";
            close OUT;
            printLog($LOG, $vblevel, LOG_INFO1, "Report generated at '$fname'");
        }
        else
        {
#             if ($Eext eq '') { $Eext = '.db'; }
#             my $docbook = '<?xml version="1.0" encoding="ISO-8859-1"?>
#               <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
#               "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"
#               [
#               <!ENTITY version "0.01">
#               <!ENTITY dx "DocBook-XML">
#               ]>
# <article>
#   <section>';
#             $docbook .= getMergedReport('docbook');
#             $docbook .= '</section></article>';
#             my $tfh = new File::Temp(TEMPLATE => "/tmp/smt-report-XXXXXXXX", UNLINK => 0, SUFFIX => ".db");
#             my $tname = $tfh->filename();
#             print $tfh $docbook."\n";
#             close $tfh;
#             printLog($LOG, $vblevel, LOG_ERROR, "Created : $tname");
            printLog($LOG, $vblevel, LOG_ERROR, "Cannot create PDF: /usr/bin/htmldoc not found.");
        }
    }
    elsif( $xml )
    {
        if ($Eext eq '') { $Eext = '.xml'; }
        $fname = $Edir.$Efile.$Eext;
        open(XML, "> $fname")  ||  die sprintf(__("Can not open target file %s"), $fname);
        print XML '<?xml version="1.0" encoding="UTF-8"?>'."\n";
        print XML getMergedReport('xml');
        print XML '</report>';
        close XML;
        printLog($LOG, $vblevel, LOG_INFO1, "Report generated at '$fname'");
    }
    else
    {
        if ($Eext eq '') { $Eext = '.txt'; }
        $fname = $Edir.$Efile.$Eext;
        open(REPFILE, "> $fname")  ||  die sprintf(__("Can not open target file %s"), $fname);
        print REPFILE getMergedReport('asciitable');
        close REPFILE;
        printLog($LOG, $vblevel, LOG_INFO1, "Report generated at '$fname'");
    }

    if ($certErrors ne '')
    {
        $fname = $Edir.$Efile.'-certificatecheck.txt';
        open(ERRFILE, "> $fname");
        print ERRFILE $certErrors;
        close ERRFILE;
    }
}



if (defined $mail  &&  $mail == 1)
{
    my %ATTACH = ();

    if (defined $attach  &&  $attach == 1)
    {
        my %rep = getSeparateReports('csv');

        while ( my ($rname, $rdata) = each(%rep) )
        {
            my $extension = '.csv';
            if ( $rname =~ /alerts/i ) { $extension = '.txt';  }
            my $csvName = $defaultFilePrefix.'-'.$rname.$extension;
            $ATTACH{$csvName} = $rdata;
        }

        if (defined $certErrors  &&  $certErrors ne '')
        {
            $ATTACH{"$defaultFilePrefix-certificatecheck .txt"} = $certErrors;
        }
    }

    my $MailBody = '';
    if ($certErrors ne '') { $MailBody .= $certErrors."\n\n"; }
    $MailBody .= getMergedReport('asciitable');

    my $datestring = POSIX::strftime("%Y-%m-%d %H:%M", localtime);
    my $subject = sprintf("SMT Subscription Report $datestring (%s)", SMT::Utils::getFQDN());
    SMT::Utils::sendMailToAdmins($subject, $MailBody, \%ATTACH);

    open(TIME, "> $timestampfile") and do
    {
        print TIME $currenttime;
        close TIME;
    };
}

exit 0;

#
# Manpage
#

=head1 NAME

smt report

=head1 SYNOPSIS

smt [help|--help|-h] report

smt report [--mail|-m] [--attach|-a] [--quiet|-q] [--csv|-c] [--file|-F [file]] [--logfile|-L file] [--debug|-d]

smt report

=head1 DESCRIPTION

I<smt report> creates reports on SMT and SCC data. Reports of the kinds local report and scc report can be created.
The reports can be printed to STDOUT, exported to one or multiple files as well as mailed to the administrator(s).

The kind of the report is computed automatically based on your SMT setup but can as well be defined by parameters.


=head1 OPTIONS

=head2 OUTPUT FORMAT and TARGET

=over

=item --quiet|-q

Creates a report in quiet mode which supresses any output to STDOUT. No report will be printed to STDOUT.

=item --file|-F [file]

Writes the report to a file (or files). By default the report will be written to a single file rendered as tables. In csv mode (see B<--csv> section) each report will be written to its own file in csv format.

The B<file> name is optional and may as well define a path where to create the report file(s). If no file name is specified a default will be used which contains a timestamp. It will however not be checked if the file(s) already exist(s).

In csv mode the file name will expand to [path/]B<filename->I<reportname>[.extension] for every report.

B<Note:> If the file name contains I<.csv> as extension the report format will be csv (same as using B<--csv>).


=item --csv|-c

Export the report data in csv format to multiple files. Only to be used with B<--file> (see B<--file> section).
The first line of each csv file consists of the column names, data starts on line two.

=item --pdf|-p

Export the report data in PDF format. Only to be used with B<--file> (see B<--file> section).

=item --xml|-x

Export the report data in XML format. Only to be used with B<--file> (see B<--file> section).
See also B<XML FORMAT DESCRIPTION>.

=item --mail|-m

Activate mailing of the report. The report will be mailed rendered as table to the address(es) defined via the SMT YaST module.
The recipient list and optional mail relay settings can be setup in the I<REPORT> section in B</etc/smt.conf>.

=item --attach|-a

Reports rendered in csv format will be attached to the mailing. The files that would be created using B<--file ./ --csv> will be attached to the mail. Only to be used with B<--mail>.

=back

=head2 XML FORMAT DESCRIPTION

=over

The root element is I<report>. In I<report> there are I<table> elements. A summary, active subscriptions, subscriptions which expire soon and expired subscriptions.
Inside of the I<table> we have I<row> elements, which contain I<col> elements.

The I<report> element has three attributes:

=over 8

=item B<id>

id can have the value I<sccreport> or I<localreport> describing which kind of report was generated.

=item B<date>

The date and time when this report was created.

=item B<title>

A title for this report.

=back

The I<table> element has three attributes:

=over 8

=item B<id>

id can has the value I<summary> for the Summary table, I<active> for the table containing the active subscriptions,
I<soon> for the table containing subscription which expires within the next 30 days and I<expired> for the table
containing the already expired subscriptions.

=item B<date>

The date and time when this table was created.

=item B<title>

A title for this table.

=back

The I<row> element has no attributes.

The I<col> element has the attribute I<id>. The id describe the content of this column.
The following ids are available in the summary table:

=over 8

=item B<subtype>

The name of the subscription.

=item B<regsystems>

Number of registered systems. (Only in sccreport)

=item B<regsystemsvirt>

Number of registered virtual systems.  (Only in sccreport)

=item B<localregsystems>

Number of registered systems at this SMT server.

=item B<localregsystemsvirt>

Number of registered virtual systems at this SMT server.

=item B<active>

Number of active subscriptions. (value B<-1> means "unlimited")

=item B<expiresoon>

Number of subscriptions which expires within the next 30 days. (value B<-1> means "unlimited")

=item B<overlimit>

If this number is greater then 0, more systems then subscriptions are registered.

=back

The following ids are available in the other tables:

=over 8

=item B<sub>

The name of the subscription.

=item B<regcode>

The registration code of this subscription.

=item B<number>

The number of how many systems are allowed to use this subscription. The value B<-1> means "unlimited".

=item B<used>

The number of how many systems using this subscription. (means number of registrations using the regcode of this subscription.)
Virtual systems are not counted here. (Only in sccreport)

=item B<usedvirt>

The number of how many virtual systems using this subscription. (Only in sccreport)

=item B<localused>

The number of how many systems using this subscription and are registered using this SMT server.
Virtual systems are not counted here.

=item B<localusedvirt>

The number of how many virtual systems using this subscription and are registered using this SMT server.

=item B<expires>

The date when this subscription expired. If this element is empty, this subscription expires never.

=back

=back

=head2 DEBUG

=over

=item --debug|-d

Enable debug mode for verbose logging.

=item --verboselevel -v <level>

Set the output verbose level. The following categories exists.
These categories can be bitwise-or'd to use as verbose level.

=over 4

=item error messages

Value: 0x0001 == 1

=item warning messages

Value: 0x0002 == 2

=item info messages 1

Value: 0x0004 == 4

=item info messages 2

Value: 0x0008 == 8

=item debug messages 1

Value: 0x0010 == 16

=item debug messages 2

Value: 0x0020 == 32

=item debug messages 3

Value: 0x0040 == 64

=back

The default verbose level is 7 (error, warning and info1 messages).
B<--debug> set the verbose level to 63.

=item --logfile|-L file

Write log messages to B<file>.

=back


=head1 EXAMPLES

Print all reports to STDOUT

 smt report

Only mail the default report to the administrator(s) and suppress console output

 smt report --mail --quiet

Export all reports as separate files in B<csv> format to B<./reports/>

 smt report --file ./reports/ --csv

Mail all reports including csv attachments to the administrators and suppress console output (convenient for a cron job)

 smt report --mail --attach --quiet

Start the report procedure with logging

 smt report --logfile /var/log/smt-report.log


=head1 AUTHORS and CONTRIBUTORS

Duncan Mac-Vicar Prett, Lukas Ocilka, Jens Daniel Schmidt, Michael Calmer

=head1 LICENSE

Copyright (c) 2007-2012 SUSE LINUX Products GmbH, Nuernberg, Germany.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
Ave, Cambridge, MA 02139, USA.

=cut
