Различия между версиями 17 и 18
Версия 17 от 2008-07-08 11:37:07
Размер: 31691
Редактор: DmitryChistikov
Комментарий:
Версия 18 от 2008-07-08 12:20:24
Размер: 28832
Редактор: DmitryChistikov
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 69: Строка 69:
=== Потыкаем === Проиллюстрируем описанную схему. Посмотрим список пакетов в нашем дистрибутиве, относящихся к Alterator:
Строка 71: Строка 71:
Прежде чем тыкать, посмотрим в консоли apt-cache search alterator. Можно увидеть пакеты для различных модулей. alterator-что-то, есть даже отдельно alterator-backend-что-то, хотя в последнем случае обычно содержится и frontend, и backend, и этих пакетов немаленькое число. {{{
[user@demo ~]$ apt-cache search alterator
}}}
Строка 73: Строка 75:
вот lookout это как раз третий уровень. Что бы нам посмотреть?  ''Где тайпскрипт? Нужен список, он иллюстрирует модульную архитектуру Alterator'a.'' -- DmitryChistikov <<DateTime(2008-07-08T13:20:23+0400)>>
Строка 75: Строка 77:
Если сказать rpm -ql alterator-xkb, то можно увидеть утилиты, которыми он пользуется: На экране появился список основных компонентов и модулей Alterator'а. К примеру, alterator-lookout - это компонент, отвечающий за уровень представления, а alterator-xkb - модуль, управляющий настройками клавиатуры. Выведем список файлов в системе, относящихся к пакету alterator-xkb:
Строка 78: Строка 81:
/usr/bin/xkbdatadump                                 \ вот это фронтэнды
/usr/bin/xkbmapconf                                  /
/usr/lib/alterator/backend3/template-xkb             \ вот это бэкенды
/usr/lib/alterator/backend3/xkb                      /
/usr/share/alterator/applications/xkb.desktop        \
/usr/share/alterator/ui/xkb |

/usr/share/alterator/ui/xkb/avail_layout.scm         |
/usr/share/alterator/ui/xkb/html-messages.scm        |
/usr/share/alterator/ui/xkb/index.scm                | а вот это ui вместе с файлами локализации.
/usr/share/locale/be/LC_MESSAGES/alterator-xkb.mo    |
/usr/share/locale/ru/LC_MESSAGES/alterator-xkb.mo    |
/usr/share/locale/uk/LC_MESSAGES/alterator-xkb.mo    |
/var/www/html/fbi                                    |
/var/www/html/fbi/xkb-layout.html                    |
/var/www/html/fbi/xkb.html                           /
/usr/bin/xkbdatadump
/usr/bin/xkbmapconf
/usr/lib/alterator/backend3/template-xkb
/usr/lib/alterator/backend3/xkb
/usr/share/alterator/applications/xkb.desktop
/usr/share/alterator/ui/xkb

/usr/share/alterator/ui/xkb/avail_layout.scm
/usr/share/alterator/ui/xkb/html-messages.scm
/usr/share/alterator/ui/xkb/index.scm
/usr/share/locale/be/LC_MESSAGES/alterator-xkb.mo
/usr/share/locale/ru/LC_MESSAGES/alterator-xkb.mo
/usr/share/locale/uk/LC_MESSAGES/alterator-xkb.mo
/var/www/html/fbi
/var/www/html/fbi/xkb-layout.html
/var/www/html/fbi/xkb.html
Строка 95: Строка 98:
Посмотрите, в центр управления, есть там про клавиатуру?.. Есть. Я не понимаю, где здесь бэкэнд. А, вот (?), template. А вот это утилита, которая к нему ходит. Покажите-ка вот это, наверняка он на Scheme написан... хрен, на шелле он написан, ну вот. Вот эта часть -- представление (ui), эта часть (backend), эта часть -- представление в другом ui (html), это для конфигуратора который запускается через веб, а это специальная утилита, которая облегчает backend'у жизнь, и так оно устроено практически везде, в любом модуле мы увидим...

С alterator'ом избретался отнюдь не велосипед, потому что даже я слегка более жестко и менее аккуратно выдержан по этой трехуровневой архитектуре, и, в свое время моя была задача, чтобы системному администратору, которому все эти дизайнерские заморочки до лампочки, позволить писать свои бэкэнды на чем хочешь, на шелле, на awk, на perl, на Scheme, у нас не только ui на Scheme, но и backend'ы тоже можно писать. Тут UI написан на Scheme. Давайте посмотрим в ...layout, вы увидите, что это как-то безумно просто... 66 строк.

