nova list trace - dianaclarke/openstack-notes GitHub Wiki

Deep dive: What does nova list do under the hood?

  • Setup a simple DevStack standbox
  • Create an instance called instance-1 using the Dashboard
  • Configure the credentials you're going to use for the nova command line client
$ . openrc admin demo
  • List the instance using nova list
$ nova list
+--------------------------------------+------------+--------+------------+-------------+------------------+
| ID                                   | Name       | Status | Task State | Power State | Networks         |
+--------------------------------------+------------+--------+------------+-------------+------------------+
| 114ee114-cb45-4871-bab5-c877b301e4f5 | instance-1 | ACTIVE | -          | Running     | private=10.0.0.2 |
+--------------------------------------+------------+--------+------------+-------------+------------------+
  • Attach the debugger to the nova command line client by adding a import pdb; pdb.set_trace() right before line 830 in /usr/lib/python2.7/site-packages/novaclient/shell.py.
    ...
    import pdb; pdb.set_trace()
    args.func(self.cs, args)
    ...
  • Call nova list again, and this time step into the call. Note that you now know that nova list will call do_list().
$ nova list
> /usr/lib/python2.7/site-packages/novaclient/shell.py(832)main()
-> args.func(self.cs, args)
(Pdb) s
--Call--
> /usr/lib/python2.7/site-packages/novaclient/v2/shell.py(1227)do_list()
-> @cliutils.arg(
def do_list(cs, args):
    """List active servers."""

    ...

    servers = cs.servers.list(detailed=detailed,
                              search_opts=search_opts,
                              sort_keys=sort_keys,
                              sort_dirs=sort_dirs,
                              marker=args.marker,
                              limit=args.limit)
    
    ...
    def list(self, detailed=True, search_opts=None, marker=None, limit=None,
             sort_keys=None, sort_dirs=None):
           
        ...
   
            servers = self._list("/servers%s%s" % (detail, query_string),
                                 "servers")
        ...
    def _list(self, url, response_key, obj_class=None, body=None):

        ...
            _resp, body = self.api.client.get(url)
        ...
{
  "servers": [
    {
      "OS-DCF:diskConfig": "AUTO", 
      "OS-EXT-AZ:availability_zone": "nova", 
      "OS-EXT-SRV-ATTR:host": "localhost.localdomain", 
      "OS-EXT-SRV-ATTR:hostname": "instance-1", 
      "OS-EXT-SRV-ATTR:hypervisor_hostname": "localhost.localdomain", 
      "OS-EXT-SRV-ATTR:instance_name": "instance-00000001", 
      "OS-EXT-SRV-ATTR:kernel_id": "b9a04ceb-36e0-4056-8b17-d293562311c7", 
      "OS-EXT-SRV-ATTR:launch_index": 0, 
      "OS-EXT-SRV-ATTR:ramdisk_id": "d970dcc9-47e3-4955-b05b-e57fa7945cae", 
      "OS-EXT-SRV-ATTR:reservation_id": "r-joc3mzr4", 
      "OS-EXT-SRV-ATTR:root_device_name": "/dev/vda", 
      "OS-EXT-SRV-ATTR:user_data": null, 
      "OS-EXT-STS:power_state": 1, 
      "OS-EXT-STS:task_state": null, 
      "OS-EXT-STS:vm_state": "active", 
      "OS-SRV-USG:launched_at": "2015-09-28T17:45:34.000000", 
      "OS-SRV-USG:terminated_at": null, 
      "accessIPv4": "", 
      "accessIPv6": "", 
      "addresses": {
        "private": [
          {
            "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:07:de:2d", 
            "OS-EXT-IPS:type": "fixed", 
            "addr": "10.0.0.2", 
            "version": 4
          }
        ]
      }, 
      "config_drive": "True", 
      "created": "2015-09-28T17:45:06Z", 
      "flavor": {
        "id": "42", 
        "links": [
          {
            "href": "http://192.168.122.55:8774/76ec4597d1df4910bdd98f185e925065/flavors/42", 
            "rel": "bookmark"
          }
        ]
      }, 
      "hostId": "68810647eeee49257031df253fd2a8da0258a9e906293bfd5b5768df", 
      "id": "114ee114-cb45-4871-bab5-c877b301e4f5", 
      "image": {
        "id": "95cfe253-bb56-4776-8908-cd204ea64c9d", 
        "links": [
          {
            "href": "http://192.168.122.55:8774/76ec4597d1df4910bdd98f185e925065/images/95cfe253-bb56-4776-8908-cd204ea64c9d", 
            "rel": "bookmark"
          }
        ]
      }, 
      "key_name": null, 
      "links": [
        {
          "href": "http://192.168.122.55:8774/v2.1/76ec4597d1df4910bdd98f185e925065/servers/114ee114-cb45-4871-bab5-c877b301e4f5", 
          "rel": "self"
        }, 
        {
          "href": "http://192.168.122.55:8774/76ec4597d1df4910bdd98f185e925065/servers/114ee114-cb45-4871-bab5-c877b301e4f5", 
          "rel": "bookmark"
        }
      ], 
      "locked": false, 
      "metadata": {}, 
      "name": "instance-1", 
      "os-extended-volumes:volumes_attached": [], 
      "progress": 0, 
      "security_groups": [
        {
          "name": "default"
        }
      ], 
      "status": "ACTIVE", 
      "tenant_id": "76ec4597d1df4910bdd98f185e925065", 
      "updated": "2015-09-28T17:45:34Z", 
      "user_id": "0761a535feca411184d6cd0af20a99f8"
    }
  ]
}
  • That was all in the nova client, now let's look what happened in nova during the /servers/detail HTTP call. The /servers/detail URL dispatches to the ServersController in nova. In particular, it calls servers.ServersController.details().
    @extensions.expected_errors((400, 403))
    def detail(self, req):
        """Returns a list of server details for a given user."""
        context = req.environ['nova.context']
        authorize(context, action="detail")
        try:
            servers = self._get_servers(req, is_detail=True)
        except exception.Invalid as err:
            raise exc.HTTPBadRequest(explanation=err.format_message())
        return servers
            instance_list = self.compute_api.get_all(elevated or context,
                    search_opts=search_opts, limit=limit, marker=marker,
                    want_objects=True, expected_attrs=expected_attrs,
                    sort_keys=sort_keys, sort_dirs=sort_dirs)
    def get_all(self, context, search_opts=None, limit=None, marker=None,
                want_objects=False, expected_attrs=None, sort_keys=None,
                sort_dirs=None):
        ...
        inst_models = self._get_instances_by_filters(context, filters,
                limit=limit, marker=marker, expected_attrs=expected_attrs,
                sort_keys=sort_keys, sort_dirs=sort_dirs)
        ...

    def _get_instances_by_filters(self, context, filters,
                                  limit=None, marker=None, expected_attrs=None,
                                  sort_keys=None, sort_dirs=None):
        fields = ['metadata', 'system_metadata', 'info_cache',
                  'security_groups']
        if expected_attrs:
            fields.extend(expected_attrs)
        return objects.InstanceList.get_by_filters(
            context, filters=filters, limit=limit, marker=marker,
            expected_attrs=fields, sort_keys=sort_keys, sort_dirs=sort_dirs)
def instance_get_all_by_filters_sort(context, filters, limit=None,
                                     marker=None, columns_to_join=None,
                                     use_slave=False, sort_keys=None,
                                     sort_dirs=None):
    """Get all instances that match all filters sorted by multiple keys.

    sort_keys and sort_dirs must be a list of strings.
    """
    return IMPL.instance_get_all_by_filters_sort(
        context, filters, limit=limit, marker=marker,
        columns_to_join=columns_to_join, use_slave=use_slave,
        sort_keys=sort_keys, sort_dirs=sort_dirs)
@require_context
def instance_get_all_by_filters_sort(context, filters, limit=None, marker=None,
                                     columns_to_join=None, use_slave=False,
                                     sort_keys=None, sort_dirs=None):
    """Return instances that match all filters sorted the the given keys.
    Deleted instances will be returned by default, unless there's a filter that
    says otherwise.

    Depending on the name of a filter, matching for that filter is
    performed using either exact matching or as regular expression
    matching. Exact matching is applied for the following filters::

    |   ['project_id', 'user_id', 'image_ref',
    |    'vm_state', 'instance_type_id', 'uuid',
    |    'metadata', 'host', 'system_metadata']


    A third type of filter (also using exact matching), filters
    based on instance metadata tags when supplied under a special
    key named 'filter'::

    |   filters = {
    |       'filter': [
    |           {'name': 'tag-key', 'value': '<metakey>'},
    |           {'name': 'tag-value', 'value': '<metaval>'},
    |           {'name': 'tag:<metakey>', 'value': '<metaval>'}
    |       ]
    |   }

    Special keys are used to tweek the query further::

    |   'changes-since' - only return instances updated after
    |   'deleted' - only return (or exclude) deleted instances
    |   'soft_deleted' - modify behavior of 'deleted' to either
    |                    include or exclude instances whose
    |                    vm_state is SOFT_DELETED.

    A fourth type of filter (also using exact matching), filters
    based on instance tags (not metadata tags). There are two types
    of these tags:

    `tag` -- One or more strings that will be used to filter results
            in an AND expression.

    `tag-any` -- One or more strings that will be used to filter results in
            an OR expression.

    Tags should be represented as list::

    |    filters = {
    |        'tag': [some-tag, some-another-tag],
    |        'tag-any: [some-any-tag, some-another-any-tag]
    |    }

    """
    # NOTE(mriedem): If the limit is 0 there is no point in even going
    # to the database since nothing is going to be returned anyway.
    if limit == 0:
        return []

    sort_keys, sort_dirs = process_sort_params(sort_keys,
                                               sort_dirs,
                                               default_dir='desc')

    if CONF.database.slave_connection == '':
        use_slave = False

    session = get_session(use_slave=use_slave)

    if columns_to_join is None:
        columns_to_join_new = ['info_cache', 'security_groups']
        manual_joins = ['metadata', 'system_metadata']
    else:
        manual_joins, columns_to_join_new = (
            _manual_join_columns(columns_to_join))

    query_prefix = session.query(models.Instance)
    for column in columns_to_join_new:
        if 'extra.' in column:
            query_prefix = query_prefix.options(undefer(column))
        else:
            query_prefix = query_prefix.options(joinedload(column))

    # Note: order_by is done in the sqlalchemy.utils.py paginate_query(),
    # no need to do it here as well

    # Make a copy of the filters dictionary to use going forward, as we'll
    # be modifying it and we shouldn't affect the caller's use of it.
    filters = filters.copy()

    if 'changes-since' in filters:
        changes_since = timeutils.normalize_time(filters['changes-since'])
        query_prefix = query_prefix.\
                            filter(models.Instance.updated_at >= changes_since)

    deleted = False
    if 'deleted' in filters:
        # Instances can be soft or hard deleted and the query needs to
        # include or exclude both
        deleted = filters.pop('deleted')
        if deleted:
            if filters.pop('soft_deleted', True):
                delete = or_(
                    models.Instance.deleted == models.Instance.id,
                    models.Instance.vm_state == vm_states.SOFT_DELETED
                    )
                query_prefix = query_prefix.\
                    filter(delete)
            else:
                query_prefix = query_prefix.\
                    filter(models.Instance.deleted == models.Instance.id)
        else:
            query_prefix = query_prefix.\
                    filter_by(deleted=0)
            if not filters.pop('soft_deleted', False):
                # It would be better to have vm_state not be nullable
                # but until then we test it explicitly as a workaround.
                not_soft_deleted = or_(
                    models.Instance.vm_state != vm_states.SOFT_DELETED,
                    models.Instance.vm_state == null()
                    )
                query_prefix = query_prefix.filter(not_soft_deleted)

    if 'cleaned' in filters:
        if filters.pop('cleaned'):
            query_prefix = query_prefix.filter(models.Instance.cleaned == 1)
        else:
            query_prefix = query_prefix.filter(models.Instance.cleaned == 0)

    if 'tag' in filters:
        tags = filters.pop('tag')
        # We build a JOIN ladder expression for each tag, JOIN'ing
        # the first tag to the instances table, and each subsequent
        # tag to the last JOIN'd tags table
        first_tag = tags.pop(0)
        query_prefix = query_prefix.join(models.Instance.tags)
        query_prefix = query_prefix.filter(models.Tag.tag == first_tag)

        for tag in tags:
            tag_alias = aliased(models.Tag)
            query_prefix = query_prefix.join(tag_alias,
                                             models.Instance.tags)
            query_prefix = query_prefix.filter(tag_alias.tag == tag)

    if 'tag-any' in filters:
        tags = filters.pop('tag-any')
        tag_alias = aliased(models.Tag)
        query_prefix = query_prefix.join(tag_alias, models.Instance.tags)
        query_prefix = query_prefix.filter(tag_alias.tag.in_(tags))

    if not context.is_admin:
        # If we're not admin context, add appropriate filter..
        if context.project_id:
            filters['project_id'] = context.project_id
        else:
            filters['user_id'] = context.user_id

    # Filters for exact matches that we can do along with the SQL query...
    # For other filters that don't match this, we will do regexp matching
    exact_match_filter_names = ['project_id', 'user_id', 'image_ref',
                                'vm_state', 'instance_type_id', 'uuid',
                                'metadata', 'host', 'task_state',
                                'system_metadata']

    # Filter the query
    query_prefix = _exact_instance_filter(query_prefix,
                                filters, exact_match_filter_names)
    query_prefix = _regex_instance_filter(query_prefix, filters)
    query_prefix = _tag_instance_filter(context, query_prefix, filters)

    # paginate query
    if marker is not None:
        try:
            marker = _instance_get_by_uuid(
                    context.elevated(read_deleted='yes'), marker,
                    session=session)
        except exception.InstanceNotFound:
            raise exception.MarkerNotFound(marker)
    try:
        query_prefix = sqlalchemyutils.paginate_query(query_prefix,
                               models.Instance, limit,
                               sort_keys,
                               marker=marker,
                               sort_dirs=sort_dirs)
    except db_exc.InvalidSortKey:
        raise exception.InvalidSortKey()

    return _instances_fill_metadata(context, query_prefix.all(), manual_joins)
SELECT instance_faults.created_at AS instance_faults_created_at, instance_faults.updated_at AS instance_faults_updated_at, instance_faults.deleted_at AS instance_faults_deleted_at, instance_faults.deleted AS instance_faults_deleted, instance_faults.id AS instance_faults_id, instance_faults.instance_uuid AS instance_faults_instance_uuid, instance_faults.code AS instance_faults_code, instance_faults.message AS instance_faults_message, instance_faults.details AS instance_faults_details, instance_faults.host AS instance_faults_host 
FROM instance_faults 
WHERE instance_faults.deleted = 0 AND instance_faults.instance_uuid IN ('e0f41dae-9579-47b5-94a1-d6b5f15cc263', '44f3f532-e773-4add-8f45-980988899471', '53ce3de4-bd65-4e04-a7d7-f220c895ed92', '6aec54ab-f069-4159-ba67-fc8376c164c7', 'e9512e80-e25b-4ff1-9e29-a2cc617ee71b') ORDER BY instance_faults.created_at DESC, instance_faults.id DESC;
SELECT block_device_mapping.created_at AS block_device_mapping_created_at, block_device_mapping.updated_at AS block_device_mapping_updated_at, block_device_mapping.deleted_at AS block_device_mapping_deleted_at, block_device_mapping.deleted AS block_device_mapping_deleted, block_device_mapping.id AS block_device_mapping_id, block_device_mapping.instance_uuid AS block_device_mapping_instance_uuid, block_device_mapping.source_type AS block_device_mapping_source_type, block_device_mapping.destination_type AS block_device_mapping_destination_type, block_device_mapping.guest_format AS block_device_mapping_guest_format, block_device_mapping.device_type AS block_device_mapping_device_type, block_device_mapping.disk_bus AS block_device_mapping_disk_bus, block_device_mapping.boot_index AS block_device_mapping_boot_index, block_device_mapping.device_name AS block_device_mapping_device_name, block_device_mapping.delete_on_termination AS block_device_mapping_delete_on_termination, block_device_mapping.snapshot_id AS block_device_mapping_snapshot_id, block_device_mapping.volume_id AS block_device_mapping_volume_id, block_device_mapping.volume_size AS block_device_mapping_volume_size, block_device_mapping.image_id AS block_device_mapping_image_id, block_device_mapping.no_device AS block_device_mapping_no_device, block_device_mapping.connection_info AS block_device_mapping_connection_info 
FROM block_device_mapping 
WHERE block_device_mapping.deleted = 0 AND block_device_mapping.instance_uuid = 'e0f41dae-9579-47b5-94a1-d6b5f15cc263';
SELECT block_device_mapping.created_at AS block_device_mapping_created_at, block_device_mapping.updated_at AS block_device_mapping_updated_at, block_device_mapping.deleted_at AS block_device_mapping_deleted_at, block_device_mapping.deleted AS block_device_mapping_deleted, block_device_mapping.id AS block_device_mapping_id, block_device_mapping.instance_uuid AS block_device_mapping_instance_uuid, block_device_mapping.source_type AS block_device_mapping_source_type, block_device_mapping.destination_type AS block_device_mapping_destination_type, block_device_mapping.guest_format AS block_device_mapping_guest_format, block_device_mapping.device_type AS block_device_mapping_device_type, block_device_mapping.disk_bus AS block_device_mapping_disk_bus, block_device_mapping.boot_index AS block_device_mapping_boot_index, block_device_mapping.device_name AS block_device_mapping_device_name, block_device_mapping.delete_on_termination AS block_device_mapping_delete_on_termination, block_device_mapping.snapshot_id AS block_device_mapping_snapshot_id, block_device_mapping.volume_id AS block_device_mapping_volume_id, block_device_mapping.volume_size AS block_device_mapping_volume_size, block_device_mapping.image_id AS block_device_mapping_image_id, block_device_mapping.no_device AS block_device_mapping_no_device, block_device_mapping.connection_info AS block_device_mapping_connection_info 
FROM block_device_mapping 
WHERE block_device_mapping.deleted = 0 AND block_device_mapping.instance_uuid = '44f3f532-e773-4add-8f45-980988899471';
SELECT block_device_mapping.created_at AS block_device_mapping_created_at, block_device_mapping.updated_at AS block_device_mapping_updated_at, block_device_mapping.deleted_at AS block_device_mapping_deleted_at, block_device_mapping.deleted AS block_device_mapping_deleted, block_device_mapping.id AS block_device_mapping_id, block_device_mapping.instance_uuid AS block_device_mapping_instance_uuid, block_device_mapping.source_type AS block_device_mapping_source_type, block_device_mapping.destination_type AS block_device_mapping_destination_type, block_device_mapping.guest_format AS block_device_mapping_guest_format, block_device_mapping.device_type AS block_device_mapping_device_type, block_device_mapping.disk_bus AS block_device_mapping_disk_bus, block_device_mapping.boot_index AS block_device_mapping_boot_index, block_device_mapping.device_name AS block_device_mapping_device_name, block_device_mapping.delete_on_termination AS block_device_mapping_delete_on_termination, block_device_mapping.snapshot_id AS block_device_mapping_snapshot_id, block_device_mapping.volume_id AS block_device_mapping_volume_id, block_device_mapping.volume_size AS block_device_mapping_volume_size, block_device_mapping.image_id AS block_device_mapping_image_id, block_device_mapping.no_device AS block_device_mapping_no_device, block_device_mapping.connection_info AS block_device_mapping_connection_info 
FROM block_device_mapping 
WHERE block_device_mapping.deleted = 0 AND block_device_mapping.instance_uuid = '53ce3de4-bd65-4e04-a7d7-f220c895ed92';
SELECT block_device_mapping.created_at AS block_device_mapping_created_at, block_device_mapping.updated_at AS block_device_mapping_updated_at, block_device_mapping.deleted_at AS block_device_mapping_deleted_at, block_device_mapping.deleted AS block_device_mapping_deleted, block_device_mapping.id AS block_device_mapping_id, block_device_mapping.instance_uuid AS block_device_mapping_instance_uuid, block_device_mapping.source_type AS block_device_mapping_source_type, block_device_mapping.destination_type AS block_device_mapping_destination_type, block_device_mapping.guest_format AS block_device_mapping_guest_format, block_device_mapping.device_type AS block_device_mapping_device_type, block_device_mapping.disk_bus AS block_device_mapping_disk_bus, block_device_mapping.boot_index AS block_device_mapping_boot_index, block_device_mapping.device_name AS block_device_mapping_device_name, block_device_mapping.delete_on_termination AS block_device_mapping_delete_on_termination, block_device_mapping.snapshot_id AS block_device_mapping_snapshot_id, block_device_mapping.volume_id AS block_device_mapping_volume_id, block_device_mapping.volume_size AS block_device_mapping_volume_size, block_device_mapping.image_id AS block_device_mapping_image_id, block_device_mapping.no_device AS block_device_mapping_no_device, block_device_mapping.connection_info AS block_device_mapping_connection_info 
FROM block_device_mapping 
WHERE block_device_mapping.deleted = 0 AND block_device_mapping.instance_uuid = '6aec54ab-f069-4159-ba67-fc8376c164c7';
SELECT block_device_mapping.created_at AS block_device_mapping_created_at, block_device_mapping.updated_at AS block_device_mapping_updated_at, block_device_mapping.deleted_at AS block_device_mapping_deleted_at, block_device_mapping.deleted AS block_device_mapping_deleted, block_device_mapping.id AS block_device_mapping_id, block_device_mapping.instance_uuid AS block_device_mapping_instance_uuid, block_device_mapping.source_type AS block_device_mapping_source_type, block_device_mapping.destination_type AS block_device_mapping_destination_type, block_device_mapping.guest_format AS block_device_mapping_guest_format, block_device_mapping.device_type AS block_device_mapping_device_type, block_device_mapping.disk_bus AS block_device_mapping_disk_bus, block_device_mapping.boot_index AS block_device_mapping_boot_index, block_device_mapping.device_name AS block_device_mapping_device_name, block_device_mapping.delete_on_termination AS block_device_mapping_delete_on_termination, block_device_mapping.snapshot_id AS block_device_mapping_snapshot_id, block_device_mapping.volume_id AS block_device_mapping_volume_id, block_device_mapping.volume_size AS block_device_mapping_volume_size, block_device_mapping.image_id AS block_device_mapping_image_id, block_device_mapping.no_device AS block_device_mapping_no_device, block_device_mapping.connection_info AS block_device_mapping_connection_info 
FROM block_device_mapping 
WHERE block_device_mapping.deleted = 0 AND block_device_mapping.instance_uuid = 'e9512e80-e25b-4ff1-9e29-a2cc617ee71b';
  • Perhaps it's from the relationship declared in the following mapping, but I doubt it given the clause order differs (and I think SQLAlchemy preserves the order):
class BlockDeviceMapping(BASE, NovaBase):
    """Represents block device mapping that is defined by EC2."""
    __tablename__ = "block_device_mapping"
    __table_args__ = (
        Index('snapshot_id', 'snapshot_id'),
        Index('volume_id', 'volume_id'),
        Index('block_device_mapping_instance_uuid_device_name_idx',
              'instance_uuid', 'device_name'),
        Index('block_device_mapping_instance_uuid_volume_id_idx',
              'instance_uuid', 'volume_id'),
        Index('block_device_mapping_instance_uuid_idx', 'instance_uuid'),
    )
    id = Column(Integer, primary_key=True, autoincrement=True)

    instance_uuid = Column(String(36), ForeignKey('instances.uuid'))
    instance = orm.relationship(Instance,
                            backref=orm.backref('block_device_mapping'),
                            foreign_keys=instance_uuid,
                            primaryjoin='and_(BlockDeviceMapping.'
                                              'instance_uuid=='
                                              'Instance.uuid,'
                                              'BlockDeviceMapping.deleted=='
                                              '0)')
    ...
  • All the queries executed during a nova list with 2 instances.
-----> Grab the instances

SELECT anon_1.instances_created_at AS anon_1_instances_created_at, anon_1.instances_updated_at AS anon_1_instances_updated_at, anon_1.instances_deleted_at AS anon_1_instances_deleted_at, anon_1.instances_deleted AS anon_1_instances_deleted, anon_1.instances_id AS anon_1_instances_id, anon_1.instances_user_id AS anon_1_instances_user_id, anon_1.instances_project_id AS anon_1_instances_project_id, anon_1.instances_image_ref AS anon_1_instances_image_ref, anon_1.instances_kernel_id AS anon_1_instances_kernel_id, anon_1.instances_ramdisk_id AS anon_1_instances_ramdisk_id, anon_1.instances_hostname AS anon_1_instances_hostname, anon_1.instances_launch_index AS anon_1_instances_launch_index, anon_1.instances_key_name AS anon_1_instances_key_name, anon_1.instances_key_data AS anon_1_instances_key_data, anon_1.instances_power_state AS anon_1_instances_power_state, anon_1.instances_vm_state AS anon_1_instances_vm_state, anon_1.instances_task_state AS anon_1_instances_task_state, anon_1.instances_memory_mb AS anon_1_instances_memory_mb, anon_1.instances_vcpus AS anon_1_instances_vcpus, anon_1.instances_root_gb AS anon_1_instances_root_gb, anon_1.instances_ephemeral_gb AS anon_1_instances_ephemeral_gb, anon_1.instances_ephemeral_key_uuid AS anon_1_instances_ephemeral_key_uuid, anon_1.instances_host AS anon_1_instances_host, anon_1.instances_node AS anon_1_instances_node, anon_1.instances_instance_type_id AS anon_1_instances_instance_type_id, anon_1.instances_user_data AS anon_1_instances_user_data, anon_1.instances_reservation_id AS anon_1_instances_reservation_id, anon_1.instances_launched_at AS anon_1_instances_launched_at, anon_1.instances_terminated_at AS anon_1_instances_terminated_at, anon_1.instances_availability_zone AS anon_1_instances_availability_zone, anon_1.instances_display_name AS anon_1_instances_display_name, anon_1.instances_display_description AS anon_1_instances_display_description, anon_1.instances_launched_on AS anon_1_instances_launched_on, anon_1.instances_locked AS anon_1_instances_locked, anon_1.instances_locked_by AS anon_1_instances_locked_by, anon_1.instances_os_type AS anon_1_instances_os_type, anon_1.instances_architecture AS anon_1_instances_architecture, anon_1.instances_vm_mode AS anon_1_instances_vm_mode, anon_1.instances_uuid AS anon_1_instances_uuid, anon_1.instances_root_device_name AS anon_1_instances_root_device_name, anon_1.instances_default_ephemeral_device AS anon_1_instances_default_ephemeral_device, anon_1.instances_default_swap_device AS anon_1_instances_default_swap_device, anon_1.instances_config_drive AS anon_1_instances_config_drive, anon_1.instances_access_ip_v4 AS anon_1_instances_access_ip_v4, anon_1.instances_access_ip_v6 AS anon_1_instances_access_ip_v6, anon_1.instances_auto_disk_config AS anon_1_instances_auto_disk_config, anon_1.instances_progress AS anon_1_instances_progress, anon_1.instances_shutdown_terminate AS anon_1_instances_shutdown_terminate, anon_1.instances_disable_terminate AS anon_1_instances_disable_terminate, anon_1.instances_cell_name AS anon_1_instances_cell_name, anon_1.instances_internal_id AS anon_1_instances_internal_id, anon_1.instances_cleaned AS anon_1_instances_cleaned, security_groups_1.created_at AS security_groups_1_created_at, security_groups_1.updated_at AS security_groups_1_updated_at, security_groups_1.deleted_at AS security_groups_1_deleted_at, security_groups_1.deleted AS security_groups_1_deleted, security_groups_1.id AS security_groups_1_id, security_groups_1.name AS security_groups_1_name, security_groups_1.description AS security_groups_1_description, security_groups_1.user_id AS security_groups_1_user_id, security_groups_1.project_id AS security_groups_1_project_id, instance_metadata_1.created_at AS instance_metadata_1_created_at, instance_metadata_1.updated_at AS instance_metadata_1_updated_at, instance_metadata_1.deleted_at AS instance_metadata_1_deleted_at, instance_metadata_1.deleted AS instance_metadata_1_deleted, instance_metadata_1.id AS instance_metadata_1_id, instance_metadata_1.`key` AS instance_metadata_1_key, instance_metadata_1.value AS instance_metadata_1_value, instance_metadata_1.instance_uuid AS instance_metadata_1_instance_uuid, instance_info_caches_1.created_at AS instance_info_caches_1_created_at, instance_info_caches_1.updated_at AS instance_info_caches_1_updated_at, instance_info_caches_1.deleted_at AS instance_info_caches_1_deleted_at, instance_info_caches_1.deleted AS instance_info_caches_1_deleted, instance_info_caches_1.id AS instance_info_caches_1_id, instance_info_caches_1.network_info AS instance_info_caches_1_network_info, instance_info_caches_1.instance_uuid AS instance_info_caches_1_instance_uuid, instance_extra_1.flavor AS instance_extra_1_flavor, instance_extra_1.created_at AS instance_extra_1_created_at, instance_extra_1.updated_at AS instance_extra_1_updated_at, instance_extra_1.deleted_at AS instance_extra_1_deleted_at, instance_extra_1.deleted AS instance_extra_1_deleted, instance_extra_1.id AS instance_extra_1_id, instance_extra_1.instance_uuid AS instance_extra_1_instance_uuid 
FROM (SELECT instances.created_at AS instances_created_at, instances.updated_at AS instances_updated_at, instances.deleted_at AS instances_deleted_at, instances.deleted AS instances_deleted, instances.id AS instances_id, instances.user_id AS instances_user_id, instances.project_id AS instances_project_id, instances.image_ref AS instances_image_ref, instances.kernel_id AS instances_kernel_id, instances.ramdisk_id AS instances_ramdisk_id, instances.hostname AS instances_hostname, instances.launch_index AS instances_launch_index, instances.key_name AS instances_key_name, instances.key_data AS instances_key_data, instances.power_state AS instances_power_state, instances.vm_state AS instances_vm_state, instances.task_state AS instances_task_state, instances.memory_mb AS instances_memory_mb, instances.vcpus AS instances_vcpus, instances.root_gb AS instances_root_gb, instances.ephemeral_gb AS instances_ephemeral_gb, instances.ephemeral_key_uuid AS instances_ephemeral_key_uuid, instances.host AS instances_host, instances.node AS instances_node, instances.instance_type_id AS instances_instance_type_id, instances.user_data AS instances_user_data, instances.reservation_id AS instances_reservation_id, instances.launched_at AS instances_launched_at, instances.terminated_at AS instances_terminated_at, instances.availability_zone AS instances_availability_zone, instances.display_name AS instances_display_name, instances.display_description AS instances_display_description, instances.launched_on AS instances_launched_on, instances.locked AS instances_locked, instances.locked_by AS instances_locked_by, instances.os_type AS instances_os_type, instances.architecture AS instances_architecture, instances.vm_mode AS instances_vm_mode, instances.uuid AS instances_uuid, instances.root_device_name AS instances_root_device_name, instances.default_ephemeral_device AS instances_default_ephemeral_device, instances.default_swap_device AS instances_default_swap_device, instances.config_drive AS instances_config_drive, instances.access_ip_v4 AS instances_access_ip_v4, instances.access_ip_v6 AS instances_access_ip_v6, instances.auto_disk_config AS instances_auto_disk_config, instances.progress AS instances_progress, instances.shutdown_terminate AS instances_shutdown_terminate, instances.disable_terminate AS instances_disable_terminate, instances.cell_name AS instances_cell_name, instances.internal_id AS instances_internal_id, instances.cleaned AS instances_cleaned 
FROM instances 
WHERE instances.deleted = %s AND (instances.vm_state != %s OR instances.vm_state IS NULL) AND instances.project_id = %s ORDER BY instances.created_at DESC, instances.id DESC 
 LIMIT %s) AS anon_1 LEFT OUTER JOIN (security_group_instance_association AS security_group_instance_association_1 INNER JOIN security_groups AS security_groups_1 ON security_groups_1.id = security_group_instance_association_1.security_group_id AND security_group_instance_association_1.deleted = %s AND security_groups_1.deleted = %s) ON security_group_instance_association_1.instance_uuid = anon_1.instances_uuid AND anon_1.instances_deleted = %s LEFT OUTER JOIN instance_metadata AS instance_metadata_1 ON instance_metadata_1.instance_uuid = anon_1.instances_uuid AND instance_metadata_1.deleted = %s LEFT OUTER JOIN instance_info_caches AS instance_info_caches_1 ON instance_info_caches_1.instance_uuid = anon_1.instances_uuid LEFT OUTER JOIN instance_extra AS instance_extra_1 ON instance_extra_1.instance_uuid = anon_1.instances_uuid ORDER BY anon_1.instances_created_at DESC, anon_1.instances_id DESC
(0, 'soft-delete', u'56c6ffd000e1439ca019bd00fc1aa41a', 1000, 0, 0, 0, 0)

-----> The following 3 queries are coming from the _instances_fill_metadata call.

SELECT instance_metadata.created_at AS instance_metadata_created_at, instance_metadata.updated_at AS instance_metadata_updated_at, instance_metadata.deleted_at AS instance_metadata_deleted_at, instance_metadata.deleted AS instance_metadata_deleted, instance_metadata.id AS instance_metadata_id, instance_metadata.`key` AS instance_metadata_key, instance_metadata.value AS instance_metadata_value, instance_metadata.instance_uuid AS instance_metadata_instance_uuid 
FROM instance_metadata 
WHERE instance_metadata.deleted = %s AND instance_metadata.instance_uuid IN (%s, %s)
(0, u'02c5093d-a7f5-4b8c-91a6-26bb2ca285e8', u'e70c5625-3d8a-461b-b586-f0bdfbbcb33d')

SELECT instance_system_metadata.created_at AS instance_system_metadata_created_at, instance_system_metadata.updated_at AS instance_system_metadata_updated_at, instance_system_metadata.deleted_at AS instance_system_metadata_deleted_at, instance_system_metadata.deleted AS instance_system_metadata_deleted, instance_system_metadata.id AS instance_system_metadata_id, instance_system_metadata.`key` AS instance_system_metadata_key, instance_system_metadata.value AS instance_system_metadata_value, instance_system_metadata.instance_uuid AS instance_system_metadata_instance_uuid 
FROM instance_system_metadata 
WHERE instance_system_metadata.instance_uuid IN (%s, %s)
(u'02c5093d-a7f5-4b8c-91a6-26bb2ca285e8', u'e70c5625-3d8a-461b-b586-f0bdfbbcb33d')

SELECT pci_devices.created_at AS pci_devices_created_at, pci_devices.updated_at AS pci_devices_updated_at, pci_devices.deleted_at AS pci_devices_deleted_at, pci_devices.deleted AS pci_devices_deleted, pci_devices.id AS pci_devices_id, pci_devices.compute_node_id AS pci_devices_compute_node_id, pci_devices.address AS pci_devices_address, pci_devices.vendor_id AS pci_devices_vendor_id, pci_devices.product_id AS pci_devices_product_id, pci_devices.dev_type AS pci_devices_dev_type, pci_devices.dev_id AS pci_devices_dev_id, pci_devices.label AS pci_devices_label, pci_devices.status AS pci_devices_status, pci_devices.request_id AS pci_devices_request_id, pci_devices.extra_info AS pci_devices_extra_info, pci_devices.instance_uuid AS pci_devices_instance_uuid, pci_devices.numa_node AS pci_devices_numa_node 
FROM pci_devices 
WHERE pci_devices.deleted = %s AND pci_devices.status = %s AND pci_devices.instance_uuid IN (%s, %s)
(0, 'allocated', u'02c5093d-a7f5-4b8c-91a6-26bb2ca285e8', u'e70c5625-3d8a-461b-b586-f0bdfbbcb33d')

-----> This is from instance_list.fill_faults() in servers.py, line 405

SELECT instance_faults.created_at AS instance_faults_created_at, instance_faults.updated_at AS instance_faults_updated_at, instance_faults.deleted_at AS instance_faults_deleted_at, instance_faults.deleted AS instance_faults_deleted, instance_faults.id AS instance_faults_id, instance_faults.instance_uuid AS instance_faults_instance_uuid, instance_faults.code AS instance_faults_code, instance_faults.message AS instance_faults_message, instance_faults.details AS instance_faults_details, instance_faults.host AS instance_faults_host 
FROM instance_faults 
WHERE instance_faults.deleted = %s AND instance_faults.instance_uuid IN (%s, %s) ORDER BY instance_faults.created_at DESC, instance_faults.id DESC
(0, '02c5093d-a7f5-4b8c-91a6-26bb2ca285e8', 'e70c5625-3d8a-461b-b586-f0bdfbbcb33d')

-----> Where are these coming from?
-----> Answer: block_device_mapping_get_all_by_instance()
-----> But who's calling it?

SELECT block_device_mapping.created_at AS block_device_mapping_created_at, block_device_mapping.updated_at AS block_device_mapping_updated_at, block_device_mapping.deleted_at AS block_device_mapping_deleted_at, block_device_mapping.deleted AS block_device_mapping_deleted, block_device_mapping.id AS block_device_mapping_id, block_device_mapping.instance_uuid AS block_device_mapping_instance_uuid, block_device_mapping.source_type AS block_device_mapping_source_type, block_device_mapping.destination_type AS block_device_mapping_destination_type, block_device_mapping.guest_format AS block_device_mapping_guest_format, block_device_mapping.device_type AS block_device_mapping_device_type, block_device_mapping.disk_bus AS block_device_mapping_disk_bus, block_device_mapping.boot_index AS block_device_mapping_boot_index, block_device_mapping.device_name AS block_device_mapping_device_name, block_device_mapping.delete_on_termination AS block_device_mapping_delete_on_termination, block_device_mapping.snapshot_id AS block_device_mapping_snapshot_id, block_device_mapping.volume_id AS block_device_mapping_volume_id, block_device_mapping.volume_size AS block_device_mapping_volume_size, block_device_mapping.image_id AS block_device_mapping_image_id, block_device_mapping.no_device AS block_device_mapping_no_device, block_device_mapping.connection_info AS block_device_mapping_connection_info 
FROM block_device_mapping 
WHERE block_device_mapping.deleted = %s AND block_device_mapping.instance_uuid = %s
(0, '02c5093d-a7f5-4b8c-91a6-26bb2ca285e8')

SELECT block_device_mapping.created_at AS block_device_mapping_created_at, block_device_mapping.updated_at AS block_device_mapping_updated_at, block_device_mapping.deleted_at AS block_device_mapping_deleted_at, block_device_mapping.deleted AS block_device_mapping_deleted, block_device_mapping.id AS block_device_mapping_id, block_device_mapping.instance_uuid AS block_device_mapping_instance_uuid, block_device_mapping.source_type AS block_device_mapping_source_type, block_device_mapping.destination_type AS block_device_mapping_destination_type, block_device_mapping.guest_format AS block_device_mapping_guest_format, block_device_mapping.device_type AS block_device_mapping_device_type, block_device_mapping.disk_bus AS block_device_mapping_disk_bus, block_device_mapping.boot_index AS block_device_mapping_boot_index, block_device_mapping.device_name AS block_device_mapping_device_name, block_device_mapping.delete_on_termination AS block_device_mapping_delete_on_termination, block_device_mapping.snapshot_id AS block_device_mapping_snapshot_id, block_device_mapping.volume_id AS block_device_mapping_volume_id, block_device_mapping.volume_size AS block_device_mapping_volume_size, block_device_mapping.image_id AS block_device_mapping_image_id, block_device_mapping.no_device AS block_device_mapping_no_device, block_device_mapping.connection_info AS block_device_mapping_connection_info 
FROM block_device_mapping 
WHERE block_device_mapping.deleted = %s AND block_device_mapping.instance_uuid = %s
(0, 'e70c5625-3d8a-461b-b586-f0bdfbbcb33d')
  • Those queries are coming from BlockDeviceMappingList.get_by_instance_uuid(), but I'm still not sure how that's being invoked N times.

  • Toss an exception in there to see the caller. Ah! Apparently there is some kind of post-processing you can hook into:

2015-09-29 21:18:36.532 ERROR nova.api.openstack [req-1b5a7a93-78af-4c6a-b7e3-a44a6aaab4f5 admin admin] Caught error: HELLO!
2015-09-29 21:18:36.532 TRACE nova.api.openstack Traceback (most recent call last):
File "/opt/stack/nova/nova/api/openstack/__init__.py", line 134, in __call__
  return req.get_response(self.application)
File "/usr/lib/python2.7/site-packages/webob/request.py", line 1317, in send
  application, catch_exc_info=False)
