def list_az(self, req, tenant_id): ''' list availability-zones info ''' auth_token = req.headers.get("x-auth-token") result = ops_api.get_hosts_az(tenant_id, auth_token) return result
def get_az_capacity(self, req, tenant_id, az_name): """ get capacity for some az """ az_capacity = {} auth_token = req.headers.get("x-auth-token") hosts_capacity = ops_api.get_hosts_capacity(tenant_id, auth_token) zones = ops_api.get_hosts_az(tenant_id, auth_token) if "availability_zones" not in zones: LOG.warn("availability_zones does not exists in zones(%s)" % zones) zones = zones.get("availability_zones", []) az_hosts = [] for zone in zones: if az_name == zone["zoneName"]: az_hosts = zone["hosts"] break for hostname in hosts_capacity.keys(): if hostname in az_hosts: host_capacity = hosts_capacity.get(hostname, {}) if not az_capacity: az_capacity.update(host_capacity) else: for item in az_capacity.keys(): az_capacity[item] += host_capacity.get(item, 0) return az_capacity
def show_by_host(self, req, tenant_id): """ list platform usage """ def get_zone_by_host(zones, host): for zone in zones: if host in zone["hosts"]: return zone["zoneName"] auth_token = req.headers.get("x-auth-token") m = manager.Manager() usages = m.request_usages(models.HOST_LEVEL) hosts_capacity = ops_api.get_hosts_capacity(tenant_id, auth_token) zones = ops_api.get_hosts_az(tenant_id, auth_token) if "availability_zones" not in zones: LOG.warn("availability_zones does not exists in zones(%s)" % zones) zones = zones.get("availability_zones", []) for v in usages: # NOTE(hzzhoushaoyu): usages is a iterative value and here is only # one item. items = self._construct_usage(v) result = [] for hostname in items: value = items[hostname] value.update(hostname=hostname) value.update(hosts_capacity.get(hostname, {})) zone_name = get_zone_by_host(zones, hostname) value.update(availability_zone=zone_name) # FIXME : This is a little ugly. when instances in the host # doesn't use any floating ip, we need to set the # ips_used number to 0. Currently I can't find a much # proper place to do this thing. if "private_ips_used" not in value.keys(): value.update(private_ips_used=0) if "public_ips_used" not in value.keys(): value.update(public_ips_used=0) result.append(value) # Add statistics for hosts with no vms. for hostname in hosts_capacity.keys(): already_counted = False for value in result: if value["hostname"] == hostname: already_counted = True break if not already_counted: value = {} value.update(hostname=hostname) value.update(hosts_capacity.get(hostname, {})) value.update(private_ips_used=0) value.update(public_ips_used=0) zone_name = get_zone_by_host(zones, hostname) value.update(availability_zone=zone_name) result.append(value) result = list_filter.filter_host_usages(req, result) result = list_sort.sort_host_usage(req, result) return dict(hosts=result)
def get_item(self, data_key, used_key, level=models.PLATFORM_LEVEL, need_capacity=True, az_name=None): """ calculate usage for specify resource such as memory. :param data_key: key in usages for usage data list. :param used_key: key in each usage data for used calculating. :param token: admin auth token. :param level: calculating level(models.PLATFORM/HOST/AZ/USER_LEVEL) result[{data_key}] should look like: {"memory_mb": {"memory_mb": [ { "project_id": "xx1", "instance_id": "uuid1", "host": "host1", "memory_mb": 128 }, { "project_id": "xx2", "instance_id": "uuid2", "host": "host2", "memory_mb": 256 }, ] }, "capacity": 10240} :return : sample as: { 'memory_mb': { 'platform': [ { 'instance_id': 'uuid1', 'memory_mb': 128, 'host': 'host1', 'project_id': 'xx1' }, { 'instance_id': 'uuid2', 'memory_mb': 256, 'host': 'host2', 'project_id': 'xx2' } ], 'platform_used': 384 } } """ token = api.request_admin_token() if self.usage is None: try: result = api.get_usages(token["tenant"]["id"], token["id"]) except KeyError: LOG.exception(_("get usage failed.")) raise exc.HTTPFailedDependency(_("Nova or Keystone verstion not match.")) self.usage = result else: result = self.usage try: item_usage = calc_item(result[data_key][data_key], level, used_key) zone_usage = {} if level == models.AZ_LEVEL and az_name != None: for i in range(len(item_usage)): az_key = item_usage.keys()[i] # filter usage info by az_name if az_key == az_name: zone_usage.update({az_key: item_usage.get(az_key)}) elif az_key == "%s_used" % az_name: zone_usage.update({az_key: item_usage.get(az_key)}) item_usage = {} item_usage.update(zone_usage) else: zone_usage.update(item_usage) if not need_capacity: return item_usage # calculate platform capacity and remainder. item_capacity = result[data_key]["capacity"] if level == models.PLATFORM_LEVEL: # calculate remainder resource for platform level calc_resource_remainder(item_usage, item_capacity, None) item_usage.update({"platform_capacity": item_capacity}) if level == models.AZ_LEVEL: zones = api.get_hosts_az(token["tenant"]["id"], token["id"]) zones = zones["availability_zones"] host_capacities = api.get_hosts_capacity(token["tenant"]["id"], token["id"]) mapped_key = { "ecus": "ecus", "local_gb": "disk_gb", "memory_mb": "memory_mb", "public_qos": "public_network_qos_mbps", "private_qos": "private_network_qos_mbps", } for i in range(len(item_usage)): az = item_usage.keys()[i] if "_used" in az: continue capacity = 0 for zone in zones: if zone["zoneName"] == az: hosts = zone["hosts"] for host in hosts: host_capacity = host_capacities[host].get(mapped_key[data_key], 0) capacity += host_capacity zone_usage.update({"%s_capacity" % az: capacity}) calc_resource_remainder(zone_usage, capacity, None, unit=az) # AZ item_usage data structure sample as # { # u'nova_capacity': 1000, # u'nova': [ # { # u'instance_id': u'71c5ab41-b8e7-4d40-8439', # u'host': u'10-120-240-46', # u'project_id': u'dc32392af0ae4a098fb7235760077f', # u'type': u'public' # }, # { # u'instance_id': u'0f6c6354-3d92-45a5-8221', # u'host': u'10-120-240-46', # u'project_id': u'dc32392af0ae4a098fb7235760077', # u'type': u'public' # } # ], # u'nova_used': 0 # } item_usage = {} item_usage.update(zone_usage) return item_usage except KeyError: LOG.exception(_("Calculate %s usage failed.") % data_key) raise exception.ServiceUnavailable(_("Nova version not match."))
def calc_item(items, level, key): """ :param items: A list of all items, samples as: [ { "tenant_id": "xx1", "instance_id": "uuid1", "host": "host1", "{key}": 10 }, { "tenant_id": "xx2", "instance_id": "uuid2", "host": "host2", "{key}": 5 } ] :param level: specify which level to calcute usage :param key: specify which key is to be used as usage return sample as: {u'10-120-240-46': [ {u'instance_id': u'71c5ab41-b8e7', u'host': u'10-120-240-46', u'project_id': u'dc32392af0ae4a098fb7235760077fa6', u'local_gb': 10}, {u'instance_id': u'0f6c6354-3d92-45a5', u'host': u'10-120-240-46', u'project_id': u'dc32392af0ae4a098fb7235760077fa6', u'local_gb': 10}], u'10-120-240-46_used': 20} """ item_classify = {} zones = None if level == models.AZ_LEVEL: token = api.request_admin_token() all_az = api.get_hosts_az(token["tenant"]["id"], token["id"]) try: zones = all_az["availability_zones"] except: LOG.exception(_("Get AZ information error.")) raise for item in items: # NOTE(hzzhoushaoyu): item sample as: # {u'instance_id': u'0f6c6354-3d92-45a5-8221-aa0035c07f43', # u'host': u'10-120-240-46', u'local_gb': 10, # u'project_id': u'dc32392af0ae4a098fb7235760077fa6'} if not item: continue if level == models.PLATFORM_LEVEL: classify_item(item, item_classify, "platform") elif level == models.HOST_LEVEL: host = _get_item_host(item) if host is None: continue classify_item(item, item_classify, host) elif level == models.AZ_LEVEL: for zone in zones: if "hosts" not in zone: LOG.warn(_("Zone information does not contain hosts.")) hosts = zone.get("hosts", []) host = _get_item_host(item) if host in hosts: classify_item(item, item_classify, zone["zoneName"]) elif level == models.USER_LEVEL: classify_item(item, item_classify, item["project_id"]) if len(items) == 0 and level == models.PLATFORM_LEVEL: item_classify = {"platform": []} analysis_item_used(item_classify, key) return item_classify