## вышеуказанные 66 строк смотрелись в view, так что сходу их не вытащишь, нужно повторить это тому, у кого есть под рукой ПСПО ;)
Файлы из /usr/lib/alterator/backend3 - это собственно back-end, исполняемые файлы из /usr/bin - используемые ими специальные утилиты. В /usr/share/locale лежат данные для локализации. Написанные на языке Scheme сценарии для интерфейса находятся в /usr/share/alterator/ui (в специальном подкаталоге), а в /var/www/html/fbi размещены файлы, относящиеся к Web-интерфейсу (обратим внимание на наличие двух разных способов представления). Заметим, что Alterator позволяет писать back-end'ы на чем угодно: подойдет и Shell, и awk, и Perl, и Scheme (который, как мы видим, в данном случае использовался для написания UI; заглянув в файл avail_layout.scm, мы увидим всего лишь 66 строк программного кода).
Строка 103: Строка 102:
Какой недостаток этого всего безобразия --- недостаток трехуровневого, да и вообще, составного, сложного конфигуратора в том, что он очень текучий. Никто до конца не знает, какой самый правильный протокол взаимодействия между уровня, и его постоянно надо менять, никто не знает, какая самая правильная дисциплина построения ui, мы ее отвязали от конкретного представления и можем что угодно делать, а в реальности если мы позволяем делать что угодно, он бывает такой развесистый, всякий, а надо бы сделать такую библиотеку, чтобы ей все пользовались, чтобы она была простая, чтобы сказал такой-такой-такой, берет данные оттуда, посылает данные туда, всем до свидания, вот что надо было сделать. И вообще говоря, его тоже нужно поддерживать. Главный недостаток рассмотренной конструкции (да и составного конфигуратора вообще) - его "текучесть". Обыкновенно очень тяжело разобраться, какой именно "самый правильный" протокол взаимодействия между уровням: он постоянно претерпевает значительные изменения. То же и с пользовательским интерфейсом: он не связан с конкретным представлением, но предоставляет множество разнородных элементов. Конструирование библиотек для таких интерфейсов - задача весьма непростая.
Строка 107: Строка 106:
 * Поддержка легче, чем в случае монолитного подхода. Традиционно костяк альтератора поддерживается 1--2 человеками, а модули пишет много кто. Человеческих ресурсов расходуется существенно меньше, хотя модулей достаточно много.
 * Независимость уровней. Независимость уровня бэкэнда от середины я уже показал, это (что выше) пишется на шелле, а это (что ниже) вообще может быть бинарник, а может быть на чем угодно, даже на scheme, т.к. там прямые ручки к среднему уровню, там не нужно переводить на один язык, потом на другой. Точно также есть независимость между уровнем представления и уровнем логики, о чем свидетельствует вот эта часть (?), это другое представление, предназначенное для html, для form-based интерфейс (FBI), это штука, которая используется в ALT Linux Server, и вообще во всех веб-конфигураторах наших. Это не переписанный конфигуратор, а переписанное только представление, разумеется мы сначала ввести промежуточный уровень унифицированного представления, но поняли, что это бессмысленно, если мы работаем с html -- там одни способы представления, если мы работаем с QT -- другие, если мы работаем с текстом -- вообще третьи, потому что нельзя на текстовом экране представить то, что можно представить...
 * Несмотря на то, что поддерживать "трехслойный" конфигуратор весьма непросто, это оказывается легче, чем при монолитном подходе. Главную часть Alterator'а традиционно поддерживают один-два человека, модули же пишутся гораздо большим количеством людей. Человеческих ресурсов при такой схеме расходуется существенно меньше, хотя модулей достаточно много.
