27 декабря 2009 г.

GWT. Взаимодействие с Django

Вся работа в GWT имеет подробную документацию. В ней все понятно и прозрачно. Но наше дело тормозится тем, что в качестве бекенда у нас выступает Django. То есть стандартный GWT RPC нам не подходит. Встает вопрос о том, как обмениваться данными между GWT и Django.

Я долго раздумывал, какой интерфейс взаимодействия выбрать. Технология-то одна - ajax, а вот какой инструмент более удобен? Можно попробовать использовать RequestBuilder, но этот метод не совсем удобен и не совсем универсален. Поэтому я выбрал json-rpc. Для него уже все создано, как на стороне django, так и на стороне GWT.

Json-rpc, это легкий протокол удаленного вызова процедур, использующий для своего функционирования формат Json.
Пример запроса и ответа:

--> { "method": "echo", "params": ["Hello JSON-RPC"], "id": 1}
<-- { "result": "Hello JSON-RPC", "error": null, "id": 1}

Начнем с django. Добавляем поддержку json-rpc в наш проект.

Импортируем django-json-rpc и добавляем точку входа в urls.py.
 

from jsonrpc import jsonrpc_site
import myproj.myapp.views # подключаем файл, в котором буду храниться rpc функции

urlpatterns += patterns('',
url(r'^json/', jsonrpc_site.dispatch, name="jsonrpc_mountpoint"),
)

Возьмем пример с readme:
 

from jsonrpc import jsonrpc_method

@jsonrpc_method('myapp.sayHello')
def whats_the_time(request, name='Lester'):
return "Hello %s" % name

Запускаем сервер, запускаем шел django
 

./manage.py runserver 8080
./manage.py shell

И тестируем:
 

>>> from jsonrpc.proxy import ServiceProxy
>>> s = ServiceProxy('http://localhost:8080/json/')
>>> s.myapp.sayHello('Sam')
{u'error': None, u'id': u'jsonrpc', u'result': u'Hello Sam'}

В общем, в документе все написано. Также в приложении есть своей браузер, зайти на него можно по адресу http://localhost:8080/json/browse/ , добавив в urls.py, например так:
 

if settings.DEBUG:
urlpatterns += patterns('',
url(r'^json/browse/', 'jsonrpc.views.browse', name="jsonrpc_browser"), # for the graphical browser/web console only, omissible
)

urlpatterns += patterns('',
url(r'^json/', jsonrpc_site.dispatch, name="jsonrpc_mountpoint"),
)


Я нашел несколько неточностей в документации, так, там name="jsonrpc_browser" без буквы "r" на конце, плюс url браузера
идет после r'^json/', который перекрывает его вызов.

Итак, rpc в django у нас теперь есть. Переходим к клиентской части rpc в gwt.

Проделываем все операции, указанные в readme и... у меня не заработало.
 

09:36:42.942 [ERROR] [myapp] Errors in 'jar:file:/lovely.gwt.jsonrpc-0.7.jar!/lovely/gwt/jsonrpc/client/JSONServiceBase.java'
09:36:42.957 [ERROR] [myapp] Line 29: The type JSONServiceBase must implement the inherited abstract method ServiceDefTarget.setRpcRequestBuilder(RpcRequestBuilder)


Судя по всему, в GWT 2.0 изменились какие-то механизмы в сервисах JSON. Наверное класс JSONServiceBase раньше не требовал реализации метода ServiceDefTarget.setRpcRequestBuilder.
Что ж, давайте взглянем на исходники.
Действительно, функции setRpcRequestBuilder нет.

Проект не обновляется, разбираться времени нет, так что пробуем еще один вариант gwt-json-rpc.
По инструкции подключаем библиотеку. В инструкции написано что библиотека использует свой JSON кодер/декодер, поэтому можно использовать простые типы java: String, int, boolean, Array, HashMap, ArrayList, Vector, вместо классов GWT. В общем, она даже проще, чем lovely-gwt-jsonrpc.
У меня получился следующий код.

 

//Create a new JsonRpc instance
JsonRpc jsonRpc = new JsonRpc();

//Create a callback handler
AsyncCallback callback = new AsyncCallback() {

public void onFailure(Throwable caught) {
SC.say(caught.toString());
};

public void onSuccess(Object result) {
SC.say(result.toString());
};
};
jsonRpc.request(
"http://localhost:8080/json/",
"myapp.sayHello",
null,
callback);

Что такое SC смотрим здесь.

После запуска мы обнаруживаем, что все результаты попыток вызова функции попадают в onFailure. Обусловлено это скорее всего тем, что сервер Django и сервер gwt находятся на разных портах, а это противоречит Same Origin Policy.
Далее, я скомпилировал проект, чтобы скопировать его в статический путь в проекте Django, и запустить под сервером Django, чтобы не нарушать SOP. И обнаружил, что CsrfMiddleware не дает скомпилированному gwt приложению делать POST запросы. Но мы знаем, что фрейморки, вроде jQuery позволяли это с легкостью делать. А все потому, что gwt-json-rpc при создании RequestBuilder не создает заголовок вида "X-Requested-With: XMLHttpRequest", поэтому django (точнее middleware) считает, что запрос сделан с другого домена, и возвращает ошибку 403. Значит надо сообщить ему об этом. AJAX запросы считаются безопасными и не нуждаются в проверке, так как современные браузеры придерживаются SOP. Придется добавить данный заголовок в код библиотеки и пересобрать ее. Разработчику проблему описал. Может быть на момент прочтения статьи в ней будет прописан данный заголовок (функция JsonRpc.request):

builder.setHeader("X-Requested-With", "XMLHttpRequest");

Я его добавил сам и сделал новый jar. Компилируем проект, копируем в путь для статики в django, и проверяем - все должно работать.
Остался один ньюанс - работа в дебаг режиме и ajax запросы. Не будем же мы каждый раз компилировать проект, тем более терять все прелести дебага. Воспользуемся HTTP proxy servlet.
Качаем сервлет, копируем в папку WEB-INF/lib, правим web.xml, у меня примерно следующее:


HttpProxy
com.jsos.httpproxy.HttpProxyServlet

host
http://localhost:8080/json/




HttpProxy
/json/


Меняем путь запроса:

jsonRpc.request(
"/json/",
"myapp.sayHello",
null,
callback);


и проверяем работу в дебаг режиме.

Вот и все. Удачной разработки.

22 декабря 2009 г.

GWT. Передача параметров в GWT

Этой серией буду учиться вместе с вами, как работать с GWT в виде фронтенда и Django в виде бекенда. Пишу простым языком, так как сам разбираюсь в процессе.

Для начала надо научиться передавать параметры в GWT. Первая и основная причина - идеология django - нельзя жестко использовать url адреса. Django для этого предоставляет множество средств, как то и специальный тег url в шаблонах, и специальную функцию reverse для использования в коде. То есть смысл определяется тем, что нельзя использовать url напрямую где бы-то ни было, кроме определения его в файле url.py. Любое изменение конфигурации url'ов в url.py не должно приводить к поломке приложения. В общем, для запуска GWT фронтенда нам необходим набор url-ов определенных в бекенде для ajax запросов.

На стороне Django мы используем тег {% url %}, и выводим url'ы ajax запросов с помощью него, с этим все понятно. Но как их передать в GWT?

Так как GWT и находится в клиентском окружении javascript окна, то мы можем передать параметры в темплейте Django как словарь javascript:



И получить эти url'ы в GWT:


public void useURLsDictionary() {
Dictionary URLsDict = Dictionary.getDictionary("ajaxsUrls");

String ajaxUrl1 = URLsDict.get("ajaxUrl1");
String ajaxUrl2 = URLsDict.get("ajaxUrl2");

}

16 декабря 2009 г.

Google Web Toolkit 2, Eclipse, SmartGWT

Google Web Toolkit - В Google Web Toolkit (GWT) интерфейс AJAX пишется на языке программирования Java, а затем GWT кросс-компилирует его в оптимизированный JavaScript, автоматически работающий во всех основных браузерах. При разработке можно быстро проходить по привычному для разработчиков JavaScript циклу "изменить – обновить – посмотреть", а также отлаживать код Java построчно.

Eclipse (/iˈklɪps/, от англ. затмение[1]) — свободный фреймворк для разработки модульных кроссплатформенных приложений. Разрабатывается и поддерживается Eclipse Foundation.
Наиболее известные приложения на основе Eclipse Platform — различные «Eclipse IDE» для разработки ПО на множестве языков (например, наиболее популярный «Java IDE», поддерживавшийся изначально, не полагается на какие-либо закрытые расширения, использует стандартный открытый API для доступа к Eclipse Platform).

SmartGWT - Полная библиотека виджетов, основана на JS библиотеке SmartClient. Главная особенность- позволяет связывать пользовательские виджеты с серверными компонентами. Что позволяет делать управление данными на стороне сервера. Серьезный конкурент библиотеке Ext GWT. Распространяется как по платной так и бесплатной лицензиям. В платной лицензии есть возможность использования Enterprise объектов и визуального редактора виджетов.

Смысл ясен. Надо соединить все это вместе.

1. Скачиваем eclipse для java.
http://www.eclipse.org/downloads/

2. Ставим поверх Web Tools Platform (WTP) Project.
http://www.eclipse.org/webtools/

3. Ставим GWT plugin для eclipse.
http://code.google.com/intl/ru/eclipse/docs/getting_started.html

4. Создаем проект Web Application Project.


5. Скачиваем SmartGWT.
http://code.google.com/p/smartgwt/

6. Заходим в свойства проекта, добавляем в Java Build Path -> Libraries - Add External JARs библиотеки:
smartgwt.jar
smartgwt-skins.jar (если вы планируете изменить скин, в обратном случае, скин по умолчанию находится в основной библиотеке)

7. Заходим в директорию war, добавляем в главном html файле перед основным подключенным js файлом следующее (для указания пути статики SmartGWT):



8. Добавляем в ModuleName.gwt.xml:



9. В классе EntryPoint (точка входа нашего приложения) ищем функцию onModuleLoad();
Пробуем SmartGMT, дописывая следующее:

SC.say("Привет, мир!");

Плюс импорт в начало:

import com.smartgwt.client.util.SC;

10. Жмем Debug, переходим по адресу, который отображает консоль Develompment Mode, устанавливаем плагин для Вашего браузера.
Видим примерно следующее:

Далее работает в обычном режиме - точки останова, дебаггинг и прочее.

11. Компиляция для опубликования.


12. Ну и пощупать SmartGWT online можно здесь, а gwt - здесь.

ps. К сожалению плагина для Google Chrome под linux нет. Выражены некоторые надежды на появлении его в пятой версии браузера.
К счастью разработку это не затормозит, так как есть версия плагина для Firefox.

8 декабря 2009 г.

CppCMS — C++ Web Framework

Нашел довольно интересный проект. Называется CppCMS. Несмотря на название - это не CMS - это фреймворк. Многие идеи взяты из django, как ни странно. Как я понял, разрабатывает его один человек.

Что может:
- Разные API веб серверов – FastCGI, SCGI, CGI
- Разные рабочие модели: single thread, thread pool, prefork.
- URL маппинг.
- Система шаблонов.
- Кешировние (в памяти, в расширяемой памяти и распределенном режиме)
- Простая обработка HTML форм и верификация данных с них.
- Интернационализация, включая поддержку языков RTL (справа налево).
- Библиотека простого доступа к SQL.
- Простое конфигурирование.
- Прозрачное управление сессиями, используя различные механизмы: зашифрованные куки, кэш, базу данных, распределенные по сети и их различные комбинации.

Довольно-таки неплохой наборчик.

А что будет в версии 1 (выйдет через месяца три, как я понял)?
А вот что:
- Стабильное и обратно совместимое API и ABI между минор релизами.
- Полная документация на Doxygen.
- Сокращение зависимостей от сторонних библиотек.
- JSON - теперь формат внутреннего представления данных и управления конфигурацией.
- Поддержка событий
- Поддержка технологии Comet/Server Push.
- Поддержка синхронного и асинхронного JSON-RPC, как главного формата коммуникации между приложениями фреймворка.
- Поддержка Win32 через Mingw.
- Внутренний Веб сервер для разработки или запуска через http-прокси.

3 декабря 2009 г.

Google открыл публичные DNS серверы

Раньше как-то пользовался OpenDNS (провайдер не мог добиться стабильной работы своих DNS серверов). Но он кое чем меня не устраивал.

Теперь google открыл свои публичные DNS сервера. Их адреса:

8.8.8.8
8.8.4.4

Ну и статья как их использовать.

27 октября 2009 г.

Дебагинг django в eclipse c помощью PyDev

Pydev в сентябре переехал. Да еще его расширения стали Open Source:
Pydev Extensions is now merged with Pydev, and its once closed source code has become open source. Thus, there is no more Pydev Extensions, only the open source Pydev, with all the capabilities of Pydev Extensions incorporated.


Изменился и сайт апдейта для eclipse - http://pydev.org/updates .

А что нам это дает? А это нам дает бесплатную штуку под названием "Debug 'server' for remote debugging", с помощью которой можно дебажить django очень удобным способом.

Для начала выполняем условия, как написано здесь, в том числе заносим в PYTHONPATH в настройках Eclipse путь примерно следующего содержания
"eclipse\plugins\org.python.pydev.debug_1.5.0.1251989166\pysrc\" (найдете у себя подобный) и запускаем сервер (из перспективы debug):



Добавляем следующий код в manage.py (после if __name__ == "__main__":) проекта, что дает нам возможность обернуть PyDev брейкпоинты в pydevd.settrace(), который пересылает трейс Debug Remote серверу (для теста рекомендую сначала использовать --noreload и pydevd.settrace(), и убедиться, что трейс возникает именно на Debug Remote server, так же можно попробовать запускать проект не в режиме дебага, а в режиме run, трейс должен отправляться в любом режиме):


import sys

if len(sys.argv) > 1:
command = sys.argv[1]
if settings.DEBUG and (command == "runserver" or command == "testserver"):
# Make pydev debugger works for auto reload.
try:
import pydevd
except ImportError:
sys.stderr.write("Error: " +
"You must add org.python.pydev.debug.pysrc to your PYTHONPATH.")
sys.exit(1)

from django.utils import autoreload
m = autoreload.main
def main(main_func, args=None, kwargs=None):
import os
if os.environ.get("RUN_MAIN") == "true":
def pydevdDecorator(func):
def wrap(*args, **kws):
pydevd.settrace(suspend=False)
return func(*args, **kws)
return wrap
main_func = pydevdDecorator(main_func)

return m(main_func, args, kwargs)

autoreload.main = main




А для чего мы это, собственно говоря, делали? А чтобы запускать runserver без --noreload. Чтобы и изменение кода и брейкпоинты обрабатывались "онлайн".
Примерно вот такая картина:

24 октября 2009 г.

Google Chorme в Debian

Debian в качестве ОС для нетбука asus eeepc 1000 меня полностью устраивал. Во всем, кроме браузеров. Идущий в комплекте Iceweasel ничем не отличился от обычного firefox, который я установил, после Iceweasel. И тот и другой потребляли неимоверное количество памяти и процессора, веб разработка на коленке казалась просто невозможной. Flash плеер, который идет в дебиане (не помню его название) - это просто тихий ужас. Он был заменен официальным с сайта adobe. После этого флеш заработал как надо, но потребляет очень много процессорного времени.
Так как в общем, такая скорость меня не устраивала, решил попробовать Google Chrome. Стабильного релиза под линукс до сих пор нет, официальный сайт google предлагает нам оставить e-mail для оповещения о выходе релиза браузера. Но, как известно, есть не стабильная ветка, deb пакет которой можно взять отсюда: http://dev.chromium.org/getting-involved/dev-channel
Я скачал dev пакет, установил.
Все очень приятно удивляло.
1. Пакет устанавливает дополнительный репозиторий, с которого, по-видимому, он планирует обновляться.
2. Первый запуск - предложение импортировать настройки браузера с firefox.
3. Русский интерфейс (правда не весь, новые функции наверное не успевают переводить).
4. БОльшая полезная площадь страниц (что особенно актуально в нетбуках).
5. Ну конечно скорость! Намного шустрее.
6. Поедание памяти (без флеша -1-3% на 10 вкладках, в то время как мозила - до 20%).

С флешом таже беда, флеш на torrents.ru занимает 50% процессора сразу. Но это проблема флеша, попробую найти ее решение позже.

Далее, мне нужен был firebug или аналог.
В самом Crome есть DeveloperTools - который, в принципе, может заменить и firebug - он уже сейчас предоставляет много функций, хотя может быть не привычно для любителей firebug'а.
Также, хромисты пошли дальше, выпустили в августе так называемый CrhomeDevtools, который позволяет использовать eclipse для дебага яваскрипта в eclipse.



Еще есть приложение диспетчер задач. Он показывает нагрузку на процессор и скорость закачки страниц, как для всего браузера, так и для каждой вкладки (у меня скорость показывал для каждой вкладки, а процессор - нет, только общий, наверное не сделано еще).

В общем, первые впечатления самые наиположительнейшие, дерзайте.

3 сентября 2009 г.

Отмена обработки события load дизайнером форм Visual Studio 2005

Иногда при конструировании сложных форм в Visual Studio, особенно при наследовании Дизайнер студии не справляется с загрузкой сторонних компонентов из солюшена (например, не может динамически прилинковать class assembly другого проекта солюшена).
Дизайнер обрабатывает конструктор и событие Load формы\контрола.
Решается это довольно просто, вот таким способом мы определяем, что загрузка функции идет от дизайнера и прекращаем обработку события (или конструктора).


private void MyUserControl_Load(object sender, EventArgs e)
{
if (this.DesignMode) return;

... а здесь наш код ...
}

1 сентября 2009 г.

Nhibernate в .NET

Надоел мне, так называемый raw SQL на работе, и воодушевившийся django я подумал, а нет ли ORM для C# .NET 2.0 (тем более, что в NET 3.5 и студии 2008 уже заложена пооддержка ORM в виде LINQ (хотя, как я понял - это не совсем ORM, а скорее аналог HQL). Оказалось есть и не одна.

Так как я приверженец os, поэтому неудивительно, что мой выбор пал на NHibernate.

NHibernate — ORM-решение для платформы Microsoft .NET портированное с Java. Это бесплатная библиотека с открытым кодом, распространяется под лицензией GNU Lesser General Public License.

NHibernate позволяет отображать объекты бизнес-логики на реляционную базу данных. По заданному XML-описанию сущностей и связей NHibernate автоматически создает SQL-запросы для загрузки и сохранения объектов.

NHibernate является портом на .NET популярной на платформе Java библиотеки Hibernate. Версия 1.0 покрывает набор возможностей Hibernate 2.1, а также часть возможностей Hibernate 3. NHibernate 1.2.1, выпущенная в ноябре 2007 года, предоставляет ещё больше возможностей из Hibernate 3, поддерживает .NET 2.0, хранимые процедуры, generics и nullable типы. NHibernate 2.0.1, выпущенная в конце сентября 2008 года предоставляет бо́льшую часть возможностей Hibernate 3.
Поддерживаемые СУБД

* Microsoft SQL Server
* Oracle
* Microsoft Access
* Firebird
* PostgreSQL
* DB2 UDB
* MySQL
* SQLite


http://ru.wikipedia.org/wiki/NHibernate

Чтобы быстро начать с ним работать, рекомендую просмотреть следущие скринкасты:
Summer of nhibernate

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

ps. приверженцы Djanjo оценят, я уверен =)
pps. Да, с Днем Знаний всех! Помните, учиться никогда не поздно! ;)

укапывп

31 августа 2009 г.

Используем gitextensions

Я сначала даже писать не хотел, все так ясно и прозрачно. Но так как на русском ничего нет, то решил все-таки кое-чего написать.

Для начала возможности gitextensions

* интеграция Git в Windows Explorer
* Плагин в Visual Studio (2005/2008) для Git
* Богатый пользовательский интерфейс Git
* Один инсталлер для Git, GitExtensions и утилиты слияния KDiff3
* поддержка 32bit и 64bit!

Ну собственно, качаем, устанавливаем.

Вот так выглядит плагин для студии:



Для push'а в нашу установку установки GIT сервера, прописываем путь примерно так:

gituser@SERVER:project.git

в поле url на следующем скрине:



На странице проекта много скринов примеров использования.

Больших сложностей в использовании я не вижу, удачи! ;)

25 августа 2009 г.

Первый сайт на Django. izmenimsya.ru

Ну как бы больше для развлечения. :)



Что такое izmenimsya.ru?

Вы знаете, иногда мы хотим стать лучше, но все время это лучшее оттягиваем на потом.

Бросить курить, бросить выпивать, бросить наркотики, не изменять, жертвовать, не врать, делать добро, выучить физику.

Подумав, мы решили, что под пристальным взглядом общественности, когда за твоим "изменением" следят тысячи, сорваться (избавляясь от чего-то) гораздо сложнее, а делать больше - гораздо проще.
читать дальше...

Вот такие штуки можно добавлять в подпись на форумах или в блоги:




ps. Кстати, лого нарисован в blender :)

24 июня 2009 г.

Ldap авторизация в Django

Вопрос ldap авторизации в Python довольно хорошо рассмотрен. Теперь разберем, как привязать эту авторизацию к Django.
Первый вариант в рамках компании будет регистрация на сайте с django путем авторизации в ldap.
Другой вариант - полная интеграция авторизации ldap в джанго, но тогда все преимущества групп и контроля доступа теряются, если только не получать эту дополнительную информацию от ldap или других источников.
Третий, наиболее гибкий вариант. Отсутствие регистрации. Логиним пользователя - ищем его профиль в auth у Django - если его нет, создаем, если есть - то используем найденный профиль (если пароль в Django не совпадает с ldap паролем - обновляем его).

Давайте пойдем по третьему пути.

Для начала подготавливаем Django. У нас будет расширенный стандартный Django User, так как после авторизации пользователя в ldap мы еще получим его данные с корпоративной базы mssql.

Устанавливаем python-ldap:

$ sudo apt-get install python-ldap

Прописываем в settings.py:

LDAP_DOMAIN='mydomain.com'
LDAP_SERVER='ldaps://%s' % LDAP_DOMAIN #SSL connection

Правим файл auth.py:

# -*- coding: utf-8 -*-

from django.conf import settings
from django.contrib.auth.backends import ModelBackend
from django.core.exceptions import ImproperlyConfigured
from django.db.models import get_model
from social.models import CustomUser

class CustomUserModelBackend(ModelBackend):

def get_local_user(self, email, password=None):

try:
user = self.user_class.objects.get(email=email.lower())
if user.check_password(password):
return user
else:
self.exist_user=user#save user for refresh local data
except self.user_class.DoesNotExist:
return None

def get_ldap_refresh_create_user(self, username=None, password=None):
import ldap, sys

#create new local user
if '@' in username:
#user@domain
LDAP_USERNAME=username
username=username.split('@')[0]
else:
#user
LDAP_USERNAME='%s@%s' % (username, settings.LDAP_DOMAIN)

LDAP_PASSWORD=password

try:
# build a client
ldap_client = ldap.initialize(settings.LDAP_SERVER)
# perform a synchronous bind
ldap_client.simple_bind_s(LDAP_USERNAME, LDAP_PASSWORD)
except ldap.INVALID_CREDENTIALS, e:
return False
except ldap.SERVER_DOWN, e:
return False#@todo raise Validation error

#lpad auth succes:

#try to get local user
user=self.get_local_user(LDAP_USERNAME, password)

if user:#if we check user in localbase
return user
else:#else create new or refresh old pass
if hasattr(self, 'exist_user'):
#refresh local auth data from ldap in case of change pass
self.exist_user.set_password(password)
self.exist_user.save()#write new pass
user=self.exist_user
else:
user=CustomUser.objects.create_user(username,LDAP_USERNAME,password)

return user

def updape_user_info(self, user):
pass

def authenticate(self, username=None, password=None):
#try to auth with ldap
#and refresh user data in success or create new one if user does not exist
user=self.get_ldap_refresh_create_user(username, password)
if user:
self.updape_user_info(user)#get data from mssql
return user
else:
return None# error ldap auth

def get_user(self, user_id):
try:
return self.user_class.objects.get(pk=user_id)
except self.user_class.DoesNotExist:
return None

@property
def user_class(self):
if not hasattr(self, '_user_class'):
#self._user_class = get_model(*settings.CUSTOM_USER_MODEL.split('.', 3))
self._user_class = CustomUser
if not self._user_class:
raise ImproperlyConfigured('Could not get custom user model')
return self._user_class


Функция updape_user_info на самостоятельное написание, она должна дописывать необходимую расширенную информацию.

ps. прозрачная авторизация в принципе возможна, но только с IE, можете попробовать.

blender - быстрый старт

Если вам уж очень хочется нарисовать что-то в 3D, сделать рендер или анимацию и бесплатно, то вам - прямая дорога к blender. Но при первом знакомстве Вы обнаружите, что интерфейс программы не дружественен к пользователю.

Здесь хотел было рассказать о базовых функциях, но позже нашёл все то, о чем я хотел рассказать:

Blender QuickStart или Blender шпаргалка


Добавлю, что выделение всех элементов меша в режиме редактирования - кнопочка - A.

Со временем, думаю буду добавлять полезные кнопки управления, ибо если не работать с blenderом профессионально или хотя бы регулярно, то все это очень быстро забывается.

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

3 июня 2009 г.

Установка Redmine на FreeBSD 7.2, используя apache, mod_rails и postgres sql

Разобравшись с git сервером и GUI клиентами в прошлой статье, я обещал рассмотреть установку GitPlugin для Trac (пользуюсь давно, все устраивало, когда был SVN). Но сейчас меня смутили несколько вещей:
1. Trac не поддерживает git из коробки (реализован в виде плагина, что не есть уже хорошо).
2. Trac хорош для одного крупного проекта (для запуска дополнительного надо много телодвижений), а мы хотим построить СКВ для многих проектов.
3. В trac нет русификации, а она желательна (возможен доступ пользователей программ для создания задач или сообщений о багах).
4. В trac нет удобной системы распределения прав (есть конечно дополнительные пакеты, но если все это сложить, получается уж очень громоздко).

Поэтому я решил поискать систему, которая бы меня устраивала.
И я ее нашел, redmine. Он написан на Ruby, поддерживает кучу баз данных, есть русский язык, лишен всех недостатков перечисленных выше, самое главное, поддерживает git "из коробки"!

Краткий обзор возможностей отсюда:

* Поддержка нескольких проектов в одной базе данных;
* Гибкая система настройки пользовательских прав доступа;
* Гибкая система тикетов и заданий;
* Поддержка календаря и графиков Гантта
* Поддержка файлового архива, документация и новостных лент по проекту
* Сквозное логирование событий в системе и поддержка отсылки на еmail
* Встроенная система Wiki по проекту
* Встроенная система форумов по проекту
* Простая система учета времени
* Возможность добавлять произвольные пользовательские поля к проектам, заданиям и пользователям
* Интеграция с системами контроля версий (SVN, CVS, Mercurial, Bazaar and Darcs)
* Поддержка LDAP авторизации
* Поддержка регистрации пользователей
* Мультиязычность (Русский и Украинский присутствуют)
* Поддержка различных баз данных


Дополню, что git тоже поддерживается.

Начнем.

Системе 3 года, но уже информации по ней много, все хвалят, соответственно в поиске можно найти много мануалов по установке прямо под вашу систему.
Но мы пройдем этот путь заново :)
Считаем, что apache2 и postgres 8.3 уже установлен.

Следуем официальному руководству по установке:

1. Проверяем и устанавливаем необходимые пакеты:

#ruby --version
ruby 1.8.7 (2007-03-13 patchlevel 0) [i386-freebsd7]
#cd /usr/ports/www/rubygem-rails
#make clean install

Этот пакет содержит все компоненты, которые необходимы для запуска Ruby On Rails (собственно, на котором и написан redmine).
Таблицу с необходимыми версиями смотрим здесь.

У меня с портами REALEASE-7.2 встала версия 2.3.2

#cd /usr/ports/converters/ruby-iconv
#make clean install

2. Скачиваем стабильную ветку:

#wget http://rubyforge.org/frs/download.php/56909/redmine-0.8.4.tar.gz
#tar -zxvf redmine-0.8.4.tar.gz

3. Конфигурируем базу данных.
Добавляем пользователя redmine в базу данных postgres:

#su pgsql
$createuser redmine -–no-superuser -–no-createdb -–no-createrole -–login –-pwprompt -–encrypted
$createdb --owner=redmine --encoding=utf-8 redmine
$exit

Редактируем pg_hba.conf при необходимости.

Копируем ~/redmine-0.8.4/config/database.yml.example в ~/redmine-0.8.4/config/database.yml и редактируем:

production:
adapter: postgresql
database: redmine
host: localhost
username: redmine
password: password
encoding: utf8

Заполняем базу данных схемой Redmine, выполнив команду в директории redmine-0.8.4:

#rake db:migrate RAILS_ENV="production"

Загружаем первоначальную конфигурацию Redmine:

#rake redmine:load_default_data RAILS_ENV="production"

4. Устанавливаем права.
Пользователь www должен иметь право писать в директории files, log, tmp.

#cd redmine-0.8.4
#chown -R www:www files log tmp public/plugin_assets
#chmod -R 755 files log tmp public/plugin_assets

5. Пробный запуск.

#sudo -u www ruby script/server webrick -e production

Переходим по адресу http://SERVER:3000/, все должно работать.
Можно залогиниться от admin, пароль admin.

Примеры настройки smtp сервера здесь.

6. Связываем apache и Redmine.
Есть официальное how to.

Мне оно не понравилось, использует CGI, в общем все кисло :)
Гораздо более интересно решение "Настройка Redmine на работу через apache and mongrel_cluster по HTTPS", изначально подсмотренное здесь.
Предлагается использовать mongrel в качестве бэкенда к серверу apache.
Mongrel является HTTP-сервером и библиотекой на Ruby, которая предназначена для хостинга разнообразных веб-приложений написанных на языке программирования Ruby, используя HTTP протокол, а не FastCGI или SCGI.
Вот это уже гораздо интересней. Тем более https.

Но я решил пойти немного другим путем, установкой Phusion Passenger (aka mod_rails).

# cd /usr/ports/www/rubygem-passenger
# make clean install

Настраиваем апач:

Доступные настройки mod_rails:
* RailsEnv - задает среду выполнения приложения. Значение по умолчанию: production.
* RailsBaseURI - задает директорию, в которую размещается приложение. По этому адресу должна находиться директория public приложения.
* RailsRuby - задает интерпретатор, который будет использован для выполнения приложения. Имеет смысл, если у Вас установлено несколько интерпретаторов Руби.
* RailsMaxPoolSize - максимальное количество запущенных экземпляров приложения. Оптимально значение зависит от конфигурации системы. Значение по умолчанию: 20.
* RailsPoolIdleTime - максимальное время бездействия экземпляра приложения в секундах. По истечении этого времени экземпляр приложения будет остановлен для экономии памяти. Разработчики рекомендуют в качестве оптимального значения 2*x, где x - время, которое пользователь тратит на просмотр страницы. Значение по умолчанию: 120.

Настроен апач примерно так.
Создаем сертификаты.

А потом настраиваем секьюрный хост:

SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM
SSLMutex file:/usr/local/etc/apache22/logs/ssl_mutex
SSLSessionCache shm:/usr/local/etc/apache22/logs/ssl_cache_shm
SSLSessionCacheTimeout 600


AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl


SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0

NameVirtualHost *:80

LoadModule passenger_module /usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.2/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.2
PassengerRuby /usr/local/bin/ruby18

PassengerDefaultUser www
PassengerMaxPoolSize 1
PassengerUseGlobalQueue on
PassengerMaxInstancesPerApp 1


ServerName SERVER

ErrorLog etc/apache22/logs/httpd-redmine.log

RewriteEngine On
Options +FollowSymlinks
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=permanent]



RailsEnv production
ServerName SERVER

SSLEngine on
SSLVerifyClient none
SSLCertificateFile etc/apache22/keys/new.crt
SSLCertificateKeyFile etc/apache22/keys/new.key
SSLCACertificateFile etc/apache22/keys/cacert.pem
SSLProtocol all -SSLv2
DocumentRoot /tank/redmine/redmine-0.8.4/public
ErrorLog etc/apache22/logs/httpsd-redmine.log


Options FollowSymLinks
AllowOverride None
SSLOptions +StdEnvVars
Order allow,deny
Allow from all



Проверяем конфигурацию apache:

#/usr/local/etc/rc.d/apache22 configtest

Стартуем и может быть получаем ошибку

Error message:
No such file or directory - /nonexistent
Exception class:
Errno::ENOENT

если у нашего пользователя www нет домашней директории. Решается это так:

Покопавшись немного обнаружил, что проблема вызвана конфликтом Passenger и gem и исправляется внесением изменений в файл rubygems.rb в метод self.set_paths.
Необходимо заменить код

# only create by matching user
next if Etc.getpwuid.uid != File::Stat.new(Gem.user_home).uid

на:

# only create by matching user
home_folder_uid = File::Stat.new(Gem.user_home).uid rescue nil
next if Etc.getpwuid.uid != home_folder_uid

Файл находится здесь /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb .

Перезапускаем апач, http://SERVER (должен выполниться редирект на https://SERVER).

Настройка самого redmine через веб-интерфейс интуитивно понятна, удачи!



PS. Кстати, напоследок линк: Git User's Manual

1 июня 2009 г.

Установка git сервера на Freebsd 7.2 c клиентами EGit на Eclipse под Windows

Введение в git.

Система спроектирована как набор программ, специально разработанных с учётом их использования в скриптах. Это позволяет удобно создавать специализированные системы контроля версий на базе Git или пользовательские интерфейсы. Например, Cogito является именно таким примером фронтенда к репозиториям Git. А StGit использует Git для управления коллекцией патчей.

Git поддерживает быстрое разделение и слияние версий, включает инструменты для визуализации и навигации по нелинейной истории разработки. Как и Darcs, BitKeeper, Mercurial, SVK, Bazaar и Monotone, Git предоставляет каждому разработчику локальную копию всей истории разработки, изменения копируются из одного репозитория в другой.

Удалённый доступ к репозиториям Git обеспечивается git-daemon, SSH, или HTTP сервером. TCP-сервис git-daemon входит в дистрибутив Git и является наряду с SSH наиболее распространённым и надёжным методом доступа. HTTP метод доступа, несмотря на ряд ограничений, очень популярен в контролируемых сетях, потому что позволяет использование существующих конфигураций сетевых фильтров.


Установка.

cd /usr/ports/devel/git
make && make install

Для публичного доступа к репозиторию можно воспользоваться git-daemon.
Также возможен доступ через http (апач+dav+gitweb).
Я же выбрал более простой и надёжный путь - ssh.

Для начала определимся с сервером.
Создаем пользователя, который будет работать с репозиториями, а так же являться администратором gitosis: gituser (создаем без пароля).

$sudo adduser gituser

При создании, в качестве домашней указываем корневую директорию с репозиториями.

Для начала мы сосредоточимся на авторизации пользователя через ssh.
Для этого, проверим настройки sshd, примерно как здесь.

Устанавливаем gitosis, набор скриптов, которые выполняются при открытии ssh-сессии, позволяют использовать ssh ключи для авторизации в репозиториях, а также освобождают от необходимости создавать много пользователей в системе для доступа к репозиториям.

$git clone git://eagain.net/gitosis.git
$cd gitosis
$sudo python setup.py install

Далее надо создать gitosis-хостинг с авторизацией только по ключам:
То есть проинициализировать репозиторий самого gitosis в указанной нами директории.
Я решил управление gitosis оставить на сервере.

$ssh-keygen -t rsa

Эта команда создает в домашней директории пользователя gituser пару id_rsa и id_rsa.pub. Первый файл - секретный, должен быть закрыт от любого пользователя на системе, а так же не передаваться по сети.
Второй ключ публичный, мы его должны передать в gitosis при инициализации gitosis. Его рекомендуют скопировать в директорию, доступную всем для чтения, например /tmp . Далее инициализируем gitosis и его репозиторий.
(Первые две команды, в случае, если у вас не установлен sudo.)

#cd /usr/ports/security/sudo ; make install clean
#rehash
#sudo -H -u gituser gitosis-init < /tmp/id_rsa.pub
Initialized empty Git repository in /tank/gitrepos/repositories/gitosis-admin.git/
Reinitialized existing Git repository in /tank/gitrepos/repositories/gitosis-admin.git/

ключ -H обязателен, иначе команда sudo будет выполняться в домашнюю директорию предыдущего пользователя (например /root).

Теперь у нас есть несколько директорий в домашней директории gituser. Папка repositories предназначена для хранения репозиториев, там уже находится репозиторий настроек gitosis (gitosis-admin).

Если у вас старый setuptools, рекомендуют прописать следующие права:

sudo chmod 755 ~/repositories/gitosis-admin.git/hooks/post-update

Далее, заходим под пользователем gituser и забираем репозиторий администрирования gitosis:

$git clone gituser@YOUR_SERVER_HOSTNAME:gitosis-admin.git
$cd gitosis-admin

Это удаленно, а у так как у нас админ на этом же хосте, то локально:

#su gituser
$cd ~/tmp
$git clone ~/repositories/gitosis-admin.git gitosis-admin
$cd gitosis-admin

Создание "репозиториев" в gitosis.
Редактируем файл gitosis.conf:

[group projectteam]
members = vasya
writable = project

где project - название будущего репозитория.

Создаем публичный ключ в клиенте windows.
Для этого используем пакет msysGit. Я выбрал portable версию, ибо нам из пакета нужен только генератор ssh ключей (PortableGit\bin\ssh-keygen.exe).

>ssh-keygen -C “vasya” -t rsa

Обычно пара сохраняется в папку c:\\Documents and Settings\\Username\\.ssh на XP или c:\\Users\\Username\\.ssh на Vista. Заливаем публичный ключ (vasya.pub) в директорию gitosis-admin/keydir, место куда мы извлекли репозиторий настроек gitosis.

"Пушим" настройки в репозиторий gitosis.

git add keydir/vasya.pub
git commit -a -m "Allow vasya write access to project"
git push

После этого проверить, что файл конфигурации изменился (есть ссылка в домашней директории gituser), а также скопировались ключи в ~/repositories/gitosis-admin.git/gitosis-export/keydir. При загрузке в репозиторий gitosis сам извлекает изменившееся файлы в директорию gitosis-admin.

Создаем репозиторий на сервере под юзером gituser:

$mkdir ~/repositories/project.git
$cd project.git
$git --bare init

--bare обозначает, что у нас нет намерения хранить файлы самого проекта на сервере, только diff и файлы, которые генерирует сам git (проще говоря, структура git репозитория). Что кстати, совершенно достаточно даже для Git Plugin for Trac, который мы намереваемся установить.

Теперь нам необходимо создать ветку (branch), иначе EGit будет ругаться на отсутствие оных. Выполнить push на полностью пустом репозитории нельзя.
Для первого коммита автоматически создается бранч с именем master, в него же по умолчанию попадают следующие коммиты

#su gituser
$cd ~/tmp
$git clone ~/repositories/project.git project
$cd project
$echo "test" > test
$git add test
$git commit -a -m "initial branch"
$git push origin master

Попробуем получить проект через ssh с помощью плагина EGit.
Установка eclipse и самого плагина очень проста.
В меню eclipse выбираем File-Import, Git Repository. Выбираем протокол git+ssh:// , указываем путь:

git+ssh://gituser@SERVER/project.git

Самое главное! eclipse прописывает путь к ssh, как $HOME/ssh. Его необходимо поправить на $HOME/.ssh в меню:
Window-Preferences - General - Network Connection - SSH2. Там же можно управлять ключами и просматривать их. Если eclipse не найдет ключи ничего забираться не будет.
Дальнейшие действия по добавлению проекта интуитивно понятны.

Единственное, в новой версии появилась галочка Import projects after clone, которую надо снять, ибо она у меня привела к пустому списку проектов, попробуйте, может у вас получится. Это не страшно, по вышеприведенному примеру указано как просто сделать share project с извлеченного проекта на диске (плюс показано ниже).

Можно также забрать проект через консоль:

Запускаем PortableGit\git-cmd.bat и выполняем:

>git clone gituser@SERVER:project.git

Далее, создаем проект в eclipse, добавляем в него наш извлеченный проект (Import-File System), жмем на проекте Team-Share (Git) и все, наш проект теперь помечен, как гит репозиторий. Пробуем менять файлы, коммитить и пушить.



Если возникают какие-либо проблемы, то смотрим /var/log/auth.log .
А также в eclipse ( Help - About Eclipse - Configuration Details - View Error Log).
Также можно добавить после строчки [gitosis] в gitosis.conf:

loglevel=DEBUG

При задании которого при обращении к gitosis (через консольный клиент) будут выведена дополнительная информация при ошибках.

Об установке багтрекера Trac для git, а также использовании git в Visual Studio в следующий раз.

29 мая 2009 г.

Россия в мире сейчас, объективный взгляд

Перейдем от интернационального мира ПО к реальному миру. Даже администратору\программисту необходимо знать, что происходит за экраном монитора. Приступим к чтению мировой прессы.
"United Press International" в пятницу пишет:

Демократы же, хотя и не с таким бешеным энтузиазмом верят, будто электронное супероружие сводит к нулю потребность в огромных массах войск с более примитивным оружием, все же полагают, что эпоха массовых противостояний наземных армий ушла в прошлое.
В это же верят и все большие страны Европейского Союза, а в особенности - руководство Еврокомиссии в Брюсселе.

Демократы тут - демократическая партия США. Осознаем данный тезис.
Абзац говорит о победе США над мыслящими людьми в Европе. Нормальному же человеку понятно, что США ни в коем случае не сокращает огромные массы войск, тем более расширяя НАТО в Европе. Эти несопоставимые тезисы сразу нас убеждают в полном вранье журналиста.
Далее, та же статья, в той же газете.

Единственная проблема состоит в том, что руководство целого ряда мировых держав в это не верит - и строит свои планы в соответствии с совершенно другими принципами.

И что же, вы думаете, что в мире все такие тупоголовые, как ваш народ?

Далее.

Россия продолжает энергично укомплектовывать свою армию новейшими танками Т-90С, ударными вертолетами тактической поддержки Ка-50, боевыми машинами пехоты БМП-90, реактивными системами залпового огня и прочим.

И что ж? Есть пословицы в России - "в своем глазу бревно не вижу, в чужом соломинку замечу".

Кроме того, недавно Совет безопасности России, возглавляемый суровым союзником премьер-министра Владимира Путина Николаем Патрушевым, объявил о новой доктрине национальной безопасности, в которой подчеркивается необходимость накопления как обычных, так и ядерных вооружений стратегического назначения с целью отражения предполагаемого противника, в особенности США и Организации Североатлантического альянса (НАТО).

Это очень опасно конечно для страны, которая ни на кого не нападала, и вообще не вела войн практически век (издевка).

В то же время, Франция пришет:

В четверг стало ясно, что уже не двусмысленная. Москва действительно сильно смягчила свою позицию. Пока Совет безопасности готовится к принятию резолюции, Кремль высказывается против 'языка санкций' и призывает к сдержанности и терпению. Таким образом, вероятность того, что по отношению к Ким Чен Иру будут применены санкции, очень невелика.


Почему же мы в Европе кажемся более чем добрыми, а в США определено плохими? Хотя название статьи газеты TF-1 без определения смысла уже принуждает читателя к отрицательному отношению к политике России ("Позиция России по отношению к Ким Чен Иру не такая уж и жесткая").

Jamestown Foundation на полном серьезе печатает статью репортера Александр Меликишвили под названием "Грузинский парламентарий: неудачный путч финансировал олигарх, живущий в России".

В частности, Таргамадзе утверждал, что неудачный мятеж на военной базе Мухровани 5 мая спонсировал Александр Ебралидзе (Alexander Ebralidze), олигарх грузинского происхождения, уже тридцать лет живущий в России. Известно также, что он находится в личном контакте с российским премьер-министром Владимиром Путиным.

В такую чушь в матушке России поверит не всякая блондинка, как такое может подаваться западному обывателю - непонятно. Феерический бред, не заслуживающий внимания даже прапора ФСБ.

Столь же впечатляет и криминальное прошлое Ебралидзе. Он был дважды осужден: первый раз за разбойное нападение и незаконное хранение оружия, второй - за хулиганство и сопротивление властям.

Смешно, ей-богу. Но что же мы хотим в итоге? Читаем.

В резолюции, принятой на вышеупомянутой учредительной конференции, по сути, повторяются требования Кремля к Тбилиси: 'Грузия должна стать нейтральным, внеблоковым государством, развивающим отношения со своими соседями и со всеми государствами мира. С территории нашей родины не должна исходить военная угроза для кого бы то ни было. Грузия в свою очередь должна получить международные гарантии невмешательства в ее внутренние дела. Важнейшим приоритетом Грузии должно стать восстановление и развитие добрососедских, равноправных отношений с РФ'.

Какое слово здесь может задеть американца?!

По словам Таргамадзе, организаторами этих встреч были известные криминальные авторитеты грузинского происхождения, активно действующие в России - Тариэль Ониани (Tariel Oniani) и Бондо Шаликиани (Bondo Shalikiani). Следует отметить, что 18 мая президент Саакашвили упомянул Шаликиани в качестве одного из 'активных спонсоров' проходящих в Грузии демонстраций оппозиции, а в марте министр внутренних дел страны Вано Мерабишвили (Vano Merabishvili) назвал Тариэля Ониани в числе подстрекателей к беспорядкам.

Даже если это правда. почему это Англия может держать политических беженцев, а мы нет? Великобритания отвечает за их действия? а почему мы должны?

Пожалуй, удачнее всего побудительные мотивы кремлевских менеджеров 'проекта Ебралидзе' подытожил корреспондент 'Комсомольской правды' Владимир Ворсобин: 'А в Москве, похоже, поняли: чтобы восстановить российское влияние России, придется повозиться с тбилисским политическим террариумом. Пока разочарование грузин политикой США велико, пока тбилисская власть неустойчива, Москва получила шанс отвоевать у США хотя бы маленький плацдарм для пророссийских политиков. В Сочи, например, 'агентов влияния' появилось сразу двое - для национального большинства и меньшинства. Пусть неуклюже, пусть топорно, но подготовка политического 'десанта', похоже, началась'.

Ну что сказать, газета - попса, и журналист сволочь (если такой существует вообще).

ps. Хостинг блоггера в Америке, пишу на русском, встречал случаи удаления акков. (Надо бы кросс пост делать)

27 мая 2009 г.

GUI Менеджер сетевых соединений wicd в debian

Все-таки я вернулся к wicd.

То есть, поставил на asus eee pc debian lenny, тут же выкинув NetworkManager ибо он сразу не заработал.
По-быстрому настроил wifi через interfaces и wpasupplicant:

#wpa_passphrase your_ssid your_psk

Так я создал хеш ключа для сети (your_ssid - имя wifi сети, your_psk - pre shared key - ключ, то есть).

wpa_supplicant.conf я создавать не стал, просто прописал что-то вроде

auto ath0
iface ath0 inet dhcp
wpa-driver wext
wpa-ssid имя сети
wpa-ap-scan 1
wpa-proto WPA
wpa-pairwise TKIP
wpa-group TKIP
wpa-key-mgmt WPA-PSK
wpa-psk паскей (созданный выше хеш)


Все тут же завелось и забегало.
В этом же процессе пытался поставить GUI-шные менеджеры: wifi-radar, тот же network manager (из пакетов), а так же wicd (поставил почему-то с репы убунты, потыкал, что-то не понравилось, тут же снес, надеясь что будущем найду что-то получше).
Несколько дней меня это устраивало, пока я не дошел до работы. Настройки wifi другие, да и dhcp по проводам хочется (а дома еще не подключал, но традиционно статика), покумекав, я все-таки понял, что на ноуте должен стоят GUI-шный менеджер сетевых интерфейсов, это обязательное условие для оперативного изменения сетевых подключений. Хотя лукавлю, можно конечно написать скрипт, но хочется же лучшего и сразу (статуса сети в трее например, переключение сетей мышкой и т.п.).
Так как NetworkManager из коробки никаких признаков о сетях не подавал, решил поставить версию из сырцов, надеясь на лучшее.
Процесс установки протекал очень напряженно. Я не буду рассказывать про все dev пакеты которые пришлось поставить, размер их был не меньше 50 мб. Но я твердо решил испробовать новую версию.
Ну вот вроде бы и скомпилировалось и поставилось. Поставиться-то поставилось, но запускаться не хотело. То есть сам Менеджер. Пару часов ковыряний порядком поднадоели, конфиги уже были раскиданы по местам (их много, особенно которые относятся к dbbus) из диры с сырцами, когда я сообразил, что конфиги-то проинсталлированы только не в ту диру. /usr/local/etc вместо /etc. Может я ключик при конфигурировании не указал, а может под а-ля bsd систему конфигуратор, разбираться не стал, так как менеджер вроде запущен и работает.
На заметку, посмотреть, что происходит с менеджером, если он у вас не запускается как демон, можно так:

#NetworkManager --no-daemon

Я наивно полагал, что nm-applet входит в состав NetworkManager (как в пакете), а вот и не так. Его, оказывается, надо ставить отдельно. Его еще и не сразу найдешь, так как NetworkManager находится далеко в списке на ftp от апплета.

Ладно, решил, так решил. Ооо, установка апплета - это нечто монстроидальное. Столько зависимостей наверное сложно придумать (казалось бы - апплетик, иконка с меню, ну может она и разруливает там брелоки какие-нибудь). Пришлось еще влить около 100 мб всякой всячины. Я уж был хотел передумать, но упорство взяло верх.

Установил таки, работает! Правда все приходится запускать вручную. И менеджер и апплет.
Работает не сеть конечно, работает пока только этот менеджер. В документации сказано - чтобы все правильно работало, очистите файл /etc/interfaces , оставив в нем только лупбек. Ну что ж, открываю интерфейсы - вот же, менеджер "любезно" удалил все, включая закомменченые настройки. Вот спасибо! Теперь дома мне тоже не видать связи, подумал я. Хотя, я ему это простил, надеясь на то, что раз он такой умный, то он мне и сеть поднимет любую.
Начали с dhcp+wifi. И сразу наткнулись на баг, который обмусолен на всяческих забугорных убунтовых форумах - по логам - dchp клиент получает ответ от dhcp сервера, но Менеджер его не принимает (или не понимает) и говорит нам о тайм ауте ответа от dhcp сервера. Сразу говорю - я эту проблему так и не решил. Говорят дело в dhcp3 , но мне так не кажется.
Решил отложить эту проблему в строну и заняться автозагрузкой апплета и менеджера.
Для начала я прописал статику в проводной интерфейс и только так сеть завелась с Менеджером.
Сам Менеджер беспроблемно прописался в update-rc.d, а вот с апплетом начались чудеса.
Используем nm-applet.desktop файл из сырцов - закидываем его в /etc/xdg/autostart .
Перезагружаем бук, и - о, чудо, значек апплета и соединения сети. Но! Упал апплет микшера и раскладки. Я сначала подумал совпадение. Попробовал разные варианты - апплет (с ключем --sm, все как полагается - оно же в desktop прописывается) виноват. Мало того, так приложения не запускаются из гномовского меню! В чем была причина, я так и не понял. Было время идти домой.
Дома, в отличии от работы, wifi с wpa , решил попробовать подключиться. О, чудо, схватил dhcp от моего роутера да еще и с WPA. Вот это странность. В общем, такая нестабильность меня не устраивала, тем более что приложения так и не запускались, посему я, в расстроенных чувствах, решил прибить все, что связано с NetworkManager, до сих пор удивляюсь - как такой сырой софт может стоят дефолтом во многих дистрибах, ужас просто.
Покумекав, чем же все-таки мне заменить NM вспомнил о галопах по wicd, подумал, надо бы уделить побольше времени, вдруг, что из этого выйдет.
Начав изучение, обнаружил, что зря ставил с репы убунты его в прошлый раз, видно попалась не та страница, оказывается его можно ставить с репы дебиана:

deb http://apt.wicd.net lenny extras

получаем ключ:
wget -q http://apt.wicd.net/wicd.gpg -O- | sudo apt-key add -
обновляем репу и ставим wicd.
Вот так все просто и все свежее! (установка 5 минут против полдня на NM)
А дальше что? Да ничего, перезагружаемся - у нас и апплет и все интерфейсы и все работает.
(только также надо предварительно все закомментить в interfaces кроме lo).
wifi с WPA, проводной ethernet - все без проблем. Впечатления - отменные!
Надеюсь, что и дальше такие же будет от использования wicd, чего и вам желаю!

19 мая 2009 г.

Файловые менеджеры linux

