Rewrite of the whole dashboard.
Change-Id: I91d2338ce3225e80ba4c53a1a88a5300d5af9c44
This commit is contained in:
parent
797a89586b
commit
3364dc8dd2
|
@ -13,3 +13,4 @@ htmlcov
|
|||
dist
|
||||
*.egg
|
||||
*.sw?
|
||||
.ropeproject
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[DEFAULT]
|
||||
test_command=${PYTHON:-python} -m subunit.run discover -t ./ ./cloudkittydashboard/tests $LISTOPT $IDOPTION
|
||||
test_id_option=--load-list $IDFILE
|
||||
test_list_option=--list
|
|
@ -0,0 +1,16 @@
|
|||
If you would like to contribute to the development of OpenStack,
|
||||
you must follow the steps in this page:
|
||||
|
||||
http://docs.openstack.org/infra/manual/developers.html
|
||||
|
||||
Once those steps have been completed, changes to OpenStack
|
||||
should be submitted for review via the Gerrit tool, following
|
||||
the workflow documented at:
|
||||
|
||||
http://docs.openstack.org/infra/manual/developers.html#development-workflow
|
||||
|
||||
Pull requests submitted through GitHub will be ignored.
|
||||
|
||||
Bugs should be filed on Launchpad, not GitHub:
|
||||
|
||||
https://bugs.launchpad.net/cloudkitty
|
|
@ -0,0 +1,4 @@
|
|||
cloudkitty-dashboard Style Commandments
|
||||
===============================================
|
||||
|
||||
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/
|
|
@ -0,0 +1,6 @@
|
|||
include AUTHORS
|
||||
include ChangeLog
|
||||
exclude .gitignore
|
||||
exclude .gitreview
|
||||
|
||||
global-exclude *.pyc
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack_dashboard.utils import settings
|
||||
|
||||
import cloudkittydashboard.enabled
|
||||
|
||||
|
||||
ADD_INSTALLED_APPS = ['cloudkittydashboard']
|
||||
UPDATE_HORIZON_CONFIG = {}
|
||||
DASHBOARD = ''
|
||||
|
||||
|
||||
settings.update_dashboards(
|
||||
(cloudkittydashboard.enabled,),
|
||||
UPDATE_HORIZON_CONFIG,
|
||||
ADD_INSTALLED_APPS
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import pbr.version
|
||||
|
||||
|
||||
__version__ = pbr.version.VersionInfo(
|
||||
'cloudkittydashboard').version_string()
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2014 Objectif Libre
|
||||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
|
@ -13,36 +13,36 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# @author: François Magimel (linkid)
|
||||
import collections
|
||||
|
||||
"""
|
||||
The API for the CloudKitty Horizon plugin.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from cloudkittyclient import client as cloudkitty_client
|
||||
from django.conf import settings
|
||||
from horizon.utils.memoized import memoized # noqa
|
||||
|
||||
from cloudkittyclient import client as ck_client
|
||||
from openstack_dashboard.api import base
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@memoized
|
||||
def cloudkittyclient(request):
|
||||
"""Initialization of CloudKitty client."""
|
||||
username = request.user.username
|
||||
token = request.user.token.id
|
||||
tenant_name = request.user.tenant_id
|
||||
endpoint = base.url_for(request, 'billing')
|
||||
auth_url = base.url_for(request, 'identity')
|
||||
"""Initialization of Cloudkitty client."""
|
||||
|
||||
LOG.debug('cloudkittyclient connection created using token "%s" '
|
||||
'and endpoint "%s"' % (request.user.token.id, endpoint))
|
||||
endpoint = base.url_for(request, 'rating')
|
||||
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
|
||||
cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None)
|
||||
return ck_client.Client('1', endpoint,
|
||||
token=(lambda: request.user.token.id),
|
||||
insecure=insecure,
|
||||
cacert=cacert)
|
||||
|
||||
return cloudkitty_client.Client('1',
|
||||
username=username,
|
||||
token=token,
|
||||
tenant_name=tenant_name,
|
||||
auth_url=auth_url,
|
||||
endpoint=endpoint)
|
||||
|
||||
def identify(what, name=False, key=None):
|
||||
if isinstance(what, collections.Iterable):
|
||||
for i in what:
|
||||
i.id = getattr(i, key or "%s_id" % i.key)
|
||||
if name:
|
||||
i.name = getattr(i, key or "%s_id" % i.key)
|
||||
else:
|
||||
what.id = getattr(what, key or "%s_id" % what.key)
|
||||
if name:
|
||||
what.name = getattr(what, key or "%s_id" % what.key)
|
||||
return what
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import horizon
|
||||
|
||||
from cloudkittydashboard.dashboards.admin.hashmap import panel as hashmap_panel
|
||||
from cloudkittydashboard.dashboards.admin.modules import panel as modules_panel
|
||||
|
||||
|
||||
class CloudkittyPanels(horizon.PanelGroup):
|
||||
slug = "cloudkitty"
|
||||
name = _("Rating")
|
||||
panels = (modules_panel.Modules,
|
||||
hashmap_panel.Hashmap)
|
|
@ -0,0 +1,107 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import forms
|
||||
|
||||
from cloudkittydashboard.api import cloudkitty as api
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CreateServiceForm(forms.SelfHandlingForm):
|
||||
name = forms.CharField(label=_("Name"))
|
||||
|
||||
def handle(self, request, data):
|
||||
name = data['name']
|
||||
LOG.info('Creating service with name %s' % (name))
|
||||
return api.cloudkittyclient(request).hashmap.services.create(name=name)
|
||||
|
||||
|
||||
class CreateFieldForm(forms.SelfHandlingForm):
|
||||
name = forms.CharField(label=_("Name"))
|
||||
service_id = forms.CharField(label=_("Service ID"),
|
||||
widget=forms.TextInput(
|
||||
attrs={'readonly': 'readonly'}))
|
||||
|
||||
def handle(self, request, data):
|
||||
name = data['name']
|
||||
service_id = data['service_id']
|
||||
LOG.info('Creating field with name %s' % (name))
|
||||
field_client = api.cloudkittyclient(request).hashmap.fields
|
||||
return field_client.create(name=name, service_id=service_id)
|
||||
|
||||
|
||||
class CreateMappingForm(forms.SelfHandlingForm):
|
||||
cost = forms.DecimalField(label=_("Cost"))
|
||||
type = forms.ChoiceField(label=_("Type"),
|
||||
choices=(("flat", _("Flat")),
|
||||
("rate", _("Rate")),
|
||||
("threshold", _("Threshold"))))
|
||||
group_id = forms.CharField(label=_("Group"), required=False)
|
||||
|
||||
def handle(self, request, data):
|
||||
mapping_client = api.cloudkittyclient(request).hashmap.mappings
|
||||
mapping = {k: v for k, v in data.items() if v and v != ''}
|
||||
return mapping_client.create(**mapping)
|
||||
|
||||
|
||||
class CreateFieldMappingForm(CreateMappingForm):
|
||||
field_id = forms.CharField(label=_("Field ID"),
|
||||
widget=forms.TextInput(
|
||||
attrs={'readonly': 'readonly'}),
|
||||
required=False)
|
||||
value = forms.CharField(label=_("Value"))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CreateFieldMappingForm, self).__init__(*args, **kwargs)
|
||||
self.fields.keyOrder = ['value',
|
||||
'cost',
|
||||
'type',
|
||||
'group_id',
|
||||
'field_id']
|
||||
|
||||
|
||||
class CreateServiceMappingForm(CreateMappingForm):
|
||||
service_id = forms.CharField(label=_("Service ID"),
|
||||
widget=forms.TextInput(
|
||||
attrs={'readonly': 'readonly'}),
|
||||
required=False)
|
||||
|
||||
|
||||
class EditServiceMappingForm(CreateServiceMappingForm):
|
||||
mapping_id = forms.CharField(label=_("Mapping ID"),
|
||||
widget=forms.TextInput(
|
||||
attrs={'readonly': 'readonly'}))
|
||||
|
||||
def handle(self, request, data):
|
||||
mapping_client = api.cloudkittyclient(request).hashmap.mappings
|
||||
mapping = {k: v for k, v in data.items() if v and v != ''}
|
||||
mapping['mapping_id'] = self.initial['mapping_id']
|
||||
return mapping_client.update(**mapping)
|
||||
|
||||
|
||||
class EditFieldMappingForm(CreateFieldMappingForm):
|
||||
mapping_id = forms.CharField(label=_("Mapping ID"),
|
||||
widget=forms.TextInput(
|
||||
attrs={'readonly': 'readonly'}))
|
||||
|
||||
def handle(self, request, data):
|
||||
mapping_client = api.cloudkittyclient(request).hashmap.mappings
|
||||
mapping = {k: v for k, v in data.items() if v and v != ''}
|
||||
mapping['mapping_id'] = self.initial['mapping_id']
|
||||
return mapping_client.update(**mapping)
|
|
@ -0,0 +1,22 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
|
||||
class Hashmap(horizon.Panel):
|
||||
name = _("Hashmap")
|
||||
slug = "hashmap"
|
|
@ -0,0 +1,227 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import tables
|
||||
from horizon import tabs
|
||||
|
||||
from cloudkittydashboard.api import cloudkitty as api
|
||||
|
||||
|
||||
class CreateService(tables.LinkAction):
|
||||
name = "createservice"
|
||||
verbose_name = _("Create new Service")
|
||||
url = 'horizon:admin:hashmap:service_create'
|
||||
icon = "create"
|
||||
ajax = True
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class DeleteService(tables.BatchAction):
|
||||
name = "deleteservice"
|
||||
verbose_name = _("Delete Service")
|
||||
action_present = _("Delete")
|
||||
action_past = _("Deleted")
|
||||
data_type_singular = _("Service")
|
||||
data_type_plural = _("Services")
|
||||
icon = "remove"
|
||||
|
||||
def action(self, request, service_id):
|
||||
api.cloudkittyclient(request).hashmap.services.delete(
|
||||
service_id=service_id
|
||||
)
|
||||
|
||||
|
||||
class ServicesTable(tables.DataTable):
|
||||
"""This table list the available services.
|
||||
|
||||
Clicking on a service name sends you to a ServiceTabs page.
|
||||
"""
|
||||
name = tables.Column('name', verbose_name=_("Name"),
|
||||
link='horizon:admin:hashmap:service')
|
||||
|
||||
class Meta(object):
|
||||
name = "services"
|
||||
verbose_name = _("Services")
|
||||
table_actions = (CreateService,)
|
||||
row_actions = (DeleteService,)
|
||||
|
||||
|
||||
class DeleteField(tables.BatchAction):
|
||||
name = "deletefield"
|
||||
verbose_name = _("Delete Field")
|
||||
action_present = _("Delete")
|
||||
action_past = _("Deleted")
|
||||
data_type_singular = _("Field")
|
||||
data_type_plural = _("Fields")
|
||||
icon = "remove"
|
||||
|
||||
def action(self, request, field_id):
|
||||
api.cloudkittyclient(request).hashmap.fields.delete(
|
||||
field_id=field_id
|
||||
)
|
||||
|
||||
|
||||
class CreateField(tables.LinkAction):
|
||||
name = "createfield"
|
||||
verbose_name = _("Create new Field")
|
||||
icon = "create"
|
||||
ajax = True
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
def get_link_url(self, datum=None):
|
||||
url = 'horizon:admin:hashmap:field_create'
|
||||
service_id = self.table.request.service_id
|
||||
return reverse(url, args=[service_id])
|
||||
|
||||
|
||||
class FieldsTable(tables.DataTable):
|
||||
"""This table lists the available fields for a given service.
|
||||
|
||||
Clicking on a fields sends you to a MappingsTable.
|
||||
"""
|
||||
name = tables.Column('name', verbose_name=_("Name"),
|
||||
link='horizon:admin:hashmap:field')
|
||||
|
||||
class Meta(object):
|
||||
name = "fields"
|
||||
verbose_name = _("Fields")
|
||||
multi_select = False
|
||||
row_actions = (DeleteField,)
|
||||
table_actions = (CreateField,)
|
||||
|
||||
|
||||
class FieldsTab(tabs.TableTab):
|
||||
name = _("Fields")
|
||||
slug = "hashmap_fields"
|
||||
table_classes = (FieldsTable,)
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
preload = True
|
||||
|
||||
def get_fields_data(self):
|
||||
client = api.cloudkittyclient(self.request)
|
||||
fields = client.hashmap.fields.list(service_id=self.request.service_id)
|
||||
return api.identify(fields)
|
||||
|
||||
|
||||
class DeleteMapping(tables.BatchAction):
|
||||
name = "deletemapping"
|
||||
verbose_name = _("Delete Mapping")
|
||||
action_present = _("Delete")
|
||||
action_past = _("Deleted")
|
||||
data_type_singular = _("Mapping")
|
||||
data_type_plural = _("Mappings")
|
||||
icon = "remove"
|
||||
|
||||
def action(self, request, mapping_id):
|
||||
api.cloudkittyclient(request).hashmap.mappings.delete(
|
||||
mapping_id=mapping_id
|
||||
)
|
||||
|
||||
|
||||
class CreateServiceMapping(tables.LinkAction):
|
||||
name = "createiservicemapping"
|
||||
verbose_name = _("Create new Mapping")
|
||||
icon = "create"
|
||||
ajax = True
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
def get_link_url(self, datum=None):
|
||||
url = 'horizon:admin:hashmap:service_mapping_create'
|
||||
service_id = self.table.request.service_id
|
||||
return reverse(url, args=[service_id])
|
||||
|
||||
|
||||
class EditServiceMapping(tables.LinkAction):
|
||||
name = "editservicemapping"
|
||||
verbose_name = _("Edit Mapping")
|
||||
icon = "edit"
|
||||
ajax = True
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
def get_link_url(self, datum=None):
|
||||
url = 'horizon:admin:hashmap:service_mapping_edit'
|
||||
return reverse(url, args=[datum.mapping_id])
|
||||
|
||||
|
||||
class ServiceMappingsTable(tables.DataTable):
|
||||
cost = tables.Column('cost', verbose_name=_("Cost"))
|
||||
type = tables.Column('type', verbose_name=_("Type"))
|
||||
group_id = tables.Column('group_id', verbose_name=_("Group"))
|
||||
|
||||
class Meta(object):
|
||||
name = "mappings"
|
||||
verbose_name = _("Mappings")
|
||||
row_actions = (EditServiceMapping, DeleteMapping)
|
||||
table_actions = (CreateServiceMapping,)
|
||||
|
||||
|
||||
class CreateFieldMapping(tables.LinkAction):
|
||||
name = "createfieldmapping"
|
||||
verbose_name = _("Create new Mapping")
|
||||
icon = "create"
|
||||
ajax = True
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
def get_link_url(self, datum=None):
|
||||
url = 'horizon:admin:hashmap:field_mapping_create'
|
||||
field_id = self.table.request.field_id
|
||||
return reverse(url, args=[field_id])
|
||||
|
||||
|
||||
class EditFieldMapping(tables.LinkAction):
|
||||
name = "editfieldmapping"
|
||||
verbose_name = _("Edit Mapping")
|
||||
icon = "edit"
|
||||
ajax = True
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
def get_link_url(self, datum=None):
|
||||
url = 'horizon:admin:hashmap:field_mapping_edit'
|
||||
return reverse(url, args=[datum.mapping_id])
|
||||
|
||||
|
||||
class FieldMappingsTable(tables.DataTable):
|
||||
value = tables.Column('value', verbose_name=_("Value"))
|
||||
cost = tables.Column('cost', verbose_name=_("Cost"))
|
||||
type = tables.Column('type', verbose_name=_("Type"))
|
||||
group_id = tables.Column('group_id', verbose_name=_("Group"))
|
||||
|
||||
class Meta(object):
|
||||
name = "mappings"
|
||||
verbose_name = _("Mappings")
|
||||
row_actions = (EditFieldMapping, DeleteMapping)
|
||||
table_actions = (CreateFieldMapping,)
|
||||
|
||||
|
||||
class MappingsTab(tabs.TableTab):
|
||||
name = _("Mappings")
|
||||
slug = "hashmap_mappings"
|
||||
table_classes = (ServiceMappingsTable,)
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
preload = True
|
||||
|
||||
def get_mappings_data(self):
|
||||
client = api.cloudkittyclient(self.request)
|
||||
mappings = client.hashmap.mappings.list(
|
||||
service_id=self.request.service_id
|
||||
)
|
||||
return api.identify(mappings)
|
||||
|
||||
|
||||
class ServiceTabs(tabs.TabGroup):
|
||||
slug = "services_tabs"
|
||||
tabs = (FieldsTab, MappingsTab)
|
||||
sticky = True
|
|
@ -0,0 +1,13 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Fields" %}{% endblock %}
|
||||
|
||||
|
||||
{% block main %}
|
||||
|
||||
{{ table.render }}
|
||||
|
||||
{{ modules }}
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Hashmap" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,16 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Services" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Services") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
{{ table.render }}
|
||||
|
||||
{{ modules }}
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from horizon.test import helpers as test
|
||||
|
||||
|
||||
class CkprojectTests(test.TestCase):
|
||||
# Unit tests for ckproject.
|
||||
def test_me(self):
|
||||
self.assertTrue(1 + 1 == 2)
|
|
@ -0,0 +1,47 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.conf.urls import patterns
|
||||
from django.conf.urls import url
|
||||
|
||||
from cloudkittydashboard.dashboards.admin.hashmap import views
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||
url(r'^service/(?P<service_id>[^/]+)/?$',
|
||||
views.ServiceView.as_view(),
|
||||
name='service'),
|
||||
url(r'^create_service/?$',
|
||||
views.ServiceCreateView.as_view(),
|
||||
name='service_create'),
|
||||
url(r'^field/(?P<field_id>[^/]+)/?$',
|
||||
views.FieldView.as_view(),
|
||||
name='field'),
|
||||
url(r'^create_field/service/(?P<service_id>[^/]+)/?$',
|
||||
views.FieldCreateView.as_view(),
|
||||
name='field_create'),
|
||||
url(r'^create_mapping/service/(?P<service_id>[^/]+)/?$',
|
||||
views.ServiceMappingCreateView.as_view(),
|
||||
name='service_mapping_create'),
|
||||
url(r'^create_mapping/field/(?P<field_id>[^/]+)/?$',
|
||||
views.FieldMappingCreateView.as_view(),
|
||||
name='field_mapping_create'),
|
||||
url(r'^edit_mapping/service/(?P<mapping_id>[^/]+)/?$',
|
||||
views.ServiceMappingEditView.as_view(),
|
||||
name='service_mapping_edit'),
|
||||
url(r'^edit_mapping/field/(?P<mapping_id>[^/]+)/?$',
|
||||
views.FieldMappingEditView.as_view(),
|
||||
name='field_mapping_edit'),
|
||||
)
|
|
@ -0,0 +1,194 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from horizon import forms
|
||||
from horizon import tables
|
||||
from horizon import tabs
|
||||
|
||||
from cloudkittydashboard.api import cloudkitty as api
|
||||
from cloudkittydashboard.dashboards.admin.hashmap import forms as hashmap_forms
|
||||
from cloudkittydashboard.dashboards.admin.hashmap \
|
||||
import tables as hashmap_tables
|
||||
|
||||
|
||||
class IndexView(tables.DataTableView):
|
||||
table_class = hashmap_tables.ServicesTable
|
||||
template_name = "admin/hashmap/services_list.html"
|
||||
|
||||
def get_data(self):
|
||||
out = api.cloudkittyclient(self.request).hashmap.services.list()
|
||||
return api.identify(out)
|
||||
|
||||
|
||||
class ServiceView(tabs.TabbedTableView):
|
||||
tab_group_class = hashmap_tables.ServiceTabs
|
||||
template_name = 'admin/hashmap/service_details.html'
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
service = api.cloudkittyclient(self.request).hashmap.services.get(
|
||||
service_id=kwargs['service_id']
|
||||
)
|
||||
self.request.service_id = service.service_id
|
||||
self.page_title = "Hashmap Service : %s" % service.name
|
||||
return super(ServiceView, self).get(*args, **kwargs)
|
||||
|
||||
|
||||
class ServiceCreateView(forms.ModalFormView):
|
||||
form_class = hashmap_forms.CreateServiceForm
|
||||
template_name = 'horizon/common/modal_form.html'
|
||||
success_url = reverse_lazy('horizon:admin:hashmap:index')
|
||||
submit_url = reverse_lazy('horizon:admin:hashmap:service_create')
|
||||
|
||||
def get_object_id(self, obj):
|
||||
return obj.service_id
|
||||
|
||||
|
||||
class FieldView(tables.DataTableView):
|
||||
table_class = hashmap_tables.FieldMappingsTable
|
||||
template_name = 'admin/hashmap/field_details.html'
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
field = api.cloudkittyclient(self.request).hashmap.fields.get(
|
||||
field_id=kwargs['field_id']
|
||||
)
|
||||
self.request.field_id = field.field_id
|
||||
self.page_title = "Hashmap Field : %s" % field.name
|
||||
return super(FieldView, self).get(*args, **kwargs)
|
||||
|
||||
def get_data(self):
|
||||
out = api.cloudkittyclient(self.request).hashmap.mappings.list(
|
||||
field_id=self.kwargs['field_id']
|
||||
)
|
||||
return api.identify(out)
|
||||
|
||||
|
||||
class FieldCreateView(forms.ModalFormView):
|
||||
form_class = hashmap_forms.CreateFieldForm
|
||||
template_name = 'horizon/common/modal_form.html'
|
||||
success_url = 'horizon:admin:hashmap:service'
|
||||
submit_url = 'horizon:admin:hashmap:field_create'
|
||||
|
||||
def get_object_id(self, obj):
|
||||
return obj.field_id
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(FieldCreateView, self).get_context_data(**kwargs)
|
||||
context["service_id"] = self.kwargs['service_id']
|
||||
args = (self.kwargs['service_id'],)
|
||||
context['submit_url'] = reverse_lazy(self.submit_url, args=args)
|
||||
return context
|
||||
|
||||
def get_initial(self):
|
||||
return {"service_id": self.kwargs["service_id"]}
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
args = (self.kwargs['service_id'],)
|
||||
return reverse_lazy(self.success_url, args=args)
|
||||
|
||||
|
||||
class ServiceMappingCreateView(forms.ModalFormView):
|
||||
form_class = hashmap_forms.CreateServiceMappingForm
|
||||
template_name = 'horizon/common/modal_form.html'
|
||||
submit_url = 'horizon:admin:hashmap:service_mapping_create'
|
||||
|
||||
def get_object_id(self, obj):
|
||||
return obj.mapping_id
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ServiceMappingCreateView,
|
||||
self).get_context_data(**kwargs)
|
||||
context["service_id"] = self.kwargs.get('service_id')
|
||||
context['submit_url'] = reverse_lazy(self.submit_url,
|
||||
args=(context['service_id'], ))
|
||||
return context
|
||||
|
||||
def get_initial(self):
|
||||
return {"service_id": self.kwargs.get("service_id")}
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
return reverse('horizon:admin:hashmap:service',
|
||||
args=(self.kwargs['service_id'],))
|
||||
|
||||
|
||||
class ServiceMappingEditView(ServiceMappingCreateView):
|
||||
form_class = hashmap_forms.EditServiceMappingForm
|
||||
submit_url = 'horizon:admin:hashmap:service_mapping_edit'
|
||||
|
||||
def get_initial(self):
|
||||
out = api.cloudkittyclient(self.request).hashmap.mappings.get(
|
||||
mapping_id=self.kwargs['mapping_id'])
|
||||
self.initial = out.to_dict()
|
||||
return self.initial
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ServiceMappingEditView,
|
||||
self).get_context_data(**kwargs)
|
||||
context["mapping_id"] = self.kwargs.get('mapping_id')
|
||||
context['submit_url'] = reverse_lazy(self.submit_url,
|
||||
args=(context['mapping_id'], ))
|
||||
return context
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
return reverse('horizon:admin:hashmap:service',
|
||||
args=(self.initial['service_id'], ))
|
||||
|
||||
|
||||
class FieldMappingCreateView(forms.ModalFormView):
|
||||
form_class = hashmap_forms.CreateFieldMappingForm
|
||||
template_name = 'horizon/common/modal_form.html'
|
||||
submit_url = 'horizon:admin:hashmap:field_mapping_create'
|
||||
|
||||
def get_object_id(self, obj):
|
||||
return obj.mapping_id
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(FieldMappingCreateView,
|
||||
self).get_context_data(**kwargs)
|
||||
context["field_id"] = self.kwargs.get('field_id')
|
||||
context['submit_url'] = reverse_lazy(self.submit_url,
|
||||
args=(context['field_id'], ))
|
||||
return context
|
||||
|
||||
def get_initial(self):
|
||||
return {"field_id": self.kwargs.get("field_id")}
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
return reverse('horizon:admin:hashmap:field',
|
||||
args=(self.kwargs['field_id'], ))
|
||||
|
||||
|
||||
class FieldMappingEditView(FieldMappingCreateView):
|
||||
form_class = hashmap_forms.EditFieldMappingForm
|
||||
submit_url = 'horizon:admin:hashmap:field_mapping_edit'
|
||||
|
||||
def get_initial(self):
|
||||
out = api.cloudkittyclient(self.request).hashmap.mappings.get(
|
||||
mapping_id=self.kwargs['mapping_id'])
|
||||
self.initial = out.to_dict()
|
||||
return self.initial
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(FieldMappingEditView,
|
||||
self).get_context_data(**kwargs)
|
||||
context["mapping_id"] = self.kwargs.get('mapping_id')
|
||||
context['submit_url'] = reverse_lazy(self.submit_url,
|
||||
args=(context['mapping_id'], ))
|
||||
return context
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
return reverse('horizon:admin:hashmap:field',
|
||||
args=(self.initial['field_id'], ))
|
|
@ -0,0 +1,22 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
|
||||
class Modules(horizon.Panel):
|
||||
name = _("Rating Modules")
|
||||
slug = "rating_modules"
|
|
@ -0,0 +1,60 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import tables
|
||||
|
||||
from cloudkittydashboard.api import cloudkitty as api
|
||||
|
||||
ENABLE = 0
|
||||
DISABLE = 1
|
||||
|
||||
|
||||
class ToggleEnabledModule(tables.BatchAction):
|
||||
name = "toggle_module"
|
||||
action_present = (_("Enable"), _("Disable"))
|
||||
action_past = (_("Enabled"), _("Disabled"))
|
||||
data_type_singular = _("Module")
|
||||
data_type_plural = _("Modules")
|
||||
classes = ("btn-toggle",)
|
||||
|
||||
def allowed(self, request, module=None):
|
||||
self.enabled = module.enabled
|
||||
if self.enabled:
|
||||
self.current_present_action = DISABLE
|
||||
else:
|
||||
self.current_present_action = ENABLE
|
||||
return True
|
||||
|
||||
def action(self, request, obj_id):
|
||||
module = api.cloudkittyclient(request).modules.get(module_id=obj_id)
|
||||
self.enabled = module.enabled
|
||||
if self.enabled:
|
||||
self.current_past_action = DISABLE
|
||||
module.disable()
|
||||
else:
|
||||
module.enable()
|
||||
self.current_past_action = ENABLE
|
||||
|
||||
|
||||
class ModulesTable(tables.DataTable):
|
||||
name = tables.Column('name', verbose_name=_("Name"))
|
||||
description = tables.Column('description', verbose_name=_("Description"))
|
||||
hot_config = tables.Column('hot-config', verbose_name=_("Configurable"))
|
||||
enabled = tables.Column('enabled', verbose_name=_("Enabled"))
|
||||
|
||||
class Meta(object):
|
||||
name = "modules"
|
||||
verbose_name = _("Modules")
|
||||
row_actions = (ToggleEnabledModule,)
|
|
@ -0,0 +1,16 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Modules" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Modules") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
{{ table.render }}
|
||||
|
||||
{{ modules }}
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
from horizon.test import helpers as test
|
||||
|
||||
|
||||
class CkprojectTests(test.TestCase):
|
||||
# Unit tests for ckproject.
|
||||
def test_me(self):
|
||||
self.assertTrue(1 + 1 == 2)
|
|
@ -0,0 +1,24 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.conf.urls import patterns
|
||||
from django.conf.urls import url
|
||||
|
||||
from cloudkittydashboard.dashboards.admin.modules.views \
|
||||
import IndexView
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^$', IndexView.as_view(), name='index'),
|
||||
)
|
|
@ -0,0 +1,32 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from horizon import tables
|
||||
|
||||
from cloudkittydashboard.api import cloudkitty as api
|
||||
from cloudkittydashboard.dashboards.admin.modules import tables as admin_tables
|
||||
|
||||
|
||||
class IndexView(tables.DataTableView):
|
||||
# A very simple class-based view...
|
||||
template_name = 'admin/rating_modules/index.html'
|
||||
table_class = admin_tables.ModulesTable
|
||||
|
||||
def get_data(self):
|
||||
# Add data to the context here...
|
||||
modules = api.identify(
|
||||
api.cloudkittyclient(self.request).modules.list(),
|
||||
name=True
|
||||
)
|
||||
return modules
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import horizon
|
||||
from openstack_dashboard.dashboards.project import dashboard
|
||||
|
||||
|
||||
class Project_rating(horizon.Panel):
|
||||
name = _("Rating")
|
||||
slug = "rating"
|
||||
|
||||
|
||||
dashboard.Project.register(Project_rating)
|
|
@ -0,0 +1,15 @@
|
|||
{% include 'project/instances/_launch_details_help.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
|
||||
{% block price %}
|
||||
<table class="flavor_table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="price">{% trans "Price" %}</td><td><span id="price"></span> {% trans "$" %}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
|
||||
<script src='{% static "cloudkitty/js/pricing.js" %}' type='text/javascript' charset='utf-8'></script>
|
|
@ -0,0 +1,13 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Rating" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Rating") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
Total : {{ total }}
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
from horizon.test import helpers as test
|
||||
|
||||
|
||||
class CkprojectTests(test.TestCase):
|
||||
# Unit tests for ckproject.
|
||||
def test_me(self):
|
||||
self.assertTrue(1 + 1 == 2)
|
|
@ -0,0 +1,24 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.conf.urls import patterns
|
||||
from django.conf.urls import url
|
||||
|
||||
from cloudkittydashboard.dashboards.project.rating import views
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||
url(r'^quote$', views.quote, name='quote')
|
||||
)
|
|
@ -0,0 +1,49 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
|
||||
from django import http
|
||||
from horizon import exceptions
|
||||
from horizon import views
|
||||
|
||||
from cloudkittydashboard.api import cloudkitty as api
|
||||
|
||||
|
||||
class IndexView(views.APIView):
|
||||
# A very simple class-based view...
|
||||
template_name = 'project/rating/index.html'
|
||||
|
||||
def get_data(self, request, context, *args, **kwargs):
|
||||
# Add data to the context here...
|
||||
total = api.cloudkittyclient(request).reports.get_total(
|
||||
tenant_id=request.user.tenant_id) or 0.00
|
||||
context['total'] = total
|
||||
return context
|
||||
|
||||
|
||||
def quote(request):
|
||||
pricing = "0"
|
||||
if request.is_ajax():
|
||||
if request.method == 'POST':
|
||||
json_data = json.loads(request.body)
|
||||
try:
|
||||
pricing = (api.cloudkittyclient(request)
|
||||
.quotations.quote(json_data))
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Unable to retrieve price.'))
|
||||
|
||||
return http.HttpResponse(json.dumps(pricing),
|
||||
content_type='application/json')
|
|
@ -0,0 +1,17 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
PANEL_GROUP = 'rating'
|
||||
PANEL_GROUP_NAME = 'Rating'
|
||||
PANEL_GROUP_DASHBOARD = 'admin'
|
|
@ -0,0 +1,17 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
PANEL_GROUP = 'rating'
|
||||
PANEL_GROUP_NAME = 'Rating'
|
||||
PANEL_GROUP_DASHBOARD = 'project'
|
|
@ -0,0 +1,21 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
PANEL_GROUP = 'rating'
|
||||
PANEL_DASHBOARD = 'admin'
|
||||
PANEL = 'hashmap'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = \
|
||||
'cloudkittydashboard.dashboards.admin.hashmap.panel.Hashmap'
|
|
@ -0,0 +1,21 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
PANEL_GROUP = 'rating'
|
||||
PANEL_DASHBOARD = 'admin'
|
||||
PANEL = 'rating_modules'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = \
|
||||
'cloudkittydashboard.dashboards.admin.modules.panel.Modules'
|
|
@ -0,0 +1,24 @@
|
|||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
PANEL_GROUP = 'rating'
|
||||
PANEL_DASHBOARD = 'project'
|
||||
PANEL = 'rating'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = \
|
||||
'cloudkittydashboard.dashboards.project.rating.panel.Project_rating'
|
||||
|
||||
UPDATE_HORIZON_CONFIG = {'customization_module':
|
||||
"cloudkittydashboard.overrides"}
|
|
@ -0,0 +1,38 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2015 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from django.conf.urls import patterns # noqa
|
||||
from django.conf.urls import url # noqa
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from openstack_dashboard.dashboards.project.instances.workflows \
|
||||
import create_instance
|
||||
|
||||
|
||||
# Instances Panel
|
||||
class InstancePredictivePricing(create_instance.SetInstanceDetailsAction):
|
||||
class Meta(object):
|
||||
name = _("Details")
|
||||
help_text_template = ("project/rating/"
|
||||
"_launch_details_price.html")
|
||||
|
||||
def get_help_text(self, extra_context=None):
|
||||
extra = extra_context or {}
|
||||
extra['price'] = 0
|
||||
extra = super(InstancePredictivePricing,
|
||||
self).get_help_text(extra_context=extra)
|
||||
return extra
|
||||
|
||||
create_instance.SetInstanceDetails.action_class = InstancePredictivePricing
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
Copyright 2015 Objectif Libre
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
pricing = {
|
||||
is_price: false, // Is this a price display ?
|
||||
|
||||
init: function() {
|
||||
this._attachInputHandlers(); // handler
|
||||
},
|
||||
|
||||
init_work: function() {
|
||||
this.is_price = true;
|
||||
//$('#price').text('0');
|
||||
|
||||
this.init();
|
||||
this.work();
|
||||
},
|
||||
|
||||
/*
|
||||
Attaches event handlers for the form elements associated with the price
|
||||
(see horizon.Quota._attachInputHandlers).
|
||||
*/
|
||||
_attachInputHandlers: function() {
|
||||
var scope = this;
|
||||
|
||||
if (this.is_price) {
|
||||
var eventCallback = function(evt) {
|
||||
scope.work();
|
||||
};
|
||||
|
||||
$('#id_flavor').on('change', eventCallback);
|
||||
$('#id_count').on('keyup', eventCallback);
|
||||
$('#id_image_id').on('change', eventCallback);
|
||||
}
|
||||
},
|
||||
|
||||
work: function() {
|
||||
// Quota available → what about the selected flavor
|
||||
if (horizon.Quota.selected_flavor) {
|
||||
// get data of the flavor (form)
|
||||
_image = horizon.Quota.getSelectedImage();
|
||||
var flavor = horizon.Quota.selected_flavor.name;
|
||||
var vcpus = horizon.Quota.selected_flavor.vcpus;
|
||||
var disk = horizon.Quota.selected_flavor.disk;
|
||||
var ephemeral = horizon.Quota.selected_flavor["OS-FLV-EXT-DATA:ephemeral"];
|
||||
var disk_total = horizon.Quota.selected_flavor.disk + horizon.Quota.selected_flavor["OS-FLV-EXT-DATA:ephemeral"];
|
||||
var disk_total_display = disk_total;
|
||||
var ram = horizon.Quota.selected_flavor.ram;
|
||||
var source_type = $('#id_source_type option:selected').val();
|
||||
var source_val = $('#id_' + source_type + ' option:selected').val();
|
||||
var instance_count = parseInt($("#id_count").val());
|
||||
|
||||
// make the json data form
|
||||
desc_form = {
|
||||
'flavor': flavor,
|
||||
'source_type': source_type,
|
||||
'source_val': source_val, // images : horizon.Quota.findImageById(source_val);
|
||||
'vcpus': vcpus,
|
||||
'disk': disk,
|
||||
'ephemeral': ephemeral,
|
||||
'disk_total': disk_total,
|
||||
'disk_total_display': disk_total_display,
|
||||
'ram': ram
|
||||
}
|
||||
if (_image != undefined) {
|
||||
desc_form['image_id'] = _image.id
|
||||
}
|
||||
var form_data = [{"service": "compute", "desc": desc_form, "volume": instance_count}];
|
||||
|
||||
// send the JSON by a POST request
|
||||
var url_data = '/project/rating/quote';
|
||||
this.sendPost(form_data, url_data);
|
||||
}
|
||||
},
|
||||
|
||||
sendPost: function(form_data, url_data) {
|
||||
$.ajax({
|
||||
type: "post", // send POST data
|
||||
url: url_data,
|
||||
dataType: 'json',
|
||||
data: JSON.stringify(form_data), // data sent
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
success: function (data) {
|
||||
$("#price").text(data);
|
||||
},
|
||||
beforeSend: function(xhr, settings){
|
||||
$.ajaxSettings.beforeSend(xhr, settings);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
|
||||
// http://stackoverflow.com/a/6199592
|
||||
// http://coreymaynard.com/blog/performing-ajax-post-requests-in-django/
|
||||
function getCookie(name) {
|
||||
var cookieValue = null;
|
||||
if (document.cookie && document.cookie != '') {
|
||||
var cookies = document.cookie.split(';');
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
var cookie = jQuery.trim(cookies[i]);
|
||||
// Does this cookie string begin with the name we want?
|
||||
if (cookie.substring(0, name.length + 1) == (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr, settings) {
|
||||
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
|
||||
// Only send the token to relative URLs i.e. locally.
|
||||
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(typeof horizon.Quota !== 'undefined') {
|
||||
pricing.init_work();
|
||||
} else {
|
||||
addHorizonLoadEvent(function() {
|
||||
pricing.init_work();
|
||||
});
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright 2014 Objectif Libre
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2010-2011 OpenStack Foundation
|
||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
|
@ -13,13 +15,9 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from django.core.management import execute_from_command_line # noqa
|
||||
from oslotest import base
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
|
||||
"openstack_dashboard.settings")
|
||||
execute_from_command_line(sys.argv)
|
||||
class TestCase(base.BaseTestCase):
|
||||
|
||||
"""Test case base class for all unit tests."""
|
|
@ -1,133 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2014 Objectif Libre
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from horizon.test.settings import * # noqa
|
||||
from horizon.utils import secret_key as secret_key_utils
|
||||
from openstack_dashboard import exceptions
|
||||
|
||||
|
||||
TEST_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
ROOT_PATH = os.path.abspath(os.path.join(TEST_DIR, ".."))
|
||||
|
||||
SECRET_KEY = secret_key_utils.generate_or_read_from_file(
|
||||
os.path.join(TEST_DIR, '.secret_key_store'))
|
||||
ROOT_URLCONF = 'openstack_dashboard.urls'
|
||||
TEMPLATE_DIRS = (
|
||||
os.path.join(TEST_DIR, 'templates'),
|
||||
)
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS += (
|
||||
'openstack_dashboard.context_processors.openstack',
|
||||
)
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.humanize',
|
||||
'django_nose',
|
||||
'openstack_auth',
|
||||
'compressor',
|
||||
'horizon',
|
||||
'openstack_dashboard',
|
||||
'openstack_dashboard.dashboards.project',
|
||||
'openstack_dashboard.dashboards.admin',
|
||||
'openstack_dashboard.dashboards.settings',
|
||||
)
|
||||
|
||||
AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',)
|
||||
|
||||
SITE_BRANDING = 'OpenStack'
|
||||
|
||||
HORIZON_CONFIG = {
|
||||
'dashboards': ('project', 'admin',),
|
||||
'default_dashboard': 'project',
|
||||
"password_validator": {
|
||||
"regex": '^.{8,18}$',
|
||||
"help_text": _("Password must be between 8 and 18 characters.")
|
||||
},
|
||||
'user_home': None,
|
||||
'help_url': "http://docs.openstack.org",
|
||||
'exceptions': {'recoverable': exceptions.RECOVERABLE,
|
||||
'not_found': exceptions.NOT_FOUND,
|
||||
'unauthorized': exceptions.UNAUTHORIZED},
|
||||
'angular_modules': [],
|
||||
'js_files': [],
|
||||
}
|
||||
|
||||
# Set to True to allow users to upload images to glance via Horizon server.
|
||||
# When enabled, a file form field will appear on the create image form.
|
||||
# See documentation for deployment considerations.
|
||||
HORIZON_IMAGES_ALLOW_UPLOAD = True
|
||||
|
||||
AVAILABLE_REGIONS = [
|
||||
('http://localhost:5000/v2.0', 'local'),
|
||||
('http://remote:5000/v2.0', 'remote'),
|
||||
]
|
||||
|
||||
OPENSTACK_KEYSTONE_URL = "http://localhost:5000/v2.0"
|
||||
OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_"
|
||||
|
||||
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True
|
||||
OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'test_domain'
|
||||
|
||||
OPENSTACK_KEYSTONE_BACKEND = {
|
||||
'name': 'native',
|
||||
'can_edit_user': True,
|
||||
'can_edit_group': True,
|
||||
'can_edit_project': True,
|
||||
'can_edit_domain': True,
|
||||
'can_edit_role': True
|
||||
}
|
||||
|
||||
OPENSTACK_HYPERVISOR_FEATURES = {
|
||||
'can_set_mount_point': True,
|
||||
'can_set_password': True,
|
||||
}
|
||||
|
||||
LOGGING['loggers']['openstack_dashboard'] = {
|
||||
'handlers': ['test'],
|
||||
'propagate': False,
|
||||
}
|
||||
|
||||
SECURITY_GROUP_RULES = {
|
||||
'all_tcp': {
|
||||
'name': 'ALL TCP',
|
||||
'ip_protocol': 'tcp',
|
||||
'from_port': '1',
|
||||
'to_port': '65535',
|
||||
},
|
||||
'http': {
|
||||
'name': 'HTTP',
|
||||
'ip_protocol': 'tcp',
|
||||
'from_port': '80',
|
||||
'to_port': '80',
|
||||
},
|
||||
}
|
||||
|
||||
NOSE_ARGS = ['--nocapture',
|
||||
'--nologcapture',
|
||||
'--with-coverage',
|
||||
'--cover-package=cloudkittydashboard',
|
||||
'--cover-inclusive',
|
||||
'--all-modules']
|
||||
|
||||
CLOUDKITTY_ENDPOINT_URL = "http://127.0.0.1:8888"
|
|
@ -0,0 +1,29 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2015 Objectif Libre
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
test_cloudkittydashboard
|
||||
----------------------------------
|
||||
|
||||
Tests for `cloudkittydashboard` module.
|
||||
"""
|
||||
|
||||
from cloudkittydashboard.tests import base
|
||||
|
||||
|
||||
class TestCloudkittydashboard(base.TestCase):
|
||||
|
||||
def test_something(self):
|
||||
pass
|
|
@ -1,6 +0,0 @@
|
|||
import testtools
|
||||
|
||||
|
||||
class FakeTest(testtools.TestCase):
|
||||
def test_foo(self):
|
||||
pass
|
177
doc/makefile
177
doc/makefile
|
@ -1,177 +0,0 @@
|
|||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = build
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/cloudkitty-dashboard.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/cloudkitty-dashboard.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/cloudkitty-dashboard"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/cloudkitty-dashboard"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
latexpdfja:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
xml:
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
|
@ -0,0 +1,4 @@
|
|||
============
|
||||
Contributing
|
||||
============
|
||||
.. include:: ../../CONTRIBUTING.rst
|
|
@ -1,21 +1,20 @@
|
|||
.. cloudkitty-dashboard documentation master file, created by
|
||||
sphinx-quickstart on Thu Jul 3 17:15:04 2014.
|
||||
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to the CloudKitty Dashboard's documentation!
|
||||
====================================================
|
||||
Welcome to cloudkitty-dashboard's documentation!
|
||||
========================================================
|
||||
|
||||
Introduction
|
||||
============
|
||||
Contents:
|
||||
|
||||
CloudKitty is a PricingAsAService project aimed at translating Ceilometer
|
||||
metrics to prices.
|
||||
|
||||
python-cloudkitty is the Python client library for CloudKitty API.
|
||||
|
||||
cloudkitty-dashboard is the Horizon plugin for CloudKitty.
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
readme
|
||||
installation
|
||||
usage
|
||||
contributing
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
@ -23,3 +22,4 @@ Indices and tables
|
|||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
============
|
||||
Installation
|
||||
============
|
||||
|
||||
At the command line::
|
||||
|
||||
$ pip install cloudkitty-dashboard
|
||||
|
||||
Or, if you have virtualenvwrapper installed::
|
||||
|
||||
$ mkvirtualenv cloudkitty-dashboard
|
||||
$ pip install cloudkitty-dashboard
|
|
@ -0,0 +1 @@
|
|||
.. include:: ../../README.rst
|
|
@ -0,0 +1,7 @@
|
|||
========
|
||||
Usage
|
||||
========
|
||||
|
||||
To use cloudkitty-dashboard in a project::
|
||||
|
||||
import cloudkittydashboard
|
|
@ -0,0 +1,6 @@
|
|||
[DEFAULT]
|
||||
|
||||
# The list of modules to copy from oslo-incubator.git
|
||||
|
||||
# The base module to hold the copy of openstack.common
|
||||
base=cloudkittydashboard
|
|
@ -1,5 +1,2 @@
|
|||
pbr>=0.6,!=0.7,<1.0
|
||||
http://tarballs.openstack.org/python-cloudkittyclient/python-cloudkittyclient-master.tar.gz
|
||||
|
||||
# Horizon Core Requirements
|
||||
Django>=1.4.2,<1.7
|
||||
Babel>=1.3
|
||||
|
|
39
setup.cfg
39
setup.cfg
|
@ -1,34 +1,47 @@
|
|||
[metadata]
|
||||
name = cloudkitty-dashboard
|
||||
summary = CloudKitty Horizon Plugin
|
||||
summary = CloudKitty Horizon dashboard
|
||||
description-file =
|
||||
README.rst
|
||||
author = Objectif Libre
|
||||
author-email = francois.magimel@objectif-libre.com
|
||||
home-page = http://objectif-libre.com
|
||||
author-email = openstack-dev@lists.openstack.org
|
||||
home-page = http://www.objectif-libre.com
|
||||
classifier =
|
||||
Environment :: OpenStack
|
||||
Framework :: Django
|
||||
Intended Audience :: Information Technology
|
||||
Intended Audience :: System Administrators
|
||||
License :: OSI Approved :: Apache Software License
|
||||
Operating System :: OS Independent
|
||||
Operating System :: POSIX :: Linux
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 2
|
||||
Programming Language :: Python :: 2.6
|
||||
Programming Language :: Python :: 2.7
|
||||
Topic :: Internet :: WWW/HTTP
|
||||
Programming Language :: Python :: 2.6
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.3
|
||||
Programming Language :: Python :: 3.4
|
||||
|
||||
[files]
|
||||
packages =
|
||||
cloudkittydashboard
|
||||
|
||||
[global]
|
||||
setup-hooks =
|
||||
pbr.hooks.setup_hook
|
||||
|
||||
[build_sphinx]
|
||||
all_files = 1
|
||||
build-dir = doc/build
|
||||
source-dir = doc/source
|
||||
build-dir = doc/build
|
||||
all_files = 1
|
||||
|
||||
[upload_sphinx]
|
||||
upload-dir = doc/build/html
|
||||
|
||||
[compile_catalog]
|
||||
directory = cloudkittydashboard/locale
|
||||
domain = cloudkitty-dashboard
|
||||
|
||||
[update_catalog]
|
||||
domain = cloudkitty-dashboard
|
||||
output_dir = cloudkittydashboard/locale
|
||||
input_file = cloudkittydashboard/locale/cloudkitty-dashboard.pot
|
||||
|
||||
[extract_messages]
|
||||
keywords = _ gettext ngettext l_ lazy_gettext
|
||||
mapping_file = babel.cfg
|
||||
output_file = cloudkittydashboard/locale/cloudkitty-dashboard.pot
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright 2014 Objectif Libre
|
||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
||||
import setuptools
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
hacking>=0.9.1,<0.10
|
||||
hacking<0.11,>=0.10.0
|
||||
|
||||
coverage>=3.6
|
||||
django-nose
|
||||
doc8
|
||||
nose
|
||||
openstack.nose_plugin>=0.7
|
||||
oslosphinx
|
||||
oslotest
|
||||
sphinx>=1.1.2
|
||||
discover
|
||||
python-subunit>=0.0.18
|
||||
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
|
||||
oslosphinx>=2.2.0 # Apache-2.0
|
||||
oslotest>=1.2.0 # Apache-2.0
|
||||
testrepository>=0.0.18
|
||||
|
||||
http://tarballs.openstack.org/horizon/horizon-master.tar.gz
|
||||
testscenarios>=0.4
|
||||
testtools>=0.9.36,!=1.2.0
|
||||
|
|
46
tox.ini
46
tox.ini
|
@ -1,44 +1,36 @@
|
|||
[tox]
|
||||
envlist = py26,py27,py33,pep8
|
||||
minversion = 1.6
|
||||
envlist = py26,py27,pypy,pep8
|
||||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
usedevelop = True
|
||||
install_command = pip install -U {opts} {packages}
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = python {toxinidir}/manage.py test cloudkittydashboard --settings=cloudkittydashboard.tests.settings
|
||||
|
||||
[tox:jenkins]
|
||||
downloadcache = ~/cache/pip
|
||||
commands = python setup.py testr --slowest --testr-args='{posargs}'
|
||||
|
||||
[testenv:pep8]
|
||||
setenv = DJANGO_SETTINGS_MODULE=cloudkittydashboard.tests.settings
|
||||
commands = flake8 {posargs}
|
||||
|
||||
[testenv:cover]
|
||||
commands =
|
||||
coverage erase
|
||||
coverage run {toxinidir}/manage.py test cloudkittydashboard --settings=cloudkittydashboard.tests.settings
|
||||
coverage html -d cover
|
||||
|
||||
[testenv:docs]
|
||||
setenv = DJANGO_SETTINGS_MODULE=cloudkittydashboard.tests.settings
|
||||
commands =
|
||||
doc8 -e .rst README.rst doc/source
|
||||
python setup.py build_sphinx
|
||||
commands = flake8
|
||||
|
||||
[testenv:venv]
|
||||
commands = {posargs}
|
||||
|
||||
[testenv:cover]
|
||||
commands = python setup.py testr --coverage --testr-args='{posargs}'
|
||||
|
||||
[testenv:docs]
|
||||
commands = python setup.py build_sphinx
|
||||
|
||||
[testenv:debug]
|
||||
commands = oslo_debug_helper {posargs}
|
||||
|
||||
[flake8]
|
||||
# H102 Apache 2.0 license header not found
|
||||
# H302 import only modules.
|
||||
# H307 like imports should be grouped together
|
||||
# H904 Wrap long lines in parentheses instead of a backslash
|
||||
# E265 block comment should start with '# '
|
||||
ignore = H102,H302,H307,H904,E265
|
||||
# E123, E125 skipped as they are invalid PEP-8.
|
||||
|
||||
show-source = True
|
||||
exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,tools,enabled
|
||||
ignore = E123,E125
|
||||
builtins = _
|
||||
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,.ropeproject
|
||||
|
|
Loading…
Reference in New Issue