Строка 110: Строка 108:
debconf в этом случае очень технологичен, он в некоторых случаях очень хорош, но у него есть недостаток -- он точно не ориентирован на задачу, он аналогично ориентирован на тот инструмент, который он конфигурирует, и в этом смысле это все упрощает, у него нету вот этого, манипуляции логикой. А дополнительный UI, когда вы выдаете все то же самое, переписанное в строчку, конечно, не катит.  * Главное достоинство "трехслойного" конфигуратора - независимость уровней. Для нижней пары уровней мы это уже видели, а для верхней пары это следует, к примеру, из существования разных интерфейсов. В Alterator, как мы видели, есть возможность использования form-based interface (FBI) - это уровень представления для Web. При создании Alterator'а была возможность вставки еще одного промежуточного уровня, но от этой идеи отказались, так как в Qt и, допустим, HTML (или тексте) слишком разные способы представления данных и команд. Хорошим технологичным примером в этом смысле служит Debconf, но у него нет центрального слоя, управления логикой (он ориентирован на инструмент, а не на задачу). В RHEL же и Fedora вместо этого используется целое семейство конфигураторов с разными интерфейсами.
Строка 112: Строка 110:
Кстати, в RHEL-Fedora, у них семейство конфигураторов, у них ничего единого, у них поддерживается текстовая часть, но поддерживается точно также, берется и переписывается большая часть с GUI на текст. У них есть силы на это.

## {01:39:20}
Строка 121: Строка 116:
|| 30 || 1 || 1 || 1 || || 1 || PavelSutyrin, DmitryChistikov || || || || 35 || 1 || 1 || 1 || || 1 || PavelSutyrin, DmitryChistikov || || ||

Использование конфигураторов: продолжение

1. Решение в лоб (из предыдущего раздела)

Недостатки

  • Вторая проблема заключается в обеспечении полного покрытия тех задач, которые нам нужны. Сделать это, разумеется, можно, но каждый раз приходится взаимодействовать с разными людьми, которые занимаются созданием соответствующих модулей. К примеру, нам нужно решить задачу "добавления пользователя". Это означает, что добавлять пользователя придется в passwd, в Samba, в хранилища типа LDAP и т. п. Заметим в скобках, что в линейке дистрибутивов ПСПО есть подсистемы, имеющие отдельный интерфейс конфигурирования, отличный от Alterator. Кроме того, конфигураторские интерфейсы часто разрабатываются не под задачу, а под инструмент. Типичный пример - графический конфигуратор /etc/net. Его использование, пожалуй, доставляет больше трудностей, чем непосредственное редактирование конфигурационных файлов: чтобы его использовать, надо знать, как именно функционирует /etc/net. Итак, здесь возникают значительные сложности в сопровождении.
  • Третья проблема - это синхронизация пространства имен. С одной стороны, это проекция первых двух проблем, с другой - проблема более общего плана. К примеру, при настройке различных подсистем приходится вводить один и тот же IP-адрес компьютера. Такая процедура вызывает раздражение со стороны пользователя. А если допустить возможность ошибки? Если в разных конфигураторах ввести разные адреса, то гарантировать корректность функционирования всех конфигурируемых таким образом подсистем будет невозможно. Таким образом, проблема унификации имен связана и с проблемой пересечения областей воздействия таких конфигураторов. Если для настройки некоторой службы нужно отредактировать, скажем, 10 файлов, а для настройки другой службы - 5, из которых 2 встречаются среди первых 10, то в случае разрозненных инструментов система, скорее всего, функционировать не будет вообще.

Достоинства

  • Достоинство такого подхода состоит в легкости сопровождения каждого модуля в отдельности. Достаточно следить за обновлением служб, которые он конфигурирует, и адаптировать его в случае изменения синтаксиса тех или иных конфигурационных файлов. Человек, пользующийся и этим файлом, и конфигуратором, сделает это без всякого напряжения. Здесь один из указанных ранее недостатков обращается в достоинство: когда инструмент конфигурации привязан не к задаче, а к инструменту, сопровождение его особенно легко. Конфигуратор для уже названного /etc/net пишется самими авторами, поэтому любое изменение в /etc/net сразу находит отражение в "редакторе настройки".

Заметим, что именно по этому принципу устроено большинство компонентов конфигуратора Debian GNU/Linux (не путать с Ubuntu). Среди требований, предъявляемых к пакетам, есть требование наличия специального конфигурационного скрипта, работающего по протоколу Debconf. При соблюдении этих требований инструмент и система его конфигурирования создаются одним и тем же человеком - мейнтейнером (либо сообществом мейнтейнеров). Это преимущество активно используется в Debian: в каждый момент времени к любому модулю системы в любой части системы существует работающий конфигуратор. Другими словами, без конфигуратора сервис вообще не может существовать. Естественно вытекающий недостаток заключается в том, что Debconf конфигурирует инструменты, а вовсе не решает задачи. Считается, что эффективно пользоваться Debconf могут только специалисты, знающие, к каким конкретным изменениям в системе приведет, скажем, нажатие той или иной кнопки.