File "/usr/lib/python2.7/site-packages/webob/request.py", line 1281, in call_application
  app_iter = application(self.environ, start_response)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 144, in __call__
  return resp(environ, start_response)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
  resp = self.call_func(req, *args, **self.kwargs)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
  return self.func(req, *args, **kwargs)
File "/usr/lib/python2.7/site-packages/keystonemiddleware/auth_token/__init__.py", line 454, in __call__
  response = req.get_response(self._app)
File "/usr/lib/python2.7/site-packages/webob/request.py", line 1317, in send
  application, catch_exc_info=False)
File "/usr/lib/python2.7/site-packages/webob/request.py", line 1281, in call_application
  app_iter = application(self.environ, start_response)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 144, in __call__
  return resp(environ, start_response)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 144, in __call__
  return resp(environ, start_response)
File "/usr/lib/python2.7/site-packages/routes/middleware.py", line 136, in __call__
  response = self.app(environ, start_response)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 144, in __call__
  return resp(environ, start_response)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
  resp = self.call_func(req, *args, **self.kwargs)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
  return self.func(req, *args, **kwargs)
File "/opt/stack/nova/nova/api/openstack/wsgi.py", line 765, in __call__
  content_type, body, accept)
File "/opt/stack/nova/nova/api/openstack/wsgi.py", line 856, in _process_stack
  request, action_args)
