понедельник, 21 октября 2013 г.

Alcatel-Lucent OXE. Перезагрузка платы CPU, резервное копирование, смена роли платы.

Предисловие

За четыре года администрирования телефонных станций Alcatel-Lucent у меня накопилось некоторое количество мануалов, которые я писал для себя. Прошло некоторое время с той поры, и я решил вывалить это добро в сеть.

Самая суть

OXE поддерживает возможность резервирования CPU. В конфигурации, с которой мне довелось работать, на каждой телефонной станции было установлено по две платы CPU (CPU7-2). Одна из этих плат находится в рабочем (активном) режиме, вторая – в резервном. Каждой станции соответствуют три IP-адреса:
  • Первый – IP-адрес основной платы, 
  • Второй – IP-адрес резервной платы, 
  • Третий – «виртуальный» адрес, который всегда ссылается на ту плату, которая в данный момент работает в активном режиме. 
Через систему управления OmniVista можно в режиме конфигурации зайти на любую станцию и посмотреть установленные платы, их адреса и в каком режиме они находятся (см. Рис. 1):

Рис. 1.
В полке ACT платы CPU располагаются по центру кристалла, в слотах 6 и 20. При этом, как правило, если станция функционирует в штатном режиме, роль основной платы выполняет та, которая установлена в слоте №6. При доступе на эту плату через telnet она имеет имя вида xb….
Для доступа через telnet к платам CPU лучше пользоваться программным обеспечением putty или его форком kitty. 

Проверка состояния платы

Залогинившись на плату, первым делом смотрим на строку приглашения. Она должна выглядеть следующим образом (боевой пример с 6-го узла ABC-F-сети, состоящей из семи станций):
(106)xb001006>
В скобках указывается номер узла в сети ABC-F. Если в скобках находится буква E, значит, что-то не так, и на плате не запущены сервисы телефонии.
Чтобы узнать роль платы, на которую мы залогинились, необходимо выполнить команду role:
(106)xb001006> role
MAIN
Если бы плата была резервной, мы бы получили ответ STAND-BY.
Теперь необходимо проверить состояние синхронизации с резервной платой CPU, выполнив команду twin:
(106)xb001006> twin
Tue Nov 15 08:17:07 GMT-4 2011
Usage : twin [Redundancy Cpu Enable (y/n)]
Role and CPU positions:
Role of the CPU : MAIN
CPU position : 06
CPU address : 10.162.67.70
Twin CPU position : 20
Twin CPU address : 10.162.67.69
Redundancy State:
Duplicated configuration : YES
Wished sig. transfer mode : C1 signalling channel
Used sig. transfer mode : C1 signalling channel
Transmission CPU-CPU : READY
Telephony redundancy : READY
monitel redundancy : READY
memloader redundancy : READY
All applications redundancy : READY

