Pages

Εμφάνιση αναρτήσεων με ετικέτα service. Εμφάνιση όλων των αναρτήσεων
Εμφάνιση αναρτήσεων με ετικέτα service. Εμφάνιση όλων των αναρτήσεων

Παρασκευή 31 Μαΐου 2013

Ubiquity UniFi Controller Software στο Raspberry PiUbiquity UniFi Controller Software on Raspberry Pi

Εισαγωγή

Introduction

Βασικά η ιστορία συνεχίζεται από προηγούμενο άρθρο που βρίσκεται σε αυτό το blog. Για να υπάρξει μια σύνδεση με τα προηγούμενα, θα γίνει μια γενική περιγραφή του προβλήματος. Στη συνέχεια θα δούμε λίγα πράγματα για ένα εργαλείο που θα χρησιμοποιήσουμε (το Raspberry Pi) για τη λύση του προβλήματος και θα προχωρήσουμε στον τρόπο που ακολουθήθηκε για να επιτευχθεί το επιθυμητό αποτέλεσμα.

The story continues from an earlier post posted in the current blog. For clarity and connection to the previously mentioned information, there will be a general description of the problem. Then we will get to know the tool we use in this article (Raspberry Pi) for the solution of the problem and we will present the way we followed to reach our goal.

Επιγραμματικά ακολουθούν:

Briefly:

Το βασικό πρόβλημα

The Problem

Το βασικό κομμάτι που μας ενδιαφέρει εδώ, είναι το στήσιμο ενός δικτύου ξενοδοχείου. Αυτό, με τη σειρά του, συνεπάγεται όλο το καλό πακέτο του ελέγχου σύνδεσης των πελατών, ποσού διακίνησης δεδομένων κ.λ.π. Αυτό το επιτυγχάνουν επαρκώς και με το παραπάνω τα Access Points της Ubiquity. Η χρήση ενός UniFi Outdoor Access Point λύνει όλα τα προβλήματα δικτύωσης. Το μόνο μειονέκτημα (και αυτό που μας απασχολεί στο παρόν άρθρο) είναι πως θα πρέπει να υπάρχει ένα μηχάνημα που να τρέχει το software της εταιρίας για τον έλεγχο και τη διαχείριση του δικτύου. Αυτό με τη σειρά του συνεπάγεται κατανάλωση ενέργειας για PC, θόρυβος από τα ανεμιστηράκια του, απαραίτητη χρήση UPS που να αντέχει σε μεγάλες διακοπές ρεύματος, license του λειτουργικού του συστήματος αν πρόκειται για μηχάνημα που τρέχει Bugindows, συχνές επανεκκινήσεις λόγω των προβλημάρων του αναφερόμενου λειτουργικού κ.λ.π. Ειδικα τα δύο τελευταία προβλήματα (που είναι και τα πιο σημαντικά) λύθηκαν με την εγκατάσταση λειτουργικού Linux και συγκεκριμένα της διανομής openSUSE, όπως φαίνεται και σε άλλο άρθρο του ίδιου blog.

The basic part in question at this point is a network setup for a hotel. This means the whole packet of services for controlling client access, bandwidth limiting per client, data quota etc. For Ubiquity's Access Points this is only part of their capabilities. Usage of a UniFi Outdoor Access Point is the solution for all our networking problems. The only drawback (and what is covered in this article) is the necessity of a computer running the controller software for all the network monitoring and managing, 24 hours a day. And this, in turn, leads to much energy consumption from a PC, noise from its fans, the necessity of UPS usage that is able to keep the system up during long duration power failures, license for its operating system if it runs Bugindows, probably frequently reboots because of this (non) operating system and many more... Especially the two last problems we presented (which are the most important) were solved by installing a Linux distribution; more specifically openSUSE, as presented in a previous article in this blog.

Η λύση των υπολοίπων προβλημάτων διερευνήθηκε περισσότερο για να βρει ο γράφων δουλειά να κάνει (!!! Τι πρωτότυπο :)). Δεν είναι κάτι άλλο από το πασίγνωστο, πλέον στο χώρο των gadgetάκιδων, Raspberry Pi.

The research for solutions to the other problems started just for the author to kill some of his spear time (!!! How rare :)). The research led to, famous in the gadget lovers' cycles, Raspberry Pi.

Raspberry Pi ως server...

Raspberry Pi as a server...

Το Raspberry Pi είναι ένας υπολογιστής, όπως ακριβώς κι ένα κινητό. Η διαφορά του είναι πως δεν έχει οθόνη. Τι διαθέτει αυτός ο υπολογιστής (βασικά χαρακτηριστικά):

Raspberry Pi is a small computer, just like a smartphone. Its difference is the lack of a screen. Part of its specifications are presented:

  • Επεξεργαστής: ARM στα 700MHz, με δυνατότητα Overclocking στο 1GHz
  • Processor: ARM running at 700MHz, with Overclocking capability up to 1GHz
  • Μνήμη: 256 MBytes η παλιά έκδοση (Α), 512 MBytes η έκδοση Β
  • Memory: 256 MBytes at the old version (Α), 512 MBytes at its newer version, Β
  • Ethernet: 10/100 Mbit
  • Video out: Δε μας ενδιαφέρει. Server θέλουμε να το κάνουμε, αλλά ως άχρηστη πληροφορία της ημέρας διαθέτει έξοδο HDMI και TVWe don't care. We want to use it as a server, but as useless information of the day it has HDMI and Composite Video outputs
  • USB: 2 πόρτεςports
  • Boot: από κάρτα μνήμηςfrom an SD Card
  • Τροφοδοσία: 5V με μικρή κατανάλωση ρεύματος (μέγιστη στα 700mA στην έκδοση Β)
  • Power: 5V having small power consumption (maximum 700mA on version Β)

Αυτά τα χαρακτηριστικά το κάνουν ιδανικό για χρήση ως server. Δίνουν, επίσης, τη δυνατότητα να μπορέσει να τροφοδοτηθεί, αργότερα, από ένα σύστημα UPS που να παράγει τα 5V που χρειάζονται απ' ευθείας από τη μπαταρία του. Κατά συνέπεια μια διακοπή της ΔΕΗ για... πολλές ώρες δεν θα το ενοχλήσει :)

These specifications make this thing ideal for making a server. They also give it the ability to be, later, powered by a small UPS system that supplies 5V DC straight from a battery, without the need of inverters and 220V AC. So, a power failure because of the power company for... looong duration won't bother the system :)

Άλλο ένα καλό του εν λόγω gadget είναι πως πάρα πολλές διανομές Linux έχουν στηθεί για το Raspberry Pi· ακόμα και FreeBSD μπορούμε να βρούμε (αν και κανονικά αυτό δεν πρέπει να μας κάνει εντύπωση!). Μιας και την τελευταία φορά που έστησα το σύστημα του UniFi Controller ήταν επάνω σε openSUSE, δοκίμασα την εν λόγω διανομή και στο Raspberry Pi. Τα αποτελέσματα ήταν θαυμάσια. Το μόνο περίεργο ήταν η εγκατάσταση της Java, αλλά δεν ήταν κάτι που να αξίζει αναφοράς.

Another plus of this gadget is that there are so many Linux distributions running on Raspberry Pi right now; you can even find FreeBSD (though this should not impress us!). Since my last time I set up UniFi Controller was in an openSUSE Linux, I also tried it in Raspberry Pi. The results were marvellous. The only weird thing was the Java installation, but nothing worth mentioning here.

Κάτι που με "έτρωγε" ήταν πως αν κάποιος πάρει ένα Raspberry Pi και θελήσει να ασχοληθεί με τη χρήση του σε δίκτυο, όπως και αυτό που ήταν το έναυσμα για αυτή την ιστορία, τότε αμφιβάλλω αν θα ασχοληθεί με το να βάλει openSUSE· σίγουρα θα ασχοληθεί με το "έτοιμο" Raspbian που είναι βασισμένο επάνω στη διανομή Debian. Οπότε, για να μπορέσω να συμβάλλω και σε αυτό τον τομέα θα έπρεπε να δοκιμάσω αυτή τη διανομή για τις "ταρζανιές".

Something that really made me worried was that if someone gets a Raspberry Pi and wants to use it like what described in this article then I doubt he/she will install openSUSE; I bet on the default Raspbian operating system that is based on Debian. So, for me to be a contributor at this part I should use this distribution for all the play.

Το Στήσιμο

The Setup

Το στήσιμο του συστήματος δεν είναι καθόλου δύσκολο. Μπορεί κάποιος να κατεβάσει το κατάλληλο image και να το γράψει σε μια κάρτα μνήμης SD, ή να χρησιμοποιήσει το BerryBoot. Η δεύτερη επιλογή απλά θα προσθέσει μερικά δευτερόλεπτα στο bootάρισμα του συστήματος, αλλά αν κάποιος θέλει να "παίξει" με το Raspberry τότε είναι μια καλή λύση.

The system's setup is not difficult at all. Anyone can download the correct OS image that suits his/her needs and write it in an SD Memory Card. Alternatively BerryBoot can be used. The latter will just add some seconds during boot up of the system, but if somebody wants to "play" with Raspberry then it is a marvellous choice.

Η κάρτα που χρησιμοποιήθηκε στο στήσιμό μας είναι μια 8GB SD Class 10. Δίνει αρκετό χώρο για "παιχνίδια", ενώ είναι αρκετά γρήγορη για ένα ικανοποιητικό χρόνο εκκίνησης. Εκεί εγκαταστάθηκε το Raspbian, ρυθμίστηκε για λίγο overclocking (800 MHz) και έγινε και expand το partition που περιέχει το λειτουργικό. Αυτά, επειδή δεν υπήρχε πληκτρολόγιο στο Raspberry, έγινε μέσω ssh, εκτελώντας από εκεί το raspi-config.

The memory card used here is a 8GB SD Class 10. It gives much space to play, while at the same time is very fast for a short boot time. There was Raspbian installed, configured for some overclocking (800 MHz) and the partition containing the operating system was expanded. Because of lack of a keyboard connected to Raspberry, all these were done through ssh, running raspi-config.

Σε γενικές γραμμές η εγκατάσταση του συστήματος δε νομίζω πως χρειάζεται παρουσίαση. Όλα υπάρχουν στο Internet και είναι αρκετά κατανοητά για κάποιον ο οποίος αποφασίζει να ασχοληθεί με το Raspberry. Έτσι, οι λεπτομέρειες της εγκατάστασης λειτουργικού και ενεργοποίησης του συστήματος, καθώς επίσης και της αναβάθμισης του λογισμικού δεν περιγράφονται.

In general, the system installation was smooth and it doesn't worth mentioning. Every tip and information on that lies in the Internet and are crystal clear for anybody who wishes to use Raspberry Pi. So, all these installation details as well as those for updating the operating system are not presented.

Η αρχική εγκατάσταση περιέχει ένα χρήστη με το όνομα pi, ο οποίος ανήκει στο group pi, έχει password το raspberry, ενώ το όνομα του συστήματος στο δίκτυο είναι raspberrypi. Φυσικά, σε όλα αυτά έγιναν αλλαγές, οπότε ο χρήστης του συστήματος ονομάστηκε elias (λέμε τώρα!), το αρχικό group του χρήστη έχει το ίδιο όνομα, ενώ το δικτυακό όνομα του συστήματος έγινε unificontroll και διάφορα άλλα μικροσεταρίσματα.

The default installation has a user named pi, who belongs to pi group, identified by raspberry as password and the network name of the system is raspberrypi. Of course, changes have been made to all of these settings, so the user name now becomes elias (well, for the clarity of this article!), the initial user's group has the same name and the network name becomes unificontroll. There were also some minor alterations on the setup not worth mentioning.

Προεργασία

Groundwork

1. Εγκατάσταση Java
1. Java Installation

Για να λειτουργήσει το UniFi Controller χρειάζεται τη βάση δεδομένων mongodb και τη γλώσσα Java να είναι εγκαταστημένα στο σύστημα. Για τη Java δεν υπάρχει κάποιο πρόβλημα, μιας και είναι έτοιμη σε πακέτο .deb για το Raspbian. Αρκεί ένα

For UniFi Controller to be able to operate, it needs mongodb database and Java programming language installed in the target system. Java is no problem since there is already a .deb package for Raspbian. Just execute:

elias@unificontrol:~ > sudo apt-get install openjdk-7-jdk
[sudo] password for elias:
.
.
.

2. Εγκατάσταση MongoDB
2. MongoDB Installation