File "/opt/stack/nova/nova/api/openstack/wsgi.py", line 719, in post_process_extensions
  **action_args)
File "/opt/stack/nova/nova/api/openstack/compute/extended_volumes.py", line 65, in detail
  req.api_version_request)
File "/opt/stack/nova/nova/api/openstack/compute/extended_volumes.py", line 32, in _extend_server
  context, instance.uuid)
File "/usr/lib/python2.7/site-packages/oslo_versionedobjects/base.py", line 171, in wrapper
  result = fn(cls, context, *args, **kwargs)
File "/opt/stack/nova/nova/objects/block_device.py", line 294, in get_by_instance_uuid
  raise Exception('HELLO!')
2015-09-29 21:18:36.532 TRACE nova.api.openstack Exception: HELLO!
  • Post-processing extensions:
<bound method ConfigDriveController.detail of <nova.api.openstack.compute.config_drive.ConfigDriveController object at 0x7f1c45fa6790>>

<bound method ServerUsageController.detail of <nova.api.openstack.compute.server_usage.ServerUsageController object at 0x7f1c45f9c8d0>>

<bound method ExtendedStatusController.detail of <nova.api.openstack.compute.extended_status.ExtendedStatusController object at 0x7f1c45f9c7d0>>

<bound method ExtendedAZController.detail of <nova.api.openstack.compute.extended_availability_zone.ExtendedAZController object at 0x7f1c45f97c10>>

