Own installation Ganeti Web Manager + own Python environment + localization (by desire).

Актуально для текущей-последней версии GWM (в репозитории pip), для Python 2.17.13 (собственная оригинальная инсталляция в /opt).
Apache 2.4, Ganeti 2.15.2 on CentOS7.

Для развертывания django приложения, коим является GWM, используется “правильный” подход запуска приложений “изпод” выделенных аккаунтов на сервере, в своей домашней директории, со всеми своими спефическими добавлениями. Подразумевается, что на данный момент в системе создан пользователь, с доступом к командной оболочке и со своим домашником каталогом.

В домашнем каталоге созданы или существуют две директории “logs” и “public_html”. Также подразумевается, что уже загружен файл для получения pip по сети, обновлен профильный скрипт оболочки для корректного отражения путей поиска. Обо всем этом сказано уже здесь – http://upwork.link/python/additional-version-of-python-2-7-from-source-code-local-pip-and-mod_wsgi-on-apache2-4. И собственно получен и установлен pip в режиме –user. Так же не плохо добавить переменную в локальный профиль – export DJANGO_SETTINGS_MODULE=”ganeti_webmgr.ganeti_web.settings”. Если это так, то далее:

1
2
3
webapp03@104:~/public_html> mkdir ganeti_webmgr
webapp03@104:~/public_html> pip install --user virtualenv
webapp03@104:~/public_html> virtualenv --setuptools --no-site-packages ganeti_webmgr

И сразу выполняем скрипт создания переменных среды

1
2
3
webapp03@104:~/public_html> source ganeti_webmgr/bin/activate
(ganeti_webmgr) webapp03@104:~/public_html>
(ganeti_webmgr) webapp03@104:~/public_html> pip install --upgrade setuptools pip wheel

