def get_data(self): instance_id = self.kwargs['instance_id'] try: instance = api.nova.server_get(self.request, instance_id) except Exception: redirect = reverse(self.redirect_url) exceptions.handle(self.request, _('Unable to retrieve details for ' 'instance "%s".') % instance_id, redirect=redirect) # Not all exception types handled above will result in a redirect. # Need to raise here just in case. raise exceptions.Http302(redirect) choices = project_tables.STATUS_DISPLAY_CHOICES instance.status_label = ( filters.get_display_label(choices, instance.status)) futurist_utils.call_functions_parallel( (self._get_volumes, [instance]), (self._get_flavor, [instance]), (self._get_security_groups, [instance]), (self._update_addresses, [instance]), ) return instance
def tenant_quota_usages(request, tenant_id=None, targets=None): """Get our quotas and construct our usage object. :param tenant_id: Target tenant ID. If no tenant_id is provided, a the request.user.project_id is assumed to be used. :param targets: A tuple of quota names to be retrieved. If unspecified, all quota and usage information is retrieved. """ if not tenant_id: tenant_id = request.user.project_id disabled_quotas = get_disabled_quotas(request) usages = QuotaUsage() if targets: if set(targets) - QUOTA_FIELDS: raise ValueError('Unknown quota field names are included: %s' % set(targets) - QUOTA_FIELDS) enabled_quotas = set(QUOTA_FIELDS) - disabled_quotas enabled_quotas &= set(targets) disabled_quotas = set(QUOTA_FIELDS) - enabled_quotas futurist_utils.call_functions_parallel( (_get_tenant_compute_usages, [request, usages, disabled_quotas, tenant_id]), (_get_tenant_network_usages, [request, usages, disabled_quotas, tenant_id]), (_get_tenant_volume_usages, [request, usages, disabled_quotas, tenant_id])) return usages
def get_data(self): instance_id = self.kwargs['instance_id'] try: instance = api.nova.server_get(self.request, instance_id) except Exception: redirect = reverse(self.redirect_url) exceptions.handle(self.request, _('Unable to retrieve details for ' 'instance "%s".') % instance_id, redirect=redirect) # Not all exception types handled above will result in a redirect. # Need to raise here just in case. raise exceptions.Http302(redirect) choices = project_tables.STATUS_DISPLAY_CHOICES instance.status_label = (filters.get_display_label( choices, instance.status)) futurist_utils.call_functions_parallel( (self._get_volumes, [instance]), (self._get_flavor, [instance]), (self._get_security_groups, [instance]), (self._update_addresses, [instance]), ) return instance
def get_data(self): marker, sort_dir = self._get_marker() search_opts = self.get_filters({'marker': marker, 'paginate': True}) image_dict, flavor_dict, volume_dict = \ futurist_utils.call_functions_parallel( self._get_images, self._get_flavors, self._get_volumes ) non_api_filter_info = ( ('image_name', 'image', image_dict.values()), ('flavor_name', 'flavor', flavor_dict.values()), ) if not process_non_api_filters(search_opts, non_api_filter_info): self._more = False return [] instances = self._get_instances(search_opts, sort_dir) # Loop through instances to get flavor info. for instance in instances: self._populate_image_info(instance, image_dict, volume_dict) flavor_id = instance.flavor["id"] if flavor_id in flavor_dict: instance.full_flavor = flavor_dict[flavor_id] else: # If the flavor_id is not in flavor_dict, # put info in the log file. LOG.info('Unable to retrieve flavor "%s" for instance "%s".', flavor_id, instance.id) return instances
def get_data(self): marker, sort_dir = self._get_marker() search_opts = self.get_filters({'marker': marker, 'paginate': True}) image_dict, flavor_dict, volume_dict = \ futurist_utils.call_functions_parallel( self._get_images, self._get_flavors, self._get_volumes ) non_api_filter_info = ( ('image_name', 'image', image_dict.values()), ('flavor_name', 'flavor', flavor_dict.values()), ) if not process_non_api_filters(search_opts, non_api_filter_info): self._more = False return [] instances = self._get_instances(search_opts, sort_dir) # Loop through instances to get flavor info. for instance in instances: self._populate_image_info(instance, image_dict, volume_dict) flavor_id = instance.flavor["id"] if flavor_id in flavor_dict: instance.full_flavor = flavor_dict[flavor_id] else: # If the flavor_id is not in flavor_dict, # put info in the log file. LOG.info('Unable to retrieve flavor "%s" for instance "%s".', flavor_id, instance.id) return instances
def test_call_functions_parallel(self): def func1(): return 10 def func2(): return 20 ret = futurist_utils.call_functions_parallel(func1, func2) self.assertEqual(ret, (10, 20))
def get_context_data(self, **kwargs): context = super(DetailView, self).get_context_data(**kwargs) port = self.get_data() network_url = "horizon:project:networks:detail" subnet_url = "horizon:project:networks:subnets:detail" @memoized.memoized_method def get_network(network_id): try: network = api.neutron.network_get(self.request, network_id) except Exception: network = {} msg = _('Unable to retrieve network details.') exceptions.handle(self.request, msg) return network @memoized.memoized_method def get_security_groups(sg_ids): # Avoid extra API calls if no security group is associated. if not sg_ids: return [] try: security_groups = api.neutron.security_group_list(self.request, id=sg_ids) except Exception: security_groups = [] msg = _("Unable to retrieve security groups for the port.") exceptions.handle(self.request, msg) return security_groups results = futurist_utils.call_functions_parallel( (get_network, [port.network_id]), (get_security_groups, [tuple(port.security_groups)])) network, port.security_groups = results port.network_name = network.get('name') port.network_url = reverse(network_url, args=[port.network_id]) for ip in port.fixed_ips: ip['subnet_url'] = reverse(subnet_url, args=[ip['subnet_id']]) table = project_tables.PortsTable(self.request, network_id=port.network_id) # TODO(robcresswell) Add URL for "Ports" crumb after bug/1416838 breadcrumb = [ ((port.network_name or port.network_id), port.network_url), (_("Ports"), None) ] context["custom_breadcrumb"] = breadcrumb context["port"] = port context["url"] = reverse( 'horizon:project:networks:ports_tab', args=[port.network_id]) context["actions"] = table.render_row_actions(port) return context
def get_context_data(self, **kwargs): context = super(DetailView, self).get_context_data(**kwargs) port = self.get_data() network_url = "horizon:project:networks:detail" subnet_url = "horizon:project:networks:subnets:detail" @memoized.memoized_method def get_network(network_id): try: network = api.neutron.network_get(self.request, network_id) except Exception: network = {} msg = _('Unable to retrieve network details.') exceptions.handle(self.request, msg) return network @memoized.memoized_method def get_security_groups(sg_ids): # Avoid extra API calls if no security group is associated. if not sg_ids: return [] try: security_groups = api.neutron.security_group_list(self.request, id=sg_ids) except Exception: security_groups = [] msg = _("Unable to retrieve security groups for the port.") exceptions.handle(self.request, msg) return security_groups results = futurist_utils.call_functions_parallel( (get_network, [port.network_id]), (get_security_groups, [tuple(port.security_groups)])) network, port.security_groups = results port.network_name = network.get('name') port.network_url = reverse(network_url, args=[port.network_id]) for ip in port.fixed_ips: ip['subnet_url'] = reverse(subnet_url, args=[ip['subnet_id']]) table = project_tables.PortsTable(self.request, network_id=port.network_id) # TODO(robcresswell) Add URL for "Ports" crumb after bug/1416838 breadcrumb = [ ((port.network_name or port.network_id), port.network_url), (_("Ports"), None) ] context["custom_breadcrumb"] = breadcrumb context["port"] = port context["url"] = self.get_redirect_url() context["actions"] = table.render_row_actions(port) return context
def tenant_quota_usages(request, tenant_id=None, targets=None): """Get our quotas and construct our usage object. :param tenant_id: Target tenant ID. If no tenant_id is provided, a the request.user.project_id is assumed to be used. :param targets: A tuple of quota names to be retrieved. If unspecified, all quota and usage information is retrieved. """ if not tenant_id: tenant_id = request.user.project_id disabled_quotas = get_disabled_quotas(request, targets) usages = QuotaUsage() futurist_utils.call_functions_parallel( (_get_tenant_compute_usages, [request, usages, disabled_quotas, tenant_id]), (_get_tenant_network_usages, [request, usages, disabled_quotas, tenant_id]), (_get_tenant_volume_usages, [request, usages, disabled_quotas, tenant_id])) return usages
def get_data(self): volumes = [] attached_instance_ids = [] instances = [] volume_ids_with_snapshots = [] def _task_get_volumes(): volumes.extend(self._get_volumes()) attached_instance_ids.extend( self._get_attached_instance_ids(volumes)) def _task_get_instances(): # As long as Nova API does not allow passing attached_instance_ids # to nova.server_list, this call can be forged to pass anything # != None instances.extend(self._get_instances()) # In volumes tab we don't need to know about the assignment # instance-image, therefore fixing it to an empty value for instance in instances: if hasattr(instance, 'image'): if isinstance(instance.image, dict): instance.image['name'] = "-" def _task_get_volumes_snapshots(): volume_ids_with_snapshots.extend( self._get_volumes_ids_with_snapshots()) futurist_utils.call_functions_parallel( _task_get_volumes, _task_get_instances, _task_get_volumes_snapshots) self._set_volume_attributes( volumes, instances, volume_ids_with_snapshots) self._get_groups(volumes) return volumes
def test_call_functions_parallel_with_kwargs(self): def func1(a): return a def func2(a, b): return a + b def func3(): return 3 ret = futurist_utils.call_functions_parallel( (func1, [], {'a': 5}), (func2, [], {'a': 10, 'b': 20}), func3) self.assertEqual(ret, (5, 30, 3))
def test_call_functions_parallel_with_args(self): def func1(a): return a def func2(a, b): return a + b def func3(): return 3 ret = futurist_utils.call_functions_parallel( (func1, [5]), (func2, [10, 20]), func3) self.assertEqual(ret, (5, 30, 3))
def get_data(self): marker = self.request.GET.get( project_tables.InstancesTable._meta.pagination_param, None) search_opts = self.get_filters({'marker': marker, 'paginate': True}) image_dict, flavor_dict = futurist_utils.call_functions_parallel( self._get_images, self._get_flavors) non_api_filter_info = ( ('image_name', 'image', image_dict.values()), ('flavor_name', 'flavor', flavor_dict.values()), ) if not process_non_api_filters(search_opts, non_api_filter_info): self._more = False return [] instances = self._get_instances(search_opts) # Loop through instances to get flavor info. for instance in instances: if hasattr(instance, 'image'): # Instance from image returns dict if isinstance(instance.image, dict): image_id = instance.image.get('id') if image_id in image_dict: instance.image = image_dict[image_id] # In case image not found in image_dict, set name to empty # to avoid fallback API call to Glance in api/nova.py # until the call is deprecated in api itself else: instance.image['name'] = _("-") flavor_id = instance.flavor["id"] if flavor_id in flavor_dict: instance.full_flavor = flavor_dict[flavor_id] else: # If the flavor_id is not in flavor_dict, # put info in the log file. LOG.info('Unable to retrieve flavor "%s" for instance "%s".', flavor_id, instance.id) return instances
def get_data(self): instances = [] marker = self.request.GET.get( project_tables.AdminInstancesTable._meta.pagination_param, None) default_search_opts = {'marker': marker, 'paginate': True, 'all_tenants': True} search_opts = self.get_filters(default_search_opts.copy()) # If filter_first is set and if there are not other filters # selected, then search criteria must be provided and return an empty # list filter_first = getattr(settings, 'FILTER_DATA_FIRST', {}) if (filter_first.get('admin.instances', False) and len(search_opts) == len(default_search_opts)): self._needs_filter_first = True self._more = False return [] self._needs_filter_first = False results = futurist_utils.call_functions_parallel( self._get_images, self._get_flavors, self._get_tenants) image_dict, flavor_dict, tenant_dict = results non_api_filter_info = ( ('project', 'tenant_id', tenant_dict.values()), ('image_name', 'image', image_dict.values()), ('flavor_name', 'flavor', flavor_dict.values()), ) if not views.process_non_api_filters(search_opts, non_api_filter_info): self._more = False return [] instances = self._get_instances(search_opts) # Loop through instances to get image, flavor and tenant info. for inst in instances: if hasattr(inst, 'image') and isinstance(inst.image, dict): image_id = inst.image.get('id') if image_id in image_dict: inst.image = image_dict[image_id] # In case image not found in image_map, set name to empty # to avoid fallback API call to Glance in api/nova.py # until the call is deprecated in api itself else: inst.image['name'] = _("-") flavor_id = inst.flavor["id"] try: if flavor_id in flavor_dict: inst.full_flavor = flavor_dict[flavor_id] else: # If the flavor_id is not in flavor_dict list, # gets it via nova api. inst.full_flavor = api.nova.flavor_get( self.request, flavor_id) except Exception: msg = _('Unable to retrieve instance size information.') exceptions.handle(self.request, msg) tenant = tenant_dict.get(inst.tenant_id, None) inst.tenant_name = getattr(tenant, "name", None) return instances
def get_data(self): marker, sort_dir = self._get_marker() search_opts = self.get_filters({'marker': marker, 'paginate': True}) image_dict, flavor_dict, volume_dict = \ futurist_utils.call_functions_parallel( self._get_images, self._get_flavors, self._get_volumes ) non_api_filter_info = ( ('image_name', 'image', image_dict.values()), ('flavor_name', 'flavor', flavor_dict.values()), ) if not process_non_api_filters(search_opts, non_api_filter_info): self._more = False return [] instances = self._get_instances(search_opts, sort_dir) # Loop through instances to get flavor info. for instance in instances: if hasattr(instance, 'image'): # Instance from image returns dict if isinstance(instance.image, dict): image_id = instance.image.get('id') if image_id in image_dict: instance.image = image_dict[image_id] # In case image not found in image_dict, set name to empty # to avoid fallback API call to Glance in api/nova.py # until the call is deprecated in api itself else: instance.image['name'] = _("-") # Otherwise trying to get image from volume metadata else: instance_volumes = [ attachment for volume in volume_dict.values() for attachment in volume.attachments if attachment['server_id'] == instance.id ] # Sorting attached volumes by device name (eg '/dev/sda') instance_volumes.sort(key=lambda attach: attach['device']) # While instance from volume is being created, # it does not have volumes if instance_volumes: # Getting volume object, which is as attached # as the first device boot_volume = volume_dict[instance_volumes[0]['id']] if hasattr(boot_volume, "volume_image_metadata"): instance.image = image_dict[ boot_volume.volume_image_metadata['image_id']] flavor_id = instance.flavor["id"] if flavor_id in flavor_dict: instance.full_flavor = flavor_dict[flavor_id] else: # If the flavor_id is not in flavor_dict, # put info in the log file. LOG.info('Unable to retrieve flavor "%s" for instance "%s".', flavor_id, instance.id) return instances
def get_data(self): default_filters = {'all_tenants': True} filters = self.get_filters(default_filters.copy()) filter_first = settings.FILTER_DATA_FIRST volumes = [] self.table.needs_filter_first = False if (filter_first['admin.volumes'] and len(filters) == len(default_filters)): self.table.needs_filter_first = True return volumes volumes = [] attached_instance_ids = [] tenants = [] tenant_dict = {} instances = [] volume_ids_with_snapshots = [] def _task_get_tenants(): # Gather our tenants to correlate against IDs try: tmp_tenants, __ = keystone.tenant_list(self.request) tenants.extend(tmp_tenants) tenant_dict.update([(t.id, t) for t in tenants]) except Exception: msg = _('Unable to retrieve volume project information.') exceptions.handle(self.request, msg) def _task_get_instances(): # As long as Nova API does not allow passing attached_instance_ids # to nova.server_list, this call can be forged to pass anything # != None instances.extend( self._get_instances(search_opts={'all_tenants': True})) # In volumes tab we don't need to know about the assignment # instance-image, therefore fixing it to an empty value for instance in instances: if hasattr(instance, 'image'): if isinstance(instance.image, dict): instance.image['name'] = "-" def _task_get_volumes_snapshots(): volume_ids_with_snapshots.extend( self._get_volumes_ids_with_snapshots( search_opts={'all_tenants': True})) def _task_get_volumes(): volumes.extend(self._get_volumes(search_opts=filters)) # update group name for volumes self._get_groups(volumes, search_opts={'all_tenants': True}) attached_instance_ids.extend( self._get_attached_instance_ids(volumes)) if 'project' in filters: futurist_utils.call_functions_parallel( _task_get_tenants, _task_get_instances, _task_get_volumes_snapshots) tenant_ids = [ t.id for t in tenants if t.name == filters['project'] ] if not tenant_ids: return [] del filters['project'] for id in tenant_ids: filters['project_id'] = id volumes += self._get_volumes(search_opts=filters) attached_instance_ids = self._get_attached_instance_ids(volumes) else: futurist_utils.call_functions_parallel( _task_get_volumes, _task_get_tenants, _task_get_instances, _task_get_volumes_snapshots) self._set_volume_attributes(volumes, instances, volume_ids_with_snapshots) for volume in volumes: tenant_id = getattr(volume, "os-vol-tenant-attr:tenant_id", None) tenant = tenant_dict.get(tenant_id, None) volume.tenant_name = getattr(tenant, "name", None) return volumes
def get_data(self): default_filters = {'all_tenants': True} filters = self.get_filters(default_filters.copy()) filter_first = getattr(settings, 'FILTER_DATA_FIRST', {}) volumes = [] self.table.needs_filter_first = False if filter_first.get('admin.volumes', False) and \ len(filters) == len(default_filters): self.table.needs_filter_first = True return volumes volumes = [] attached_instance_ids = [] tenants = [] tenant_dict = {} instances = [] volume_ids_with_snapshots = [] def _task_get_tenants(): # Gather our tenants to correlate against IDs try: tmp_tenants, __ = keystone.tenant_list(self.request) tenants.extend(tmp_tenants) tenant_dict.update([(t.id, t) for t in tenants]) except Exception: msg = _('Unable to retrieve volume project information.') exceptions.handle(self.request, msg) def _task_get_instances(): # As long as Nova API does not allow passing attached_instance_ids # to nova.server_list, this call can be forged to pass anything # != None instances.extend(self._get_instances( search_opts={'all_tenants': True})) # In volumes tab we don't need to know about the assignment # instance-image, therefore fixing it to an empty value for instance in instances: if hasattr(instance, 'image'): if isinstance(instance.image, dict): instance.image['name'] = "-" def _task_get_volumes_snapshots(): volume_ids_with_snapshots.extend( self._get_volumes_ids_with_snapshots( search_opts={'all_tenants': True} )) def _task_get_volumes(): volumes.extend(self._get_volumes(search_opts=filters)) # update group name for volumes self._get_groups(volumes, search_opts={'all_tenants': True}) attached_instance_ids.extend( self._get_attached_instance_ids(volumes)) if 'project' in filters: futurist_utils.call_functions_parallel( _task_get_tenants, _task_get_instances, _task_get_volumes_snapshots ) tenant_ids = [t.id for t in tenants if t.name == filters['project']] if not tenant_ids: return [] del filters['project'] for id in tenant_ids: filters['project_id'] = id volumes += self._get_volumes(search_opts=filters) attached_instance_ids = self._get_attached_instance_ids(volumes) else: futurist_utils.call_functions_parallel( _task_get_volumes, _task_get_tenants, _task_get_instances, _task_get_volumes_snapshots ) self._set_volume_attributes( volumes, instances, volume_ids_with_snapshots) for volume in volumes: tenant_id = getattr(volume, "os-vol-tenant-attr:tenant_id", None) tenant = tenant_dict.get(tenant_id, None) volume.tenant_name = getattr(tenant, "name", None) return volumes
def get_instances_data(self): instances = [] if self.roles.__contains__( 'project_manager') or self.roles.__contains__('user'): marker = self.request.GET.get( project_tables.InstancesTable._meta.pagination_param, None) search_opts = {'marker': marker, 'paginate': True} image_dict, flavor_dict = futurist_utils.call_functions_parallel( self._get_images, self._get_flavors) instances = self._get_instances(search_opts) # Loop through instances to get flavor info. for instance in instances: if hasattr(instance, 'image'): # Instance from image returns dict if isinstance(instance.image, dict): image_id = instance.image.get('id') if image_id in image_dict: instance.image = image_dict[image_id] # In case image not found in image_dict, set name to empty # to avoid fallback API call to Glance in api/nova.py # until the call is deprecated in api itself else: instance.image['name'] = _("-") flavor_id = instance.flavor["id"] if flavor_id in flavor_dict: instance.full_flavor = flavor_dict[flavor_id] else: # If the flavor_id is not in flavor_dict, # put info in the log file. LOG.info( 'Unable to retrieve flavor "%s" for instance "%s".', flavor_id, instance.id) return instances else: marker = self.request.GET.get( instance_tables.AdminInstancesTable._meta.pagination_param, None) search_opts = { 'marker': marker, 'paginate': True, 'all_tenants': True } results = futurist_utils.call_functions_parallel( self._get_images, self._get_flavors, self._get_tenants) image_dict, flavor_dict, tenant_dict = results instances = self._get_instances(search_opts) # Loop through instances to get image, flavor and tenant info. for inst in instances: if hasattr(inst, 'image') and isinstance(inst.image, dict): image_id = inst.image.get('id') if image_id in image_dict: inst.image = image_dict[image_id] # In case image not found in image_map, set name to empty # to avoid fallback API call to Glance in api/nova.py # until the call is deprecated in api itself else: inst.image['name'] = _("-") flavor_id = inst.flavor["id"] try: if flavor_id in flavor_dict: inst.full_flavor = flavor_dict[flavor_id] else: # If the flavor_id is not in flavor_dict list, # gets it via nova api. inst.full_flavor = api.nova.flavor_get( self.request, flavor_id) except Exception: msg = _('Unable to retrieve instance size information.') exceptions.handle(self.request, msg) tenant = tenant_dict.get(inst.tenant_id, None) inst.tenant_name = getattr(tenant, "name", None) return instances
def get_data(self): marker = self.request.GET.get( project_tables.AdminInstancesTable._meta.pagination_param, None) default_search_opts = {'marker': marker, 'paginate': True, 'all_tenants': True} search_opts = self.get_filters(default_search_opts.copy()) # If filter_first is set and if there are not other filters # selected, then search criteria must be provided and return an empty # list filter_first = getattr(settings, 'FILTER_DATA_FIRST', {}) if (filter_first.get('admin.instances', False) and len(search_opts) == len(default_search_opts)): self._needs_filter_first = True self._more = False return [] self._needs_filter_first = False instances = self._get_instances(search_opts) results = futurist_utils.call_functions_parallel( (self._get_images, [tuple(instances)]), self._get_flavors, self._get_tenants) image_dict, flavor_dict, tenant_dict = results non_api_filter_info = ( ('project', 'tenant_id', tenant_dict.values()), ('image_name', 'image', image_dict.values()), ('flavor_name', 'flavor', flavor_dict.values()), ) if not views.process_non_api_filters(search_opts, non_api_filter_info): self._more = False return [] # Loop through instances to get image, flavor and tenant info. for inst in instances: if hasattr(inst, 'image') and isinstance(inst.image, dict): image_id = inst.image.get('id') if image_id in image_dict: inst.image = image_dict[image_id] # In case image not found in image_map, set name to empty # to avoid fallback API call to Glance in api/nova.py # until the call is deprecated in api itself else: inst.image['name'] = _("-") flavor_id = inst.flavor["id"] try: if flavor_id in flavor_dict: inst.full_flavor = flavor_dict[flavor_id] else: # If the flavor_id is not in flavor_dict list, # gets it via nova api. inst.full_flavor = api.nova.flavor_get( self.request, flavor_id) except Exception: msg = _('Unable to retrieve instance size information.') exceptions.handle(self.request, msg) tenant = tenant_dict.get(inst.tenant_id, None) inst.tenant_name = getattr(tenant, "name", None) return instances
def get_data(self): marker, sort_dir = self._get_marker() search_opts = self.get_filters({'marker': marker, 'paginate': True}) image_dict, flavor_dict, volume_dict = \ futurist_utils.call_functions_parallel( self._get_images, self._get_flavors, self._get_volumes ) non_api_filter_info = ( ('image_name', 'image', image_dict.values()), ('flavor_name', 'flavor', flavor_dict.values()), ) if not process_non_api_filters(search_opts, non_api_filter_info): self._more = False return [] instances = self._get_instances(search_opts, sort_dir) # Loop through instances to get flavor info. for instance in instances: if hasattr(instance, 'image'): # Instance from image returns dict if isinstance(instance.image, dict): image_id = instance.image.get('id') if image_id in image_dict: instance.image = image_dict[image_id] # In case image not found in image_dict, set name to empty # to avoid fallback API call to Glance in api/nova.py # until the call is deprecated in api itself else: instance.image['name'] = _("-") # Otherwise trying to get image from volume metadata else: instance_volumes = [ attachment for volume in volume_dict.values() for attachment in volume.attachments if attachment['server_id'] == instance.id ] # Sorting attached volumes by device name (eg '/dev/sda') instance_volumes.sort(key=lambda attach: attach['device']) # While instance from volume is being created, # it does not have volumes if instance_volumes: # Getting volume object, which is as attached # as the first device boot_volume = volume_dict[instance_volumes[0]['id']] if hasattr(boot_volume, "volume_image_metadata"): instance.image = image_dict[ boot_volume.volume_image_metadata['image_id'] ] flavor_id = instance.flavor["id"] if flavor_id in flavor_dict: instance.full_flavor = flavor_dict[flavor_id] else: # If the flavor_id is not in flavor_dict, # put info in the log file. LOG.info('Unable to retrieve flavor "%s" for instance "%s".', flavor_id, instance.id) return instances