sqlalchemy 를 사용하면서 sql 문을 log 로 남기는 방법

1. create_engine() 의 전달인자 중에서 echo 값을 True 로 설정 

2. nova/db/sqlalchemy/session.py 66 라인에 값을 변경

engine_args = {

    "pool_recycle": FLAGS.sql_idle_timeout,

    "echo": True,

}



3. nova/db/sqlalchemy/models.py 878 라인의 값을 변경

engine = create_engine(FLAGS.sql_connection, echo=True)



4. nova/db/sqlalchemy/api.py 의 43 라인 변경

LOG = logging.getLogger("sqlalchemy.engine")

LOG.setLevel(logging.INFO)




5. nova.conf 값에 추가하여 처리할 수도 있음

# /etc/nova/nova.conf
--sql_echo=True

# nova/db/sqlalchemy/session.py
flags.DEFINE_bool('sql_echo', False, 'show sql log output')

# nova/db/sqlalchemy/session.py
engine_args = {

    "pool_recycle": FLAGS.sql_idle_timeout,

    "echo": FLAGS.sql_echo,

}

# nova/db/sqlalchemy/models.py
engine = create_engine(FLAGS.sql_connection, echo= FLAGS.sql_echo) 




 
반응형
Posted by seungkyua@gmail.com
,
I. Import 하기

from carrot import connection as carrot_connection
from carrot import messaging

II. Connection 객체 생성

params = dict(hostname=FLAGS.rabbit_host,
                    port=FLAGS.rabbit_port,
                    ssl=FLAGS.rabbit_use_ssl,
                    userid=FLAGS.rabbit_userid,
                    password=FLAGS.rabbit_password,
                    virtual_host=FLAGS.rabbit_virtual_host)

connection = carrot_connection.BrokerConnection(params);

III. Consumer 생성

consumer = messaging.Consumer( connection=self,
                                                  topic=topic,
                                                  proxy=proxy)

