精华内容
下载资源
问答
  • Nova创建虚拟机流程解读.pdf
  • nova 创建虚拟机流程

    2015-08-19 11:21:06
    1 Nova创建虚机流程 Openstack创建虚拟机的整个流程如图1所示。前端horizon发送创建虚机的请求...图 1 nova创建虚拟机流程 1.1 Nova api Nova api接受到前端(horizon)发来的创建虚机的请求后,调用create(self, r

    1   Nova创建虚机流程

    Openstack创建虚拟机的整个流程如图1所示。前端horizon发送创建虚机的请求之后,novaapi接收请求,并作处理,详见1.1节。注:Nova scheduler在另外章节介绍。


    图 1 nova创建虚拟机流程

    1.1  Nova api

    Nova api接受到前端(horizon)发来的创建虚机的请求后,调用create(self, req, body)函数(/opt/stack/nova/nova/api/openstack/compute/servers.pyà1088)。该函数主要获取前端发来的body数据并解析,将相应参数传递给compute api(1.2节)。

    1.2  Compute api

    Compute api接受到请求之后,调用create函数。

    def create(self, context, instance_type,image_href, kernel_id=None, ramdisk_id=None, min_count=None, max_count=None, display_name=None,
                        display_description=None, key_name=None, key_data=None, security_group=None,availability_zone=None,  user_data=None,metadata=None,
                        injected_files=None, admin_password=None,               block_device_mapping=None, access_ip_v4=None,access_ip_v6=None, requested_networks=None,                         config_drive=None,auto_disk_config=None, scheduler_hints=None, iolimit=None, hypervisor=None
    ):

       “””

        代码位置:/opt/stack/nova/nova/compute/api.pyà749

    部分参数如下:

    display_name=test

    admin_password=123456

    image_href=66c50770-21a4-46ce-85ee-392f29b05081

    metadata={}

    injected_files=[]

    requested_networks={}

    min_count=1

    max_count=1

    instance_type ={'memory_mb': 512L, 'root_gb': 0L, 'deleted_at': None, 'name':u'm1.tiny'         , 'deleted': False,'created_at': None, 'ephemeral_gb': 0L, 'updated_at': None, 'disabled': False,'vcpus': 1L, 'extra_specs': {}, 'swap': 0L, 'rxtx_factor': 1.0, 'is_public':True, 'flavorid': u'1', 'vcpu_weight': None, 'id': 4L}

    ”””

    • 检查各种参数及配额

    _check_num_instances_quota(context, instance_type, min_count, max_count,hypervisor=hypervisor)

    _check_metadata_properties_quota(context, metadata)

    _check_injected_file_quota(context, injected_files)

    _check_requested_networks(context, requested_networks)

    •  获取镜像信息,检查flavor的ram,disk是否超出镜像规定的最小限额
      (image_service, image_id) = lance.get_remote_image_service(image_href)
      image = image_service.show(context, image_id)
      if instance_type['memory_mb'] < int(image.get('min_ram') or 0):
      raise exception
      if instance_type['root_gb'] < int(image.get('min_disk') or 0):
      raise exception
    • 将参数放入字典base_options={

    'vm_state': 'building',

    'ephemeral_gb': 0L,

    'access_ip_v6': None,

    'access_ip_v4': None,

    'kernel_id': 'adaf51fe-c235-40b6-8aa7-80216d42303c',

    'key_name': None,

    'ramdisk_id': 'f9216b02-8e27-44da-b159-8d64401a16f2',

    'instance_type_id': 4L,

    'user_data':u'IyEvYmluL2Jhc2gKdXNlcmFkZCAtbSByb290CnBhc3N3ZCByb290IDw8IEVPRgpyb290CnJvb3QKRU9GCnBhc3N3ZCByb290IDw8IEVPRgpyb290CnJvb3QKRU9GCg==',

    'vm_mode': '',

    'display_name': u'test',

    'config_drive_id': '',

    'reservation_id': 'r-yl00q2af','architecture': 'Unknown',

    'key_data': None, 'root_gb': 0L,

    'user_id': u'c94cf849c7a94174b18f516c8fe497ee', 'hypervisor':u'libvirt',

    'availability_zone': None,

    'launch_time': '2014-10-30T05:28:15Z',

    'metadata': {},

    'display_description': u'test',

    'memory_mb': 512L,

    'vcpus': 1L,

    'locked': False,

    'image_ref': u'66c50770-21a4-46ce-85ee-392f29b05081',

    'root_device_name': None,

    'power_state': 0,

    'progress': 0,

    'cdrom_active': False,

    'project_id': u'1ec9c7671c824b798fb9a028623aaccc',

    'config_drive': ''}


    •   利用base_options在数据库创建instance

      instance = self.create_db_entry_for_new_instance(context, instance_type,image, base_options, security_group, block_device_mapping)

    • rpc调用启动虚机(发请求到compute manger)

      self.scheduler_rpcapi.run_instance(context,request_spec=request_spec, admin_password=admin_password,injected_files=injected_files, requested_networks=requested_networks,is_first_time=True, filter_properties=filter_properties)

    1.3  Compute manager

    Computemanager收到run_instance的请求后,运行函数run_instance。该函数内部会调用_run_instance函数如下:

    def _run_instance(self,context, request_spec, filter_properties, requested_networks,                   injected_files,admin_password, is_first_time, instance):

    “””

    代码位置:/opt/stack/nova/nova/compute/manager.pyà510

    参数实际值:

    request_spec:={

    'block_device_mapping':[],

    'security_group': [u'default'],
    'instance_uuids': ['8383fb3d-7dcf-4203-b639- 14c617b55259']

    'instance_uuids': ['8383fb3d-7dcf-4203-b639- 14c617b55259']

    'instance_uuids': ['8383fb3d-7dcf-4203-b639- 14c617b55259']

    'image': {'status': 'active',

    'name':'cirros-test-image',

    'deleted':False, 

    'container_format':'ami',

    'created_at':'2014-10-30T04:21:05.000000',

    'disk_format': 'ami',

    'updated_at':'2014-10-30T04:21:09.000000',

    'properties': {'kernel_id':'adaf51fe-c235-40b6-8aa7-80216d42303c',

    'source': 'nova',

    'ramdisk_id':'f9216b02-8e27-44da-b159-8d64401a16f2'},

    'min_disk': 0,

    'min_ram': 0,

    'checksum':'2f81976cae15c16ef0010c51e3a6c163',

    'owner':'1ec9c7671c824b798fb9a028623aaccc',

    'is_public': True,

    'deleted_at': None,

    'id':'66c50770-21a4-46ce-85ee-392f29b05081', 'size': 25165824},

    'instance_type': {'memory_mb': 512L,

    'root_gb': 0L,

    'deleted_at': None,

    'name': u'm1.tiny',

    'deleted': False,

    'created_at': None,

    'ephemeral_gb': 0L,

    'updated_at': None,

    'disabled': False,

    'vcpus': 1L,

    'extra_specs': {},

    'swap': 0L,

    'rxtx_factor': 1.0,

    'is_public': True,

    'flavorid': u'1',

    'vcpu_weight': None,

    'id': 4L},

    'instance_properties': {'vm_state': 'building',

    'ephemeral_gb': 0L,

    'access_ip_v6': None,

    'access_ip_v4': None,

    'kernel_id': 'adaf51fe-c235-40b6-8aa7-80216d42303c',

    'key_name': None,

    'ramdisk_id':'f9216b02-8e27-44da-b159-8d64401a16f2', 'instance_type_id': 4L,

    'user_data':u'IyEvYmluL2Jhc2gKdXNlcmFkZCAtbSByb290CnBhc3N3ZCByb290IDw8IEVPRgpyb290CnJvb3QKRU9GCnBhc3N3ZCByb290IDw8IEVPRgpyb290CnJvb3QKRU9GCg==',

    'vm_mode': None,

    'display_name':u'test',

    'config_drive_id':'',

    'reservation_id':'r-yl00q2af',

    'os_type': None,

    'architecture': None,

    'key_data': None,

    'iolimit': None,

    'root_gb': 0L,

    'user_id':u'c94cf849c7a94174b18f516c8fe497ee',

    'hypervisor':u'libvirt',

    'availability_zone':None,

    'launch_time':'2014-10-30T05:28:15Z',

    'metadata': {},

    'display_description':u'test',

    'memory_mb': 512L,

    'vcpus': 1L,

    'locked': False,

    'image_ref':u'66c50770-21a4-46ce-85ee-392f29b05081', 'root_device_name': None,

    'power_state': 0,

    'auto_disk_config':None,

    'progress': 0,

    'cdrom_active':False,

    'project_id':  u'1ec9c7671c824b798fb9a028623aaccc',

    'config_drive': ''}

    }

    admin_password=123456

    injected_files=[]

    requested_networks={}

    ”””

    •  查看虚机是否存在

    self._check_instance_not_already_created(context, instance)

    • 查看镜像大小超过flavor规定最大值

    self._check_image_size(context, instance)

    • 更新虚机的状态(db)

    self._start_building(context, instance)

    • 分配网络,见1.4 network

    self._allocate_network

    network_info=self.network_api.allocate_for_instance(context,instance,vpn=is_vpn, requested_networks=requested_networks)

    •  孵化虚拟机,见1.5libvirt driver

    self.driver.spawn(context, instance, image_meta, network_info,    block_device_info, injected_files,admin_password)

    1.4  network

    1.4.1 network api

    networkapi收到compute manager发送的请求之后调用allocate_for_instance,增加一些参数,远程rpc调用将请求发送给network manager。

    def allocate_for_instance(self,context, instance, **kwargs):

        """代码位置:/opt/stack/nova/nova/network/api.pyà277

         Allocates all network structures for an instance.

        :returns: network info as fromget_instance_nw_info() below

        """

           args = kwargs

           args['instance_id'] = instance['id']

           args['instance_uuid'] = instance['uuid']

           args['project_id'] = instance['project_id']

           args['host'] = instance['host']

           args['rxtx_factor'] = instance['instance_type']['rxtx_factor']

           nw_info = rpc.call(context, FLAGS.network_topic,

                               {'method':'allocate_for_instance',

                                'args': args})

           return network_model.NetworkInfo.hydrate(nw_info)

    1.4.2 network manager

    networkmanager收到请求后,调用函数allocate_for_instance。

    def allocate_for_instance(self, context, **kwargs):

     """

    代码位置:/opt/stack/nova/nova/network/manager.pyàclass NetworkManagerà1063

      """

    • 从数据库获取所有网络networks

    注:该网络是在安装时,写入数据库的

    networks = self._get_networks_for_instance(admin_context, instance_id,project_id, requested_networks=requested_networks)à 1078

    本环境只有一个network

    {'bridge': u'br100',

    'vpn_public_port': None,

    'dhcp_start': u'10.1.0.2',

    'bridge_interface': u'eth0',

    'updated_at': None,

    'id': 1L,

    'cidr_v6': None,

    'deleted_at': None,

    'gateway':u'10.1.0.1',

    'rxtx_base': None,

    'uuid':u'e011b388-163b-4080-a083-bb63ebed7f6a',

    'label':u'private',

    'priority': None,

    'project_id': None,

    'netmask_v6': None,

    '_sa_instance_state': <sqlalchemy.orm.state.InstanceStateobject at 0x42c4790>,

    'deleted': False,

    'vlan': None,

    'broadcast':u'10.1.255.255',

    'netmask':u'255.255.0.0',

    'injected': False,

    'cidr':u'10.1.0.0/16',

    'vpn_public_address': None,

    'multi_host': True,

    'dns2': None,

    'dns1':u'8.8.4.4',

    'host': None,

    'gateway_v6': None,

    'vpn_private_address': None,

    'created_at':datetime.datetime(2014, 10, 30, 4, 22, 44)}

    • 分配mac地址

    self._allocate_mac_addresses(context, instance_uuid, networks)->1083

    mac为自动生成(address=utils.generate_mac_address),返回结果为vif

    {'uuid':'7344166b-e3ef-44be-80e3-ecfa5696cce8',

    'instance_uuid':u'90844617-d71f-474f-9cdf-35e244c846b0',

    'network_id':1L,

    'address':'fa:16:3e:76:b4:2f‘}

    •  分配fixed ip

    self._allocate_fixed_ips(admin_context, instance_id, host, networks,vpn=vpn, requested_networks=requested_networks)->1084

    allocate_fixed_ip(self, context, instance_id, network, **kwargs)à2124

    1)   从数据库(fixedip池)获取address,本例为10.1.0.2

    self.db.fixed_ip_associate_pool(context.elevated(),network['id'],instance_ref['uuid'])->2142)

    2)   从数据库获取网卡vif 信息

    self.db.virtual_interface_get_by_instance_and_network(context,instance_ref['uuid'],network['id'])->2148)

    3)   更新数据库,标示该fixed_ip被分配,对应网卡为vif

    注:macip写配置文件/opt/stack/data/nova/networks/nova-br100.conf

    values = {'allocated': True,'virtual_interface_id': vif['id']}

    self.db.fixed_ip_update(context,address, values)->2152

    4)   宿主机建立网络self._setup_network_on_host(context, network)à2153

    def_setup_network_on_host(self, context, network):à2055

    """

    功能:1.设置dhcp_serverip

              2.创建网桥,并绑定特定网卡

              3.设置iptables规则,并应用

    """

         #network['dhcp_server']= self._get_dhcp_ip(context, network)从数据库获取,若不存在则从fixedip池中获取。本例为10.1.0.3。

    try:

    fip = self.db.fixed_ip_get_by_network_host(context,network_id, host)

    return fip['address']

    except exception.FixedIpNotFoundForNetworkHost:

      elevated = context.elevated()

    return self.db.fixed_ip_associate_pool(elevated,network_id, host=host)

    #self.l3driver.initialize_gateway(network)

      /opt/stack/nova/nova/network/l3.py(101)initialize_gateway()

    def initialize_gateway(self,network_ref):

    mac_address = utils.generate_mac_address()#生成mac地址

    #network_ref['gateway']=10.1.0.1àgateway=True

    dev = linux_net.plug(network_ref, mac_address,

    gateway=(network_ref['gateway'] is not None))

    linux_net.initialize_gateway_device(dev, network_ref)

      /opt/stack/nova/nova/network/linux_net.py->1106

    def plug(self, network, mac_address, gateway=True):

        iface = FLAGS.flat_interface ornetwork['bridge_interface'] #iface=eth0

            LinuxBridgeInterfaceDriver.ensure_bridge(network['bridge'],

                                             iface, network, gateway)

        iptables_manager.apply()

      /opt/stack/nova/nova/network/linux_net.py->1168

    def ensure_bridge(_self, bridge, interface, net_attrs=None,gateway=True):

    # bridge=br100; interface=eth0, gateway=True

    if not _device_exists(bridge):#br100若不存在,则创建

               _execute('brctl', 'addbr', bridge, run_as_root=True)

               _execute('brctl', 'setfd', bridge, 0, run_as_root=True)

               _execute('brctl', 'stp', bridge, 'off', run_as_root=True)

               _execute('ip', 'link', 'set', bridge, 'up', run_as_root=True)

                 if interface:

               out, err = _execute('brctl', 'addif', bridge, interface, )#绑定网卡                               

               old_routes = []

                         #显示eth0route,并删除

               out, err = _execute('ip', 'route', 'show', 'dev', interface)

               for line in out.split('\n'):

                   fields = line.split()

                   if fields and 'via' in fields:

                       old_routes.append(fields)

                       _execute('ip', 'route', 'del', *fields, run_as_root=True)

                #eth0ip删除,并复制给br100

               out, err = _execute('ip', 'addr', 'show', 'dev', interface,)

               for line in out.split('\n'):

                   fields = line.split()

                   if fields and fields[0] == 'inet':

                       params = fields[1:-1]

                       _execute(*_ip_bridge_cmd('del', params, fields[-1]),

                       _execute(*_ip_bridge_cmd('add', params, bridge),

               for fields in old_routes:

                   _execute('ip', 'route', 'add', *fields, run_as_root=True)

                 #添加规则

            ipv4_filter =iptables_manager.ipv4['filter']

            if gateway:

                ipv4_filter.add_rule('FORWARD',

                                    '--in-interface %s -j ACCEPT' % bridge)

                ipv4_filter.add_rule('FORWARD',

                                    '--out-interface %s -j ACCEPT' % bridge)

    #self.driver.update_dhcp(context, dev, network)重启dhcpserver

    /usr/sbin/dnsmasq--strict-order --bind-interfaces

    --conf-file=/opt/stack/data/dnsmasq.conf--domain=novalocal

    --pid-file=/opt/stack/data/nova/networks/nova-br100.pid--listen-address=10.1.0.3 --except-interface=lo --dhcp-range=set:'private',10.1.0.2,static,120s--dhcp-lease-max=65536     --dhcp-hostsfile=/opt/stack/data/nova/networks/nova-br100.conf

    --dhcp-script=/opt/stack/nova/bin/nova-dhcpbridge --leasefile-ro

    • 获取分配给instance的networkinfo

    self.get_instance_nw_info(context, instance_id, instance_uuid,rxtx_factor, host)

    获得的network_info如下:

    [VIF(

     {'network':

         Network(

           {'bridge': u'br100',

            'subnets': [

              Subnet({‘ips’:[FixedIP({‘meta’: {},

                                 ‘version’: 4,

                                 ‘type’: u‘fixed’,

                                 ‘floating_ips': [],

                                 'address':u'10.1.0.2'})],

                     'version': 4,

                     'meta': {u'dhcp_server':u'10.1.0.3'},

                     'dns': [IP({'meta': {},'version': 4,

                             'type': u'dns','address': u'8.8.4.4'})],

                     'routes': [],

     'cidr': u'10.1.0.0/16',

     gateway': IP({'meta': {}, 'version': 4,

                'type': u'gateway',

                'address': u'10.1.0.1'})}),

              Subnet({'ips': [],

    'version': None,

    'meta': {u'dhcp_server': u'10.1.0.3'},

    'dns': [],

    'routes': [],

    'cidr': None,

    'gateway': IP({'meta': {}, 'version': None,

                'type': u'gateway',

                'address': None})})],

            'meta': {u'tenant_id': None,

    u'multi_host': True,

    u'should_create_bridge': True,

    u'bridge_interface': u'eth0'},

            'id':u'e011b388-163b-4080-a083-bb63ebed7f6a',

            'label': u'private'}),

         'meta': {},

         'id':u'99a3c937-1a0f-48f7-8015-166d7644e9a0',

         'address': u'fa:16:3e:5a:f4:23'})]


    1.4.3 nova network 总结


    1.  宿主机配置br100(eth0)ip地址为192.168.96.80

    auto br100

    iface br100 inet static

        address 192.168.96.80

        netmask 255.255.255.0

        gateway 192.168.96.254

        dns-nameservers114.114.114.114

    bridge-ports eth0

    2.  配置文件

    FIXED_RANGE=10.1.0.0/16

    FIXED_NETWORK_SIZE=65535

    3.  nova network 安装时,会执行以下命令,创建networks写入数据库。本例中,只有一个网络。

     if [ !"$FIXED_RANGE" = "" ]; then

          nova-manage network create private$FIXED_RANGE 1 $FIXED_NETWORK_SIZE

    { 'bridge': u'br100',

    'vpn_public_port': None,

    'dhcp_start': u'10.1.0.2',

    'bridge_interface': u'eth0',

    'updated_at': None,

    'id': 1L,

    'cidr_v6': None,

    'deleted_at': None,

    'gateway':u'10.1.0.1',

    'rxtx_base': None,

    'uuid':u'e011b388-163b-4080-a083-bb63ebed7f6a',

    'label':u'private',

    'priority': None,

    'project_id': None,

    'netmask_v6': None,

    '_sa_instance_state': <sqlalchemy.orm.state.InstanceStateobject at 0x42c4790>,

    'deleted': False,

    'vlan': None,

    'broadcast':u'10.1.255.255',

    'netmask':u'255.255.0.0',

    'injected': False,

    'cidr':u'10.1.0.0/16',

    'vpn_public_address': None,

    'multi_host': True,

    'dns2': None,

    'dns1':u'8.8.4.4',

    'host': None,

    'gateway_v6': None,

    'vpn_private_address': None,

    'created_at': datetime.datetime(2014, 10, 30,4, 22, 44)}

    4.  在创建第一个虚机时,会给宿主机br100分配一个在FIXED_RANGE之内的ip(10.1.0.3),该ip作为该宿主机上vmdhcpserver来分配ip地址。同时也作为vmdefault gateway,与外界通信。

    5.  给虚机分配网络时,自动生成mac地址,从数据库选择一个没有用过的fixedip(10.1.0.2),将mac:ip写入配置文件/opt/stack/data/nova/networks/nova-br100.confdhcpserver使用。

    6.  虚机向dhcp服务器发送请求时携带mac地址,dnsmasq收到请求后,将配置文件中对应mac地址的ip返回

    1.5  libvirt driver

    至此,新建的vm的所有数据信息(基本信息+网络)都已准备完毕。接下来就要调用libvirt的driver启动虚机了。调用的函数为spawn。

    def spawn(self, context, instance, image_meta, injected_files,admin_password, network_info=None, block_device_info=None):

    “””

    代码位置:/opt/stack/nova/nova/virt/libvirt/driver.pyà1245

    “””

    1.   转换成libvirt所需的xml

           xml = self.to_xml(instance, network_info, image_meta,block_device_info=block_device_info)

    生成的xml为

    <domain type="qemu">

     <uuid>b110ed3b-9cc3-4d30-b433-a71090166b2c</uuid>

     <name>instance-00000002</name>

     <memory>524288</memory>

      <vcpu>1</vcpu>

      <os>

    <type>hvm</type>

    <kernel>/opt/stack/data/nova/instances/instance-00000002/kernel</kernel>

    <initrd>/opt/stack/data/nova/instances/instance-00000002/ramdisk</initrd>

        <cmdline>root=/dev/vdaconsole=ttyS0</cmdline>

      </os>

      <features>

        <acpi/>

      </features>

      <clockoffset="utc"/>

      <devices>

        <disk type="file"device="cdrom">

          <drivername="qemu"/>

          <targetbus="ide" dev="hdb"/>

        </disk>

        <disk type="file"device="disk">

          <drivername="qemu" type="qcow2" cache="writeback"/>

          <source file="/opt/stack/data/nova/instances/instance-00000002/disk"/>

          <targetbus="virtio" dev="hda"/>

        </disk>

        <interfacetype="bridge">

          <macaddress="fa:16:3e:47:ef:94"/>

          <modeltype="virtio"/>

          <sourcebridge="br100"/>

          <filterreffilter="nova-instance-instance-00000002-fa163e47ef94">

            <parametername="IP" value="10.1.0.4"/>

            <parametername="DHCPSERVER" value="10.1.0.3"/>

            <parametername="PROJNET" value="10.1.0.0"/>

            <parametername="PROJMASK" value="255.255.0.0"/>

          </filterref>

        </interface>

        <serialtype="file">

          <source path="/opt/stack/data/nova/instances/instance-00000002/console.log"/>

        </serial>

        <serialtype="pty"/>

        <inputtype="tablet" bus="usb"/>

        <graphicstype="vnc" autoport="yes" keymap="en-us"listen="0.0.0.0"/>

        <video>

          <modeltype="vga"/>

        </video>

      </devices>

    </domain>

    2.   准备镜像(将镜像拷贝到宿主机)

    self._create_image(context, instance, xml, network_info=network_info, block_device_info=block_device_info,files=injected_files, admin_pass=admin_password)

    详细请见1.6

    3.   利用libvirt api创建domain,并将iptalbes规则应用到vm。

    self._create_domain_and_network(xml, instance, network_info,block_device_info)

    1)        self.plug_vifs(instance,network_info)

    2)        self.firewall_driver.setup_basic_filtering(instance,network_info)

          Basic_filter=[nova_base]

    3)        self.firewall_driver.prepare_instance_filter(instance,network_info)

    ²  ipv4_rules

    ²  ['-m state --state INVALID -jDROP', '-m state --state ESTABLISHED,RELATED -j ACCEPT', '-j $provider', u'-s10.1.0.3 -p udp --sport 67 --dport 68 -j ACCEPT', u'-s 10.1.0.0/16 -j ACCEPT',u'-j ACCEPT -p icmp -s 0.0.0.0/0', u'-j ACCEPT -p tcp --dport 80 -s 0.0.0.0/0',u'-j ACCEPT -p tcp --dport 22 -s 0.0.0.0/0', u'-j ACCEPT -p tcp --dport 3389 -s0.0.0.0/0', u'-j ACCEPT -p tcp --dport 50070 -s 0.0.0.0/0', u'-j ACCEPT -p tcp--dport 50030 -s 0.0.0.0/0', '-j $sg-fallback']

    4)        domain =self._create_domain(xml)

    5)        self.firewall_driver.apply_instance_filter(instance,network_info)

    6)        vm建成!!!!

    1.6  Image

    1.6.1 create_image

    libvirtdriver把libvirt_xml创建好之后,我们发现对应的kernel,ramdisk和disk文件还没有。这时候就要开始创建镜像了。具体流程如下:

    def _create_image(self, context, instance, libvirt_xml, suffix='',disk_images=None, network_info=None, block_device_info=None, files=None,admin_pass=None):

    “””

    代码位置:/opt/stack/nova/nova/virt/libvirt/driver.py 1428

    ”””

    1.  定义basepath函数

    def basepath(fname='', suffix=suffix):

       returnos.path.join(FLAGS.instances_path,

                       instance['name'],

                       fname + suffix)

       returnos.path.join(FLAGS.instances_path,

                       instance['name'],

                       fname + suffix)

    FLAGS.instance_path=/opt/stack/data/nova/instances

    2.  确保instance_path存在

    utils.ensure_tree(basepath(suffix=''))

    3.  将生成的libvirt_xml写入文件

    libvirt_utils.write_to_file(basepath('libvirt.xml'),libvirt_xml)

    /opt/stack/data/nova/instances/instance-0000000a/libvirt.xml

    4.  修改console.log权限和写文件(若没有则创建)

    /opt/stack/data/nova/instances/instance-0000000a/console.log

    5.  获取ramdisk,kernel和disk文件(详见1.6.2节相应方法)

    disk_images = {'image_id': instance['image_ref'],

                         'kernel_id': instance['kernel_id'],

                                 'ramdisk_id': instance['ramdisk_id']}

    • 获取kernel(调用imagebackend.py文件中Raw类相应的方法)

    注:libvirt_utils.fetch_image是从glance下载镜像

    raw('kernel').cache(fetch_func=libvirt_utils.fetch_image,

    context=context,

    filename=fname,

    image_id=disk_images['kernel_id'],

    user_id=instance['user_id'],

    project_id=instance['project_id'])

    fname =disk_images['kernel_id']->adaf51fe-c235-40b6-8aa7-80216d42303c

    • 获取ramdisk(调用imagebackend.py文件中Raw类相应的方法)

    raw('ramdisk').cache(fetch_func=libvirt_utils.fetch_image,

    context=context,

    filename=fname,

    image_id=disk_images['ramdisk_id'],

    user_id=instance['user_id'],

    project_id=instance['project_id'])

    fname = disk_images['ramdisk_id']->f9216b02-8e27-44da-b159-8d64401a16f2

    • 获取disk(调用imagebackend.py文件中Qcow2类相应的方法)

    image('disk').cache(fetch_func=libvirt_utils.fetch_image,

    context=context,

    filename=root_fname,

    size=size,

    image_id=disk_images['image_id'],

    user_id=instance['user_id'],

    project_id=instance['project_id'])

    root_fname = hashlib.sha1(str(disk_images['image_id'])).hexdigest()

    1.6.2 virt/libvirt/imagebackend

    该文件定义了基类Image,Raw和Qcow2为子类。基类Image定义cache方法,主要功能是生成base路径(如:/opt/stack/data/nova/instances/_base/adaf51fe-c235…7-0216d42303c),调用子类create_image方法创建镜像文件(kernel,ramdisk,disk)。

     

    注:子类的create_image方法第一个参数prepare_template被设置为基类Image中 cache的内部方法call_if_not_exists该方法判断target文件是否存在,若不存在则调用libvirt_utils.fetch_image(详见1.6.3fetch_image方法) 下载镜像文件。


    class Image(object):

    def cache(self, fetch_func, filename,size=None, *args, **kwargs)

    “””

    代码位置:/opt/stack/nova/nova/virt/libvirt/imagebackend.pyà105

    self.path=/opt/stack/data/nova/instances/instance-0000000c/kernel

    base=/opt/stack/data/nova/instances/_base/adaf51fe-c235-40b6-8aa7-0216d42303c

    ”””

    @utils.synchronized(filename,external=True, lock_path=self.lock_path)

    defcall_if_not_exists(target, *args, **kwargs):

    “””

    该方法作为子类中create_image方法的参数prepare_template

    作用是若target文件不存在,则调用fetch_fuc获取文件

    本例中fetch_fuc= libvirt_utils.fetch_image,即从glance下载镜像

    ”””

    if notos.path.exists(target):

                   fetch_func(target=target,*args, **kwargs)

    if not os.path.exists(self.path):

    base_dir= os.path.join(FLAGS.instances_path, '_base')

    if not os.path.exists(base_dir):

    utils.ensure_tree(base_dir)

    base = os.path.join(base_dir, filename)

    #调用子类的create_image方法,prepare_template=call_if_not_exists

    self.create_image(call_if_not_exists, base, size, *args,  **kwargs)

     

    class Raw(Image):

    def __init__(self,instance, name):

    super(Raw, self).__init__("file", "raw",is_block_dev=False)

    self.path=os.path.join(FLAGS.instances_path, instance, name)

    def create_image(self, prepare_template, base, size, *args, **kwargs):

    “””

    代码位置:/opt/stack/nova/nova/virt/libvirt/imagebackend.pyà139

    prepare_template = call_if_not_exists

    base=/opt/stack/data/nova/instances/_base/adaf51fe-c235-…6-8aa7-0216d42303c

    self.path=/opt/stack/data/nova/instances/instance-0000000c/kernel

    ”””

    @utils.synchronized(base,external=True, lock_path=self.lock_path)

    def copy_raw_image(base,target, size):

                “””

    该方法利用cp,将base目录下的文件拷贝到target

    ”””

    libvirt_utils.copy_image(base,target)à详见1.6.3copy_image方法

    if size:

    disk.extend(target, size)

    generating = 'image_id' not in kwargs

    if generating:

    #Generating image in place

    prepare_template(target=self.path, *args, **kwargs)

    else:

    #准备basekernelramdisk镜像,确保base目录下的文件存在

    prepare_template(target=base,*args, **kwargs)# call_if_not_exists

    with utils.remove_path_on_error(self.path):

    # base文件拷贝到instance目录下

    copy_raw_image(base,self.path, size)

    class Qcow2(Image):

    def __init__(self,instance, name):

    super(Qcow2, self).__init__("file","qcow2", is_block_dev=False)

    self.path=os.path.join(FLAGS.instances_path, instance, name)

    def create_image(self, prepare_template, base, size, *args, **kwargs):

    “””

    代码位置:/opt/stack/nova/nova/virt/libvirt/imagebackend.pyà163

    self.path=/opt/stack/data/nova/instances/instance-0000000c/disk

    base=/opt/stack/data/nova/instances/_base/dd0ce6ec1af…eef7867f1063c9b5b028db

    ”””

    @utils.synchronized(base, external=True,lock_path=self.lock_path)

    def copy_qcow2_image(base, target, size):

    “””

    该方法利用qemu-img命令创建镜像,并设置backing_file

    qemu-img create –f disk_format –o preallocation=metadata –obacking_file=base  target

    ”””

                qcow2_base = base

                if size:

                    size_gb = size / (1024 * 1024 *1024)

                    qcow2_base += '_%d' % size_gb

                    if notos.path.exists(qcow2_base):

                        withutils.remove_path_on_error(qcow2_base):

                           libvirt_utils.copy_image(base, qcow2_base)

                            disk.extend(qcow2_base,size)

               libvirt_utils.create_cow_image(qcow2_base,target) 

      ->详见1.6.3create_cow_image方法

    # 准备 base disk 镜像,确保 base 目录下的文件存在

    prepare_template(target=base, *args, **kwargs)

    withutils.remove_path_on_error(self.path):

    # 利用qemu-img命令创建disk文件,backing_filebase文件

    copy_qcow2_image(base,self.path, size)

    1.6.3 virt/libvirt/utils.py

    def fetch_image(context,target, image_id, user_id, project_id):

    “””

    代码位置:/opt/stack/nova/nova/virt/libvirt/utils.pyà397

    ”””

     

    #该函数调用/opt/stack/nova/nova/virt/images.py中的fetch_to_raw方法(见1.6.4节)

    images.fetch_to_raw(context, image_id, target, user_id, project_id)

    ….

    def copy_image(src, dest,host=None):

    “””

    代码位置:/opt/stack/nova/nova/virt/libvirt/utils.pyà215

    函数功能:利用cprsync命令拷贝镜像

    ”””

    if not host:

    execute('cp', src, dest)

    else:

           try:

             execute('rsync', '--sparse', '--compress', '--dry-run', src,dest)

           except exception.ProcessExecutionError:

              execute('scp',src, dest)

      else:

             execute('rsync', '--sparse', '--compress', src, dest)

    def create_cow_image(backing_file,path):

    “””

    代码位置:/opt/stack/nova/nova/virt/libvirt/utils.pyà84

    函数功能:调用qemu-img命令创建镜像文件

    ”””

    execute('qemu-img','create', '-f', 'qcow2', '-o preallocation=metadata', '-o',

             'backing_file=%s'% backing_file, path)

    1.6.4 virt/images.py

    def fetch_to_raw(context,image_href, path, user_id, project_id):

    “””

    代码位置:/opt/stack/nova/nova/virt/images.pyà75

    函数功能:调用fetch函数

    ”””

    path_tmp = "%s.part" % path

    fetch(context, image_href, path_tmp, user_id, project_id)

    def fetch(context,image_href, path, _user_id, _project_id):

    “””

    代码位置:/opt/stack/nova/nova/virt/images.pyà63

    函数功能:从glance下载镜像文件

    ”””

        (image_service, image_id) =glance.get_remote_image_service(context, image_href)

       with utils.remove_path_on_error(path):

           with open(path, "wb") as image_file:

               image_service.download(context, image_id, image_file)

    展开全文
  • 登录 | 注册 bingxx11的专栏 目录视图摘要视图订阅 2016攒课第二期之你听课我买单,快来攒你想听的课...Nova创建虚拟机实例过程简述 2014-


     

    Nova创建虚拟机实例过程简述

      3037人阅读  评论(0)  收藏  举报

    有了前面的一些基础之后,我们再来看一下,大家可能非常关系的一个问题,就是如何通过OpenStack创建一个虚拟机实例。本文注重结构性分析,细节性问题,请小伙伴们自己多思考撒,因为我也是正在边学Python,边看nova源码的,我的理解肯定会有错误的地方,也劳烦大神们,看到错误的时候,和小弟说一下,先谢了。



    1、nova-api  <文件位于/nova/api/openstackcompute/server.py>

          nova-api起到了一个Cloud Controller的作用,主要为所有的API查询提供了一个接口(比如Openstack API ,EC2 API),引发多数业务流程的活动(如运行一个实例),并实施一些政策(主要是配额检查)。

          因为今天我们主题是虚拟机实例的启动过程,所以,重点关注/nova/api/openstackcompute/server.py。找到类class Controller(wsgi.Controller):create()代码段,我们知道nova-api的作用就是对外提供标准REST接口的服务。下面的代码段,已经标注了很多内容,大家看一下即可。

    [python]  view plain copy
    1. #对外提供创建虚拟机实例的外部接口,nova-api.create()  
    2.     #其中req是整个http报文内容,body就是REST中传递过来的参数  
    3.     #整个方法的作用是将REST接口参数映射到内部接口compute-api.create()  
    4.     #比如非常重要的环节,将image-flavor的id转换成虚拟机具体配置信息instanc_type  
    5.     def create(self, req, body):  
    6.         """Creates a new server for a given user."""  
    7.         if not self.is_valid_body(body, 'server'):  
    8.             raise exc.HTTPUnprocessableEntity()  
    9.   
    10.         #A mapping object representing the string environment.   
    11.         #For example, environ['HOME'] is the pathname of your   
    12.         #home directory (on some platforms), and is equivalent to getenv("HOME") in C  
    13.           
    14.         #对下面两个参数的讨论,设计到webob等概念,需要在以后做专门的讲述  
    15.         #*****************经常会用到的两个参数***************  
    16.         context = req.environ['nova.context']  
    17.         server_dict = body['server']  
    18.         #*****************经常会用到的两个参数***************  


    nova-api的create方法作用是将REST接口参数映射到内部接口compute-api.create(),参数转换完成后,create最后会调用如下代码,转去调用comput-api
    [python]  view plain copy
    1. (instances, resv_id) = self.compute_api.create(context,  
    2.                            inst_type,  ###*****已经转换的flavor  
    3.                            image_uuid,  
    4.                            display_name=name,  
    5.                            display_description=name,  
    6.                            key_name=key_name,  
    7.                            metadata=server_dict.get('metadata', {}),  
    8.                            access_ip_v4=access_ip_v4,  
    9.                            access_ip_v6=access_ip_v6,  
    10.                            injected_files=injected_files,  
    11.                            admin_password=password,  
    12.                            min_count=min_count,  
    13.                            max_count=max_count,  
    14.                            requested_networks=requested_networks,  
    15.                            security_group=sg_names,  
    16.                            user_data=user_data,  
    17.                            availability_zone=availability_zone,  
    18.                            config_drive=config_drive,  
    19.                            block_device_mapping=block_device_mapping,  
    20.                            auto_disk_config=auto_disk_config,  
    21.                            scheduler_hints=scheduler_hints,  
    22.                            legacy_bdm=legacy_bdm)  


    2、compute-api 的处理过程

           compute-api的作用是对外提供了管理compute的api接口,外部模块通过这些接口完成对计算资源的操作。

           

    [python]  view plain copy
    1. #*********************************#compute-api下面的create()函数*******************************#  
    2.     @hooks.add_hook("create_instance")  
    3.     def create(self, context, instance_type,     #由/nova/api/compute/service.py的套餐id转换到这个type  
    4.                image_href, kernel_id=None, ramdisk_id=None,  
    5.                min_count=None, max_count=None,  
    6.                display_name=None, display_description=None,  
    7.                key_name=None, key_data=None, security_group=None,  
    8.                availability_zone=None, user_data=None, metadata=None,  
    9.                injected_files=None, admin_password=None,  
    10.                block_device_mapping=None, access_ip_v4=None,  
    11.                access_ip_v6=None, requested_networks=None, config_drive=None,  
    12.                auto_disk_config=None, scheduler_hints=None, legacy_bdm=True):  
    13.         """ 
    14.         Provision instances, sending instance information to the 
    15.         scheduler.  The scheduler will determine where the instance(s) 
    16.         go and will handle creating the DB entries. 
    17.              
    18.         Returns a tuple of (instances, reservation_id) 
    19.         """  
    20.         #policy是nova中一个资格验证机制  
    21.         self._check_create_policies(context, availability_zone,  
    22.                 requested_networks, block_device_mapping)  
    23.         #创建一个实例的函数,  
    24.         return self._create_instance(  
    25.                                context, instance_type,  
    26.                                image_href, kernel_id, ramdisk_id,  
    27.                                min_count, max_count,  
    28.                                display_name, display_description,  
    29.                                key_name, key_data, security_group,  
    30.                                availability_zone, user_data, metadata,  
    31.                                injected_files, admin_password,  
    32.                                access_ip_v4, access_ip_v6,  
    33.                                requested_networks, config_drive,  
    34.                                block_device_mapping, auto_disk_config,  
    35.                                scheduler_hints=scheduler_hints,  
    36.                                legacy_bdm=legacy_bdm)  


    我们看下上面的代码:a) 首先进行了能否创建实例的资格验证  b)再调用了_create_instance()方法


    3、在_create_instance()方法中,做的一些操作有,验证各种参数,如意套餐类型instance_type是否存在,租户配额限制检查等,没问题后,commit一下,确定资源的占用。为了简化问题,我大概描述一下该方法做的事情,具体小伙伴们看一下代码就知道了。

    完成上面的操作后,在_create_instance() 最后调用了 self.compute_task_api.build_instances(context,***)方法


    4、我们通过寻找compute_task_api,找到了这个其实conductor.ComputeTaskAPI()的一个对象。

    注:关于conductor的话,我们单独还会再讲,G版中开始添加了这个conductor,以前的版本是没有这个东西的。主要作用是隔离compute对数据库的直接操作。

    我们转到/nova/conductor/api.py文件下

    [python]  view plain copy
    1. #创建实例的调用  
    2.     def build_instances(self, context, instances, image, filter_properties,  
    3.             admin_password, injected_files, requested_networks,  
    4.             security_groups, block_device_mapping, legacy_bdm=True):  
    5.         self.conductor_compute_rpcapi.build_instances(context,  
    6.                 instances=instances, image=image,  
    7.                 filter_properties=filter_properties,  
    8.                 admin_password=admin_password, injected_files=injected_files,  
    9.                 requested_networks=requested_networks,  
    10.                 security_groups=security_groups,  
    11.                 block_device_mapping=block_device_mapping,  
    12.                 legacy_bdm=legacy_bdm)  

    通过上述代码,我们看到,compute调用了conductor的API接口,再调用了conductor的RpcAPi接口,转到 /nova/conductor/rpcapi.py看如下代码:
    [python]  view plain copy
    1. #创建虚拟机实例  
    2.     def build_instances(self, context, instances, image, filter_properties,  
    3.             admin_password, injected_files, requested_networks,  
    4.             security_groups, block_device_mapping, legacy_bdm=True):  
    5.         instances_p = [jsonutils.to_primitive(inst) for inst in instances]  
    6.         image_p = jsonutils.to_primitive(image)  
    7.           
    8.         cctxt = self.client.prepare(version='1.5')  
    9.           
    10.         cctxt.cast(context, 'build_instances',  
    11.                    instances=instances_p, image=image_p,  
    12.                    filter_properties=filter_properties,  
    13.                    admin_password=admin_password,  
    14.                    injected_files=injected_files,  
    15.                    requested_networks=requested_networks,  
    16.                    security_groups=security_groups%2
    展开全文
  • Nova创建虚拟机流程1

    Nova创建虚拟机流程1


    展开全文
  • 本节说明nova创建虚拟机的请求发送到openstack之后,nova是如何处理该条URL的请求,分析到处理的类。 nova对于URL请求的处理在上一篇博文中以刻画了简化版的模型,参考该模型,能够快速理解openstack中真实的处理...

     前面讲了很多nova restful的功能,无非是为本篇博文分析做铺垫。本节说明nova创建虚拟机的请求发送到openstack之后,nova是如何处理该条URL的请求,分析到处理的类。

    nova对于URL请求的处理在上一篇博文中以刻画了简化版的模型,参考该模型,能够快速理解openstack中真实的处理情景。

    首先来熟悉nova的代码

    openstack  nova的源码分布如下,其中比较重要的是nova文件夹,几乎所有的功能实现都是在这个文件夹下。

    WSGI服务器的实现。

    路径:/nova/service.py

     

    configure.ini配置文件

    路径:/etc/nova/api-paste.ini

    #############
    # OpenStack #
    #############
    
    [composite:osapi_compute]
    use = call:nova.api.openstack.urlmap:urlmap_factory
    /: oscomputeversions
    # v21 is an exactly feature match for v2, except it has more stringent
    # input validation on the wsgi surface (prevents fuzzing early on the
    # API). It also provides new features via API microversions which are
    # opt into for clients. Unaware clients will receive the same frozen
    # v2 API feature set, but with some relaxed validation
    #<-------------------------------------------->#
    #http://192.168.252.177:8000/v2.0
    #判断api的版本信息,也是IP地址之后的第一个路径
    #<-------------------------------------------->#
    /v2: openstack_compute_api_v21_legacy_v2_compatible
    /v2.1: openstack_compute_api_v21
    
    [composite:openstack_compute_api_v21]
    use = call:nova.api.auth:pipeline_factory_v21
    noauth2 = cors http_proxy_to_wsgi compute_req_id faultwrap sizelimit noauth2 osapi_compute_app_v21
    keystone = cors http_proxy_to_wsgi compute_req_id faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v21
    
    [composite:openstack_compute_api_v21_legacy_v2_compatible]
    use = call:nova.api.auth:pipeline_factory_v21
    noauth2 = cors http_proxy_to_wsgi compute_req_id faultwrap sizelimit noauth2 legacy_v2_compatible osapi_compute_app_v21
    keystone = cors http_proxy_to_wsgi compute_req_id faultwrap sizelimit authtoken keystonecontext legacy_v2_compatible osapi_compute_app_v21
    
    [filter:request_id]
    paste.filter_factory = oslo_middleware:RequestId.factory
    
    [filter:compute_req_id]
    paste.filter_factory = nova.api.compute_req_id:ComputeReqIdMiddleware.factory
    
    [filter:faultwrap]
    paste.filter_factory = nova.api.openstack:FaultWrapper.factory
    
    [filter:noauth2]
    paste.filter_factory = nova.api.openstack.auth:NoAuthMiddleware.factory
    
    [filter:sizelimit]
    paste.filter_factory = oslo_middleware:RequestBodySizeLimiter.factory
    
    [filter:http_proxy_to_wsgi]
    paste.filter_factory = oslo_middleware.http_proxy_to_wsgi:HTTPProxyToWSGI.factory
    
    [filter:legacy_v2_compatible]
    paste.filter_factory = nova.api.openstack:LegacyV2CompatibleWrapper.factory
    
    #<-------------------------------------------->#
    #最终到了应用的部分,osapi_compute_app_v21的实现在
    /nova/api/openstack/compute/__init__.py中
    #<-------------------------------------------->#
    [app:osapi_compute_app_v21]
    paste.app_factory = nova.api.openstack.compute:APIRouterV21.factory
    
    [pipeline:oscomputeversions]
    pipeline = faultwrap http_proxy_to_wsgi oscomputeversionapp
    
    [app:oscomputeversionapp]
    paste.app_factory = nova.api.openstack.compute.versions:Versions.factory
     

    configure.ini的分发策略是:

    /       --->  [composite:osapi_compute]
    /v2     --->  openstack_compute_api_v21_legacy_v2_compatible
    /v2.1   --->  openstack_compute_api_v21
    openstack_compute_api_v21_legacy_v2_compatible 的实现:
    根据配置文件,可以选择两中认证模式,分别是:
    keystone 的认证方法是: cors--> http_proxy_to_wsgi --> compute_req_id --> faultwrap 
    --> sizelimit --> authtoken --> keystonecontext -->
    --> legacy_v2_compatible---- osapi_compute_app_v21
    前面都是过滤,直到最后的osapi_compute_app_v21是处理函数。
    处理函数的实现:

     在nova/api/openstack/compute下的APIRouterV21.factory工厂方法中,所以下一步,会进入该方法。

    APIRouterV21.factory
    路径:/nova/api/openstack/compute/__init__.py


    该类是继承自:nova.api.openstack.APIRouterV21,功能实现在该类中。
    APIRouterV21
    路径:/nova/api/openstack/__init__.py

     这里实现了一个重要的URL和处理方法绑定功能,功能如同下面的函数。请求方法 + URL 绑定到对应的处理函数上,实现注册的功能。

    该类继承自 base_wsgi.Router,所以去该类上查看具体的实现。

     

    base_wsgi.Router

    路径:nova/wsgi.py

     看到这里就应该很熟悉了,mapper对象,RoutesMiddleware()函数,_dispatch()函数。

    mapper将请求URL解析,根据注册的方法和处理函数获取处理的类,然后将该类传递给_dispatch()函数。函数_dispatch获取处理的类的名称,

    然后判断是否为空,如果存在该类,则在return中调用该类的__call__方法。

    注:__call__()方法是python类中的一个方法。在函数返回当中不能返回一个对象,可以返回一个函数。所以__call__实现功能是在python类中调用该类的方法,变量

    实现一个函数的功能。

    在_disptach函数最后的返回中,调用了处理类的__call__方法。nova创建虚拟机过程中,就会调用Controller中的create方法,所以调用的就是下面的方法:

     

     

     

     

     

     

     

     

     









    转载于:https://www.cnblogs.com/goldsunshine/p/7777161.html

    展开全文
  • 先粗略了解一下nova创建虚拟机的四个核心模块 api服务:负责处理客户端发送的http请求,路由到具体调用函数(包括一些中间件处理,如鉴权) conductor服务:主要用于数据库的访问,为数据库访问提供安全保障,...
  • Nova创建虚拟机流程2 -scheduler
  • Nova创建虚拟机流程3-compute
  • Nova创建虚拟机流程解读

    千次阅读 2018-03-27 21:44:56
    一 介绍创建一个虚拟机至少需要指定的参数有3个:虚拟机名字,镜像,Flavor。执行“nova image-list”命令可以看到目前可用的虚拟机镜像。命令执行结果如下:[root@localhost ~(keystone_demo)]# nova image-list ...
  • Nova创建虚拟机流程2 本博客欢迎转发,但请保留原作者(@孔令贤HW)信息!内容系本人学习、研究和总结,如有雷同,实属荣幸! 本博客欢迎转发,但请保留原作者(@孔令贤HW)信息!内容系本人学习、研究和总结,...
  • openstack使用命令行nova创建虚拟机

    万次阅读 2018-06-29 16:23:44
    所以我们就只需要查出这些配置信息,然后就可以创建虚拟机了。说明一下,本人是利用公司里docker容器里部署的openstack,所以在创建之前,先用命令行进入相应容器中:docker exec -it -u 0 neutron-server /bin/bash...
  • NOVA 创建虚拟机流程

    千次阅读 2016-01-04 09:17:28
    当用户通过身份验证后,需要一个客户端发送创建请求,openstack现在提供两种客户端: (1) 网页交互界面horizon,通过勾选等方式选择参数后,点击启动按钮进行创建:     (2) 通过CLI命令行指令nova,以及...
  • nova创建虚拟机时资源的检测

    千次阅读 2017-02-24 09:01:42
    在通过/nova/compute/manager.py:ComputeManager中的_build_and_run_instance来创建虚拟机的时候,会通过claim机制来监视当前的资源是否够创建虚拟机  def _build_and_run_instance(self, context, instance, ...
  • nova部署虚拟机源码调用过程简要分析,从服务器段接收到服务请求开始,根据函数调用流程对虚拟机创建过程进行分析。
  • def _schedule_instances(self, context, request_spec, filter_properties): scheduler_utils.setup_instance_group(context, request_spec, filter_properties) # TODO(sbauza): Hydrate here the object until...
  • 管理员在cli命令行创建虚拟机的时候会输入大概一个这样的命令 nova boot --flavor FLAVOR --image IMAGE --nic net-id=XXX NAME 然后就输出我平时看起来像是nova show 就可以看出来的,但是仔细发现有几个属性上不...
  • 1、nova-api <文件位于/nova/api/openstackcompute/server.py> nova-api起到了一个Cloud ...因为今天我们主题是虚拟机实例的启动过程,所以,重点关注/nova/api/openstackcompute/server.py。找到类class Contr
  • 1. 背景需求 在openstack中,nova负责openstack虚拟机的生命周期的管理,neutron则负责虚拟机的网络管理工作,默认情况下,创建一台虚拟机nova会根据nova-scheduler调度算法,选择一台最合适的compute节点,同时...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,993
精华内容 3,197
关键字:

nova创建虚拟机