В выводе данной команды мы видим, в каких позициях установлены основная и резервная плата, их IP-адреса, а также состояние сервисов репликации данных между платами. Если состояние сервисов отлично от READY, значит синхронизация между платами нарушена, и менять роли плат не рекомендуется. В таком случае нужно залогиниться на резервную плату и вручную скопировать базы с основной через интерфейс команды swinst. Об этом речь пойдёт позже.
Ещё перед тем как всё ломать, рекомендуется проверить состояние остальных плат конструктива при помощи команды config. Аргумент для этой команды – номер кабинета ACT (к примеру, в станции ГУ их два: 0 и 2). Можно выполнить команду config all, и тогда мы сможем увидеть все сконфигурированные кристаллы станции, в т.ч. виртуальные:
(106)xb001006> config 0
Tue Nov 15 08:32:49 GMT-4 2011
+-------------------------------------------------------------------+
| Cr | cpl| cpl type | hw type | cpl state | coupler ID |
|----|----|------------|-----------|--------------|-----------------|
| 0 | 0 | NPRAE|---------- | IN SERVICE | 3BA23254ABJE02 |
| 0 | 2 | eUA32|---------- | IN SERVICE | 3BA23266AAJA03 |
| 0 | 4 | eUA32|---------- | IN SERVICE | 3BA23266AAJA03 |
| 0 | 6 | CPU7_STEP2|---------- | IN SERVICE | BAD PCMS CODE |
| 0 | 8 | NDDI2|---------- | IN SERVICE | 3BA23171ABBE02 |
| 0 | 9 | eUA32|---------- | IN SERVICE | 3BA23266AAJA03 |
| 0 | 11 | eUA32|---------- | IN SERVICE | 3BA23266AAJA03 |
| 0 | 12 | eZ32|---------- | IN SERVICE | 3BA23265ABLB03 |
| 0 | 14 | EMTL|---------- | IN SERVICE | 3BA53116AAAB |
| 0 | 15 | INTIPA| INT-IP | IN SERVICE | 3BA23193ACJF05 |
| 0 | 17 | BRA2|---------- | IN SERVICE | 3BA23073ABJD04 |
| 0 | 20 | CPU7_STEP2|---------- | IN SERVICE | BAD PCMS CODE |
| 0 | 22 | BRA2|---------- | IN SERVICE | 3BA23073ABJD04 |
| 0 | 24 | BRA2|---------- | IN SERVICE | 3BA23073ABJD04 |
| 0 | 25 | GPA2|---------- | IN SERVICE | 3BA23241AAJC05 |
| 0 | 26 | RMA|---------- |ONLY MAO FILE | BAD PCMS CODE |
| 0 | 27 | NDDI2|---------- | IN SERVICE | 3BA23171ABBE02 |
+-------------------------------------------------------------------+
> Reference rack not set

В идеале в столбце cpl state все состояния плат кроме RMA должны быть IN SERVICE, а в поле coupler ID напротив всех плат кроме CPU и RMA должны находиться идентификаторы плат. Если состояние какой-нибудь платы не соответствует описанному, можно попробовать сбросить её командой rstcpl x y, где x – значение первого, а y – значение второго столбца из таблицы, выдаваемой командой config. 
Это, соответственно, номер кристалла и номер платы.
Ещё будет не лишним проверить таблицу инцидентов, выполнив команду incvisu. Смотрим сообщения, анализируем, ищем информацию в сети или запрашиваем её у сервисных инженеров, если есть оплаченная техподдержка.

Смена ролей между основной и резервной платой

Если всё хорошо, то есть платы CPU синхронизированы, все платы в рабочем состоянии, можем менять роли. Для этого мы должны, будучи залогиненными на основной плате, выполнить команду bascul. При этом на некоторое время (несколько минут) пропадут IP-соединения между станцией, на которой осуществляется перенос ролей и всеми остальными станциями. Все внутренние разговоры, а также внешние голосовые соединения по аналоговым соединительным линиями и по цифровым потокам не должны прерываться.
Зачем вообще нужен перенос ролей? Он полезен в одном из следующих случаев:​ 
  • Какая-либо неисправность основной платы; 
  • Необходимость перезагрузки платы (в случае смены времени, например) ; 
  • Резервное копирование данных с жесткого диска платы; 
  • Установка обновлений; 
Смена роли в данных случаях позволяет не прерывать работу станции.

Потеря синхронизации между платами

Если в ответ на команду twin нам вываливается информация о том, что между платами нарушена синхронизация, то необходимо, залогинившись на резервной плате выполнить следующие действия:
  1. Остановить телефонию;
  2. Выполнить команду swinst (пароль по дефолту: SoftInst, но ДОЛЖЕН быть сменён);
  3. Выбрать последовательно: Expert Menu - Cloning & duplicate operations - CPU cloning;
  4. По очереди выполнить команды: Cloning Linux data, Cloning delivery и Cloning databases. Со всем соглашаться.

Резервное копирование HDD станции