<bound method Controller.detail of <nova.api.openstack.compute.hide_server_addresses.Controller object at 0x7f1c4600dd10>>



-------------> This one:

<bound method ExtendedVolumesController.detail of <nova.api.openstack.compute.extended_volumes.ExtendedVolumesController object at 0x7f1c460043d0>>

<--------------


<bound method ServerDiskConfigController.detail of <nova.api.openstack.compute.disk_config.ServerDiskConfigController object at 0x7f1c45ff9ad0>>

<bound method AccessIPsController.detail of <nova.api.openstack.compute.access_ips.AccessIPsController object at 0x7f1c45ff9a90>>

<bound method SecurityGroupsOutputController.detail of <nova.api.openstack.compute.security_groups.SecurityGroupsOutputController object at 0x7f1c45feea50>>

<bound method ExtendedServerAttributesController.detail of <nova.api.openstack.compute.extended_server_attributes.ExtendedServerAttributesController object at 0x7f1c45fee9d0>>

<bound method Controller.detail of <nova.api.openstack.compute.keypairs.Controller object at 0x7f1c46a70890>>

Here's the class that's doing N queries in the detail() case:

class ExtendedVolumesController(wsgi.Controller):
    def __init__(self, *args, **kwargs):
        super(ExtendedVolumesController, self).__init__(*args, **kwargs)
        self.api_version_2_3 = api_version_request.APIVersionRequest('2.3')

    def _extend_server(self, context, server, instance, requested_version):
        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
                context, instance.uuid)
        volumes_attached = []
        for bdm in bdms:
            if bdm.get('volume_id'):
                volume_attached = {'id': bdm['volume_id']}
                if requested_version >= self.api_version_2_3:
                    volume_attached['delete_on_termination'] = (
                        bdm['delete_on_termination'])
                volumes_attached.append(volume_attached)
        key = "%s:volumes_attached" % ExtendedVolumes.alias
        server[key] = volumes_attached

    @wsgi.extends
    def show(self, req, resp_obj, id):
        context = req.environ['nova.context']
        if soft_authorize(context):
            server = resp_obj.obj['server']
            db_instance = req.get_db_instance(server['id'])
            # server['id'] is guaranteed to be in the cache due to
            # the core API adding it in its 'show' method.
            self._extend_server(context, server, db_instance,
                                req.api_version_request)

    @wsgi.extends
    def detail(self, req, resp_obj):
        context = req.environ['nova.context']
        if soft_authorize(context):
            servers = list(resp_obj.obj['servers'])
            for server in servers:
                db_instance = req.get_db_instance(server['id'])
                # server['id'] is guaranteed to be in the cache due to
                # the core API adding it in its 'detail' method.
                self._extend_server(context, server, db_instance,
                                    req.api_version_request)

  • What do we know about this table & data?