Другой пример - виртуализация в ALT Linux Server 4.0. Существует web-интерфейс, который позволяет эффективно управлять виртуализацией - если знать, что такое виртуализация, что такое openvz, bearcounter (?) и пр.

2. Монолитная схема

Рассмотрим теперь монолитную схему построения конфигуратора: в одной большой (вероятно, модульной) программе перечислены решаемые задачи. Для каждой такой задачи существует отдельное решение, которое модифицирует конфигурационные файлы. Типичный пример более или менее монолитной программы - webmin.

Достоинства

  • Монолитный конфигуратор создается одной командной разработчиков. Для эффективной работы им достаточно адаптироваться к одному и тому же интерфейсу UI и API.
  • Монолитный конфигуратор прозрачен для пользователя. Существует единый интерфейс, к которому нужно привыкнуть, но на этом все сложности заканчиваются: достаточно обучить пользователя правильно заполнять все поля. Подобным образом конфигурируется, скажем, большинство подсистем в Windows. Как, к примеру, происходит подключение к провайдеру обычного пользователя? Ему выдается инструкция со скриншотами, в которой сказано: вписать такое-то значение в такое-то поле. Настройку могут производить те же самые люди, которые осуществляют собственно подключение домов. Заметим, что это достоинство может обернуться серьезным недостатком: с теченим времени оно становится legacy (необходимостью поддерживать большое количество чего-либо старого, доставшегося по наследству). В какой-то момент придется изменять внешний вид, потому что изменились принципы функционирования. Сохранить старый интерфейс при новой "начинке" бывает необычайно тяжело. Отметим, однако, что разделение областей происходит по задачам, а не по инструментам. Задачи же меняются значительно реже: задача подключения к сети или добавления пользователя вряд ли изменится, а вот инструмент для решения - вполне возможно.

Недостатки

Главный недостаток монолитного конфигуратора заключается в том, что его крайне сложно поддерживать. Иными словами, на это требуется очень много ресурсов. Если в линукс-системе немного изменился синтаксис одного из конфигурационных файлов, которыми конфигуратор умеет манипулировать, то нужно вовремя отследить это изменение и отреагировать на него, переписав соответствующую часть конфигуратора. При этом переписывание части может повлечь переписывание всего, начиная с интерфейса и заканчивая конкретным синтаксическим анализатором. Программист такой системы должен обладать талантами как в области системного администрирования (нужно хорошо представлять, как и что мы исправляем), так и в областях проектирования логики работы и программирования собственно интерфейса. По этой причине монолитный подход хорошо работает только в не очень быстро (лучше - последовательно) развивающихся системах с достаточно большим количеством разработчиков, занимающихся именно задачей построения конфигуратора. Выход новой версии, допустим, Red Hat Enterprise Linux сопровождается практически полным переписыванием того, что у них называется конфигуратором: это anaconda, их установщик, и несколько разрозненных модулей. Чтобы оценить объем проделываемой работы, достаточно взглянуть на Changelog.

3. Трехслойная схема

Теория

Возможен и третий подход к построению конфигуратора - трехслойный. В нем разделяются действия системного администратора, который принимает решения о том, как нужно управлять конфигурационными файлами, системного архитектора (как нужно конфигурировать всю систему в целом - логика) и, скажем так, дизайнера (создает графический интерфейс). Фактически, есть и горизонтальное (по слоям), и вертикальное (по задачам) деление архитектуры системы:

     задача 1       | задача 2
|===================+=======================
|     ---------     |  ---------            |
|     |       |     |  |       |            |  (уровень представления, UI, front-end)
|     ---------     |  ---------            |
|=========|=========|======|================|<--- унифицированные высокоуровневые команды
|       ----        |     ----              |
|       |  |        |     |  |              |  (уровень логики)
|       ----        |     ----              |
|=======/===\=======+=====/===\=============|<---- унифицированные низкоуровневые команды
|     ---    \---> --- <-/    ---           |
|     | |          | |        | |           |  (уровень конфигурационных файлов, back-end)
|     ---          ---        ---           |
|===========================================

Нижний уровень работает с конфигурационным файлом, средний - с логикой представления. Понятно, что уже на уровне представления одна задача может вылиться во взаимодействие сразу с несколькими конфигурационными файлами, управляемой некоторой логикой. Рассмотрим простой пример. Пусть на уровне представления есть следующая задача: добавить пользователя (в базу данных пользователей). Для оператора ЭВМ это означает, что где-то в интерфейсе есть список пользователей, обладающих тем или иным набором свойств. Он нажимет кнопку "добавить еще пользователя" и задает его свойства (пароль, домашний каталог, группу и пр.). На этом его роль заканчивается. На уровене же модификации конфигурационных файлов добавление пользователя - это достаточно непростая и зачастую неатомарная операция. Она не сводится к добавлению строки к /etc/passwd: есть еще Samba-пользователи и пр. Известно, что пользователи Samba хранятся в отдельной БД, причем список полей этой БД сильно отличается от списка полей в /etc/passwd. В Samba хранятся, к примеру, пароли пользователей, а в /etc/passwd хранятся лишь хэши паролей. Таким образом, на нижнем уровне операция добавления пользователя должна привести к модификации нескольких конфигурационных файлов. В зависимости от того, сколько есть "мест" в системе, ответственных за понятия пользователя, изменяется на уровне представления и содержимое того окна, куда оператор вводит данные. Например, там может быть такое поле: сделать общедоступным по smb его домашний каталог. Заметим, что человеку, который планирует эту систему, разбираться в том, какой синтаксис у /etc/passwd, а какой у smbpasswd, не следует. Не должен он и писать программу, которая редактирует (сама) файл /etc/passwd. Существуют специальные программы, занимающиеся модифицированием этого файла, например adduser, он же useradd. Подобные же утилиты существуют и для Samba. Человек, который реализует цепочку от представления и заполнения полей до нижнего уровня, не должен задумываться о том, с какими ключами вызывается та или иная программа.

Поэтому между уровнем логики и уровнем конфигурационных файлов существует, скажем так, прослойка, задача которой - унификация передаваемых данных. На уровне конфигурации специальный модуль распознает уже унифицированные низкоуровневые команды и превращает их в работу с passwd или что-либо иное - для другого модуля. Эти модули регистрируются на уровне представления. Когда человек добавляет пользователя, он видит окно, а в нем два модуля: Samba и POSIX (Unix) users. Пользователь уровню логики дает высокоуровневые команды, передавая данные из полей. Уровень логики транслирует это в низкоуровневые команды: модулю posix добавить пользователя с таким-то паролем, модулю smb добавить пользователя с таким-то паролем. После чего "нижние" модули делают свое дело и отвечают уровню логики на некотором унифицированном языке: "Я пользователя добавил, все в порядке", "Я пользователя пытался добавить, но там проблемы, ошибка вышла", - тогда уровень логики может сказать первому: "Отмени внесенные изменения" (иначе будет потеряна целостность системы). Управляет этим процессом именно уровень логики, а на уровень интерфейса выносится сообщение об ошибке, оттранслированное, скажем, следующим образом: "При добавлении пользователя в Samba произошла ошибка, операция отменена". Преобразование низкоуровневых унифицированных команд в работу с различными файлами и программами осуществляется специальными сценариями на языке Shell (либо awk, Scheme или иных).

Точно так же происходит и простой просмотр данных. Уровень логики говорит: "У меня есть задача получить список пользователей, кто даст?" Модуль Samba отвечает: "Я", модуль passwd отвечает: "Я". Данные пойдут так, как описано, только уже снизу вверх.

Понятно, что разделение на три уровня в данной схеме принципиально. Если одна команда сверху транслируется в несколько действий снизу, то без разделения на администраторскую, архитекторскую и дизайнерскую часть работать весьма непросто. Подобным образом устроен конфигуратор YaST в SUSE, хотя разделение на уровни там менее жесткое: возможно написать один большой YaST-модуль, который будет выполнять все части работы, за исключением собственно записи конфигурационного файла. Два верхних уровня в YaST вообще часто слиты в один. В конфигураторе же Alterator, используемом в дистрибутивах ПСПО ALT Linux, разделение соблюдается строже: выделены описание политик (уровень представления), трансляция команд и принятие решений (уровень логики) и собственно конфигурирование.

  • Фрагмент расшифровки не вполне внятен; при переводе неясные подробности опущены. -- DmitryChistikov 2008-07-08 11:25:51

Проиллюстрируем описанную схему. Посмотрим список пакетов в нашем дистрибутиве, относящихся к Alterator:

[user@demo ~]$ apt-cache search alterator
  • Где тайпскрипт? Нужен список, он иллюстрирует модульную архитектуру Alterator'a. -- DmitryChistikov 2008-07-08 12:20:23

На экране появился список основных компонентов и модулей Alterator'а. К примеру, alterator-lookout - это компонент, отвечающий за уровень представления, а alterator-xkb - модуль, управляющий настройками клавиатуры. Выведем список файлов в системе, относящихся к пакету alterator-xkb:

[user@demo ~]$ rpm -ql alterator-xkb
/usr/bin/xkbdatadump
/usr/bin/xkbmapconf
/usr/lib/alterator/backend3/template-xkb
/usr/lib/alterator/backend3/xkb
/usr/share/alterator/applications/xkb.desktop
/usr/share/alterator/ui/xkb
/usr/share/alterator/ui/xkb/avail_layout.scm
/usr/share/alterator/ui/xkb/html-messages.scm
/usr/share/alterator/ui/xkb/index.scm
/usr/share/locale/be/LC_MESSAGES/alterator-xkb.mo
/usr/share/locale/ru/LC_MESSAGES/alterator-xkb.mo
/usr/share/locale/uk/LC_MESSAGES/alterator-xkb.mo
/var/www/html/fbi
/var/www/html/fbi/xkb-layout.html
/var/www/html/fbi/xkb.html

Файлы из /usr/lib/alterator/backend3 - это собственно back-end, исполняемые файлы из /usr/bin - используемые ими специальные утилиты. В /usr/share/locale лежат данные для локализации. Написанные на языке Scheme сценарии для интерфейса находятся в /usr/share/alterator/ui (в специальном подкаталоге), а в /var/www/html/fbi размещены файлы, относящиеся к Web-интерфейсу (обратим внимание на наличие двух разных способов представления). Заметим, что Alterator позволяет писать back-end'ы на чем угодно: подойдет и Shell, и awk, и Perl, и Scheme (который, как мы видим, в данном случае использовался для написания UI; заглянув в файл avail_layout.scm, мы увидим всего лишь 66 строк программного кода).

Недостатки

Главный недостаток рассмотренной конструкции (да и составного конфигуратора вообще) - его "текучесть". Обыкновенно очень тяжело разобраться, какой именно "самый правильный" протокол взаимодействия между уровням: он постоянно претерпевает значительные изменения. То же и с пользовательским интерфейсом: он не связан с конкретным представлением, но предоставляет множество разнородных элементов. Конструирование библиотек для таких интерфейсов - задача весьма непростая.

Достоинства

  • Несмотря на то, что поддерживать "трехслойный" конфигуратор весьма непросто, это оказывается легче, чем при монолитном подходе. Главную часть Alterator'а традиционно поддерживают один-два человека, модули же пишутся гораздо большим количеством людей. Человеческих ресурсов при такой схеме расходуется существенно меньше, хотя модулей достаточно много.
  • Главное достоинство "трехслойного" конфигуратора - независимость уровней. Для нижней пары уровней мы это уже видели, а для верхней пары это следует, к примеру, из существования разных интерфейсов. В Alterator, как мы видели, есть возможность использования form-based interface (FBI) - это уровень представления для Web. При создании Alterator'а была возможность вставки еще одного промежуточного уровня, но от этой идеи отказались, так как в Qt и, допустим, HTML (или тексте) слишком разные способы представления данных и команд. Хорошим технологичным примером в этом смысле служит Debconf, но у него нет центрального слоя, управления логикой (он ориентирован на инструмент, а не на задачу). В RHEL же и Fedora вместо этого используется целое семейство конфигураторов с разными интерфейсами.


Сведения о ресурсах

Готовность (%)

Продолжительность (ак. ч.)

Подготовка (календ. ч.)

Полный текст (раб. д.)

Предварительные знания

Level

Maintainer

Start date

End date

35

1

1

1

1

PavelSutyrin, DmitryChistikov


PspoClasses/080704/02ConfigTheory (последним исправлял пользователь MaximByshevskiKonopko 2008-10-10 00:11:41)