Теперь, когда мы всё умеем проверять, рассказываю методику резервного копирования жёстких дисков АТС, осуществлять которую заставила меня судьба.
Для успешного осуществления резервного копирования нам понадобится следующее барахло:
  • Ноутбук или десктоп. Там должен быть COM-порт (подойдёт USB-переходник), Ethernet-порт, CD-ROM, два USB-порта. 
  • Переходник SATA-USB. 
  • Загрузочный CD-ROM Acronis True Image. 
  • Отвёртка с насадкой типа «звёздочка». 
  • Кабель для COM. 
  • Ethernet патч-корд. 
По идее здесь должна быть информация о том, как законнектиться на COM-порт или воткнуть сетевой кабель в Ethernet-разъём АТС-ки, чтобы можно было получить telnet-доступ к плате, но я пока опущу эти базовые сведения. Будем считать, что мы уже залогинились.
  1. Логинимся на основную плату CPU (20-й слот).
  2. Проверяем всё так, как описано во втором пункте данного руководства.
  3. Меняем роли плат.
  4. Выключаем плату, ставшую резервной, при помощи команды shutdown.
  5. Вынимаем плату из АТС. Откручиваем три болта крепления переходника HDD, откручиваем три болта крепления HDD к переходнику, вынимаем HDD из переходника.
  6. Подключаем HDD к переходнику SATA-USB, переходник втыкаем в рабочую станцию. Загружаемся с диска, бекапим.
  7. Втыкаем диск обратно в плату, плату в АТС. Включаем.
  8. Логинимся на вторую плату CPU (6-й слот). Проверяем, что забекапленная плата поднялась, находится в режиме STAND-BY, синхронизация ок, телефония на ней запустилась.
  9. Повторяем пункты 2-8 для второй платы.

Резервное копирование настроек станции по сети

Ежедневные архивы настроек станции лежат на самой станции, на активной процессорной плате, в каталоге /usr4/BACKUP/DAY. Всё, что нам нужно – это забрать эти настройки по FTP.
На гитхаб лежит готовый скрипт с комментариями, конфигурационный файл для скрипта, содержащий построчно имя станции, IP-адрес, имя и пароль пользователя для FTP-подключения и путь, куда сохранять скачанное.

Получение OPS-файлов по сети

OPS-файлы тоже можно забрать по FTP, они на станции в каталоге /usr4/BACKUP/OPS/. Однако, перед тем, как забрать файлы, необходимо сформировать их свежую версию, выполнив на станции следующие действия:
  1. Залогиниться на основную плату под пользователем mtcl;
  2. Запустить swinst;
  3. Выбрать п. 1 Easy menu;
  4. Выбрать п. 5 Backup OPS files on cpu disk;
  5. Подтвердить бекап файлов Confirm the backup of OPS files (y/n, default y): y
Все эти действия можно выполнить автоматически, используя программное обеспечение под названием Telnet Scripting Tool. Для этого необходимо сформировать Telnet-script в формате данной программы и скормить его ей.
На гитхабе также лежит скрипт сбора OPS-файлов, пример конфигурационного файл станций и исполняемый модуль Telnet Scripting Tool. По каждой станции также ведётся лог выполненных команд, который пишется в этот же каталог.

среда, 10 апреля 2013 г.

Знакомство с Jenkins


Данное руководство содержит пошаговые инструкции для установки системы непрерывной разработки Jenkins. Развёртывание системы происходило на виртуальной машине под управлением Proxmox. Этапы настройки Proxmox и создания виртуальной машины опущены.
  1. Установка и настройка операционной системы.
    1.1. Cтавим голый CentOS. Я брал дистрибутив network install вот отсюда: http://centos.arcticnetwork.ca/6.3/isos/i386/CentOS-6.3-i386-netinstall.iso, однако на специфическом железе лучше скачать DVD, т.к. может понадобиться, например, собирать драйверы на сетевую карту.
    1.2. По умолчанию на свежей системе поднят только loopback интерфейс, поэтому при необходимости конфигурируем путём изменения файла /etc/sysconfig/network-scpipts/ifcfg-eth0 (установить параметр ONBOOT=”yes”) и запускаем скриптом ifup-eth0.
    1.3. Устанавливаем Midnight Commander, просто так, на всякий случай: yum install mc, При необходимости устанавливаем sshd: yum install openssh-server (вообще-то по дефолту ssh server уже должен быть установлен).
    1.4. Устанавливаем hostname (в файле /etc/sysconfig/network), меняем пароль рута, поскольку через Java-апплет управления, предоставляемый PROXMOX, как-то было неудобно эти параметры сразу нормально выставить.

    Затем смотрим ip-адрес ifconfig и конннектимся через SSH: ssh root@192.168.10.235