MariaDB [nova]> select * from block_device_mapping\G
*************************** 1. row ***************************
           created_at: 2015-09-29 20:21:36
           updated_at: 2015-09-29 20:21:37
           deleted_at: NULL
                   id: 1
          device_name: /dev/vda
delete_on_termination: 1
          snapshot_id: NULL
            volume_id: NULL
          volume_size: NULL
            no_device: 0
      connection_info: NULL
        instance_uuid: e70c5625-3d8a-461b-b586-f0bdfbbcb33d
              deleted: 0
          source_type: image
     destination_type: local
         guest_format: NULL
          device_type: disk
             disk_bus: NULL
           boot_index: 0
             image_id: 76742559-84d6-4804-8a82-7f707c1ca9da
*************************** 2. row ***************************
           created_at: 2015-09-29 21:26:33
           updated_at: 2015-09-29 21:26:35
           deleted_at: NULL
                   id: 2
          device_name: /dev/vda
delete_on_termination: 1
          snapshot_id: NULL
            volume_id: NULL
          volume_size: NULL
            no_device: 0
      connection_info: NULL
        instance_uuid: 02c5093d-a7f5-4b8c-91a6-26bb2ca285e8
              deleted: 0
          source_type: image
     destination_type: local
         guest_format: NULL
          device_type: disk
             disk_bus: NULL
           boot_index: 0
             image_id: 76742559-84d6-4804-8a82-7f707c1ca9da
