diff --git a/dashboard/templates/layout.html b/dashboard/templates/layout.html
index 17ce5a6bd..41a30371c 100644
--- a/dashboard/templates/layout.html
+++ b/dashboard/templates/layout.html
@@ -265,8 +265,15 @@
diff --git a/dashboard/web.py b/dashboard/web.py
index a1cfe088e..7a9fefdde 100644
--- a/dashboard/web.py
+++ b/dashboard/web.py
@@ -47,11 +47,6 @@ METRIC_LABELS = {
'commits': 'Commits',
}
-PROJECT_TYPES = {
- 'openstack': 'OpenStack',
- 'stackforge': 'StackForge',
-}
-
DEFAULT_RECORDS_LIMIT = 10
@@ -96,6 +91,8 @@ def get_vault():
vault['modules'] = dict((r['module'].lower(),
r['project_type'].lower()) for r in modules)
app.stackalytics_vault = vault
+
+ init_project_types(vault)
else:
if not getattr(flask.request, 'stackalytics_updated', None):
flask.request.stackalytics_updated = True
@@ -110,6 +107,63 @@ def get_memory_storage():
return get_vault()['memory_storage']
+def init_project_types(vault):
+ persistent_storage_inst = vault['persistent_storage']
+ project_type_options = {}
+ project_type_group_index = {'all': set()}
+
+ for repo in persistent_storage_inst.get_repos():
+ project_type = repo['project_type'].lower()
+ project_group = None
+ if 'project_group' in repo:
+ project_group = repo['project_group'].lower()
+
+ if project_type in project_type_options:
+ if project_group:
+ project_type_options[project_type].add(project_group)
+ else:
+ if project_group:
+ project_type_options[project_type] = set([project_group])
+ else:
+ project_type_options[project_type] = set()
+
+ module = repo['module']
+ if project_type in project_type_group_index:
+ project_type_group_index[project_type].add(module)
+ else:
+ project_type_group_index[project_type] = set([module])
+
+ if project_group:
+ if project_group in project_type_group_index:
+ project_type_group_index[project_group].add(module)
+ else:
+ project_type_group_index[project_group] = set([module])
+
+ project_type_group_index['all'].add(module)
+
+ vault['project_type_options'] = project_type_options
+ vault['project_type_group_index'] = project_type_group_index
+
+
+def get_project_type_options():
+ return get_vault()['project_type_options']
+
+
+def is_project_type_valid(project_type):
+ if not project_type:
+ return False
+ project_type = project_type.lower()
+ if project_type == 'all':
+ return True
+ project_types = get_project_type_options()
+ if project_type in project_types:
+ return True
+ for p, g in project_types.iteritems():
+ if project_type in g:
+ return True
+ return False
+
+
# Utils ---------
def get_default(param_name):
@@ -158,9 +212,12 @@ def record_filter(ignore=None, use_default=True):
param = get_parameter(kwargs, 'project_type', 'project_types',
use_default)
if param:
- modules = [module for module, project_type
- in vault['modules'].iteritems()
- if project_type in param]
+ ptgi = vault['project_type_group_index']
+ modules = set()
+ for project_type in param:
+ project_type = project_type.lower()
+ if project_type in ptgi:
+ modules |= ptgi[project_type]
record_ids &= (
memory_storage.get_record_ids_by_modules(modules))
@@ -253,10 +310,9 @@ def templated(template=None):
ctx['metric_label'] = METRIC_LABELS[ctx['metric']]
project_type = flask.request.args.get('project_type')
- if project_type not in PROJECT_TYPES:
- project_type = None
- ctx['project_type'] = project_type or get_default('project_type')
- ctx['project_type_label'] = PROJECT_TYPES[ctx['project_type']]
+ if not is_project_type_valid(project_type):
+ project_type = get_default('project_type')
+ ctx['project_type'] = project_type
release = flask.request.args.get('release')
releases = vault['releases']
@@ -268,6 +324,8 @@ def templated(template=None):
release = releases[release]['release_name']
ctx['release'] = (release or get_default('release')).lower()
+ ctx['project_type_options'] = get_project_type_options()
+
return flask.render_template(template_name, **ctx)
return templated_decorated_function
diff --git a/etc/default_data.json b/etc/default_data.json
index 2fa74e475..88796723b 100644
--- a/etc/default_data.json
+++ b/etc/default_data.json
@@ -13482,6 +13482,7 @@
"branches": ["master"],
"module": "nova",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/nova.git",
"releases": [
{
@@ -13510,6 +13511,7 @@
"branches": ["master"],
"module": "keystone",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/keystone.git",
"releases": [
{
@@ -13538,6 +13540,7 @@
"branches": ["master"],
"module": "cinder",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/cinder.git",
"releases": [
{
@@ -13561,6 +13564,7 @@
"branches": ["master"],
"module": "glance",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/glance.git",
"releases": [
{
@@ -13589,6 +13593,7 @@
"branches": ["master"],
"module": "neutron",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/neutron.git",
"releases": [
{
@@ -13617,6 +13622,7 @@
"branches": ["master"],
"module": "horizon",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/horizon.git",
"releases": [
{
@@ -13645,6 +13651,7 @@
"branches": ["master"],
"module": "swift",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/swift.git",
"releases": [
{
@@ -13673,6 +13680,7 @@
"branches": ["master"],
"module": "python-keystoneclient",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/python-keystoneclient.git",
"releases": [
{
@@ -13696,6 +13704,7 @@
"branches": ["master"],
"module": "python-novaclient",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/python-novaclient.git",
"releases": [
{
@@ -13719,6 +13728,7 @@
"branches": ["master"],
"module": "python-cinderclient",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/python-cinderclient.git",
"releases": [
{
@@ -13737,6 +13747,7 @@
"branches": ["master"],
"module": "python-glanceclient",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/python-glanceclient.git",
"releases": [
{
@@ -13755,6 +13766,7 @@
"branches": ["master"],
"module": "python-neutronclient",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/python-neutronclient.git",
"releases": [
{
@@ -13778,6 +13790,7 @@
"branches": ["master"],
"module": "python-swiftclient",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/python-swiftclient.git",
"releases": [
{
@@ -13796,6 +13809,7 @@
"branches": ["master"],
"module": "heat",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/heat.git",
"releases": [
{
@@ -13814,6 +13828,7 @@
"branches": ["master"],
"module": "python-heatclient",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/python-heatclient.git",
"releases": [
{
@@ -13832,6 +13847,7 @@
"branches": ["master"],
"module": "ceilometer",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/ceilometer.git",
"releases": [
{
@@ -13850,6 +13866,7 @@
"branches": ["master"],
"module": "python-ceilometerclient",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/python-ceilometerclient.git",
"releases": [
{
@@ -13863,6 +13880,7 @@
"branches": ["master"],
"module": "oslo-incubator",
"project_type": "openstack",
+ "project_group": "incubation",
"uri": "git://github.com/openstack/oslo-incubator.git",
"releases": [
{
@@ -13876,6 +13894,7 @@
"branches": ["master"],
"module": "oslo.config",
"project_type": "openstack",
+ "project_group": "core",
"uri": "git://github.com/openstack/oslo.config.git",
"releases": [
{
@@ -13889,6 +13908,7 @@
"branches": ["master"],
"module": "compute-api",
"project_type": "openstack",
+ "project_group": "documentation",
"uri": "git://github.com/openstack/compute-api.git",
"releases": [
{
@@ -13902,6 +13922,7 @@
"branches": ["master"],
"module": "identity-api",
"project_type": "openstack",
+ "project_group": "documentation",
"uri": "git://github.com/openstack/identity-api.git",
"releases": [
{
@@ -13915,6 +13936,7 @@
"branches": ["master"],
"module": "image-api",
"project_type": "openstack",
+ "project_group": "documentation",
"uri": "git://github.com/openstack/image-api.git",
"releases": [
{
@@ -13928,6 +13950,7 @@
"branches": ["master"],
"module": "netconn-api",
"project_type": "openstack",
+ "project_group": "documentation",
"uri": "git://github.com/openstack/netconn-api.git",
"releases": [
{
@@ -13941,6 +13964,7 @@
"branches": ["master"],
"module": "object-api",
"project_type": "openstack",
+ "project_group": "documentation",
"uri": "git://github.com/openstack/object-api.git",
"releases": [
{
@@ -13954,6 +13978,7 @@
"branches": ["master"],
"module": "volume-api",
"project_type": "openstack",
+ "project_group": "documentation",
"uri": "git://github.com/openstack/volume-api.git",
"releases": [
{
@@ -13967,6 +13992,7 @@
"branches": ["master"],
"module": "openstack-manuals",
"project_type": "openstack",
+ "project_group": "documentation",
"uri": "git://github.com/openstack/openstack-manuals.git",
"releases": [
{
@@ -13990,6 +14016,7 @@
"branches": ["master"],
"module": "api-site",
"project_type": "openstack",
+ "project_group": "documentation",
"uri": "git://github.com/openstack/api-site.git",
"releases": [
{
@@ -14004,6 +14031,7 @@
"branches": ["master"],
"module": "devstack",
"project_type": "openstack",
+ "project_group": "other",
"uri": "git://github.com/openstack-dev/devstack.git",
"releases": [
{
@@ -14017,6 +14045,7 @@
"branches": ["master"],
"module": "tempest",
"project_type": "openstack",
+ "project_group": "other",
"uri": "git://github.com/openstack/tempest.git",
"releases": [
{
@@ -14030,6 +14059,7 @@
"branches": ["master"],
"module": "requirements",
"project_type": "openstack",
+ "project_group": "other",
"uri": "git://github.com/openstack/requirements.git",
"releases": [
{
@@ -14042,8 +14072,9 @@
{
"branches": ["master"],
- "module": "requirements",
- "project_type": "trove",
+ "module": "trove",
+ "project_type": "openstack",
+ "project_group": "incubation",
"uri": "git://github.com/openstack/trove.git",
"releases": [
{
@@ -14057,6 +14088,7 @@
"branches": ["master"],
"module": "trove-integration",
"project_type": "openstack",
+ "project_group": "incubation",
"uri": "git://github.com/openstack/trove-integration.git",
"releases": [
{
@@ -14070,6 +14102,7 @@
"branches": ["master"],
"module": "python-troveclient",
"project_type": "openstack",
+ "project_group": "incubation",
"uri": "git://github.com/openstack/python-troveclient.git",
"releases": [
{
@@ -14083,6 +14116,7 @@
"branches": ["master"],
"module": "ironic",
"project_type": "openstack",
+ "project_group": "incubation",
"uri": "git://github.com/openstack/ironic.git",
"releases": [
{