На этом этапе я забекапил виртуалку:
/var/lib/vz/backups//dump/vzdump-qemu-501-2012_10_09-18_06_01.tar.gz
  1. Установка и настройка Mercurial.
    2.1. Посмотрим, что у нас есть в репозиториях:
[root@jenkins-edi ~]# yum search mercurial
...
mercurial.i686 : A fast, lightweight distributed source control management system
...
[root@jenkins-edi ~]# yum info mercurial.i686
...
Version : 1.4
Release : 3.el6
Size : 1.5 M
...

Версии староваты. Поэтому подключим дополнительные репозитории по этому мануалу: http://repoforge.org/use/
[root@jenkins-edi ~]# rpm -Uvh http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.i686.rpm
...


Далее нам нужно включить репозиторий rpmforge-extra. Это осуществляется правкой конфигурационного файла /etc/yum.repos.d/rpmforge.repo. Нужная строка выделена жирным.

[rpmforge-extras]
...
enabled = 1
...

Проверяем версию доступного для установки Mercurial:

[root@jenkins-edi yum.repos.d]# yum info mercurial.i686
...
Version : 2.2.2
Release : 1.el6.rfx
Size : 2.8 M
Repo : rpmforge-extras
...

Теперь версия свежая. Вот её и установим.

[root@jenkins-edi yum.repos.d]# yum install mercurial.i686


Тут я решил создать ещё один бекап:
/var/lib/vz/backups//dump/vzdump-qemu-501-2012_10_10-12_14_44.tar.gz'


2.2. Теперь необходимо настроить ssh-доступ к репозиторию. Создаём нового пользователя и директорию для нашего будущего репозитория:

[root@jenkins-edi yum.repos.d]# adduser hg
[root@jenkins-edi yum.repos.d]# passwd hg
[root@jenkins-edi /]# su hg
[hg@jenkins-edi /]$ mkdir /home/hg/repo
[hg@jenkins-edi /]$ cd /home/hg
[hg@jenkins-edi ~]$ chmod 700 repo/
[hg@jenkins-edi ~]$ ll
итого 4
drwx------. 2 hg hg 4096 Окт 10 13:54 repo

Подготавливаем клиента. У меня это будет виртуальная машина с Windows XP. С официального сайта http://mercurial.selenic.com/ скачан дистрибутив Mercurial и установлен с указанием прописать в path путь до исполняемых модулей приложения.
Помимо этого установим Eclipse c JDK для создания тестового проекта, который мы будем размещать на наш сервер-репозитарий.
Для успешной работы Mercurial необходимо указать имя пользователя, которое будет фигурировать в каждом коммите. В нашем случае оно указывается в конфигурационном файле:
C:\Program Files\Mercurial\Mercurial.ini
Там мы в разделе [ui] прописываем следующее:
username = Dmirty Myasnikov <d****v@***.ru>
Также для успешного доступа к удалённому репозиторию через ssh нам необходимо указать используемый ssh-клиент под Windows. Я для этих целей установил TortoiseHG и в том же разделе конфигурационного файла Mercurial прописал (раскомментировал):
ssh = "C:\Progra~1\TortoiseHg\TortoisePlink.exe" -ssh -2
Первый тестовый проект разместим в каком-нибудь каталоге. Запустим командную строку Windows и перейдём в этот каталог. Затем будем выполнять команды для работы с репозиторием:

