środa, 23 grudnia 2009

HP SmartArray P410i - what a piece of shit!

Platforma DL 160 jest oferowana w 2 wersjach 4x3,5" i 8x2,5". Pierwsza wersja jest NO Hotplug podłączona do kontrolera INTEL ICH10R, kolejna ma już kieszonki na dyski i działa na kontrolerze HP SmartArray P410i/ZM ( nie da się z niego zrezygnować, przynajmniej mi się nie udało )

Co do samego kontrolera HP SmartArray P410i, jest to urzadzenie które z premedytacją ukrywa dyski przed systemem więc przy instalacji debiana był 1wszy zonk, gdzie mam go zainstalować?

Pomęczyłem troche support HP i dostalem w koncu odpowiedz: "NIE DA SIE".
Ba, support był wielce zdziwiony że jak to chce wyłączyć funkcje raid w ich kontrolerze, przecież to nie będzie działać...
Pewnie tak samo sie dziwił dział zamówień że zamówilismy serwery bez cdromów... lol

Wcześniej miałem doczynienia z serwerami Fujitsu-Siemens i do głowy mi nie przyszło że taki absurd może się pojawić, ale cóż, to tylko hp.

Obejściem tego okazało się zrobienie fizycznej macierzy RAID z poziomu narzędzia zwanego ORCA - taki mini bios tego kontrolera, cholernie ograniczony z minimalną ilością opcji.
Teraz zamiast mieć wszędzie raid softwarowy przez to badziewie jesteśmy zmuszeni do robienia wyjątków w konfiguracji i korzystania z raidu softwarowego. Oczywiście tak samo wygląda sprawa w przypadku S.M.A.R.T - hp daje swoje własne narzędzie. Oczywiscie pod debianem to kolejny klopot bo daja to w RPM-ach do Redhata.

Kolejna sprawa to wydajność, domyślnie SmartArray ma wyłączoną opcję buforowania zapisu, więc działa baaardzo słabo. Ale troche magi w narzędziu zwanym hpacucli, czyli:

=> ctrl slot=4 modify drivewritecache=enable

i udało się to włączyć.

Naszczęscie kontroler ten poprawnie rozpoznał dyski INTEL-a, a tu miałem trochę wątpliwości bo nikt nie był mi w stanie tego potwierdzić. Niby wspiera SATA, ale kto wie jakie ficzery HP mógł tam dopisać...

Ciekawe jak będę zmieniał firmware w tych dyskach skoro nie mam do nich dostępu z systemu...

Podsumowując: narazie działają, ale ciągle żałuje że ich nie wyrzuciłem i nie zastąpiłem np INTELEM SASUC8I który ma tzw RAID-passthrough więc dyski sa normalnie widoczne.

wtorek, 30 czerwca 2009

rcov plugin overwrites its results

tak sie dzieje dla zadania rake test:test:rcov, testy funkcjonalne nadpisuja jednostkowe itd...
Dlatego dodałem prosty task:



for test_task in %w(test:units test:functionals test:integration)
task_name = "rcov:set_proper_output_directory_for_#{test_task.gsub(/(test:)/,'')}".to_sym
task task_name do |t, args|
t.name =~ (/set_proper_output_directory_for_(.*)/); test_type=$1
RcovTestSettings.output_dir = File.expand_path("./coverage/#{test_type}")
end
task test_task.to_sym => task_name
end


który uruchamia się przed każdym testem i ustawia poprawny katalog gdzie rcov ma zapisywać.
Inne rozwiazanie znalazłem na blogu ale nie udało mi się go uruchomić(nie bawiłem sie nad tym):

niedziela, 31 maja 2009

Multiple database connections in Rails with tests and fixtures

Kolejnym problemem okazało sie wykorzystanie fixturek w testach które miały by działać na różnych bazach.

Same fixturki można ładnie rozrzucić po różnych katalogach:
fixtures/
import/
i ładować je przez
fixtures :"import/fixture_name"
jednak domyślnie klasa Fixturek korzysta z ActiveRecord::Base.connection więc cały plan legnie w gruzach.
W tym miejscu na ratunek wychodzi kolejny plugin: use_db
script/plugin install git://github.com/remi/use_db.git
W modelach zamiast estabilish_connection dajemy:
use_db :prefix => "import_", :rails_env => RAILS_ENV.split('_').last
self.abstract_class = true
Plugin ten nadpisuje domyślne ładowanie fixturek i jeśli znajdzie pasujący model do fixturki który korzysta z use_db to wykorzysta Model.connection zamiast AR::Base.connection do operacji ładowania danych.

