Magento und UPS Shipping

Das UPS Shipping für Magento erstellt in jedem Fall nur UPS Aufkleber über das Testsystem, egal welche Daten man für den UPS Server einträgt. Das liegt daran, dass im UPS Modul fest wwwcie.ups.com eingetragen ist. Ich hatte schon vor Ewigkeiten einen Patch im Magento Bugtracker hinterlegt, aber leider besteht ja keine Möglichkeit das ausser Magento jemand an diese Patches herankommt. Falls also noch jemand Code benötigt um korrekte UPS Label zu erzeugen ist hier der Patch (leider nur als core Patch möglich).

Konfiguration UPS Shipping Label
Konfiguration UPS Shipping Label
Index: app/code/core/Mage/Usa/etc/system.xml
===================================================================
--- app/code/core/Mage/Usa/etc/system.xml       (revision 164118)
+++ app/code/core/Mage/Usa/etc/system.xml       (working copy)
@@ -735,14 +735,46 @@
                             <show_in_website>1</show_in_website>
                             <show_in_store>0</show_in_store>
                         </gateway_url>
+                                               <domain_xml_url_live translate="label">
+                            <label>Gateway XML Domain Live</label>
+                            <frontend_type>text</frontend_type>
+                            <sort_order>30</sort_order>
+                            <show_in_default>1</show_in_default>
+                            <show_in_website>1</show_in_website>
+                            <show_in_store>0</show_in_store>
+                        </domain_xml_url_live>
+                                               <domain_xml_url_debug translate="label">
+                            <label>Gateway XML Domain Debug</label>
+                            <frontend_type>text</frontend_type>
+                            <sort_order>30</sort_order>
+                            <show_in_default>1</show_in_default>
+                            <show_in_website>1</show_in_website>
+                            <show_in_store>0</show_in_store>
+                        </domain_xml_url_debug>
                         <gateway_xml_url translate="label">
-                            <label>Gateway XML URL</label>
+                            <label>Gateway XML URL Rate</label>
                             <frontend_type>text</frontend_type>
                             <sort_order>30</sort_order>
                             <show_in_default>1</show_in_default>
                             <show_in_website>1</show_in_website>
                             <show_in_store>0</show_in_store>
                         </gateway_xml_url>
+                        <shipconfirm_xml_url translate="label">
+                            <label>Gateway XML URL ShipConfirm</label>
+                            <frontend_type>text</frontend_type>
+                            <sort_order>30</sort_order>
+                            <show_in_default>1</show_in_default>
+                            <show_in_website>1</show_in_website>
+                            <show_in_store>0</show_in_store>
+                        </shipconfirm_xml_url>
+                        <shipaccept_xml_url translate="label">
+                            <label>Gateway XML URL ShipAccept</label>
+                            <frontend_type>text</frontend_type>
+                            <sort_order>30</sort_order>
+                            <show_in_default>1</show_in_default>
+                            <show_in_website>1</show_in_website>
+                            <show_in_store>0</show_in_store>
+                        </shipaccept_xml_url>
                         <handling_type translate="label">
                             <label>Calculate Handling Fee</label>
                             <frontend_type>select</frontend_type>
Index: app/code/core/Mage/Usa/etc/config.xml
===================================================================
--- app/code/core/Mage/Usa/etc/config.xml       (revision 164118)
+++ app/code/core/Mage/Usa/etc/config.xml       (working copy)
@@ -164,12 +164,12 @@
                 <dest_type>RES</dest_type>
                 <free_method>GND</free_method>
                 <gateway_url>http://www.ups.com/using/services/rave/qcostcgi.cgi</gateway_url>
-                <gateway_xml_url>https://onlinetools.ups.com/ups.app/xml/Rate</gateway_xml_url>
+                <gateway_xml_url>/ups.app/xml/Rate</gateway_xml_url>
                 <handling>0</handling>
                 <model>usa/shipping_carrier_ups</model>
                 <pickup>CC</pickup>
                 <title>United Parcel Service</title>
-                <tracking_xml_url>https://www.ups.com/ups.app/xml/Track</tracking_xml_url>
+                <tracking_xml_url>/ups.app/xml/Track</tracking_xml_url>
                 <unit_of_measure>LBS</unit_of_measure>
                 <username backend_model="adminhtml/system_config_backend_encrypted"/>
                 <password backend_model="adminhtml/system_config_backend_encrypted"/>
@@ -180,6 +180,10 @@
                 <handling_action>O</handling_action>
                 <negotiated_active>0</negotiated_active>
                 <mode_xml>1</mode_xml>
+                               <domain_xml_url_live>onlinetools.ups.com</domain_xml_url_live>
+                               <domain_xml_url_debug>wwwcie.ups.com</domain_xml_url_debug>
+                <shipconfirm_xml_url>/ups.app/xml/ShipConfirm</shipconfirm_xml_url>
+                <shipaccept_xml_url>/ups.app/xml/ShipAcept</shipaccept_xml_url>
                 <type>UPS</type>
             </ups>
             <usps>