C:\Documents and Settings\Admin>cd c:\java\projects
C:\java\projects>cd HelloMercurials
C:\java\projects\HelloMercurial>hg init
C:\java\projects\HelloMercurial>hg add
adding .classpath
adding .project
adding .settings\org.eclipse.jdt.core.prefs
adding bin\ru\ediweb\ci\MyMain.class
adding bin\test\TestMyMain.class
adding src\ru\ediweb\ci\MyMain.java
adding src\test\TestMyMain.java
C:\java\projects\HelloMercurial>hg commit -m "First version of project"

А теперь склонируем репозиторий на удалённый сервер (параметр -v указываем для вывода дополнительной информации):

C:\java\projects\HelloMercurial>hg clone . ssh://hg@192.168.10.235/repo/HelloMercurial -v
running "C:\Progra~1\TortoiseHg\TortoisePlink.exe" -ssh -2 hg@192.168.10.235 "hg init repo/HelloMercurial"
running "C:\Progra~1\TortoiseHg\TortoisePlink.exe" -ssh -2 hg@192.168.10.235 "hg -R repo/HelloMercurial serve --stdio"
searching for changes
1 changesets found
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 7 changes to 7 files

Получилось! Попробуем что-нибудь изменить в проекте. К примеру я создал новый класс. Выполним следующие команды, чтобы добавить новые файлы, просмотреть изменения по сравнению с исходным проектом и закоммитить эти изменения:

C:\java\projects\HelloMercurial>hg add
adding bin\ru\ediweb\ci\SimpleClass.class
adding src\ru\ediweb\ci\SimpleClass.java
C:\java\projects\HelloMercurial>hg diff
diff -r 8e52463bc091 bin/ru/ediweb/ci/SimpleClass.class
Binary file bin/ru/ediweb/ci/SimpleClass.class has changed
diff -r 8e52463bc091 src/ru/ediweb/ci/SimpleClass.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ru/ediweb/ci/SimpleClass.java Wed Oct 10 16:38:29 2012 +0400
@@ -0,0 +1,14 @@
+package ru.ediweb.ci;
+
+public class SimpleClass {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
C:\java\projects\HelloMercurial>hg commit -m "Adding new class"

Проталкиваем изменения на сервер:

C:\java\projects\HelloMercurial>hg push ssh://hg@192.168.10.235/repo/HelloMercurial -v
pushing to ssh://hg@192.168.10.235/repo/HelloMercurial
running "C:\Progra~1\TortoiseHg\TortoisePlink.exe" -ssh -2 hg@192.168.10.235 "hg -R repo/HelloMercurial serve --stdio"
searching for changes
1 changesets found
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 2 changes to 2 files
  1. Теперь у нас есть свой Mercurial сервер с доступом к репозиторию по SSH. По идее перед тем как устанавливать Jenkins было бы неплохо на этом сервере развернуть какую-нибудь систему сборки проектов и автоматизированного тестирования, которые брали бы проект из репозитория Mercurial, собирали и тестировали бы его. Мой тестовый проект написан на Java, поэтому для экспериментов я поставлю Ant и JUnit. Помимо них нам ещё понадобится JDK для сборки.
В случае работы с PHP-проектами нам нужно будет дополнительно поднять веб сервер с PHP-движком, систему сборки Phing и, очевидно, какой-нибудь PHPUnit.

Вообще, можно поступить хитрее и попробовать настроить некоторые вещи через Jenkins. Однако мы всё сделаем руками, чтобы знать, что, где и зачем. Настройка Jenkins в плане привязки установленного программного обеспечения рассмотрена в п. 4.2.

Перед тем как идти дальше, забекапим-ка нашу виртуальную машину:
/var/lib/vz/backups//dump/vzdump-qemu-501-2012_10_10-16_57_06.tar.gz'

             3.1. Cкачиваем JDK c сайта Oracle и копируем его на наш хост:
На сервере:

[root@jenkins-edi ~]# mkdir install

На клиенте:

Z:\home\install\win\putty>pscp "c:\Documents and Settings\Admin\Мои документы\Downloads\jdk-7u7-linux-i586.rpm" root@192.168.10.235:/root/install/
root@192.168.10.235's password:
jdk-7u7-linux-i586.rpm | 123515 kB | 4117.2 kB/s | ETA: 00:00:00 | 100%

На сервере:

[root@jenkins-edi ~]# cd install
[root@jenkins-edi install]# rpm -i jdk-7u7-linux-i586.rpm

Проверяем, установилась ли Java:

[root@jenkins-edi install]# java -version
java version "1.7.0_07"
Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
Java HotSpot(TM) Client VM (build 23.3-b01, mixed mode, sharing

3.2. Устанавливаем Ant. Предварительно устанавливаем wget.

[root@jenkins-edi ~]# yum install wget
…
[root@jenkins-edi install]# wget http://www.apache.org/dist/ant/binaries/apache-ant-1.8.4-bin.tar.bz2 /root/install
[root@jenkins-edi install]# tar xvf apache-ant-1.8.4-bin.tar.bz2
…
[root@jenkins-edi install]# mv apache-ant-1.8.4 /opt
[root@jenkins-edi install]# export JAVA_HOME=/usr/java/jdk1.7.0_07/
[root@jenkins-edi install]# export ANT_HOME=/opt/apache-ant-1.8.4/
[root@jenkins-edi install]# export PATH=$PATH:$ANT_HOME/bin

Последние три строки нужно бы добавить в ~/.bash_profile соответствующего пользователя, чтобы переменные окружения автоматически инициализировались при перезагрузке. Я работаю под рутом, поэтому в /root/.bash_profile добавил следующие строки:

JAVA_HOME=/usr/java/jdk1.7.0_07
export JAVA_HOME  
ANT_HOME=/opt/apache-ant-1.8.4/
export ANT_HOME
PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin
export PATH  

Проверяем, работает ли наш Ant.

[root@jenkins-edi install]# ant
Buildfile: build.xml does not exist!
Build failed

Ant работает. Теперь поколдуем над нашим тестовым проектом.

3.3. Скачаем JUnit на клиент, создадим Ant-скрипт, проверим работу всего этого на сервере.

На клиенте скачанный JUnit будет расположен в папке C:\Java в виде файла junit-4.10.jar. Попробуем для начала натравить JUnit на наш проект:

C:\java\projects\HelloMercurial>java -cp c:\java\junit-4.10.jar;.\bin\ junit.textui.TestRunner test.TestMyMain
..
Time: 0,016
OK (2 tests)

В сам проект добавим каталог /lib, куда поместим junit-4.10.jar (хотя это неправильно, но мы оставим так в тестовых целях, чтобы не править потом build.xml на сервере) и создадим buildfile для Ant следующего содержания:

<?xml version="1.0" encoding="UTF-8"?>
<project name="HelloMercurial" default="compile" basedir=".">
<path id="JUnit.classpath">
<pathelement location="./lib/junit-4.10.jar"/>
</path>

<path id="HelloMercurial.classpath">
<pathelement location="bin"/>
</path>

<target name ="compile" description="Compile project">
<javac srcdir="src" destdir="bin"/>
</target>
<target name ="test" description="Test project">
<junit printsummary="yes">
<classpath refid="JUnit.classpath" />
<classpath refid="HelloMercurial.classpath" />
<test name="test.TestMyMain"/>
</junit>
</target>
</project>

Весь это проект протолкнём в наш репозиторий:

C:\java\projects\HelloMercurial>hg add
adding build.xml
adding lib\junit-4.10.jar

C:\java\projects\HelloMercurial>hg commit -m "Tests, Ant build"
C:\java\projects\HelloMercurial>hg push ssh://hg@192.168.10.235/repo/HelloMercurial -v
pushing to ssh://hg@192.168.10.235/repo/HelloMercurial
running "C:\Progra~1\TortoiseHg\TortoisePlink.exe" -ssh -2 hg@192.168.10.235 "hg
-R repo/HelloMercurial serve --stdio"
searching for changes
1 changesets found
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 5 changes to 5 files

теперь на сервере сделаем следующее:

[root@jenkins-edi /]# cd /home/hg/repo/
[root@jenkins-edi repo]# hg clone HelloMercurial /root/HelloMercurial

обновляемся на ветку default

11 файлов обновлено, 0 слито, 0 удалено, 0 c конфликтами
[root@jenkins-edi repo]# cd /root/HelloMercurial/
[root@jenkins-edi HelloMercurial]# ant test
Buildfile: /root/HelloMercurial/build.xml

test:
[junit] Running test.TestMyMain
[junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0,002 sec

BUILD SUCCESSFUL
Total time: 0 seconds

И тут мы опять бекапимся! /var/lib/vz/backups//dump/vzdump-qemu-501-2012_10_11-17_21_58.tar.gz

  1. Отлично. Теперь на сервере у нас работают и Mercurial, и Ant и JUnit. Не совсем канонично настроенные, но вполне ок такие. Приступаем к установке Jenkins.
4.1. Добавляем нужные репозитории:

[root@jenkins-edi HelloMercurial]# wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
--2012-10-11 14:21:58-- http://pkg.jenkins-ci.org/redhat/jenkins.repo
Распознаётся pkg.jenkins-ci.org... 63.246.20.93
Устанавливается соединение с pkg.jenkins-ci.org|63.246.20.93|:80... соединение установлено.
Запрос HTTP послан, ожидается ответ... 200 OK
Длина: 75 [text/plain]
Saving to: «/etc/yum.repos.d/jenkins.repo»
100%[======================================>] 75 --.-K/s в 0s
2012-10-11 14:21:59 (11,4 MB/s) - «/etc/yum.repos.d/jenkins.repo» saved [75/75]
[root@jenkins-edi HelloMercurial]# rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key

Устанавливаем Jenkins:

[root@jenkins-edi HelloMercurial]# yum install jenkins

Открываем порт 8080 в IPTABLES

[root@jenkins-edi ~]# iptables -I INPUT 2 -p tcp -i eth0 --dport 8080 -j ACCEPT
[root@jenkins-edi ~]# iptables -A OUTPUT -p tcp --sport 8080 -j ACCEPT
[root@jenkins-edi ~]# /etc/init.d/iptables save

Запускаем Jenkins

[root@jenkins-edi ~]# /etc/init.d/jenkins start
Starting Jenkins [ OK ]

4.2.  Теперь мы можем обратиться к порту 8080 нашего хоста по http. Там мы должны увидеть веб-интерфейс Jenkins:
Рис. 1. Веб-интерфейс Jenkins.
Нажимаем на кнопку Manage Jenkins. На следующей странице нажимаем на Manage Plugins. Воспользовавшись поиском, поставим плагин Mercurial:

Рис. 2. Mercurial plugin.
Теперь нажимаем Manage Jenkins – Configure System. Указываем там параметры установленного на сервере JDK:
Рис. 3. Параметры JDK.
Параметры установленного Mercurial:
Рис. 4. Параметры Mercurial.
Параметры установленного Ant:
Рис. 5. Параметры Ant.
Нажмём кнопку Save, чтобы сохранить сделанные изменения и приступим к созданию нашего первого задания. Для этого нажмём на кнопку New Job и зададим имя заданию.
Рис. 6. Создание нового задания.
Настроим ежеминутную сборку нашего проекта, чтобы не пришлось долго ждать результата:


Рис. 7. Настройка проекта и планировщика сборки.
Далее на той же странице в разделе Build жмём кнопку Add build step и выбираем пункт Invoke Ant. Добавим два таких шага:
Рис. 8. Настройка сборки.
Сборка должна завершиться ошибкой. Ещё бы, ведь при доступе к репозиторию по SSH необходимо вводить пароль. Исправим это. Настроим SSH-авторизацию по RSA-ключу:
[root@jenkins-edi /]# sudo -u jenkins ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/var/lib/jenkins/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /var/lib/jenkins/.ssh/id_rsa.
Your public key has been saved in /var/lib/jenkins/.ssh/id_rsa.pub.
The key fingerprint is:
dd:78:a9:26:19:26:a8:ae:48:0f:04:29:80:9c:22:d1 jenkins@jenkins-edi
The key's randomart image is:
+--[ RSA 2048]----+
|=o. |
|=+E |
|* |
|o . . o . |
| . . . S o + |
|. . o o o |
| o. o o |
|o.o o |
|o... |
+-----------------+
[root@jenkins-edi /]# cat /var/lib/jenkins/.ssh/id_rsa.pub >> /home/hg/.ssh/authorized_keys

Добавим на хосте сами себя в список известных хостов:
[root@jenkins-edi bin]# sudo -u jenkins /usr/bin/ssh hg@192.168.10.235
The authenticity of host '192.168.10.235 (192.168.10.235)' can't be established.
RSA key fingerprint is f1:ff:dc:32:fe:42:50:84:74:7c:78:85:14:2d:df:5b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.10.235' (RSA) to the list of known hosts.

В некоторых рекомендациях по конфигурированию Jenkins говорится следующее:
По умолчанию при выполнении задания у пользователя jenkins не определена переменная окружения HOME, поэтому он не знает, где ему искать параметры подключения к SSH-серверу. Поэтому необходимо в свойствах задания указать дополнительный параметр в разделе This build is parametrized.
У меня всё работает и без указания дополнительных параметров, однако на всякий случай я приведу скриншоты этих настроек. Думаю, они будут актуальны при хранении ssh-ключей в месте, отличном от JENKINS_HOME.

Рис. 9. Добавление строкового параметра.
Рис. 10. Необходимый параметр

Переходим на главную страницу и видим, что проект успешно собран:
Рис. 11. Первый успех.
Посмотрим, что у нас в потоке вывода. Подведём курсор мыши к нужному месту и выберем Console Output:
Рис. 12. Просмотр вывода сборщика проекта.
Вот что там у нас:

Started by timer
Building in workspace /var/lib/jenkins/jobs/MyFirstJob/workspace
[workspace] $ /usr/bin/hg showconfig paths.default
[workspace] $ /usr/bin/hg pull --rev default
[workspace] $ /usr/bin/hg update --clean --rev default
0 файлов обновлено, 0 слито, 0 удалено, 0 c конфликтами
[workspace] $ /usr/bin/hg log --rev . --template {node}
[workspace] $ /usr/bin/hg log --rev . --template {rev}
[workspace] $ /usr/bin/hg log --rev 67d89a607a40570bdd1a2b50c4cbd3eeac8fc9ac
[workspace] $ /usr/bin/hg log --template "<changeset node='{node}' author='{author|xmlescape}' rev='{rev}' date='{date}'><msg>{desc|xmlescape}</msg><added>{file_adds|stringify|xmlescape}</added><deleted>{file_dels|stringify|xmlescape}</deleted><files>{files|stringify|xmlescape}</files><parents>{parents}</parents></changeset>\n" --rev default:0 --follow --prune 67d89a607a40570bdd1a2b50c4cbd3eeac8fc9ac
[workspace] $ /opt/apache-ant-1.8.4/bin/ant test
Buildfile: /var/lib/jenkins/jobs/MyFirstJob/workspace/build.xml

test:
[junit] Running test.TestMyMain
[junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0,002 sec

BUILD SUCCESSFUL
Total time: 0 seconds
[workspace] $ /opt/apache-ant-1.8.4/bin/ant
Buildfile: /var/lib/jenkins/jobs/MyFirstJob/workspace/build.xml

compile:
[javac] /var/lib/jenkins/jobs/MyFirstJob/workspace/build.xml:13: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds

BUILD SUCCESSFUL
Total time: 0 seconds
Finished: SUCCESS

Тест и компиляция, заданные в соответствующем ant-скрипте проходят, как этого и следовало ожидать. С первичной настройкой сервера покончено.

Ссылки:

CentOS:
Официальный сайт Mercurial:
Графический клиент Mercurial под Windows:
Настройка сервера для работы с Mercurial:
Ant:
JUnit:
Jenkins: