Tag: MadeByKidd

OpenStack: allow_overlapping_ip의 해결 아이디어 간단 구현

quantum 제한사항에서 allow_overlapping_ip 기능이 안된다고 이전에 포스트 했었고, 이에 대해서 잠깐 생각을 하다가 아이디어가 떠올라서 몇 가지 작업했더니 대충은 동작합니다.

안되는 근본 원인은 instance의 ip를 가지고 어떤 instance인지 특정할 수 없다는 것이었는데, 여기다 tenant-id를 같이 조합하면 된다는 것이죠. 문제는 어떻게 tenant-id를 넘기느냐 였는데, http를 사용하니 header에 집어넣고, 이 header를 집어 넣는 역할을 하는 proxy를 l3 router namespace에서 동작하면 되는 것입니다.

이제 아래처럼 metadata 요청 흐름이 바뀌는 것이죠.

  • instance --> DNAT --> metadata server
  • instance --> proxy in router namespace --> metadata server

prox 서버는 간단히 twisted를 이용해서 만들었습니다.

적용 순서는...

  1. metadata patch 적용: https://github.com/whitekid/nova/commit/de9b371a4667dd66f510093a1e207bc7f9e02c6d
  2. metadata api restart

router name space에서

  1. lo device에 metadata ip 추가
    $ ip netns exec qrouter-XXXX ip addr add 169.254.169.254/32 device lo
  2. DNAT하는 iptables rule 삭제
    $ ip netns exec qrouter-XXXX
    $ iptables -t nat -L quantum-l3-agent-PREROUTING | grep 169.254.169.254 > /dev/null && iptables -t nat -D quantum-l3-agent-PREROUTING 1
    $ exit
  3. metadata proxy 실행
    $ ip netns exec qrouter-XXX python metadata-proxy [real-metadata-api-server-ip] [tenant-id]

그냥 단순히 아이디어 검증 차원이라, 실제로 쓰고자 한다면 많은 추가 작업이 필요할 것 같습니다.

https://github.com/whitekid/metadata_proxy

ps. 아.. 영어 어렵다.. ㅡㅡ


OpenStack: Quantum과 사용할 때 metadata request back routing 문제

Quantum으로 tenant network를 디자인 할 때, 딱 드는 생각은 tenant subnet을 private network을 구성하자 입니다. 물론 그렇겠죠. aws처럼 모든 생성되는 가상머신이 모두 public ip를 가질 필요는 없으니깐요. 필요한 인스턴스에 floating ip를 연결해서 외부에서 접속이 가능하게 하면 됩니다.

Quantum 가이드에 나온 Per-tenant Routers with Private Networks처럼 말이지요. 아래 그림처럼 된다면 참으로 멋진 구성이 될 텐데 말입니다. 사용자가 알아서 DMZ도 구성할 수 있고, 개발환경, production 환경의 네트웍을 똑같이 구성하여 테스트할 수 있고... 그런데 이렇게 하면서 quantum에서 예상치 못하는 결과가 발생합니다.

그중에 하나가(overlapping_ip 문제는 별도의 문제!) instance가 처음 부팅할 때 보내는 meta data request의 패킷이 metadata api 서버로는 잘 가지만, 다시 돌아올 경로가 없습니다.

Network Node --> Controller 노드까지 경로를 보면, metadata api가 public_ip이기 때문에 instance에서는 잘 접속이 됩니다. 하지만 패킷이 다시 돌아갈 instance의 주소는 private 네트워크이고 api-host에서 다시 돌아간 패킷은 external-router에서 내부 routing 경로가 아니라고 세상 밖으로 던져져 버립니다.

그래서 metadata connection이 맺여지지 않습니다.

metadata를 가져오지 못하면, 다른 것 다 제쳐두고라도 instance에 ssh keypair를 설정할 수 없기 때문에 가상 머신에 ssh 할 수 없는... 즉 만들었지만 접근하지 못하는 오직 ping만 할 수 있는 상황이 발생합니다. ㅎㅎ

그래서 external-router에서 내부 network으로 routing 틀어줘야 합니다.

어쨌든 그래서 아래처럼 quantum l3_agent를 소스를 기반으로 간단하게 routing 경로를 잡는 agent를 만들었고, 그 일을 하는 소스는 아래와 같습니다. 하나도 정리안된.. 막무가내 소스입니다. ㅎㅎ

tenant의 external router로 연결된 router에 대해서 해당 tenant의 subnet으로 가는 경로를 그 tenant에 기본으로 할당된 public ip로 잡아주는 것이죠. 그러면 해당 l3 name space에서는 적당히 알아서 그 instance로 보내줍니다.

def do_single_loop(self):
    routers = self.qclient.list_routers()['routers'];
    ports = self.qclient.list_ports()

    route_info = []
    for r in routers:
        # get tenant's subnet
        subnet = self.qclient.list_ports(device_id=r['id'],
                device_owner='network:router_interface')['ports'][0]['fixed_ips'][0]['subnet_id']
        cidr = self.qclient.show_subnet(subnet=subnet)['subnet']['cidr']

        # get the tenant's gw
        fixed_ip = self.qclient.list_ports(device_id=r['id'],
                device_owner='network:router_gateway')['ports'][0]['fixed_ips'][0]['ip_address']
        route_info.append((cidr, fixed_ip))

    # get current route info
    old_routes = [x.split() for x in subprocess.check_output(['ip', 'route']).splitlines()[2:] if ('via' in x and 'default' not in x) ]
    old_routes = [(x[0], x[2]) for x in old_routes]

    # add new routing info
    for cidr, fixed_ip in set(route_info) - set(old_routes):
        subprocess.check_call(['route', 'add', '-net', cidr, 'gw', fixed_ip])

    # remove routing info
    for cidr, fixed_ip in set(old_routes) - set(route_info):
            subprocess.check_call(['route', 'del', '-net', cidr, 'gw', fixed_ip])

그리고 더 해야하는 게, openstack에서 외부 명령을 실행하는 것은 rootwarp을 이용해서 사용하도록 되어있습니다. 아무래도 보안상 이유겠지요. 근데 지금은 우선 잘 되는지 테스트 하기 위해서 그거 신경 안썻습니다. 나중에 시간나면 정리 합니다~ ㅎㅎ

마지막으로 소스 위치~
https://github.com/whitekid/metadata_route_agent


twisted를 이용한 심플한 dns proxy: dnspost

Mac OSX의 resolver라는 기능이 있습니다. 간단히 말해서 특정 도메인에 해당하는 DNS 쿼리를 특정 DNS 서버에 요청하는 것이지요.. 뭐 일상생활에서는 필요없겠는데, 개발용으로 내부 네임서버를 돌리고 있는 경우에 가끔 유용하게 쓸 수 있습니다.

아래처럼 도메일별로 다른 서버에 DNS 쿼리가 가능하다는 것이죠.

  • *.dev.company.com --> 192.168.1.199
  • *.myteam.company.com -> 192.168.1.200
  • 나머지 --> 168.126.63.1

OSX에서는 resover를 사용해서 하고.. 또한 우리 회사 개발자도 OSX를 좋아해서 이 기능을 쓰라고 그러고, 다른 OS는 별로 관심이 없습니다.(OSX가 기본 개발 OS인양...). Ubuntu를 데스크탑으로 사용하는 제가 이상하게 소외받는 ㅎㅎ

그래서 목마른 사람이 우물을 판다고 python twisted name 라이브러리를 이용해서 간단히 뚝딱뚝딱 만들어 봤습니다. 로컬에서 네임서버 돌리고 이 것을 사용하면 됩니다.

https://github.com/whitekid/dnspost

Installation

$ apt-get install python-twisted-names
$ git clone https://github.com/whitekid/dnspost.git
$ cd dnspost
# edit dnspost.conf listen_port
$ ./dnspost.py

Ubuntu/NetworkManager note

ubuntu desktop에서는 NetworkManager를 사용하고, NetworkManager에서는 dnsmasq를 사용하여 dns를 캐슁하면서 로컬에서 서비스 하고 있습니다. NetworkManager에서 dnsmasq가 상위 dns 쿼리할때 특정 포트로 쿼리할 수 있는 기능이 있다면 로컬에서 별도의 포트로 돌리고있는 dnspost로 설정하여 할 수 있지만, 그런 기능이 없기에 dnsmasq를 사용하지 않고 합니다.

disable dnsmasq

/etc/NetworkManager/NetworkManager.conf에서 dns=dnsmasq라는 라인을 삭제합니다

#dns=dnsmasq

NetworkManager restart

$ service network-manager restart

px ax | grep dnsmasq로 dnsmasq가 없는지 확인합니다.

set nameserver to localhost

네트워크 연결 설정에서 DNS 서버를 127.0.0.1로 변경합니다. 설정을 변경한 후 /etc/resolv.conf에는 설정이 없거나 127.0.0.1로 설정이 됩니다.

만일 반영이 안되면 network-manager를 다시 시작합니다.

$ service network-manager restart

register dnspost upstart service

$ cp dnspost.conf /etc/init/dnspost.conf
$ ln -s /lib/upstart-job /etc/init.d/dnspost
$ service dnspost start

test

$ dig daum.net localhost

잘 동작하는 것을 확인하였다면 이제 설정파일 적당히 바꿔서 도메인별로 DNS Server를 다르게 사용해보시기 바랍니다. - 끝 -


TimeSync: Windows7에서 안되는 문제

SyncTime 이라는 컴퓨터의 시간을 타입서버와 맞춰주는 개인적으로 만든 프로그램이 있었지요.

그런데 Windows 7으로 업그레이드한 후 작동을 하지 않습니다. 아주아주 간단한 프로그램인데 말입니다.

뒤져보니 SetLocalTime API가 SE_SYSTEMTIME_NAME 이라는 권한을 필요하다고 하네요. Windows Vista 이후 부터는 시간이라는 것도 시스템 자원이라는 개념으로 들어갔다는군요.

그래서 이 권한을 획득하고 처리했는데... 안됩니다. 뭐냐고.. Indy에서도 확인해보니 SE_SYSTEMTIME_NAME 권한을 획득하고 처리하고 있지요. 하라는데로 다 했는데 SetLocalTime 호출하면 오류가 납니다.

뒤져보니 사용자가 SetLocalTime을 호출할 이유가 없다라는 답도 있었지만, 필요에 따라서는 시간을 맞춰줄 필요가 있는데 말입니다. 위 링크에 이야기 언급한 서비스로 만드는건 배보다 배꼽이 큽니다.

생각하다가 그냥 서비스까지 동원해서 작업해버리기로 했습니다. 덕분에 설치하는 것이 조금 복잡해 지긴 했습니다. 이렇게 복잡해지니 단순 실행파일만 가지고는 안되서 셋업본으로 만들었습니다.

설치 및 다운로드는 TimeSync 페이지를 보세요.


pgdbx4 0.4 Release: dbExpress driver for PostgreSQL

그간 방치해뒀던 PostgreSQL용 dbExpress 드라이버를 오늘 좀 수정했습니다.

  • Boolean 형태가 잘 안가져오던 문제
  • BYTEA/TEXT 타입이 Next를 해도 다음 row를 가져오지 못하던 문제
  • 기타 기억안나는 자잘한 것...

자세한 내용은 pgexp4 페이지를 참고하세요.


TLinkLabel에 WordWrap 적용하기

TLinkLabel은 사용하기 따라서 상당히 유용합니다. 근디 WordWrap이 없군요. 이게 없으니깐 AutoSize를 줘도 한줄로 길게 쭈욱 나와버립니다. TLabel의 WordWrap과 같이 동작하면 참 편하겠는데 말이지요. 어찌 되었건 아래처럼 MaxWidth 변수가 사용되는 부분만 몇줄 추가하면 원하는데로 됩니다.

procedure TnxLinkLabel.AdjustBounds;
var
  DC: HDC;
  SaveFont: HFont;
  TextSize: TSize;
  Parsed: string;
  MaxWidth: Integer;
begin
  if not (csLoading in ComponentState) and FAutoSize then
  begin
    if CheckWin32Version(6) and UseThemes then
    begin
      if HandleAllocated then
      begin
        if FWordWrap then
          MaxWidth := ClientWidth else
          MaxWidth := MaxInt;

        SendGetStructMessage(Handle, LM_GETIDEALSIZE, MaxWidth, TextSize);
        SetBounds(Left, Top, TextSize.cx + (GetSystemMetrics(SM_CXBORDER) * 4),
          TextSize.cy + (GetSystemMetrics(SM_CYBORDER) * 4));
      end;
    end
    else

TCustomLinkLabel.AdjustBounds를 단 몇 줄 수정하면 되는데, AdjustBounds가 virtual로만 되어있어도 편한데 그게 아니라서 이렇게 수정만 해서는 안됩니다. 그렇다고 vcl을 직접 다시 컴파일하기도 그렇고..

결국은 TCustomLinkLabel, TLinkLabel을 모두 몽땅 가져다가 새 이름으로 콤포넌트를 등록해버렸군요. 찝찝하지만 Go~


wslib v2

wslib v2가 릴리스 되었습니다.

TwsListView에서 컬럼을 클릭하면 자동으로 정렬하는 옵션을 추가했네요. 리스트뷰 정렬에 이제 코딩이 하나도 필요없습니다.

덧) 버전을 r2에서 v2로 변경했습니다. Google code 위키에서 r2를 SubVersion revision으로 인식하고 바로 거기로 링크를 해버리네요.


시간 동기화하기

월요일 아침엔 회의가 있습니다. 컴퓨터 시간으로 확인하고 가보니.. 헉. . 지각입니다. 이놈의 컴퓨터 시간이 늦어진거죠. 뭔 이런 일이.. 저기 있는 아날로그 시계는 정확한데, 항상 앞에두고 보는 시계가 부정확합니다.

그래서 시간 동기화하는 툴 만들었습니다. Indy를 이용하니 소스도 23줄 밖에 안됩니다. 뭐 Indy가 다하니깐요.

program TimeSync;

uses
  Windows,
  SysUtils,
  IdSNTP;

{$R *.res}

begin
  try
    with TIdSNTP.Create(nil) do
    try
      Host := '2.kr.pool.ntp.org';
      SyncTime;
    finally
      Free;
    end;
  except
    on E: Exception do
      MessageBox(0, PChar(E.Message), 'Error', MB_ICONEXCLAMATION);
  end;
end.

시작 프로그램에 등록해야겠습니다.

추가: 10.11.02

Window Vista, Windows 7에서는 동작하지 않습니다. MSDN에 보면 SetLocalTime이 SE_SYSTEMTIME_NAME 권한이 필요하다고 되어있지요. 그래서 그렇게 해주고 했는데 안됩니다. ㅡㅡ, 그래서 Indy 소스도 뒤져봤는데 Indy도 SE_SYSTEMTIME_NAME 권한을 획득하고 처리하고 있습니다. 그래도 안됩니다.

결국 관리자 권한에서 실행하는 수 밖에 없군요.

찾아보면서 본 글중에 하나는 "도데체 일반 사용자가 시간을 조종할 필요가 뭐가있냐?"라는 건데, 해주고픈 말은 야 이눔아 내 컴퓨터 시간이 잘못되어있다니깐!!!! 그래서 정확한 시간으로 맞추고 싶다고!!!!


  • Copyright © 1996-2010 Your wish is my command. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress