piątek, 28 grudnia 2012

Paczkowanie LMS'a - część pierwsza


LMS od dłuższego czasu nie ma żadnego stabilnego wydania. Postanowiłem wypełnić tą lukę poprzz zapakowanie kodu w paczkę i dołączenie ją do repozytorium Debiana. Plan jest długofalowy, bo targetem jest kolejna po wheezy dystrybucja. Zobaczymy czy wystarczy mi czasu i chęci.

Przygotowanie źródeł do budowania:

1. Przygotowanie źródeł
wget https://github.com/lmsgit/lms/archive/master.zip
unzip master.zip
mv lms-master lms-1.11~git20121227
tar -cvf lms.tar.gz ./lms-1.11~git20121227
dh_make -f ../lms.tar.gz --copyright gpl2

2. Wstępnie przygotowany plik debian/control.

Source: lms
Section: admin
Priority: optional
Maintainer: Rafal Ramocki <rafal@ramocki.pl>
Build-Depends: cdbs, debhelper (>= 7.0.50~)
Standards-Version: 3.8.4
Homepage: http://lms.org.pl/
#Vcs-Git: git://git.debian.org/collab-maint/lms.git
#Vcs-Browser: http://git.debian.org/?p=collab-maint/lms.git;a=summary

Package: lms
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Lan Management System siutable for ISP
 "LMS" (LAN Management System) is the integrated system of networks management
 designed for various size internet providers (ISP).
 .
 That software writed in PHP, Perl and C, works with variuos database systems.
 It consists a friendly web user interface (frontend) and programs installed
 on servers (backend). The main features of LMS are:
 .
 - internet access administration (e.g. traffic control and stats)
 - finances with invoicing (automatic billing),
 - database of customers and network devices (network map),
 - serial mailing and administration messages to customers,
 - hosting and accounts management,
 - bug tracking system (helpdesk),
 - any services management,
 - time organizer (timetable),
 - customer web panel.

3. Przygotowany plik debian/copyright. Tutaj pomocny okazał się listy debian-devel z 2006 roku. https://lists.debian.org/debian-devel-announce/2006/03/msg00023.html.

4. Podczas przygotowywania pliku debian/rules odpowiedzialnego za budowanie pojawiła się seria problemów. Chcę budować demona - co wydaje się być oczywiste. Niestety okazuje się, że plik configure używany do wyprodukowania plików Makefile jest napisany z palca i nie akceptuje domyślnych parametrów automake. W pierwszej kolejności chciałem pominąć te parametry. Użyłem do tego dyrektywy DEB_CONFIGURE_NORMAL_ARGS, która nadpisuje wszystkie argumenty z autotools.mk. Mniej - więcej przeszło. Ale chcę też budować wersję dla postgresa i dla mysql. Tutaj niestety ściana. Skrypt konfiguracyjny zakłada, że będzie wykonywany podczas gdy użytkownik będzie w katalogu bieżącym. Niestety podczas budowy z różnymi parametrami narzędzie debianowe wykonują go nie będąc tam. Jedyne sensowne rozwiązanie jakie przychodzi mi do głowy, to poprawa pliku configure tak, by był zgodny z ogólnie przyjętymi standardami. Ponieważ mam dostęp do repozytorium LMS, to może - po konsultacjach z chiłkiem i alecem zaktualizuje globalnie, tak by w przyszłości nie było problemu. Na chwilę obecną szybka konwersja do automake (bez parametrów opcjonalnych) wygląda tak jak poniżej. Poleciałem zgodnie z http://www.galassi.org/mark/mydocs/autoconf_tutorial_2.html:

for i in `find ./ -name Makefile ` ; do echo `dirname $i` ; cd `dirname $i` ; cp Makefile Makefile.orig ; mv Makefile Makefile.in ; autoheader ; cd ~/lms_packaging/work1_temp1/lms-1.11~git20121227/daemon ; done

autoscan
mv configure.scan configure.in
autoheader
autoconf