IV. Sample (http://nathanborror.com/posts/2009/may/20/working-django-and-rabbitmq/)

########## Set global variables ###################

AMQP_SERVER = 'localhost'
AMQP_PORT = 5672
AMQP_USER = 'guest'
AMQP_PASSWORD = 'guest'
AMQP_VHOST = '/'

########## Create a consumer ###################

>>> from flopsy import Connection, Consumer
>>> consumer = Consumer(connection=Connection())
>>> consumer.declare(queue='books', exchange='readernaut', routing_key='importer', auto_delete=False)

>>> def message_callback(message):
...     print 'Recieved: ' + message.body
...     consumer.channel.basic_ack(message.delivery_tag)
>>>
>>> consumer.register(message_callback)
>>> consumer.wait()


########## Create a publisher ###################

>>> from flopsy import Connection, Publisher
>>> publisher = Publisher(connection=Connection(), exchange='readernaut', routing_key='importer')
>>> publisher.publish('Test message!')
>>> publisher.close()



[ Pool 사용 ]

1. Publisher 가 cast 로 호출할 때 pools.Pool을 사용 (Connection 을 Pool로 연결)

from eventlet import pools

class Pool(pools.Pool):
    def create(self):
        LOG.debug('Pool creating new connection')
        return Connection.instance(new=True)

ConnectionPool = Pool(
        max_size=FLAGS.rpc_conn_pool_size,
        order_as_stack=True)

with ConnectionPool.item() as conn:
        publisher = DirectPublisher(connection=conn, msg_id=msg_id)

2. Consumer 가 메세지를 받을 때 GreenPool을 사용 (메소드를 Pool로 실행)

from eventlet import greenpool

self.pool = greenpool.GreenPool(FLAGS.rpc_thread_pool_size)
self.pool.spawn_n(self._process_data, msg_id, ctxt, method, args)

def _process_data(self, msg_id, ctxt, method, args):
...
 
3. Consumer 를 Thread로 변경하여 실행을 분기시키고자 할 때 eventlet.spawn을 사용
    - 코드를 wait() block 없이 계속 실행
    - 해당 Thread 가 return 값으로 넘어옮

import eventlet

self._rpc_consumer_thread = eventlet.spawn(_consumer_thread)
 
4. Report 와 같이 내부 LoopingCall 을 분기시켜 실행하고자 할 때 eventlet.greenthread 를 사용

from eventlet import greenthread

def _inner():
    ...
    greenthread.sleep(interval)
    ...

greenthread.spawn(_inner)




[ 용어 정리 ]
- queue      : Queue 이름을 의미
- exchange : Queue 와 Bind 하기 위한 exchange 이름을 의미
- exchange_type :
    . direct  : routing_key 가 정확하게 매칭되어야 함
    . topic   : routing_key 를 패턴 매칭으로 사용 가능
    . fanout : routing_key 가 필요 없이 모두 통신
- routing_key : Key 이름에 해당하는 Queue 에만 메세지를 보낼 수 있음




반응형
Posted by seungkyua@gmail.com
,

I. import 모듈

import eventlet.patcher
eventlet.patcher.monkey_patch()

import eventlet.db_pool
import sqlalchemy.orm
import sqlalchemy.pool

try:
    import MySQLdb
except ImportError:
    MySQLdb = None

II. orm sessionmaker 함수를 통한 session 생성

session = sqlalchemy.orm.sessionmaker(bind=engine,
                                                          autocommit=autocommit,
                                                          expire_on_commit=expire_on_commit)

III. sessionmaker의 첫번째 인수, bind 를 하기 위한 engine 을 생성하는 방법

engine = sqlalchemy.create_engine(FLAGS.sql_connection, **engine_args)

IV. create_engine을 하기 위한 engine_args dict 변수를 만드는 방법

engine_args = {
    "pool_recycle": FLAGS.sql_idle_timeout,
    "echo": False,
}
engine_args["pool_size"] = FLAGS.sql_max_pool_size
engine_args["pool_timeout"] = FLAGS.sql_pool_timeout
engine_args["creator"] = creator.create

V. creator (Connection Pool) 를 구하는 방법

creator = eventlet.db_pool.ConnectionPool(MySQLdb, **pool_args)

VI. ConnectionPool을 구하기 위한 pool_args 변수를 만드는 방법

# sqlalchemy.engine.url.make_url 을 이용하면 url 을 가지고 dict 형태로 변환이 가능하다.
connection_dict = sqlalchemy.engine.url.make_url(FLAGS.sql_connection)

pool_args = {
        "db": connection_dict.database,
        "passwd": password,
        "host": connection_dict.host,
        "user": connection_dict.username,
        "min_size": FLAGS.sql_min_pool_size,
        "max_size": FLAGS.sql_max_pool_size,
        "max_idle": FLAGS.sql_idle_timeout,
}





















 

반응형
Posted by seungkyua@gmail.com
,
[ context ]
{'request_id': 'd3f06598-456a-41d4-8b64-0f363f1c881d',
  'user_id': 'test_user_id',
  'roles': [],
  'timestamp': '2011-10-21T09:21:40.225901',
  'is_admin': True,
  'auth_token': None,
  'project_id': 'test_project',
  'remote_address': '127.0.0.1',
  'read_deleted': False,
  'strategy': 'noauth'
}


[ body ]
{'server': {'name': 'ahn1',
                'imageRef': '3', 
                'key_name': None, 
                'flavorRef': '2', 
                'max_count': 1, 
                'min_count': 1
               }
}

* 'server' 에 더 추가될 수 있는 내용
'server': {'personality':
              'config_drive':
              'security_groups':
              'networks':
              'blob':
              'key_name':
              'user_data':
              'availability_zone':
              'reservation_id':
             }



[ image_meta ]
{'status': 'active',
 'properties': {'kernel_id': '2', 'ramdisk_id': '1'},
 'name': 'lucid_ami',
 'deleted': False,
 'container_format': 'ami',
 'created_at': '2011-10-17T23:30:45.570475',
 'disk_format': 'ami',
 'updated_at': '2011-10-17T23:30:50.942699',
 'id': 3,
 'min_disk': '0',
 'location': 'file:///var/lib/glance/images/3',
 'checksum': 'a36d714c27b2a0eabd2e32289ec70800',
 'owner': None,
 'is_public': True,
 'deleted_at': None,
 'min_ram': '0',
 'size': 524288000
}
 
반응형
Posted by seungkyua@gmail.com
,
Rackspace Nova Client 를 사용하여 API 서버에 호출하는 경로

1.  novaclient/shell.main() 이 entry point 임

2.  novaclient/v1_1/shell.do_boot() 를 호출
    - instance 생성시에 "nova boot ....." 처럼 호출하면 "do_" 를 붙힌 메소드가 호출된다.

3. novaclient/v1_1/client.py 를 이용하여 novaclient/v1_1/servers.ServerManager.create() 를 호출
    - novaclient/v1_1/servers.ServerManager 는 novaclient/v1_1/base.BootingManagerWithFind 를
      상속받았으므로 self._boot() 를 호출하면 novaclient/v1_1/base.BootingManagerWithFind._boot() 가 호출됨
    - novaclient/v1_1/base.BootingManagerWithFind._boot() 에서 self._create() 가 호출되면 
      상속받은 novaclient/v1_1/base.ManagerWithFind 에서 찾고 여기에 없으므로 그 위의 클래스인
      novaclient/v1_1/base.Manager._create() 를 호출

4. novaclient/client.post() -> novaclient/client.request() 를 호출하여 HTTP Request 를 던진다.
    - standard out 으로 print 하려면 환경변수에 NOVACLIENT_DEBUG 를 추가하면 된다.


[파일 호출 순서]
novaclient/shell.py -> novaclient/v1_1/shell.py -> novaclient/v1_1/client.py -> novaclient/v1_1/servers.py 
-> novaclient/v1_1/base.py -> novaclient/base.py -> novaclient/client.py



 
반응형
Posted by seungkyua@gmail.com
,
python 에서 argv 를 이용하여 args 를 동적으로 추가하고자 한다면 다음과 같이 사용

1. sys.argv[1:] 를 이용
   -  main 의 프로그램명을 제외한 cli 에서 입력한 argv 가 입력됨

2.  argparse.ArgumentParser.add_argument 를 이용하여 환경설정 값을 args 로 추가
반응형
Posted by seungkyua@gmail.com
,
일반적으로 노바의 로그는 /var/log/nova/nova-xxx.log 형태로 남는다.

/etc/nova/nova.conf 에 보면 logdir=/var/log/nova 로 되어 있어서 해당 디렉토리에 서비스 모듈명의 이름으로 로그가 남는데 이는 프로세스별로 로그를 만드는 것이다.

만약 사용자 정의의 로그를 만들고 싶으면 다음과 같이 수정한다.

# vi /usr/lib/pymodules/python2.6/nova/log.py

def setup():
...
    reset()
    _ask_setup_log()   // 추가
...
askLogger = logging.getLogger('nova.ask')
def _ask_setup_log():

    if FLAGS.logdir:

        logname = '%s.log' % (os.path.join(FLAGS.logdir, 'nova-ask'),)

        global askLogger

        askLogger = logging.getLogger('nova.ask')

        askLogger.propagate = 0

        askHandler = WatchedFileHandler(logname)

        askHandler.setFormatter(_formatter)

        askLogger.addHandler(askHandler)

 
# vi /usr/lib/pymodules/python2.6/nova/scheduler/chance.py

...
from nova import log as logging
...

    logging.askLogger.debug('********* %s, %s *************', context, topic)


이와 같이 수정하면 /var/log/nova/nova-ask.log 가 생성되며 어떤 프로세스에서 호출하던지 해당 로그에 남게 되어 있다.


novaclient 모듈에서 로그를 추가하고 싶으면 다음과 같이 하면 된다.

# vi /usr/lib/pymodules/python2.6/novaclient/log.py

import logging

from logging.handlers import WatchedFileHandler


logger = logging.getLogger('nova.client')

logger.setLevel(logging.DEBUG)

fh = WatchedFileHandler('/var/log/nova/nova-client.log')

formatter = logging.Formatter('%(asctime)s %(levelname)s %(name)s [-] %(message)s from (pid=%(process)d) %(funcName)s %(pathname)s:%(lineno)d')

fh.setFormatter(formatter)

logger.addHandler(fh)


# vi /usr/lib/pymodules/python2.6/novaclient/shell.py

...
from log import logger
...

logger.debug('******* shell.py called !! ****************')







 
반응형
Posted by seungkyua@gmail.com
,
Eclipse 에서 PHP SDK 를 설치하기위해서는 아래 플러그인 사이트에서 업데이트를 한다.

1. Software Update Site
    - PDT 를 update 하기 위해서 helios 사이트에서 Programming Languages -> PDT SDK Feature 를 설치한다.
        . http://download.eclipse.org/releases/helios/

    - 그런데 현재는 버그가 있군요.. 그래서 아래 사이트에서 설치해야 함..
        . name : PDT Update Site
        . URL : http://download.eclipse.org/tools/pdt/updates/2.2/milestones/

    - 3.0 은 설치가 안되던데.. 나중에 다시 테스트 
        . URL : http://ftp.daum.net/eclipse/tools/pdt/updates/3.0/milestones/
반응형
Posted by seungkyua@gmail.com
,
1. Virtual box 다운로드 및 설치
    http://www.virtualbox.org/wiki/Downloads

2. Vagrant 를 설치 후 이용하여 Virtual box 인스턴스 생성
     $> sudo gem update -- system

    RubyGems version 이 1.3.6 보다 낮아 에러가 난다면
    $> sudo gem install rubygems-update
    $> sudo update_rubygems

    $> sudo gem update -- system
    $> sudo gem install vagrant -- pre

    ※ Vagrant 를 체험하고 싶으면 아래와 같이 해볼 수 있다.
$> cd ~
$> vagrant box add lucid32 http://files.vagrantup.com/lucid32.box        ~/.vagrant/boxes/lucid32 디렉토리가 생김

만약 박스를 없애고 싶으면
$> vagrant box remove lucid32

$> mkdir OpenStack
$> cd OpenStack
$> mkdir vagrant
$> cd vagrant
$> vagrant init lucid32        -> Vagrant 파일이 생성됨
$> vagrant up                      -> ~/VirtualBox VMs 에 가상 서버가 생김

아직 ssh 는 가동되지 않았으므로 ssh 를 가동
$> vagrant ssh

ssh 접속이 실패하면 가상서버를 내렸다 다시 올린다. (버그가 있는 것 같음)

만약 가상서버를 내리 싶으면
$> vagrant destroy
    
3. Chef Recipes 를 받는다.
    $> cd ~
    $> git clone -v https://github.com/openstack/openstack-cookbooks openstack-cookbooks

4. Set Up Some Directories
    $> cd ~
    $> mkdir OpenStack
    $> cd OpenStack
    $> mkdir aptcache
    $> mkdir chef
    $> cd chef

5. chef-solo 기반으로 수행할 Vagrant file 을 받는다.
    chef 는 독립적으로 수행할 수 있는 chef-solo 방법과 chef server 를 설치하고 client 로 접속하여 설치하는 방법이 있다.

    $> curl -o Vagrantfile https://raw.github.com/gist/786945/solo.rb
    $> vi Vagrantfile
#aptdir = (ENV['APTCACHE'] or "#{ENV['HOME']}/aptcache/")
# 아래와 같이 수정
aptdir = (ENV['APTCACHE'] or "#{ENV['HOME']}/OpenStack/aptcache/") 

6. Running OpenStack Compute within a Vagrant Instance
    $> vagrant up

7. Virtual Machine 접속
    $> vagrant ssh
    $> sudo apt-get install euca2ools
    $> euca-add-keypair test > test.pem
    $> chmod 600 test.pem
    $> euca-run-instances -t m1.tiny -k test ami-tty
    $> ssh -i test.pem root@10.0.0.3

8. Virtual Machine 삭제
    $> vagrant destroy
    $> rm *.pem novarc






3. swift 다운로드
    http://www.openstack.org/projects/storage/ 

4. 도큐먼트 설치
    #> sudo easy_install -U sphinx              install Sphinx
    #> python setup.py build_sphinx           builds the document






 
반응형
Posted by seungkyua@gmail.com
,
1. Python 설치
    . http://www.python.org/download/ 

2. Pydev 설치
    . update site : http://pydev.org/updates
    . eclipse -> Window -> Preferences -> Interpreter-Python에서 New 에서  python.exe 의 경로를 찾아 선택

3. Python 환경변수 및 패스 설정
    . Windows
        환경변수명 : PYTHONPATH
        환경변수값 : %PYTHONPATH%;C\Python32
        패스추가    : C\Python32

    . Mac
        환경변수 추가 : export PYTHONPATH=/Library/Python/2.6

반응형
Posted by seungkyua@gmail.com
,