Index: app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php
===================================================================
--- app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php       (revision 164118)
+++ app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php       (working copy)
@@ -95,23 +95,6 @@
     protected $_xmlAccessRequest = null;

     /**
-     * Default cgi gateway url
-     *
-     * @var string
-     */
-    protected $_defaultCgiGatewayUrl = 'http://www.ups.com:80/using/services/rave/qcostcgi.cgi';
-
-    /**
-     * Default urls for shipment
-     *
-     * @var array
-     */
-    protected $_defaultUrls = array(
-        'ShipConfirm' => 'https://wwwcie.ups.com/ups.app/xml/ShipConfirm',
-        'ShipAccept'  => 'https://wwwcie.ups.com/ups.app/xml/ShipAccept',
-    );
-
-    /**
      * Container types that could be customized for UPS carrier
      *
      * @var array
@@ -125,6 +108,37 @@
      * @return Mage_Shipping_Model_Rate_Result|bool|null
      */

+       protected function _getUpsUrlCgiGateway()
+       {
+        $url = $this->getConfigData('gateway_url');
+               if (!$url) {
+                       $_url = 'http://www.ups.com:80/using/services/rave/qcostcgi.cgi';
+               }
+               return ($url);
+       }
+
+       protected function _getUpsUrlXmlService($service)
+       {
+               if((boolean)$this->getConfigFlag('mode_xml')) {
+                       $url = "https://" . $this->getConfigData('domain_xml_url_live');
+               } else {
+                       $url = "https://" .$this->getConfigData('domain_xml_url_debug');
+               }
+               switch($service) {
+                       case 'Track':           $url .= $this->getConfigData('tracking_xml_url');
+                               break;
+                       case 'Rate':            $url .= $this->getConfigData('gateway_xml_url');
+                               break;
+                       case 'ShipConfirm':     $url .= $this->getConfigData('shipconfirm_xml_url');
+                               break;
+                       case 'ShipAccept':      $url .= $this->getConfigData('shipaccept_xml_url');
+                               break;
+                       default:
+                               throw new Exception(Mage::helper('usa')->__('Invalid service type >%s< for UPS API', $service));
+               }
+               return ($url);
+       }
+
     public function collectRates(Mage_Shipping_Model_Rate_Request $request)
     {
         if (!$this->getConfigFlag($this->_activeFlag)) {
@@ -379,10 +393,7 @@
         if ($responseBody === null) {
             $debugData = array('request' => $params);
             try {
-                $url = $this->getConfigData('gateway_url');
-                if (!$url) {
-                    $url = $this->_defaultCgiGatewayUrl;
-                }
+                $url = $this->_getUpsUrlCgiGateway();
                 $client = new Zend_Http_Client();
                 $client->setUri($url);
                 $client->setConfig(array('maxredirects'=>0, 'timeout'=>30));
@@ -790,7 +801,7 @@
      */
     protected function _getXmlQuotes()
     {
-        $url = $this->getConfigData('gateway_xml_url');
+        $url = $this->_getUpsUrlXmlService('Rate');

         $this->setXMLAccessRequest();
         $xmlRequest=$this->_xmlAccessRequest;
@@ -1143,7 +1154,7 @@
      */
     protected function _getXmlTracking($trackings)
     {
-        $url = $this->getConfigData('tracking_xml_url');
+        $url = $this->_getUpsUrlXmlService('Track');

         foreach($trackings as $tracking){
             $xmlRequest=$this->_xmlAccessRequest;
@@ -1356,6 +1367,9 @@
         $height = $packageParams->getHeight();
         $width = $packageParams->getWidth();
         $length = $packageParams->getLength();
+               Mage::Log("DEBUG: " . $packageParams->getWeightUnits(), 0);
+               Mage::Log("DEBUG: " . $packageParams->getWeightUnits(), 0);
+
         $weightUnits = $packageParams->getWeightUnits() == Zend_Measure_Weight::POUND ? 'LBS' : 'KGS';
         $dimensionsUnits = $packageParams->getDimensionUnits() == Zend_Measure_Length::INCH ? 'IN' : 'CM';

@@ -1559,7 +1573,7 @@

         $debugData = array('request' => $xmlRequest->asXML());
         try {
-            $url = $this->_defaultUrls['ShipAccept'];
+            $url = $this->_getUpsUrlXmlService('ShipAccept');

             $ch = curl_init($url);
             curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
@@ -1612,10 +1626,7 @@
         $xmlResponse = $this->_getCachedQuotes($xmlRequest);

         if ($xmlResponse === null) {
-            $url = $this->getConfigData('url');
-            if (!$url) {
-                $url = $this->_defaultUrls['ShipConfirm'];
-            }
+                       $url = $this->_getUpsUrlXmlService('ShipConfirm');

             $debugData = array('request' => $xmlRequest);
             $ch = curl_init();

phpmyadmin und der nicht sichtbare „Benutzer“ Tab

Ich nutze ab und an phpmyadmin. Gerade zum überprüfen der Benutzerrechte finde ich das ganz praktisch. Umso nerviges ist es, wenn der phpmyadmin Benutzer angeblich selber keine GRANT Rechte hat. Wenn man Google fragt gibt es das Problem ziemlich häufig und meitens liegt es halt wirklich daran das dem phpmyadmin Benutzer GRANT Rechte fehlen. Aber zumindest bei mir liegt es nicht an fehlenden Rechten der phpmyadmin Benutzers, sondern an einem Problem von phpmyadmin selber (aktuell gerade wieder mit 3.5.3-rc1 aufgetreten). Auf dem IRC Channel #phpmyadmin bekam ich den richtigen Tipp, der fehlende Tab liegt an einem fehlerhaften Cookie. Und tatsächlich, nachdem ich eben alle phpmyadmin Cookies gelöscht habe taucht der Benutzer Tab wieder auf. Das ist IMHO ein ziemlich nerviger Fehler…

rsync und inotify Schnittstelle bzw. incrond

Ich nutze gerne den incrond um Konfigurationsdateien zu überwachen. Für ein aktuelles Setup wollte ich eine Kombination von rsync und incrond benutzen, um vor dem Einsatz der neuen Konfigurationsdatei automatisiert ein Backup anzulegen. Meine incrond.d Datei sah so aus:

/home/eximsync/exim4.conf IN_CLOSE_WRITE /opt/mystuff/bin/eximsync

Das funktionierte soweit auch ganz gut, allerdings immer nur genau für eine Änderung bzw. einen rsync Lauf. Nach einiger Grübelei war dann auch klar warum, rsync erstellt jedesmal eine neue Datei wenn man ein Update vornimmt und der Watch (inotify) verliert dann seine Gültigkeit. Die Lösung für dieses Problem ist simpel, einfach die rsync Option –inplace benutzen und schon bleibt der Watch bestehen. Man muss nur erst einmal darauf kommen das die inotify Schnittstelle ja nicht den Dateinamen überwacht (der sich nicht ändert), sondern die Datei selber (die durch rsync ja gelöscht wird).

HowTo: Firmwareupdate für OCZ-VERTEX2 SSD mit Debian squeeze

Ich habe heute die Firmware von einer OCZ-VERTEX2 SSD, die in einem Rootserver bei dem Provider serverloft, steht aktualisiert. Ganz so einfach, wie ich mir das anfangs vorgestellt habett ging es aber nicht, daher hier eine Kurzanleitung.

Im ersten Schritt habe ich die aktuelle SSD Firmware für die OCZ-VERTEX2 von OCZ. über die URL http://www.ocztechnology.com/ssd_tools/OCZ_Vertex_2,_Vertex_LE,_Agility_2/ geholt, bzw. bin ich von dort in einem Forum gelandet. In dem Forum steht, dass für ein Update von der Firmware < 1.25 ein anderer Download benötigt wird. Also erstmal ein Update vor dem Update durchführen, man kennt das ja. Und so wie es aussieht bietet OCZ nur ein vorbereitetes Linux ISO an um ein Firmwareupdate durchzuführen. Meine erster Gedanke war die in dem Server verbaute IPMI Karte dafür zu nutzen, nur leider ermöglicht die IPMI Lizenz von serverloft nur die Verwendung einer Textkonsole. Da die Bildschirmfotos im Forum eindeutig grafikbasierte sind habe ich da gar nicht weitergesucht ob das funktionieren würde. Zumal ich mit der IPMI Karte bei serverloft sowieso div. Probleme habe und da auch scheinbar nicht der einzige bin. Eigentlich funktioniert der Zugriff auf die IPMI Karte immer nur sporadisch, wirklich zuverlässig ist das nicht.

Da die zur Aktualisierung der Firmware notwendigen Programme ansonsten nicht zum Download zur Verfügung stehen habe ich mir diese aus dem ISO extrahiert. Im ersten Schritt wird dazu das ISO heruntergeladen, entpacket und über das Loopdevice einhängt.

cd /root
wget http://www.ocztechnology.com/files/ssd_tools/ocz-tools-xxx.zip
unzip ocz-tools-xxx.zip
mkdir iso
mount -o loop ocz-tools-xxx.iso iso

Jetz können wir uns den Inhalt der CD ansehen und finden ziemlich fix die Datei tinycore.gz die als initrd Image dient. Dort müssen die für uns notwendigen Tools enthalten sein, also fix den Inhalt auspacken mit:

mkdir ozc
cd ozc
zcat ../iso/boot/tinycore.gz | cpio -i

Dann sehen wir uns ein wenig um und finden unter home/tc/ocz/apps das Programm für die Durchführung der Firmwareaktualisierung. In den Scripten unter home/tc/ocz steht in den Kommentaren auch, dass die Firmware direkt von OCZ heruntergeladen wird, also brauchen wir nur das Programm fwupd aus dem Verzeichnis home/tc/ocz/apps kopieren. Den Rest der CD benötigen wir nicht, die ausgepackete initrd kann gleich wieder gelöscht werden und das per Loopdevice eingehängte ISO ausgehängt werden. Wir können jetzt das eigentliche Firmwareupdate starten (Warnhinweise beachten!) mit:

./fwupd -log /dev/sd?

Das wurde dann erstmal mit der Fehlermeldung:

-su: ./fwupd: Datei oder Verzeichnis nicht gefunden

kommentiert. Häh, was zum Teufel soll das? Ein kurzer Blick in die Datei zeigt, ja das ist ein binäres Executable und kein Shellscript. Nochmal kurz in die Datei geschaut, ja das ist definitv ein 32-bit ELF executable. Moment, 32-bit da war doch was… Und genau, ich hatte bisher die ia32-libs noch nicht auf dem System installiert. Also fix noch ein:

aptitude install ia32-libs
Die folgenden NEUEN Pakete werden zusätzlich installiert:
  ia32-libs lib32asound2{a} lib32bz2-1.0{a} lib32gcc1{a} lib32ncurses5{a} lib32stdc++6{a} lib32v4l-0{a} lib32z1{a} libc6-i386{a} libv4l-0{a}
0 Pakete aktualisiert, 10 zusätzlich installiert, 0 werden entfernt und 0 nicht aktualisiert.
Muss 39,4 MB an Archiven herunterladen. Nach dem Entpacken werden 96,8 MB zusätzlich belegt sein.
Wollen Sie fortsetzen? [Y/n/?]
Hole:1 http://ftp.de.debian.org/debian/ squeeze/main libc6-i386 amd64 2.11.3-3 [3.813 kB]
Hole:2 http://ftp.de.debian.org/debian/ squeeze/main lib32bz2-1.0 amd64 1.0.5-6+squeeze1 [39,5 kB]
Hole:3 http://ftp.de.debian.org/debian/ squeeze/main lib32asound2 amd64 1.0.23-2.1 [327 kB]
Hole:4 http://ftp.de.debian.org/debian/ squeeze/main lib32gcc1 amd64 1:4.4.5-8 [55,2 kB]
Hole:5 http://ftp.de.debian.org/debian/ squeeze/main lib32ncurses5 amd64 5.7+20100313-5 [345 kB]
Hole:6 http://ftp.de.debian.org/debian/ squeeze/main lib32stdc++6 amd64 4.4.5-8 [347 kB]
Hole:7 http://ftp.de.debian.org/debian/ squeeze/main libv4l-0 amd64 0.8.0-1 [105 kB]
Hole:8 http://ftp.de.debian.org/debian/ squeeze/main lib32v4l-0 amd64 0.8.0-1 [75,7 kB]
Hole:9 http://ftp.de.debian.org/debian/ squeeze/main lib32z1 amd64 1:1.2.3.4.dfsg-3 [76,1 kB]
Hole:10 http://ftp.de.debian.org/debian/ squeeze/main ia32-libs amd64 20120102 [34,2 MB]
39,4 MB wurden in 9 s heruntergeladen (4.375 kB/s)
Vormals abgewähltes Paket libc6-i386 wird gewählt.
(Lese Datenbank ... 36297 Dateien und Verzeichnisse sind derzeit installiert.)
Entpacken von libc6-i386 (aus .../libc6-i386_2.11.3-3_amd64.deb) ...
libc6-i386 (2.11.3-3) wird eingerichtet ...
Vormals abgewähltes Paket lib32bz2-1.0 wird gewählt.
(Lese Datenbank ... 36599 Dateien und Verzeichnisse sind derzeit installiert.)
Entpacken von lib32bz2-1.0 (aus .../lib32bz2-1.0_1.0.5-6+squeeze1_amd64.deb) ...
Vormals abgewähltes Paket lib32asound2 wird gewählt.
Entpacken von lib32asound2 (aus .../lib32asound2_1.0.23-2.1_amd64.deb) ...
Vormals abgewähltes Paket lib32gcc1 wird gewählt.
Entpacken von lib32gcc1 (aus .../lib32gcc1_1%3a4.4.5-8_amd64.deb) ...
Vormals abgewähltes Paket lib32ncurses5 wird gewählt.
Entpacken von lib32ncurses5 (aus .../lib32ncurses5_5.7+20100313-5_amd64.deb) ...
Vormals abgewähltes Paket lib32stdc++6 wird gewählt.
Entpacken von lib32stdc++6 (aus .../lib32stdc++6_4.4.5-8_amd64.deb) ...
Vormals abgewähltes Paket libv4l-0 wird gewählt.
Entpacken von libv4l-0 (aus .../libv4l-0_0.8.0-1_amd64.deb) ...
Vormals abgewähltes Paket lib32v4l-0 wird gewählt.
Entpacken von lib32v4l-0 (aus .../lib32v4l-0_0.8.0-1_amd64.deb) ...
Vormals abgewähltes Paket lib32z1 wird gewählt.
Entpacken von lib32z1 (aus .../lib32z1_1%3a1.2.3.4.dfsg-3_amd64.deb) ...
Vormals abgewähltes Paket ia32-libs wird gewählt.
Entpacken von ia32-libs (aus .../ia32-libs_20120102_amd64.deb) ...
lib32bz2-1.0 (1.0.5-6+squeeze1) wird eingerichtet ...
lib32asound2 (1.0.23-2.1) wird eingerichtet ...
lib32gcc1 (1:4.4.5-8) wird eingerichtet ...
lib32ncurses5 (5.7+20100313-5) wird eingerichtet ...
lib32stdc++6 (4.4.5-8) wird eingerichtet ...
libv4l-0 (0.8.0-1) wird eingerichtet ...
lib32v4l-0 (0.8.0-1) wird eingerichtet ...
lib32z1 (1:1.2.3.4.dfsg-3) wird eingerichtet ...
ia32-libs (20120102) wird eingerichtet ...

Danach nochmal das Progrann für die Firmwareaktualisierung gestartet und es sieht schon viel besser aus:

./fwupd
fwupd v2.14.03: update drive firmware/bios

Usage: fwupd [-log] [-force] [-cfg] [-bios] [-pkg package | -loc location] <device> [device ...]
Options:
 -log           Enable logging
 -force         Force firmware update
 -cfg           Print the config and return
 -bios          Enable BIOS update
 -pkg pkgname   Enable updating from local firmware package "pkgname"
 -loc location  Enable updating from specified location on webserver

device can be:
 - device paths separated by space

        ./fwupd -log /dev/sda /dev/sdb /dev/sdc

 - device paths with wildcards * and ?

        ./fwupd -log /dev/sd*
        ./fwupd -log /dev/sd?

 - range of device paths

        ./fwupd -log /dev/sd[a-d]

Ja, das sieht richtig aus. Also jetzt das ganze nochmal mit den richtigen Parametern gestartet und voila, es geht:

./fwupd -log  /dev/sdc
fwupd v2.14.03: update drive firmware/bios

/dev/sdc:

        Model Number     :   OCZ-VERTEX2
        Serial Number    :   OCZ-N7D5EXYxxxxxxxx
        Firmware Revision:   1.24

Accessing firmware file...

Updating firmware...............
Firmware update succeeded.

        Model Number     :   OCZ-VERTEX2
        Serial Number    :   OCZ-N7D5EXYxxxxxxxx
        Firmware Revision:   1.37

Danach habe ich das System neu gestartet und die gleiche Prozedur nochmal mit dem aktuellen ISO für die Firmware durchgeführt. Dort heisst das Programm zur Aktualisierung der Firmware nun clout, aber da sich die Firmware der SSD von mir nicht weiter aktualisieren liess lasse ich den Teil weg wie ich dieses Programm ausgepackt habe, es geht im Prinzip genau wie mit der alten ISO Datei. Lohn der Mühe ist das die SSD jetzt auch das TRIM Kommando versteht:

hdparm -I /dev/sdc

/dev/sdc:

ATA device, with non-removable media
        Model Number:       OCZ-VERTEX2
        Serial Number:      OCZ-N7D5EXYxxxxxxxx
        Firmware Revision:  1.37
        Transport:          Serial
Standards:
        Used: unknown (minor revision code 0x0028)
        Supported: 8 7 6 5
        Likely used: 8
Configuration:
        Logical         max     current
        cylinders       16383   16383
        heads           16      16
        sectors/track   63      63
        --
        CHS current addressable sectors:   16514064
        LBA    user addressable sectors:  117231408
        LBA48  user addressable sectors:  117231408
        Logical  Sector size:                   512 bytes
        Physical Sector size:                   512 bytes
        Logical Sector-0 offset:                  0 bytes
        device size with M = 1024*1024:       57241 MBytes
        device size with M = 1000*1000:       60022 MBytes (60 GB)
        cache/buffer size  = unknown
        Nominal Media Rotation Rate: Solid State Device
Capabilities:
        LBA, IORDY(can be disabled)
        Queue depth: 32
        Standby timer values: spec'd by Standard, no device specific minimum
        R/W multiple sector transfer: Max = 16  Current = 16
        DMA: mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 udma4 udma5 *udma6
             Cycle time: min=120ns recommended=120ns
        PIO: pio0 pio1 pio2 pio3 pio4
             Cycle time: no flow control=120ns  IORDY flow control=120ns
Commands/features:
        Enabled Supported:
           *    SMART feature set
                Security Mode feature set
           *    Power Management feature set
           *    Write cache
           *    Look-ahead
                Host Protected Area feature set
           *    WRITE_BUFFER command
           *    READ_BUFFER command
           *    NOP cmd
           *    DOWNLOAD_MICROCODE
                SET_MAX security extension
           *    48-bit Address feature set
           *    Mandatory FLUSH_CACHE
           *    FLUSH_CACHE_EXT
           *    SMART error logging
           *    SMART self-test
           *    General Purpose Logging feature set
           *    WRITE_{DMA|MULTIPLE}_FUA_EXT
           *    64-bit World wide name
           *    IDLE_IMMEDIATE with UNLOAD
           *    WRITE_UNCORRECTABLE_EXT command
           *    Segmented DOWNLOAD_MICROCODE
           *    Gen1 signaling speed (1.5Gb/s)
           *    Gen2 signaling speed (3.0Gb/s)
           *    Native Command Queueing (NCQ)
           *    Host-initiated interface power management
           *    Phy event counters
           *    DMA Setup Auto-Activate optimization
                Device-initiated interface power management
           *    Software settings preservation
           *    SMART Command Transport (SCT) feature set
           *    SCT LBA Segment Access (AC2)
           *    SCT Error Recovery Control (AC3)
           *    SCT Features Control (AC4)
           *    SCT Data Tables (AC5)
           *    Data Set Management TRIM supported (limit 1 block)
           *    Deterministic read data after TRIM
Security:
                supported
        not     enabled
        not     locked
                frozen
        not     expired: security count
                supported: enhanced erase
        400min for SECURITY ERASE UNIT. 400min for ENHANCED SECURITY ERASE UNIT.
Logical Unit WWN Device Identifier: 5e83a9xxxxxxxx
        NAA             : 5
        IEEE OUI        : e83a97
        Unique ID       : fa3f62bf7
Checksum: correct

Auch wenn der Weg ziemlich umständlich war hat es sich doch gelohnt. Zusammen mit einem aktuellen Kernel unterstützt die SSD nun das TRIM Kommando unter Linux und ich konnte als Dateisystem nun beruhigt ext4 benutzen benutzen und bin nicht mehr nilfs2 angewiesen. In den nächsten Tagen muss ich mich noch mit dem batch discard auseinandersetzen, die eigentlich dafür vorgesehen mount Option „discard“ nutze ich im Moment nicht.

Piwik funktioniert nach einem Update nicht mehr, PHP Fatal error: Class ‚Piwik_Db_Schema_Myisam‘ not found in

Seit ein paar Tagen spinnt eine Piwikinstallation von mir mit einem bekanntem Bug (PHP Fatal error:  Class ‚Piwik_Db_Schema_Myisam‘ not found in /var/www/…/piwik/core/Db/Schema.php on line 150) oder auch die Diskussion im Piwik Forum. Die Folge ist das man beim Aufruf von Piwik anstelle der Statistiken nur den Hinweis „lade Daten …“ sieht oder eine PHP Fehlermeldung oder gar nichts. Nach etwas suchen konnte ich relativ schnell den Fehler #3049 im Piwikbugtracker finden, aber die vorgeschlagenen Lösungen wie den APC Cache zu löschen (z.B. einfach mit diesem PHP Shellcode)

<?php
if (function_exists('apc_clear_cache')) {
        if (apc_clear_cache() && apc_clear_cache('user'))
                print 'All Clear!';
        else
                print 'Clearing Failed!';
        print '<pre>';
        print_r(apc_cache_info());
        print '</pre>';
}
?>

oder APC für diesen vhost (per .htaccess) zu deaktivieren

php_flag apc.cache_by_default Off

brachten mich nicht weiter. Aber als ich testweise prüfen wollte, ob es wirklich an APC liegt und ein

aptitude remove php-apc

sofortigen Erfolg brachte war ich doch überrascht. Interessant ist das es selbst nach der erneuten Installation APC weiterhin mit Piwik funktioniert. Ich muss bei Gelegenheit nochmal suchen warum das löschen des APC Caches nicht hilft, aber eine Deinstallation mit anschliessender Neuinstallation von APC schon.

Ok, 1h später heißt es jetzt wieder „Lade Widget, bitte warten…“ bzw. „error while loading data (SecurityError)“. Ich muss der Sache jetzt auf den Grund gehen …

Update vom 18.06.2012

Ich denke ich habe jetzt mit folgenden Einstellungen in der apc.ini Erfolg:

extension=apc.so

apc.enabled=1
apc.shm_size=512M
apc.num_files_hint=10000
apc.user_entries_hint=10000
apc.max_file_size=5M
apc.stat=1
apc.optimization=0
apc.shm_segments=1
apc.enable_cli=1
apc.cache_by_default=1
apc.include_once_override=0
;apc.lazy_functions=1
;apc.lazy_classes=1
apc.file_md5=1

Zusätzlich nutze ich jetzt noch die APC Version 3.1.9 (über squeeze Backports installiert). Damit läuft Piwik seit dem 14.06.2012 wieder stabil.

Piwikeinbindung für Magento

Für einen Onlineshop, an dem ich beteiligt bin, war ich auf der Suche nach einer datenschutzkonformen Möglichkeit des Trackings. Wie viele bin ich nach relativ kurzer Zeit auf Piwik gestossen und habe mir diese Software genauer angesehen. Relativ neu ist eine extra Ecommerce API die sehr interessant aussah. Leider gab es bei Piwik direkt kein Plugin was für unserer Shopsystem (Magento) geeignet ist. Nach etwas Suche im Magento Connect wurde ich fündig. Es gibt zwei Magentoerweiterungen die eine Integration von Piwik in Magento versprechen:

  • pvePlus – Ist keine direkte Einbindung von Piwik, sondern eher die Möglichkeit Piwik einzubinden durch Übergabe von Trackingparametern an eine Piwikinstallation. Die Beschreibung der Erweiterung ist deutsch und liest sich sonst ganz gut. Die 149.00€ wären mit Sicherheit gut angelegt, wenn Piwik wirklich eingebunden wäre. Aber so muss man schauen das man die Integration selber vornimmt und die dafür notwendigen URL Parameter anpasst. Nachdem ich ein wenig über die Magentointernas gelernt habe dürfte das über rewrites innerhalb der Erweiterung funktionieren. Rewrites an sich sind nichts schlechtes, aber in der Regel hat man auch eine SEO Erweiterung und die wird sich auch an die Rewrites hängen und wer weiss ob das immer hinhaut?
  • Piwik Integration Pro – Ist ganz frisch vom 20.05.2012 und war bei meiner ersten Suche noch nicht veröffentlich. Dementsprechend gibt es auch noch keine Anwenderberichte oder Kommentare. Diese Erweiterung kostet $34.99. Viel mehr kann ich dazu leider nicht sagen. Falls jemand diese Erweiterung getestet hat wäre ein Kommentar dazu wirklich sehr nett.
  • Jirafe Ecommerce Analytics – Sieht auf den ersten Blick am besten aus, kostet nichts und hat viele Installation vorzuweisen. Wenn man sich aber die Anwenderkommentare durchliest wird einem schnell klar wo der Haken ist. Diese Erweiterung nutzt zwar Piwik, sendet die Daten aber zur Auswertung (oder auch hier) an den Hersteller der Erweiterung Jirafe und damit ist der datenschutzkonforme Einsatz dieser Erweiterung fast nicht möglich.

Da die Piwik Integration Pro bei meiner ersten Suche noch nicht veröffentlich war, habe ich mich hingesetzt und selber angefangen eine Magentoerweiterung für Piwik zu schreiben. Mein Ziele waren dabei:

  • Die Erweiterung soll so wenig Abhängigkeiten wie möglich haben, d.h. keine Änderungen an Dateien vornehmen oder Klassen von Magento überschreiben.
  • Die Erweiterung soll alle Möglichkeiten von Piwik nutzen soweit das irgendwie möglich ist.
  • Nach der Installation soll die Erweiterung einfach über das Magentobackend konfigurierbar sein.

Hier ist ein Bild von der Piwikkonfiguration im Backend:

Piwikkonfiguration in Magento.

Das schöne an der Erweiterung ist, das sie wirklich alles ausnutzt was aktuell mit Magento & Piwik möglich ist. Ich habe auch bereits einen Erweiterungsvorschlag an Piwik eingereicht um die Auswertung noch weiter zu verbesseren. Zumindest auf Seiten von Magento wäre dies kein Problem.

Noch ist die Piwikerweiterung nicht 100% fertig, ich muss noch einige Dinge verbessern und vor allem noch etwas testen. Aber ich denke in den nächsten Tagen werde ich zumindest eine Betaversion der Erweiterung veröffentlichen. Eine große Baustelle ist noch eine mögliche Filterkonfiguration von unerwünschten Request. Wir nutzen in unseren Shop z.B. die SuperStage Erweiterung um Produktbilder als Vollbild darzustellen. Diese Erweiterung erzeugt leider bei der Produktansicht einen zweiten Request der das Piwiklog nur unnötig füllt.

Für den Abschluss noch ein Bild aus dem Piwik Dashboard vom Piwik „Besucher-Log“.

Piwikansicht „Besucher-Log“ mit aktiven Ecommercetracking.

Ich denke in den nächsten Tagen werde ich mehr berichten können und dann auch schon eine Betaversion zeigen können.

WordPress und OpenID und das Drama nimmt seinen Lauf…

Nachdem ich gestern abend in den versprochenen 5 Minuten WordPress installiert hatte wollte ich heute gleich schauen ob es für WordPress die Möglichkeit gibt als OpenID Consumer zu fungieren. Ein kurzer Blick auf die vorhandenen WordPress Plugins sah erst einmal gut aus. Es gibt folgende OpenID Plugins für WordPress:

  • OpenID sieht am vielversprechendsten aus und hat auch die meisten Empfehlungen.
  • Loginza ist leider nur in russisch (?) verfügar.
  • LiberatID ist ein eigener Dienst der als Option auch die Möglichkeit bietet andere OpenID Provider zu nutzen.
  • Social Login ist ein Dienst der erst mit einem Konto auf der Seite des Pluginanbieters funktioniert. Mit Sicherheit nicht das was ich will.

Anhand der Liste habe ich mich dann für OpenID entschieden und die Installation war in 2-3 Minuten erledigt. Allerdings funktionierte die Anmeldung mittels OpenID nicht. Das ist blöd, liegt aber vermutlich daran, dass ich den RC von WordPress 3.4 installiert habe.

Ich muss noch dazu sagen, das ich einen eigenen OpenID Server nutze der auf OpenID-LDAP-PHP basiert. Dieser Dienst greift auf ein Windows AD zu und somit ist es möglich sich überall wo eine OpenID Anmeldung möglich ist sich mit seinem Windowsbenutzernamen und Passwort anzumelden. Das hört sich erstmal unsicher an, aber man muss bei OpenID immer daran denken, dass die Verarbeitung des Benutzernamens und Passwortes beim OpenID Server durchgeführt wird. In meinem Fall also auf meinem eigenen Server. Daher sehe ich da keine Probleme. Zusätzlich nutze ich noch einen OTP Token c200, um selbst bei einem mitgeloggtem Passwort noch eine zusätzlich Hürde zu haben.

Nachdem ich dann etwas Diagnose betrieben habe stellte sich heraus, dass es Probleme mit dem SSL Zertifikat auf dem OpenID Server gibt. Da ich ein „echtes“ SSL Zertifikat von StartSSL nutze war mir erst nicht klar wo das Problem liegt. Aber ein testweise abgesetztes:

curl https://openid.anolo.de

curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). If the default bundle file isn't adequate, you can specify an alternate file using the --cacert option.

If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL).

If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option.

Zeigte dann doch deutlich, ja da ist ein Problem. Ich habe daraufhin erstmal die üblichen Tests gemacht und ein IE oder FireFox hatte kein Problem mit der Seite. Das ca-certificates Paket war auch installiert und die Ubuntu Version 12.04 war ja gerade einmal ein paar Wochen alt. Ich habe daraufhin angefangen zu schauen warum das SSL Zertifikat nicht akzeptiert wird und viele abenteuerliche Tipps und Tricks gesehen die ich hier lieber nicht wiedergebe. Wirklich hilfreich und gut beschrieben war allerdings dieses HowTo cURL: Adding/Installing/Trusting New Self-Signed Certificate. Nachdem ich das durchgearbeitet hatte und auch mittels Add StartSSL to trusted CA store in OpenSSL geprüft hatte ob der Hash für das SSL Zertifikat korrekt ist und immer noch die cURL Fehlermeldung kam ich langsam ins grübeln was da noch schief laufen könnte. Und dann kam mir die rettende Idee, das Zwischenzertifikat für das SSL Zertifikate auf dem OpenID Server war nicht das richtige. Ich hatte irgendwann vor Monaten das Zertifikat ausgetauscht und das neue Zertifikat nur fix mit einem aktuellen Browser geprüft. Das blöde war nur, das neue SSL Zertifikat benötigte ein anderes Zwischenzertifikat. Anstelle von SSLCertificateChainFile sub.class1.server.ca.pem mußte es für die neue Zertifikate dieses hier sein: sub.class2.server.ca.pem. Man kann das übrigend relativ gut mit OpenSSL prüfen oder online mit dem Dienst SSL Installation Diagnostics – Check SSL Certificate. Nachdem ich nun das richtige Zwischenzertifikat installiert hatte war auch cURL zufrieden.

Beim nächsten Test meldete das WordPress OpenID Plugin Fehler in der XML Struktur der Seite. Das sah dann so aus:

[OpenID] Library Error 2: DOMDocument::loadXML(): Specification mandate value for attribute style in Entity, line: 16 in /var/www/wp-content/plugins/openid/Auth/Yadis/XML.php :237, referer: https://claas.hilbrecht.name/wp-login.php?finish_openid=1&identity_url=https%3A%2F%2Fopenid.anolo.de%2Fclaas.hilbrecht&redirect_to=https://claas.hilbrecht.name/wp-admin/&_wpnonce=xxxxxxx

Also musste ich erst einmal die Fehler in der Seitenstrukur beseitigen. Meine erste Anlaufstelle bei solchen Problemen ist immer der W3C Markup Validation Service. Nachdem ich dann reichlich Fehler in dem Dokument beseitigt hatte bekam ich aber dann doch sprichtwörtlich grünes Licht und endlich waren alle XML Fehler beseitigt.

Also auf zum nächsten Versuch mit dem WordPress OpenID Plugin. Und leider funktioniert es immer noch nicht. Jetzt wurde eine veraltete Funktion vom OpenID Plugin gemeldet:

get_userdatabylogin is <strong>deprecated</strong> since version 3.3! Use get_user_by('login') instead

Also erstmal den alten Code durch

get_user_by('login',

ersetzt und einen neuen Version gewagt. Und was soll ich sagen? Immer noch nichts. Nachdem ich mich jetzt 6h mit dem Problem auseinandergesetzt habe lasse ich das erst einmal liegen. Ich denke morgen werde ich noch einen Versuch starten und mir zwischendurch ansehen ob es irgendwelche API Änderungen in der Version 3.4 gegeben hat.

Die ersten Schritte als Blogger

Heute starten meine ersten Schritte als Blogger. Bei der Gelegenheit will ich gleich etwas positives über Webtropia berichten (auf einem Professional-S Server läuft dieser Blog). Die komplette Einrichtung des Server war in wenigen Stunden erledigt und ich konnte loslegen. Ganz zufrieden bin ich allerdings nicht, die Ubuntu 12.04 Installation als Raid sieht nach der Standardinstallation so aus:

Filesystem Size Used Avail Use% Mounted on
/dev/md0 927G 16G 866G 2% /
udev 7.9G 4.0K 7.9G 1% /dev
tmpfs 3.2G 276K 3.2G 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 7.9G 0 7.9G 0% /run/shm

Das sieht nicht ganz so aus wie ich mir das vorgestellt habe, aber ich hatte sowieso vor die Installation von Hand per iLO nochmal selber durchzuführen. Ziel der Aktion ist ein Rootserver mit Ubuntu + KVM und der Konfiguration der VM per virt-manager von einer Konsole @work. Aber ich denke bevor ich damit die nächsten Tage starte werde ich das mit KVM + Webtropia erst einmal weiter testen und mich vor allem mit WordPress vertraut machen.

PS: Ich teste das ganze hier mit dem Release Candidate von WordPress 3.4