'boot'에 해당되는 글 1건

  1. 2011.11.04 Nova Boot 순서

Nova Boot 순서

OpenStack/Nova 2011.11.04 18:00

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,
                                                               FLAGS.scheduler_topic,
                                                               {"method": "run_instance",
                                                                    "args": {"topic": FLAGS.compute_topic,
                                                                                "instance_id": instance_id,
                                                                                "request_spec": request_spec,
                                                                                "availability_zone": availability_zone,
                                                                                "admin_password": admin_password,
                                                                                "injected_files": injected_files,
                                                                                "requested_networks": requested_networks}})
                                                   - 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,
                                  db.queue_get_for(context, topic, host),
                                  {"method": method,
                                    "args": kwargs})
                     - 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-3. network/api.py.API -> allocate_for_instance()
                  3-1-3-1. rpc.call(context, FLAGS.network_topic,
                                    {'method': 'allocate_for_instance',
                                     'args': args})
           3-1-4. self._instance_update()
                     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,
                                                               FLAGS.scheduler_topic,
                                                               {"method": "create_volume",
                                                                "args": {"topic": FLAGS.volume_topic,
                                                                            "volume_id": volume['id'],
                                                                            "snapshot_id": snapshot_id}})
                                                  - 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()
                                                                      3-1-5-7-2-2-1. self._get_iscsi_properties()
                                                                                            - self._execute('iscsiadm', '-m',
                                                                                                                  'discovery',
                                                                                                                  '-t', 'sendtargets',
                                                                                                                  '-p', volume['host'],
                                                                                                                   run_as_root=True)
                                                                                             - mount_device = ("/dev/disk/by-path/ip-
                                                                                                                       %s-iscsi-%s-lun-0" %
                                                                                                           (iscsi_properties['target_portal'],
                                                                                                            iscsi_properties['target_iqn']))
                                                                                             - 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. self._instance_update()
                     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. self.iptables.apply()
                                                                     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. virt/libvirt/firewall.py.IptablesFirewallDriver -> prepare_instance_filter()
                                  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,
                                                       'compute.instance.create',
                                                       notifier.INFO, usage_info)



Posted by Kubernetes Korea co-leader seungkyua@gmail.com