Το περίεργο της υπόθεσης είναι πως δεν υπάρχει πακέτο για MongoDB (τουλάχιστον μέχρι τη στιγμή που γράφεται το παρόν άρθρο). Κατά συνέπεια μπαίνουμε σε διαδικασίες compile κ.λ.π. Μετά από λίγο ψάξιμο βρέθηκε ένα πολύ καλό άρθρο για την εγκατάσταση της mongopi που είναι η μεταφορά της εν λόγω βάσης δεδομένων στο Raspberry. Το συγκεκριμένο άρθρο που βρέθηκε δίνει πληροφορίες για την εγκατάσταση ενός ολόκληρου συστήματος με πολλά Raspberries. Η περιγραφή που θα γίνει στο παρόν άρθρο είναι μόνο για την εγκατάσταση της MongoDB, ως το σημείο που χρειάζεται για να λειτουργήσει με το UniFi Controller.

Perhaps it is strange, but there is no package available for MongoDB (at least at the time of this writing). So, we have to proceed to other procedures like compiling etc. After some searching through the internet there was an article found for mongopi installation, which is the database in question patched for Raspberry. This article gives information for the whole process of a system with many Raspberries setup. The description in here, will be only for MongoDB installation, up to the necessary point to be functional and usable by UniFi Controller.

Ο κώδικας της mongopi είναι στο github. Για να γίνει η εγκατάσταση θα πρέπει να εγκατασταθούν πρώτα το git και κάτι ψιλά... Ξεκινάμε με την εγκατάσταση των απαραίτητων πακέτων γι' αυτή τη δουλειά:

mongopi code is available to download in github. For the total installation process to be complete, git and some other packages as well, must be installed... Lets start all these necessary installations:

elias@unificontrol:~ > sudo apt-get install git-core build-essential scons \
   libpcre++-dev xulrunner-dev libboost-dev \
   libboost-program-options-dev libboost-thread-dev \
   libboost-filesystem-dev
.
.
.

Στη συνέχεια κλωνοποιήσουμε το αποθετήριο με τα αρχεία της mongopi από το github:

OK. Now lets clone the mongopi repository from github:

elias@unificontrol:~ > git clone git://github.com/RickP/mongopi.git

Η συνέχεια θέλει υπομονή... Ώρα για compilation... Αυτό γίνεται με τη βοήθεια του εργαλείου scons και μπορεί να πάρει αρκετές ώρες (περίπου 4):

What follows needs patience... Time to compile the code... This is done using a tool named scons and it may take some hours (well, about 4):

elias@unificontrol:~ > cd mongopi
elias@unificontrol:~/mongopi > scons

Μετά από... λίγη ημέρα :) το compilation θα έχει τελειώσει. Συνέχεια έχει η εγκατάσταση. Αυτή θα χρειαστεί μόνο... 3 ώρες!...

After some... day passes :) the compilation process will be over. Installation follows. This will take only about... 3 hours!...

elias@unificontrol:~/mongopi > sudo scons --prefix=/opt/mongo install

Αυτή η εντολή θα εγκαταστήσει τη mongopi στον κατάλογο /opt/mongo. Φυσικά η όλη διαδικασία έπιασε και υπερβολικό χώρο στην κάρτα μνήμης (περίπου 2GB) οπότε καλό είναι να σβήσετε τον κατάλογο που περιέχει τον πηγαίο κώδικα:

That command will install mongopi in /opt/mongo directory. Naturally, the whole compilation/installation process allocated a huge space in the memory card (something around 2GB) so it is very good thing to delete the directory that contains the source code:

elias@unificontrol:~/mongopi > cd ..
elias@unificontrol:~ > sudo rm -rf mongopi
elias@unificontrol:~ > 

Καλό είναι να μπει στο PATH του συστήματος ο κατάλογος με τα εκτελέσιμα της MongoDB για να είναι εύκολη η διαχείριση των βάσεών της. Αυτό γίνεται απλά με την προσθήκη του στο αρχείο .bashrc της ακόλουθης γραμμής:

It is also a nice idea to insert into the PATH system variable the directory that contains all the executables of MongoDB, for easy access during databases administration. Just insert the following line in .bashrc file:

export PATH=$PATH:/opt/mongo/bin

Σε αυτό το σημείο η εγκατάσταση της MongoDB έχει γίνει. Αν χρειαστεί να τη χρησιμοποιήσετε και σε άλλες εφαρμογές, τότε πιθανό είναι να πρέπει να δημιουργήσετε και τον κατάλογο /data/db στο σύστημά σας. Αυτό στην περίπτωση του UniFi Controller δεν είναι απαραίτητο γιατί τη δικιά του βάση δεδομένων την κρατάει σε δικό του κατάλογο.

We reached the point that MongoDB is installed in the system. If you are going to also use it in other applications you possibly have to create /data/db directory, or mongo will complain. In the case of just using it only with UniFi Controller that step can be omitted, because it uses its own directory for the database contents.

Εγκατάσταση UniFi Controller

UniFi Controller Installation

Η εγκατάσταση του UniFi Controller δεν έχει κάποια δυσκολία. Σε γενικές γραμμές είναι ίδια με αυτή που έχει γίνει και σε προηγούμενο άρθρο σε άλλη έκδοση του λειτουργικού Linux

UniFi Controller installation is not difficult at all. It is about the same as described in a previous article in another Linux distribution.

Ξεκινάμε με το να δημιουργήσουμε ένα group με το όνομα unifid, όπου εκεί θα μπει και ο χρήστης που θα έχει τη δυνατότητα του custom portal για τους πελάτες του δικτύου. Μιας και ο μόνος χρήστης που υπάρχει αυτή τη στιγμή στο σύστημα είναι ο elias, αυτός είναι που θα προστεθεί και στο εν λόγω group.

Start from creating a user group named unifid, that will contain the user who will have the ability to create/alter the custom portal for the network clients. Since the only user existed in the system right now is elias, this user will be added into the group in question.

elias@unificontrol:~ > sudo addgroup unifid
Adding group `unifid' (GID 1003) ...
Done.
elias@unificontrol:~ > sudo adduser elias unifid
Adding user `elias' to group `unifid' ...
Adding user elias to group unifid
Done.

Για να δει το σύστημα την αλλαγή στα groups θα πρέπει να κάνουμε ένα logout και μετά ξανά login. Αυτό που φαίνεται στις ακόλουθες εντολές είναι η σύνδεση μέσω ssh από άλλον υπολογιστή:

For the system to read the new settings in you'll have to logout and relogin. What is presented in the following commands is a connection from another computer through ssh:

elias@unificontrol:~ > logout
Connection to 192.168.1.10 closed.
elias@otherpc:~> ssh 192.168.1.10
elias@192.168.1.10's password: 
Linux unificontrol 3.6.11+ #456 PREEMPT Mon May 20 17:42:15 BST 2013 armv6l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu May 30 11:43:24 2013 from 192.168.1.20
elias@unificontrol:~ > groups
elias adm dialout cdrom sudo audio video plugdev games users netdev input unifid
elias@unificontrol:~ > 

Το επόμενο βήμα είναι να κατεβάσουμε το .zip αρχείο του προγράμματος. Οι διαθέσιμες εκδόσεις είναι δύο:

The next step is to download the desirable .zip file of the program. The available versions (at the time of this writing) are two:

Όποια από τις δύο εκδόσεις και αν ενδιαφερθείτε να εγκαταστήσετε, ο τρόπος είναι ακριβώς ο ίδιος. Απλώς κατεβάστε το αρχείο .zip και αποσυμπιέστε το. Επειδή θα πρέπει να αποδεχθείτε την άδεια χρήσης του προγράμματος, θα πρέπει να το κατεβάσετε με τη βοήθεια κάποιου browser στον υπολογιστή σας και στη συνέχεια να το μεταφέρετε με scp στο Raspberry. Στη συνέχεια το αποσυμπιέζετε:

Whichever of these you may choose to install, the way is exactly the same. Just download the desired .zip file and uncompress it. Because you'll have to accept the license agreement, you have to download it using your computer's browser and transfer the file to Raspberry Pi using scp. There you can uncompress it:

elias@otherpc:~ > scp ~/Downloads/UniFi.unix.zip 192.168.1.10:/home/elias/
elias@192.168.1.10's password:
UniFi.unix.zip    100%   28MB   1.2MB/s   00:23
elias@otherpc:~ > ssh 192.168.1.10
elias@192.168.1.10's password:
.
.
elias@unificontrol:~ > cd /opt/
elias@unificontrol:/opt > sudo unzip /home/elias/UniFi.unix.zip
Archive:  UniFi.unix.zip
   creating: UniFi/
   creating: UniFi/bin/
    linking: UniFi/bin/mongod        -> /usr/bin/mongod 
.
.
.
elias@unificontrol:/opt >

Το πρόγραμμα έχει εγκατασταθεί στο Raspberry. Μένουν λίγες ακόμα λεπτές πινελιές για τη λειτουργία του. Καταρχήν το link που βρίσκεται μέσα στον κατάλογο UniFi/bin δεν χρειάζεται κάποια αλλαγή, γιατί η εγκατάσταση της MongoDB έχει φροντίσει να υπάρχει το αρχείο /usr/bin/mongod που χρειάζεται το UniFi Controller. Αυτό που χρειαζεται να γίνει, είναι να δημιουργθεί ο κατάλογος data που θα φιλοξενεί όλες τις παραμέτρους για το δίκτυό μας. Ο κατάλογος αυτός θα περιέχει και το portal της εισόδου των πελατών του ξενοδοχείου στο δίκτυο, έτσι θα πρέπει να μπορεί ο χρήστης που ανήκει στο group unifid να αλλάζει τα δεδομένα χωρίς να υπάρχουν προβλήματα με τα δικαιώματα. Επειδή θα πειράξουμε λίγο τη λίστα δικαιωμάτων, θα χρειαστεί να εγκατασταθεί και το πακέτο acl με την εντολή:

The program is now installed in Raspbian. There are some finishing touches for its correct operation. Begining with the link that lies in UniFi/bin directory, it does not need any change, since the MongoDB installation has placed the executable /usr/bin/mongod where UniFi Controller expects it. But what is necessary to be done is the creation of a directory named data. In there, all the parameters and information of the network will be stored. There will also be the entry portal of the hotel clients, so the user who belongs to unifid group must have the correct access rights for being able to alter those files without problems. We are going to change the access rights list a little bit, so we need to install acl package using the command:

elias@unificontrol:/opt > sudo apt-get install acl
...

Το επόμενο βήμα είναι να δημιουργθεί ο κατάλογος data και να του δοθούν τα κατάλληλα δικαιώματα:

The step that follows creates the data directory and gives the correct access rights to it:

elias@unificontrol:/opt > cd UniFi
elias@unificontrol:/opt/UniFi > sudo mkdir data
elias@unificontrol:/opt/UniFi > sudo chgrp unifid data
elias@unificontrol:/opt/UniFi > sudo chmod 0774 data
elias@unificontrol:/opt/UniFi > sudo chmod g+s data
elias@unificontrol:/opt/UniFi > sudo setfacl -d -m u::rwX,g::rwX,o::r data
elias@unificontrol:/opt/UniFi > ls -ld data
drwxrwsr--+ 7 root unifid 4096 May 29 13:13 data
elias@unificontrol:/opt/UniFi > getfacl data
# file: data
# owner: root
# group: unifid
# flags: -s-
user::rwx
group::rwx
other::r--
default:user::rwx
default:group::rwx
default:other::r--
elias@unificontrol:/opt/UniFi >

Πλέον είμαστε έτοιμοι να δοκιμάσουμε αν το πρόγραμμα λειτουργεί σωστά. Μην ξεχνάμε ότι η εγκατάσταση έχει γίνει με τέτοιο τρόπο που τρέχει από τον root. Για να ξεκινήσει το UniFi Controller θα πρέπει να δώσουμε την εντολή:

Now we are ready to test if the program works as expected. Do not forget that the installations has been made in a way that only root can execute it. To start the UniFi Controller run the following command from the command line interface:

elias@unificontrol:/opt/UniFi > sudo /usr/bin/java -jar /opt/UniFi/lib/ace.jar start &

Εδώ θα πρέπει να περιμένουμε λίγο χρονικό διάστημα (αρκετά δευτερόλεπτα) πριν καταφέρουμε να μπούμε στο σύστημα. Για να δοκιμάσουμε το σύστημά μας, θα πρέπει να χρησιμοποιήσουμε τον browser ενός υπολογιστή. Αν προσπαθήσουμε να μπούμε πριν το πρόγραμμα κάνει όλα τα απαραίτητα, τότε απλά θα έχουμε μήνυμα λάθους από τον browser. Αν όμως το σύστημα ετοιμαστεί τότε δίνοντας τη διεύθυνση του Raspberry με πόρτα την 8080, θα δούμε την εισαγωγική οθόνη του UniFi Controller. Η διεύθυνση που έχει αυτή τη στιγμή είναι η 192.168.1.10, οπότε η διεύθυνση που θα πληκτρολογήσουμε στον browser μας είναι η http://192.168.1.10:8080/. Η σελίδα θα κάνει redirection σε https, αλλά στην ίδια διεύθυνση και ο browser θα μας παραπονεθεί για το πιστοποιητικό της σελίδας. Όταν τελικά το αποδεχτούμε:

We will have to wait for a short time (several seconds) before trying to enter the system. To test it we will have to use the browser of another computer. If we try to enter before the program finishes all its intro tasks then we will simply receive an error message from our browser. But if the system is ready to accept connections, then by entering the IP address of the Raspberry Pi using port 8080, we will get the introduction screen of UniFi Controller. The address used during the righting of this article is 192.168.1.10, so this is the address we will type in our browser: http://192.168.1.10:8080/; the page will redirect to https protocol at the same IP address and our browser will complain about this page's certificate. When we finally accept it:

Για να σταματήσουμε το πρόγραμμα, αρκεί να τρέξουμε την εντολή:

To stop the program, we have to enter the following command:

elias@unificontrol:/opt/UniFi > sudo /usr/bin/java -jar /opt/UniFi/lib/ace.jar stop

Για την ώρα δεν χρειάζεται να κάνουμε παραμετροποίηση του συστήματος. Μπορούμε να την αφήσουμε για αργότερα, όταν όλα θα είναι έτοιμα!

For now we will not continue to any network configuration. We can leave it for later on, when everything is in place!

Δημιουργία service script

Service Script Creation

Τώρα που το σύστημα λειτουργεί, θα πρέπει να το κάνουμε να ενεργοποιείται στα κατάλληλα runlevels του Raspbian.

Now we know that the system works, we must make it automatically activated at the appropriate Raspbian runlevels.

Η διαδικασία είναι η ίδια με αυτή που περιγράφεται στο αντίστοιχο άρθρο για το openSUSE. Ο κατάλογος /etc/init.d/ περιέχει όλα τα scripts για τα services. Περιέχει κι ένα αρχείο που μας ενδιαφέρει περισσότερο, το skeleton. Αυτό είναι ένα αρχείο στο οποίο μπορούμε να βασιστούμε για να φτιάξουμε το δικό μας script, έτσι ώστε το UniFi Controller να μπορεί να ενεργοποιηθεί και να απενεργοποιηθεί όπως ακριβώς και όλα τα υπόλοιπα services που διαθέτει το σύστημα. Το αρχείο που θα δημιουργήσουμε είναι το unifid. Μπορείτε να το δημιουργήσετε μόνοι σας από την αρχή, απλά αντιγράφοντας το ακόλουθο και σώζοντάς το μέσα στον εν λόγω κατάλογο:

The procedure is the same as the one described in the similar article for openSUSE. The /etc/init.d/ contains all the scripts for all the available services. It also contains a file that we need more, named skeleton. That is the file we will be based on to create our own service script, to make UniFi Controller activated and deactivated in the same way as the rest of the system's services. The file we will create is called unifid. You can create it by yourselves from the very beginning, by simply copying and pasting the following code and saving it in the directory in question:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          unifid
# Required-Start:    $local_fs $syslog $network
# Required-Stop:     $local_fs $syslog $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: unifid daemon providing Controller server for UniFi Access Points
# Description:       Start unifid to allow the UniFi Controller Software to be able to
#       control the UniFi Access Points of Ubiquity in the network. The softare runs in Java
#       and is installed in /opt/ directory.
### END INIT INFO

# Author: Elias Chrysocheris 
#

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="UniFi Controller Service for assisting Ubiquity's UniFi Access Points"
JAVA_BIN=/usr/bin/java
NAME=unifid
MONGOD_BIN=/opt/UniFi/bin/mongod
DAEMON=/opt/UniFi/lib/ace.jar
DAEMON_ARGS="-jar $DAEMON"
SCRIPTNAME=/etc/init.d/$NAME

# Exit if Java package is not installed
[ -x "$JAVA_BIN" ] || { echo "Cannot find java executable in $JAVA_BIN, or java is not installed...";
    if [ "$1" = "stop" ]; then exit 0;
    else exit 5; fi; }

# Also, mongoDB must be installed. The extra step here is that there must be a valid link in
# /opt/UniFi/bin/mongod that points to the mongod executable
if [ ! \( -e $MONGOD_BIN \) ]
then
    echo "Cannot find mongod executable in $MONGOD_BIN, or mongoDB is not installed...";
    if [ "$1" = "stop" ]; then exit 0;
    else exit 5; fi;
fi

# Exit if the package is not installed
[ -e "$DAEMON" ] || { echo "Cannot find UniFi Controller executable in $DAEMON, or the controller software is not installed...";
    if [ "$1" = "stop" ]; then exit 0;
    else exit 5; fi; }

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    start-stop-daemon --test --start --quiet --exec $JAVA_BIN -- $DAEMON_ARGS start > /dev/null \
        || return 1
    start-stop-daemon --start --quiet --exec $JAVA_BIN -- $DAEMON_ARGS start &
    RETVAL="$?"
    [ $RETVAL > 0 ] && return 2
    # Add code here, if necessary, that waits for the process to be ready
    # to handle requests from services started subsequently which depend
    # on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --exec $JAVA_BIN -- $DAEMON_ARGS stop
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    # Wait for children to finish too if this is a daemon that forks
    # and if the daemon is only ever run from this initscript.
    # If the above conditions are not satisfied then add some other code
    # that waits for the process to drop all resources that could be
    # needed by services started subsequently.  A last resort is to
    # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2
    return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
    #
    # If the daemon can reload its configuration without
    # restarting (for example, when it is sent a SIGHUP),
    # then implement that here.
    #
    start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
    return 0
}

case "$1" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
    do_start
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  stop)
    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
    do_stop
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  status)
    status_of_proc "$JAVA_BIN -jar $DAEMON" "$NAME" && exit 0 || exit $?
    ;;
  #reload|force-reload)
    #
    # If do_reload() is not implemented then leave this commented out
    # and leave 'force-reload' as an alias for 'restart'.
    #
    #log_daemon_msg "Reloading $DESC" "$NAME"
    #do_reload
    #log_end_msg $?
    #;;
  restart|force-reload)
    #
    # If the "reload" option is implemented then remove the
    # 'force-reload' alias
    #
    log_daemon_msg "Restarting $DESC" "$NAME"
    do_stop
    case "$?" in
      0|1)
        do_start
        case "$?" in
            0) log_end_msg 0 ;;
            1) log_end_msg 1 ;; # Old process is still running
            *) log_end_msg 1 ;; # Failed to start
        esac
        ;;
      *)
        # Failed to stop
        log_end_msg 1
        ;;
    esac
    ;;
  *)
    #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
    exit 3
    ;;
esac

Το script θα πρέπει να είναι εκτελέσιμο, οπότε όταν δημιουργηθεί στο δίσκο θα πρέπει να του ενεργοποιηθούν και τα κατάλληλα δικαιώματα εκτέλεσης. Επίσης, η δημιουργία του γίνεται από τον χρήστη root, αλλοιώς το σύστημα θα αρνηθεί να το σώσει μέσα στον κατάλογο init.d. Τέλος θα πρέπει να γίνουν update τα links των καταλόγων rc?.d, έτσι ώστε το service να ξεκινάει ή να σταματάει αυτόματα, ανάλογα με το runlevel στο οποίο μεταπηδάει το Raspbian. Οι εντολές για τα δικαιώματα και την ενημέρωση των runlevels είναι οι ακόλουθες:

The script must be marked executable, so when it is created in the disc we must alter its access rights. Another tip is that it ust be created from the root user, or the system will deny its saving into init.d. Last, the links of all rc?.d directories must be updated, for the service to be started or stopped automatically, according to runlevel transitions of the operating system. The commands for altering the access rights and updating the runlevel links are:

elias@unificontrol:/opt/UniFi > cd /etc/init.d/
elias@unificontrol:/etc/init.d > sudo chmod 0755 unifid
elias@unificontrol:/etc/init.d > sudo update-rc.d unifid defaults
update-rc.d: using dependency based boot sequencing
elias@unificontrol:/etc/init.d > 

Μπορεί να γίνει να δοκιμή του script που μόλις ενεργοποιήθηκε δίνοντας τις ακόλουθες εντολές και κοιτάζοντας τις αποκρίσεις:

We can test the newlly created and activated script by executing the folowing commands and observe their response:

elias@unificontrol:/etc/init.d > sudo /etc/init.d/unifid start
elias@unificontrol:/etc/init.d > sudo /etc/init.d/unifid status
[ ok ] unifid is running.
elias@unificontrol:/etc/init.d > sudo /etc/init.d/unifid stop
elias@unificontrol:/etc/init.d > sudo /etc/init.d/unifid status
[FAIL] unifid is not running ... failed!
elias@unificontrol:/etc/init.d > 

Αν όλα πήγαν καλά, τότε μετά από μια επανεκκίνηση αν εκτελέσουμε την εντολή ps aux | grep ace.jar θα πρέπει να δούμε τα ακόλουθα:

If everything went right, after a restart of Raspbian, using the command ps aux | grep ace.jar we must get something like:

elias@unificontrol:~ > ps aux | grep ace.jar
root      3189 54.0  5.2 370688 25212 ?        Sl   23:43   0:16 /usr/bin/java -jar /opt/UniFi/lib/ace.jar start
elias     3241  0.0  0.1   3548   892 pts/0    S+   23:43   0:00 grep --color=auto ace.jar
elias@unificontrol:~ > 

Αυτό που μας ενδιαφέρει είναι η πρώτη γραμμή που δείχνει πως ένα process τρέχει αυτή τη στιγμή στον επεξεργαστή κι έχει την εντολή ενεργοποίησης του service του UniFi Controller. Η συνέχεια είναι απλή. Ανοίγουμε και πάλι τον browser και δίνοντας την IP διεύθυνση του Raspberry με την πόρτα 8080, όπως κάναμε και πριν, ξεκινάμε την παραμετροποίηση του συστήματος των Access Points. Όταν όλα τελειώσουν μπορούμε να έχουμε μια εικόνα σαν αυτή:

What we are interested in, is the first line showing there is an active process running in our processor, started by the same command we used to start the UniFi Controller. What follows is natural; We open a browser in our computer and by entering the Raspberry's IP address and port 8080, as we did before, we can start the configuration of our Access Points. When everything is done we must get a page like that:

Συμπεράσματα

Conclutions

Το Raspberry Pi, είναι ένα gadgetάκι που, μπορεί κάποιος να μη μείνει ικανοποιημένος αν προσπαθήσει να το χρησιμοποιήσει όπως ένα Desktop υπολογιστή. Όταν το χρησιμοποιήσετε απλά για internet κ.λ.π. θα διαπιστώσετε ότι μοιάζει πολύ με ένα υπολογιστή τεχνολογίας εποχής του KDE3. Ναι μεν μπορείς να κάνεις κάποια δουλειά, αλλά οι χρόνοι καθυστέρησης σε γυρίζουν λίγο πίσω... Από την άλλη, σαν ένας μικρός server έχει αρκετά πλεονεκτήματα. Έχει ικανοποιητική ταχύτητα για τη διαχείριση ενός μικρού δικτύου. Μπορεί να αναλάβει "μικροδουλειές" όπως backup/file server, firewall ή ακόμα και για να τραβάει φωτογραφίες σαν σύστημα παρακολούθησης/ασφάλειας. Στη δική μας περίπτωση, αυτό που μας ενδιέφερε είναι να μπορέσει να λειτουργήσει ως διαχειριστής δικτύου ξενοδοχείου και αυτή τη δουλειά την κάνει αρκετά καλά.

Raspberry Pi is a small gadget that someone may not be satisfied if he/she uses it as a desktop computer. If you use it simply for internet browsing etc. you will find out it is very similar, in terms of processing power, to a computer that used KDE3. It is true you can do some work, but the execution times takes you a little bit back in time... In contrast, working as a small server has many advantages. Its speed is satisfactory for using in a small network. It can handle some simple tasks such as a backup/file server, a firewall or even taking photos as an area survailance/security system. In our case, what we were interested in was to be able to handle access control and portal serving in a hotel's network. And that is a job that can handle very well.

Μια ακόμα δυνατότητα είναι πως μπορεί πολύ εύκολα να τροφοδοτηθεί από μια επαναφορτιζόμενη μπαταρία. Λόγω την μικρής του κατανάλωσης μια τέτοια μπαταρία είναι ικανή να το κρατήσει σε λειτουργία για πραγματικά πολλές ώρες, σε περίπτωση διακοπής της ΔΕΗ.

Another posibility is that it can be easily powered by a rechargable battery. Due to its low power consumption a battery like that can keep it functional even during long time power failures of the power company.

