Showing posts with label web. Show all posts
Showing posts with label web. Show all posts

Wednesday, April 1, 2009

Links: tddspry, ItQuest.ru

Link 1. tddspry

Что такое tddspry? Это небольшой набор утилит для тестирования django-приложений с помощью nosetests. Если по какой-то причине Вы не можете воспользоваться Django Test-execution Framework или джанговские тесты просто Вас раздражают, то обязательно обратите внимание на этот небольшой проект. На данный момент в состав tddspry включены хэлперы для написания тестов, а также моки для БД и twill. В дальнейшем возможно включение поддержки Windmill, etc. Проект открыт для предложений. :)
Пример использования:
class TestUI(TwillMock, DbMock):
def setup(self):
super(TestUI,self).setup()
login_to_admin(username='admin', password='admin')

@show_on_error
def test_order_add_no_transport(self): # ticket:9
go(SITE + '/shop/order/add/')
code(200)
assert not "Transport" in show(), show()

Link 2. ItQuest.ru

Возможно, многие из читателей уже слышали о таком сервисе, как ItQuest.ru. А если не слышали - обязательно обратите на него внимание. Ресурс идейно схож с StackOverflow - большая база вопросов и ответов на IT тематику. Так что если у Вас есть вопрос, ответ на который не знает даже Google, попробуйте задать его здесь.
P.S. Сайт написан на Django. Еще один повод присмотреться.

Thursday, August 28, 2008

IPv6 не будет

Слегка адаптированная мной заметка по мотивам http://www.extremetech.com/article2/0,2845,2328258,00.asp:

Arbor Networks измерили объем IPv6 траффика, проходящего через 2400 бэкбонов и роутеров у 87 провайдеров Интернет по всему миру. Учет велся с Июня 2007 по Июль 2008 года. Полученные данные были использованы для исследования, которое компания считает наиболее всеохватывающим исследованием ситуации с IPv6 на сегодняшнее время. В целом Arbor отследил 15 экзабайт траффика - при этом все человеческое знание занимает 4 экзабайта, как заявляют представители компании.

Это исследование показало, насколько плачевна ситуация в стане IPv6. Если верить полученным данным, объем междоменного IPv6 траффика составил всего 0.0026% от объема IPv4 траффика. Были замечены два пика активности между 4 ноября и Рождеством 2007 года, на пике процентное соотношение поднялось до 0.012%. При этом, процент соответствия IPv6 и IPv4 траффика оставался неизменным за все время исследования.

Я уже писал о том, что такое IPv6 и насколько переход на него с устаревшего IPv4 важен. В действительности, если не будет существенных сдвигов в ближайшее время, то по некоторым оценкам уже к 2011 году IPv4 адреса закончатся и развитие сети Интернет остановится. Переход же на IPv6 даст возможность использовать 340 миллиардов миллиардов миллиардов миллиардов адресов, чего должно хватить на ближайшее будущее :)

"Я не думаю, что переход уже начался", - говорит Scott Iekel-Johnson, основной автор исследования и главный специалист по программному обеспечению в компании Arbor, -"Не похоже, что хотя бы в какой-нибудь значительной части из охваченных исследованием регионов были существенные сдвиги"
Как это ни дико, по заявлениям исследователей, один из пиков совпал с собранием рабочей группы проектирования Интернет (IETF) - одной из групп, которая яростно толкает индустрию к использованию IPv6 адресования. Во время собрания, как говорят представители Arbor, участников попросили выключить IPv4 функциональность на своих компьютерах и роутерах и проверить, какие сайты будут доступны. Чтобы протестировать инфраструктуру, они смотрят онлайн-видео, качают файлы больших объемов. Предполагается, что это и вызвало учтенный пик.

Тем не менее, на этом собрании было зарегистрировано только 1168 человек. Т.е., по данным компании, всего чуть более тысячи человек вызвали самый высокий всплеск IPv6 активности за последние 12 месяцев. Это говорит о многом.