Co do wypełnienia bazy schemą to wykorzystałem loopy_multiple_databases:
RAILS_ENV=import_development rake db:test:load
niestety w samych testach nie działa odwoływanie się do fixturek przez
fixture_name(:rekord)
więc trzeba rekordy wczytywać ręcznie, ale jeszcze nad tym będę pracował.

Linki:
use_db blog entry
use_db fixed git clone

czwartek, 28 maja 2009

Multiple database connections in Rails

w obecnym projekcie wykorzystuje naraz 3 różne bazy danych, dodatkowo ostatni typ jest shardowany - czyli występuje na wielu maszynach.

O ile dostęp do wielu baz naraz można uzyskać przez definicje w stylu
development:
<<: *dev_basics
database: import_sharded
host: 127.0.0.1

import_development:
<<: *dev_basics
database: import
host: 127.0.0.1
a następnie przez stworzenie modeli Proxy:
class ImportProxy < ActiveRecord::Base
establish_connection "import_#{RAILS_ENV.split('_').last}"
end
o tyle problem pojawia się w migracjach - jak zapewnić aby migracje działały na różnych bazach ?

Sprawa okazała się trywialna:
class CreateImportOffers < ActiveRecord::Migration
def self.connection
ImportProxy.connection
end

def self.up
create_table :offers do |t|
wystarczyło nadpisać metode connection.

Tu jednak sprawa sie nie kończy bo jak pisałem na wstępie mamy to do czynienia z bazami shardowanymi a informacje o przeprowadzponych migracjach są trzymane tylko w 1 miejscu,
czyli jesli serwer S1 wykonal wszystkie migracje - czesc globalnych a czesc lokalnie na swojej bazie , zakładam że główne połączenie jest do bazy wspólnej to serwer S2 już nic nam nie będzie chciał zrobić a jego baza lokalna pozostanie pusta. Odwracając sytuacje gdzie główne połączenie jest na bazie lokalnej to wystąpi konflikt przy migracjach na bazie wspólnej - 1 z serwerów nie będzie wiedział że migracje już zostały wykonane.

Rozwiązanie ? Może 2 osobne projekty - 1 działający na maszynach shardowanych a 2gi działający na maszynie wspólnej ?

Taki też był pierwszy pomysł, ale w rzeczywistosci oba projekty różniły by się jedynie katalogiem migracji i plikiem databases.yml - wszystko inne było by w jakiś sposób linkowane.
Bez sensu.

Naszczescie znalazlem gotowe rozwiązanie tego problemu - plugin loopy_multiple_databases

Co to mi dało ?

Teraz mam możliwosc spearacji migracji per środowisko - osobne podkatalogi w db/migrate, w zależniości od sposobu uruchamiania wykonuje się inny zestaw migracji:
RAILS_ENV=import_development rake db:migrate:up VERSION=20090520143515
RAILS_ENV=development rake db:migrate:up VERSION=20090520113821
domyślne zadanie rake db:migrate zostało nadpisane i powoduje wykonanie migracji na wszystkich zdefiniowanych środowiskach poprzez uruchomienie:
RAILS_ENV=srodowisko rake db:migrate_without_other_databases

wtorek, 19 maja 2009

Rake - multiple task execution / invocation

standardowo taski Rake dają się uruchomić tylko raz, ponowne ich wywołanie nic nie daje.
Problem z którym się spotkałem polagał na tym aby móc uruchomić pojedyńczy task z konsoli jak i wykonać serie pojedyńczych tasków z innego zadania rake. Poniższy przykład wszystko wyjaśni:

task :start do
$queue = Queue.new
$queue << start_jobs =""> [:working1, :working2] do
puts "start_jobs END"
end

task :working1 do
process_shop(1)
end

task :working2 do
process_shop(2)
end

def process_shop(worker_id)
while true do
shop_id = $queue.pop(false)
puts "[#{worker_id}]processing shop: #{shop_id}"
t = Rake::Task['shop_job']
t.reenable
t.invoke(shop_id, worker_id)
sleep 1
end
rescue
end

task :shop_job, [:shop_id, :worker_id] do |t, args|
puts " [#{args.worker_id}]hello from shop_job #{args.shop_id}"
end