Хотя предоставленный авторами вариант установки желает использование уже готовых образов пакетов с их сайта (http://ftp.osuosl.org/pub/osl/ganeti-webmgr/centos/6/x86_64) или где-то там из недр их хранилища явно не учитывающего присутствие основных версий дистрибутивов Linux, все же будет более логичным собрать требуемые версии пакетов обычным порядком.

С большой долей вероятности, при развертывании в не совсем новой системе, можно получить подобные ошибки в процессе сборки модулей криптографии, из-за старости пакета openssl

1
2
3
4
5
6
7
8
    build/temp.linux-x86_64-2.7/_openssl.c:680: error: parameter name omitted
    build/temp.linux-x86_64-2.7/_openssl.c:73007: error: expected ‘{’ at end of input
    error: command 'gcc' failed with exit status 1
   
    ----------------------------------------
Command ".../public_html/ganeti_webmgr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-fTbAzD/cryptography/setup.py';f=getattr(tok
enize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-ZPqe3k-record/install-rec
ord.txt --single-version-externally-managed --compile"
failed with error code 1 in /tmp/pip-build-fTbAzD/cryptography/

Нужно просто обеспечить наличие в системе openssl библиотек версии не ниже 1.0.1g и конечно dev версии пакетов в случае пакетной установки. Если это будет обеспечено, то установка пакета cryptography пройдет успешно в качестве теста, как показано ниже

1
2
3
4
5
6
7
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr> pip install cryptography
Collecting cryptography
  Using cached cryptography-1.7.2.tar.gz
...
Successfully built cryptography
Installing collected packages: cryptography
Successfully installed cryptography-1.7.2

Далее получаем официальную последнюю версию GWM из репозитория git или иным способом (или где-то тут на сайте). И распаковываем ее содержимое в нашем случае в $HOME/soft/ganeti_webmgr-master. Дальше уже проще.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
(ganeti_webmgr) webapp03@104: pip install --upgrade $HOME/soft/ganeti_webmgr-master
Processing .../soft/ganeti_webmgr-master                                                                                                        [98/2861]
Collecting Django<1.5,>=1.4 (from ganeti-webmgr==0.11.1)
  Downloading Django-1.4.22.tar.gz (7.8MB)
    100% |████████████████████████████████| 7.8MB 107kB/s
Collecting django-fields==0.2.1 (from ganeti-webmgr==0.11.1)
  Downloading django-fields-0.2.1.tar.gz
Collecting django-haystack==1.2.1 (from ganeti-webmgr==0.11.1)
  Downloading django-haystack-1.2.1.tar.gz (108kB)
    100% |████████████████████████████████| 112kB 5.6MB/s
Collecting django-registration<0.8,>=0.7 (from ganeti-webmgr==0.11.1)
  Downloading django-registration-0.7.tar.gz
Collecting django-tables2==0.13.0 (from ganeti-webmgr==0.11.1)
  Downloading django-tables2-0.13.0.tar.gz (44kB)
    100% |████████████████████████████████| 51kB 7.4MB/s
Collecting requests>=2.7.0 (from ganeti-webmgr==0.11.1)
  Downloading requests-2.13.0-py2.py3-none-any.whl (584kB)
    100% |████████████████████████████████| 593kB 1.5MB/s
Collecting simplejson==3.3.0 (from ganeti-webmgr==0.11.1)
  Downloading simplejson-3.3.0.tar.gz (67kB)
    100% |████████████████████████████████| 71kB 7.2MB/s
Collecting South==0.8.4 (from ganeti-webmgr==0.11.1)
  Downloading South-0.8.4-py2.py3-none-any.whl (135kB)
    100% |████████████████████████████████| 143kB 4.3MB/s
Collecting Whoosh==1.8.1 (from ganeti-webmgr==0.11.1)
  Downloading Whoosh-1.8.1.tar.gz (443kB)
    100% |████████████████████████████████| 450kB 1.3MB/s
Collecting django-include-strip-tag==0.1.0 (from ganeti-webmgr==0.11.1)
  Downloading django-include-strip-tag-0.1.0.tar.gz
Collecting VNCAuthProxy==1.1.1 (from ganeti-webmgr==0.11.1)
  Downloading VNCAuthProxy-1.1.1.tar.gz
Collecting django-object-log==0.7.1 (from ganeti-webmgr==0.11.1)
  Downloading django-object-log-0.7.1.tar.gz
Collecting django-object-permissions==1.4.6 (from ganeti-webmgr==0.11.1)
  Downloading django-object-permissions-1.4.6.tar.gz (84kB)
    100% |████████████████████████████████| 92kB 5.1MB/s
Collecting pyyaml==3.11 (from ganeti-webmgr==0.11.1)
  Downloading PyYAML-3.11.zip (371kB)
    100% |████████████████████████████████| 378kB 2.5MB/s
Collecting pycrypto (from django-fields==0.2.1->ganeti-webmgr==0.11.1)
  Downloading pycrypto-2.6.1.tar.gz (446kB)
    100% |████████████████████████████████| 450kB 2.0MB/s
Collecting Twisted>=10.2.0 (from VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
  Downloading Twisted-17.1.0.tar.bz2 (3.0MB)
    100% |████████████████████████████████| 3.0MB 294kB/s
Collecting txWS==0.9.1 (from VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
  Downloading txWS-0.9.1.tar.gz
Collecting pyopenssl (from VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
  Downloading pyOpenSSL-16.2.0-py2.py3-none-any.whl (43kB)
    100% |████████████████████████████████| 51kB 6.6MB/s
Collecting zope.interface>=3.6.0 (from Twisted>=10.2.0->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
  Downloading zope.interface-4.3.3.tar.gz (150kB)
    100% |████████████████████████████████| 153kB 3.7MB/s
Collecting constantly>=15.1 (from Twisted>=10.2.0->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
  Downloading constantly-15.1.0-py2.py3-none-any.whl
Collecting incremental>=16.10.1 (from Twisted>=10.2.0->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
  Downloading incremental-16.10.1-py2.py3-none-any.whl
Collecting Automat>=0.3.0 (from Twisted>=10.2.0->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
  Downloading Automat-0.5.0-py2.py3-none-any.whl
Requirement already up-to-date: six>=1.5.2 in .../.local/lib/python2.7/site-packages (from pyopenssl->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
Requirement already up-to-date: cryptography>=1.3.4 in ./lib/python2.7/site-packages (from pyopenssl->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
Requirement already up-to-date: setuptools in .../.local/lib/python2.7/site-packages (from zope.interface>=3.6.0->Twisted>=10.2.0->VNCAuthProxy==1.1.1->$
aneti-webmgr==0.11.1)
Collecting attrs (from Automat>=0.3.0->Twisted>=10.2.0->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
  Downloading attrs-16.3.0-py2.py3-none-any.whl
Requirement already up-to-date: ipaddress in ./lib/python2.7/site-packages (from cryptography>=1.3.4->pyopenssl->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
Requirement already up-to-date: asn1crypto>=0.21.0 in ./lib/python2.7/site-packages (from cryptography>=1.3.4->pyopenssl->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
Requirement already up-to-date: packaging in .../.local/lib/python2.7/site-packages (from cryptography>=1.3.4->pyopenssl->VNCAuthProxy==1.1.1->ganeti-we$
mgr==0.11.1)
Requirement already up-to-date: enum34 in ./lib/python2.7/site-packages (from cryptography>=1.3.4->pyopenssl->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
Requirement already up-to-date: idna>=2.1 in ./lib/python2.7/site-packages (from cryptography>=1.3.4->pyopenssl->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
Requirement already up-to-date: cffi>=1.4.1 in ./lib/python2.7/site-packages (from cryptography>=1.3.4->pyopenssl->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11.1)
Requirement already up-to-date: appdirs>=1.4.0 in .../.local/lib/python2.7/site-packages (from setuptools->zope.interface>=3.6.0->Twisted>=10.2.0->VNCAu$
hProxy==1.1.1->ganeti-webmgr==0.11.1)
Requirement already up-to-date: pyparsing in .../.local/lib/python2.7/site-packages (from packaging->cryptography>=1.3.4->pyopenssl->VNCAuthProxy==1.1.1$
>ganeti-webmgr==0.11.1)
Requirement already up-to-date: pycparser in ./lib/python2.7/site-packages (from cffi>=1.4.1->cryptography>=1.3.4->pyopenssl->VNCAuthProxy==1.1.1->ganeti-webmgr==0.11$
1)
Building wheels for collected packages: ganeti-webmgr, Django, django-fields, django-haystack, django-registration, django-tables2, simplejson, Whoosh, django-include$
strip-tag, VNCAuthProxy, django-object-log, django-object-permissions, pyyaml, pycrypto, Twisted, txWS, zope.interface
  Running setup.py bdist_wheel for ganeti-webmgr ... done
  Stored in directory: .../.cache/pip/wheels/40/a8/14/996eb2cc25c7a77a17a2d217156bd5f805bfbcbfd4a97ad803
  Running setup.py bdist_wheel for Django ... error
  Complete output from command .../ganeti_webmgr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-s57I66/Django/setup.$
y';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))"
bdist_wheel -d /tmp/tmp_KaSx8pip-w$
eel- --python-tag cp27:
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/tmp/pip-build-s57I66/Django/setup.py", line 69, in <module>
      raise RuntimeError('Django 1.4 does not support wheel. This error is safe to ignore.')
  RuntimeError: Django 1.4 does not support wheel. This error is safe to ignore.
 
  ----------------------------------------
  Failed building wheel for Django
...
...
Successfully built ganeti-webmgr django-fields django-haystack django-registration django-tables2 simplejson Whoosh django-include-strip-tag VNCAuthProxy django-object-log django-object-permissions pyyaml pycrypto Twisted txWS zope.interface
Failed to build Django
Installing collected packages: Django, pycrypto, django-fields, django-haystack, django-registration, django-tables2, requests, simplejson, South, Whoosh, django-include-strip-tag, zope.interface, constantly, incremental, attrs, Automat, Twisted, txWS, pyopenssl, VNCAuthProxy, django-object-log, django-object-permissions, pyyaml, ganeti-webmgr
  Running setup.py install for Django ... done
Successfully installed Automat-0.5.0 Django-1.4.22 South-0.8.4 Twisted-17.1.0 VNCAuthProxy-1.1.1 Whoosh-1.8.1 attrs-16.3.0 constantly-15.1.0 django-fields-0.2.1 django-haystack-1.2.1 django-include-strip-tag-0.1.0 django-object-log-0.7.1 django-object-permissions-1.4.6 django-registration-0.7 django-tables2-0.13.0 ganeti-webmgr-0.11.1 incremental-16.10.1 pycrypto-2.6.1 pyopenssl-16.2.0 pyyaml-3.11 requests-2.13.0 simplejson-3.3.0 txWS-0.9.1 zope.interface-4.3.3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(ganeti_webmgr) webapp03@itk-104:~> pip install --upgrade psycopg2
Collecting psycopg2
  Downloading psycopg2-2.7-cp27-cp27m-manylinux1_x86_64.whl (2.1MB)
    100% |████████████████████████████████| 2.1MB 445kB/s
Installing collected packages: psycopg2
Successfully installed psycopg2-2.7
(ganeti_webmgr) webapp03@itk-104:~>
(ganeti_webmgr) webapp03@itk-104:~> pip install --upgrade MySQL-python
Collecting MySQL-python
  Downloading MySQL-python-1.2.5.zip (108kB)
    100% |████████████████████████████████| 112kB 886kB/s
Building wheels for collected packages: MySQL-python
  Running setup.py bdist_wheel for MySQL-python ... done
  Stored in directory: .../.cache/pip/wheels/38/a3/89/ec87e092cfb38450fc91a62562055231deb0049a029054dc62
Successfully built MySQL-python
Installing collected packages: MySQL-python
Successfully installed MySQL-python-1.2.5
(ganeti_webmgr) webapp03@itk-104:~>

Создаем директорию для нашего конфига и генерим пару ключиков длиной – “ValueError: AES key must be either 16, 24, or 32 bytes long

1
2
3
4
5
6
(ganeti_webmgr) webapp03@itk-104:~> mkdir config
(ganeti_webmgr) webapp03@itk-104:~> head -c24 /dev/urandom | base64
8RP1lU0XQldB7/gWgoqAlAWIhq2KZrrQ
(ganeti_webmgr) webapp03@itk-104:~> head -c24 /dev/urandom | base64
GwX1g0XKLlZ4Jo4QsnEGENvwQYG2M19r
(ganeti_webmgr) webapp03@itk-104:~>

Далее все просто – набиваем конфиг, мигрируем базу (базу сделать заранее). Готовим статику и в конце обычный конфиг для Apache для модуля WSGI, именно под этого пользователя. Тестируем здесь – http://dashboard.g1.blades.uiip.openstack.by. Если нравится, по пишем мне и заказывваем такой же за 50$.

Так же не плохо, чтобы все получилось заменить некоторые неудобные жестко забитые автором пути – ‘/opt/ganeti_webmgr’ в файлах lib/python2.7/site-packages/ganeti_webmgr/ganeti_web/settings/settings.py.dist и lib/python2.7/site-packages/ganeti_webmgr/ganeti_web/settings/helpers.py на наш – $HOME/public_html/ganeti_webmgr. А также /static на /gwms.

Для заполнения базы таблицами после создания файла конфигурации пользуемся командой:

1
(ganeti_webmgr) webapp03@104:~> django-admin.py syncdb --migrate

Для создания индекса пользуемся командой:

1
(ganeti_webmgr) webapp03@104:~> django-admin.py rebuild_index

Для исправления жестко закодированных урлов автора, придется переделать файлы автора под свой путь к статике

1
2
3
4
5
6
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr/lib/python2.7/site-packages/ganeti_webmgr/templates> sed -i "s/\/static\//\/gwms\//g" ganeti/forms/*      
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr/lib/python2.7/site-packages/ganeti_webmgr/templates> sed -i "s/\/static\//\/gwms\//g" ganeti/cluster/*
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr/lib/python2.7/site-packages/ganeti_webmgr/templates> sed -i "s/\/static\//\/gwms\//g" ganeti/node/*
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr/lib/python2.7/site-packages/ganeti_webmgr/static> sed -i "s/\/static\//\/gwms\//g" css/*
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr/lib/python2.7/site-packages/ganeti_webmgr/static> sed -i "s/\/static\//\/gwms\//g" js/*
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr> django-admin.py collectstatic

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

1
2
3
4
5
6
7
8
9
10
On the ganeti master node, generate a strong random password like this:
 
# echo -n 'ganeti_webmgr_g0:Ganeti Remote API:blabla' | openssl md5
(stdin)= 4bc7b672420c7a5976ffc2be5f579780

Finally, as root create a file /var/lib/ganeti/rapi/users containing this one line

ganeti_webmgr_g0 {HA1}4bc7b672420c7a5976ffc2be5f579780 read,write
 
#  gnt-cluster copyfile /var/lib/ganeti/rapi/users

Если вы добрались до работы VNC консоли в веб оболочке (websocket), то очень вероятно в какой то момент времени у вас возникнет вопрос: а сколько и какие порты я должен открыть на машине с работающими менеджерами. Спешу немного огорчить, но студенты-питонята и тут снова нагадили в своем духе. В качестве прокси сервера они используют модуль под именем twisted. Много студенческого труда и … . В этих недрах присутствует модуль vncap (lib/python2.7/site-packages/vncap/control.py), его использует этот типа сервер и как Вы возможно поняли эти порты просто вбили в код скрпита даже не подумав !!! что это настройки должны быть как параметры. И даже соответствовать специальному динамическому диапазону.

1
2
3
4
5
6
7
8
...
from vncap.vnc.factory import VNCProxy

# Allowed proxy port ranges.
# By default, this is the VNC port range.
# To use a different port range, simply change the following two lines.
FIRST_PORT = 5800
LAST_PORT = 5900

Если уж … так делаете, так хоть берите не назначеный диапазон из /etc/services. К примеру – # 59800-59900 Unassigned. И конечно используйте для каждого менеджера свой!

И конечно для запуска этого проксирующего процесса, нужно положить в домашний ‘bin’ пользователя короткий скрипт, который и будет контролировать VNC через websocket для этого менеджера

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#! /bin/sh

DESC="VNC Auth Proxy"
NAME="vncauthproxy"
PIDFILE=$HOME/var/run/vncauthproxy/proxy.pid
LOGFILE=$HOME/var/log/vncauthproxy/proxy.log
DAEMON="$HOME/public_html/ganeti_webmgr/bin/twistd"
TWISTD_ARGS=" --pidfile=$PIDFILE --logfile=$LOGFILE vncap"
VNCAP_ARGS=" -c tcp:888X:interface=0.0.0.0" #  Выбрать уникальный порт в соответствии с конфигом!


source $HOME/public_html/ganeti_webmgr/bin/activate

if [ ! -d $HOME/var/run/vncauthproxy ] ; then
   mkdir -p $HOME/var/run/vncauthproxy
fi
if [ ! -d $HOME/var/log/vncauthproxy ] ; then
   mkdir -p $HOME/var/log/vncauthproxy
fi


do_start() {
   $DAEMON $TWISTD_ARGS $VNCAP_ARGS > /dev/null
}

if [ ! -e $PIDFILE ]; then
    echo "Daemon is not running"
    do_start  
else
    echo "PID file exists, checking process"
fi

PID=`cat $PIDFILE`

if [ ! -e /proc/$PID ]; then
    echo "Directory of process doesn't exists. Need to remove PIDFILE for restarting."
else
    echo "Directory of process exists. Seems process is active. "
fi

Следующей удивительной засиралкой логов веб сервера с сообщениями подобными:

1
2
[Tue Mar 07 05:48:55.189015 2017] [wsgi:error] [pid 13515]   InsecureRequestWarning)
[Tue Mar 07 05:48:56.290183 2017] [wsgi:error] [pid 13515] .../lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings

А причина проста, просто одни питонята решили кинуть питонят собственников другого такого же модуля прородителя и пилить свой … код. Вот так прямо и пишут:

1
2
3
4
5
6
7
8
requests.packages.urllib3 is not urllib3

With version ``2.5.2``, requests started to maintain its own stub, so that
distro-specific breakage would be reduced to a minimum, even though the whole
issue is not requests' fault in the first place. See
https://github.com/kennethreitz/requests/pull/2375 for the corresponding pull
request.
'
''

чтобы успокоить …, просто подсунем оригинальный совет отцов в requests/packages/__init__.py

1
2
3
4
5
6
7
try:
    from . import urllib3
except ImportError:
    import urllib3
    sys.modules['%s.urllib3' % __name__] = urllib3

urllib3.disable_warnings()  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<   ЭТО

На тему локализация интерфейса – как должно быть для всех русских и всего отстального мира. Сначала помним, что все что не может понять config.yml, и все остальные куски этой поделки, лучше сразуть исправить в файле -> lib/python2.7/site-packages/ganeti_webmgr/ganeti_web/settings/base.py. А именно оставляем там вместо греческой абракадабры только русский и английский:

1
2
3
4
LANGUAGES = (
  ('ru', ugettext('Russian')),
  ('en', ugettext('English')),
)

Теперь надо сделать файлики джанговской трансляции для всего где помечено. Подсказки читаем здесь – http://djangobook.com/localization-create-language-files. (или даже еще здесь – http://djbook.ru/rel1.7/ref/settings.html#language-code). Исходя из прочитанного переходим в корень установленного модуля ganeti_webmgr и творим от всей души:

1
2
3
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr/lib/python2.7/site-packages/ganeti_webmgr> django-admin.py makemessages -l ru
processing language ru
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr/lib/python2.7/site-packages:w/ganeti_webmgr>

И видим заветный файл для перевода – ganeti_webmgr/locale/ru/LC_MESSAGES/django.po. И начинаем его править как бы хотелось или можно спросить меня где его взять за 20$, для тех кому лень. После завершения всех переводов или в промежутках, выполняем компиляцию для тестов:

1
2
3
4
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr/lib/python2.7/site-packages/ganeti_webmgr> django-admin.py compilemessages
processing file django.po in .../public_html/ganeti_webmgr/lib/python2.7/site-packages/ganeti_webmgr/locale/ru/LC_MESSAGES
processing file django.po in .../public_html/ganeti_webmgr/lib/python2.7/site-packages/ganeti_webmgr/locale/en_US/LC_MESSAGES
(ganeti_webmgr) webapp03@104:~/public_html/ganeti_webmgr/lib/python2.7/site-packages/ganeti_webmgr>

PS -Обновление странички может случиться когда вздумается

Scroll to top