Исследователи видят два способа разрешения проблемы. Первый - поддержка идеи компаниями и государственными органами. Второй - проникновение идеи глубоко в массы. Iekel-Johnson делает ставку на первый вариант. Он приводит пример: "Если Comcast(ISP - прим. моё) скажет своим клиентам: 'Окей, вам нужно использовать IPv6, потому что у нас кончаются адреса, а мы хотим добавлять новых пользователей' - это приведет к существенным продвижениям".
Со своей стороны хочется добавить, что это исследование раскрыло мне глаза на то, насколько все плохо с IPv6. Возможно, понимание того, что мы еще в самом начале пути, подстегнет крупные компании, представителей государства и простых пользователей и продвижение пойдет быстрее.
Чтобы избежать обвинения в искажении фактов при адаптации я предлагаю поучаствовать в полном переводе статьи - сам я не смогу довести ее до читабельного вида без существенных правок. Поучаствовать и почитать текущий вариант перевода можно здесь

Friday, June 20, 2008

Использование Google Search API и Google Translate API в Python

Как известно, Google предоставляет множество различных API для доступа к своим сервисам. Список и описание их можно найти здесь. Я же хочу остановиться на двух весьма удобных сервисах от Google - поиске и переводе. Точнее, хочется предложить простенький рецепт по использованию предоставляемых для них API из Python.

Google Search API и Google Translate API представляют собой AJAX API: вызовы функций - это HTTP запросы, ответ возвращается в формате JSON. В связи с последним нам понадобится библиотека simplejson для парсинга ответов. Итак, начнем с перевода.

def translate(text,langpair):
import urllib
import simplejson

query = urllib.urlencode({'q' : text.encode("utf-8"),'langpair':langpair})
url = u'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&%s'.encode("utf-8") \
% (query)
search_results = urllib.urlopen(url)
json = simplejson.loads(search_results.read())
mess = json['responseData']['translatedText']
return mess

translated = translate("I am feeling lucky","en|ru")
print "Translated:", translated
Не сложнее и API для поиска:
def search(text):
import urllib
import simplejson

query = urllib.urlencode({'q' : text.encode("utf-8")})
url = u'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&%s'.encode("utf-8") \
% (query)
search_results = urllib.urlopen(url)
json = simplejson.loads(search_results.read())
results = json['responseData']['results']
return results

results = search("text to search")
title = results[0]['title']
noh_title = title.replace('', '').replace('', '')
url = results[0]['url']
print noh_title+": "+url # Мне повезет! :)
Для работы API не требуется регистрации, что весьма приятно. Удачного применения!

Wednesday, March 26, 2008

Собственные фильтры в админке django (Custom FilterSpecs)

Обновление от 04.05.2012. Данная статья была написана довольно давно, но до сих пор вызывает некоторый интерес. Спешу сообщить, что с 23-го марта 2012 года с релизом Django 1.4 начинать поиск информации про custom фильтры стоит с официальной документации

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

Существуют также случаи, когда админка Django предоставляет практически весь функционал, который нужен на сайте. Например, если вам нужно приложение для внутреннего использования, которое показывает сохранённую в базе информацию по каким-нибудь событиям(пример из повседневной жизни :) ), то лучше встроенной админки не найдёшь - можно легко настроить, какие поля показывать, по каким полям вести поиск, по каким фильтровать - и всё это - лишь пара строчек кода!
Фильтры в админке - более чем удобная вещь. Например, если у вас есть поля, которые могут принимать значения из фиксированного набора(успех/не успех, номер ошибки, и т.д.), то фильтры позволяют быстро отфильтровать, например, все "успешные" записи, или все записи с упоминанием ошибки 302. Однако, может случиться, что стандартных наборов фильтров вам не хватит, и вы пожелаете добавить свой собственный.

Я постараюсь показать весь процесс добавления нового фильтра на весьма полезном примере - на фильтре, который позволит фильтровать записи по заданному промежутку времени. Например, если у вас есть поле "Время создания", то можно будет отфильтровать все записи, которые были созданы в промежутке между 25 марта 2008 года 00:00 и 26 марта 2008 года 15:00. Итак, начнём.

Все фильтры, которые есть в админке, расположены в django.contrib.admin.filterspecs, все фильтры являются наследниками FilterSpec, у которого есть два особо интересных метода - create и register. Новый фильтр нужно будет зарегистрировать, вызвав функцию FilterSpec.register(test,factory), где test - это функция, принимающая объект ..Field (фильтры создаются автоматически через интроспекцию существующих полей модели) и возвращающая True, если данный фильтр применим для данного поля, а factory - это обычно класс фильтра. Функция register() просто сохраняет эту пару во внутренний список. Функция create() вызывается, когда для какого-нибудь поля нужно создать фильтр - данная функция просматривает список, запускает test функции, и когда находит подходящий фильтр - использует factory для создания объекта и возвращает его. После объявления класса FilterSpec идут сами фильтры, которые сразу же и регистрируются.
Здесь следует важное замечание: фильтры добавляются в список append'ом, поэтому последний добавленный фильтр и будет при create вызван последним. А так как в уже рассмотренном файлике последним добавляется фильтр, который умеет фильтровать любые поля, что означает, что если мы зарегистрируем новый фильтр, то до него при create просто никогда не дойдёт очередь. Такое поведение мне не очень понятно(я привык, что последние добавленные обработчики обрабатываются первыми:) ), к тому же оно сводит на нет прямолинейные попытки добавить свой собственный фильтр.

Однако есть как минимум два способа обойти это недоразумение:
- Тикет #5883 содержит патч, который меняет порядок добавления. Он очень простой и вполне разумный. Я надеюсь, что когда-нибудь он войдёт в основную ветку :)
- Вместо register() можно вставлять нужную запись напрямую в список: FilterSpec.filter_specs.insert(-1, (test, factory))
Что использовать - ваш выбор. Я для себя выбрал путь патча, ибо хоть второй и не требует изменения кода django, однако он противоречит дзену :)

Разобравшись в том, как регистрировать фильтр, перейдём к тому, как он функционирует. Все фильтры рендерятся через шаблон filters.html (django/contrib/admin/templates/admin/filters.html). Для того, чтобы фильтр нормально отобразился, он должен уметь возвращать список опций выбора(choices), которые и будут отображены автоматически. Естественно, это не подходит для нашей цели(как вы помните, мы пытаемся сделать фильтрование по промежутку времени, для задания этого промежутка нам понадобится два текстовых поля), поэтому мы поменяем поведение шаблона(как подменить шаблон админки на свой можно прочитать всё в той же 6ой главе Djangobook). Текст шаблона filters.html ниже:

{% load admin_list %}
{% load i18n %}
{% load filter_tags %}
{% if cl.has_filters %}<div id="changelist-filter">
<h2>{% trans 'Filter' %} </h2>
{% for spec in cl.filter_specs %}
{% if spec.is_datetime_interval_filter %}
{% datetime_interval_filter cl spec %}
{% else%}
{% filter cl spec %}
{% endif %}
{% endfor %}</div>{% endif %}
Хочется обратить внимания на отличия от стандартного файла - подгружаются filter_tags - именно в нём у нас будет находиться inclusion tag datetime_interval_filter, который будет использоваться для всех фильтров, для которых is_datetime_interval_filter есть True(т.е., для нашего фильтра). Теперь посмотрим на новый тэг:
from django import template
register = template.Library()

@register.inclusion_tag('datetime_interval_filter.html')
def datetime_interval_filter(cl, spec):
return spec.get_output_dict(cl)
Ничего интересного в нём нет - он просто возвращает нужный для рендеринга контекст, оставляя процесс генерации его нашему объекту-наследнику FilterSpec(схожим образом действует и стандартный тэг filter). Как видно, он использует темплейт datetime_interval_filter.html - его текст ниже:
<script language='javascript'>
function set_new_location_{{field_name}}()
{
var lte = document.getElementById("{{field_name}}_lte_edit").value;
var gte = document.getElementById("{{field_name}}_gte_edit").value;
document.location.href = '{{query_str}}&{{field_name}}__gte='+gte+'&{{field_name}}__lte='+lte;
}
</script>
<h3>By {{field_title|escape}}:</h3>
<ul>
<li><input id="{{field_name}}_gte_edit" value="{{gte_old_value}}" /></li>
<li><input id="{{field_name}}_lte_edit" value="{{lte_old_value}}" /></li>
<li><a onClick='javascript:set_new_location_{{field_name}}();' style="cursor:pointer;">Filter</a></li>
</ul>
Что есть в темплейте - для каждого нашего фильтра создаётся небольшой скрипт, который займётся обработкой переходов на новую страницу с отфильтрованными данными. Также выводятся два текстовых поля и ссылка для перехода. Для того, чтобы корректно отрендерить этот темплейт, нужно передать:

field_name - имя поля, по которому будем фильтровать.
query_str - строка запроса, которая может содержать и другие значения фильтров.
field_title - название поля.
gte_old_value/lte_old_value - сохранённые значения текстовых полей. Выводятся в те же поля после применения фильтра, что очень удобно для редактирования.

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

Ну, и наконец, сам объект-фильтр:
from django.contrib.admin.filterspecs import FilterSpec
from django.utils.encoding import iri_to_uri

class DateFieldIntervalFilterSpec(FilterSpec):
def __init__(self, f, request, params, model):
super(DateFieldIntervalFilterSpec, self).__init__(f, request, params, model)

is_datetime_interval_filter = True

def get_output_dict(self,cl):
p = cl.params.copy()
return {
'field_name': self.field.name,
'query_str': iri_to_uri(cl.get_query_string(remove=["%s__lte"%self.field.name,"%s__gte"%self.field.name])),
'gte_old_value': p.get('%s__gte'%self.field.name,''),
'lte_old_value': p.get('%s__lte'%self.field.name,''),
'field_title':self.field.verbose_name
}
Небольшие пояснения по коду - как я уже говорил выше - мы наследуемся от FilterSpec. Конструктор не представляет никакого интереса. Флажок is_datetime_interval_filter мы уже упоминали - когда рассматривали темплейт filters.html. Единственная функция, которая требует рассмотрения - это get_output_dict(), которая возвращает словарь, используемый для рендеринга конечного html кода. field_name и field_title не представляют особого интереса - мы просто возвращаем имена поля, для которого работает фильтр. query_str мы получаем из объекта ChangeList - это основной объект, который содержит все фильтры, а также предоставляет доступ к нужным этим фильтрам параметрам(найти его можно в django.contrib.admin.views.main). В качестве параметров функции мы передаём список remove - в нём находятся те значения, которые возвращать не нужно, даже если они указаны. Это позволит нам избежать повторений вида &time__lte=smth1&time__lte=smth2. gte_old_value/lte_old_value мы получаем также из ChangeList - из текущих параметров.

После этого осталось зарегистрировать новый шаблон(для тестирования это можно сделать даже в Urlconf, хотя это и может вызвать некоторые проблемы при автоматической перезагрузке девелопмент сервера):
FilterSpec.register(lambda f: isinstance(f, models.DateField),DateFieldIntervalFilterSpec)
Хочу заметить, что я подменяю все DateTimeField(мне откровенно не нравится стандартный фильтр для DateTime), в то время, как можно добавить проверку на наличие у поля дополнительного атрибута, который добавлять только тем полям в модели, для которых нужен такой фильтр.

Ну, и конечно, хотелось бы посмотреть на результат. Вот скриншшот:На скриншоте - сохраненные Cdr events от Asterisk. Если как-нибудь будет время - я постараюсь осветить тот небольшой код, который позволяет сохранять евенты от Астериска в базе - это потрясающая иллюстрация возможностей Python, Django и Twisted.

Буду рад любым фидбекам и исправлениям. :)

Tuesday, February 26, 2008

Django urlpatterns для hostname