2 rows in set (0.00 sec)

MariaDB [nova]> describe block_device_mapping;
+-----------------------+--------------+------+-----+---------+----------------+
| Field                 | Type         | Null | Key | Default | Extra          |
+-----------------------+--------------+------+-----+---------+----------------+
| created_at            | datetime     | YES  |     | NULL    |                |
| updated_at            | datetime     | YES  |     | NULL    |                |
| deleted_at            | datetime     | YES  |     | NULL    |                |
| id                    | int(11)      | NO   | PRI | NULL    | auto_increment |
| device_name           | varchar(255) | YES  |     | NULL    |                |
| delete_on_termination | tinyint(1)   | YES  |     | NULL    |                |
| snapshot_id           | varchar(36)  | YES  | MUL | NULL    |                |
| volume_id             | varchar(36)  | YES  | MUL | NULL    |                |
| volume_size           | int(11)      | YES  |     | NULL    |                |
| no_device             | tinyint(1)   | YES  |     | NULL    |                |
| connection_info       | mediumtext   | YES  |     | NULL    |                |
| instance_uuid         | varchar(36)  | YES  | MUL | NULL    |                |
| deleted               | int(11)      | YES  |     | NULL    |                |
| source_type           | varchar(255) | YES  |     | NULL    |                |
| destination_type      | varchar(255) | YES  |     | NULL    |                |
| guest_format          | varchar(255) | YES  |     | NULL    |                |
| device_type           | varchar(255) | YES  |     | NULL    |                |
| disk_bus              | varchar(255) | YES  |     | NULL    |                |
| boot_index            | int(11)      | YES  |     | NULL    |                |
| image_id              | varchar(36)  | YES  |     | NULL    |                |
+-----------------------+--------------+------+-----+---------+----------------+
20 rows in set (0.00 sec)
MariaDB [nova]> update block_device_mapping set volume_id=concat('some_volumne_id_', id);

MariaDB [nova]> select * from block_device_mapping\G
*************************** 1. row ***************************
           created_at: 2015-09-29 20:21:36
           updated_at: 2015-09-29 20:21:37
           deleted_at: NULL
                   id: 1
          device_name: /dev/vda
delete_on_termination: 1
          snapshot_id: NULL
            volume_id: some_volumne_id_1
          volume_size: NULL
            no_device: 0
      connection_info: NULL
        instance_uuid: e70c5625-3d8a-461b-b586-f0bdfbbcb33d
              deleted: 0
          source_type: image
     destination_type: local
         guest_format: NULL
          device_type: disk
             disk_bus: NULL
           boot_index: 0
             image_id: 76742559-84d6-4804-8a82-7f707c1ca9da
*************************** 2. row ***************************
           created_at: 2015-09-29 21:26:33
           updated_at: 2015-09-29 21:26:35
           deleted_at: NULL
                   id: 2
          device_name: /dev/vda
delete_on_termination: 1
          snapshot_id: NULL
            volume_id: some_volumne_id_2
          volume_size: NULL
            no_device: 0
      connection_info: NULL
        instance_uuid: 02c5093d-a7f5-4b8c-91a6-26bb2ca285e8
              deleted: 0
          source_type: image
     destination_type: local
         guest_format: NULL
          device_type: disk
             disk_bus: NULL
           boot_index: 0
             image_id: 7
  • Note the volume id in the results now:
[
  {
    "OS-DCF:diskConfig": "AUTO", 
    "OS-EXT-AZ:availability_zone": "nova", 
    "OS-EXT-SRV-ATTR:host": "reserved", 
    "OS-EXT-SRV-ATTR:hostname": "instance-2", 
    "OS-EXT-SRV-ATTR:hypervisor_hostname": "reserved", 
    "OS-EXT-SRV-ATTR:instance_name": "instance-00000002", 
    "OS-EXT-SRV-ATTR:kernel_id": "37060936-0e85-44da-b792-ec5b27f959c6", 
    "OS-EXT-SRV-ATTR:launch_index": 0, 
    "OS-EXT-SRV-ATTR:ramdisk_id": "3196473f-b7f6-43f6-bcb4-ca81607b8188", 
    "OS-EXT-SRV-ATTR:reservation_id": "r-ikjkrugu", 
    "OS-EXT-SRV-ATTR:root_device_name": "/dev/vda", 
    "OS-EXT-SRV-ATTR:user_data": null, 
    "OS-EXT-STS:power_state": 1, 
    "OS-EXT-STS:task_state": null, 
    "OS-EXT-STS:vm_state": "active", 
    "OS-SRV-USG:launched_at": "2015-09-30T13:57:19.000000", 
    "OS-SRV-USG:terminated_at": null, 
    "accessIPv4": "", 
    "accessIPv6": "", 
    "addresses": {
      "private": [
        {
          "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:b3:c4:68", 
          "OS-EXT-IPS:type": "fixed", 
          "addr": "10.0.0.3", 
          "version": 4
        }
      ]
    }, 
    "config_drive": "True", 
    "created": "2015-09-29T21:26:33Z", 
    "flavor": {
      "id": "42", 
      "links": [
        {
          "href": "http://192.168.122.15:8774/56c6ffd000e1439ca019bd00fc1aa41a/flavors/42", 
          "rel": "bookmark"
        }
      ]
    }, 
    "hostId": "28a24236a69fe969a3121c663df3326d18b49588964b6b0a2ad842ef", 
    "id": "02c5093d-a7f5-4b8c-91a6-26bb2ca285e8", 
    "image": {
      "id": "76742559-84d6-4804-8a82-7f707c1ca9da", 
      "links": [
        {
          "href": "http://192.168.122.15:8774/56c6ffd000e1439ca019bd00fc1aa41a/images/76742559-84d6-4804-8a82-7f707c1ca9da", 
          "rel": "bookmark"
        }
      ]
    }, 
    "key_name": null, 
    "links": [
      {
        "href": "http://192.168.122.15:8774/v2.1/56c6ffd000e1439ca019bd00fc1aa41a/servers/02c5093d-a7f5-4b8c-91a6-26bb2ca285e8", 
        "rel": "self"
      }, 
      {
        "href": "http://192.168.122.15:8774/56c6ffd000e1439ca019bd00fc1aa41a/servers/02c5093d-a7f5-4b8c-91a6-26bb2ca285e8", 
        "rel": "bookmark"
      }
    ], 
    "locked": false, 
    "metadata": {}, 
    "name": "instance-2", 
    "os-extended-volumes:volumes_attached": [
      {
        "delete_on_termination": true, 
        "id": "some_volumne_id_2"          <-------- see!
      }
    ], 
    "progress": 0, 
    "security_groups": [
      {
        "name": "default"
      }
    ], 
    "status": "ACTIVE", 
    "tenant_id": "56c6ffd000e1439ca019bd00fc1aa41a", 
    "updated": "2015-09-30T13:57:19Z", 
    "user_id": "469cb305d1f94c15b97985dde3eba3b3"
  }, 
  {
    "OS-DCF:diskConfig": "AUTO", 
    "OS-EXT-AZ:availability_zone": "nova", 
    "OS-EXT-SRV-ATTR:host": "reserved", 
    "OS-EXT-SRV-ATTR:hostname": "instance-1", 
    "OS-EXT-SRV-ATTR:hypervisor_hostname": "reserved", 
    "OS-EXT-SRV-ATTR:instance_name": "instance-00000001", 
    "OS-EXT-SRV-ATTR:kernel_id": "37060936-0e85-44da-b792-ec5b27f959c6", 
    "OS-EXT-SRV-ATTR:launch_index": 0, 
    "OS-EXT-SRV-ATTR:ramdisk_id": "3196473f-b7f6-43f6-bcb4-ca81607b8188", 
    "OS-EXT-SRV-ATTR:reservation_id": "r-mlgvzrde", 
    "OS-EXT-SRV-ATTR:root_device_name": "/dev/vda", 
    "OS-EXT-SRV-ATTR:user_data": null, 
    "OS-EXT-STS:power_state": 1, 
    "OS-EXT-STS:task_state": null, 
    "OS-EXT-STS:vm_state": "active", 
    "OS-SRV-USG:launched_at": "2015-09-29T20:22:03.000000", 
    "OS-SRV-USG:terminated_at": null, 
    "accessIPv4": "", 
    "accessIPv6": "", 
    "addresses": {
      "private": [
        {
          "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:14:4b:b5", 
          "OS-EXT-IPS:type": "fixed", 
          "addr": "10.0.0.2", 
          "version": 4
        }
      ]
    }, 
    "config_drive": "True", 
    "created": "2015-09-29T20:21:35Z", 
    "flavor": {
      "id": "42", 
      "links": [
        {
          "href": "http://192.168.122.15:8774/56c6ffd000e1439ca019bd00fc1aa41a/flavors/42", 
          "rel": "bookmark"
        }
      ]
    }, 
    "hostId": "28a24236a69fe969a3121c663df3326d18b49588964b6b0a2ad842ef", 
    "id": "e70c5625-3d8a-461b-b586-f0bdfbbcb33d", 
    "image": {
      "id": "76742559-84d6-4804-8a82-7f707c1ca9da", 
      "links": [
        {
          "href": "http://192.168.122.15:8774/56c6ffd000e1439ca019bd00fc1aa41a/images/76742559-84d6-4804-8a82-7f707c1ca9da", 
          "rel": "bookmark"
        }
      ]
    }, 
    "key_name": null, 
    "links": [
      {
        "href": "http://192.168.122.15:8774/v2.1/56c6ffd000e1439ca019bd00fc1aa41a/servers/e70c5625-3d8a-461b-b586-f0bdfbbcb33d", 
        "rel": "self"
      }, 
      {
        "href": "http://192.168.122.15:8774/56c6ffd000e1439ca019bd00fc1aa41a/servers/e70c5625-3d8a-461b-b586-f0bdfbbcb33d", 
        "rel": "bookmark"
      }
    ], 
    "locked": false, 
    "metadata": {}, 
    "name": "instance-1", 
    "os-extended-volumes:volumes_attached": [
      {
        "delete_on_termination": true, 
        "id": "some_volumne_id_1"          <-------- see!
      }
    ], 
    "progress": 0, 
    "security_groups": [
      {
        "name": "default"
      }
    ], 
    "status": "ACTIVE", 
    "tenant_id": "56c6ffd000e1439ca019bd00fc1aa41a", 
    "updated": "2015-09-29T20:22:03Z", 
    "user_id": "469cb305d1f94c15b97985dde3eba3b3"
  }
]

⚠️ **GitHub.com Fallback** ⚠️