MacOS Case-Sensitive FIle System

Published 1/13/2013 by e0ne
Tags:

Какое-то время назад, для меня было удивительно, что в Mac OS X, в отличии от Linux, стоит Case-Insensitive файловая система. Т.е. файловая система не чувствительная к регистру файлов и директорий. В большинстве случаев, это не причиняет вреда, но иногда приносит достаточно досадные проблемы. Что бы избавиться от этого можно либо создать раздел с Case-Sensitive файловой системой, либо создать временный (или не очень) виртуальный диск. Плюс второго способа в том, что этот диск будет храниться одним файлом и, при необходимости, если легко будет удалить.

В Mac OS это делается с помощью встроенной программы Disk Utility:

 

Такой небольшой диск прост в создании и использовании и дает возможность проверить работу приложения в более приблеженном к linux окружении (имеется в виду ошибки в путях к файлах и реозиториям).


Суббота, вечер, пишу очень IMHO. Мнение атора может не совпадать с мнениями других и действительностью.

С моей точки зрения, как разработчика проекты делятся на:

 

  • Outsourcing - вроде все понятно, самый популярный вид разработки в наших краях, но бывает разный
    • product development - когда вся разработка происходит тут, у нас, менеджмент тоже свой, но заказчик кто-то из вне. Собственно заказчик, со всемы вытикающими отсюда плюсами и минусами, единственное, что отличает этот пункт, от пункта "own product
    • "классический аутсорс" (не знаю как правильно называется) - когда заказчик возводится чуть ли не до уровня Бога, а мы для него становимся просто дешовой рабочей силой, которая должна молча, быстро и хорошо выполнять задачи, которые меняются по срокам, целям и приоритетам по неизвестной для нас причине.
  • Outstuffing - когда продают команду, фактически, команда тут становится равноправной командой заказчика, просто удаленной.
  • Own Product - разработка своего продукта. Не все так радужно и классно, как может показаться на первый взгляд. Если это первая версия - то да, драйв, код и рок-н-ролл: мы выбираем технологии, фичи, делаем эстимейты, никакого легаси кода. Но как только продукт может случиться такое: начинает использоваться, появляется легаси код, архитектура становится не такой классной и т.д.
  • Startup - модно, стильно, быстро. Иногда много денег, иногда - нет. Сложность и интересность проектов (с точки зрения разработчиков) зависит только от фантазии основателя и наличие энтузиазма/денег на еду у программистов. Риски тут 50/50 - или повезет, или нет.

 


Давно решил не писать отзывы к библиотекам/фреймворкам, но эта поражает меня уже второй раз так, что в твиттере не помещается вся мысль.

TestFixtures (http://packages.python.org/testfixtures/) - приятное дополнение, а в некоторых случаях, и замена Mock.

То, что она умеет делать mock’и объектов - этим никого не удивишь. Вся прелесть TestFixtures в том, что в ней уже из коробки доступны те самые вещи, которые часто приходится писать самому, тем самым изобретать свой велосипед:(.

Начиная от небольших функций, вроде generator и wrap, библиотека включает в себя то, из-за чего лично я ее использую: различные helper’ы для тестирования логгирования и вывода в потоки (stream’s) (когда-то очень помогла, найти ошибку и некорректным перехватом исключения и, вследствии чего, потерей части логов), а также всякие полезности для тестирования работы с датами и исключеними. 

Для меня это темерь однозначно must use в юнит-тестах.


 

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

DNS (Domain Name Service) - служба доменных имен. С ним (DNS) все сталкивались, но далеко не все знают как он работает и что может. В простейшем случае - это сервис, который переводит доменное имя в IP адрес, а вот что у него внутри - читайте ниже.

Как и большинство протоколов, DNS имеет свою спецификацию, описанную в RFC 1035 и RFC 1706.

DNS имеет иерархическую структуру:

 

 

Корневые DNS серверы (“.”, root name servers, http://en.wikipedia.org/wiki/Root_name_server) отвечают за информазию о доменах верхнего (1-го) уровня, таких как .com, .net, .info и так далее. За ними идут DNS серверы второго уровня, которые содержат информацию о доменах 2-го уровня (поддомены). И так далее по иерархии

 

 

Записи в DNS имеют разны значения и время жизни (TTL, time to live). TTL означает то, сколько времени будет храниться кеш об DNS записи, что-бы DNS-сервере не нужно было лишний раз образаться с запросом к вышестоящему DNS.

Поля DNS записей:

 

  • NAME - собственно само доменное имя;
  • TYPE - тип домена;
  • CLASS - класс записи; в стандате RFC прописано, что DNS может работать не только в сетях по TCP/IP, класс записи определяет тип сети;
  • RDLEN, RDATA - длина и формат с данными о домене.

 

Типы записей DNS (с чем чаще всего приходится работать):

 

  • A record - определяет соответствие домена IP-адресу;
  • AAAA - тоже самое, что и  A, но для IPv6;
  • CNAME - каноническое имя, alias домена, используется для редиректов на другое (под)домен;
  • MX - mail exchage, указывает адреса серверов, которые отвечают за работу с email’ами для данного домена;
  • PTR - pointer, нужен для обратных (reverse) DNS-запросов, которые по IP адресу возвращают FQDN.

 

 

Отдельно стоит сказать про FQDN  - fullly qualified domain name, полное уникальное имя домена, включаещее также корневой домен и завершается точкой (“.”): blog.e0ne.info.

Если спуститься на уровень протокола, то формат сообщения между DNS сервером и клиентом выглядит так:

 

 

Бывает полезно при работе с TCP Dump и другими анализаторами траффика на разных уровнях модели OSI

Идентификатор:

  • 16-битовое поле для обозначения соответствия между запросами и откликами.
  • Q
  • 1-битовый флаг запроса (query).

Запрос:

  • 4-битовое описание типа сообщения:
  • 0   стандартный запрос (адрес по имени).
  • 1   обратный запрос (имя по адресу).
  • 2   запрос состояния сервера.

A:

  • Authoritative Answer - 1-битовый флаг, показывающий отклик от уполномоченного (authoritative) сервера имен.

T:

  • Truncation - отбрасывание. 1-битовый флаг, говорящий об отбрасывании сообщения.

R:

  • 1-битовый флаг, устанавливаемый устанавливаемый для разрешения запроса рекурсивным путем.

V:

  • 1-битовый флаг поддержки рекурсивного сервиса.

B:

  • 3-битовое поле, зарезервированное для использования в будущем (0).

RCode:

  • Код отклика - 4-битовое поле, устанавливаемое сервером имен для обозначения состояния запроса:
    • 0   нет ошибок.
    • 1   невозможно интерпретировать запрос из-за формальной ошибки.
    • 2   обработка невозможна из-за сбоя на сервере.
    • 3   запрошенное имя не существует.
    • 4   неподдерживаемый тип запроса.
    • 5   отказ от выполнения запроса.

Счетчик вопросов:

  • 16-битовое поле, содержащее число записей в разделе вопросов.

Счетчик ответов:

  • 16-битовое поле, содержащее число записей о ресурсах в разделе ответов.

Счетчик Authority:

  • 16-битовое поле, определяющее число записей о ресурсах сервера имен в разделе authority.

Счетчик дополнений:

  • 16-битовое поле, определяющее число записей о ресурсах сервера имен в дополнительном разделе.



4 января вышел релиз кандидат fullstack-фрейморка для разработки веб-приложения Django. Обзоры, наверено, не писали/читали только ленивые. Но пишут, в основном, про мажорные фичи, из-за которых и выпускают релиз. Я перевел свой небольшой прототипчик одного приложения на Django 1.5 RC и поюзал некоторые минорные нововведения, о которых пишут мало, но которые почти делают каждый релиз тем, из-за чего часто хочется использовать именно его. Из того, что мне понравилось - это:

  • изменения в template engine: теперь True, False, None воспринимаются так же, как и в python;
  • дополнительные батарейки для работы с временными зонами - мелочь, а очень приятно;
  • исправленна ошибка OutOfMemory при использовании команды dumpdata - особенно полезно на небольших хостингах;
  • mod_wsgi auth handler - для тех, кто все еще использует Apache и Basic авторизацию;
  • в debug конфигурации приложения логи дополнительно выводятся в консоль;
  • user_login_failed событие - понятно что это такое, +1 к секьюрити: легче блокировать ботов от перебора паролей и плюс к защите от DDoS;
  • loaddata имеет опцию для игнорирования колонок, которых больше нет в модели - просто в восторге от этой фичи, имхо, она для меня теперь станет неаменимой при разработке, кода модель активно меняется, а django south использовать еще рано (в момент разработки, а не при выходе в production).
Из всего вышесказанного, кроме mod_wsgi auth handler попробовал все и хоче сказать: дявол кроется в деталях, они делают любой продукт именно таким, чтоб им (не) хотелось пользоваться.

Ну и не могу сказать про одно мажорное изменения - эксперементальная поддержка Python 3.2+! Осталось подождать и/или портировать нужные зависимости для проектов и можно начинать использовать. На свой страх и риск, конечно, т.к. production код должен быть как можно стабильнее, а не в статусе "эксперементальная фича". Хотя, time to market никто не отменял...

Подробности на оффициальном сайте Django:


Читая серию заметок Кости Данилова "Облака 'на коленке'" подумалось: велосипеды - это хорошо. Но, что б это было хорошо, они должны соответствовать таким требованиям (1 или более):

  • выполнять роль прототипа (PoC);
  • создаваться для того, что бы разобраться с каким-то фреймворком и/или технологией;
  • удаляться при первом же понимании того, что кто-то это уже сделал.
Если ни одно из вышеперечисленных правил не выполняется, то:
  • разрабочик чего-то не знает
    или
  • разработчик думает, что занет все :).

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


 

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

 

  1. Установить значения username/email:
    $ git config --global user.email "e0ne@e0ne.info"
    $ git config --global user.name "e0ne"

    через .gitconfig это делать не всегда удобно, т.к. иногда нужно разные name/email для разных upstream repos
  2. Установить upstream branch:
    $ git branch --set-upstream master upstream/master
  3. Поменять последний коммит:
    $ git commit --amend -a
  4. Поменять автора нескольких коммитов:
    $ git filter-branch --commit-filter '
            if [ "$GIT_COMMITTER_NAME" = "<Old Name>" ];
            then
                    GIT_COMMITTER_NAME="<New Name>";
                    GIT_AUTHOR_NAME="<New Name>";
                    GIT_COMMITTER_EMAIL="<New Email>";
                    GIT_AUTHOR_EMAIL="<New Email>";
                    git commit-tree "$@";
            else
                    git commit-tree "$@";
            fi' HEAD
    $ git push
  5. После мерджа пометить конфиликт как resolved:
    $ git add file
  6. Откатить локальные коммиты:
    reset --soft HEAD^
  7. Переместить тег на другой коммит:
    $ git tag -d ver_0.1
    $ git push origin :refs/tags/ver_0.1
  8. Лучший мануал по git’у:
    http://git-scm.com/book
  9. Мой .gitconfig лежит тут: https://github.com/e0ne/dot-files/blob/master/.gitconfig
  10. Мой .gitignore лежит тут: https://github.com/e0ne/dot-files/blob/master/.gitignore
  11. Cоздаем branch из tag'а: http://blog.e0ne.info/post/Git-create-branch-from-tag.aspx
  12. Мерджим апдейты с другого репозитория: http://korenkov.info/fetching-updates-from-another-git-repo

    [Updated 26.04.13]
  13. Обновить исходники, затирая локальные изменения:
    $ git fetch --all
    $ git reset --hard origin/master
  14. Удалить все недобавленные в репозиторий файлы и директории:
    $ git clean -f -d

 


Почему-то, информации на тему “что такое network namespace” я практически не нашел, что в очередной раз доказыват: английский - основной язык для ИТ.

Network namespace - это логически отделенный от других стек сетевых протоколов в Linux. Такая себе контейнерная виртуализация для сетевых интервейсов, когда chroot LXC и нужна виртуализация только сетевых интерфейсов. Эмулируется полностью сетевой стек: сетевые интерфейсы, таблица маршрутизации, файрволл и т.д. Так, как это работает на уровне ядра и для определенных процессов, то вполне можно получить рабочую конфигурации, когда на одной машине есть несколько сетевых интерфейсов с одинаковыми IP-адресами и ничто не конфликтует. 

Их поддержка в виде патчей появилась еще в версии 2.6.20 (из коробки в дистрибутивах было замечено мной только начиная с 2.6.32) ядра Linux, а в 3-й ветке стали доступы из коробки. Также для работы с ними необходима утилита iproute2. Полный список дистрибутивов и поддерживаемых ядер можно наяти по ссылке http://code.google.com/p/coreemu/wiki/NamespaceKernels. От себя добавлю, что с Ubuntu 12.04/12.10 проблем не было, а вот на RHEL 6.3 и, основанной на нем, CentOS 6.3 поддержки network namespaces нету на уровне ядра. Сростой способ проверки - посмотреть наличие директории /proc/self/ns/

Основные действия с ними можно выполнять с помощью команды ip netns (ip netns - process network namespace management):

  • ip netns list - посмотреть все network namespaces
  • ip netns add NAME - создать новый network namespace
  • ip netns delete NAME - удалить network namespace
  • ip netns exec NAME cmd - выполнить команду внутри network namespace

При запуске любого процесса с определенным network namespace у него в /proc/ID/ns/ будут данные о данном неймспейсе, что поможет ядру правильно подставить сетевой стек. Также все network namespace можно будет найти в /var/run/netns/ns_name в виде обычных файлов. Пока файловые дескрипторы этих файлов открыты, считается, что network namespacе работает. Если создать файлы /etc/netns/ns_name/{resolv.conf, hosts, ...}, то ip-netns будет подставлять процессам именно эти файлы, а не системные, что очень удобно для отладки и не только.

Чтобы посмотреть в каком network namespace выполняется нужный процесс достаточно посмотреть содержимое директории /proc/proc_id/ns/.

Разные network namespace можно объединять между собой с помощью виртуальных сетевых интерфейсов (veth).

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

ip link set eth1 netns samplens

По умолчанию, все сетевые процессы находятся в так называемом initial network namespace, у которого нет имени :). Но все конманды для работы с network namespace кроме имени, в качестве параметров, могут принимать ID процесса, который управляет неймспейсом. Для initial network namespace ID равен 1, что равнозначно ID init процесса. Таким образовом, чтобы обрать интерфейс из неймспейса, его стоит добавить в неймспейс с ID=1:

ip link set eth1 netns 1

 

Дополнительные ссылке по теме:

 

P.S. При виртуализации сетевых интерфейсов не могу не упомянуть про tun/tap устройста (http://www.kernel.org/pub/linux/kernel/people/marcelo/linux-2.4/Documentation/networking/tuntap.txt, http://backreference.org/2010/03/26/tuntap-interface-tutorial/). Что это такое я уже крато писал в одном из предыдущих постов. Сам подход, что они реализовываются через файловые дескрипторы(файлы), существует и по сей день. В Linux - почти все файлы, и сетевые интерфейсы не исключение :)


В очередной раз чуть не наткнулся на давнюю проблему, но вовремя опомнился. При pylint “радостно” сообщил, что в некоторых модулях есть unused imports и их можно(нужно) удалить. Все было бы хорошо, если б не одно но: python очень даже динамический язык, а pylint ничего не знает о том, что будет происходить с кодом во время выполнения. Исходя из этого, уже можно представить какие проблемы могут быть. В моем случае, код был такой:

from quantum.openstack.common import cfg
...
from quantum.plugins.openvswitch.common import config

И pylint “ругался” на 2-й импорт, который нигде больше не использовался. Но если посмотреть на код этого модуля (https://github.com/openstack/quantum/blob/master/quantum/plugins/openvswitch/common/config.py) и вспомнить как работает механизм импорта в Python’е, то становится ясно, какие проблемы могут быть: при загрузке модуля config, он устанавливает значения по умолчанию настроек. А так, как со всемы настройками принято работать через общий интерфейс cfg, и не импортировать можуль config, то, с большой вероятностью, где-то в runtime у нас произойдет исключение. 

Описанный выше пример простой и банальный, но приводит нас к двум простым правилам:

  • нельзя слепо доверять анализаторам кода, особенно, если этот код динамический;
  • при проведении review кода нужно смотреть не только на новый/измененный фрагмент, а следует держать в голове полную картину и представлять как этот код будет работать с остальными частями приложения.

Вот интересно, если бы не unit-тесты и понимание работы import’ов, сколько бы времени потратил на фикс бага, после такого “улучшения” кода?


В этор раз идет подготовка сразу к двум KhakrivPy, соответственно докладчиков нужно найти больше.

26-го января пройдет KharkivPy #0, посвященный функциональным языкам программирования (Erlang, Lisp, Haskel, Scala, etc). На данный момент к нам в гости с докладом согласился приехать из Киева Владимир Кирилов (http://kirillov.im/, @darkproger) с докладом про Erlang, тема уточняется.

Ищем докладчиков, которые расскажут что-то интересное о других языках и/или про Erlang. Опыт в продкашн приветствуется.

2-го марта традиционный KharkivPy #7, на который тоже ищутся докладчики.

Желающие поделиться своим опытом могут обращаться ко мне  по телефону(+380919050626), скайпу (e0ne-user) или email'у (e0ne@e0ne.info)ю

Так де 19-го января в Киеве пройдет KyivPy, туда так же требуются докладчики. Подробности тут.

 

P.S. Этот пост написан в рамках акции, в которой я принимаю участие, которая запущена Стефани Бус и называется #back2blog, подразумевает написание 10 постов в блог за 10 дней. Это 1й пост из 10.