Όσο για την τιμή του, είναι ιδανική για αυτό που προσφέρει και αυτά που μπορεί να κάνει, ειδικά σαν "δικτυακό βοήθημα". Οι γενικές εντυπώσεις μας είναι άριστες!

And for its price, it is ideal for what it can offer and perform, aspecially as a "network assistant". Our general impression is more than surprising!

Ηλίας Χρυσοχέρης

Elias Chrysocheris

Πέμπτη 2 Δεκεμβρίου 2010

Αναβάθμιση σκληρού δίσκου σε laptop με openSUSE

Μιας και τον τελευταίο καιρό οι αλλαγές σκληρού δίσκου στα μηχανήματά μου δίνουν και παίρνουν (:Ρ) είπα να κάνω και μια αλλαγή στο laptop. Βασικά τα partitions του σκληρού μου είχαν αρχίσει να γεμίζουν επικίνδυνα και έτσι χρειαζόμουν ένα μεγαλύτερο σκληρό δίσκο σε χωρητικότητα. Ο αρχικός δίσκος ήταν 320G. Οι κατατμήσεις που περιέχει είναι τέσσερις: Μια που περιέχει το backup των άθλιων Bugindow sVista (ναι καλά διαβάσατε... Το ξαναγράφω για σιγουριά: Bugindow sVista! Δεν υπάρχει λάθος ούτε στο spelling, ούτε στα κενά!) από την εταιρία του laptop, ένα που περιέχει το πλήρες άθλιο λειτουργικό που ανέφερα, αλλά απαραίτητο όταν θέλεις να εκτυπώσεις CD σε Canon εκτυπωτή (:(), και άλλα δύο για το αγαπημένο μου openSUSE που το έχω αφήσει ακόμα στην έκδοση 11.2 (Λειτουργικό + Swap).

Τόσο το partition των Bugindows όσο και αυτό του Linux έχουν σχεδόν γεμίσει, των Bugindows γιατί είναι μικρό (LOL) και του Linux από ένα σωρό προγράμματα και Virtual Machines που χρησιμοποιώ. Όχι, τα downloaded files δεν βρίσκονται σε αυτό το σκληρό δίσκο, αλλά σε ένα δεύτερο που διαθέτει το laptop (Ναί, έχει δύο σκληρούς δίσκους αυτό το μικρούλι 17ιντσο!).

"Καλά!", θα έλεγε κάποιος. "Και πού είναι η δυσκολία στο να αντικαταστήσεις τον σκληρό σου δίσκο;". Όχι, δυσκολία δεν υπάρχει, απλά αν περιγράψω κάποια κακώς κείμενα, κάποιος που το κάνει για πρώτη φορά ίσως αποφύγει τα μικροπροβλήματα που δημιουργούνται. Κατά τ' άλλα όλα είναι λογικά και εύκολα. Ο σκοπός μας είναι να αντιγράψουμε τα πάντα από τον ένα σκληρό δίσκο στον άλλο χωρίς ιδιαίτερο κόπο. Όταν τελικά αντικαταστήσουμε τον εσωτερικό σκληρό με τον καινούργιο θα θέλαμε το μηχάνημά μας να κάνει boot όπως ακριβώς ήταν και πριν.

Τι θα χρειαστούμε αρχικά;

Η λίστα των απαραίτητων είναι μικρή:
  • Ένα USB κουτάκι με το οποίο θα συνδέσουμε τον καινούριο σκληρό δίσκο στο μηχάνημά μας
  • Ένα Live CD με το CloneZilla
  • Ένα κατσαβιδάκι για την αλλαγή του σκληρού δίσκου
  • Αρκετή υπομονή και ώρα!

Προετοιμασία για αντιγραφή των partitions

Πρώτα κατεβάζουμε το CloneZilla και το καίμε σε ένα CD. Εναλλακτικά μπορούμε να κατεβάσουμε την έκδοση για USB Flash Stick και να το έχουμε σε ένα Flashάκι. Με αυτό θα κάνουμε αργότερα boot για να αντιγράψουμε τα partitions του αρχικού σκληρού δίσκου στον καινούργιο. Η συνέχεια είναι λίγο kinky! Θα πρέπει να πω κάποια λίγα πράγματα για τον GRUB. Λίγα και βασικά! Μην περιμένετε να τον αναλύσω εξ ολοκλήρου!

Κατ' αρχήν, το Linux για να δει τους σκληρούς δίσκους χρησιμοποιεί τα κλασικά device files, /dev/sda, /dev/sdb κ.λ.π. Υπάρχει, όμως, και ένας εναλλακτικός τρόπος για την πρόσβαση στους σκληρούς δίσκους. Αν μπούμε μέσα στον κατάλογο /dev/disk, θα δούμε ότι υπάρχουν κάποιοι υποκατάλογοι ακόμα. Σε ένα σύστημα openSUSE θα βρείτε τους by-id, by-label, by-path και by-uuid. Σε κάθε ένα από αυτούς τους υποκαταλόγους βλέπουμε ένα σωρό links που δείχνουν προς τα κλασικά αρχεία των συσκευών /dev/sda κ.λ.π. Ο λόγος είναι πως η ανάθεση των device files γίνεται κατά την εκκίνηση και όταν αλλάξουμε κάποιο σκληρό δίσκο, ή ακόμα και αν κάνουμε αναβάθμιση στο BIOS του υπολογιστή, αυτά τα ονόματα δεν θα δείχνουν απαραίτητα στον ίδιο σκληρό δίσκο που εμείς θα θέλαμε, με αποτέλεσμα να έχουμε διάφορες εκπλήξεις! Γι' αυτό το λόγο έχουν δημιουργηθεί και οι υποκατάλογοι μέσα στο /dev/disk.

eliaschr@orion:~> cd /dev/disk
eliaschr@orion:/dev/disk> ls -Rl
.:                              
total 0                         
drwxr-xr-x 2 root root 380 2010-11-18 11:58 by-id
drwxr-xr-x 2 root root 100 2010-11-18 13:58 by-label
drwxr-xr-x 2 root root 220 2010-11-18 11:58 by-path
drwxr-xr-x 2 root root 140 2010-11-18 13:58 by-uuid

./by-id:
total 0 
lrwxrwxrwx 1 root root  9 2010-11-18 13:58 ata-ST9500420AS_5VJ7ND82 -> ../../sda
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 ata-ST9500420AS_5VJ7ND82-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 ata-ST9500420AS_5VJ7ND82-part2 -> ../../sda2
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 ata-ST9500420AS_5VJ7ND82-part3 -> ../../sda3
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 ata-ST9500420AS_5VJ7ND82-part4 -> ../../sda4
lrwxrwxrwx 1 root root  9 2010-11-18 13:58 ata-WDC_WD5000BEVT-00A0RT0_WD-WX10AA9D0409 -> ../../sdb
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 ata-WDC_WD5000BEVT-00A0RT0_WD-WX10AA9D0409-part1 -> ../../sdb1
lrwxrwxrwx 1 root root  9 2010-11-18 11:58 edd-int13_dev80 -> ../../sda                                  
lrwxrwxrwx 1 root root  9 2010-11-18 11:58 edd-int13_dev81 -> ../../sdb                                  
lrwxrwxrwx 1 root root  9 2010-11-18 13:58 scsi-SATA_ST9500420AS_5VJ7ND82 -> ../../sda                   
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 scsi-SATA_ST9500420AS_5VJ7ND82-part1 -> ../../sda1            
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 scsi-SATA_ST9500420AS_5VJ7ND82-part2 -> ../../sda2            
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 scsi-SATA_ST9500420AS_5VJ7ND82-part3 -> ../../sda3            
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 scsi-SATA_ST9500420AS_5VJ7ND82-part4 -> ../../sda4            
lrwxrwxrwx 1 root root  9 2010-11-18 13:58 scsi-SATA_WDC_WD5000BEVT-_WD-WX10AA9D0409 -> ../../sdb        
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 scsi-SATA_WDC_WD5000BEVT-_WD-WX10AA9D0409-part1 -> ../../sdb1 
lrwxrwxrwx 1 root root  9 2010-11-18 13:58 usb-Generic-_Multi-Card_20060413092100000-0:0 -> ../../sdc

./by-label:
total 0
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 Common -> ../../sdb1
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 HDD -> ../../sda2
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 _OEMBP -> ../../sda1

./by-path:
total 0
lrwxrwxrwx 1 root root  9 2010-11-18 13:58 pci-0000:00:02.1-usb-0:2:1.0-scsi-0:0:0:0 -> ../../sdc
lrwxrwxrwx 1 root root  9 2010-11-18 11:58 pci-0000:00:06.0-scsi-0:0:0:0 -> ../../sr0
lrwxrwxrwx 1 root root  9 2010-11-18 13:58 pci-0000:00:09.0-scsi-0:0:0:0 -> ../../sda
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 pci-0000:00:09.0-scsi-0:0:0:0-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 pci-0000:00:09.0-scsi-0:0:0:0-part2 -> ../../sda2
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 pci-0000:00:09.0-scsi-0:0:0:0-part3 -> ../../sda3
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 pci-0000:00:09.0-scsi-0:0:0:0-part4 -> ../../sda4
lrwxrwxrwx 1 root root  9 2010-11-18 13:58 pci-0000:00:09.0-scsi-1:0:0:0 -> ../../sdb
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 pci-0000:00:09.0-scsi-1:0:0:0-part1 -> ../../sdb1

./by-uuid:
total 0
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 0C90BD9C90BD8D28 -> ../../sda2
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 14A4F162A4F14730 -> ../../sdb1
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 269cc848-3599-4559-9c2b-5494643d6b64 -> ../../sda3
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 90CEA1A2CEA180D8 -> ../../sda1
lrwxrwxrwx 1 root root 10 2010-11-18 13:58 970013ea-d703-4b36-8d77-44d9aca0ea65 -> ../../sda4
eliaschr@orion:/dev/disk>

Αυτά όλα τα links οδηγούν στα κλασικά device files. Αλλά αυτά παράγονται από διάφορα χαρακτηριστικά που έχει ο κάθε συνδεδεμένος σκληρός επάνω στο σύστημά μας (όπως π.χ. όνομα μοντέλου, σειριακός αριθμός κ.λ.π.). Αυτά τα χαρακτηριστικά δεν άλλάζουν ανάλογα με τη σύνδεση, γιατί είναι χαρακτηριστικά του ίδιου του σκληρού δίσκου που υπάρχει στο σύστημα. Γιατί τόσος λόγος για αυτά τα αρχεία; Γιατί ο GRUB ρυθμίζεται με βάση αυτά στο openSUSE και όταν θα αλλάξουμε σκληρό δίσκο στο μηχάνημά μας θα υπάρχει πρόβλημα στην εκκίνηση.

Το αρχείο το οποίο καθορίζει τις ρυθμίσεις του GRUB είναι το /boot/grub/grub.conf, ενώ από αυτό φτιάχνονται και κάποια άλλα αρχεία όπως το /boot/grub/menu.lst. Σε αυτά τα δύο αρχεία θα επέμβουμε πριν ξεκινήσουμε την αντιγραφή του σκληρού δίσκου στον καινούργιο.

Πιο συγκεκριμένα, το αρχείο /boot/grub/grub.conf περιέχει τα παρακάτω:
eliaschr@orion:~> su                       
Password:                                  
orion:/home/eliaschr # cat /boot/grub/grub.conf  
# Modified by YaST2. Last modification on Tue Mar 23 13:58:50 EET 2010
# THIS FILE WILL BE PARTIALLY OVERWRITTEN by perl-Bootloader
# Configure custom boot parameters for updated kernels in /etc/sysconfig/bootloader

default 0
timeout 8
##YaST - generic_mbr
gfxmenu (hd0,2)/boot/message
##YaST - activate

###Don't change this comment - YaST2 identifier: Original name: linux###
title Desktop -- openSUSE 11.2 - 2.6.31.12-0.2
    root (hd0,2)
    kernel /boot/vmlinuz-2.6.31.12-0.2-desktop root=/dev/disk/by-id/ata-ST9500420AS_5VJ7ND82-part3 resume=/dev/disk/by-id/ata-ST9500420A_5VJ7ND82-part4 quiet showopts vga=0x365
    initrd /boot/initrd-2.6.31.12-0.2-desktop

###Don't change this comment - YaST2 identifier: Original name: failsafe###
title Failsafe -- openSUSE 11.2 - 2.6.31.12-0.2
    root (hd0,2)
    kernel /boot/vmlinuz-2.6.31.12-0.2-desktop root=/dev/disk/by-id/ata-ST9500420AS_5VJ7ND82-part3 showopts apm=off noresume edd=off powersaved=off nohz=off highres=off processor.max_cstate=1 x11failsafe vga=0x314
    initrd /boot/initrd-2.6.31.12-0.2-desktop

###Don't change this comment - YaST2 identifier: Original name: windows 1###
title Bugindow sVista
    rootnoverify (hd0,1)
    chainloader +1
orion:/home/eliaschr #

Παρατηρούμε ότι στις παραμέτρους root και resume χρησιμοποιούνται ονομασίες κατατμήσεων από τον υποκατάλογο /dev/disk/by-id. Παρατηρούμε, επίσης, τις πρώτες γραμμές να μας προειδοποιούν ότι αυτό το αρχείο αλλάζει από κάποιο script αυτόματα, που σημαίνει ότι αν κάνουμε αλλαγές σε αυτό, κάποια στιγμή οι αλλαγές θα χαθούν. Βέβαια, τα πράγματα δεν είναι τόσο τραγικά, αλλά για να χρησιμοποιήσουμε τις ευκολίες του γραφικού περιβάλλοντος του openSUSE θα το τροποποιήσουμε από το εργαλείο Yast2.

Αρχικά, από το μενού του γραφικού περιβάλλοντος KDE4 στην καρτέλα "Υπολογιστής" ("Computer") κάνουμε κλικ στην πρώτη επιλογή, "YaST".

Από το παράθυρο που ανοίγει επιλέγουμε από την αριστερή στήλη το "Σύστημα" ("System") και από τις επιλογές της δεξιάς στήλης επιλέγουμε το "Bootloader". Τότε θα ανοίξει το ακόλουθο παράθυρο:

Εκεί, μπορούμε να παρατηρήσουμε τις επιλογές που μας εμφανίζει ο GRUB κατά την εκκίνηση του υπολογιστή μας. Σε αυτές είναι που θα επέμβουμε, λιγάκι. Για να κάνουμε την επέμβαση, απλά επιλέγουμε την επιλογή που μας ενδιαφέρει και πατάμε το "Edit". Τότε εμφανίζεται και το ακόλουθο παράθυρο. Εκεί, φυσικά, οι δικές σας ρυθμίσεις θα είναι διαφορετικές από αυτές που φαίνονται στην εικόνα.

Οι ρυθμίσεις που μας ενδιαφέρουν είναι οι root και η resume. Η πρώτη βρίσκεται στο "Root Device", ενώ η δεύτερη βρίσκεται στο "Optional Kernel Command Line Parameter". Αυτά τα ρυθμίζουμε να περιέχουν τα standard device names ανάλογα με το partition που δείχνουν. Στη δικιά μου περίπτωση είναι αυτά που φαίνονται στην ακόλουθη εικόνα (/dev/sda3 και /dev/sda4 αντίστοιχα):

Εκεί πατάμε το "OK" και επιστρέφουμε στην προηγούμενη εικόνα. Επαναλαμβάνουμε τα ίδια για κάθε επιλογή του GRUB, και βάζουμε στις ρυθμίσεις τις αντίστοιχες, πάντα, κατατμήσεις σε standard device names. Προσέχουμε να δείχνουν τις σωστές κατατμήσεις κάθε φορά. Στο τέλος πατάμε και σε αυτή την εικόνα το "OK". Ο υπολογιστής κάνει την καινούργια εγκατάσταση του GRUB.

Κάτι που ΔΕΝ ΠΡΕΠΕΙ ΝΑ ΞΕΧΑΣΟΥΜΕ είναι να κάνουμε τις αντίστοιχες διορθώσεις και στο αρχείο /etc/fstab. Για να γίνουν οι αλλαγές πρέπει να είμαστε logged in σαν root χρησιμοποιώντας τον αγαπημένο μας editor, όπως π.χ. τον vi. Ένα τυπικό αρχείο με τις αλλαγές του είναι το:

orion:/home/eliaschr # cat /etc/fstab
/dev/sda4  swap               swap     defaults              0 0
/dev/sda3  /                  ext3     acl,user_xattr        1 1
/dev/sda2  /windows/C         ntfs-3g  users,gid=users,fmask=113,dmask=002,locale=el_GR.UTF-8 0 0
/dev/sdb1  /windows/D         ntfs-3g  users,gid=users,fmask=113,dmask=002,locale=el_GR.UTF-8 0 0
proc       /proc              proc     defaults              0 0
sysfs      /sys               sysfs    noauto                0 0
debugfs    /sys/kernel/debug  debugfs  noauto                0 0
usbfs      /proc/bus/usb      usbfs    noauto                0 0
devpts     /dev/pts           devpts   mode=0620,gid=5       0 0
orion:/home/eliaschr #

Αντιγραφή των κατατμήσεων στον καινούργιο σκληρό δίσκο

Ήρθε η ώρα να κάνουμε boot το CloneZilla. Εδώ οι εικόνες που εμφανίζονται είναι, φυσικά, από εικονικό μηχάνημα γιατί αλλιώς δε θα μπορούσαμε να τις τραβήξουμε από το σύστημα την ώρα που τρέχει. Το εικονικό μηχάνημα θα μας βοηθήσει να καταλάβουμε τι κάνουμε, με τη διαφορά μόνο στις ονομασίες των σκληρών δίσκων.

Αφού βάλουμε το CD του CloneZilla στον οδηγό του υπολογιστή μας, ελέγχουμε ότι το BIOS μας θα προσπαθήσει να κάνει boot πρώτα από εκεί και όχι από τον σκληρό δίσκο. Αν όλα είναι εντάξει τότε η εκκίνηση του υπολογιστή θα δείξει την ακόλουθη εικόνα:

Εδώ ξεκινάμε το CloneZilla, όπως φαίνεται και στην εικόνα. Αφού επιλέξουμε στις ακόλουθες εικόνες τη γλώσσα και το keymap του πληκτρολογίου μας (αφήνουμε τα προεπιλεγμένα) καταλλήγουμε στην εικόνα:

Η επιλογή μας δε θα μπορούσε να είναι άλλη από την εκκίνηση του προγράμματος, όπως φαίνεται και η ενεργοποιημένη επιλογή. Η επόμενη ερώτηση που μας κάνει ο υπολογιστής είναι αν η αντιγραφή θα αφορά image από partition ή αν θα γίνει σε κανονικά devices απ' ευθείας. Εφόσον πάμε να αντιγράψουμε έναν ολόκληρο σκληρό δίσκο σε έναν άλλο, δε θα κάνουμε καθόλου με images των partitions. Οπότε η σωστή επιλογή είναι αυτή που φαίνεται στο στιγμιότυπο:

Και για όλους εμάς που είμαστε καινούργιοι στο άθλημα του CloneZilla καλό είναι να επιλέξουμε το Beginner mode...

Τη συνέχεια, λίγο πολύ, τη φανταζόμαστε. Επιλέγουμε αν η κλωνοποίηση θα γίνει τοπικά ή απομακρυσμένα. Φυσικά επειδή και οι δύο συσκευές σκληρών δίσκων είναι επάνω στο ίδιο μηχάνημα η κλωνοποίηση είναι τοπική. Εδώ καλό είναι να συνδέσουμε τον εξωτερικό σκληρό δίσκο στη USB θύρα πριν προχωρήσουμε. Ο παλιός σκληρός δίσκος, δηλαδή, είναι ο εσωτερικός του μηχανήματος, ενώ ο δίσκος που θα δεχθεί τα δεδομένα είναι ο εξωτερικός που συνδέουμε στη θύρα USB.

Σε αυτό το σημείο θα επιλέξουμε τον σκληρό δίσκο από τον οποίο θα πάρουμε τα δεδομένα (Source). Είναι ο δίσκος που περιέχει τα λειτουργικά συστήματά μας και είναι συνδεδεμένος εσωτερικά στο μηχάνημα. Αυτό σημαίνει ότι θα τον βλέπουμε με το όνομα sda.

Όταν συνδέσαμε τον εξωτερικό σκληρό δίσκο στη θύρα USB είδαμε κάποια μηνύματα που μας έδειχναν την ονομασία του εξωτερικού σκληρού δίσκου. Σε αυτό το παράδειγμα ο εξωτερικός δίσκος είναι ο sdb. Αυτόν θα επιλέξουμε και σαν συσκευή που θα δεχθεί τα δεδομένα μας (Destination).

Αφού πατήσουμε το OK, είμαστε στο τελευταίο σημείο πριν ξεκινήσει η κλωνοποίηση. Καλό είναι να κάνουμε έναν έλεγχο για το αν έχουμε κάνει τη σωστή επιλογή στους σκληρούς δίσκους, γιατί ένα λάθος θα μπορούσε να είναι μοιραίο για τα δεδομένα μας! Προσοχή!

Η τελική μας επιλογή, αν όλα είναι σωστά, είναι να γράψουμε y και η κλωνοποίηση ξεκινάει. Τώρα έχετε πάρα πολύ χρόνο να ασχοληθείτε με οτιδήποτε άλλο εκτός από τον υπολογιστή σας... :D

Τελικές Κινήσεις

Όταν τελειώσει η κλωνοποίηση μπορούμε να κάνουμε shutdown στον υπολογιστή μας. Τώρα ήρθε η ώρα να πιάσουμε κατσαβίδι στα χέρια μας και να ανταλλάξουμε θέσεις στους σκληρούς δίσκους. Δεν είναι καμιά ιδιαίτερα δύσκολη διαδικασία, όσο είμαστε προσεκτικοί σε αυτό που κάνουμε, όλα θα πάνε καλά.

Μόλις γίνει η αλλαγή των σκληρών δίσκων, μπορούμε να ανάψουμε τον υπολογιστή μας ξανά. Αν όλα τα κάναμε σωστά τότε το openSUSE θα εκκινήσει κανονικά!. Το μόνο που θα παρατηρήσουμε είναι ότι η αρχική εικόνα του GRUB δεν έχει το γραφικό τμήμα, αλλά είναι όλη σε text mode. Πώς μπορούμε να το φτιάξουμε αυτό; Με μια κίνηση επανεγκατάστασης δύο πακέτων. Ας δούμε τη διαδικασία:

Αρχικά τρέχουμε το YaST όπως ακριβώς κάναμε και στην αρχή του άρθρου. Εκεί θα επιλέξουμε τη "Διαχείριση Λογισμικού" ("Software Management").

Εδώ θα ψάξουμε τα διαθέσιμα πακέτα με τη λέξη grub οπότε θα μας εμφανίσει ο υπολογιστής μας 3 πακέτα. Τα δύο είναι ήδη εγκαταστημένα.

Κάνοντας δεξί κλικ σε μια επιλογή, στο μενού που εμφανίζεται πάμε τον κέρσορα του ποντικιού μας στην επιλογή "Όλα σε αυτή τη λίστα..." ("All in this list...") και εμφανίζεται ακόμα ένα υπομενού. Η επιλογή που μας ενδιαφέρει είναι η "Ενημέρωση χωρίς συνθήκες" ("Update unconditionally"). Όταν κάνουμε την επιλογή τα δύο εικονίδια δίπλα από τα πακέτα που είναι ήδη εγκαταστημένα στον υπολογιστή αλλάζουν και μας δείχνουν ότι πρόκειται να ενημερωθούν. Πατώντας το πλήκτρο "Αποδοχή" ("Accept") που βρίσκεται κάτω και δεξιά, γίνεται η εγκατάσταση των δύο πακέτων. Μετά από αυτό, στην επόμενη επανεκκίνηση του υπολογιστή μας θα δούμε και το κλασικό γραφικό περιβάλλον του GRUB, όπως το είχαμε συνηθίσει!

Αν κάτι δεν πάει καλά στην εκκίνηση του καινούργιου σκληρού

Κάτι που θα πρέπει να πω είναι ότι το openSUSE μας δίνει τη δυνατότητα να κάνουμε επιδιόρθωση του λειτουργικού μας συστήματος από το DVD εκκίνησης. Αν λοιπόν, όταν εκκινήσουμε τον υπολογιστή μας με τον καινούργιο σκληρό δίσκο, δε μπορέσουμε να δούμε την εικόνα του GRUB, τότε μάλλον κάτι έχουμε κάνει λάθος παραπάνω. Μπορούμε πάντα να επιδιορθώσουμε τον bootloader με τη βοήθεια του DVD εγκατάστασης. Αν κάνουμε από αυτό εκκίνηση του υπολογιστή τότε θα δούμε την ακόλουθη εικόνα:

Η επιλογή "Resque System" μας βγάζει σε κονσόλα όπου έχουμε δικαιώματα υπερχρήστη. Έτσι μπορούμε να κάνουμε ότι θέλουμε στο σύστημά μας. Ενδείκνυται για τους σκληροπυρηνικούς τύπους, που μπορούν να κάνουν τα πάντα από την κονσόλα σε ένα σύστημα. Αν όμως δεν είστε από αυτούς, τότε μπορείτε να επέμβετε στο σύστημα λίγο πιο απλά με το εργαλείο "Repair Installed System", όπως φαίνεται και στην εικόνα.

Για την πρώτη περίπτωση δεν έχουμε να πούμε και πολλά... Σε αυτό το how-to θα ασχοληθούμε με το εργαλείο που φαίνεται να επιλέγουμε και στο στιγμιότυπο παραπάνω. Μετά την επιλογή του θα δούμε την ακόλουθη εικόνα:

Εδώ η επιλογή "Expert Tools" είναι αυτή που μας χρειάζεται. Αυτή θα μας εμφανίσει αρκετά εργαλεία που θα μπορέσουμε να χρησιμοποιήσουμε για να κάνουμε επιδιόρθωση στο σύστημά μας.

Και η πρώτη επιλογή είναι αυτή που μας χρειάζεται! "Install New Boot Loader". Όταν την επιλέξουμε θα δούμε ένα αρκετά γνώριμο περιβάλλον. Είναι το YaST και συγκεκριμένα το κομμάτι του με το οποίο ρυθμίζουμε, τι άλλο, τον GRUB.

Κάτω και δεξιά υπάρχει ένα πλήκτρο που ονομάζεται "Other". Όταν το επιλέξουμε εμφανίζεται ένα μενού που έχει κάποιες επιλογές. Αυτή που μας ενδιαφέρει σε πρώτη φάση είναι η επιλογή "Reread Configuration from Disk". Όταν κάνουμε κλικ επάνω της, θα δούμε να εμφανίζονται οι επιλογές που έχει κανονικά ο GRUB.

Επιστρέφουμε πάλι στο μενού "Other" για να επιλέξουμε την τελευταία επιλογή του, "Write Bootloader Boot Code to Disk".

Τέλος επιλέγουμε την καρτέλα "Boot Loader Installation" και εκεί κάνουμε τις ρυθμίσεις που φαίνονται στο ακόλουθο στιγμιότυπο:

Αφού γίνουν όλα αυτά, πατάμε το "OK" και αφήνουμε τον υπολογιστή να εγκαταστήσει τον GRUB και πάλι. Έτσι, διορθώνουμε και το πρόβλημα του boot.

Εδώ, άλλο ένα how-to τελειώνει. Ελπίζω να βοήθησα όποιον ενδιαφέρεται να "μεγαλώσει" λίγο τον σκληρό του δίσκο στο laptop. Αν έχετε openSUSE 11.3, η διαφορά είναι πως εκεί υπάρχει μόνο η επιλογή "Resque System" και έτσι θα έχετε να κάνετε με περιβάλλον κονσόλας, το οποίο βέβαια δεν είναι απαραίτητα κακό! Απλά, μια λίγο καλύτερη γνώση στην εκκίνηση και στα συστήματα αρχείων είναι καλό να υπάρχει, καθώς επίσης να γνωρίζεται εντολές του τύπου fdisk κ.λ.π.

May the source be with you

Ηλίας Χρυσοχέρης

Τρίτη 2 Νοεμβρίου 2010

Αλλαγή Ελαττωματικού Σκληρού Δίσκου σε ZFS-Only FreeBSD ΣύστημαChanging of malfunctioned hard disc in a ZFS-Only FreeBSD system

Μιας και τα hardware failures δίνουν και παίρνουν τον τελευταίο καιρό, δεν ξέφυγα κι εγώ από την ανάγκη αντικατάστασης ενός σκληρού δίσκου σε FreeBSD Server με ZFS-Only σύστημα αρχείων!

Since hardware failures are very common (to me) lately, I fell in the need of replacing one hard disc in my ZFS-Only FreeBSD Server!

Πιο συγκεκριμένα, πριν από λίγες ημέρες και ενώ ξύπνησα το πρωί και έκανα λίγο chat με τα μέλη του Chania-LUG, κάποια στιγμή το γραφικό περιβάλλον στον υπολογιστή μου πάγωσε! Η οθόνη γέμισε με πράσινες γραμμές, το ποντίκι κόλλησε και γενικά το μηχάνημα σταμάτησε να αποκρίνεται. Η πρώτη κίνηση που έκανα ήταν να μπω στο σύστημα μέσω δικτύου με ssh (από το κινητό γιατί το να στήσω laptop τα χαράματα ήταν μια διαδικασία... Αλλά αυτό δεν έχει καμιά σημασία). Είδα ότι το σύστημα είχε απόκριση, αλλά αρκετά αργή. Το ίδιο έκανα και με τον browser, όπου έλεγξα ότι ο υπολογιστής ανταποκρίνεται σε http requests κ.λ.π. Βασικά έκανα έλεγχο σε όλες τις υπηρεσίες που ήθελα να δουλεύουν. Παντού το ίδιο. Το γραφικό περιβάλλον παγωμένο με τους μπλε και πράσινους κόκκους και γραμμές, ενώ οι υπηρεσίες δουλεύαν όλες, αλλά με αρκετά μικρότερη ταχύτητα απόκρισης. Φυσικά αφού το μηχάνημα έχει και γραφικό περιβάλλον θα καταλάβατε ότι το χρησιμοποιώ και σαν desktop :P

Specifically, few days ago I woke up in the morning, had some chat with the members of Chania-LUG, and in a while the graphical environment of my PC was frozen! The screen was filled by vertical green lines, the mouse cursor was stuck to a place and didn't follow my mouse moves and the computer stopped responding. My first move was to try to ssh into the frozen computer through my network (from my cellphone because it was a little bit hard to get my laptop out of its bag early in the morning... But this has nothing to do with the story). The connection was successful, meaning that the system was up and running! I made a connection to the apache server running on the defected machine, using again my cellphone's browser and I could see the web pages served, but in a very poor and slow transfer rate. I also checked every single service that were running... the same results. Frozen graphical environment with all those blue and green spots and lines, but the services were all up and running in a slower rate. Of course, since the PC as a graphical environment you understand that I also use it as a desktop :P

Η πρώτη μου σκέψη ήταν "Μπόρα είναι θα περάσει! Κάτι κάνει το μηχάνημα από πίσω και την κάνει τη δουλειά. Το απόγευμα που θα γυρίσω σπίτι από τη δουλειά θα είναι όλα μια χαρά!" Σωστά σκέφτηκα γιατί όντως το μηχάνημα έκανε δουλειά. Για την ακρίβεια το ZFS Subsystem δούλευε για λογαριασμό μου. Για την ακρίβεια διόρθωνε και έσωζε δεδομένα που έβρισκε εσφαλμένα, εξ αιτίας του σκληρού δίσκου...

My first thought was that it was something temporary, the machine was busy on doing something and that is the reason for all the slow performance. I believed that in the afternoon, when back from my work everything will be back to normal. Well, my thought was correct... the system was busy and more specifically the ZFS Subsystem. It was trying to save data from the broken hard drive...

Το απόγευμα και αφού γύρισα σπίτι, είδα το μηχάνημα στην ίδια ακριβώς κατάσταση. Ξαναέκανα τον έλεγχο των υπηρεσιών και την έπεσα για έναν υπνάκο μιας και έβλεπα πως θα χρειαζόμουν όλες μου τις δυνάμεις για να μπορέσω να δω τι γίνεται...

In the afternoon after coming back home I found the computer in the same state. I rechecked its services and I fell in bed; I needed all my strength to find out what is really going on and to recover it...

Όταν τελικά αποφάσισα να ξεκινήσω τη δουλειά της επιδιόρθωσης του προβλήματος, κράτησα σημειώσεις για όλα όσα έκανα γιατί ήταν ευκαιρία να ξεκινήσω ένα ωραιότατο how-to. Και φυσικά, πού αλλού θα το αναρτούσα; Στην πιο κατάλληλη σελίδα του συλλόγου, την FreeBSD World. Εκεί βρίσκεται τώρα αναρτημένη η σελίδα που περιγράφει όλη τη διαδικασία της αλλαγής του ελαττωματικού σκληρού δίσκου, χωρίς να χρειαστεί εγκατάσταση του λειτουργικού από την αρχή. Η ιδιαιτερότητα είναι, φυσικά, το ZFS Filesystem. Απολαύστε την και ελπίζω να βοηθήσει αρκετά όποιον πάθει μια από τα ίδια.

When I finally decided to start working on the computer's problem I noted down all the steps I followed, as it was a very nice opportunity to make a how-to for problems like that. Hard discs fail! So, we must be prepared! And of course, this how-to is posted, where else? in FreeBSD World. There is the post that describes the whole process of changing a malfunctioned hard disc drive, without reinstalling the operating system from the very beginning. The specificity of the post is the ZFS Filesystem. The post is in Greek language, so I will translate it here. I think it is helpfull for those of you running a ZFS FreeBSD installation and have problems with the hard disc...

What's in this article

2. Time to loose our uptime... (again...)

It is time to reboot the computer... Logging in through ssh (this time from my laptop) I send the magical command...

eliaschr@pluto:~ > su
Password:
pluto# shutdown -r now
pluto#

In a while I received the normal Connection to pluto closed. message. From that point on we have to work on the defected computer only; no more network party!

When the monitor went up again and showing kernel messages I noticed some

ad0: FAILURE - READ_DMA48 status=51 error=40 LBA=383250045
ad0: FAILURE - READ_DMA48 status=51 error=1 LBA=383250045
ZFS: vdev I/O failure, zpool=zroot path=/dev/gpt/disk0 offset=191928776192 size=120320 error=5
ZFS: vdev I/O failure, zpool=zroot path=/dev/gpt/disk0 offset=191928776192 size=120320 error=5
ZFS: zpool I/O failure, zpool=zroot error=5
.
.
.

and many more of that type... The hard drive was at its last. Hmmm. Time to study ZFS Administration Handbook, to see what tools ZFS offers for cases like ours.This document is also in printed form in my library, of course... Just in case (is it one?)

What really impressed me is the fact that even with a malfunctioned hard disc the system went up! But without the graphical environment. Even through the errors in hard disc's data, ZFS used its magic and data, even then, were in a way safe! I would never imagine that!

3. Should I take a Backup?
a. Some ZFS info

Of course the answer is well known. It's time to describe some small details on helper ZFS functions on that part. Though the word "partition" is totally different from ZFS "Storage Pool Dataset", in the following text I'm going to use the word "partition" as if it has the same meaning as "ZFS Dataset". The reason is that a new ZFS user may have not distinguished the differences well enough. In that way, I believe that the text will be clearer.

The first ZFS functionality we need to know is the creation of snapshots. Snapshots are also a kind of ZFS dataset that we can mount on our system and use them in the same way as Read-Only Partitions. Their starting size is very small, just enough to hold some information for the dataset that they are a snapshot of. While we change data and files in the original dataset, ZFS stores the old data in the snapshot and then alters them in the original dataset. This means that the size of a snapshot in our hard drive is as small as possible, because it stores only the differences from the original ZFS dataset that it derives from.

The second functionality that we must be aware of (we will not use it here) is the ability of making clones. Clones can start only from a snapshot. Specifically a clone is a copy of the files of a snapshot to another part of the hard disc, together with the unchanged files that are in the ZFS dataset the snapshot comes from. So, a clone can be used as another Read/Write partition that contains all the original files of a dataset at the time we took its snapshot. In a snapshot there are only the "first release" of the altered/deleted files, while in a clone there are all the files of the snapshoted dataset. Spot that there is a snapshot to clone relationship; the snapshot is the "parent" of the clone. This relationship can be reversed if we desire. For more information about clones download and read the ZFS Administration Handbook. We will not use clones in this how-to so we won't cover clones more.

The third functionality contains the power we need and is send/receive. It is very much alike with the well known dump/restore to FreeBSD users. ZFS has the ability to send a whole dataset in a stream. That stream can be either saved as a file, or pipe it, i.e. through ssh, to a remote system. Looks very much like dump(8). What we need to say is that send can only be used in a snapshot and not in an alive dataset!

The reversed function is receive that looks alike restore(8). receive takes the data from a stream and generates a dataset. So, we could create a copy of a local dataset to a remote machine using ssh and the ZFS functions send and receive.

Armoured with those capabilities we described we can understand that ZFS provides us with a whole toolset to create a backup of our datasets; either by using clones, or by making a kind of a dump file, or even by having a remote machine with the role of a replicated backup server in case of failure of our main machine!

b. System setup

One thing we have to know is the system setup; the pools that exist in our system. In that way we can explain the state of the computer to find out what is going on. At the same time we will explain the reasons we decided to use this kind of real estate at the storage pools. The hard discs contained in the computer are one 1.5TB and two 500GB. The following diagram can bring some light and help us explain the whole setup:

A Testing ZFS Scheme

In the diagram the partitions of the hard discs are presented. In those disc partitions there will be the ZFS Storage Pools. The partitioning scheme is GPT and not the ordinary old geom(4).

The first 500GB of the hard disc are used for the operating system. Here there are the following partitions:

  • ad0p1: Boot Partition for the bootloader of the operating system. It has small size, 256KB are enough. Its partition type is freebsd-boot and contains the code of gptzfsboot.
  • ad0p2: Swap Partition for the virtual memory space of our operating system. Its size is 4GB and its type is freebsd-swap. The name of the partition is swap0
  • ad0p3: Here lies our operating system. The size of the artition is the rest of the first 500GB of the hard disc. Since there will be the ZFS Storage datasets, its type is freebsd-zfs.

In the last big part (the operating system's one) there are information that don't need to be mirrored. A failure in the operating system's part just needs another installation and nothing more.

There are other two big partitions on the disc of 1.5TB and they are both of size 500GB. These two partitions (ad0p4 and ad0p5 respectively) are mirrored by the two other hard discs of size 500GB each (ad1p1 and ad2p1 respectively). The reason that we do this mirroring is to have an automatic backup of our data to the other physical devices. In that way, whatever lies in partition ad0p4 it is also written in the hard disc ad1 and whatever lies in ad0p5 it is also written automatically in hard disc ad2.

One of the reasons we decided to use this configuration is the easiness of finding 500GB devices in a low price. So, it's a tactics we can use to be able to recover easily our system. At the same time, if a hard disc fails (which is the reason for this article's existance :)) then it is better to loose only 500GB of data than more (of course the best thing is not to loose a single bit, but...). In our case, the malfunctioned disc is, which one according to Murfy's Law, ad0 with capacity of 1.5TB. But even in that case the configuration we followed saved our data.