Просто ссылки, выбираем на вкус и цвет.
1. Nautilus, http://live.gnome.org/Nautilus (desktop)
2. Dolphin, http://dolphin.kde.org/ (desktop)
3. Konqueror, http://www.konqueror.org/ (desktop)
4. Thunar, http://thunar.xfce.org/index.html (desktop)
5. PCManFM, http://pcmanfm.sourceforge.net/ (desktop)
6. Krusader, http://www.krusader.org/ (GUI)
7. Xfe, http://roland65.free.fr/xfe/ (GUI)
8. ROX-Filer, http://roscidus.com/desktop/ROX-Filer (desktop)
9. Midnight Commander, http://www.midnight-commander.org/ (console)
10. Vifm, http://vifm.sourceforge.net/ (GUI)
11. GNOME Commander, http://www.nongnu.org/gcmd/ (GUI)
12. emelFM2, http://emelfm2.net/ (GUI)
13. Tuxcommander, http://tuxcmd.sourceforge.net/ (GUI)
14. Double Commander, http://doublecmd.sourceforge.net/ (GUI)
15. FlyBird, http://fly-bird.org/ (GUI)
16. gentoo, http://obsession.se/gentoo/ (GUI)
17. Worker, http://www.boomerangsworld.de/worker/ (GUI)
18. lfm - Last File Manager, http://www.terra.es/personal7/inigoserna/lfm/
(console)
19. Filerunner, http://linux.maruhn.com/sec/filerunner.html (GUI)
20. BeeSoft Commander, http://www.beesoft.org/ (GUI)
21. Necromancer's DOS Navigator, http://ndn.muxe.com/ (console)
22. FileCommander, http://silk.apana.org.au/fc2development.html (console)
23. FDclone, http://hp.vector.co.jp/authors/VA012337/soft/fd/ (console)
24. FileRunner, http://www.cd.chalmers.se/~hch/filerunner.html (GUI)
25. Desktop File Manager, http://www.kaisersite.de/dfm/ (desktop)
26. TKDesk, http://tkdesk.sourceforge.net/ (desktop)
27. muCommander, http://www.mucommander.com/ (GUI)
28. XNC - X Northern Captain, http://www.xnc.dubna.su/ (GUI) (похоже, разработка прекращена)

Из двух-панельных я использовал mc (ставлю всегда), krusader (в KDE), gnome commander (в Gnome).

Кто знает еще какие?

Управление модулями апача 2 в дебиане

Постоянно забываю утилиты для управления модулями apache2 в дебиане (ибо редко я его настраиваю). Сделаю заметку.

a2enmod: включить модуль апача (ничего особенного он не делает, создает ссылки на модуль .load и .conf файлы в папке mods-enabled).

Например, включить модуль rewrite:
#a2enmod rewrite

a2dismod: делает вещи обратные a2enmod
Например для отключения модуля:
#a2dismod rewrite

Эти утилиты без параметров выдают список модулей, которые можно активировать в случае a2enmod и список модулей, которые можно деактивировать в случае a2dismod.

17 мая 2009 г.

Создание загрузочной флешки из img образа в windows

Утилитка, которая корректно залила образ *.img linux на флешку из под windows:
UNetbootin.
Рекомендую.

1 апреля 2009 г.

Байка

Задались мы тут семейством вопросом слова "байка". Мне казалось, что это сказка, полностью лишенная реальной подосновы. Начали спорить.
В итоге - википедия говорит, что
Байка — юмористический рассказ, как правило, основанный на реальных событиях. Достоверность байки несколько выше, чем анекдота, но это не исключает литературных приёмов, с помощью которых рассказчик подаёт байку в желаемом виде.
, а вот словарь Ожегова, что
БАЙКА2, -и, ас. (разг.) Побасенка, выдумка, басня (во 2 знач.).Охотничьи байки. Что-то не похожа эта б. на правду.

Я верю Ожегову. А вы?

15 марта 2009 г.

Архивирование системы или бекап в debian linux

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

dmpfile=backup.tar.bz2
srcdir=/
trgdir=/share
cd $trgdir && tar -cfj $dmpfile --exclude-from=/exclude_back $srcdir

Скрипт переходит в директорию куда надо сохранить архив, и выполняет tar.

--exclude-from - берем список исключений из файла в корне (сам скрипт тоже в корне)

# cat exclude_back
/proc
/mnt
/var/run
/dev
/sys
/home/repo
/share

Последние две - мои директории.

11 марта 2009 г.

Контекстные процессоры Django

Как пишет django book

Для обработки шаблона вам необходим контекст. Обычно это экземпляр django.template.Context, но в поставку Django также входит специальный подкласс — django.template.RequestContext, который работает немного иначе. Класс RequestContext по умолчанию добавляет группу переменных в контекст шаблона - такие как объект HttpRequest или информацию о текущем пользователе.


Класс RequestContext и контекстные процессоры были созданы для решения этой задачи. Контекстные процессоры позволяют вам указывать ряд переменных, которые будут устанавливаться автоматически для каждого контекста, без необходимости их указания в каждом вызове render_to_response(). Надо лишь использовать RequestContext вместо Context при обработке шаблона.


То есть, собственно говоря, для чего на нужны контекстные процессоры?
Контекстный процессор принимает объект HttpRequest и возвращает словарь переменных для его последующего использования в контексте шаблона.
То есть, для поставленной перед собой задачи - вывод дополнительной информации в любых шаблонах он справляется.

В django книге описано, как создавать свои глобальные процессоры.

Есть еще варианты - http://softwaremaniacs.org/forum/django/1439/

3 марта 2009 г.

Django. Валидация формсетов. Часть вторая

При использовании двух формсетов в одном виде возникает следующая проблема валидации:
1. Валидация формсета проходит следующим образом:
а)Валидируются все формы, входящие в рамки:
self._total_form_count = self.management_form.cleaned_data[TOTAL_FORM_COUNT]
б)экстра-формы, в которых нет вообще никаких данных игнорируются.
2. В связи с синхронным использованием двух формсетов может возникнуть следующая проблема:

У одного формсета валидируются, например, 1,2 и 5 форма, а у другого только 1,2, в связи с тем что у второго формсета 5 форма пустая.

Вот эту проблему и попытаемся сегодня решить.

Начало функции, отвечающей за валидацию вормы (валидация формсетов - это просто валидация каждой формы в формсете)

208 def full_clean(self):
209 """
210 Cleans all of self.data and populates self._errors and
211 self.cleaned_data.
212 """
213 self._errors = ErrorDict()
214 if not self.is_bound: # Stop further processing.
215 return
216 self.cleaned_data = {}
217 # If the form is permitted to be empty, and none of the form data has
218 # changed from the initial data, short circuit any validation.
219 if self.empty_permitted and not self.has_changed():
220 return

Как написано в комментариях в коде - если форме разрешено быть пустой, прекращаем всякую валидацию. Значит, наша задача, привести свойство empty_permitted или метод has_changed() для каждой формы в каждом формсете к единому синхронному виду.

Переопределяем функцию has_changed(), в обоих классах, в котором мы описываем формы, использующиеся в формсетах:

def has_changed(self):
"""
Returns True if data differs from initial.
"""
if hasattr(self, 'is_change'):#проверяем, если наш динамический атрибут is_change
return True
else:
return bool(self.changed_data)


Дальше ясно - создаем динамический новый атрибут для объекта формы в случае, если в формсетах две синхронные формы имеют разные зачения has_changed(), в итоге, они станут иметь одинаковые. Ес-но, это надо проделать до валидации формсетов.

23 февраля 2009 г.

googlefight.com

Набрел на забавный сервис http://www.googlefight.com/, подсчитывает количество страниц результатов по данному запросу в гугле и выявляет победителя, например:
http://www.googlefight.com/index.php?lang=en_GB&word1=linux&word2=windows
http://www.googlefight.com/index.php?lang=en_GB&word1=linux&word2=freebsd
http://www.googlefight.com/index.php?lang=en_GB&word1=jazz&word2=pop

22 февраля 2009 г.

bash во freebsd 6.2

При установке серверов в freebsd скрипты запуска обычно копируются в /usr/local/etc/rc.d/ . Установив по необходимости систему именно freebsd и парочку серверов был озадачен тем, что скрипты-то не запускаются. То есть, ни ошибок, не предупреждений - ничего. Очень давнишний опыт настройки сервера помог мне вспомнить, что в freebsd по умолчанию стоит не bash, а как выяснилось csh.

Посему, устанавливаем bash из портов, меняем редактор по умолчанию с vi на ee (лично мне он удобнее):


# cd ~
# ee .cshrc

Изменяем setenv EDITOR ee

Перелогинились.

# cd ~
# ee .profile

Добавляем
export EDITOR=ee


# chpass

Меняем shell на /usr/local/bin/bash.

Перезагружаемся.

Кстати, я так и не понял, на чем скрипты. Но на bash у они таки заработали.

14 февраля 2009 г.

Запуск (установка и быстрая настройка) сервера subversion в debian lenny

Устанавливаем сервер и создаем репозиторий:

# apt-get install subversion
# svnadmin create /path/to/svnrepo/
# groupadd subversion
# chown -R root:subversion /path/to/svnrepo/
# chmod -R ug+rw /path/to/svnrepo/

Создаем файл:

/etc/init.d# cat svnserver
svnserve -d -r /path/to/svnrepo/
/etc/init.d# chmod 755 svnserver

Регистрируем в init.d для автозагрузки:

# update-rc.d svnserver defaults

Можно пользоваться:

# svn co svn://localhost/path/to/svnrepo/


ps. Помните, серверу svnserve не обязательно указывать существующий репозиторий. Путь, указанный в аргументе - только лишь указание серверу с какого места начинать просмотр директорий. Поэтому, путь может быть таким:

/path/to/svnrepos

в поддиректориях которого могут располагаться несколько репозиториев:

/path/to/svnrepos/repo1
/path/to/svnrepos/repo2
..
/path/to/svnrepos/repoN

12 февраля 2009 г.

Моя установка (перемещение с windows) trac на debian lenny с базой postgresql

Устанавливаем базу postgresql и дополнительные нужные пакеты:

# apt-get install postgresql postgresql-client postgresql-contrib-8.3

Считаем, что python уже стоит:

# apt-get install python-psycopg2
# apt-get install postgresql-plpython-8.3
# apt-get install python-svn python-subversion

Первый пакет предоставляет доступ к базе из python.
Второй пакет устанавливает возможность писать хранимые процедуры в БД на языке python, которые используются в trac.
Третий позволяет работать с svn репозиториями из python.

Создаем базу данных для trac и пользователя (роль) для базы данных:

# su postgres
$ createuser tracuser -P
Enter password for new role:
Введите снова:
Shall the new role be a superuser? (y/n) y

Тут дописываем: /etc/postgresql/8.3/main/pg_hba.conf .

local trac tracuser md5

Это надо для того, чтобы мы могли соединяться к базе через локальный сокет с помощью нашей роли в базе, а не через tcp/ip . По умолчанию все соединения через local идут для роли безопасности в конфигурационном файле indent sameuser - вкратце, необходимо наличия такого же системного пользователя.

После изменения - "$/etc/init.d/postgresql-8.3 restart" .

Создаем базу данных:

$ createdb -T template0 -h localhost -U tracuser -W trac

Устанавливаем trac и создаем проект:

# wget ftp://ftp.edgewall.com/pub/trac/Trac-0.11.2.1.tar.gz
# tar zxfv Trac-0.11.2.1.tar.gz
# cd Trac-0.11.2.1
# python ./setup.py install
# trac-admin /path/to/myproject initenv

Это для создания нового проекта, для перемещения старого (в моем случае) копируем папку окружения, изменяем конфиг. Делаем бекап базы данных.

Например с windows:

c:\Program Files\PostgreSQL\8.3\bin>pg_dump -U admin trac > tracplain.dump

Восстанавливаем на lenny созданную базу (createlang plpythonu pg_dump сам предусмотрительно прописывает, для этого мы сделали пользователя суперюзером):

# psql -U tracuser -W -f trac.plain trac

Устанавливаем trac через mod_wsgi

# apt-get install libapache2-mod-wsgi

Прописываем в конфиге apache2

WSGIScriptAlias /trac /path/to/trac/mysite.wsgi

WSGIApplicationGroup %{GLOBAL}
AuthType Basic
AuthName "Trac"
AuthUserFile /homr/svn/passwd
Require valid-user
Order deny,allow
Allow from all


Файл с пользователями создаем с помощью passwd.

Содержание файла /path/to/trac/mysite.wsgi:

# cat mysite.wsgi
import os

os.environ['TRAC_ENV'] = '/path/to/trac/'
os.environ['PYTHON_EGG_CACHE'] = '/path/to/trac/eggs'

import trac.web.main
application = trac.web.main.dispatch_request

import site
site.addsitedir('/usr/lib/python2.5/site-packages')

Ресинхронизируем окружение:

# trac-admin /path/to/trac/ resync

Осталось настроить права для каталога окружения проекта и все должно работать.
Также можно урезать права пользователю tracuser с помощью ALTER ROLE

И напоследок, Postgresql quickstart:

1. To start postgres
# /etc/init.d/postgresql start
2. To stop postgres
# /etc/init.d/postgresql stop
3. To start using postgres, change to user postgres
$ su - postgres
4. To create new database
$ createdb dbname
5. To delete database
$ dropdb dbname
6. To access database
$ psql dbname
7. To dump database (backup)
$ pg_dump dbname > backup.out
8. Reload db from file
$ psql -d dbname -f db.out
9. To dump all database to file
$ pg_dumpall > dumpall.sql
10. Reload all from file
$ psql -f dumpall.sql
11. List database
$ psql -l
12. Clean all database
$ vacuumdb --quiet --all

Commands inside psql (PostgreSQL interactive terminal)

1. Access psql
# psql
2. Get help about commands
# \h
3. Quit psql
# \q
4. Import from file
# \i input.sql
5. Show databases
# \l
6. Show tables
# \dt
7. Show users
# \du
8. Connect to database
# \c dbname
9. Change user password
# \c template1
# ALTER USER postgres with password 'new_password';
10. Clean database
# VACUUM FULL;
11. Help on syntax command
# \h SYNTAXNAME

9 февраля 2009 г.

Александр Блок

Александр Блок

Ночь, улица, фонарь, аптека,
Бессмысленный и тусклый свет.
Живи еще хоть четверть века -
Все будет так. Исхода нет.

Умрешь - начнешь опять сначала,
И повторится все, как встарь,
Ночь, ледяная рябь канала,
Аптека, улица, фонарь.

1 февраля 2009 г.

"Серверная" на балконе

Решил я обезопасить и сделать более комфортным свое жилище. Обезопасить - это потому, что у меня инет канал обычно не пустует, зачем ему зря пропадать, как говориться, а меня иногда не бывает дома - а комп работает - я случаев таких не знаю, но есть вероятность воспламенения компьютера. Более комфортным - это понятно - нет ночного гула.

Начнем с железной части.

Так как дело происходит зимой, то главный вопрос, который возникает - а выдержит ли холода система.
На одном форуме доказывал человек о стойкости железа к морозам, приводя в пример системы моментальных платежей, аргументируя это тем, что в них находятся обычные комплектующие.
Я решил проверить это. Сначала я поставил системник (pentium 1200 с 512 Mb DIMM) просто голым, проведя предварительно питание и сеть, больше ничего не надо. Проработал ночь при 0 градусов на улице (балког застеклен, не не утеплен), с утра отвалился, пинги не шли, но все крутилось. Думал - холодно ему, надо сделать ящик, да и от внешнего воздействия не помешает. Сделали ящик, попутно устанавливая софт, все это заняло около недели.

О софте.

Поставлен debian etch - единственный дистрибутив, который у меня был 32 битным. Иксы ставить не стал, ибо незачем =). Настроил sshd, samba (подключен сетевой диск с шарой к винде), для закачек поставлен дополнительный винт 160 Гб, который отформатирован в файловую систему reiser fs; apache, установлен rtorrent, последний из svn, как написано тут, но wtorrent ставить не стал - точнее поставил, но отказался, нашел более интересную веб морду - называется ruTorrent, практически аналог utorrenta, но в вебе, почти все на яваскрипте, ниже скрин.



Текущая версия ruTorrent - 1.6, на скрине 0.1. Единственный момент - пришлось скачать по ссылке файлик settings.txt и поместить его в папку settings.
Веб мордочка очень понравилась. Единственный минус, правда это минус самого rtorrent - нет очереди закачки. Но есть приоритеты и ограничения глобальных слотов скачки. В принципе, это тоже самое.

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



А вот как устроена связь:



Процесс размещения системы в стойке =) Естественно, комп был прогрет дома и запущен сразу.



А вот так он выглядит в боевом состоянии:



Так вот, первый заход оказался неудачным - те же симптомы, что и при первой пробе, но быстрее, ибо температура на улице минус 10 градусов - пинг пропадает, хотя по звуку все крутится. Проработал полчаса, вот температура, снятая сенсорами каждые 5-10 минут:

M/B Temp: +17°C (high = +105°C, hyst = +0°C)
CPU Temp: +36.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +14°C (high = +105°C, hyst = +0°C)
CPU Temp: +29.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +13°C (high = +105°C, hyst = +0°C)
CPU Temp: +28.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +13°C (high = +105°C, hyst = +0°C)
CPU Temp: +27.0°C (high = +100°C, hyst = +92°C)

Дальше он не отвечал на запросы.
Вернул системник назад - открыл - потрогал руками самые холодные места - сетевая была самой холодной. Это было какая-то сетевушка под названием complex, очевидно качество не очень. Решил заменить, нашел acorp с чипом realtek. Провел ту же процедуру помещения в стойку =). Вечером похолодало до -12 градусов. ПРоцесс снятия температуры:

M/B Temp: +14°C (high = +105°C, hyst = +0°C)
CPU Temp: +34.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +13°C (high = +105°C, hyst = +0°C)
CPU Temp: +27.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +12°C (high = +105°C, hyst = +0°C)
CPU Temp: +26.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +11°C (high = +105°C, hyst = +0°C)
CPU Temp: +25.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +11°C (high = +105°C, hyst = +0°C)
CPU Temp: +26.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +11°C (high = +105°C, hyst = +0°C)
CPU Temp: +25.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +10°C (high = +105°C, hyst = +0°C)
CPU Temp: +25.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +10°C (high = +105°C, hyst = +0°C)
CPU Temp: +27.0°C (high = +100°C, hyst = +92°C)

M/B Temp: +10°C (high = +105°C, hyst = +0°C)
CPU Temp: +23.0°C (high = +100°C, hyst = +92°C)

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