-<p>Jeg overvar i dag <a href="http://www.regjeringen.no/nb/dep/fad/Tema/Lonns-_og_personalpolitikk/statens_reiseregulativ/reiseregningenno-som-fri-programvare.html">FADs pressepresentasjon</a> av arbeidet med ny
-programvare for <a href="http://www.reiseregningen.no/">skriving av
-reiseregninger</a>, som de gir ut som fri programvare. Den gode
-nyheten er at FAD med dette prosjektet demonstrerer vilje til å gå
-foran i å etablere en delingskultur i offentlig sektor, og denne gang
-har hatt fokus på å lage en løsning som fungerer på flere platformer,
-konkret Linux, MacOS X og Windows. Løsningen er utviklet av
-<a href="http://makingwaves.no">Making Waves</a> på oppdrag fra FAD, og
-kildekoden er tilgjengelig fra
-<a href="https://www.coderesort.com/p/reiseregningen">CodeResort</a>.
-En får lesetilgang til kode og dokumentasjon uten å registrere seg,
-men må registrere seg for f.eks. å melde inn feil og skrive i wikien.
-FAD håper å få erfaring med fri programvareprosjekter vha. dette
-prosjektet, som er første gang de gir ut kildekode fra et
-"egenutviklet" prosjekt.</p>
-
-<p>Løsningen er BSD-lisensiert, og basert på Adobe Flash, konkret
-Adobe Flex. Den bruker Flash 9, og fungerer ikke med Gnash. I
-tillegg til at selve flash-binæren ikke fungerer med Gnash, så er det
-lagt JavaScript-kode foran web-programmet som nekter å starte
-flash-programmet hvis ikke Adobe Flash 9 er installert. Det var
-irriterende, og jeg måtte hente ut URL til Flash-binæren fra
-HTML-siden og lage min egen testside for å sjekke om den fungerte med
-gnash. Fikk bare en blank flate der programmet skulle startet. Laget
-en side med følgende HTML-snutt for å laste programmet
-<pre><blockquote>&lt;object
- data="http://213.225.125.209/kunder/dss/Reiseregningen.swf"
- width="100%"
- height="100%"
-&gt;</blockquote></pre></p>
-
-<p>Bruken av Adobe Flash er spesielt problematisk da Adobes
-Flash-utgave har en lisens som ikke tillater andre en Adobe å
-distribuere deres programpakke. Det gjør det umulig for
-linux-distribusjoner som Debian, Ubuntu og RedHat å legge ved Adobes
-Flash i sine distribusjoner. Adobe Flash er ikke fri programvare.
-Det finnes noen ikke-komplette Flash-implementasjoner som er fri
-programvare, som <a href="http://www.getgnash.org/">Gnash</a> og
-<a href="http://swfdec.freedesktop.org/">swfdec</a>. Jeg spurte
-utviklerne om de hadde testet med alternative utgaver av Flash som
-Gnash og swfdec, men utviklerne hadde ikke hørt om alternativer og
-heller ikke testet løsningen mot disse.</p>
-
-<p>Videreutvikling av reiseregningsprogrammet vil kreve aksept for
-lisensen til Adobe Flex. I følge Adobe finnes Adobe Flax som
-Eclipse-utvidelse i
-<a href="http://labs.adobe.com/technologies/flex/flexbuilder_linux/">en
-betautgave for Linux</a>, men jeg vet ikke om denne er tilstrekkelig
-for å bygge reiseregningsprogrammet. Jeg mistenker at valg av
-teknologi gjør at svært få fri programvareutviklere ser det som
-interessant å involvere seg i videreutvikling av dette prosjektet.
-Personlig begrenser jeg meg til å jobbe med prosjekter som kan bygges
-og videreutvikles ved hjelp av fri programvare. Andre utviklere av
-fri programvare ser det åpenbart annerledes, da det jo finnes fri
-programvare på Windows. Vi får se om det er tilstrekkelig mange av
-dem til at FAD får bidragsytere utenfra. Prosjektet bærer litt preg
-av "kast det over gjerdet"-metoden for deling, der en legger ut koden
-men det ikke er klart hvem som skal skape fellesskapet som trengs for
-å få et fungerende fri programvareutviklingsmiljø.</p>
-
-<p>Systemet viser fram et dynamisk skjema som fylles ut fortløpende,
-og der tidligere svar styrer hvilke alternativer en må fylle ut
-senere. Det henter informasjon om takster og regler fra FADs sider,
-der informasjonen skal være lagt ut i maskinlesbart format. Når en er
-ferdig med å fylle ut kan en hente ut en PDF og en XML-fil for
-utskrift eller videre lagring/behandling. Skjemaet er kun
-klientbiten, og eventuell integrering mot økonomisystemer følger ikke
-med. FAD lovte at de skulle bidra til at takster og regelfilene
-skulle holdes oppdatert. Konvertering til PDF var visst .NET-basert.
-Utviklerne hadde ingen idé om dette fungerte med fri
-programvareutgaver som Mono. .NET-utgaven skulle være en begrenset
-del av løsningen, og visstnok ble .NET valgt for å integreres med FADs
-eksisterende tjenerløsning. Løsningen kunne gjenbruke
-personinformasjon vha. XML-filer lagret lokalt på brukerens maskin,
-slik at en slapp å skrive inn samme informasjon hver gang. Sentralt
-lagring var ikke ønsket for å unngå personvernspørsmål, selv om dette
-gjorde det litt vanskeligere for brukeren.</p>
+<p>At work, we have a few hundred Linux servers, and with that amount
+of hardware it is important to keep track of when the hardware support
+contract expire for each server. We have a machine (and service)
+register, which until recently did not contain much useful besides the
+machine room location and contact information for the system owner for
+each machine. To make it easier for us to track support contract
+status, I've recently spent time on extending the machine register to
+include information about when the support contract expire, and to tag
+machines with expired contracts to make it easy to get a list of such
+machines. I extended a perl script already being used to import
+information about machines into the register, to also do some screen
+scraping off the sites of Dell, HP and IBM (our majority of machines
+are from these vendors), and automatically check the support status
+for the relevant machines. This make the support status information
+easily available and I hope it will make it easier for the computer
+owner to know when to get new hardware or renew the support contract.
+The result of this work documented that 27% of the machines in the
+registry is without a support contract, and made it very easy to find
+them. 27% might seem like a lot, but I see it more as the case of us
+using machines a bit longer than the 3 years a normal support contract
+last, to have test machines and a platform for less important
+services. After all, the machines without a contract are working fine
+at the moment and the lack of contract is only a problem if any of
+them break down. When that happen, we can either fix it using spare
+parts from other machines or move the service to another old
+machine.</p>
+
+<p>I believe the code for screen scraping the Dell site was originally
+written by Trond Hasle Amundsen, and later adjusted by me and Morten
+Werner Forsbring. The HP scraping was written by me after reading a
+nice article in ;login: about how to use WWW::Mechanize, and the IBM
+scraping was written by me based on the Dell code. I know the HTML
+parsing could be done using nice libraries, but did not want to
+introduce more dependencies. This is the current incarnation:</p>
+
+<pre>
+use LWP::Simple;
+use POSIX;
+use WWW::Mechanize;
+use Date::Parse;
+[...]
+sub get_support_info {
+ my ($machine, $model, $serial, $productnumber) = @_;
+ my $str;
+
+ if ( $model =~ m/^Dell / ) {
+ # fetch website from Dell support
+ my $url = "http://support.euro.dell.com/support/topics/topic.aspx/emea/shared/support/my_systems_info/no/details?c=no&amp;cs=nodhs1&amp;l=no&amp;s=dhs&amp;ServiceTag=$serial";
+ my $webpage = get($url);
+ return undef unless ($webpage);
+
+ my $daysleft = -1;
+ my @lines = split(/\n/, $webpage);
+ foreach my $line (@lines) {
+ next unless ($line =~ m/Beskrivelse/);
+ $line =~ s/&lt;[^>]+?>/;/gm;
+ $line =~ s/^.+?;(Beskrivelse;)/$1/;
+
+ my @f = split(/\;/, $line);
+ @f = @f[13 .. $#f];
+ my $lastend = "";
+ while ($f[3] eq "DELL") {
+ my ($type, $startstr, $endstr, $days) = @f[0, 5, 7, 10];
+
+ my $start = POSIX::strftime("%Y-%m-%d",
+ localtime(str2time($startstr)));
+ my $end = POSIX::strftime("%Y-%m-%d",
+ localtime(str2time($endstr)));
+ $str .= "$type $start -> $end ";
+ @f = @f[14 .. $#f];
+ $lastend = $end if ($end gt $lastend);
+ }
+ my $today = POSIX::strftime("%Y-%m-%d", localtime(time));
+ tag_machine_unsupported($machine)
+ if ($lastend lt $today);
+ }
+ } elsif ( $model =~ m/^HP / ) {
+ my $mech = WWW::Mechanize->new();
+ my $url =
+ 'http://www1.itrc.hp.com/service/ewarranty/warrantyInput.do';
+ $mech->get($url);
+ my $fields = {
+ 'BODServiceID' => 'NA',
+ 'RegisteredPurchaseDate' => '',
+ 'country' => 'NO',
+ 'productNumber' => $productnumber,
+ 'serialNumber1' => $serial,
+ };
+ $mech->submit_form( form_number => 2,
+ fields => $fields );
+ # Next step is screen scraping
+ my $content = $mech->content();
+
+ $content =~ s/&lt;[^>]+?>/;/gm;
+ $content =~ s/\s+/ /gm;
+ $content =~ s/;\s*;/;;/gm;
+ $content =~ s/;[\s;]+/;/gm;
+
+ my $today = POSIX::strftime("%Y-%m-%d", localtime(time));
+
+ while ($content =~ m/;Warranty Type;/) {
+ my ($type, $status, $startstr, $stopstr) = $content =~
+ m/;Warranty Type;([^;]+);.+?;Status;(\w+);Start Date;([^;]+);End Date;([^;]+);/;
+ $content =~ s/^.+?;Warranty Type;//;
+ my $start = POSIX::strftime("%Y-%m-%d",
+ localtime(str2time($startstr)));
+ my $end = POSIX::strftime("%Y-%m-%d",
+ localtime(str2time($stopstr)));
+
+ $str .= "$type ($status) $start -> $end ";
+
+ tag_machine_unsupported($machine)
+ if ($end lt $today);
+ }
+ } elsif ( $model =~ m/^IBM / ) {
+ # This code ignore extended support contracts.
+ my ($producttype) = $model =~ m/.*-\[(.{4}).+\]-/;
+ if ($producttype &amp;&amp; $serial) {
+ my $content =
+ get("http://www-947.ibm.com/systems/support/supportsite.wss/warranty?action=warranty&amp;brandind=5000008&amp;Submit=Submit&amp;type=$producttype&amp;serial=$serial");
+ if ($content) {
+ $content =~ s/&lt;[^>]+?>/;/gm;
+ $content =~ s/\s+/ /gm;
+ $content =~ s/;\s*;/;;/gm;
+ $content =~ s/;[\s;]+/;/gm;
+
+ $content =~ s/^.+?;Warranty status;//;
+ my ($status, $end) = $content =~ m/;Warranty status;([^;]+)\s*;Expiration date;(\S+) ;/;
+
+ $str .= "($status) -> $end ";
+
+ my $today = POSIX::strftime("%Y-%m-%d", localtime(time));
+ tag_machine_unsupported($machine)
+ if ($end lt $today);
+ }
+ }
+ }
+ return $str;
+}
+</pre>
+
+<p>Here are some examples on how to use the function, using fake
+serial numbers. The information passed in as arguments are fetched
+from dmidecode.</p>
+
+<pre>
+print get_support_info("hp.host", "HP ProLiant BL460c G1", "1234567890"
+ "447707-B21");
+print get_support_info("dell.host", "Dell Inc. PowerEdge 2950", "1234567");
+print get_support_info("ibm.host", "IBM eserver xSeries 345 -[867061X]-",
+ "1234567");
+</pre>
+
+<p>I would recommend this approach for tracking support contracts for
+everyone with more than a few computers to administer. :)</p>
+
+<p>Update 2009-03-06: The IBM page do not include extended support
+contracts, so it is useless in that case. The original Dell code do
+not handle extended support contracts either, but has been updated to
+do so.</p>