Я не буду сейчас детально рассказывать, что такое urlpatterns в django, понадеясь на осведомлённость возможных читателей. Однако для тех, кому это внове, дам краткий пример. В Django для сопоставления url`ов коду используются конфигурационные файлы urls.py (Urlconf). Основной смысл этих файлов в подобных строчках:

(r'login/$', 'someapp.views.login')
Данная строка означает, что когда пользователь зайдёт на страницу www.example.com/login/ , то для генерации страницы вызовется функция someapp.views.login . В простейшем случаем первым параметром такой строки является регулярка, вторым - нужная функция. Заметьте, что регулярка сопоставляется только с путём, а хостнейм отбрасывается. Сами urlconf весьма удобны, но такое игнорирование хостнейма не даёт использовать стандартные джанговские подходы для реализации подобных вещей:
  • Вызов различных функций в зависимости от части хостнейма, например, pda.example.com - PDA версия сайта, blog.example.com - блог на сайте. Конечно, это можно реализовать и другими средствами, однако создание разветвлённой структуры всё же затруднено.

  • Передача параметров в функции в зависимости от хостнейма. Например, tilarids.blogspot.com - на самом деле, все такие страницы могут генерироваться одной функцией в зависимости от имени пользователя
Т.о., возникает желание получить механизм, который бы работал аналогично urlconf, но вместо пути работал бы с хостнеймом. После небольшого исследования на эту тему у меня создалось впечатление, что это так нигде и не реализовано. Отсюда и родился подобный код:
class HostnameDispatcher(object):
def __init__(self, view, myregex):
self.regex = re.compile(myregex, re.UNICODE)
self.view_func = view
def __call__(self, request, *args, **kwargs):
current_site = RequestSite(request)
match = self.regex.search(current_site.domain)
print "Current args:",args, kwargs
if match:
new_kwargs = match.groupdict()
if new_kwargs:
new_args = args
else:
new_args = match.groups() + args
new_kwargs.update(kwargs);
return self.view_func(request,*new_args,**new_kwargs)

class HostnameRegexPattern(RegexURLPattern):
def __init__(self, regex, callback, hostname_re,proto=u'http://',default_args=None, name=None):
RegexURLPattern.__init__(self,regex,callback,default_args, name)
self.hostname_regex = hostname_re
self.dispatcher = HostnameDispatcher(self.callback, self.hostname_regex)
self.old_regex = self.regex
self.regex = re.compile(u'\b'+proto+hostname_re+u'/'+regex,re.UNICODE)

def resolve(self, path):
match = self.old_regex.search(path)
if match:
kwargs = match.groupdict()
if kwargs:
args = ()
else:
args = match.groups()
kwargs.update(self.default_args)
return self.dispatcher, args, kwargs

Хочется заметить, что основными требованиями к коду были:
  • Полная совместимость со стандартными способами resolve и reverse (получения функции по адресу и адреса по функции соответственно)
  • Безболезненное встраивание в рабочую систему Django
Возможно, код несколько сумбурный - несмотря на недолгую жизнь, он успел почувствовать на себе процесс развития и переделывания. Постараюсь объяснить, что здесь зачем. Итак:
  • HostnameDispatcher - класс, который позволяет resolv`ить функцию по хостнейму, являсь некой надстройкой над этими самими функциями(вернёмся к терминологии django и будем называть их view). Например,
    disp = HostnameDispatcher(my_view,r'^(.*)$')
    создаёт на основе существующего view новый объект, который при резолве добавляет параметры из хостнейма. Удобно, быстро, но никак не поможет при reverse. А вот reverse - это как раз самая сложная, но и не менее нужная часть
  • HostnameRegexPattern - это замена стандартным урлпаттернам. resolve здесь реализуется через уже упомянутый HostnameDispatcher. А вот с reverse пришлось извратиться. В django нет хорошей возможности изменять стандартное поведение reverse. Т.о., я просто изменил существующую регулярку, и в итоге получил почти правильный результат. Единственное, выскакивает '/' в начале. Для его устранения я не придумал ничего лучше, чем сделать небольшой патч для django(в django.core.urlresolvers):
    def backspace_process(func):
    def reverse_new(viewname, urlconf=None, args=None, kwargs=None):
    ret_val = func(viewname, urlconf, args, kwargs)
    if ret_val[:4]=='/%08':
    return ret_val[4:]
    return ret_val
    return reverse_new

    def reverse(viewname, urlconf=None, args=None, kwargs=None):
    args = args or []
    kwargs = kwargs or {}
    return iri_to_uri(u'/' + get_resolver(urlconf).reverse(viewname, *args, **kwargs))

    reverse = backspace_process(reverse)
    Т.е., добавляется в начале отдельный символ(\b), который потом удаляется при надобности. Такое удаление не должно никак повлиять на другие urlpatterns
Ну и наконец: как это использовать. Нет ничего проще- записываем в urls.py в паттерны такую строчку:
HostnameRegexPattern('test/(\d+)/$', 'blog.views.test',r'^(.*)$'),
, где первый параметр - регулярка для пути, второй - функция, третий - регулярка для хостнейма. Всё! :)

Кто может предложить что-нибудь более интересное, или улучшить уже существующий код - буду весьма благодарен.

Wednesday, January 23, 2008

Получение IPv6 адреса - краткое руководство

Данное руководство не является подробной записью всех кликов мышкой, которые приведут вас к нужному результату. Но оно будет полезно в качестве проводника в мир IPv6.

Как можно прочесть в Википедии:

IPv6 — это новая версия протокола IP, призванная решить проблемы, с которыми столкнулась предыдущая версия (IPv4) при её использовании в Интернете
С полным перечнем недостатков IP можно ознакомиться в той же Вики, а я ограничусь напоминанием, как сложно бывает получить реальный IP в наше тяжёлое время. Связано это в первую очередь с малым объёмом 32-битного адресного пространства и банальным недостатком адресов. В том же случае, если вы хотите опробовать IPv6, то вы можете зарегистрировать себе реальный адрес без особых проблем. О том, как это сделать, и пойдёт речь в этой статье.
Данная статья не рассчитана на какую-либо определённую платформу, однако примеры будут приводиться на двух ОС: Windows XP SP2 и Ubuntu 6.06.1 LTS(многократно обновлённой до неузнаваемости). Эти ОС изначально поддерживают IPv6 протокол, но если вы хотите использовать IPv6 на более старых ОС, то это, как правило, не проблема - нужно просто установить обновления(не освещается данным руководством). Для тех, кого не смущает английский язык, могу порекомендовать руководство на http://sixxs.net. Мануал, который вы сейчас читаете является вольным переводом мануала с sixxs.net, дополненным и переработанным.
Итак, начнём. Замечу, что IPv6 адрес будет нами настроен через туннель, который любезно предоставит нам брокер SixXS
1. Для начала, вам понадобится RIPE handle. Если вы не знаете, что это такое - не расстраивайтесь. Вы можете выбрать два пути - или зарегистрировать себе отдельно RIPE handle (довольно простая операция, руководство можно найти здесь) или воспользоваться сервисом прямой регистрации на SixXS.
2. Если у вас уже есть RIPE handle, или вы успешно создали его, вы можете переходить к SixXS Signup. Здесь вас попросят ввести свой RIPE handle и причину, по которой вы желаете зарегистрироваться. Хочется обратить внимание, что SixXS не любит пользователей, которые указали в качестве email адреса адрес, расположенный на бесплатном почтовике. Например, GMail не подходит. Где найти себе "платный" почтовый аккаунт - решать вам.
3. После того, как вы пройдёте шаг SixXS Signup, на указанный email прийдет регистрационное письмо для проверки вашего почтового адреса. Просто перейдите по ссылке, указанной в этом письме. После этого подождите, пока персонал SixXS проверит и подтвердит заявку. Стоит уважать человеческий труд и терпеливо ждать ответа(может прийти как через 15 минут, так и через день).
4. Запросите туннель. (Request a tunnel). После того, как вам будет выслан пароль к вашей учётной записи, зайдите на страницу управления туннелями и закажите туннель. Здесь вам доступно три варианта туннеля: AYIYA, Heartbeat и static. static применим, когда у вас есть статический IPv4 адрес, Heratbeat - когда IPv4 адрес у вас динамический, но вы не находитесь за NAT. Самым безопасным(но наиболее неудобным для серверов SixXS) является AYIYA. Этот вариант работает практически всегда. Также он наиболее часто и используется. После заказа туннеля нужно подождать подтверждения персоналом. Будьте терпеливы!
5. Загрузите приложение AICCU для вашей платформы. Также вам может понадобиться загрузить драйвер для Windows, Mac OS X или NetBSD(на той же странице, что и AICCU, или здесь). Если у вас возникли какие-то проблемы с драйвером, или вы просто хотите получить больше, можно посетить сайт OpenVPN. Ubuntu же, например, из коробки имеет все, что нам нужно для работы AICCU.

  • Для Windows вы получаете небольшое приложение, которое выглядит приблизительно так:


  • Как вы уже наверное, догадались, нужно ввести свой логин и пароль, а в качестве провайдера выбрать SixXS. После этого вам нужно нажать кнопку ОК и выбрать туннель, который вы заказали. Возможно, это будет единственный туннель в списке :) После того, как вы сделаете все это, вы должны увидеть такое информационное окно:
    Кнопочка Enable сделает вас счастливым обладателем реального IPv6 адреса. Обратите внимание, что туннель может быть активирован не сразу после того, как персонал SixXS подтвердит заказ, а в течении часа-двух.
  • Для Ubuntu. Вся процедура намного упрощается тем, что существует уже готовый пакет для установки. Возможно, он потянет за собой какие-то зависимости - однако их разрешение - это удел статьи другой направленности. Также стоит отметить, что все данные, которые в Windows приложении вводятся в GUI окно, нужно ввести еще на этапе инсталляции.
6. Как проверить, что всё это работает? Очень просто - посмотрите в ifconfig (ipconfig в Windows), появился ли у вас интерфейс с IPv6 адресом. Также можно пропинговать этот адрес(ping в Windows и ping6 в Linux). Ну, или зайти на IPv6Calc, чтобы посмотреть, как вас видно из внешнего мира.

Но для Windows пользователей могут возникнуть некоторые затруднения. Например, Firefox для Windows иногда не желает заходить на веб-сайты по IPv6. Также бунтует IExplorer. Хорошая новость для Опероманов - Opera 9.25 прекрасно справляется с IPv6 сайтами. Для Ububntu этот абзац не актуален - всё работает прекрасно и в Firefox тоже. Возможные обходные пути чтобы заставить работать FF в Windows в процессе поиска.

Ну, и последнее, что может быть интересно. SixXS предоставляет простой доступ к IPv4 сайтам - просто добавляйте .sixxs.org к адресу(например, example.com.sixxs.org). Конечно, сейчас сложно поверить, что когда-нибудь это будет единственным путём на сайты, обеспечивающие доступ по устаревшему IPv4 протоколу. Но хочется надеяться, что когда-нибудь это свершится - ведь как удобно было бы иметь свой IP адрес для каждого кремниевого устройства на планете?

Небольшое дополнение для счастливых обладателей статического IPv4 адреса и линуха с поддержкой IPv6, SIT туннелей и установленным пакетом iproute2. Для вас процедура настройки очень упрощается. Достаточно выполнить такие команды:
ip tun add sixxs0 mode sit local _свой_реальный_ipv4_адрес_ remote _ipv4_адрес_который_дали_ 
ip -6 addr add _ipv6_адрес_который_дали_/_маска_ dev sixxs0
ip -6 r add default via _ipv6_шлюз_который_дали

И вуаля - туннель готов. Все нужные параметры можно получить на странице учётной записи. Стоит обратить внимание, что static туннель обязывает вас держать компьютер включенным 24/7 - иначе вас лишат ценных кредитов, которые можно использовать на заказы подсетей и туннелей. Но с другой стороны, если вы будете держать туннель в поднятом состоянии, то кредиты наоборот будут капать. Удачи!
За дополнение спасибо Opium'у.

Friday, January 18, 2008

Django WEB Framework

Не так давно открыл для себя весьма интересный веб-фреймворк для разработки сайтов по концепции MVC - это Django. Радует он хорошо продуманной структурой, документацией, а также выбранным языком программирования - Python обеспечивает ощутимую при разработке мощь. В общем, первое и незабываемое впечатление о Django - этот фреймворк писался для разработчиков, а не для пользователей.

Рекомендую! :)