To wyprodukowało mi potrzebną konfigurację. ./configure pokazało, że jeszcze brakuje pliku install-sh. Na chwilę obecną nie wiem do czego on ma służyć. Najmniejszą linią oporu będzie:

touch install-sh

Lecąc dalej musiałem przygotować odpowiednią wersję configure.in. Sprawa okazała się czasochłonna. O 01:46 w nocy uzyskałem działającą i implementującą wszystkie funkcje ze starego systemu konfiguracji wersję plików configure.in oraz Makefile.in. Ku potomności przedstawiam.

configure.in:
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.67])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([lmsd.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_YACC
AC_PROG_CXX
AC_PROG_CC
AC_PROG_LEX
AC_PROG_INSTALL

# Checks for libraries.
# FIXME: Replace `main' with a function in `-ldl':
AC_CHECK_LIB([dl], [main])
# FIXME: Replace `main' with a function in `-lfl':
AC_CHECK_LIB([fl], [main])
# FIXME: Replace `main' with a function in `-lgadu':
AC_CHECK_LIB([gadu], [main])
# FIXME: Replace `main' with a function in `-liberty':
AC_CHECK_LIB([iberty], [main])
# FIXME: Replace `main' with a function in `-lm':
AC_CHECK_LIB([m], [main])
AC_CHECK_LIB([pq], [PQconnectdb],
  [have_pgsql=yes
   LIBS="-lpq $LIBS"])
# FIXME: Replace `main' with a function in `-lrxspencer':
AC_CHECK_LIB([rxspencer], [main])
#AC_CHECK_LIB([mysqlclient], [mysql_fetch_row], )
AC_CHECK_LIB([mysqlclient], [mysql_fetch_row],
  [have_mysql=yes
   LIBS="-lmysqlclient $LIBS"])

# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h locale.h netinet/in.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h syslog.h unistd.h])

# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T

# Checks for library functions.
AC_FUNC_FORK
AC_FUNC_MALLOC
AC_FUNC_MKTIME
AC_FUNC_REALLOC
AC_CHECK_FUNCS([getdelim gethostname gettimeofday inet_ntoa memset pow regcomp select setlocale socket strchr strdup strerror strstr strtol strtoul])

AC_CONFIG_FILES([Makefile
                 modules/Makefile
                 modules/cutoff/Makefile
                 modules/dhcp/Makefile
                 modules/dns/Makefile
                 modules/ethers/Makefile
                 modules/ewx-pt/Makefile
                 modules/ewx-stm-channels/Makefile
                 modules/ewx-stm/Makefile
                 modules/ggnotify/Makefile
                 modules/hostfile/Makefile
                 modules/notify/Makefile
                 modules/oident/Makefile
                 modules/parser/Makefile
                 modules/parser/extensions/Makefile
                 modules/parser/lib/Makefile
                 modules/payments/Makefile
                 modules/pinger/Makefile
                 modules/system/Makefile
                 modules/tc-new/Makefile
                 modules/tc/Makefile
                 modules/traffic/Makefile])

AC_ARG_ENABLE([debug0],
    AS_HELP_STRING([--enable-debug0], [SQL query logging (disabled)]))
AC_ARG_ENABLE([debug1],
    AS_HELP_STRING([--enable-debug1], [events logging (disabled)]))
AC_ARG_WITH([mysql],
    AS_HELP_STRING([--with-mysql], [enables use of MySQL database (enabled)]))
AC_ARG_WITH([pgsql],
    AS_HELP_STRING([--with-pgsql], [enables use of PostgreSQL database (disabled)]))
AC_ARG_WITH(lmslibdir,
    [AC_HELP_STRING([--with-lmslibdir=DIR], [sets location of target LMS modules (PREFIX/lms/lib)])],
    lmslibdir="$withval",
    lmslibdir=$ac_default_prefix/lib/lms
)
AC_SUBST(lmslibdir)

# User can't choos to drivers during one build
AS_IF([test "x$with_mysql" = "xyes" && test "x$with_pgsql" = "xyes"],
     [AC_MSG_ERROR([can't build with mysql and pgsql simultanously])])

# User didn't choos SQL library? Whe chosse mysql if it's available.
# And if not we choose pgsql if its available.
AS_IF([test "x$with_mysql" = "x" && test "x$with_pgsql" = "x"],
    [AS_IF([test "x$have_mysql" = "xyes"], [with_mysql="yes"])],
    [AS_IF([test "x$have_pgsql" = "xyes"], [with_pgsql="yes"])])

# User didn't choose SQL library or we don't have any available
AS_IF([test "x$with_mysql" = "xno" && test "x$with_pgsql" = "xno"],
     [AC_MSG_ERROR([You need postgres or mysql client library])])

# User choose PGSQL library, but it isn't available
AS_IF([test "x$have_pgsql" != "xyes" && test "x$with_pgsql" = "xyes"],
     [AC_MSG_ERROR([pgsql requested but library is missing])])

# User choose MySQL library, but it isn't available
AS_IF([test "x$have_mysql" != "xyes" && test "x$with_mysql" = "xyes"],
     [AC_MSG_ERROR([mysql requested but library is missing])])

AS_IF([test "x$with_pgsql" = "xyes"],
     [AC_SUBST([DBDRIVER], [pgsql])
      CFLAGS="$CFLAGS -DUSE_PGSQL"])

AS_IF([test "x$with_mysql" = "xyes"],
     [AC_SUBST([DBDRIVER], [mysql])
      CFLAGS="$CFLAGS -DUSE_MYSQL"])

AC_OUTPUT

Makefile.in (sam początek, który musiałem dostosować)
INSTALLDIR = @INSTALL@
MODULESDIR = @lmslibdir@
LIBS = @LIBS@
LDFLAGS = @LDFLAGS@
CFLAGS = $(CPPFLAGS) @CFLAGS@ -DLMS_LIB_DIR=\"@lmslibdir@\"
DBDRIVER = @DBDRIVER@
OUT = lms
OS = $OS

środa, 26 grudnia 2012

XEN API - Słabość OpenSource prowadzonego przez komercyjne organizacje

Ostatnio stanąłem przed problemem projektowym, którego idealnym rozwiązaniem zdawała się zdalna, automatyczna instalacja zwirtualizowanego systemu, użycie go do określonego zadania i usunięcie. Wiedziałem o istnieniu XENAPI, ale nigdy nie był mi potrzebny. Tutaj xenowe api byłoby jak znalazł. Projektując takie API pewnie pierwszą z zaimplementowanych rzeczy (oprócz sprawdzania statusu) byłaby zdalna instalacja. Okazuje się, że samo API jest ułomne, OpenSourceowe API jest wykastrowane, a wersja dostępna w Debianie nie działa z powodu braku biblioteki.

Ułomność API polega na tym, że zdalna instalacja jest możliwa tylko z predefiniowanego template'u będącego w istocie zatrzymaną maszyną wirtualną z ustawioną odpowiednią flagą. Ustawienie tej flagi przez API nie jest możliwe. API w wersji OpenSource jest wykastrowane ponieważ próba użycia metody CLONE używanej do instalacji nowego systemu poprzez sklonowanie szablonu kończy się komunikatem błędu "NOTIMPLEMETED". Jest tak w wersji 4.0 jak i w 4.1. Ustawienie flagi is_a_template w debianie graniczy z cudem. Wymagane jest do tego użycie "xm new", któego użycie nie jest możliwe z powodu brakującej biblioteki.

By to wszystko ustalić potrzebowałem jednego dnia. Jedyny plus jest taki, że dowiedziałem się że można definiować maszyny wirtualne inaczej niż pliki konfiguracyjne w /etc/xen. Oprócz owych plików jest jeszcze wewnętrzny store. Użycie alternatywnej metody pozwala na wyświetlenie w xm list również maszyn zatrzymanych.
 

poniedziałek, 24 grudnia 2012

Przydatne zapytania - lista do ubicia

Czasem pojawia się konieczność ubicia najdłużej wykonujących się zapytań na bazie. Z reguły jest to sytuacja awaryjna i nie ma zbyt wiele czasu, najczęściej chodzi o to by jak najszybciej odzyskać stabilność aplikacji. W takiej sytuacji przydaje się określenie które procesy wykonują najbardziej kosztowne zapytania - te są w kolejności do ubicia. Można to osiągnąć takim oto zapytaniem:

postgres=# SELECT procpid,query_start FROM pg_stat_activity WHERE current_query != '<IDLE>' ORDER BY query_start;
 procpid |          query_start         
---------+-------------------------------
   18422 | 2012-12-24 11:12:15.877034+01
   18434 | 2012-12-24 11:40:36.074373+01
   18394 | 2012-12-24 11:40:36.648773+01
   18261 |
(4 rows)


W tym wypadku podejrzane jest pierwsze z zapytań. Wygląda na bardzo kosztowne obliczeniowo więc jest kandydatem do ubicia. Jeżeli jest na to czas, to wskazana jest weryfikacja jakie to zapytanie zostało wywołane - może być wskazana jego optymalizacja.

postgres=# SELECT current_query FROM pg_stat_activity WHERE procpid = 18422;

Mając tą listę i wiedząc co to za zapytanie można zostaje już tyko ubicie tego konkretnego zapytania. 

postgres=# SELECT pg_cancel_backend(18422);

W wyniku wywołania funkcji pg_cancel_backend() zostanie przerwane tylko zapytanie. Połączenie aplikacji nie zostanie zerwane. To, co aplikacja zrobi już bardzo mocno zależy od tego w czym jest napisana i jak bardzo przewidujących mamy deweloperów.

środa, 19 grudnia 2012

Jak replikację zestawiano....

Proste zadanie - zestawić replikację master-slave. Nic trudnego, master i slave w ramach tego samego serwera, bo replikacja ma być jedynie testowa, ale za to wymóg jest taki, że po wdrożeniu na produkcję ma być dostępny failover - czyli wszystkie tabele i sekwencje mają być replikowane. By było prościej mamy RedHat Enterprise Linux 5 i równie starego nierozwijanego od grudnia 2011 roku postgresa 8.2 . Wszystko proste z punktu widzenia deweloperów pewnie na 10 minut. Ustaliliśmy sobie że nie takie 10 minut, że ma ograniczenia i broń borze nie modyfikować struktury bazy danych, bo przy replikacji przepuszcza się to przez slonik_execute_script. Wszystko rozumieją, akceptują. Startujemy no i zaczynamy pasmo problemów.

Ponieważ replikacja ma być master-slave i ponieważ na slave mają być generowane raporty, to oczywistym wydaje się być użycie slony1. Szukamy slony1 w repozytoriach RedHata - brak. No nic okazuje się, że postgres też nie jest z instalowany z repozytoriów ponieważ RHEL 5 ma tylko PG 8.3 i 8.4. Okazuje się, że na http://yum.postgresql.org/ oprócz postgresa są też dodatki do niego w tym i pożądany slony1. Oczywiście jest informacja, że wersje dla PG 8.2 nie są wspierane. Pobieramy, instalujemy - problem w zależnościach. Nie można zainstalować bo brakuje perl(log). Dlaczego jest taka zależność i jak znaleźć tą paczkę oczywiście nie wiadomo. Po googlaniach bez rezultatu, po upewnieniu się że zainstalowane jest wszystko to co pasuje do *perl*log* i braku jakichkolwiek innych możliwości wymuszam instalację slony1. Nie via YUM, bo nie chcę niepotrzebnie aktualizować starego postgresa. Pomyślałem, że nie ma co ściągać na siebie problemów - działa, to nie naprawiaj. Jeden problem z głowy.

Zabieramy się za przygotowanie konfiguracji. Zapytania, szybka weryfikacja tabel... znowu problem. Nie wszystkie tabele nadają się do replikacji. Slony wymaga, by tabele miały albo klucz główny, albo unikalny indeks. Kilka tabel tego nie ma. Pierwszy kontakt z deweloperami by ustalić plan działania - nie ma? to se dodaj. Ale zaraz... ja tylko admin. Po krótkich przepychankach zgodzili się poprawić sami - to ich aplikacja, oni bazę projektowali. Super... mogę przygotowywać konfigurację slony1.

Pora startu i kolejne rozczarowanie. O ile np slony1 dostarczany z Debianem z automatu przewiduje konfigurację odpalenia wielu węzłów na jednej maszynie, o tyle ten z http://yum.postgresql.org takiej możliwości nie ma. Chcesz to zrobić? Musisz sobie sam poprzerabiać skrypty startowe, a właściwie z /etc/init.d/slony1 zrobić dwa lekko przerobione. Eh nic... znowu trochę czasu i kolejny problem rozwiązany.

Pora uruchomienia replikacji. Lecimy ze standardem pg_dump -s, restore, slonik_init_cluster, slonik_create_set, slonik_subcribe_set i... czekamy. Długo czekamy bo baza ma kilkadziesiąt GB. Dokładnie czekamy jakieś siedem godzin i... tadam! Działa, sprawę możemy zamykać - przynajmniej tak mi się wtedy wydawało.

Dwa dni później deweloperzy zgłaszają, że replikacja nie działa. No to patrzymy... okazuje się, że OID tabeli, taki jaki zna slony i taki jaki faktycznie jest w PG się nie zgadza. Znowu komunikacja z deweloperami - szybkie pytanie... czy robiliście drop table po zestawieniu replikacji?
- nie
- okej bo zmienił mi się OID i ktoś musiał usunąć tabelę i dodać ją ponowie
- no my nie
- aplikacja?
- aa faktycznie, ma "DROP TABLE" w jednym miejscu bo to tabela tymczasowa
Potem przeprowadziłem z deweloperami uroczą dyskusję skupiającą się na wyjaśnieniu dlaczego aplikacja nie powinna usuwać tabeli i jak to ma się do slonego - przyjęto do wiadomości. Aplikację poprawiono, można zestawiać ponownie replikację od nowa. Odpalam więc znaną sekwencję pg_dump -s, restore, slonik_init_cluster, slonik_create_set, slonik_init_set, slonik_subscribe_set - siedem godzin... gotowe! Kolejny bohatersko rozwiązany problem za nami.

Nastał poniedziałek, sprawdzam kontrolnie czy replikacja działa. Jak nie trudno się domyślić okazało się, że nie działa. Zatrzymała się w niedzielę. Ustalenia z deweloperami czy poprawili w aplikacji funkcjonalność która odpowiadała za usuwanie i tworzenie tabeli - twierdzą że tak. Często kłamią sprawdzam więc czy aby na pewno - oidy się zgadzają. Dzisiaj nie mam czasu na diagnozę, jakieś inserty nie poszły może to archaiczny slony, postgres i system. Zestawmy jeszcze raz - zobaczymy co się stanie. Zaczynam więc standardową śpiewkę  pg_dump -s, restore, slonik_init_cluster, slonik_create_set, slonik_init_set i idziemy do domu, może problem rozwiązany? Miałem jeszcze ochotę skrypt do tego napisać, ale pomyślałem, że może tym razem będzie już wszystko w porządku i nie warto.

Rano pierwsza rzecz jaką sprawdzam to replikacja... nadal się zestawia. Pierwsza myśl, to że to maszyna wirtualna, może coś innego skonsumowało CPU. Ostatnio trwało to w prawdzie siedem godzin, ale może teraz potrzebuje np 14-u. Nic, mam inne rzeczy do zrobienia, poczekam. W połowie dnia się nadal zestawia, coś nie tak, ale nie mam czasu na to więc niech jeszcze popracuje... uporałem się ze sprawami bieżącymi wrócę. Pod koniec dnia nadal się zestawia. Coś nie tak. Weryfikacja logów slony1 okazuje się, że nie może skopiować jednej tabel ze względu na różną ilość kolumn na masterze i slave po czym startuje jeszcze raz licząc pewnie żę tym razem się doliczy brakującej na slave kolumny.  Westchnąłem tylko i uderzam do deweloperów z pytaniem:
- modyfikowaliście schemę
- ja nie
- bo wiesz replikacja się nie zestawiła, bo ktoś dodał kolumnę
- a to? To ja zleciłem a robił X....
Po krótkiej powtórce z ograniczeń slonego i replikacji oraz stwierdzeniu, ze jak jeszcze raz ktoś mi samowolnie schemę zmodyfikuje to łapki pourywam, posadzę i dam się nimi pobawić możemy zaczynać znaną już sekwencję. Wcześniej sprawdzam, czy nie poprawili czegoś w związku z niereplikowanymi tabelami. Okazuje się, że poprawili - wszystkie z wyjątkiem jednej. No nic dodaję do slon_tools.conf i jedziemy ze znaną procedurą pg_dump -s, restore, slonik_init_cluster, slonik_create_set, slonik_init_set i idziemy do domu.

Rano sprawdzamy czy replikacja działa... ku mojemu zaskoczeniu tak. Super, pora poruszyć temat niereplikowanej jeszcze tabeli bez klucza głównego i bez unikalnego indeksu. Deweloperzy znowu twierdzą, ze przecież sam mogę sobie dodać, bo tabela jest prosta, tylko dwie kolumny. Zwykle nie wyręczam deweloperów w takich sprawach, ale to już tyle trwa - sam dodałem ten indeks. Przyglądam się dokładniej - okazuje się, że unikalny indeks jest... hmmm pomylili się? A może ja? Dodaję do konfiguracji slonego seta i dodaję do replikacji. Niestety przy próbie utworzenia seta slony stwierdził, że nie może mi tego zrobić, bo nie ma odpowiedniego indeksu. Szukanie informacji i oczywistym się staje że indeks musi być nie tylko unikaly, ale równeiż "NOT NULL". Po weryfikacji okazuje się, że obie kolumny na których założony jest indeks akceptują NULLe. Konsultacje z deweloperami - to zmień. Niech im będzie - i tak to za długo trwa. Dwa altery później można było dodać tabelę do replikacji - mamy komplet - hura! Czyżby to koniec problemów?

Kilka dni później sprawdzam czy replikacja działa - niestety nie działa, deweloperzy tego jeszcze nie zauważyli. Sprawdzam, Znowu wisimy na insercie do tabeli podczas gdy podobny rekord już jest... co jest nie tak? A no pytanie gdzieś czuje, ze ktoś wykonał TRUNCATE na tabeli. Oczywiście deweloperzy w pierwszym kontakcie mówią, że nie ma w aplikacji komendy TRUNCATE. Jak mówię, że tak jak ostatnio stało się to około siódmej rano to nagle nastało olśnienie, że przecież aplikacja ma rano jakieś zadanie w czasie którego aktualizuje tą tabelę i podczas aktualizacji tej niemałej tabeli jest tabela obcinana. Wiedziałem, że slony nie replikuje TRUNCATE, ale postanowiłem sprawdzić czy się nie mylę. Okazało się, że od postgresa 8.4 można założyć trigger na TRUNCATE. Z racji tego, że slony działa właśnie w oparciu o triggery, to może to jest pora by pozbyć się starego PG 8.2 z poza systemu i zainstalować nowszego, pochodzącego z dystrybucji postgresa 8.4. Proponuję deweloperom - akceptacja. Dziś już nie zdążę, zacznę następnego dnia.

Nastał nowy dzionek. Lecimy z aktualizacją postgresa. Dump bazy. Przesuwam profilaktycznie katalog data na bok. Usuwam postgresa 8.2, instaluję 8.4. Migruję ustawienia z 8.2 do 8.4 - pomiędzy tymi wersjami kilka dyrektyw się zmieniło, część zniknęła a część zmieniła format - nie tak łatwo, ale do przejścia. Po dostosowaniu konfiguracji startujemy i wgrywamy dumpa. Z racji czasochłonności tego procesu to by było na tyle jeżeli chodzi o to zadanie w tym dniu. W zasadzie problem TRUNCATE mam już rozwiązany, ale zobaczymy jutro.

Następnego dnia okazało się, że dump się skończył, ale część tabel jest pusta. O co chodzi? Oczywiście firewall klienta jest na tyle sprytny, że po pewnym czasie zrywa połączenia, a ja na tyle niesprytny, że zapomniałem o screenie. No to lecimy jeszcze raz z odtworzeniem bazy danych. W momencie gdy kończyłem pracę nadal się odtwarzało więc, znowu dzień w plecy, ale problem zasadniczo rozwiązany.

Przychodzę do pracy master dump się wgrał. Fajnie, pytanie czy aplikacja działa, ale może uruchomię jeszcze proces zestawiania replikacji. Znana bajeczka...  pg_dump -s, restore, slonik_init_cluster... i dupa, nieznane symbole bibliotece slonego ładowanej do postgresa. O co chodzi? A no o to, że po aktualizacji slonego nie zaktualizowałem slonika, ale by dojść do tego potrzebna znowu była godzina czytania - nie lubię ani redhata, ani paczek z http://yum.postgresql.org. Debianowcy radzą sobie z tym lepiej. Tak czy siak wymiana slony1 na slony1-II i lecimy dalej z bajeczką: slonik_create_set, slonik_init_set, slonik_subscribe_set  i czekamy. Do końca dnia zestawiać się nie skończyła, więc zobaczymy jutro, ale przecież dużo problemów już nie może być przede mną.

Nastał nowy piękny dzień. Deweloperzy testują i... trafiają na problem. Kilka zapytań raportowych się nie wykonuje. Okazuje się, że postgres pluje błędem informującym, że nie może porównać typu "text" z "int". Znowu szybkie ustalenia za deweloperów i okazuje, się że w postgresie 8.3 usunięto "implicit casts". Miało to na celu poprawę wydajności postgresa. Okazało się też, że można ponownie dodać tą funkcjonalność dodając odpowiednie rzutowania typów za pomocą tego, gotowego zestawu komend: http://wiki.postgresql.org/wiki/File:Pg83-implicit-casts.sql Proponuje deweloperom takie rozwiązanie, ale Ci stwierdzają, że już w aplikacji zamienili ten TRUNCATE na DELETE i chcą powrotu do wersji 8.2. Ech, odpisuję na maila upewniając się, że chcą się wycofać w tym momencie.... oby nie.

Następnego dnia otrzymuję potwierdzenie. Cofamy się do poprzedniej wersji postgresa. No nic, dobrze że przynajmniej zachowałem sobie stary katalog data z postgresa 8.2. Odinstalowuję wersję 8.4 i slonego, instaluję postgresa 8.2, instaluję slonego. Uruchamiam... działa. Czy to koniec? Okazuje się, że nie. Przez przypadek usunąłem bibliotekę potrzebną przez httpd, a z nim cały httpd. No nic, instalujemy jeszcze raz - przecież to 5 minut. Okazuje się, że jednak nie, bo te 40MB (aktualizacja danych o repo + sam apache) idzie jak krew z nosa. Nie wiem co się dzieje ale zaczęły już mi się przypominać czasy modemowe. No dobra, po 40-u minutach mamy httpd,

Czy aplikacja jest dostępna? Nie, było by za łatwo, dostaję 404. Znowu ustalenia, i okazuje się, żę brakuje mod_jk. Nic prostrzego yum search i.... nie ma. W RHEL nie ma mod_jk - bo po co ułatwiać zadania. Na szczęście. Ten kto przygotowywał system w /root/ zostawił źródła. Pewnie ze źródeł było instalowane. Wg dokumentacji configure i... nie ma axps. No dobra, to nie problem doinstalujemy. yum instal i modem. Bajty przeciskają się przez miedź niczym klej przez słomkę. Zrobiło się na prawdę nostalgicznie. Mam czas, tyle to już trwa, potrwa jeszcze te trzydzieści minut. Jest, no to znowu configure, make, make install. Aplikacja jest dostępna. Informacja w stronę deweloperów. Potwierdzają jest OK! Sukces! No prawie... replikacja niby prosta, a wyszło zadanie na dwa tygodnie z kawłkiem.

Czy życie nie może być proste...