링 크 : /usr/lib/python2.7/dist-packages/nova
nova 에서 instance 를 생성할 때 호출되는 Sequence 흐름을 표현한다.
모듈별 흐름으로 보면 다음과 같다.
API -> COMPUTE -> RabbitMQ -> SCHEDULER -> RabbitMQ -> COMPUTE
1. api/openstack/servers.py -> create()
1-1. api/openstack/create_instance_helper.py -> create_instance()
- request 로 넘어온 값을 추출
- glance Image 서버에 접근할 수 있는 객체 생성
- glance 로 부터 image id, kernel id, ramdisk id 를 조회
1-1-1. compute/instance_types.py -> get_instance_type_by_flavor_id()
- db로 부터 instance type 을 조회
1-1-2. compute/api.py -> create()
- 넘어온 파라미터에 대한 체크
1-1-2-1. create_db_entry_for_new_instance()
1-1-2-1-1. self.db.security_group_get_by_name()
- db에서 security group name 으로 id를 조회
1-1-2-1-2. self.db.instance_create()
- instance 테이블에 기본 값만 추가하여 instance id 를 생성
1-1-2-1-3. self.db.instance_add_security_group()
- security_group_instance_association 테이블에 값을 추가
1-1-2-1-4. self._update_image_block_device_mapping()
- glance 에서 가져온 image 메타데이터 mappings 정보를 이용
1-1-2-1-4-1. self.db.block_device_mapping_update_or_create()
- 파라미터로 넘어온 mappings 값이 있으면
block_device_mapping 테이블에 저장
1-1-2-1-5. self._update_block_device_mapping()
- glance 에서 가져온 image 메타데이터 block_device_mappings
정보를 이용
1-1-2-1-5-1. self.db.block_device_mapping_update_or_create()
- 파라미터로 넘어온 mappings 값이 있으면
block_device_mapping 테이블에 저장
1-1-2-1-6. self._update_block_device_mapping()
- 파라미터로 넘어온 mappings 정보를 이용
1-1-2-1-6-1. self.db.block_device_mapping_update_or_create()
- 파라미터로 넘어온 mappings 값이 있으면
block_device_mapping 테이블에 저장
1-1-2-1-7. self.update()
1-1-2-1-7-1. self.db.instance_update()
- instances 테이블에 vm_state 와 task_state 값을
BUILDING, SCHEDULING 으로 수정
1-1-2-2. _ask_scheduler_to_create_instance()
1-1-2-2-1. rpc.cast(context,
- rpc.cast 로 scheduler 의 run_instance 메소드를 호출
2. scheduler/manager.py.SchedulerManager -> __getattr__()
- run_instance 메소드가 없으니 __getattr__ 메소드가 호출됨
2-1. _schedule()
2-1-1. scheduler/multi.py -> __getattr__()
- schedule_run_instance 메소드가 없으니 __getattr__ 메소드가 호출
2-1-1-1. scheduler/chance.py.ChanceScheduler -> schedule_run_instance()
- schedule_run_instance() 가 없어 AttributeError exception 이 발생
2-1-2. scheduler/multi.py -> schedule()
2-1-2-1. scheduler/chance.py.ChanceScheduler -> schedule()
2-1-3. rpc.cast(context,
- rpc.cast 로 compute 의 run_instance 메소드를 호출
3. compute/manager.py.ComputeManager -> run_instance()
3-1. self._run_instance()
3-1-1. self.db.instance_get()
- db 에서 instance 정보를 조회함
3-1-2. virt/libvirt/connection.py.LibvirtConnection -> list_instances()
- libvirt 를 이용하여 kvm 에서 기동중인 instance vm id 를 조회
- instance['name'] 이 kvm 에서 조회되는 vm id 임
3-1-3. self.db.instance_update()
- instances 테이블에 vm_state 와 task_state 를 BUILDING, NETWORKING 으로 변경
- FLAGS.stub_network 이 False 이면
3-1-4-1. self.db.instance_update()
- instances 테이블에 vm_state 와 task_state 를 BUILDING,
BLOCK_DEVICE_MAPPING으로 변경
3-1-5. self._setup_block_device_mapping()
3-1-5-1. self.db.block_device_mapping_get_all_by_instance()
- instances 테이블과 block_device_mapping 테이블을 조인하여 조회
- snapshot_id 값이 있고, volume_id 값이 없으면 아래가 호출됨
3-1-5-2. volume/apy.py.API -> create()
3-1-5-2-1. self.db.snapshot_get()
3-1-5-2-2. quota.py -> allowed_volumes()
3-1-5-2-3. self.db.volume_create()
- volumes 테이블에 추가, status, attach_status 는 creating,
detached 로 세팅
3-1-5-2-4. rpc.cast(context,
- rpc.cast 로 Volume 을 호출
3-1-5-3. volume/manager.py.VolumeManager -> create_volume()
3-1-5-3-1. self.db.volume_get()
- volumes 테이블 정보 조회
3-1-5-3-2. self.db.volume_update()
- volumes 테이블 host colume 에 떠있는 host 값 저장
- snapshot_id 가 없으면 아래가 호출
3-1-5-3-3. volume.san.py.HpSanISCSIDriver -> create_volume()
- snapshot_id 가 있으면 아래가 호출
3-1-5-3-4. self.db.snapshot_get()
3-1-5-3-5. volume.san.py.HpSanISCSIDriver ->
create_volume_from_snapshot()
- iSCSI 를 노출
3-1-5-3-6. volume.san.py.HpSanISCSIDriver -> create_export()
3-1-5-3-7. self.db.volume_update()
- volumes 테이블의 status, launched_at 을 available,
utils.py -> utcnow() 로 수정
3-1-5-4. volume/apy.py.API -> wait_creation()
- greenthread.sleep(1) 을 호출하여 volumes 테이블의 status 를 체킹
3-1-5-5. self.db.block_device_mapping_update()
- block_device_mapping 테이블의 volume_id 값을 volumes 테이블의 id 로 세팅
3-1-5-6. volume/apy.py.API -> check_attach()
- volumes 테이블을 조회하여 status 가 available 인지 체크
3-1-5-7. self._attach_volume_boot()
3-1-5-7-1. volume/apy.py.API -> check_attach()
3-1-5-7-2. volume/manager.py.VolumeManager -> setup_compute_volume()
- volumes 테이블을 조회하여 host 값이 현재의 host 와 같고
FLAGS.use_local_volumes 값이 True 이면
3-1-5-7-2-1. volume.san.py.HpSanISCSIDriver -> local_path()
- 아니면
3-1-5-7-2-2. volume.driver.py.ISCSIDriver -> discover_volume()
- self._execute('iscsiadm', '-m',
'discovery',
'-p', volume['host'],
run_as_root=True)
- mount_device = ("/dev/disk/by-path/ip-
%s-iscsi-%s-lun-0" %
- export 가 안되면
FLAGS.num_iscsi_scan_tries만큼 반복
3-1-5-7-2-3. self.db.volume_attached()
- volumes 테이블의 status, mountpoint, attach_status 값을
in-use, device_name, attached 로 변경
3-1-6-1. self.db.instance_update()
- instances 테이블에 vm_state 와 task_state 를 BUILDING, SPAWNING 으로 변경
3-1-7. virt/libvirt/connection.py.LibvirtConnection -> spawn()
3-1-7-1. self.to_xml()
3-1-7-1-1. self._prepare_xml_info()
3-1-7-1-1-1. virt/driver.py -> block_device_info_get_mapping()
3-1-7-1-1-2. virt/libvirt/vif.py.LibvirtBridgeDriver -> plug()
- multi_host 가 False 이고 should_create_bridge 가 True
- should_create_vlan 이 True 이면
3-1-7-1-1-2-1. network/linux_net.py.
LinuxBridgeInterfaceDriver
-> ensure_vlan_bridge()
- should_create_vlan 이 False 이면
3-1-7-1-1-2-2. network/linux_net.py.
LinuxBridgeInterfaceDriver
-> ensure_bridge()
3-1-7-1-1-2-3. self._get_configurations()
3-1-7-1-1-3. compute/instance_types.py -> get_instance.type()
3-1-7-1-1-4. self._volume_in_mapping()
3-1-7-1-1-5. virt/driver.py -> block_device_info_get_ephemerals()
3-1-7-1-1-6. virt/driver.py -> block_device_info_get_root()
- root_device_name 이 있다면 그대로 데이터를 이용
- root_device_name 이 없다면
3-1-7-1-1-7. db.instance_update()
- local_device 가 True 라면
3-1-7-1-1-8. db.instance_update()
3-1-7-1-1-9. virt/driver.py -> block_device_info_get_swap()
- FLAGS.vnc_enabled and FLAGS.libvirt_type not in ('lxc', 'uml') 라면
xml_info['vncserver_host'] 및 xml_info['vnc_keymap'] 에 세팅
3-1-7-2. virt/libvirt/firewall.py.IptablesFirewallDriver -> setup_basic_filtering()
3-1-7-2-1. virt/libvirt/firewall.py.NWFilterFirewall -> setup_basic_filtering()
3-1-7-2-1-1. self._ensure_static_filters()
3-1-7-2-1-2. self._define_filter(self._filter_container())
3-1-7-2-2. self.refresh_provider_fw_rules()
3-1-7-2-2-1. self._do_refresh_provider_fw_rules()
3-1-7-2-2-1-1. self._purge_provider_fw_rules()
3-1-7-2-2-1-2. self._build_provider_fw_rules()
3-1-7-2-2-2-1. network/linux_net.py.IptablesManager
-> apply()
3-1-7-2-2-2-1-1. self._modify_rules()
3-1-7-3-1. self.add_filters_for_instance()
3-1-7-3-1-1. network/linux_net.py.IpTablesTable -> add_chain()
3-1-7-3-1-2. self._filters_for_instance()
3-1-7-3-1-3. self._add_filters()
3-1-7-3-1-4. self.instance_rules()
3-1-7-3-1-3. self._add_filters()
3-1-7-3-2. network/linux_net.py.IpTablesTable -> apply()
3-1-7-3-2-1. self._modify_rules()
3-1-7-4. self._create_image()
.......
3-1-7-5. self._create_new_domain()
.......
3-1-7-6. virt/libvirt/firewall.py.IptablesFirewallDriver -> apply_instance_filter()
pass
3-1-7-7. utils.py.LoopingCall(_wait_for_boot)
3-1-7-7-1. self.get_info()
- libvirt 로 부터 state를 주기적으로 받아와서 power_state.RUNNING 일 때
멈춤
3-1-7-8. utils.py.LoopingCall -> timer.start()
3-1-8. self._get_power_state()
........
3-1-9. self._instance_update()
3-1-9-1. self.db.instance_update()
- instances 테이블에 power_state, vm_state 와 task_state 를 libvirt를 조회하여
compute/power_state.py.변수, ACTIVE, None 으로 변경
3-1-10. utils.py -> usage_from_instance()
- instance 상태 변수를 넘겨서 usage_info dict 변수 값으로 변경하여 리턴
3-1-11. notifier/api.py -> notify('compute.%s' % self.host,
-
Jordan 11 2011/11/30 16:11
와이어에 단어가 마이클 조던 / 에어 조던 신발 부여 향해 경의, 그들은 특별한 인식 마이크와 자신에게 감사를 지불하기 위해 에어 조던 신발 23 버전을 생산한다고합니다.
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)
from carrot import messaging
II. Connection 객체 생성
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 생성
topic=topic,
proxy=proxy)
IV. Sample (http://nathanborror.com/posts/2009/may/20/working-django-and-rabbitmq/)
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로 연결)
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로 실행)
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 값으로 넘어옮
self._rpc_consumer_thread = eventlet.spawn(_consumer_thread)
4. Report 와 같이 내부 LoopingCall 을 분기시켜 실행하고자 할 때 eventlet.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 에만 메세지를 보낼 수 있음
-
Air Jordan 13 2011/11/21 11:51
나이키는 비트와 분위기를 수행할 수있는 압력하지만 나이키와 마이클은 결국 resounding 패션의 모든 비평가 답변을 것입니다 전에 에어 조단 XI의 출시를 주저되었을 수도 있습니다 기분이되어 있어야합니다
-
UGG Boots Sale 2011/11/21 11:51
나이키는 비트와 분위기를 수행할 수있는 압력하지만 나이키와 마이클은 결국 resounding 패션의 모든 비평가 답변을 것입니다 전에 에어 조단 XI의 출시를 주저되었을 수도 있습니다 기분이되어 있어야합니다
-
UGGs On Sale 2011/11/21 11:51
당신은 캐주얼과 파티 착용을 위해 부츠의 시원한 한쪽을 찾고있다면, 사용자의 요구에 높이 세련된 UGG의 고전을 확인하십시오.우수한 품질의 Ugg 부츠 입고 일년 내내 완벽한하고 거친 사용을 견딜 수 있습니다.
Python에서 MySQL Connection Pool을 활용할 수 있는 DB Session 구하기

I. import 모듈
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 생성
autocommit=autocommit,
expire_on_commit=expire_on_commit)
III. sessionmaker의 첫번째 인수, bind 를 하기 위한 engine 을 생성하는 방법
IV. create_engine을 하기 위한 engine_args dict 변수를 만드는 방법
"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) 를 구하는 방법
VI. ConnectionPool을 구하기 위한 pool_args 변수를 만드는 방법
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,
}
{'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
}
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
-
Christian Louboutin Shoes 2011/12/08 15:20
신발의 언급에서, 나는 많은 사람들이 최고 명품 신발 브랜드, 기독교 Louboutin 신발 생각할 수 있다고 생각합니다. 이러한 신발의 가장 독특한 특징은 붉은 옻칠 솔입니다.
1. sys.argv[1:] 를 이용
- main 의 프로그램명을 제외한 cli 에서 입력한 argv 가 입력됨
2. argparse.ArgumentParser.add_argument 를 이용하여 환경설정 값을 args 로 추가
/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 !! ****************')
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/
Prev
Rss Feed