In order to be able to recover our system we need to have a new device of 1.5TB, that we will connect to the system externally on a USB. That means that the name of the new device will be da0. The following diagram presents the partitioning of the new hard drive and its relationship to the old malfunctioned one.

Replacing The Malfunctioned Disc

In the diagram the partitions are designed using dashed lines. This means that they do not exist and we have to create them. Don't forget that the new hard drive da0 is brand new.

Also, in the same diagram we can see that the partitions need to be copied are only three, ad0p3, ad0p4 and ad0p5. This is true because there is no need to copy neither the swap data, nor gptzfsboot code. The latter will be written in the new hard drive from the very beginning.

c. Check and data recovery

To be able to backup our data we must ensure that they are safe and correct. Only root user can perform such operations. Lets first check the state of the available ZFS Pools:

eliaschr@pluto:~ > su
Password:
pluto# zpool status -v #it could be -x as well
  pool: Common1
 state: ONLINE
status: The pool is formatted using an older on-disk format.  The pool can
        still be used, but some features are unavailable.
action: Upgrade the pool using 'zpool upgrade'.  Once this is done, the
        pool will no longer be accessible on older software versions.
 scrub: none requested
config:

        NAME             STATE     READ WRITE CKSUM
        Common1          ONLINE       0     0     0
          mirror         ONLINE       0     0     0
            gpt/disk1    ONLINE       0     0     0
            gpt/Mirror1  ONLINE       0     0     0

errors: No known data errors

  pool: Common2
 state: ONLINE
status: The pool is formatted using an older on-disk format.  The pool can
        still be used, but some features are unavailable.
action: Upgrade the pool using 'zpool upgrade'.  Once this is done, the
        pool will no longer be accessible on older software versions.
 scrub: none requested
config:

        NAME             STATE     READ WRITE CKSUM
        Common2          ONLINE       0     0     0
          mirror         ONLINE       0     0     0
            gpt/disk2    ONLINE       0     0     0
            gpt/Mirror2  ONLINE       0     0     0

errors: No known data errors

  pool: zroot
 state: ONLINE
status: One or more devices has experienced an unrecoverable error.  An
        attempt was made to correct the error.  Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
        using 'zpool clear' or replace the device with 'zpool replace'.
   see: http://www.sun.com/msg/ZFS-8000-9P
 scrub: none requested
config:

        NAME         STATE     READ WRITE CKSUM
        zroot        ONLINE       0     0     0
          gpt/disk0  ONLINE     198     0     0

errors: No known data errors
pluto#

Here we can see that the pool experienced unrecoverable error is the one that has contains the operating system, zrootTime to let ZFS to try to check the pool and recover whatever errors it can handle. This is how it is done:

pluto# zpool scrub
pluto# zpool status -v
  pool: Common1                                    
 state: ONLINE                                     
status: The pool is formatted using an older on-disk format.  The pool can
        still be used, but some features are unavailable.                 
action: Upgrade the pool using 'zpool upgrade'.  Once this is done, the   
        pool will no longer be accessible on older software versions.     
 scrub: none requested                                                    
config:                                                                   

        NAME             STATE     READ WRITE CKSUM
        Common1          ONLINE       0     0     0
          mirror         ONLINE       0     0     0
            gpt/disk1    ONLINE       0     0     0
            gpt/Mirror1  ONLINE       0     0     0

errors: No known data errors

  pool: Common2
 state: ONLINE 
status: The pool is formatted using an older on-disk format.  The pool can
        still be used, but some features are unavailable.                 
action: Upgrade the pool using 'zpool upgrade'.  Once this is done, the   
        pool will no longer be accessible on older software versions.
 scrub: none requested
config:

        NAME             STATE     READ WRITE CKSUM
        Common2          ONLINE       0     0     0
          mirror         ONLINE       0     0     0
            gpt/disk2    ONLINE       0     0     0
            gpt/Mirror2  ONLINE       0     0     0

errors: No known data errors

  pool: zroot
 state: ONLINE
status: One or more devices has experienced an unrecoverable error.  An
        attempt was made to correct the error.  Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
        using 'zpool clear' or replace the device with 'zpool replace'.
   see: http://www.sun.com/msg/ZFS-8000-9P
 scrub: scrub completed after 23h20m with 0 errors on Mon Oct 18 23:54:39 2010
config:

        NAME         STATE     READ WRITE CKSUM
        zroot        ONLINE       0     0     0
          gpt/disk0  ONLINE     249     0     0  256K repaired

errors: No known data errors
pluto#

After many hours of hard work, ZFS made its miracle! It recovered all the errors it found.

d. Data backup

To backup our data we need to follow two steps. The first is to make a snapshot of the datasets we want to backup and then we need to create the backup file fro the snapshot. The best way to do the latter in a mulfunctioned system is the ZFS send:

pluto# zfs list
NAME                            USED  AVAIL  REFER  MOUNTPOINT
Common1                         274G   182G   274G  /Common
Common2                         224G   233G    18K  /Common2
Common2/Backups                73,1G   233G  73,1G  /Common/Backups
Common2/Datasheets             7,43G   233G  7,43G  /Common/Datasheets
Common2/Documentation Section  3,22G   233G  3,22G  /Common/Documentation Section
Common2/ECh Documents          21,4G   233G  21,4G  /Common/ECh Documents
Common2/Pictures               13,4G   233G  13,4G  /Common/Pictures
Common2/home                    105G   233G   105G  /usr/home
Common2/www                     275M   233G   275M  /usr/local/www
zroot                           107G   346G   221M  legacy
zroot/tmp                       380M   346G   380M  /tmp
zroot/usr                      19,5G   346G  14,6G  /usr
zroot/usr/ports                4,64G   346G   270M  /usr/ports
zroot/usr/ports/distfiles      4,38G   346G  4,38G  /usr/ports/distfiles
zroot/usr/ports/packages         18K   346G    18K  /usr/ports/packages
zroot/usr/src                   303M   346G   303M  /usr/src
zroot/var                      2,32G   346G  13,5M  /var
zroot/var/crash                1024M   346G  1024M  /var/crash
zroot/var/db                   1,15G   346G  1,09G  /var/db
zroot/var/db/pkg               58,6M   346G  58,6M  /var/db/pkg
zroot/var/empty                  18K   346G    18K  /var/empty
zroot/var/log                  92,4M   346G  92,3M  /var/log
zroot/var/mail                  200K   346G   200K  /var/mail
zroot/var/run                   130K   346G   111K  /var/run
zroot/var/tmp                  67,3M   346G  67,3M  /var/tmp
pluto# zfs snapshot -r zroot/var@2010-10-20
pluto# zfs snapshot -r zroot/tmp@2010-10-20
pluto# zfs snapshot -r zroot/usr@2010-10-20
pluto# zfs snapshot zroot@2010-10-20
pluto# zfs list -t snapshot
NAME                                   USED  AVAIL  REFER  MOUNTPOINT
zroot@2010-10-20                        98K      -   221M  -         
zroot/tmp@2010-10-20                      0      -   380M  -         
zroot/usr@2010-10-20                   326K      -  14,6G  -         
zroot/usr/ports@2010-10-20                0      -   270M  -         
zroot/usr/ports/distfiles@2010-10-20      0      -  4,38G  -         
zroot/usr/ports/packages@2010-10-20       0      -    18K  -         
zroot/usr/src@2010-10-20                  0      -   303M  -         
zroot/var@2010-10-20                    21K      -  13,5M  -         
zroot/var/crash@2010-10-20                0      -  1024M  -         
zroot/var/db@2010-10-20                156K      -  1,09G  -         
zroot/var/db/pkg@2010-10-20               0      -  58,6M  -         
zroot/var/empty@2010-10-20                0      -    18K  -         
zroot/var/log@2010-10-20              85,5K      -  92,3M  -         
zroot/var/mail@2010-10-20                 0      -   200K  -         
zroot/var/run@2010-10-20                19K      -   111K  -         
zroot/var/tmp@2010-10-20                  0      -  67,3M  -         
pluto#

Snapshots are ready. Don't forget that snapshots are like partitions and can be mounted like any other partition. The only difference is that they contain only the old version of the files altered since the making of the snapshot and indexes to the unaltered ones.

Now we need to create copies of the snapshots but having all the files (not indexes). The real problem is the destination of the copies. If we connect an external drive at computer's USB then it is more likely that it will be formated using FAT32 or NTFS filesystem. FAT32 has the problem of maximum file size of 4GB. This is not appropriate for our situation because the data we need to backup are more than this maximum file size... In contrary NTFS can handle very large files but in FreeBSD fuse-ntfs is very unstable. It is very easy to have problems during writing to NTFS and have a very beautiful kernel core dump! So, we avoid using it.

The solution is our internal mirrored setup. The good thing about the existence of two mirrors is that the same data are in two hard discs at the same time. So, if one of them starts failing during a write cycle, ZFS knows well how to handle then and to keep the correct ones using the mirrored drive. Alternatively, we could run a ssh server in a remote machine in our network and send the backup there. There are solutions for everybody's taste! :P

Time for the real backup:

pluto# zfs send -Rv zroot/usr@2010-10-20 > /Common2/usr.20101020
.
.
.
pluto# zfs send -Rv zroot/tmp@2010-10-20 > /Common2/tmp.20101020
.
.
.
pluto# zfs send -Rv zroot/var@2010-10-20 > /Common2/var.20101020
.
.
.
pluto# zfs send -v zroot@2010-10-20 > /Common2/root.20101020
.
.
.
pluto# ls -l /Common2
-rw-r--r--  1 root  wheel    240931640 21 Οκτ 00:25 root.20101020
-rw-r--r--  1 root  wheel    563447860 20 Οκτ 22:27 tmp.20101020
-rw-r--r--  1 root  wheel  22777054676 20 Οκτ 20:08 usr.20101020
-rw-r--r--  1 root  wheel   4975268576 20 Οκτ 22:07 var.20101020
pluto#

Four files created form the backup of the whole operating system. The backup files were created in the second mirror. During ZFS send there are some warning messages, but that is normal due to ad0 hard disk malfunction.

4. Replacing the old malfunctioned hard disc

Since we are done with the backup, it is time to replace the malfunctioned device. We need to avoid installation of a new operating system (since we are able to do that) and transfer all the ZFS Pools in the new device to avoid the rest discomfort.

a. Preparation of the new hard drive

There is no need to power off the computer for this step, nor to have an empty SATA connector on our motherboard. Copying ZFS Pools/Datasets from a hard drive to another requires the new hard disc to be partitioned, like the old one. That is the preparation we need to apply to the new device. We will repeat the steps we made during the first time we installed FreeBSD on ZFS. The difference is that we will perform these actions on the hard drive connected to USB. When we connect the new hard drive using a SATA to USB converter we will see some kernel messages:

Oct 23 10:43:21 pluto kernel: ugen4.2:  at usbus4
Oct 23 10:43:21 pluto kernel: umass0:  on usbus4
Oct 23 10:43:21 pluto kernel: umass0:  SCSI over Bulk-Only; quirks = 0x4000
Oct 23 10:43:23 pluto kernel: umass0:2:0:-1: Attached to scbus2
Oct 23 10:43:23 pluto kernel: da0 at umass-sim0 bus 0 scbus2 target 0 lun 0
Oct 23 10:43:23 pluto kernel: da0:  Fixed Direct Access SCSI-2 device
Oct 23 10:43:23 pluto kernel: da0: 40.000MB/s transfers
Oct 23 10:43:23 pluto kernel: da0: 1430799MB (2930277168 512 byte sectors: 255H 63S/T 182401C)

It is clear from these messages that the system uses the name da0 to access the newly connected hard disc. Caution is needed when writing the name of the drive, because it is very easy to mistype it to ad0 which is the old malfunctioned one! The partitioning is made in the following way:

pluto# gpart destroy # may fail
pluto# gpart create -s gpt da0 # Create gpt scheme on external hard disc
pluto# gpart add -s 256K -t freebsd-boot da0 # Create the boot loader's partition
pluto# gpart add -s 4G -t freebsd-swap da0 # Do not label it yet

The two first partitions are created, one for bootcode and another for swap memory. The latter does not have a label yet, because the name we want to give to it is the same as the one already in use by the system. To write the boot code we must execute the following command:

pluto# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0
pluto#

If the command fails with a message that there is already a boot code written in the Boot Record then we just omit the command line switch -b, meaning:

da0 has bootcode
pluto# gpart bootcode -p /boot/gptzfsboot -i 1 da0
pluto#

It is very difficult to remember the exact size of the partitions disk0, disk1 and disk2 of the base hard drive (the malfunctioned one), it is a very good approach to ask gpart to show us:

pluto# gpart list ad0
Geom name: ad0             
fwheads: 16                
fwsectors: 63              
last: 2930275021           
first: 34                  
entries: 128               
scheme: GPT                
Providers:                 
1. Name: ad0p1             
   Mediasize: 262144 (256K)
   Sectorsize: 512         
   Mode: r0w0e0            
   rawtype: 83bd6b9d-7f41-11dc-be0b-001560b84f0f
   label: (null)                                
   length: 262144                               
   offset: 17408                                
   type: freebsd-boot                           
   index: 1                                     
   end: 545                                     
   start: 34                                    
2. Name: ad0p2                                  
   Mediasize: 4294967296 (4.0G)                 
   Sectorsize: 512                              
   Mode: r1w1e1                                 
   rawtype: 516e7cb5-6ecf-11d6-8ff8-00022d09712b
   label: swap0                                 
   length: 4294967296                           
   offset: 279552                               
   type: freebsd-swap                           
   index: 2                                     
   end: 8389153                                 
   start: 546                                   
3. Name: ad0p3                                  
   Mediasize: 495790956544 (462G)               
   Sectorsize: 512                              
   Mode: r1w1e2                                 
   rawtype: 516e7cba-6ecf-11d6-8ff8-00022d09712b
   label: disk0                                 
   length: 495790956544                         
   offset: 4295246848                           
   type: freebsd-zfs                            
   index: 3                                     
   end: 976730865                               
   start: 8389154                              
4. Name: ad0p4                                  
   Mediasize: 500107862016 (466G)               
   Sectorsize: 512                              
   Mode: r1w1e2                                 
   rawtype: 516e7cba-6ecf-11d6-8ff8-00022d09712b
   label: disk1                                 
   length: 500107862016                         
   offset: 500086203392                         
   type: freebsd-zfs                            
   index: 4                                     
   end: 1953504033                              
   start: 976730866                             
5. Name: ad0p5                                  
   Mediasize: 500106745856 (466G)               
   Sectorsize: 512                              
   Mode: r1w1e2                                 
   rawtype: 516e7cba-6ecf-11d6-8ff8-00022d09712b
   label: disk2                                 
   length: 500106745856                         
   offset: 1000194065408                        
   type: freebsd-zfs                            
   index: 5                                     
   end: 2930275021                              
   start: 1953504034                          
Consumers:                                      
1. Name: ad0                                    
   Mediasize: 1500300828160 (1.4T)              
   Sectorsize: 512                              
   Mode: r4w4e11                                

pluto#

The needed partitions are labelled disk0, disk1 and disk2, meaning those with index numbers 3, 4 and 5, respectively. In every block presented there are two values we need to consider. The first one is start and the second one is end. To figure out the size we need to pass to the following commands we must calculate end-start+1. For the showed partitions we have:

Label Start End Calculated Length
disk0 8389154 976730865 976730865 -8389154 +1 = 968341712
disk1 976730866 1953504033 1953504033 -976730866 +1 = 976773168
disk2 1953504034 2930277134 2930277134 -1953504034 +1 = 976773101

Knowing those values we can create the new partitions with exactly the same size as the old ones. The size we calculated is in number of blocks. The labels of the new partitions will be main0, main1 and main2, respectively (we cannot use the same labels as the ones already used by the system). For the last partition there is no need to specify size value. The system will occupy the rest of the free space of the device, without leaving unused space.

pluto# gpart add -s 968341712 -t freebsd-zfs -l main0 da0
pluto# gpart add -s 976773168 -t freebsd-zfs -l main1 da0
pluto# gpart add -t freebsd-zfs -l main2 da0
pluto#

Now the new hard disc drive is ready to replace the old malfunctioned one. The only step left is to copy the data.

b. Replacing the ZFS pools

ZFS has unbelievable power to administer its filesystems. It can even replace its pools! This is the ability we will use now:

pluto# zpool replace zroot gpt/disk0 gpt/main0
pluto# zpool status zroot
  pool: zroot
 state: ONLINE
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
 scrub: resilver in progress for 0h4m, 1,15% done, 6h15m to go
config:

        NAME           STATE     READ WRITE CKSUM
        zroot          ONLINE       0     0     0
          replacing    ONLINE       0     0     0
            gpt/disk0  ONLINE     259     0     0
            gpt/main0  ONLINE       0     0     0  1,23G resilvered

errors: No known data errors
pluto#

The first command (replace) starts a process called resilvering. Of course, this process takes a lot of time. ZFS Subsystem does whatever is needed in the background, leaving the user to perform other tasks as usual. The only difference is that the performance of the computer drops, something that is already true due to the malfunctioned hard disc. The second one (status) can be executed from time to time to see the status of the resilvering process. When resilvering of the pool finishes we can start the resilvering of the two other ZFS Pools. Use the following commands:

pluto# zpool replace Common1 gpt/disk1 gpt/main1 #wait until this process is finished and then...
pluto# zpool replace Common2 gpt/disk2 gpt/main2 #again, wait until the end of the process
pluto#

Finally, when all the resilvering of all available pools finishes, the new hard disc will contain all the data that could be recovered from the old one. ZFS subsystem will use the new pools that are now in the new hard drive. Time to power off the machine and replace the old malfunctioned device with the new one in the PC box.

pluto# shutdown -p now
5. WE ARE NOT DONE!!!!

OOOPS! What happened? Why the system does not boot up?

While trying to boot our machine with the new drive, just after the loader's menu we stay in mountroot with the notification that zfs:zroot could not be mounted! Whatever we do the system cannot boot our operating system. This makes us think that something is wrong with zpool.cache file. This file, in short, contains information for the structure of the ZFS pools and it is very important for the correct boot of the system. During the resilvering process this file was copied from the old hard disc, but its contained information describe the pools of the old device. So, these information do not match the new pools.

I believe you noticed that the labels of the gpt partitions are not the same as those applied in the old hard disc device but this is not a problem for the ZFS subsystem as we will see shortly. ZFS knows its pools by a unique ID that it applies to the pools at the time of their creation.

a. Changing of the labels of gpt partitions

In this procedure described here, the only mandatory part is to give swap partition the label that had in its previous device. This is convenient for us to avoid altering the /etc/fstab file. The rest are not necessary to be applied. We just restore the old labels for clarity, because we were used to them and not for any other reason. We will proove it here. The following procedure demands us to boot from livefs and use the Fixit console. There, we can check the state of the ZFS Pools.

Fixit# #lets load the zfs subsystem
Fixit# kldload /mnt2/boot/kernel/opensolaris.ko
Fixit# kldload /mnt2/boot/kernel/zfs.ko
Fixit# export LD_LIBRARY_PATH=/mnt2/lib

These commands must be executed every time we use Fixit console to be able to use the ZFS filesystem and access our ZFS Pools. Time for the pools check:

Fixit# zpool import
  pool: Common1
    id: 16786791901886102938
 state: ONLINE
action: The pool can be imported using its name or numeric identifier
config:

        NAME             STATE     READ WRITE CKSUM
        Common1          ONLINE       0     0     0
          mirror         ONLINE       0     0     0
            gpt/main1    ONLINE       0     0     0
            gpt/Mirror1  ONLINE       0     0     0

errors: No known data errors

  pool: Common2
    id: 2880185314831596717
 state: ONLINE
action: The pool can be imported using its name or numeric identifier
config:

        NAME             STATE     READ WRITE CKSUM
        Common2          ONLINE       0     0     0
          mirror         ONLINE       0     0     0
            gpt/main2    ONLINE       0     0     0
            gpt/Mirror2  ONLINE       0     0     0

errors: No known data errors

  pool: zroot
    id: 1188189039061593219
 state: ONLINE
action: The pool can be imported using its name or numeric identifier
config:

        NAME         STATE     READ WRITE CKSUM
        zroot        ONLINE       0     0     0
          gpt/main0  ONLINE       0     0     0

errors: No known data errors
Fixit#

Here we can see that the gpt partitions used by the pools are the correct ones. So, it is not really necessary to change their labels. Also, observe the id number. This is the unique number we mentioned earlier.

To change the gpt labels we have to use the following commands:

Fixit# gpart modify -i 2 -l swap0 ad0 #label the swap partition as swap0
Fixit# gpart modify -i 3 -l disk0 ad0
Fixit# gpart modify -i 4 -l disk1 ad0
Fixit# gpart modify -i 5 -l disk2 ad0

The biggest problem we have on zpool.cache file creation is that the pools must be imported normally and not using altroot. This forbids us from using -R command line switch in import command. And this in turn brings us more trouble because zroot, when mounted, sits over the already existed Fixit system and replaces everything, and the file we need is copied from a system before we use it! Wrong file! We have to find a solution to have the correct zpool.cache file and this is done in two steps. First we must import zroot using altroot to be able to set the mountpoints.

Fixit# zpool import -fR /zroot zroot
Fixit# zpool import -f Common1
Fixit# zpool import -f Common2
Fixit# zfs unmount -a
Fixit# zfs set mountpoint=none zroot
Fixit# zpool export Common2
Fixit# zpool export Common1
Fixit# zpool export zroot
Fixit#

What we achieved with this is that the system does not complain when we import the pools, warning us that we need to use -f option and, second, zroot's main filesystem does not automatically get mounted, so it does not replace the files of Fixit console. Now, the new problem is that /boot/zfs directory of zroot is not available so we can not write any file into it.

To be able to create zpool.cache, the directory /boot/zfs must be existed. This is not true in the Fixit console so we have to create the directory in question by ourselves:

Fixit# mkdir /boot/zfs
Fixit#

zpool.cache now will be created automatically when we import the pools. So:

Fixit# zpool import zroot
Fixit# zpool import Common1
Fixit# zpool import Common2
Fixit#

At that point /boot/zfs/zpool.cache file is created with the valid information that ZFS system needs to be operative. The only thing left is to copy this file into another part of zroot that is already accessible. The place we choose is the /tmp directory. After the copy we will unmount the filesystems and restore the mountpoint we altered earlier.

Fixit# cp /boot/zfs/zpool.cache /tmp
Fixit# zfs unmount -a
Fixit# zfs set mountpoint=/ zroot
Fixit# zpool export Common2
Fixit# zpool export Common1
Fixit# zpool export zroot

Now we are in position to copy the new zpool.cache in its correct place in zroot and to restore th final mountpoint as it should be for the system to get propperly boot-up.

Fixit# zpool import -fR /zroot zroot
Fixit# zpool import -f Common1
Fixit# zpool import -f Common2
Fixit# cp /zroot/tmp/zpool.cache /zroot/boot/zfs/
Fixit# zfs unmount -a
Fixit# zfs set mountpoint=legacy zroot
Fixit# reboot
.
.
.

If all things are done correctly after restarting, out FreeBSD will finally boot, without any problems from the new hard disc drive. Do not forget that we had a malfunctioned hard disc and its data could be corrupted making the operating system unusable...

To everybody who started to use this article and change a malfunctioned hard disc drive, I wish you good luck. May the source be with you!

Ηλίας Χρυσοχερης

Elias Chrysocheris